brintos

brintos / llvm-project-archived public Read only

0
0
Text · 207.3 KiB · f8274fc Raw
6434 lines · cpp
1//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This class implements a parser for assembly files similar to gas syntax.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/ADT/APFloat.h"14#include "llvm/ADT/APInt.h"15#include "llvm/ADT/ArrayRef.h"16#include "llvm/ADT/STLExtras.h"17#include "llvm/ADT/SmallSet.h"18#include "llvm/ADT/SmallString.h"19#include "llvm/ADT/SmallVector.h"20#include "llvm/ADT/StringExtras.h"21#include "llvm/ADT/StringMap.h"22#include "llvm/ADT/StringRef.h"23#include "llvm/ADT/Twine.h"24#include "llvm/BinaryFormat/Dwarf.h"25#include "llvm/DebugInfo/CodeView/SymbolRecord.h"26#include "llvm/MC/MCAsmInfo.h"27#include "llvm/MC/MCCodeView.h"28#include "llvm/MC/MCContext.h"29#include "llvm/MC/MCDirectives.h"30#include "llvm/MC/MCDwarf.h"31#include "llvm/MC/MCExpr.h"32#include "llvm/MC/MCInstPrinter.h"33#include "llvm/MC/MCInstrDesc.h"34#include "llvm/MC/MCInstrInfo.h"35#include "llvm/MC/MCParser/AsmCond.h"36#include "llvm/MC/MCParser/AsmLexer.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/MCSymbolWasm.h"48#include "llvm/MC/MCTargetOptions.h"49#include "llvm/MC/MCValue.h"50#include "llvm/Support/Base64.h"51#include "llvm/Support/Casting.h"52#include "llvm/Support/CommandLine.h"53#include "llvm/Support/ErrorHandling.h"54#include "llvm/Support/MD5.h"55#include "llvm/Support/MathExtras.h"56#include "llvm/Support/MemoryBuffer.h"57#include "llvm/Support/SMLoc.h"58#include "llvm/Support/SourceMgr.h"59#include "llvm/Support/raw_ostream.h"60#include <algorithm>61#include <cassert>62#include <cctype>63#include <climits>64#include <cstddef>65#include <cstdint>66#include <deque>67#include <memory>68#include <optional>69#include <sstream>70#include <string>71#include <tuple>72#include <utility>73#include <vector>74 75using namespace llvm;76 77MCAsmParserSemaCallback::~MCAsmParserSemaCallback() = default;78 79namespace {80 81/// Helper types for tracking macro definitions.82typedef std::vector<AsmToken> MCAsmMacroArgument;83typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;84 85/// Helper class for storing information about an active macro86/// instantiation.87struct MacroInstantiation {88  /// The location of the instantiation.89  SMLoc InstantiationLoc;90 91  /// The buffer where parsing should resume upon instantiation completion.92  unsigned ExitBuffer;93 94  /// The location where parsing should resume upon instantiation completion.95  SMLoc ExitLoc;96 97  /// The depth of TheCondStack at the start of the instantiation.98  size_t CondStackDepth;99};100 101struct ParseStatementInfo {102  /// The parsed operands from the last parsed statement.103  SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;104 105  /// The opcode from the last parsed instruction.106  unsigned Opcode = ~0U;107 108  /// Was there an error parsing the inline assembly?109  bool ParseError = false;110 111  SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;112 113  ParseStatementInfo() = delete;114  ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)115    : AsmRewrites(rewrites) {}116};117 118/// The concrete assembly parser instance.119class AsmParser : public MCAsmParser {120private:121  SourceMgr::DiagHandlerTy SavedDiagHandler;122  void *SavedDiagContext;123  std::unique_ptr<MCAsmParserExtension> PlatformParser;124  SMLoc StartTokLoc;125  std::optional<SMLoc> CFIStartProcLoc;126 127  /// This is the current buffer index we're lexing from as managed by the128  /// SourceMgr object.129  unsigned CurBuffer;130 131  AsmCond TheCondState;132  std::vector<AsmCond> TheCondStack;133 134  /// maps directive names to handler methods in parser135  /// extensions. Extensions register themselves in this map by calling136  /// addDirectiveHandler.137  StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;138 139  /// Stack of active macro instantiations.140  std::vector<MacroInstantiation*> ActiveMacros;141 142  /// List of bodies of anonymous macros.143  std::deque<MCAsmMacro> MacroLikeBodies;144 145  /// Boolean tracking whether macro substitution is enabled.146  unsigned MacrosEnabledFlag : 1;147 148  /// Keeps track of how many .macro's have been instantiated.149  unsigned NumOfMacroInstantiations = 0;150 151  /// The values from the last parsed cpp hash file line comment if any.152  struct CppHashInfoTy {153    StringRef Filename;154    int64_t LineNumber;155    SMLoc Loc;156    unsigned Buf;157    CppHashInfoTy() : LineNumber(0), Buf(0) {}158  };159  CppHashInfoTy CppHashInfo;160 161  /// Have we seen any file line comment.162  bool HadCppHashFilename = false;163 164  /// List of forward directional labels for diagnosis at the end.165  SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;166 167  SmallSet<StringRef, 2> LTODiscardSymbols;168 169  /// AssemblerDialect. ~OU means unset value and use value provided by MAI.170  unsigned AssemblerDialect = ~0U;171 172  /// is Darwin compatibility enabled?173  bool IsDarwin = false;174 175  /// Are we parsing ms-style inline assembly?176  bool ParsingMSInlineAsm = false;177 178  /// Did we already inform the user about inconsistent MD5 usage?179  bool ReportedInconsistentMD5 = false;180 181  // Is alt macro mode enabled.182  bool AltMacroMode = false;183 184protected:185  virtual bool parseStatement(ParseStatementInfo &Info,186                              MCAsmParserSemaCallback *SI);187 188  /// This routine uses the target specific ParseInstruction function to189  /// parse an instruction into Operands, and then call the target specific190  /// MatchAndEmit function to match and emit the instruction.191  bool parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info,192                                             StringRef IDVal, AsmToken ID,193                                             SMLoc IDLoc);194 195  /// Should we emit DWARF describing this assembler source?  (Returns false if196  /// the source has .file directives, which means we don't want to generate197  /// info describing the assembler source itself.)198  bool enabledGenDwarfForAssembly();199 200public:201  AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,202            const MCAsmInfo &MAI, unsigned CB);203  AsmParser(const AsmParser &) = delete;204  AsmParser &operator=(const AsmParser &) = delete;205  ~AsmParser() override;206 207  bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;208 209  void addDirectiveHandler(StringRef Directive,210                           ExtensionDirectiveHandler Handler) override {211    ExtensionDirectiveMap[Directive] = Handler;212  }213 214  void addAliasForDirective(StringRef Directive, StringRef Alias) override {215    DirectiveKindMap[Directive.lower()] = DirectiveKindMap[Alias.lower()];216  }217 218  /// @name MCAsmParser Interface219  /// {220 221  CodeViewContext &getCVContext() { return Ctx.getCVContext(); }222 223  unsigned getAssemblerDialect() override {224    if (AssemblerDialect == ~0U)225      return MAI.getAssemblerDialect();226    else227      return AssemblerDialect;228  }229  void setAssemblerDialect(unsigned i) override {230    AssemblerDialect = i;231  }232 233  void Note(SMLoc L, const Twine &Msg, SMRange Range = {}) override;234  bool Warning(SMLoc L, const Twine &Msg, SMRange Range = {}) override;235  bool printError(SMLoc L, const Twine &Msg, SMRange Range = {}) override;236 237  const AsmToken &Lex() override;238 239  void setParsingMSInlineAsm(bool V) override {240    ParsingMSInlineAsm = V;241    // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and242    // hex integer literals.243    Lexer.setLexMasmIntegers(V);244  }245  bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }246 247  bool discardLTOSymbol(StringRef Name) const override {248    return LTODiscardSymbols.contains(Name);249  }250 251  bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs,252                        unsigned &NumInputs,253                        SmallVectorImpl<std::pair<void *, bool>> &OpDecls,254                        SmallVectorImpl<std::string> &Constraints,255                        SmallVectorImpl<std::string> &Clobbers,256                        const MCInstrInfo *MII, MCInstPrinter *IP,257                        MCAsmParserSemaCallback &SI) override;258 259  bool parseExpression(const MCExpr *&Res);260  bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;261  bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,262                        AsmTypeInfo *TypeInfo) override;263  bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;264  bool parseAbsoluteExpression(int64_t &Res) override;265 266  /// Parse a floating point expression using the float \p Semantics267  /// and set \p Res to the value.268  bool parseRealValue(const fltSemantics &Semantics, APInt &Res);269 270  /// Parse an identifier or string (as a quoted identifier)271  /// and set \p Res to the identifier contents.272  bool parseIdentifier(StringRef &Res) override;273  void eatToEndOfStatement() override;274 275  bool checkForValidSection() override;276 277  /// }278 279private:280  bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);281  bool parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo = true);282 283  void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body,284                        ArrayRef<MCAsmMacroParameter> Parameters);285  bool expandMacro(raw_svector_ostream &OS, MCAsmMacro &Macro,286                   ArrayRef<MCAsmMacroParameter> Parameters,287                   ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable);288 289  /// Are macros enabled in the parser?290  bool areMacrosEnabled() {return MacrosEnabledFlag;}291 292  /// Control a flag in the parser that enables or disables macros.293  void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;}294 295  /// Are we inside a macro instantiation?296  bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}297 298  /// Handle entry to macro instantiation.299  ///300  /// \param M The macro.301  /// \param NameLoc Instantiation location.302  bool handleMacroEntry(MCAsmMacro *M, SMLoc NameLoc);303 304  /// Handle exit from macro instantiation.305  void handleMacroExit();306 307  /// Extract AsmTokens for a macro argument.308  bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg);309 310  /// Parse all macro arguments for a given macro.311  bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A);312 313  void printMacroInstantiations();314  void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,315                    SMRange Range = {}) const {316    ArrayRef<SMRange> Ranges(Range);317    SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);318  }319  static void DiagHandler(const SMDiagnostic &Diag, void *Context);320 321  /// Enter the specified file. This returns true on failure.322  bool enterIncludeFile(const std::string &Filename);323 324  /// Process the specified file for the .incbin directive.325  /// This returns true on failure.326  bool processIncbinFile(const std::string &Filename, int64_t Skip = 0,327                         const MCExpr *Count = nullptr, SMLoc Loc = SMLoc());328 329  /// Reset the current lexer position to that given by \p Loc. The330  /// current token is not set; clients should ensure Lex() is called331  /// subsequently.332  ///333  /// \param InBuffer If not 0, should be the known buffer id that contains the334  /// location.335  void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0);336 337  /// Parse up to the end of statement and a return the contents from the338  /// current token until the end of the statement; the current token on exit339  /// will be either the EndOfStatement or EOF.340  StringRef parseStringToEndOfStatement() override;341 342  /// Parse until the end of a statement or a comma is encountered,343  /// return the contents from the current token up to the end or comma.344  StringRef parseStringToComma();345 346  enum class AssignmentKind {347    Set,348    Equiv,349    Equal,350    LTOSetConditional,351  };352 353  bool parseAssignment(StringRef Name, AssignmentKind Kind);354 355  unsigned getBinOpPrecedence(AsmToken::TokenKind K,356                              MCBinaryExpr::Opcode &Kind);357 358  bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);359  bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);360  bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);361 362  bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc);363 364  bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName);365  bool parseCVFileId(int64_t &FileId, StringRef DirectiveName);366 367  // Generic (target and platform independent) directive parsing.368  enum DirectiveKind {369    DK_NO_DIRECTIVE, // Placeholder370    DK_SET,371    DK_EQU,372    DK_EQUIV,373    DK_ASCII,374    DK_ASCIZ,375    DK_STRING,376    DK_BYTE,377    DK_SHORT,378    DK_RELOC,379    DK_VALUE,380    DK_2BYTE,381    DK_LONG,382    DK_INT,383    DK_4BYTE,384    DK_QUAD,385    DK_8BYTE,386    DK_OCTA,387    DK_DC,388    DK_DC_A,389    DK_DC_B,390    DK_DC_D,391    DK_DC_L,392    DK_DC_S,393    DK_DC_W,394    DK_DC_X,395    DK_DCB,396    DK_DCB_B,397    DK_DCB_D,398    DK_DCB_L,399    DK_DCB_S,400    DK_DCB_W,401    DK_DCB_X,402    DK_DS,403    DK_DS_B,404    DK_DS_D,405    DK_DS_L,406    DK_DS_P,407    DK_DS_S,408    DK_DS_W,409    DK_DS_X,410    DK_SINGLE,411    DK_FLOAT,412    DK_DOUBLE,413    DK_ALIGN,414    DK_ALIGN32,415    DK_BALIGN,416    DK_BALIGNW,417    DK_BALIGNL,418    DK_P2ALIGN,419    DK_P2ALIGNW,420    DK_P2ALIGNL,421    DK_ORG,422    DK_FILL,423    DK_ENDR,424    DK_ZERO,425    DK_EXTERN,426    DK_GLOBL,427    DK_GLOBAL,428    DK_LAZY_REFERENCE,429    DK_NO_DEAD_STRIP,430    DK_SYMBOL_RESOLVER,431    DK_PRIVATE_EXTERN,432    DK_REFERENCE,433    DK_WEAK_DEFINITION,434    DK_WEAK_REFERENCE,435    DK_WEAK_DEF_CAN_BE_HIDDEN,436    DK_COLD,437    DK_COMM,438    DK_COMMON,439    DK_LCOMM,440    DK_ABORT,441    DK_INCLUDE,442    DK_INCBIN,443    DK_CODE16,444    DK_CODE16GCC,445    DK_REPT,446    DK_IRP,447    DK_IRPC,448    DK_IF,449    DK_IFEQ,450    DK_IFGE,451    DK_IFGT,452    DK_IFLE,453    DK_IFLT,454    DK_IFNE,455    DK_IFB,456    DK_IFNB,457    DK_IFC,458    DK_IFEQS,459    DK_IFNC,460    DK_IFNES,461    DK_IFDEF,462    DK_IFNDEF,463    DK_IFNOTDEF,464    DK_ELSEIF,465    DK_ELSE,466    DK_ENDIF,467    DK_SPACE,468    DK_SKIP,469    DK_FILE,470    DK_LINE,471    DK_LOC,472    DK_LOC_LABEL,473    DK_STABS,474    DK_CV_FILE,475    DK_CV_FUNC_ID,476    DK_CV_INLINE_SITE_ID,477    DK_CV_LOC,478    DK_CV_LINETABLE,479    DK_CV_INLINE_LINETABLE,480    DK_CV_DEF_RANGE,481    DK_CV_STRINGTABLE,482    DK_CV_STRING,483    DK_CV_FILECHECKSUMS,484    DK_CV_FILECHECKSUM_OFFSET,485    DK_CV_FPO_DATA,486    DK_CFI_SECTIONS,487    DK_CFI_STARTPROC,488    DK_CFI_ENDPROC,489    DK_CFI_DEF_CFA,490    DK_CFI_DEF_CFA_OFFSET,491    DK_CFI_ADJUST_CFA_OFFSET,492    DK_CFI_DEF_CFA_REGISTER,493    DK_CFI_LLVM_DEF_ASPACE_CFA,494    DK_CFI_OFFSET,495    DK_CFI_REL_OFFSET,496    DK_CFI_PERSONALITY,497    DK_CFI_LSDA,498    DK_CFI_REMEMBER_STATE,499    DK_CFI_RESTORE_STATE,500    DK_CFI_SAME_VALUE,501    DK_CFI_RESTORE,502    DK_CFI_ESCAPE,503    DK_CFI_RETURN_COLUMN,504    DK_CFI_SIGNAL_FRAME,505    DK_CFI_UNDEFINED,506    DK_CFI_REGISTER,507    DK_CFI_WINDOW_SAVE,508    DK_CFI_LABEL,509    DK_CFI_B_KEY_FRAME,510    DK_CFI_VAL_OFFSET,511    DK_MACROS_ON,512    DK_MACROS_OFF,513    DK_ALTMACRO,514    DK_NOALTMACRO,515    DK_MACRO,516    DK_EXITM,517    DK_ENDM,518    DK_ENDMACRO,519    DK_PURGEM,520    DK_SLEB128,521    DK_ULEB128,522    DK_ERR,523    DK_ERROR,524    DK_WARNING,525    DK_PRINT,526    DK_ADDRSIG,527    DK_ADDRSIG_SYM,528    DK_PSEUDO_PROBE,529    DK_LTO_DISCARD,530    DK_LTO_SET_CONDITIONAL,531    DK_CFI_MTE_TAGGED_FRAME,532    DK_MEMTAG,533    DK_BASE64,534    DK_END535  };536 537  /// Maps directive name --> DirectiveKind enum, for538  /// directives parsed by this class.539  StringMap<DirectiveKind> DirectiveKindMap;540 541  // Codeview def_range type parsing.542  enum CVDefRangeType {543    CVDR_DEFRANGE = 0, // Placeholder544    CVDR_DEFRANGE_REGISTER,545    CVDR_DEFRANGE_FRAMEPOINTER_REL,546    CVDR_DEFRANGE_SUBFIELD_REGISTER,547    CVDR_DEFRANGE_REGISTER_REL548  };549 550  /// Maps Codeview def_range types --> CVDefRangeType enum, for551  /// Codeview def_range types parsed by this class.552  StringMap<CVDefRangeType> CVDefRangeTypeMap;553 554  // ".ascii", ".asciz", ".string"555  bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);556  bool parseDirectiveBase64();                  // ".base64"557  bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc"558  bool parseDirectiveValue(StringRef IDVal,559                           unsigned Size);       // ".byte", ".long", ...560  bool parseDirectiveOctaValue(StringRef IDVal); // ".octa", ...561  bool parseDirectiveRealValue(StringRef IDVal,562                               const fltSemantics &); // ".single", ...563  bool parseDirectiveFill(); // ".fill"564  bool parseDirectiveZero(); // ".zero"565  // ".set", ".equ", ".equiv", ".lto_set_conditional"566  bool parseDirectiveSet(StringRef IDVal, AssignmentKind Kind);567  bool parseDirectiveOrg(); // ".org"568  // ".align{,32}", ".p2align{,w,l}"569  bool parseDirectiveAlign(bool IsPow2, uint8_t ValueSize);570 571  // ".file", ".line", ".loc", ".loc_label", ".stabs"572  bool parseDirectiveFile(SMLoc DirectiveLoc);573  bool parseDirectiveLine();574  bool parseDirectiveLoc();575  bool parseDirectiveLocLabel(SMLoc DirectiveLoc);576  bool parseDirectiveStabs();577 578  // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",579  // ".cv_inline_linetable", ".cv_def_range", ".cv_string"580  bool parseDirectiveCVFile();581  bool parseDirectiveCVFuncId();582  bool parseDirectiveCVInlineSiteId();583  bool parseDirectiveCVLoc();584  bool parseDirectiveCVLinetable();585  bool parseDirectiveCVInlineLinetable();586  bool parseDirectiveCVDefRange();587  bool parseDirectiveCVString();588  bool parseDirectiveCVStringTable();589  bool parseDirectiveCVFileChecksums();590  bool parseDirectiveCVFileChecksumOffset();591  bool parseDirectiveCVFPOData();592 593  // .cfi directives594  bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);595  bool parseDirectiveCFIWindowSave(SMLoc DirectiveLoc);596  bool parseDirectiveCFISections();597  bool parseDirectiveCFIStartProc();598  bool parseDirectiveCFIEndProc();599  bool parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc);600  bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);601  bool parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc);602  bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);603  bool parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc);604  bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);605  bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);606  bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);607  bool parseDirectiveCFIRememberState(SMLoc DirectiveLoc);608  bool parseDirectiveCFIRestoreState(SMLoc DirectiveLoc);609  bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);610  bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);611  bool parseDirectiveCFIEscape(SMLoc DirectiveLoc);612  bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);613  bool parseDirectiveCFISignalFrame(SMLoc DirectiveLoc);614  bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);615  bool parseDirectiveCFILabel(SMLoc DirectiveLoc);616  bool parseDirectiveCFIValOffset(SMLoc DirectiveLoc);617 618  // macro directives619  bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);620  bool parseDirectiveExitMacro(StringRef Directive);621  bool parseDirectiveEndMacro(StringRef Directive);622  bool parseDirectiveMacro(SMLoc DirectiveLoc);623  bool parseDirectiveMacrosOnOff(StringRef Directive);624  // alternate macro mode directives625  bool parseDirectiveAltmacro(StringRef Directive);626 627  // ".space", ".skip"628  bool parseDirectiveSpace(StringRef IDVal);629 630  // ".dcb"631  bool parseDirectiveDCB(StringRef IDVal, unsigned Size);632  bool parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &);633  // ".ds"634  bool parseDirectiveDS(StringRef IDVal, unsigned Size);635 636  // .sleb128 (Signed=true) and .uleb128 (Signed=false)637  bool parseDirectiveLEB128(bool Signed);638 639  /// Parse a directive like ".globl" which640  /// accepts a single symbol (which should be a label or an external).641  bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);642 643  bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"644 645  bool parseDirectiveAbort(SMLoc DirectiveLoc); // ".abort"646  bool parseDirectiveInclude(); // ".include"647  bool parseDirectiveIncbin(); // ".incbin"648 649  // ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne"650  bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);651  // ".ifb" or ".ifnb", depending on ExpectBlank.652  bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);653  // ".ifc" or ".ifnc", depending on ExpectEqual.654  bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);655  // ".ifeqs" or ".ifnes", depending on ExpectEqual.656  bool parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual);657  // ".ifdef" or ".ifndef", depending on expect_defined658  bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);659  bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"660  bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"661  bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif662  bool parseEscapedString(std::string &Data) override;663  bool parseAngleBracketString(std::string &Data) override;664 665  // Macro-like directives666  MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);667  void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,668                                raw_svector_ostream &OS);669  bool parseDirectiveRept(SMLoc DirectiveLoc, StringRef Directive);670  bool parseDirectiveIrp(SMLoc DirectiveLoc);  // ".irp"671  bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"672  bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"673 674  // "_emit" or "__emit"675  bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,676                            size_t Len);677 678  // "align"679  bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);680 681  // "end"682  bool parseDirectiveEnd(SMLoc DirectiveLoc);683 684  // ".err" or ".error"685  bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage);686 687  // ".warning"688  bool parseDirectiveWarning(SMLoc DirectiveLoc);689 690  // .print <double-quotes-string>691  bool parseDirectivePrint(SMLoc DirectiveLoc);692 693  // .pseudoprobe694  bool parseDirectivePseudoProbe();695 696  // ".lto_discard"697  bool parseDirectiveLTODiscard();698 699  // Directives to support address-significance tables.700  bool parseDirectiveAddrsig();701  bool parseDirectiveAddrsigSym();702 703  void initializeDirectiveKindMap();704  void initializeCVDefRangeTypeMap();705};706 707class HLASMAsmParser final : public AsmParser {708private:709  AsmLexer &Lexer;710  MCStreamer &Out;711 712  void lexLeadingSpaces() {713    while (Lexer.is(AsmToken::Space))714      Lexer.Lex();715  }716 717  bool parseAsHLASMLabel(ParseStatementInfo &Info, MCAsmParserSemaCallback *SI);718  bool parseAsMachineInstruction(ParseStatementInfo &Info,719                                 MCAsmParserSemaCallback *SI);720 721public:722  HLASMAsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,723                 const MCAsmInfo &MAI, unsigned CB = 0)724      : AsmParser(SM, Ctx, Out, MAI, CB), Lexer(getLexer()), Out(Out) {725    Lexer.setSkipSpace(false);726    Lexer.setAllowHashInIdentifier(true);727    Lexer.setLexHLASMIntegers(true);728    Lexer.setLexHLASMStrings(true);729  }730 731  ~HLASMAsmParser() override { Lexer.setSkipSpace(true); }732 733  bool parseStatement(ParseStatementInfo &Info,734                      MCAsmParserSemaCallback *SI) override;735};736 737} // end anonymous namespace738 739namespace llvm {740 741extern cl::opt<unsigned> AsmMacroMaxNestingDepth;742 743} // end namespace llvm744 745AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,746                     const MCAsmInfo &MAI, unsigned CB = 0)747    : MCAsmParser(Ctx, Out, SM, MAI), CurBuffer(CB ? CB : SM.getMainFileID()),748      MacrosEnabledFlag(true) {749  HadError = false;750  // Save the old handler.751  SavedDiagHandler = SrcMgr.getDiagHandler();752  SavedDiagContext = SrcMgr.getDiagContext();753  // Set our own handler which calls the saved handler.754  SrcMgr.setDiagHandler(DiagHandler, this);755  Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());756  // Make MCStreamer aware of the StartTokLoc for locations in diagnostics.757  Out.setStartTokLocPtr(&StartTokLoc);758 759  // Initialize the platform / file format parser.760  switch (Ctx.getObjectFileType()) {761  case MCContext::IsCOFF:762    PlatformParser.reset(createCOFFAsmParser());763    break;764  case MCContext::IsMachO:765    PlatformParser.reset(createDarwinAsmParser());766    IsDarwin = true;767    break;768  case MCContext::IsELF:769    PlatformParser.reset(createELFAsmParser());770    break;771  case MCContext::IsGOFF:772    PlatformParser.reset(createGOFFAsmParser());773    break;774  case MCContext::IsSPIRV:775    report_fatal_error(776        "Need to implement createSPIRVAsmParser for SPIRV format.");777    break;778  case MCContext::IsWasm:779    PlatformParser.reset(createWasmAsmParser());780    break;781  case MCContext::IsXCOFF:782    PlatformParser.reset(createXCOFFAsmParser());783    break;784  case MCContext::IsDXContainer:785    report_fatal_error("DXContainer is not supported yet");786    break;787  }788 789  PlatformParser->Initialize(*this);790  initializeDirectiveKindMap();791  initializeCVDefRangeTypeMap();792}793 794AsmParser::~AsmParser() {795  assert((HadError || ActiveMacros.empty()) &&796         "Unexpected active macro instantiation!");797 798  // Remove MCStreamer's reference to the parser SMLoc.799  Out.setStartTokLocPtr(nullptr);800  // Restore the saved diagnostics handler and context for use during801  // finalization.802  SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);803}804 805void AsmParser::printMacroInstantiations() {806  // Print the active macro instantiation stack.807  for (MacroInstantiation *M : reverse(ActiveMacros))808    printMessage(M->InstantiationLoc, SourceMgr::DK_Note,809                 "while in macro instantiation");810}811 812void AsmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {813  printPendingErrors();814  printMessage(L, SourceMgr::DK_Note, Msg, Range);815  printMacroInstantiations();816}817 818bool AsmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {819  if(getTargetParser().getTargetOptions().MCNoWarn)820    return false;821  if (getTargetParser().getTargetOptions().MCFatalWarnings)822    return Error(L, Msg, Range);823  printMessage(L, SourceMgr::DK_Warning, Msg, Range);824  printMacroInstantiations();825  return false;826}827 828bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {829  HadError = true;830  printMessage(L, SourceMgr::DK_Error, Msg, Range);831  printMacroInstantiations();832  return true;833}834 835bool AsmParser::enterIncludeFile(const std::string &Filename) {836  std::string IncludedFile;837  unsigned NewBuf =838      SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);839  if (!NewBuf)840    return true;841 842  CurBuffer = NewBuf;843  Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());844  return false;845}846 847/// Process the specified .incbin file by searching for it in the include paths848/// then just emitting the byte contents of the file to the streamer. This849/// returns true on failure.850bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip,851                                  const MCExpr *Count, SMLoc Loc) {852  std::string IncludedFile;853  unsigned NewBuf =854      SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);855  if (!NewBuf)856    return true;857 858  // Pick up the bytes from the file and emit them.859  StringRef Bytes = SrcMgr.getMemoryBuffer(NewBuf)->getBuffer();860  Bytes = Bytes.drop_front(Skip);861  if (Count) {862    int64_t Res;863    if (!Count->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))864      return Error(Loc, "expected absolute expression");865    if (Res < 0)866      return Warning(Loc, "negative count has no effect");867    Bytes = Bytes.take_front(Res);868  }869  getStreamer().emitBytes(Bytes);870  return false;871}872 873void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) {874  CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);875  Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),876                  Loc.getPointer());877}878 879const AsmToken &AsmParser::Lex() {880  if (Lexer.getTok().is(AsmToken::Error))881    Error(Lexer.getErrLoc(), Lexer.getErr());882 883  // if it's a end of statement with a comment in it884  if (getTok().is(AsmToken::EndOfStatement)) {885    // if this is a line comment output it.886    if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&887        getTok().getString().front() != '\r' && MAI.preserveAsmComments())888      Out.addExplicitComment(Twine(getTok().getString()));889  }890 891  const AsmToken *tok = &Lexer.Lex();892 893  // Parse comments here to be deferred until end of next statement.894  while (tok->is(AsmToken::Comment)) {895    if (MAI.preserveAsmComments())896      Out.addExplicitComment(Twine(tok->getString()));897    tok = &Lexer.Lex();898  }899 900  if (tok->is(AsmToken::Eof)) {901    // If this is the end of an included file, pop the parent file off the902    // include stack.903    SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);904    if (ParentIncludeLoc != SMLoc()) {905      jumpToLoc(ParentIncludeLoc);906      return Lex();907    }908  }909 910  return *tok;911}912 913bool AsmParser::enabledGenDwarfForAssembly() {914  // Check whether the user specified -g.915  if (!getContext().getGenDwarfForAssembly())916    return false;917  // If we haven't encountered any .file directives (which would imply that918  // the assembler source was produced with debug info already) then emit one919  // describing the assembler source file itself.920  if (getContext().getGenDwarfFileNumber() == 0) {921    const MCDwarfFile &RootFile =922        getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile();923    getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective(924        /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name,925        RootFile.Checksum, RootFile.Source));926  }927  return true;928}929 930bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {931  LTODiscardSymbols.clear();932 933  // Create the initial section, if requested.934  if (!NoInitialTextSection)935    Out.initSections(false, getTargetParser().getSTI());936 937  // Prime the lexer.938  Lex();939 940  HadError = false;941  AsmCond StartingCondState = TheCondState;942  SmallVector<AsmRewrite, 4> AsmStrRewrites;943 944  // If we are generating dwarf for assembly source files save the initial text945  // section.  (Don't use enabledGenDwarfForAssembly() here, as we aren't946  // emitting any actual debug info yet and haven't had a chance to parse any947  // embedded .file directives.)948  if (getContext().getGenDwarfForAssembly()) {949    MCSection *Sec = getStreamer().getCurrentSectionOnly();950    if (!Sec->getBeginSymbol()) {951      MCSymbol *SectionStartSym = getContext().createTempSymbol();952      getStreamer().emitLabel(SectionStartSym);953      Sec->setBeginSymbol(SectionStartSym);954    }955    bool InsertResult = getContext().addGenDwarfSection(Sec);956    assert(InsertResult && ".text section should not have debug info yet");957    (void)InsertResult;958  }959 960  getTargetParser().onBeginOfFile();961 962  // While we have input, parse each statement.963  while (Lexer.isNot(AsmToken::Eof)) {964    ParseStatementInfo Info(&AsmStrRewrites);965    bool HasError = parseStatement(Info, nullptr);966 967    // If we have a Lexer Error we are on an Error Token. Load in Lexer Error968    // for printing ErrMsg via Lex() only if no (presumably better) parser error969    // exists.970    if (HasError && !hasPendingError() && Lexer.getTok().is(AsmToken::Error))971      Lex();972 973    // parseStatement returned true so may need to emit an error.974    printPendingErrors();975 976    // Skipping to the next line if needed.977    if (HasError && !getLexer().justConsumedEOL())978      eatToEndOfStatement();979  }980 981  getTargetParser().onEndOfFile();982  printPendingErrors();983 984  // All errors should have been emitted.985  assert(!hasPendingError() && "unexpected error from parseStatement");986 987  if (TheCondState.TheCond != StartingCondState.TheCond ||988      TheCondState.Ignore != StartingCondState.Ignore)989    printError(getTok().getLoc(), "unmatched .ifs or .elses");990  // Check to see there are no empty DwarfFile slots.991  const auto &LineTables = getContext().getMCDwarfLineTables();992  if (!LineTables.empty()) {993    unsigned Index = 0;994    for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) {995      if (File.Name.empty() && Index != 0)996        printError(getTok().getLoc(), "unassigned file number: " +997                                          Twine(Index) +998                                          " for .file directives");999      ++Index;1000    }1001  }1002 1003  // Check to see that all assembler local symbols were actually defined.1004  // Targets that don't do subsections via symbols may not want this, though,1005  // so conservatively exclude them. Only do this if we're finalizing, though,1006  // as otherwise we won't necessarily have seen everything yet.1007  if (!NoFinalize) {1008    if (MAI.hasSubsectionsViaSymbols()) {1009      for (const auto &TableEntry : getContext().getSymbols()) {1010        MCSymbol *Sym = TableEntry.getValue().Symbol;1011        // Variable symbols may not be marked as defined, so check those1012        // explicitly. If we know it's a variable, we have a definition for1013        // the purposes of this check.1014        if (Sym && Sym->isTemporary() && !Sym->isVariable() &&1015            !Sym->isDefined())1016          // FIXME: We would really like to refer back to where the symbol was1017          // first referenced for a source location. We need to add something1018          // to track that. Currently, we just point to the end of the file.1019          printError(getTok().getLoc(), "assembler local symbol '" +1020                                            Sym->getName() + "' not defined");1021      }1022    }1023 1024    // Temporary symbols like the ones for directional jumps don't go in the1025    // symbol table. They also need to be diagnosed in all (final) cases.1026    for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {1027      if (std::get<2>(LocSym)->isUndefined()) {1028        // Reset the state of any "# line file" directives we've seen to the1029        // context as it was at the diagnostic site.1030        CppHashInfo = std::get<1>(LocSym);1031        printError(std::get<0>(LocSym), "directional label undefined");1032      }1033    }1034  }1035  // Finalize the output stream if there are no errors and if the client wants1036  // us to.1037  if (!HadError && !NoFinalize) {1038    if (auto *TS = Out.getTargetStreamer())1039      TS->emitConstantPools();1040 1041    Out.finish(Lexer.getLoc());1042  }1043 1044  return HadError || getContext().hadError();1045}1046 1047bool AsmParser::checkForValidSection() {1048  if (!ParsingMSInlineAsm && !getStreamer().getCurrentFragment()) {1049    Out.initSections(false, getTargetParser().getSTI());1050    return Error(getTok().getLoc(),1051                 "expected section directive before assembly directive");1052  }1053  return false;1054}1055 1056/// Throw away the rest of the line for testing purposes.1057void AsmParser::eatToEndOfStatement() {1058  while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))1059    Lexer.Lex();1060 1061  // Eat EOL.1062  if (Lexer.is(AsmToken::EndOfStatement))1063    Lexer.Lex();1064}1065 1066StringRef AsmParser::parseStringToEndOfStatement() {1067  const char *Start = getTok().getLoc().getPointer();1068 1069  while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))1070    Lexer.Lex();1071 1072  const char *End = getTok().getLoc().getPointer();1073  return StringRef(Start, End - Start);1074}1075 1076StringRef AsmParser::parseStringToComma() {1077  const char *Start = getTok().getLoc().getPointer();1078 1079  while (Lexer.isNot(AsmToken::EndOfStatement) &&1080         Lexer.isNot(AsmToken::Comma) && Lexer.isNot(AsmToken::Eof))1081    Lexer.Lex();1082 1083  const char *End = getTok().getLoc().getPointer();1084  return StringRef(Start, End - Start);1085}1086 1087/// Parse a paren expression and return it.1088/// NOTE: This assumes the leading '(' has already been consumed.1089///1090/// parenexpr ::= expr)1091///1092bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {1093  if (parseExpression(Res))1094    return true;1095  EndLoc = Lexer.getTok().getEndLoc();1096  return parseRParen();1097}1098 1099/// Parse a bracket expression and return it.1100/// NOTE: This assumes the leading '[' has already been consumed.1101///1102/// bracketexpr ::= expr]1103///1104bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {1105  if (parseExpression(Res))1106    return true;1107  EndLoc = getTok().getEndLoc();1108  if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))1109    return true;1110  return false;1111}1112 1113/// Parse a primary expression and return it.1114///  primaryexpr ::= (parenexpr1115///  primaryexpr ::= symbol1116///  primaryexpr ::= number1117///  primaryexpr ::= '.'1118///  primaryexpr ::= ~,+,- primaryexpr1119bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,1120                                 AsmTypeInfo *TypeInfo) {1121  SMLoc FirstTokenLoc = getLexer().getLoc();1122  AsmToken::TokenKind FirstTokenKind = Lexer.getKind();1123  switch (FirstTokenKind) {1124  default:1125    return TokError("unknown token in expression");1126  // If we have an error assume that we've already handled it.1127  case AsmToken::Error:1128    return true;1129  case AsmToken::Exclaim:1130    Lex(); // Eat the operator.1131    if (parsePrimaryExpr(Res, EndLoc, TypeInfo))1132      return true;1133    Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);1134    return false;1135  case AsmToken::Dollar:1136  case AsmToken::Star:1137  case AsmToken::At:1138  case AsmToken::String:1139  case AsmToken::Identifier: {1140    StringRef Identifier;1141    if (parseIdentifier(Identifier)) {1142      // We may have failed but '$'|'*' may be a valid token in context of1143      // the current PC.1144      if (getTok().is(AsmToken::Dollar) || getTok().is(AsmToken::Star)) {1145        bool ShouldGenerateTempSymbol = false;1146        if ((getTok().is(AsmToken::Dollar) && MAI.getDollarIsPC()) ||1147            (getTok().is(AsmToken::Star) && MAI.isHLASM()))1148          ShouldGenerateTempSymbol = true;1149 1150        if (!ShouldGenerateTempSymbol)1151          return Error(FirstTokenLoc, "invalid token in expression");1152 1153        // Eat the '$'|'*' token.1154        Lex();1155        // This is either a '$'|'*' reference, which references the current PC.1156        // Emit a temporary label to the streamer and refer to it.1157        MCSymbol *Sym = Ctx.createTempSymbol();1158        Out.emitLabel(Sym);1159        Res = MCSymbolRefExpr::create(Sym, getContext());1160        EndLoc = FirstTokenLoc;1161        return false;1162      }1163    }1164    // Parse an optional relocation specifier.1165    std::pair<StringRef, StringRef> Split;1166    if (MAI.useAtForSpecifier()) {1167      if (FirstTokenKind == AsmToken::String) {1168        if (Lexer.is(AsmToken::At)) {1169          Lex(); // eat @1170          SMLoc AtLoc = getLexer().getLoc();1171          StringRef VName;1172          if (parseIdentifier(VName))1173            return Error(AtLoc, "expected symbol variant after '@'");1174 1175          Split = std::make_pair(Identifier, VName);1176        }1177      } else if (Lexer.getAllowAtInIdentifier()) {1178        Split = Identifier.split('@');1179      }1180    } else if (MAI.useParensForSpecifier() &&1181               parseOptionalToken(AsmToken::LParen)) {1182      StringRef VName;1183      parseIdentifier(VName);1184      if (parseRParen())1185        return true;1186      Split = std::make_pair(Identifier, VName);1187    }1188 1189    EndLoc = SMLoc::getFromPointer(Identifier.end());1190 1191    // This is a symbol reference.1192    StringRef SymbolName = Identifier;1193    if (SymbolName.empty())1194      return Error(getLexer().getLoc(), "expected a symbol reference");1195 1196    // Lookup the @specifier if used.1197    uint16_t Spec = 0;1198    if (!Split.second.empty()) {1199      auto MaybeSpecifier = MAI.getSpecifierForName(Split.second);1200      if (MaybeSpecifier) {1201        SymbolName = Split.first;1202        Spec = *MaybeSpecifier;1203      } else if (!MAI.doesAllowAtInName()) {1204        return Error(SMLoc::getFromPointer(Split.second.begin()),1205                     "invalid variant '" + Split.second + "'");1206      }1207    }1208 1209    MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);1210    if (!Sym)1211      Sym = getContext().parseSymbol(MAI.isHLASM() ? SymbolName.upper()1212                                                   : SymbolName);1213 1214    // If this is an absolute variable reference, substitute it now to preserve1215    // semantics in the face of reassignment.1216    if (Sym->isVariable()) {1217      auto V = Sym->getVariableValue();1218      bool DoInline = isa<MCConstantExpr>(V) && !Spec;1219      if (auto TV = dyn_cast<MCTargetExpr>(V))1220        DoInline = TV->inlineAssignedExpr();1221      if (DoInline) {1222        if (Spec)1223          return Error(EndLoc, "unexpected modifier on variable reference");1224        Res = Sym->getVariableValue();1225        return false;1226      }1227    }1228 1229    // Otherwise create a symbol ref.1230    Res = MCSymbolRefExpr::create(Sym, Spec, getContext(), FirstTokenLoc);1231    return false;1232  }1233  case AsmToken::BigNum:1234    return TokError("literal value out of range for directive");1235  case AsmToken::Integer: {1236    SMLoc Loc = getTok().getLoc();1237    int64_t IntVal = getTok().getIntVal();1238    Res = MCConstantExpr::create(IntVal, getContext());1239    EndLoc = Lexer.getTok().getEndLoc();1240    Lex(); // Eat token.1241    // Look for 'b' or 'f' following an Integer as a directional label1242    if (Lexer.getKind() == AsmToken::Identifier) {1243      StringRef IDVal = getTok().getString();1244      // Lookup the symbol variant if used.1245      std::pair<StringRef, StringRef> Split = IDVal.split('@');1246      uint16_t Spec = 0;1247      if (Split.first.size() != IDVal.size()) {1248        auto MaybeSpec = MAI.getSpecifierForName(Split.second);1249        if (!MaybeSpec)1250          return TokError("invalid variant '" + Split.second + "'");1251        IDVal = Split.first;1252        Spec = *MaybeSpec;1253      }1254      if (IDVal == "f" || IDVal == "b") {1255        MCSymbol *Sym =1256            Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");1257        Res = MCSymbolRefExpr::create(Sym, Spec, getContext(), Loc);1258        if (IDVal == "b" && Sym->isUndefined())1259          return Error(Loc, "directional label undefined");1260        DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym));1261        EndLoc = Lexer.getTok().getEndLoc();1262        Lex(); // Eat identifier.1263      }1264    }1265    return false;1266  }1267  case AsmToken::Real: {1268    APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());1269    uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();1270    Res = MCConstantExpr::create(IntVal, getContext());1271    EndLoc = Lexer.getTok().getEndLoc();1272    Lex(); // Eat token.1273    return false;1274  }1275  case AsmToken::Dot: {1276    if (MAI.isHLASM())1277      return TokError("cannot use . as current PC");1278 1279    // This is a '.' reference, which references the current PC.  Emit a1280    // temporary label to the streamer and refer to it.1281    MCSymbol *Sym = Ctx.createTempSymbol();1282    Out.emitLabel(Sym);1283    Res = MCSymbolRefExpr::create(Sym, getContext());1284    EndLoc = Lexer.getTok().getEndLoc();1285    Lex(); // Eat identifier.1286    return false;1287  }1288  case AsmToken::LParen:1289    Lex(); // Eat the '('.1290    return parseParenExpr(Res, EndLoc);1291  case AsmToken::LBrac:1292    if (!PlatformParser->HasBracketExpressions())1293      return TokError("brackets expression not supported on this target");1294    Lex(); // Eat the '['.1295    return parseBracketExpr(Res, EndLoc);1296  case AsmToken::Minus:1297    Lex(); // Eat the operator.1298    if (parsePrimaryExpr(Res, EndLoc, TypeInfo))1299      return true;1300    Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);1301    return false;1302  case AsmToken::Plus:1303    Lex(); // Eat the operator.1304    if (parsePrimaryExpr(Res, EndLoc, TypeInfo))1305      return true;1306    Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);1307    return false;1308  case AsmToken::Tilde:1309    Lex(); // Eat the operator.1310    if (parsePrimaryExpr(Res, EndLoc, TypeInfo))1311      return true;1312    Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);1313    return false;1314  }1315}1316 1317bool AsmParser::parseExpression(const MCExpr *&Res) {1318  SMLoc EndLoc;1319  return parseExpression(Res, EndLoc);1320}1321 1322const MCExpr *MCAsmParser::applySpecifier(const MCExpr *E, uint32_t Spec) {1323  // Ask the target implementation about this expression first.1324  const MCExpr *NewE = getTargetParser().applySpecifier(E, Spec, Ctx);1325  if (NewE)1326    return NewE;1327  // Recurse over the given expression, rebuilding it to apply the given variant1328  // if there is exactly one symbol.1329  switch (E->getKind()) {1330  case MCExpr::Specifier:1331    llvm_unreachable("cannot apply another specifier to MCSpecifierExpr");1332  case MCExpr::Target:1333  case MCExpr::Constant:1334    return nullptr;1335 1336  case MCExpr::SymbolRef: {1337    const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);1338 1339    if (SRE->getSpecifier()) {1340      TokError("invalid variant on expression '" + getTok().getIdentifier() +1341               "' (already modified)");1342      return E;1343    }1344 1345    return MCSymbolRefExpr::create(&SRE->getSymbol(), Spec, getContext(),1346                                   SRE->getLoc());1347  }1348 1349  case MCExpr::Unary: {1350    const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);1351    const MCExpr *Sub = applySpecifier(UE->getSubExpr(), Spec);1352    if (!Sub)1353      return nullptr;1354    return MCUnaryExpr::create(UE->getOpcode(), Sub, getContext(),1355                               UE->getLoc());1356  }1357 1358  case MCExpr::Binary: {1359    const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);1360    const MCExpr *LHS = applySpecifier(BE->getLHS(), Spec);1361    const MCExpr *RHS = applySpecifier(BE->getRHS(), Spec);1362 1363    if (!LHS && !RHS)1364      return nullptr;1365 1366    if (!LHS)1367      LHS = BE->getLHS();1368    if (!RHS)1369      RHS = BE->getRHS();1370 1371    return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, getContext(),1372                                BE->getLoc());1373  }1374  }1375 1376  llvm_unreachable("Invalid expression kind!");1377}1378 1379/// This function checks if the next token is <string> type or arithmetic.1380/// string that begin with character '<' must end with character '>'.1381/// otherwise it is arithmetics.1382/// If the function returns a 'true' value,1383/// the End argument will be filled with the last location pointed to the '>'1384/// character.1385 1386/// There is a gap between the AltMacro's documentation and the single quote1387/// implementation. GCC does not fully support this feature and so we will not1388/// support it.1389/// TODO: Adding single quote as a string.1390static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {1391  assert((StrLoc.getPointer() != nullptr) &&1392         "Argument to the function cannot be a NULL value");1393  const char *CharPtr = StrLoc.getPointer();1394  while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&1395         (*CharPtr != '\0')) {1396    if (*CharPtr == '!')1397      CharPtr++;1398    CharPtr++;1399  }1400  if (*CharPtr == '>') {1401    EndLoc = StrLoc.getFromPointer(CharPtr + 1);1402    return true;1403  }1404  return false;1405}1406 1407/// creating a string without the escape characters '!'.1408static std::string angleBracketString(StringRef AltMacroStr) {1409  std::string Res;1410  for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {1411    if (AltMacroStr[Pos] == '!')1412      Pos++;1413    Res += AltMacroStr[Pos];1414  }1415  return Res;1416}1417 1418bool MCAsmParser::parseAtSpecifier(const MCExpr *&Res, SMLoc &EndLoc) {1419  if (parseOptionalToken(AsmToken::At)) {1420    if (getLexer().isNot(AsmToken::Identifier))1421      return TokError("expected specifier following '@'");1422 1423    auto Spec = MAI.getSpecifierForName(getTok().getIdentifier());1424    if (!Spec)1425      return TokError("invalid specifier '@" + getTok().getIdentifier() + "'");1426 1427    const MCExpr *ModifiedRes = applySpecifier(Res, *Spec);1428    if (ModifiedRes)1429      Res = ModifiedRes;1430    Lex();1431  }1432  return false;1433}1434 1435/// Parse an expression and return it.1436///1437///  expr ::= expr &&,|| expr               -> lowest.1438///  expr ::= expr |,^,&,! expr1439///  expr ::= expr ==,!=,<>,<,<=,>,>= expr1440///  expr ::= expr <<,>> expr1441///  expr ::= expr +,- expr1442///  expr ::= expr *,/,% expr               -> highest.1443///  expr ::= primaryexpr1444///1445bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {1446  // Parse the expression.1447  Res = nullptr;1448  auto &TS = getTargetParser();1449  if (TS.parsePrimaryExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc))1450    return true;1451 1452  // As a special case, we support 'a op b @ modifier' by rewriting the1453  // expression to include the modifier. This is inefficient, but in general we1454  // expect users to use 'a@modifier op b'.1455  if (Lexer.getAllowAtInIdentifier() && parseOptionalToken(AsmToken::At)) {1456    if (Lexer.isNot(AsmToken::Identifier))1457      return TokError("unexpected symbol modifier following '@'");1458 1459    auto Spec = MAI.getSpecifierForName(getTok().getIdentifier());1460    if (!Spec)1461      return TokError("invalid variant '" + getTok().getIdentifier() + "'");1462 1463    const MCExpr *ModifiedRes = applySpecifier(Res, *Spec);1464    if (!ModifiedRes) {1465      return TokError("invalid modifier '" + getTok().getIdentifier() +1466                      "' (no symbols present)");1467    }1468 1469    Res = ModifiedRes;1470    Lex();1471  }1472 1473  // Try to constant fold it up front, if possible. Do not exploit1474  // assembler here.1475  int64_t Value;1476  if (Res->evaluateAsAbsolute(Value))1477    Res = MCConstantExpr::create(Value, getContext());1478 1479  return false;1480}1481 1482bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {1483  Res = nullptr;1484  return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);1485}1486 1487bool AsmParser::parseAbsoluteExpression(int64_t &Res) {1488  const MCExpr *Expr;1489 1490  SMLoc StartLoc = Lexer.getLoc();1491  if (parseExpression(Expr))1492    return true;1493 1494  if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))1495    return Error(StartLoc, "expected absolute expression");1496 1497  return false;1498}1499 1500static unsigned getDarwinBinOpPrecedence(AsmToken::TokenKind K,1501                                         MCBinaryExpr::Opcode &Kind,1502                                         bool ShouldUseLogicalShr) {1503  switch (K) {1504  default:1505    return 0; // not a binop.1506 1507  // Lowest Precedence: &&, ||1508  case AsmToken::AmpAmp:1509    Kind = MCBinaryExpr::LAnd;1510    return 1;1511  case AsmToken::PipePipe:1512    Kind = MCBinaryExpr::LOr;1513    return 1;1514 1515  // Low Precedence: |, &, ^1516  case AsmToken::Pipe:1517    Kind = MCBinaryExpr::Or;1518    return 2;1519  case AsmToken::Caret:1520    Kind = MCBinaryExpr::Xor;1521    return 2;1522  case AsmToken::Amp:1523    Kind = MCBinaryExpr::And;1524    return 2;1525 1526  // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >=1527  case AsmToken::EqualEqual:1528    Kind = MCBinaryExpr::EQ;1529    return 3;1530  case AsmToken::ExclaimEqual:1531  case AsmToken::LessGreater:1532    Kind = MCBinaryExpr::NE;1533    return 3;1534  case AsmToken::Less:1535    Kind = MCBinaryExpr::LT;1536    return 3;1537  case AsmToken::LessEqual:1538    Kind = MCBinaryExpr::LTE;1539    return 3;1540  case AsmToken::Greater:1541    Kind = MCBinaryExpr::GT;1542    return 3;1543  case AsmToken::GreaterEqual:1544    Kind = MCBinaryExpr::GTE;1545    return 3;1546 1547  // Intermediate Precedence: <<, >>1548  case AsmToken::LessLess:1549    Kind = MCBinaryExpr::Shl;1550    return 4;1551  case AsmToken::GreaterGreater:1552    Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;1553    return 4;1554 1555  // High Intermediate Precedence: +, -1556  case AsmToken::Plus:1557    Kind = MCBinaryExpr::Add;1558    return 5;1559  case AsmToken::Minus:1560    Kind = MCBinaryExpr::Sub;1561    return 5;1562 1563  // Highest Precedence: *, /, %1564  case AsmToken::Star:1565    Kind = MCBinaryExpr::Mul;1566    return 6;1567  case AsmToken::Slash:1568    Kind = MCBinaryExpr::Div;1569    return 6;1570  case AsmToken::Percent:1571    Kind = MCBinaryExpr::Mod;1572    return 6;1573  }1574}1575 1576static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI,1577                                      AsmToken::TokenKind K,1578                                      MCBinaryExpr::Opcode &Kind,1579                                      bool ShouldUseLogicalShr) {1580  switch (K) {1581  default:1582    return 0; // not a binop.1583 1584  // Lowest Precedence: &&, ||1585  case AsmToken::AmpAmp:1586    Kind = MCBinaryExpr::LAnd;1587    return 2;1588  case AsmToken::PipePipe:1589    Kind = MCBinaryExpr::LOr;1590    return 1;1591 1592  // Low Precedence: ==, !=, <>, <, <=, >, >=1593  case AsmToken::EqualEqual:1594    Kind = MCBinaryExpr::EQ;1595    return 3;1596  case AsmToken::ExclaimEqual:1597  case AsmToken::LessGreater:1598    Kind = MCBinaryExpr::NE;1599    return 3;1600  case AsmToken::Less:1601    Kind = MCBinaryExpr::LT;1602    return 3;1603  case AsmToken::LessEqual:1604    Kind = MCBinaryExpr::LTE;1605    return 3;1606  case AsmToken::Greater:1607    Kind = MCBinaryExpr::GT;1608    return 3;1609  case AsmToken::GreaterEqual:1610    Kind = MCBinaryExpr::GTE;1611    return 3;1612 1613  // Low Intermediate Precedence: +, -1614  case AsmToken::Plus:1615    Kind = MCBinaryExpr::Add;1616    return 4;1617  case AsmToken::Minus:1618    Kind = MCBinaryExpr::Sub;1619    return 4;1620 1621  // High Intermediate Precedence: |, !, &, ^1622  //1623  case AsmToken::Pipe:1624    Kind = MCBinaryExpr::Or;1625    return 5;1626  case AsmToken::Exclaim:1627    // Hack to support ARM compatible aliases (implied 'sp' operand in 'srs*'1628    // instructions like 'srsda #31!') and not parse ! as an infix operator.1629    if (MAI.getCommentString() == "@")1630      return 0;1631    Kind = MCBinaryExpr::OrNot;1632    return 5;1633  case AsmToken::Caret:1634    Kind = MCBinaryExpr::Xor;1635    return 5;1636  case AsmToken::Amp:1637    Kind = MCBinaryExpr::And;1638    return 5;1639 1640  // Highest Precedence: *, /, %, <<, >>1641  case AsmToken::Star:1642    Kind = MCBinaryExpr::Mul;1643    return 6;1644  case AsmToken::Slash:1645    Kind = MCBinaryExpr::Div;1646    return 6;1647  case AsmToken::Percent:1648    Kind = MCBinaryExpr::Mod;1649    return 6;1650  case AsmToken::LessLess:1651    Kind = MCBinaryExpr::Shl;1652    return 6;1653  case AsmToken::GreaterGreater:1654    Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;1655    return 6;1656  }1657}1658 1659unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K,1660                                       MCBinaryExpr::Opcode &Kind) {1661  bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();1662  return IsDarwin ? getDarwinBinOpPrecedence(K, Kind, ShouldUseLogicalShr)1663                  : getGNUBinOpPrecedence(MAI, K, Kind, ShouldUseLogicalShr);1664}1665 1666/// Parse all binary operators with precedence >= 'Precedence'.1667/// Res contains the LHS of the expression on input.1668bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,1669                              SMLoc &EndLoc) {1670  SMLoc StartLoc = Lexer.getLoc();1671  while (true) {1672    MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;1673    unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);1674 1675    // If the next token is lower precedence than we are allowed to eat, return1676    // successfully with what we ate already.1677    if (TokPrec < Precedence)1678      return false;1679 1680    Lex();1681 1682    // Eat the next primary expression.1683    const MCExpr *RHS;1684    if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))1685      return true;1686 1687    // If BinOp binds less tightly with RHS than the operator after RHS, let1688    // the pending operator take RHS as its LHS.1689    MCBinaryExpr::Opcode Dummy;1690    unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);1691    if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))1692      return true;1693 1694    // Merge LHS and RHS according to operator.1695    Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);1696  }1697}1698 1699/// ParseStatement:1700///   ::= EndOfStatement1701///   ::= Label* Directive ...Operands... EndOfStatement1702///   ::= Label* Identifier OperandList* EndOfStatement1703bool AsmParser::parseStatement(ParseStatementInfo &Info,1704                               MCAsmParserSemaCallback *SI) {1705  assert(!hasPendingError() && "parseStatement started with pending error");1706  // Eat initial spaces and comments1707  while (Lexer.is(AsmToken::Space))1708    Lex();1709  if (Lexer.is(AsmToken::EndOfStatement)) {1710    // if this is a line comment we can drop it safely1711    if (getTok().getString().empty() || getTok().getString().front() == '\r' ||1712        getTok().getString().front() == '\n')1713      Out.addBlankLine();1714    Lex();1715    return false;1716  }1717  // Statements always start with an identifier.1718  AsmToken ID = getTok();1719  SMLoc IDLoc = ID.getLoc();1720  StringRef IDVal;1721  int64_t LocalLabelVal = -1;1722  StartTokLoc = ID.getLoc();1723  if (Lexer.is(AsmToken::HashDirective))1724    return parseCppHashLineFilenameComment(IDLoc,1725                                           !isInsideMacroInstantiation());1726 1727  // Allow an integer followed by a ':' as a directional local label.1728  if (Lexer.is(AsmToken::Integer)) {1729    LocalLabelVal = getTok().getIntVal();1730    if (LocalLabelVal < 0) {1731      if (!TheCondState.Ignore) {1732        Lex(); // always eat a token1733        return Error(IDLoc, "unexpected token at start of statement");1734      }1735      IDVal = "";1736    } else {1737      IDVal = getTok().getString();1738      Lex(); // Consume the integer token to be used as an identifier token.1739      if (Lexer.getKind() != AsmToken::Colon) {1740        if (!TheCondState.Ignore) {1741          Lex(); // always eat a token1742          return Error(IDLoc, "unexpected token at start of statement");1743        }1744      }1745    }1746  } else if (Lexer.is(AsmToken::Dot)) {1747    // Treat '.' as a valid identifier in this context.1748    Lex();1749    IDVal = ".";1750  } else if (getTargetParser().tokenIsStartOfStatement(ID.getKind())) {1751    Lex();1752    IDVal = ID.getString();1753  } else if (parseIdentifier(IDVal)) {1754    if (!TheCondState.Ignore) {1755      Lex(); // always eat a token1756      return Error(IDLoc, "unexpected token at start of statement");1757    }1758    IDVal = "";1759  }1760 1761  // Handle conditional assembly here before checking for skipping.  We1762  // have to do this so that .endif isn't skipped in a ".if 0" block for1763  // example.1764  StringMap<DirectiveKind>::const_iterator DirKindIt =1765      DirectiveKindMap.find(IDVal.lower());1766  DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())1767                              ? DK_NO_DIRECTIVE1768                              : DirKindIt->getValue();1769  switch (DirKind) {1770  default:1771    break;1772  case DK_IF:1773  case DK_IFEQ:1774  case DK_IFGE:1775  case DK_IFGT:1776  case DK_IFLE:1777  case DK_IFLT:1778  case DK_IFNE:1779    return parseDirectiveIf(IDLoc, DirKind);1780  case DK_IFB:1781    return parseDirectiveIfb(IDLoc, true);1782  case DK_IFNB:1783    return parseDirectiveIfb(IDLoc, false);1784  case DK_IFC:1785    return parseDirectiveIfc(IDLoc, true);1786  case DK_IFEQS:1787    return parseDirectiveIfeqs(IDLoc, true);1788  case DK_IFNC:1789    return parseDirectiveIfc(IDLoc, false);1790  case DK_IFNES:1791    return parseDirectiveIfeqs(IDLoc, false);1792  case DK_IFDEF:1793    return parseDirectiveIfdef(IDLoc, true);1794  case DK_IFNDEF:1795  case DK_IFNOTDEF:1796    return parseDirectiveIfdef(IDLoc, false);1797  case DK_ELSEIF:1798    return parseDirectiveElseIf(IDLoc);1799  case DK_ELSE:1800    return parseDirectiveElse(IDLoc);1801  case DK_ENDIF:1802    return parseDirectiveEndIf(IDLoc);1803  }1804 1805  // Ignore the statement if in the middle of inactive conditional1806  // (e.g. ".if 0").1807  if (TheCondState.Ignore) {1808    eatToEndOfStatement();1809    return false;1810  }1811 1812  // FIXME: Recurse on local labels?1813 1814  // Check for a label.1815  //   ::= identifier ':'1816  //   ::= number ':'1817  if (Lexer.is(AsmToken::Colon) && getTargetParser().isLabel(ID)) {1818    if (checkForValidSection())1819      return true;1820 1821    Lex(); // Consume the ':'.1822 1823    // Diagnose attempt to use '.' as a label.1824    if (IDVal == ".")1825      return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");1826 1827    // Diagnose attempt to use a variable as a label.1828    //1829    // FIXME: Diagnostics. Note the location of the definition as a label.1830    // FIXME: This doesn't diagnose assignment to a symbol which has been1831    // implicitly marked as external.1832    MCSymbol *Sym;1833    if (LocalLabelVal == -1) {1834      if (ParsingMSInlineAsm && SI) {1835        StringRef RewrittenLabel =1836            SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);1837        assert(!RewrittenLabel.empty() &&1838               "We should have an internal name here.");1839        Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),1840                                       RewrittenLabel);1841        IDVal = RewrittenLabel;1842      }1843      Sym = getContext().parseSymbol(IDVal);1844    } else1845      Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);1846    // End of Labels should be treated as end of line for lexing1847    // purposes but that information is not available to the Lexer who1848    // does not understand Labels. This may cause us to see a Hash1849    // here instead of a preprocessor line comment.1850    if (getTok().is(AsmToken::Hash)) {1851      StringRef CommentStr = parseStringToEndOfStatement();1852      Lexer.Lex();1853      Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));1854    }1855 1856    // Consume any end of statement token, if present, to avoid spurious1857    // addBlankLine calls().1858    if (getTok().is(AsmToken::EndOfStatement)) {1859      Lex();1860    }1861 1862    if (MAI.isMachO() && CFIStartProcLoc) {1863      auto *SymM = static_cast<MCSymbolMachO *>(Sym);1864      if (SymM->isExternal() && !SymM->isAltEntry())1865        return Error(StartTokLoc, "non-private labels cannot appear between "1866                                  ".cfi_startproc / .cfi_endproc pairs") &&1867               Error(*CFIStartProcLoc, "previous .cfi_startproc was here");1868    }1869 1870    if (discardLTOSymbol(IDVal))1871      return false;1872 1873    getTargetParser().doBeforeLabelEmit(Sym, IDLoc);1874 1875    // Emit the label.1876    if (!getTargetParser().isParsingMSInlineAsm())1877      Out.emitLabel(Sym, IDLoc);1878 1879    // If we are generating dwarf for assembly source files then gather the1880    // info to make a dwarf label entry for this label if needed.1881    if (enabledGenDwarfForAssembly())1882      MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),1883                                 IDLoc);1884 1885    getTargetParser().onLabelParsed(Sym);1886 1887    return false;1888  }1889 1890  // Check for an assignment statement.1891  //   ::= identifier '='1892  if (Lexer.is(AsmToken::Equal) && getTargetParser().equalIsAsmAssignment()) {1893    Lex();1894    return parseAssignment(IDVal, AssignmentKind::Equal);1895  }1896 1897  // If macros are enabled, check to see if this is a macro instantiation.1898  if (areMacrosEnabled())1899    if (MCAsmMacro *M = getContext().lookupMacro(IDVal))1900      return handleMacroEntry(M, IDLoc);1901 1902  // Otherwise, we have a normal instruction or directive.1903 1904  // Directives start with "."1905  if (IDVal.starts_with(".") && IDVal != ".") {1906    // There are several entities interested in parsing directives:1907    //1908    // 1. The target-specific assembly parser. Some directives are target1909    //    specific or may potentially behave differently on certain targets.1910    // 2. Asm parser extensions. For example, platform-specific parsers1911    //    (like the ELF parser) register themselves as extensions.1912    // 3. The generic directive parser implemented by this class. These are1913    //    all the directives that behave in a target and platform independent1914    //    manner, or at least have a default behavior that's shared between1915    //    all targets and platforms.1916 1917    getTargetParser().flushPendingInstructions(getStreamer());1918 1919    ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(ID);1920    assert(TPDirectiveReturn.isFailure() == hasPendingError() &&1921           "Should only return Failure iff there was an error");1922    if (TPDirectiveReturn.isFailure())1923      return true;1924    if (TPDirectiveReturn.isSuccess())1925      return false;1926 1927    // Next, check the extension directive map to see if any extension has1928    // registered itself to parse this directive.1929    std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =1930        ExtensionDirectiveMap.lookup(IDVal);1931    if (Handler.first)1932      return (*Handler.second)(Handler.first, IDVal, IDLoc);1933 1934    // Finally, if no one else is interested in this directive, it must be1935    // generic and familiar to this class.1936    switch (DirKind) {1937    default:1938      break;1939    case DK_SET:1940    case DK_EQU:1941      return parseDirectiveSet(IDVal, AssignmentKind::Set);1942    case DK_EQUIV:1943      return parseDirectiveSet(IDVal, AssignmentKind::Equiv);1944    case DK_LTO_SET_CONDITIONAL:1945      return parseDirectiveSet(IDVal, AssignmentKind::LTOSetConditional);1946    case DK_ASCII:1947      return parseDirectiveAscii(IDVal, false);1948    case DK_ASCIZ:1949    case DK_STRING:1950      return parseDirectiveAscii(IDVal, true);1951    case DK_BASE64:1952      return parseDirectiveBase64();1953    case DK_BYTE:1954    case DK_DC_B:1955      return parseDirectiveValue(IDVal, 1);1956    case DK_DC:1957    case DK_DC_W:1958    case DK_SHORT:1959    case DK_VALUE:1960    case DK_2BYTE:1961      return parseDirectiveValue(IDVal, 2);1962    case DK_LONG:1963    case DK_INT:1964    case DK_4BYTE:1965    case DK_DC_L:1966      return parseDirectiveValue(IDVal, 4);1967    case DK_QUAD:1968    case DK_8BYTE:1969      return parseDirectiveValue(IDVal, 8);1970    case DK_DC_A:1971      return parseDirectiveValue(1972          IDVal, getContext().getAsmInfo()->getCodePointerSize());1973    case DK_OCTA:1974      return parseDirectiveOctaValue(IDVal);1975    case DK_SINGLE:1976    case DK_FLOAT:1977    case DK_DC_S:1978      return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle());1979    case DK_DOUBLE:1980    case DK_DC_D:1981      return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble());1982    case DK_ALIGN: {1983      bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();1984      return parseDirectiveAlign(IsPow2, /*ExprSize=*/1);1985    }1986    case DK_ALIGN32: {1987      bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();1988      return parseDirectiveAlign(IsPow2, /*ExprSize=*/4);1989    }1990    case DK_BALIGN:1991      return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);1992    case DK_BALIGNW:1993      return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);1994    case DK_BALIGNL:1995      return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);1996    case DK_P2ALIGN:1997      return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);1998    case DK_P2ALIGNW:1999      return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);2000    case DK_P2ALIGNL:2001      return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);2002    case DK_ORG:2003      return parseDirectiveOrg();2004    case DK_FILL:2005      return parseDirectiveFill();2006    case DK_ZERO:2007      return parseDirectiveZero();2008    case DK_EXTERN:2009      eatToEndOfStatement(); // .extern is the default, ignore it.2010      return false;2011    case DK_GLOBL:2012    case DK_GLOBAL:2013      return parseDirectiveSymbolAttribute(MCSA_Global);2014    case DK_LAZY_REFERENCE:2015      return parseDirectiveSymbolAttribute(MCSA_LazyReference);2016    case DK_NO_DEAD_STRIP:2017      return parseDirectiveSymbolAttribute(MCSA_NoDeadStrip);2018    case DK_SYMBOL_RESOLVER:2019      return parseDirectiveSymbolAttribute(MCSA_SymbolResolver);2020    case DK_PRIVATE_EXTERN:2021      return parseDirectiveSymbolAttribute(MCSA_PrivateExtern);2022    case DK_REFERENCE:2023      return parseDirectiveSymbolAttribute(MCSA_Reference);2024    case DK_WEAK_DEFINITION:2025      return parseDirectiveSymbolAttribute(MCSA_WeakDefinition);2026    case DK_WEAK_REFERENCE:2027      return parseDirectiveSymbolAttribute(MCSA_WeakReference);2028    case DK_WEAK_DEF_CAN_BE_HIDDEN:2029      return parseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);2030    case DK_COLD:2031      return parseDirectiveSymbolAttribute(MCSA_Cold);2032    case DK_COMM:2033    case DK_COMMON:2034      return parseDirectiveComm(/*IsLocal=*/false);2035    case DK_LCOMM:2036      return parseDirectiveComm(/*IsLocal=*/true);2037    case DK_ABORT:2038      return parseDirectiveAbort(IDLoc);2039    case DK_INCLUDE:2040      return parseDirectiveInclude();2041    case DK_INCBIN:2042      return parseDirectiveIncbin();2043    case DK_CODE16:2044    case DK_CODE16GCC:2045      return TokError(Twine(IDVal) +2046                      " not currently supported for this target");2047    case DK_REPT:2048      return parseDirectiveRept(IDLoc, IDVal);2049    case DK_IRP:2050      return parseDirectiveIrp(IDLoc);2051    case DK_IRPC:2052      return parseDirectiveIrpc(IDLoc);2053    case DK_ENDR:2054      return parseDirectiveEndr(IDLoc);2055    case DK_SLEB128:2056      return parseDirectiveLEB128(true);2057    case DK_ULEB128:2058      return parseDirectiveLEB128(false);2059    case DK_SPACE:2060    case DK_SKIP:2061      return parseDirectiveSpace(IDVal);2062    case DK_FILE:2063      return parseDirectiveFile(IDLoc);2064    case DK_LINE:2065      return parseDirectiveLine();2066    case DK_LOC:2067      return parseDirectiveLoc();2068    case DK_LOC_LABEL:2069      return parseDirectiveLocLabel(IDLoc);2070    case DK_STABS:2071      return parseDirectiveStabs();2072    case DK_CV_FILE:2073      return parseDirectiveCVFile();2074    case DK_CV_FUNC_ID:2075      return parseDirectiveCVFuncId();2076    case DK_CV_INLINE_SITE_ID:2077      return parseDirectiveCVInlineSiteId();2078    case DK_CV_LOC:2079      return parseDirectiveCVLoc();2080    case DK_CV_LINETABLE:2081      return parseDirectiveCVLinetable();2082    case DK_CV_INLINE_LINETABLE:2083      return parseDirectiveCVInlineLinetable();2084    case DK_CV_DEF_RANGE:2085      return parseDirectiveCVDefRange();2086    case DK_CV_STRING:2087      return parseDirectiveCVString();2088    case DK_CV_STRINGTABLE:2089      return parseDirectiveCVStringTable();2090    case DK_CV_FILECHECKSUMS:2091      return parseDirectiveCVFileChecksums();2092    case DK_CV_FILECHECKSUM_OFFSET:2093      return parseDirectiveCVFileChecksumOffset();2094    case DK_CV_FPO_DATA:2095      return parseDirectiveCVFPOData();2096    case DK_CFI_SECTIONS:2097      return parseDirectiveCFISections();2098    case DK_CFI_STARTPROC:2099      return parseDirectiveCFIStartProc();2100    case DK_CFI_ENDPROC:2101      return parseDirectiveCFIEndProc();2102    case DK_CFI_DEF_CFA:2103      return parseDirectiveCFIDefCfa(IDLoc);2104    case DK_CFI_DEF_CFA_OFFSET:2105      return parseDirectiveCFIDefCfaOffset(IDLoc);2106    case DK_CFI_ADJUST_CFA_OFFSET:2107      return parseDirectiveCFIAdjustCfaOffset(IDLoc);2108    case DK_CFI_DEF_CFA_REGISTER:2109      return parseDirectiveCFIDefCfaRegister(IDLoc);2110    case DK_CFI_LLVM_DEF_ASPACE_CFA:2111      return parseDirectiveCFILLVMDefAspaceCfa(IDLoc);2112    case DK_CFI_OFFSET:2113      return parseDirectiveCFIOffset(IDLoc);2114    case DK_CFI_REL_OFFSET:2115      return parseDirectiveCFIRelOffset(IDLoc);2116    case DK_CFI_PERSONALITY:2117      return parseDirectiveCFIPersonalityOrLsda(true);2118    case DK_CFI_LSDA:2119      return parseDirectiveCFIPersonalityOrLsda(false);2120    case DK_CFI_REMEMBER_STATE:2121      return parseDirectiveCFIRememberState(IDLoc);2122    case DK_CFI_RESTORE_STATE:2123      return parseDirectiveCFIRestoreState(IDLoc);2124    case DK_CFI_SAME_VALUE:2125      return parseDirectiveCFISameValue(IDLoc);2126    case DK_CFI_RESTORE:2127      return parseDirectiveCFIRestore(IDLoc);2128    case DK_CFI_ESCAPE:2129      return parseDirectiveCFIEscape(IDLoc);2130    case DK_CFI_RETURN_COLUMN:2131      return parseDirectiveCFIReturnColumn(IDLoc);2132    case DK_CFI_SIGNAL_FRAME:2133      return parseDirectiveCFISignalFrame(IDLoc);2134    case DK_CFI_UNDEFINED:2135      return parseDirectiveCFIUndefined(IDLoc);2136    case DK_CFI_REGISTER:2137      return parseDirectiveCFIRegister(IDLoc);2138    case DK_CFI_WINDOW_SAVE:2139      return parseDirectiveCFIWindowSave(IDLoc);2140    case DK_CFI_LABEL:2141      return parseDirectiveCFILabel(IDLoc);2142    case DK_CFI_VAL_OFFSET:2143      return parseDirectiveCFIValOffset(IDLoc);2144    case DK_MACROS_ON:2145    case DK_MACROS_OFF:2146      return parseDirectiveMacrosOnOff(IDVal);2147    case DK_MACRO:2148      return parseDirectiveMacro(IDLoc);2149    case DK_ALTMACRO:2150    case DK_NOALTMACRO:2151      return parseDirectiveAltmacro(IDVal);2152    case DK_EXITM:2153      return parseDirectiveExitMacro(IDVal);2154    case DK_ENDM:2155    case DK_ENDMACRO:2156      return parseDirectiveEndMacro(IDVal);2157    case DK_PURGEM:2158      return parseDirectivePurgeMacro(IDLoc);2159    case DK_END:2160      return parseDirectiveEnd(IDLoc);2161    case DK_ERR:2162      return parseDirectiveError(IDLoc, false);2163    case DK_ERROR:2164      return parseDirectiveError(IDLoc, true);2165    case DK_WARNING:2166      return parseDirectiveWarning(IDLoc);2167    case DK_RELOC:2168      return parseDirectiveReloc(IDLoc);2169    case DK_DCB:2170    case DK_DCB_W:2171      return parseDirectiveDCB(IDVal, 2);2172    case DK_DCB_B:2173      return parseDirectiveDCB(IDVal, 1);2174    case DK_DCB_D:2175      return parseDirectiveRealDCB(IDVal, APFloat::IEEEdouble());2176    case DK_DCB_L:2177      return parseDirectiveDCB(IDVal, 4);2178    case DK_DCB_S:2179      return parseDirectiveRealDCB(IDVal, APFloat::IEEEsingle());2180    case DK_DC_X:2181    case DK_DCB_X:2182      return TokError(Twine(IDVal) +2183                      " not currently supported for this target");2184    case DK_DS:2185    case DK_DS_W:2186      return parseDirectiveDS(IDVal, 2);2187    case DK_DS_B:2188      return parseDirectiveDS(IDVal, 1);2189    case DK_DS_D:2190      return parseDirectiveDS(IDVal, 8);2191    case DK_DS_L:2192    case DK_DS_S:2193      return parseDirectiveDS(IDVal, 4);2194    case DK_DS_P:2195    case DK_DS_X:2196      return parseDirectiveDS(IDVal, 12);2197    case DK_PRINT:2198      return parseDirectivePrint(IDLoc);2199    case DK_ADDRSIG:2200      return parseDirectiveAddrsig();2201    case DK_ADDRSIG_SYM:2202      return parseDirectiveAddrsigSym();2203    case DK_PSEUDO_PROBE:2204      return parseDirectivePseudoProbe();2205    case DK_LTO_DISCARD:2206      return parseDirectiveLTODiscard();2207    case DK_MEMTAG:2208      return parseDirectiveSymbolAttribute(MCSA_Memtag);2209    }2210 2211    return Error(IDLoc, "unknown directive");2212  }2213 2214  // __asm _emit or __asm __emit2215  if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||2216                             IDVal == "_EMIT" || IDVal == "__EMIT"))2217    return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());2218 2219  // __asm align2220  if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))2221    return parseDirectiveMSAlign(IDLoc, Info);2222 2223  if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))2224    Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);2225  if (checkForValidSection())2226    return true;2227 2228  return parseAndMatchAndEmitTargetInstruction(Info, IDVal, ID, IDLoc);2229}2230 2231bool AsmParser::parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info,2232                                                      StringRef IDVal,2233                                                      AsmToken ID,2234                                                      SMLoc IDLoc) {2235  // Canonicalize the opcode to lower case.2236  std::string OpcodeStr = IDVal.lower();2237  ParseInstructionInfo IInfo(Info.AsmRewrites);2238  bool ParseHadError = getTargetParser().parseInstruction(IInfo, OpcodeStr, ID,2239                                                          Info.ParsedOperands);2240  Info.ParseError = ParseHadError;2241 2242  // Dump the parsed representation, if requested.2243  if (getShowParsedOperands()) {2244    SmallString<256> Str;2245    raw_svector_ostream OS(Str);2246    OS << "parsed instruction: [";2247    for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {2248      if (i != 0)2249        OS << ", ";2250      Info.ParsedOperands[i]->print(OS, MAI);2251    }2252    OS << "]";2253 2254    printMessage(IDLoc, SourceMgr::DK_Note, OS.str());2255  }2256 2257  // Fail even if ParseInstruction erroneously returns false.2258  if (hasPendingError() || ParseHadError)2259    return true;2260 2261  // If we are generating dwarf for the current section then generate a .loc2262  // directive for the instruction.2263  if (!ParseHadError && enabledGenDwarfForAssembly() &&2264      getContext().getGenDwarfSectionSyms().count(2265          getStreamer().getCurrentSectionOnly())) {2266    unsigned Line;2267    if (ActiveMacros.empty())2268      Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);2269    else2270      Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,2271                                   ActiveMacros.front()->ExitBuffer);2272 2273    // If we previously parsed a cpp hash file line comment then make sure the2274    // current Dwarf File is for the CppHashFilename if not then emit the2275    // Dwarf File table for it and adjust the line number for the .loc.2276    if (!CppHashInfo.Filename.empty()) {2277      unsigned FileNumber = getStreamer().emitDwarfFileDirective(2278          0, StringRef(), CppHashInfo.Filename);2279      getContext().setGenDwarfFileNumber(FileNumber);2280 2281      unsigned CppHashLocLineNo =2282        SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);2283      Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);2284    }2285 2286    getStreamer().emitDwarfLocDirective(2287        getContext().getGenDwarfFileNumber(), Line, 0,2288        DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0,2289        StringRef());2290  }2291 2292  // If parsing succeeded, match the instruction.2293  if (!ParseHadError) {2294    uint64_t ErrorInfo;2295    if (getTargetParser().matchAndEmitInstruction(2296            IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,2297            getTargetParser().isParsingMSInlineAsm()))2298      return true;2299  }2300  return false;2301}2302 2303// Parse and erase curly braces marking block start/end2304bool2305AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {2306  // Identify curly brace marking block start/end2307  if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))2308    return false;2309 2310  SMLoc StartLoc = Lexer.getLoc();2311  Lex(); // Eat the brace2312  if (Lexer.is(AsmToken::EndOfStatement))2313    Lex(); // Eat EndOfStatement following the brace2314 2315  // Erase the block start/end brace from the output asm string2316  AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -2317                                                  StartLoc.getPointer());2318  return true;2319}2320 2321/// parseCppHashLineFilenameComment as this:2322///   ::= # number "filename"2323bool AsmParser::parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo) {2324  Lex(); // Eat the hash token.2325  // Lexer only ever emits HashDirective if it fully formed if it's2326  // done the checking already so this is an internal error.2327  assert(getTok().is(AsmToken::Integer) &&2328         "Lexing Cpp line comment: Expected Integer");2329  int64_t LineNumber = getTok().getIntVal();2330  Lex();2331  assert(getTok().is(AsmToken::String) &&2332         "Lexing Cpp line comment: Expected String");2333  StringRef Filename = getTok().getString();2334  Lex();2335 2336  if (!SaveLocInfo)2337    return false;2338 2339  // Get rid of the enclosing quotes.2340  Filename = Filename.substr(1, Filename.size() - 2);2341 2342  // Save the SMLoc, Filename and LineNumber for later use by diagnostics2343  // and possibly DWARF file info.2344  CppHashInfo.Loc = L;2345  CppHashInfo.Filename = Filename;2346  CppHashInfo.LineNumber = LineNumber;2347  CppHashInfo.Buf = CurBuffer;2348  if (!HadCppHashFilename) {2349    HadCppHashFilename = true;2350    // If we haven't encountered any .file directives, then the first #line2351    // directive describes the "root" file and directory of the compilation2352    // unit.2353    if (getContext().getGenDwarfForAssembly() &&2354        getContext().getGenDwarfFileNumber() == 0) {2355      // It's preprocessed, so there is no checksum, and of course no source2356      // directive.2357      getContext().setMCLineTableRootFile(2358          /*CUID=*/0, getContext().getCompilationDir(), Filename,2359          /*Cksum=*/std::nullopt, /*Source=*/std::nullopt);2360    }2361  }2362  return false;2363}2364 2365/// will use the last parsed cpp hash line filename comment2366/// for the Filename and LineNo if any in the diagnostic.2367void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {2368  auto *Parser = static_cast<AsmParser *>(Context);2369  raw_ostream &OS = errs();2370 2371  const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();2372  SMLoc DiagLoc = Diag.getLoc();2373  unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);2374  unsigned CppHashBuf =2375      Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);2376 2377  // Like SourceMgr::printMessage() we need to print the include stack if any2378  // before printing the message.2379  unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);2380  if (!Parser->SavedDiagHandler && DiagCurBuffer &&2381      DiagCurBuffer != DiagSrcMgr.getMainFileID()) {2382    SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);2383    DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);2384  }2385 2386  // If we have not parsed a cpp hash line filename comment or the source2387  // manager changed or buffer changed (like in a nested include) then just2388  // print the normal diagnostic using its Filename and LineNo.2389  if (!Parser->CppHashInfo.LineNumber || DiagBuf != CppHashBuf) {2390    if (Parser->SavedDiagHandler)2391      Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);2392    else2393      Parser->getContext().diagnose(Diag);2394    return;2395  }2396 2397  // Use the CppHashFilename and calculate a line number based on the2398  // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc2399  // for the diagnostic.2400  const std::string &Filename = std::string(Parser->CppHashInfo.Filename);2401 2402  int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);2403  int CppHashLocLineNo =2404      Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);2405  int LineNo =2406      Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);2407 2408  SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,2409                       Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),2410                       Diag.getLineContents(), Diag.getRanges());2411 2412  if (Parser->SavedDiagHandler)2413    Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);2414  else2415    Parser->getContext().diagnose(NewDiag);2416}2417 2418// FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The2419// difference being that that function accepts '@' as part of identifiers and2420// we can't do that. AsmLexer.cpp should probably be changed to handle2421// '@' as a special case when needed.2422static bool isIdentifierChar(char c) {2423  return isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$' ||2424         c == '.';2425}2426 2427bool AsmParser::expandMacro(raw_svector_ostream &OS, MCAsmMacro &Macro,2428                            ArrayRef<MCAsmMacroParameter> Parameters,2429                            ArrayRef<MCAsmMacroArgument> A,2430                            bool EnableAtPseudoVariable) {2431  unsigned NParameters = Parameters.size();2432  auto expandArg = [&](unsigned Index) {2433    bool HasVararg = NParameters ? Parameters.back().Vararg : false;2434    bool VarargParameter = HasVararg && Index == (NParameters - 1);2435    for (const AsmToken &Token : A[Index])2436      // For altmacro mode, you can write '%expr'.2437      // The prefix '%' evaluates the expression 'expr'2438      // and uses the result as a string (e.g. replace %(1+2) with the2439      // string "3").2440      // Here, we identify the integer token which is the result of the2441      // absolute expression evaluation and replace it with its string2442      // representation.2443      if (AltMacroMode && Token.getString().front() == '%' &&2444          Token.is(AsmToken::Integer))2445        // Emit an integer value to the buffer.2446        OS << Token.getIntVal();2447      // Only Token that was validated as a string and begins with '<'2448      // is considered altMacroString!!!2449      else if (AltMacroMode && Token.getString().front() == '<' &&2450               Token.is(AsmToken::String)) {2451        OS << angleBracketString(Token.getStringContents());2452      }2453      // We expect no quotes around the string's contents when2454      // parsing for varargs.2455      else if (Token.isNot(AsmToken::String) || VarargParameter)2456        OS << Token.getString();2457      else2458        OS << Token.getStringContents();2459  };2460 2461  // A macro without parameters is handled differently on Darwin:2462  // gas accepts no arguments and does no substitutions2463  StringRef Body = Macro.Body;2464  size_t I = 0, End = Body.size();2465  while (I != End) {2466    if (Body[I] == '\\' && I + 1 != End) {2467      // Check for \@ and \+ pseudo variables.2468      if (EnableAtPseudoVariable && Body[I + 1] == '@') {2469        OS << NumOfMacroInstantiations;2470        I += 2;2471        continue;2472      }2473      if (Body[I + 1] == '+') {2474        OS << Macro.Count;2475        I += 2;2476        continue;2477      }2478      if (Body[I + 1] == '(' && Body[I + 2] == ')') {2479        I += 3;2480        continue;2481      }2482 2483      size_t Pos = ++I;2484      while (I != End && isIdentifierChar(Body[I]))2485        ++I;2486      StringRef Argument(Body.data() + Pos, I - Pos);2487      if (AltMacroMode && I != End && Body[I] == '&')2488        ++I;2489      unsigned Index = 0;2490      for (; Index < NParameters; ++Index)2491        if (Parameters[Index].Name == Argument)2492          break;2493      if (Index == NParameters)2494        OS << '\\' << Argument;2495      else2496        expandArg(Index);2497      continue;2498    }2499 2500    // In Darwin mode, $ is used for macro expansion, not considered an2501    // identifier char.2502    if (Body[I] == '$' && I + 1 != End && IsDarwin && !NParameters) {2503      // This macro has no parameters, look for $0, $1, etc.2504      switch (Body[I + 1]) {2505      // $$ => $2506      case '$':2507        OS << '$';2508        I += 2;2509        continue;2510      // $n => number of arguments2511      case 'n':2512        OS << A.size();2513        I += 2;2514        continue;2515      default: {2516        if (!isDigit(Body[I + 1]))2517          break;2518        // $[0-9] => argument2519        // Missing arguments are ignored.2520        unsigned Index = Body[I + 1] - '0';2521        if (Index < A.size())2522          for (const AsmToken &Token : A[Index])2523            OS << Token.getString();2524        I += 2;2525        continue;2526      }2527      }2528    }2529 2530    if (!isIdentifierChar(Body[I]) || IsDarwin) {2531      OS << Body[I++];2532      continue;2533    }2534 2535    const size_t Start = I;2536    while (++I && isIdentifierChar(Body[I])) {2537    }2538    StringRef Token(Body.data() + Start, I - Start);2539    if (AltMacroMode) {2540      unsigned Index = 0;2541      for (; Index != NParameters; ++Index)2542        if (Parameters[Index].Name == Token)2543          break;2544      if (Index != NParameters) {2545        expandArg(Index);2546        if (I != End && Body[I] == '&')2547          ++I;2548        continue;2549      }2550    }2551    OS << Token;2552  }2553 2554  ++Macro.Count;2555  return false;2556}2557 2558static bool isOperator(AsmToken::TokenKind kind) {2559  switch (kind) {2560  default:2561    return false;2562  case AsmToken::Plus:2563  case AsmToken::Minus:2564  case AsmToken::Tilde:2565  case AsmToken::Slash:2566  case AsmToken::Star:2567  case AsmToken::Dot:2568  case AsmToken::Equal:2569  case AsmToken::EqualEqual:2570  case AsmToken::Pipe:2571  case AsmToken::PipePipe:2572  case AsmToken::Caret:2573  case AsmToken::Amp:2574  case AsmToken::AmpAmp:2575  case AsmToken::Exclaim:2576  case AsmToken::ExclaimEqual:2577  case AsmToken::Less:2578  case AsmToken::LessEqual:2579  case AsmToken::LessLess:2580  case AsmToken::LessGreater:2581  case AsmToken::Greater:2582  case AsmToken::GreaterEqual:2583  case AsmToken::GreaterGreater:2584    return true;2585  }2586}2587 2588namespace {2589 2590class AsmLexerSkipSpaceRAII {2591public:2592  AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {2593    Lexer.setSkipSpace(SkipSpace);2594  }2595 2596  ~AsmLexerSkipSpaceRAII() {2597    Lexer.setSkipSpace(true);2598  }2599 2600private:2601  AsmLexer &Lexer;2602};2603 2604} // end anonymous namespace2605 2606bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {2607 2608  if (Vararg) {2609    if (Lexer.isNot(AsmToken::EndOfStatement)) {2610      StringRef Str = parseStringToEndOfStatement();2611      MA.emplace_back(AsmToken::String, Str);2612    }2613    return false;2614  }2615 2616  unsigned ParenLevel = 0;2617 2618  // Darwin doesn't use spaces to delmit arguments.2619  AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);2620 2621  bool SpaceEaten;2622 2623  while (true) {2624    SpaceEaten = false;2625    if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))2626      return TokError("unexpected token in macro instantiation");2627 2628    if (ParenLevel == 0) {2629 2630      if (Lexer.is(AsmToken::Comma))2631        break;2632 2633      if (parseOptionalToken(AsmToken::Space))2634        SpaceEaten = true;2635 2636      // Spaces can delimit parameters, but could also be part an expression.2637      // If the token after a space is an operator, add the token and the next2638      // one into this argument2639      if (!IsDarwin) {2640        if (isOperator(Lexer.getKind())) {2641          MA.push_back(getTok());2642          Lexer.Lex();2643 2644          // Whitespace after an operator can be ignored.2645          parseOptionalToken(AsmToken::Space);2646          continue;2647        }2648      }2649      if (SpaceEaten)2650        break;2651    }2652 2653    // handleMacroEntry relies on not advancing the lexer here2654    // to be able to fill in the remaining default parameter values2655    if (Lexer.is(AsmToken::EndOfStatement))2656      break;2657 2658    // Adjust the current parentheses level.2659    if (Lexer.is(AsmToken::LParen))2660      ++ParenLevel;2661    else if (Lexer.is(AsmToken::RParen) && ParenLevel)2662      --ParenLevel;2663 2664    // Append the token to the current argument list.2665    MA.push_back(getTok());2666    Lexer.Lex();2667  }2668 2669  if (ParenLevel != 0)2670    return TokError("unbalanced parentheses in macro argument");2671  return false;2672}2673 2674// Parse the macro instantiation arguments.2675bool AsmParser::parseMacroArguments(const MCAsmMacro *M,2676                                    MCAsmMacroArguments &A) {2677  const unsigned NParameters = M ? M->Parameters.size() : 0;2678  bool NamedParametersFound = false;2679  SmallVector<SMLoc, 4> FALocs;2680 2681  A.resize(NParameters);2682  FALocs.resize(NParameters);2683 2684  // Parse two kinds of macro invocations:2685  // - macros defined without any parameters accept an arbitrary number of them2686  // - macros defined with parameters accept at most that many of them2687  bool HasVararg = NParameters ? M->Parameters.back().Vararg : false;2688  for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;2689       ++Parameter) {2690    SMLoc IDLoc = Lexer.getLoc();2691    MCAsmMacroParameter FA;2692 2693    if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) {2694      if (parseIdentifier(FA.Name))2695        return Error(IDLoc, "invalid argument identifier for formal argument");2696 2697      if (Lexer.isNot(AsmToken::Equal))2698        return TokError("expected '=' after formal parameter identifier");2699 2700      Lex();2701 2702      NamedParametersFound = true;2703    }2704    bool Vararg = HasVararg && Parameter == (NParameters - 1);2705 2706    if (NamedParametersFound && FA.Name.empty())2707      return Error(IDLoc, "cannot mix positional and keyword arguments");2708 2709    SMLoc StrLoc = Lexer.getLoc();2710    SMLoc EndLoc;2711    if (AltMacroMode && Lexer.is(AsmToken::Percent)) {2712      const MCExpr *AbsoluteExp;2713      int64_t Value;2714      /// Eat '%'2715      Lex();2716      if (parseExpression(AbsoluteExp, EndLoc))2717        return false;2718      if (!AbsoluteExp->evaluateAsAbsolute(Value,2719                                           getStreamer().getAssemblerPtr()))2720        return Error(StrLoc, "expected absolute expression");2721      const char *StrChar = StrLoc.getPointer();2722      const char *EndChar = EndLoc.getPointer();2723      AsmToken newToken(AsmToken::Integer,2724                        StringRef(StrChar, EndChar - StrChar), Value);2725      FA.Value.push_back(newToken);2726    } else if (AltMacroMode && Lexer.is(AsmToken::Less) &&2727               isAngleBracketString(StrLoc, EndLoc)) {2728      const char *StrChar = StrLoc.getPointer();2729      const char *EndChar = EndLoc.getPointer();2730      jumpToLoc(EndLoc, CurBuffer);2731      /// Eat from '<' to '>'2732      Lex();2733      AsmToken newToken(AsmToken::String,2734                        StringRef(StrChar, EndChar - StrChar));2735      FA.Value.push_back(newToken);2736    } else if(parseMacroArgument(FA.Value, Vararg))2737      return true;2738 2739    unsigned PI = Parameter;2740    if (!FA.Name.empty()) {2741      unsigned FAI = 0;2742      for (FAI = 0; FAI < NParameters; ++FAI)2743        if (M->Parameters[FAI].Name == FA.Name)2744          break;2745 2746      if (FAI >= NParameters) {2747        assert(M && "expected macro to be defined");2748        return Error(IDLoc, "parameter named '" + FA.Name +2749                                "' does not exist for macro '" + M->Name + "'");2750      }2751      PI = FAI;2752    }2753 2754    if (!FA.Value.empty()) {2755      if (A.size() <= PI)2756        A.resize(PI + 1);2757      A[PI] = FA.Value;2758 2759      if (FALocs.size() <= PI)2760        FALocs.resize(PI + 1);2761 2762      FALocs[PI] = Lexer.getLoc();2763    }2764 2765    // At the end of the statement, fill in remaining arguments that have2766    // default values. If there aren't any, then the next argument is2767    // required but missing2768    if (Lexer.is(AsmToken::EndOfStatement)) {2769      bool Failure = false;2770      for (unsigned FAI = 0; FAI < NParameters; ++FAI) {2771        if (A[FAI].empty()) {2772          if (M->Parameters[FAI].Required) {2773            Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),2774                  "missing value for required parameter "2775                  "'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");2776            Failure = true;2777          }2778 2779          if (!M->Parameters[FAI].Value.empty())2780            A[FAI] = M->Parameters[FAI].Value;2781        }2782      }2783      return Failure;2784    }2785 2786    parseOptionalToken(AsmToken::Comma);2787  }2788 2789  return TokError("too many positional arguments");2790}2791 2792bool AsmParser::handleMacroEntry(MCAsmMacro *M, SMLoc NameLoc) {2793  // Arbitrarily limit macro nesting depth (default matches 'as'). We can2794  // eliminate this, although we should protect against infinite loops.2795  unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;2796  if (ActiveMacros.size() == MaxNestingDepth) {2797    std::ostringstream MaxNestingDepthError;2798    MaxNestingDepthError << "macros cannot be nested more than "2799                         << MaxNestingDepth << " levels deep."2800                         << " Use -asm-macro-max-nesting-depth to increase "2801                            "this limit.";2802    return TokError(MaxNestingDepthError.str());2803  }2804 2805  MCAsmMacroArguments A;2806  if (parseMacroArguments(M, A))2807    return true;2808 2809  // Macro instantiation is lexical, unfortunately. We construct a new buffer2810  // to hold the macro body with substitutions.2811  SmallString<256> Buf;2812  raw_svector_ostream OS(Buf);2813 2814  if ((!IsDarwin || M->Parameters.size()) && M->Parameters.size() != A.size())2815    return Error(getTok().getLoc(), "Wrong number of arguments");2816  if (expandMacro(OS, *M, M->Parameters, A, true))2817    return true;2818 2819  // We include the .endmacro in the buffer as our cue to exit the macro2820  // instantiation.2821  OS << ".endmacro\n";2822 2823  std::unique_ptr<MemoryBuffer> Instantiation =2824      MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");2825 2826  // Create the macro instantiation object and add to the current macro2827  // instantiation stack.2828  MacroInstantiation *MI = new MacroInstantiation{2829      NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};2830  ActiveMacros.push_back(MI);2831 2832  ++NumOfMacroInstantiations;2833 2834  // Jump to the macro instantiation and prime the lexer.2835  CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());2836  Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());2837  Lex();2838 2839  return false;2840}2841 2842void AsmParser::handleMacroExit() {2843  // Jump to the EndOfStatement we should return to, and consume it.2844  jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer);2845  Lex();2846  // If .endm/.endr is followed by \n instead of a comment, consume it so that2847  // we don't print an excess \n.2848  if (getTok().is(AsmToken::EndOfStatement))2849    Lex();2850 2851  // Pop the instantiation entry.2852  delete ActiveMacros.back();2853  ActiveMacros.pop_back();2854}2855 2856bool AsmParser::parseAssignment(StringRef Name, AssignmentKind Kind) {2857  MCSymbol *Sym;2858  const MCExpr *Value;2859  SMLoc ExprLoc = getTok().getLoc();2860  bool AllowRedef =2861      Kind == AssignmentKind::Set || Kind == AssignmentKind::Equal;2862  if (MCParserUtils::parseAssignmentExpression(Name, AllowRedef, *this, Sym,2863                                               Value))2864    return true;2865 2866  if (!Sym) {2867    // In the case where we parse an expression starting with a '.', we will2868    // not generate an error, nor will we create a symbol.  In this case we2869    // should just return out.2870    return false;2871  }2872 2873  if (discardLTOSymbol(Name))2874    return false;2875 2876  // Do the assignment.2877  switch (Kind) {2878  case AssignmentKind::Equal:2879    Out.emitAssignment(Sym, Value);2880    break;2881  case AssignmentKind::Set:2882  case AssignmentKind::Equiv:2883    Out.emitAssignment(Sym, Value);2884    Out.emitSymbolAttribute(Sym, MCSA_NoDeadStrip);2885    break;2886  case AssignmentKind::LTOSetConditional:2887    if (Value->getKind() != MCExpr::SymbolRef)2888      return Error(ExprLoc, "expected identifier");2889 2890    Out.emitConditionalAssignment(Sym, Value);2891    break;2892  }2893 2894  return false;2895}2896 2897/// parseIdentifier:2898///   ::= identifier2899///   ::= string2900bool AsmParser::parseIdentifier(StringRef &Res) {2901  // The assembler has relaxed rules for accepting identifiers, in particular we2902  // allow things like '.globl $foo' and '.def @feat.00', which would normally be2903  // separate tokens. At this level, we have already lexed so we cannot (currently)2904  // handle this as a context dependent token, instead we detect adjacent tokens2905  // and return the combined identifier.2906  if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {2907    SMLoc PrefixLoc = getLexer().getLoc();2908 2909    // Consume the prefix character, and check for a following identifier.2910 2911    AsmToken Buf[1];2912    Lexer.peekTokens(Buf, false);2913 2914    if (Buf[0].isNot(AsmToken::Identifier) && Buf[0].isNot(AsmToken::Integer))2915      return true;2916 2917    // We have a '$' or '@' followed by an identifier or integer token, make2918    // sure they are adjacent.2919    if (PrefixLoc.getPointer() + 1 != Buf[0].getLoc().getPointer())2920      return true;2921 2922    // eat $ or @2923    Lexer.Lex(); // Lexer's Lex guarantees consecutive token.2924    // Construct the joined identifier and consume the token.2925    Res = StringRef(PrefixLoc.getPointer(), getTok().getString().size() + 1);2926    Lex(); // Parser Lex to maintain invariants.2927    return false;2928  }2929 2930  if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))2931    return true;2932 2933  Res = getTok().getIdentifier();2934 2935  Lex(); // Consume the identifier token.2936 2937  return false;2938}2939 2940/// parseDirectiveSet:2941///   ::= .equ identifier ',' expression2942///   ::= .equiv identifier ',' expression2943///   ::= .set identifier ',' expression2944///   ::= .lto_set_conditional identifier ',' expression2945bool AsmParser::parseDirectiveSet(StringRef IDVal, AssignmentKind Kind) {2946  StringRef Name;2947  if (check(parseIdentifier(Name), "expected identifier") || parseComma() ||2948      parseAssignment(Name, Kind))2949    return true;2950  return false;2951}2952 2953bool AsmParser::parseEscapedString(std::string &Data) {2954  if (check(getTok().isNot(AsmToken::String), "expected string"))2955    return true;2956 2957  Data = "";2958  StringRef Str = getTok().getStringContents();2959  for (unsigned i = 0, e = Str.size(); i != e; ++i) {2960    if (Str[i] != '\\') {2961      if ((Str[i] == '\n') || (Str[i] == '\r')) {2962        // Don't double-warn for Windows newlines.2963        if ((Str[i] == '\n') && (i > 0) && (Str[i - 1] == '\r'))2964          continue;2965 2966        SMLoc NewlineLoc = SMLoc::getFromPointer(Str.data() + i);2967        if (Warning(NewlineLoc, "unterminated string; newline inserted"))2968          return true;2969      }2970      Data += Str[i];2971      continue;2972    }2973 2974    // Recognize escaped characters. Note that this escape semantics currently2975    // loosely follows Darwin 'as'.2976    ++i;2977    if (i == e)2978      return TokError("unexpected backslash at end of string");2979 2980    // Recognize hex sequences similarly to GNU 'as'.2981    if (Str[i] == 'x' || Str[i] == 'X') {2982      size_t length = Str.size();2983      if (i + 1 >= length || !isHexDigit(Str[i + 1]))2984        return TokError("invalid hexadecimal escape sequence");2985 2986      // Consume hex characters. GNU 'as' reads all hexadecimal characters and2987      // then truncates to the lower 16 bits. Seems reasonable.2988      unsigned Value = 0;2989      while (i + 1 < length && isHexDigit(Str[i + 1]))2990        Value = Value * 16 + hexDigitValue(Str[++i]);2991 2992      Data += (unsigned char)(Value & 0xFF);2993      continue;2994    }2995 2996    // Recognize octal sequences.2997    if ((unsigned)(Str[i] - '0') <= 7) {2998      // Consume up to three octal characters.2999      unsigned Value = Str[i] - '0';3000 3001      if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {3002        ++i;3003        Value = Value * 8 + (Str[i] - '0');3004 3005        if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) {3006          ++i;3007          Value = Value * 8 + (Str[i] - '0');3008        }3009      }3010 3011      if (Value > 255)3012        return TokError("invalid octal escape sequence (out of range)");3013 3014      Data += (unsigned char)Value;3015      continue;3016    }3017 3018    // Otherwise recognize individual escapes.3019    switch (Str[i]) {3020    default:3021      // Just reject invalid escape sequences for now.3022      return TokError("invalid escape sequence (unrecognized character)");3023 3024    case 'b': Data += '\b'; break;3025    case 'f': Data += '\f'; break;3026    case 'n': Data += '\n'; break;3027    case 'r': Data += '\r'; break;3028    case 't': Data += '\t'; break;3029    case '"': Data += '"'; break;3030    case '\\': Data += '\\'; break;3031    }3032  }3033 3034  Lex();3035  return false;3036}3037 3038bool AsmParser::parseAngleBracketString(std::string &Data) {3039  SMLoc EndLoc, StartLoc = getTok().getLoc();3040  if (isAngleBracketString(StartLoc, EndLoc)) {3041    const char *StartChar = StartLoc.getPointer() + 1;3042    const char *EndChar = EndLoc.getPointer() - 1;3043    jumpToLoc(EndLoc, CurBuffer);3044    /// Eat from '<' to '>'3045    Lex();3046 3047    Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));3048    return false;3049  }3050  return true;3051}3052 3053/// parseDirectiveAscii:3054//    ::= .ascii [ "string"+ ( , "string"+ )* ]3055///   ::= ( .asciz | .string ) [ "string" ( , "string" )* ]3056bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {3057  auto parseOp = [&]() -> bool {3058    std::string Data;3059    if (checkForValidSection())3060      return true;3061    // Only support spaces as separators for .ascii directive for now. See the3062    // discusssion at https://reviews.llvm.org/D91460 for more details.3063    do {3064      if (parseEscapedString(Data))3065        return true;3066      getStreamer().emitBytes(Data);3067    } while (!ZeroTerminated && getTok().is(AsmToken::String));3068    if (ZeroTerminated)3069      getStreamer().emitBytes(StringRef("\0", 1));3070    return false;3071  };3072 3073  return parseMany(parseOp);3074}3075 3076/// parseDirectiveBase64:3077//    ::= .base64 "string" (, "string" )*3078bool AsmParser::parseDirectiveBase64() {3079  auto parseOp = [&]() -> bool {3080    if (checkForValidSection())3081      return true;3082 3083    if (getTok().isNot(AsmToken::String)) {3084      return true;3085    }3086 3087    std::vector<char> Decoded;3088    std::string const str = getTok().getStringContents().str();3089    if (check(str.empty(), "expected nonempty string")) {3090      return true;3091    }3092 3093    llvm::Error e = decodeBase64(str, Decoded);3094    if (e) {3095      consumeError(std::move(e));3096      return Error(Lexer.getLoc(), "failed to base64 decode string data");3097    }3098 3099    getStreamer().emitBytes(std::string(Decoded.begin(), Decoded.end()));3100    Lex();3101    return false;3102  };3103 3104  return check(parseMany(parseOp), "expected string");3105}3106 3107/// parseDirectiveReloc3108///  ::= .reloc expression , identifier [ , expression ]3109bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {3110  const MCExpr *Offset;3111  const MCExpr *Expr = nullptr;3112 3113  if (parseExpression(Offset))3114    return true;3115  if (parseComma() ||3116      check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))3117    return true;3118 3119  SMLoc NameLoc = Lexer.getTok().getLoc();3120  StringRef Name = Lexer.getTok().getIdentifier();3121  Lex();3122 3123  if (Lexer.is(AsmToken::Comma)) {3124    Lex();3125    SMLoc ExprLoc = Lexer.getLoc();3126    if (parseExpression(Expr))3127      return true;3128 3129    MCValue Value;3130    if (!Expr->evaluateAsRelocatable(Value, nullptr))3131      return Error(ExprLoc, "expression must be relocatable");3132  }3133 3134  if (parseEOL())3135    return true;3136 3137  getStreamer().emitRelocDirective(*Offset, Name, Expr, NameLoc);3138  return false;3139}3140 3141/// parseDirectiveValue3142///  ::= (.byte | .short | ... ) [ expression (, expression)* ]3143bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {3144  auto parseOp = [&]() -> bool {3145    const MCExpr *Value;3146    SMLoc ExprLoc = getLexer().getLoc();3147    if (checkForValidSection() || getTargetParser().parseDataExpr(Value))3148      return true;3149    // Special case constant expressions to match code generator.3150    if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {3151      assert(Size <= 8 && "Invalid size");3152      uint64_t IntValue = MCE->getValue();3153      if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))3154        return Error(ExprLoc, "out of range literal value");3155      getStreamer().emitIntValue(IntValue, Size);3156    } else3157      getStreamer().emitValue(Value, Size, ExprLoc);3158    return false;3159  };3160 3161  return parseMany(parseOp);3162}3163 3164static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) {3165  if (Asm.getTok().isNot(AsmToken::Integer) &&3166      Asm.getTok().isNot(AsmToken::BigNum))3167    return Asm.TokError("unknown token in expression");3168  SMLoc ExprLoc = Asm.getTok().getLoc();3169  APInt IntValue = Asm.getTok().getAPIntVal();3170  Asm.Lex();3171  if (!IntValue.isIntN(128))3172    return Asm.Error(ExprLoc, "out of range literal value");3173  if (!IntValue.isIntN(64)) {3174    hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();3175    lo = IntValue.getLoBits(64).getZExtValue();3176  } else {3177    hi = 0;3178    lo = IntValue.getZExtValue();3179  }3180  return false;3181}3182 3183/// ParseDirectiveOctaValue3184///  ::= .octa [ hexconstant (, hexconstant)* ]3185 3186bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {3187  auto parseOp = [&]() -> bool {3188    if (checkForValidSection())3189      return true;3190    uint64_t hi, lo;3191    if (parseHexOcta(*this, hi, lo))3192      return true;3193    if (MAI.isLittleEndian()) {3194      getStreamer().emitInt64(lo);3195      getStreamer().emitInt64(hi);3196    } else {3197      getStreamer().emitInt64(hi);3198      getStreamer().emitInt64(lo);3199    }3200    return false;3201  };3202 3203  return parseMany(parseOp);3204}3205 3206bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {3207  // We don't truly support arithmetic on floating point expressions, so we3208  // have to manually parse unary prefixes.3209  bool IsNeg = false;3210  if (getLexer().is(AsmToken::Minus)) {3211    Lexer.Lex();3212    IsNeg = true;3213  } else if (getLexer().is(AsmToken::Plus))3214    Lexer.Lex();3215 3216  if (Lexer.is(AsmToken::Error))3217    return TokError(Lexer.getErr());3218  if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&3219      Lexer.isNot(AsmToken::Identifier))3220    return TokError("unexpected token in directive");3221 3222  // Convert to an APFloat.3223  APFloat Value(Semantics);3224  StringRef IDVal = getTok().getString();3225  if (getLexer().is(AsmToken::Identifier)) {3226    if (!IDVal.compare_insensitive("infinity") ||3227        !IDVal.compare_insensitive("inf"))3228      Value = APFloat::getInf(Semantics);3229    else if (!IDVal.compare_insensitive("nan"))3230      Value = APFloat::getNaN(Semantics, false, ~0);3231    else3232      return TokError("invalid floating point literal");3233  } else if (errorToBool(3234                 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)3235                     .takeError()))3236    return TokError("invalid floating point literal");3237  if (IsNeg)3238    Value.changeSign();3239 3240  // Consume the numeric token.3241  Lex();3242 3243  Res = Value.bitcastToAPInt();3244 3245  return false;3246}3247 3248/// parseDirectiveRealValue3249///  ::= (.single | .double) [ expression (, expression)* ]3250bool AsmParser::parseDirectiveRealValue(StringRef IDVal,3251                                        const fltSemantics &Semantics) {3252  auto parseOp = [&]() -> bool {3253    APInt AsInt;3254    if (checkForValidSection() || parseRealValue(Semantics, AsInt))3255      return true;3256    getStreamer().emitIntValue(AsInt.getLimitedValue(),3257                               AsInt.getBitWidth() / 8);3258    return false;3259  };3260 3261  return parseMany(parseOp);3262}3263 3264/// parseDirectiveZero3265///  ::= .zero expression3266bool AsmParser::parseDirectiveZero() {3267  SMLoc NumBytesLoc = Lexer.getLoc();3268  const MCExpr *NumBytes;3269  if (checkForValidSection() || parseExpression(NumBytes))3270    return true;3271 3272  int64_t Val = 0;3273  if (getLexer().is(AsmToken::Comma)) {3274    Lex();3275    if (parseAbsoluteExpression(Val))3276      return true;3277  }3278 3279  if (parseEOL())3280    return true;3281  getStreamer().emitFill(*NumBytes, Val, NumBytesLoc);3282 3283  return false;3284}3285 3286/// parseDirectiveFill3287///  ::= .fill expression [ , expression [ , expression ] ]3288bool AsmParser::parseDirectiveFill() {3289  SMLoc NumValuesLoc = Lexer.getLoc();3290  const MCExpr *NumValues;3291  if (checkForValidSection() || parseExpression(NumValues))3292    return true;3293 3294  int64_t FillSize = 1;3295  int64_t FillExpr = 0;3296 3297  SMLoc SizeLoc, ExprLoc;3298 3299  if (parseOptionalToken(AsmToken::Comma)) {3300    SizeLoc = getTok().getLoc();3301    if (parseAbsoluteExpression(FillSize))3302      return true;3303    if (parseOptionalToken(AsmToken::Comma)) {3304      ExprLoc = getTok().getLoc();3305      if (parseAbsoluteExpression(FillExpr))3306        return true;3307    }3308  }3309  if (parseEOL())3310    return true;3311 3312  if (FillSize < 0) {3313    Warning(SizeLoc, "'.fill' directive with negative size has no effect");3314    return false;3315  }3316  if (FillSize > 8) {3317    Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8");3318    FillSize = 8;3319  }3320 3321  if (!isUInt<32>(FillExpr) && FillSize > 4)3322    Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits");3323 3324  getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc);3325 3326  return false;3327}3328 3329/// parseDirectiveOrg3330///  ::= .org expression [ , expression ]3331bool AsmParser::parseDirectiveOrg() {3332  const MCExpr *Offset;3333  SMLoc OffsetLoc = Lexer.getLoc();3334  if (checkForValidSection() || parseExpression(Offset))3335    return true;3336 3337  // Parse optional fill expression.3338  int64_t FillExpr = 0;3339  if (parseOptionalToken(AsmToken::Comma))3340    if (parseAbsoluteExpression(FillExpr))3341      return true;3342  if (parseEOL())3343    return true;3344 3345  getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);3346  return false;3347}3348 3349/// parseDirectiveAlign3350///  ::= {.align, ...} expression [ , expression [ , expression ]]3351bool AsmParser::parseDirectiveAlign(bool IsPow2, uint8_t ValueSize) {3352  SMLoc AlignmentLoc = getLexer().getLoc();3353  int64_t Alignment;3354  SMLoc MaxBytesLoc;3355  bool HasFillExpr = false;3356  int64_t FillExpr = 0;3357  int64_t MaxBytesToFill = 0;3358  SMLoc FillExprLoc;3359 3360  auto parseAlign = [&]() -> bool {3361    if (parseAbsoluteExpression(Alignment))3362      return true;3363    if (parseOptionalToken(AsmToken::Comma)) {3364      // The fill expression can be omitted while specifying a maximum number of3365      // alignment bytes, e.g:3366      //  .align 3,,43367      if (getTok().isNot(AsmToken::Comma)) {3368        HasFillExpr = true;3369        if (parseTokenLoc(FillExprLoc) || parseAbsoluteExpression(FillExpr))3370          return true;3371      }3372      if (parseOptionalToken(AsmToken::Comma))3373        if (parseTokenLoc(MaxBytesLoc) ||3374            parseAbsoluteExpression(MaxBytesToFill))3375          return true;3376    }3377    return parseEOL();3378  };3379 3380  if (checkForValidSection())3381    return true;3382  // Ignore empty '.p2align' directives for GNU-as compatibility3383  if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) {3384    Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored");3385    return parseEOL();3386  }3387  if (parseAlign())3388    return true;3389 3390  // Always emit an alignment here even if we thrown an error.3391  bool ReturnVal = false;3392 3393  // Compute alignment in bytes.3394  if (IsPow2) {3395    // FIXME: Diagnose overflow.3396    if (Alignment >= 32) {3397      ReturnVal |= Error(AlignmentLoc, "invalid alignment value");3398      Alignment = 31;3399    }3400 3401    Alignment = 1ULL << Alignment;3402  } else {3403    // Reject alignments that aren't either a power of two or zero,3404    // for gas compatibility. Alignment of zero is silently rounded3405    // up to one.3406    if (Alignment == 0)3407      Alignment = 1;3408    else if (!isPowerOf2_64(Alignment)) {3409      ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");3410      Alignment = llvm::bit_floor<uint64_t>(Alignment);3411    }3412    if (!isUInt<32>(Alignment)) {3413      ReturnVal |= Error(AlignmentLoc, "alignment must be smaller than 2**32");3414      Alignment = 1u << 31;3415    }3416  }3417 3418  // Diagnose non-sensical max bytes to align.3419  if (MaxBytesLoc.isValid()) {3420    if (MaxBytesToFill < 1) {3421      ReturnVal |= Error(MaxBytesLoc,3422                         "alignment directive can never be satisfied in this "3423                         "many bytes, ignoring maximum bytes expression");3424      MaxBytesToFill = 0;3425    }3426 3427    if (MaxBytesToFill >= Alignment) {3428      Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "3429                           "has no effect");3430      MaxBytesToFill = 0;3431    }3432  }3433 3434  const MCSection *Section = getStreamer().getCurrentSectionOnly();3435  assert(Section && "must have section to emit alignment");3436 3437  if (HasFillExpr && FillExpr != 0 && Section->isBssSection()) {3438    ReturnVal |=3439        Warning(FillExprLoc, "ignoring non-zero fill value in BSS section '" +3440                                 Section->getName() + "'");3441    FillExpr = 0;3442  }3443 3444  // Check whether we should use optimal code alignment for this .align3445  // directive.3446  if (MAI.useCodeAlign(*Section) && !HasFillExpr) {3447    getStreamer().emitCodeAlignment(3448        Align(Alignment), &getTargetParser().getSTI(), MaxBytesToFill);3449  } else {3450    // FIXME: Target specific behavior about how the "extra" bytes are filled.3451    getStreamer().emitValueToAlignment(Align(Alignment), FillExpr, ValueSize,3452                                       MaxBytesToFill);3453  }3454 3455  return ReturnVal;3456}3457 3458/// parseDirectiveFile3459/// ::= .file filename3460/// ::= .file number [directory] filename [md5 checksum] [source source-text]3461bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {3462  // FIXME: I'm not sure what this is.3463  int64_t FileNumber = -1;3464  if (getLexer().is(AsmToken::Integer)) {3465    FileNumber = getTok().getIntVal();3466    Lex();3467 3468    if (FileNumber < 0)3469      return TokError("negative file number");3470  }3471 3472  std::string Path;3473 3474  // Usually the directory and filename together, otherwise just the directory.3475  // Allow the strings to have escaped octal character sequence.3476  if (parseEscapedString(Path))3477    return true;3478 3479  StringRef Directory;3480  StringRef Filename;3481  std::string FilenameData;3482  if (getLexer().is(AsmToken::String)) {3483    if (check(FileNumber == -1,3484              "explicit path specified, but no file number") ||3485        parseEscapedString(FilenameData))3486      return true;3487    Filename = FilenameData;3488    Directory = Path;3489  } else {3490    Filename = Path;3491  }3492 3493  uint64_t MD5Hi, MD5Lo;3494  bool HasMD5 = false;3495 3496  std::optional<StringRef> Source;3497  bool HasSource = false;3498  std::string SourceString;3499 3500  while (!parseOptionalToken(AsmToken::EndOfStatement)) {3501    StringRef Keyword;3502    if (check(getTok().isNot(AsmToken::Identifier),3503              "unexpected token in '.file' directive") ||3504        parseIdentifier(Keyword))3505      return true;3506    if (Keyword == "md5") {3507      HasMD5 = true;3508      if (check(FileNumber == -1,3509                "MD5 checksum specified, but no file number") ||3510          parseHexOcta(*this, MD5Hi, MD5Lo))3511        return true;3512    } else if (Keyword == "source") {3513      HasSource = true;3514      if (check(FileNumber == -1,3515                "source specified, but no file number") ||3516          check(getTok().isNot(AsmToken::String),3517                "unexpected token in '.file' directive") ||3518          parseEscapedString(SourceString))3519        return true;3520    } else {3521      return TokError("unexpected token in '.file' directive");3522    }3523  }3524 3525  if (FileNumber == -1) {3526    // Ignore the directive if there is no number and the target doesn't support3527    // numberless .file directives. This allows some portability of assembler3528    // between different object file formats.3529    if (getContext().getAsmInfo()->hasSingleParameterDotFile())3530      getStreamer().emitFileDirective(Filename);3531  } else {3532    // In case there is a -g option as well as debug info from directive .file,3533    // we turn off the -g option, directly use the existing debug info instead.3534    // Throw away any implicit file table for the assembler source.3535    if (Ctx.getGenDwarfForAssembly()) {3536      Ctx.getMCDwarfLineTable(0).resetFileTable();3537      Ctx.setGenDwarfForAssembly(false);3538    }3539 3540    std::optional<MD5::MD5Result> CKMem;3541    if (HasMD5) {3542      MD5::MD5Result Sum;3543      for (unsigned i = 0; i != 8; ++i) {3544        Sum[i] = uint8_t(MD5Hi >> ((7 - i) * 8));3545        Sum[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));3546      }3547      CKMem = Sum;3548    }3549    if (HasSource) {3550      char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));3551      memcpy(SourceBuf, SourceString.data(), SourceString.size());3552      Source = StringRef(SourceBuf, SourceString.size());3553    }3554    if (FileNumber == 0) {3555      // Upgrade to Version 5 for assembly actions like clang -c a.s.3556      if (Ctx.getDwarfVersion() < 5)3557        Ctx.setDwarfVersion(5);3558      getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);3559    } else {3560      Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(3561          FileNumber, Directory, Filename, CKMem, Source);3562      if (!FileNumOrErr)3563        return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));3564    }3565    // Alert the user if there are some .file directives with MD5 and some not.3566    // But only do that once.3567    if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {3568      ReportedInconsistentMD5 = true;3569      return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");3570    }3571  }3572 3573  return false;3574}3575 3576/// parseDirectiveLine3577/// ::= .line [number]3578bool AsmParser::parseDirectiveLine() {3579  parseOptionalToken(AsmToken::Integer);3580  return parseEOL();3581}3582 3583/// parseDirectiveLoc3584/// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]3585///                                [epilogue_begin] [is_stmt VALUE] [isa VALUE]3586/// The first number is a file number, must have been previously assigned with3587/// a .file directive, the second number is the line number and optionally the3588/// third number is a column position (zero if not specified).  The remaining3589/// optional items are .loc sub-directives.3590bool AsmParser::parseDirectiveLoc() {3591  int64_t FileNumber = 0, LineNumber = 0;3592  SMLoc Loc = getTok().getLoc();3593  if (parseIntToken(FileNumber) ||3594      check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,3595            "file number less than one in '.loc' directive") ||3596      check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,3597            "unassigned file number in '.loc' directive"))3598    return true;3599 3600  // optional3601  if (getLexer().is(AsmToken::Integer)) {3602    LineNumber = getTok().getIntVal();3603    if (LineNumber < 0)3604      return TokError("line number less than zero in '.loc' directive");3605    Lex();3606  }3607 3608  int64_t ColumnPos = 0;3609  if (getLexer().is(AsmToken::Integer)) {3610    ColumnPos = getTok().getIntVal();3611    if (ColumnPos < 0)3612      return TokError("column position less than zero in '.loc' directive");3613    Lex();3614  }3615 3616  auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();3617  unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;3618  unsigned Isa = 0;3619  int64_t Discriminator = 0;3620 3621  auto parseLocOp = [&]() -> bool {3622    StringRef Name;3623    SMLoc Loc = getTok().getLoc();3624    if (parseIdentifier(Name))3625      return TokError("unexpected token in '.loc' directive");3626 3627    if (Name == "basic_block")3628      Flags |= DWARF2_FLAG_BASIC_BLOCK;3629    else if (Name == "prologue_end")3630      Flags |= DWARF2_FLAG_PROLOGUE_END;3631    else if (Name == "epilogue_begin")3632      Flags |= DWARF2_FLAG_EPILOGUE_BEGIN;3633    else if (Name == "is_stmt") {3634      Loc = getTok().getLoc();3635      const MCExpr *Value;3636      if (parseExpression(Value))3637        return true;3638      // The expression must be the constant 0 or 1.3639      if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {3640        int Value = MCE->getValue();3641        if (Value == 0)3642          Flags &= ~DWARF2_FLAG_IS_STMT;3643        else if (Value == 1)3644          Flags |= DWARF2_FLAG_IS_STMT;3645        else3646          return Error(Loc, "is_stmt value not 0 or 1");3647      } else {3648        return Error(Loc, "is_stmt value not the constant value of 0 or 1");3649      }3650    } else if (Name == "isa") {3651      Loc = getTok().getLoc();3652      const MCExpr *Value;3653      if (parseExpression(Value))3654        return true;3655      // The expression must be a constant greater or equal to 0.3656      if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {3657        int Value = MCE->getValue();3658        if (Value < 0)3659          return Error(Loc, "isa number less than zero");3660        Isa = Value;3661      } else {3662        return Error(Loc, "isa number not a constant value");3663      }3664    } else if (Name == "discriminator") {3665      if (parseAbsoluteExpression(Discriminator))3666        return true;3667    } else {3668      return Error(Loc, "unknown sub-directive in '.loc' directive");3669    }3670    return false;3671  };3672 3673  if (parseMany(parseLocOp, false /*hasComma*/))3674    return true;3675 3676  getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,3677                                      Isa, Discriminator, StringRef());3678 3679  return false;3680}3681 3682/// parseDirectiveLoc3683/// ::= .loc_label label3684bool AsmParser::parseDirectiveLocLabel(SMLoc DirectiveLoc) {3685  StringRef Name;3686  DirectiveLoc = Lexer.getLoc();3687  if (parseIdentifier(Name))3688    return TokError("expected identifier");3689  if (parseEOL())3690    return true;3691  getStreamer().emitDwarfLocLabelDirective(DirectiveLoc, Name);3692  return false;3693}3694 3695/// parseDirectiveStabs3696/// ::= .stabs string, number, number, number3697bool AsmParser::parseDirectiveStabs() {3698  return TokError("unsupported directive '.stabs'");3699}3700 3701/// parseDirectiveCVFile3702/// ::= .cv_file number filename [checksum] [checksumkind]3703bool AsmParser::parseDirectiveCVFile() {3704  SMLoc FileNumberLoc = getTok().getLoc();3705  int64_t FileNumber;3706  std::string Filename;3707  std::string Checksum;3708  int64_t ChecksumKind = 0;3709 3710  if (parseIntToken(FileNumber, "expected file number") ||3711      check(FileNumber < 1, FileNumberLoc, "file number less than one") ||3712      check(getTok().isNot(AsmToken::String),3713            "unexpected token in '.cv_file' directive") ||3714      parseEscapedString(Filename))3715    return true;3716  if (!parseOptionalToken(AsmToken::EndOfStatement)) {3717    if (check(getTok().isNot(AsmToken::String),3718              "unexpected token in '.cv_file' directive") ||3719        parseEscapedString(Checksum) ||3720        parseIntToken(ChecksumKind,3721                      "expected checksum kind in '.cv_file' directive") ||3722        parseEOL())3723      return true;3724  }3725 3726  Checksum = fromHex(Checksum);3727  void *CKMem = Ctx.allocate(Checksum.size(), 1);3728  memcpy(CKMem, Checksum.data(), Checksum.size());3729  ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),3730                                    Checksum.size());3731 3732  if (!getStreamer().emitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,3733                                         static_cast<uint8_t>(ChecksumKind)))3734    return Error(FileNumberLoc, "file number already allocated");3735 3736  return false;3737}3738 3739bool AsmParser::parseCVFunctionId(int64_t &FunctionId,3740                                  StringRef DirectiveName) {3741  SMLoc Loc;3742  return parseTokenLoc(Loc) ||3743         parseIntToken(FunctionId, "expected function id") ||3744         check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,3745               "expected function id within range [0, UINT_MAX)");3746}3747 3748bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {3749  SMLoc Loc;3750  return parseTokenLoc(Loc) ||3751         parseIntToken(FileNumber, "expected file number") ||3752         check(FileNumber < 1, Loc,3753               "file number less than one in '" + DirectiveName +3754                   "' directive") ||3755         check(!getCVContext().isValidFileNumber(FileNumber), Loc,3756               "unassigned file number in '" + DirectiveName + "' directive");3757}3758 3759/// parseDirectiveCVFuncId3760/// ::= .cv_func_id FunctionId3761///3762/// Introduces a function ID that can be used with .cv_loc.3763bool AsmParser::parseDirectiveCVFuncId() {3764  SMLoc FunctionIdLoc = getTok().getLoc();3765  int64_t FunctionId;3766 3767  if (parseCVFunctionId(FunctionId, ".cv_func_id") || parseEOL())3768    return true;3769 3770  if (!getStreamer().emitCVFuncIdDirective(FunctionId))3771    return Error(FunctionIdLoc, "function id already allocated");3772 3773  return false;3774}3775 3776/// parseDirectiveCVInlineSiteId3777/// ::= .cv_inline_site_id FunctionId3778///         "within" IAFunc3779///         "inlined_at" IAFile IALine [IACol]3780///3781/// Introduces a function ID that can be used with .cv_loc. Includes "inlined3782/// at" source location information for use in the line table of the caller,3783/// whether the caller is a real function or another inlined call site.3784bool AsmParser::parseDirectiveCVInlineSiteId() {3785  SMLoc FunctionIdLoc = getTok().getLoc();3786  int64_t FunctionId;3787  int64_t IAFunc;3788  int64_t IAFile;3789  int64_t IALine;3790  int64_t IACol = 0;3791 3792  // FunctionId3793  if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))3794    return true;3795 3796  // "within"3797  if (check((getLexer().isNot(AsmToken::Identifier) ||3798             getTok().getIdentifier() != "within"),3799            "expected 'within' identifier in '.cv_inline_site_id' directive"))3800    return true;3801  Lex();3802 3803  // IAFunc3804  if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))3805    return true;3806 3807  // "inlined_at"3808  if (check((getLexer().isNot(AsmToken::Identifier) ||3809             getTok().getIdentifier() != "inlined_at"),3810            "expected 'inlined_at' identifier in '.cv_inline_site_id' "3811            "directive") )3812    return true;3813  Lex();3814 3815  // IAFile IALine3816  if (parseCVFileId(IAFile, ".cv_inline_site_id") ||3817      parseIntToken(IALine, "expected line number after 'inlined_at'"))3818    return true;3819 3820  // [IACol]3821  if (getLexer().is(AsmToken::Integer)) {3822    IACol = getTok().getIntVal();3823    Lex();3824  }3825 3826  if (parseEOL())3827    return true;3828 3829  if (!getStreamer().emitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,3830                                                 IALine, IACol, FunctionIdLoc))3831    return Error(FunctionIdLoc, "function id already allocated");3832 3833  return false;3834}3835 3836/// parseDirectiveCVLoc3837/// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]3838///                                [is_stmt VALUE]3839/// The first number is a file number, must have been previously assigned with3840/// a .file directive, the second number is the line number and optionally the3841/// third number is a column position (zero if not specified).  The remaining3842/// optional items are .loc sub-directives.3843bool AsmParser::parseDirectiveCVLoc() {3844  SMLoc DirectiveLoc = getTok().getLoc();3845  int64_t FunctionId, FileNumber;3846  if (parseCVFunctionId(FunctionId, ".cv_loc") ||3847      parseCVFileId(FileNumber, ".cv_loc"))3848    return true;3849 3850  int64_t LineNumber = 0;3851  if (getLexer().is(AsmToken::Integer)) {3852    LineNumber = getTok().getIntVal();3853    if (LineNumber < 0)3854      return TokError("line number less than zero in '.cv_loc' directive");3855    Lex();3856  }3857 3858  int64_t ColumnPos = 0;3859  if (getLexer().is(AsmToken::Integer)) {3860    ColumnPos = getTok().getIntVal();3861    if (ColumnPos < 0)3862      return TokError("column position less than zero in '.cv_loc' directive");3863    Lex();3864  }3865 3866  bool PrologueEnd = false;3867  uint64_t IsStmt = 0;3868 3869  auto parseOp = [&]() -> bool {3870    StringRef Name;3871    SMLoc Loc = getTok().getLoc();3872    if (parseIdentifier(Name))3873      return TokError("unexpected token in '.cv_loc' directive");3874    if (Name == "prologue_end")3875      PrologueEnd = true;3876    else if (Name == "is_stmt") {3877      Loc = getTok().getLoc();3878      const MCExpr *Value;3879      if (parseExpression(Value))3880        return true;3881      // The expression must be the constant 0 or 1.3882      IsStmt = ~0ULL;3883      if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))3884        IsStmt = MCE->getValue();3885 3886      if (IsStmt > 1)3887        return Error(Loc, "is_stmt value not 0 or 1");3888    } else {3889      return Error(Loc, "unknown sub-directive in '.cv_loc' directive");3890    }3891    return false;3892  };3893 3894  if (parseMany(parseOp, false /*hasComma*/))3895    return true;3896 3897  getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,3898                                   ColumnPos, PrologueEnd, IsStmt, StringRef(),3899                                   DirectiveLoc);3900  return false;3901}3902 3903/// parseDirectiveCVLinetable3904/// ::= .cv_linetable FunctionId, FnStart, FnEnd3905bool AsmParser::parseDirectiveCVLinetable() {3906  int64_t FunctionId;3907  MCSymbol *FnStartSym, *FnEndSym;3908  SMLoc Loc = getTok().getLoc();3909  if (parseCVFunctionId(FunctionId, ".cv_linetable") || parseComma() ||3910      parseTokenLoc(Loc) ||3911      check(parseSymbol(FnStartSym), Loc, "expected identifier in directive") ||3912      parseComma() || parseTokenLoc(Loc) ||3913      check(parseSymbol(FnEndSym), Loc, "expected identifier in directive"))3914    return true;3915 3916  getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);3917  return false;3918}3919 3920/// parseDirectiveCVInlineLinetable3921/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd3922bool AsmParser::parseDirectiveCVInlineLinetable() {3923  int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;3924  MCSymbol *FnStartSym, *FnEndSym;3925  SMLoc Loc = getTok().getLoc();3926  if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||3927      parseTokenLoc(Loc) ||3928      parseIntToken(SourceFileId, "expected SourceField") ||3929      check(SourceFileId <= 0, Loc, "File id less than zero") ||3930      parseTokenLoc(Loc) ||3931      parseIntToken(SourceLineNum, "expected SourceLineNum") ||3932      check(SourceLineNum < 0, Loc, "Line number less than zero") ||3933      parseTokenLoc(Loc) ||3934      check(parseSymbol(FnStartSym), Loc, "expected identifier") ||3935      parseTokenLoc(Loc) ||3936      check(parseSymbol(FnEndSym), Loc, "expected identifier"))3937    return true;3938 3939  if (parseEOL())3940    return true;3941 3942  getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,3943                                               SourceLineNum, FnStartSym,3944                                               FnEndSym);3945  return false;3946}3947 3948void AsmParser::initializeCVDefRangeTypeMap() {3949  CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;3950  CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;3951  CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;3952  CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;3953}3954 3955/// parseDirectiveCVDefRange3956/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*3957bool AsmParser::parseDirectiveCVDefRange() {3958  SMLoc Loc;3959  std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;3960  while (getLexer().is(AsmToken::Identifier)) {3961    Loc = getLexer().getLoc();3962    MCSymbol *GapStartSym;3963    if (parseSymbol(GapStartSym))3964      return Error(Loc, "expected identifier in directive");3965 3966    Loc = getLexer().getLoc();3967    MCSymbol *GapEndSym;3968    if (parseSymbol(GapEndSym))3969      return Error(Loc, "expected identifier in directive");3970 3971    Ranges.push_back({GapStartSym, GapEndSym});3972  }3973 3974  StringRef CVDefRangeTypeStr;3975  if (parseToken(3976          AsmToken::Comma,3977          "expected comma before def_range type in .cv_def_range directive") ||3978      parseIdentifier(CVDefRangeTypeStr))3979    return Error(Loc, "expected def_range type in directive");3980 3981  StringMap<CVDefRangeType>::const_iterator CVTypeIt =3982      CVDefRangeTypeMap.find(CVDefRangeTypeStr);3983  CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())3984                                ? CVDR_DEFRANGE3985                                : CVTypeIt->getValue();3986  switch (CVDRType) {3987  case CVDR_DEFRANGE_REGISTER: {3988    int64_t DRRegister;3989    if (parseToken(AsmToken::Comma, "expected comma before register number in "3990                                    ".cv_def_range directive") ||3991        parseAbsoluteExpression(DRRegister))3992      return Error(Loc, "expected register number");3993 3994    codeview::DefRangeRegisterHeader DRHdr;3995    DRHdr.Register = DRRegister;3996    DRHdr.MayHaveNoName = 0;3997    getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);3998    break;3999  }4000  case CVDR_DEFRANGE_FRAMEPOINTER_REL: {4001    int64_t DROffset;4002    if (parseToken(AsmToken::Comma,4003                   "expected comma before offset in .cv_def_range directive") ||4004        parseAbsoluteExpression(DROffset))4005      return Error(Loc, "expected offset value");4006 4007    codeview::DefRangeFramePointerRelHeader DRHdr;4008    DRHdr.Offset = DROffset;4009    getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);4010    break;4011  }4012  case CVDR_DEFRANGE_SUBFIELD_REGISTER: {4013    int64_t DRRegister;4014    int64_t DROffsetInParent;4015    if (parseToken(AsmToken::Comma, "expected comma before register number in "4016                                    ".cv_def_range directive") ||4017        parseAbsoluteExpression(DRRegister))4018      return Error(Loc, "expected register number");4019    if (parseToken(AsmToken::Comma,4020                   "expected comma before offset in .cv_def_range directive") ||4021        parseAbsoluteExpression(DROffsetInParent))4022      return Error(Loc, "expected offset value");4023 4024    codeview::DefRangeSubfieldRegisterHeader DRHdr;4025    DRHdr.Register = DRRegister;4026    DRHdr.MayHaveNoName = 0;4027    DRHdr.OffsetInParent = DROffsetInParent;4028    getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);4029    break;4030  }4031  case CVDR_DEFRANGE_REGISTER_REL: {4032    int64_t DRRegister;4033    int64_t DRFlags;4034    int64_t DRBasePointerOffset;4035    if (parseToken(AsmToken::Comma, "expected comma before register number in "4036                                    ".cv_def_range directive") ||4037        parseAbsoluteExpression(DRRegister))4038      return Error(Loc, "expected register value");4039    if (parseToken(4040            AsmToken::Comma,4041            "expected comma before flag value in .cv_def_range directive") ||4042        parseAbsoluteExpression(DRFlags))4043      return Error(Loc, "expected flag value");4044    if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "4045                                    "in .cv_def_range directive") ||4046        parseAbsoluteExpression(DRBasePointerOffset))4047      return Error(Loc, "expected base pointer offset value");4048 4049    codeview::DefRangeRegisterRelHeader DRHdr;4050    DRHdr.Register = DRRegister;4051    DRHdr.Flags = DRFlags;4052    DRHdr.BasePointerOffset = DRBasePointerOffset;4053    getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);4054    break;4055  }4056  default:4057    return Error(Loc, "unexpected def_range type in .cv_def_range directive");4058  }4059  return true;4060}4061 4062/// parseDirectiveCVString4063/// ::= .cv_stringtable "string"4064bool AsmParser::parseDirectiveCVString() {4065  std::string Data;4066  if (checkForValidSection() || parseEscapedString(Data))4067    return true;4068 4069  // Put the string in the table and emit the offset.4070  std::pair<StringRef, unsigned> Insertion =4071      getCVContext().addToStringTable(Data);4072  getStreamer().emitInt32(Insertion.second);4073  return false;4074}4075 4076/// parseDirectiveCVStringTable4077/// ::= .cv_stringtable4078bool AsmParser::parseDirectiveCVStringTable() {4079  getStreamer().emitCVStringTableDirective();4080  return false;4081}4082 4083/// parseDirectiveCVFileChecksums4084/// ::= .cv_filechecksums4085bool AsmParser::parseDirectiveCVFileChecksums() {4086  getStreamer().emitCVFileChecksumsDirective();4087  return false;4088}4089 4090/// parseDirectiveCVFileChecksumOffset4091/// ::= .cv_filechecksumoffset fileno4092bool AsmParser::parseDirectiveCVFileChecksumOffset() {4093  int64_t FileNo;4094  if (parseIntToken(FileNo))4095    return true;4096  if (parseEOL())4097    return true;4098  getStreamer().emitCVFileChecksumOffsetDirective(FileNo);4099  return false;4100}4101 4102/// parseDirectiveCVFPOData4103/// ::= .cv_fpo_data procsym4104bool AsmParser::parseDirectiveCVFPOData() {4105  SMLoc DirLoc = getLexer().getLoc();4106  MCSymbol *ProcSym;4107  if (parseSymbol(ProcSym))4108    return TokError("expected symbol name");4109  if (parseEOL())4110    return true;4111  getStreamer().emitCVFPOData(ProcSym, DirLoc);4112  return false;4113}4114 4115/// parseDirectiveCFISections4116/// ::= .cfi_sections section [, section][, section]4117bool AsmParser::parseDirectiveCFISections() {4118  StringRef Name;4119  bool EH = false;4120  bool Debug = false;4121  bool SFrame = false;4122 4123  if (!parseOptionalToken(AsmToken::EndOfStatement)) {4124    for (;;) {4125      if (parseIdentifier(Name))4126        return TokError("expected .eh_frame, .debug_frame, or .sframe");4127      if (Name == ".eh_frame")4128        EH = true;4129      else if (Name == ".debug_frame")4130        Debug = true;4131      else if (Name == ".sframe")4132        SFrame = true;4133      if (parseOptionalToken(AsmToken::EndOfStatement))4134        break;4135      if (parseComma())4136        return true;4137    }4138  }4139  getStreamer().emitCFISections(EH, Debug, SFrame);4140  return false;4141}4142 4143/// parseDirectiveCFIStartProc4144/// ::= .cfi_startproc [simple]4145bool AsmParser::parseDirectiveCFIStartProc() {4146  CFIStartProcLoc = StartTokLoc;4147 4148  StringRef Simple;4149  if (!parseOptionalToken(AsmToken::EndOfStatement)) {4150    if (check(parseIdentifier(Simple) || Simple != "simple",4151              "unexpected token") ||4152        parseEOL())4153      return true;4154  }4155 4156  // TODO(kristina): Deal with a corner case of incorrect diagnostic context4157  // being produced if this directive is emitted as part of preprocessor macro4158  // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.4159  // Tools like llvm-mc on the other hand are not affected by it, and report4160  // correct context information.4161  getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());4162  return false;4163}4164 4165/// parseDirectiveCFIEndProc4166/// ::= .cfi_endproc4167bool AsmParser::parseDirectiveCFIEndProc() {4168  CFIStartProcLoc = std::nullopt;4169 4170  if (parseEOL())4171    return true;4172 4173  getStreamer().emitCFIEndProc();4174  return false;4175}4176 4177/// parse register name or number.4178bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,4179                                              SMLoc DirectiveLoc) {4180  MCRegister RegNo;4181 4182  if (getLexer().isNot(AsmToken::Integer)) {4183    if (getTargetParser().parseRegister(RegNo, DirectiveLoc, DirectiveLoc))4184      return true;4185    Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);4186  } else4187    return parseAbsoluteExpression(Register);4188 4189  return false;4190}4191 4192/// parseDirectiveCFIDefCfa4193/// ::= .cfi_def_cfa register,  offset4194bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {4195  int64_t Register = 0, Offset = 0;4196  if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||4197      parseAbsoluteExpression(Offset) || parseEOL())4198    return true;4199 4200  getStreamer().emitCFIDefCfa(Register, Offset, DirectiveLoc);4201  return false;4202}4203 4204/// parseDirectiveCFIDefCfaOffset4205/// ::= .cfi_def_cfa_offset offset4206bool AsmParser::parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc) {4207  int64_t Offset = 0;4208  if (parseAbsoluteExpression(Offset) || parseEOL())4209    return true;4210 4211  getStreamer().emitCFIDefCfaOffset(Offset, DirectiveLoc);4212  return false;4213}4214 4215/// parseDirectiveCFIRegister4216/// ::= .cfi_register register, register4217bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {4218  int64_t Register1 = 0, Register2 = 0;4219  if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || parseComma() ||4220      parseRegisterOrRegisterNumber(Register2, DirectiveLoc) || parseEOL())4221    return true;4222 4223  getStreamer().emitCFIRegister(Register1, Register2, DirectiveLoc);4224  return false;4225}4226 4227/// parseDirectiveCFIWindowSave4228/// ::= .cfi_window_save4229bool AsmParser::parseDirectiveCFIWindowSave(SMLoc DirectiveLoc) {4230  if (parseEOL())4231    return true;4232  getStreamer().emitCFIWindowSave(DirectiveLoc);4233  return false;4234}4235 4236/// parseDirectiveCFIAdjustCfaOffset4237/// ::= .cfi_adjust_cfa_offset adjustment4238bool AsmParser::parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc) {4239  int64_t Adjustment = 0;4240  if (parseAbsoluteExpression(Adjustment) || parseEOL())4241    return true;4242 4243  getStreamer().emitCFIAdjustCfaOffset(Adjustment, DirectiveLoc);4244  return false;4245}4246 4247/// parseDirectiveCFIDefCfaRegister4248/// ::= .cfi_def_cfa_register register4249bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {4250  int64_t Register = 0;4251  if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())4252    return true;4253 4254  getStreamer().emitCFIDefCfaRegister(Register, DirectiveLoc);4255  return false;4256}4257 4258/// parseDirectiveCFILLVMDefAspaceCfa4259/// ::= .cfi_llvm_def_aspace_cfa register, offset, address_space4260bool AsmParser::parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc) {4261  int64_t Register = 0, Offset = 0, AddressSpace = 0;4262  if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||4263      parseAbsoluteExpression(Offset) || parseComma() ||4264      parseAbsoluteExpression(AddressSpace) || parseEOL())4265    return true;4266 4267  getStreamer().emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace,4268                                        DirectiveLoc);4269  return false;4270}4271 4272/// parseDirectiveCFIOffset4273/// ::= .cfi_offset register, offset4274bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {4275  int64_t Register = 0;4276  int64_t Offset = 0;4277 4278  if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||4279      parseAbsoluteExpression(Offset) || parseEOL())4280    return true;4281 4282  getStreamer().emitCFIOffset(Register, Offset, DirectiveLoc);4283  return false;4284}4285 4286/// parseDirectiveCFIRelOffset4287/// ::= .cfi_rel_offset register, offset4288bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {4289  int64_t Register = 0, Offset = 0;4290 4291  if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||4292      parseAbsoluteExpression(Offset) || parseEOL())4293    return true;4294 4295  getStreamer().emitCFIRelOffset(Register, Offset, DirectiveLoc);4296  return false;4297}4298 4299static bool isValidEncoding(int64_t Encoding) {4300  if (Encoding & ~0xff)4301    return false;4302 4303  if (Encoding == dwarf::DW_EH_PE_omit)4304    return true;4305 4306  const unsigned Format = Encoding & 0xf;4307  if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&4308      Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&4309      Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&4310      Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)4311    return false;4312 4313  const unsigned Application = Encoding & 0x70;4314  if (Application != dwarf::DW_EH_PE_absptr &&4315      Application != dwarf::DW_EH_PE_pcrel)4316    return false;4317 4318  return true;4319}4320 4321/// parseDirectiveCFIPersonalityOrLsda4322/// IsPersonality true for cfi_personality, false for cfi_lsda4323/// ::= .cfi_personality encoding, [symbol_name]4324/// ::= .cfi_lsda encoding, [symbol_name]4325bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {4326  int64_t Encoding = 0;4327  if (parseAbsoluteExpression(Encoding))4328    return true;4329  if (Encoding == dwarf::DW_EH_PE_omit)4330    return false;4331 4332  MCSymbol *Sym;4333  if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||4334      parseComma() ||4335      check(parseSymbol(Sym), "expected identifier in directive") || parseEOL())4336    return true;4337 4338  if (IsPersonality)4339    getStreamer().emitCFIPersonality(Sym, Encoding);4340  else4341    getStreamer().emitCFILsda(Sym, Encoding);4342  return false;4343}4344 4345/// parseDirectiveCFIRememberState4346/// ::= .cfi_remember_state4347bool AsmParser::parseDirectiveCFIRememberState(SMLoc DirectiveLoc) {4348  if (parseEOL())4349    return true;4350  getStreamer().emitCFIRememberState(DirectiveLoc);4351  return false;4352}4353 4354/// parseDirectiveCFIRestoreState4355/// ::= .cfi_remember_state4356bool AsmParser::parseDirectiveCFIRestoreState(SMLoc DirectiveLoc) {4357  if (parseEOL())4358    return true;4359  getStreamer().emitCFIRestoreState(DirectiveLoc);4360  return false;4361}4362 4363/// parseDirectiveCFISameValue4364/// ::= .cfi_same_value register4365bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {4366  int64_t Register = 0;4367 4368  if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())4369    return true;4370 4371  getStreamer().emitCFISameValue(Register, DirectiveLoc);4372  return false;4373}4374 4375/// parseDirectiveCFIRestore4376/// ::= .cfi_restore register4377bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {4378  int64_t Register = 0;4379  if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())4380    return true;4381 4382  getStreamer().emitCFIRestore(Register, DirectiveLoc);4383  return false;4384}4385 4386/// parseDirectiveCFIEscape4387/// ::= .cfi_escape expression[,...]4388bool AsmParser::parseDirectiveCFIEscape(SMLoc DirectiveLoc) {4389  std::string Values;4390  int64_t CurrValue;4391  if (parseAbsoluteExpression(CurrValue))4392    return true;4393 4394  Values.push_back((uint8_t)CurrValue);4395 4396  while (getLexer().is(AsmToken::Comma)) {4397    Lex();4398 4399    if (parseAbsoluteExpression(CurrValue))4400      return true;4401 4402    Values.push_back((uint8_t)CurrValue);4403  }4404 4405  getStreamer().emitCFIEscape(Values, DirectiveLoc);4406  return false;4407}4408 4409/// parseDirectiveCFIReturnColumn4410/// ::= .cfi_return_column register4411bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {4412  int64_t Register = 0;4413  if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())4414    return true;4415  getStreamer().emitCFIReturnColumn(Register);4416  return false;4417}4418 4419/// parseDirectiveCFISignalFrame4420/// ::= .cfi_signal_frame4421bool AsmParser::parseDirectiveCFISignalFrame(SMLoc DirectiveLoc) {4422  if (parseEOL())4423    return true;4424 4425  getStreamer().emitCFISignalFrame();4426  return false;4427}4428 4429/// parseDirectiveCFIUndefined4430/// ::= .cfi_undefined register4431bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {4432  int64_t Register = 0;4433 4434  if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL())4435    return true;4436 4437  getStreamer().emitCFIUndefined(Register, DirectiveLoc);4438  return false;4439}4440 4441/// parseDirectiveCFILabel4442/// ::= .cfi_label label4443bool AsmParser::parseDirectiveCFILabel(SMLoc Loc) {4444  StringRef Name;4445  Loc = Lexer.getLoc();4446  if (parseIdentifier(Name))4447    return TokError("expected identifier");4448  if (parseEOL())4449    return true;4450  getStreamer().emitCFILabelDirective(Loc, Name);4451  return false;4452}4453 4454/// parseDirectiveCFIValOffset4455/// ::= .cfi_val_offset register, offset4456bool AsmParser::parseDirectiveCFIValOffset(SMLoc DirectiveLoc) {4457  int64_t Register = 0;4458  int64_t Offset = 0;4459 4460  if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() ||4461      parseAbsoluteExpression(Offset) || parseEOL())4462    return true;4463 4464  getStreamer().emitCFIValOffset(Register, Offset, DirectiveLoc);4465  return false;4466}4467 4468/// parseDirectiveAltmacro4469/// ::= .altmacro4470/// ::= .noaltmacro4471bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {4472  if (parseEOL())4473    return true;4474  AltMacroMode = (Directive == ".altmacro");4475  return false;4476}4477 4478/// parseDirectiveMacrosOnOff4479/// ::= .macros_on4480/// ::= .macros_off4481bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) {4482  if (parseEOL())4483    return true;4484  setMacrosEnabled(Directive == ".macros_on");4485  return false;4486}4487 4488/// parseDirectiveMacro4489/// ::= .macro name[,] [parameters]4490bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {4491  StringRef Name;4492  if (parseIdentifier(Name))4493    return TokError("expected identifier in '.macro' directive");4494 4495  if (getLexer().is(AsmToken::Comma))4496    Lex();4497 4498  MCAsmMacroParameters Parameters;4499  while (getLexer().isNot(AsmToken::EndOfStatement)) {4500 4501    if (!Parameters.empty() && Parameters.back().Vararg)4502      return Error(Lexer.getLoc(), "vararg parameter '" +4503                                       Parameters.back().Name +4504                                       "' should be the last parameter");4505 4506    MCAsmMacroParameter Parameter;4507    if (parseIdentifier(Parameter.Name))4508      return TokError("expected identifier in '.macro' directive");4509 4510    // Emit an error if two (or more) named parameters share the same name4511    for (const MCAsmMacroParameter& CurrParam : Parameters)4512      if (CurrParam.Name == Parameter.Name)4513        return TokError("macro '" + Name + "' has multiple parameters"4514                        " named '" + Parameter.Name + "'");4515 4516    if (Lexer.is(AsmToken::Colon)) {4517      Lex();  // consume ':'4518 4519      SMLoc QualLoc;4520      StringRef Qualifier;4521 4522      QualLoc = Lexer.getLoc();4523      if (parseIdentifier(Qualifier))4524        return Error(QualLoc, "missing parameter qualifier for "4525                     "'" + Parameter.Name + "' in macro '" + Name + "'");4526 4527      if (Qualifier == "req")4528        Parameter.Required = true;4529      else if (Qualifier == "vararg")4530        Parameter.Vararg = true;4531      else4532        return Error(QualLoc, Qualifier + " is not a valid parameter qualifier "4533                     "for '" + Parameter.Name + "' in macro '" + Name + "'");4534    }4535 4536    if (getLexer().is(AsmToken::Equal)) {4537      Lex();4538 4539      SMLoc ParamLoc;4540 4541      ParamLoc = Lexer.getLoc();4542      if (parseMacroArgument(Parameter.Value, /*Vararg=*/false ))4543        return true;4544 4545      if (Parameter.Required)4546        Warning(ParamLoc, "pointless default value for required parameter "4547                "'" + Parameter.Name + "' in macro '" + Name + "'");4548    }4549 4550    Parameters.push_back(std::move(Parameter));4551 4552    if (getLexer().is(AsmToken::Comma))4553      Lex();4554  }4555 4556  // Eat just the end of statement.4557  Lexer.Lex();4558 4559  // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors4560  AsmToken EndToken, StartToken = getTok();4561  unsigned MacroDepth = 0;4562  // Lex the macro definition.4563  while (true) {4564    // Ignore Lexing errors in macros.4565    while (Lexer.is(AsmToken::Error)) {4566      Lexer.Lex();4567    }4568 4569    // Check whether we have reached the end of the file.4570    if (getLexer().is(AsmToken::Eof))4571      return Error(DirectiveLoc, "no matching '.endmacro' in definition");4572 4573    // Otherwise, check whether we have reach the .endmacro or the start of a4574    // preprocessor line marker.4575    if (getLexer().is(AsmToken::Identifier)) {4576      if (getTok().getIdentifier() == ".endm" ||4577          getTok().getIdentifier() == ".endmacro") {4578        if (MacroDepth == 0) { // Outermost macro.4579          EndToken = getTok();4580          Lexer.Lex();4581          if (getLexer().isNot(AsmToken::EndOfStatement))4582            return TokError("unexpected token in '" + EndToken.getIdentifier() +4583                            "' directive");4584          break;4585        } else {4586          // Otherwise we just found the end of an inner macro.4587          --MacroDepth;4588        }4589      } else if (getTok().getIdentifier() == ".macro") {4590        // We allow nested macros. Those aren't instantiated until the outermost4591        // macro is expanded so just ignore them for now.4592        ++MacroDepth;4593      }4594    } else if (Lexer.is(AsmToken::HashDirective)) {4595      (void)parseCppHashLineFilenameComment(getLexer().getLoc());4596    }4597 4598    // Otherwise, scan til the end of the statement.4599    eatToEndOfStatement();4600  }4601 4602  if (getContext().lookupMacro(Name)) {4603    return Error(DirectiveLoc, "macro '" + Name + "' is already defined");4604  }4605 4606  const char *BodyStart = StartToken.getLoc().getPointer();4607  const char *BodyEnd = EndToken.getLoc().getPointer();4608  StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);4609  checkForBadMacro(DirectiveLoc, Name, Body, Parameters);4610  MCAsmMacro Macro(Name, Body, std::move(Parameters));4611  DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";4612                  Macro.dump());4613  getContext().defineMacro(Name, std::move(Macro));4614  return false;4615}4616 4617/// checkForBadMacro4618///4619/// With the support added for named parameters there may be code out there that4620/// is transitioning from positional parameters.  In versions of gas that did4621/// not support named parameters they would be ignored on the macro definition.4622/// But to support both styles of parameters this is not possible so if a macro4623/// definition has named parameters but does not use them and has what appears4624/// to be positional parameters, strings like $1, $2, ... and $n, then issue a4625/// warning that the positional parameter found in body which have no effect.4626/// Hoping the developer will either remove the named parameters from the macro4627/// definition so the positional parameters get used if that was what was4628/// intended or change the macro to use the named parameters.  It is possible4629/// this warning will trigger when the none of the named parameters are used4630/// and the strings like $1 are infact to simply to be passed trough unchanged.4631void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,4632                                 StringRef Body,4633                                 ArrayRef<MCAsmMacroParameter> Parameters) {4634  // If this macro is not defined with named parameters the warning we are4635  // checking for here doesn't apply.4636  unsigned NParameters = Parameters.size();4637  if (NParameters == 0)4638    return;4639 4640  bool NamedParametersFound = false;4641  bool PositionalParametersFound = false;4642 4643  // Look at the body of the macro for use of both the named parameters and what4644  // are likely to be positional parameters.  This is what expandMacro() is4645  // doing when it finds the parameters in the body.4646  while (!Body.empty()) {4647    // Scan for the next possible parameter.4648    std::size_t End = Body.size(), Pos = 0;4649    for (; Pos != End; ++Pos) {4650      // Check for a substitution or escape.4651      // This macro is defined with parameters, look for \foo, \bar, etc.4652      if (Body[Pos] == '\\' && Pos + 1 != End)4653        break;4654 4655      // This macro should have parameters, but look for $0, $1, ..., $n too.4656      if (Body[Pos] != '$' || Pos + 1 == End)4657        continue;4658      char Next = Body[Pos + 1];4659      if (Next == '$' || Next == 'n' ||4660          isdigit(static_cast<unsigned char>(Next)))4661        break;4662    }4663 4664    // Check if we reached the end.4665    if (Pos == End)4666      break;4667 4668    if (Body[Pos] == '$') {4669      switch (Body[Pos + 1]) {4670      // $$ => $4671      case '$':4672        break;4673 4674      // $n => number of arguments4675      case 'n':4676        PositionalParametersFound = true;4677        break;4678 4679      // $[0-9] => argument4680      default: {4681        PositionalParametersFound = true;4682        break;4683      }4684      }4685      Pos += 2;4686    } else {4687      unsigned I = Pos + 1;4688      while (isIdentifierChar(Body[I]) && I + 1 != End)4689        ++I;4690 4691      const char *Begin = Body.data() + Pos + 1;4692      StringRef Argument(Begin, I - (Pos + 1));4693      unsigned Index = 0;4694      for (; Index < NParameters; ++Index)4695        if (Parameters[Index].Name == Argument)4696          break;4697 4698      if (Index == NParameters) {4699        if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')')4700          Pos += 3;4701        else {4702          Pos = I;4703        }4704      } else {4705        NamedParametersFound = true;4706        Pos += 1 + Argument.size();4707      }4708    }4709    // Update the scan point.4710    Body = Body.substr(Pos);4711  }4712 4713  if (!NamedParametersFound && PositionalParametersFound)4714    Warning(DirectiveLoc, "macro defined with named parameters which are not "4715                          "used in macro body, possible positional parameter "4716                          "found in body which will have no effect");4717}4718 4719/// parseDirectiveExitMacro4720/// ::= .exitm4721bool AsmParser::parseDirectiveExitMacro(StringRef Directive) {4722  if (parseEOL())4723    return true;4724 4725  if (!isInsideMacroInstantiation())4726    return TokError("unexpected '" + Directive + "' in file, "4727                                                 "no current macro definition");4728 4729  // Exit all conditionals that are active in the current macro.4730  while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {4731    TheCondState = TheCondStack.back();4732    TheCondStack.pop_back();4733  }4734 4735  handleMacroExit();4736  return false;4737}4738 4739/// parseDirectiveEndMacro4740/// ::= .endm4741/// ::= .endmacro4742bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {4743  if (getLexer().isNot(AsmToken::EndOfStatement))4744    return TokError("unexpected token in '" + Directive + "' directive");4745 4746  // If we are inside a macro instantiation, terminate the current4747  // instantiation.4748  if (isInsideMacroInstantiation()) {4749    handleMacroExit();4750    return false;4751  }4752 4753  // Otherwise, this .endmacro is a stray entry in the file; well formed4754  // .endmacro directives are handled during the macro definition parsing.4755  return TokError("unexpected '" + Directive + "' in file, "4756                                               "no current macro definition");4757}4758 4759/// parseDirectivePurgeMacro4760/// ::= .purgem name4761bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {4762  StringRef Name;4763  SMLoc Loc;4764  if (parseTokenLoc(Loc) ||4765      check(parseIdentifier(Name), Loc,4766            "expected identifier in '.purgem' directive") ||4767      parseEOL())4768    return true;4769 4770  if (!getContext().lookupMacro(Name))4771    return Error(DirectiveLoc, "macro '" + Name + "' is not defined");4772 4773  getContext().undefineMacro(Name);4774  DEBUG_WITH_TYPE("asm-macros", dbgs()4775                                    << "Un-defining macro: " << Name << "\n");4776  return false;4777}4778 4779/// parseDirectiveSpace4780/// ::= (.skip | .space) expression [ , expression ]4781bool AsmParser::parseDirectiveSpace(StringRef IDVal) {4782  SMLoc NumBytesLoc = Lexer.getLoc();4783  const MCExpr *NumBytes;4784  if (checkForValidSection() || parseExpression(NumBytes))4785    return true;4786 4787  int64_t FillExpr = 0;4788  if (parseOptionalToken(AsmToken::Comma))4789    if (parseAbsoluteExpression(FillExpr))4790      return true;4791  if (parseEOL())4792    return true;4793 4794  // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.4795  getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc);4796 4797  return false;4798}4799 4800/// parseDirectiveDCB4801/// ::= .dcb.{b, l, w} expression, expression4802bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) {4803  SMLoc NumValuesLoc = Lexer.getLoc();4804  int64_t NumValues;4805  if (checkForValidSection() || parseAbsoluteExpression(NumValues))4806    return true;4807 4808  if (NumValues < 0) {4809    Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");4810    return false;4811  }4812 4813  if (parseComma())4814    return true;4815 4816  const MCExpr *Value;4817  SMLoc ExprLoc = getLexer().getLoc();4818  if (parseExpression(Value))4819    return true;4820 4821  // Special case constant expressions to match code generator.4822  if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {4823    assert(Size <= 8 && "Invalid size");4824    uint64_t IntValue = MCE->getValue();4825    if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))4826      return Error(ExprLoc, "literal value out of range for directive");4827    for (uint64_t i = 0, e = NumValues; i != e; ++i)4828      getStreamer().emitIntValue(IntValue, Size);4829  } else {4830    for (uint64_t i = 0, e = NumValues; i != e; ++i)4831      getStreamer().emitValue(Value, Size, ExprLoc);4832  }4833 4834  return parseEOL();4835}4836 4837/// parseDirectiveRealDCB4838/// ::= .dcb.{d, s} expression, expression4839bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) {4840  SMLoc NumValuesLoc = Lexer.getLoc();4841  int64_t NumValues;4842  if (checkForValidSection() || parseAbsoluteExpression(NumValues))4843    return true;4844 4845  if (NumValues < 0) {4846    Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");4847    return false;4848  }4849 4850  if (parseComma())4851    return true;4852 4853  APInt AsInt;4854  if (parseRealValue(Semantics, AsInt) || parseEOL())4855    return true;4856 4857  for (uint64_t i = 0, e = NumValues; i != e; ++i)4858    getStreamer().emitIntValue(AsInt.getLimitedValue(),4859                               AsInt.getBitWidth() / 8);4860 4861  return false;4862}4863 4864/// parseDirectiveDS4865/// ::= .ds.{b, d, l, p, s, w, x} expression4866bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) {4867  SMLoc NumValuesLoc = Lexer.getLoc();4868  int64_t NumValues;4869  if (checkForValidSection() || parseAbsoluteExpression(NumValues) ||4870      parseEOL())4871    return true;4872 4873  if (NumValues < 0) {4874    Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");4875    return false;4876  }4877 4878  for (uint64_t i = 0, e = NumValues; i != e; ++i)4879    getStreamer().emitFill(Size, 0);4880 4881  return false;4882}4883 4884/// parseDirectiveLEB1284885/// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]4886bool AsmParser::parseDirectiveLEB128(bool Signed) {4887  if (checkForValidSection())4888    return true;4889 4890  auto parseOp = [&]() -> bool {4891    const MCExpr *Value;4892    if (parseExpression(Value))4893      return true;4894    if (Signed)4895      getStreamer().emitSLEB128Value(Value);4896    else4897      getStreamer().emitULEB128Value(Value);4898    return false;4899  };4900 4901  return parseMany(parseOp);4902}4903 4904/// parseDirectiveSymbolAttribute4905///  ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]4906bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {4907  auto parseOp = [&]() -> bool {4908    StringRef Name;4909    SMLoc Loc = getTok().getLoc();4910    if (parseIdentifier(Name))4911      return Error(Loc, "expected identifier");4912 4913    if (discardLTOSymbol(Name))4914      return false;4915 4916    MCSymbol *Sym = getContext().parseSymbol(Name);4917 4918    // Assembler local symbols don't make any sense here, except for directives4919    // that the symbol should be tagged.4920    if (Sym->isTemporary() && Attr != MCSA_Memtag)4921      return Error(Loc, "non-local symbol required");4922 4923    if (!getStreamer().emitSymbolAttribute(Sym, Attr))4924      return Error(Loc, "unable to emit symbol attribute");4925    return false;4926  };4927 4928  return parseMany(parseOp);4929}4930 4931/// parseDirectiveComm4932///  ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]4933bool AsmParser::parseDirectiveComm(bool IsLocal) {4934  if (checkForValidSection())4935    return true;4936 4937  SMLoc IDLoc = getLexer().getLoc();4938  MCSymbol *Sym;4939  if (parseSymbol(Sym))4940    return TokError("expected identifier in directive");4941 4942  if (parseComma())4943    return true;4944 4945  int64_t Size;4946  SMLoc SizeLoc = getLexer().getLoc();4947  if (parseAbsoluteExpression(Size))4948    return true;4949 4950  int64_t Pow2Alignment = 0;4951  SMLoc Pow2AlignmentLoc;4952  if (getLexer().is(AsmToken::Comma)) {4953    Lex();4954    Pow2AlignmentLoc = getLexer().getLoc();4955    if (parseAbsoluteExpression(Pow2Alignment))4956      return true;4957 4958    LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();4959    if (IsLocal && LCOMM == LCOMM::NoAlignment)4960      return Error(Pow2AlignmentLoc, "alignment not supported on this target");4961 4962    // If this target takes alignments in bytes (not log) validate and convert.4963    if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||4964        (IsLocal && LCOMM == LCOMM::ByteAlignment)) {4965      if (!isPowerOf2_64(Pow2Alignment))4966        return Error(Pow2AlignmentLoc, "alignment must be a power of 2");4967      Pow2Alignment = Log2_64(Pow2Alignment);4968    }4969  }4970 4971  if (parseEOL())4972    return true;4973 4974  // NOTE: a size of zero for a .comm should create a undefined symbol4975  // but a size of .lcomm creates a bss symbol of size zero.4976  if (Size < 0)4977    return Error(SizeLoc, "size must be non-negative");4978 4979  Sym->redefineIfPossible();4980  if (!Sym->isUndefined())4981    return Error(IDLoc, "invalid symbol redefinition");4982 4983  // Create the Symbol as a common or local common with Size and Pow2Alignment4984  if (IsLocal) {4985    getStreamer().emitLocalCommonSymbol(Sym, Size,4986                                        Align(1ULL << Pow2Alignment));4987    return false;4988  }4989 4990  getStreamer().emitCommonSymbol(Sym, Size, Align(1ULL << Pow2Alignment));4991  return false;4992}4993 4994/// parseDirectiveAbort4995///  ::= .abort [... message ...]4996bool AsmParser::parseDirectiveAbort(SMLoc DirectiveLoc) {4997  StringRef Str = parseStringToEndOfStatement();4998  if (parseEOL())4999    return true;5000 5001  if (Str.empty())5002    return Error(DirectiveLoc, ".abort detected. Assembly stopping");5003 5004  // FIXME: Actually abort assembly here.5005  return Error(DirectiveLoc,5006               ".abort '" + Str + "' detected. Assembly stopping");5007}5008 5009/// parseDirectiveInclude5010///  ::= .include "filename"5011bool AsmParser::parseDirectiveInclude() {5012  // Allow the strings to have escaped octal character sequence.5013  std::string Filename;5014  SMLoc IncludeLoc = getTok().getLoc();5015 5016  if (check(getTok().isNot(AsmToken::String),5017            "expected string in '.include' directive") ||5018      parseEscapedString(Filename) ||5019      check(getTok().isNot(AsmToken::EndOfStatement),5020            "unexpected token in '.include' directive") ||5021      // Attempt to switch the lexer to the included file before consuming the5022      // end of statement to avoid losing it when we switch.5023      check(enterIncludeFile(Filename), IncludeLoc,5024            "Could not find include file '" + Filename + "'"))5025    return true;5026 5027  return false;5028}5029 5030/// parseDirectiveIncbin5031///  ::= .incbin "filename" [ , skip [ , count ] ]5032bool AsmParser::parseDirectiveIncbin() {5033  // Allow the strings to have escaped octal character sequence.5034  std::string Filename;5035  SMLoc IncbinLoc = getTok().getLoc();5036  if (check(getTok().isNot(AsmToken::String),5037            "expected string in '.incbin' directive") ||5038      parseEscapedString(Filename))5039    return true;5040 5041  int64_t Skip = 0;5042  const MCExpr *Count = nullptr;5043  SMLoc SkipLoc, CountLoc;5044  if (parseOptionalToken(AsmToken::Comma)) {5045    // The skip expression can be omitted while specifying the count, e.g:5046    //  .incbin "filename",,45047    if (getTok().isNot(AsmToken::Comma)) {5048      if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip))5049        return true;5050    }5051    if (parseOptionalToken(AsmToken::Comma)) {5052      CountLoc = getTok().getLoc();5053      if (parseExpression(Count))5054        return true;5055    }5056  }5057 5058  if (parseEOL())5059    return true;5060 5061  if (check(Skip < 0, SkipLoc, "skip is negative"))5062    return true;5063 5064  // Attempt to process the included file.5065  if (processIncbinFile(Filename, Skip, Count, CountLoc))5066    return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'");5067  return false;5068}5069 5070/// parseDirectiveIf5071/// ::= .if{,eq,ge,gt,le,lt,ne} expression5072bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {5073  TheCondStack.push_back(TheCondState);5074  TheCondState.TheCond = AsmCond::IfCond;5075  if (TheCondState.Ignore) {5076    eatToEndOfStatement();5077  } else {5078    int64_t ExprValue;5079    if (parseAbsoluteExpression(ExprValue) || parseEOL())5080      return true;5081 5082    switch (DirKind) {5083    default:5084      llvm_unreachable("unsupported directive");5085    case DK_IF:5086    case DK_IFNE:5087      break;5088    case DK_IFEQ:5089      ExprValue = ExprValue == 0;5090      break;5091    case DK_IFGE:5092      ExprValue = ExprValue >= 0;5093      break;5094    case DK_IFGT:5095      ExprValue = ExprValue > 0;5096      break;5097    case DK_IFLE:5098      ExprValue = ExprValue <= 0;5099      break;5100    case DK_IFLT:5101      ExprValue = ExprValue < 0;5102      break;5103    }5104 5105    TheCondState.CondMet = ExprValue;5106    TheCondState.Ignore = !TheCondState.CondMet;5107  }5108 5109  return false;5110}5111 5112/// parseDirectiveIfb5113/// ::= .ifb string5114bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {5115  TheCondStack.push_back(TheCondState);5116  TheCondState.TheCond = AsmCond::IfCond;5117 5118  if (TheCondState.Ignore) {5119    eatToEndOfStatement();5120  } else {5121    StringRef Str = parseStringToEndOfStatement();5122 5123    if (parseEOL())5124      return true;5125 5126    TheCondState.CondMet = ExpectBlank == Str.empty();5127    TheCondState.Ignore = !TheCondState.CondMet;5128  }5129 5130  return false;5131}5132 5133/// parseDirectiveIfc5134/// ::= .ifc string1, string25135/// ::= .ifnc string1, string25136bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {5137  TheCondStack.push_back(TheCondState);5138  TheCondState.TheCond = AsmCond::IfCond;5139 5140  if (TheCondState.Ignore) {5141    eatToEndOfStatement();5142  } else {5143    StringRef Str1 = parseStringToComma();5144 5145    if (parseComma())5146      return true;5147 5148    StringRef Str2 = parseStringToEndOfStatement();5149 5150    if (parseEOL())5151      return true;5152 5153    TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim());5154    TheCondState.Ignore = !TheCondState.CondMet;5155  }5156 5157  return false;5158}5159 5160/// parseDirectiveIfeqs5161///   ::= .ifeqs string1, string25162bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {5163  TheCondStack.push_back(TheCondState);5164  TheCondState.TheCond = AsmCond::IfCond;5165 5166  if (TheCondState.Ignore) {5167    eatToEndOfStatement();5168  } else {5169    if (Lexer.isNot(AsmToken::String)) {5170      if (ExpectEqual)5171        return TokError("expected string parameter for '.ifeqs' directive");5172      return TokError("expected string parameter for '.ifnes' directive");5173    }5174 5175    StringRef String1 = getTok().getStringContents();5176    Lex();5177 5178    if (Lexer.isNot(AsmToken::Comma)) {5179      if (ExpectEqual)5180        return TokError(5181            "expected comma after first string for '.ifeqs' directive");5182      return TokError(5183          "expected comma after first string for '.ifnes' directive");5184    }5185 5186    Lex();5187 5188    if (Lexer.isNot(AsmToken::String)) {5189      if (ExpectEqual)5190        return TokError("expected string parameter for '.ifeqs' directive");5191      return TokError("expected string parameter for '.ifnes' directive");5192    }5193 5194    StringRef String2 = getTok().getStringContents();5195    Lex();5196 5197    TheCondState.CondMet = ExpectEqual == (String1 == String2);5198    TheCondState.Ignore = !TheCondState.CondMet;5199  }5200 5201  return false;5202}5203 5204/// parseDirectiveIfdef5205/// ::= .ifdef symbol5206bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {5207  StringRef Name;5208  TheCondStack.push_back(TheCondState);5209  TheCondState.TheCond = AsmCond::IfCond;5210 5211  if (TheCondState.Ignore) {5212    eatToEndOfStatement();5213  } else {5214    if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") ||5215        parseEOL())5216      return true;5217 5218    MCSymbol *Sym = getContext().lookupSymbol(Name);5219 5220    if (expect_defined)5221      TheCondState.CondMet = (Sym && !Sym->isUndefined());5222    else5223      TheCondState.CondMet = (!Sym || Sym->isUndefined());5224    TheCondState.Ignore = !TheCondState.CondMet;5225  }5226 5227  return false;5228}5229 5230/// parseDirectiveElseIf5231/// ::= .elseif expression5232bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {5233  if (TheCondState.TheCond != AsmCond::IfCond &&5234      TheCondState.TheCond != AsmCond::ElseIfCond)5235    return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"5236                               " .if or  an .elseif");5237  TheCondState.TheCond = AsmCond::ElseIfCond;5238 5239  bool LastIgnoreState = false;5240  if (!TheCondStack.empty())5241    LastIgnoreState = TheCondStack.back().Ignore;5242  if (LastIgnoreState || TheCondState.CondMet) {5243    TheCondState.Ignore = true;5244    eatToEndOfStatement();5245  } else {5246    int64_t ExprValue;5247    if (parseAbsoluteExpression(ExprValue))5248      return true;5249 5250    if (parseEOL())5251      return true;5252 5253    TheCondState.CondMet = ExprValue;5254    TheCondState.Ignore = !TheCondState.CondMet;5255  }5256 5257  return false;5258}5259 5260/// parseDirectiveElse5261/// ::= .else5262bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {5263  if (parseEOL())5264    return true;5265 5266  if (TheCondState.TheCond != AsmCond::IfCond &&5267      TheCondState.TheCond != AsmCond::ElseIfCond)5268    return Error(DirectiveLoc, "Encountered a .else that doesn't follow "5269                               " an .if or an .elseif");5270  TheCondState.TheCond = AsmCond::ElseCond;5271  bool LastIgnoreState = false;5272  if (!TheCondStack.empty())5273    LastIgnoreState = TheCondStack.back().Ignore;5274  if (LastIgnoreState || TheCondState.CondMet)5275    TheCondState.Ignore = true;5276  else5277    TheCondState.Ignore = false;5278 5279  return false;5280}5281 5282/// parseDirectiveEnd5283/// ::= .end5284bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {5285  if (parseEOL())5286    return true;5287 5288  while (Lexer.isNot(AsmToken::Eof))5289    Lexer.Lex();5290 5291  return false;5292}5293 5294/// parseDirectiveError5295///   ::= .err5296///   ::= .error [string]5297bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {5298  if (!TheCondStack.empty()) {5299    if (TheCondStack.back().Ignore) {5300      eatToEndOfStatement();5301      return false;5302    }5303  }5304 5305  if (!WithMessage)5306    return Error(L, ".err encountered");5307 5308  StringRef Message = ".error directive invoked in source file";5309  if (Lexer.isNot(AsmToken::EndOfStatement)) {5310    if (Lexer.isNot(AsmToken::String))5311      return TokError(".error argument must be a string");5312 5313    Message = getTok().getStringContents();5314    Lex();5315  }5316 5317  return Error(L, Message);5318}5319 5320/// parseDirectiveWarning5321///   ::= .warning [string]5322bool AsmParser::parseDirectiveWarning(SMLoc L) {5323  if (!TheCondStack.empty()) {5324    if (TheCondStack.back().Ignore) {5325      eatToEndOfStatement();5326      return false;5327    }5328  }5329 5330  StringRef Message = ".warning directive invoked in source file";5331 5332  if (!parseOptionalToken(AsmToken::EndOfStatement)) {5333    if (Lexer.isNot(AsmToken::String))5334      return TokError(".warning argument must be a string");5335 5336    Message = getTok().getStringContents();5337    Lex();5338    if (parseEOL())5339      return true;5340  }5341 5342  return Warning(L, Message);5343}5344 5345/// parseDirectiveEndIf5346/// ::= .endif5347bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {5348  if (parseEOL())5349    return true;5350 5351  if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())5352    return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "5353                               "an .if or .else");5354  if (!TheCondStack.empty()) {5355    TheCondState = TheCondStack.back();5356    TheCondStack.pop_back();5357  }5358 5359  return false;5360}5361 5362void AsmParser::initializeDirectiveKindMap() {5363  /* Lookup will be done with the directive5364   * converted to lower case, so all these5365   * keys should be lower case.5366   * (target specific directives are handled5367   *  elsewhere)5368   */5369  DirectiveKindMap[".set"] = DK_SET;5370  DirectiveKindMap[".equ"] = DK_EQU;5371  DirectiveKindMap[".equiv"] = DK_EQUIV;5372  DirectiveKindMap[".ascii"] = DK_ASCII;5373  DirectiveKindMap[".asciz"] = DK_ASCIZ;5374  DirectiveKindMap[".string"] = DK_STRING;5375  DirectiveKindMap[".byte"] = DK_BYTE;5376  DirectiveKindMap[".base64"] = DK_BASE64;5377  DirectiveKindMap[".short"] = DK_SHORT;5378  DirectiveKindMap[".value"] = DK_VALUE;5379  DirectiveKindMap[".2byte"] = DK_2BYTE;5380  DirectiveKindMap[".long"] = DK_LONG;5381  DirectiveKindMap[".int"] = DK_INT;5382  DirectiveKindMap[".4byte"] = DK_4BYTE;5383  DirectiveKindMap[".quad"] = DK_QUAD;5384  DirectiveKindMap[".8byte"] = DK_8BYTE;5385  DirectiveKindMap[".octa"] = DK_OCTA;5386  DirectiveKindMap[".single"] = DK_SINGLE;5387  DirectiveKindMap[".float"] = DK_FLOAT;5388  DirectiveKindMap[".double"] = DK_DOUBLE;5389  DirectiveKindMap[".align"] = DK_ALIGN;5390  DirectiveKindMap[".align32"] = DK_ALIGN32;5391  DirectiveKindMap[".balign"] = DK_BALIGN;5392  DirectiveKindMap[".balignw"] = DK_BALIGNW;5393  DirectiveKindMap[".balignl"] = DK_BALIGNL;5394  DirectiveKindMap[".p2align"] = DK_P2ALIGN;5395  DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW;5396  DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL;5397  DirectiveKindMap[".org"] = DK_ORG;5398  DirectiveKindMap[".fill"] = DK_FILL;5399  DirectiveKindMap[".zero"] = DK_ZERO;5400  DirectiveKindMap[".extern"] = DK_EXTERN;5401  DirectiveKindMap[".globl"] = DK_GLOBL;5402  DirectiveKindMap[".global"] = DK_GLOBAL;5403  DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE;5404  DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP;5405  DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER;5406  DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN;5407  DirectiveKindMap[".reference"] = DK_REFERENCE;5408  DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION;5409  DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE;5410  DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN;5411  DirectiveKindMap[".cold"] = DK_COLD;5412  DirectiveKindMap[".comm"] = DK_COMM;5413  DirectiveKindMap[".common"] = DK_COMMON;5414  DirectiveKindMap[".lcomm"] = DK_LCOMM;5415  DirectiveKindMap[".abort"] = DK_ABORT;5416  DirectiveKindMap[".include"] = DK_INCLUDE;5417  DirectiveKindMap[".incbin"] = DK_INCBIN;5418  DirectiveKindMap[".code16"] = DK_CODE16;5419  DirectiveKindMap[".code16gcc"] = DK_CODE16GCC;5420  DirectiveKindMap[".rept"] = DK_REPT;5421  DirectiveKindMap[".rep"] = DK_REPT;5422  DirectiveKindMap[".irp"] = DK_IRP;5423  DirectiveKindMap[".irpc"] = DK_IRPC;5424  DirectiveKindMap[".endr"] = DK_ENDR;5425  DirectiveKindMap[".if"] = DK_IF;5426  DirectiveKindMap[".ifeq"] = DK_IFEQ;5427  DirectiveKindMap[".ifge"] = DK_IFGE;5428  DirectiveKindMap[".ifgt"] = DK_IFGT;5429  DirectiveKindMap[".ifle"] = DK_IFLE;5430  DirectiveKindMap[".iflt"] = DK_IFLT;5431  DirectiveKindMap[".ifne"] = DK_IFNE;5432  DirectiveKindMap[".ifb"] = DK_IFB;5433  DirectiveKindMap[".ifnb"] = DK_IFNB;5434  DirectiveKindMap[".ifc"] = DK_IFC;5435  DirectiveKindMap[".ifeqs"] = DK_IFEQS;5436  DirectiveKindMap[".ifnc"] = DK_IFNC;5437  DirectiveKindMap[".ifnes"] = DK_IFNES;5438  DirectiveKindMap[".ifdef"] = DK_IFDEF;5439  DirectiveKindMap[".ifndef"] = DK_IFNDEF;5440  DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF;5441  DirectiveKindMap[".elseif"] = DK_ELSEIF;5442  DirectiveKindMap[".else"] = DK_ELSE;5443  DirectiveKindMap[".end"] = DK_END;5444  DirectiveKindMap[".endif"] = DK_ENDIF;5445  DirectiveKindMap[".skip"] = DK_SKIP;5446  DirectiveKindMap[".space"] = DK_SPACE;5447  DirectiveKindMap[".file"] = DK_FILE;5448  DirectiveKindMap[".line"] = DK_LINE;5449  DirectiveKindMap[".loc"] = DK_LOC;5450  DirectiveKindMap[".loc_label"] = DK_LOC_LABEL;5451  DirectiveKindMap[".stabs"] = DK_STABS;5452  DirectiveKindMap[".cv_file"] = DK_CV_FILE;5453  DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;5454  DirectiveKindMap[".cv_loc"] = DK_CV_LOC;5455  DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;5456  DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;5457  DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;5458  DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;5459  DirectiveKindMap[".cv_string"] = DK_CV_STRING;5460  DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;5461  DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;5462  DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;5463  DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;5464  DirectiveKindMap[".sleb128"] = DK_SLEB128;5465  DirectiveKindMap[".uleb128"] = DK_ULEB128;5466  DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;5467  DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;5468  DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;5469  DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;5470  DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;5471  DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;5472  DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;5473  DirectiveKindMap[".cfi_llvm_def_aspace_cfa"] = DK_CFI_LLVM_DEF_ASPACE_CFA;5474  DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;5475  DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;5476  DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;5477  DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;5478  DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;5479  DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;5480  DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;5481  DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;5482  DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;5483  DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;5484  DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;5485  DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;5486  DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;5487  DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;5488  DirectiveKindMap[".cfi_label"] = DK_CFI_LABEL;5489  DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;5490  DirectiveKindMap[".cfi_mte_tagged_frame"] = DK_CFI_MTE_TAGGED_FRAME;5491  DirectiveKindMap[".cfi_val_offset"] = DK_CFI_VAL_OFFSET;5492  DirectiveKindMap[".macros_on"] = DK_MACROS_ON;5493  DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;5494  DirectiveKindMap[".macro"] = DK_MACRO;5495  DirectiveKindMap[".exitm"] = DK_EXITM;5496  DirectiveKindMap[".endm"] = DK_ENDM;5497  DirectiveKindMap[".endmacro"] = DK_ENDMACRO;5498  DirectiveKindMap[".purgem"] = DK_PURGEM;5499  DirectiveKindMap[".err"] = DK_ERR;5500  DirectiveKindMap[".error"] = DK_ERROR;5501  DirectiveKindMap[".warning"] = DK_WARNING;5502  DirectiveKindMap[".altmacro"] = DK_ALTMACRO;5503  DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;5504  DirectiveKindMap[".reloc"] = DK_RELOC;5505  DirectiveKindMap[".dc"] = DK_DC;5506  DirectiveKindMap[".dc.a"] = DK_DC_A;5507  DirectiveKindMap[".dc.b"] = DK_DC_B;5508  DirectiveKindMap[".dc.d"] = DK_DC_D;5509  DirectiveKindMap[".dc.l"] = DK_DC_L;5510  DirectiveKindMap[".dc.s"] = DK_DC_S;5511  DirectiveKindMap[".dc.w"] = DK_DC_W;5512  DirectiveKindMap[".dc.x"] = DK_DC_X;5513  DirectiveKindMap[".dcb"] = DK_DCB;5514  DirectiveKindMap[".dcb.b"] = DK_DCB_B;5515  DirectiveKindMap[".dcb.d"] = DK_DCB_D;5516  DirectiveKindMap[".dcb.l"] = DK_DCB_L;5517  DirectiveKindMap[".dcb.s"] = DK_DCB_S;5518  DirectiveKindMap[".dcb.w"] = DK_DCB_W;5519  DirectiveKindMap[".dcb.x"] = DK_DCB_X;5520  DirectiveKindMap[".ds"] = DK_DS;5521  DirectiveKindMap[".ds.b"] = DK_DS_B;5522  DirectiveKindMap[".ds.d"] = DK_DS_D;5523  DirectiveKindMap[".ds.l"] = DK_DS_L;5524  DirectiveKindMap[".ds.p"] = DK_DS_P;5525  DirectiveKindMap[".ds.s"] = DK_DS_S;5526  DirectiveKindMap[".ds.w"] = DK_DS_W;5527  DirectiveKindMap[".ds.x"] = DK_DS_X;5528  DirectiveKindMap[".print"] = DK_PRINT;5529  DirectiveKindMap[".addrsig"] = DK_ADDRSIG;5530  DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM;5531  DirectiveKindMap[".pseudoprobe"] = DK_PSEUDO_PROBE;5532  DirectiveKindMap[".lto_discard"] = DK_LTO_DISCARD;5533  DirectiveKindMap[".lto_set_conditional"] = DK_LTO_SET_CONDITIONAL;5534  DirectiveKindMap[".memtag"] = DK_MEMTAG;5535}5536 5537MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {5538  AsmToken EndToken, StartToken = getTok();5539 5540  unsigned NestLevel = 0;5541  while (true) {5542    // Check whether we have reached the end of the file.5543    if (getLexer().is(AsmToken::Eof)) {5544      printError(DirectiveLoc, "no matching '.endr' in definition");5545      return nullptr;5546    }5547 5548    if (Lexer.is(AsmToken::Identifier)) {5549      StringRef Ident = getTok().getIdentifier();5550      if (Ident == ".rep" || Ident == ".rept" || Ident == ".irp" ||5551          Ident == ".irpc") {5552        ++NestLevel;5553      } else if (Ident == ".endr") {5554        if (NestLevel == 0) {5555          EndToken = getTok();5556          Lex();5557          if (Lexer.is(AsmToken::EndOfStatement))5558            break;5559          printError(getTok().getLoc(), "expected newline");5560          return nullptr;5561        }5562        --NestLevel;5563      }5564    }5565 5566    // Otherwise, scan till the end of the statement.5567    eatToEndOfStatement();5568  }5569 5570  const char *BodyStart = StartToken.getLoc().getPointer();5571  const char *BodyEnd = EndToken.getLoc().getPointer();5572  StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);5573 5574  // We Are Anonymous.5575  MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());5576  return &MacroLikeBodies.back();5577}5578 5579void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,5580                                         raw_svector_ostream &OS) {5581  OS << ".endr\n";5582 5583  std::unique_ptr<MemoryBuffer> Instantiation =5584      MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");5585 5586  // Create the macro instantiation object and add to the current macro5587  // instantiation stack.5588  MacroInstantiation *MI = new MacroInstantiation{5589      DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};5590  ActiveMacros.push_back(MI);5591 5592  // Jump to the macro instantiation and prime the lexer.5593  CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());5594  Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());5595  Lex();5596}5597 5598/// parseDirectiveRept5599///   ::= .rep | .rept count5600bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {5601  const MCExpr *CountExpr;5602  SMLoc CountLoc = getTok().getLoc();5603  if (parseExpression(CountExpr))5604    return true;5605 5606  int64_t Count;5607  if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {5608    return Error(CountLoc, "unexpected token in '" + Dir + "' directive");5609  }5610 5611  if (check(Count < 0, CountLoc, "Count is negative") || parseEOL())5612    return true;5613 5614  // Lex the rept definition.5615  MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);5616  if (!M)5617    return true;5618 5619  // Macro instantiation is lexical, unfortunately. We construct a new buffer5620  // to hold the macro body with substitutions.5621  SmallString<256> Buf;5622  raw_svector_ostream OS(Buf);5623  while (Count--) {5624    // Note that the AtPseudoVariable is disabled for instantiations of .rep(t).5625    if (expandMacro(OS, *M, {}, {}, false))5626      return true;5627  }5628  instantiateMacroLikeBody(M, DirectiveLoc, OS);5629 5630  return false;5631}5632 5633/// parseDirectiveIrp5634/// ::= .irp symbol,values5635bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {5636  MCAsmMacroParameter Parameter;5637  MCAsmMacroArguments A;5638  if (check(parseIdentifier(Parameter.Name),5639            "expected identifier in '.irp' directive") ||5640      parseComma() || parseMacroArguments(nullptr, A) || parseEOL())5641    return true;5642 5643  // Lex the irp definition.5644  MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);5645  if (!M)5646    return true;5647 5648  // Macro instantiation is lexical, unfortunately. We construct a new buffer5649  // to hold the macro body with substitutions.5650  SmallString<256> Buf;5651  raw_svector_ostream OS(Buf);5652 5653  for (const MCAsmMacroArgument &Arg : A) {5654    // Note that the AtPseudoVariable is enabled for instantiations of .irp.5655    // This is undocumented, but GAS seems to support it.5656    if (expandMacro(OS, *M, Parameter, Arg, true))5657      return true;5658  }5659 5660  instantiateMacroLikeBody(M, DirectiveLoc, OS);5661 5662  return false;5663}5664 5665/// parseDirectiveIrpc5666/// ::= .irpc symbol,values5667bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {5668  MCAsmMacroParameter Parameter;5669  MCAsmMacroArguments A;5670 5671  if (check(parseIdentifier(Parameter.Name),5672            "expected identifier in '.irpc' directive") ||5673      parseComma() || parseMacroArguments(nullptr, A))5674    return true;5675 5676  if (A.size() != 1 || A.front().size() != 1)5677    return TokError("unexpected token in '.irpc' directive");5678  if (parseEOL())5679    return true;5680 5681  // Lex the irpc definition.5682  MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);5683  if (!M)5684    return true;5685 5686  // Macro instantiation is lexical, unfortunately. We construct a new buffer5687  // to hold the macro body with substitutions.5688  SmallString<256> Buf;5689  raw_svector_ostream OS(Buf);5690 5691  StringRef Values = A[0][0].is(AsmToken::String) ? A[0][0].getStringContents()5692                                                  : A[0][0].getString();5693  for (std::size_t I = 0, End = Values.size(); I != End; ++I) {5694    MCAsmMacroArgument Arg;5695    Arg.emplace_back(AsmToken::Identifier, Values.substr(I, 1));5696 5697    // Note that the AtPseudoVariable is enabled for instantiations of .irpc.5698    // This is undocumented, but GAS seems to support it.5699    if (expandMacro(OS, *M, Parameter, Arg, true))5700      return true;5701  }5702 5703  instantiateMacroLikeBody(M, DirectiveLoc, OS);5704 5705  return false;5706}5707 5708bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {5709  if (ActiveMacros.empty())5710    return TokError("unmatched '.endr' directive");5711 5712  // The only .repl that should get here are the ones created by5713  // instantiateMacroLikeBody.5714  assert(getLexer().is(AsmToken::EndOfStatement));5715 5716  handleMacroExit();5717  return false;5718}5719 5720bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,5721                                     size_t Len) {5722  const MCExpr *Value;5723  SMLoc ExprLoc = getLexer().getLoc();5724  if (parseExpression(Value))5725    return true;5726  const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);5727  if (!MCE)5728    return Error(ExprLoc, "unexpected expression in _emit");5729  uint64_t IntValue = MCE->getValue();5730  if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))5731    return Error(ExprLoc, "literal value out of range for directive");5732 5733  Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);5734  return false;5735}5736 5737bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {5738  const MCExpr *Value;5739  SMLoc ExprLoc = getLexer().getLoc();5740  if (parseExpression(Value))5741    return true;5742  const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);5743  if (!MCE)5744    return Error(ExprLoc, "unexpected expression in align");5745  uint64_t IntValue = MCE->getValue();5746  if (!isPowerOf2_64(IntValue))5747    return Error(ExprLoc, "literal value not a power of two greater then zero");5748 5749  Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));5750  return false;5751}5752 5753bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {5754  const AsmToken StrTok = getTok();5755  Lex();5756  if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"')5757    return Error(DirectiveLoc, "expected double quoted string after .print");5758  if (parseEOL())5759    return true;5760  llvm::outs() << StrTok.getStringContents() << '\n';5761  return false;5762}5763 5764bool AsmParser::parseDirectiveAddrsig() {5765  if (parseEOL())5766    return true;5767  getStreamer().emitAddrsig();5768  return false;5769}5770 5771bool AsmParser::parseDirectiveAddrsigSym() {5772  MCSymbol *Sym;5773  if (check(parseSymbol(Sym), "expected identifier") || parseEOL())5774    return true;5775  getStreamer().emitAddrsigSym(Sym);5776  return false;5777}5778 5779bool AsmParser::parseDirectivePseudoProbe() {5780  int64_t Guid;5781  int64_t Index;5782  int64_t Type;5783  int64_t Attr;5784  int64_t Discriminator = 0;5785  if (parseIntToken(Guid))5786    return true;5787  if (parseIntToken(Index))5788    return true;5789  if (parseIntToken(Type))5790    return true;5791  if (parseIntToken(Attr))5792    return true;5793  if (hasDiscriminator(Attr) && parseIntToken(Discriminator))5794    return true;5795 5796  // Parse inline stack like @ GUID:11:12 @ GUID:1:11 @ GUID:3:215797  MCPseudoProbeInlineStack InlineStack;5798 5799  while (getLexer().is(AsmToken::At)) {5800    // eat @5801    Lex();5802 5803    int64_t CallerGuid = 0;5804    if (getLexer().is(AsmToken::Integer)) {5805      CallerGuid = getTok().getIntVal();5806      Lex();5807    }5808 5809    // eat colon5810    if (getLexer().is(AsmToken::Colon))5811      Lex();5812 5813    int64_t CallerProbeId = 0;5814    if (getLexer().is(AsmToken::Integer)) {5815      CallerProbeId = getTok().getIntVal();5816      Lex();5817    }5818 5819    InlineSite Site(CallerGuid, CallerProbeId);5820    InlineStack.push_back(Site);5821  }5822 5823  // Parse function entry name5824  StringRef FnName;5825  if (parseIdentifier(FnName))5826    return Error(getLexer().getLoc(), "expected identifier");5827  MCSymbol *FnSym = getContext().lookupSymbol(FnName);5828 5829  if (parseEOL())5830    return true;5831 5832  getStreamer().emitPseudoProbe(Guid, Index, Type, Attr, Discriminator,5833                                InlineStack, FnSym);5834  return false;5835}5836 5837/// parseDirectiveLTODiscard5838///  ::= ".lto_discard" [ identifier ( , identifier )* ]5839/// The LTO library emits this directive to discard non-prevailing symbols.5840/// We ignore symbol assignments and attribute changes for the specified5841/// symbols.5842bool AsmParser::parseDirectiveLTODiscard() {5843  auto ParseOp = [&]() -> bool {5844    StringRef Name;5845    SMLoc Loc = getTok().getLoc();5846    if (parseIdentifier(Name))5847      return Error(Loc, "expected identifier");5848    LTODiscardSymbols.insert(Name);5849    return false;5850  };5851 5852  LTODiscardSymbols.clear();5853  return parseMany(ParseOp);5854}5855 5856// We are comparing pointers, but the pointers are relative to a single string.5857// Thus, this should always be deterministic.5858static int rewritesSort(const AsmRewrite *AsmRewriteA,5859                        const AsmRewrite *AsmRewriteB) {5860  if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())5861    return -1;5862  if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())5863    return 1;5864 5865  // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output5866  // rewrite to the same location.  Make sure the SizeDirective rewrite is5867  // performed first, then the Imm/ImmPrefix and finally the Input/Output.  This5868  // ensures the sort algorithm is stable.5869  if (AsmRewritePrecedence[AsmRewriteA->Kind] >5870      AsmRewritePrecedence[AsmRewriteB->Kind])5871    return -1;5872 5873  if (AsmRewritePrecedence[AsmRewriteA->Kind] <5874      AsmRewritePrecedence[AsmRewriteB->Kind])5875    return 1;5876  llvm_unreachable("Unstable rewrite sort.");5877}5878 5879bool AsmParser::parseMSInlineAsm(5880    std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs,5881    SmallVectorImpl<std::pair<void *, bool>> &OpDecls,5882    SmallVectorImpl<std::string> &Constraints,5883    SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,5884    MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {5885  SmallVector<void *, 4> InputDecls;5886  SmallVector<void *, 4> OutputDecls;5887  SmallVector<bool, 4> InputDeclsAddressOf;5888  SmallVector<bool, 4> OutputDeclsAddressOf;5889  SmallVector<std::string, 4> InputConstraints;5890  SmallVector<std::string, 4> OutputConstraints;5891  SmallVector<MCRegister, 4> ClobberRegs;5892 5893  SmallVector<AsmRewrite, 4> AsmStrRewrites;5894 5895  // Prime the lexer.5896  Lex();5897 5898  // While we have input, parse each statement.5899  unsigned InputIdx = 0;5900  unsigned OutputIdx = 0;5901  while (getLexer().isNot(AsmToken::Eof)) {5902    // Parse curly braces marking block start/end5903    if (parseCurlyBlockScope(AsmStrRewrites))5904      continue;5905 5906    ParseStatementInfo Info(&AsmStrRewrites);5907    bool StatementErr = parseStatement(Info, &SI);5908 5909    if (StatementErr || Info.ParseError) {5910      // Emit pending errors if any exist.5911      printPendingErrors();5912      return true;5913    }5914 5915    // No pending error should exist here.5916    assert(!hasPendingError() && "unexpected error from parseStatement");5917 5918    if (Info.Opcode == ~0U)5919      continue;5920 5921    const MCInstrDesc &Desc = MII->get(Info.Opcode);5922 5923    // Build the list of clobbers, outputs and inputs.5924    for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {5925      MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];5926 5927      // Register operand.5928      if (Operand.isReg() && !Operand.needAddressOf() &&5929          !getTargetParser().omitRegisterFromClobberLists(Operand.getReg())) {5930        unsigned NumDefs = Desc.getNumDefs();5931        // Clobber.5932        if (NumDefs && Operand.getMCOperandNum() < NumDefs)5933          ClobberRegs.push_back(Operand.getReg());5934        continue;5935      }5936 5937      // Expr/Input or Output.5938      StringRef SymName = Operand.getSymName();5939      if (SymName.empty())5940        continue;5941 5942      void *OpDecl = Operand.getOpDecl();5943      if (!OpDecl)5944        continue;5945 5946      StringRef Constraint = Operand.getConstraint();5947      if (Operand.isImm()) {5948        // Offset as immediate5949        if (Operand.isOffsetOfLocal())5950          Constraint = "r";5951        else5952          Constraint = "i";5953      }5954 5955      bool isOutput = (i == 1) && Desc.mayStore();5956      bool Restricted = Operand.isMemUseUpRegs();5957      SMLoc Start = SMLoc::getFromPointer(SymName.data());5958      if (isOutput) {5959        ++InputIdx;5960        OutputDecls.push_back(OpDecl);5961        OutputDeclsAddressOf.push_back(Operand.needAddressOf());5962        OutputConstraints.push_back(("=" + Constraint).str());5963        AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size(), 0,5964                                    Restricted);5965      } else {5966        InputDecls.push_back(OpDecl);5967        InputDeclsAddressOf.push_back(Operand.needAddressOf());5968        InputConstraints.push_back(Constraint.str());5969        if (Desc.operands()[i - 1].isBranchTarget())5970          AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size(), 0,5971                                      Restricted);5972        else5973          AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size(), 0,5974                                      Restricted);5975      }5976    }5977 5978    // Consider implicit defs to be clobbers.  Think of cpuid and push.5979    llvm::append_range(ClobberRegs, Desc.implicit_defs());5980  }5981 5982  // Set the number of Outputs and Inputs.5983  NumOutputs = OutputDecls.size();5984  NumInputs = InputDecls.size();5985 5986  // Set the unique clobbers.5987  array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());5988  ClobberRegs.erase(llvm::unique(ClobberRegs), ClobberRegs.end());5989  Clobbers.assign(ClobberRegs.size(), std::string());5990  for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {5991    raw_string_ostream OS(Clobbers[I]);5992    IP->printRegName(OS, ClobberRegs[I]);5993  }5994 5995  // Merge the various outputs and inputs.  Output are expected first.5996  if (NumOutputs || NumInputs) {5997    unsigned NumExprs = NumOutputs + NumInputs;5998    OpDecls.resize(NumExprs);5999    Constraints.resize(NumExprs);6000    for (unsigned i = 0; i < NumOutputs; ++i) {6001      OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);6002      Constraints[i] = OutputConstraints[i];6003    }6004    for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {6005      OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);6006      Constraints[j] = InputConstraints[i];6007    }6008  }6009 6010  // Build the IR assembly string.6011  std::string AsmStringIR;6012  raw_string_ostream OS(AsmStringIR);6013  StringRef ASMString =6014      SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer();6015  const char *AsmStart = ASMString.begin();6016  const char *AsmEnd = ASMString.end();6017  array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);6018  for (auto I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) {6019    const AsmRewrite &AR = *I;6020    // Check if this has already been covered by another rewrite...6021    if (AR.Done)6022      continue;6023    AsmRewriteKind Kind = AR.Kind;6024 6025    const char *Loc = AR.Loc.getPointer();6026    assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");6027 6028    // Emit everything up to the immediate/expression.6029    if (unsigned Len = Loc - AsmStart)6030      OS << StringRef(AsmStart, Len);6031 6032    // Skip the original expression.6033    if (Kind == AOK_Skip) {6034      AsmStart = Loc + AR.Len;6035      continue;6036    }6037 6038    unsigned AdditionalSkip = 0;6039    // Rewrite expressions in $N notation.6040    switch (Kind) {6041    default:6042      break;6043    case AOK_IntelExpr:6044      assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");6045      if (AR.IntelExp.NeedBracs)6046        OS << "[";6047      if (AR.IntelExp.hasBaseReg())6048        OS << AR.IntelExp.BaseReg;6049      if (AR.IntelExp.hasIndexReg())6050        OS << (AR.IntelExp.hasBaseReg() ? " + " : "")6051           << AR.IntelExp.IndexReg;6052      if (AR.IntelExp.Scale > 1)6053        OS << " * $$" << AR.IntelExp.Scale;6054      if (AR.IntelExp.hasOffset()) {6055        if (AR.IntelExp.hasRegs())6056          OS << " + ";6057        // Fuse this rewrite with a rewrite of the offset name, if present.6058        StringRef OffsetName = AR.IntelExp.OffsetName;6059        SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());6060        size_t OffsetLen = OffsetName.size();6061        auto rewrite_it = std::find_if(6062            I, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {6063              return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&6064                     (FusingAR.Kind == AOK_Input ||6065                      FusingAR.Kind == AOK_CallInput);6066            });6067        if (rewrite_it == AsmStrRewrites.end()) {6068          OS << "offset " << OffsetName;6069        } else if (rewrite_it->Kind == AOK_CallInput) {6070          OS << "${" << InputIdx++ << ":P}";6071          rewrite_it->Done = true;6072        } else {6073          OS << '$' << InputIdx++;6074          rewrite_it->Done = true;6075        }6076      }6077      if (AR.IntelExp.Imm || AR.IntelExp.emitImm())6078        OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;6079      if (AR.IntelExp.NeedBracs)6080        OS << "]";6081      break;6082    case AOK_Label:6083      OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;6084      break;6085    case AOK_Input:6086      if (AR.IntelExpRestricted)6087        OS << "${" << InputIdx++ << ":P}";6088      else6089        OS << '$' << InputIdx++;6090      break;6091    case AOK_CallInput:6092      OS << "${" << InputIdx++ << ":P}";6093      break;6094    case AOK_Output:6095      if (AR.IntelExpRestricted)6096        OS << "${" << OutputIdx++ << ":P}";6097      else6098        OS << '$' << OutputIdx++;6099      break;6100    case AOK_SizeDirective:6101      switch (AR.Val) {6102      default: break;6103      case 8:  OS << "byte ptr "; break;6104      case 16: OS << "word ptr "; break;6105      case 32: OS << "dword ptr "; break;6106      case 64: OS << "qword ptr "; break;6107      case 80: OS << "xword ptr "; break;6108      case 128: OS << "xmmword ptr "; break;6109      case 256: OS << "ymmword ptr "; break;6110      }6111      break;6112    case AOK_Emit:6113      OS << ".byte";6114      break;6115    case AOK_Align: {6116      // MS alignment directives are measured in bytes. If the native assembler6117      // measures alignment in bytes, we can pass it straight through.6118      OS << ".align";6119      if (getContext().getAsmInfo()->getAlignmentIsInBytes())6120        break;6121 6122      // Alignment is in log2 form, so print that instead and skip the original6123      // immediate.6124      unsigned Val = AR.Val;6125      OS << ' ' << Val;6126      assert(Val < 10 && "Expected alignment less then 2^10.");6127      AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;6128      break;6129    }6130    case AOK_EVEN:6131      OS << ".even";6132      break;6133    case AOK_EndOfStatement:6134      OS << "\n\t";6135      break;6136    }6137 6138    // Skip the original expression.6139    AsmStart = Loc + AR.Len + AdditionalSkip;6140  }6141 6142  // Emit the remainder of the asm string.6143  if (AsmStart != AsmEnd)6144    OS << StringRef(AsmStart, AsmEnd - AsmStart);6145 6146  AsmString = std::move(AsmStringIR);6147  return false;6148}6149 6150bool HLASMAsmParser::parseAsHLASMLabel(ParseStatementInfo &Info,6151                                       MCAsmParserSemaCallback *SI) {6152  AsmToken LabelTok = getTok();6153  SMLoc LabelLoc = LabelTok.getLoc();6154  StringRef LabelVal;6155 6156  if (parseIdentifier(LabelVal))6157    return Error(LabelLoc, "The HLASM Label has to be an Identifier");6158 6159  // We have validated whether the token is an Identifier.6160  // Now we have to validate whether the token is a6161  // valid HLASM Label.6162  if (!getTargetParser().isLabel(LabelTok) || checkForValidSection())6163    return true;6164 6165  // Lex leading spaces to get to the next operand.6166  lexLeadingSpaces();6167 6168  // We shouldn't emit the label if there is nothing else after the label.6169  // i.e asm("<token>\n")6170  if (getTok().is(AsmToken::EndOfStatement))6171    return Error(LabelLoc,6172                 "Cannot have just a label for an HLASM inline asm statement");6173 6174  MCSymbol *Sym = getContext().parseSymbol(6175      getContext().getAsmInfo()->isHLASM() ? LabelVal.upper() : LabelVal);6176 6177  // Emit the label.6178  Out.emitLabel(Sym, LabelLoc);6179 6180  // If we are generating dwarf for assembly source files then gather the6181  // info to make a dwarf label entry for this label if needed.6182  if (enabledGenDwarfForAssembly())6183    MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),6184                               LabelLoc);6185 6186  return false;6187}6188 6189bool HLASMAsmParser::parseAsMachineInstruction(ParseStatementInfo &Info,6190                                               MCAsmParserSemaCallback *SI) {6191  AsmToken OperationEntryTok = Lexer.getTok();6192  SMLoc OperationEntryLoc = OperationEntryTok.getLoc();6193  StringRef OperationEntryVal;6194 6195  // Attempt to parse the first token as an Identifier6196  if (parseIdentifier(OperationEntryVal))6197    return Error(OperationEntryLoc, "unexpected token at start of statement");6198 6199  // Once we've parsed the operation entry successfully, lex6200  // any spaces to get to the OperandEntries.6201  lexLeadingSpaces();6202 6203  return parseAndMatchAndEmitTargetInstruction(6204      Info, OperationEntryVal, OperationEntryTok, OperationEntryLoc);6205}6206 6207bool HLASMAsmParser::parseStatement(ParseStatementInfo &Info,6208                                    MCAsmParserSemaCallback *SI) {6209  assert(!hasPendingError() && "parseStatement started with pending error");6210 6211  // Should the first token be interpreted as a HLASM Label.6212  bool ShouldParseAsHLASMLabel = false;6213 6214  // If a Name Entry exists, it should occur at the very6215  // start of the string. In this case, we should parse the6216  // first non-space token as a Label.6217  // If the Name entry is missing (i.e. there's some other6218  // token), then we attempt to parse the first non-space6219  // token as a Machine Instruction.6220  if (getTok().isNot(AsmToken::Space))6221    ShouldParseAsHLASMLabel = true;6222 6223  // If we have an EndOfStatement (which includes the target's comment6224  // string) we can appropriately lex it early on)6225  if (Lexer.is(AsmToken::EndOfStatement)) {6226    // if this is a line comment we can drop it safely6227    if (getTok().getString().empty() || getTok().getString().front() == '\r' ||6228        getTok().getString().front() == '\n')6229      Out.addBlankLine();6230    Lex();6231    return false;6232  }6233 6234  // We have established how to parse the inline asm statement.6235  // Now we can safely lex any leading spaces to get to the6236  // first token.6237  lexLeadingSpaces();6238 6239  // If we see a new line or carriage return as the first operand,6240  // after lexing leading spaces, emit the new line and lex the6241  // EndOfStatement token.6242  if (Lexer.is(AsmToken::EndOfStatement)) {6243    if (getTok().getString().front() == '\n' ||6244        getTok().getString().front() == '\r') {6245      Out.addBlankLine();6246      Lex();6247      return false;6248    }6249  }6250 6251  // Handle the label first if we have to before processing the rest6252  // of the tokens as a machine instruction.6253  if (ShouldParseAsHLASMLabel) {6254    // If there were any errors while handling and emitting the label,6255    // early return.6256    if (parseAsHLASMLabel(Info, SI)) {6257      // If we know we've failed in parsing, simply eat until end of the6258      // statement. This ensures that we don't process any other statements.6259      eatToEndOfStatement();6260      return true;6261    }6262  }6263 6264  return parseAsMachineInstruction(Info, SI);6265}6266 6267// Structural equality of two assembler-assignment expressions. Used only to6268// decide whether a repeated wasm "=" / ".set" assignment is an identical6269// (idempotent) redefinition; it must never report two genuinely-different6270// expressions as equal (that would silently merge a conflict). Conservative:6271// anything it cannot prove equal is treated as different.6272static bool isEquivalentAssignment(const MCExpr *A, const MCExpr *B) {6273  if (A == B)6274    return true;6275  if (!A || !B || A->getKind() != B->getKind())6276    return false;6277  switch (A->getKind()) {6278  case MCExpr::Constant:6279    return cast<MCConstantExpr>(A)->getValue() ==6280           cast<MCConstantExpr>(B)->getValue();6281  case MCExpr::SymbolRef: {6282    const auto *SA = cast<MCSymbolRefExpr>(A);6283    const auto *SB = cast<MCSymbolRefExpr>(B);6284    return &SA->getSymbol() == &SB->getSymbol() &&6285           SA->getSpecifier() == SB->getSpecifier();6286  }6287  case MCExpr::Unary: {6288    const auto *UA = cast<MCUnaryExpr>(A);6289    const auto *UB = cast<MCUnaryExpr>(B);6290    return UA->getOpcode() == UB->getOpcode() &&6291           isEquivalentAssignment(UA->getSubExpr(), UB->getSubExpr());6292  }6293  case MCExpr::Binary: {6294    const auto *BA = cast<MCBinaryExpr>(A);6295    const auto *BB = cast<MCBinaryExpr>(B);6296    return BA->getOpcode() == BB->getOpcode() &&6297           isEquivalentAssignment(BA->getLHS(), BB->getLHS()) &&6298           isEquivalentAssignment(BA->getRHS(), BB->getRHS());6299  }6300  case MCExpr::Specifier: {6301    const auto *PA = cast<MCSpecifierExpr>(A);6302    const auto *PB = cast<MCSpecifierExpr>(B);6303    return PA->getSpecifier() == PB->getSpecifier() &&6304           isEquivalentAssignment(PA->getSubExpr(), PB->getSubExpr());6305  }6306  case MCExpr::Target:6307    // Target-specific expressions have no generic comparison; treat distinct6308    // instances as different so a conflict is never silently accepted.6309    return false;6310  }6311  llvm_unreachable("invalid MCExpr kind");6312}6313 6314bool llvm::MCParserUtils::parseAssignmentExpression(StringRef Name,6315                                                    bool allow_redef,6316                                                    MCAsmParser &Parser,6317                                                    MCSymbol *&Sym,6318                                                    const MCExpr *&Value) {6319 6320  // FIXME: Use better location, we should use proper tokens.6321  SMLoc EqualLoc = Parser.getTok().getLoc();6322  if (Parser.parseExpression(Value))6323    return Parser.TokError("missing expression");6324  if (Parser.parseEOL())6325    return true;6326  // Relocation specifiers are not permitted. For now, handle just6327  // MCSymbolRefExpr.6328  if (auto *S = dyn_cast<MCSymbolRefExpr>(Value); S && S->getSpecifier())6329    return Parser.Error(6330        EqualLoc, "relocation specifier not permitted in symbol equating");6331 6332  // Validate that the LHS is allowed to be a variable (either it has not been6333  // used as a symbol, or it is an absolute symbol).6334  Sym = Parser.getContext().lookupSymbol(Name);6335  if (Sym) {6336    // wasm: an absolute-constant assignment ("sym = N" / ".set sym, N", no6337    // symbol reference) was lowered to a *defined data object* holding the6338    // constant (MCWasmStreamer::emitAssignment, 751ce8312), so the symbol is no6339    // longer a redefinable variable. glibc emits exactly this for address-taken6340    // linkage markers (e.g. _nl_current_LC_*_used from _NL_CURRENT_DEFINE in6341    // locale/localeinfo.h, x12 LC_* per locale TU), and llvm-link concatenates6342    // the per-TU module-asm without dedup, so the merged module carries several6343    // identical "sym = N" definitions. The first lowers to the data object;6344    // each later one reaches here as a redefinition of a now-defined label and6345    // used to fail loudly ("redefinition of 'sym'"), the surviving duplicate-6346    // definition consequence of the data-object lowering.6347    //6348    // Mirror the alias idempotence (66319942b) for this absolute-constant form,6349    // matching GNU-as where "=" / ".set" is freely reassignable and an identical6350    // reassignment is a no-op: a repeat to the *same* constant is accepted as6351    // idempotent (Sym is cleared so the caller skips re-emitting the label; the6352    // single data object already holds the value), and a repeat to a *different*6353    // value is a genuine conflict that is still rejected loudly -- never-silent,6354    // we never pick one of two differing definitions. wasm-guarded; ELF/COFF/6355    // MachO and the symbol-alias case are untouched. (HWJS-B-1; same module-asm6356    // family as 4f7e79cc9 / ad022aa91 / 751ce8312 / e55169103 / 3cfbb7dd5 /6357    // 66319942b.)6358    if (Parser.getContext().getObjectFileType() == MCContext::IsWasm &&6359        Sym->isDefined() && !Sym->isVariable()) {6360      if (auto *WS = static_cast<MCSymbolWasm *>(Sym);6361          WS->hasAbsoluteConstant()) {6362        int64_t NewConst;6363        if (Value->evaluateAsAbsolute(NewConst) &&6364            NewConst == WS->getAbsoluteConstant()) {6365          // Identical repeat: keep the single existing data object, emit6366          // nothing more.6367          Sym = nullptr;6368          return false;6369        }6370        return Parser.Error(6371            EqualLoc, "conflicting redefinition of '" + Name +6372                          "' (wasm: an absolute-constant '=' / '.set' may be "6373                          "repeated only with an identical value)");6374      }6375    }6376    if ((Sym->isVariable() || Sym->isDefined()) &&6377        (!allow_redef || !Sym->isRedefinable()))6378      return Parser.Error(EqualLoc, "redefinition of '" + Name + "'");6379    // If the symbol is redefinable, clone it and update the symbol table6380    // to the new symbol. Existing references to the original symbol remain6381    // unchanged.6382    if (Sym->isRedefinable()) {6383      // The wasm object format has no MCSymbol clone path: MCContext::cloneSymbol6384      // aborts with "fatal error: .set redefinition is not supported" for6385      // IsWasm. This is hit en masse when many glibc translation units are6386      // merged into one bitcode module with llvm-link: each TU emits the same6387      // module-level asm symbol assignment (e.g. "mempcpy = __mempcpy" from6388      // libc_hidden_def / weak_alias / __GI_ / <string.h> builtins), and the6389      // merged module's module-asm blocks are concatenated without dedup, so the6390      // identical "X = Y" appears more than once and the second one reaches this6391      // clone.6392      //6393      // Match GNU-as semantics, where "=" / ".set" is freely reassignable and an6394      // identical reassignment is a no-op: accept a redefinition to the *same*6395      // value as idempotent (keep the existing symbol; the caller re-emits the6396      // identical value harmlessly). A redefinition to a *different* value is a6397      // genuine conflict and is still rejected loudly -- never silently pick one.6398      // wasm-guarded; ELF/COFF/MachO keep their existing clone-based semantics.6399      // (HWJS-B-1; same X=Y module-asm family as 4f7e79cc9 / ad022aa91 /6400      // 751ce8312 / e55169103 / 3cfbb7dd5.)6401      if (Parser.getContext().getObjectFileType() == MCContext::IsWasm &&6402          Sym->isVariable()) {6403        if (isEquivalentAssignment(Sym->getVariableValue(), Value)) {6404          Sym->setRedefinable(allow_redef);6405          return false;6406        }6407        return Parser.Error(6408            EqualLoc, "conflicting redefinition of '" + Name +6409                          "' (wasm: '=' / '.set' may be repeated only with an "6410                          "identical value)");6411      }6412      Sym = Parser.getContext().cloneSymbol(*Sym);6413    }6414  } else if (Name == ".") {6415    Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc);6416    return false;6417  } else6418    Sym = Parser.getContext().parseSymbol(Name);6419 6420  Sym->setRedefinable(allow_redef);6421 6422  return false;6423}6424 6425/// Create an MCAsmParser instance.6426MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,6427                                     MCStreamer &Out, const MCAsmInfo &MAI,6428                                     unsigned CB) {6429  if (C.getTargetTriple().isSystemZ() && C.getTargetTriple().isOSzOS())6430    return new HLASMAsmParser(SM, C, Out, MAI, CB);6431 6432  return new AsmParser(SM, C, Out, MAI, CB);6433}6434