Path: blob/main/contrib/llvm-project/llvm/lib/MC/MCParser/AsmParser.cpp
35266 views
//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This class implements a parser for assembly files similar to gas syntax.9//10//===----------------------------------------------------------------------===//1112#include "llvm/ADT/APFloat.h"13#include "llvm/ADT/APInt.h"14#include "llvm/ADT/ArrayRef.h"15#include "llvm/ADT/STLExtras.h"16#include "llvm/ADT/SmallSet.h"17#include "llvm/ADT/SmallString.h"18#include "llvm/ADT/SmallVector.h"19#include "llvm/ADT/StringExtras.h"20#include "llvm/ADT/StringMap.h"21#include "llvm/ADT/StringRef.h"22#include "llvm/ADT/Twine.h"23#include "llvm/BinaryFormat/Dwarf.h"24#include "llvm/DebugInfo/CodeView/SymbolRecord.h"25#include "llvm/MC/MCAsmInfo.h"26#include "llvm/MC/MCCodeView.h"27#include "llvm/MC/MCContext.h"28#include "llvm/MC/MCDirectives.h"29#include "llvm/MC/MCDwarf.h"30#include "llvm/MC/MCExpr.h"31#include "llvm/MC/MCInstPrinter.h"32#include "llvm/MC/MCInstrDesc.h"33#include "llvm/MC/MCInstrInfo.h"34#include "llvm/MC/MCParser/AsmCond.h"35#include "llvm/MC/MCParser/AsmLexer.h"36#include "llvm/MC/MCParser/MCAsmLexer.h"37#include "llvm/MC/MCParser/MCAsmParser.h"38#include "llvm/MC/MCParser/MCAsmParserExtension.h"39#include "llvm/MC/MCParser/MCAsmParserUtils.h"40#include "llvm/MC/MCParser/MCParsedAsmOperand.h"41#include "llvm/MC/MCParser/MCTargetAsmParser.h"42#include "llvm/MC/MCRegisterInfo.h"43#include "llvm/MC/MCSection.h"44#include "llvm/MC/MCStreamer.h"45#include "llvm/MC/MCSymbol.h"46#include "llvm/MC/MCSymbolMachO.h"47#include "llvm/MC/MCTargetOptions.h"48#include "llvm/MC/MCValue.h"49#include "llvm/Support/Casting.h"50#include "llvm/Support/CommandLine.h"51#include "llvm/Support/ErrorHandling.h"52#include "llvm/Support/MD5.h"53#include "llvm/Support/MathExtras.h"54#include "llvm/Support/MemoryBuffer.h"55#include "llvm/Support/SMLoc.h"56#include "llvm/Support/SourceMgr.h"57#include "llvm/Support/raw_ostream.h"58#include <algorithm>59#include <cassert>60#include <cctype>61#include <climits>62#include <cstddef>63#include <cstdint>64#include <deque>65#include <memory>66#include <optional>67#include <sstream>68#include <string>69#include <tuple>70#include <utility>71#include <vector>7273using namespace llvm;7475MCAsmParserSemaCallback::~MCAsmParserSemaCallback() = default;7677namespace {7879/// Helper types for tracking macro definitions.80typedef std::vector<AsmToken> MCAsmMacroArgument;81typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;8283/// Helper class for storing information about an active macro84/// instantiation.85struct MacroInstantiation {86/// The location of the instantiation.87SMLoc InstantiationLoc;8889/// The buffer where parsing should resume upon instantiation completion.90unsigned ExitBuffer;9192/// The location where parsing should resume upon instantiation completion.93SMLoc ExitLoc;9495/// The depth of TheCondStack at the start of the instantiation.96size_t CondStackDepth;97};9899struct ParseStatementInfo {100/// The parsed operands from the last parsed statement.101SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;102103/// The opcode from the last parsed instruction.104unsigned Opcode = ~0U;105106/// Was there an error parsing the inline assembly?107bool ParseError = false;108109SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;110111ParseStatementInfo() = delete;112ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)113: AsmRewrites(rewrites) {}114};115116/// The concrete assembly parser instance.117class AsmParser : public MCAsmParser {118private:119AsmLexer Lexer;120MCContext &Ctx;121MCStreamer &Out;122const MCAsmInfo &MAI;123SourceMgr &SrcMgr;124SourceMgr::DiagHandlerTy SavedDiagHandler;125void *SavedDiagContext;126std::unique_ptr<MCAsmParserExtension> PlatformParser;127SMLoc StartTokLoc;128std::optional<SMLoc> CFIStartProcLoc;129130/// This is the current buffer index we're lexing from as managed by the131/// SourceMgr object.132unsigned CurBuffer;133134AsmCond TheCondState;135std::vector<AsmCond> TheCondStack;136137/// maps directive names to handler methods in parser138/// extensions. Extensions register themselves in this map by calling139/// addDirectiveHandler.140StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;141142/// Stack of active macro instantiations.143std::vector<MacroInstantiation*> ActiveMacros;144145/// List of bodies of anonymous macros.146std::deque<MCAsmMacro> MacroLikeBodies;147148/// Boolean tracking whether macro substitution is enabled.149unsigned MacrosEnabledFlag : 1;150151/// Keeps track of how many .macro's have been instantiated.152unsigned NumOfMacroInstantiations;153154/// The values from the last parsed cpp hash file line comment if any.155struct CppHashInfoTy {156StringRef Filename;157int64_t LineNumber;158SMLoc Loc;159unsigned Buf;160CppHashInfoTy() : LineNumber(0), Buf(0) {}161};162CppHashInfoTy CppHashInfo;163164/// The filename from the first cpp hash file line comment, if any.165StringRef FirstCppHashFilename;166167/// List of forward directional labels for diagnosis at the end.168SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;169170SmallSet<StringRef, 2> LTODiscardSymbols;171172/// AssemblerDialect. ~OU means unset value and use value provided by MAI.173unsigned AssemblerDialect = ~0U;174175/// is Darwin compatibility enabled?176bool IsDarwin = false;177178/// Are we parsing ms-style inline assembly?179bool ParsingMSInlineAsm = false;180181/// Did we already inform the user about inconsistent MD5 usage?182bool ReportedInconsistentMD5 = false;183184// Is alt macro mode enabled.185bool AltMacroMode = false;186187protected:188virtual bool parseStatement(ParseStatementInfo &Info,189MCAsmParserSemaCallback *SI);190191/// This routine uses the target specific ParseInstruction function to192/// parse an instruction into Operands, and then call the target specific193/// MatchAndEmit function to match and emit the instruction.194bool parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info,195StringRef IDVal, AsmToken ID,196SMLoc IDLoc);197198/// Should we emit DWARF describing this assembler source? (Returns false if199/// the source has .file directives, which means we don't want to generate200/// info describing the assembler source itself.)201bool enabledGenDwarfForAssembly();202203public:204AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,205const MCAsmInfo &MAI, unsigned CB);206AsmParser(const AsmParser &) = delete;207AsmParser &operator=(const AsmParser &) = delete;208~AsmParser() override;209210bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;211212void addDirectiveHandler(StringRef Directive,213ExtensionDirectiveHandler Handler) override {214ExtensionDirectiveMap[Directive] = Handler;215}216217void addAliasForDirective(StringRef Directive, StringRef Alias) override {218DirectiveKindMap[Directive.lower()] = DirectiveKindMap[Alias.lower()];219}220221/// @name MCAsmParser Interface222/// {223224SourceMgr &getSourceManager() override { return SrcMgr; }225MCAsmLexer &getLexer() override { return Lexer; }226MCContext &getContext() override { return Ctx; }227MCStreamer &getStreamer() override { return Out; }228229CodeViewContext &getCVContext() { return Ctx.getCVContext(); }230231unsigned getAssemblerDialect() override {232if (AssemblerDialect == ~0U)233return MAI.getAssemblerDialect();234else235return AssemblerDialect;236}237void setAssemblerDialect(unsigned i) override {238AssemblerDialect = i;239}240241void Note(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt) override;242bool Warning(SMLoc L, const Twine &Msg,243SMRange Range = std::nullopt) override;244bool printError(SMLoc L, const Twine &Msg,245SMRange Range = std::nullopt) override;246247const AsmToken &Lex() override;248249void setParsingMSInlineAsm(bool V) override {250ParsingMSInlineAsm = V;251// When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and252// hex integer literals.253Lexer.setLexMasmIntegers(V);254}255bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }256257bool discardLTOSymbol(StringRef Name) const override {258return LTODiscardSymbols.contains(Name);259}260261bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs,262unsigned &NumInputs,263SmallVectorImpl<std::pair<void *, bool>> &OpDecls,264SmallVectorImpl<std::string> &Constraints,265SmallVectorImpl<std::string> &Clobbers,266const MCInstrInfo *MII, const MCInstPrinter *IP,267MCAsmParserSemaCallback &SI) override;268269bool parseExpression(const MCExpr *&Res);270bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;271bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,272AsmTypeInfo *TypeInfo) override;273bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;274bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,275SMLoc &EndLoc) override;276bool parseAbsoluteExpression(int64_t &Res) override;277278/// Parse a floating point expression using the float \p Semantics279/// and set \p Res to the value.280bool parseRealValue(const fltSemantics &Semantics, APInt &Res);281282/// Parse an identifier or string (as a quoted identifier)283/// and set \p Res to the identifier contents.284bool parseIdentifier(StringRef &Res) override;285void eatToEndOfStatement() override;286287bool checkForValidSection() override;288289/// }290291private:292bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);293bool parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo = true);294295void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body,296ArrayRef<MCAsmMacroParameter> Parameters);297bool expandMacro(raw_svector_ostream &OS, MCAsmMacro &Macro,298ArrayRef<MCAsmMacroParameter> Parameters,299ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable);300301/// Are macros enabled in the parser?302bool areMacrosEnabled() {return MacrosEnabledFlag;}303304/// Control a flag in the parser that enables or disables macros.305void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;}306307/// Are we inside a macro instantiation?308bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}309310/// Handle entry to macro instantiation.311///312/// \param M The macro.313/// \param NameLoc Instantiation location.314bool handleMacroEntry(MCAsmMacro *M, SMLoc NameLoc);315316/// Handle exit from macro instantiation.317void handleMacroExit();318319/// Extract AsmTokens for a macro argument.320bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg);321322/// Parse all macro arguments for a given macro.323bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);324325void printMacroInstantiations();326void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,327SMRange Range = std::nullopt) const {328ArrayRef<SMRange> Ranges(Range);329SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);330}331static void DiagHandler(const SMDiagnostic &Diag, void *Context);332333/// Enter the specified file. This returns true on failure.334bool enterIncludeFile(const std::string &Filename);335336/// Process the specified file for the .incbin directive.337/// This returns true on failure.338bool processIncbinFile(const std::string &Filename, int64_t Skip = 0,339const MCExpr *Count = nullptr, SMLoc Loc = SMLoc());340341/// Reset the current lexer position to that given by \p Loc. The342/// current token is not set; clients should ensure Lex() is called343/// subsequently.344///345/// \param InBuffer If not 0, should be the known buffer id that contains the346/// location.347void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0);348349/// Parse up to the end of statement and a return the contents from the350/// current token until the end of the statement; the current token on exit351/// will be either the EndOfStatement or EOF.352StringRef parseStringToEndOfStatement() override;353354/// Parse until the end of a statement or a comma is encountered,355/// return the contents from the current token up to the end or comma.356StringRef parseStringToComma();357358enum class AssignmentKind {359Set,360Equiv,361Equal,362LTOSetConditional,363};364365bool parseAssignment(StringRef Name, AssignmentKind Kind);366367unsigned getBinOpPrecedence(AsmToken::TokenKind K,368MCBinaryExpr::Opcode &Kind);369370bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);371bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);372bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);373374bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc);375376bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName);377bool parseCVFileId(int64_t &FileId, StringRef DirectiveName);378379// Generic (target and platform independent) directive parsing.380enum DirectiveKind {381DK_NO_DIRECTIVE, // Placeholder382DK_SET,383DK_EQU,384DK_EQUIV,385DK_ASCII,386DK_ASCIZ,387DK_STRING,388DK_BYTE,389DK_SHORT,390DK_RELOC,391DK_VALUE,392DK_2BYTE,393DK_LONG,394DK_INT,395DK_4BYTE,396DK_QUAD,397DK_8BYTE,398DK_OCTA,399DK_DC,400DK_DC_A,401DK_DC_B,402DK_DC_D,403DK_DC_L,404DK_DC_S,405DK_DC_W,406DK_DC_X,407DK_DCB,408DK_DCB_B,409DK_DCB_D,410DK_DCB_L,411DK_DCB_S,412DK_DCB_W,413DK_DCB_X,414DK_DS,415DK_DS_B,416DK_DS_D,417DK_DS_L,418DK_DS_P,419DK_DS_S,420DK_DS_W,421DK_DS_X,422DK_SINGLE,423DK_FLOAT,424DK_DOUBLE,425DK_ALIGN,426DK_ALIGN32,427DK_BALIGN,428DK_BALIGNW,429DK_BALIGNL,430DK_P2ALIGN,431DK_P2ALIGNW,432DK_P2ALIGNL,433DK_ORG,434DK_FILL,435DK_ENDR,436DK_BUNDLE_ALIGN_MODE,437DK_BUNDLE_LOCK,438DK_BUNDLE_UNLOCK,439DK_ZERO,440DK_EXTERN,441DK_GLOBL,442DK_GLOBAL,443DK_LAZY_REFERENCE,444DK_NO_DEAD_STRIP,445DK_SYMBOL_RESOLVER,446DK_PRIVATE_EXTERN,447DK_REFERENCE,448DK_WEAK_DEFINITION,449DK_WEAK_REFERENCE,450DK_WEAK_DEF_CAN_BE_HIDDEN,451DK_COLD,452DK_COMM,453DK_COMMON,454DK_LCOMM,455DK_ABORT,456DK_INCLUDE,457DK_INCBIN,458DK_CODE16,459DK_CODE16GCC,460DK_REPT,461DK_IRP,462DK_IRPC,463DK_IF,464DK_IFEQ,465DK_IFGE,466DK_IFGT,467DK_IFLE,468DK_IFLT,469DK_IFNE,470DK_IFB,471DK_IFNB,472DK_IFC,473DK_IFEQS,474DK_IFNC,475DK_IFNES,476DK_IFDEF,477DK_IFNDEF,478DK_IFNOTDEF,479DK_ELSEIF,480DK_ELSE,481DK_ENDIF,482DK_SPACE,483DK_SKIP,484DK_FILE,485DK_LINE,486DK_LOC,487DK_STABS,488DK_CV_FILE,489DK_CV_FUNC_ID,490DK_CV_INLINE_SITE_ID,491DK_CV_LOC,492DK_CV_LINETABLE,493DK_CV_INLINE_LINETABLE,494DK_CV_DEF_RANGE,495DK_CV_STRINGTABLE,496DK_CV_STRING,497DK_CV_FILECHECKSUMS,498DK_CV_FILECHECKSUM_OFFSET,499DK_CV_FPO_DATA,500DK_CFI_SECTIONS,501DK_CFI_STARTPROC,502DK_CFI_ENDPROC,503DK_CFI_DEF_CFA,504DK_CFI_DEF_CFA_OFFSET,505DK_CFI_ADJUST_CFA_OFFSET,506DK_CFI_DEF_CFA_REGISTER,507DK_CFI_LLVM_DEF_ASPACE_CFA,508DK_CFI_OFFSET,509DK_CFI_REL_OFFSET,510DK_CFI_PERSONALITY,511DK_CFI_LSDA,512DK_CFI_REMEMBER_STATE,513DK_CFI_RESTORE_STATE,514DK_CFI_SAME_VALUE,515DK_CFI_RESTORE,516DK_CFI_ESCAPE,517DK_CFI_RETURN_COLUMN,518DK_CFI_SIGNAL_FRAME,519DK_CFI_UNDEFINED,520DK_CFI_REGISTER,521DK_CFI_WINDOW_SAVE,522DK_CFI_LABEL,523DK_CFI_B_KEY_FRAME,524DK_MACROS_ON,525DK_MACROS_OFF,526DK_ALTMACRO,527DK_NOALTMACRO,528DK_MACRO,529DK_EXITM,530DK_ENDM,531DK_ENDMACRO,532DK_PURGEM,533DK_SLEB128,534DK_ULEB128,535DK_ERR,536DK_ERROR,537DK_WARNING,538DK_PRINT,539DK_ADDRSIG,540DK_ADDRSIG_SYM,541DK_PSEUDO_PROBE,542DK_LTO_DISCARD,543DK_LTO_SET_CONDITIONAL,544DK_CFI_MTE_TAGGED_FRAME,545DK_MEMTAG,546DK_END547};548549/// Maps directive name --> DirectiveKind enum, for550/// directives parsed by this class.551StringMap<DirectiveKind> DirectiveKindMap;552553// Codeview def_range type parsing.554enum CVDefRangeType {555CVDR_DEFRANGE = 0, // Placeholder556CVDR_DEFRANGE_REGISTER,557CVDR_DEFRANGE_FRAMEPOINTER_REL,558CVDR_DEFRANGE_SUBFIELD_REGISTER,559CVDR_DEFRANGE_REGISTER_REL560};561562/// Maps Codeview def_range types --> CVDefRangeType enum, for563/// Codeview def_range types parsed by this class.564StringMap<CVDefRangeType> CVDefRangeTypeMap;565566// ".ascii", ".asciz", ".string"567bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);568bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc"569bool parseDirectiveValue(StringRef IDVal,570unsigned Size); // ".byte", ".long", ...571bool parseDirectiveOctaValue(StringRef IDVal); // ".octa", ...572bool parseDirectiveRealValue(StringRef IDVal,573const fltSemantics &); // ".single", ...574bool parseDirectiveFill(); // ".fill"575bool parseDirectiveZero(); // ".zero"576// ".set", ".equ", ".equiv", ".lto_set_conditional"577bool parseDirectiveSet(StringRef IDVal, AssignmentKind Kind);578bool parseDirectiveOrg(); // ".org"579// ".align{,32}", ".p2align{,w,l}"580bool parseDirectiveAlign(bool IsPow2, unsigned ValueSize);581582// ".file", ".line", ".loc", ".stabs"583bool parseDirectiveFile(SMLoc DirectiveLoc);584bool parseDirectiveLine();585bool parseDirectiveLoc();586bool parseDirectiveStabs();587588// ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",589// ".cv_inline_linetable", ".cv_def_range", ".cv_string"590bool parseDirectiveCVFile();591bool parseDirectiveCVFuncId();592bool parseDirectiveCVInlineSiteId();593bool parseDirectiveCVLoc();594bool parseDirectiveCVLinetable();595bool parseDirectiveCVInlineLinetable();596bool parseDirectiveCVDefRange();597bool parseDirectiveCVString();598bool parseDirectiveCVStringTable();599bool parseDirectiveCVFileChecksums();600bool parseDirectiveCVFileChecksumOffset();601bool parseDirectiveCVFPOData();602603// .cfi directives604bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);605bool parseDirectiveCFIWindowSave(SMLoc DirectiveLoc);606bool parseDirectiveCFISections();607bool parseDirectiveCFIStartProc();608bool parseDirectiveCFIEndProc();609bool parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc);610bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);611bool parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc);612bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);613bool parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc);614bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);615bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);616bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);617bool parseDirectiveCFIRememberState(SMLoc DirectiveLoc);618bool parseDirectiveCFIRestoreState(SMLoc DirectiveLoc);619bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);620bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);621bool parseDirectiveCFIEscape(SMLoc DirectiveLoc);622bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);623bool parseDirectiveCFISignalFrame(SMLoc DirectiveLoc);624bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);625bool parseDirectiveCFILabel(SMLoc DirectiveLoc);626627// macro directives628bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);629bool parseDirectiveExitMacro(StringRef Directive);630bool parseDirectiveEndMacro(StringRef Directive);631bool parseDirectiveMacro(SMLoc DirectiveLoc);632bool parseDirectiveMacrosOnOff(StringRef Directive);633// alternate macro mode directives634bool parseDirectiveAltmacro(StringRef Directive);635// ".bundle_align_mode"636bool parseDirectiveBundleAlignMode();637// ".bundle_lock"638bool parseDirectiveBundleLock();639// ".bundle_unlock"640bool parseDirectiveBundleUnlock();641642// ".space", ".skip"643bool parseDirectiveSpace(StringRef IDVal);644645// ".dcb"646bool parseDirectiveDCB(StringRef IDVal, unsigned Size);647bool parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &);648// ".ds"649bool parseDirectiveDS(StringRef IDVal, unsigned Size);650651// .sleb128 (Signed=true) and .uleb128 (Signed=false)652bool parseDirectiveLEB128(bool Signed);653654/// Parse a directive like ".globl" which655/// accepts a single symbol (which should be a label or an external).656bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);657658bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"659660bool parseDirectiveAbort(SMLoc DirectiveLoc); // ".abort"661bool parseDirectiveInclude(); // ".include"662bool parseDirectiveIncbin(); // ".incbin"663664// ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne"665bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);666// ".ifb" or ".ifnb", depending on ExpectBlank.667bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);668// ".ifc" or ".ifnc", depending on ExpectEqual.669bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);670// ".ifeqs" or ".ifnes", depending on ExpectEqual.671bool parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual);672// ".ifdef" or ".ifndef", depending on expect_defined673bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);674bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"675bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"676bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif677bool parseEscapedString(std::string &Data) override;678bool parseAngleBracketString(std::string &Data) override;679680const MCExpr *applyModifierToExpr(const MCExpr *E,681MCSymbolRefExpr::VariantKind Variant);682683// Macro-like directives684MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);685void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,686raw_svector_ostream &OS);687bool parseDirectiveRept(SMLoc DirectiveLoc, StringRef Directive);688bool parseDirectiveIrp(SMLoc DirectiveLoc); // ".irp"689bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"690bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"691692// "_emit" or "__emit"693bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,694size_t Len);695696// "align"697bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);698699// "end"700bool parseDirectiveEnd(SMLoc DirectiveLoc);701702// ".err" or ".error"703bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage);704705// ".warning"706bool parseDirectiveWarning(SMLoc DirectiveLoc);707708// .print <double-quotes-string>709bool parseDirectivePrint(SMLoc DirectiveLoc);710711// .pseudoprobe712bool parseDirectivePseudoProbe();713714// ".lto_discard"715bool parseDirectiveLTODiscard();716717// Directives to support address-significance tables.718bool parseDirectiveAddrsig();719bool parseDirectiveAddrsigSym();720721void initializeDirectiveKindMap();722void initializeCVDefRangeTypeMap();723};724725class HLASMAsmParser final : public AsmParser {726private:727MCAsmLexer &Lexer;728MCStreamer &Out;729730void lexLeadingSpaces() {731while (Lexer.is(AsmToken::Space))732Lexer.Lex();733}734735bool parseAsHLASMLabel(ParseStatementInfo &Info, MCAsmParserSemaCallback *SI);736bool parseAsMachineInstruction(ParseStatementInfo &Info,737MCAsmParserSemaCallback *SI);738739public:740HLASMAsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,741const MCAsmInfo &MAI, unsigned CB = 0)742: AsmParser(SM, Ctx, Out, MAI, CB), Lexer(getLexer()), Out(Out) {743Lexer.setSkipSpace(false);744Lexer.setAllowHashInIdentifier(true);745Lexer.setLexHLASMIntegers(true);746Lexer.setLexHLASMStrings(true);747}748749~HLASMAsmParser() { Lexer.setSkipSpace(true); }750751bool parseStatement(ParseStatementInfo &Info,752MCAsmParserSemaCallback *SI) override;753};754755} // end anonymous namespace756757namespace llvm {758759extern cl::opt<unsigned> AsmMacroMaxNestingDepth;760761extern MCAsmParserExtension *createDarwinAsmParser();762extern MCAsmParserExtension *createELFAsmParser();763extern MCAsmParserExtension *createCOFFAsmParser();764extern MCAsmParserExtension *createGOFFAsmParser();765extern MCAsmParserExtension *createXCOFFAsmParser();766extern MCAsmParserExtension *createWasmAsmParser();767768} // end namespace llvm769770enum { DEFAULT_ADDRSPACE = 0 };771772AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,773const MCAsmInfo &MAI, unsigned CB = 0)774: Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),775CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true) {776HadError = false;777// Save the old handler.778SavedDiagHandler = SrcMgr.getDiagHandler();779SavedDiagContext = SrcMgr.getDiagContext();780// Set our own handler which calls the saved handler.781SrcMgr.setDiagHandler(DiagHandler, this);782Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());783// Make MCStreamer aware of the StartTokLoc for locations in diagnostics.784Out.setStartTokLocPtr(&StartTokLoc);785786// Initialize the platform / file format parser.787switch (Ctx.getObjectFileType()) {788case MCContext::IsCOFF:789PlatformParser.reset(createCOFFAsmParser());790break;791case MCContext::IsMachO:792PlatformParser.reset(createDarwinAsmParser());793IsDarwin = true;794break;795case MCContext::IsELF:796PlatformParser.reset(createELFAsmParser());797break;798case MCContext::IsGOFF:799PlatformParser.reset(createGOFFAsmParser());800break;801case MCContext::IsSPIRV:802report_fatal_error(803"Need to implement createSPIRVAsmParser for SPIRV format.");804break;805case MCContext::IsWasm:806PlatformParser.reset(createWasmAsmParser());807break;808case MCContext::IsXCOFF:809PlatformParser.reset(createXCOFFAsmParser());810break;811case MCContext::IsDXContainer:812report_fatal_error("DXContainer is not supported yet");813break;814}815816PlatformParser->Initialize(*this);817initializeDirectiveKindMap();818initializeCVDefRangeTypeMap();819820NumOfMacroInstantiations = 0;821}822823AsmParser::~AsmParser() {824assert((HadError || ActiveMacros.empty()) &&825"Unexpected active macro instantiation!");826827// Remove MCStreamer's reference to the parser SMLoc.828Out.setStartTokLocPtr(nullptr);829// Restore the saved diagnostics handler and context for use during830// finalization.831SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);832}833834void AsmParser::printMacroInstantiations() {835// Print the active macro instantiation stack.836for (MacroInstantiation *M : reverse(ActiveMacros))837printMessage(M->InstantiationLoc, SourceMgr::DK_Note,838"while in macro instantiation");839}840841void AsmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {842printPendingErrors();843printMessage(L, SourceMgr::DK_Note, Msg, Range);844printMacroInstantiations();845}846847bool AsmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {848if(getTargetParser().getTargetOptions().MCNoWarn)849return false;850if (getTargetParser().getTargetOptions().MCFatalWarnings)851return Error(L, Msg, Range);852printMessage(L, SourceMgr::DK_Warning, Msg, Range);853printMacroInstantiations();854return false;855}856857bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {858HadError = true;859printMessage(L, SourceMgr::DK_Error, Msg, Range);860printMacroInstantiations();861return true;862}863864bool AsmParser::enterIncludeFile(const std::string &Filename) {865std::string IncludedFile;866unsigned NewBuf =867SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);868if (!NewBuf)869return true;870871CurBuffer = NewBuf;872Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());873return false;874}875876/// Process the specified .incbin file by searching for it in the include paths877/// then just emitting the byte contents of the file to the streamer. This878/// returns true on failure.879bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip,880const MCExpr *Count, SMLoc Loc) {881std::string IncludedFile;882unsigned NewBuf =883SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);884if (!NewBuf)885return true;886887// Pick up the bytes from the file and emit them.888StringRef Bytes = SrcMgr.getMemoryBuffer(NewBuf)->getBuffer();889Bytes = Bytes.drop_front(Skip);890if (Count) {891int64_t Res;892if (!Count->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))893return Error(Loc, "expected absolute expression");894if (Res < 0)895return Warning(Loc, "negative count has no effect");896Bytes = Bytes.take_front(Res);897}898getStreamer().emitBytes(Bytes);899return false;900}901902void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) {903CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);904Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),905Loc.getPointer());906}907908const AsmToken &AsmParser::Lex() {909if (Lexer.getTok().is(AsmToken::Error))910Error(Lexer.getErrLoc(), Lexer.getErr());911912// if it's a end of statement with a comment in it913if (getTok().is(AsmToken::EndOfStatement)) {914// if this is a line comment output it.915if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&916getTok().getString().front() != '\r' && MAI.preserveAsmComments())917Out.addExplicitComment(Twine(getTok().getString()));918}919920const AsmToken *tok = &Lexer.Lex();921922// Parse comments here to be deferred until end of next statement.923while (tok->is(AsmToken::Comment)) {924if (MAI.preserveAsmComments())925Out.addExplicitComment(Twine(tok->getString()));926tok = &Lexer.Lex();927}928929if (tok->is(AsmToken::Eof)) {930// If this is the end of an included file, pop the parent file off the931// include stack.932SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);933if (ParentIncludeLoc != SMLoc()) {934jumpToLoc(ParentIncludeLoc);935return Lex();936}937}938939return *tok;940}941942bool AsmParser::enabledGenDwarfForAssembly() {943// Check whether the user specified -g.944if (!getContext().getGenDwarfForAssembly())945return false;946// If we haven't encountered any .file directives (which would imply that947// the assembler source was produced with debug info already) then emit one948// describing the assembler source file itself.949if (getContext().getGenDwarfFileNumber() == 0) {950// Use the first #line directive for this, if any. It's preprocessed, so951// there is no checksum, and of course no source directive.952if (!FirstCppHashFilename.empty())953getContext().setMCLineTableRootFile(954/*CUID=*/0, getContext().getCompilationDir(), FirstCppHashFilename,955/*Cksum=*/std::nullopt, /*Source=*/std::nullopt);956const MCDwarfFile &RootFile =957getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile();958getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective(959/*CUID=*/0, getContext().getCompilationDir(), RootFile.Name,960RootFile.Checksum, RootFile.Source));961}962return true;963}964965bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {966LTODiscardSymbols.clear();967968// Create the initial section, if requested.969if (!NoInitialTextSection)970Out.initSections(false, getTargetParser().getSTI());971972// Prime the lexer.973Lex();974975HadError = false;976AsmCond StartingCondState = TheCondState;977SmallVector<AsmRewrite, 4> AsmStrRewrites;978979// If we are generating dwarf for assembly source files save the initial text980// section. (Don't use enabledGenDwarfForAssembly() here, as we aren't981// emitting any actual debug info yet and haven't had a chance to parse any982// embedded .file directives.)983if (getContext().getGenDwarfForAssembly()) {984MCSection *Sec = getStreamer().getCurrentSectionOnly();985if (!Sec->getBeginSymbol()) {986MCSymbol *SectionStartSym = getContext().createTempSymbol();987getStreamer().emitLabel(SectionStartSym);988Sec->setBeginSymbol(SectionStartSym);989}990bool InsertResult = getContext().addGenDwarfSection(Sec);991assert(InsertResult && ".text section should not have debug info yet");992(void)InsertResult;993}994995getTargetParser().onBeginOfFile();996997// While we have input, parse each statement.998while (Lexer.isNot(AsmToken::Eof)) {999ParseStatementInfo Info(&AsmStrRewrites);1000bool Parsed = parseStatement(Info, nullptr);10011002// If we have a Lexer Error we are on an Error Token. Load in Lexer Error1003// for printing ErrMsg via Lex() only if no (presumably better) parser error1004// exists.1005if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {1006Lex();1007}10081009// parseStatement returned true so may need to emit an error.1010printPendingErrors();10111012// Skipping to the next line if needed.1013if (Parsed && !getLexer().isAtStartOfStatement())1014eatToEndOfStatement();1015}10161017getTargetParser().onEndOfFile();1018printPendingErrors();10191020// All errors should have been emitted.1021assert(!hasPendingError() && "unexpected error from parseStatement");10221023getTargetParser().flushPendingInstructions(getStreamer());10241025if (TheCondState.TheCond != StartingCondState.TheCond ||1026TheCondState.Ignore != StartingCondState.Ignore)1027printError(getTok().getLoc(), "unmatched .ifs or .elses");1028// Check to see there are no empty DwarfFile slots.1029const auto &LineTables = getContext().getMCDwarfLineTables();1030if (!LineTables.empty()) {1031unsigned Index = 0;1032for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) {1033if (File.Name.empty() && Index != 0)1034printError(getTok().getLoc(), "unassigned file number: " +1035Twine(Index) +1036" for .file directives");1037++Index;1038}1039}10401041// Check to see that all assembler local symbols were actually defined.1042// Targets that don't do subsections via symbols may not want this, though,1043// so conservatively exclude them. Only do this if we're finalizing, though,1044// as otherwise we won't necessarilly have seen everything yet.1045if (!NoFinalize) {1046if (MAI.hasSubsectionsViaSymbols()) {1047for (const auto &TableEntry : getContext().getSymbols()) {1048MCSymbol *Sym = TableEntry.getValue().Symbol;1049// Variable symbols may not be marked as defined, so check those1050// explicitly. If we know it's a variable, we have a definition for1051// the purposes of this check.1052if (Sym && Sym->isTemporary() && !Sym->isVariable() &&1053!Sym->isDefined())1054// FIXME: We would really like to refer back to where the symbol was1055// first referenced for a source location. We need to add something1056// to track that. Currently, we just point to the end of the file.1057printError(getTok().getLoc(), "assembler local symbol '" +1058Sym->getName() + "' not defined");1059}1060}10611062// Temporary symbols like the ones for directional jumps don't go in the1063// symbol table. They also need to be diagnosed in all (final) cases.1064for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {1065if (std::get<2>(LocSym)->isUndefined()) {1066// Reset the state of any "# line file" directives we've seen to the1067// context as it was at the diagnostic site.1068CppHashInfo = std::get<1>(LocSym);1069printError(std::get<0>(LocSym), "directional label undefined");1070}1071}1072}1073// Finalize the output stream if there are no errors and if the client wants1074// us to.1075if (!HadError && !NoFinalize) {1076if (auto *TS = Out.getTargetStreamer())1077TS->emitConstantPools();10781079Out.finish(Lexer.getLoc());1080}10811082return HadError || getContext().hadError();1083}10841085bool AsmParser::checkForValidSection() {1086if (!ParsingMSInlineAsm && !getStreamer().getCurrentFragment()) {1087Out.initSections(false, getTargetParser().getSTI());1088return Error(getTok().getLoc(),1089"expected section directive before assembly directive");1090}1091return false;1092}10931094/// Throw away the rest of the line for testing purposes.1095void AsmParser::eatToEndOfStatement() {1096while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))1097Lexer.Lex();10981099// Eat EOL.1100if (Lexer.is(AsmToken::EndOfStatement))1101Lexer.Lex();1102}11031104StringRef AsmParser::parseStringToEndOfStatement() {1105const char *Start = getTok().getLoc().getPointer();11061107while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))1108Lexer.Lex();11091110const char *End = getTok().getLoc().getPointer();1111return StringRef(Start, End - Start);1112}11131114StringRef AsmParser::parseStringToComma() {1115const char *Start = getTok().getLoc().getPointer();11161117while (Lexer.isNot(AsmToken::EndOfStatement) &&1118Lexer.isNot(AsmToken::Comma) && Lexer.isNot(AsmToken::Eof))1119Lexer.Lex();11201121const char *End = getTok().getLoc().getPointer();1122return StringRef(Start, End - Start);1123}11241125/// Parse a paren expression and return it.1126/// NOTE: This assumes the leading '(' has already been consumed.1127///1128/// parenexpr ::= expr)1129///1130bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {1131if (parseExpression(Res))1132return true;1133EndLoc = Lexer.getTok().getEndLoc();1134return parseRParen();1135}11361137/// Parse a bracket expression and return it.1138/// NOTE: This assumes the leading '[' has already been consumed.1139///1140/// bracketexpr ::= expr]1141///1142bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {1143if (parseExpression(Res))1144return true;1145EndLoc = getTok().getEndLoc();1146if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))1147return true;1148return false;1149}11501151/// Parse a primary expression and return it.1152/// primaryexpr ::= (parenexpr1153/// primaryexpr ::= symbol1154/// primaryexpr ::= number1155/// primaryexpr ::= '.'1156/// primaryexpr ::= ~,+,- primaryexpr1157bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,1158AsmTypeInfo *TypeInfo) {1159SMLoc FirstTokenLoc = getLexer().getLoc();1160AsmToken::TokenKind FirstTokenKind = Lexer.getKind();1161switch (FirstTokenKind) {1162default:1163return TokError("unknown token in expression");1164// If we have an error assume that we've already handled it.1165case AsmToken::Error:1166return true;1167case AsmToken::Exclaim:1168Lex(); // Eat the operator.1169if (parsePrimaryExpr(Res, EndLoc, TypeInfo))1170return true;1171Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);1172return false;1173case AsmToken::Dollar:1174case AsmToken::Star:1175case AsmToken::At:1176case AsmToken::String:1177case AsmToken::Identifier: {1178StringRef Identifier;1179if (parseIdentifier(Identifier)) {1180// We may have failed but '$'|'*' may be a valid token in context of1181// the current PC.1182if (getTok().is(AsmToken::Dollar) || getTok().is(AsmToken::Star)) {1183bool ShouldGenerateTempSymbol = false;1184if ((getTok().is(AsmToken::Dollar) && MAI.getDollarIsPC()) ||1185(getTok().is(AsmToken::Star) && MAI.getStarIsPC()))1186ShouldGenerateTempSymbol = true;11871188if (!ShouldGenerateTempSymbol)1189return Error(FirstTokenLoc, "invalid token in expression");11901191// Eat the '$'|'*' token.1192Lex();1193// This is either a '$'|'*' reference, which references the current PC.1194// Emit a temporary label to the streamer and refer to it.1195MCSymbol *Sym = Ctx.createTempSymbol();1196Out.emitLabel(Sym);1197Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,1198getContext());1199EndLoc = FirstTokenLoc;1200return false;1201}1202}1203// Parse symbol variant1204std::pair<StringRef, StringRef> Split;1205if (!MAI.useParensForSymbolVariant()) {1206if (FirstTokenKind == AsmToken::String) {1207if (Lexer.is(AsmToken::At)) {1208Lex(); // eat @1209SMLoc AtLoc = getLexer().getLoc();1210StringRef VName;1211if (parseIdentifier(VName))1212return Error(AtLoc, "expected symbol variant after '@'");12131214Split = std::make_pair(Identifier, VName);1215}1216} else {1217Split = Identifier.split('@');1218}1219} else if (Lexer.is(AsmToken::LParen)) {1220Lex(); // eat '('.1221StringRef VName;1222parseIdentifier(VName);1223if (parseRParen())1224return true;1225Split = std::make_pair(Identifier, VName);1226}12271228EndLoc = SMLoc::getFromPointer(Identifier.end());12291230// This is a symbol reference.1231StringRef SymbolName = Identifier;1232if (SymbolName.empty())1233return Error(getLexer().getLoc(), "expected a symbol reference");12341235MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;12361237// Lookup the symbol variant if used.1238if (!Split.second.empty()) {1239Variant = getTargetParser().getVariantKindForName(Split.second);1240if (Variant != MCSymbolRefExpr::VK_Invalid) {1241SymbolName = Split.first;1242} else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {1243Variant = MCSymbolRefExpr::VK_None;1244} else {1245return Error(SMLoc::getFromPointer(Split.second.begin()),1246"invalid variant '" + Split.second + "'");1247}1248}12491250MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);1251if (!Sym)1252Sym = getContext().getOrCreateSymbol(1253MAI.shouldEmitLabelsInUpperCase() ? SymbolName.upper() : SymbolName);12541255// If this is an absolute variable reference, substitute it now to preserve1256// semantics in the face of reassignment.1257if (Sym->isVariable()) {1258auto V = Sym->getVariableValue(/*SetUsed*/ false);1259bool DoInline = isa<MCConstantExpr>(V) && !Variant;1260if (auto TV = dyn_cast<MCTargetExpr>(V))1261DoInline = TV->inlineAssignedExpr();1262if (DoInline) {1263if (Variant)1264return Error(EndLoc, "unexpected modifier on variable reference");1265Res = Sym->getVariableValue(/*SetUsed*/ false);1266return false;1267}1268}12691270// Otherwise create a symbol ref.1271Res = MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);1272return false;1273}1274case AsmToken::BigNum:1275return TokError("literal value out of range for directive");1276case AsmToken::Integer: {1277SMLoc Loc = getTok().getLoc();1278int64_t IntVal = getTok().getIntVal();1279Res = MCConstantExpr::create(IntVal, getContext());1280EndLoc = Lexer.getTok().getEndLoc();1281Lex(); // Eat token.1282// Look for 'b' or 'f' following an Integer as a directional label1283if (Lexer.getKind() == AsmToken::Identifier) {1284StringRef IDVal = getTok().getString();1285// Lookup the symbol variant if used.1286std::pair<StringRef, StringRef> Split = IDVal.split('@');1287MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;1288if (Split.first.size() != IDVal.size()) {1289Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);1290if (Variant == MCSymbolRefExpr::VK_Invalid)1291return TokError("invalid variant '" + Split.second + "'");1292IDVal = Split.first;1293}1294if (IDVal == "f" || IDVal == "b") {1295MCSymbol *Sym =1296Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");1297Res = MCSymbolRefExpr::create(Sym, Variant, getContext());1298if (IDVal == "b" && Sym->isUndefined())1299return Error(Loc, "directional label undefined");1300DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym));1301EndLoc = Lexer.getTok().getEndLoc();1302Lex(); // Eat identifier.1303}1304}1305return false;1306}1307case AsmToken::Real: {1308APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());1309uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();1310Res = MCConstantExpr::create(IntVal, getContext());1311EndLoc = Lexer.getTok().getEndLoc();1312Lex(); // Eat token.1313return false;1314}1315case AsmToken::Dot: {1316if (!MAI.getDotIsPC())1317return TokError("cannot use . as current PC");13181319// This is a '.' reference, which references the current PC. Emit a1320// temporary label to the streamer and refer to it.1321MCSymbol *Sym = Ctx.createTempSymbol();1322Out.emitLabel(Sym);1323Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());1324EndLoc = Lexer.getTok().getEndLoc();1325Lex(); // Eat identifier.1326return false;1327}1328case AsmToken::LParen:1329Lex(); // Eat the '('.1330return parseParenExpr(Res, EndLoc);1331case AsmToken::LBrac:1332if (!PlatformParser->HasBracketExpressions())1333return TokError("brackets expression not supported on this target");1334Lex(); // Eat the '['.1335return parseBracketExpr(Res, EndLoc);1336case AsmToken::Minus:1337Lex(); // Eat the operator.1338if (parsePrimaryExpr(Res, EndLoc, TypeInfo))1339return true;1340Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);1341return false;1342case AsmToken::Plus:1343Lex(); // Eat the operator.1344if (parsePrimaryExpr(Res, EndLoc, TypeInfo))1345return true;1346Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);1347return false;1348case AsmToken::Tilde:1349Lex(); // Eat the operator.1350if (parsePrimaryExpr(Res, EndLoc, TypeInfo))1351return true;1352Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);1353return false;1354// MIPS unary expression operators. The lexer won't generate these tokens if1355// MCAsmInfo::HasMipsExpressions is false for the target.1356case AsmToken::PercentCall16:1357case AsmToken::PercentCall_Hi:1358case AsmToken::PercentCall_Lo:1359case AsmToken::PercentDtprel_Hi:1360case AsmToken::PercentDtprel_Lo:1361case AsmToken::PercentGot:1362case AsmToken::PercentGot_Disp:1363case AsmToken::PercentGot_Hi:1364case AsmToken::PercentGot_Lo:1365case AsmToken::PercentGot_Ofst:1366case AsmToken::PercentGot_Page:1367case AsmToken::PercentGottprel:1368case AsmToken::PercentGp_Rel:1369case AsmToken::PercentHi:1370case AsmToken::PercentHigher:1371case AsmToken::PercentHighest:1372case AsmToken::PercentLo:1373case AsmToken::PercentNeg:1374case AsmToken::PercentPcrel_Hi:1375case AsmToken::PercentPcrel_Lo:1376case AsmToken::PercentTlsgd:1377case AsmToken::PercentTlsldm:1378case AsmToken::PercentTprel_Hi:1379case AsmToken::PercentTprel_Lo:1380Lex(); // Eat the operator.1381if (Lexer.isNot(AsmToken::LParen))1382return TokError("expected '(' after operator");1383Lex(); // Eat the operator.1384if (parseExpression(Res, EndLoc))1385return true;1386if (parseRParen())1387return true;1388Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx);1389return !Res;1390}1391}13921393bool AsmParser::parseExpression(const MCExpr *&Res) {1394SMLoc EndLoc;1395return parseExpression(Res, EndLoc);1396}13971398const MCExpr *1399AsmParser::applyModifierToExpr(const MCExpr *E,1400MCSymbolRefExpr::VariantKind Variant) {1401// Ask the target implementation about this expression first.1402const MCExpr *NewE = getTargetParser().applyModifierToExpr(E, Variant, Ctx);1403if (NewE)1404return NewE;1405// Recurse over the given expression, rebuilding it to apply the given variant1406// if there is exactly one symbol.1407switch (E->getKind()) {1408case MCExpr::Target:1409case MCExpr::Constant:1410return nullptr;14111412case MCExpr::SymbolRef: {1413const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);14141415if (SRE->getKind() != MCSymbolRefExpr::VK_None) {1416TokError("invalid variant on expression '" + getTok().getIdentifier() +1417"' (already modified)");1418return E;1419}14201421return MCSymbolRefExpr::create(&SRE->getSymbol(), Variant, getContext());1422}14231424case MCExpr::Unary: {1425const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);1426const MCExpr *Sub = applyModifierToExpr(UE->getSubExpr(), Variant);1427if (!Sub)1428return nullptr;1429return MCUnaryExpr::create(UE->getOpcode(), Sub, getContext());1430}14311432case MCExpr::Binary: {1433const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);1434const MCExpr *LHS = applyModifierToExpr(BE->getLHS(), Variant);1435const MCExpr *RHS = applyModifierToExpr(BE->getRHS(), Variant);14361437if (!LHS && !RHS)1438return nullptr;14391440if (!LHS)1441LHS = BE->getLHS();1442if (!RHS)1443RHS = BE->getRHS();14441445return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, getContext());1446}1447}14481449llvm_unreachable("Invalid expression kind!");1450}14511452/// This function checks if the next token is <string> type or arithmetic.1453/// string that begin with character '<' must end with character '>'.1454/// otherwise it is arithmetics.1455/// If the function returns a 'true' value,1456/// the End argument will be filled with the last location pointed to the '>'1457/// character.14581459/// There is a gap between the AltMacro's documentation and the single quote1460/// implementation. GCC does not fully support this feature and so we will not1461/// support it.1462/// TODO: Adding single quote as a string.1463static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {1464assert((StrLoc.getPointer() != nullptr) &&1465"Argument to the function cannot be a NULL value");1466const char *CharPtr = StrLoc.getPointer();1467while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&1468(*CharPtr != '\0')) {1469if (*CharPtr == '!')1470CharPtr++;1471CharPtr++;1472}1473if (*CharPtr == '>') {1474EndLoc = StrLoc.getFromPointer(CharPtr + 1);1475return true;1476}1477return false;1478}14791480/// creating a string without the escape characters '!'.1481static std::string angleBracketString(StringRef AltMacroStr) {1482std::string Res;1483for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {1484if (AltMacroStr[Pos] == '!')1485Pos++;1486Res += AltMacroStr[Pos];1487}1488return Res;1489}14901491/// Parse an expression and return it.1492///1493/// expr ::= expr &&,|| expr -> lowest.1494/// expr ::= expr |,^,&,! expr1495/// expr ::= expr ==,!=,<>,<,<=,>,>= expr1496/// expr ::= expr <<,>> expr1497/// expr ::= expr +,- expr1498/// expr ::= expr *,/,% expr -> highest.1499/// expr ::= primaryexpr1500///1501bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {1502// Parse the expression.1503Res = nullptr;1504if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||1505parseBinOpRHS(1, Res, EndLoc))1506return true;15071508// As a special case, we support 'a op b @ modifier' by rewriting the1509// expression to include the modifier. This is inefficient, but in general we1510// expect users to use 'a@modifier op b'.1511if (parseOptionalToken(AsmToken::At)) {1512if (Lexer.isNot(AsmToken::Identifier))1513return TokError("unexpected symbol modifier following '@'");15141515MCSymbolRefExpr::VariantKind Variant =1516MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier());1517if (Variant == MCSymbolRefExpr::VK_Invalid)1518return TokError("invalid variant '" + getTok().getIdentifier() + "'");15191520const MCExpr *ModifiedRes = applyModifierToExpr(Res, Variant);1521if (!ModifiedRes) {1522return TokError("invalid modifier '" + getTok().getIdentifier() +1523"' (no symbols present)");1524}15251526Res = ModifiedRes;1527Lex();1528}15291530// Try to constant fold it up front, if possible. Do not exploit1531// assembler here.1532int64_t Value;1533if (Res->evaluateAsAbsolute(Value))1534Res = MCConstantExpr::create(Value, getContext());15351536return false;1537}15381539bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {1540Res = nullptr;1541return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);1542}15431544bool AsmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,1545SMLoc &EndLoc) {1546if (parseParenExpr(Res, EndLoc))1547return true;15481549for (; ParenDepth > 0; --ParenDepth) {1550if (parseBinOpRHS(1, Res, EndLoc))1551return true;15521553// We don't Lex() the last RParen.1554// This is the same behavior as parseParenExpression().1555if (ParenDepth - 1 > 0) {1556EndLoc = getTok().getEndLoc();1557if (parseRParen())1558return true;1559}1560}1561return false;1562}15631564bool AsmParser::parseAbsoluteExpression(int64_t &Res) {1565const MCExpr *Expr;15661567SMLoc StartLoc = Lexer.getLoc();1568if (parseExpression(Expr))1569return true;15701571if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))1572return Error(StartLoc, "expected absolute expression");15731574return false;1575}15761577static unsigned getDarwinBinOpPrecedence(AsmToken::TokenKind K,1578MCBinaryExpr::Opcode &Kind,1579bool ShouldUseLogicalShr) {1580switch (K) {1581default:1582return 0; // not a binop.15831584// Lowest Precedence: &&, ||1585case AsmToken::AmpAmp:1586Kind = MCBinaryExpr::LAnd;1587return 1;1588case AsmToken::PipePipe:1589Kind = MCBinaryExpr::LOr;1590return 1;15911592// Low Precedence: |, &, ^1593case AsmToken::Pipe:1594Kind = MCBinaryExpr::Or;1595return 2;1596case AsmToken::Caret:1597Kind = MCBinaryExpr::Xor;1598return 2;1599case AsmToken::Amp:1600Kind = MCBinaryExpr::And;1601return 2;16021603// Low Intermediate Precedence: ==, !=, <>, <, <=, >, >=1604case AsmToken::EqualEqual:1605Kind = MCBinaryExpr::EQ;1606return 3;1607case AsmToken::ExclaimEqual:1608case AsmToken::LessGreater:1609Kind = MCBinaryExpr::NE;1610return 3;1611case AsmToken::Less:1612Kind = MCBinaryExpr::LT;1613return 3;1614case AsmToken::LessEqual:1615Kind = MCBinaryExpr::LTE;1616return 3;1617case AsmToken::Greater:1618Kind = MCBinaryExpr::GT;1619return 3;1620case AsmToken::GreaterEqual:1621Kind = MCBinaryExpr::GTE;1622return 3;16231624// Intermediate Precedence: <<, >>1625case AsmToken::LessLess:1626Kind = MCBinaryExpr::Shl;1627return 4;1628case AsmToken::GreaterGreater:1629Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;1630return 4;16311632// High Intermediate Precedence: +, -1633case AsmToken::Plus:1634Kind = MCBinaryExpr::Add;1635return 5;1636case AsmToken::Minus:1637Kind = MCBinaryExpr::Sub;1638return 5;16391640// Highest Precedence: *, /, %1641case AsmToken::Star:1642Kind = MCBinaryExpr::Mul;1643return 6;1644case AsmToken::Slash:1645Kind = MCBinaryExpr::Div;1646return 6;1647case AsmToken::Percent:1648Kind = MCBinaryExpr::Mod;1649return 6;1650}1651}16521653static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI,1654AsmToken::TokenKind K,1655MCBinaryExpr::Opcode &Kind,1656bool ShouldUseLogicalShr) {1657switch (K) {1658default:1659return 0; // not a binop.16601661// Lowest Precedence: &&, ||1662case AsmToken::AmpAmp:1663Kind = MCBinaryExpr::LAnd;1664return 2;1665case AsmToken::PipePipe:1666Kind = MCBinaryExpr::LOr;1667return 1;16681669// Low Precedence: ==, !=, <>, <, <=, >, >=1670case AsmToken::EqualEqual:1671Kind = MCBinaryExpr::EQ;1672return 3;1673case AsmToken::ExclaimEqual:1674case AsmToken::LessGreater:1675Kind = MCBinaryExpr::NE;1676return 3;1677case AsmToken::Less:1678Kind = MCBinaryExpr::LT;1679return 3;1680case AsmToken::LessEqual:1681Kind = MCBinaryExpr::LTE;1682return 3;1683case AsmToken::Greater:1684Kind = MCBinaryExpr::GT;1685return 3;1686case AsmToken::GreaterEqual:1687Kind = MCBinaryExpr::GTE;1688return 3;16891690// Low Intermediate Precedence: +, -1691case AsmToken::Plus:1692Kind = MCBinaryExpr::Add;1693return 4;1694case AsmToken::Minus:1695Kind = MCBinaryExpr::Sub;1696return 4;16971698// High Intermediate Precedence: |, !, &, ^1699//1700case AsmToken::Pipe:1701Kind = MCBinaryExpr::Or;1702return 5;1703case AsmToken::Exclaim:1704// Hack to support ARM compatible aliases (implied 'sp' operand in 'srs*'1705// instructions like 'srsda #31!') and not parse ! as an infix operator.1706if (MAI.getCommentString() == "@")1707return 0;1708Kind = MCBinaryExpr::OrNot;1709return 5;1710case AsmToken::Caret:1711Kind = MCBinaryExpr::Xor;1712return 5;1713case AsmToken::Amp:1714Kind = MCBinaryExpr::And;1715return 5;17161717// Highest Precedence: *, /, %, <<, >>1718case AsmToken::Star:1719Kind = MCBinaryExpr::Mul;1720return 6;1721case AsmToken::Slash:1722Kind = MCBinaryExpr::Div;1723return 6;1724case AsmToken::Percent:1725Kind = MCBinaryExpr::Mod;1726return 6;1727case AsmToken::LessLess:1728Kind = MCBinaryExpr::Shl;1729return 6;1730case AsmToken::GreaterGreater:1731Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;1732return 6;1733}1734}17351736unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K,1737MCBinaryExpr::Opcode &Kind) {1738bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();1739return IsDarwin ? getDarwinBinOpPrecedence(K, Kind, ShouldUseLogicalShr)1740: getGNUBinOpPrecedence(MAI, K, Kind, ShouldUseLogicalShr);1741}17421743/// Parse all binary operators with precedence >= 'Precedence'.1744/// Res contains the LHS of the expression on input.1745bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,1746SMLoc &EndLoc) {1747SMLoc StartLoc = Lexer.getLoc();1748while (true) {1749MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;1750unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);17511752// If the next token is lower precedence than we are allowed to eat, return1753// successfully with what we ate already.1754if (TokPrec < Precedence)1755return false;17561757Lex();17581759// Eat the next primary expression.1760const MCExpr *RHS;1761if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))1762return true;17631764// If BinOp binds less tightly with RHS than the operator after RHS, let1765// the pending operator take RHS as its LHS.1766MCBinaryExpr::Opcode Dummy;1767unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);1768if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))1769return true;17701771// Merge LHS and RHS according to operator.1772Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);1773}1774}17751776/// ParseStatement:1777/// ::= EndOfStatement1778/// ::= Label* Directive ...Operands... EndOfStatement1779/// ::= Label* Identifier OperandList* EndOfStatement1780bool AsmParser::parseStatement(ParseStatementInfo &Info,1781MCAsmParserSemaCallback *SI) {1782assert(!hasPendingError() && "parseStatement started with pending error");1783// Eat initial spaces and comments1784while (Lexer.is(AsmToken::Space))1785Lex();1786if (Lexer.is(AsmToken::EndOfStatement)) {1787// if this is a line comment we can drop it safely1788if (getTok().getString().empty() || getTok().getString().front() == '\r' ||1789getTok().getString().front() == '\n')1790Out.addBlankLine();1791Lex();1792return false;1793}1794// Statements always start with an identifier.1795AsmToken ID = getTok();1796SMLoc IDLoc = ID.getLoc();1797StringRef IDVal;1798int64_t LocalLabelVal = -1;1799StartTokLoc = ID.getLoc();1800if (Lexer.is(AsmToken::HashDirective))1801return parseCppHashLineFilenameComment(IDLoc,1802!isInsideMacroInstantiation());18031804// Allow an integer followed by a ':' as a directional local label.1805if (Lexer.is(AsmToken::Integer)) {1806LocalLabelVal = getTok().getIntVal();1807if (LocalLabelVal < 0) {1808if (!TheCondState.Ignore) {1809Lex(); // always eat a token1810return Error(IDLoc, "unexpected token at start of statement");1811}1812IDVal = "";1813} else {1814IDVal = getTok().getString();1815Lex(); // Consume the integer token to be used as an identifier token.1816if (Lexer.getKind() != AsmToken::Colon) {1817if (!TheCondState.Ignore) {1818Lex(); // always eat a token1819return Error(IDLoc, "unexpected token at start of statement");1820}1821}1822}1823} else if (Lexer.is(AsmToken::Dot)) {1824// Treat '.' as a valid identifier in this context.1825Lex();1826IDVal = ".";1827} else if (Lexer.is(AsmToken::LCurly)) {1828// Treat '{' as a valid identifier in this context.1829Lex();1830IDVal = "{";18311832} else if (Lexer.is(AsmToken::RCurly)) {1833// Treat '}' as a valid identifier in this context.1834Lex();1835IDVal = "}";1836} else if (Lexer.is(AsmToken::Star) &&1837getTargetParser().starIsStartOfStatement()) {1838// Accept '*' as a valid start of statement.1839Lex();1840IDVal = "*";1841} else if (parseIdentifier(IDVal)) {1842if (!TheCondState.Ignore) {1843Lex(); // always eat a token1844return Error(IDLoc, "unexpected token at start of statement");1845}1846IDVal = "";1847}18481849// Handle conditional assembly here before checking for skipping. We1850// have to do this so that .endif isn't skipped in a ".if 0" block for1851// example.1852StringMap<DirectiveKind>::const_iterator DirKindIt =1853DirectiveKindMap.find(IDVal.lower());1854DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())1855? DK_NO_DIRECTIVE1856: DirKindIt->getValue();1857switch (DirKind) {1858default:1859break;1860case DK_IF:1861case DK_IFEQ:1862case DK_IFGE:1863case DK_IFGT:1864case DK_IFLE:1865case DK_IFLT:1866case DK_IFNE:1867return parseDirectiveIf(IDLoc, DirKind);1868case DK_IFB:1869return parseDirectiveIfb(IDLoc, true);1870case DK_IFNB:1871return parseDirectiveIfb(IDLoc, false);1872case DK_IFC:1873return parseDirectiveIfc(IDLoc, true);1874case DK_IFEQS:1875return parseDirectiveIfeqs(IDLoc, true);1876case DK_IFNC:1877return parseDirectiveIfc(IDLoc, false);1878case DK_IFNES:1879return parseDirectiveIfeqs(IDLoc, false);1880case DK_IFDEF:1881return parseDirectiveIfdef(IDLoc, true);1882case DK_IFNDEF:1883case DK_IFNOTDEF:1884return parseDirectiveIfdef(IDLoc, false);1885case DK_ELSEIF:1886return parseDirectiveElseIf(IDLoc);1887case DK_ELSE:1888return parseDirectiveElse(IDLoc);1889case DK_ENDIF:1890return parseDirectiveEndIf(IDLoc);1891}18921893// Ignore the statement if in the middle of inactive conditional1894// (e.g. ".if 0").1895if (TheCondState.Ignore) {1896eatToEndOfStatement();1897return false;1898}18991900// FIXME: Recurse on local labels?19011902// Check for a label.1903// ::= identifier ':'1904// ::= number ':'1905if (Lexer.is(AsmToken::Colon) && getTargetParser().isLabel(ID)) {1906if (checkForValidSection())1907return true;19081909Lex(); // Consume the ':'.19101911// Diagnose attempt to use '.' as a label.1912if (IDVal == ".")1913return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");19141915// Diagnose attempt to use a variable as a label.1916//1917// FIXME: Diagnostics. Note the location of the definition as a label.1918// FIXME: This doesn't diagnose assignment to a symbol which has been1919// implicitly marked as external.1920MCSymbol *Sym;1921if (LocalLabelVal == -1) {1922if (ParsingMSInlineAsm && SI) {1923StringRef RewrittenLabel =1924SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);1925assert(!RewrittenLabel.empty() &&1926"We should have an internal name here.");1927Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),1928RewrittenLabel);1929IDVal = RewrittenLabel;1930}1931Sym = getContext().getOrCreateSymbol(IDVal);1932} else1933Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);1934// End of Labels should be treated as end of line for lexing1935// purposes but that information is not available to the Lexer who1936// does not understand Labels. This may cause us to see a Hash1937// here instead of a preprocessor line comment.1938if (getTok().is(AsmToken::Hash)) {1939StringRef CommentStr = parseStringToEndOfStatement();1940Lexer.Lex();1941Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));1942}19431944// Consume any end of statement token, if present, to avoid spurious1945// addBlankLine calls().1946if (getTok().is(AsmToken::EndOfStatement)) {1947Lex();1948}19491950if (MAI.hasSubsectionsViaSymbols() && CFIStartProcLoc &&1951Sym->isExternal() && !cast<MCSymbolMachO>(Sym)->isAltEntry())1952return Error(StartTokLoc, "non-private labels cannot appear between "1953".cfi_startproc / .cfi_endproc pairs") &&1954Error(*CFIStartProcLoc, "previous .cfi_startproc was here");19551956if (discardLTOSymbol(IDVal))1957return false;19581959getTargetParser().doBeforeLabelEmit(Sym, IDLoc);19601961// Emit the label.1962if (!getTargetParser().isParsingMSInlineAsm())1963Out.emitLabel(Sym, IDLoc);19641965// If we are generating dwarf for assembly source files then gather the1966// info to make a dwarf label entry for this label if needed.1967if (enabledGenDwarfForAssembly())1968MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),1969IDLoc);19701971getTargetParser().onLabelParsed(Sym);19721973return false;1974}19751976// Check for an assignment statement.1977// ::= identifier '='1978if (Lexer.is(AsmToken::Equal) && getTargetParser().equalIsAsmAssignment()) {1979Lex();1980return parseAssignment(IDVal, AssignmentKind::Equal);1981}19821983// If macros are enabled, check to see if this is a macro instantiation.1984if (areMacrosEnabled())1985if (MCAsmMacro *M = getContext().lookupMacro(IDVal))1986return handleMacroEntry(M, IDLoc);19871988// Otherwise, we have a normal instruction or directive.19891990// Directives start with "."1991if (IDVal.starts_with(".") && IDVal != ".") {1992// There are several entities interested in parsing directives:1993//1994// 1. The target-specific assembly parser. Some directives are target1995// specific or may potentially behave differently on certain targets.1996// 2. Asm parser extensions. For example, platform-specific parsers1997// (like the ELF parser) register themselves as extensions.1998// 3. The generic directive parser implemented by this class. These are1999// all the directives that behave in a target and platform independent2000// manner, or at least have a default behavior that's shared between2001// all targets and platforms.20022003getTargetParser().flushPendingInstructions(getStreamer());20042005ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(ID);2006assert(TPDirectiveReturn.isFailure() == hasPendingError() &&2007"Should only return Failure iff there was an error");2008if (TPDirectiveReturn.isFailure())2009return true;2010if (TPDirectiveReturn.isSuccess())2011return false;20122013// Next, check the extension directive map to see if any extension has2014// registered itself to parse this directive.2015std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =2016ExtensionDirectiveMap.lookup(IDVal);2017if (Handler.first)2018return (*Handler.second)(Handler.first, IDVal, IDLoc);20192020// Finally, if no one else is interested in this directive, it must be2021// generic and familiar to this class.2022switch (DirKind) {2023default:2024break;2025case DK_SET:2026case DK_EQU:2027return parseDirectiveSet(IDVal, AssignmentKind::Set);2028case DK_EQUIV:2029return parseDirectiveSet(IDVal, AssignmentKind::Equiv);2030case DK_LTO_SET_CONDITIONAL:2031return parseDirectiveSet(IDVal, AssignmentKind::LTOSetConditional);2032case DK_ASCII:2033return parseDirectiveAscii(IDVal, false);2034case DK_ASCIZ:2035case DK_STRING:2036return parseDirectiveAscii(IDVal, true);2037case DK_BYTE:2038case DK_DC_B:2039return parseDirectiveValue(IDVal, 1);2040case DK_DC:2041case DK_DC_W:2042case DK_SHORT:2043case DK_VALUE:2044case DK_2BYTE:2045return parseDirectiveValue(IDVal, 2);2046case DK_LONG:2047case DK_INT:2048case DK_4BYTE:2049case DK_DC_L:2050return parseDirectiveValue(IDVal, 4);2051case DK_QUAD:2052case DK_8BYTE:2053return parseDirectiveValue(IDVal, 8);2054case DK_DC_A:2055return parseDirectiveValue(2056IDVal, getContext().getAsmInfo()->getCodePointerSize());2057case DK_OCTA:2058return parseDirectiveOctaValue(IDVal);2059case DK_SINGLE:2060case DK_FLOAT:2061case DK_DC_S:2062return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle());2063case DK_DOUBLE:2064case DK_DC_D:2065return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble());2066case DK_ALIGN: {2067bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();2068return parseDirectiveAlign(IsPow2, /*ExprSize=*/1);2069}2070case DK_ALIGN32: {2071bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();2072return parseDirectiveAlign(IsPow2, /*ExprSize=*/4);2073}2074case DK_BALIGN:2075return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);2076case DK_BALIGNW:2077return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);2078case DK_BALIGNL:2079return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);2080case DK_P2ALIGN:2081return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);2082case DK_P2ALIGNW:2083return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);2084case DK_P2ALIGNL:2085return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);2086case DK_ORG:2087return parseDirectiveOrg();2088case DK_FILL:2089return parseDirectiveFill();2090case DK_ZERO:2091return parseDirectiveZero();2092case DK_EXTERN:2093eatToEndOfStatement(); // .extern is the default, ignore it.2094return false;2095case DK_GLOBL:2096case DK_GLOBAL:2097return parseDirectiveSymbolAttribute(MCSA_Global);2098case DK_LAZY_REFERENCE:2099return parseDirectiveSymbolAttribute(MCSA_LazyReference);2100case DK_NO_DEAD_STRIP:2101return parseDirectiveSymbolAttribute(MCSA_NoDeadStrip);2102case DK_SYMBOL_RESOLVER:2103return parseDirectiveSymbolAttribute(MCSA_SymbolResolver);2104case DK_PRIVATE_EXTERN:2105return parseDirectiveSymbolAttribute(MCSA_PrivateExtern);2106case DK_REFERENCE:2107return parseDirectiveSymbolAttribute(MCSA_Reference);2108case DK_WEAK_DEFINITION:2109return parseDirectiveSymbolAttribute(MCSA_WeakDefinition);2110case DK_WEAK_REFERENCE:2111return parseDirectiveSymbolAttribute(MCSA_WeakReference);2112case DK_WEAK_DEF_CAN_BE_HIDDEN:2113return parseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);2114case DK_COLD:2115return parseDirectiveSymbolAttribute(MCSA_Cold);2116case DK_COMM:2117case DK_COMMON:2118return parseDirectiveComm(/*IsLocal=*/false);2119case DK_LCOMM:2120return parseDirectiveComm(/*IsLocal=*/true);2121case DK_ABORT:2122return parseDirectiveAbort(IDLoc);2123case DK_INCLUDE:2124return parseDirectiveInclude();2125case DK_INCBIN:2126return parseDirectiveIncbin();2127case DK_CODE16:2128case DK_CODE16GCC:2129return TokError(Twine(IDVal) +2130" not currently supported for this target");2131case DK_REPT:2132return parseDirectiveRept(IDLoc, IDVal);2133case DK_IRP:2134return parseDirectiveIrp(IDLoc);2135case DK_IRPC:2136return parseDirectiveIrpc(IDLoc);2137case DK_ENDR:2138return parseDirectiveEndr(IDLoc);2139case DK_BUNDLE_ALIGN_MODE:2140return parseDirectiveBundleAlignMode();2141case DK_BUNDLE_LOCK:2142return parseDirectiveBundleLock();2143case DK_BUNDLE_UNLOCK:2144return parseDirectiveBundleUnlock();2145case DK_SLEB128:2146return parseDirectiveLEB128(true);2147case DK_ULEB128:2148return parseDirectiveLEB128(false);2149case DK_SPACE:2150case DK_SKIP:2151return parseDirectiveSpace(IDVal);2152case DK_FILE:2153return parseDirectiveFile(IDLoc);2154case DK_LINE:2155return parseDirectiveLine();2156case DK_LOC:2157return parseDirectiveLoc();2158case DK_STABS:2159return parseDirectiveStabs();2160case DK_CV_FILE:2161return parseDirectiveCVFile();2162case DK_CV_FUNC_ID:2163return parseDirectiveCVFuncId();2164case DK_CV_INLINE_SITE_ID:2165return parseDirectiveCVInlineSiteId();2166case DK_CV_LOC:2167return parseDirectiveCVLoc();2168case DK_CV_LINETABLE:2169return parseDirectiveCVLinetable();2170case DK_CV_INLINE_LINETABLE:2171return parseDirectiveCVInlineLinetable();2172case DK_CV_DEF_RANGE:2173return parseDirectiveCVDefRange();2174case DK_CV_STRING:2175return parseDirectiveCVString();2176case DK_CV_STRINGTABLE:2177return parseDirectiveCVStringTable();2178case DK_CV_FILECHECKSUMS:2179return parseDirectiveCVFileChecksums();2180case DK_CV_FILECHECKSUM_OFFSET:2181return parseDirectiveCVFileChecksumOffset();2182case DK_CV_FPO_DATA:2183return parseDirectiveCVFPOData();2184case DK_CFI_SECTIONS:2185return parseDirectiveCFISections();2186case DK_CFI_STARTPROC:2187return parseDirectiveCFIStartProc();2188case DK_CFI_ENDPROC:2189return parseDirectiveCFIEndProc();2190case DK_CFI_DEF_CFA:2191return parseDirectiveCFIDefCfa(IDLoc);2192case DK_CFI_DEF_CFA_OFFSET:2193return parseDirectiveCFIDefCfaOffset(IDLoc);2194case DK_CFI_ADJUST_CFA_OFFSET:2195return parseDirectiveCFIAdjustCfaOffset(IDLoc);2196case DK_CFI_DEF_CFA_REGISTER:2197return parseDirectiveCFIDefCfaRegister(IDLoc);2198case DK_CFI_LLVM_DEF_ASPACE_CFA:2199return parseDirectiveCFILLVMDefAspaceCfa(IDLoc);2200case DK_CFI_OFFSET:2201return parseDirectiveCFIOffset(IDLoc);2202case DK_CFI_REL_OFFSET:2203return parseDirectiveCFIRelOffset(IDLoc);2204case DK_CFI_PERSONALITY:2205return parseDirectiveCFIPersonalityOrLsda(true);2206case DK_CFI_LSDA:2207return parseDirectiveCFIPersonalityOrLsda(false);2208case DK_CFI_REMEMBER_STATE:2209return parseDirectiveCFIRememberState(IDLoc);2210case DK_CFI_RESTORE_STATE:2211return parseDirectiveCFIRestoreState(IDLoc);2212case DK_CFI_SAME_VALUE:2213return parseDirectiveCFISameValue(IDLoc);2214case DK_CFI_RESTORE:2215return parseDirectiveCFIRestore(IDLoc);2216case DK_CFI_ESCAPE:2217return parseDirectiveCFIEscape(IDLoc);2218case DK_CFI_RETURN_COLUMN:2219return parseDirectiveCFIReturnColumn(IDLoc);2220case DK_CFI_SIGNAL_FRAME:2221return parseDirectiveCFISignalFrame(IDLoc);2222case DK_CFI_UNDEFINED:2223return parseDirectiveCFIUndefined(IDLoc);2224case DK_CFI_REGISTER:2225return parseDirectiveCFIRegister(IDLoc);2226case DK_CFI_WINDOW_SAVE:2227return parseDirectiveCFIWindowSave(IDLoc);2228case DK_CFI_LABEL:2229return parseDirectiveCFILabel(IDLoc);2230case DK_MACROS_ON:2231case DK_MACROS_OFF:2232return parseDirectiveMacrosOnOff(IDVal);2233case DK_MACRO:2234return parseDirectiveMacro(IDLoc);2235case DK_ALTMACRO:2236case DK_NOALTMACRO:2237return parseDirectiveAltmacro(IDVal);2238case DK_EXITM:2239return parseDirectiveExitMacro(IDVal);2240case DK_ENDM:2241case DK_ENDMACRO:2242return parseDirectiveEndMacro(IDVal);2243case DK_PURGEM:2244return parseDirectivePurgeMacro(IDLoc);2245case DK_END:2246return parseDirectiveEnd(IDLoc);2247case DK_ERR:2248return parseDirectiveError(IDLoc, false);2249case DK_ERROR:2250return parseDirectiveError(IDLoc, true);2251case DK_WARNING:2252return parseDirectiveWarning(IDLoc);2253case DK_RELOC:2254return parseDirectiveReloc(IDLoc);2255case DK_DCB:2256case DK_DCB_W:2257return parseDirectiveDCB(IDVal, 2);2258case DK_DCB_B:2259return parseDirectiveDCB(IDVal, 1);2260case DK_DCB_D:2261return parseDirectiveRealDCB(IDVal, APFloat::IEEEdouble());2262case DK_DCB_L:2263return parseDirectiveDCB(IDVal, 4);2264case DK_DCB_S:2265return parseDirectiveRealDCB(IDVal, APFloat::IEEEsingle());2266case DK_DC_X:2267case DK_DCB_X:2268return TokError(Twine(IDVal) +2269" not currently supported for this target");2270case DK_DS:2271case DK_DS_W:2272return parseDirectiveDS(IDVal, 2);2273case DK_DS_B:2274return parseDirectiveDS(IDVal, 1);2275case DK_DS_D:2276return parseDirectiveDS(IDVal, 8);2277case DK_DS_L:2278case DK_DS_S:2279return parseDirectiveDS(IDVal, 4);2280case DK_DS_P:2281case DK_DS_X:2282return parseDirectiveDS(IDVal, 12);2283case DK_PRINT:2284return parseDirectivePrint(IDLoc);2285case DK_ADDRSIG:2286return parseDirectiveAddrsig();2287case DK_ADDRSIG_SYM:2288return parseDirectiveAddrsigSym();2289case DK_PSEUDO_PROBE:2290return parseDirectivePseudoProbe();2291case DK_LTO_DISCARD:2292return parseDirectiveLTODiscard();2293case DK_MEMTAG:2294return parseDirectiveSymbolAttribute(MCSA_Memtag);2295}22962297return Error(IDLoc, "unknown directive");2298}22992300// __asm _emit or __asm __emit2301if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||2302IDVal == "_EMIT" || IDVal == "__EMIT"))2303return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());23042305// __asm align2306if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))2307return parseDirectiveMSAlign(IDLoc, Info);23082309if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))2310Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);2311if (checkForValidSection())2312return true;23132314return parseAndMatchAndEmitTargetInstruction(Info, IDVal, ID, IDLoc);2315}23162317bool AsmParser::parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info,2318StringRef IDVal,2319AsmToken ID,2320SMLoc IDLoc) {2321// Canonicalize the opcode to lower case.2322std::string OpcodeStr = IDVal.lower();2323ParseInstructionInfo IInfo(Info.AsmRewrites);2324bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,2325Info.ParsedOperands);2326Info.ParseError = ParseHadError;23272328// Dump the parsed representation, if requested.2329if (getShowParsedOperands()) {2330SmallString<256> Str;2331raw_svector_ostream OS(Str);2332OS << "parsed instruction: [";2333for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {2334if (i != 0)2335OS << ", ";2336Info.ParsedOperands[i]->print(OS);2337}2338OS << "]";23392340printMessage(IDLoc, SourceMgr::DK_Note, OS.str());2341}23422343// Fail even if ParseInstruction erroneously returns false.2344if (hasPendingError() || ParseHadError)2345return true;23462347// If we are generating dwarf for the current section then generate a .loc2348// directive for the instruction.2349if (!ParseHadError && enabledGenDwarfForAssembly() &&2350getContext().getGenDwarfSectionSyms().count(2351getStreamer().getCurrentSectionOnly())) {2352unsigned Line;2353if (ActiveMacros.empty())2354Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);2355else2356Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,2357ActiveMacros.front()->ExitBuffer);23582359// If we previously parsed a cpp hash file line comment then make sure the2360// current Dwarf File is for the CppHashFilename if not then emit the2361// Dwarf File table for it and adjust the line number for the .loc.2362if (!CppHashInfo.Filename.empty()) {2363unsigned FileNumber = getStreamer().emitDwarfFileDirective(23640, StringRef(), CppHashInfo.Filename);2365getContext().setGenDwarfFileNumber(FileNumber);23662367unsigned CppHashLocLineNo =2368SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);2369Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);2370}23712372getStreamer().emitDwarfLocDirective(2373getContext().getGenDwarfFileNumber(), Line, 0,2374DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0,2375StringRef());2376}23772378// If parsing succeeded, match the instruction.2379if (!ParseHadError) {2380uint64_t ErrorInfo;2381if (getTargetParser().MatchAndEmitInstruction(2382IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,2383getTargetParser().isParsingMSInlineAsm()))2384return true;2385}2386return false;2387}23882389// Parse and erase curly braces marking block start/end2390bool2391AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {2392// Identify curly brace marking block start/end2393if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))2394return false;23952396SMLoc StartLoc = Lexer.getLoc();2397Lex(); // Eat the brace2398if (Lexer.is(AsmToken::EndOfStatement))2399Lex(); // Eat EndOfStatement following the brace24002401// Erase the block start/end brace from the output asm string2402AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -2403StartLoc.getPointer());2404return true;2405}24062407/// parseCppHashLineFilenameComment as this:2408/// ::= # number "filename"2409bool AsmParser::parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo) {2410Lex(); // Eat the hash token.2411// Lexer only ever emits HashDirective if it fully formed if it's2412// done the checking already so this is an internal error.2413assert(getTok().is(AsmToken::Integer) &&2414"Lexing Cpp line comment: Expected Integer");2415int64_t LineNumber = getTok().getIntVal();2416Lex();2417assert(getTok().is(AsmToken::String) &&2418"Lexing Cpp line comment: Expected String");2419StringRef Filename = getTok().getString();2420Lex();24212422if (!SaveLocInfo)2423return false;24242425// Get rid of the enclosing quotes.2426Filename = Filename.substr(1, Filename.size() - 2);24272428// Save the SMLoc, Filename and LineNumber for later use by diagnostics2429// and possibly DWARF file info.2430CppHashInfo.Loc = L;2431CppHashInfo.Filename = Filename;2432CppHashInfo.LineNumber = LineNumber;2433CppHashInfo.Buf = CurBuffer;2434if (FirstCppHashFilename.empty())2435FirstCppHashFilename = Filename;2436return false;2437}24382439/// will use the last parsed cpp hash line filename comment2440/// for the Filename and LineNo if any in the diagnostic.2441void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {2442auto *Parser = static_cast<AsmParser *>(Context);2443raw_ostream &OS = errs();24442445const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();2446SMLoc DiagLoc = Diag.getLoc();2447unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);2448unsigned CppHashBuf =2449Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);24502451// Like SourceMgr::printMessage() we need to print the include stack if any2452// before printing the message.2453unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);2454if (!Parser->SavedDiagHandler && DiagCurBuffer &&2455DiagCurBuffer != DiagSrcMgr.getMainFileID()) {2456SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);2457DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);2458}24592460// If we have not parsed a cpp hash line filename comment or the source2461// manager changed or buffer changed (like in a nested include) then just2462// print the normal diagnostic using its Filename and LineNo.2463if (!Parser->CppHashInfo.LineNumber || DiagBuf != CppHashBuf) {2464if (Parser->SavedDiagHandler)2465Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);2466else2467Parser->getContext().diagnose(Diag);2468return;2469}24702471// Use the CppHashFilename and calculate a line number based on the2472// CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc2473// for the diagnostic.2474const std::string &Filename = std::string(Parser->CppHashInfo.Filename);24752476int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);2477int CppHashLocLineNo =2478Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);2479int LineNo =2480Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);24812482SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,2483Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),2484Diag.getLineContents(), Diag.getRanges());24852486if (Parser->SavedDiagHandler)2487Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);2488else2489Parser->getContext().diagnose(NewDiag);2490}24912492// FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The2493// difference being that that function accepts '@' as part of identifiers and2494// we can't do that. AsmLexer.cpp should probably be changed to handle2495// '@' as a special case when needed.2496static bool isIdentifierChar(char c) {2497return isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$' ||2498c == '.';2499}25002501bool AsmParser::expandMacro(raw_svector_ostream &OS, MCAsmMacro &Macro,2502ArrayRef<MCAsmMacroParameter> Parameters,2503ArrayRef<MCAsmMacroArgument> A,2504bool EnableAtPseudoVariable) {2505unsigned NParameters = Parameters.size();2506auto expandArg = [&](unsigned Index) {2507bool HasVararg = NParameters ? Parameters.back().Vararg : false;2508bool VarargParameter = HasVararg && Index == (NParameters - 1);2509for (const AsmToken &Token : A[Index])2510// For altmacro mode, you can write '%expr'.2511// The prefix '%' evaluates the expression 'expr'2512// and uses the result as a string (e.g. replace %(1+2) with the2513// string "3").2514// Here, we identify the integer token which is the result of the2515// absolute expression evaluation and replace it with its string2516// representation.2517if (AltMacroMode && Token.getString().front() == '%' &&2518Token.is(AsmToken::Integer))2519// Emit an integer value to the buffer.2520OS << Token.getIntVal();2521// Only Token that was validated as a string and begins with '<'2522// is considered altMacroString!!!2523else if (AltMacroMode && Token.getString().front() == '<' &&2524Token.is(AsmToken::String)) {2525OS << angleBracketString(Token.getStringContents());2526}2527// We expect no quotes around the string's contents when2528// parsing for varargs.2529else if (Token.isNot(AsmToken::String) || VarargParameter)2530OS << Token.getString();2531else2532OS << Token.getStringContents();2533};25342535// A macro without parameters is handled differently on Darwin:2536// gas accepts no arguments and does no substitutions2537StringRef Body = Macro.Body;2538size_t I = 0, End = Body.size();2539while (I != End) {2540if (Body[I] == '\\' && I + 1 != End) {2541// Check for \@ and \+ pseudo variables.2542if (EnableAtPseudoVariable && Body[I + 1] == '@') {2543OS << NumOfMacroInstantiations;2544I += 2;2545continue;2546}2547if (Body[I + 1] == '+') {2548OS << Macro.Count;2549I += 2;2550continue;2551}2552if (Body[I + 1] == '(' && Body[I + 2] == ')') {2553I += 3;2554continue;2555}25562557size_t Pos = ++I;2558while (I != End && isIdentifierChar(Body[I]))2559++I;2560StringRef Argument(Body.data() + Pos, I - Pos);2561if (AltMacroMode && I != End && Body[I] == '&')2562++I;2563unsigned Index = 0;2564for (; Index < NParameters; ++Index)2565if (Parameters[Index].Name == Argument)2566break;2567if (Index == NParameters)2568OS << '\\' << Argument;2569else2570expandArg(Index);2571continue;2572}25732574// In Darwin mode, $ is used for macro expansion, not considered an2575// identifier char.2576if (Body[I] == '$' && I + 1 != End && IsDarwin && !NParameters) {2577// This macro has no parameters, look for $0, $1, etc.2578switch (Body[I + 1]) {2579// $$ => $2580case '$':2581OS << '$';2582I += 2;2583continue;2584// $n => number of arguments2585case 'n':2586OS << A.size();2587I += 2;2588continue;2589default: {2590if (!isDigit(Body[I + 1]))2591break;2592// $[0-9] => argument2593// Missing arguments are ignored.2594unsigned Index = Body[I + 1] - '0';2595if (Index < A.size())2596for (const AsmToken &Token : A[Index])2597OS << Token.getString();2598I += 2;2599continue;2600}2601}2602}26032604if (!isIdentifierChar(Body[I]) || IsDarwin) {2605OS << Body[I++];2606continue;2607}26082609const size_t Start = I;2610while (++I && isIdentifierChar(Body[I])) {2611}2612StringRef Token(Body.data() + Start, I - Start);2613if (AltMacroMode) {2614unsigned Index = 0;2615for (; Index != NParameters; ++Index)2616if (Parameters[Index].Name == Token)2617break;2618if (Index != NParameters) {2619expandArg(Index);2620if (I != End && Body[I] == '&')2621++I;2622continue;2623}2624}2625OS << Token;2626}26272628++Macro.Count;2629return false;2630}26312632static bool isOperator(AsmToken::TokenKind kind) {2633switch (kind) {2634default:2635return false;2636case AsmToken::Plus:2637case AsmToken::Minus:2638case AsmToken::Tilde:2639case AsmToken::Slash:2640case AsmToken::Star:2641case AsmToken::Dot:2642case AsmToken::Equal:2643case AsmToken::EqualEqual:2644case AsmToken::Pipe:2645case AsmToken::PipePipe:2646case AsmToken::Caret:2647case AsmToken::Amp:2648case AsmToken::AmpAmp:2649case AsmToken::Exclaim:2650case AsmToken::ExclaimEqual:2651case AsmToken::Less:2652case AsmToken::LessEqual:2653case AsmToken::LessLess:2654case AsmToken::LessGreater:2655case AsmToken::Greater:2656case AsmToken::GreaterEqual:2657case AsmToken::GreaterGreater:2658return true;2659}2660}26612662namespace {26632664class AsmLexerSkipSpaceRAII {2665public:2666AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {2667Lexer.setSkipSpace(SkipSpace);2668}26692670~AsmLexerSkipSpaceRAII() {2671Lexer.setSkipSpace(true);2672}26732674private:2675AsmLexer &Lexer;2676};26772678} // end anonymous namespace26792680bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {26812682if (Vararg) {2683if (Lexer.isNot(AsmToken::EndOfStatement)) {2684StringRef Str = parseStringToEndOfStatement();2685MA.emplace_back(AsmToken::String, Str);2686}2687return false;2688}26892690unsigned ParenLevel = 0;26912692// Darwin doesn't use spaces to delmit arguments.2693AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);26942695bool SpaceEaten;26962697while (true) {2698SpaceEaten = false;2699if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))2700return TokError("unexpected token in macro instantiation");27012702if (ParenLevel == 0) {27032704if (Lexer.is(AsmToken::Comma))2705break;27062707if (parseOptionalToken(AsmToken::Space))2708SpaceEaten = true;27092710// Spaces can delimit parameters, but could also be part an expression.2711// If the token after a space is an operator, add the token and the next2712// one into this argument2713if (!IsDarwin) {2714if (isOperator(Lexer.getKind())) {2715MA.push_back(getTok());2716Lexer.Lex();27172718// Whitespace after an operator can be ignored.2719parseOptionalToken(AsmToken::Space);2720continue;2721}2722}2723if (SpaceEaten)2724break;2725}27262727// handleMacroEntry relies on not advancing the lexer here2728// to be able to fill in the remaining default parameter values2729if (Lexer.is(AsmToken::EndOfStatement))2730break;27312732// Adjust the current parentheses level.2733if (Lexer.is(AsmToken::LParen))2734++ParenLevel;2735else if (Lexer.is(AsmToken::RParen) && ParenLevel)2736--ParenLevel;27372738// Append the token to the current argument list.2739MA.push_back(getTok());2740Lexer.Lex();2741}27422743if (ParenLevel != 0)2744return TokError("unbalanced parentheses in macro argument");2745return false;2746}27472748// Parse the macro instantiation arguments.2749bool AsmParser::parseMacroArguments(const MCAsmMacro *M,2750MCAsmMacroArguments &A) {2751const unsigned NParameters = M ? M->Parameters.size() : 0;2752bool NamedParametersFound = false;2753SmallVector<SMLoc, 4> FALocs;27542755A.resize(NParameters);2756FALocs.resize(NParameters);27572758// Parse two kinds of macro invocations:2759// - macros defined without any parameters accept an arbitrary number of them2760// - macros defined with parameters accept at most that many of them2761bool HasVararg = NParameters ? M->Parameters.back().Vararg : false;2762for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;2763++Parameter) {2764SMLoc IDLoc = Lexer.getLoc();2765MCAsmMacroParameter FA;27662767if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {2768if (parseIdentifier(FA.Name))2769return Error(IDLoc, "invalid argument identifier for formal argument");27702771if (Lexer.isNot(AsmToken::Equal))2772return TokError("expected '=' after formal parameter identifier");27732774Lex();27752776NamedParametersFound = true;2777}2778bool Vararg = HasVararg && Parameter == (NParameters - 1);27792780if (NamedParametersFound && FA.Name.empty())2781return Error(IDLoc, "cannot mix positional and keyword arguments");27822783SMLoc StrLoc = Lexer.getLoc();2784SMLoc EndLoc;2785if (AltMacroMode && Lexer.is(AsmToken::Percent)) {2786const MCExpr *AbsoluteExp;2787int64_t Value;2788/// Eat '%'2789Lex();2790if (parseExpression(AbsoluteExp, EndLoc))2791return false;2792if (!AbsoluteExp->evaluateAsAbsolute(Value,2793getStreamer().getAssemblerPtr()))2794return Error(StrLoc, "expected absolute expression");2795const char *StrChar = StrLoc.getPointer();2796const char *EndChar = EndLoc.getPointer();2797AsmToken newToken(AsmToken::Integer,2798StringRef(StrChar, EndChar - StrChar), Value);2799FA.Value.push_back(newToken);2800} else if (AltMacroMode && Lexer.is(AsmToken::Less) &&2801isAngleBracketString(StrLoc, EndLoc)) {2802const char *StrChar = StrLoc.getPointer();2803const char *EndChar = EndLoc.getPointer();2804jumpToLoc(EndLoc, CurBuffer);2805/// Eat from '<' to '>'2806Lex();2807AsmToken newToken(AsmToken::String,2808StringRef(StrChar, EndChar - StrChar));2809FA.Value.push_back(newToken);2810} else if(parseMacroArgument(FA.Value, Vararg))2811return true;28122813unsigned PI = Parameter;2814if (!FA.Name.empty()) {2815unsigned FAI = 0;2816for (FAI = 0; FAI < NParameters; ++FAI)2817if (M->Parameters[FAI].Name == FA.Name)2818break;28192820if (FAI >= NParameters) {2821assert(M && "expected macro to be defined");2822return Error(IDLoc, "parameter named '" + FA.Name +2823"' does not exist for macro '" + M->Name + "'");2824}2825PI = FAI;2826}28272828if (!FA.Value.empty()) {2829if (A.size() <= PI)2830A.resize(PI + 1);2831A[PI] = FA.Value;28322833if (FALocs.size() <= PI)2834FALocs.resize(PI + 1);28352836FALocs[PI] = Lexer.getLoc();2837}28382839// At the end of the statement, fill in remaining arguments that have2840// default values. If there aren't any, then the next argument is2841// required but missing2842if (Lexer.is(AsmToken::EndOfStatement)) {2843bool Failure = false;2844for (unsigned FAI = 0; FAI < NParameters; ++FAI) {2845if (A[FAI].empty()) {2846if (M->Parameters[FAI].Required) {2847Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),2848"missing value for required parameter "2849"'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");2850Failure = true;2851}28522853if (!M->Parameters[FAI].Value.empty())2854A[FAI] = M->Parameters[FAI].Value;2855}2856}2857return Failure;2858}28592860parseOptionalToken(AsmToken::Comma);2861}28622863return TokError("too many positional arguments");2864}28652866bool AsmParser::handleMacroEntry(MCAsmMacro *M, SMLoc NameLoc) {2867// Arbitrarily limit macro nesting depth (default matches 'as'). We can2868// eliminate this, although we should protect against infinite loops.2869unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;2870if (ActiveMacros.size() == MaxNestingDepth) {2871std::ostringstream MaxNestingDepthError;2872MaxNestingDepthError << "macros cannot be nested more than "2873<< MaxNestingDepth << " levels deep."2874<< " Use -asm-macro-max-nesting-depth to increase "2875"this limit.";2876return TokError(MaxNestingDepthError.str());2877}28782879MCAsmMacroArguments A;2880if (parseMacroArguments(M, A))2881return true;28822883// Macro instantiation is lexical, unfortunately. We construct a new buffer2884// to hold the macro body with substitutions.2885SmallString<256> Buf;2886raw_svector_ostream OS(Buf);28872888if ((!IsDarwin || M->Parameters.size()) && M->Parameters.size() != A.size())2889return Error(getTok().getLoc(), "Wrong number of arguments");2890if (expandMacro(OS, *M, M->Parameters, A, true))2891return true;28922893// We include the .endmacro in the buffer as our cue to exit the macro2894// instantiation.2895OS << ".endmacro\n";28962897std::unique_ptr<MemoryBuffer> Instantiation =2898MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");28992900// Create the macro instantiation object and add to the current macro2901// instantiation stack.2902MacroInstantiation *MI = new MacroInstantiation{2903NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};2904ActiveMacros.push_back(MI);29052906++NumOfMacroInstantiations;29072908// Jump to the macro instantiation and prime the lexer.2909CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());2910Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());2911Lex();29122913return false;2914}29152916void AsmParser::handleMacroExit() {2917// Jump to the EndOfStatement we should return to, and consume it.2918jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer);2919Lex();2920// If .endm/.endr is followed by \n instead of a comment, consume it so that2921// we don't print an excess \n.2922if (getTok().is(AsmToken::EndOfStatement))2923Lex();29242925// Pop the instantiation entry.2926delete ActiveMacros.back();2927ActiveMacros.pop_back();2928}29292930bool AsmParser::parseAssignment(StringRef Name, AssignmentKind Kind) {2931MCSymbol *Sym;2932const MCExpr *Value;2933SMLoc ExprLoc = getTok().getLoc();2934bool AllowRedef =2935Kind == AssignmentKind::Set || Kind == AssignmentKind::Equal;2936if (MCParserUtils::parseAssignmentExpression(Name, AllowRedef, *this, Sym,2937Value))2938return true;29392940if (!Sym) {2941// In the case where we parse an expression starting with a '.', we will2942// not generate an error, nor will we create a symbol. In this case we2943// should just return out.2944return false;2945}29462947if (discardLTOSymbol(Name))2948return false;29492950// Do the assignment.2951switch (Kind) {2952case AssignmentKind::Equal:2953Out.emitAssignment(Sym, Value);2954break;2955case AssignmentKind::Set:2956case AssignmentKind::Equiv:2957Out.emitAssignment(Sym, Value);2958Out.emitSymbolAttribute(Sym, MCSA_NoDeadStrip);2959break;2960case AssignmentKind::LTOSetConditional:2961if (Value->getKind() != MCExpr::SymbolRef)2962return Error(ExprLoc, "expected identifier");29632964Out.emitConditionalAssignment(Sym, Value);2965break;2966}29672968return false;2969}29702971/// parseIdentifier:2972/// ::= identifier2973/// ::= string2974bool AsmParser::parseIdentifier(StringRef &Res) {2975// The assembler has relaxed rules for accepting identifiers, in particular we2976// allow things like '.globl $foo' and '.def @feat.00', which would normally be2977// separate tokens. At this level, we have already lexed so we cannot (currently)2978// handle this as a context dependent token, instead we detect adjacent tokens2979// and return the combined identifier.2980if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {2981SMLoc PrefixLoc = getLexer().getLoc();29822983// Consume the prefix character, and check for a following identifier.29842985AsmToken Buf[1];2986Lexer.peekTokens(Buf, false);29872988if (Buf[0].isNot(AsmToken::Identifier) && Buf[0].isNot(AsmToken::Integer))2989return true;29902991// We have a '$' or '@' followed by an identifier or integer token, make2992// sure they are adjacent.2993if (PrefixLoc.getPointer() + 1 != Buf[0].getLoc().getPointer())2994return true;29952996// eat $ or @2997Lexer.Lex(); // Lexer's Lex guarantees consecutive token.2998// Construct the joined identifier and consume the token.2999Res = StringRef(PrefixLoc.getPointer(), getTok().getString().size() + 1);3000Lex(); // Parser Lex to maintain invariants.3001return false;3002}30033004if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))3005return true;30063007Res = getTok().getIdentifier();30083009Lex(); // Consume the identifier token.30103011return false;3012}30133014/// parseDirectiveSet:3015/// ::= .equ identifier ',' expression3016/// ::= .equiv identifier ',' expression3017/// ::= .set identifier ',' expression3018/// ::= .lto_set_conditional identifier ',' expression3019bool AsmParser::parseDirectiveSet(StringRef IDVal, AssignmentKind Kind) {3020StringRef Name;3021if (check(parseIdentifier(Name), "expected identifier") || parseComma() ||3022parseAssignment(Name, Kind))3023return true;3024return false;3025}30263027bool AsmParser::parseEscapedString(std::string &Data) {3028if (check(getTok().isNot(AsmToken::String), "expected string"))3029return true;30303031Data = "";3032StringRef Str = getTok().getStringContents();3033for (unsigned i = 0, e = Str.size(); i != e; ++i) {3034if (Str[i] != '\\') {3035if (Str[i] == '\n') {3036SMLoc NewlineLoc = SMLoc::getFromPointer(Str.data() + i);3037if (Warning(NewlineLoc, "unterminated string; newline inserted"))3038return true;3039}3040Data += Str[i];3041continue;3042}30433044// Recognize escaped characters. Note that this escape semantics currently3045// loosely follows Darwin 'as'.3046++i;3047if (i == e)3048return TokError("unexpected backslash at end of string");30493050// Recognize hex sequences similarly to GNU 'as'.3051if (Str[i] == 'x' || Str[i] == 'X') {3052size_t length = Str.size();3053if (i + 1 >= length || !isHexDigit(Str[i + 1]))3054return TokError("invalid hexadecimal escape sequence");30553056// Consume hex characters. GNU 'as' reads all hexadecimal characters and3057// then truncates to the lower 16 bits. Seems reasonable.3058unsigned Value = 0;3059while (i + 1 < length && isHexDigit(Str[i + 1]))3060Value = Value * 16 + hexDigitValue(Str[++i]);30613062Data += (unsigned char)(Value & 0xFF);3063continue;3064}30653066// Recognize octal sequences.3067if ((unsigned)(Str[i] - '0') <= 7) {3068// Consume up to three octal characters.3069unsigned Value = Str[i] - '0';30703071if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {3072++i;3073Value = Value * 8 + (Str[i] - '0');30743075if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {3076++i;3077Value = Value * 8 + (Str[i] - '0');3078}3079}30803081if (Value > 255)3082return TokError("invalid octal escape sequence (out of range)");30833084Data += (unsigned char)Value;3085continue;3086}30873088// Otherwise recognize individual escapes.3089switch (Str[i]) {3090default:3091// Just reject invalid escape sequences for now.3092return TokError("invalid escape sequence (unrecognized character)");30933094case 'b': Data += '\b'; break;3095case 'f': Data += '\f'; break;3096case 'n': Data += '\n'; break;3097case 'r': Data += '\r'; break;3098case 't': Data += '\t'; break;3099case '"': Data += '"'; break;3100case '\\': Data += '\\'; break;3101}3102}31033104Lex();3105return false;3106}31073108bool AsmParser::parseAngleBracketString(std::string &Data) {3109SMLoc EndLoc, StartLoc = getTok().getLoc();3110if (isAngleBracketString(StartLoc, EndLoc)) {3111const char *StartChar = StartLoc.getPointer() + 1;3112const char *EndChar = EndLoc.getPointer() - 1;3113jumpToLoc(EndLoc, CurBuffer);3114/// Eat from '<' to '>'3115Lex();31163117Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));3118return false;3119}3120return true;3121}31223123/// parseDirectiveAscii:3124// ::= .ascii [ "string"+ ( , "string"+ )* ]3125/// ::= ( .asciz | .string ) [ "string" ( , "string" )* ]3126bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {3127auto parseOp = [&]() -> bool {3128std::string Data;3129if (checkForValidSection())3130return true;3131// Only support spaces as separators for .ascii directive for now. See the3132// discusssion at https://reviews.llvm.org/D91460 for more details.3133do {3134if (parseEscapedString(Data))3135return true;3136getStreamer().emitBytes(Data);3137} while (!ZeroTerminated && getTok().is(AsmToken::String));3138if (ZeroTerminated)3139getStreamer().emitBytes(StringRef("\0", 1));3140return false;3141};31423143return parseMany(parseOp);3144}31453146/// parseDirectiveReloc3147/// ::= .reloc expression , identifier [ , expression ]3148bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {3149const MCExpr *Offset;3150const MCExpr *Expr = nullptr;3151SMLoc OffsetLoc = Lexer.getTok().getLoc();31523153if (parseExpression(Offset))3154return true;3155if (parseComma() ||3156check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))3157return true;31583159SMLoc NameLoc = Lexer.getTok().getLoc();3160StringRef Name = Lexer.getTok().getIdentifier();3161Lex();31623163if (Lexer.is(AsmToken::Comma)) {3164Lex();3165SMLoc ExprLoc = Lexer.getLoc();3166if (parseExpression(Expr))3167return true;31683169MCValue Value;3170if (!Expr->evaluateAsRelocatable(Value, nullptr, nullptr))3171return Error(ExprLoc, "expression must be relocatable");3172}31733174if (parseEOL())3175return true;31763177const MCTargetAsmParser &MCT = getTargetParser();3178const MCSubtargetInfo &STI = MCT.getSTI();3179if (std::optional<std::pair<bool, std::string>> Err =3180getStreamer().emitRelocDirective(*Offset, Name, Expr, DirectiveLoc,3181STI))3182return Error(Err->first ? NameLoc : OffsetLoc, Err->second);31833184return false;3185}31863187/// parseDirectiveValue3188/// ::= (.byte | .short | ... ) [ expression (, expression)* ]3189bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {3190auto parseOp = [&]() -> bool {3191const MCExpr *Value;3192SMLoc ExprLoc = getLexer().getLoc();3193if (checkForValidSection() || parseExpression(Value))3194return true;3195// Special case constant expressions to match code generator.3196if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {3197assert(Size <= 8 && "Invalid size");3198uint64_t IntValue = MCE->getValue();3199if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))3200return Error(ExprLoc, "out of range literal value");3201getStreamer().emitIntValue(IntValue, Size);3202} else3203getStreamer().emitValue(Value, Size, ExprLoc);3204return false;3205};32063207return parseMany(parseOp);3208}32093210static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) {3211if (Asm.getTok().isNot(AsmToken::Integer) &&3212Asm.getTok().isNot(AsmToken::BigNum))3213return Asm.TokError("unknown token in expression");3214SMLoc ExprLoc = Asm.getTok().getLoc();3215APInt IntValue = Asm.getTok().getAPIntVal();3216Asm.Lex();3217if (!IntValue.isIntN(128))3218return Asm.Error(ExprLoc, "out of range literal value");3219if (!IntValue.isIntN(64)) {3220hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();3221lo = IntValue.getLoBits(64).getZExtValue();3222} else {3223hi = 0;3224lo = IntValue.getZExtValue();3225}3226return false;3227}32283229/// ParseDirectiveOctaValue3230/// ::= .octa [ hexconstant (, hexconstant)* ]32313232bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {3233auto parseOp = [&]() -> bool {3234if (checkForValidSection())3235return true;3236uint64_t hi, lo;3237if (parseHexOcta(*this, hi, lo))3238return true;3239if (MAI.isLittleEndian()) {3240getStreamer().emitInt64(lo);3241getStreamer().emitInt64(hi);3242} else {3243getStreamer().emitInt64(hi);3244getStreamer().emitInt64(lo);3245}3246return false;3247};32483249return parseMany(parseOp);3250}32513252bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {3253// We don't truly support arithmetic on floating point expressions, so we3254// have to manually parse unary prefixes.3255bool IsNeg = false;3256if (getLexer().is(AsmToken::Minus)) {3257Lexer.Lex();3258IsNeg = true;3259} else if (getLexer().is(AsmToken::Plus))3260Lexer.Lex();32613262if (Lexer.is(AsmToken::Error))3263return TokError(Lexer.getErr());3264if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&3265Lexer.isNot(AsmToken::Identifier))3266return TokError("unexpected token in directive");32673268// Convert to an APFloat.3269APFloat Value(Semantics);3270StringRef IDVal = getTok().getString();3271if (getLexer().is(AsmToken::Identifier)) {3272if (!IDVal.compare_insensitive("infinity") ||3273!IDVal.compare_insensitive("inf"))3274Value = APFloat::getInf(Semantics);3275else if (!IDVal.compare_insensitive("nan"))3276Value = APFloat::getNaN(Semantics, false, ~0);3277else3278return TokError("invalid floating point literal");3279} else if (errorToBool(3280Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)3281.takeError()))3282return TokError("invalid floating point literal");3283if (IsNeg)3284Value.changeSign();32853286// Consume the numeric token.3287Lex();32883289Res = Value.bitcastToAPInt();32903291return false;3292}32933294/// parseDirectiveRealValue3295/// ::= (.single | .double) [ expression (, expression)* ]3296bool AsmParser::parseDirectiveRealValue(StringRef IDVal,3297const fltSemantics &Semantics) {3298auto parseOp = [&]() -> bool {3299APInt AsInt;3300if (checkForValidSection() || parseRealValue(Semantics, AsInt))3301return true;3302getStreamer().emitIntValue(AsInt.getLimitedValue(),3303AsInt.getBitWidth() / 8);3304return false;3305};33063307return parseMany(parseOp);3308}33093310/// parseDirectiveZero3311/// ::= .zero expression3312bool AsmParser::parseDirectiveZero() {3313SMLoc NumBytesLoc = Lexer.getLoc();3314const MCExpr *NumBytes;3315if (checkForValidSection() || parseExpression(NumBytes))3316return true;33173318int64_t Val = 0;3319if (getLexer().is(AsmToken::Comma)) {3320Lex();3321if (parseAbsoluteExpression(Val))3322return true;3323}33243325if (parseEOL())3326return true;3327getStreamer().emitFill(*NumBytes, Val, NumBytesLoc);33283329return false;3330}33313332/// parseDirectiveFill3333/// ::= .fill expression [ , expression [ , expression ] ]3334bool AsmParser::parseDirectiveFill() {3335SMLoc NumValuesLoc = Lexer.getLoc();3336const MCExpr *NumValues;3337if (checkForValidSection() || parseExpression(NumValues))3338return true;33393340int64_t FillSize = 1;3341int64_t FillExpr = 0;33423343SMLoc SizeLoc, ExprLoc;33443345if (parseOptionalToken(AsmToken::Comma)) {3346SizeLoc = getTok().getLoc();3347if (parseAbsoluteExpression(FillSize))3348return true;3349if (parseOptionalToken(AsmToken::Comma)) {3350ExprLoc = getTok().getLoc();3351if (parseAbsoluteExpression(FillExpr))3352return true;3353}3354}3355if (parseEOL())3356return true;33573358if (FillSize < 0) {3359Warning(SizeLoc, "'.fill' directive with negative size has no effect");3360return false;3361}3362if (FillSize > 8) {3363Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8");3364FillSize = 8;3365}33663367if (!isUInt<32>(FillExpr) && FillSize > 4)3368Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits");33693370getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc);33713372return false;3373}33743375/// parseDirectiveOrg3376/// ::= .org expression [ , expression ]3377bool AsmParser::parseDirectiveOrg() {3378const MCExpr *Offset;3379SMLoc OffsetLoc = Lexer.getLoc();3380if (checkForValidSection() || parseExpression(Offset))3381return true;33823383// Parse optional fill expression.3384int64_t FillExpr = 0;3385if (parseOptionalToken(AsmToken::Comma))3386if (parseAbsoluteExpression(FillExpr))3387return true;3388if (parseEOL())3389return true;33903391getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);3392return false;3393}33943395/// parseDirectiveAlign3396/// ::= {.align, ...} expression [ , expression [ , expression ]]3397bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {3398SMLoc AlignmentLoc = getLexer().getLoc();3399int64_t Alignment;3400SMLoc MaxBytesLoc;3401bool HasFillExpr = false;3402int64_t FillExpr = 0;3403int64_t MaxBytesToFill = 0;3404SMLoc FillExprLoc;34053406auto parseAlign = [&]() -> bool {3407if (parseAbsoluteExpression(Alignment))3408return true;3409if (parseOptionalToken(AsmToken::Comma)) {3410// The fill expression can be omitted while specifying a maximum number of3411// alignment bytes, e.g:3412// .align 3,,43413if (getTok().isNot(AsmToken::Comma)) {3414HasFillExpr = true;3415if (parseTokenLoc(FillExprLoc) || parseAbsoluteExpression(FillExpr))3416return true;3417}3418if (parseOptionalToken(AsmToken::Comma))3419if (parseTokenLoc(MaxBytesLoc) ||3420parseAbsoluteExpression(MaxBytesToFill))3421return true;3422}3423return parseEOL();3424};34253426if (checkForValidSection())3427return true;3428// Ignore empty '.p2align' directives for GNU-as compatibility3429if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) {3430Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored");3431return parseEOL();3432}3433if (parseAlign())3434return true;34353436// Always emit an alignment here even if we thrown an error.3437bool ReturnVal = false;34383439// Compute alignment in bytes.3440if (IsPow2) {3441// FIXME: Diagnose overflow.3442if (Alignment >= 32) {3443ReturnVal |= Error(AlignmentLoc, "invalid alignment value");3444Alignment = 31;3445}34463447Alignment = 1ULL << Alignment;3448} else {3449// Reject alignments that aren't either a power of two or zero,3450// for gas compatibility. Alignment of zero is silently rounded3451// up to one.3452if (Alignment == 0)3453Alignment = 1;3454else if (!isPowerOf2_64(Alignment)) {3455ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");3456Alignment = llvm::bit_floor<uint64_t>(Alignment);3457}3458if (!isUInt<32>(Alignment)) {3459ReturnVal |= Error(AlignmentLoc, "alignment must be smaller than 2**32");3460Alignment = 1u << 31;3461}3462}34633464if (HasFillExpr && FillExpr != 0) {3465MCSection *Sec = getStreamer().getCurrentSectionOnly();3466if (Sec && Sec->isVirtualSection()) {3467ReturnVal |=3468Warning(FillExprLoc, "ignoring non-zero fill value in " +3469Sec->getVirtualSectionKind() + " section '" +3470Sec->getName() + "'");3471FillExpr = 0;3472}3473}34743475// Diagnose non-sensical max bytes to align.3476if (MaxBytesLoc.isValid()) {3477if (MaxBytesToFill < 1) {3478ReturnVal |= Error(MaxBytesLoc,3479"alignment directive can never be satisfied in this "3480"many bytes, ignoring maximum bytes expression");3481MaxBytesToFill = 0;3482}34833484if (MaxBytesToFill >= Alignment) {3485Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "3486"has no effect");3487MaxBytesToFill = 0;3488}3489}34903491// Check whether we should use optimal code alignment for this .align3492// directive.3493const MCSection *Section = getStreamer().getCurrentSectionOnly();3494assert(Section && "must have section to emit alignment");3495bool useCodeAlign = Section->useCodeAlign();3496if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&3497ValueSize == 1 && useCodeAlign) {3498getStreamer().emitCodeAlignment(3499Align(Alignment), &getTargetParser().getSTI(), MaxBytesToFill);3500} else {3501// FIXME: Target specific behavior about how the "extra" bytes are filled.3502getStreamer().emitValueToAlignment(Align(Alignment), FillExpr, ValueSize,3503MaxBytesToFill);3504}35053506return ReturnVal;3507}35083509/// parseDirectiveFile3510/// ::= .file filename3511/// ::= .file number [directory] filename [md5 checksum] [source source-text]3512bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {3513// FIXME: I'm not sure what this is.3514int64_t FileNumber = -1;3515if (getLexer().is(AsmToken::Integer)) {3516FileNumber = getTok().getIntVal();3517Lex();35183519if (FileNumber < 0)3520return TokError("negative file number");3521}35223523std::string Path;35243525// Usually the directory and filename together, otherwise just the directory.3526// Allow the strings to have escaped octal character sequence.3527if (parseEscapedString(Path))3528return true;35293530StringRef Directory;3531StringRef Filename;3532std::string FilenameData;3533if (getLexer().is(AsmToken::String)) {3534if (check(FileNumber == -1,3535"explicit path specified, but no file number") ||3536parseEscapedString(FilenameData))3537return true;3538Filename = FilenameData;3539Directory = Path;3540} else {3541Filename = Path;3542}35433544uint64_t MD5Hi, MD5Lo;3545bool HasMD5 = false;35463547std::optional<StringRef> Source;3548bool HasSource = false;3549std::string SourceString;35503551while (!parseOptionalToken(AsmToken::EndOfStatement)) {3552StringRef Keyword;3553if (check(getTok().isNot(AsmToken::Identifier),3554"unexpected token in '.file' directive") ||3555parseIdentifier(Keyword))3556return true;3557if (Keyword == "md5") {3558HasMD5 = true;3559if (check(FileNumber == -1,3560"MD5 checksum specified, but no file number") ||3561parseHexOcta(*this, MD5Hi, MD5Lo))3562return true;3563} else if (Keyword == "source") {3564HasSource = true;3565if (check(FileNumber == -1,3566"source specified, but no file number") ||3567check(getTok().isNot(AsmToken::String),3568"unexpected token in '.file' directive") ||3569parseEscapedString(SourceString))3570return true;3571} else {3572return TokError("unexpected token in '.file' directive");3573}3574}35753576if (FileNumber == -1) {3577// Ignore the directive if there is no number and the target doesn't support3578// numberless .file directives. This allows some portability of assembler3579// between different object file formats.3580if (getContext().getAsmInfo()->hasSingleParameterDotFile())3581getStreamer().emitFileDirective(Filename);3582} else {3583// In case there is a -g option as well as debug info from directive .file,3584// we turn off the -g option, directly use the existing debug info instead.3585// Throw away any implicit file table for the assembler source.3586if (Ctx.getGenDwarfForAssembly()) {3587Ctx.getMCDwarfLineTable(0).resetFileTable();3588Ctx.setGenDwarfForAssembly(false);3589}35903591std::optional<MD5::MD5Result> CKMem;3592if (HasMD5) {3593MD5::MD5Result Sum;3594for (unsigned i = 0; i != 8; ++i) {3595Sum[i] = uint8_t(MD5Hi >> ((7 - i) * 8));3596Sum[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));3597}3598CKMem = Sum;3599}3600if (HasSource) {3601char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));3602memcpy(SourceBuf, SourceString.data(), SourceString.size());3603Source = StringRef(SourceBuf, SourceString.size());3604}3605if (FileNumber == 0) {3606// Upgrade to Version 5 for assembly actions like clang -c a.s.3607if (Ctx.getDwarfVersion() < 5)3608Ctx.setDwarfVersion(5);3609getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);3610} else {3611Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(3612FileNumber, Directory, Filename, CKMem, Source);3613if (!FileNumOrErr)3614return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));3615}3616// Alert the user if there are some .file directives with MD5 and some not.3617// But only do that once.3618if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {3619ReportedInconsistentMD5 = true;3620return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");3621}3622}36233624return false;3625}36263627/// parseDirectiveLine3628/// ::= .line [number]3629bool AsmParser::parseDirectiveLine() {3630int64_t LineNumber;3631if (getLexer().is(AsmToken::Integer)) {3632if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))3633return true;3634(void)LineNumber;3635// FIXME: Do something with the .line.3636}3637return parseEOL();3638}36393640/// parseDirectiveLoc3641/// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]3642/// [epilogue_begin] [is_stmt VALUE] [isa VALUE]3643/// The first number is a file number, must have been previously assigned with3644/// a .file directive, the second number is the line number and optionally the3645/// third number is a column position (zero if not specified). The remaining3646/// optional items are .loc sub-directives.3647bool AsmParser::parseDirectiveLoc() {3648int64_t FileNumber = 0, LineNumber = 0;3649SMLoc Loc = getTok().getLoc();3650if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||3651check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,3652"file number less than one in '.loc' directive") ||3653check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,3654"unassigned file number in '.loc' directive"))3655return true;36563657// optional3658if (getLexer().is(AsmToken::Integer)) {3659LineNumber = getTok().getIntVal();3660if (LineNumber < 0)3661return TokError("line number less than zero in '.loc' directive");3662Lex();3663}36643665int64_t ColumnPos = 0;3666if (getLexer().is(AsmToken::Integer)) {3667ColumnPos = getTok().getIntVal();3668if (ColumnPos < 0)3669return TokError("column position less than zero in '.loc' directive");3670Lex();3671}36723673auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();3674unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;3675unsigned Isa = 0;3676int64_t Discriminator = 0;36773678auto parseLocOp = [&]() -> bool {3679StringRef Name;3680SMLoc Loc = getTok().getLoc();3681if (parseIdentifier(Name))3682return TokError("unexpected token in '.loc' directive");36833684if (Name == "basic_block")3685Flags |= DWARF2_FLAG_BASIC_BLOCK;3686else if (Name == "prologue_end")3687Flags |= DWARF2_FLAG_PROLOGUE_END;3688else if (Name == "epilogue_begin")3689Flags |= DWARF2_FLAG_EPILOGUE_BEGIN;3690else if (Name == "is_stmt") {3691Loc = getTok().getLoc();3692const MCExpr *Value;3693if (parseExpression(Value))3694return true;3695// The expression must be the constant 0 or 1.3696if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {3697int Value = MCE->getValue();3698if (Value == 0)3699Flags &= ~DWARF2_FLAG_IS_STMT;3700else if (Value == 1)3701Flags |= DWARF2_FLAG_IS_STMT;3702else3703return Error(Loc, "is_stmt value not 0 or 1");3704} else {3705return Error(Loc, "is_stmt value not the constant value of 0 or 1");3706}3707} else if (Name == "isa") {3708Loc = getTok().getLoc();3709const MCExpr *Value;3710if (parseExpression(Value))3711return true;3712// The expression must be a constant greater or equal to 0.3713if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {3714int Value = MCE->getValue();3715if (Value < 0)3716return Error(Loc, "isa number less than zero");3717Isa = Value;3718} else {3719return Error(Loc, "isa number not a constant value");3720}3721} else if (Name == "discriminator") {3722if (parseAbsoluteExpression(Discriminator))3723return true;3724} else {3725return Error(Loc, "unknown sub-directive in '.loc' directive");3726}3727return false;3728};37293730if (parseMany(parseLocOp, false /*hasComma*/))3731return true;37323733getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,3734Isa, Discriminator, StringRef());37353736return false;3737}37383739/// parseDirectiveStabs3740/// ::= .stabs string, number, number, number3741bool AsmParser::parseDirectiveStabs() {3742return TokError("unsupported directive '.stabs'");3743}37443745/// parseDirectiveCVFile3746/// ::= .cv_file number filename [checksum] [checksumkind]3747bool AsmParser::parseDirectiveCVFile() {3748SMLoc FileNumberLoc = getTok().getLoc();3749int64_t FileNumber;3750std::string Filename;3751std::string Checksum;3752int64_t ChecksumKind = 0;37533754if (parseIntToken(FileNumber,3755"expected file number in '.cv_file' directive") ||3756check(FileNumber < 1, FileNumberLoc, "file number less than one") ||3757check(getTok().isNot(AsmToken::String),3758"unexpected token in '.cv_file' directive") ||3759parseEscapedString(Filename))3760return true;3761if (!parseOptionalToken(AsmToken::EndOfStatement)) {3762if (check(getTok().isNot(AsmToken::String),3763"unexpected token in '.cv_file' directive") ||3764parseEscapedString(Checksum) ||3765parseIntToken(ChecksumKind,3766"expected checksum kind in '.cv_file' directive") ||3767parseEOL())3768return true;3769}37703771Checksum = fromHex(Checksum);3772void *CKMem = Ctx.allocate(Checksum.size(), 1);3773memcpy(CKMem, Checksum.data(), Checksum.size());3774ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),3775Checksum.size());37763777if (!getStreamer().emitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,3778static_cast<uint8_t>(ChecksumKind)))3779return Error(FileNumberLoc, "file number already allocated");37803781return false;3782}37833784bool AsmParser::parseCVFunctionId(int64_t &FunctionId,3785StringRef DirectiveName) {3786SMLoc Loc;3787return parseTokenLoc(Loc) ||3788parseIntToken(FunctionId, "expected function id in '" + DirectiveName +3789"' directive") ||3790check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,3791"expected function id within range [0, UINT_MAX)");3792}37933794bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {3795SMLoc Loc;3796return parseTokenLoc(Loc) ||3797parseIntToken(FileNumber, "expected integer in '" + DirectiveName +3798"' directive") ||3799check(FileNumber < 1, Loc, "file number less than one in '" +3800DirectiveName + "' directive") ||3801check(!getCVContext().isValidFileNumber(FileNumber), Loc,3802"unassigned file number in '" + DirectiveName + "' directive");3803}38043805/// parseDirectiveCVFuncId3806/// ::= .cv_func_id FunctionId3807///3808/// Introduces a function ID that can be used with .cv_loc.3809bool AsmParser::parseDirectiveCVFuncId() {3810SMLoc FunctionIdLoc = getTok().getLoc();3811int64_t FunctionId;38123813if (parseCVFunctionId(FunctionId, ".cv_func_id") || parseEOL())3814return true;38153816if (!getStreamer().emitCVFuncIdDirective(FunctionId))3817return Error(FunctionIdLoc, "function id already allocated");38183819return false;3820}38213822/// parseDirectiveCVInlineSiteId3823/// ::= .cv_inline_site_id FunctionId3824/// "within" IAFunc3825/// "inlined_at" IAFile IALine [IACol]3826///3827/// Introduces a function ID that can be used with .cv_loc. Includes "inlined3828/// at" source location information for use in the line table of the caller,3829/// whether the caller is a real function or another inlined call site.3830bool AsmParser::parseDirectiveCVInlineSiteId() {3831SMLoc FunctionIdLoc = getTok().getLoc();3832int64_t FunctionId;3833int64_t IAFunc;3834int64_t IAFile;3835int64_t IALine;3836int64_t IACol = 0;38373838// FunctionId3839if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))3840return true;38413842// "within"3843if (check((getLexer().isNot(AsmToken::Identifier) ||3844getTok().getIdentifier() != "within"),3845"expected 'within' identifier in '.cv_inline_site_id' directive"))3846return true;3847Lex();38483849// IAFunc3850if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))3851return true;38523853// "inlined_at"3854if (check((getLexer().isNot(AsmToken::Identifier) ||3855getTok().getIdentifier() != "inlined_at"),3856"expected 'inlined_at' identifier in '.cv_inline_site_id' "3857"directive") )3858return true;3859Lex();38603861// IAFile IALine3862if (parseCVFileId(IAFile, ".cv_inline_site_id") ||3863parseIntToken(IALine, "expected line number after 'inlined_at'"))3864return true;38653866// [IACol]3867if (getLexer().is(AsmToken::Integer)) {3868IACol = getTok().getIntVal();3869Lex();3870}38713872if (parseEOL())3873return true;38743875if (!getStreamer().emitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,3876IALine, IACol, FunctionIdLoc))3877return Error(FunctionIdLoc, "function id already allocated");38783879return false;3880}38813882/// parseDirectiveCVLoc3883/// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]3884/// [is_stmt VALUE]3885/// The first number is a file number, must have been previously assigned with3886/// a .file directive, the second number is the line number and optionally the3887/// third number is a column position (zero if not specified). The remaining3888/// optional items are .loc sub-directives.3889bool AsmParser::parseDirectiveCVLoc() {3890SMLoc DirectiveLoc = getTok().getLoc();3891int64_t FunctionId, FileNumber;3892if (parseCVFunctionId(FunctionId, ".cv_loc") ||3893parseCVFileId(FileNumber, ".cv_loc"))3894return true;38953896int64_t LineNumber = 0;3897if (getLexer().is(AsmToken::Integer)) {3898LineNumber = getTok().getIntVal();3899if (LineNumber < 0)3900return TokError("line number less than zero in '.cv_loc' directive");3901Lex();3902}39033904int64_t ColumnPos = 0;3905if (getLexer().is(AsmToken::Integer)) {3906ColumnPos = getTok().getIntVal();3907if (ColumnPos < 0)3908return TokError("column position less than zero in '.cv_loc' directive");3909Lex();3910}39113912bool PrologueEnd = false;3913uint64_t IsStmt = 0;39143915auto parseOp = [&]() -> bool {3916StringRef Name;3917SMLoc Loc = getTok().getLoc();3918if (parseIdentifier(Name))3919return TokError("unexpected token in '.cv_loc' directive");3920if (Name == "prologue_end")3921PrologueEnd = true;3922else if (Name == "is_stmt") {3923Loc = getTok().getLoc();3924const MCExpr *Value;3925if (parseExpression(Value))3926return true;3927// The expression must be the constant 0 or 1.3928IsStmt = ~0ULL;3929if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))3930IsStmt = MCE->getValue();39313932if (IsStmt > 1)3933return Error(Loc, "is_stmt value not 0 or 1");3934} else {3935return Error(Loc, "unknown sub-directive in '.cv_loc' directive");3936}3937return false;3938};39393940if (parseMany(parseOp, false /*hasComma*/))3941return true;39423943getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,3944ColumnPos, PrologueEnd, IsStmt, StringRef(),3945DirectiveLoc);3946return false;3947}39483949/// parseDirectiveCVLinetable3950/// ::= .cv_linetable FunctionId, FnStart, FnEnd3951bool AsmParser::parseDirectiveCVLinetable() {3952int64_t FunctionId;3953StringRef FnStartName, FnEndName;3954SMLoc Loc = getTok().getLoc();3955if (parseCVFunctionId(FunctionId, ".cv_linetable") || parseComma() ||3956parseTokenLoc(Loc) ||3957check(parseIdentifier(FnStartName), Loc,3958"expected identifier in directive") ||3959parseComma() || parseTokenLoc(Loc) ||3960check(parseIdentifier(FnEndName), Loc,3961"expected identifier in directive"))3962return true;39633964MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);3965MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);39663967getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);3968return false;3969}39703971/// parseDirectiveCVInlineLinetable3972/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd3973bool AsmParser::parseDirectiveCVInlineLinetable() {3974int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;3975StringRef FnStartName, FnEndName;3976SMLoc Loc = getTok().getLoc();3977if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||3978parseTokenLoc(Loc) ||3979parseIntToken(3980SourceFileId,3981"expected SourceField in '.cv_inline_linetable' directive") ||3982check(SourceFileId <= 0, Loc,3983"File id less than zero in '.cv_inline_linetable' directive") ||3984parseTokenLoc(Loc) ||3985parseIntToken(3986SourceLineNum,3987"expected SourceLineNum in '.cv_inline_linetable' directive") ||3988check(SourceLineNum < 0, Loc,3989"Line number less than zero in '.cv_inline_linetable' directive") ||3990parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,3991"expected identifier in directive") ||3992parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,3993"expected identifier in directive"))3994return true;39953996if (parseEOL())3997return true;39983999MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);4000MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);4001getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,4002SourceLineNum, FnStartSym,4003FnEndSym);4004return false;4005}40064007void AsmParser::initializeCVDefRangeTypeMap() {4008CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;4009CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;4010CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;4011CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;4012}40134014/// parseDirectiveCVDefRange4015/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*4016bool AsmParser::parseDirectiveCVDefRange() {4017SMLoc Loc;4018std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;4019while (getLexer().is(AsmToken::Identifier)) {4020Loc = getLexer().getLoc();4021StringRef GapStartName;4022if (parseIdentifier(GapStartName))4023return Error(Loc, "expected identifier in directive");4024MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);40254026Loc = getLexer().getLoc();4027StringRef GapEndName;4028if (parseIdentifier(GapEndName))4029return Error(Loc, "expected identifier in directive");4030MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);40314032Ranges.push_back({GapStartSym, GapEndSym});4033}40344035StringRef CVDefRangeTypeStr;4036if (parseToken(4037AsmToken::Comma,4038"expected comma before def_range type in .cv_def_range directive") ||4039parseIdentifier(CVDefRangeTypeStr))4040return Error(Loc, "expected def_range type in directive");40414042StringMap<CVDefRangeType>::const_iterator CVTypeIt =4043CVDefRangeTypeMap.find(CVDefRangeTypeStr);4044CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())4045? CVDR_DEFRANGE4046: CVTypeIt->getValue();4047switch (CVDRType) {4048case CVDR_DEFRANGE_REGISTER: {4049int64_t DRRegister;4050if (parseToken(AsmToken::Comma, "expected comma before register number in "4051".cv_def_range directive") ||4052parseAbsoluteExpression(DRRegister))4053return Error(Loc, "expected register number");40544055codeview::DefRangeRegisterHeader DRHdr;4056DRHdr.Register = DRRegister;4057DRHdr.MayHaveNoName = 0;4058getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);4059break;4060}4061case CVDR_DEFRANGE_FRAMEPOINTER_REL: {4062int64_t DROffset;4063if (parseToken(AsmToken::Comma,4064"expected comma before offset in .cv_def_range directive") ||4065parseAbsoluteExpression(DROffset))4066return Error(Loc, "expected offset value");40674068codeview::DefRangeFramePointerRelHeader DRHdr;4069DRHdr.Offset = DROffset;4070getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);4071break;4072}4073case CVDR_DEFRANGE_SUBFIELD_REGISTER: {4074int64_t DRRegister;4075int64_t DROffsetInParent;4076if (parseToken(AsmToken::Comma, "expected comma before register number in "4077".cv_def_range directive") ||4078parseAbsoluteExpression(DRRegister))4079return Error(Loc, "expected register number");4080if (parseToken(AsmToken::Comma,4081"expected comma before offset in .cv_def_range directive") ||4082parseAbsoluteExpression(DROffsetInParent))4083return Error(Loc, "expected offset value");40844085codeview::DefRangeSubfieldRegisterHeader DRHdr;4086DRHdr.Register = DRRegister;4087DRHdr.MayHaveNoName = 0;4088DRHdr.OffsetInParent = DROffsetInParent;4089getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);4090break;4091}4092case CVDR_DEFRANGE_REGISTER_REL: {4093int64_t DRRegister;4094int64_t DRFlags;4095int64_t DRBasePointerOffset;4096if (parseToken(AsmToken::Comma, "expected comma before register number in "4097".cv_def_range directive") ||4098parseAbsoluteExpression(DRRegister))4099return Error(Loc, "expected register value");4100if (parseToken(4101AsmToken::Comma,4102"expected comma before flag value in .cv_def_range directive") ||4103parseAbsoluteExpression(DRFlags))4104return Error(Loc, "expected flag value");4105if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "4106"in .cv_def_range directive") ||4107parseAbsoluteExpression(DRBasePointerOffset))4108return Error(Loc, "expected base pointer offset value");41094110codeview::DefRangeRegisterRelHeader DRHdr;4111DRHdr.Register = DRRegister;4112DRHdr.Flags = DRFlags;4113DRHdr.BasePointerOffset = DRBasePointerOffset;4114getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);4115break;4116}4117default:4118return Error(Loc, "unexpected def_range type in .cv_def_range directive");4119}4120return true;4121}41224123/// parseDirectiveCVString4124/// ::= .cv_stringtable "string"4125bool AsmParser::parseDirectiveCVString() {4126std::string Data;4127if (checkForValidSection() || parseEscapedString(Data))4128return true;41294130// Put the string in the table and emit the offset.4131std::pair<StringRef, unsigned> Insertion =4132getCVContext().addToStringTable(Data);4133getStreamer().emitInt32(Insertion.second);4134return false;4135}41364137/// parseDirectiveCVStringTable4138/// ::= .cv_stringtable4139bool AsmParser::parseDirectiveCVStringTable() {4140getStreamer().emitCVStringTableDirective();4141return false;4142}41434144/// parseDirectiveCVFileChecksums4145/// ::= .cv_filechecksums4146bool AsmParser::parseDirectiveCVFileChecksums() {4147getStreamer().emitCVFileChecksumsDirective();4148return false;4149}41504151/// parseDirectiveCVFileChecksumOffset4152/// ::= .cv_filechecksumoffset fileno4153bool AsmParser::parseDirectiveCVFileChecksumOffset() {4154int64_t FileNo;4155if (parseIntToken(FileNo, "expected identifier in directive"))4156return true;4157if (parseEOL())4158return true;4159getStreamer().emitCVFileChecksumOffsetDirective(FileNo);4160return false;4161}41624163/// parseDirectiveCVFPOData4164/// ::= .cv_fpo_data procsym4165bool AsmParser::parseDirectiveCVFPOData() {4166SMLoc DirLoc = getLexer().getLoc();4167StringRef ProcName;4168if (parseIdentifier(ProcName))4169return TokError("expected symbol name");4170if (parseEOL())4171return true;4172MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);4173getStreamer().emitCVFPOData(ProcSym, DirLoc);4174return false;4175}41764177/// parseDirectiveCFISections4178/// ::= .cfi_sections section [, section]4179bool AsmParser::parseDirectiveCFISections() {4180StringRef Name;4181bool EH = false;4182bool Debug = false;41834184if (!parseOptionalToken(AsmToken::EndOfStatement)) {4185for (;;) {4186if (parseIdentifier(Name))4187return TokError("expected .eh_frame or .debug_frame");4188if (Name == ".eh_frame")4189EH = true;4190else if (Name == ".debug_frame")4191Debug = true;4192if (parseOptionalToken(AsmToken::EndOfStatement))4193break;4194if (parseComma())4195return true;4196}4197}4198getStreamer().emitCFISections(EH, Debug);4199return false;4200}42014202/// parseDirectiveCFIStartProc4203/// ::= .cfi_startproc [simple]4204bool AsmParser::parseDirectiveCFIStartProc() {4205CFIStartProcLoc = StartTokLoc;42064207StringRef Simple;4208if (!parseOptionalToken(AsmToken::EndOfStatement)) {4209if (check(parseIdentifier(Simple) || Simple != "simple",4210"unexpected token") ||4211parseEOL())4212return true;4213}42144215// TODO(kristina): Deal with a corner case of incorrect diagnostic context4216// being produced if this directive is emitted as part of preprocessor macro4217// expansion which can *ONLY* happen if Clang's cc1as is the API consumer.4218// Tools like llvm-mc on the other hand are not affected by it, and report4219// correct context information.4220getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());4221return false;4222}42234224/// parseDirectiveCFIEndProc4225/// ::= .cfi_endproc4226bool AsmParser::parseDirectiveCFIEndProc() {4227CFIStartProcLoc = std::nullopt;42284229if (parseEOL())4230return true;42314232getStreamer().emitCFIEndProc();4233return false;4234}42354236/// parse register name or number.4237bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,4238SMLoc DirectiveLoc) {4239MCRegister RegNo;42404241if (getLexer().isNot(AsmToken::Integer)) {4242if (getTargetParser().parseRegister(RegNo, DirectiveLoc, DirectiveLoc))4243return true;4244Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);4245} else4246return parseAbsoluteExpression(Register);42474248return false;4249}42504251/// parseDirectiveCFIDefCfa4252/// ::= .cfi_def_cfa register, offset4253bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {4254int64_t Register = 0, Offset = 0;4255if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||4256parseAbsoluteExpression(Offset) || parseEOL())4257return true;42584259getStreamer().emitCFIDefCfa(Register, Offset, DirectiveLoc);4260return false;4261}42624263/// parseDirectiveCFIDefCfaOffset4264/// ::= .cfi_def_cfa_offset offset4265bool AsmParser::parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc) {4266int64_t Offset = 0;4267if (parseAbsoluteExpression(Offset) || parseEOL())4268return true;42694270getStreamer().emitCFIDefCfaOffset(Offset, DirectiveLoc);4271return false;4272}42734274/// parseDirectiveCFIRegister4275/// ::= .cfi_register register, register4276bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {4277int64_t Register1 = 0, Register2 = 0;4278if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || parseComma() ||4279parseRegisterOrRegisterNumber(Register2, DirectiveLoc) || parseEOL())4280return true;42814282getStreamer().emitCFIRegister(Register1, Register2, DirectiveLoc);4283return false;4284}42854286/// parseDirectiveCFIWindowSave4287/// ::= .cfi_window_save4288bool AsmParser::parseDirectiveCFIWindowSave(SMLoc DirectiveLoc) {4289if (parseEOL())4290return true;4291getStreamer().emitCFIWindowSave(DirectiveLoc);4292return false;4293}42944295/// parseDirectiveCFIAdjustCfaOffset4296/// ::= .cfi_adjust_cfa_offset adjustment4297bool AsmParser::parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc) {4298int64_t Adjustment = 0;4299if (parseAbsoluteExpression(Adjustment) || parseEOL())4300return true;43014302getStreamer().emitCFIAdjustCfaOffset(Adjustment, DirectiveLoc);4303return false;4304}43054306/// parseDirectiveCFIDefCfaRegister4307/// ::= .cfi_def_cfa_register register4308bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {4309int64_t Register = 0;4310if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())4311return true;43124313getStreamer().emitCFIDefCfaRegister(Register, DirectiveLoc);4314return false;4315}43164317/// parseDirectiveCFILLVMDefAspaceCfa4318/// ::= .cfi_llvm_def_aspace_cfa register, offset, address_space4319bool AsmParser::parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc) {4320int64_t Register = 0, Offset = 0, AddressSpace = 0;4321if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||4322parseAbsoluteExpression(Offset) || parseComma() ||4323parseAbsoluteExpression(AddressSpace) || parseEOL())4324return true;43254326getStreamer().emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace,4327DirectiveLoc);4328return false;4329}43304331/// parseDirectiveCFIOffset4332/// ::= .cfi_offset register, offset4333bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {4334int64_t Register = 0;4335int64_t Offset = 0;43364337if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||4338parseAbsoluteExpression(Offset) || parseEOL())4339return true;43404341getStreamer().emitCFIOffset(Register, Offset, DirectiveLoc);4342return false;4343}43444345/// parseDirectiveCFIRelOffset4346/// ::= .cfi_rel_offset register, offset4347bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {4348int64_t Register = 0, Offset = 0;43494350if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||4351parseAbsoluteExpression(Offset) || parseEOL())4352return true;43534354getStreamer().emitCFIRelOffset(Register, Offset, DirectiveLoc);4355return false;4356}43574358static bool isValidEncoding(int64_t Encoding) {4359if (Encoding & ~0xff)4360return false;43614362if (Encoding == dwarf::DW_EH_PE_omit)4363return true;43644365const unsigned Format = Encoding & 0xf;4366if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&4367Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&4368Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&4369Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)4370return false;43714372const unsigned Application = Encoding & 0x70;4373if (Application != dwarf::DW_EH_PE_absptr &&4374Application != dwarf::DW_EH_PE_pcrel)4375return false;43764377return true;4378}43794380/// parseDirectiveCFIPersonalityOrLsda4381/// IsPersonality true for cfi_personality, false for cfi_lsda4382/// ::= .cfi_personality encoding, [symbol_name]4383/// ::= .cfi_lsda encoding, [symbol_name]4384bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {4385int64_t Encoding = 0;4386if (parseAbsoluteExpression(Encoding))4387return true;4388if (Encoding == dwarf::DW_EH_PE_omit)4389return false;43904391StringRef Name;4392if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||4393parseComma() ||4394check(parseIdentifier(Name), "expected identifier in directive") ||4395parseEOL())4396return true;43974398MCSymbol *Sym = getContext().getOrCreateSymbol(Name);43994400if (IsPersonality)4401getStreamer().emitCFIPersonality(Sym, Encoding);4402else4403getStreamer().emitCFILsda(Sym, Encoding);4404return false;4405}44064407/// parseDirectiveCFIRememberState4408/// ::= .cfi_remember_state4409bool AsmParser::parseDirectiveCFIRememberState(SMLoc DirectiveLoc) {4410if (parseEOL())4411return true;4412getStreamer().emitCFIRememberState(DirectiveLoc);4413return false;4414}44154416/// parseDirectiveCFIRestoreState4417/// ::= .cfi_remember_state4418bool AsmParser::parseDirectiveCFIRestoreState(SMLoc DirectiveLoc) {4419if (parseEOL())4420return true;4421getStreamer().emitCFIRestoreState(DirectiveLoc);4422return false;4423}44244425/// parseDirectiveCFISameValue4426/// ::= .cfi_same_value register4427bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {4428int64_t Register = 0;44294430if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())4431return true;44324433getStreamer().emitCFISameValue(Register, DirectiveLoc);4434return false;4435}44364437/// parseDirectiveCFIRestore4438/// ::= .cfi_restore register4439bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {4440int64_t Register = 0;4441if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())4442return true;44434444getStreamer().emitCFIRestore(Register, DirectiveLoc);4445return false;4446}44474448/// parseDirectiveCFIEscape4449/// ::= .cfi_escape expression[,...]4450bool AsmParser::parseDirectiveCFIEscape(SMLoc DirectiveLoc) {4451std::string Values;4452int64_t CurrValue;4453if (parseAbsoluteExpression(CurrValue))4454return true;44554456Values.push_back((uint8_t)CurrValue);44574458while (getLexer().is(AsmToken::Comma)) {4459Lex();44604461if (parseAbsoluteExpression(CurrValue))4462return true;44634464Values.push_back((uint8_t)CurrValue);4465}44664467getStreamer().emitCFIEscape(Values, DirectiveLoc);4468return false;4469}44704471/// parseDirectiveCFIReturnColumn4472/// ::= .cfi_return_column register4473bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {4474int64_t Register = 0;4475if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())4476return true;4477getStreamer().emitCFIReturnColumn(Register);4478return false;4479}44804481/// parseDirectiveCFISignalFrame4482/// ::= .cfi_signal_frame4483bool AsmParser::parseDirectiveCFISignalFrame(SMLoc DirectiveLoc) {4484if (parseEOL())4485return true;44864487getStreamer().emitCFISignalFrame();4488return false;4489}44904491/// parseDirectiveCFIUndefined4492/// ::= .cfi_undefined register4493bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {4494int64_t Register = 0;44954496if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())4497return true;44984499getStreamer().emitCFIUndefined(Register, DirectiveLoc);4500return false;4501}45024503/// parseDirectiveCFILabel4504/// ::= .cfi_label label4505bool AsmParser::parseDirectiveCFILabel(SMLoc Loc) {4506StringRef Name;4507Loc = Lexer.getLoc();4508if (parseIdentifier(Name))4509return TokError("expected identifier");4510if (parseEOL())4511return true;4512getStreamer().emitCFILabelDirective(Loc, Name);4513return false;4514}45154516/// parseDirectiveAltmacro4517/// ::= .altmacro4518/// ::= .noaltmacro4519bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {4520if (parseEOL())4521return true;4522AltMacroMode = (Directive == ".altmacro");4523return false;4524}45254526/// parseDirectiveMacrosOnOff4527/// ::= .macros_on4528/// ::= .macros_off4529bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) {4530if (parseEOL())4531return true;4532setMacrosEnabled(Directive == ".macros_on");4533return false;4534}45354536/// parseDirectiveMacro4537/// ::= .macro name[,] [parameters]4538bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {4539StringRef Name;4540if (parseIdentifier(Name))4541return TokError("expected identifier in '.macro' directive");45424543if (getLexer().is(AsmToken::Comma))4544Lex();45454546MCAsmMacroParameters Parameters;4547while (getLexer().isNot(AsmToken::EndOfStatement)) {45484549if (!Parameters.empty() && Parameters.back().Vararg)4550return Error(Lexer.getLoc(), "vararg parameter '" +4551Parameters.back().Name +4552"' should be the last parameter");45534554MCAsmMacroParameter Parameter;4555if (parseIdentifier(Parameter.Name))4556return TokError("expected identifier in '.macro' directive");45574558// Emit an error if two (or more) named parameters share the same name4559for (const MCAsmMacroParameter& CurrParam : Parameters)4560if (CurrParam.Name == Parameter.Name)4561return TokError("macro '" + Name + "' has multiple parameters"4562" named '" + Parameter.Name + "'");45634564if (Lexer.is(AsmToken::Colon)) {4565Lex(); // consume ':'45664567SMLoc QualLoc;4568StringRef Qualifier;45694570QualLoc = Lexer.getLoc();4571if (parseIdentifier(Qualifier))4572return Error(QualLoc, "missing parameter qualifier for "4573"'" + Parameter.Name + "' in macro '" + Name + "'");45744575if (Qualifier == "req")4576Parameter.Required = true;4577else if (Qualifier == "vararg")4578Parameter.Vararg = true;4579else4580return Error(QualLoc, Qualifier + " is not a valid parameter qualifier "4581"for '" + Parameter.Name + "' in macro '" + Name + "'");4582}45834584if (getLexer().is(AsmToken::Equal)) {4585Lex();45864587SMLoc ParamLoc;45884589ParamLoc = Lexer.getLoc();4590if (parseMacroArgument(Parameter.Value, /*Vararg=*/false ))4591return true;45924593if (Parameter.Required)4594Warning(ParamLoc, "pointless default value for required parameter "4595"'" + Parameter.Name + "' in macro '" + Name + "'");4596}45974598Parameters.push_back(std::move(Parameter));45994600if (getLexer().is(AsmToken::Comma))4601Lex();4602}46034604// Eat just the end of statement.4605Lexer.Lex();46064607// Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors4608AsmToken EndToken, StartToken = getTok();4609unsigned MacroDepth = 0;4610// Lex the macro definition.4611while (true) {4612// Ignore Lexing errors in macros.4613while (Lexer.is(AsmToken::Error)) {4614Lexer.Lex();4615}46164617// Check whether we have reached the end of the file.4618if (getLexer().is(AsmToken::Eof))4619return Error(DirectiveLoc, "no matching '.endmacro' in definition");46204621// Otherwise, check whether we have reach the .endmacro or the start of a4622// preprocessor line marker.4623if (getLexer().is(AsmToken::Identifier)) {4624if (getTok().getIdentifier() == ".endm" ||4625getTok().getIdentifier() == ".endmacro") {4626if (MacroDepth == 0) { // Outermost macro.4627EndToken = getTok();4628Lexer.Lex();4629if (getLexer().isNot(AsmToken::EndOfStatement))4630return TokError("unexpected token in '" + EndToken.getIdentifier() +4631"' directive");4632break;4633} else {4634// Otherwise we just found the end of an inner macro.4635--MacroDepth;4636}4637} else if (getTok().getIdentifier() == ".macro") {4638// We allow nested macros. Those aren't instantiated until the outermost4639// macro is expanded so just ignore them for now.4640++MacroDepth;4641}4642} else if (Lexer.is(AsmToken::HashDirective)) {4643(void)parseCppHashLineFilenameComment(getLexer().getLoc());4644}46454646// Otherwise, scan til the end of the statement.4647eatToEndOfStatement();4648}46494650if (getContext().lookupMacro(Name)) {4651return Error(DirectiveLoc, "macro '" + Name + "' is already defined");4652}46534654const char *BodyStart = StartToken.getLoc().getPointer();4655const char *BodyEnd = EndToken.getLoc().getPointer();4656StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);4657checkForBadMacro(DirectiveLoc, Name, Body, Parameters);4658MCAsmMacro Macro(Name, Body, std::move(Parameters));4659DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";4660Macro.dump());4661getContext().defineMacro(Name, std::move(Macro));4662return false;4663}46644665/// checkForBadMacro4666///4667/// With the support added for named parameters there may be code out there that4668/// is transitioning from positional parameters. In versions of gas that did4669/// not support named parameters they would be ignored on the macro definition.4670/// But to support both styles of parameters this is not possible so if a macro4671/// definition has named parameters but does not use them and has what appears4672/// to be positional parameters, strings like $1, $2, ... and $n, then issue a4673/// warning that the positional parameter found in body which have no effect.4674/// Hoping the developer will either remove the named parameters from the macro4675/// definition so the positional parameters get used if that was what was4676/// intended or change the macro to use the named parameters. It is possible4677/// this warning will trigger when the none of the named parameters are used4678/// and the strings like $1 are infact to simply to be passed trough unchanged.4679void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,4680StringRef Body,4681ArrayRef<MCAsmMacroParameter> Parameters) {4682// If this macro is not defined with named parameters the warning we are4683// checking for here doesn't apply.4684unsigned NParameters = Parameters.size();4685if (NParameters == 0)4686return;46874688bool NamedParametersFound = false;4689bool PositionalParametersFound = false;46904691// Look at the body of the macro for use of both the named parameters and what4692// are likely to be positional parameters. This is what expandMacro() is4693// doing when it finds the parameters in the body.4694while (!Body.empty()) {4695// Scan for the next possible parameter.4696std::size_t End = Body.size(), Pos = 0;4697for (; Pos != End; ++Pos) {4698// Check for a substitution or escape.4699// This macro is defined with parameters, look for \foo, \bar, etc.4700if (Body[Pos] == '\\' && Pos + 1 != End)4701break;47024703// This macro should have parameters, but look for $0, $1, ..., $n too.4704if (Body[Pos] != '$' || Pos + 1 == End)4705continue;4706char Next = Body[Pos + 1];4707if (Next == '$' || Next == 'n' ||4708isdigit(static_cast<unsigned char>(Next)))4709break;4710}47114712// Check if we reached the end.4713if (Pos == End)4714break;47154716if (Body[Pos] == '$') {4717switch (Body[Pos + 1]) {4718// $$ => $4719case '$':4720break;47214722// $n => number of arguments4723case 'n':4724PositionalParametersFound = true;4725break;47264727// $[0-9] => argument4728default: {4729PositionalParametersFound = true;4730break;4731}4732}4733Pos += 2;4734} else {4735unsigned I = Pos + 1;4736while (isIdentifierChar(Body[I]) && I + 1 != End)4737++I;47384739const char *Begin = Body.data() + Pos + 1;4740StringRef Argument(Begin, I - (Pos + 1));4741unsigned Index = 0;4742for (; Index < NParameters; ++Index)4743if (Parameters[Index].Name == Argument)4744break;47454746if (Index == NParameters) {4747if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')4748Pos += 3;4749else {4750Pos = I;4751}4752} else {4753NamedParametersFound = true;4754Pos += 1 + Argument.size();4755}4756}4757// Update the scan point.4758Body = Body.substr(Pos);4759}47604761if (!NamedParametersFound && PositionalParametersFound)4762Warning(DirectiveLoc, "macro defined with named parameters which are not "4763"used in macro body, possible positional parameter "4764"found in body which will have no effect");4765}47664767/// parseDirectiveExitMacro4768/// ::= .exitm4769bool AsmParser::parseDirectiveExitMacro(StringRef Directive) {4770if (parseEOL())4771return true;47724773if (!isInsideMacroInstantiation())4774return TokError("unexpected '" + Directive + "' in file, "4775"no current macro definition");47764777// Exit all conditionals that are active in the current macro.4778while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {4779TheCondState = TheCondStack.back();4780TheCondStack.pop_back();4781}47824783handleMacroExit();4784return false;4785}47864787/// parseDirectiveEndMacro4788/// ::= .endm4789/// ::= .endmacro4790bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {4791if (getLexer().isNot(AsmToken::EndOfStatement))4792return TokError("unexpected token in '" + Directive + "' directive");47934794// If we are inside a macro instantiation, terminate the current4795// instantiation.4796if (isInsideMacroInstantiation()) {4797handleMacroExit();4798return false;4799}48004801// Otherwise, this .endmacro is a stray entry in the file; well formed4802// .endmacro directives are handled during the macro definition parsing.4803return TokError("unexpected '" + Directive + "' in file, "4804"no current macro definition");4805}48064807/// parseDirectivePurgeMacro4808/// ::= .purgem name4809bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {4810StringRef Name;4811SMLoc Loc;4812if (parseTokenLoc(Loc) ||4813check(parseIdentifier(Name), Loc,4814"expected identifier in '.purgem' directive") ||4815parseEOL())4816return true;48174818if (!getContext().lookupMacro(Name))4819return Error(DirectiveLoc, "macro '" + Name + "' is not defined");48204821getContext().undefineMacro(Name);4822DEBUG_WITH_TYPE("asm-macros", dbgs()4823<< "Un-defining macro: " << Name << "\n");4824return false;4825}48264827/// parseDirectiveBundleAlignMode4828/// ::= {.bundle_align_mode} expression4829bool AsmParser::parseDirectiveBundleAlignMode() {4830// Expect a single argument: an expression that evaluates to a constant4831// in the inclusive range 0-30.4832SMLoc ExprLoc = getLexer().getLoc();4833int64_t AlignSizePow2;4834if (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) ||4835parseEOL() ||4836check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc,4837"invalid bundle alignment size (expected between 0 and 30)"))4838return true;48394840getStreamer().emitBundleAlignMode(Align(1ULL << AlignSizePow2));4841return false;4842}48434844/// parseDirectiveBundleLock4845/// ::= {.bundle_lock} [align_to_end]4846bool AsmParser::parseDirectiveBundleLock() {4847if (checkForValidSection())4848return true;4849bool AlignToEnd = false;48504851StringRef Option;4852SMLoc Loc = getTok().getLoc();4853const char *kInvalidOptionError =4854"invalid option for '.bundle_lock' directive";48554856if (!parseOptionalToken(AsmToken::EndOfStatement)) {4857if (check(parseIdentifier(Option), Loc, kInvalidOptionError) ||4858check(Option != "align_to_end", Loc, kInvalidOptionError) || parseEOL())4859return true;4860AlignToEnd = true;4861}48624863getStreamer().emitBundleLock(AlignToEnd);4864return false;4865}48664867/// parseDirectiveBundleLock4868/// ::= {.bundle_lock}4869bool AsmParser::parseDirectiveBundleUnlock() {4870if (checkForValidSection() || parseEOL())4871return true;48724873getStreamer().emitBundleUnlock();4874return false;4875}48764877/// parseDirectiveSpace4878/// ::= (.skip | .space) expression [ , expression ]4879bool AsmParser::parseDirectiveSpace(StringRef IDVal) {4880SMLoc NumBytesLoc = Lexer.getLoc();4881const MCExpr *NumBytes;4882if (checkForValidSection() || parseExpression(NumBytes))4883return true;48844885int64_t FillExpr = 0;4886if (parseOptionalToken(AsmToken::Comma))4887if (parseAbsoluteExpression(FillExpr))4888return true;4889if (parseEOL())4890return true;48914892// FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.4893getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc);48944895return false;4896}48974898/// parseDirectiveDCB4899/// ::= .dcb.{b, l, w} expression, expression4900bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) {4901SMLoc NumValuesLoc = Lexer.getLoc();4902int64_t NumValues;4903if (checkForValidSection() || parseAbsoluteExpression(NumValues))4904return true;49054906if (NumValues < 0) {4907Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");4908return false;4909}49104911if (parseComma())4912return true;49134914const MCExpr *Value;4915SMLoc ExprLoc = getLexer().getLoc();4916if (parseExpression(Value))4917return true;49184919// Special case constant expressions to match code generator.4920if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {4921assert(Size <= 8 && "Invalid size");4922uint64_t IntValue = MCE->getValue();4923if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))4924return Error(ExprLoc, "literal value out of range for directive");4925for (uint64_t i = 0, e = NumValues; i != e; ++i)4926getStreamer().emitIntValue(IntValue, Size);4927} else {4928for (uint64_t i = 0, e = NumValues; i != e; ++i)4929getStreamer().emitValue(Value, Size, ExprLoc);4930}49314932return parseEOL();4933}49344935/// parseDirectiveRealDCB4936/// ::= .dcb.{d, s} expression, expression4937bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) {4938SMLoc NumValuesLoc = Lexer.getLoc();4939int64_t NumValues;4940if (checkForValidSection() || parseAbsoluteExpression(NumValues))4941return true;49424943if (NumValues < 0) {4944Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");4945return false;4946}49474948if (parseComma())4949return true;49504951APInt AsInt;4952if (parseRealValue(Semantics, AsInt) || parseEOL())4953return true;49544955for (uint64_t i = 0, e = NumValues; i != e; ++i)4956getStreamer().emitIntValue(AsInt.getLimitedValue(),4957AsInt.getBitWidth() / 8);49584959return false;4960}49614962/// parseDirectiveDS4963/// ::= .ds.{b, d, l, p, s, w, x} expression4964bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) {4965SMLoc NumValuesLoc = Lexer.getLoc();4966int64_t NumValues;4967if (checkForValidSection() || parseAbsoluteExpression(NumValues) ||4968parseEOL())4969return true;49704971if (NumValues < 0) {4972Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");4973return false;4974}49754976for (uint64_t i = 0, e = NumValues; i != e; ++i)4977getStreamer().emitFill(Size, 0);49784979return false;4980}49814982/// parseDirectiveLEB1284983/// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]4984bool AsmParser::parseDirectiveLEB128(bool Signed) {4985if (checkForValidSection())4986return true;49874988auto parseOp = [&]() -> bool {4989const MCExpr *Value;4990if (parseExpression(Value))4991return true;4992if (Signed)4993getStreamer().emitSLEB128Value(Value);4994else4995getStreamer().emitULEB128Value(Value);4996return false;4997};49984999return parseMany(parseOp);5000}50015002/// parseDirectiveSymbolAttribute5003/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]5004bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {5005auto parseOp = [&]() -> bool {5006StringRef Name;5007SMLoc Loc = getTok().getLoc();5008if (parseIdentifier(Name))5009return Error(Loc, "expected identifier");50105011if (discardLTOSymbol(Name))5012return false;50135014MCSymbol *Sym = getContext().getOrCreateSymbol(Name);50155016// Assembler local symbols don't make any sense here, except for directives5017// that the symbol should be tagged.5018if (Sym->isTemporary() && Attr != MCSA_Memtag)5019return Error(Loc, "non-local symbol required");50205021if (!getStreamer().emitSymbolAttribute(Sym, Attr))5022return Error(Loc, "unable to emit symbol attribute");5023return false;5024};50255026return parseMany(parseOp);5027}50285029/// parseDirectiveComm5030/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]5031bool AsmParser::parseDirectiveComm(bool IsLocal) {5032if (checkForValidSection())5033return true;50345035SMLoc IDLoc = getLexer().getLoc();5036StringRef Name;5037if (parseIdentifier(Name))5038return TokError("expected identifier in directive");50395040// Handle the identifier as the key symbol.5041MCSymbol *Sym = getContext().getOrCreateSymbol(Name);50425043if (parseComma())5044return true;50455046int64_t Size;5047SMLoc SizeLoc = getLexer().getLoc();5048if (parseAbsoluteExpression(Size))5049return true;50505051int64_t Pow2Alignment = 0;5052SMLoc Pow2AlignmentLoc;5053if (getLexer().is(AsmToken::Comma)) {5054Lex();5055Pow2AlignmentLoc = getLexer().getLoc();5056if (parseAbsoluteExpression(Pow2Alignment))5057return true;50585059LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();5060if (IsLocal && LCOMM == LCOMM::NoAlignment)5061return Error(Pow2AlignmentLoc, "alignment not supported on this target");50625063// If this target takes alignments in bytes (not log) validate and convert.5064if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||5065(IsLocal && LCOMM == LCOMM::ByteAlignment)) {5066if (!isPowerOf2_64(Pow2Alignment))5067return Error(Pow2AlignmentLoc, "alignment must be a power of 2");5068Pow2Alignment = Log2_64(Pow2Alignment);5069}5070}50715072if (parseEOL())5073return true;50745075// NOTE: a size of zero for a .comm should create a undefined symbol5076// but a size of .lcomm creates a bss symbol of size zero.5077if (Size < 0)5078return Error(SizeLoc, "size must be non-negative");50795080Sym->redefineIfPossible();5081if (!Sym->isUndefined())5082return Error(IDLoc, "invalid symbol redefinition");50835084// Create the Symbol as a common or local common with Size and Pow2Alignment5085if (IsLocal) {5086getStreamer().emitLocalCommonSymbol(Sym, Size,5087Align(1ULL << Pow2Alignment));5088return false;5089}50905091getStreamer().emitCommonSymbol(Sym, Size, Align(1ULL << Pow2Alignment));5092return false;5093}50945095/// parseDirectiveAbort5096/// ::= .abort [... message ...]5097bool AsmParser::parseDirectiveAbort(SMLoc DirectiveLoc) {5098StringRef Str = parseStringToEndOfStatement();5099if (parseEOL())5100return true;51015102if (Str.empty())5103return Error(DirectiveLoc, ".abort detected. Assembly stopping");51045105// FIXME: Actually abort assembly here.5106return Error(DirectiveLoc,5107".abort '" + Str + "' detected. Assembly stopping");5108}51095110/// parseDirectiveInclude5111/// ::= .include "filename"5112bool AsmParser::parseDirectiveInclude() {5113// Allow the strings to have escaped octal character sequence.5114std::string Filename;5115SMLoc IncludeLoc = getTok().getLoc();51165117if (check(getTok().isNot(AsmToken::String),5118"expected string in '.include' directive") ||5119parseEscapedString(Filename) ||5120check(getTok().isNot(AsmToken::EndOfStatement),5121"unexpected token in '.include' directive") ||5122// Attempt to switch the lexer to the included file before consuming the5123// end of statement to avoid losing it when we switch.5124check(enterIncludeFile(Filename), IncludeLoc,5125"Could not find include file '" + Filename + "'"))5126return true;51275128return false;5129}51305131/// parseDirectiveIncbin5132/// ::= .incbin "filename" [ , skip [ , count ] ]5133bool AsmParser::parseDirectiveIncbin() {5134// Allow the strings to have escaped octal character sequence.5135std::string Filename;5136SMLoc IncbinLoc = getTok().getLoc();5137if (check(getTok().isNot(AsmToken::String),5138"expected string in '.incbin' directive") ||5139parseEscapedString(Filename))5140return true;51415142int64_t Skip = 0;5143const MCExpr *Count = nullptr;5144SMLoc SkipLoc, CountLoc;5145if (parseOptionalToken(AsmToken::Comma)) {5146// The skip expression can be omitted while specifying the count, e.g:5147// .incbin "filename",,45148if (getTok().isNot(AsmToken::Comma)) {5149if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip))5150return true;5151}5152if (parseOptionalToken(AsmToken::Comma)) {5153CountLoc = getTok().getLoc();5154if (parseExpression(Count))5155return true;5156}5157}51585159if (parseEOL())5160return true;51615162if (check(Skip < 0, SkipLoc, "skip is negative"))5163return true;51645165// Attempt to process the included file.5166if (processIncbinFile(Filename, Skip, Count, CountLoc))5167return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'");5168return false;5169}51705171/// parseDirectiveIf5172/// ::= .if{,eq,ge,gt,le,lt,ne} expression5173bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {5174TheCondStack.push_back(TheCondState);5175TheCondState.TheCond = AsmCond::IfCond;5176if (TheCondState.Ignore) {5177eatToEndOfStatement();5178} else {5179int64_t ExprValue;5180if (parseAbsoluteExpression(ExprValue) || parseEOL())5181return true;51825183switch (DirKind) {5184default:5185llvm_unreachable("unsupported directive");5186case DK_IF:5187case DK_IFNE:5188break;5189case DK_IFEQ:5190ExprValue = ExprValue == 0;5191break;5192case DK_IFGE:5193ExprValue = ExprValue >= 0;5194break;5195case DK_IFGT:5196ExprValue = ExprValue > 0;5197break;5198case DK_IFLE:5199ExprValue = ExprValue <= 0;5200break;5201case DK_IFLT:5202ExprValue = ExprValue < 0;5203break;5204}52055206TheCondState.CondMet = ExprValue;5207TheCondState.Ignore = !TheCondState.CondMet;5208}52095210return false;5211}52125213/// parseDirectiveIfb5214/// ::= .ifb string5215bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {5216TheCondStack.push_back(TheCondState);5217TheCondState.TheCond = AsmCond::IfCond;52185219if (TheCondState.Ignore) {5220eatToEndOfStatement();5221} else {5222StringRef Str = parseStringToEndOfStatement();52235224if (parseEOL())5225return true;52265227TheCondState.CondMet = ExpectBlank == Str.empty();5228TheCondState.Ignore = !TheCondState.CondMet;5229}52305231return false;5232}52335234/// parseDirectiveIfc5235/// ::= .ifc string1, string25236/// ::= .ifnc string1, string25237bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {5238TheCondStack.push_back(TheCondState);5239TheCondState.TheCond = AsmCond::IfCond;52405241if (TheCondState.Ignore) {5242eatToEndOfStatement();5243} else {5244StringRef Str1 = parseStringToComma();52455246if (parseComma())5247return true;52485249StringRef Str2 = parseStringToEndOfStatement();52505251if (parseEOL())5252return true;52535254TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim());5255TheCondState.Ignore = !TheCondState.CondMet;5256}52575258return false;5259}52605261/// parseDirectiveIfeqs5262/// ::= .ifeqs string1, string25263bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {5264if (Lexer.isNot(AsmToken::String)) {5265if (ExpectEqual)5266return TokError("expected string parameter for '.ifeqs' directive");5267return TokError("expected string parameter for '.ifnes' directive");5268}52695270StringRef String1 = getTok().getStringContents();5271Lex();52725273if (Lexer.isNot(AsmToken::Comma)) {5274if (ExpectEqual)5275return TokError(5276"expected comma after first string for '.ifeqs' directive");5277return TokError("expected comma after first string for '.ifnes' directive");5278}52795280Lex();52815282if (Lexer.isNot(AsmToken::String)) {5283if (ExpectEqual)5284return TokError("expected string parameter for '.ifeqs' directive");5285return TokError("expected string parameter for '.ifnes' directive");5286}52875288StringRef String2 = getTok().getStringContents();5289Lex();52905291TheCondStack.push_back(TheCondState);5292TheCondState.TheCond = AsmCond::IfCond;5293TheCondState.CondMet = ExpectEqual == (String1 == String2);5294TheCondState.Ignore = !TheCondState.CondMet;52955296return false;5297}52985299/// parseDirectiveIfdef5300/// ::= .ifdef symbol5301bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {5302StringRef Name;5303TheCondStack.push_back(TheCondState);5304TheCondState.TheCond = AsmCond::IfCond;53055306if (TheCondState.Ignore) {5307eatToEndOfStatement();5308} else {5309if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") ||5310parseEOL())5311return true;53125313MCSymbol *Sym = getContext().lookupSymbol(Name);53145315if (expect_defined)5316TheCondState.CondMet = (Sym && !Sym->isUndefined(false));5317else5318TheCondState.CondMet = (!Sym || Sym->isUndefined(false));5319TheCondState.Ignore = !TheCondState.CondMet;5320}53215322return false;5323}53245325/// parseDirectiveElseIf5326/// ::= .elseif expression5327bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {5328if (TheCondState.TheCond != AsmCond::IfCond &&5329TheCondState.TheCond != AsmCond::ElseIfCond)5330return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"5331" .if or an .elseif");5332TheCondState.TheCond = AsmCond::ElseIfCond;53335334bool LastIgnoreState = false;5335if (!TheCondStack.empty())5336LastIgnoreState = TheCondStack.back().Ignore;5337if (LastIgnoreState || TheCondState.CondMet) {5338TheCondState.Ignore = true;5339eatToEndOfStatement();5340} else {5341int64_t ExprValue;5342if (parseAbsoluteExpression(ExprValue))5343return true;53445345if (parseEOL())5346return true;53475348TheCondState.CondMet = ExprValue;5349TheCondState.Ignore = !TheCondState.CondMet;5350}53515352return false;5353}53545355/// parseDirectiveElse5356/// ::= .else5357bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {5358if (parseEOL())5359return true;53605361if (TheCondState.TheCond != AsmCond::IfCond &&5362TheCondState.TheCond != AsmCond::ElseIfCond)5363return Error(DirectiveLoc, "Encountered a .else that doesn't follow "5364" an .if or an .elseif");5365TheCondState.TheCond = AsmCond::ElseCond;5366bool LastIgnoreState = false;5367if (!TheCondStack.empty())5368LastIgnoreState = TheCondStack.back().Ignore;5369if (LastIgnoreState || TheCondState.CondMet)5370TheCondState.Ignore = true;5371else5372TheCondState.Ignore = false;53735374return false;5375}53765377/// parseDirectiveEnd5378/// ::= .end5379bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {5380if (parseEOL())5381return true;53825383while (Lexer.isNot(AsmToken::Eof))5384Lexer.Lex();53855386return false;5387}53885389/// parseDirectiveError5390/// ::= .err5391/// ::= .error [string]5392bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {5393if (!TheCondStack.empty()) {5394if (TheCondStack.back().Ignore) {5395eatToEndOfStatement();5396return false;5397}5398}53995400if (!WithMessage)5401return Error(L, ".err encountered");54025403StringRef Message = ".error directive invoked in source file";5404if (Lexer.isNot(AsmToken::EndOfStatement)) {5405if (Lexer.isNot(AsmToken::String))5406return TokError(".error argument must be a string");54075408Message = getTok().getStringContents();5409Lex();5410}54115412return Error(L, Message);5413}54145415/// parseDirectiveWarning5416/// ::= .warning [string]5417bool AsmParser::parseDirectiveWarning(SMLoc L) {5418if (!TheCondStack.empty()) {5419if (TheCondStack.back().Ignore) {5420eatToEndOfStatement();5421return false;5422}5423}54245425StringRef Message = ".warning directive invoked in source file";54265427if (!parseOptionalToken(AsmToken::EndOfStatement)) {5428if (Lexer.isNot(AsmToken::String))5429return TokError(".warning argument must be a string");54305431Message = getTok().getStringContents();5432Lex();5433if (parseEOL())5434return true;5435}54365437return Warning(L, Message);5438}54395440/// parseDirectiveEndIf5441/// ::= .endif5442bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {5443if (parseEOL())5444return true;54455446if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())5447return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "5448"an .if or .else");5449if (!TheCondStack.empty()) {5450TheCondState = TheCondStack.back();5451TheCondStack.pop_back();5452}54535454return false;5455}54565457void AsmParser::initializeDirectiveKindMap() {5458/* Lookup will be done with the directive5459* converted to lower case, so all these5460* keys should be lower case.5461* (target specific directives are handled5462* elsewhere)5463*/5464DirectiveKindMap[".set"] = DK_SET;5465DirectiveKindMap[".equ"] = DK_EQU;5466DirectiveKindMap[".equiv"] = DK_EQUIV;5467DirectiveKindMap[".ascii"] = DK_ASCII;5468DirectiveKindMap[".asciz"] = DK_ASCIZ;5469DirectiveKindMap[".string"] = DK_STRING;5470DirectiveKindMap[".byte"] = DK_BYTE;5471DirectiveKindMap[".short"] = DK_SHORT;5472DirectiveKindMap[".value"] = DK_VALUE;5473DirectiveKindMap[".2byte"] = DK_2BYTE;5474DirectiveKindMap[".long"] = DK_LONG;5475DirectiveKindMap[".int"] = DK_INT;5476DirectiveKindMap[".4byte"] = DK_4BYTE;5477DirectiveKindMap[".quad"] = DK_QUAD;5478DirectiveKindMap[".8byte"] = DK_8BYTE;5479DirectiveKindMap[".octa"] = DK_OCTA;5480DirectiveKindMap[".single"] = DK_SINGLE;5481DirectiveKindMap[".float"] = DK_FLOAT;5482DirectiveKindMap[".double"] = DK_DOUBLE;5483DirectiveKindMap[".align"] = DK_ALIGN;5484DirectiveKindMap[".align32"] = DK_ALIGN32;5485DirectiveKindMap[".balign"] = DK_BALIGN;5486DirectiveKindMap[".balignw"] = DK_BALIGNW;5487DirectiveKindMap[".balignl"] = DK_BALIGNL;5488DirectiveKindMap[".p2align"] = DK_P2ALIGN;5489DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW;5490DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL;5491DirectiveKindMap[".org"] = DK_ORG;5492DirectiveKindMap[".fill"] = DK_FILL;5493DirectiveKindMap[".zero"] = DK_ZERO;5494DirectiveKindMap[".extern"] = DK_EXTERN;5495DirectiveKindMap[".globl"] = DK_GLOBL;5496DirectiveKindMap[".global"] = DK_GLOBAL;5497DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE;5498DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP;5499DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER;5500DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN;5501DirectiveKindMap[".reference"] = DK_REFERENCE;5502DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION;5503DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE;5504DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN;5505DirectiveKindMap[".cold"] = DK_COLD;5506DirectiveKindMap[".comm"] = DK_COMM;5507DirectiveKindMap[".common"] = DK_COMMON;5508DirectiveKindMap[".lcomm"] = DK_LCOMM;5509DirectiveKindMap[".abort"] = DK_ABORT;5510DirectiveKindMap[".include"] = DK_INCLUDE;5511DirectiveKindMap[".incbin"] = DK_INCBIN;5512DirectiveKindMap[".code16"] = DK_CODE16;5513DirectiveKindMap[".code16gcc"] = DK_CODE16GCC;5514DirectiveKindMap[".rept"] = DK_REPT;5515DirectiveKindMap[".rep"] = DK_REPT;5516DirectiveKindMap[".irp"] = DK_IRP;5517DirectiveKindMap[".irpc"] = DK_IRPC;5518DirectiveKindMap[".endr"] = DK_ENDR;5519DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE;5520DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK;5521DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK;5522DirectiveKindMap[".if"] = DK_IF;5523DirectiveKindMap[".ifeq"] = DK_IFEQ;5524DirectiveKindMap[".ifge"] = DK_IFGE;5525DirectiveKindMap[".ifgt"] = DK_IFGT;5526DirectiveKindMap[".ifle"] = DK_IFLE;5527DirectiveKindMap[".iflt"] = DK_IFLT;5528DirectiveKindMap[".ifne"] = DK_IFNE;5529DirectiveKindMap[".ifb"] = DK_IFB;5530DirectiveKindMap[".ifnb"] = DK_IFNB;5531DirectiveKindMap[".ifc"] = DK_IFC;5532DirectiveKindMap[".ifeqs"] = DK_IFEQS;5533DirectiveKindMap[".ifnc"] = DK_IFNC;5534DirectiveKindMap[".ifnes"] = DK_IFNES;5535DirectiveKindMap[".ifdef"] = DK_IFDEF;5536DirectiveKindMap[".ifndef"] = DK_IFNDEF;5537DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF;5538DirectiveKindMap[".elseif"] = DK_ELSEIF;5539DirectiveKindMap[".else"] = DK_ELSE;5540DirectiveKindMap[".end"] = DK_END;5541DirectiveKindMap[".endif"] = DK_ENDIF;5542DirectiveKindMap[".skip"] = DK_SKIP;5543DirectiveKindMap[".space"] = DK_SPACE;5544DirectiveKindMap[".file"] = DK_FILE;5545DirectiveKindMap[".line"] = DK_LINE;5546DirectiveKindMap[".loc"] = DK_LOC;5547DirectiveKindMap[".stabs"] = DK_STABS;5548DirectiveKindMap[".cv_file"] = DK_CV_FILE;5549DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;5550DirectiveKindMap[".cv_loc"] = DK_CV_LOC;5551DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;5552DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;5553DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;5554DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;5555DirectiveKindMap[".cv_string"] = DK_CV_STRING;5556DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;5557DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;5558DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;5559DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;5560DirectiveKindMap[".sleb128"] = DK_SLEB128;5561DirectiveKindMap[".uleb128"] = DK_ULEB128;5562DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;5563DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;5564DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;5565DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;5566DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;5567DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;5568DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;5569DirectiveKindMap[".cfi_llvm_def_aspace_cfa"] = DK_CFI_LLVM_DEF_ASPACE_CFA;5570DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;5571DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;5572DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;5573DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;5574DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;5575DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;5576DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;5577DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;5578DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;5579DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;5580DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;5581DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;5582DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;5583DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;5584DirectiveKindMap[".cfi_label"] = DK_CFI_LABEL;5585DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;5586DirectiveKindMap[".cfi_mte_tagged_frame"] = DK_CFI_MTE_TAGGED_FRAME;5587DirectiveKindMap[".macros_on"] = DK_MACROS_ON;5588DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;5589DirectiveKindMap[".macro"] = DK_MACRO;5590DirectiveKindMap[".exitm"] = DK_EXITM;5591DirectiveKindMap[".endm"] = DK_ENDM;5592DirectiveKindMap[".endmacro"] = DK_ENDMACRO;5593DirectiveKindMap[".purgem"] = DK_PURGEM;5594DirectiveKindMap[".err"] = DK_ERR;5595DirectiveKindMap[".error"] = DK_ERROR;5596DirectiveKindMap[".warning"] = DK_WARNING;5597DirectiveKindMap[".altmacro"] = DK_ALTMACRO;5598DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;5599DirectiveKindMap[".reloc"] = DK_RELOC;5600DirectiveKindMap[".dc"] = DK_DC;5601DirectiveKindMap[".dc.a"] = DK_DC_A;5602DirectiveKindMap[".dc.b"] = DK_DC_B;5603DirectiveKindMap[".dc.d"] = DK_DC_D;5604DirectiveKindMap[".dc.l"] = DK_DC_L;5605DirectiveKindMap[".dc.s"] = DK_DC_S;5606DirectiveKindMap[".dc.w"] = DK_DC_W;5607DirectiveKindMap[".dc.x"] = DK_DC_X;5608DirectiveKindMap[".dcb"] = DK_DCB;5609DirectiveKindMap[".dcb.b"] = DK_DCB_B;5610DirectiveKindMap[".dcb.d"] = DK_DCB_D;5611DirectiveKindMap[".dcb.l"] = DK_DCB_L;5612DirectiveKindMap[".dcb.s"] = DK_DCB_S;5613DirectiveKindMap[".dcb.w"] = DK_DCB_W;5614DirectiveKindMap[".dcb.x"] = DK_DCB_X;5615DirectiveKindMap[".ds"] = DK_DS;5616DirectiveKindMap[".ds.b"] = DK_DS_B;5617DirectiveKindMap[".ds.d"] = DK_DS_D;5618DirectiveKindMap[".ds.l"] = DK_DS_L;5619DirectiveKindMap[".ds.p"] = DK_DS_P;5620DirectiveKindMap[".ds.s"] = DK_DS_S;5621DirectiveKindMap[".ds.w"] = DK_DS_W;5622DirectiveKindMap[".ds.x"] = DK_DS_X;5623DirectiveKindMap[".print"] = DK_PRINT;5624DirectiveKindMap[".addrsig"] = DK_ADDRSIG;5625DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM;5626DirectiveKindMap[".pseudoprobe"] = DK_PSEUDO_PROBE;5627DirectiveKindMap[".lto_discard"] = DK_LTO_DISCARD;5628DirectiveKindMap[".lto_set_conditional"] = DK_LTO_SET_CONDITIONAL;5629DirectiveKindMap[".memtag"] = DK_MEMTAG;5630}56315632MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {5633AsmToken EndToken, StartToken = getTok();56345635unsigned NestLevel = 0;5636while (true) {5637// Check whether we have reached the end of the file.5638if (getLexer().is(AsmToken::Eof)) {5639printError(DirectiveLoc, "no matching '.endr' in definition");5640return nullptr;5641}56425643if (Lexer.is(AsmToken::Identifier)) {5644StringRef Ident = getTok().getIdentifier();5645if (Ident == ".rep" || Ident == ".rept" || Ident == ".irp" ||5646Ident == ".irpc") {5647++NestLevel;5648} else if (Ident == ".endr") {5649if (NestLevel == 0) {5650EndToken = getTok();5651Lex();5652if (Lexer.is(AsmToken::EndOfStatement))5653break;5654printError(getTok().getLoc(), "expected newline");5655return nullptr;5656}5657--NestLevel;5658}5659}56605661// Otherwise, scan till the end of the statement.5662eatToEndOfStatement();5663}56645665const char *BodyStart = StartToken.getLoc().getPointer();5666const char *BodyEnd = EndToken.getLoc().getPointer();5667StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);56685669// We Are Anonymous.5670MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());5671return &MacroLikeBodies.back();5672}56735674void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,5675raw_svector_ostream &OS) {5676OS << ".endr\n";56775678std::unique_ptr<MemoryBuffer> Instantiation =5679MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");56805681// Create the macro instantiation object and add to the current macro5682// instantiation stack.5683MacroInstantiation *MI = new MacroInstantiation{5684DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};5685ActiveMacros.push_back(MI);56865687// Jump to the macro instantiation and prime the lexer.5688CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());5689Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());5690Lex();5691}56925693/// parseDirectiveRept5694/// ::= .rep | .rept count5695bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {5696const MCExpr *CountExpr;5697SMLoc CountLoc = getTok().getLoc();5698if (parseExpression(CountExpr))5699return true;57005701int64_t Count;5702if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {5703return Error(CountLoc, "unexpected token in '" + Dir + "' directive");5704}57055706if (check(Count < 0, CountLoc, "Count is negative") || parseEOL())5707return true;57085709// Lex the rept definition.5710MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);5711if (!M)5712return true;57135714// Macro instantiation is lexical, unfortunately. We construct a new buffer5715// to hold the macro body with substitutions.5716SmallString<256> Buf;5717raw_svector_ostream OS(Buf);5718while (Count--) {5719// Note that the AtPseudoVariable is disabled for instantiations of .rep(t).5720if (expandMacro(OS, *M, std::nullopt, std::nullopt, false))5721return true;5722}5723instantiateMacroLikeBody(M, DirectiveLoc, OS);57245725return false;5726}57275728/// parseDirectiveIrp5729/// ::= .irp symbol,values5730bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {5731MCAsmMacroParameter Parameter;5732MCAsmMacroArguments A;5733if (check(parseIdentifier(Parameter.Name),5734"expected identifier in '.irp' directive") ||5735parseComma() || parseMacroArguments(nullptr, A) || parseEOL())5736return true;57375738// Lex the irp definition.5739MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);5740if (!M)5741return true;57425743// Macro instantiation is lexical, unfortunately. We construct a new buffer5744// to hold the macro body with substitutions.5745SmallString<256> Buf;5746raw_svector_ostream OS(Buf);57475748for (const MCAsmMacroArgument &Arg : A) {5749// Note that the AtPseudoVariable is enabled for instantiations of .irp.5750// This is undocumented, but GAS seems to support it.5751if (expandMacro(OS, *M, Parameter, Arg, true))5752return true;5753}57545755instantiateMacroLikeBody(M, DirectiveLoc, OS);57565757return false;5758}57595760/// parseDirectiveIrpc5761/// ::= .irpc symbol,values5762bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {5763MCAsmMacroParameter Parameter;5764MCAsmMacroArguments A;57655766if (check(parseIdentifier(Parameter.Name),5767"expected identifier in '.irpc' directive") ||5768parseComma() || parseMacroArguments(nullptr, A))5769return true;57705771if (A.size() != 1 || A.front().size() != 1)5772return TokError("unexpected token in '.irpc' directive");5773if (parseEOL())5774return true;57755776// Lex the irpc definition.5777MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);5778if (!M)5779return true;57805781// Macro instantiation is lexical, unfortunately. We construct a new buffer5782// to hold the macro body with substitutions.5783SmallString<256> Buf;5784raw_svector_ostream OS(Buf);57855786StringRef Values = A.front().front().getString();5787for (std::size_t I = 0, End = Values.size(); I != End; ++I) {5788MCAsmMacroArgument Arg;5789Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1));57905791// Note that the AtPseudoVariable is enabled for instantiations of .irpc.5792// This is undocumented, but GAS seems to support it.5793if (expandMacro(OS, *M, Parameter, Arg, true))5794return true;5795}57965797instantiateMacroLikeBody(M, DirectiveLoc, OS);57985799return false;5800}58015802bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {5803if (ActiveMacros.empty())5804return TokError("unmatched '.endr' directive");58055806// The only .repl that should get here are the ones created by5807// instantiateMacroLikeBody.5808assert(getLexer().is(AsmToken::EndOfStatement));58095810handleMacroExit();5811return false;5812}58135814bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,5815size_t Len) {5816const MCExpr *Value;5817SMLoc ExprLoc = getLexer().getLoc();5818if (parseExpression(Value))5819return true;5820const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);5821if (!MCE)5822return Error(ExprLoc, "unexpected expression in _emit");5823uint64_t IntValue = MCE->getValue();5824if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))5825return Error(ExprLoc, "literal value out of range for directive");58265827Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);5828return false;5829}58305831bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {5832const MCExpr *Value;5833SMLoc ExprLoc = getLexer().getLoc();5834if (parseExpression(Value))5835return true;5836const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);5837if (!MCE)5838return Error(ExprLoc, "unexpected expression in align");5839uint64_t IntValue = MCE->getValue();5840if (!isPowerOf2_64(IntValue))5841return Error(ExprLoc, "literal value not a power of two greater then zero");58425843Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));5844return false;5845}58465847bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {5848const AsmToken StrTok = getTok();5849Lex();5850if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"')5851return Error(DirectiveLoc, "expected double quoted string after .print");5852if (parseEOL())5853return true;5854llvm::outs() << StrTok.getStringContents() << '\n';5855return false;5856}58575858bool AsmParser::parseDirectiveAddrsig() {5859if (parseEOL())5860return true;5861getStreamer().emitAddrsig();5862return false;5863}58645865bool AsmParser::parseDirectiveAddrsigSym() {5866StringRef Name;5867if (check(parseIdentifier(Name), "expected identifier") || parseEOL())5868return true;5869MCSymbol *Sym = getContext().getOrCreateSymbol(Name);5870getStreamer().emitAddrsigSym(Sym);5871return false;5872}58735874bool AsmParser::parseDirectivePseudoProbe() {5875int64_t Guid;5876int64_t Index;5877int64_t Type;5878int64_t Attr;5879int64_t Discriminator = 0;58805881if (parseIntToken(Guid, "unexpected token in '.pseudoprobe' directive"))5882return true;58835884if (parseIntToken(Index, "unexpected token in '.pseudoprobe' directive"))5885return true;58865887if (parseIntToken(Type, "unexpected token in '.pseudoprobe' directive"))5888return true;58895890if (parseIntToken(Attr, "unexpected token in '.pseudoprobe' directive"))5891return true;58925893if (hasDiscriminator(Attr)) {5894if (parseIntToken(Discriminator,5895"unexpected token in '.pseudoprobe' directive"))5896return true;5897}58985899// Parse inline stack like @ GUID:11:12 @ GUID:1:11 @ GUID:3:215900MCPseudoProbeInlineStack InlineStack;59015902while (getLexer().is(AsmToken::At)) {5903// eat @5904Lex();59055906int64_t CallerGuid = 0;5907if (getLexer().is(AsmToken::Integer)) {5908if (parseIntToken(CallerGuid,5909"unexpected token in '.pseudoprobe' directive"))5910return true;5911}59125913// eat colon5914if (getLexer().is(AsmToken::Colon))5915Lex();59165917int64_t CallerProbeId = 0;5918if (getLexer().is(AsmToken::Integer)) {5919if (parseIntToken(CallerProbeId,5920"unexpected token in '.pseudoprobe' directive"))5921return true;5922}59235924InlineSite Site(CallerGuid, CallerProbeId);5925InlineStack.push_back(Site);5926}59275928// Parse function entry name5929StringRef FnName;5930if (parseIdentifier(FnName))5931return Error(getLexer().getLoc(), "unexpected token in '.pseudoprobe' directive");5932MCSymbol *FnSym = getContext().lookupSymbol(FnName);59335934if (parseEOL())5935return true;59365937getStreamer().emitPseudoProbe(Guid, Index, Type, Attr, Discriminator,5938InlineStack, FnSym);5939return false;5940}59415942/// parseDirectiveLTODiscard5943/// ::= ".lto_discard" [ identifier ( , identifier )* ]5944/// The LTO library emits this directive to discard non-prevailing symbols.5945/// We ignore symbol assignments and attribute changes for the specified5946/// symbols.5947bool AsmParser::parseDirectiveLTODiscard() {5948auto ParseOp = [&]() -> bool {5949StringRef Name;5950SMLoc Loc = getTok().getLoc();5951if (parseIdentifier(Name))5952return Error(Loc, "expected identifier");5953LTODiscardSymbols.insert(Name);5954return false;5955};59565957LTODiscardSymbols.clear();5958return parseMany(ParseOp);5959}59605961// We are comparing pointers, but the pointers are relative to a single string.5962// Thus, this should always be deterministic.5963static int rewritesSort(const AsmRewrite *AsmRewriteA,5964const AsmRewrite *AsmRewriteB) {5965if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())5966return -1;5967if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())5968return 1;59695970// It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output5971// rewrite to the same location. Make sure the SizeDirective rewrite is5972// performed first, then the Imm/ImmPrefix and finally the Input/Output. This5973// ensures the sort algorithm is stable.5974if (AsmRewritePrecedence[AsmRewriteA->Kind] >5975AsmRewritePrecedence[AsmRewriteB->Kind])5976return -1;59775978if (AsmRewritePrecedence[AsmRewriteA->Kind] <5979AsmRewritePrecedence[AsmRewriteB->Kind])5980return 1;5981llvm_unreachable("Unstable rewrite sort.");5982}59835984bool AsmParser::parseMSInlineAsm(5985std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs,5986SmallVectorImpl<std::pair<void *, bool>> &OpDecls,5987SmallVectorImpl<std::string> &Constraints,5988SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,5989const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {5990SmallVector<void *, 4> InputDecls;5991SmallVector<void *, 4> OutputDecls;5992SmallVector<bool, 4> InputDeclsAddressOf;5993SmallVector<bool, 4> OutputDeclsAddressOf;5994SmallVector<std::string, 4> InputConstraints;5995SmallVector<std::string, 4> OutputConstraints;5996SmallVector<unsigned, 4> ClobberRegs;59975998SmallVector<AsmRewrite, 4> AsmStrRewrites;59996000// Prime the lexer.6001Lex();60026003// While we have input, parse each statement.6004unsigned InputIdx = 0;6005unsigned OutputIdx = 0;6006while (getLexer().isNot(AsmToken::Eof)) {6007// Parse curly braces marking block start/end6008if (parseCurlyBlockScope(AsmStrRewrites))6009continue;60106011ParseStatementInfo Info(&AsmStrRewrites);6012bool StatementErr = parseStatement(Info, &SI);60136014if (StatementErr || Info.ParseError) {6015// Emit pending errors if any exist.6016printPendingErrors();6017return true;6018}60196020// No pending error should exist here.6021assert(!hasPendingError() && "unexpected error from parseStatement");60226023if (Info.Opcode == ~0U)6024continue;60256026const MCInstrDesc &Desc = MII->get(Info.Opcode);60276028// Build the list of clobbers, outputs and inputs.6029for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {6030MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];60316032// Register operand.6033if (Operand.isReg() && !Operand.needAddressOf() &&6034!getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {6035unsigned NumDefs = Desc.getNumDefs();6036// Clobber.6037if (NumDefs && Operand.getMCOperandNum() < NumDefs)6038ClobberRegs.push_back(Operand.getReg());6039continue;6040}60416042// Expr/Input or Output.6043StringRef SymName = Operand.getSymName();6044if (SymName.empty())6045continue;60466047void *OpDecl = Operand.getOpDecl();6048if (!OpDecl)6049continue;60506051StringRef Constraint = Operand.getConstraint();6052if (Operand.isImm()) {6053// Offset as immediate6054if (Operand.isOffsetOfLocal())6055Constraint = "r";6056else6057Constraint = "i";6058}60596060bool isOutput = (i == 1) && Desc.mayStore();6061bool Restricted = Operand.isMemUseUpRegs();6062SMLoc Start = SMLoc::getFromPointer(SymName.data());6063if (isOutput) {6064++InputIdx;6065OutputDecls.push_back(OpDecl);6066OutputDeclsAddressOf.push_back(Operand.needAddressOf());6067OutputConstraints.push_back(("=" + Constraint).str());6068AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size(), 0,6069Restricted);6070} else {6071InputDecls.push_back(OpDecl);6072InputDeclsAddressOf.push_back(Operand.needAddressOf());6073InputConstraints.push_back(Constraint.str());6074if (Desc.operands()[i - 1].isBranchTarget())6075AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size(), 0,6076Restricted);6077else6078AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size(), 0,6079Restricted);6080}6081}60826083// Consider implicit defs to be clobbers. Think of cpuid and push.6084llvm::append_range(ClobberRegs, Desc.implicit_defs());6085}60866087// Set the number of Outputs and Inputs.6088NumOutputs = OutputDecls.size();6089NumInputs = InputDecls.size();60906091// Set the unique clobbers.6092array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());6093ClobberRegs.erase(llvm::unique(ClobberRegs), ClobberRegs.end());6094Clobbers.assign(ClobberRegs.size(), std::string());6095for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {6096raw_string_ostream OS(Clobbers[I]);6097IP->printRegName(OS, ClobberRegs[I]);6098}60996100// Merge the various outputs and inputs. Output are expected first.6101if (NumOutputs || NumInputs) {6102unsigned NumExprs = NumOutputs + NumInputs;6103OpDecls.resize(NumExprs);6104Constraints.resize(NumExprs);6105for (unsigned i = 0; i < NumOutputs; ++i) {6106OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);6107Constraints[i] = OutputConstraints[i];6108}6109for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {6110OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);6111Constraints[j] = InputConstraints[i];6112}6113}61146115// Build the IR assembly string.6116std::string AsmStringIR;6117raw_string_ostream OS(AsmStringIR);6118StringRef ASMString =6119SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer();6120const char *AsmStart = ASMString.begin();6121const char *AsmEnd = ASMString.end();6122array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);6123for (auto I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) {6124const AsmRewrite &AR = *I;6125// Check if this has already been covered by another rewrite...6126if (AR.Done)6127continue;6128AsmRewriteKind Kind = AR.Kind;61296130const char *Loc = AR.Loc.getPointer();6131assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");61326133// Emit everything up to the immediate/expression.6134if (unsigned Len = Loc - AsmStart)6135OS << StringRef(AsmStart, Len);61366137// Skip the original expression.6138if (Kind == AOK_Skip) {6139AsmStart = Loc + AR.Len;6140continue;6141}61426143unsigned AdditionalSkip = 0;6144// Rewrite expressions in $N notation.6145switch (Kind) {6146default:6147break;6148case AOK_IntelExpr:6149assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");6150if (AR.IntelExp.NeedBracs)6151OS << "[";6152if (AR.IntelExp.hasBaseReg())6153OS << AR.IntelExp.BaseReg;6154if (AR.IntelExp.hasIndexReg())6155OS << (AR.IntelExp.hasBaseReg() ? " + " : "")6156<< AR.IntelExp.IndexReg;6157if (AR.IntelExp.Scale > 1)6158OS << " * $$" << AR.IntelExp.Scale;6159if (AR.IntelExp.hasOffset()) {6160if (AR.IntelExp.hasRegs())6161OS << " + ";6162// Fuse this rewrite with a rewrite of the offset name, if present.6163StringRef OffsetName = AR.IntelExp.OffsetName;6164SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());6165size_t OffsetLen = OffsetName.size();6166auto rewrite_it = std::find_if(6167I, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {6168return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&6169(FusingAR.Kind == AOK_Input ||6170FusingAR.Kind == AOK_CallInput);6171});6172if (rewrite_it == AsmStrRewrites.end()) {6173OS << "offset " << OffsetName;6174} else if (rewrite_it->Kind == AOK_CallInput) {6175OS << "${" << InputIdx++ << ":P}";6176rewrite_it->Done = true;6177} else {6178OS << '$' << InputIdx++;6179rewrite_it->Done = true;6180}6181}6182if (AR.IntelExp.Imm || AR.IntelExp.emitImm())6183OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;6184if (AR.IntelExp.NeedBracs)6185OS << "]";6186break;6187case AOK_Label:6188OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;6189break;6190case AOK_Input:6191if (AR.IntelExpRestricted)6192OS << "${" << InputIdx++ << ":P}";6193else6194OS << '$' << InputIdx++;6195break;6196case AOK_CallInput:6197OS << "${" << InputIdx++ << ":P}";6198break;6199case AOK_Output:6200if (AR.IntelExpRestricted)6201OS << "${" << OutputIdx++ << ":P}";6202else6203OS << '$' << OutputIdx++;6204break;6205case AOK_SizeDirective:6206switch (AR.Val) {6207default: break;6208case 8: OS << "byte ptr "; break;6209case 16: OS << "word ptr "; break;6210case 32: OS << "dword ptr "; break;6211case 64: OS << "qword ptr "; break;6212case 80: OS << "xword ptr "; break;6213case 128: OS << "xmmword ptr "; break;6214case 256: OS << "ymmword ptr "; break;6215}6216break;6217case AOK_Emit:6218OS << ".byte";6219break;6220case AOK_Align: {6221// MS alignment directives are measured in bytes. If the native assembler6222// measures alignment in bytes, we can pass it straight through.6223OS << ".align";6224if (getContext().getAsmInfo()->getAlignmentIsInBytes())6225break;62266227// Alignment is in log2 form, so print that instead and skip the original6228// immediate.6229unsigned Val = AR.Val;6230OS << ' ' << Val;6231assert(Val < 10 && "Expected alignment less then 2^10.");6232AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;6233break;6234}6235case AOK_EVEN:6236OS << ".even";6237break;6238case AOK_EndOfStatement:6239OS << "\n\t";6240break;6241}62426243// Skip the original expression.6244AsmStart = Loc + AR.Len + AdditionalSkip;6245}62466247// Emit the remainder of the asm string.6248if (AsmStart != AsmEnd)6249OS << StringRef(AsmStart, AsmEnd - AsmStart);62506251AsmString = AsmStringIR;6252return false;6253}62546255bool HLASMAsmParser::parseAsHLASMLabel(ParseStatementInfo &Info,6256MCAsmParserSemaCallback *SI) {6257AsmToken LabelTok = getTok();6258SMLoc LabelLoc = LabelTok.getLoc();6259StringRef LabelVal;62606261if (parseIdentifier(LabelVal))6262return Error(LabelLoc, "The HLASM Label has to be an Identifier");62636264// We have validated whether the token is an Identifier.6265// Now we have to validate whether the token is a6266// valid HLASM Label.6267if (!getTargetParser().isLabel(LabelTok) || checkForValidSection())6268return true;62696270// Lex leading spaces to get to the next operand.6271lexLeadingSpaces();62726273// We shouldn't emit the label if there is nothing else after the label.6274// i.e asm("<token>\n")6275if (getTok().is(AsmToken::EndOfStatement))6276return Error(LabelLoc,6277"Cannot have just a label for an HLASM inline asm statement");62786279MCSymbol *Sym = getContext().getOrCreateSymbol(6280getContext().getAsmInfo()->shouldEmitLabelsInUpperCase()6281? LabelVal.upper()6282: LabelVal);62836284getTargetParser().doBeforeLabelEmit(Sym, LabelLoc);62856286// Emit the label.6287Out.emitLabel(Sym, LabelLoc);62886289// If we are generating dwarf for assembly source files then gather the6290// info to make a dwarf label entry for this label if needed.6291if (enabledGenDwarfForAssembly())6292MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),6293LabelLoc);62946295getTargetParser().onLabelParsed(Sym);62966297return false;6298}62996300bool HLASMAsmParser::parseAsMachineInstruction(ParseStatementInfo &Info,6301MCAsmParserSemaCallback *SI) {6302AsmToken OperationEntryTok = Lexer.getTok();6303SMLoc OperationEntryLoc = OperationEntryTok.getLoc();6304StringRef OperationEntryVal;63056306// Attempt to parse the first token as an Identifier6307if (parseIdentifier(OperationEntryVal))6308return Error(OperationEntryLoc, "unexpected token at start of statement");63096310// Once we've parsed the operation entry successfully, lex6311// any spaces to get to the OperandEntries.6312lexLeadingSpaces();63136314return parseAndMatchAndEmitTargetInstruction(6315Info, OperationEntryVal, OperationEntryTok, OperationEntryLoc);6316}63176318bool HLASMAsmParser::parseStatement(ParseStatementInfo &Info,6319MCAsmParserSemaCallback *SI) {6320assert(!hasPendingError() && "parseStatement started with pending error");63216322// Should the first token be interpreted as a HLASM Label.6323bool ShouldParseAsHLASMLabel = false;63246325// If a Name Entry exists, it should occur at the very6326// start of the string. In this case, we should parse the6327// first non-space token as a Label.6328// If the Name entry is missing (i.e. there's some other6329// token), then we attempt to parse the first non-space6330// token as a Machine Instruction.6331if (getTok().isNot(AsmToken::Space))6332ShouldParseAsHLASMLabel = true;63336334// If we have an EndOfStatement (which includes the target's comment6335// string) we can appropriately lex it early on)6336if (Lexer.is(AsmToken::EndOfStatement)) {6337// if this is a line comment we can drop it safely6338if (getTok().getString().empty() || getTok().getString().front() == '\r' ||6339getTok().getString().front() == '\n')6340Out.addBlankLine();6341Lex();6342return false;6343}63446345// We have established how to parse the inline asm statement.6346// Now we can safely lex any leading spaces to get to the6347// first token.6348lexLeadingSpaces();63496350// If we see a new line or carriage return as the first operand,6351// after lexing leading spaces, emit the new line and lex the6352// EndOfStatement token.6353if (Lexer.is(AsmToken::EndOfStatement)) {6354if (getTok().getString().front() == '\n' ||6355getTok().getString().front() == '\r') {6356Out.addBlankLine();6357Lex();6358return false;6359}6360}63616362// Handle the label first if we have to before processing the rest6363// of the tokens as a machine instruction.6364if (ShouldParseAsHLASMLabel) {6365// If there were any errors while handling and emitting the label,6366// early return.6367if (parseAsHLASMLabel(Info, SI)) {6368// If we know we've failed in parsing, simply eat until end of the6369// statement. This ensures that we don't process any other statements.6370eatToEndOfStatement();6371return true;6372}6373}63746375return parseAsMachineInstruction(Info, SI);6376}63776378namespace llvm {6379namespace MCParserUtils {63806381/// Returns whether the given symbol is used anywhere in the given expression,6382/// or subexpressions.6383static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) {6384switch (Value->getKind()) {6385case MCExpr::Binary: {6386const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value);6387return isSymbolUsedInExpression(Sym, BE->getLHS()) ||6388isSymbolUsedInExpression(Sym, BE->getRHS());6389}6390case MCExpr::Target:6391case MCExpr::Constant:6392return false;6393case MCExpr::SymbolRef: {6394const MCSymbol &S =6395static_cast<const MCSymbolRefExpr *>(Value)->getSymbol();6396if (S.isVariable() && !S.isWeakExternal())6397return isSymbolUsedInExpression(Sym, S.getVariableValue());6398return &S == Sym;6399}6400case MCExpr::Unary:6401return isSymbolUsedInExpression(6402Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr());6403}64046405llvm_unreachable("Unknown expr kind!");6406}64076408bool parseAssignmentExpression(StringRef Name, bool allow_redef,6409MCAsmParser &Parser, MCSymbol *&Sym,6410const MCExpr *&Value) {64116412// FIXME: Use better location, we should use proper tokens.6413SMLoc EqualLoc = Parser.getTok().getLoc();6414if (Parser.parseExpression(Value))6415return Parser.TokError("missing expression");64166417// Note: we don't count b as used in "a = b". This is to allow6418// a = b6419// b = c64206421if (Parser.parseEOL())6422return true;64236424// Validate that the LHS is allowed to be a variable (either it has not been6425// used as a symbol, or it is an absolute symbol).6426Sym = Parser.getContext().lookupSymbol(Name);6427if (Sym) {6428// Diagnose assignment to a label.6429//6430// FIXME: Diagnostics. Note the location of the definition as a label.6431// FIXME: Diagnose assignment to protected identifier (e.g., register name).6432if (isSymbolUsedInExpression(Sym, Value))6433return Parser.Error(EqualLoc, "Recursive use of '" + Name + "'");6434else if (Sym->isUndefined(/*SetUsed*/ false) && !Sym->isUsed() &&6435!Sym->isVariable())6436; // Allow redefinitions of undefined symbols only used in directives.6437else if (Sym->isVariable() && !Sym->isUsed() && allow_redef)6438; // Allow redefinitions of variables that haven't yet been used.6439else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef))6440return Parser.Error(EqualLoc, "redefinition of '" + Name + "'");6441else if (!Sym->isVariable())6442return Parser.Error(EqualLoc, "invalid assignment to '" + Name + "'");6443else if (!isa<MCConstantExpr>(Sym->getVariableValue()))6444return Parser.Error(EqualLoc,6445"invalid reassignment of non-absolute variable '" +6446Name + "'");6447} else if (Name == ".") {6448Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc);6449return false;6450} else6451Sym = Parser.getContext().getOrCreateSymbol(Name);64526453Sym->setRedefinable(allow_redef);64546455return false;6456}64576458} // end namespace MCParserUtils6459} // end namespace llvm64606461/// Create an MCAsmParser instance.6462MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,6463MCStreamer &Out, const MCAsmInfo &MAI,6464unsigned CB) {6465if (C.getTargetTriple().isSystemZ() && C.getTargetTriple().isOSzOS())6466return new HLASMAsmParser(SM, C, Out, MAI, CB);64676468return new AsmParser(SM, C, Out, MAI, CB);6469}647064716472