10b57cec5SDimitry Andric //===- AsmParser.cpp - Parser for Assembly Files --------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 95ffd83dbSDimitry Andric // This class implements a parser for assembly files similar to gas syntax. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h" 140b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 150b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 160b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 17fe6060f1SDimitry Andric #include "llvm/ADT/SmallSet.h" 180b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 190b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 200b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 210b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h" 220b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 230b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 240b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 258bcb0991SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 260b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 270b57cec5SDimitry Andric #include "llvm/MC/MCCodeView.h" 280b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 290b57cec5SDimitry Andric #include "llvm/MC/MCDirectives.h" 300b57cec5SDimitry Andric #include "llvm/MC/MCDwarf.h" 310b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 320b57cec5SDimitry Andric #include "llvm/MC/MCInstPrinter.h" 330b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 340b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 350b57cec5SDimitry Andric #include "llvm/MC/MCParser/AsmCond.h" 360b57cec5SDimitry Andric #include "llvm/MC/MCParser/AsmLexer.h" 370b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h" 380b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParser.h" 390b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParserExtension.h" 400b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParserUtils.h" 410b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 420b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h" 430b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 440b57cec5SDimitry Andric #include "llvm/MC/MCSection.h" 450b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 460b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h" 47439352acSDimitry Andric #include "llvm/MC/MCSymbolMachO.h" 480b57cec5SDimitry Andric #include "llvm/MC/MCTargetOptions.h" 490b57cec5SDimitry Andric #include "llvm/MC/MCValue.h" 500b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 510b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 520b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 530b57cec5SDimitry Andric #include "llvm/Support/MD5.h" 540b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 550b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 560b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h" 570b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h" 580b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 590b57cec5SDimitry Andric #include <algorithm> 600b57cec5SDimitry Andric #include <cassert> 610b57cec5SDimitry Andric #include <cctype> 620b57cec5SDimitry Andric #include <climits> 630b57cec5SDimitry Andric #include <cstddef> 640b57cec5SDimitry Andric #include <cstdint> 650b57cec5SDimitry Andric #include <deque> 660b57cec5SDimitry Andric #include <memory> 67bdd1243dSDimitry Andric #include <optional> 680b57cec5SDimitry Andric #include <sstream> 690b57cec5SDimitry Andric #include <string> 700b57cec5SDimitry Andric #include <tuple> 710b57cec5SDimitry Andric #include <utility> 720b57cec5SDimitry Andric #include <vector> 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric using namespace llvm; 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric MCAsmParserSemaCallback::~MCAsmParserSemaCallback() = default; 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric namespace { 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric /// Helper types for tracking macro definitions. 810b57cec5SDimitry Andric typedef std::vector<AsmToken> MCAsmMacroArgument; 820b57cec5SDimitry Andric typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments; 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric /// Helper class for storing information about an active macro 850b57cec5SDimitry Andric /// instantiation. 860b57cec5SDimitry Andric struct MacroInstantiation { 870b57cec5SDimitry Andric /// The location of the instantiation. 880b57cec5SDimitry Andric SMLoc InstantiationLoc; 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric /// The buffer where parsing should resume upon instantiation completion. 91480093f4SDimitry Andric unsigned ExitBuffer; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric /// The location where parsing should resume upon instantiation completion. 940b57cec5SDimitry Andric SMLoc ExitLoc; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric /// The depth of TheCondStack at the start of the instantiation. 970b57cec5SDimitry Andric size_t CondStackDepth; 980b57cec5SDimitry Andric }; 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric struct ParseStatementInfo { 1010b57cec5SDimitry Andric /// The parsed operands from the last parsed statement. 1020b57cec5SDimitry Andric SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric /// The opcode from the last parsed instruction. 1050b57cec5SDimitry Andric unsigned Opcode = ~0U; 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric /// Was there an error parsing the inline assembly? 1080b57cec5SDimitry Andric bool ParseError = false; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr; 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric ParseStatementInfo() = delete; 1130b57cec5SDimitry Andric ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites) 1140b57cec5SDimitry Andric : AsmRewrites(rewrites) {} 1150b57cec5SDimitry Andric }; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric /// The concrete assembly parser instance. 1180b57cec5SDimitry Andric class AsmParser : public MCAsmParser { 1190b57cec5SDimitry Andric private: 1200b57cec5SDimitry Andric AsmLexer Lexer; 1210b57cec5SDimitry Andric MCContext &Ctx; 1220b57cec5SDimitry Andric MCStreamer &Out; 1230b57cec5SDimitry Andric const MCAsmInfo &MAI; 1240b57cec5SDimitry Andric SourceMgr &SrcMgr; 1250b57cec5SDimitry Andric SourceMgr::DiagHandlerTy SavedDiagHandler; 1260b57cec5SDimitry Andric void *SavedDiagContext; 1270b57cec5SDimitry Andric std::unique_ptr<MCAsmParserExtension> PlatformParser; 128e8d8bef9SDimitry Andric SMLoc StartTokLoc; 1295f757f3fSDimitry Andric std::optional<SMLoc> CFIStartProcLoc; 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric /// This is the current buffer index we're lexing from as managed by the 1320b57cec5SDimitry Andric /// SourceMgr object. 1330b57cec5SDimitry Andric unsigned CurBuffer; 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric AsmCond TheCondState; 1360b57cec5SDimitry Andric std::vector<AsmCond> TheCondStack; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric /// maps directive names to handler methods in parser 1390b57cec5SDimitry Andric /// extensions. Extensions register themselves in this map by calling 1400b57cec5SDimitry Andric /// addDirectiveHandler. 1410b57cec5SDimitry Andric StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap; 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric /// Stack of active macro instantiations. 1440b57cec5SDimitry Andric std::vector<MacroInstantiation*> ActiveMacros; 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric /// List of bodies of anonymous macros. 1470b57cec5SDimitry Andric std::deque<MCAsmMacro> MacroLikeBodies; 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric /// Boolean tracking whether macro substitution is enabled. 1500b57cec5SDimitry Andric unsigned MacrosEnabledFlag : 1; 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric /// Keeps track of how many .macro's have been instantiated. 1530b57cec5SDimitry Andric unsigned NumOfMacroInstantiations; 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric /// The values from the last parsed cpp hash file line comment if any. 1560b57cec5SDimitry Andric struct CppHashInfoTy { 1570b57cec5SDimitry Andric StringRef Filename; 1580b57cec5SDimitry Andric int64_t LineNumber; 1590b57cec5SDimitry Andric SMLoc Loc; 1600b57cec5SDimitry Andric unsigned Buf; 16104eeddc0SDimitry Andric CppHashInfoTy() : LineNumber(0), Buf(0) {} 1620b57cec5SDimitry Andric }; 1630b57cec5SDimitry Andric CppHashInfoTy CppHashInfo; 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric /// The filename from the first cpp hash file line comment, if any. 1660b57cec5SDimitry Andric StringRef FirstCppHashFilename; 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric /// List of forward directional labels for diagnosis at the end. 1690b57cec5SDimitry Andric SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels; 1700b57cec5SDimitry Andric 171fe6060f1SDimitry Andric SmallSet<StringRef, 2> LTODiscardSymbols; 172fe6060f1SDimitry Andric 1730b57cec5SDimitry Andric /// AssemblerDialect. ~OU means unset value and use value provided by MAI. 1740b57cec5SDimitry Andric unsigned AssemblerDialect = ~0U; 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric /// is Darwin compatibility enabled? 1770b57cec5SDimitry Andric bool IsDarwin = false; 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric /// Are we parsing ms-style inline assembly? 1805ffd83dbSDimitry Andric bool ParsingMSInlineAsm = false; 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric /// Did we already inform the user about inconsistent MD5 usage? 1830b57cec5SDimitry Andric bool ReportedInconsistentMD5 = false; 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric // Is alt macro mode enabled. 1860b57cec5SDimitry Andric bool AltMacroMode = false; 1870b57cec5SDimitry Andric 188fe6060f1SDimitry Andric protected: 189fe6060f1SDimitry Andric virtual bool parseStatement(ParseStatementInfo &Info, 190fe6060f1SDimitry Andric MCAsmParserSemaCallback *SI); 191fe6060f1SDimitry Andric 192fe6060f1SDimitry Andric /// This routine uses the target specific ParseInstruction function to 193fe6060f1SDimitry Andric /// parse an instruction into Operands, and then call the target specific 194fe6060f1SDimitry Andric /// MatchAndEmit function to match and emit the instruction. 195fe6060f1SDimitry Andric bool parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info, 196fe6060f1SDimitry Andric StringRef IDVal, AsmToken ID, 197fe6060f1SDimitry Andric SMLoc IDLoc); 198fe6060f1SDimitry Andric 199fe6060f1SDimitry Andric /// Should we emit DWARF describing this assembler source? (Returns false if 200fe6060f1SDimitry Andric /// the source has .file directives, which means we don't want to generate 201fe6060f1SDimitry Andric /// info describing the assembler source itself.) 202fe6060f1SDimitry Andric bool enabledGenDwarfForAssembly(); 203fe6060f1SDimitry Andric 2040b57cec5SDimitry Andric public: 2050b57cec5SDimitry Andric AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, 2060b57cec5SDimitry Andric const MCAsmInfo &MAI, unsigned CB); 2070b57cec5SDimitry Andric AsmParser(const AsmParser &) = delete; 2080b57cec5SDimitry Andric AsmParser &operator=(const AsmParser &) = delete; 2090b57cec5SDimitry Andric ~AsmParser() override; 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric bool Run(bool NoInitialTextSection, bool NoFinalize = false) override; 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric void addDirectiveHandler(StringRef Directive, 2140b57cec5SDimitry Andric ExtensionDirectiveHandler Handler) override { 2150b57cec5SDimitry Andric ExtensionDirectiveMap[Directive] = Handler; 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric void addAliasForDirective(StringRef Directive, StringRef Alias) override { 2195ffd83dbSDimitry Andric DirectiveKindMap[Directive.lower()] = DirectiveKindMap[Alias.lower()]; 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric /// @name MCAsmParser Interface 2230b57cec5SDimitry Andric /// { 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric SourceMgr &getSourceManager() override { return SrcMgr; } 2260b57cec5SDimitry Andric MCAsmLexer &getLexer() override { return Lexer; } 2270b57cec5SDimitry Andric MCContext &getContext() override { return Ctx; } 2280b57cec5SDimitry Andric MCStreamer &getStreamer() override { return Out; } 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric CodeViewContext &getCVContext() { return Ctx.getCVContext(); } 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric unsigned getAssemblerDialect() override { 2330b57cec5SDimitry Andric if (AssemblerDialect == ~0U) 2340b57cec5SDimitry Andric return MAI.getAssemblerDialect(); 2350b57cec5SDimitry Andric else 2360b57cec5SDimitry Andric return AssemblerDialect; 2370b57cec5SDimitry Andric } 2380b57cec5SDimitry Andric void setAssemblerDialect(unsigned i) override { 2390b57cec5SDimitry Andric AssemblerDialect = i; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 242bdd1243dSDimitry Andric void Note(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt) override; 243bdd1243dSDimitry Andric bool Warning(SMLoc L, const Twine &Msg, 244bdd1243dSDimitry Andric SMRange Range = std::nullopt) override; 245bdd1243dSDimitry Andric bool printError(SMLoc L, const Twine &Msg, 246bdd1243dSDimitry Andric SMRange Range = std::nullopt) override; 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric const AsmToken &Lex() override; 2490b57cec5SDimitry Andric 2505ffd83dbSDimitry Andric void setParsingMSInlineAsm(bool V) override { 2515ffd83dbSDimitry Andric ParsingMSInlineAsm = V; 2520b57cec5SDimitry Andric // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and 2530b57cec5SDimitry Andric // hex integer literals. 2540b57cec5SDimitry Andric Lexer.setLexMasmIntegers(V); 2550b57cec5SDimitry Andric } 2565ffd83dbSDimitry Andric bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; } 2570b57cec5SDimitry Andric 258fe6060f1SDimitry Andric bool discardLTOSymbol(StringRef Name) const override { 259fe6060f1SDimitry Andric return LTODiscardSymbols.contains(Name); 260fe6060f1SDimitry Andric } 261fe6060f1SDimitry Andric 262fe6060f1SDimitry Andric bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs, 263fe6060f1SDimitry Andric unsigned &NumInputs, 2640b57cec5SDimitry Andric SmallVectorImpl<std::pair<void *, bool>> &OpDecls, 2650b57cec5SDimitry Andric SmallVectorImpl<std::string> &Constraints, 2660b57cec5SDimitry Andric SmallVectorImpl<std::string> &Clobbers, 2670b57cec5SDimitry Andric const MCInstrInfo *MII, const MCInstPrinter *IP, 2680b57cec5SDimitry Andric MCAsmParserSemaCallback &SI) override; 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric bool parseExpression(const MCExpr *&Res); 2710b57cec5SDimitry Andric bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override; 272e8d8bef9SDimitry Andric bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc, 273e8d8bef9SDimitry Andric AsmTypeInfo *TypeInfo) override; 2740b57cec5SDimitry Andric bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override; 2750b57cec5SDimitry Andric bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res, 2760b57cec5SDimitry Andric SMLoc &EndLoc) override; 2770b57cec5SDimitry Andric bool parseAbsoluteExpression(int64_t &Res) override; 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric /// Parse a floating point expression using the float \p Semantics 2800b57cec5SDimitry Andric /// and set \p Res to the value. 2810b57cec5SDimitry Andric bool parseRealValue(const fltSemantics &Semantics, APInt &Res); 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric /// Parse an identifier or string (as a quoted identifier) 2840b57cec5SDimitry Andric /// and set \p Res to the identifier contents. 2850b57cec5SDimitry Andric bool parseIdentifier(StringRef &Res) override; 2860b57cec5SDimitry Andric void eatToEndOfStatement() override; 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric bool checkForValidSection() override; 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric /// } 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric private: 2930b57cec5SDimitry Andric bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites); 2945ffd83dbSDimitry Andric bool parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo = true); 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body, 2970b57cec5SDimitry Andric ArrayRef<MCAsmMacroParameter> Parameters); 298*0fca6ea1SDimitry Andric bool expandMacro(raw_svector_ostream &OS, MCAsmMacro &Macro, 2990b57cec5SDimitry Andric ArrayRef<MCAsmMacroParameter> Parameters, 300*0fca6ea1SDimitry Andric ArrayRef<MCAsmMacroArgument> A, bool EnableAtPseudoVariable); 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric /// Are macros enabled in the parser? 3030b57cec5SDimitry Andric bool areMacrosEnabled() {return MacrosEnabledFlag;} 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric /// Control a flag in the parser that enables or disables macros. 3060b57cec5SDimitry Andric void setMacrosEnabled(bool Flag) {MacrosEnabledFlag = Flag;} 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric /// Are we inside a macro instantiation? 3090b57cec5SDimitry Andric bool isInsideMacroInstantiation() {return !ActiveMacros.empty();} 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric /// Handle entry to macro instantiation. 3120b57cec5SDimitry Andric /// 3130b57cec5SDimitry Andric /// \param M The macro. 3140b57cec5SDimitry Andric /// \param NameLoc Instantiation location. 315*0fca6ea1SDimitry Andric bool handleMacroEntry(MCAsmMacro *M, SMLoc NameLoc); 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric /// Handle exit from macro instantiation. 3180b57cec5SDimitry Andric void handleMacroExit(); 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric /// Extract AsmTokens for a macro argument. 3210b57cec5SDimitry Andric bool parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg); 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric /// Parse all macro arguments for a given macro. 3240b57cec5SDimitry Andric bool parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A); 3250b57cec5SDimitry Andric 3260b57cec5SDimitry Andric void printMacroInstantiations(); 3270b57cec5SDimitry Andric void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg, 328bdd1243dSDimitry Andric SMRange Range = std::nullopt) const { 3290b57cec5SDimitry Andric ArrayRef<SMRange> Ranges(Range); 3300b57cec5SDimitry Andric SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges); 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric static void DiagHandler(const SMDiagnostic &Diag, void *Context); 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric /// Enter the specified file. This returns true on failure. 3350b57cec5SDimitry Andric bool enterIncludeFile(const std::string &Filename); 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric /// Process the specified file for the .incbin directive. 3380b57cec5SDimitry Andric /// This returns true on failure. 3390b57cec5SDimitry Andric bool processIncbinFile(const std::string &Filename, int64_t Skip = 0, 3400b57cec5SDimitry Andric const MCExpr *Count = nullptr, SMLoc Loc = SMLoc()); 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric /// Reset the current lexer position to that given by \p Loc. The 3430b57cec5SDimitry Andric /// current token is not set; clients should ensure Lex() is called 3440b57cec5SDimitry Andric /// subsequently. 3450b57cec5SDimitry Andric /// 3460b57cec5SDimitry Andric /// \param InBuffer If not 0, should be the known buffer id that contains the 3470b57cec5SDimitry Andric /// location. 3480b57cec5SDimitry Andric void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0); 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric /// Parse up to the end of statement and a return the contents from the 3510b57cec5SDimitry Andric /// current token until the end of the statement; the current token on exit 3520b57cec5SDimitry Andric /// will be either the EndOfStatement or EOF. 3530b57cec5SDimitry Andric StringRef parseStringToEndOfStatement() override; 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric /// Parse until the end of a statement or a comma is encountered, 3560b57cec5SDimitry Andric /// return the contents from the current token up to the end or comma. 3570b57cec5SDimitry Andric StringRef parseStringToComma(); 3580b57cec5SDimitry Andric 3590eae32dcSDimitry Andric enum class AssignmentKind { 3600eae32dcSDimitry Andric Set, 3610eae32dcSDimitry Andric Equiv, 3620eae32dcSDimitry Andric Equal, 3630eae32dcSDimitry Andric LTOSetConditional, 3640eae32dcSDimitry Andric }; 3650eae32dcSDimitry Andric 3660eae32dcSDimitry Andric bool parseAssignment(StringRef Name, AssignmentKind Kind); 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric unsigned getBinOpPrecedence(AsmToken::TokenKind K, 3690b57cec5SDimitry Andric MCBinaryExpr::Opcode &Kind); 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc); 3720b57cec5SDimitry Andric bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc); 3730b57cec5SDimitry Andric bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc); 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc); 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName); 3780b57cec5SDimitry Andric bool parseCVFileId(int64_t &FileId, StringRef DirectiveName); 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric // Generic (target and platform independent) directive parsing. 3810b57cec5SDimitry Andric enum DirectiveKind { 3820b57cec5SDimitry Andric DK_NO_DIRECTIVE, // Placeholder 3830b57cec5SDimitry Andric DK_SET, 3840b57cec5SDimitry Andric DK_EQU, 3850b57cec5SDimitry Andric DK_EQUIV, 3860b57cec5SDimitry Andric DK_ASCII, 3870b57cec5SDimitry Andric DK_ASCIZ, 3880b57cec5SDimitry Andric DK_STRING, 3890b57cec5SDimitry Andric DK_BYTE, 3900b57cec5SDimitry Andric DK_SHORT, 3910b57cec5SDimitry Andric DK_RELOC, 3920b57cec5SDimitry Andric DK_VALUE, 3930b57cec5SDimitry Andric DK_2BYTE, 3940b57cec5SDimitry Andric DK_LONG, 3950b57cec5SDimitry Andric DK_INT, 3960b57cec5SDimitry Andric DK_4BYTE, 3970b57cec5SDimitry Andric DK_QUAD, 3980b57cec5SDimitry Andric DK_8BYTE, 3990b57cec5SDimitry Andric DK_OCTA, 4000b57cec5SDimitry Andric DK_DC, 4010b57cec5SDimitry Andric DK_DC_A, 4020b57cec5SDimitry Andric DK_DC_B, 4030b57cec5SDimitry Andric DK_DC_D, 4040b57cec5SDimitry Andric DK_DC_L, 4050b57cec5SDimitry Andric DK_DC_S, 4060b57cec5SDimitry Andric DK_DC_W, 4070b57cec5SDimitry Andric DK_DC_X, 4080b57cec5SDimitry Andric DK_DCB, 4090b57cec5SDimitry Andric DK_DCB_B, 4100b57cec5SDimitry Andric DK_DCB_D, 4110b57cec5SDimitry Andric DK_DCB_L, 4120b57cec5SDimitry Andric DK_DCB_S, 4130b57cec5SDimitry Andric DK_DCB_W, 4140b57cec5SDimitry Andric DK_DCB_X, 4150b57cec5SDimitry Andric DK_DS, 4160b57cec5SDimitry Andric DK_DS_B, 4170b57cec5SDimitry Andric DK_DS_D, 4180b57cec5SDimitry Andric DK_DS_L, 4190b57cec5SDimitry Andric DK_DS_P, 4200b57cec5SDimitry Andric DK_DS_S, 4210b57cec5SDimitry Andric DK_DS_W, 4220b57cec5SDimitry Andric DK_DS_X, 4230b57cec5SDimitry Andric DK_SINGLE, 4240b57cec5SDimitry Andric DK_FLOAT, 4250b57cec5SDimitry Andric DK_DOUBLE, 4260b57cec5SDimitry Andric DK_ALIGN, 4270b57cec5SDimitry Andric DK_ALIGN32, 4280b57cec5SDimitry Andric DK_BALIGN, 4290b57cec5SDimitry Andric DK_BALIGNW, 4300b57cec5SDimitry Andric DK_BALIGNL, 4310b57cec5SDimitry Andric DK_P2ALIGN, 4320b57cec5SDimitry Andric DK_P2ALIGNW, 4330b57cec5SDimitry Andric DK_P2ALIGNL, 4340b57cec5SDimitry Andric DK_ORG, 4350b57cec5SDimitry Andric DK_FILL, 4360b57cec5SDimitry Andric DK_ENDR, 4370b57cec5SDimitry Andric DK_BUNDLE_ALIGN_MODE, 4380b57cec5SDimitry Andric DK_BUNDLE_LOCK, 4390b57cec5SDimitry Andric DK_BUNDLE_UNLOCK, 4400b57cec5SDimitry Andric DK_ZERO, 4410b57cec5SDimitry Andric DK_EXTERN, 4420b57cec5SDimitry Andric DK_GLOBL, 4430b57cec5SDimitry Andric DK_GLOBAL, 4440b57cec5SDimitry Andric DK_LAZY_REFERENCE, 4450b57cec5SDimitry Andric DK_NO_DEAD_STRIP, 4460b57cec5SDimitry Andric DK_SYMBOL_RESOLVER, 4470b57cec5SDimitry Andric DK_PRIVATE_EXTERN, 4480b57cec5SDimitry Andric DK_REFERENCE, 4490b57cec5SDimitry Andric DK_WEAK_DEFINITION, 4500b57cec5SDimitry Andric DK_WEAK_REFERENCE, 4510b57cec5SDimitry Andric DK_WEAK_DEF_CAN_BE_HIDDEN, 4520b57cec5SDimitry Andric DK_COLD, 4530b57cec5SDimitry Andric DK_COMM, 4540b57cec5SDimitry Andric DK_COMMON, 4550b57cec5SDimitry Andric DK_LCOMM, 4560b57cec5SDimitry Andric DK_ABORT, 4570b57cec5SDimitry Andric DK_INCLUDE, 4580b57cec5SDimitry Andric DK_INCBIN, 4590b57cec5SDimitry Andric DK_CODE16, 4600b57cec5SDimitry Andric DK_CODE16GCC, 4610b57cec5SDimitry Andric DK_REPT, 4620b57cec5SDimitry Andric DK_IRP, 4630b57cec5SDimitry Andric DK_IRPC, 4640b57cec5SDimitry Andric DK_IF, 4650b57cec5SDimitry Andric DK_IFEQ, 4660b57cec5SDimitry Andric DK_IFGE, 4670b57cec5SDimitry Andric DK_IFGT, 4680b57cec5SDimitry Andric DK_IFLE, 4690b57cec5SDimitry Andric DK_IFLT, 4700b57cec5SDimitry Andric DK_IFNE, 4710b57cec5SDimitry Andric DK_IFB, 4720b57cec5SDimitry Andric DK_IFNB, 4730b57cec5SDimitry Andric DK_IFC, 4740b57cec5SDimitry Andric DK_IFEQS, 4750b57cec5SDimitry Andric DK_IFNC, 4760b57cec5SDimitry Andric DK_IFNES, 4770b57cec5SDimitry Andric DK_IFDEF, 4780b57cec5SDimitry Andric DK_IFNDEF, 4790b57cec5SDimitry Andric DK_IFNOTDEF, 4800b57cec5SDimitry Andric DK_ELSEIF, 4810b57cec5SDimitry Andric DK_ELSE, 4820b57cec5SDimitry Andric DK_ENDIF, 4830b57cec5SDimitry Andric DK_SPACE, 4840b57cec5SDimitry Andric DK_SKIP, 4850b57cec5SDimitry Andric DK_FILE, 4860b57cec5SDimitry Andric DK_LINE, 4870b57cec5SDimitry Andric DK_LOC, 4880b57cec5SDimitry Andric DK_STABS, 4890b57cec5SDimitry Andric DK_CV_FILE, 4900b57cec5SDimitry Andric DK_CV_FUNC_ID, 4910b57cec5SDimitry Andric DK_CV_INLINE_SITE_ID, 4920b57cec5SDimitry Andric DK_CV_LOC, 4930b57cec5SDimitry Andric DK_CV_LINETABLE, 4940b57cec5SDimitry Andric DK_CV_INLINE_LINETABLE, 4950b57cec5SDimitry Andric DK_CV_DEF_RANGE, 4960b57cec5SDimitry Andric DK_CV_STRINGTABLE, 4970b57cec5SDimitry Andric DK_CV_STRING, 4980b57cec5SDimitry Andric DK_CV_FILECHECKSUMS, 4990b57cec5SDimitry Andric DK_CV_FILECHECKSUM_OFFSET, 5000b57cec5SDimitry Andric DK_CV_FPO_DATA, 5010b57cec5SDimitry Andric DK_CFI_SECTIONS, 5020b57cec5SDimitry Andric DK_CFI_STARTPROC, 5030b57cec5SDimitry Andric DK_CFI_ENDPROC, 5040b57cec5SDimitry Andric DK_CFI_DEF_CFA, 5050b57cec5SDimitry Andric DK_CFI_DEF_CFA_OFFSET, 5060b57cec5SDimitry Andric DK_CFI_ADJUST_CFA_OFFSET, 5070b57cec5SDimitry Andric DK_CFI_DEF_CFA_REGISTER, 508fe6060f1SDimitry Andric DK_CFI_LLVM_DEF_ASPACE_CFA, 5090b57cec5SDimitry Andric DK_CFI_OFFSET, 5100b57cec5SDimitry Andric DK_CFI_REL_OFFSET, 5110b57cec5SDimitry Andric DK_CFI_PERSONALITY, 5120b57cec5SDimitry Andric DK_CFI_LSDA, 5130b57cec5SDimitry Andric DK_CFI_REMEMBER_STATE, 5140b57cec5SDimitry Andric DK_CFI_RESTORE_STATE, 5150b57cec5SDimitry Andric DK_CFI_SAME_VALUE, 5160b57cec5SDimitry Andric DK_CFI_RESTORE, 5170b57cec5SDimitry Andric DK_CFI_ESCAPE, 5180b57cec5SDimitry Andric DK_CFI_RETURN_COLUMN, 5190b57cec5SDimitry Andric DK_CFI_SIGNAL_FRAME, 5200b57cec5SDimitry Andric DK_CFI_UNDEFINED, 5210b57cec5SDimitry Andric DK_CFI_REGISTER, 5220b57cec5SDimitry Andric DK_CFI_WINDOW_SAVE, 523*0fca6ea1SDimitry Andric DK_CFI_LABEL, 5240b57cec5SDimitry Andric DK_CFI_B_KEY_FRAME, 5250b57cec5SDimitry Andric DK_MACROS_ON, 5260b57cec5SDimitry Andric DK_MACROS_OFF, 5270b57cec5SDimitry Andric DK_ALTMACRO, 5280b57cec5SDimitry Andric DK_NOALTMACRO, 5290b57cec5SDimitry Andric DK_MACRO, 5300b57cec5SDimitry Andric DK_EXITM, 5310b57cec5SDimitry Andric DK_ENDM, 5320b57cec5SDimitry Andric DK_ENDMACRO, 5330b57cec5SDimitry Andric DK_PURGEM, 5340b57cec5SDimitry Andric DK_SLEB128, 5350b57cec5SDimitry Andric DK_ULEB128, 5360b57cec5SDimitry Andric DK_ERR, 5370b57cec5SDimitry Andric DK_ERROR, 5380b57cec5SDimitry Andric DK_WARNING, 5390b57cec5SDimitry Andric DK_PRINT, 5400b57cec5SDimitry Andric DK_ADDRSIG, 5410b57cec5SDimitry Andric DK_ADDRSIG_SYM, 542e8d8bef9SDimitry Andric DK_PSEUDO_PROBE, 543fe6060f1SDimitry Andric DK_LTO_DISCARD, 5440eae32dcSDimitry Andric DK_LTO_SET_CONDITIONAL, 54581ad6265SDimitry Andric DK_CFI_MTE_TAGGED_FRAME, 546bdd1243dSDimitry Andric DK_MEMTAG, 5470b57cec5SDimitry Andric DK_END 5480b57cec5SDimitry Andric }; 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric /// Maps directive name --> DirectiveKind enum, for 5510b57cec5SDimitry Andric /// directives parsed by this class. 5520b57cec5SDimitry Andric StringMap<DirectiveKind> DirectiveKindMap; 5530b57cec5SDimitry Andric 5548bcb0991SDimitry Andric // Codeview def_range type parsing. 5558bcb0991SDimitry Andric enum CVDefRangeType { 5568bcb0991SDimitry Andric CVDR_DEFRANGE = 0, // Placeholder 5578bcb0991SDimitry Andric CVDR_DEFRANGE_REGISTER, 5588bcb0991SDimitry Andric CVDR_DEFRANGE_FRAMEPOINTER_REL, 5598bcb0991SDimitry Andric CVDR_DEFRANGE_SUBFIELD_REGISTER, 5608bcb0991SDimitry Andric CVDR_DEFRANGE_REGISTER_REL 5618bcb0991SDimitry Andric }; 5628bcb0991SDimitry Andric 5638bcb0991SDimitry Andric /// Maps Codeview def_range types --> CVDefRangeType enum, for 5648bcb0991SDimitry Andric /// Codeview def_range types parsed by this class. 5658bcb0991SDimitry Andric StringMap<CVDefRangeType> CVDefRangeTypeMap; 5668bcb0991SDimitry Andric 5670b57cec5SDimitry Andric // ".ascii", ".asciz", ".string" 5680b57cec5SDimitry Andric bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated); 5690b57cec5SDimitry Andric bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc" 5700b57cec5SDimitry Andric bool parseDirectiveValue(StringRef IDVal, 5710b57cec5SDimitry Andric unsigned Size); // ".byte", ".long", ... 5720b57cec5SDimitry Andric bool parseDirectiveOctaValue(StringRef IDVal); // ".octa", ... 5730b57cec5SDimitry Andric bool parseDirectiveRealValue(StringRef IDVal, 5740b57cec5SDimitry Andric const fltSemantics &); // ".single", ... 5750b57cec5SDimitry Andric bool parseDirectiveFill(); // ".fill" 5760b57cec5SDimitry Andric bool parseDirectiveZero(); // ".zero" 5770eae32dcSDimitry Andric // ".set", ".equ", ".equiv", ".lto_set_conditional" 5780eae32dcSDimitry Andric bool parseDirectiveSet(StringRef IDVal, AssignmentKind Kind); 5790b57cec5SDimitry Andric bool parseDirectiveOrg(); // ".org" 5800b57cec5SDimitry Andric // ".align{,32}", ".p2align{,w,l}" 5810b57cec5SDimitry Andric bool parseDirectiveAlign(bool IsPow2, unsigned ValueSize); 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric // ".file", ".line", ".loc", ".stabs" 5840b57cec5SDimitry Andric bool parseDirectiveFile(SMLoc DirectiveLoc); 5850b57cec5SDimitry Andric bool parseDirectiveLine(); 5860b57cec5SDimitry Andric bool parseDirectiveLoc(); 5870b57cec5SDimitry Andric bool parseDirectiveStabs(); 5880b57cec5SDimitry Andric 5890b57cec5SDimitry Andric // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable", 5900b57cec5SDimitry Andric // ".cv_inline_linetable", ".cv_def_range", ".cv_string" 5910b57cec5SDimitry Andric bool parseDirectiveCVFile(); 5920b57cec5SDimitry Andric bool parseDirectiveCVFuncId(); 5930b57cec5SDimitry Andric bool parseDirectiveCVInlineSiteId(); 5940b57cec5SDimitry Andric bool parseDirectiveCVLoc(); 5950b57cec5SDimitry Andric bool parseDirectiveCVLinetable(); 5960b57cec5SDimitry Andric bool parseDirectiveCVInlineLinetable(); 5970b57cec5SDimitry Andric bool parseDirectiveCVDefRange(); 5980b57cec5SDimitry Andric bool parseDirectiveCVString(); 5990b57cec5SDimitry Andric bool parseDirectiveCVStringTable(); 6000b57cec5SDimitry Andric bool parseDirectiveCVFileChecksums(); 6010b57cec5SDimitry Andric bool parseDirectiveCVFileChecksumOffset(); 6020b57cec5SDimitry Andric bool parseDirectiveCVFPOData(); 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric // .cfi directives 6050b57cec5SDimitry Andric bool parseDirectiveCFIRegister(SMLoc DirectiveLoc); 60606c3fb27SDimitry Andric bool parseDirectiveCFIWindowSave(SMLoc DirectiveLoc); 6070b57cec5SDimitry Andric bool parseDirectiveCFISections(); 6080b57cec5SDimitry Andric bool parseDirectiveCFIStartProc(); 6090b57cec5SDimitry Andric bool parseDirectiveCFIEndProc(); 61006c3fb27SDimitry Andric bool parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc); 6110b57cec5SDimitry Andric bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc); 61206c3fb27SDimitry Andric bool parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc); 6130b57cec5SDimitry Andric bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc); 614fe6060f1SDimitry Andric bool parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc); 6150b57cec5SDimitry Andric bool parseDirectiveCFIOffset(SMLoc DirectiveLoc); 6160b57cec5SDimitry Andric bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc); 6170b57cec5SDimitry Andric bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality); 61806c3fb27SDimitry Andric bool parseDirectiveCFIRememberState(SMLoc DirectiveLoc); 61906c3fb27SDimitry Andric bool parseDirectiveCFIRestoreState(SMLoc DirectiveLoc); 6200b57cec5SDimitry Andric bool parseDirectiveCFISameValue(SMLoc DirectiveLoc); 6210b57cec5SDimitry Andric bool parseDirectiveCFIRestore(SMLoc DirectiveLoc); 62206c3fb27SDimitry Andric bool parseDirectiveCFIEscape(SMLoc DirectiveLoc); 6230b57cec5SDimitry Andric bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc); 62406c3fb27SDimitry Andric bool parseDirectiveCFISignalFrame(SMLoc DirectiveLoc); 6250b57cec5SDimitry Andric bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc); 626*0fca6ea1SDimitry Andric bool parseDirectiveCFILabel(SMLoc DirectiveLoc); 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric // macro directives 6290b57cec5SDimitry Andric bool parseDirectivePurgeMacro(SMLoc DirectiveLoc); 6300b57cec5SDimitry Andric bool parseDirectiveExitMacro(StringRef Directive); 6310b57cec5SDimitry Andric bool parseDirectiveEndMacro(StringRef Directive); 6320b57cec5SDimitry Andric bool parseDirectiveMacro(SMLoc DirectiveLoc); 6330b57cec5SDimitry Andric bool parseDirectiveMacrosOnOff(StringRef Directive); 6340b57cec5SDimitry Andric // alternate macro mode directives 6350b57cec5SDimitry Andric bool parseDirectiveAltmacro(StringRef Directive); 6360b57cec5SDimitry Andric // ".bundle_align_mode" 6370b57cec5SDimitry Andric bool parseDirectiveBundleAlignMode(); 6380b57cec5SDimitry Andric // ".bundle_lock" 6390b57cec5SDimitry Andric bool parseDirectiveBundleLock(); 6400b57cec5SDimitry Andric // ".bundle_unlock" 6410b57cec5SDimitry Andric bool parseDirectiveBundleUnlock(); 6420b57cec5SDimitry Andric 6430b57cec5SDimitry Andric // ".space", ".skip" 6440b57cec5SDimitry Andric bool parseDirectiveSpace(StringRef IDVal); 6450b57cec5SDimitry Andric 6460b57cec5SDimitry Andric // ".dcb" 6470b57cec5SDimitry Andric bool parseDirectiveDCB(StringRef IDVal, unsigned Size); 6480b57cec5SDimitry Andric bool parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &); 6490b57cec5SDimitry Andric // ".ds" 6500b57cec5SDimitry Andric bool parseDirectiveDS(StringRef IDVal, unsigned Size); 6510b57cec5SDimitry Andric 6520b57cec5SDimitry Andric // .sleb128 (Signed=true) and .uleb128 (Signed=false) 6530b57cec5SDimitry Andric bool parseDirectiveLEB128(bool Signed); 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric /// Parse a directive like ".globl" which 6560b57cec5SDimitry Andric /// accepts a single symbol (which should be a label or an external). 6570b57cec5SDimitry Andric bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr); 6580b57cec5SDimitry Andric 6590b57cec5SDimitry Andric bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm" 6600b57cec5SDimitry Andric 661*0fca6ea1SDimitry Andric bool parseDirectiveAbort(SMLoc DirectiveLoc); // ".abort" 6620b57cec5SDimitry Andric bool parseDirectiveInclude(); // ".include" 6630b57cec5SDimitry Andric bool parseDirectiveIncbin(); // ".incbin" 6640b57cec5SDimitry Andric 6650b57cec5SDimitry Andric // ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne" 6660b57cec5SDimitry Andric bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind); 6670b57cec5SDimitry Andric // ".ifb" or ".ifnb", depending on ExpectBlank. 6680b57cec5SDimitry Andric bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank); 6690b57cec5SDimitry Andric // ".ifc" or ".ifnc", depending on ExpectEqual. 6700b57cec5SDimitry Andric bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual); 6710b57cec5SDimitry Andric // ".ifeqs" or ".ifnes", depending on ExpectEqual. 6720b57cec5SDimitry Andric bool parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual); 6730b57cec5SDimitry Andric // ".ifdef" or ".ifndef", depending on expect_defined 6740b57cec5SDimitry Andric bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined); 6750b57cec5SDimitry Andric bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif" 6760b57cec5SDimitry Andric bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else" 6770b57cec5SDimitry Andric bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif 6780b57cec5SDimitry Andric bool parseEscapedString(std::string &Data) override; 6795ffd83dbSDimitry Andric bool parseAngleBracketString(std::string &Data) override; 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric const MCExpr *applyModifierToExpr(const MCExpr *E, 6820b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind Variant); 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric // Macro-like directives 6850b57cec5SDimitry Andric MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc); 6860b57cec5SDimitry Andric void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, 6870b57cec5SDimitry Andric raw_svector_ostream &OS); 6880b57cec5SDimitry Andric bool parseDirectiveRept(SMLoc DirectiveLoc, StringRef Directive); 6890b57cec5SDimitry Andric bool parseDirectiveIrp(SMLoc DirectiveLoc); // ".irp" 6900b57cec5SDimitry Andric bool parseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc" 6910b57cec5SDimitry Andric bool parseDirectiveEndr(SMLoc DirectiveLoc); // ".endr" 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric // "_emit" or "__emit" 6940b57cec5SDimitry Andric bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info, 6950b57cec5SDimitry Andric size_t Len); 6960b57cec5SDimitry Andric 6970b57cec5SDimitry Andric // "align" 6980b57cec5SDimitry Andric bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info); 6990b57cec5SDimitry Andric 7000b57cec5SDimitry Andric // "end" 7010b57cec5SDimitry Andric bool parseDirectiveEnd(SMLoc DirectiveLoc); 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andric // ".err" or ".error" 7040b57cec5SDimitry Andric bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage); 7050b57cec5SDimitry Andric 7060b57cec5SDimitry Andric // ".warning" 7070b57cec5SDimitry Andric bool parseDirectiveWarning(SMLoc DirectiveLoc); 7080b57cec5SDimitry Andric 7090b57cec5SDimitry Andric // .print <double-quotes-string> 7100b57cec5SDimitry Andric bool parseDirectivePrint(SMLoc DirectiveLoc); 7110b57cec5SDimitry Andric 712e8d8bef9SDimitry Andric // .pseudoprobe 713e8d8bef9SDimitry Andric bool parseDirectivePseudoProbe(); 714e8d8bef9SDimitry Andric 715fe6060f1SDimitry Andric // ".lto_discard" 716fe6060f1SDimitry Andric bool parseDirectiveLTODiscard(); 717fe6060f1SDimitry Andric 7180b57cec5SDimitry Andric // Directives to support address-significance tables. 7190b57cec5SDimitry Andric bool parseDirectiveAddrsig(); 7200b57cec5SDimitry Andric bool parseDirectiveAddrsigSym(); 7210b57cec5SDimitry Andric 7220b57cec5SDimitry Andric void initializeDirectiveKindMap(); 7238bcb0991SDimitry Andric void initializeCVDefRangeTypeMap(); 7240b57cec5SDimitry Andric }; 7250b57cec5SDimitry Andric 726fe6060f1SDimitry Andric class HLASMAsmParser final : public AsmParser { 727fe6060f1SDimitry Andric private: 728fe6060f1SDimitry Andric MCAsmLexer &Lexer; 729fe6060f1SDimitry Andric MCStreamer &Out; 730fe6060f1SDimitry Andric 731fe6060f1SDimitry Andric void lexLeadingSpaces() { 732fe6060f1SDimitry Andric while (Lexer.is(AsmToken::Space)) 733fe6060f1SDimitry Andric Lexer.Lex(); 734fe6060f1SDimitry Andric } 735fe6060f1SDimitry Andric 736fe6060f1SDimitry Andric bool parseAsHLASMLabel(ParseStatementInfo &Info, MCAsmParserSemaCallback *SI); 737fe6060f1SDimitry Andric bool parseAsMachineInstruction(ParseStatementInfo &Info, 738fe6060f1SDimitry Andric MCAsmParserSemaCallback *SI); 739fe6060f1SDimitry Andric 740fe6060f1SDimitry Andric public: 741fe6060f1SDimitry Andric HLASMAsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, 742fe6060f1SDimitry Andric const MCAsmInfo &MAI, unsigned CB = 0) 743fe6060f1SDimitry Andric : AsmParser(SM, Ctx, Out, MAI, CB), Lexer(getLexer()), Out(Out) { 744fe6060f1SDimitry Andric Lexer.setSkipSpace(false); 745fe6060f1SDimitry Andric Lexer.setAllowHashInIdentifier(true); 746fe6060f1SDimitry Andric Lexer.setLexHLASMIntegers(true); 747fe6060f1SDimitry Andric Lexer.setLexHLASMStrings(true); 748fe6060f1SDimitry Andric } 749fe6060f1SDimitry Andric 750fe6060f1SDimitry Andric ~HLASMAsmParser() { Lexer.setSkipSpace(true); } 751fe6060f1SDimitry Andric 752fe6060f1SDimitry Andric bool parseStatement(ParseStatementInfo &Info, 753fe6060f1SDimitry Andric MCAsmParserSemaCallback *SI) override; 754fe6060f1SDimitry Andric }; 755fe6060f1SDimitry Andric 7560b57cec5SDimitry Andric } // end anonymous namespace 7570b57cec5SDimitry Andric 7580b57cec5SDimitry Andric namespace llvm { 7590b57cec5SDimitry Andric 760bdd1243dSDimitry Andric extern cl::opt<unsigned> AsmMacroMaxNestingDepth; 761bdd1243dSDimitry Andric 7620b57cec5SDimitry Andric extern MCAsmParserExtension *createDarwinAsmParser(); 7630b57cec5SDimitry Andric extern MCAsmParserExtension *createELFAsmParser(); 7640b57cec5SDimitry Andric extern MCAsmParserExtension *createCOFFAsmParser(); 765349cc55cSDimitry Andric extern MCAsmParserExtension *createGOFFAsmParser(); 766fe6060f1SDimitry Andric extern MCAsmParserExtension *createXCOFFAsmParser(); 7670b57cec5SDimitry Andric extern MCAsmParserExtension *createWasmAsmParser(); 7680b57cec5SDimitry Andric 7690b57cec5SDimitry Andric } // end namespace llvm 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric enum { DEFAULT_ADDRSPACE = 0 }; 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, 7740b57cec5SDimitry Andric const MCAsmInfo &MAI, unsigned CB = 0) 7750b57cec5SDimitry Andric : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM), 7760b57cec5SDimitry Andric CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true) { 7770b57cec5SDimitry Andric HadError = false; 7780b57cec5SDimitry Andric // Save the old handler. 7790b57cec5SDimitry Andric SavedDiagHandler = SrcMgr.getDiagHandler(); 7800b57cec5SDimitry Andric SavedDiagContext = SrcMgr.getDiagContext(); 7810b57cec5SDimitry Andric // Set our own handler which calls the saved handler. 7820b57cec5SDimitry Andric SrcMgr.setDiagHandler(DiagHandler, this); 7830b57cec5SDimitry Andric Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); 784e8d8bef9SDimitry Andric // Make MCStreamer aware of the StartTokLoc for locations in diagnostics. 785e8d8bef9SDimitry Andric Out.setStartTokLocPtr(&StartTokLoc); 7860b57cec5SDimitry Andric 7870b57cec5SDimitry Andric // Initialize the platform / file format parser. 788fe6060f1SDimitry Andric switch (Ctx.getObjectFileType()) { 789fe6060f1SDimitry Andric case MCContext::IsCOFF: 7900b57cec5SDimitry Andric PlatformParser.reset(createCOFFAsmParser()); 7910b57cec5SDimitry Andric break; 792fe6060f1SDimitry Andric case MCContext::IsMachO: 7930b57cec5SDimitry Andric PlatformParser.reset(createDarwinAsmParser()); 7940b57cec5SDimitry Andric IsDarwin = true; 7950b57cec5SDimitry Andric break; 796fe6060f1SDimitry Andric case MCContext::IsELF: 7970b57cec5SDimitry Andric PlatformParser.reset(createELFAsmParser()); 7980b57cec5SDimitry Andric break; 799fe6060f1SDimitry Andric case MCContext::IsGOFF: 800349cc55cSDimitry Andric PlatformParser.reset(createGOFFAsmParser()); 801349cc55cSDimitry Andric break; 80281ad6265SDimitry Andric case MCContext::IsSPIRV: 80381ad6265SDimitry Andric report_fatal_error( 80481ad6265SDimitry Andric "Need to implement createSPIRVAsmParser for SPIRV format."); 80581ad6265SDimitry Andric break; 806fe6060f1SDimitry Andric case MCContext::IsWasm: 8070b57cec5SDimitry Andric PlatformParser.reset(createWasmAsmParser()); 8080b57cec5SDimitry Andric break; 809fe6060f1SDimitry Andric case MCContext::IsXCOFF: 810fe6060f1SDimitry Andric PlatformParser.reset(createXCOFFAsmParser()); 8110b57cec5SDimitry Andric break; 81281ad6265SDimitry Andric case MCContext::IsDXContainer: 8135f757f3fSDimitry Andric report_fatal_error("DXContainer is not supported yet"); 81481ad6265SDimitry Andric break; 8150b57cec5SDimitry Andric } 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric PlatformParser->Initialize(*this); 8180b57cec5SDimitry Andric initializeDirectiveKindMap(); 8198bcb0991SDimitry Andric initializeCVDefRangeTypeMap(); 8200b57cec5SDimitry Andric 8210b57cec5SDimitry Andric NumOfMacroInstantiations = 0; 8220b57cec5SDimitry Andric } 8230b57cec5SDimitry Andric 8240b57cec5SDimitry Andric AsmParser::~AsmParser() { 8250b57cec5SDimitry Andric assert((HadError || ActiveMacros.empty()) && 8260b57cec5SDimitry Andric "Unexpected active macro instantiation!"); 8270b57cec5SDimitry Andric 828e8d8bef9SDimitry Andric // Remove MCStreamer's reference to the parser SMLoc. 829e8d8bef9SDimitry Andric Out.setStartTokLocPtr(nullptr); 8300b57cec5SDimitry Andric // Restore the saved diagnostics handler and context for use during 8310b57cec5SDimitry Andric // finalization. 8320b57cec5SDimitry Andric SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext); 8330b57cec5SDimitry Andric } 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric void AsmParser::printMacroInstantiations() { 8360b57cec5SDimitry Andric // Print the active macro instantiation stack. 837*0fca6ea1SDimitry Andric for (MacroInstantiation *M : reverse(ActiveMacros)) 838*0fca6ea1SDimitry Andric printMessage(M->InstantiationLoc, SourceMgr::DK_Note, 8390b57cec5SDimitry Andric "while in macro instantiation"); 8400b57cec5SDimitry Andric } 8410b57cec5SDimitry Andric 8420b57cec5SDimitry Andric void AsmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) { 8430b57cec5SDimitry Andric printPendingErrors(); 8440b57cec5SDimitry Andric printMessage(L, SourceMgr::DK_Note, Msg, Range); 8450b57cec5SDimitry Andric printMacroInstantiations(); 8460b57cec5SDimitry Andric } 8470b57cec5SDimitry Andric 8480b57cec5SDimitry Andric bool AsmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) { 8490b57cec5SDimitry Andric if(getTargetParser().getTargetOptions().MCNoWarn) 8500b57cec5SDimitry Andric return false; 8510b57cec5SDimitry Andric if (getTargetParser().getTargetOptions().MCFatalWarnings) 8520b57cec5SDimitry Andric return Error(L, Msg, Range); 8530b57cec5SDimitry Andric printMessage(L, SourceMgr::DK_Warning, Msg, Range); 8540b57cec5SDimitry Andric printMacroInstantiations(); 8550b57cec5SDimitry Andric return false; 8560b57cec5SDimitry Andric } 8570b57cec5SDimitry Andric 8580b57cec5SDimitry Andric bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) { 8590b57cec5SDimitry Andric HadError = true; 8600b57cec5SDimitry Andric printMessage(L, SourceMgr::DK_Error, Msg, Range); 8610b57cec5SDimitry Andric printMacroInstantiations(); 8620b57cec5SDimitry Andric return true; 8630b57cec5SDimitry Andric } 8640b57cec5SDimitry Andric 8650b57cec5SDimitry Andric bool AsmParser::enterIncludeFile(const std::string &Filename) { 8660b57cec5SDimitry Andric std::string IncludedFile; 8670b57cec5SDimitry Andric unsigned NewBuf = 8680b57cec5SDimitry Andric SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); 8690b57cec5SDimitry Andric if (!NewBuf) 8700b57cec5SDimitry Andric return true; 8710b57cec5SDimitry Andric 8720b57cec5SDimitry Andric CurBuffer = NewBuf; 8730b57cec5SDimitry Andric Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); 8740b57cec5SDimitry Andric return false; 8750b57cec5SDimitry Andric } 8760b57cec5SDimitry Andric 8770b57cec5SDimitry Andric /// Process the specified .incbin file by searching for it in the include paths 8780b57cec5SDimitry Andric /// then just emitting the byte contents of the file to the streamer. This 8790b57cec5SDimitry Andric /// returns true on failure. 8800b57cec5SDimitry Andric bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip, 8810b57cec5SDimitry Andric const MCExpr *Count, SMLoc Loc) { 8820b57cec5SDimitry Andric std::string IncludedFile; 8830b57cec5SDimitry Andric unsigned NewBuf = 8840b57cec5SDimitry Andric SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); 8850b57cec5SDimitry Andric if (!NewBuf) 8860b57cec5SDimitry Andric return true; 8870b57cec5SDimitry Andric 8880b57cec5SDimitry Andric // Pick up the bytes from the file and emit them. 8890b57cec5SDimitry Andric StringRef Bytes = SrcMgr.getMemoryBuffer(NewBuf)->getBuffer(); 8900b57cec5SDimitry Andric Bytes = Bytes.drop_front(Skip); 8910b57cec5SDimitry Andric if (Count) { 8920b57cec5SDimitry Andric int64_t Res; 8930b57cec5SDimitry Andric if (!Count->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr())) 8940b57cec5SDimitry Andric return Error(Loc, "expected absolute expression"); 8950b57cec5SDimitry Andric if (Res < 0) 8960b57cec5SDimitry Andric return Warning(Loc, "negative count has no effect"); 8970b57cec5SDimitry Andric Bytes = Bytes.take_front(Res); 8980b57cec5SDimitry Andric } 8995ffd83dbSDimitry Andric getStreamer().emitBytes(Bytes); 9000b57cec5SDimitry Andric return false; 9010b57cec5SDimitry Andric } 9020b57cec5SDimitry Andric 9030b57cec5SDimitry Andric void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) { 9040b57cec5SDimitry Andric CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc); 9050b57cec5SDimitry Andric Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), 9060b57cec5SDimitry Andric Loc.getPointer()); 9070b57cec5SDimitry Andric } 9080b57cec5SDimitry Andric 9090b57cec5SDimitry Andric const AsmToken &AsmParser::Lex() { 9100b57cec5SDimitry Andric if (Lexer.getTok().is(AsmToken::Error)) 9110b57cec5SDimitry Andric Error(Lexer.getErrLoc(), Lexer.getErr()); 9120b57cec5SDimitry Andric 9130b57cec5SDimitry Andric // if it's a end of statement with a comment in it 9140b57cec5SDimitry Andric if (getTok().is(AsmToken::EndOfStatement)) { 9150b57cec5SDimitry Andric // if this is a line comment output it. 9160b57cec5SDimitry Andric if (!getTok().getString().empty() && getTok().getString().front() != '\n' && 9170b57cec5SDimitry Andric getTok().getString().front() != '\r' && MAI.preserveAsmComments()) 9180b57cec5SDimitry Andric Out.addExplicitComment(Twine(getTok().getString())); 9190b57cec5SDimitry Andric } 9200b57cec5SDimitry Andric 9210b57cec5SDimitry Andric const AsmToken *tok = &Lexer.Lex(); 9220b57cec5SDimitry Andric 9230b57cec5SDimitry Andric // Parse comments here to be deferred until end of next statement. 9240b57cec5SDimitry Andric while (tok->is(AsmToken::Comment)) { 9250b57cec5SDimitry Andric if (MAI.preserveAsmComments()) 9260b57cec5SDimitry Andric Out.addExplicitComment(Twine(tok->getString())); 9270b57cec5SDimitry Andric tok = &Lexer.Lex(); 9280b57cec5SDimitry Andric } 9290b57cec5SDimitry Andric 9300b57cec5SDimitry Andric if (tok->is(AsmToken::Eof)) { 9310b57cec5SDimitry Andric // If this is the end of an included file, pop the parent file off the 9320b57cec5SDimitry Andric // include stack. 9330b57cec5SDimitry Andric SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); 9340b57cec5SDimitry Andric if (ParentIncludeLoc != SMLoc()) { 9350b57cec5SDimitry Andric jumpToLoc(ParentIncludeLoc); 9360b57cec5SDimitry Andric return Lex(); 9370b57cec5SDimitry Andric } 9380b57cec5SDimitry Andric } 9390b57cec5SDimitry Andric 9400b57cec5SDimitry Andric return *tok; 9410b57cec5SDimitry Andric } 9420b57cec5SDimitry Andric 9430b57cec5SDimitry Andric bool AsmParser::enabledGenDwarfForAssembly() { 9440b57cec5SDimitry Andric // Check whether the user specified -g. 9450b57cec5SDimitry Andric if (!getContext().getGenDwarfForAssembly()) 9460b57cec5SDimitry Andric return false; 9470b57cec5SDimitry Andric // If we haven't encountered any .file directives (which would imply that 9480b57cec5SDimitry Andric // the assembler source was produced with debug info already) then emit one 9490b57cec5SDimitry Andric // describing the assembler source file itself. 9500b57cec5SDimitry Andric if (getContext().getGenDwarfFileNumber() == 0) { 9510b57cec5SDimitry Andric // Use the first #line directive for this, if any. It's preprocessed, so 9520b57cec5SDimitry Andric // there is no checksum, and of course no source directive. 9530b57cec5SDimitry Andric if (!FirstCppHashFilename.empty()) 954bdd1243dSDimitry Andric getContext().setMCLineTableRootFile( 955bdd1243dSDimitry Andric /*CUID=*/0, getContext().getCompilationDir(), FirstCppHashFilename, 956bdd1243dSDimitry Andric /*Cksum=*/std::nullopt, /*Source=*/std::nullopt); 9570b57cec5SDimitry Andric const MCDwarfFile &RootFile = 9580b57cec5SDimitry Andric getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile(); 9595ffd83dbSDimitry Andric getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective( 9600b57cec5SDimitry Andric /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name, 9610b57cec5SDimitry Andric RootFile.Checksum, RootFile.Source)); 9620b57cec5SDimitry Andric } 9630b57cec5SDimitry Andric return true; 9640b57cec5SDimitry Andric } 9650b57cec5SDimitry Andric 9660b57cec5SDimitry Andric bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { 967fe6060f1SDimitry Andric LTODiscardSymbols.clear(); 968fe6060f1SDimitry Andric 9690b57cec5SDimitry Andric // Create the initial section, if requested. 9700b57cec5SDimitry Andric if (!NoInitialTextSection) 971349cc55cSDimitry Andric Out.initSections(false, getTargetParser().getSTI()); 9720b57cec5SDimitry Andric 9730b57cec5SDimitry Andric // Prime the lexer. 9740b57cec5SDimitry Andric Lex(); 9750b57cec5SDimitry Andric 9760b57cec5SDimitry Andric HadError = false; 9770b57cec5SDimitry Andric AsmCond StartingCondState = TheCondState; 9780b57cec5SDimitry Andric SmallVector<AsmRewrite, 4> AsmStrRewrites; 9790b57cec5SDimitry Andric 9800b57cec5SDimitry Andric // If we are generating dwarf for assembly source files save the initial text 9810b57cec5SDimitry Andric // section. (Don't use enabledGenDwarfForAssembly() here, as we aren't 9820b57cec5SDimitry Andric // emitting any actual debug info yet and haven't had a chance to parse any 9830b57cec5SDimitry Andric // embedded .file directives.) 9840b57cec5SDimitry Andric if (getContext().getGenDwarfForAssembly()) { 9850b57cec5SDimitry Andric MCSection *Sec = getStreamer().getCurrentSectionOnly(); 9860b57cec5SDimitry Andric if (!Sec->getBeginSymbol()) { 9870b57cec5SDimitry Andric MCSymbol *SectionStartSym = getContext().createTempSymbol(); 9885ffd83dbSDimitry Andric getStreamer().emitLabel(SectionStartSym); 9890b57cec5SDimitry Andric Sec->setBeginSymbol(SectionStartSym); 9900b57cec5SDimitry Andric } 9910b57cec5SDimitry Andric bool InsertResult = getContext().addGenDwarfSection(Sec); 9920b57cec5SDimitry Andric assert(InsertResult && ".text section should not have debug info yet"); 9930b57cec5SDimitry Andric (void)InsertResult; 9940b57cec5SDimitry Andric } 9950b57cec5SDimitry Andric 996fe6060f1SDimitry Andric getTargetParser().onBeginOfFile(); 997fe6060f1SDimitry Andric 9980b57cec5SDimitry Andric // While we have input, parse each statement. 9990b57cec5SDimitry Andric while (Lexer.isNot(AsmToken::Eof)) { 10000b57cec5SDimitry Andric ParseStatementInfo Info(&AsmStrRewrites); 1001480093f4SDimitry Andric bool Parsed = parseStatement(Info, nullptr); 10020b57cec5SDimitry Andric 10030b57cec5SDimitry Andric // If we have a Lexer Error we are on an Error Token. Load in Lexer Error 10040b57cec5SDimitry Andric // for printing ErrMsg via Lex() only if no (presumably better) parser error 10050b57cec5SDimitry Andric // exists. 1006480093f4SDimitry Andric if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) { 10070b57cec5SDimitry Andric Lex(); 10080b57cec5SDimitry Andric } 10090b57cec5SDimitry Andric 10100b57cec5SDimitry Andric // parseStatement returned true so may need to emit an error. 10110b57cec5SDimitry Andric printPendingErrors(); 10120b57cec5SDimitry Andric 10130b57cec5SDimitry Andric // Skipping to the next line if needed. 1014480093f4SDimitry Andric if (Parsed && !getLexer().isAtStartOfStatement()) 10150b57cec5SDimitry Andric eatToEndOfStatement(); 10160b57cec5SDimitry Andric } 10170b57cec5SDimitry Andric 10180b57cec5SDimitry Andric getTargetParser().onEndOfFile(); 10190b57cec5SDimitry Andric printPendingErrors(); 10200b57cec5SDimitry Andric 10210b57cec5SDimitry Andric // All errors should have been emitted. 10220b57cec5SDimitry Andric assert(!hasPendingError() && "unexpected error from parseStatement"); 10230b57cec5SDimitry Andric 10240b57cec5SDimitry Andric getTargetParser().flushPendingInstructions(getStreamer()); 10250b57cec5SDimitry Andric 10260b57cec5SDimitry Andric if (TheCondState.TheCond != StartingCondState.TheCond || 10270b57cec5SDimitry Andric TheCondState.Ignore != StartingCondState.Ignore) 10280b57cec5SDimitry Andric printError(getTok().getLoc(), "unmatched .ifs or .elses"); 10290b57cec5SDimitry Andric // Check to see there are no empty DwarfFile slots. 10300b57cec5SDimitry Andric const auto &LineTables = getContext().getMCDwarfLineTables(); 10310b57cec5SDimitry Andric if (!LineTables.empty()) { 10320b57cec5SDimitry Andric unsigned Index = 0; 10330b57cec5SDimitry Andric for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) { 10340b57cec5SDimitry Andric if (File.Name.empty() && Index != 0) 10350b57cec5SDimitry Andric printError(getTok().getLoc(), "unassigned file number: " + 10360b57cec5SDimitry Andric Twine(Index) + 10370b57cec5SDimitry Andric " for .file directives"); 10380b57cec5SDimitry Andric ++Index; 10390b57cec5SDimitry Andric } 10400b57cec5SDimitry Andric } 10410b57cec5SDimitry Andric 10420b57cec5SDimitry Andric // Check to see that all assembler local symbols were actually defined. 10430b57cec5SDimitry Andric // Targets that don't do subsections via symbols may not want this, though, 10440b57cec5SDimitry Andric // so conservatively exclude them. Only do this if we're finalizing, though, 10450b57cec5SDimitry Andric // as otherwise we won't necessarilly have seen everything yet. 10460b57cec5SDimitry Andric if (!NoFinalize) { 10470b57cec5SDimitry Andric if (MAI.hasSubsectionsViaSymbols()) { 10480b57cec5SDimitry Andric for (const auto &TableEntry : getContext().getSymbols()) { 1049*0fca6ea1SDimitry Andric MCSymbol *Sym = TableEntry.getValue().Symbol; 10500b57cec5SDimitry Andric // Variable symbols may not be marked as defined, so check those 10510b57cec5SDimitry Andric // explicitly. If we know it's a variable, we have a definition for 10520b57cec5SDimitry Andric // the purposes of this check. 1053*0fca6ea1SDimitry Andric if (Sym && Sym->isTemporary() && !Sym->isVariable() && 1054*0fca6ea1SDimitry Andric !Sym->isDefined()) 10550b57cec5SDimitry Andric // FIXME: We would really like to refer back to where the symbol was 10560b57cec5SDimitry Andric // first referenced for a source location. We need to add something 10570b57cec5SDimitry Andric // to track that. Currently, we just point to the end of the file. 10580b57cec5SDimitry Andric printError(getTok().getLoc(), "assembler local symbol '" + 10590b57cec5SDimitry Andric Sym->getName() + "' not defined"); 10600b57cec5SDimitry Andric } 10610b57cec5SDimitry Andric } 10620b57cec5SDimitry Andric 10630b57cec5SDimitry Andric // Temporary symbols like the ones for directional jumps don't go in the 10640b57cec5SDimitry Andric // symbol table. They also need to be diagnosed in all (final) cases. 10650b57cec5SDimitry Andric for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) { 10660b57cec5SDimitry Andric if (std::get<2>(LocSym)->isUndefined()) { 10670b57cec5SDimitry Andric // Reset the state of any "# line file" directives we've seen to the 10680b57cec5SDimitry Andric // context as it was at the diagnostic site. 10690b57cec5SDimitry Andric CppHashInfo = std::get<1>(LocSym); 10700b57cec5SDimitry Andric printError(std::get<0>(LocSym), "directional label undefined"); 10710b57cec5SDimitry Andric } 10720b57cec5SDimitry Andric } 10730b57cec5SDimitry Andric } 10740b57cec5SDimitry Andric // Finalize the output stream if there are no errors and if the client wants 10750b57cec5SDimitry Andric // us to. 1076349cc55cSDimitry Andric if (!HadError && !NoFinalize) { 1077349cc55cSDimitry Andric if (auto *TS = Out.getTargetStreamer()) 1078349cc55cSDimitry Andric TS->emitConstantPools(); 1079349cc55cSDimitry Andric 108081ad6265SDimitry Andric Out.finish(Lexer.getLoc()); 1081349cc55cSDimitry Andric } 10820b57cec5SDimitry Andric 10830b57cec5SDimitry Andric return HadError || getContext().hadError(); 10840b57cec5SDimitry Andric } 10850b57cec5SDimitry Andric 10860b57cec5SDimitry Andric bool AsmParser::checkForValidSection() { 1087*0fca6ea1SDimitry Andric if (!ParsingMSInlineAsm && !getStreamer().getCurrentFragment()) { 1088349cc55cSDimitry Andric Out.initSections(false, getTargetParser().getSTI()); 10890b57cec5SDimitry Andric return Error(getTok().getLoc(), 10900b57cec5SDimitry Andric "expected section directive before assembly directive"); 10910b57cec5SDimitry Andric } 10920b57cec5SDimitry Andric return false; 10930b57cec5SDimitry Andric } 10940b57cec5SDimitry Andric 10950b57cec5SDimitry Andric /// Throw away the rest of the line for testing purposes. 10960b57cec5SDimitry Andric void AsmParser::eatToEndOfStatement() { 10970b57cec5SDimitry Andric while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof)) 10980b57cec5SDimitry Andric Lexer.Lex(); 10990b57cec5SDimitry Andric 11000b57cec5SDimitry Andric // Eat EOL. 11010b57cec5SDimitry Andric if (Lexer.is(AsmToken::EndOfStatement)) 11020b57cec5SDimitry Andric Lexer.Lex(); 11030b57cec5SDimitry Andric } 11040b57cec5SDimitry Andric 11050b57cec5SDimitry Andric StringRef AsmParser::parseStringToEndOfStatement() { 11060b57cec5SDimitry Andric const char *Start = getTok().getLoc().getPointer(); 11070b57cec5SDimitry Andric 11080b57cec5SDimitry Andric while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof)) 11090b57cec5SDimitry Andric Lexer.Lex(); 11100b57cec5SDimitry Andric 11110b57cec5SDimitry Andric const char *End = getTok().getLoc().getPointer(); 11120b57cec5SDimitry Andric return StringRef(Start, End - Start); 11130b57cec5SDimitry Andric } 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andric StringRef AsmParser::parseStringToComma() { 11160b57cec5SDimitry Andric const char *Start = getTok().getLoc().getPointer(); 11170b57cec5SDimitry Andric 11180b57cec5SDimitry Andric while (Lexer.isNot(AsmToken::EndOfStatement) && 11190b57cec5SDimitry Andric Lexer.isNot(AsmToken::Comma) && Lexer.isNot(AsmToken::Eof)) 11200b57cec5SDimitry Andric Lexer.Lex(); 11210b57cec5SDimitry Andric 11220b57cec5SDimitry Andric const char *End = getTok().getLoc().getPointer(); 11230b57cec5SDimitry Andric return StringRef(Start, End - Start); 11240b57cec5SDimitry Andric } 11250b57cec5SDimitry Andric 11260b57cec5SDimitry Andric /// Parse a paren expression and return it. 11270b57cec5SDimitry Andric /// NOTE: This assumes the leading '(' has already been consumed. 11280b57cec5SDimitry Andric /// 11290b57cec5SDimitry Andric /// parenexpr ::= expr) 11300b57cec5SDimitry Andric /// 11310b57cec5SDimitry Andric bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) { 11320b57cec5SDimitry Andric if (parseExpression(Res)) 11330b57cec5SDimitry Andric return true; 11340b57cec5SDimitry Andric EndLoc = Lexer.getTok().getEndLoc(); 113504eeddc0SDimitry Andric return parseRParen(); 11360b57cec5SDimitry Andric } 11370b57cec5SDimitry Andric 11380b57cec5SDimitry Andric /// Parse a bracket expression and return it. 11390b57cec5SDimitry Andric /// NOTE: This assumes the leading '[' has already been consumed. 11400b57cec5SDimitry Andric /// 11410b57cec5SDimitry Andric /// bracketexpr ::= expr] 11420b57cec5SDimitry Andric /// 11430b57cec5SDimitry Andric bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) { 11440b57cec5SDimitry Andric if (parseExpression(Res)) 11450b57cec5SDimitry Andric return true; 11460b57cec5SDimitry Andric EndLoc = getTok().getEndLoc(); 11470b57cec5SDimitry Andric if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression")) 11480b57cec5SDimitry Andric return true; 11490b57cec5SDimitry Andric return false; 11500b57cec5SDimitry Andric } 11510b57cec5SDimitry Andric 11520b57cec5SDimitry Andric /// Parse a primary expression and return it. 11530b57cec5SDimitry Andric /// primaryexpr ::= (parenexpr 11540b57cec5SDimitry Andric /// primaryexpr ::= symbol 11550b57cec5SDimitry Andric /// primaryexpr ::= number 11560b57cec5SDimitry Andric /// primaryexpr ::= '.' 11570b57cec5SDimitry Andric /// primaryexpr ::= ~,+,- primaryexpr 1158e8d8bef9SDimitry Andric bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc, 1159e8d8bef9SDimitry Andric AsmTypeInfo *TypeInfo) { 11600b57cec5SDimitry Andric SMLoc FirstTokenLoc = getLexer().getLoc(); 11610b57cec5SDimitry Andric AsmToken::TokenKind FirstTokenKind = Lexer.getKind(); 11620b57cec5SDimitry Andric switch (FirstTokenKind) { 11630b57cec5SDimitry Andric default: 11640b57cec5SDimitry Andric return TokError("unknown token in expression"); 11650b57cec5SDimitry Andric // If we have an error assume that we've already handled it. 11660b57cec5SDimitry Andric case AsmToken::Error: 11670b57cec5SDimitry Andric return true; 11680b57cec5SDimitry Andric case AsmToken::Exclaim: 11690b57cec5SDimitry Andric Lex(); // Eat the operator. 1170e8d8bef9SDimitry Andric if (parsePrimaryExpr(Res, EndLoc, TypeInfo)) 11710b57cec5SDimitry Andric return true; 11720b57cec5SDimitry Andric Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc); 11730b57cec5SDimitry Andric return false; 11740b57cec5SDimitry Andric case AsmToken::Dollar: 1175fe6060f1SDimitry Andric case AsmToken::Star: 11760b57cec5SDimitry Andric case AsmToken::At: 11770b57cec5SDimitry Andric case AsmToken::String: 11780b57cec5SDimitry Andric case AsmToken::Identifier: { 11790b57cec5SDimitry Andric StringRef Identifier; 11800b57cec5SDimitry Andric if (parseIdentifier(Identifier)) { 1181fe6060f1SDimitry Andric // We may have failed but '$'|'*' may be a valid token in context of 1182fe6060f1SDimitry Andric // the current PC. 1183fe6060f1SDimitry Andric if (getTok().is(AsmToken::Dollar) || getTok().is(AsmToken::Star)) { 1184fe6060f1SDimitry Andric bool ShouldGenerateTempSymbol = false; 1185fe6060f1SDimitry Andric if ((getTok().is(AsmToken::Dollar) && MAI.getDollarIsPC()) || 1186fe6060f1SDimitry Andric (getTok().is(AsmToken::Star) && MAI.getStarIsPC())) 1187fe6060f1SDimitry Andric ShouldGenerateTempSymbol = true; 1188fe6060f1SDimitry Andric 1189fe6060f1SDimitry Andric if (!ShouldGenerateTempSymbol) 1190fe6060f1SDimitry Andric return Error(FirstTokenLoc, "invalid token in expression"); 1191fe6060f1SDimitry Andric 1192fe6060f1SDimitry Andric // Eat the '$'|'*' token. 11930b57cec5SDimitry Andric Lex(); 1194fe6060f1SDimitry Andric // This is either a '$'|'*' reference, which references the current PC. 1195fe6060f1SDimitry Andric // Emit a temporary label to the streamer and refer to it. 11960b57cec5SDimitry Andric MCSymbol *Sym = Ctx.createTempSymbol(); 11975ffd83dbSDimitry Andric Out.emitLabel(Sym); 11980b57cec5SDimitry Andric Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, 11990b57cec5SDimitry Andric getContext()); 12000b57cec5SDimitry Andric EndLoc = FirstTokenLoc; 12010b57cec5SDimitry Andric return false; 12020b57cec5SDimitry Andric } 12030b57cec5SDimitry Andric } 12040b57cec5SDimitry Andric // Parse symbol variant 12050b57cec5SDimitry Andric std::pair<StringRef, StringRef> Split; 12060b57cec5SDimitry Andric if (!MAI.useParensForSymbolVariant()) { 12070b57cec5SDimitry Andric if (FirstTokenKind == AsmToken::String) { 12080b57cec5SDimitry Andric if (Lexer.is(AsmToken::At)) { 12090b57cec5SDimitry Andric Lex(); // eat @ 12100b57cec5SDimitry Andric SMLoc AtLoc = getLexer().getLoc(); 12110b57cec5SDimitry Andric StringRef VName; 12120b57cec5SDimitry Andric if (parseIdentifier(VName)) 12130b57cec5SDimitry Andric return Error(AtLoc, "expected symbol variant after '@'"); 12140b57cec5SDimitry Andric 12150b57cec5SDimitry Andric Split = std::make_pair(Identifier, VName); 12160b57cec5SDimitry Andric } 12170b57cec5SDimitry Andric } else { 12180b57cec5SDimitry Andric Split = Identifier.split('@'); 12190b57cec5SDimitry Andric } 12200b57cec5SDimitry Andric } else if (Lexer.is(AsmToken::LParen)) { 12210b57cec5SDimitry Andric Lex(); // eat '('. 12220b57cec5SDimitry Andric StringRef VName; 12230b57cec5SDimitry Andric parseIdentifier(VName); 122404eeddc0SDimitry Andric if (parseRParen()) 12250b57cec5SDimitry Andric return true; 12260b57cec5SDimitry Andric Split = std::make_pair(Identifier, VName); 12270b57cec5SDimitry Andric } 12280b57cec5SDimitry Andric 12290b57cec5SDimitry Andric EndLoc = SMLoc::getFromPointer(Identifier.end()); 12300b57cec5SDimitry Andric 12310b57cec5SDimitry Andric // This is a symbol reference. 12320b57cec5SDimitry Andric StringRef SymbolName = Identifier; 12330b57cec5SDimitry Andric if (SymbolName.empty()) 12340b57cec5SDimitry Andric return Error(getLexer().getLoc(), "expected a symbol reference"); 12350b57cec5SDimitry Andric 12360b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; 12370b57cec5SDimitry Andric 12380b57cec5SDimitry Andric // Lookup the symbol variant if used. 12390b57cec5SDimitry Andric if (!Split.second.empty()) { 1240*0fca6ea1SDimitry Andric Variant = getTargetParser().getVariantKindForName(Split.second); 12410b57cec5SDimitry Andric if (Variant != MCSymbolRefExpr::VK_Invalid) { 12420b57cec5SDimitry Andric SymbolName = Split.first; 12430b57cec5SDimitry Andric } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) { 12440b57cec5SDimitry Andric Variant = MCSymbolRefExpr::VK_None; 12450b57cec5SDimitry Andric } else { 12460b57cec5SDimitry Andric return Error(SMLoc::getFromPointer(Split.second.begin()), 12470b57cec5SDimitry Andric "invalid variant '" + Split.second + "'"); 12480b57cec5SDimitry Andric } 12490b57cec5SDimitry Andric } 12500b57cec5SDimitry Andric 12510b57cec5SDimitry Andric MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName); 12520b57cec5SDimitry Andric if (!Sym) 1253fe6060f1SDimitry Andric Sym = getContext().getOrCreateSymbol( 1254fe6060f1SDimitry Andric MAI.shouldEmitLabelsInUpperCase() ? SymbolName.upper() : SymbolName); 12550b57cec5SDimitry Andric 12560b57cec5SDimitry Andric // If this is an absolute variable reference, substitute it now to preserve 12570b57cec5SDimitry Andric // semantics in the face of reassignment. 12580b57cec5SDimitry Andric if (Sym->isVariable()) { 12590b57cec5SDimitry Andric auto V = Sym->getVariableValue(/*SetUsed*/ false); 12600b57cec5SDimitry Andric bool DoInline = isa<MCConstantExpr>(V) && !Variant; 12610b57cec5SDimitry Andric if (auto TV = dyn_cast<MCTargetExpr>(V)) 12620b57cec5SDimitry Andric DoInline = TV->inlineAssignedExpr(); 12630b57cec5SDimitry Andric if (DoInline) { 12640b57cec5SDimitry Andric if (Variant) 12650b57cec5SDimitry Andric return Error(EndLoc, "unexpected modifier on variable reference"); 12660b57cec5SDimitry Andric Res = Sym->getVariableValue(/*SetUsed*/ false); 12670b57cec5SDimitry Andric return false; 12680b57cec5SDimitry Andric } 12690b57cec5SDimitry Andric } 12700b57cec5SDimitry Andric 12710b57cec5SDimitry Andric // Otherwise create a symbol ref. 12720b57cec5SDimitry Andric Res = MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc); 12730b57cec5SDimitry Andric return false; 12740b57cec5SDimitry Andric } 12750b57cec5SDimitry Andric case AsmToken::BigNum: 12760b57cec5SDimitry Andric return TokError("literal value out of range for directive"); 12770b57cec5SDimitry Andric case AsmToken::Integer: { 12780b57cec5SDimitry Andric SMLoc Loc = getTok().getLoc(); 12790b57cec5SDimitry Andric int64_t IntVal = getTok().getIntVal(); 12800b57cec5SDimitry Andric Res = MCConstantExpr::create(IntVal, getContext()); 12810b57cec5SDimitry Andric EndLoc = Lexer.getTok().getEndLoc(); 12820b57cec5SDimitry Andric Lex(); // Eat token. 12830b57cec5SDimitry Andric // Look for 'b' or 'f' following an Integer as a directional label 12840b57cec5SDimitry Andric if (Lexer.getKind() == AsmToken::Identifier) { 12850b57cec5SDimitry Andric StringRef IDVal = getTok().getString(); 12860b57cec5SDimitry Andric // Lookup the symbol variant if used. 12870b57cec5SDimitry Andric std::pair<StringRef, StringRef> Split = IDVal.split('@'); 12880b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; 12890b57cec5SDimitry Andric if (Split.first.size() != IDVal.size()) { 12900b57cec5SDimitry Andric Variant = MCSymbolRefExpr::getVariantKindForName(Split.second); 12910b57cec5SDimitry Andric if (Variant == MCSymbolRefExpr::VK_Invalid) 12920b57cec5SDimitry Andric return TokError("invalid variant '" + Split.second + "'"); 12930b57cec5SDimitry Andric IDVal = Split.first; 12940b57cec5SDimitry Andric } 12950b57cec5SDimitry Andric if (IDVal == "f" || IDVal == "b") { 12960b57cec5SDimitry Andric MCSymbol *Sym = 12970b57cec5SDimitry Andric Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b"); 12980b57cec5SDimitry Andric Res = MCSymbolRefExpr::create(Sym, Variant, getContext()); 12990b57cec5SDimitry Andric if (IDVal == "b" && Sym->isUndefined()) 13000b57cec5SDimitry Andric return Error(Loc, "directional label undefined"); 13010b57cec5SDimitry Andric DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym)); 13020b57cec5SDimitry Andric EndLoc = Lexer.getTok().getEndLoc(); 13030b57cec5SDimitry Andric Lex(); // Eat identifier. 13040b57cec5SDimitry Andric } 13050b57cec5SDimitry Andric } 13060b57cec5SDimitry Andric return false; 13070b57cec5SDimitry Andric } 13080b57cec5SDimitry Andric case AsmToken::Real: { 13090b57cec5SDimitry Andric APFloat RealVal(APFloat::IEEEdouble(), getTok().getString()); 13100b57cec5SDimitry Andric uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue(); 13110b57cec5SDimitry Andric Res = MCConstantExpr::create(IntVal, getContext()); 13120b57cec5SDimitry Andric EndLoc = Lexer.getTok().getEndLoc(); 13130b57cec5SDimitry Andric Lex(); // Eat token. 13140b57cec5SDimitry Andric return false; 13150b57cec5SDimitry Andric } 13160b57cec5SDimitry Andric case AsmToken::Dot: { 1317fe6060f1SDimitry Andric if (!MAI.getDotIsPC()) 1318fe6060f1SDimitry Andric return TokError("cannot use . as current PC"); 1319fe6060f1SDimitry Andric 13200b57cec5SDimitry Andric // This is a '.' reference, which references the current PC. Emit a 13210b57cec5SDimitry Andric // temporary label to the streamer and refer to it. 13220b57cec5SDimitry Andric MCSymbol *Sym = Ctx.createTempSymbol(); 13235ffd83dbSDimitry Andric Out.emitLabel(Sym); 13240b57cec5SDimitry Andric Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 13250b57cec5SDimitry Andric EndLoc = Lexer.getTok().getEndLoc(); 13260b57cec5SDimitry Andric Lex(); // Eat identifier. 13270b57cec5SDimitry Andric return false; 13280b57cec5SDimitry Andric } 13290b57cec5SDimitry Andric case AsmToken::LParen: 13300b57cec5SDimitry Andric Lex(); // Eat the '('. 13310b57cec5SDimitry Andric return parseParenExpr(Res, EndLoc); 13320b57cec5SDimitry Andric case AsmToken::LBrac: 13330b57cec5SDimitry Andric if (!PlatformParser->HasBracketExpressions()) 13340b57cec5SDimitry Andric return TokError("brackets expression not supported on this target"); 13350b57cec5SDimitry Andric Lex(); // Eat the '['. 13360b57cec5SDimitry Andric return parseBracketExpr(Res, EndLoc); 13370b57cec5SDimitry Andric case AsmToken::Minus: 13380b57cec5SDimitry Andric Lex(); // Eat the operator. 1339e8d8bef9SDimitry Andric if (parsePrimaryExpr(Res, EndLoc, TypeInfo)) 13400b57cec5SDimitry Andric return true; 13410b57cec5SDimitry Andric Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc); 13420b57cec5SDimitry Andric return false; 13430b57cec5SDimitry Andric case AsmToken::Plus: 13440b57cec5SDimitry Andric Lex(); // Eat the operator. 1345e8d8bef9SDimitry Andric if (parsePrimaryExpr(Res, EndLoc, TypeInfo)) 13460b57cec5SDimitry Andric return true; 13470b57cec5SDimitry Andric Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc); 13480b57cec5SDimitry Andric return false; 13490b57cec5SDimitry Andric case AsmToken::Tilde: 13500b57cec5SDimitry Andric Lex(); // Eat the operator. 1351e8d8bef9SDimitry Andric if (parsePrimaryExpr(Res, EndLoc, TypeInfo)) 13520b57cec5SDimitry Andric return true; 13530b57cec5SDimitry Andric Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc); 13540b57cec5SDimitry Andric return false; 13550b57cec5SDimitry Andric // MIPS unary expression operators. The lexer won't generate these tokens if 13560b57cec5SDimitry Andric // MCAsmInfo::HasMipsExpressions is false for the target. 13570b57cec5SDimitry Andric case AsmToken::PercentCall16: 13580b57cec5SDimitry Andric case AsmToken::PercentCall_Hi: 13590b57cec5SDimitry Andric case AsmToken::PercentCall_Lo: 13600b57cec5SDimitry Andric case AsmToken::PercentDtprel_Hi: 13610b57cec5SDimitry Andric case AsmToken::PercentDtprel_Lo: 13620b57cec5SDimitry Andric case AsmToken::PercentGot: 13630b57cec5SDimitry Andric case AsmToken::PercentGot_Disp: 13640b57cec5SDimitry Andric case AsmToken::PercentGot_Hi: 13650b57cec5SDimitry Andric case AsmToken::PercentGot_Lo: 13660b57cec5SDimitry Andric case AsmToken::PercentGot_Ofst: 13670b57cec5SDimitry Andric case AsmToken::PercentGot_Page: 13680b57cec5SDimitry Andric case AsmToken::PercentGottprel: 13690b57cec5SDimitry Andric case AsmToken::PercentGp_Rel: 13700b57cec5SDimitry Andric case AsmToken::PercentHi: 13710b57cec5SDimitry Andric case AsmToken::PercentHigher: 13720b57cec5SDimitry Andric case AsmToken::PercentHighest: 13730b57cec5SDimitry Andric case AsmToken::PercentLo: 13740b57cec5SDimitry Andric case AsmToken::PercentNeg: 13750b57cec5SDimitry Andric case AsmToken::PercentPcrel_Hi: 13760b57cec5SDimitry Andric case AsmToken::PercentPcrel_Lo: 13770b57cec5SDimitry Andric case AsmToken::PercentTlsgd: 13780b57cec5SDimitry Andric case AsmToken::PercentTlsldm: 13790b57cec5SDimitry Andric case AsmToken::PercentTprel_Hi: 13800b57cec5SDimitry Andric case AsmToken::PercentTprel_Lo: 13810b57cec5SDimitry Andric Lex(); // Eat the operator. 13820b57cec5SDimitry Andric if (Lexer.isNot(AsmToken::LParen)) 13830b57cec5SDimitry Andric return TokError("expected '(' after operator"); 13840b57cec5SDimitry Andric Lex(); // Eat the operator. 13850b57cec5SDimitry Andric if (parseExpression(Res, EndLoc)) 13860b57cec5SDimitry Andric return true; 138704eeddc0SDimitry Andric if (parseRParen()) 138804eeddc0SDimitry Andric return true; 13890b57cec5SDimitry Andric Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx); 13900b57cec5SDimitry Andric return !Res; 13910b57cec5SDimitry Andric } 13920b57cec5SDimitry Andric } 13930b57cec5SDimitry Andric 13940b57cec5SDimitry Andric bool AsmParser::parseExpression(const MCExpr *&Res) { 13950b57cec5SDimitry Andric SMLoc EndLoc; 13960b57cec5SDimitry Andric return parseExpression(Res, EndLoc); 13970b57cec5SDimitry Andric } 13980b57cec5SDimitry Andric 13990b57cec5SDimitry Andric const MCExpr * 14000b57cec5SDimitry Andric AsmParser::applyModifierToExpr(const MCExpr *E, 14010b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind Variant) { 14020b57cec5SDimitry Andric // Ask the target implementation about this expression first. 14030b57cec5SDimitry Andric const MCExpr *NewE = getTargetParser().applyModifierToExpr(E, Variant, Ctx); 14040b57cec5SDimitry Andric if (NewE) 14050b57cec5SDimitry Andric return NewE; 14060b57cec5SDimitry Andric // Recurse over the given expression, rebuilding it to apply the given variant 14070b57cec5SDimitry Andric // if there is exactly one symbol. 14080b57cec5SDimitry Andric switch (E->getKind()) { 14090b57cec5SDimitry Andric case MCExpr::Target: 14100b57cec5SDimitry Andric case MCExpr::Constant: 14110b57cec5SDimitry Andric return nullptr; 14120b57cec5SDimitry Andric 14130b57cec5SDimitry Andric case MCExpr::SymbolRef: { 14140b57cec5SDimitry Andric const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E); 14150b57cec5SDimitry Andric 14160b57cec5SDimitry Andric if (SRE->getKind() != MCSymbolRefExpr::VK_None) { 14170b57cec5SDimitry Andric TokError("invalid variant on expression '" + getTok().getIdentifier() + 14180b57cec5SDimitry Andric "' (already modified)"); 14190b57cec5SDimitry Andric return E; 14200b57cec5SDimitry Andric } 14210b57cec5SDimitry Andric 14220b57cec5SDimitry Andric return MCSymbolRefExpr::create(&SRE->getSymbol(), Variant, getContext()); 14230b57cec5SDimitry Andric } 14240b57cec5SDimitry Andric 14250b57cec5SDimitry Andric case MCExpr::Unary: { 14260b57cec5SDimitry Andric const MCUnaryExpr *UE = cast<MCUnaryExpr>(E); 14270b57cec5SDimitry Andric const MCExpr *Sub = applyModifierToExpr(UE->getSubExpr(), Variant); 14280b57cec5SDimitry Andric if (!Sub) 14290b57cec5SDimitry Andric return nullptr; 14300b57cec5SDimitry Andric return MCUnaryExpr::create(UE->getOpcode(), Sub, getContext()); 14310b57cec5SDimitry Andric } 14320b57cec5SDimitry Andric 14330b57cec5SDimitry Andric case MCExpr::Binary: { 14340b57cec5SDimitry Andric const MCBinaryExpr *BE = cast<MCBinaryExpr>(E); 14350b57cec5SDimitry Andric const MCExpr *LHS = applyModifierToExpr(BE->getLHS(), Variant); 14360b57cec5SDimitry Andric const MCExpr *RHS = applyModifierToExpr(BE->getRHS(), Variant); 14370b57cec5SDimitry Andric 14380b57cec5SDimitry Andric if (!LHS && !RHS) 14390b57cec5SDimitry Andric return nullptr; 14400b57cec5SDimitry Andric 14410b57cec5SDimitry Andric if (!LHS) 14420b57cec5SDimitry Andric LHS = BE->getLHS(); 14430b57cec5SDimitry Andric if (!RHS) 14440b57cec5SDimitry Andric RHS = BE->getRHS(); 14450b57cec5SDimitry Andric 14460b57cec5SDimitry Andric return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, getContext()); 14470b57cec5SDimitry Andric } 14480b57cec5SDimitry Andric } 14490b57cec5SDimitry Andric 14500b57cec5SDimitry Andric llvm_unreachable("Invalid expression kind!"); 14510b57cec5SDimitry Andric } 14520b57cec5SDimitry Andric 14530b57cec5SDimitry Andric /// This function checks if the next token is <string> type or arithmetic. 14540b57cec5SDimitry Andric /// string that begin with character '<' must end with character '>'. 14550b57cec5SDimitry Andric /// otherwise it is arithmetics. 14560b57cec5SDimitry Andric /// If the function returns a 'true' value, 14570b57cec5SDimitry Andric /// the End argument will be filled with the last location pointed to the '>' 14580b57cec5SDimitry Andric /// character. 14590b57cec5SDimitry Andric 14600b57cec5SDimitry Andric /// There is a gap between the AltMacro's documentation and the single quote 14610b57cec5SDimitry Andric /// implementation. GCC does not fully support this feature and so we will not 14620b57cec5SDimitry Andric /// support it. 14630b57cec5SDimitry Andric /// TODO: Adding single quote as a string. 14645ffd83dbSDimitry Andric static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) { 14650b57cec5SDimitry Andric assert((StrLoc.getPointer() != nullptr) && 14660b57cec5SDimitry Andric "Argument to the function cannot be a NULL value"); 14670b57cec5SDimitry Andric const char *CharPtr = StrLoc.getPointer(); 14680b57cec5SDimitry Andric while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') && 14690b57cec5SDimitry Andric (*CharPtr != '\0')) { 14700b57cec5SDimitry Andric if (*CharPtr == '!') 14710b57cec5SDimitry Andric CharPtr++; 14720b57cec5SDimitry Andric CharPtr++; 14730b57cec5SDimitry Andric } 14740b57cec5SDimitry Andric if (*CharPtr == '>') { 14750b57cec5SDimitry Andric EndLoc = StrLoc.getFromPointer(CharPtr + 1); 14760b57cec5SDimitry Andric return true; 14770b57cec5SDimitry Andric } 14780b57cec5SDimitry Andric return false; 14790b57cec5SDimitry Andric } 14800b57cec5SDimitry Andric 14810b57cec5SDimitry Andric /// creating a string without the escape characters '!'. 14825ffd83dbSDimitry Andric static std::string angleBracketString(StringRef AltMacroStr) { 14830b57cec5SDimitry Andric std::string Res; 14840b57cec5SDimitry Andric for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) { 14850b57cec5SDimitry Andric if (AltMacroStr[Pos] == '!') 14860b57cec5SDimitry Andric Pos++; 14870b57cec5SDimitry Andric Res += AltMacroStr[Pos]; 14880b57cec5SDimitry Andric } 14890b57cec5SDimitry Andric return Res; 14900b57cec5SDimitry Andric } 14910b57cec5SDimitry Andric 14920b57cec5SDimitry Andric /// Parse an expression and return it. 14930b57cec5SDimitry Andric /// 14940b57cec5SDimitry Andric /// expr ::= expr &&,|| expr -> lowest. 14950b57cec5SDimitry Andric /// expr ::= expr |,^,&,! expr 14960b57cec5SDimitry Andric /// expr ::= expr ==,!=,<>,<,<=,>,>= expr 14970b57cec5SDimitry Andric /// expr ::= expr <<,>> expr 14980b57cec5SDimitry Andric /// expr ::= expr +,- expr 14990b57cec5SDimitry Andric /// expr ::= expr *,/,% expr -> highest. 15000b57cec5SDimitry Andric /// expr ::= primaryexpr 15010b57cec5SDimitry Andric /// 15020b57cec5SDimitry Andric bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) { 15030b57cec5SDimitry Andric // Parse the expression. 15040b57cec5SDimitry Andric Res = nullptr; 15050b57cec5SDimitry Andric if (getTargetParser().parsePrimaryExpr(Res, EndLoc) || 15060b57cec5SDimitry Andric parseBinOpRHS(1, Res, EndLoc)) 15070b57cec5SDimitry Andric return true; 15080b57cec5SDimitry Andric 15090b57cec5SDimitry Andric // As a special case, we support 'a op b @ modifier' by rewriting the 15100b57cec5SDimitry Andric // expression to include the modifier. This is inefficient, but in general we 15110b57cec5SDimitry Andric // expect users to use 'a@modifier op b'. 1512*0fca6ea1SDimitry Andric if (parseOptionalToken(AsmToken::At)) { 15130b57cec5SDimitry Andric if (Lexer.isNot(AsmToken::Identifier)) 15140b57cec5SDimitry Andric return TokError("unexpected symbol modifier following '@'"); 15150b57cec5SDimitry Andric 15160b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind Variant = 15170b57cec5SDimitry Andric MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier()); 15180b57cec5SDimitry Andric if (Variant == MCSymbolRefExpr::VK_Invalid) 15190b57cec5SDimitry Andric return TokError("invalid variant '" + getTok().getIdentifier() + "'"); 15200b57cec5SDimitry Andric 15210b57cec5SDimitry Andric const MCExpr *ModifiedRes = applyModifierToExpr(Res, Variant); 15220b57cec5SDimitry Andric if (!ModifiedRes) { 15230b57cec5SDimitry Andric return TokError("invalid modifier '" + getTok().getIdentifier() + 15240b57cec5SDimitry Andric "' (no symbols present)"); 15250b57cec5SDimitry Andric } 15260b57cec5SDimitry Andric 15270b57cec5SDimitry Andric Res = ModifiedRes; 15280b57cec5SDimitry Andric Lex(); 15290b57cec5SDimitry Andric } 15300b57cec5SDimitry Andric 15310b57cec5SDimitry Andric // Try to constant fold it up front, if possible. Do not exploit 15320b57cec5SDimitry Andric // assembler here. 15330b57cec5SDimitry Andric int64_t Value; 15340b57cec5SDimitry Andric if (Res->evaluateAsAbsolute(Value)) 15350b57cec5SDimitry Andric Res = MCConstantExpr::create(Value, getContext()); 15360b57cec5SDimitry Andric 15370b57cec5SDimitry Andric return false; 15380b57cec5SDimitry Andric } 15390b57cec5SDimitry Andric 15400b57cec5SDimitry Andric bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) { 15410b57cec5SDimitry Andric Res = nullptr; 15420b57cec5SDimitry Andric return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc); 15430b57cec5SDimitry Andric } 15440b57cec5SDimitry Andric 15450b57cec5SDimitry Andric bool AsmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res, 15460b57cec5SDimitry Andric SMLoc &EndLoc) { 15470b57cec5SDimitry Andric if (parseParenExpr(Res, EndLoc)) 15480b57cec5SDimitry Andric return true; 15490b57cec5SDimitry Andric 15500b57cec5SDimitry Andric for (; ParenDepth > 0; --ParenDepth) { 15510b57cec5SDimitry Andric if (parseBinOpRHS(1, Res, EndLoc)) 15520b57cec5SDimitry Andric return true; 15530b57cec5SDimitry Andric 15540b57cec5SDimitry Andric // We don't Lex() the last RParen. 15550b57cec5SDimitry Andric // This is the same behavior as parseParenExpression(). 15560b57cec5SDimitry Andric if (ParenDepth - 1 > 0) { 15570b57cec5SDimitry Andric EndLoc = getTok().getEndLoc(); 155804eeddc0SDimitry Andric if (parseRParen()) 15590b57cec5SDimitry Andric return true; 15600b57cec5SDimitry Andric } 15610b57cec5SDimitry Andric } 15620b57cec5SDimitry Andric return false; 15630b57cec5SDimitry Andric } 15640b57cec5SDimitry Andric 15650b57cec5SDimitry Andric bool AsmParser::parseAbsoluteExpression(int64_t &Res) { 15660b57cec5SDimitry Andric const MCExpr *Expr; 15670b57cec5SDimitry Andric 15680b57cec5SDimitry Andric SMLoc StartLoc = Lexer.getLoc(); 15690b57cec5SDimitry Andric if (parseExpression(Expr)) 15700b57cec5SDimitry Andric return true; 15710b57cec5SDimitry Andric 15720b57cec5SDimitry Andric if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr())) 15730b57cec5SDimitry Andric return Error(StartLoc, "expected absolute expression"); 15740b57cec5SDimitry Andric 15750b57cec5SDimitry Andric return false; 15760b57cec5SDimitry Andric } 15770b57cec5SDimitry Andric 15780b57cec5SDimitry Andric static unsigned getDarwinBinOpPrecedence(AsmToken::TokenKind K, 15790b57cec5SDimitry Andric MCBinaryExpr::Opcode &Kind, 15800b57cec5SDimitry Andric bool ShouldUseLogicalShr) { 15810b57cec5SDimitry Andric switch (K) { 15820b57cec5SDimitry Andric default: 15830b57cec5SDimitry Andric return 0; // not a binop. 15840b57cec5SDimitry Andric 15850b57cec5SDimitry Andric // Lowest Precedence: &&, || 15860b57cec5SDimitry Andric case AsmToken::AmpAmp: 15870b57cec5SDimitry Andric Kind = MCBinaryExpr::LAnd; 15880b57cec5SDimitry Andric return 1; 15890b57cec5SDimitry Andric case AsmToken::PipePipe: 15900b57cec5SDimitry Andric Kind = MCBinaryExpr::LOr; 15910b57cec5SDimitry Andric return 1; 15920b57cec5SDimitry Andric 15930b57cec5SDimitry Andric // Low Precedence: |, &, ^ 15940b57cec5SDimitry Andric case AsmToken::Pipe: 15950b57cec5SDimitry Andric Kind = MCBinaryExpr::Or; 15960b57cec5SDimitry Andric return 2; 15970b57cec5SDimitry Andric case AsmToken::Caret: 15980b57cec5SDimitry Andric Kind = MCBinaryExpr::Xor; 15990b57cec5SDimitry Andric return 2; 16000b57cec5SDimitry Andric case AsmToken::Amp: 16010b57cec5SDimitry Andric Kind = MCBinaryExpr::And; 16020b57cec5SDimitry Andric return 2; 16030b57cec5SDimitry Andric 16040b57cec5SDimitry Andric // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >= 16050b57cec5SDimitry Andric case AsmToken::EqualEqual: 16060b57cec5SDimitry Andric Kind = MCBinaryExpr::EQ; 16070b57cec5SDimitry Andric return 3; 16080b57cec5SDimitry Andric case AsmToken::ExclaimEqual: 16090b57cec5SDimitry Andric case AsmToken::LessGreater: 16100b57cec5SDimitry Andric Kind = MCBinaryExpr::NE; 16110b57cec5SDimitry Andric return 3; 16120b57cec5SDimitry Andric case AsmToken::Less: 16130b57cec5SDimitry Andric Kind = MCBinaryExpr::LT; 16140b57cec5SDimitry Andric return 3; 16150b57cec5SDimitry Andric case AsmToken::LessEqual: 16160b57cec5SDimitry Andric Kind = MCBinaryExpr::LTE; 16170b57cec5SDimitry Andric return 3; 16180b57cec5SDimitry Andric case AsmToken::Greater: 16190b57cec5SDimitry Andric Kind = MCBinaryExpr::GT; 16200b57cec5SDimitry Andric return 3; 16210b57cec5SDimitry Andric case AsmToken::GreaterEqual: 16220b57cec5SDimitry Andric Kind = MCBinaryExpr::GTE; 16230b57cec5SDimitry Andric return 3; 16240b57cec5SDimitry Andric 16250b57cec5SDimitry Andric // Intermediate Precedence: <<, >> 16260b57cec5SDimitry Andric case AsmToken::LessLess: 16270b57cec5SDimitry Andric Kind = MCBinaryExpr::Shl; 16280b57cec5SDimitry Andric return 4; 16290b57cec5SDimitry Andric case AsmToken::GreaterGreater: 16300b57cec5SDimitry Andric Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr; 16310b57cec5SDimitry Andric return 4; 16320b57cec5SDimitry Andric 16330b57cec5SDimitry Andric // High Intermediate Precedence: +, - 16340b57cec5SDimitry Andric case AsmToken::Plus: 16350b57cec5SDimitry Andric Kind = MCBinaryExpr::Add; 16360b57cec5SDimitry Andric return 5; 16370b57cec5SDimitry Andric case AsmToken::Minus: 16380b57cec5SDimitry Andric Kind = MCBinaryExpr::Sub; 16390b57cec5SDimitry Andric return 5; 16400b57cec5SDimitry Andric 16410b57cec5SDimitry Andric // Highest Precedence: *, /, % 16420b57cec5SDimitry Andric case AsmToken::Star: 16430b57cec5SDimitry Andric Kind = MCBinaryExpr::Mul; 16440b57cec5SDimitry Andric return 6; 16450b57cec5SDimitry Andric case AsmToken::Slash: 16460b57cec5SDimitry Andric Kind = MCBinaryExpr::Div; 16470b57cec5SDimitry Andric return 6; 16480b57cec5SDimitry Andric case AsmToken::Percent: 16490b57cec5SDimitry Andric Kind = MCBinaryExpr::Mod; 16500b57cec5SDimitry Andric return 6; 16510b57cec5SDimitry Andric } 16520b57cec5SDimitry Andric } 16530b57cec5SDimitry Andric 1654e8d8bef9SDimitry Andric static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI, 1655e8d8bef9SDimitry Andric AsmToken::TokenKind K, 16560b57cec5SDimitry Andric MCBinaryExpr::Opcode &Kind, 16570b57cec5SDimitry Andric bool ShouldUseLogicalShr) { 16580b57cec5SDimitry Andric switch (K) { 16590b57cec5SDimitry Andric default: 16600b57cec5SDimitry Andric return 0; // not a binop. 16610b57cec5SDimitry Andric 16620b57cec5SDimitry Andric // Lowest Precedence: &&, || 16630b57cec5SDimitry Andric case AsmToken::AmpAmp: 16640b57cec5SDimitry Andric Kind = MCBinaryExpr::LAnd; 16650b57cec5SDimitry Andric return 2; 16660b57cec5SDimitry Andric case AsmToken::PipePipe: 16670b57cec5SDimitry Andric Kind = MCBinaryExpr::LOr; 16680b57cec5SDimitry Andric return 1; 16690b57cec5SDimitry Andric 16700b57cec5SDimitry Andric // Low Precedence: ==, !=, <>, <, <=, >, >= 16710b57cec5SDimitry Andric case AsmToken::EqualEqual: 16720b57cec5SDimitry Andric Kind = MCBinaryExpr::EQ; 16730b57cec5SDimitry Andric return 3; 16740b57cec5SDimitry Andric case AsmToken::ExclaimEqual: 16750b57cec5SDimitry Andric case AsmToken::LessGreater: 16760b57cec5SDimitry Andric Kind = MCBinaryExpr::NE; 16770b57cec5SDimitry Andric return 3; 16780b57cec5SDimitry Andric case AsmToken::Less: 16790b57cec5SDimitry Andric Kind = MCBinaryExpr::LT; 16800b57cec5SDimitry Andric return 3; 16810b57cec5SDimitry Andric case AsmToken::LessEqual: 16820b57cec5SDimitry Andric Kind = MCBinaryExpr::LTE; 16830b57cec5SDimitry Andric return 3; 16840b57cec5SDimitry Andric case AsmToken::Greater: 16850b57cec5SDimitry Andric Kind = MCBinaryExpr::GT; 16860b57cec5SDimitry Andric return 3; 16870b57cec5SDimitry Andric case AsmToken::GreaterEqual: 16880b57cec5SDimitry Andric Kind = MCBinaryExpr::GTE; 16890b57cec5SDimitry Andric return 3; 16900b57cec5SDimitry Andric 16910b57cec5SDimitry Andric // Low Intermediate Precedence: +, - 16920b57cec5SDimitry Andric case AsmToken::Plus: 16930b57cec5SDimitry Andric Kind = MCBinaryExpr::Add; 16940b57cec5SDimitry Andric return 4; 16950b57cec5SDimitry Andric case AsmToken::Minus: 16960b57cec5SDimitry Andric Kind = MCBinaryExpr::Sub; 16970b57cec5SDimitry Andric return 4; 16980b57cec5SDimitry Andric 1699e8d8bef9SDimitry Andric // High Intermediate Precedence: |, !, &, ^ 17000b57cec5SDimitry Andric // 17010b57cec5SDimitry Andric case AsmToken::Pipe: 17020b57cec5SDimitry Andric Kind = MCBinaryExpr::Or; 17030b57cec5SDimitry Andric return 5; 1704e8d8bef9SDimitry Andric case AsmToken::Exclaim: 1705e8d8bef9SDimitry Andric // Hack to support ARM compatible aliases (implied 'sp' operand in 'srs*' 1706e8d8bef9SDimitry Andric // instructions like 'srsda #31!') and not parse ! as an infix operator. 1707e8d8bef9SDimitry Andric if (MAI.getCommentString() == "@") 1708e8d8bef9SDimitry Andric return 0; 1709e8d8bef9SDimitry Andric Kind = MCBinaryExpr::OrNot; 1710e8d8bef9SDimitry Andric return 5; 17110b57cec5SDimitry Andric case AsmToken::Caret: 17120b57cec5SDimitry Andric Kind = MCBinaryExpr::Xor; 17130b57cec5SDimitry Andric return 5; 17140b57cec5SDimitry Andric case AsmToken::Amp: 17150b57cec5SDimitry Andric Kind = MCBinaryExpr::And; 17160b57cec5SDimitry Andric return 5; 17170b57cec5SDimitry Andric 17180b57cec5SDimitry Andric // Highest Precedence: *, /, %, <<, >> 17190b57cec5SDimitry Andric case AsmToken::Star: 17200b57cec5SDimitry Andric Kind = MCBinaryExpr::Mul; 17210b57cec5SDimitry Andric return 6; 17220b57cec5SDimitry Andric case AsmToken::Slash: 17230b57cec5SDimitry Andric Kind = MCBinaryExpr::Div; 17240b57cec5SDimitry Andric return 6; 17250b57cec5SDimitry Andric case AsmToken::Percent: 17260b57cec5SDimitry Andric Kind = MCBinaryExpr::Mod; 17270b57cec5SDimitry Andric return 6; 17280b57cec5SDimitry Andric case AsmToken::LessLess: 17290b57cec5SDimitry Andric Kind = MCBinaryExpr::Shl; 17300b57cec5SDimitry Andric return 6; 17310b57cec5SDimitry Andric case AsmToken::GreaterGreater: 17320b57cec5SDimitry Andric Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr; 17330b57cec5SDimitry Andric return 6; 17340b57cec5SDimitry Andric } 17350b57cec5SDimitry Andric } 17360b57cec5SDimitry Andric 17370b57cec5SDimitry Andric unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K, 17380b57cec5SDimitry Andric MCBinaryExpr::Opcode &Kind) { 17390b57cec5SDimitry Andric bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr(); 17400b57cec5SDimitry Andric return IsDarwin ? getDarwinBinOpPrecedence(K, Kind, ShouldUseLogicalShr) 1741e8d8bef9SDimitry Andric : getGNUBinOpPrecedence(MAI, K, Kind, ShouldUseLogicalShr); 17420b57cec5SDimitry Andric } 17430b57cec5SDimitry Andric 17440b57cec5SDimitry Andric /// Parse all binary operators with precedence >= 'Precedence'. 17450b57cec5SDimitry Andric /// Res contains the LHS of the expression on input. 17460b57cec5SDimitry Andric bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, 17470b57cec5SDimitry Andric SMLoc &EndLoc) { 17480b57cec5SDimitry Andric SMLoc StartLoc = Lexer.getLoc(); 17490b57cec5SDimitry Andric while (true) { 17500b57cec5SDimitry Andric MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add; 17510b57cec5SDimitry Andric unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind); 17520b57cec5SDimitry Andric 17530b57cec5SDimitry Andric // If the next token is lower precedence than we are allowed to eat, return 17540b57cec5SDimitry Andric // successfully with what we ate already. 17550b57cec5SDimitry Andric if (TokPrec < Precedence) 17560b57cec5SDimitry Andric return false; 17570b57cec5SDimitry Andric 17580b57cec5SDimitry Andric Lex(); 17590b57cec5SDimitry Andric 17600b57cec5SDimitry Andric // Eat the next primary expression. 17610b57cec5SDimitry Andric const MCExpr *RHS; 17620b57cec5SDimitry Andric if (getTargetParser().parsePrimaryExpr(RHS, EndLoc)) 17630b57cec5SDimitry Andric return true; 17640b57cec5SDimitry Andric 17650b57cec5SDimitry Andric // If BinOp binds less tightly with RHS than the operator after RHS, let 17660b57cec5SDimitry Andric // the pending operator take RHS as its LHS. 17670b57cec5SDimitry Andric MCBinaryExpr::Opcode Dummy; 17680b57cec5SDimitry Andric unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy); 17690b57cec5SDimitry Andric if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc)) 17700b57cec5SDimitry Andric return true; 17710b57cec5SDimitry Andric 17720b57cec5SDimitry Andric // Merge LHS and RHS according to operator. 17730b57cec5SDimitry Andric Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc); 17740b57cec5SDimitry Andric } 17750b57cec5SDimitry Andric } 17760b57cec5SDimitry Andric 17770b57cec5SDimitry Andric /// ParseStatement: 17780b57cec5SDimitry Andric /// ::= EndOfStatement 17790b57cec5SDimitry Andric /// ::= Label* Directive ...Operands... EndOfStatement 17800b57cec5SDimitry Andric /// ::= Label* Identifier OperandList* EndOfStatement 17810b57cec5SDimitry Andric bool AsmParser::parseStatement(ParseStatementInfo &Info, 17820b57cec5SDimitry Andric MCAsmParserSemaCallback *SI) { 17830b57cec5SDimitry Andric assert(!hasPendingError() && "parseStatement started with pending error"); 17840b57cec5SDimitry Andric // Eat initial spaces and comments 17850b57cec5SDimitry Andric while (Lexer.is(AsmToken::Space)) 17860b57cec5SDimitry Andric Lex(); 17870b57cec5SDimitry Andric if (Lexer.is(AsmToken::EndOfStatement)) { 17880b57cec5SDimitry Andric // if this is a line comment we can drop it safely 17890b57cec5SDimitry Andric if (getTok().getString().empty() || getTok().getString().front() == '\r' || 17900b57cec5SDimitry Andric getTok().getString().front() == '\n') 179181ad6265SDimitry Andric Out.addBlankLine(); 17920b57cec5SDimitry Andric Lex(); 17930b57cec5SDimitry Andric return false; 17940b57cec5SDimitry Andric } 17950b57cec5SDimitry Andric // Statements always start with an identifier. 17960b57cec5SDimitry Andric AsmToken ID = getTok(); 17970b57cec5SDimitry Andric SMLoc IDLoc = ID.getLoc(); 17980b57cec5SDimitry Andric StringRef IDVal; 17990b57cec5SDimitry Andric int64_t LocalLabelVal = -1; 1800e8d8bef9SDimitry Andric StartTokLoc = ID.getLoc(); 18010b57cec5SDimitry Andric if (Lexer.is(AsmToken::HashDirective)) 18025ffd83dbSDimitry Andric return parseCppHashLineFilenameComment(IDLoc, 18035ffd83dbSDimitry Andric !isInsideMacroInstantiation()); 18045ffd83dbSDimitry Andric 18050b57cec5SDimitry Andric // Allow an integer followed by a ':' as a directional local label. 18060b57cec5SDimitry Andric if (Lexer.is(AsmToken::Integer)) { 18070b57cec5SDimitry Andric LocalLabelVal = getTok().getIntVal(); 18080b57cec5SDimitry Andric if (LocalLabelVal < 0) { 18090b57cec5SDimitry Andric if (!TheCondState.Ignore) { 18100b57cec5SDimitry Andric Lex(); // always eat a token 18110b57cec5SDimitry Andric return Error(IDLoc, "unexpected token at start of statement"); 18120b57cec5SDimitry Andric } 18130b57cec5SDimitry Andric IDVal = ""; 18140b57cec5SDimitry Andric } else { 18150b57cec5SDimitry Andric IDVal = getTok().getString(); 18160b57cec5SDimitry Andric Lex(); // Consume the integer token to be used as an identifier token. 18170b57cec5SDimitry Andric if (Lexer.getKind() != AsmToken::Colon) { 18180b57cec5SDimitry Andric if (!TheCondState.Ignore) { 18190b57cec5SDimitry Andric Lex(); // always eat a token 18200b57cec5SDimitry Andric return Error(IDLoc, "unexpected token at start of statement"); 18210b57cec5SDimitry Andric } 18220b57cec5SDimitry Andric } 18230b57cec5SDimitry Andric } 18240b57cec5SDimitry Andric } else if (Lexer.is(AsmToken::Dot)) { 18250b57cec5SDimitry Andric // Treat '.' as a valid identifier in this context. 18260b57cec5SDimitry Andric Lex(); 18270b57cec5SDimitry Andric IDVal = "."; 18280b57cec5SDimitry Andric } else if (Lexer.is(AsmToken::LCurly)) { 18290b57cec5SDimitry Andric // Treat '{' as a valid identifier in this context. 18300b57cec5SDimitry Andric Lex(); 18310b57cec5SDimitry Andric IDVal = "{"; 18320b57cec5SDimitry Andric 18330b57cec5SDimitry Andric } else if (Lexer.is(AsmToken::RCurly)) { 18340b57cec5SDimitry Andric // Treat '}' as a valid identifier in this context. 18350b57cec5SDimitry Andric Lex(); 18360b57cec5SDimitry Andric IDVal = "}"; 18370b57cec5SDimitry Andric } else if (Lexer.is(AsmToken::Star) && 18380b57cec5SDimitry Andric getTargetParser().starIsStartOfStatement()) { 18390b57cec5SDimitry Andric // Accept '*' as a valid start of statement. 18400b57cec5SDimitry Andric Lex(); 18410b57cec5SDimitry Andric IDVal = "*"; 18420b57cec5SDimitry Andric } else if (parseIdentifier(IDVal)) { 18430b57cec5SDimitry Andric if (!TheCondState.Ignore) { 18440b57cec5SDimitry Andric Lex(); // always eat a token 18450b57cec5SDimitry Andric return Error(IDLoc, "unexpected token at start of statement"); 18460b57cec5SDimitry Andric } 18470b57cec5SDimitry Andric IDVal = ""; 18480b57cec5SDimitry Andric } 18490b57cec5SDimitry Andric 18500b57cec5SDimitry Andric // Handle conditional assembly here before checking for skipping. We 18510b57cec5SDimitry Andric // have to do this so that .endif isn't skipped in a ".if 0" block for 18520b57cec5SDimitry Andric // example. 18530b57cec5SDimitry Andric StringMap<DirectiveKind>::const_iterator DirKindIt = 18545ffd83dbSDimitry Andric DirectiveKindMap.find(IDVal.lower()); 18550b57cec5SDimitry Andric DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end()) 18560b57cec5SDimitry Andric ? DK_NO_DIRECTIVE 18570b57cec5SDimitry Andric : DirKindIt->getValue(); 18580b57cec5SDimitry Andric switch (DirKind) { 18590b57cec5SDimitry Andric default: 18600b57cec5SDimitry Andric break; 18610b57cec5SDimitry Andric case DK_IF: 18620b57cec5SDimitry Andric case DK_IFEQ: 18630b57cec5SDimitry Andric case DK_IFGE: 18640b57cec5SDimitry Andric case DK_IFGT: 18650b57cec5SDimitry Andric case DK_IFLE: 18660b57cec5SDimitry Andric case DK_IFLT: 18670b57cec5SDimitry Andric case DK_IFNE: 18680b57cec5SDimitry Andric return parseDirectiveIf(IDLoc, DirKind); 18690b57cec5SDimitry Andric case DK_IFB: 18700b57cec5SDimitry Andric return parseDirectiveIfb(IDLoc, true); 18710b57cec5SDimitry Andric case DK_IFNB: 18720b57cec5SDimitry Andric return parseDirectiveIfb(IDLoc, false); 18730b57cec5SDimitry Andric case DK_IFC: 18740b57cec5SDimitry Andric return parseDirectiveIfc(IDLoc, true); 18750b57cec5SDimitry Andric case DK_IFEQS: 18760b57cec5SDimitry Andric return parseDirectiveIfeqs(IDLoc, true); 18770b57cec5SDimitry Andric case DK_IFNC: 18780b57cec5SDimitry Andric return parseDirectiveIfc(IDLoc, false); 18790b57cec5SDimitry Andric case DK_IFNES: 18800b57cec5SDimitry Andric return parseDirectiveIfeqs(IDLoc, false); 18810b57cec5SDimitry Andric case DK_IFDEF: 18820b57cec5SDimitry Andric return parseDirectiveIfdef(IDLoc, true); 18830b57cec5SDimitry Andric case DK_IFNDEF: 18840b57cec5SDimitry Andric case DK_IFNOTDEF: 18850b57cec5SDimitry Andric return parseDirectiveIfdef(IDLoc, false); 18860b57cec5SDimitry Andric case DK_ELSEIF: 18870b57cec5SDimitry Andric return parseDirectiveElseIf(IDLoc); 18880b57cec5SDimitry Andric case DK_ELSE: 18890b57cec5SDimitry Andric return parseDirectiveElse(IDLoc); 18900b57cec5SDimitry Andric case DK_ENDIF: 18910b57cec5SDimitry Andric return parseDirectiveEndIf(IDLoc); 18920b57cec5SDimitry Andric } 18930b57cec5SDimitry Andric 18940b57cec5SDimitry Andric // Ignore the statement if in the middle of inactive conditional 18950b57cec5SDimitry Andric // (e.g. ".if 0"). 18960b57cec5SDimitry Andric if (TheCondState.Ignore) { 18970b57cec5SDimitry Andric eatToEndOfStatement(); 18980b57cec5SDimitry Andric return false; 18990b57cec5SDimitry Andric } 19000b57cec5SDimitry Andric 19010b57cec5SDimitry Andric // FIXME: Recurse on local labels? 19020b57cec5SDimitry Andric 1903bdd1243dSDimitry Andric // Check for a label. 1904bdd1243dSDimitry Andric // ::= identifier ':' 1905bdd1243dSDimitry Andric // ::= number ':' 1906bdd1243dSDimitry Andric if (Lexer.is(AsmToken::Colon) && getTargetParser().isLabel(ID)) { 19070b57cec5SDimitry Andric if (checkForValidSection()) 19080b57cec5SDimitry Andric return true; 19090b57cec5SDimitry Andric 1910bdd1243dSDimitry Andric Lex(); // Consume the ':'. 19110b57cec5SDimitry Andric 19120b57cec5SDimitry Andric // Diagnose attempt to use '.' as a label. 19130b57cec5SDimitry Andric if (IDVal == ".") 19140b57cec5SDimitry Andric return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label"); 19150b57cec5SDimitry Andric 19160b57cec5SDimitry Andric // Diagnose attempt to use a variable as a label. 19170b57cec5SDimitry Andric // 19180b57cec5SDimitry Andric // FIXME: Diagnostics. Note the location of the definition as a label. 19190b57cec5SDimitry Andric // FIXME: This doesn't diagnose assignment to a symbol which has been 19200b57cec5SDimitry Andric // implicitly marked as external. 19210b57cec5SDimitry Andric MCSymbol *Sym; 19220b57cec5SDimitry Andric if (LocalLabelVal == -1) { 19235ffd83dbSDimitry Andric if (ParsingMSInlineAsm && SI) { 19240b57cec5SDimitry Andric StringRef RewrittenLabel = 19250b57cec5SDimitry Andric SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true); 19260b57cec5SDimitry Andric assert(!RewrittenLabel.empty() && 19270b57cec5SDimitry Andric "We should have an internal name here."); 19280b57cec5SDimitry Andric Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(), 19290b57cec5SDimitry Andric RewrittenLabel); 19300b57cec5SDimitry Andric IDVal = RewrittenLabel; 19310b57cec5SDimitry Andric } 19320b57cec5SDimitry Andric Sym = getContext().getOrCreateSymbol(IDVal); 19330b57cec5SDimitry Andric } else 19340b57cec5SDimitry Andric Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal); 19350b57cec5SDimitry Andric // End of Labels should be treated as end of line for lexing 19360b57cec5SDimitry Andric // purposes but that information is not available to the Lexer who 19370b57cec5SDimitry Andric // does not understand Labels. This may cause us to see a Hash 19380b57cec5SDimitry Andric // here instead of a preprocessor line comment. 19390b57cec5SDimitry Andric if (getTok().is(AsmToken::Hash)) { 19400b57cec5SDimitry Andric StringRef CommentStr = parseStringToEndOfStatement(); 19410b57cec5SDimitry Andric Lexer.Lex(); 19420b57cec5SDimitry Andric Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr)); 19430b57cec5SDimitry Andric } 19440b57cec5SDimitry Andric 19450b57cec5SDimitry Andric // Consume any end of statement token, if present, to avoid spurious 194681ad6265SDimitry Andric // addBlankLine calls(). 19470b57cec5SDimitry Andric if (getTok().is(AsmToken::EndOfStatement)) { 19480b57cec5SDimitry Andric Lex(); 19490b57cec5SDimitry Andric } 19500b57cec5SDimitry Andric 1951439352acSDimitry Andric if (MAI.hasSubsectionsViaSymbols() && CFIStartProcLoc && 1952439352acSDimitry Andric Sym->isExternal() && !cast<MCSymbolMachO>(Sym)->isAltEntry()) 19535f757f3fSDimitry Andric return Error(StartTokLoc, "non-private labels cannot appear between " 19545f757f3fSDimitry Andric ".cfi_startproc / .cfi_endproc pairs") && 19555f757f3fSDimitry Andric Error(*CFIStartProcLoc, "previous .cfi_startproc was here"); 19565f757f3fSDimitry Andric 1957fe6060f1SDimitry Andric if (discardLTOSymbol(IDVal)) 1958fe6060f1SDimitry Andric return false; 1959fe6060f1SDimitry Andric 1960bdd1243dSDimitry Andric getTargetParser().doBeforeLabelEmit(Sym, IDLoc); 19610b57cec5SDimitry Andric 19620b57cec5SDimitry Andric // Emit the label. 19635ffd83dbSDimitry Andric if (!getTargetParser().isParsingMSInlineAsm()) 19645ffd83dbSDimitry Andric Out.emitLabel(Sym, IDLoc); 19650b57cec5SDimitry Andric 19660b57cec5SDimitry Andric // If we are generating dwarf for assembly source files then gather the 19670b57cec5SDimitry Andric // info to make a dwarf label entry for this label if needed. 19680b57cec5SDimitry Andric if (enabledGenDwarfForAssembly()) 19690b57cec5SDimitry Andric MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(), 19700b57cec5SDimitry Andric IDLoc); 19710b57cec5SDimitry Andric 19720b57cec5SDimitry Andric getTargetParser().onLabelParsed(Sym); 19730b57cec5SDimitry Andric 19740b57cec5SDimitry Andric return false; 19750b57cec5SDimitry Andric } 19760b57cec5SDimitry Andric 1977bdd1243dSDimitry Andric // Check for an assignment statement. 1978bdd1243dSDimitry Andric // ::= identifier '=' 1979bdd1243dSDimitry Andric if (Lexer.is(AsmToken::Equal) && getTargetParser().equalIsAsmAssignment()) { 19800b57cec5SDimitry Andric Lex(); 19810eae32dcSDimitry Andric return parseAssignment(IDVal, AssignmentKind::Equal); 19820b57cec5SDimitry Andric } 19830b57cec5SDimitry Andric 19840b57cec5SDimitry Andric // If macros are enabled, check to see if this is a macro instantiation. 19850b57cec5SDimitry Andric if (areMacrosEnabled()) 1986*0fca6ea1SDimitry Andric if (MCAsmMacro *M = getContext().lookupMacro(IDVal)) 19870b57cec5SDimitry Andric return handleMacroEntry(M, IDLoc); 19880b57cec5SDimitry Andric 19890b57cec5SDimitry Andric // Otherwise, we have a normal instruction or directive. 19900b57cec5SDimitry Andric 19910b57cec5SDimitry Andric // Directives start with "." 19925f757f3fSDimitry Andric if (IDVal.starts_with(".") && IDVal != ".") { 19930b57cec5SDimitry Andric // There are several entities interested in parsing directives: 19940b57cec5SDimitry Andric // 19950b57cec5SDimitry Andric // 1. The target-specific assembly parser. Some directives are target 19960b57cec5SDimitry Andric // specific or may potentially behave differently on certain targets. 19970b57cec5SDimitry Andric // 2. Asm parser extensions. For example, platform-specific parsers 19980b57cec5SDimitry Andric // (like the ELF parser) register themselves as extensions. 19990b57cec5SDimitry Andric // 3. The generic directive parser implemented by this class. These are 20000b57cec5SDimitry Andric // all the directives that behave in a target and platform independent 20010b57cec5SDimitry Andric // manner, or at least have a default behavior that's shared between 20020b57cec5SDimitry Andric // all targets and platforms. 20030b57cec5SDimitry Andric 20040b57cec5SDimitry Andric getTargetParser().flushPendingInstructions(getStreamer()); 20050b57cec5SDimitry Andric 200606c3fb27SDimitry Andric ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(ID); 200706c3fb27SDimitry Andric assert(TPDirectiveReturn.isFailure() == hasPendingError() && 200806c3fb27SDimitry Andric "Should only return Failure iff there was an error"); 200906c3fb27SDimitry Andric if (TPDirectiveReturn.isFailure()) 20100b57cec5SDimitry Andric return true; 201106c3fb27SDimitry Andric if (TPDirectiveReturn.isSuccess()) 20120b57cec5SDimitry Andric return false; 20130b57cec5SDimitry Andric 20140b57cec5SDimitry Andric // Next, check the extension directive map to see if any extension has 20150b57cec5SDimitry Andric // registered itself to parse this directive. 20160b57cec5SDimitry Andric std::pair<MCAsmParserExtension *, DirectiveHandler> Handler = 20170b57cec5SDimitry Andric ExtensionDirectiveMap.lookup(IDVal); 20180b57cec5SDimitry Andric if (Handler.first) 20190b57cec5SDimitry Andric return (*Handler.second)(Handler.first, IDVal, IDLoc); 20200b57cec5SDimitry Andric 20210b57cec5SDimitry Andric // Finally, if no one else is interested in this directive, it must be 20220b57cec5SDimitry Andric // generic and familiar to this class. 20230b57cec5SDimitry Andric switch (DirKind) { 20240b57cec5SDimitry Andric default: 20250b57cec5SDimitry Andric break; 20260b57cec5SDimitry Andric case DK_SET: 20270b57cec5SDimitry Andric case DK_EQU: 20280eae32dcSDimitry Andric return parseDirectiveSet(IDVal, AssignmentKind::Set); 20290b57cec5SDimitry Andric case DK_EQUIV: 20300eae32dcSDimitry Andric return parseDirectiveSet(IDVal, AssignmentKind::Equiv); 20310eae32dcSDimitry Andric case DK_LTO_SET_CONDITIONAL: 20320eae32dcSDimitry Andric return parseDirectiveSet(IDVal, AssignmentKind::LTOSetConditional); 20330b57cec5SDimitry Andric case DK_ASCII: 20340b57cec5SDimitry Andric return parseDirectiveAscii(IDVal, false); 20350b57cec5SDimitry Andric case DK_ASCIZ: 20360b57cec5SDimitry Andric case DK_STRING: 20370b57cec5SDimitry Andric return parseDirectiveAscii(IDVal, true); 20380b57cec5SDimitry Andric case DK_BYTE: 20390b57cec5SDimitry Andric case DK_DC_B: 20400b57cec5SDimitry Andric return parseDirectiveValue(IDVal, 1); 20410b57cec5SDimitry Andric case DK_DC: 20420b57cec5SDimitry Andric case DK_DC_W: 20430b57cec5SDimitry Andric case DK_SHORT: 20440b57cec5SDimitry Andric case DK_VALUE: 20450b57cec5SDimitry Andric case DK_2BYTE: 20460b57cec5SDimitry Andric return parseDirectiveValue(IDVal, 2); 20470b57cec5SDimitry Andric case DK_LONG: 20480b57cec5SDimitry Andric case DK_INT: 20490b57cec5SDimitry Andric case DK_4BYTE: 20500b57cec5SDimitry Andric case DK_DC_L: 20510b57cec5SDimitry Andric return parseDirectiveValue(IDVal, 4); 20520b57cec5SDimitry Andric case DK_QUAD: 20530b57cec5SDimitry Andric case DK_8BYTE: 20540b57cec5SDimitry Andric return parseDirectiveValue(IDVal, 8); 20550b57cec5SDimitry Andric case DK_DC_A: 20560b57cec5SDimitry Andric return parseDirectiveValue( 20570b57cec5SDimitry Andric IDVal, getContext().getAsmInfo()->getCodePointerSize()); 20580b57cec5SDimitry Andric case DK_OCTA: 20590b57cec5SDimitry Andric return parseDirectiveOctaValue(IDVal); 20600b57cec5SDimitry Andric case DK_SINGLE: 20610b57cec5SDimitry Andric case DK_FLOAT: 20620b57cec5SDimitry Andric case DK_DC_S: 20630b57cec5SDimitry Andric return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle()); 20640b57cec5SDimitry Andric case DK_DOUBLE: 20650b57cec5SDimitry Andric case DK_DC_D: 20660b57cec5SDimitry Andric return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble()); 20670b57cec5SDimitry Andric case DK_ALIGN: { 20680b57cec5SDimitry Andric bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes(); 20690b57cec5SDimitry Andric return parseDirectiveAlign(IsPow2, /*ExprSize=*/1); 20700b57cec5SDimitry Andric } 20710b57cec5SDimitry Andric case DK_ALIGN32: { 20720b57cec5SDimitry Andric bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes(); 20730b57cec5SDimitry Andric return parseDirectiveAlign(IsPow2, /*ExprSize=*/4); 20740b57cec5SDimitry Andric } 20750b57cec5SDimitry Andric case DK_BALIGN: 20760b57cec5SDimitry Andric return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1); 20770b57cec5SDimitry Andric case DK_BALIGNW: 20780b57cec5SDimitry Andric return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2); 20790b57cec5SDimitry Andric case DK_BALIGNL: 20800b57cec5SDimitry Andric return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4); 20810b57cec5SDimitry Andric case DK_P2ALIGN: 20820b57cec5SDimitry Andric return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1); 20830b57cec5SDimitry Andric case DK_P2ALIGNW: 20840b57cec5SDimitry Andric return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2); 20850b57cec5SDimitry Andric case DK_P2ALIGNL: 20860b57cec5SDimitry Andric return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4); 20870b57cec5SDimitry Andric case DK_ORG: 20880b57cec5SDimitry Andric return parseDirectiveOrg(); 20890b57cec5SDimitry Andric case DK_FILL: 20900b57cec5SDimitry Andric return parseDirectiveFill(); 20910b57cec5SDimitry Andric case DK_ZERO: 20920b57cec5SDimitry Andric return parseDirectiveZero(); 20930b57cec5SDimitry Andric case DK_EXTERN: 20940b57cec5SDimitry Andric eatToEndOfStatement(); // .extern is the default, ignore it. 20950b57cec5SDimitry Andric return false; 20960b57cec5SDimitry Andric case DK_GLOBL: 20970b57cec5SDimitry Andric case DK_GLOBAL: 20980b57cec5SDimitry Andric return parseDirectiveSymbolAttribute(MCSA_Global); 20990b57cec5SDimitry Andric case DK_LAZY_REFERENCE: 21000b57cec5SDimitry Andric return parseDirectiveSymbolAttribute(MCSA_LazyReference); 21010b57cec5SDimitry Andric case DK_NO_DEAD_STRIP: 21020b57cec5SDimitry Andric return parseDirectiveSymbolAttribute(MCSA_NoDeadStrip); 21030b57cec5SDimitry Andric case DK_SYMBOL_RESOLVER: 21040b57cec5SDimitry Andric return parseDirectiveSymbolAttribute(MCSA_SymbolResolver); 21050b57cec5SDimitry Andric case DK_PRIVATE_EXTERN: 21060b57cec5SDimitry Andric return parseDirectiveSymbolAttribute(MCSA_PrivateExtern); 21070b57cec5SDimitry Andric case DK_REFERENCE: 21080b57cec5SDimitry Andric return parseDirectiveSymbolAttribute(MCSA_Reference); 21090b57cec5SDimitry Andric case DK_WEAK_DEFINITION: 21100b57cec5SDimitry Andric return parseDirectiveSymbolAttribute(MCSA_WeakDefinition); 21110b57cec5SDimitry Andric case DK_WEAK_REFERENCE: 21120b57cec5SDimitry Andric return parseDirectiveSymbolAttribute(MCSA_WeakReference); 21130b57cec5SDimitry Andric case DK_WEAK_DEF_CAN_BE_HIDDEN: 21140b57cec5SDimitry Andric return parseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate); 21150b57cec5SDimitry Andric case DK_COLD: 21160b57cec5SDimitry Andric return parseDirectiveSymbolAttribute(MCSA_Cold); 21170b57cec5SDimitry Andric case DK_COMM: 21180b57cec5SDimitry Andric case DK_COMMON: 21190b57cec5SDimitry Andric return parseDirectiveComm(/*IsLocal=*/false); 21200b57cec5SDimitry Andric case DK_LCOMM: 21210b57cec5SDimitry Andric return parseDirectiveComm(/*IsLocal=*/true); 21220b57cec5SDimitry Andric case DK_ABORT: 2123*0fca6ea1SDimitry Andric return parseDirectiveAbort(IDLoc); 21240b57cec5SDimitry Andric case DK_INCLUDE: 21250b57cec5SDimitry Andric return parseDirectiveInclude(); 21260b57cec5SDimitry Andric case DK_INCBIN: 21270b57cec5SDimitry Andric return parseDirectiveIncbin(); 21280b57cec5SDimitry Andric case DK_CODE16: 21290b57cec5SDimitry Andric case DK_CODE16GCC: 21300b57cec5SDimitry Andric return TokError(Twine(IDVal) + 21310b57cec5SDimitry Andric " not currently supported for this target"); 21320b57cec5SDimitry Andric case DK_REPT: 21330b57cec5SDimitry Andric return parseDirectiveRept(IDLoc, IDVal); 21340b57cec5SDimitry Andric case DK_IRP: 21350b57cec5SDimitry Andric return parseDirectiveIrp(IDLoc); 21360b57cec5SDimitry Andric case DK_IRPC: 21370b57cec5SDimitry Andric return parseDirectiveIrpc(IDLoc); 21380b57cec5SDimitry Andric case DK_ENDR: 21390b57cec5SDimitry Andric return parseDirectiveEndr(IDLoc); 21400b57cec5SDimitry Andric case DK_BUNDLE_ALIGN_MODE: 21410b57cec5SDimitry Andric return parseDirectiveBundleAlignMode(); 21420b57cec5SDimitry Andric case DK_BUNDLE_LOCK: 21430b57cec5SDimitry Andric return parseDirectiveBundleLock(); 21440b57cec5SDimitry Andric case DK_BUNDLE_UNLOCK: 21450b57cec5SDimitry Andric return parseDirectiveBundleUnlock(); 21460b57cec5SDimitry Andric case DK_SLEB128: 21470b57cec5SDimitry Andric return parseDirectiveLEB128(true); 21480b57cec5SDimitry Andric case DK_ULEB128: 21490b57cec5SDimitry Andric return parseDirectiveLEB128(false); 21500b57cec5SDimitry Andric case DK_SPACE: 21510b57cec5SDimitry Andric case DK_SKIP: 21520b57cec5SDimitry Andric return parseDirectiveSpace(IDVal); 21530b57cec5SDimitry Andric case DK_FILE: 21540b57cec5SDimitry Andric return parseDirectiveFile(IDLoc); 21550b57cec5SDimitry Andric case DK_LINE: 21560b57cec5SDimitry Andric return parseDirectiveLine(); 21570b57cec5SDimitry Andric case DK_LOC: 21580b57cec5SDimitry Andric return parseDirectiveLoc(); 21590b57cec5SDimitry Andric case DK_STABS: 21600b57cec5SDimitry Andric return parseDirectiveStabs(); 21610b57cec5SDimitry Andric case DK_CV_FILE: 21620b57cec5SDimitry Andric return parseDirectiveCVFile(); 21630b57cec5SDimitry Andric case DK_CV_FUNC_ID: 21640b57cec5SDimitry Andric return parseDirectiveCVFuncId(); 21650b57cec5SDimitry Andric case DK_CV_INLINE_SITE_ID: 21660b57cec5SDimitry Andric return parseDirectiveCVInlineSiteId(); 21670b57cec5SDimitry Andric case DK_CV_LOC: 21680b57cec5SDimitry Andric return parseDirectiveCVLoc(); 21690b57cec5SDimitry Andric case DK_CV_LINETABLE: 21700b57cec5SDimitry Andric return parseDirectiveCVLinetable(); 21710b57cec5SDimitry Andric case DK_CV_INLINE_LINETABLE: 21720b57cec5SDimitry Andric return parseDirectiveCVInlineLinetable(); 21730b57cec5SDimitry Andric case DK_CV_DEF_RANGE: 21740b57cec5SDimitry Andric return parseDirectiveCVDefRange(); 21750b57cec5SDimitry Andric case DK_CV_STRING: 21760b57cec5SDimitry Andric return parseDirectiveCVString(); 21770b57cec5SDimitry Andric case DK_CV_STRINGTABLE: 21780b57cec5SDimitry Andric return parseDirectiveCVStringTable(); 21790b57cec5SDimitry Andric case DK_CV_FILECHECKSUMS: 21800b57cec5SDimitry Andric return parseDirectiveCVFileChecksums(); 21810b57cec5SDimitry Andric case DK_CV_FILECHECKSUM_OFFSET: 21820b57cec5SDimitry Andric return parseDirectiveCVFileChecksumOffset(); 21830b57cec5SDimitry Andric case DK_CV_FPO_DATA: 21840b57cec5SDimitry Andric return parseDirectiveCVFPOData(); 21850b57cec5SDimitry Andric case DK_CFI_SECTIONS: 21860b57cec5SDimitry Andric return parseDirectiveCFISections(); 21870b57cec5SDimitry Andric case DK_CFI_STARTPROC: 21880b57cec5SDimitry Andric return parseDirectiveCFIStartProc(); 21890b57cec5SDimitry Andric case DK_CFI_ENDPROC: 21900b57cec5SDimitry Andric return parseDirectiveCFIEndProc(); 21910b57cec5SDimitry Andric case DK_CFI_DEF_CFA: 21920b57cec5SDimitry Andric return parseDirectiveCFIDefCfa(IDLoc); 21930b57cec5SDimitry Andric case DK_CFI_DEF_CFA_OFFSET: 219406c3fb27SDimitry Andric return parseDirectiveCFIDefCfaOffset(IDLoc); 21950b57cec5SDimitry Andric case DK_CFI_ADJUST_CFA_OFFSET: 219606c3fb27SDimitry Andric return parseDirectiveCFIAdjustCfaOffset(IDLoc); 21970b57cec5SDimitry Andric case DK_CFI_DEF_CFA_REGISTER: 21980b57cec5SDimitry Andric return parseDirectiveCFIDefCfaRegister(IDLoc); 2199fe6060f1SDimitry Andric case DK_CFI_LLVM_DEF_ASPACE_CFA: 2200fe6060f1SDimitry Andric return parseDirectiveCFILLVMDefAspaceCfa(IDLoc); 22010b57cec5SDimitry Andric case DK_CFI_OFFSET: 22020b57cec5SDimitry Andric return parseDirectiveCFIOffset(IDLoc); 22030b57cec5SDimitry Andric case DK_CFI_REL_OFFSET: 22040b57cec5SDimitry Andric return parseDirectiveCFIRelOffset(IDLoc); 22050b57cec5SDimitry Andric case DK_CFI_PERSONALITY: 22060b57cec5SDimitry Andric return parseDirectiveCFIPersonalityOrLsda(true); 22070b57cec5SDimitry Andric case DK_CFI_LSDA: 22080b57cec5SDimitry Andric return parseDirectiveCFIPersonalityOrLsda(false); 22090b57cec5SDimitry Andric case DK_CFI_REMEMBER_STATE: 221006c3fb27SDimitry Andric return parseDirectiveCFIRememberState(IDLoc); 22110b57cec5SDimitry Andric case DK_CFI_RESTORE_STATE: 221206c3fb27SDimitry Andric return parseDirectiveCFIRestoreState(IDLoc); 22130b57cec5SDimitry Andric case DK_CFI_SAME_VALUE: 22140b57cec5SDimitry Andric return parseDirectiveCFISameValue(IDLoc); 22150b57cec5SDimitry Andric case DK_CFI_RESTORE: 22160b57cec5SDimitry Andric return parseDirectiveCFIRestore(IDLoc); 22170b57cec5SDimitry Andric case DK_CFI_ESCAPE: 221806c3fb27SDimitry Andric return parseDirectiveCFIEscape(IDLoc); 22190b57cec5SDimitry Andric case DK_CFI_RETURN_COLUMN: 22200b57cec5SDimitry Andric return parseDirectiveCFIReturnColumn(IDLoc); 22210b57cec5SDimitry Andric case DK_CFI_SIGNAL_FRAME: 222206c3fb27SDimitry Andric return parseDirectiveCFISignalFrame(IDLoc); 22230b57cec5SDimitry Andric case DK_CFI_UNDEFINED: 22240b57cec5SDimitry Andric return parseDirectiveCFIUndefined(IDLoc); 22250b57cec5SDimitry Andric case DK_CFI_REGISTER: 22260b57cec5SDimitry Andric return parseDirectiveCFIRegister(IDLoc); 22270b57cec5SDimitry Andric case DK_CFI_WINDOW_SAVE: 222806c3fb27SDimitry Andric return parseDirectiveCFIWindowSave(IDLoc); 2229*0fca6ea1SDimitry Andric case DK_CFI_LABEL: 2230*0fca6ea1SDimitry Andric return parseDirectiveCFILabel(IDLoc); 22310b57cec5SDimitry Andric case DK_MACROS_ON: 22320b57cec5SDimitry Andric case DK_MACROS_OFF: 22330b57cec5SDimitry Andric return parseDirectiveMacrosOnOff(IDVal); 22340b57cec5SDimitry Andric case DK_MACRO: 22350b57cec5SDimitry Andric return parseDirectiveMacro(IDLoc); 22360b57cec5SDimitry Andric case DK_ALTMACRO: 22370b57cec5SDimitry Andric case DK_NOALTMACRO: 22380b57cec5SDimitry Andric return parseDirectiveAltmacro(IDVal); 22390b57cec5SDimitry Andric case DK_EXITM: 22400b57cec5SDimitry Andric return parseDirectiveExitMacro(IDVal); 22410b57cec5SDimitry Andric case DK_ENDM: 22420b57cec5SDimitry Andric case DK_ENDMACRO: 22430b57cec5SDimitry Andric return parseDirectiveEndMacro(IDVal); 22440b57cec5SDimitry Andric case DK_PURGEM: 22450b57cec5SDimitry Andric return parseDirectivePurgeMacro(IDLoc); 22460b57cec5SDimitry Andric case DK_END: 22470b57cec5SDimitry Andric return parseDirectiveEnd(IDLoc); 22480b57cec5SDimitry Andric case DK_ERR: 22490b57cec5SDimitry Andric return parseDirectiveError(IDLoc, false); 22500b57cec5SDimitry Andric case DK_ERROR: 22510b57cec5SDimitry Andric return parseDirectiveError(IDLoc, true); 22520b57cec5SDimitry Andric case DK_WARNING: 22530b57cec5SDimitry Andric return parseDirectiveWarning(IDLoc); 22540b57cec5SDimitry Andric case DK_RELOC: 22550b57cec5SDimitry Andric return parseDirectiveReloc(IDLoc); 22560b57cec5SDimitry Andric case DK_DCB: 22570b57cec5SDimitry Andric case DK_DCB_W: 22580b57cec5SDimitry Andric return parseDirectiveDCB(IDVal, 2); 22590b57cec5SDimitry Andric case DK_DCB_B: 22600b57cec5SDimitry Andric return parseDirectiveDCB(IDVal, 1); 22610b57cec5SDimitry Andric case DK_DCB_D: 22620b57cec5SDimitry Andric return parseDirectiveRealDCB(IDVal, APFloat::IEEEdouble()); 22630b57cec5SDimitry Andric case DK_DCB_L: 22640b57cec5SDimitry Andric return parseDirectiveDCB(IDVal, 4); 22650b57cec5SDimitry Andric case DK_DCB_S: 22660b57cec5SDimitry Andric return parseDirectiveRealDCB(IDVal, APFloat::IEEEsingle()); 22670b57cec5SDimitry Andric case DK_DC_X: 22680b57cec5SDimitry Andric case DK_DCB_X: 22690b57cec5SDimitry Andric return TokError(Twine(IDVal) + 22700b57cec5SDimitry Andric " not currently supported for this target"); 22710b57cec5SDimitry Andric case DK_DS: 22720b57cec5SDimitry Andric case DK_DS_W: 22730b57cec5SDimitry Andric return parseDirectiveDS(IDVal, 2); 22740b57cec5SDimitry Andric case DK_DS_B: 22750b57cec5SDimitry Andric return parseDirectiveDS(IDVal, 1); 22760b57cec5SDimitry Andric case DK_DS_D: 22770b57cec5SDimitry Andric return parseDirectiveDS(IDVal, 8); 22780b57cec5SDimitry Andric case DK_DS_L: 22790b57cec5SDimitry Andric case DK_DS_S: 22800b57cec5SDimitry Andric return parseDirectiveDS(IDVal, 4); 22810b57cec5SDimitry Andric case DK_DS_P: 22820b57cec5SDimitry Andric case DK_DS_X: 22830b57cec5SDimitry Andric return parseDirectiveDS(IDVal, 12); 22840b57cec5SDimitry Andric case DK_PRINT: 22850b57cec5SDimitry Andric return parseDirectivePrint(IDLoc); 22860b57cec5SDimitry Andric case DK_ADDRSIG: 22870b57cec5SDimitry Andric return parseDirectiveAddrsig(); 22880b57cec5SDimitry Andric case DK_ADDRSIG_SYM: 22890b57cec5SDimitry Andric return parseDirectiveAddrsigSym(); 2290e8d8bef9SDimitry Andric case DK_PSEUDO_PROBE: 2291e8d8bef9SDimitry Andric return parseDirectivePseudoProbe(); 2292fe6060f1SDimitry Andric case DK_LTO_DISCARD: 2293fe6060f1SDimitry Andric return parseDirectiveLTODiscard(); 2294bdd1243dSDimitry Andric case DK_MEMTAG: 2295bdd1243dSDimitry Andric return parseDirectiveSymbolAttribute(MCSA_Memtag); 22960b57cec5SDimitry Andric } 22970b57cec5SDimitry Andric 22980b57cec5SDimitry Andric return Error(IDLoc, "unknown directive"); 22990b57cec5SDimitry Andric } 23000b57cec5SDimitry Andric 23010b57cec5SDimitry Andric // __asm _emit or __asm __emit 23025ffd83dbSDimitry Andric if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" || 23030b57cec5SDimitry Andric IDVal == "_EMIT" || IDVal == "__EMIT")) 23040b57cec5SDimitry Andric return parseDirectiveMSEmit(IDLoc, Info, IDVal.size()); 23050b57cec5SDimitry Andric 23060b57cec5SDimitry Andric // __asm align 23075ffd83dbSDimitry Andric if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN")) 23080b57cec5SDimitry Andric return parseDirectiveMSAlign(IDLoc, Info); 23090b57cec5SDimitry Andric 23105ffd83dbSDimitry Andric if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN")) 23110b57cec5SDimitry Andric Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4); 23120b57cec5SDimitry Andric if (checkForValidSection()) 23130b57cec5SDimitry Andric return true; 23140b57cec5SDimitry Andric 2315fe6060f1SDimitry Andric return parseAndMatchAndEmitTargetInstruction(Info, IDVal, ID, IDLoc); 2316fe6060f1SDimitry Andric } 2317fe6060f1SDimitry Andric 2318fe6060f1SDimitry Andric bool AsmParser::parseAndMatchAndEmitTargetInstruction(ParseStatementInfo &Info, 2319fe6060f1SDimitry Andric StringRef IDVal, 2320fe6060f1SDimitry Andric AsmToken ID, 2321fe6060f1SDimitry Andric SMLoc IDLoc) { 23220b57cec5SDimitry Andric // Canonicalize the opcode to lower case. 23230b57cec5SDimitry Andric std::string OpcodeStr = IDVal.lower(); 23240b57cec5SDimitry Andric ParseInstructionInfo IInfo(Info.AsmRewrites); 23250b57cec5SDimitry Andric bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID, 23260b57cec5SDimitry Andric Info.ParsedOperands); 23270b57cec5SDimitry Andric Info.ParseError = ParseHadError; 23280b57cec5SDimitry Andric 23290b57cec5SDimitry Andric // Dump the parsed representation, if requested. 23300b57cec5SDimitry Andric if (getShowParsedOperands()) { 23310b57cec5SDimitry Andric SmallString<256> Str; 23320b57cec5SDimitry Andric raw_svector_ostream OS(Str); 23330b57cec5SDimitry Andric OS << "parsed instruction: ["; 23340b57cec5SDimitry Andric for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) { 23350b57cec5SDimitry Andric if (i != 0) 23360b57cec5SDimitry Andric OS << ", "; 23370b57cec5SDimitry Andric Info.ParsedOperands[i]->print(OS); 23380b57cec5SDimitry Andric } 23390b57cec5SDimitry Andric OS << "]"; 23400b57cec5SDimitry Andric 23410b57cec5SDimitry Andric printMessage(IDLoc, SourceMgr::DK_Note, OS.str()); 23420b57cec5SDimitry Andric } 23430b57cec5SDimitry Andric 23440b57cec5SDimitry Andric // Fail even if ParseInstruction erroneously returns false. 23450b57cec5SDimitry Andric if (hasPendingError() || ParseHadError) 23460b57cec5SDimitry Andric return true; 23470b57cec5SDimitry Andric 23480b57cec5SDimitry Andric // If we are generating dwarf for the current section then generate a .loc 23490b57cec5SDimitry Andric // directive for the instruction. 23500b57cec5SDimitry Andric if (!ParseHadError && enabledGenDwarfForAssembly() && 23510b57cec5SDimitry Andric getContext().getGenDwarfSectionSyms().count( 23520b57cec5SDimitry Andric getStreamer().getCurrentSectionOnly())) { 23530b57cec5SDimitry Andric unsigned Line; 23540b57cec5SDimitry Andric if (ActiveMacros.empty()) 23550b57cec5SDimitry Andric Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer); 23560b57cec5SDimitry Andric else 23570b57cec5SDimitry Andric Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc, 23580b57cec5SDimitry Andric ActiveMacros.front()->ExitBuffer); 23590b57cec5SDimitry Andric 23600b57cec5SDimitry Andric // If we previously parsed a cpp hash file line comment then make sure the 23610b57cec5SDimitry Andric // current Dwarf File is for the CppHashFilename if not then emit the 23620b57cec5SDimitry Andric // Dwarf File table for it and adjust the line number for the .loc. 23630b57cec5SDimitry Andric if (!CppHashInfo.Filename.empty()) { 23645ffd83dbSDimitry Andric unsigned FileNumber = getStreamer().emitDwarfFileDirective( 23650b57cec5SDimitry Andric 0, StringRef(), CppHashInfo.Filename); 23660b57cec5SDimitry Andric getContext().setGenDwarfFileNumber(FileNumber); 23670b57cec5SDimitry Andric 23680b57cec5SDimitry Andric unsigned CppHashLocLineNo = 23690b57cec5SDimitry Andric SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf); 23700b57cec5SDimitry Andric Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo); 23710b57cec5SDimitry Andric } 23720b57cec5SDimitry Andric 23735ffd83dbSDimitry Andric getStreamer().emitDwarfLocDirective( 23740b57cec5SDimitry Andric getContext().getGenDwarfFileNumber(), Line, 0, 23750b57cec5SDimitry Andric DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0, 23760b57cec5SDimitry Andric StringRef()); 23770b57cec5SDimitry Andric } 23780b57cec5SDimitry Andric 23790b57cec5SDimitry Andric // If parsing succeeded, match the instruction. 23800b57cec5SDimitry Andric if (!ParseHadError) { 23810b57cec5SDimitry Andric uint64_t ErrorInfo; 23820b57cec5SDimitry Andric if (getTargetParser().MatchAndEmitInstruction( 23830b57cec5SDimitry Andric IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo, 23845ffd83dbSDimitry Andric getTargetParser().isParsingMSInlineAsm())) 23850b57cec5SDimitry Andric return true; 23860b57cec5SDimitry Andric } 23870b57cec5SDimitry Andric return false; 23880b57cec5SDimitry Andric } 23890b57cec5SDimitry Andric 23900b57cec5SDimitry Andric // Parse and erase curly braces marking block start/end 23910b57cec5SDimitry Andric bool 23920b57cec5SDimitry Andric AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) { 23930b57cec5SDimitry Andric // Identify curly brace marking block start/end 23940b57cec5SDimitry Andric if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly)) 23950b57cec5SDimitry Andric return false; 23960b57cec5SDimitry Andric 23970b57cec5SDimitry Andric SMLoc StartLoc = Lexer.getLoc(); 23980b57cec5SDimitry Andric Lex(); // Eat the brace 23990b57cec5SDimitry Andric if (Lexer.is(AsmToken::EndOfStatement)) 24000b57cec5SDimitry Andric Lex(); // Eat EndOfStatement following the brace 24010b57cec5SDimitry Andric 24020b57cec5SDimitry Andric // Erase the block start/end brace from the output asm string 24030b57cec5SDimitry Andric AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() - 24040b57cec5SDimitry Andric StartLoc.getPointer()); 24050b57cec5SDimitry Andric return true; 24060b57cec5SDimitry Andric } 24070b57cec5SDimitry Andric 24080b57cec5SDimitry Andric /// parseCppHashLineFilenameComment as this: 24090b57cec5SDimitry Andric /// ::= # number "filename" 24105ffd83dbSDimitry Andric bool AsmParser::parseCppHashLineFilenameComment(SMLoc L, bool SaveLocInfo) { 24110b57cec5SDimitry Andric Lex(); // Eat the hash token. 24120b57cec5SDimitry Andric // Lexer only ever emits HashDirective if it fully formed if it's 24130b57cec5SDimitry Andric // done the checking already so this is an internal error. 24140b57cec5SDimitry Andric assert(getTok().is(AsmToken::Integer) && 24150b57cec5SDimitry Andric "Lexing Cpp line comment: Expected Integer"); 24160b57cec5SDimitry Andric int64_t LineNumber = getTok().getIntVal(); 24170b57cec5SDimitry Andric Lex(); 24180b57cec5SDimitry Andric assert(getTok().is(AsmToken::String) && 24190b57cec5SDimitry Andric "Lexing Cpp line comment: Expected String"); 24200b57cec5SDimitry Andric StringRef Filename = getTok().getString(); 24210b57cec5SDimitry Andric Lex(); 24220b57cec5SDimitry Andric 24235ffd83dbSDimitry Andric if (!SaveLocInfo) 24245ffd83dbSDimitry Andric return false; 24255ffd83dbSDimitry Andric 24260b57cec5SDimitry Andric // Get rid of the enclosing quotes. 24270b57cec5SDimitry Andric Filename = Filename.substr(1, Filename.size() - 2); 24280b57cec5SDimitry Andric 24290b57cec5SDimitry Andric // Save the SMLoc, Filename and LineNumber for later use by diagnostics 24300b57cec5SDimitry Andric // and possibly DWARF file info. 24310b57cec5SDimitry Andric CppHashInfo.Loc = L; 24320b57cec5SDimitry Andric CppHashInfo.Filename = Filename; 24330b57cec5SDimitry Andric CppHashInfo.LineNumber = LineNumber; 24340b57cec5SDimitry Andric CppHashInfo.Buf = CurBuffer; 24350b57cec5SDimitry Andric if (FirstCppHashFilename.empty()) 24360b57cec5SDimitry Andric FirstCppHashFilename = Filename; 24370b57cec5SDimitry Andric return false; 24380b57cec5SDimitry Andric } 24390b57cec5SDimitry Andric 24400b57cec5SDimitry Andric /// will use the last parsed cpp hash line filename comment 24410b57cec5SDimitry Andric /// for the Filename and LineNo if any in the diagnostic. 24420b57cec5SDimitry Andric void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { 2443fe6060f1SDimitry Andric auto *Parser = static_cast<AsmParser *>(Context); 24440b57cec5SDimitry Andric raw_ostream &OS = errs(); 24450b57cec5SDimitry Andric 24460b57cec5SDimitry Andric const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr(); 24470b57cec5SDimitry Andric SMLoc DiagLoc = Diag.getLoc(); 24480b57cec5SDimitry Andric unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); 24490b57cec5SDimitry Andric unsigned CppHashBuf = 24500b57cec5SDimitry Andric Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc); 24510b57cec5SDimitry Andric 24520b57cec5SDimitry Andric // Like SourceMgr::printMessage() we need to print the include stack if any 24530b57cec5SDimitry Andric // before printing the message. 24540b57cec5SDimitry Andric unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); 24550b57cec5SDimitry Andric if (!Parser->SavedDiagHandler && DiagCurBuffer && 24560b57cec5SDimitry Andric DiagCurBuffer != DiagSrcMgr.getMainFileID()) { 24570b57cec5SDimitry Andric SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer); 24580b57cec5SDimitry Andric DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS); 24590b57cec5SDimitry Andric } 24600b57cec5SDimitry Andric 24610b57cec5SDimitry Andric // If we have not parsed a cpp hash line filename comment or the source 24620b57cec5SDimitry Andric // manager changed or buffer changed (like in a nested include) then just 24630b57cec5SDimitry Andric // print the normal diagnostic using its Filename and LineNo. 2464fe6060f1SDimitry Andric if (!Parser->CppHashInfo.LineNumber || DiagBuf != CppHashBuf) { 24650b57cec5SDimitry Andric if (Parser->SavedDiagHandler) 24660b57cec5SDimitry Andric Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext); 24670b57cec5SDimitry Andric else 2468fe6060f1SDimitry Andric Parser->getContext().diagnose(Diag); 24690b57cec5SDimitry Andric return; 24700b57cec5SDimitry Andric } 24710b57cec5SDimitry Andric 24720b57cec5SDimitry Andric // Use the CppHashFilename and calculate a line number based on the 24730b57cec5SDimitry Andric // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc 24740b57cec5SDimitry Andric // for the diagnostic. 24755ffd83dbSDimitry Andric const std::string &Filename = std::string(Parser->CppHashInfo.Filename); 24760b57cec5SDimitry Andric 24770b57cec5SDimitry Andric int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf); 24780b57cec5SDimitry Andric int CppHashLocLineNo = 24790b57cec5SDimitry Andric Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf); 24800b57cec5SDimitry Andric int LineNo = 24810b57cec5SDimitry Andric Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo); 24820b57cec5SDimitry Andric 24830b57cec5SDimitry Andric SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo, 24840b57cec5SDimitry Andric Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(), 24850b57cec5SDimitry Andric Diag.getLineContents(), Diag.getRanges()); 24860b57cec5SDimitry Andric 24870b57cec5SDimitry Andric if (Parser->SavedDiagHandler) 2488fe6060f1SDimitry Andric Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext); 24890b57cec5SDimitry Andric else 2490fe6060f1SDimitry Andric Parser->getContext().diagnose(NewDiag); 24910b57cec5SDimitry Andric } 24920b57cec5SDimitry Andric 24930b57cec5SDimitry Andric // FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The 24940b57cec5SDimitry Andric // difference being that that function accepts '@' as part of identifiers and 24950b57cec5SDimitry Andric // we can't do that. AsmLexer.cpp should probably be changed to handle 24960b57cec5SDimitry Andric // '@' as a special case when needed. 24970b57cec5SDimitry Andric static bool isIdentifierChar(char c) { 24980b57cec5SDimitry Andric return isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$' || 24990b57cec5SDimitry Andric c == '.'; 25000b57cec5SDimitry Andric } 25010b57cec5SDimitry Andric 2502*0fca6ea1SDimitry Andric bool AsmParser::expandMacro(raw_svector_ostream &OS, MCAsmMacro &Macro, 25030b57cec5SDimitry Andric ArrayRef<MCAsmMacroParameter> Parameters, 25040b57cec5SDimitry Andric ArrayRef<MCAsmMacroArgument> A, 2505*0fca6ea1SDimitry Andric bool EnableAtPseudoVariable) { 25060b57cec5SDimitry Andric unsigned NParameters = Parameters.size(); 2507*0fca6ea1SDimitry Andric auto expandArg = [&](unsigned Index) { 25080b57cec5SDimitry Andric bool HasVararg = NParameters ? Parameters.back().Vararg : false; 25090b57cec5SDimitry Andric bool VarargParameter = HasVararg && Index == (NParameters - 1); 25100b57cec5SDimitry Andric for (const AsmToken &Token : A[Index]) 25110b57cec5SDimitry Andric // For altmacro mode, you can write '%expr'. 25120b57cec5SDimitry Andric // The prefix '%' evaluates the expression 'expr' 25130b57cec5SDimitry Andric // and uses the result as a string (e.g. replace %(1+2) with the 25140b57cec5SDimitry Andric // string "3"). 25150b57cec5SDimitry Andric // Here, we identify the integer token which is the result of the 25160b57cec5SDimitry Andric // absolute expression evaluation and replace it with its string 25170b57cec5SDimitry Andric // representation. 25180b57cec5SDimitry Andric if (AltMacroMode && Token.getString().front() == '%' && 25190b57cec5SDimitry Andric Token.is(AsmToken::Integer)) 25200b57cec5SDimitry Andric // Emit an integer value to the buffer. 25210b57cec5SDimitry Andric OS << Token.getIntVal(); 25220b57cec5SDimitry Andric // Only Token that was validated as a string and begins with '<' 25230b57cec5SDimitry Andric // is considered altMacroString!!! 25240b57cec5SDimitry Andric else if (AltMacroMode && Token.getString().front() == '<' && 25250b57cec5SDimitry Andric Token.is(AsmToken::String)) { 25265ffd83dbSDimitry Andric OS << angleBracketString(Token.getStringContents()); 25270b57cec5SDimitry Andric } 25280b57cec5SDimitry Andric // We expect no quotes around the string's contents when 25290b57cec5SDimitry Andric // parsing for varargs. 25300b57cec5SDimitry Andric else if (Token.isNot(AsmToken::String) || VarargParameter) 25310b57cec5SDimitry Andric OS << Token.getString(); 25320b57cec5SDimitry Andric else 25330b57cec5SDimitry Andric OS << Token.getStringContents(); 2534*0fca6ea1SDimitry Andric }; 25350b57cec5SDimitry Andric 2536*0fca6ea1SDimitry Andric // A macro without parameters is handled differently on Darwin: 2537*0fca6ea1SDimitry Andric // gas accepts no arguments and does no substitutions 2538*0fca6ea1SDimitry Andric StringRef Body = Macro.Body; 2539*0fca6ea1SDimitry Andric size_t I = 0, End = Body.size(); 2540*0fca6ea1SDimitry Andric while (I != End) { 2541*0fca6ea1SDimitry Andric if (Body[I] == '\\' && I + 1 != End) { 2542*0fca6ea1SDimitry Andric // Check for \@ and \+ pseudo variables. 2543*0fca6ea1SDimitry Andric if (EnableAtPseudoVariable && Body[I + 1] == '@') { 2544*0fca6ea1SDimitry Andric OS << NumOfMacroInstantiations; 2545*0fca6ea1SDimitry Andric I += 2; 2546*0fca6ea1SDimitry Andric continue; 25470b57cec5SDimitry Andric } 2548*0fca6ea1SDimitry Andric if (Body[I + 1] == '+') { 2549*0fca6ea1SDimitry Andric OS << Macro.Count; 2550*0fca6ea1SDimitry Andric I += 2; 2551*0fca6ea1SDimitry Andric continue; 25520b57cec5SDimitry Andric } 2553*0fca6ea1SDimitry Andric if (Body[I + 1] == '(' && Body[I + 2] == ')') { 2554*0fca6ea1SDimitry Andric I += 3; 2555*0fca6ea1SDimitry Andric continue; 25560b57cec5SDimitry Andric } 25570b57cec5SDimitry Andric 2558*0fca6ea1SDimitry Andric size_t Pos = ++I; 2559*0fca6ea1SDimitry Andric while (I != End && isIdentifierChar(Body[I])) 2560*0fca6ea1SDimitry Andric ++I; 2561*0fca6ea1SDimitry Andric StringRef Argument(Body.data() + Pos, I - Pos); 2562*0fca6ea1SDimitry Andric if (AltMacroMode && I != End && Body[I] == '&') 2563*0fca6ea1SDimitry Andric ++I; 2564*0fca6ea1SDimitry Andric unsigned Index = 0; 2565*0fca6ea1SDimitry Andric for (; Index < NParameters; ++Index) 2566*0fca6ea1SDimitry Andric if (Parameters[Index].Name == Argument) 2567*0fca6ea1SDimitry Andric break; 2568*0fca6ea1SDimitry Andric if (Index == NParameters) 2569*0fca6ea1SDimitry Andric OS << '\\' << Argument; 2570*0fca6ea1SDimitry Andric else 2571*0fca6ea1SDimitry Andric expandArg(Index); 2572*0fca6ea1SDimitry Andric continue; 2573*0fca6ea1SDimitry Andric } 2574*0fca6ea1SDimitry Andric 2575*0fca6ea1SDimitry Andric // In Darwin mode, $ is used for macro expansion, not considered an 2576*0fca6ea1SDimitry Andric // identifier char. 2577*0fca6ea1SDimitry Andric if (Body[I] == '$' && I + 1 != End && IsDarwin && !NParameters) { 2578*0fca6ea1SDimitry Andric // This macro has no parameters, look for $0, $1, etc. 2579*0fca6ea1SDimitry Andric switch (Body[I + 1]) { 2580*0fca6ea1SDimitry Andric // $$ => $ 2581*0fca6ea1SDimitry Andric case '$': 2582*0fca6ea1SDimitry Andric OS << '$'; 2583*0fca6ea1SDimitry Andric I += 2; 2584*0fca6ea1SDimitry Andric continue; 2585*0fca6ea1SDimitry Andric // $n => number of arguments 2586*0fca6ea1SDimitry Andric case 'n': 2587*0fca6ea1SDimitry Andric OS << A.size(); 2588*0fca6ea1SDimitry Andric I += 2; 2589*0fca6ea1SDimitry Andric continue; 2590*0fca6ea1SDimitry Andric default: { 2591*0fca6ea1SDimitry Andric if (!isDigit(Body[I + 1])) 2592*0fca6ea1SDimitry Andric break; 2593*0fca6ea1SDimitry Andric // $[0-9] => argument 2594*0fca6ea1SDimitry Andric // Missing arguments are ignored. 2595*0fca6ea1SDimitry Andric unsigned Index = Body[I + 1] - '0'; 2596*0fca6ea1SDimitry Andric if (Index < A.size()) 2597*0fca6ea1SDimitry Andric for (const AsmToken &Token : A[Index]) 2598*0fca6ea1SDimitry Andric OS << Token.getString(); 2599*0fca6ea1SDimitry Andric I += 2; 2600*0fca6ea1SDimitry Andric continue; 2601*0fca6ea1SDimitry Andric } 2602*0fca6ea1SDimitry Andric } 2603*0fca6ea1SDimitry Andric } 2604*0fca6ea1SDimitry Andric 2605*0fca6ea1SDimitry Andric if (!isIdentifierChar(Body[I]) || IsDarwin) { 2606*0fca6ea1SDimitry Andric OS << Body[I++]; 2607*0fca6ea1SDimitry Andric continue; 2608*0fca6ea1SDimitry Andric } 2609*0fca6ea1SDimitry Andric 2610*0fca6ea1SDimitry Andric const size_t Start = I; 2611*0fca6ea1SDimitry Andric while (++I && isIdentifierChar(Body[I])) { 2612*0fca6ea1SDimitry Andric } 2613*0fca6ea1SDimitry Andric StringRef Token(Body.data() + Start, I - Start); 2614*0fca6ea1SDimitry Andric if (AltMacroMode) { 2615*0fca6ea1SDimitry Andric unsigned Index = 0; 2616*0fca6ea1SDimitry Andric for (; Index != NParameters; ++Index) 2617*0fca6ea1SDimitry Andric if (Parameters[Index].Name == Token) 2618*0fca6ea1SDimitry Andric break; 2619*0fca6ea1SDimitry Andric if (Index != NParameters) { 2620*0fca6ea1SDimitry Andric expandArg(Index); 2621*0fca6ea1SDimitry Andric if (I != End && Body[I] == '&') 2622*0fca6ea1SDimitry Andric ++I; 2623*0fca6ea1SDimitry Andric continue; 2624*0fca6ea1SDimitry Andric } 2625*0fca6ea1SDimitry Andric } 2626*0fca6ea1SDimitry Andric OS << Token; 2627*0fca6ea1SDimitry Andric } 2628*0fca6ea1SDimitry Andric 2629*0fca6ea1SDimitry Andric ++Macro.Count; 26300b57cec5SDimitry Andric return false; 26310b57cec5SDimitry Andric } 26320b57cec5SDimitry Andric 26330b57cec5SDimitry Andric static bool isOperator(AsmToken::TokenKind kind) { 26340b57cec5SDimitry Andric switch (kind) { 26350b57cec5SDimitry Andric default: 26360b57cec5SDimitry Andric return false; 26370b57cec5SDimitry Andric case AsmToken::Plus: 26380b57cec5SDimitry Andric case AsmToken::Minus: 26390b57cec5SDimitry Andric case AsmToken::Tilde: 26400b57cec5SDimitry Andric case AsmToken::Slash: 26410b57cec5SDimitry Andric case AsmToken::Star: 26420b57cec5SDimitry Andric case AsmToken::Dot: 26430b57cec5SDimitry Andric case AsmToken::Equal: 26440b57cec5SDimitry Andric case AsmToken::EqualEqual: 26450b57cec5SDimitry Andric case AsmToken::Pipe: 26460b57cec5SDimitry Andric case AsmToken::PipePipe: 26470b57cec5SDimitry Andric case AsmToken::Caret: 26480b57cec5SDimitry Andric case AsmToken::Amp: 26490b57cec5SDimitry Andric case AsmToken::AmpAmp: 26500b57cec5SDimitry Andric case AsmToken::Exclaim: 26510b57cec5SDimitry Andric case AsmToken::ExclaimEqual: 26520b57cec5SDimitry Andric case AsmToken::Less: 26530b57cec5SDimitry Andric case AsmToken::LessEqual: 26540b57cec5SDimitry Andric case AsmToken::LessLess: 26550b57cec5SDimitry Andric case AsmToken::LessGreater: 26560b57cec5SDimitry Andric case AsmToken::Greater: 26570b57cec5SDimitry Andric case AsmToken::GreaterEqual: 26580b57cec5SDimitry Andric case AsmToken::GreaterGreater: 26590b57cec5SDimitry Andric return true; 26600b57cec5SDimitry Andric } 26610b57cec5SDimitry Andric } 26620b57cec5SDimitry Andric 26630b57cec5SDimitry Andric namespace { 26640b57cec5SDimitry Andric 26650b57cec5SDimitry Andric class AsmLexerSkipSpaceRAII { 26660b57cec5SDimitry Andric public: 26670b57cec5SDimitry Andric AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) { 26680b57cec5SDimitry Andric Lexer.setSkipSpace(SkipSpace); 26690b57cec5SDimitry Andric } 26700b57cec5SDimitry Andric 26710b57cec5SDimitry Andric ~AsmLexerSkipSpaceRAII() { 26720b57cec5SDimitry Andric Lexer.setSkipSpace(true); 26730b57cec5SDimitry Andric } 26740b57cec5SDimitry Andric 26750b57cec5SDimitry Andric private: 26760b57cec5SDimitry Andric AsmLexer &Lexer; 26770b57cec5SDimitry Andric }; 26780b57cec5SDimitry Andric 26790b57cec5SDimitry Andric } // end anonymous namespace 26800b57cec5SDimitry Andric 26810b57cec5SDimitry Andric bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) { 26820b57cec5SDimitry Andric 26830b57cec5SDimitry Andric if (Vararg) { 26840b57cec5SDimitry Andric if (Lexer.isNot(AsmToken::EndOfStatement)) { 26850b57cec5SDimitry Andric StringRef Str = parseStringToEndOfStatement(); 26860b57cec5SDimitry Andric MA.emplace_back(AsmToken::String, Str); 26870b57cec5SDimitry Andric } 26880b57cec5SDimitry Andric return false; 26890b57cec5SDimitry Andric } 26900b57cec5SDimitry Andric 26910b57cec5SDimitry Andric unsigned ParenLevel = 0; 26920b57cec5SDimitry Andric 26930b57cec5SDimitry Andric // Darwin doesn't use spaces to delmit arguments. 26940b57cec5SDimitry Andric AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin); 26950b57cec5SDimitry Andric 26960b57cec5SDimitry Andric bool SpaceEaten; 26970b57cec5SDimitry Andric 26980b57cec5SDimitry Andric while (true) { 26990b57cec5SDimitry Andric SpaceEaten = false; 27000b57cec5SDimitry Andric if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal)) 27010b57cec5SDimitry Andric return TokError("unexpected token in macro instantiation"); 27020b57cec5SDimitry Andric 27030b57cec5SDimitry Andric if (ParenLevel == 0) { 27040b57cec5SDimitry Andric 27050b57cec5SDimitry Andric if (Lexer.is(AsmToken::Comma)) 27060b57cec5SDimitry Andric break; 27070b57cec5SDimitry Andric 2708*0fca6ea1SDimitry Andric if (parseOptionalToken(AsmToken::Space)) 27090b57cec5SDimitry Andric SpaceEaten = true; 27100b57cec5SDimitry Andric 27110b57cec5SDimitry Andric // Spaces can delimit parameters, but could also be part an expression. 27120b57cec5SDimitry Andric // If the token after a space is an operator, add the token and the next 27130b57cec5SDimitry Andric // one into this argument 27140b57cec5SDimitry Andric if (!IsDarwin) { 27150b57cec5SDimitry Andric if (isOperator(Lexer.getKind())) { 27160b57cec5SDimitry Andric MA.push_back(getTok()); 27170b57cec5SDimitry Andric Lexer.Lex(); 27180b57cec5SDimitry Andric 27190b57cec5SDimitry Andric // Whitespace after an operator can be ignored. 2720*0fca6ea1SDimitry Andric parseOptionalToken(AsmToken::Space); 27210b57cec5SDimitry Andric continue; 27220b57cec5SDimitry Andric } 27230b57cec5SDimitry Andric } 27240b57cec5SDimitry Andric if (SpaceEaten) 27250b57cec5SDimitry Andric break; 27260b57cec5SDimitry Andric } 27270b57cec5SDimitry Andric 27280b57cec5SDimitry Andric // handleMacroEntry relies on not advancing the lexer here 27290b57cec5SDimitry Andric // to be able to fill in the remaining default parameter values 27300b57cec5SDimitry Andric if (Lexer.is(AsmToken::EndOfStatement)) 27310b57cec5SDimitry Andric break; 27320b57cec5SDimitry Andric 27330b57cec5SDimitry Andric // Adjust the current parentheses level. 27340b57cec5SDimitry Andric if (Lexer.is(AsmToken::LParen)) 27350b57cec5SDimitry Andric ++ParenLevel; 27360b57cec5SDimitry Andric else if (Lexer.is(AsmToken::RParen) && ParenLevel) 27370b57cec5SDimitry Andric --ParenLevel; 27380b57cec5SDimitry Andric 27390b57cec5SDimitry Andric // Append the token to the current argument list. 27400b57cec5SDimitry Andric MA.push_back(getTok()); 27410b57cec5SDimitry Andric Lexer.Lex(); 27420b57cec5SDimitry Andric } 27430b57cec5SDimitry Andric 27440b57cec5SDimitry Andric if (ParenLevel != 0) 27450b57cec5SDimitry Andric return TokError("unbalanced parentheses in macro argument"); 27460b57cec5SDimitry Andric return false; 27470b57cec5SDimitry Andric } 27480b57cec5SDimitry Andric 27490b57cec5SDimitry Andric // Parse the macro instantiation arguments. 27500b57cec5SDimitry Andric bool AsmParser::parseMacroArguments(const MCAsmMacro *M, 27510b57cec5SDimitry Andric MCAsmMacroArguments &A) { 27520b57cec5SDimitry Andric const unsigned NParameters = M ? M->Parameters.size() : 0; 27530b57cec5SDimitry Andric bool NamedParametersFound = false; 27540b57cec5SDimitry Andric SmallVector<SMLoc, 4> FALocs; 27550b57cec5SDimitry Andric 27560b57cec5SDimitry Andric A.resize(NParameters); 27570b57cec5SDimitry Andric FALocs.resize(NParameters); 27580b57cec5SDimitry Andric 27590b57cec5SDimitry Andric // Parse two kinds of macro invocations: 27600b57cec5SDimitry Andric // - macros defined without any parameters accept an arbitrary number of them 27610b57cec5SDimitry Andric // - macros defined with parameters accept at most that many of them 27620b57cec5SDimitry Andric bool HasVararg = NParameters ? M->Parameters.back().Vararg : false; 27630b57cec5SDimitry Andric for (unsigned Parameter = 0; !NParameters || Parameter < NParameters; 27640b57cec5SDimitry Andric ++Parameter) { 27650b57cec5SDimitry Andric SMLoc IDLoc = Lexer.getLoc(); 27660b57cec5SDimitry Andric MCAsmMacroParameter FA; 27670b57cec5SDimitry Andric 27680b57cec5SDimitry Andric if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) { 27690b57cec5SDimitry Andric if (parseIdentifier(FA.Name)) 27700b57cec5SDimitry Andric return Error(IDLoc, "invalid argument identifier for formal argument"); 27710b57cec5SDimitry Andric 27720b57cec5SDimitry Andric if (Lexer.isNot(AsmToken::Equal)) 27730b57cec5SDimitry Andric return TokError("expected '=' after formal parameter identifier"); 27740b57cec5SDimitry Andric 27750b57cec5SDimitry Andric Lex(); 27760b57cec5SDimitry Andric 27770b57cec5SDimitry Andric NamedParametersFound = true; 27780b57cec5SDimitry Andric } 27790b57cec5SDimitry Andric bool Vararg = HasVararg && Parameter == (NParameters - 1); 27800b57cec5SDimitry Andric 27810b57cec5SDimitry Andric if (NamedParametersFound && FA.Name.empty()) 27820b57cec5SDimitry Andric return Error(IDLoc, "cannot mix positional and keyword arguments"); 27830b57cec5SDimitry Andric 27840b57cec5SDimitry Andric SMLoc StrLoc = Lexer.getLoc(); 27850b57cec5SDimitry Andric SMLoc EndLoc; 27860b57cec5SDimitry Andric if (AltMacroMode && Lexer.is(AsmToken::Percent)) { 27870b57cec5SDimitry Andric const MCExpr *AbsoluteExp; 27880b57cec5SDimitry Andric int64_t Value; 27890b57cec5SDimitry Andric /// Eat '%' 27900b57cec5SDimitry Andric Lex(); 27910b57cec5SDimitry Andric if (parseExpression(AbsoluteExp, EndLoc)) 27920b57cec5SDimitry Andric return false; 27930b57cec5SDimitry Andric if (!AbsoluteExp->evaluateAsAbsolute(Value, 27940b57cec5SDimitry Andric getStreamer().getAssemblerPtr())) 27950b57cec5SDimitry Andric return Error(StrLoc, "expected absolute expression"); 27960b57cec5SDimitry Andric const char *StrChar = StrLoc.getPointer(); 27970b57cec5SDimitry Andric const char *EndChar = EndLoc.getPointer(); 27980b57cec5SDimitry Andric AsmToken newToken(AsmToken::Integer, 27990b57cec5SDimitry Andric StringRef(StrChar, EndChar - StrChar), Value); 28000b57cec5SDimitry Andric FA.Value.push_back(newToken); 28010b57cec5SDimitry Andric } else if (AltMacroMode && Lexer.is(AsmToken::Less) && 28025ffd83dbSDimitry Andric isAngleBracketString(StrLoc, EndLoc)) { 28030b57cec5SDimitry Andric const char *StrChar = StrLoc.getPointer(); 28040b57cec5SDimitry Andric const char *EndChar = EndLoc.getPointer(); 28050b57cec5SDimitry Andric jumpToLoc(EndLoc, CurBuffer); 28060b57cec5SDimitry Andric /// Eat from '<' to '>' 28070b57cec5SDimitry Andric Lex(); 28080b57cec5SDimitry Andric AsmToken newToken(AsmToken::String, 28090b57cec5SDimitry Andric StringRef(StrChar, EndChar - StrChar)); 28100b57cec5SDimitry Andric FA.Value.push_back(newToken); 28110b57cec5SDimitry Andric } else if(parseMacroArgument(FA.Value, Vararg)) 28120b57cec5SDimitry Andric return true; 28130b57cec5SDimitry Andric 28140b57cec5SDimitry Andric unsigned PI = Parameter; 28150b57cec5SDimitry Andric if (!FA.Name.empty()) { 28160b57cec5SDimitry Andric unsigned FAI = 0; 28170b57cec5SDimitry Andric for (FAI = 0; FAI < NParameters; ++FAI) 28180b57cec5SDimitry Andric if (M->Parameters[FAI].Name == FA.Name) 28190b57cec5SDimitry Andric break; 28200b57cec5SDimitry Andric 28210b57cec5SDimitry Andric if (FAI >= NParameters) { 28220b57cec5SDimitry Andric assert(M && "expected macro to be defined"); 28230b57cec5SDimitry Andric return Error(IDLoc, "parameter named '" + FA.Name + 28240b57cec5SDimitry Andric "' does not exist for macro '" + M->Name + "'"); 28250b57cec5SDimitry Andric } 28260b57cec5SDimitry Andric PI = FAI; 28270b57cec5SDimitry Andric } 28280b57cec5SDimitry Andric 28290b57cec5SDimitry Andric if (!FA.Value.empty()) { 28300b57cec5SDimitry Andric if (A.size() <= PI) 28310b57cec5SDimitry Andric A.resize(PI + 1); 28320b57cec5SDimitry Andric A[PI] = FA.Value; 28330b57cec5SDimitry Andric 28340b57cec5SDimitry Andric if (FALocs.size() <= PI) 28350b57cec5SDimitry Andric FALocs.resize(PI + 1); 28360b57cec5SDimitry Andric 28370b57cec5SDimitry Andric FALocs[PI] = Lexer.getLoc(); 28380b57cec5SDimitry Andric } 28390b57cec5SDimitry Andric 28400b57cec5SDimitry Andric // At the end of the statement, fill in remaining arguments that have 28410b57cec5SDimitry Andric // default values. If there aren't any, then the next argument is 28420b57cec5SDimitry Andric // required but missing 28430b57cec5SDimitry Andric if (Lexer.is(AsmToken::EndOfStatement)) { 28440b57cec5SDimitry Andric bool Failure = false; 28450b57cec5SDimitry Andric for (unsigned FAI = 0; FAI < NParameters; ++FAI) { 28460b57cec5SDimitry Andric if (A[FAI].empty()) { 28470b57cec5SDimitry Andric if (M->Parameters[FAI].Required) { 28480b57cec5SDimitry Andric Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(), 28490b57cec5SDimitry Andric "missing value for required parameter " 28500b57cec5SDimitry Andric "'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'"); 28510b57cec5SDimitry Andric Failure = true; 28520b57cec5SDimitry Andric } 28530b57cec5SDimitry Andric 28540b57cec5SDimitry Andric if (!M->Parameters[FAI].Value.empty()) 28550b57cec5SDimitry Andric A[FAI] = M->Parameters[FAI].Value; 28560b57cec5SDimitry Andric } 28570b57cec5SDimitry Andric } 28580b57cec5SDimitry Andric return Failure; 28590b57cec5SDimitry Andric } 28600b57cec5SDimitry Andric 2861*0fca6ea1SDimitry Andric parseOptionalToken(AsmToken::Comma); 28620b57cec5SDimitry Andric } 28630b57cec5SDimitry Andric 28640b57cec5SDimitry Andric return TokError("too many positional arguments"); 28650b57cec5SDimitry Andric } 28660b57cec5SDimitry Andric 2867*0fca6ea1SDimitry Andric bool AsmParser::handleMacroEntry(MCAsmMacro *M, SMLoc NameLoc) { 28680b57cec5SDimitry Andric // Arbitrarily limit macro nesting depth (default matches 'as'). We can 28690b57cec5SDimitry Andric // eliminate this, although we should protect against infinite loops. 28700b57cec5SDimitry Andric unsigned MaxNestingDepth = AsmMacroMaxNestingDepth; 28710b57cec5SDimitry Andric if (ActiveMacros.size() == MaxNestingDepth) { 28720b57cec5SDimitry Andric std::ostringstream MaxNestingDepthError; 28730b57cec5SDimitry Andric MaxNestingDepthError << "macros cannot be nested more than " 28740b57cec5SDimitry Andric << MaxNestingDepth << " levels deep." 28750b57cec5SDimitry Andric << " Use -asm-macro-max-nesting-depth to increase " 28760b57cec5SDimitry Andric "this limit."; 28770b57cec5SDimitry Andric return TokError(MaxNestingDepthError.str()); 28780b57cec5SDimitry Andric } 28790b57cec5SDimitry Andric 28800b57cec5SDimitry Andric MCAsmMacroArguments A; 28810b57cec5SDimitry Andric if (parseMacroArguments(M, A)) 28820b57cec5SDimitry Andric return true; 28830b57cec5SDimitry Andric 28840b57cec5SDimitry Andric // Macro instantiation is lexical, unfortunately. We construct a new buffer 28850b57cec5SDimitry Andric // to hold the macro body with substitutions. 28860b57cec5SDimitry Andric SmallString<256> Buf; 28870b57cec5SDimitry Andric raw_svector_ostream OS(Buf); 28880b57cec5SDimitry Andric 2889*0fca6ea1SDimitry Andric if ((!IsDarwin || M->Parameters.size()) && M->Parameters.size() != A.size()) 2890*0fca6ea1SDimitry Andric return Error(getTok().getLoc(), "Wrong number of arguments"); 2891*0fca6ea1SDimitry Andric if (expandMacro(OS, *M, M->Parameters, A, true)) 28920b57cec5SDimitry Andric return true; 28930b57cec5SDimitry Andric 28940b57cec5SDimitry Andric // We include the .endmacro in the buffer as our cue to exit the macro 28950b57cec5SDimitry Andric // instantiation. 28960b57cec5SDimitry Andric OS << ".endmacro\n"; 28970b57cec5SDimitry Andric 28980b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> Instantiation = 28990b57cec5SDimitry Andric MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>"); 29000b57cec5SDimitry Andric 29010b57cec5SDimitry Andric // Create the macro instantiation object and add to the current macro 29020b57cec5SDimitry Andric // instantiation stack. 2903480093f4SDimitry Andric MacroInstantiation *MI = new MacroInstantiation{ 2904480093f4SDimitry Andric NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()}; 29050b57cec5SDimitry Andric ActiveMacros.push_back(MI); 29060b57cec5SDimitry Andric 29070b57cec5SDimitry Andric ++NumOfMacroInstantiations; 29080b57cec5SDimitry Andric 29090b57cec5SDimitry Andric // Jump to the macro instantiation and prime the lexer. 29100b57cec5SDimitry Andric CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc()); 29110b57cec5SDimitry Andric Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); 29120b57cec5SDimitry Andric Lex(); 29130b57cec5SDimitry Andric 29140b57cec5SDimitry Andric return false; 29150b57cec5SDimitry Andric } 29160b57cec5SDimitry Andric 29170b57cec5SDimitry Andric void AsmParser::handleMacroExit() { 29180b57cec5SDimitry Andric // Jump to the EndOfStatement we should return to, and consume it. 29190b57cec5SDimitry Andric jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer); 29200b57cec5SDimitry Andric Lex(); 2921*0fca6ea1SDimitry Andric // If .endm/.endr is followed by \n instead of a comment, consume it so that 2922*0fca6ea1SDimitry Andric // we don't print an excess \n. 2923*0fca6ea1SDimitry Andric if (getTok().is(AsmToken::EndOfStatement)) 2924*0fca6ea1SDimitry Andric Lex(); 29250b57cec5SDimitry Andric 29260b57cec5SDimitry Andric // Pop the instantiation entry. 29270b57cec5SDimitry Andric delete ActiveMacros.back(); 29280b57cec5SDimitry Andric ActiveMacros.pop_back(); 29290b57cec5SDimitry Andric } 29300b57cec5SDimitry Andric 29310eae32dcSDimitry Andric bool AsmParser::parseAssignment(StringRef Name, AssignmentKind Kind) { 29320b57cec5SDimitry Andric MCSymbol *Sym; 29330b57cec5SDimitry Andric const MCExpr *Value; 29340eae32dcSDimitry Andric SMLoc ExprLoc = getTok().getLoc(); 29350eae32dcSDimitry Andric bool AllowRedef = 29360eae32dcSDimitry Andric Kind == AssignmentKind::Set || Kind == AssignmentKind::Equal; 29370eae32dcSDimitry Andric if (MCParserUtils::parseAssignmentExpression(Name, AllowRedef, *this, Sym, 29380b57cec5SDimitry Andric Value)) 29390b57cec5SDimitry Andric return true; 29400b57cec5SDimitry Andric 29410b57cec5SDimitry Andric if (!Sym) { 29420b57cec5SDimitry Andric // In the case where we parse an expression starting with a '.', we will 29430b57cec5SDimitry Andric // not generate an error, nor will we create a symbol. In this case we 29440b57cec5SDimitry Andric // should just return out. 29450b57cec5SDimitry Andric return false; 29460b57cec5SDimitry Andric } 29470b57cec5SDimitry Andric 2948fe6060f1SDimitry Andric if (discardLTOSymbol(Name)) 2949fe6060f1SDimitry Andric return false; 2950fe6060f1SDimitry Andric 29510b57cec5SDimitry Andric // Do the assignment. 29520eae32dcSDimitry Andric switch (Kind) { 29530eae32dcSDimitry Andric case AssignmentKind::Equal: 29545ffd83dbSDimitry Andric Out.emitAssignment(Sym, Value); 29550eae32dcSDimitry Andric break; 29560eae32dcSDimitry Andric case AssignmentKind::Set: 29570eae32dcSDimitry Andric case AssignmentKind::Equiv: 29580eae32dcSDimitry Andric Out.emitAssignment(Sym, Value); 29595ffd83dbSDimitry Andric Out.emitSymbolAttribute(Sym, MCSA_NoDeadStrip); 29600eae32dcSDimitry Andric break; 29610eae32dcSDimitry Andric case AssignmentKind::LTOSetConditional: 29620eae32dcSDimitry Andric if (Value->getKind() != MCExpr::SymbolRef) 29630eae32dcSDimitry Andric return Error(ExprLoc, "expected identifier"); 29640eae32dcSDimitry Andric 29650eae32dcSDimitry Andric Out.emitConditionalAssignment(Sym, Value); 29660eae32dcSDimitry Andric break; 29670eae32dcSDimitry Andric } 29680b57cec5SDimitry Andric 29690b57cec5SDimitry Andric return false; 29700b57cec5SDimitry Andric } 29710b57cec5SDimitry Andric 29720b57cec5SDimitry Andric /// parseIdentifier: 29730b57cec5SDimitry Andric /// ::= identifier 29740b57cec5SDimitry Andric /// ::= string 29750b57cec5SDimitry Andric bool AsmParser::parseIdentifier(StringRef &Res) { 29760b57cec5SDimitry Andric // The assembler has relaxed rules for accepting identifiers, in particular we 29770b57cec5SDimitry Andric // allow things like '.globl $foo' and '.def @feat.00', which would normally be 29780b57cec5SDimitry Andric // separate tokens. At this level, we have already lexed so we cannot (currently) 29790b57cec5SDimitry Andric // handle this as a context dependent token, instead we detect adjacent tokens 29800b57cec5SDimitry Andric // and return the combined identifier. 29810b57cec5SDimitry Andric if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) { 29820b57cec5SDimitry Andric SMLoc PrefixLoc = getLexer().getLoc(); 29830b57cec5SDimitry Andric 29840b57cec5SDimitry Andric // Consume the prefix character, and check for a following identifier. 29850b57cec5SDimitry Andric 29860b57cec5SDimitry Andric AsmToken Buf[1]; 29870b57cec5SDimitry Andric Lexer.peekTokens(Buf, false); 29880b57cec5SDimitry Andric 29895ffd83dbSDimitry Andric if (Buf[0].isNot(AsmToken::Identifier) && Buf[0].isNot(AsmToken::Integer)) 29900b57cec5SDimitry Andric return true; 29910b57cec5SDimitry Andric 29925ffd83dbSDimitry Andric // We have a '$' or '@' followed by an identifier or integer token, make 29935ffd83dbSDimitry Andric // sure they are adjacent. 29940b57cec5SDimitry Andric if (PrefixLoc.getPointer() + 1 != Buf[0].getLoc().getPointer()) 29950b57cec5SDimitry Andric return true; 29960b57cec5SDimitry Andric 29970b57cec5SDimitry Andric // eat $ or @ 29980b57cec5SDimitry Andric Lexer.Lex(); // Lexer's Lex guarantees consecutive token. 29990b57cec5SDimitry Andric // Construct the joined identifier and consume the token. 30005ffd83dbSDimitry Andric Res = StringRef(PrefixLoc.getPointer(), getTok().getString().size() + 1); 30010b57cec5SDimitry Andric Lex(); // Parser Lex to maintain invariants. 30020b57cec5SDimitry Andric return false; 30030b57cec5SDimitry Andric } 30040b57cec5SDimitry Andric 30050b57cec5SDimitry Andric if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String)) 30060b57cec5SDimitry Andric return true; 30070b57cec5SDimitry Andric 30080b57cec5SDimitry Andric Res = getTok().getIdentifier(); 30090b57cec5SDimitry Andric 30100b57cec5SDimitry Andric Lex(); // Consume the identifier token. 30110b57cec5SDimitry Andric 30120b57cec5SDimitry Andric return false; 30130b57cec5SDimitry Andric } 30140b57cec5SDimitry Andric 30150b57cec5SDimitry Andric /// parseDirectiveSet: 30160b57cec5SDimitry Andric /// ::= .equ identifier ',' expression 30170b57cec5SDimitry Andric /// ::= .equiv identifier ',' expression 30180b57cec5SDimitry Andric /// ::= .set identifier ',' expression 30190eae32dcSDimitry Andric /// ::= .lto_set_conditional identifier ',' expression 30200eae32dcSDimitry Andric bool AsmParser::parseDirectiveSet(StringRef IDVal, AssignmentKind Kind) { 30210b57cec5SDimitry Andric StringRef Name; 3022fe6060f1SDimitry Andric if (check(parseIdentifier(Name), "expected identifier") || parseComma() || 30230eae32dcSDimitry Andric parseAssignment(Name, Kind)) 3024fe6060f1SDimitry Andric return true; 30250b57cec5SDimitry Andric return false; 30260b57cec5SDimitry Andric } 30270b57cec5SDimitry Andric 30280b57cec5SDimitry Andric bool AsmParser::parseEscapedString(std::string &Data) { 30290b57cec5SDimitry Andric if (check(getTok().isNot(AsmToken::String), "expected string")) 30300b57cec5SDimitry Andric return true; 30310b57cec5SDimitry Andric 30320b57cec5SDimitry Andric Data = ""; 30330b57cec5SDimitry Andric StringRef Str = getTok().getStringContents(); 30340b57cec5SDimitry Andric for (unsigned i = 0, e = Str.size(); i != e; ++i) { 30350b57cec5SDimitry Andric if (Str[i] != '\\') { 3036*0fca6ea1SDimitry Andric if (Str[i] == '\n') { 3037*0fca6ea1SDimitry Andric SMLoc NewlineLoc = SMLoc::getFromPointer(Str.data() + i); 3038*0fca6ea1SDimitry Andric if (Warning(NewlineLoc, "unterminated string; newline inserted")) 3039*0fca6ea1SDimitry Andric return true; 3040*0fca6ea1SDimitry Andric } 30410b57cec5SDimitry Andric Data += Str[i]; 30420b57cec5SDimitry Andric continue; 30430b57cec5SDimitry Andric } 30440b57cec5SDimitry Andric 30450b57cec5SDimitry Andric // Recognize escaped characters. Note that this escape semantics currently 30468bcb0991SDimitry Andric // loosely follows Darwin 'as'. 30470b57cec5SDimitry Andric ++i; 30480b57cec5SDimitry Andric if (i == e) 30490b57cec5SDimitry Andric return TokError("unexpected backslash at end of string"); 30500b57cec5SDimitry Andric 30518bcb0991SDimitry Andric // Recognize hex sequences similarly to GNU 'as'. 30528bcb0991SDimitry Andric if (Str[i] == 'x' || Str[i] == 'X') { 30538bcb0991SDimitry Andric size_t length = Str.size(); 30548bcb0991SDimitry Andric if (i + 1 >= length || !isHexDigit(Str[i + 1])) 30558bcb0991SDimitry Andric return TokError("invalid hexadecimal escape sequence"); 30568bcb0991SDimitry Andric 30578bcb0991SDimitry Andric // Consume hex characters. GNU 'as' reads all hexadecimal characters and 30588bcb0991SDimitry Andric // then truncates to the lower 16 bits. Seems reasonable. 30598bcb0991SDimitry Andric unsigned Value = 0; 30608bcb0991SDimitry Andric while (i + 1 < length && isHexDigit(Str[i + 1])) 30618bcb0991SDimitry Andric Value = Value * 16 + hexDigitValue(Str[++i]); 30628bcb0991SDimitry Andric 30638bcb0991SDimitry Andric Data += (unsigned char)(Value & 0xFF); 30648bcb0991SDimitry Andric continue; 30658bcb0991SDimitry Andric } 30668bcb0991SDimitry Andric 30670b57cec5SDimitry Andric // Recognize octal sequences. 30680b57cec5SDimitry Andric if ((unsigned)(Str[i] - '0') <= 7) { 30690b57cec5SDimitry Andric // Consume up to three octal characters. 30700b57cec5SDimitry Andric unsigned Value = Str[i] - '0'; 30710b57cec5SDimitry Andric 30720b57cec5SDimitry Andric if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) { 30730b57cec5SDimitry Andric ++i; 30740b57cec5SDimitry Andric Value = Value * 8 + (Str[i] - '0'); 30750b57cec5SDimitry Andric 30760b57cec5SDimitry Andric if (i + 1 != e && ((unsigned)(Str[i + 1] - '0')) <= 7) { 30770b57cec5SDimitry Andric ++i; 30780b57cec5SDimitry Andric Value = Value * 8 + (Str[i] - '0'); 30790b57cec5SDimitry Andric } 30800b57cec5SDimitry Andric } 30810b57cec5SDimitry Andric 30820b57cec5SDimitry Andric if (Value > 255) 30830b57cec5SDimitry Andric return TokError("invalid octal escape sequence (out of range)"); 30840b57cec5SDimitry Andric 30850b57cec5SDimitry Andric Data += (unsigned char)Value; 30860b57cec5SDimitry Andric continue; 30870b57cec5SDimitry Andric } 30880b57cec5SDimitry Andric 30890b57cec5SDimitry Andric // Otherwise recognize individual escapes. 30900b57cec5SDimitry Andric switch (Str[i]) { 30910b57cec5SDimitry Andric default: 30920b57cec5SDimitry Andric // Just reject invalid escape sequences for now. 30930b57cec5SDimitry Andric return TokError("invalid escape sequence (unrecognized character)"); 30940b57cec5SDimitry Andric 30950b57cec5SDimitry Andric case 'b': Data += '\b'; break; 30960b57cec5SDimitry Andric case 'f': Data += '\f'; break; 30970b57cec5SDimitry Andric case 'n': Data += '\n'; break; 30980b57cec5SDimitry Andric case 'r': Data += '\r'; break; 30990b57cec5SDimitry Andric case 't': Data += '\t'; break; 31000b57cec5SDimitry Andric case '"': Data += '"'; break; 31010b57cec5SDimitry Andric case '\\': Data += '\\'; break; 31020b57cec5SDimitry Andric } 31030b57cec5SDimitry Andric } 31040b57cec5SDimitry Andric 31050b57cec5SDimitry Andric Lex(); 31060b57cec5SDimitry Andric return false; 31070b57cec5SDimitry Andric } 31080b57cec5SDimitry Andric 31095ffd83dbSDimitry Andric bool AsmParser::parseAngleBracketString(std::string &Data) { 31105ffd83dbSDimitry Andric SMLoc EndLoc, StartLoc = getTok().getLoc(); 31115ffd83dbSDimitry Andric if (isAngleBracketString(StartLoc, EndLoc)) { 31125ffd83dbSDimitry Andric const char *StartChar = StartLoc.getPointer() + 1; 31135ffd83dbSDimitry Andric const char *EndChar = EndLoc.getPointer() - 1; 31145ffd83dbSDimitry Andric jumpToLoc(EndLoc, CurBuffer); 31155ffd83dbSDimitry Andric /// Eat from '<' to '>' 31165ffd83dbSDimitry Andric Lex(); 31175ffd83dbSDimitry Andric 31185ffd83dbSDimitry Andric Data = angleBracketString(StringRef(StartChar, EndChar - StartChar)); 31195ffd83dbSDimitry Andric return false; 31205ffd83dbSDimitry Andric } 31215ffd83dbSDimitry Andric return true; 31225ffd83dbSDimitry Andric } 31235ffd83dbSDimitry Andric 31240b57cec5SDimitry Andric /// parseDirectiveAscii: 3125e8d8bef9SDimitry Andric // ::= .ascii [ "string"+ ( , "string"+ )* ] 3126e8d8bef9SDimitry Andric /// ::= ( .asciz | .string ) [ "string" ( , "string" )* ] 31270b57cec5SDimitry Andric bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) { 31280b57cec5SDimitry Andric auto parseOp = [&]() -> bool { 31290b57cec5SDimitry Andric std::string Data; 3130e8d8bef9SDimitry Andric if (checkForValidSection()) 3131e8d8bef9SDimitry Andric return true; 3132e8d8bef9SDimitry Andric // Only support spaces as separators for .ascii directive for now. See the 3133e8d8bef9SDimitry Andric // discusssion at https://reviews.llvm.org/D91460 for more details. 3134e8d8bef9SDimitry Andric do { 3135e8d8bef9SDimitry Andric if (parseEscapedString(Data)) 31360b57cec5SDimitry Andric return true; 31375ffd83dbSDimitry Andric getStreamer().emitBytes(Data); 3138e8d8bef9SDimitry Andric } while (!ZeroTerminated && getTok().is(AsmToken::String)); 31390b57cec5SDimitry Andric if (ZeroTerminated) 31405ffd83dbSDimitry Andric getStreamer().emitBytes(StringRef("\0", 1)); 31410b57cec5SDimitry Andric return false; 31420b57cec5SDimitry Andric }; 31430b57cec5SDimitry Andric 3144fe6060f1SDimitry Andric return parseMany(parseOp); 31450b57cec5SDimitry Andric } 31460b57cec5SDimitry Andric 31470b57cec5SDimitry Andric /// parseDirectiveReloc 31480b57cec5SDimitry Andric /// ::= .reloc expression , identifier [ , expression ] 31490b57cec5SDimitry Andric bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) { 31500b57cec5SDimitry Andric const MCExpr *Offset; 31510b57cec5SDimitry Andric const MCExpr *Expr = nullptr; 31520b57cec5SDimitry Andric SMLoc OffsetLoc = Lexer.getTok().getLoc(); 31530b57cec5SDimitry Andric 31540b57cec5SDimitry Andric if (parseExpression(Offset)) 31550b57cec5SDimitry Andric return true; 3156fe6060f1SDimitry Andric if (parseComma() || 31575ffd83dbSDimitry Andric check(getTok().isNot(AsmToken::Identifier), "expected relocation name")) 31580b57cec5SDimitry Andric return true; 31590b57cec5SDimitry Andric 31600b57cec5SDimitry Andric SMLoc NameLoc = Lexer.getTok().getLoc(); 31610b57cec5SDimitry Andric StringRef Name = Lexer.getTok().getIdentifier(); 31620b57cec5SDimitry Andric Lex(); 31630b57cec5SDimitry Andric 31640b57cec5SDimitry Andric if (Lexer.is(AsmToken::Comma)) { 31650b57cec5SDimitry Andric Lex(); 31660b57cec5SDimitry Andric SMLoc ExprLoc = Lexer.getLoc(); 31670b57cec5SDimitry Andric if (parseExpression(Expr)) 31680b57cec5SDimitry Andric return true; 31690b57cec5SDimitry Andric 31700b57cec5SDimitry Andric MCValue Value; 31710b57cec5SDimitry Andric if (!Expr->evaluateAsRelocatable(Value, nullptr, nullptr)) 31720b57cec5SDimitry Andric return Error(ExprLoc, "expression must be relocatable"); 31730b57cec5SDimitry Andric } 31740b57cec5SDimitry Andric 3175fe6060f1SDimitry Andric if (parseEOL()) 31760b57cec5SDimitry Andric return true; 31770b57cec5SDimitry Andric 31780b57cec5SDimitry Andric const MCTargetAsmParser &MCT = getTargetParser(); 31790b57cec5SDimitry Andric const MCSubtargetInfo &STI = MCT.getSTI(); 3180bdd1243dSDimitry Andric if (std::optional<std::pair<bool, std::string>> Err = 31815ffd83dbSDimitry Andric getStreamer().emitRelocDirective(*Offset, Name, Expr, DirectiveLoc, 31825ffd83dbSDimitry Andric STI)) 31835ffd83dbSDimitry Andric return Error(Err->first ? NameLoc : OffsetLoc, Err->second); 31840b57cec5SDimitry Andric 31850b57cec5SDimitry Andric return false; 31860b57cec5SDimitry Andric } 31870b57cec5SDimitry Andric 31880b57cec5SDimitry Andric /// parseDirectiveValue 31890b57cec5SDimitry Andric /// ::= (.byte | .short | ... ) [ expression (, expression)* ] 31900b57cec5SDimitry Andric bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) { 31910b57cec5SDimitry Andric auto parseOp = [&]() -> bool { 31920b57cec5SDimitry Andric const MCExpr *Value; 31930b57cec5SDimitry Andric SMLoc ExprLoc = getLexer().getLoc(); 31940b57cec5SDimitry Andric if (checkForValidSection() || parseExpression(Value)) 31950b57cec5SDimitry Andric return true; 31960b57cec5SDimitry Andric // Special case constant expressions to match code generator. 31970b57cec5SDimitry Andric if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { 31980b57cec5SDimitry Andric assert(Size <= 8 && "Invalid size"); 31990b57cec5SDimitry Andric uint64_t IntValue = MCE->getValue(); 32000b57cec5SDimitry Andric if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue)) 32010b57cec5SDimitry Andric return Error(ExprLoc, "out of range literal value"); 32025ffd83dbSDimitry Andric getStreamer().emitIntValue(IntValue, Size); 32030b57cec5SDimitry Andric } else 32045ffd83dbSDimitry Andric getStreamer().emitValue(Value, Size, ExprLoc); 32050b57cec5SDimitry Andric return false; 32060b57cec5SDimitry Andric }; 32070b57cec5SDimitry Andric 3208fe6060f1SDimitry Andric return parseMany(parseOp); 32090b57cec5SDimitry Andric } 32100b57cec5SDimitry Andric 32110b57cec5SDimitry Andric static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) { 32120b57cec5SDimitry Andric if (Asm.getTok().isNot(AsmToken::Integer) && 32130b57cec5SDimitry Andric Asm.getTok().isNot(AsmToken::BigNum)) 32140b57cec5SDimitry Andric return Asm.TokError("unknown token in expression"); 32150b57cec5SDimitry Andric SMLoc ExprLoc = Asm.getTok().getLoc(); 32160b57cec5SDimitry Andric APInt IntValue = Asm.getTok().getAPIntVal(); 32170b57cec5SDimitry Andric Asm.Lex(); 32180b57cec5SDimitry Andric if (!IntValue.isIntN(128)) 32190b57cec5SDimitry Andric return Asm.Error(ExprLoc, "out of range literal value"); 32200b57cec5SDimitry Andric if (!IntValue.isIntN(64)) { 32210b57cec5SDimitry Andric hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue(); 32220b57cec5SDimitry Andric lo = IntValue.getLoBits(64).getZExtValue(); 32230b57cec5SDimitry Andric } else { 32240b57cec5SDimitry Andric hi = 0; 32250b57cec5SDimitry Andric lo = IntValue.getZExtValue(); 32260b57cec5SDimitry Andric } 32270b57cec5SDimitry Andric return false; 32280b57cec5SDimitry Andric } 32290b57cec5SDimitry Andric 32300b57cec5SDimitry Andric /// ParseDirectiveOctaValue 32310b57cec5SDimitry Andric /// ::= .octa [ hexconstant (, hexconstant)* ] 32320b57cec5SDimitry Andric 32330b57cec5SDimitry Andric bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) { 32340b57cec5SDimitry Andric auto parseOp = [&]() -> bool { 32350b57cec5SDimitry Andric if (checkForValidSection()) 32360b57cec5SDimitry Andric return true; 32370b57cec5SDimitry Andric uint64_t hi, lo; 32380b57cec5SDimitry Andric if (parseHexOcta(*this, hi, lo)) 32390b57cec5SDimitry Andric return true; 32400b57cec5SDimitry Andric if (MAI.isLittleEndian()) { 32415ffd83dbSDimitry Andric getStreamer().emitInt64(lo); 32425ffd83dbSDimitry Andric getStreamer().emitInt64(hi); 32430b57cec5SDimitry Andric } else { 32445ffd83dbSDimitry Andric getStreamer().emitInt64(hi); 32455ffd83dbSDimitry Andric getStreamer().emitInt64(lo); 32460b57cec5SDimitry Andric } 32470b57cec5SDimitry Andric return false; 32480b57cec5SDimitry Andric }; 32490b57cec5SDimitry Andric 3250fe6060f1SDimitry Andric return parseMany(parseOp); 32510b57cec5SDimitry Andric } 32520b57cec5SDimitry Andric 32530b57cec5SDimitry Andric bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) { 32540b57cec5SDimitry Andric // We don't truly support arithmetic on floating point expressions, so we 32550b57cec5SDimitry Andric // have to manually parse unary prefixes. 32560b57cec5SDimitry Andric bool IsNeg = false; 32570b57cec5SDimitry Andric if (getLexer().is(AsmToken::Minus)) { 32580b57cec5SDimitry Andric Lexer.Lex(); 32590b57cec5SDimitry Andric IsNeg = true; 32600b57cec5SDimitry Andric } else if (getLexer().is(AsmToken::Plus)) 32610b57cec5SDimitry Andric Lexer.Lex(); 32620b57cec5SDimitry Andric 32630b57cec5SDimitry Andric if (Lexer.is(AsmToken::Error)) 32640b57cec5SDimitry Andric return TokError(Lexer.getErr()); 32650b57cec5SDimitry Andric if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) && 32660b57cec5SDimitry Andric Lexer.isNot(AsmToken::Identifier)) 32670b57cec5SDimitry Andric return TokError("unexpected token in directive"); 32680b57cec5SDimitry Andric 32690b57cec5SDimitry Andric // Convert to an APFloat. 32700b57cec5SDimitry Andric APFloat Value(Semantics); 32710b57cec5SDimitry Andric StringRef IDVal = getTok().getString(); 32720b57cec5SDimitry Andric if (getLexer().is(AsmToken::Identifier)) { 3273fe6060f1SDimitry Andric if (!IDVal.compare_insensitive("infinity") || 3274fe6060f1SDimitry Andric !IDVal.compare_insensitive("inf")) 32750b57cec5SDimitry Andric Value = APFloat::getInf(Semantics); 3276fe6060f1SDimitry Andric else if (!IDVal.compare_insensitive("nan")) 32770b57cec5SDimitry Andric Value = APFloat::getNaN(Semantics, false, ~0); 32780b57cec5SDimitry Andric else 32790b57cec5SDimitry Andric return TokError("invalid floating point literal"); 3280480093f4SDimitry Andric } else if (errorToBool( 3281480093f4SDimitry Andric Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) 3282480093f4SDimitry Andric .takeError())) 32830b57cec5SDimitry Andric return TokError("invalid floating point literal"); 32840b57cec5SDimitry Andric if (IsNeg) 32850b57cec5SDimitry Andric Value.changeSign(); 32860b57cec5SDimitry Andric 32870b57cec5SDimitry Andric // Consume the numeric token. 32880b57cec5SDimitry Andric Lex(); 32890b57cec5SDimitry Andric 32900b57cec5SDimitry Andric Res = Value.bitcastToAPInt(); 32910b57cec5SDimitry Andric 32920b57cec5SDimitry Andric return false; 32930b57cec5SDimitry Andric } 32940b57cec5SDimitry Andric 32950b57cec5SDimitry Andric /// parseDirectiveRealValue 32960b57cec5SDimitry Andric /// ::= (.single | .double) [ expression (, expression)* ] 32970b57cec5SDimitry Andric bool AsmParser::parseDirectiveRealValue(StringRef IDVal, 32980b57cec5SDimitry Andric const fltSemantics &Semantics) { 32990b57cec5SDimitry Andric auto parseOp = [&]() -> bool { 33000b57cec5SDimitry Andric APInt AsInt; 33010b57cec5SDimitry Andric if (checkForValidSection() || parseRealValue(Semantics, AsInt)) 33020b57cec5SDimitry Andric return true; 33035ffd83dbSDimitry Andric getStreamer().emitIntValue(AsInt.getLimitedValue(), 33040b57cec5SDimitry Andric AsInt.getBitWidth() / 8); 33050b57cec5SDimitry Andric return false; 33060b57cec5SDimitry Andric }; 33070b57cec5SDimitry Andric 3308fe6060f1SDimitry Andric return parseMany(parseOp); 33090b57cec5SDimitry Andric } 33100b57cec5SDimitry Andric 33110b57cec5SDimitry Andric /// parseDirectiveZero 33120b57cec5SDimitry Andric /// ::= .zero expression 33130b57cec5SDimitry Andric bool AsmParser::parseDirectiveZero() { 33140b57cec5SDimitry Andric SMLoc NumBytesLoc = Lexer.getLoc(); 33150b57cec5SDimitry Andric const MCExpr *NumBytes; 33160b57cec5SDimitry Andric if (checkForValidSection() || parseExpression(NumBytes)) 33170b57cec5SDimitry Andric return true; 33180b57cec5SDimitry Andric 33190b57cec5SDimitry Andric int64_t Val = 0; 33200b57cec5SDimitry Andric if (getLexer().is(AsmToken::Comma)) { 33210b57cec5SDimitry Andric Lex(); 33220b57cec5SDimitry Andric if (parseAbsoluteExpression(Val)) 33230b57cec5SDimitry Andric return true; 33240b57cec5SDimitry Andric } 33250b57cec5SDimitry Andric 3326fe6060f1SDimitry Andric if (parseEOL()) 33270b57cec5SDimitry Andric return true; 33280b57cec5SDimitry Andric getStreamer().emitFill(*NumBytes, Val, NumBytesLoc); 33290b57cec5SDimitry Andric 33300b57cec5SDimitry Andric return false; 33310b57cec5SDimitry Andric } 33320b57cec5SDimitry Andric 33330b57cec5SDimitry Andric /// parseDirectiveFill 33340b57cec5SDimitry Andric /// ::= .fill expression [ , expression [ , expression ] ] 33350b57cec5SDimitry Andric bool AsmParser::parseDirectiveFill() { 33360b57cec5SDimitry Andric SMLoc NumValuesLoc = Lexer.getLoc(); 33370b57cec5SDimitry Andric const MCExpr *NumValues; 33380b57cec5SDimitry Andric if (checkForValidSection() || parseExpression(NumValues)) 33390b57cec5SDimitry Andric return true; 33400b57cec5SDimitry Andric 33410b57cec5SDimitry Andric int64_t FillSize = 1; 33420b57cec5SDimitry Andric int64_t FillExpr = 0; 33430b57cec5SDimitry Andric 33440b57cec5SDimitry Andric SMLoc SizeLoc, ExprLoc; 33450b57cec5SDimitry Andric 33460b57cec5SDimitry Andric if (parseOptionalToken(AsmToken::Comma)) { 33470b57cec5SDimitry Andric SizeLoc = getTok().getLoc(); 33480b57cec5SDimitry Andric if (parseAbsoluteExpression(FillSize)) 33490b57cec5SDimitry Andric return true; 33500b57cec5SDimitry Andric if (parseOptionalToken(AsmToken::Comma)) { 33510b57cec5SDimitry Andric ExprLoc = getTok().getLoc(); 33520b57cec5SDimitry Andric if (parseAbsoluteExpression(FillExpr)) 33530b57cec5SDimitry Andric return true; 33540b57cec5SDimitry Andric } 33550b57cec5SDimitry Andric } 3356fe6060f1SDimitry Andric if (parseEOL()) 33570b57cec5SDimitry Andric return true; 33580b57cec5SDimitry Andric 33590b57cec5SDimitry Andric if (FillSize < 0) { 33600b57cec5SDimitry Andric Warning(SizeLoc, "'.fill' directive with negative size has no effect"); 33610b57cec5SDimitry Andric return false; 33620b57cec5SDimitry Andric } 33630b57cec5SDimitry Andric if (FillSize > 8) { 33640b57cec5SDimitry Andric Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8"); 33650b57cec5SDimitry Andric FillSize = 8; 33660b57cec5SDimitry Andric } 33670b57cec5SDimitry Andric 33680b57cec5SDimitry Andric if (!isUInt<32>(FillExpr) && FillSize > 4) 33690b57cec5SDimitry Andric Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits"); 33700b57cec5SDimitry Andric 33710b57cec5SDimitry Andric getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc); 33720b57cec5SDimitry Andric 33730b57cec5SDimitry Andric return false; 33740b57cec5SDimitry Andric } 33750b57cec5SDimitry Andric 33760b57cec5SDimitry Andric /// parseDirectiveOrg 33770b57cec5SDimitry Andric /// ::= .org expression [ , expression ] 33780b57cec5SDimitry Andric bool AsmParser::parseDirectiveOrg() { 33790b57cec5SDimitry Andric const MCExpr *Offset; 33800b57cec5SDimitry Andric SMLoc OffsetLoc = Lexer.getLoc(); 33810b57cec5SDimitry Andric if (checkForValidSection() || parseExpression(Offset)) 33820b57cec5SDimitry Andric return true; 33830b57cec5SDimitry Andric 33840b57cec5SDimitry Andric // Parse optional fill expression. 33850b57cec5SDimitry Andric int64_t FillExpr = 0; 33860b57cec5SDimitry Andric if (parseOptionalToken(AsmToken::Comma)) 33870b57cec5SDimitry Andric if (parseAbsoluteExpression(FillExpr)) 3388fe6060f1SDimitry Andric return true; 3389fe6060f1SDimitry Andric if (parseEOL()) 3390fe6060f1SDimitry Andric return true; 33910b57cec5SDimitry Andric 33920b57cec5SDimitry Andric getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc); 33930b57cec5SDimitry Andric return false; 33940b57cec5SDimitry Andric } 33950b57cec5SDimitry Andric 33960b57cec5SDimitry Andric /// parseDirectiveAlign 33970b57cec5SDimitry Andric /// ::= {.align, ...} expression [ , expression [ , expression ]] 33980b57cec5SDimitry Andric bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) { 33990b57cec5SDimitry Andric SMLoc AlignmentLoc = getLexer().getLoc(); 34000b57cec5SDimitry Andric int64_t Alignment; 34010b57cec5SDimitry Andric SMLoc MaxBytesLoc; 34020b57cec5SDimitry Andric bool HasFillExpr = false; 34030b57cec5SDimitry Andric int64_t FillExpr = 0; 34040b57cec5SDimitry Andric int64_t MaxBytesToFill = 0; 34055f757f3fSDimitry Andric SMLoc FillExprLoc; 34060b57cec5SDimitry Andric 34070b57cec5SDimitry Andric auto parseAlign = [&]() -> bool { 34080b57cec5SDimitry Andric if (parseAbsoluteExpression(Alignment)) 34090b57cec5SDimitry Andric return true; 34100b57cec5SDimitry Andric if (parseOptionalToken(AsmToken::Comma)) { 34110b57cec5SDimitry Andric // The fill expression can be omitted while specifying a maximum number of 34120b57cec5SDimitry Andric // alignment bytes, e.g: 34130b57cec5SDimitry Andric // .align 3,,4 34140b57cec5SDimitry Andric if (getTok().isNot(AsmToken::Comma)) { 34150b57cec5SDimitry Andric HasFillExpr = true; 34165f757f3fSDimitry Andric if (parseTokenLoc(FillExprLoc) || parseAbsoluteExpression(FillExpr)) 34170b57cec5SDimitry Andric return true; 34180b57cec5SDimitry Andric } 34190b57cec5SDimitry Andric if (parseOptionalToken(AsmToken::Comma)) 34200b57cec5SDimitry Andric if (parseTokenLoc(MaxBytesLoc) || 34210b57cec5SDimitry Andric parseAbsoluteExpression(MaxBytesToFill)) 34220b57cec5SDimitry Andric return true; 34230b57cec5SDimitry Andric } 3424fe6060f1SDimitry Andric return parseEOL(); 34250b57cec5SDimitry Andric }; 34260b57cec5SDimitry Andric 34270b57cec5SDimitry Andric if (checkForValidSection()) 3428fe6060f1SDimitry Andric return true; 34290b57cec5SDimitry Andric // Ignore empty '.p2align' directives for GNU-as compatibility 34300b57cec5SDimitry Andric if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) { 34310b57cec5SDimitry Andric Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored"); 3432fe6060f1SDimitry Andric return parseEOL(); 34330b57cec5SDimitry Andric } 34340b57cec5SDimitry Andric if (parseAlign()) 3435fe6060f1SDimitry Andric return true; 34360b57cec5SDimitry Andric 34370b57cec5SDimitry Andric // Always emit an alignment here even if we thrown an error. 34380b57cec5SDimitry Andric bool ReturnVal = false; 34390b57cec5SDimitry Andric 34400b57cec5SDimitry Andric // Compute alignment in bytes. 34410b57cec5SDimitry Andric if (IsPow2) { 34420b57cec5SDimitry Andric // FIXME: Diagnose overflow. 34430b57cec5SDimitry Andric if (Alignment >= 32) { 34440b57cec5SDimitry Andric ReturnVal |= Error(AlignmentLoc, "invalid alignment value"); 34450b57cec5SDimitry Andric Alignment = 31; 34460b57cec5SDimitry Andric } 34470b57cec5SDimitry Andric 34480b57cec5SDimitry Andric Alignment = 1ULL << Alignment; 34490b57cec5SDimitry Andric } else { 34500b57cec5SDimitry Andric // Reject alignments that aren't either a power of two or zero, 34510b57cec5SDimitry Andric // for gas compatibility. Alignment of zero is silently rounded 34520b57cec5SDimitry Andric // up to one. 34530b57cec5SDimitry Andric if (Alignment == 0) 34540b57cec5SDimitry Andric Alignment = 1; 345581ad6265SDimitry Andric else if (!isPowerOf2_64(Alignment)) { 34560b57cec5SDimitry Andric ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2"); 345706c3fb27SDimitry Andric Alignment = llvm::bit_floor<uint64_t>(Alignment); 345881ad6265SDimitry Andric } 345981ad6265SDimitry Andric if (!isUInt<32>(Alignment)) { 3460e8d8bef9SDimitry Andric ReturnVal |= Error(AlignmentLoc, "alignment must be smaller than 2**32"); 346181ad6265SDimitry Andric Alignment = 1u << 31; 346281ad6265SDimitry Andric } 34630b57cec5SDimitry Andric } 34640b57cec5SDimitry Andric 34655f757f3fSDimitry Andric if (HasFillExpr && FillExpr != 0) { 34665f757f3fSDimitry Andric MCSection *Sec = getStreamer().getCurrentSectionOnly(); 34675f757f3fSDimitry Andric if (Sec && Sec->isVirtualSection()) { 34685f757f3fSDimitry Andric ReturnVal |= 34695f757f3fSDimitry Andric Warning(FillExprLoc, "ignoring non-zero fill value in " + 34705f757f3fSDimitry Andric Sec->getVirtualSectionKind() + " section '" + 34715f757f3fSDimitry Andric Sec->getName() + "'"); 34725f757f3fSDimitry Andric FillExpr = 0; 34735f757f3fSDimitry Andric } 34745f757f3fSDimitry Andric } 34755f757f3fSDimitry Andric 34760b57cec5SDimitry Andric // Diagnose non-sensical max bytes to align. 34770b57cec5SDimitry Andric if (MaxBytesLoc.isValid()) { 34780b57cec5SDimitry Andric if (MaxBytesToFill < 1) { 34790b57cec5SDimitry Andric ReturnVal |= Error(MaxBytesLoc, 34800b57cec5SDimitry Andric "alignment directive can never be satisfied in this " 34810b57cec5SDimitry Andric "many bytes, ignoring maximum bytes expression"); 34820b57cec5SDimitry Andric MaxBytesToFill = 0; 34830b57cec5SDimitry Andric } 34840b57cec5SDimitry Andric 34850b57cec5SDimitry Andric if (MaxBytesToFill >= Alignment) { 34860b57cec5SDimitry Andric Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and " 34870b57cec5SDimitry Andric "has no effect"); 34880b57cec5SDimitry Andric MaxBytesToFill = 0; 34890b57cec5SDimitry Andric } 34900b57cec5SDimitry Andric } 34910b57cec5SDimitry Andric 34920b57cec5SDimitry Andric // Check whether we should use optimal code alignment for this .align 34930b57cec5SDimitry Andric // directive. 34940b57cec5SDimitry Andric const MCSection *Section = getStreamer().getCurrentSectionOnly(); 34950b57cec5SDimitry Andric assert(Section && "must have section to emit alignment"); 349681ad6265SDimitry Andric bool useCodeAlign = Section->useCodeAlign(); 34970b57cec5SDimitry Andric if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) && 349881ad6265SDimitry Andric ValueSize == 1 && useCodeAlign) { 3499bdd1243dSDimitry Andric getStreamer().emitCodeAlignment( 3500bdd1243dSDimitry Andric Align(Alignment), &getTargetParser().getSTI(), MaxBytesToFill); 35010b57cec5SDimitry Andric } else { 35020b57cec5SDimitry Andric // FIXME: Target specific behavior about how the "extra" bytes are filled. 3503bdd1243dSDimitry Andric getStreamer().emitValueToAlignment(Align(Alignment), FillExpr, ValueSize, 35040b57cec5SDimitry Andric MaxBytesToFill); 35050b57cec5SDimitry Andric } 35060b57cec5SDimitry Andric 35070b57cec5SDimitry Andric return ReturnVal; 35080b57cec5SDimitry Andric } 35090b57cec5SDimitry Andric 35100b57cec5SDimitry Andric /// parseDirectiveFile 35110b57cec5SDimitry Andric /// ::= .file filename 35120b57cec5SDimitry Andric /// ::= .file number [directory] filename [md5 checksum] [source source-text] 35130b57cec5SDimitry Andric bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) { 35140b57cec5SDimitry Andric // FIXME: I'm not sure what this is. 35150b57cec5SDimitry Andric int64_t FileNumber = -1; 35160b57cec5SDimitry Andric if (getLexer().is(AsmToken::Integer)) { 35170b57cec5SDimitry Andric FileNumber = getTok().getIntVal(); 35180b57cec5SDimitry Andric Lex(); 35190b57cec5SDimitry Andric 35200b57cec5SDimitry Andric if (FileNumber < 0) 35210b57cec5SDimitry Andric return TokError("negative file number"); 35220b57cec5SDimitry Andric } 35230b57cec5SDimitry Andric 35240b57cec5SDimitry Andric std::string Path; 35250b57cec5SDimitry Andric 35260b57cec5SDimitry Andric // Usually the directory and filename together, otherwise just the directory. 35270b57cec5SDimitry Andric // Allow the strings to have escaped octal character sequence. 3528fe6060f1SDimitry Andric if (parseEscapedString(Path)) 35290b57cec5SDimitry Andric return true; 35300b57cec5SDimitry Andric 35310b57cec5SDimitry Andric StringRef Directory; 35320b57cec5SDimitry Andric StringRef Filename; 35330b57cec5SDimitry Andric std::string FilenameData; 35340b57cec5SDimitry Andric if (getLexer().is(AsmToken::String)) { 35350b57cec5SDimitry Andric if (check(FileNumber == -1, 35360b57cec5SDimitry Andric "explicit path specified, but no file number") || 35370b57cec5SDimitry Andric parseEscapedString(FilenameData)) 35380b57cec5SDimitry Andric return true; 35390b57cec5SDimitry Andric Filename = FilenameData; 35400b57cec5SDimitry Andric Directory = Path; 35410b57cec5SDimitry Andric } else { 35420b57cec5SDimitry Andric Filename = Path; 35430b57cec5SDimitry Andric } 35440b57cec5SDimitry Andric 35450b57cec5SDimitry Andric uint64_t MD5Hi, MD5Lo; 35460b57cec5SDimitry Andric bool HasMD5 = false; 35470b57cec5SDimitry Andric 3548bdd1243dSDimitry Andric std::optional<StringRef> Source; 35490b57cec5SDimitry Andric bool HasSource = false; 35500b57cec5SDimitry Andric std::string SourceString; 35510b57cec5SDimitry Andric 35520b57cec5SDimitry Andric while (!parseOptionalToken(AsmToken::EndOfStatement)) { 35530b57cec5SDimitry Andric StringRef Keyword; 35540b57cec5SDimitry Andric if (check(getTok().isNot(AsmToken::Identifier), 35550b57cec5SDimitry Andric "unexpected token in '.file' directive") || 35560b57cec5SDimitry Andric parseIdentifier(Keyword)) 35570b57cec5SDimitry Andric return true; 35580b57cec5SDimitry Andric if (Keyword == "md5") { 35590b57cec5SDimitry Andric HasMD5 = true; 35600b57cec5SDimitry Andric if (check(FileNumber == -1, 35610b57cec5SDimitry Andric "MD5 checksum specified, but no file number") || 35620b57cec5SDimitry Andric parseHexOcta(*this, MD5Hi, MD5Lo)) 35630b57cec5SDimitry Andric return true; 35640b57cec5SDimitry Andric } else if (Keyword == "source") { 35650b57cec5SDimitry Andric HasSource = true; 35660b57cec5SDimitry Andric if (check(FileNumber == -1, 35670b57cec5SDimitry Andric "source specified, but no file number") || 35680b57cec5SDimitry Andric check(getTok().isNot(AsmToken::String), 35690b57cec5SDimitry Andric "unexpected token in '.file' directive") || 35700b57cec5SDimitry Andric parseEscapedString(SourceString)) 35710b57cec5SDimitry Andric return true; 35720b57cec5SDimitry Andric } else { 35730b57cec5SDimitry Andric return TokError("unexpected token in '.file' directive"); 35740b57cec5SDimitry Andric } 35750b57cec5SDimitry Andric } 35760b57cec5SDimitry Andric 35770b57cec5SDimitry Andric if (FileNumber == -1) { 35780b57cec5SDimitry Andric // Ignore the directive if there is no number and the target doesn't support 35790b57cec5SDimitry Andric // numberless .file directives. This allows some portability of assembler 35800b57cec5SDimitry Andric // between different object file formats. 35810b57cec5SDimitry Andric if (getContext().getAsmInfo()->hasSingleParameterDotFile()) 35825ffd83dbSDimitry Andric getStreamer().emitFileDirective(Filename); 35830b57cec5SDimitry Andric } else { 35840b57cec5SDimitry Andric // In case there is a -g option as well as debug info from directive .file, 35850b57cec5SDimitry Andric // we turn off the -g option, directly use the existing debug info instead. 35860b57cec5SDimitry Andric // Throw away any implicit file table for the assembler source. 35870b57cec5SDimitry Andric if (Ctx.getGenDwarfForAssembly()) { 35880b57cec5SDimitry Andric Ctx.getMCDwarfLineTable(0).resetFileTable(); 35890b57cec5SDimitry Andric Ctx.setGenDwarfForAssembly(false); 35900b57cec5SDimitry Andric } 35910b57cec5SDimitry Andric 3592bdd1243dSDimitry Andric std::optional<MD5::MD5Result> CKMem; 35930b57cec5SDimitry Andric if (HasMD5) { 35940b57cec5SDimitry Andric MD5::MD5Result Sum; 35950b57cec5SDimitry Andric for (unsigned i = 0; i != 8; ++i) { 359681ad6265SDimitry Andric Sum[i] = uint8_t(MD5Hi >> ((7 - i) * 8)); 359781ad6265SDimitry Andric Sum[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8)); 35980b57cec5SDimitry Andric } 35990b57cec5SDimitry Andric CKMem = Sum; 36000b57cec5SDimitry Andric } 36010b57cec5SDimitry Andric if (HasSource) { 36020b57cec5SDimitry Andric char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size())); 36030b57cec5SDimitry Andric memcpy(SourceBuf, SourceString.data(), SourceString.size()); 36040b57cec5SDimitry Andric Source = StringRef(SourceBuf, SourceString.size()); 36050b57cec5SDimitry Andric } 36060b57cec5SDimitry Andric if (FileNumber == 0) { 3607fe6060f1SDimitry Andric // Upgrade to Version 5 for assembly actions like clang -c a.s. 36080b57cec5SDimitry Andric if (Ctx.getDwarfVersion() < 5) 3609fe6060f1SDimitry Andric Ctx.setDwarfVersion(5); 36100b57cec5SDimitry Andric getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source); 36110b57cec5SDimitry Andric } else { 36120b57cec5SDimitry Andric Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective( 36130b57cec5SDimitry Andric FileNumber, Directory, Filename, CKMem, Source); 36140b57cec5SDimitry Andric if (!FileNumOrErr) 36150b57cec5SDimitry Andric return Error(DirectiveLoc, toString(FileNumOrErr.takeError())); 36160b57cec5SDimitry Andric } 36170b57cec5SDimitry Andric // Alert the user if there are some .file directives with MD5 and some not. 36180b57cec5SDimitry Andric // But only do that once. 36190b57cec5SDimitry Andric if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) { 36200b57cec5SDimitry Andric ReportedInconsistentMD5 = true; 36210b57cec5SDimitry Andric return Warning(DirectiveLoc, "inconsistent use of MD5 checksums"); 36220b57cec5SDimitry Andric } 36230b57cec5SDimitry Andric } 36240b57cec5SDimitry Andric 36250b57cec5SDimitry Andric return false; 36260b57cec5SDimitry Andric } 36270b57cec5SDimitry Andric 36280b57cec5SDimitry Andric /// parseDirectiveLine 36290b57cec5SDimitry Andric /// ::= .line [number] 36300b57cec5SDimitry Andric bool AsmParser::parseDirectiveLine() { 36310b57cec5SDimitry Andric int64_t LineNumber; 36320b57cec5SDimitry Andric if (getLexer().is(AsmToken::Integer)) { 36330b57cec5SDimitry Andric if (parseIntToken(LineNumber, "unexpected token in '.line' directive")) 36340b57cec5SDimitry Andric return true; 36350b57cec5SDimitry Andric (void)LineNumber; 36360b57cec5SDimitry Andric // FIXME: Do something with the .line. 36370b57cec5SDimitry Andric } 3638fe6060f1SDimitry Andric return parseEOL(); 36390b57cec5SDimitry Andric } 36400b57cec5SDimitry Andric 36410b57cec5SDimitry Andric /// parseDirectiveLoc 36420b57cec5SDimitry Andric /// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end] 36430b57cec5SDimitry Andric /// [epilogue_begin] [is_stmt VALUE] [isa VALUE] 36440b57cec5SDimitry Andric /// The first number is a file number, must have been previously assigned with 36450b57cec5SDimitry Andric /// a .file directive, the second number is the line number and optionally the 36460b57cec5SDimitry Andric /// third number is a column position (zero if not specified). The remaining 36470b57cec5SDimitry Andric /// optional items are .loc sub-directives. 36480b57cec5SDimitry Andric bool AsmParser::parseDirectiveLoc() { 36490b57cec5SDimitry Andric int64_t FileNumber = 0, LineNumber = 0; 36500b57cec5SDimitry Andric SMLoc Loc = getTok().getLoc(); 36510b57cec5SDimitry Andric if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") || 36520b57cec5SDimitry Andric check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc, 36530b57cec5SDimitry Andric "file number less than one in '.loc' directive") || 36540b57cec5SDimitry Andric check(!getContext().isValidDwarfFileNumber(FileNumber), Loc, 36550b57cec5SDimitry Andric "unassigned file number in '.loc' directive")) 36560b57cec5SDimitry Andric return true; 36570b57cec5SDimitry Andric 36580b57cec5SDimitry Andric // optional 36590b57cec5SDimitry Andric if (getLexer().is(AsmToken::Integer)) { 36600b57cec5SDimitry Andric LineNumber = getTok().getIntVal(); 36610b57cec5SDimitry Andric if (LineNumber < 0) 36620b57cec5SDimitry Andric return TokError("line number less than zero in '.loc' directive"); 36630b57cec5SDimitry Andric Lex(); 36640b57cec5SDimitry Andric } 36650b57cec5SDimitry Andric 36660b57cec5SDimitry Andric int64_t ColumnPos = 0; 36670b57cec5SDimitry Andric if (getLexer().is(AsmToken::Integer)) { 36680b57cec5SDimitry Andric ColumnPos = getTok().getIntVal(); 36690b57cec5SDimitry Andric if (ColumnPos < 0) 36700b57cec5SDimitry Andric return TokError("column position less than zero in '.loc' directive"); 36710b57cec5SDimitry Andric Lex(); 36720b57cec5SDimitry Andric } 36730b57cec5SDimitry Andric 36745ffd83dbSDimitry Andric auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags(); 36755ffd83dbSDimitry Andric unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT; 36760b57cec5SDimitry Andric unsigned Isa = 0; 36770b57cec5SDimitry Andric int64_t Discriminator = 0; 36780b57cec5SDimitry Andric 36790b57cec5SDimitry Andric auto parseLocOp = [&]() -> bool { 36800b57cec5SDimitry Andric StringRef Name; 36810b57cec5SDimitry Andric SMLoc Loc = getTok().getLoc(); 36820b57cec5SDimitry Andric if (parseIdentifier(Name)) 36830b57cec5SDimitry Andric return TokError("unexpected token in '.loc' directive"); 36840b57cec5SDimitry Andric 36850b57cec5SDimitry Andric if (Name == "basic_block") 36860b57cec5SDimitry Andric Flags |= DWARF2_FLAG_BASIC_BLOCK; 36870b57cec5SDimitry Andric else if (Name == "prologue_end") 36880b57cec5SDimitry Andric Flags |= DWARF2_FLAG_PROLOGUE_END; 36890b57cec5SDimitry Andric else if (Name == "epilogue_begin") 36900b57cec5SDimitry Andric Flags |= DWARF2_FLAG_EPILOGUE_BEGIN; 36910b57cec5SDimitry Andric else if (Name == "is_stmt") { 36920b57cec5SDimitry Andric Loc = getTok().getLoc(); 36930b57cec5SDimitry Andric const MCExpr *Value; 36940b57cec5SDimitry Andric if (parseExpression(Value)) 36950b57cec5SDimitry Andric return true; 36960b57cec5SDimitry Andric // The expression must be the constant 0 or 1. 36970b57cec5SDimitry Andric if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { 36980b57cec5SDimitry Andric int Value = MCE->getValue(); 36990b57cec5SDimitry Andric if (Value == 0) 37000b57cec5SDimitry Andric Flags &= ~DWARF2_FLAG_IS_STMT; 37010b57cec5SDimitry Andric else if (Value == 1) 37020b57cec5SDimitry Andric Flags |= DWARF2_FLAG_IS_STMT; 37030b57cec5SDimitry Andric else 37040b57cec5SDimitry Andric return Error(Loc, "is_stmt value not 0 or 1"); 37050b57cec5SDimitry Andric } else { 37060b57cec5SDimitry Andric return Error(Loc, "is_stmt value not the constant value of 0 or 1"); 37070b57cec5SDimitry Andric } 37080b57cec5SDimitry Andric } else if (Name == "isa") { 37090b57cec5SDimitry Andric Loc = getTok().getLoc(); 37100b57cec5SDimitry Andric const MCExpr *Value; 37110b57cec5SDimitry Andric if (parseExpression(Value)) 37120b57cec5SDimitry Andric return true; 37130b57cec5SDimitry Andric // The expression must be a constant greater or equal to 0. 37140b57cec5SDimitry Andric if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { 37150b57cec5SDimitry Andric int Value = MCE->getValue(); 37160b57cec5SDimitry Andric if (Value < 0) 37170b57cec5SDimitry Andric return Error(Loc, "isa number less than zero"); 37180b57cec5SDimitry Andric Isa = Value; 37190b57cec5SDimitry Andric } else { 37200b57cec5SDimitry Andric return Error(Loc, "isa number not a constant value"); 37210b57cec5SDimitry Andric } 37220b57cec5SDimitry Andric } else if (Name == "discriminator") { 37230b57cec5SDimitry Andric if (parseAbsoluteExpression(Discriminator)) 37240b57cec5SDimitry Andric return true; 37250b57cec5SDimitry Andric } else { 37260b57cec5SDimitry Andric return Error(Loc, "unknown sub-directive in '.loc' directive"); 37270b57cec5SDimitry Andric } 37280b57cec5SDimitry Andric return false; 37290b57cec5SDimitry Andric }; 37300b57cec5SDimitry Andric 37310b57cec5SDimitry Andric if (parseMany(parseLocOp, false /*hasComma*/)) 37320b57cec5SDimitry Andric return true; 37330b57cec5SDimitry Andric 37345ffd83dbSDimitry Andric getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags, 37350b57cec5SDimitry Andric Isa, Discriminator, StringRef()); 37360b57cec5SDimitry Andric 37370b57cec5SDimitry Andric return false; 37380b57cec5SDimitry Andric } 37390b57cec5SDimitry Andric 37400b57cec5SDimitry Andric /// parseDirectiveStabs 37410b57cec5SDimitry Andric /// ::= .stabs string, number, number, number 37420b57cec5SDimitry Andric bool AsmParser::parseDirectiveStabs() { 37430b57cec5SDimitry Andric return TokError("unsupported directive '.stabs'"); 37440b57cec5SDimitry Andric } 37450b57cec5SDimitry Andric 37460b57cec5SDimitry Andric /// parseDirectiveCVFile 37470b57cec5SDimitry Andric /// ::= .cv_file number filename [checksum] [checksumkind] 37480b57cec5SDimitry Andric bool AsmParser::parseDirectiveCVFile() { 37490b57cec5SDimitry Andric SMLoc FileNumberLoc = getTok().getLoc(); 37500b57cec5SDimitry Andric int64_t FileNumber; 37510b57cec5SDimitry Andric std::string Filename; 37520b57cec5SDimitry Andric std::string Checksum; 37530b57cec5SDimitry Andric int64_t ChecksumKind = 0; 37540b57cec5SDimitry Andric 37550b57cec5SDimitry Andric if (parseIntToken(FileNumber, 37560b57cec5SDimitry Andric "expected file number in '.cv_file' directive") || 37570b57cec5SDimitry Andric check(FileNumber < 1, FileNumberLoc, "file number less than one") || 37580b57cec5SDimitry Andric check(getTok().isNot(AsmToken::String), 37590b57cec5SDimitry Andric "unexpected token in '.cv_file' directive") || 37600b57cec5SDimitry Andric parseEscapedString(Filename)) 37610b57cec5SDimitry Andric return true; 37620b57cec5SDimitry Andric if (!parseOptionalToken(AsmToken::EndOfStatement)) { 37630b57cec5SDimitry Andric if (check(getTok().isNot(AsmToken::String), 37640b57cec5SDimitry Andric "unexpected token in '.cv_file' directive") || 37650b57cec5SDimitry Andric parseEscapedString(Checksum) || 37660b57cec5SDimitry Andric parseIntToken(ChecksumKind, 37670b57cec5SDimitry Andric "expected checksum kind in '.cv_file' directive") || 376881ad6265SDimitry Andric parseEOL()) 37690b57cec5SDimitry Andric return true; 37700b57cec5SDimitry Andric } 37710b57cec5SDimitry Andric 37720b57cec5SDimitry Andric Checksum = fromHex(Checksum); 37730b57cec5SDimitry Andric void *CKMem = Ctx.allocate(Checksum.size(), 1); 37740b57cec5SDimitry Andric memcpy(CKMem, Checksum.data(), Checksum.size()); 37750b57cec5SDimitry Andric ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem), 37760b57cec5SDimitry Andric Checksum.size()); 37770b57cec5SDimitry Andric 377881ad6265SDimitry Andric if (!getStreamer().emitCVFileDirective(FileNumber, Filename, ChecksumAsBytes, 37790b57cec5SDimitry Andric static_cast<uint8_t>(ChecksumKind))) 37800b57cec5SDimitry Andric return Error(FileNumberLoc, "file number already allocated"); 37810b57cec5SDimitry Andric 37820b57cec5SDimitry Andric return false; 37830b57cec5SDimitry Andric } 37840b57cec5SDimitry Andric 37850b57cec5SDimitry Andric bool AsmParser::parseCVFunctionId(int64_t &FunctionId, 37860b57cec5SDimitry Andric StringRef DirectiveName) { 37870b57cec5SDimitry Andric SMLoc Loc; 37880b57cec5SDimitry Andric return parseTokenLoc(Loc) || 37890b57cec5SDimitry Andric parseIntToken(FunctionId, "expected function id in '" + DirectiveName + 37900b57cec5SDimitry Andric "' directive") || 37910b57cec5SDimitry Andric check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc, 37920b57cec5SDimitry Andric "expected function id within range [0, UINT_MAX)"); 37930b57cec5SDimitry Andric } 37940b57cec5SDimitry Andric 37950b57cec5SDimitry Andric bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) { 37960b57cec5SDimitry Andric SMLoc Loc; 37970b57cec5SDimitry Andric return parseTokenLoc(Loc) || 37980b57cec5SDimitry Andric parseIntToken(FileNumber, "expected integer in '" + DirectiveName + 37990b57cec5SDimitry Andric "' directive") || 38000b57cec5SDimitry Andric check(FileNumber < 1, Loc, "file number less than one in '" + 38010b57cec5SDimitry Andric DirectiveName + "' directive") || 38020b57cec5SDimitry Andric check(!getCVContext().isValidFileNumber(FileNumber), Loc, 38030b57cec5SDimitry Andric "unassigned file number in '" + DirectiveName + "' directive"); 38040b57cec5SDimitry Andric } 38050b57cec5SDimitry Andric 38060b57cec5SDimitry Andric /// parseDirectiveCVFuncId 38070b57cec5SDimitry Andric /// ::= .cv_func_id FunctionId 38080b57cec5SDimitry Andric /// 38090b57cec5SDimitry Andric /// Introduces a function ID that can be used with .cv_loc. 38100b57cec5SDimitry Andric bool AsmParser::parseDirectiveCVFuncId() { 38110b57cec5SDimitry Andric SMLoc FunctionIdLoc = getTok().getLoc(); 38120b57cec5SDimitry Andric int64_t FunctionId; 38130b57cec5SDimitry Andric 381481ad6265SDimitry Andric if (parseCVFunctionId(FunctionId, ".cv_func_id") || parseEOL()) 38150b57cec5SDimitry Andric return true; 38160b57cec5SDimitry Andric 381781ad6265SDimitry Andric if (!getStreamer().emitCVFuncIdDirective(FunctionId)) 38180b57cec5SDimitry Andric return Error(FunctionIdLoc, "function id already allocated"); 38190b57cec5SDimitry Andric 38200b57cec5SDimitry Andric return false; 38210b57cec5SDimitry Andric } 38220b57cec5SDimitry Andric 38230b57cec5SDimitry Andric /// parseDirectiveCVInlineSiteId 38240b57cec5SDimitry Andric /// ::= .cv_inline_site_id FunctionId 38250b57cec5SDimitry Andric /// "within" IAFunc 38260b57cec5SDimitry Andric /// "inlined_at" IAFile IALine [IACol] 38270b57cec5SDimitry Andric /// 38280b57cec5SDimitry Andric /// Introduces a function ID that can be used with .cv_loc. Includes "inlined 38290b57cec5SDimitry Andric /// at" source location information for use in the line table of the caller, 38300b57cec5SDimitry Andric /// whether the caller is a real function or another inlined call site. 38310b57cec5SDimitry Andric bool AsmParser::parseDirectiveCVInlineSiteId() { 38320b57cec5SDimitry Andric SMLoc FunctionIdLoc = getTok().getLoc(); 38330b57cec5SDimitry Andric int64_t FunctionId; 38340b57cec5SDimitry Andric int64_t IAFunc; 38350b57cec5SDimitry Andric int64_t IAFile; 38360b57cec5SDimitry Andric int64_t IALine; 38370b57cec5SDimitry Andric int64_t IACol = 0; 38380b57cec5SDimitry Andric 38390b57cec5SDimitry Andric // FunctionId 38400b57cec5SDimitry Andric if (parseCVFunctionId(FunctionId, ".cv_inline_site_id")) 38410b57cec5SDimitry Andric return true; 38420b57cec5SDimitry Andric 38430b57cec5SDimitry Andric // "within" 38440b57cec5SDimitry Andric if (check((getLexer().isNot(AsmToken::Identifier) || 38450b57cec5SDimitry Andric getTok().getIdentifier() != "within"), 38460b57cec5SDimitry Andric "expected 'within' identifier in '.cv_inline_site_id' directive")) 38470b57cec5SDimitry Andric return true; 38480b57cec5SDimitry Andric Lex(); 38490b57cec5SDimitry Andric 38500b57cec5SDimitry Andric // IAFunc 38510b57cec5SDimitry Andric if (parseCVFunctionId(IAFunc, ".cv_inline_site_id")) 38520b57cec5SDimitry Andric return true; 38530b57cec5SDimitry Andric 38540b57cec5SDimitry Andric // "inlined_at" 38550b57cec5SDimitry Andric if (check((getLexer().isNot(AsmToken::Identifier) || 38560b57cec5SDimitry Andric getTok().getIdentifier() != "inlined_at"), 38570b57cec5SDimitry Andric "expected 'inlined_at' identifier in '.cv_inline_site_id' " 38580b57cec5SDimitry Andric "directive") ) 38590b57cec5SDimitry Andric return true; 38600b57cec5SDimitry Andric Lex(); 38610b57cec5SDimitry Andric 38620b57cec5SDimitry Andric // IAFile IALine 38630b57cec5SDimitry Andric if (parseCVFileId(IAFile, ".cv_inline_site_id") || 38640b57cec5SDimitry Andric parseIntToken(IALine, "expected line number after 'inlined_at'")) 38650b57cec5SDimitry Andric return true; 38660b57cec5SDimitry Andric 38670b57cec5SDimitry Andric // [IACol] 38680b57cec5SDimitry Andric if (getLexer().is(AsmToken::Integer)) { 38690b57cec5SDimitry Andric IACol = getTok().getIntVal(); 38700b57cec5SDimitry Andric Lex(); 38710b57cec5SDimitry Andric } 38720b57cec5SDimitry Andric 387381ad6265SDimitry Andric if (parseEOL()) 38740b57cec5SDimitry Andric return true; 38750b57cec5SDimitry Andric 387681ad6265SDimitry Andric if (!getStreamer().emitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile, 38770b57cec5SDimitry Andric IALine, IACol, FunctionIdLoc)) 38780b57cec5SDimitry Andric return Error(FunctionIdLoc, "function id already allocated"); 38790b57cec5SDimitry Andric 38800b57cec5SDimitry Andric return false; 38810b57cec5SDimitry Andric } 38820b57cec5SDimitry Andric 38830b57cec5SDimitry Andric /// parseDirectiveCVLoc 38840b57cec5SDimitry Andric /// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end] 38850b57cec5SDimitry Andric /// [is_stmt VALUE] 38860b57cec5SDimitry Andric /// The first number is a file number, must have been previously assigned with 38870b57cec5SDimitry Andric /// a .file directive, the second number is the line number and optionally the 38880b57cec5SDimitry Andric /// third number is a column position (zero if not specified). The remaining 38890b57cec5SDimitry Andric /// optional items are .loc sub-directives. 38900b57cec5SDimitry Andric bool AsmParser::parseDirectiveCVLoc() { 38910b57cec5SDimitry Andric SMLoc DirectiveLoc = getTok().getLoc(); 38920b57cec5SDimitry Andric int64_t FunctionId, FileNumber; 38930b57cec5SDimitry Andric if (parseCVFunctionId(FunctionId, ".cv_loc") || 38940b57cec5SDimitry Andric parseCVFileId(FileNumber, ".cv_loc")) 38950b57cec5SDimitry Andric return true; 38960b57cec5SDimitry Andric 38970b57cec5SDimitry Andric int64_t LineNumber = 0; 38980b57cec5SDimitry Andric if (getLexer().is(AsmToken::Integer)) { 38990b57cec5SDimitry Andric LineNumber = getTok().getIntVal(); 39000b57cec5SDimitry Andric if (LineNumber < 0) 39010b57cec5SDimitry Andric return TokError("line number less than zero in '.cv_loc' directive"); 39020b57cec5SDimitry Andric Lex(); 39030b57cec5SDimitry Andric } 39040b57cec5SDimitry Andric 39050b57cec5SDimitry Andric int64_t ColumnPos = 0; 39060b57cec5SDimitry Andric if (getLexer().is(AsmToken::Integer)) { 39070b57cec5SDimitry Andric ColumnPos = getTok().getIntVal(); 39080b57cec5SDimitry Andric if (ColumnPos < 0) 39090b57cec5SDimitry Andric return TokError("column position less than zero in '.cv_loc' directive"); 39100b57cec5SDimitry Andric Lex(); 39110b57cec5SDimitry Andric } 39120b57cec5SDimitry Andric 39130b57cec5SDimitry Andric bool PrologueEnd = false; 39140b57cec5SDimitry Andric uint64_t IsStmt = 0; 39150b57cec5SDimitry Andric 39160b57cec5SDimitry Andric auto parseOp = [&]() -> bool { 39170b57cec5SDimitry Andric StringRef Name; 39180b57cec5SDimitry Andric SMLoc Loc = getTok().getLoc(); 39190b57cec5SDimitry Andric if (parseIdentifier(Name)) 39200b57cec5SDimitry Andric return TokError("unexpected token in '.cv_loc' directive"); 39210b57cec5SDimitry Andric if (Name == "prologue_end") 39220b57cec5SDimitry Andric PrologueEnd = true; 39230b57cec5SDimitry Andric else if (Name == "is_stmt") { 39240b57cec5SDimitry Andric Loc = getTok().getLoc(); 39250b57cec5SDimitry Andric const MCExpr *Value; 39260b57cec5SDimitry Andric if (parseExpression(Value)) 39270b57cec5SDimitry Andric return true; 39280b57cec5SDimitry Andric // The expression must be the constant 0 or 1. 39290b57cec5SDimitry Andric IsStmt = ~0ULL; 39300b57cec5SDimitry Andric if (const auto *MCE = dyn_cast<MCConstantExpr>(Value)) 39310b57cec5SDimitry Andric IsStmt = MCE->getValue(); 39320b57cec5SDimitry Andric 39330b57cec5SDimitry Andric if (IsStmt > 1) 39340b57cec5SDimitry Andric return Error(Loc, "is_stmt value not 0 or 1"); 39350b57cec5SDimitry Andric } else { 39360b57cec5SDimitry Andric return Error(Loc, "unknown sub-directive in '.cv_loc' directive"); 39370b57cec5SDimitry Andric } 39380b57cec5SDimitry Andric return false; 39390b57cec5SDimitry Andric }; 39400b57cec5SDimitry Andric 39410b57cec5SDimitry Andric if (parseMany(parseOp, false /*hasComma*/)) 39420b57cec5SDimitry Andric return true; 39430b57cec5SDimitry Andric 39445ffd83dbSDimitry Andric getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber, 39450b57cec5SDimitry Andric ColumnPos, PrologueEnd, IsStmt, StringRef(), 39460b57cec5SDimitry Andric DirectiveLoc); 39470b57cec5SDimitry Andric return false; 39480b57cec5SDimitry Andric } 39490b57cec5SDimitry Andric 39500b57cec5SDimitry Andric /// parseDirectiveCVLinetable 39510b57cec5SDimitry Andric /// ::= .cv_linetable FunctionId, FnStart, FnEnd 39520b57cec5SDimitry Andric bool AsmParser::parseDirectiveCVLinetable() { 39530b57cec5SDimitry Andric int64_t FunctionId; 39540b57cec5SDimitry Andric StringRef FnStartName, FnEndName; 39550b57cec5SDimitry Andric SMLoc Loc = getTok().getLoc(); 3956fe6060f1SDimitry Andric if (parseCVFunctionId(FunctionId, ".cv_linetable") || parseComma() || 3957fe6060f1SDimitry Andric parseTokenLoc(Loc) || 3958fe6060f1SDimitry Andric check(parseIdentifier(FnStartName), Loc, 39590b57cec5SDimitry Andric "expected identifier in directive") || 3960fe6060f1SDimitry Andric parseComma() || parseTokenLoc(Loc) || 3961fe6060f1SDimitry Andric check(parseIdentifier(FnEndName), Loc, 39620b57cec5SDimitry Andric "expected identifier in directive")) 39630b57cec5SDimitry Andric return true; 39640b57cec5SDimitry Andric 39650b57cec5SDimitry Andric MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName); 39660b57cec5SDimitry Andric MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName); 39670b57cec5SDimitry Andric 39685ffd83dbSDimitry Andric getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym); 39690b57cec5SDimitry Andric return false; 39700b57cec5SDimitry Andric } 39710b57cec5SDimitry Andric 39720b57cec5SDimitry Andric /// parseDirectiveCVInlineLinetable 39730b57cec5SDimitry Andric /// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd 39740b57cec5SDimitry Andric bool AsmParser::parseDirectiveCVInlineLinetable() { 39750b57cec5SDimitry Andric int64_t PrimaryFunctionId, SourceFileId, SourceLineNum; 39760b57cec5SDimitry Andric StringRef FnStartName, FnEndName; 39770b57cec5SDimitry Andric SMLoc Loc = getTok().getLoc(); 39780b57cec5SDimitry Andric if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") || 39790b57cec5SDimitry Andric parseTokenLoc(Loc) || 39800b57cec5SDimitry Andric parseIntToken( 39810b57cec5SDimitry Andric SourceFileId, 39820b57cec5SDimitry Andric "expected SourceField in '.cv_inline_linetable' directive") || 39830b57cec5SDimitry Andric check(SourceFileId <= 0, Loc, 39840b57cec5SDimitry Andric "File id less than zero in '.cv_inline_linetable' directive") || 39850b57cec5SDimitry Andric parseTokenLoc(Loc) || 39860b57cec5SDimitry Andric parseIntToken( 39870b57cec5SDimitry Andric SourceLineNum, 39880b57cec5SDimitry Andric "expected SourceLineNum in '.cv_inline_linetable' directive") || 39890b57cec5SDimitry Andric check(SourceLineNum < 0, Loc, 39900b57cec5SDimitry Andric "Line number less than zero in '.cv_inline_linetable' directive") || 39910b57cec5SDimitry Andric parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc, 39920b57cec5SDimitry Andric "expected identifier in directive") || 39930b57cec5SDimitry Andric parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc, 39940b57cec5SDimitry Andric "expected identifier in directive")) 39950b57cec5SDimitry Andric return true; 39960b57cec5SDimitry Andric 399781ad6265SDimitry Andric if (parseEOL()) 39980b57cec5SDimitry Andric return true; 39990b57cec5SDimitry Andric 40000b57cec5SDimitry Andric MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName); 40010b57cec5SDimitry Andric MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName); 40025ffd83dbSDimitry Andric getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId, 40030b57cec5SDimitry Andric SourceLineNum, FnStartSym, 40040b57cec5SDimitry Andric FnEndSym); 40050b57cec5SDimitry Andric return false; 40060b57cec5SDimitry Andric } 40070b57cec5SDimitry Andric 40088bcb0991SDimitry Andric void AsmParser::initializeCVDefRangeTypeMap() { 40098bcb0991SDimitry Andric CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER; 40108bcb0991SDimitry Andric CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL; 40118bcb0991SDimitry Andric CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER; 40128bcb0991SDimitry Andric CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL; 40138bcb0991SDimitry Andric } 40148bcb0991SDimitry Andric 40150b57cec5SDimitry Andric /// parseDirectiveCVDefRange 40160b57cec5SDimitry Andric /// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes* 40170b57cec5SDimitry Andric bool AsmParser::parseDirectiveCVDefRange() { 40180b57cec5SDimitry Andric SMLoc Loc; 40190b57cec5SDimitry Andric std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges; 40200b57cec5SDimitry Andric while (getLexer().is(AsmToken::Identifier)) { 40210b57cec5SDimitry Andric Loc = getLexer().getLoc(); 40220b57cec5SDimitry Andric StringRef GapStartName; 40230b57cec5SDimitry Andric if (parseIdentifier(GapStartName)) 40240b57cec5SDimitry Andric return Error(Loc, "expected identifier in directive"); 40250b57cec5SDimitry Andric MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName); 40260b57cec5SDimitry Andric 40270b57cec5SDimitry Andric Loc = getLexer().getLoc(); 40280b57cec5SDimitry Andric StringRef GapEndName; 40290b57cec5SDimitry Andric if (parseIdentifier(GapEndName)) 40300b57cec5SDimitry Andric return Error(Loc, "expected identifier in directive"); 40310b57cec5SDimitry Andric MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName); 40320b57cec5SDimitry Andric 40330b57cec5SDimitry Andric Ranges.push_back({GapStartSym, GapEndSym}); 40340b57cec5SDimitry Andric } 40350b57cec5SDimitry Andric 40368bcb0991SDimitry Andric StringRef CVDefRangeTypeStr; 40378bcb0991SDimitry Andric if (parseToken( 40388bcb0991SDimitry Andric AsmToken::Comma, 40398bcb0991SDimitry Andric "expected comma before def_range type in .cv_def_range directive") || 40408bcb0991SDimitry Andric parseIdentifier(CVDefRangeTypeStr)) 40418bcb0991SDimitry Andric return Error(Loc, "expected def_range type in directive"); 40420b57cec5SDimitry Andric 40438bcb0991SDimitry Andric StringMap<CVDefRangeType>::const_iterator CVTypeIt = 40448bcb0991SDimitry Andric CVDefRangeTypeMap.find(CVDefRangeTypeStr); 40458bcb0991SDimitry Andric CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end()) 40468bcb0991SDimitry Andric ? CVDR_DEFRANGE 40478bcb0991SDimitry Andric : CVTypeIt->getValue(); 40488bcb0991SDimitry Andric switch (CVDRType) { 40498bcb0991SDimitry Andric case CVDR_DEFRANGE_REGISTER: { 40508bcb0991SDimitry Andric int64_t DRRegister; 40518bcb0991SDimitry Andric if (parseToken(AsmToken::Comma, "expected comma before register number in " 40528bcb0991SDimitry Andric ".cv_def_range directive") || 40538bcb0991SDimitry Andric parseAbsoluteExpression(DRRegister)) 40548bcb0991SDimitry Andric return Error(Loc, "expected register number"); 40558bcb0991SDimitry Andric 40568bcb0991SDimitry Andric codeview::DefRangeRegisterHeader DRHdr; 40578bcb0991SDimitry Andric DRHdr.Register = DRRegister; 40588bcb0991SDimitry Andric DRHdr.MayHaveNoName = 0; 40595ffd83dbSDimitry Andric getStreamer().emitCVDefRangeDirective(Ranges, DRHdr); 40608bcb0991SDimitry Andric break; 40618bcb0991SDimitry Andric } 40628bcb0991SDimitry Andric case CVDR_DEFRANGE_FRAMEPOINTER_REL: { 40638bcb0991SDimitry Andric int64_t DROffset; 40648bcb0991SDimitry Andric if (parseToken(AsmToken::Comma, 40658bcb0991SDimitry Andric "expected comma before offset in .cv_def_range directive") || 40668bcb0991SDimitry Andric parseAbsoluteExpression(DROffset)) 40678bcb0991SDimitry Andric return Error(Loc, "expected offset value"); 40688bcb0991SDimitry Andric 40698bcb0991SDimitry Andric codeview::DefRangeFramePointerRelHeader DRHdr; 40708bcb0991SDimitry Andric DRHdr.Offset = DROffset; 40715ffd83dbSDimitry Andric getStreamer().emitCVDefRangeDirective(Ranges, DRHdr); 40728bcb0991SDimitry Andric break; 40738bcb0991SDimitry Andric } 40748bcb0991SDimitry Andric case CVDR_DEFRANGE_SUBFIELD_REGISTER: { 40758bcb0991SDimitry Andric int64_t DRRegister; 40768bcb0991SDimitry Andric int64_t DROffsetInParent; 40778bcb0991SDimitry Andric if (parseToken(AsmToken::Comma, "expected comma before register number in " 40788bcb0991SDimitry Andric ".cv_def_range directive") || 40798bcb0991SDimitry Andric parseAbsoluteExpression(DRRegister)) 40808bcb0991SDimitry Andric return Error(Loc, "expected register number"); 40818bcb0991SDimitry Andric if (parseToken(AsmToken::Comma, 40828bcb0991SDimitry Andric "expected comma before offset in .cv_def_range directive") || 40838bcb0991SDimitry Andric parseAbsoluteExpression(DROffsetInParent)) 40848bcb0991SDimitry Andric return Error(Loc, "expected offset value"); 40858bcb0991SDimitry Andric 40868bcb0991SDimitry Andric codeview::DefRangeSubfieldRegisterHeader DRHdr; 40878bcb0991SDimitry Andric DRHdr.Register = DRRegister; 40888bcb0991SDimitry Andric DRHdr.MayHaveNoName = 0; 40898bcb0991SDimitry Andric DRHdr.OffsetInParent = DROffsetInParent; 40905ffd83dbSDimitry Andric getStreamer().emitCVDefRangeDirective(Ranges, DRHdr); 40918bcb0991SDimitry Andric break; 40928bcb0991SDimitry Andric } 40938bcb0991SDimitry Andric case CVDR_DEFRANGE_REGISTER_REL: { 40948bcb0991SDimitry Andric int64_t DRRegister; 40958bcb0991SDimitry Andric int64_t DRFlags; 40968bcb0991SDimitry Andric int64_t DRBasePointerOffset; 40978bcb0991SDimitry Andric if (parseToken(AsmToken::Comma, "expected comma before register number in " 40988bcb0991SDimitry Andric ".cv_def_range directive") || 40998bcb0991SDimitry Andric parseAbsoluteExpression(DRRegister)) 41008bcb0991SDimitry Andric return Error(Loc, "expected register value"); 41018bcb0991SDimitry Andric if (parseToken( 41028bcb0991SDimitry Andric AsmToken::Comma, 41038bcb0991SDimitry Andric "expected comma before flag value in .cv_def_range directive") || 41048bcb0991SDimitry Andric parseAbsoluteExpression(DRFlags)) 41058bcb0991SDimitry Andric return Error(Loc, "expected flag value"); 41068bcb0991SDimitry Andric if (parseToken(AsmToken::Comma, "expected comma before base pointer offset " 41078bcb0991SDimitry Andric "in .cv_def_range directive") || 41088bcb0991SDimitry Andric parseAbsoluteExpression(DRBasePointerOffset)) 41098bcb0991SDimitry Andric return Error(Loc, "expected base pointer offset value"); 41108bcb0991SDimitry Andric 41118bcb0991SDimitry Andric codeview::DefRangeRegisterRelHeader DRHdr; 41128bcb0991SDimitry Andric DRHdr.Register = DRRegister; 41138bcb0991SDimitry Andric DRHdr.Flags = DRFlags; 41148bcb0991SDimitry Andric DRHdr.BasePointerOffset = DRBasePointerOffset; 41155ffd83dbSDimitry Andric getStreamer().emitCVDefRangeDirective(Ranges, DRHdr); 41168bcb0991SDimitry Andric break; 41178bcb0991SDimitry Andric } 41188bcb0991SDimitry Andric default: 41198bcb0991SDimitry Andric return Error(Loc, "unexpected def_range type in .cv_def_range directive"); 41208bcb0991SDimitry Andric } 41218bcb0991SDimitry Andric return true; 41220b57cec5SDimitry Andric } 41230b57cec5SDimitry Andric 41240b57cec5SDimitry Andric /// parseDirectiveCVString 41250b57cec5SDimitry Andric /// ::= .cv_stringtable "string" 41260b57cec5SDimitry Andric bool AsmParser::parseDirectiveCVString() { 41270b57cec5SDimitry Andric std::string Data; 41280b57cec5SDimitry Andric if (checkForValidSection() || parseEscapedString(Data)) 4129fe6060f1SDimitry Andric return true; 41300b57cec5SDimitry Andric 41310b57cec5SDimitry Andric // Put the string in the table and emit the offset. 41320b57cec5SDimitry Andric std::pair<StringRef, unsigned> Insertion = 41330b57cec5SDimitry Andric getCVContext().addToStringTable(Data); 41345ffd83dbSDimitry Andric getStreamer().emitInt32(Insertion.second); 41350b57cec5SDimitry Andric return false; 41360b57cec5SDimitry Andric } 41370b57cec5SDimitry Andric 41380b57cec5SDimitry Andric /// parseDirectiveCVStringTable 41390b57cec5SDimitry Andric /// ::= .cv_stringtable 41400b57cec5SDimitry Andric bool AsmParser::parseDirectiveCVStringTable() { 41415ffd83dbSDimitry Andric getStreamer().emitCVStringTableDirective(); 41420b57cec5SDimitry Andric return false; 41430b57cec5SDimitry Andric } 41440b57cec5SDimitry Andric 41450b57cec5SDimitry Andric /// parseDirectiveCVFileChecksums 41460b57cec5SDimitry Andric /// ::= .cv_filechecksums 41470b57cec5SDimitry Andric bool AsmParser::parseDirectiveCVFileChecksums() { 41485ffd83dbSDimitry Andric getStreamer().emitCVFileChecksumsDirective(); 41490b57cec5SDimitry Andric return false; 41500b57cec5SDimitry Andric } 41510b57cec5SDimitry Andric 41520b57cec5SDimitry Andric /// parseDirectiveCVFileChecksumOffset 41530b57cec5SDimitry Andric /// ::= .cv_filechecksumoffset fileno 41540b57cec5SDimitry Andric bool AsmParser::parseDirectiveCVFileChecksumOffset() { 41550b57cec5SDimitry Andric int64_t FileNo; 41560b57cec5SDimitry Andric if (parseIntToken(FileNo, "expected identifier in directive")) 41570b57cec5SDimitry Andric return true; 415881ad6265SDimitry Andric if (parseEOL()) 41590b57cec5SDimitry Andric return true; 41605ffd83dbSDimitry Andric getStreamer().emitCVFileChecksumOffsetDirective(FileNo); 41610b57cec5SDimitry Andric return false; 41620b57cec5SDimitry Andric } 41630b57cec5SDimitry Andric 41640b57cec5SDimitry Andric /// parseDirectiveCVFPOData 41650b57cec5SDimitry Andric /// ::= .cv_fpo_data procsym 41660b57cec5SDimitry Andric bool AsmParser::parseDirectiveCVFPOData() { 41670b57cec5SDimitry Andric SMLoc DirLoc = getLexer().getLoc(); 41680b57cec5SDimitry Andric StringRef ProcName; 41690b57cec5SDimitry Andric if (parseIdentifier(ProcName)) 41700b57cec5SDimitry Andric return TokError("expected symbol name"); 4171fe6060f1SDimitry Andric if (parseEOL()) 4172fe6060f1SDimitry Andric return true; 41730b57cec5SDimitry Andric MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName); 417481ad6265SDimitry Andric getStreamer().emitCVFPOData(ProcSym, DirLoc); 41750b57cec5SDimitry Andric return false; 41760b57cec5SDimitry Andric } 41770b57cec5SDimitry Andric 41780b57cec5SDimitry Andric /// parseDirectiveCFISections 41790b57cec5SDimitry Andric /// ::= .cfi_sections section [, section] 41800b57cec5SDimitry Andric bool AsmParser::parseDirectiveCFISections() { 41810b57cec5SDimitry Andric StringRef Name; 41820b57cec5SDimitry Andric bool EH = false; 41830b57cec5SDimitry Andric bool Debug = false; 41840b57cec5SDimitry Andric 4185fe6060f1SDimitry Andric if (!parseOptionalToken(AsmToken::EndOfStatement)) { 4186fe6060f1SDimitry Andric for (;;) { 41870b57cec5SDimitry Andric if (parseIdentifier(Name)) 4188fe6060f1SDimitry Andric return TokError("expected .eh_frame or .debug_frame"); 41890b57cec5SDimitry Andric if (Name == ".eh_frame") 41900b57cec5SDimitry Andric EH = true; 41910b57cec5SDimitry Andric else if (Name == ".debug_frame") 41920b57cec5SDimitry Andric Debug = true; 4193fe6060f1SDimitry Andric if (parseOptionalToken(AsmToken::EndOfStatement)) 4194fe6060f1SDimitry Andric break; 4195fe6060f1SDimitry Andric if (parseComma()) 4196fe6060f1SDimitry Andric return true; 41970b57cec5SDimitry Andric } 4198fe6060f1SDimitry Andric } 41995ffd83dbSDimitry Andric getStreamer().emitCFISections(EH, Debug); 42000b57cec5SDimitry Andric return false; 42010b57cec5SDimitry Andric } 42020b57cec5SDimitry Andric 42030b57cec5SDimitry Andric /// parseDirectiveCFIStartProc 42040b57cec5SDimitry Andric /// ::= .cfi_startproc [simple] 42050b57cec5SDimitry Andric bool AsmParser::parseDirectiveCFIStartProc() { 42065f757f3fSDimitry Andric CFIStartProcLoc = StartTokLoc; 42075f757f3fSDimitry Andric 42080b57cec5SDimitry Andric StringRef Simple; 42090b57cec5SDimitry Andric if (!parseOptionalToken(AsmToken::EndOfStatement)) { 42100b57cec5SDimitry Andric if (check(parseIdentifier(Simple) || Simple != "simple", 42110b57cec5SDimitry Andric "unexpected token") || 4212fe6060f1SDimitry Andric parseEOL()) 4213fe6060f1SDimitry Andric return true; 42140b57cec5SDimitry Andric } 42150b57cec5SDimitry Andric 42160b57cec5SDimitry Andric // TODO(kristina): Deal with a corner case of incorrect diagnostic context 42170b57cec5SDimitry Andric // being produced if this directive is emitted as part of preprocessor macro 42180b57cec5SDimitry Andric // expansion which can *ONLY* happen if Clang's cc1as is the API consumer. 42190b57cec5SDimitry Andric // Tools like llvm-mc on the other hand are not affected by it, and report 42200b57cec5SDimitry Andric // correct context information. 42215ffd83dbSDimitry Andric getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc()); 42220b57cec5SDimitry Andric return false; 42230b57cec5SDimitry Andric } 42240b57cec5SDimitry Andric 42250b57cec5SDimitry Andric /// parseDirectiveCFIEndProc 42260b57cec5SDimitry Andric /// ::= .cfi_endproc 42270b57cec5SDimitry Andric bool AsmParser::parseDirectiveCFIEndProc() { 42285f757f3fSDimitry Andric CFIStartProcLoc = std::nullopt; 42295f757f3fSDimitry Andric 4230fe6060f1SDimitry Andric if (parseEOL()) 4231fe6060f1SDimitry Andric return true; 42325f757f3fSDimitry Andric 42335ffd83dbSDimitry Andric getStreamer().emitCFIEndProc(); 42340b57cec5SDimitry Andric return false; 42350b57cec5SDimitry Andric } 42360b57cec5SDimitry Andric 42370b57cec5SDimitry Andric /// parse register name or number. 42380b57cec5SDimitry Andric bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register, 42390b57cec5SDimitry Andric SMLoc DirectiveLoc) { 4240bdd1243dSDimitry Andric MCRegister RegNo; 42410b57cec5SDimitry Andric 42420b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::Integer)) { 4243bdd1243dSDimitry Andric if (getTargetParser().parseRegister(RegNo, DirectiveLoc, DirectiveLoc)) 42440b57cec5SDimitry Andric return true; 42450b57cec5SDimitry Andric Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true); 42460b57cec5SDimitry Andric } else 42470b57cec5SDimitry Andric return parseAbsoluteExpression(Register); 42480b57cec5SDimitry Andric 42490b57cec5SDimitry Andric return false; 42500b57cec5SDimitry Andric } 42510b57cec5SDimitry Andric 42520b57cec5SDimitry Andric /// parseDirectiveCFIDefCfa 42530b57cec5SDimitry Andric /// ::= .cfi_def_cfa register, offset 42540b57cec5SDimitry Andric bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) { 42550b57cec5SDimitry Andric int64_t Register = 0, Offset = 0; 4256fe6060f1SDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() || 4257fe6060f1SDimitry Andric parseAbsoluteExpression(Offset) || parseEOL()) 42580b57cec5SDimitry Andric return true; 42590b57cec5SDimitry Andric 426006c3fb27SDimitry Andric getStreamer().emitCFIDefCfa(Register, Offset, DirectiveLoc); 42610b57cec5SDimitry Andric return false; 42620b57cec5SDimitry Andric } 42630b57cec5SDimitry Andric 42640b57cec5SDimitry Andric /// parseDirectiveCFIDefCfaOffset 42650b57cec5SDimitry Andric /// ::= .cfi_def_cfa_offset offset 426606c3fb27SDimitry Andric bool AsmParser::parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc) { 42670b57cec5SDimitry Andric int64_t Offset = 0; 4268fe6060f1SDimitry Andric if (parseAbsoluteExpression(Offset) || parseEOL()) 42690b57cec5SDimitry Andric return true; 42700b57cec5SDimitry Andric 427106c3fb27SDimitry Andric getStreamer().emitCFIDefCfaOffset(Offset, DirectiveLoc); 42720b57cec5SDimitry Andric return false; 42730b57cec5SDimitry Andric } 42740b57cec5SDimitry Andric 42750b57cec5SDimitry Andric /// parseDirectiveCFIRegister 42760b57cec5SDimitry Andric /// ::= .cfi_register register, register 42770b57cec5SDimitry Andric bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) { 42780b57cec5SDimitry Andric int64_t Register1 = 0, Register2 = 0; 4279fe6060f1SDimitry Andric if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || parseComma() || 4280fe6060f1SDimitry Andric parseRegisterOrRegisterNumber(Register2, DirectiveLoc) || parseEOL()) 42810b57cec5SDimitry Andric return true; 42820b57cec5SDimitry Andric 428306c3fb27SDimitry Andric getStreamer().emitCFIRegister(Register1, Register2, DirectiveLoc); 42840b57cec5SDimitry Andric return false; 42850b57cec5SDimitry Andric } 42860b57cec5SDimitry Andric 42870b57cec5SDimitry Andric /// parseDirectiveCFIWindowSave 42880b57cec5SDimitry Andric /// ::= .cfi_window_save 428906c3fb27SDimitry Andric bool AsmParser::parseDirectiveCFIWindowSave(SMLoc DirectiveLoc) { 4290fe6060f1SDimitry Andric if (parseEOL()) 4291fe6060f1SDimitry Andric return true; 429206c3fb27SDimitry Andric getStreamer().emitCFIWindowSave(DirectiveLoc); 42930b57cec5SDimitry Andric return false; 42940b57cec5SDimitry Andric } 42950b57cec5SDimitry Andric 42960b57cec5SDimitry Andric /// parseDirectiveCFIAdjustCfaOffset 42970b57cec5SDimitry Andric /// ::= .cfi_adjust_cfa_offset adjustment 429806c3fb27SDimitry Andric bool AsmParser::parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc) { 42990b57cec5SDimitry Andric int64_t Adjustment = 0; 4300fe6060f1SDimitry Andric if (parseAbsoluteExpression(Adjustment) || parseEOL()) 43010b57cec5SDimitry Andric return true; 43020b57cec5SDimitry Andric 430306c3fb27SDimitry Andric getStreamer().emitCFIAdjustCfaOffset(Adjustment, DirectiveLoc); 43040b57cec5SDimitry Andric return false; 43050b57cec5SDimitry Andric } 43060b57cec5SDimitry Andric 43070b57cec5SDimitry Andric /// parseDirectiveCFIDefCfaRegister 43080b57cec5SDimitry Andric /// ::= .cfi_def_cfa_register register 43090b57cec5SDimitry Andric bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) { 43100b57cec5SDimitry Andric int64_t Register = 0; 4311fe6060f1SDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL()) 43120b57cec5SDimitry Andric return true; 43130b57cec5SDimitry Andric 431406c3fb27SDimitry Andric getStreamer().emitCFIDefCfaRegister(Register, DirectiveLoc); 43150b57cec5SDimitry Andric return false; 43160b57cec5SDimitry Andric } 43170b57cec5SDimitry Andric 4318fe6060f1SDimitry Andric /// parseDirectiveCFILLVMDefAspaceCfa 4319fe6060f1SDimitry Andric /// ::= .cfi_llvm_def_aspace_cfa register, offset, address_space 4320fe6060f1SDimitry Andric bool AsmParser::parseDirectiveCFILLVMDefAspaceCfa(SMLoc DirectiveLoc) { 4321fe6060f1SDimitry Andric int64_t Register = 0, Offset = 0, AddressSpace = 0; 4322fe6060f1SDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() || 4323fe6060f1SDimitry Andric parseAbsoluteExpression(Offset) || parseComma() || 4324fe6060f1SDimitry Andric parseAbsoluteExpression(AddressSpace) || parseEOL()) 4325fe6060f1SDimitry Andric return true; 4326fe6060f1SDimitry Andric 432706c3fb27SDimitry Andric getStreamer().emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace, 432806c3fb27SDimitry Andric DirectiveLoc); 4329fe6060f1SDimitry Andric return false; 4330fe6060f1SDimitry Andric } 4331fe6060f1SDimitry Andric 43320b57cec5SDimitry Andric /// parseDirectiveCFIOffset 43330b57cec5SDimitry Andric /// ::= .cfi_offset register, offset 43340b57cec5SDimitry Andric bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) { 43350b57cec5SDimitry Andric int64_t Register = 0; 43360b57cec5SDimitry Andric int64_t Offset = 0; 43370b57cec5SDimitry Andric 4338fe6060f1SDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() || 4339fe6060f1SDimitry Andric parseAbsoluteExpression(Offset) || parseEOL()) 43400b57cec5SDimitry Andric return true; 43410b57cec5SDimitry Andric 434206c3fb27SDimitry Andric getStreamer().emitCFIOffset(Register, Offset, DirectiveLoc); 43430b57cec5SDimitry Andric return false; 43440b57cec5SDimitry Andric } 43450b57cec5SDimitry Andric 43460b57cec5SDimitry Andric /// parseDirectiveCFIRelOffset 43470b57cec5SDimitry Andric /// ::= .cfi_rel_offset register, offset 43480b57cec5SDimitry Andric bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) { 43490b57cec5SDimitry Andric int64_t Register = 0, Offset = 0; 43500b57cec5SDimitry Andric 4351fe6060f1SDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseComma() || 4352fe6060f1SDimitry Andric parseAbsoluteExpression(Offset) || parseEOL()) 43530b57cec5SDimitry Andric return true; 43540b57cec5SDimitry Andric 435506c3fb27SDimitry Andric getStreamer().emitCFIRelOffset(Register, Offset, DirectiveLoc); 43560b57cec5SDimitry Andric return false; 43570b57cec5SDimitry Andric } 43580b57cec5SDimitry Andric 43590b57cec5SDimitry Andric static bool isValidEncoding(int64_t Encoding) { 43600b57cec5SDimitry Andric if (Encoding & ~0xff) 43610b57cec5SDimitry Andric return false; 43620b57cec5SDimitry Andric 43630b57cec5SDimitry Andric if (Encoding == dwarf::DW_EH_PE_omit) 43640b57cec5SDimitry Andric return true; 43650b57cec5SDimitry Andric 43660b57cec5SDimitry Andric const unsigned Format = Encoding & 0xf; 43670b57cec5SDimitry Andric if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 && 43680b57cec5SDimitry Andric Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 && 43690b57cec5SDimitry Andric Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 && 43700b57cec5SDimitry Andric Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed) 43710b57cec5SDimitry Andric return false; 43720b57cec5SDimitry Andric 43730b57cec5SDimitry Andric const unsigned Application = Encoding & 0x70; 43740b57cec5SDimitry Andric if (Application != dwarf::DW_EH_PE_absptr && 43750b57cec5SDimitry Andric Application != dwarf::DW_EH_PE_pcrel) 43760b57cec5SDimitry Andric return false; 43770b57cec5SDimitry Andric 43780b57cec5SDimitry Andric return true; 43790b57cec5SDimitry Andric } 43800b57cec5SDimitry Andric 43810b57cec5SDimitry Andric /// parseDirectiveCFIPersonalityOrLsda 43820b57cec5SDimitry Andric /// IsPersonality true for cfi_personality, false for cfi_lsda 43830b57cec5SDimitry Andric /// ::= .cfi_personality encoding, [symbol_name] 43840b57cec5SDimitry Andric /// ::= .cfi_lsda encoding, [symbol_name] 43850b57cec5SDimitry Andric bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) { 43860b57cec5SDimitry Andric int64_t Encoding = 0; 43870b57cec5SDimitry Andric if (parseAbsoluteExpression(Encoding)) 43880b57cec5SDimitry Andric return true; 43890b57cec5SDimitry Andric if (Encoding == dwarf::DW_EH_PE_omit) 43900b57cec5SDimitry Andric return false; 43910b57cec5SDimitry Andric 43920b57cec5SDimitry Andric StringRef Name; 43930b57cec5SDimitry Andric if (check(!isValidEncoding(Encoding), "unsupported encoding.") || 4394fe6060f1SDimitry Andric parseComma() || 4395fe6060f1SDimitry Andric check(parseIdentifier(Name), "expected identifier in directive") || 4396fe6060f1SDimitry Andric parseEOL()) 43970b57cec5SDimitry Andric return true; 43980b57cec5SDimitry Andric 43990b57cec5SDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 44000b57cec5SDimitry Andric 44010b57cec5SDimitry Andric if (IsPersonality) 44025ffd83dbSDimitry Andric getStreamer().emitCFIPersonality(Sym, Encoding); 44030b57cec5SDimitry Andric else 44045ffd83dbSDimitry Andric getStreamer().emitCFILsda(Sym, Encoding); 44050b57cec5SDimitry Andric return false; 44060b57cec5SDimitry Andric } 44070b57cec5SDimitry Andric 44080b57cec5SDimitry Andric /// parseDirectiveCFIRememberState 44090b57cec5SDimitry Andric /// ::= .cfi_remember_state 441006c3fb27SDimitry Andric bool AsmParser::parseDirectiveCFIRememberState(SMLoc DirectiveLoc) { 4411fe6060f1SDimitry Andric if (parseEOL()) 4412fe6060f1SDimitry Andric return true; 441306c3fb27SDimitry Andric getStreamer().emitCFIRememberState(DirectiveLoc); 44140b57cec5SDimitry Andric return false; 44150b57cec5SDimitry Andric } 44160b57cec5SDimitry Andric 44170b57cec5SDimitry Andric /// parseDirectiveCFIRestoreState 44180b57cec5SDimitry Andric /// ::= .cfi_remember_state 441906c3fb27SDimitry Andric bool AsmParser::parseDirectiveCFIRestoreState(SMLoc DirectiveLoc) { 4420fe6060f1SDimitry Andric if (parseEOL()) 4421fe6060f1SDimitry Andric return true; 442206c3fb27SDimitry Andric getStreamer().emitCFIRestoreState(DirectiveLoc); 44230b57cec5SDimitry Andric return false; 44240b57cec5SDimitry Andric } 44250b57cec5SDimitry Andric 44260b57cec5SDimitry Andric /// parseDirectiveCFISameValue 44270b57cec5SDimitry Andric /// ::= .cfi_same_value register 44280b57cec5SDimitry Andric bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) { 44290b57cec5SDimitry Andric int64_t Register = 0; 44300b57cec5SDimitry Andric 4431fe6060f1SDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL()) 44320b57cec5SDimitry Andric return true; 44330b57cec5SDimitry Andric 443406c3fb27SDimitry Andric getStreamer().emitCFISameValue(Register, DirectiveLoc); 44350b57cec5SDimitry Andric return false; 44360b57cec5SDimitry Andric } 44370b57cec5SDimitry Andric 44380b57cec5SDimitry Andric /// parseDirectiveCFIRestore 44390b57cec5SDimitry Andric /// ::= .cfi_restore register 44400b57cec5SDimitry Andric bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) { 44410b57cec5SDimitry Andric int64_t Register = 0; 4442fe6060f1SDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL()) 44430b57cec5SDimitry Andric return true; 44440b57cec5SDimitry Andric 444506c3fb27SDimitry Andric getStreamer().emitCFIRestore(Register, DirectiveLoc); 44460b57cec5SDimitry Andric return false; 44470b57cec5SDimitry Andric } 44480b57cec5SDimitry Andric 44490b57cec5SDimitry Andric /// parseDirectiveCFIEscape 44500b57cec5SDimitry Andric /// ::= .cfi_escape expression[,...] 445106c3fb27SDimitry Andric bool AsmParser::parseDirectiveCFIEscape(SMLoc DirectiveLoc) { 44520b57cec5SDimitry Andric std::string Values; 44530b57cec5SDimitry Andric int64_t CurrValue; 44540b57cec5SDimitry Andric if (parseAbsoluteExpression(CurrValue)) 44550b57cec5SDimitry Andric return true; 44560b57cec5SDimitry Andric 44570b57cec5SDimitry Andric Values.push_back((uint8_t)CurrValue); 44580b57cec5SDimitry Andric 44590b57cec5SDimitry Andric while (getLexer().is(AsmToken::Comma)) { 44600b57cec5SDimitry Andric Lex(); 44610b57cec5SDimitry Andric 44620b57cec5SDimitry Andric if (parseAbsoluteExpression(CurrValue)) 44630b57cec5SDimitry Andric return true; 44640b57cec5SDimitry Andric 44650b57cec5SDimitry Andric Values.push_back((uint8_t)CurrValue); 44660b57cec5SDimitry Andric } 44670b57cec5SDimitry Andric 446806c3fb27SDimitry Andric getStreamer().emitCFIEscape(Values, DirectiveLoc); 44690b57cec5SDimitry Andric return false; 44700b57cec5SDimitry Andric } 44710b57cec5SDimitry Andric 44720b57cec5SDimitry Andric /// parseDirectiveCFIReturnColumn 44730b57cec5SDimitry Andric /// ::= .cfi_return_column register 44740b57cec5SDimitry Andric bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) { 44750b57cec5SDimitry Andric int64_t Register = 0; 4476fe6060f1SDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL()) 44770b57cec5SDimitry Andric return true; 44785ffd83dbSDimitry Andric getStreamer().emitCFIReturnColumn(Register); 44790b57cec5SDimitry Andric return false; 44800b57cec5SDimitry Andric } 44810b57cec5SDimitry Andric 44820b57cec5SDimitry Andric /// parseDirectiveCFISignalFrame 44830b57cec5SDimitry Andric /// ::= .cfi_signal_frame 448406c3fb27SDimitry Andric bool AsmParser::parseDirectiveCFISignalFrame(SMLoc DirectiveLoc) { 4485fe6060f1SDimitry Andric if (parseEOL()) 44860b57cec5SDimitry Andric return true; 44870b57cec5SDimitry Andric 44885ffd83dbSDimitry Andric getStreamer().emitCFISignalFrame(); 44890b57cec5SDimitry Andric return false; 44900b57cec5SDimitry Andric } 44910b57cec5SDimitry Andric 44920b57cec5SDimitry Andric /// parseDirectiveCFIUndefined 44930b57cec5SDimitry Andric /// ::= .cfi_undefined register 44940b57cec5SDimitry Andric bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) { 44950b57cec5SDimitry Andric int64_t Register = 0; 44960b57cec5SDimitry Andric 4497fe6060f1SDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || parseEOL()) 44980b57cec5SDimitry Andric return true; 44990b57cec5SDimitry Andric 450006c3fb27SDimitry Andric getStreamer().emitCFIUndefined(Register, DirectiveLoc); 45010b57cec5SDimitry Andric return false; 45020b57cec5SDimitry Andric } 45030b57cec5SDimitry Andric 4504*0fca6ea1SDimitry Andric /// parseDirectiveCFILabel 4505*0fca6ea1SDimitry Andric /// ::= .cfi_label label 4506*0fca6ea1SDimitry Andric bool AsmParser::parseDirectiveCFILabel(SMLoc Loc) { 4507*0fca6ea1SDimitry Andric StringRef Name; 4508*0fca6ea1SDimitry Andric Loc = Lexer.getLoc(); 4509*0fca6ea1SDimitry Andric if (parseIdentifier(Name)) 4510*0fca6ea1SDimitry Andric return TokError("expected identifier"); 4511*0fca6ea1SDimitry Andric if (parseEOL()) 4512*0fca6ea1SDimitry Andric return true; 4513*0fca6ea1SDimitry Andric getStreamer().emitCFILabelDirective(Loc, Name); 4514*0fca6ea1SDimitry Andric return false; 4515*0fca6ea1SDimitry Andric } 4516*0fca6ea1SDimitry Andric 45170b57cec5SDimitry Andric /// parseDirectiveAltmacro 45180b57cec5SDimitry Andric /// ::= .altmacro 45190b57cec5SDimitry Andric /// ::= .noaltmacro 45200b57cec5SDimitry Andric bool AsmParser::parseDirectiveAltmacro(StringRef Directive) { 4521fe6060f1SDimitry Andric if (parseEOL()) 4522fe6060f1SDimitry Andric return true; 45230b57cec5SDimitry Andric AltMacroMode = (Directive == ".altmacro"); 45240b57cec5SDimitry Andric return false; 45250b57cec5SDimitry Andric } 45260b57cec5SDimitry Andric 45270b57cec5SDimitry Andric /// parseDirectiveMacrosOnOff 45280b57cec5SDimitry Andric /// ::= .macros_on 45290b57cec5SDimitry Andric /// ::= .macros_off 45300b57cec5SDimitry Andric bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) { 4531fe6060f1SDimitry Andric if (parseEOL()) 45320b57cec5SDimitry Andric return true; 45330b57cec5SDimitry Andric setMacrosEnabled(Directive == ".macros_on"); 45340b57cec5SDimitry Andric return false; 45350b57cec5SDimitry Andric } 45360b57cec5SDimitry Andric 45370b57cec5SDimitry Andric /// parseDirectiveMacro 45380b57cec5SDimitry Andric /// ::= .macro name[,] [parameters] 45390b57cec5SDimitry Andric bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { 45400b57cec5SDimitry Andric StringRef Name; 45410b57cec5SDimitry Andric if (parseIdentifier(Name)) 45420b57cec5SDimitry Andric return TokError("expected identifier in '.macro' directive"); 45430b57cec5SDimitry Andric 45440b57cec5SDimitry Andric if (getLexer().is(AsmToken::Comma)) 45450b57cec5SDimitry Andric Lex(); 45460b57cec5SDimitry Andric 45470b57cec5SDimitry Andric MCAsmMacroParameters Parameters; 45480b57cec5SDimitry Andric while (getLexer().isNot(AsmToken::EndOfStatement)) { 45490b57cec5SDimitry Andric 45500b57cec5SDimitry Andric if (!Parameters.empty() && Parameters.back().Vararg) 45515ffd83dbSDimitry Andric return Error(Lexer.getLoc(), "vararg parameter '" + 45525ffd83dbSDimitry Andric Parameters.back().Name + 45535ffd83dbSDimitry Andric "' should be the last parameter"); 45540b57cec5SDimitry Andric 45550b57cec5SDimitry Andric MCAsmMacroParameter Parameter; 45560b57cec5SDimitry Andric if (parseIdentifier(Parameter.Name)) 45570b57cec5SDimitry Andric return TokError("expected identifier in '.macro' directive"); 45580b57cec5SDimitry Andric 45590b57cec5SDimitry Andric // Emit an error if two (or more) named parameters share the same name 45600b57cec5SDimitry Andric for (const MCAsmMacroParameter& CurrParam : Parameters) 4561*0fca6ea1SDimitry Andric if (CurrParam.Name == Parameter.Name) 45620b57cec5SDimitry Andric return TokError("macro '" + Name + "' has multiple parameters" 45630b57cec5SDimitry Andric " named '" + Parameter.Name + "'"); 45640b57cec5SDimitry Andric 45650b57cec5SDimitry Andric if (Lexer.is(AsmToken::Colon)) { 45660b57cec5SDimitry Andric Lex(); // consume ':' 45670b57cec5SDimitry Andric 45680b57cec5SDimitry Andric SMLoc QualLoc; 45690b57cec5SDimitry Andric StringRef Qualifier; 45700b57cec5SDimitry Andric 45710b57cec5SDimitry Andric QualLoc = Lexer.getLoc(); 45720b57cec5SDimitry Andric if (parseIdentifier(Qualifier)) 45730b57cec5SDimitry Andric return Error(QualLoc, "missing parameter qualifier for " 45740b57cec5SDimitry Andric "'" + Parameter.Name + "' in macro '" + Name + "'"); 45750b57cec5SDimitry Andric 45760b57cec5SDimitry Andric if (Qualifier == "req") 45770b57cec5SDimitry Andric Parameter.Required = true; 45780b57cec5SDimitry Andric else if (Qualifier == "vararg") 45790b57cec5SDimitry Andric Parameter.Vararg = true; 45800b57cec5SDimitry Andric else 45810b57cec5SDimitry Andric return Error(QualLoc, Qualifier + " is not a valid parameter qualifier " 45820b57cec5SDimitry Andric "for '" + Parameter.Name + "' in macro '" + Name + "'"); 45830b57cec5SDimitry Andric } 45840b57cec5SDimitry Andric 45850b57cec5SDimitry Andric if (getLexer().is(AsmToken::Equal)) { 45860b57cec5SDimitry Andric Lex(); 45870b57cec5SDimitry Andric 45880b57cec5SDimitry Andric SMLoc ParamLoc; 45890b57cec5SDimitry Andric 45900b57cec5SDimitry Andric ParamLoc = Lexer.getLoc(); 45910b57cec5SDimitry Andric if (parseMacroArgument(Parameter.Value, /*Vararg=*/false )) 45920b57cec5SDimitry Andric return true; 45930b57cec5SDimitry Andric 45940b57cec5SDimitry Andric if (Parameter.Required) 45950b57cec5SDimitry Andric Warning(ParamLoc, "pointless default value for required parameter " 45960b57cec5SDimitry Andric "'" + Parameter.Name + "' in macro '" + Name + "'"); 45970b57cec5SDimitry Andric } 45980b57cec5SDimitry Andric 45990b57cec5SDimitry Andric Parameters.push_back(std::move(Parameter)); 46000b57cec5SDimitry Andric 46010b57cec5SDimitry Andric if (getLexer().is(AsmToken::Comma)) 46020b57cec5SDimitry Andric Lex(); 46030b57cec5SDimitry Andric } 46040b57cec5SDimitry Andric 46050b57cec5SDimitry Andric // Eat just the end of statement. 46060b57cec5SDimitry Andric Lexer.Lex(); 46070b57cec5SDimitry Andric 46080b57cec5SDimitry Andric // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors 46090b57cec5SDimitry Andric AsmToken EndToken, StartToken = getTok(); 46100b57cec5SDimitry Andric unsigned MacroDepth = 0; 46110b57cec5SDimitry Andric // Lex the macro definition. 46120b57cec5SDimitry Andric while (true) { 46130b57cec5SDimitry Andric // Ignore Lexing errors in macros. 46140b57cec5SDimitry Andric while (Lexer.is(AsmToken::Error)) { 46150b57cec5SDimitry Andric Lexer.Lex(); 46160b57cec5SDimitry Andric } 46170b57cec5SDimitry Andric 46180b57cec5SDimitry Andric // Check whether we have reached the end of the file. 46190b57cec5SDimitry Andric if (getLexer().is(AsmToken::Eof)) 46200b57cec5SDimitry Andric return Error(DirectiveLoc, "no matching '.endmacro' in definition"); 46210b57cec5SDimitry Andric 46225ffd83dbSDimitry Andric // Otherwise, check whether we have reach the .endmacro or the start of a 46235ffd83dbSDimitry Andric // preprocessor line marker. 46240b57cec5SDimitry Andric if (getLexer().is(AsmToken::Identifier)) { 46250b57cec5SDimitry Andric if (getTok().getIdentifier() == ".endm" || 46260b57cec5SDimitry Andric getTok().getIdentifier() == ".endmacro") { 46270b57cec5SDimitry Andric if (MacroDepth == 0) { // Outermost macro. 46280b57cec5SDimitry Andric EndToken = getTok(); 46290b57cec5SDimitry Andric Lexer.Lex(); 46300b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 46310b57cec5SDimitry Andric return TokError("unexpected token in '" + EndToken.getIdentifier() + 46320b57cec5SDimitry Andric "' directive"); 46330b57cec5SDimitry Andric break; 46340b57cec5SDimitry Andric } else { 46350b57cec5SDimitry Andric // Otherwise we just found the end of an inner macro. 46360b57cec5SDimitry Andric --MacroDepth; 46370b57cec5SDimitry Andric } 46380b57cec5SDimitry Andric } else if (getTok().getIdentifier() == ".macro") { 46390b57cec5SDimitry Andric // We allow nested macros. Those aren't instantiated until the outermost 46400b57cec5SDimitry Andric // macro is expanded so just ignore them for now. 46410b57cec5SDimitry Andric ++MacroDepth; 46420b57cec5SDimitry Andric } 46435ffd83dbSDimitry Andric } else if (Lexer.is(AsmToken::HashDirective)) { 46445ffd83dbSDimitry Andric (void)parseCppHashLineFilenameComment(getLexer().getLoc()); 46450b57cec5SDimitry Andric } 46460b57cec5SDimitry Andric 46470b57cec5SDimitry Andric // Otherwise, scan til the end of the statement. 46480b57cec5SDimitry Andric eatToEndOfStatement(); 46490b57cec5SDimitry Andric } 46500b57cec5SDimitry Andric 46510b57cec5SDimitry Andric if (getContext().lookupMacro(Name)) { 46520b57cec5SDimitry Andric return Error(DirectiveLoc, "macro '" + Name + "' is already defined"); 46530b57cec5SDimitry Andric } 46540b57cec5SDimitry Andric 46550b57cec5SDimitry Andric const char *BodyStart = StartToken.getLoc().getPointer(); 46560b57cec5SDimitry Andric const char *BodyEnd = EndToken.getLoc().getPointer(); 46570b57cec5SDimitry Andric StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); 46580b57cec5SDimitry Andric checkForBadMacro(DirectiveLoc, Name, Body, Parameters); 46590b57cec5SDimitry Andric MCAsmMacro Macro(Name, Body, std::move(Parameters)); 46600b57cec5SDimitry Andric DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n"; 46610b57cec5SDimitry Andric Macro.dump()); 46620b57cec5SDimitry Andric getContext().defineMacro(Name, std::move(Macro)); 46630b57cec5SDimitry Andric return false; 46640b57cec5SDimitry Andric } 46650b57cec5SDimitry Andric 46660b57cec5SDimitry Andric /// checkForBadMacro 46670b57cec5SDimitry Andric /// 46680b57cec5SDimitry Andric /// With the support added for named parameters there may be code out there that 46690b57cec5SDimitry Andric /// is transitioning from positional parameters. In versions of gas that did 46700b57cec5SDimitry Andric /// not support named parameters they would be ignored on the macro definition. 46710b57cec5SDimitry Andric /// But to support both styles of parameters this is not possible so if a macro 46720b57cec5SDimitry Andric /// definition has named parameters but does not use them and has what appears 46730b57cec5SDimitry Andric /// to be positional parameters, strings like $1, $2, ... and $n, then issue a 46740b57cec5SDimitry Andric /// warning that the positional parameter found in body which have no effect. 46750b57cec5SDimitry Andric /// Hoping the developer will either remove the named parameters from the macro 46760b57cec5SDimitry Andric /// definition so the positional parameters get used if that was what was 46770b57cec5SDimitry Andric /// intended or change the macro to use the named parameters. It is possible 46780b57cec5SDimitry Andric /// this warning will trigger when the none of the named parameters are used 46790b57cec5SDimitry Andric /// and the strings like $1 are infact to simply to be passed trough unchanged. 46800b57cec5SDimitry Andric void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, 46810b57cec5SDimitry Andric StringRef Body, 46820b57cec5SDimitry Andric ArrayRef<MCAsmMacroParameter> Parameters) { 46830b57cec5SDimitry Andric // If this macro is not defined with named parameters the warning we are 46840b57cec5SDimitry Andric // checking for here doesn't apply. 46850b57cec5SDimitry Andric unsigned NParameters = Parameters.size(); 46860b57cec5SDimitry Andric if (NParameters == 0) 46870b57cec5SDimitry Andric return; 46880b57cec5SDimitry Andric 46890b57cec5SDimitry Andric bool NamedParametersFound = false; 46900b57cec5SDimitry Andric bool PositionalParametersFound = false; 46910b57cec5SDimitry Andric 46920b57cec5SDimitry Andric // Look at the body of the macro for use of both the named parameters and what 46930b57cec5SDimitry Andric // are likely to be positional parameters. This is what expandMacro() is 46940b57cec5SDimitry Andric // doing when it finds the parameters in the body. 46950b57cec5SDimitry Andric while (!Body.empty()) { 46960b57cec5SDimitry Andric // Scan for the next possible parameter. 46970b57cec5SDimitry Andric std::size_t End = Body.size(), Pos = 0; 46980b57cec5SDimitry Andric for (; Pos != End; ++Pos) { 46990b57cec5SDimitry Andric // Check for a substitution or escape. 47000b57cec5SDimitry Andric // This macro is defined with parameters, look for \foo, \bar, etc. 47010b57cec5SDimitry Andric if (Body[Pos] == '\\' && Pos + 1 != End) 47020b57cec5SDimitry Andric break; 47030b57cec5SDimitry Andric 47040b57cec5SDimitry Andric // This macro should have parameters, but look for $0, $1, ..., $n too. 47050b57cec5SDimitry Andric if (Body[Pos] != '$' || Pos + 1 == End) 47060b57cec5SDimitry Andric continue; 47070b57cec5SDimitry Andric char Next = Body[Pos + 1]; 47080b57cec5SDimitry Andric if (Next == '$' || Next == 'n' || 47090b57cec5SDimitry Andric isdigit(static_cast<unsigned char>(Next))) 47100b57cec5SDimitry Andric break; 47110b57cec5SDimitry Andric } 47120b57cec5SDimitry Andric 47130b57cec5SDimitry Andric // Check if we reached the end. 47140b57cec5SDimitry Andric if (Pos == End) 47150b57cec5SDimitry Andric break; 47160b57cec5SDimitry Andric 47170b57cec5SDimitry Andric if (Body[Pos] == '$') { 47180b57cec5SDimitry Andric switch (Body[Pos + 1]) { 47190b57cec5SDimitry Andric // $$ => $ 47200b57cec5SDimitry Andric case '$': 47210b57cec5SDimitry Andric break; 47220b57cec5SDimitry Andric 47230b57cec5SDimitry Andric // $n => number of arguments 47240b57cec5SDimitry Andric case 'n': 47250b57cec5SDimitry Andric PositionalParametersFound = true; 47260b57cec5SDimitry Andric break; 47270b57cec5SDimitry Andric 47280b57cec5SDimitry Andric // $[0-9] => argument 47290b57cec5SDimitry Andric default: { 47300b57cec5SDimitry Andric PositionalParametersFound = true; 47310b57cec5SDimitry Andric break; 47320b57cec5SDimitry Andric } 47330b57cec5SDimitry Andric } 47340b57cec5SDimitry Andric Pos += 2; 47350b57cec5SDimitry Andric } else { 47360b57cec5SDimitry Andric unsigned I = Pos + 1; 47370b57cec5SDimitry Andric while (isIdentifierChar(Body[I]) && I + 1 != End) 47380b57cec5SDimitry Andric ++I; 47390b57cec5SDimitry Andric 47400b57cec5SDimitry Andric const char *Begin = Body.data() + Pos + 1; 47410b57cec5SDimitry Andric StringRef Argument(Begin, I - (Pos + 1)); 47420b57cec5SDimitry Andric unsigned Index = 0; 47430b57cec5SDimitry Andric for (; Index < NParameters; ++Index) 47440b57cec5SDimitry Andric if (Parameters[Index].Name == Argument) 47450b57cec5SDimitry Andric break; 47460b57cec5SDimitry Andric 47470b57cec5SDimitry Andric if (Index == NParameters) { 47480b57cec5SDimitry Andric if (Body[Pos + 1] == '(' && Body[Pos + 2] == ')') 47490b57cec5SDimitry Andric Pos += 3; 47500b57cec5SDimitry Andric else { 47510b57cec5SDimitry Andric Pos = I; 47520b57cec5SDimitry Andric } 47530b57cec5SDimitry Andric } else { 47540b57cec5SDimitry Andric NamedParametersFound = true; 47550b57cec5SDimitry Andric Pos += 1 + Argument.size(); 47560b57cec5SDimitry Andric } 47570b57cec5SDimitry Andric } 47580b57cec5SDimitry Andric // Update the scan point. 47590b57cec5SDimitry Andric Body = Body.substr(Pos); 47600b57cec5SDimitry Andric } 47610b57cec5SDimitry Andric 47620b57cec5SDimitry Andric if (!NamedParametersFound && PositionalParametersFound) 47630b57cec5SDimitry Andric Warning(DirectiveLoc, "macro defined with named parameters which are not " 47640b57cec5SDimitry Andric "used in macro body, possible positional parameter " 47650b57cec5SDimitry Andric "found in body which will have no effect"); 47660b57cec5SDimitry Andric } 47670b57cec5SDimitry Andric 47680b57cec5SDimitry Andric /// parseDirectiveExitMacro 47690b57cec5SDimitry Andric /// ::= .exitm 47700b57cec5SDimitry Andric bool AsmParser::parseDirectiveExitMacro(StringRef Directive) { 4771fe6060f1SDimitry Andric if (parseEOL()) 47720b57cec5SDimitry Andric return true; 47730b57cec5SDimitry Andric 47740b57cec5SDimitry Andric if (!isInsideMacroInstantiation()) 47750b57cec5SDimitry Andric return TokError("unexpected '" + Directive + "' in file, " 47760b57cec5SDimitry Andric "no current macro definition"); 47770b57cec5SDimitry Andric 47780b57cec5SDimitry Andric // Exit all conditionals that are active in the current macro. 47790b57cec5SDimitry Andric while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) { 47800b57cec5SDimitry Andric TheCondState = TheCondStack.back(); 47810b57cec5SDimitry Andric TheCondStack.pop_back(); 47820b57cec5SDimitry Andric } 47830b57cec5SDimitry Andric 47840b57cec5SDimitry Andric handleMacroExit(); 47850b57cec5SDimitry Andric return false; 47860b57cec5SDimitry Andric } 47870b57cec5SDimitry Andric 47880b57cec5SDimitry Andric /// parseDirectiveEndMacro 47890b57cec5SDimitry Andric /// ::= .endm 47900b57cec5SDimitry Andric /// ::= .endmacro 47910b57cec5SDimitry Andric bool AsmParser::parseDirectiveEndMacro(StringRef Directive) { 47920b57cec5SDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 47930b57cec5SDimitry Andric return TokError("unexpected token in '" + Directive + "' directive"); 47940b57cec5SDimitry Andric 47950b57cec5SDimitry Andric // If we are inside a macro instantiation, terminate the current 47960b57cec5SDimitry Andric // instantiation. 47970b57cec5SDimitry Andric if (isInsideMacroInstantiation()) { 47980b57cec5SDimitry Andric handleMacroExit(); 47990b57cec5SDimitry Andric return false; 48000b57cec5SDimitry Andric } 48010b57cec5SDimitry Andric 48020b57cec5SDimitry Andric // Otherwise, this .endmacro is a stray entry in the file; well formed 48030b57cec5SDimitry Andric // .endmacro directives are handled during the macro definition parsing. 48040b57cec5SDimitry Andric return TokError("unexpected '" + Directive + "' in file, " 48050b57cec5SDimitry Andric "no current macro definition"); 48060b57cec5SDimitry Andric } 48070b57cec5SDimitry Andric 48080b57cec5SDimitry Andric /// parseDirectivePurgeMacro 4809fe6060f1SDimitry Andric /// ::= .purgem name 48100b57cec5SDimitry Andric bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) { 48110b57cec5SDimitry Andric StringRef Name; 48120b57cec5SDimitry Andric SMLoc Loc; 48130b57cec5SDimitry Andric if (parseTokenLoc(Loc) || 48140b57cec5SDimitry Andric check(parseIdentifier(Name), Loc, 48150b57cec5SDimitry Andric "expected identifier in '.purgem' directive") || 4816fe6060f1SDimitry Andric parseEOL()) 48170b57cec5SDimitry Andric return true; 48180b57cec5SDimitry Andric 48190b57cec5SDimitry Andric if (!getContext().lookupMacro(Name)) 48200b57cec5SDimitry Andric return Error(DirectiveLoc, "macro '" + Name + "' is not defined"); 48210b57cec5SDimitry Andric 48220b57cec5SDimitry Andric getContext().undefineMacro(Name); 48230b57cec5SDimitry Andric DEBUG_WITH_TYPE("asm-macros", dbgs() 48240b57cec5SDimitry Andric << "Un-defining macro: " << Name << "\n"); 48250b57cec5SDimitry Andric return false; 48260b57cec5SDimitry Andric } 48270b57cec5SDimitry Andric 48280b57cec5SDimitry Andric /// parseDirectiveBundleAlignMode 48290b57cec5SDimitry Andric /// ::= {.bundle_align_mode} expression 48300b57cec5SDimitry Andric bool AsmParser::parseDirectiveBundleAlignMode() { 48310b57cec5SDimitry Andric // Expect a single argument: an expression that evaluates to a constant 48320b57cec5SDimitry Andric // in the inclusive range 0-30. 48330b57cec5SDimitry Andric SMLoc ExprLoc = getLexer().getLoc(); 48340b57cec5SDimitry Andric int64_t AlignSizePow2; 48350b57cec5SDimitry Andric if (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) || 4836fe6060f1SDimitry Andric parseEOL() || 48370b57cec5SDimitry Andric check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc, 48380b57cec5SDimitry Andric "invalid bundle alignment size (expected between 0 and 30)")) 48390b57cec5SDimitry Andric return true; 48400b57cec5SDimitry Andric 4841bdd1243dSDimitry Andric getStreamer().emitBundleAlignMode(Align(1ULL << AlignSizePow2)); 48420b57cec5SDimitry Andric return false; 48430b57cec5SDimitry Andric } 48440b57cec5SDimitry Andric 48450b57cec5SDimitry Andric /// parseDirectiveBundleLock 48460b57cec5SDimitry Andric /// ::= {.bundle_lock} [align_to_end] 48470b57cec5SDimitry Andric bool AsmParser::parseDirectiveBundleLock() { 48480b57cec5SDimitry Andric if (checkForValidSection()) 48490b57cec5SDimitry Andric return true; 48500b57cec5SDimitry Andric bool AlignToEnd = false; 48510b57cec5SDimitry Andric 48520b57cec5SDimitry Andric StringRef Option; 48530b57cec5SDimitry Andric SMLoc Loc = getTok().getLoc(); 48540b57cec5SDimitry Andric const char *kInvalidOptionError = 48550b57cec5SDimitry Andric "invalid option for '.bundle_lock' directive"; 48560b57cec5SDimitry Andric 48570b57cec5SDimitry Andric if (!parseOptionalToken(AsmToken::EndOfStatement)) { 48580b57cec5SDimitry Andric if (check(parseIdentifier(Option), Loc, kInvalidOptionError) || 4859fe6060f1SDimitry Andric check(Option != "align_to_end", Loc, kInvalidOptionError) || parseEOL()) 48600b57cec5SDimitry Andric return true; 48610b57cec5SDimitry Andric AlignToEnd = true; 48620b57cec5SDimitry Andric } 48630b57cec5SDimitry Andric 48645ffd83dbSDimitry Andric getStreamer().emitBundleLock(AlignToEnd); 48650b57cec5SDimitry Andric return false; 48660b57cec5SDimitry Andric } 48670b57cec5SDimitry Andric 48680b57cec5SDimitry Andric /// parseDirectiveBundleLock 48690b57cec5SDimitry Andric /// ::= {.bundle_lock} 48700b57cec5SDimitry Andric bool AsmParser::parseDirectiveBundleUnlock() { 4871fe6060f1SDimitry Andric if (checkForValidSection() || parseEOL()) 48720b57cec5SDimitry Andric return true; 48730b57cec5SDimitry Andric 48745ffd83dbSDimitry Andric getStreamer().emitBundleUnlock(); 48750b57cec5SDimitry Andric return false; 48760b57cec5SDimitry Andric } 48770b57cec5SDimitry Andric 48780b57cec5SDimitry Andric /// parseDirectiveSpace 48790b57cec5SDimitry Andric /// ::= (.skip | .space) expression [ , expression ] 48800b57cec5SDimitry Andric bool AsmParser::parseDirectiveSpace(StringRef IDVal) { 48810b57cec5SDimitry Andric SMLoc NumBytesLoc = Lexer.getLoc(); 48820b57cec5SDimitry Andric const MCExpr *NumBytes; 48830b57cec5SDimitry Andric if (checkForValidSection() || parseExpression(NumBytes)) 48840b57cec5SDimitry Andric return true; 48850b57cec5SDimitry Andric 48860b57cec5SDimitry Andric int64_t FillExpr = 0; 48870b57cec5SDimitry Andric if (parseOptionalToken(AsmToken::Comma)) 48880b57cec5SDimitry Andric if (parseAbsoluteExpression(FillExpr)) 4889fe6060f1SDimitry Andric return true; 4890fe6060f1SDimitry Andric if (parseEOL()) 4891fe6060f1SDimitry Andric return true; 48920b57cec5SDimitry Andric 48930b57cec5SDimitry Andric // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0. 48940b57cec5SDimitry Andric getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc); 48950b57cec5SDimitry Andric 48960b57cec5SDimitry Andric return false; 48970b57cec5SDimitry Andric } 48980b57cec5SDimitry Andric 48990b57cec5SDimitry Andric /// parseDirectiveDCB 49000b57cec5SDimitry Andric /// ::= .dcb.{b, l, w} expression, expression 49010b57cec5SDimitry Andric bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) { 49020b57cec5SDimitry Andric SMLoc NumValuesLoc = Lexer.getLoc(); 49030b57cec5SDimitry Andric int64_t NumValues; 49040b57cec5SDimitry Andric if (checkForValidSection() || parseAbsoluteExpression(NumValues)) 49050b57cec5SDimitry Andric return true; 49060b57cec5SDimitry Andric 49070b57cec5SDimitry Andric if (NumValues < 0) { 49080b57cec5SDimitry Andric Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect"); 49090b57cec5SDimitry Andric return false; 49100b57cec5SDimitry Andric } 49110b57cec5SDimitry Andric 4912fe6060f1SDimitry Andric if (parseComma()) 49130b57cec5SDimitry Andric return true; 49140b57cec5SDimitry Andric 49150b57cec5SDimitry Andric const MCExpr *Value; 49160b57cec5SDimitry Andric SMLoc ExprLoc = getLexer().getLoc(); 49170b57cec5SDimitry Andric if (parseExpression(Value)) 49180b57cec5SDimitry Andric return true; 49190b57cec5SDimitry Andric 49200b57cec5SDimitry Andric // Special case constant expressions to match code generator. 49210b57cec5SDimitry Andric if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { 49220b57cec5SDimitry Andric assert(Size <= 8 && "Invalid size"); 49230b57cec5SDimitry Andric uint64_t IntValue = MCE->getValue(); 49240b57cec5SDimitry Andric if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue)) 49250b57cec5SDimitry Andric return Error(ExprLoc, "literal value out of range for directive"); 49260b57cec5SDimitry Andric for (uint64_t i = 0, e = NumValues; i != e; ++i) 49275ffd83dbSDimitry Andric getStreamer().emitIntValue(IntValue, Size); 49280b57cec5SDimitry Andric } else { 49290b57cec5SDimitry Andric for (uint64_t i = 0, e = NumValues; i != e; ++i) 49305ffd83dbSDimitry Andric getStreamer().emitValue(Value, Size, ExprLoc); 49310b57cec5SDimitry Andric } 49320b57cec5SDimitry Andric 4933fe6060f1SDimitry Andric return parseEOL(); 49340b57cec5SDimitry Andric } 49350b57cec5SDimitry Andric 49360b57cec5SDimitry Andric /// parseDirectiveRealDCB 49370b57cec5SDimitry Andric /// ::= .dcb.{d, s} expression, expression 49380b57cec5SDimitry Andric bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) { 49390b57cec5SDimitry Andric SMLoc NumValuesLoc = Lexer.getLoc(); 49400b57cec5SDimitry Andric int64_t NumValues; 49410b57cec5SDimitry Andric if (checkForValidSection() || parseAbsoluteExpression(NumValues)) 49420b57cec5SDimitry Andric return true; 49430b57cec5SDimitry Andric 49440b57cec5SDimitry Andric if (NumValues < 0) { 49450b57cec5SDimitry Andric Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect"); 49460b57cec5SDimitry Andric return false; 49470b57cec5SDimitry Andric } 49480b57cec5SDimitry Andric 4949fe6060f1SDimitry Andric if (parseComma()) 49500b57cec5SDimitry Andric return true; 49510b57cec5SDimitry Andric 49520b57cec5SDimitry Andric APInt AsInt; 4953fe6060f1SDimitry Andric if (parseRealValue(Semantics, AsInt) || parseEOL()) 49540b57cec5SDimitry Andric return true; 49550b57cec5SDimitry Andric 49560b57cec5SDimitry Andric for (uint64_t i = 0, e = NumValues; i != e; ++i) 49575ffd83dbSDimitry Andric getStreamer().emitIntValue(AsInt.getLimitedValue(), 49580b57cec5SDimitry Andric AsInt.getBitWidth() / 8); 49590b57cec5SDimitry Andric 49600b57cec5SDimitry Andric return false; 49610b57cec5SDimitry Andric } 49620b57cec5SDimitry Andric 49630b57cec5SDimitry Andric /// parseDirectiveDS 49640b57cec5SDimitry Andric /// ::= .ds.{b, d, l, p, s, w, x} expression 49650b57cec5SDimitry Andric bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) { 49660b57cec5SDimitry Andric SMLoc NumValuesLoc = Lexer.getLoc(); 49670b57cec5SDimitry Andric int64_t NumValues; 4968fe6060f1SDimitry Andric if (checkForValidSection() || parseAbsoluteExpression(NumValues) || 4969fe6060f1SDimitry Andric parseEOL()) 49700b57cec5SDimitry Andric return true; 49710b57cec5SDimitry Andric 49720b57cec5SDimitry Andric if (NumValues < 0) { 49730b57cec5SDimitry Andric Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect"); 49740b57cec5SDimitry Andric return false; 49750b57cec5SDimitry Andric } 49760b57cec5SDimitry Andric 49770b57cec5SDimitry Andric for (uint64_t i = 0, e = NumValues; i != e; ++i) 49780b57cec5SDimitry Andric getStreamer().emitFill(Size, 0); 49790b57cec5SDimitry Andric 49800b57cec5SDimitry Andric return false; 49810b57cec5SDimitry Andric } 49820b57cec5SDimitry Andric 49830b57cec5SDimitry Andric /// parseDirectiveLEB128 49840b57cec5SDimitry Andric /// ::= (.sleb128 | .uleb128) [ expression (, expression)* ] 49850b57cec5SDimitry Andric bool AsmParser::parseDirectiveLEB128(bool Signed) { 49860b57cec5SDimitry Andric if (checkForValidSection()) 49870b57cec5SDimitry Andric return true; 49880b57cec5SDimitry Andric 49890b57cec5SDimitry Andric auto parseOp = [&]() -> bool { 49900b57cec5SDimitry Andric const MCExpr *Value; 49910b57cec5SDimitry Andric if (parseExpression(Value)) 49920b57cec5SDimitry Andric return true; 49930b57cec5SDimitry Andric if (Signed) 49945ffd83dbSDimitry Andric getStreamer().emitSLEB128Value(Value); 49950b57cec5SDimitry Andric else 49965ffd83dbSDimitry Andric getStreamer().emitULEB128Value(Value); 49970b57cec5SDimitry Andric return false; 49980b57cec5SDimitry Andric }; 49990b57cec5SDimitry Andric 5000fe6060f1SDimitry Andric return parseMany(parseOp); 50010b57cec5SDimitry Andric } 50020b57cec5SDimitry Andric 50030b57cec5SDimitry Andric /// parseDirectiveSymbolAttribute 50040b57cec5SDimitry Andric /// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ] 50050b57cec5SDimitry Andric bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) { 50060b57cec5SDimitry Andric auto parseOp = [&]() -> bool { 50070b57cec5SDimitry Andric StringRef Name; 50080b57cec5SDimitry Andric SMLoc Loc = getTok().getLoc(); 50090b57cec5SDimitry Andric if (parseIdentifier(Name)) 50100b57cec5SDimitry Andric return Error(Loc, "expected identifier"); 5011fe6060f1SDimitry Andric 5012fe6060f1SDimitry Andric if (discardLTOSymbol(Name)) 5013fe6060f1SDimitry Andric return false; 5014fe6060f1SDimitry Andric 50150b57cec5SDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 50160b57cec5SDimitry Andric 5017bdd1243dSDimitry Andric // Assembler local symbols don't make any sense here, except for directives 5018bdd1243dSDimitry Andric // that the symbol should be tagged. 5019bdd1243dSDimitry Andric if (Sym->isTemporary() && Attr != MCSA_Memtag) 50200b57cec5SDimitry Andric return Error(Loc, "non-local symbol required"); 50210b57cec5SDimitry Andric 50225ffd83dbSDimitry Andric if (!getStreamer().emitSymbolAttribute(Sym, Attr)) 50230b57cec5SDimitry Andric return Error(Loc, "unable to emit symbol attribute"); 50240b57cec5SDimitry Andric return false; 50250b57cec5SDimitry Andric }; 50260b57cec5SDimitry Andric 5027fe6060f1SDimitry Andric return parseMany(parseOp); 50280b57cec5SDimitry Andric } 50290b57cec5SDimitry Andric 50300b57cec5SDimitry Andric /// parseDirectiveComm 50310b57cec5SDimitry Andric /// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ] 50320b57cec5SDimitry Andric bool AsmParser::parseDirectiveComm(bool IsLocal) { 50330b57cec5SDimitry Andric if (checkForValidSection()) 50340b57cec5SDimitry Andric return true; 50350b57cec5SDimitry Andric 50360b57cec5SDimitry Andric SMLoc IDLoc = getLexer().getLoc(); 50370b57cec5SDimitry Andric StringRef Name; 50380b57cec5SDimitry Andric if (parseIdentifier(Name)) 50390b57cec5SDimitry Andric return TokError("expected identifier in directive"); 50400b57cec5SDimitry Andric 50410b57cec5SDimitry Andric // Handle the identifier as the key symbol. 50420b57cec5SDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 50430b57cec5SDimitry Andric 5044fe6060f1SDimitry Andric if (parseComma()) 5045fe6060f1SDimitry Andric return true; 50460b57cec5SDimitry Andric 50470b57cec5SDimitry Andric int64_t Size; 50480b57cec5SDimitry Andric SMLoc SizeLoc = getLexer().getLoc(); 50490b57cec5SDimitry Andric if (parseAbsoluteExpression(Size)) 50500b57cec5SDimitry Andric return true; 50510b57cec5SDimitry Andric 50520b57cec5SDimitry Andric int64_t Pow2Alignment = 0; 50530b57cec5SDimitry Andric SMLoc Pow2AlignmentLoc; 50540b57cec5SDimitry Andric if (getLexer().is(AsmToken::Comma)) { 50550b57cec5SDimitry Andric Lex(); 50560b57cec5SDimitry Andric Pow2AlignmentLoc = getLexer().getLoc(); 50570b57cec5SDimitry Andric if (parseAbsoluteExpression(Pow2Alignment)) 50580b57cec5SDimitry Andric return true; 50590b57cec5SDimitry Andric 50600b57cec5SDimitry Andric LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType(); 50610b57cec5SDimitry Andric if (IsLocal && LCOMM == LCOMM::NoAlignment) 50620b57cec5SDimitry Andric return Error(Pow2AlignmentLoc, "alignment not supported on this target"); 50630b57cec5SDimitry Andric 50640b57cec5SDimitry Andric // If this target takes alignments in bytes (not log) validate and convert. 50650b57cec5SDimitry Andric if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) || 50660b57cec5SDimitry Andric (IsLocal && LCOMM == LCOMM::ByteAlignment)) { 50670b57cec5SDimitry Andric if (!isPowerOf2_64(Pow2Alignment)) 50680b57cec5SDimitry Andric return Error(Pow2AlignmentLoc, "alignment must be a power of 2"); 50690b57cec5SDimitry Andric Pow2Alignment = Log2_64(Pow2Alignment); 50700b57cec5SDimitry Andric } 50710b57cec5SDimitry Andric } 50720b57cec5SDimitry Andric 5073fe6060f1SDimitry Andric if (parseEOL()) 50740b57cec5SDimitry Andric return true; 50750b57cec5SDimitry Andric 50760b57cec5SDimitry Andric // NOTE: a size of zero for a .comm should create a undefined symbol 50770b57cec5SDimitry Andric // but a size of .lcomm creates a bss symbol of size zero. 50780b57cec5SDimitry Andric if (Size < 0) 507904eeddc0SDimitry Andric return Error(SizeLoc, "size must be non-negative"); 50800b57cec5SDimitry Andric 50810b57cec5SDimitry Andric Sym->redefineIfPossible(); 50820b57cec5SDimitry Andric if (!Sym->isUndefined()) 50830b57cec5SDimitry Andric return Error(IDLoc, "invalid symbol redefinition"); 50840b57cec5SDimitry Andric 50850b57cec5SDimitry Andric // Create the Symbol as a common or local common with Size and Pow2Alignment 50860b57cec5SDimitry Andric if (IsLocal) { 5087bdd1243dSDimitry Andric getStreamer().emitLocalCommonSymbol(Sym, Size, 5088bdd1243dSDimitry Andric Align(1ULL << Pow2Alignment)); 50890b57cec5SDimitry Andric return false; 50900b57cec5SDimitry Andric } 50910b57cec5SDimitry Andric 5092bdd1243dSDimitry Andric getStreamer().emitCommonSymbol(Sym, Size, Align(1ULL << Pow2Alignment)); 50930b57cec5SDimitry Andric return false; 50940b57cec5SDimitry Andric } 50950b57cec5SDimitry Andric 50960b57cec5SDimitry Andric /// parseDirectiveAbort 50970b57cec5SDimitry Andric /// ::= .abort [... message ...] 5098*0fca6ea1SDimitry Andric bool AsmParser::parseDirectiveAbort(SMLoc DirectiveLoc) { 50990b57cec5SDimitry Andric StringRef Str = parseStringToEndOfStatement(); 5100fe6060f1SDimitry Andric if (parseEOL()) 51010b57cec5SDimitry Andric return true; 51020b57cec5SDimitry Andric 51030b57cec5SDimitry Andric if (Str.empty()) 5104*0fca6ea1SDimitry Andric return Error(DirectiveLoc, ".abort detected. Assembly stopping"); 51050b57cec5SDimitry Andric 5106*0fca6ea1SDimitry Andric // FIXME: Actually abort assembly here. 5107*0fca6ea1SDimitry Andric return Error(DirectiveLoc, 5108*0fca6ea1SDimitry Andric ".abort '" + Str + "' detected. Assembly stopping"); 51090b57cec5SDimitry Andric } 51100b57cec5SDimitry Andric 51110b57cec5SDimitry Andric /// parseDirectiveInclude 51120b57cec5SDimitry Andric /// ::= .include "filename" 51130b57cec5SDimitry Andric bool AsmParser::parseDirectiveInclude() { 51140b57cec5SDimitry Andric // Allow the strings to have escaped octal character sequence. 51150b57cec5SDimitry Andric std::string Filename; 51160b57cec5SDimitry Andric SMLoc IncludeLoc = getTok().getLoc(); 51170b57cec5SDimitry Andric 51180b57cec5SDimitry Andric if (check(getTok().isNot(AsmToken::String), 51190b57cec5SDimitry Andric "expected string in '.include' directive") || 51200b57cec5SDimitry Andric parseEscapedString(Filename) || 51210b57cec5SDimitry Andric check(getTok().isNot(AsmToken::EndOfStatement), 51220b57cec5SDimitry Andric "unexpected token in '.include' directive") || 51230b57cec5SDimitry Andric // Attempt to switch the lexer to the included file before consuming the 51240b57cec5SDimitry Andric // end of statement to avoid losing it when we switch. 51250b57cec5SDimitry Andric check(enterIncludeFile(Filename), IncludeLoc, 51260b57cec5SDimitry Andric "Could not find include file '" + Filename + "'")) 51270b57cec5SDimitry Andric return true; 51280b57cec5SDimitry Andric 51290b57cec5SDimitry Andric return false; 51300b57cec5SDimitry Andric } 51310b57cec5SDimitry Andric 51320b57cec5SDimitry Andric /// parseDirectiveIncbin 51330b57cec5SDimitry Andric /// ::= .incbin "filename" [ , skip [ , count ] ] 51340b57cec5SDimitry Andric bool AsmParser::parseDirectiveIncbin() { 51350b57cec5SDimitry Andric // Allow the strings to have escaped octal character sequence. 51360b57cec5SDimitry Andric std::string Filename; 51370b57cec5SDimitry Andric SMLoc IncbinLoc = getTok().getLoc(); 51380b57cec5SDimitry Andric if (check(getTok().isNot(AsmToken::String), 51390b57cec5SDimitry Andric "expected string in '.incbin' directive") || 51400b57cec5SDimitry Andric parseEscapedString(Filename)) 51410b57cec5SDimitry Andric return true; 51420b57cec5SDimitry Andric 51430b57cec5SDimitry Andric int64_t Skip = 0; 51440b57cec5SDimitry Andric const MCExpr *Count = nullptr; 51450b57cec5SDimitry Andric SMLoc SkipLoc, CountLoc; 51460b57cec5SDimitry Andric if (parseOptionalToken(AsmToken::Comma)) { 51470b57cec5SDimitry Andric // The skip expression can be omitted while specifying the count, e.g: 51480b57cec5SDimitry Andric // .incbin "filename",,4 51490b57cec5SDimitry Andric if (getTok().isNot(AsmToken::Comma)) { 51500b57cec5SDimitry Andric if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip)) 51510b57cec5SDimitry Andric return true; 51520b57cec5SDimitry Andric } 51530b57cec5SDimitry Andric if (parseOptionalToken(AsmToken::Comma)) { 51540b57cec5SDimitry Andric CountLoc = getTok().getLoc(); 51550b57cec5SDimitry Andric if (parseExpression(Count)) 51560b57cec5SDimitry Andric return true; 51570b57cec5SDimitry Andric } 51580b57cec5SDimitry Andric } 51590b57cec5SDimitry Andric 5160fe6060f1SDimitry Andric if (parseEOL()) 51610b57cec5SDimitry Andric return true; 51620b57cec5SDimitry Andric 51630b57cec5SDimitry Andric if (check(Skip < 0, SkipLoc, "skip is negative")) 51640b57cec5SDimitry Andric return true; 51650b57cec5SDimitry Andric 51660b57cec5SDimitry Andric // Attempt to process the included file. 51670b57cec5SDimitry Andric if (processIncbinFile(Filename, Skip, Count, CountLoc)) 51680b57cec5SDimitry Andric return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'"); 51690b57cec5SDimitry Andric return false; 51700b57cec5SDimitry Andric } 51710b57cec5SDimitry Andric 51720b57cec5SDimitry Andric /// parseDirectiveIf 51730b57cec5SDimitry Andric /// ::= .if{,eq,ge,gt,le,lt,ne} expression 51740b57cec5SDimitry Andric bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) { 51750b57cec5SDimitry Andric TheCondStack.push_back(TheCondState); 51760b57cec5SDimitry Andric TheCondState.TheCond = AsmCond::IfCond; 51770b57cec5SDimitry Andric if (TheCondState.Ignore) { 51780b57cec5SDimitry Andric eatToEndOfStatement(); 51790b57cec5SDimitry Andric } else { 51800b57cec5SDimitry Andric int64_t ExprValue; 5181fe6060f1SDimitry Andric if (parseAbsoluteExpression(ExprValue) || parseEOL()) 51820b57cec5SDimitry Andric return true; 51830b57cec5SDimitry Andric 51840b57cec5SDimitry Andric switch (DirKind) { 51850b57cec5SDimitry Andric default: 51860b57cec5SDimitry Andric llvm_unreachable("unsupported directive"); 51870b57cec5SDimitry Andric case DK_IF: 51880b57cec5SDimitry Andric case DK_IFNE: 51890b57cec5SDimitry Andric break; 51900b57cec5SDimitry Andric case DK_IFEQ: 51910b57cec5SDimitry Andric ExprValue = ExprValue == 0; 51920b57cec5SDimitry Andric break; 51930b57cec5SDimitry Andric case DK_IFGE: 51940b57cec5SDimitry Andric ExprValue = ExprValue >= 0; 51950b57cec5SDimitry Andric break; 51960b57cec5SDimitry Andric case DK_IFGT: 51970b57cec5SDimitry Andric ExprValue = ExprValue > 0; 51980b57cec5SDimitry Andric break; 51990b57cec5SDimitry Andric case DK_IFLE: 52000b57cec5SDimitry Andric ExprValue = ExprValue <= 0; 52010b57cec5SDimitry Andric break; 52020b57cec5SDimitry Andric case DK_IFLT: 52030b57cec5SDimitry Andric ExprValue = ExprValue < 0; 52040b57cec5SDimitry Andric break; 52050b57cec5SDimitry Andric } 52060b57cec5SDimitry Andric 52070b57cec5SDimitry Andric TheCondState.CondMet = ExprValue; 52080b57cec5SDimitry Andric TheCondState.Ignore = !TheCondState.CondMet; 52090b57cec5SDimitry Andric } 52100b57cec5SDimitry Andric 52110b57cec5SDimitry Andric return false; 52120b57cec5SDimitry Andric } 52130b57cec5SDimitry Andric 52140b57cec5SDimitry Andric /// parseDirectiveIfb 52150b57cec5SDimitry Andric /// ::= .ifb string 52160b57cec5SDimitry Andric bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { 52170b57cec5SDimitry Andric TheCondStack.push_back(TheCondState); 52180b57cec5SDimitry Andric TheCondState.TheCond = AsmCond::IfCond; 52190b57cec5SDimitry Andric 52200b57cec5SDimitry Andric if (TheCondState.Ignore) { 52210b57cec5SDimitry Andric eatToEndOfStatement(); 52220b57cec5SDimitry Andric } else { 52230b57cec5SDimitry Andric StringRef Str = parseStringToEndOfStatement(); 52240b57cec5SDimitry Andric 5225fe6060f1SDimitry Andric if (parseEOL()) 52260b57cec5SDimitry Andric return true; 52270b57cec5SDimitry Andric 52280b57cec5SDimitry Andric TheCondState.CondMet = ExpectBlank == Str.empty(); 52290b57cec5SDimitry Andric TheCondState.Ignore = !TheCondState.CondMet; 52300b57cec5SDimitry Andric } 52310b57cec5SDimitry Andric 52320b57cec5SDimitry Andric return false; 52330b57cec5SDimitry Andric } 52340b57cec5SDimitry Andric 52350b57cec5SDimitry Andric /// parseDirectiveIfc 52360b57cec5SDimitry Andric /// ::= .ifc string1, string2 52370b57cec5SDimitry Andric /// ::= .ifnc string1, string2 52380b57cec5SDimitry Andric bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { 52390b57cec5SDimitry Andric TheCondStack.push_back(TheCondState); 52400b57cec5SDimitry Andric TheCondState.TheCond = AsmCond::IfCond; 52410b57cec5SDimitry Andric 52420b57cec5SDimitry Andric if (TheCondState.Ignore) { 52430b57cec5SDimitry Andric eatToEndOfStatement(); 52440b57cec5SDimitry Andric } else { 52450b57cec5SDimitry Andric StringRef Str1 = parseStringToComma(); 52460b57cec5SDimitry Andric 5247fe6060f1SDimitry Andric if (parseComma()) 52480b57cec5SDimitry Andric return true; 52490b57cec5SDimitry Andric 52500b57cec5SDimitry Andric StringRef Str2 = parseStringToEndOfStatement(); 52510b57cec5SDimitry Andric 5252fe6060f1SDimitry Andric if (parseEOL()) 52530b57cec5SDimitry Andric return true; 52540b57cec5SDimitry Andric 52550b57cec5SDimitry Andric TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim()); 52560b57cec5SDimitry Andric TheCondState.Ignore = !TheCondState.CondMet; 52570b57cec5SDimitry Andric } 52580b57cec5SDimitry Andric 52590b57cec5SDimitry Andric return false; 52600b57cec5SDimitry Andric } 52610b57cec5SDimitry Andric 52620b57cec5SDimitry Andric /// parseDirectiveIfeqs 52630b57cec5SDimitry Andric /// ::= .ifeqs string1, string2 52640b57cec5SDimitry Andric bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) { 52650b57cec5SDimitry Andric if (Lexer.isNot(AsmToken::String)) { 52660b57cec5SDimitry Andric if (ExpectEqual) 52670b57cec5SDimitry Andric return TokError("expected string parameter for '.ifeqs' directive"); 52680b57cec5SDimitry Andric return TokError("expected string parameter for '.ifnes' directive"); 52690b57cec5SDimitry Andric } 52700b57cec5SDimitry Andric 52710b57cec5SDimitry Andric StringRef String1 = getTok().getStringContents(); 52720b57cec5SDimitry Andric Lex(); 52730b57cec5SDimitry Andric 52740b57cec5SDimitry Andric if (Lexer.isNot(AsmToken::Comma)) { 52750b57cec5SDimitry Andric if (ExpectEqual) 52760b57cec5SDimitry Andric return TokError( 52770b57cec5SDimitry Andric "expected comma after first string for '.ifeqs' directive"); 52780b57cec5SDimitry Andric return TokError("expected comma after first string for '.ifnes' directive"); 52790b57cec5SDimitry Andric } 52800b57cec5SDimitry Andric 52810b57cec5SDimitry Andric Lex(); 52820b57cec5SDimitry Andric 52830b57cec5SDimitry Andric if (Lexer.isNot(AsmToken::String)) { 52840b57cec5SDimitry Andric if (ExpectEqual) 52850b57cec5SDimitry Andric return TokError("expected string parameter for '.ifeqs' directive"); 52860b57cec5SDimitry Andric return TokError("expected string parameter for '.ifnes' directive"); 52870b57cec5SDimitry Andric } 52880b57cec5SDimitry Andric 52890b57cec5SDimitry Andric StringRef String2 = getTok().getStringContents(); 52900b57cec5SDimitry Andric Lex(); 52910b57cec5SDimitry Andric 52920b57cec5SDimitry Andric TheCondStack.push_back(TheCondState); 52930b57cec5SDimitry Andric TheCondState.TheCond = AsmCond::IfCond; 52940b57cec5SDimitry Andric TheCondState.CondMet = ExpectEqual == (String1 == String2); 52950b57cec5SDimitry Andric TheCondState.Ignore = !TheCondState.CondMet; 52960b57cec5SDimitry Andric 52970b57cec5SDimitry Andric return false; 52980b57cec5SDimitry Andric } 52990b57cec5SDimitry Andric 53000b57cec5SDimitry Andric /// parseDirectiveIfdef 53010b57cec5SDimitry Andric /// ::= .ifdef symbol 53020b57cec5SDimitry Andric bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { 53030b57cec5SDimitry Andric StringRef Name; 53040b57cec5SDimitry Andric TheCondStack.push_back(TheCondState); 53050b57cec5SDimitry Andric TheCondState.TheCond = AsmCond::IfCond; 53060b57cec5SDimitry Andric 53070b57cec5SDimitry Andric if (TheCondState.Ignore) { 53080b57cec5SDimitry Andric eatToEndOfStatement(); 53090b57cec5SDimitry Andric } else { 53100b57cec5SDimitry Andric if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") || 5311fe6060f1SDimitry Andric parseEOL()) 53120b57cec5SDimitry Andric return true; 53130b57cec5SDimitry Andric 53140b57cec5SDimitry Andric MCSymbol *Sym = getContext().lookupSymbol(Name); 53150b57cec5SDimitry Andric 53160b57cec5SDimitry Andric if (expect_defined) 53170b57cec5SDimitry Andric TheCondState.CondMet = (Sym && !Sym->isUndefined(false)); 53180b57cec5SDimitry Andric else 53190b57cec5SDimitry Andric TheCondState.CondMet = (!Sym || Sym->isUndefined(false)); 53200b57cec5SDimitry Andric TheCondState.Ignore = !TheCondState.CondMet; 53210b57cec5SDimitry Andric } 53220b57cec5SDimitry Andric 53230b57cec5SDimitry Andric return false; 53240b57cec5SDimitry Andric } 53250b57cec5SDimitry Andric 53260b57cec5SDimitry Andric /// parseDirectiveElseIf 53270b57cec5SDimitry Andric /// ::= .elseif expression 53280b57cec5SDimitry Andric bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) { 53290b57cec5SDimitry Andric if (TheCondState.TheCond != AsmCond::IfCond && 53300b57cec5SDimitry Andric TheCondState.TheCond != AsmCond::ElseIfCond) 53310b57cec5SDimitry Andric return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an" 53320b57cec5SDimitry Andric " .if or an .elseif"); 53330b57cec5SDimitry Andric TheCondState.TheCond = AsmCond::ElseIfCond; 53340b57cec5SDimitry Andric 53350b57cec5SDimitry Andric bool LastIgnoreState = false; 53360b57cec5SDimitry Andric if (!TheCondStack.empty()) 53370b57cec5SDimitry Andric LastIgnoreState = TheCondStack.back().Ignore; 53380b57cec5SDimitry Andric if (LastIgnoreState || TheCondState.CondMet) { 53390b57cec5SDimitry Andric TheCondState.Ignore = true; 53400b57cec5SDimitry Andric eatToEndOfStatement(); 53410b57cec5SDimitry Andric } else { 53420b57cec5SDimitry Andric int64_t ExprValue; 53430b57cec5SDimitry Andric if (parseAbsoluteExpression(ExprValue)) 53440b57cec5SDimitry Andric return true; 53450b57cec5SDimitry Andric 5346fe6060f1SDimitry Andric if (parseEOL()) 53470b57cec5SDimitry Andric return true; 53480b57cec5SDimitry Andric 53490b57cec5SDimitry Andric TheCondState.CondMet = ExprValue; 53500b57cec5SDimitry Andric TheCondState.Ignore = !TheCondState.CondMet; 53510b57cec5SDimitry Andric } 53520b57cec5SDimitry Andric 53530b57cec5SDimitry Andric return false; 53540b57cec5SDimitry Andric } 53550b57cec5SDimitry Andric 53560b57cec5SDimitry Andric /// parseDirectiveElse 53570b57cec5SDimitry Andric /// ::= .else 53580b57cec5SDimitry Andric bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) { 5359fe6060f1SDimitry Andric if (parseEOL()) 53600b57cec5SDimitry Andric return true; 53610b57cec5SDimitry Andric 53620b57cec5SDimitry Andric if (TheCondState.TheCond != AsmCond::IfCond && 53630b57cec5SDimitry Andric TheCondState.TheCond != AsmCond::ElseIfCond) 53640b57cec5SDimitry Andric return Error(DirectiveLoc, "Encountered a .else that doesn't follow " 53650b57cec5SDimitry Andric " an .if or an .elseif"); 53660b57cec5SDimitry Andric TheCondState.TheCond = AsmCond::ElseCond; 53670b57cec5SDimitry Andric bool LastIgnoreState = false; 53680b57cec5SDimitry Andric if (!TheCondStack.empty()) 53690b57cec5SDimitry Andric LastIgnoreState = TheCondStack.back().Ignore; 53700b57cec5SDimitry Andric if (LastIgnoreState || TheCondState.CondMet) 53710b57cec5SDimitry Andric TheCondState.Ignore = true; 53720b57cec5SDimitry Andric else 53730b57cec5SDimitry Andric TheCondState.Ignore = false; 53740b57cec5SDimitry Andric 53750b57cec5SDimitry Andric return false; 53760b57cec5SDimitry Andric } 53770b57cec5SDimitry Andric 53780b57cec5SDimitry Andric /// parseDirectiveEnd 53790b57cec5SDimitry Andric /// ::= .end 53800b57cec5SDimitry Andric bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) { 5381fe6060f1SDimitry Andric if (parseEOL()) 53820b57cec5SDimitry Andric return true; 53830b57cec5SDimitry Andric 53840b57cec5SDimitry Andric while (Lexer.isNot(AsmToken::Eof)) 53850b57cec5SDimitry Andric Lexer.Lex(); 53860b57cec5SDimitry Andric 53870b57cec5SDimitry Andric return false; 53880b57cec5SDimitry Andric } 53890b57cec5SDimitry Andric 53900b57cec5SDimitry Andric /// parseDirectiveError 53910b57cec5SDimitry Andric /// ::= .err 53920b57cec5SDimitry Andric /// ::= .error [string] 53930b57cec5SDimitry Andric bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) { 53940b57cec5SDimitry Andric if (!TheCondStack.empty()) { 53950b57cec5SDimitry Andric if (TheCondStack.back().Ignore) { 53960b57cec5SDimitry Andric eatToEndOfStatement(); 53970b57cec5SDimitry Andric return false; 53980b57cec5SDimitry Andric } 53990b57cec5SDimitry Andric } 54000b57cec5SDimitry Andric 54010b57cec5SDimitry Andric if (!WithMessage) 54020b57cec5SDimitry Andric return Error(L, ".err encountered"); 54030b57cec5SDimitry Andric 54040b57cec5SDimitry Andric StringRef Message = ".error directive invoked in source file"; 54050b57cec5SDimitry Andric if (Lexer.isNot(AsmToken::EndOfStatement)) { 54060b57cec5SDimitry Andric if (Lexer.isNot(AsmToken::String)) 54070b57cec5SDimitry Andric return TokError(".error argument must be a string"); 54080b57cec5SDimitry Andric 54090b57cec5SDimitry Andric Message = getTok().getStringContents(); 54100b57cec5SDimitry Andric Lex(); 54110b57cec5SDimitry Andric } 54120b57cec5SDimitry Andric 54130b57cec5SDimitry Andric return Error(L, Message); 54140b57cec5SDimitry Andric } 54150b57cec5SDimitry Andric 54160b57cec5SDimitry Andric /// parseDirectiveWarning 54170b57cec5SDimitry Andric /// ::= .warning [string] 54180b57cec5SDimitry Andric bool AsmParser::parseDirectiveWarning(SMLoc L) { 54190b57cec5SDimitry Andric if (!TheCondStack.empty()) { 54200b57cec5SDimitry Andric if (TheCondStack.back().Ignore) { 54210b57cec5SDimitry Andric eatToEndOfStatement(); 54220b57cec5SDimitry Andric return false; 54230b57cec5SDimitry Andric } 54240b57cec5SDimitry Andric } 54250b57cec5SDimitry Andric 54260b57cec5SDimitry Andric StringRef Message = ".warning directive invoked in source file"; 54270b57cec5SDimitry Andric 54280b57cec5SDimitry Andric if (!parseOptionalToken(AsmToken::EndOfStatement)) { 54290b57cec5SDimitry Andric if (Lexer.isNot(AsmToken::String)) 54300b57cec5SDimitry Andric return TokError(".warning argument must be a string"); 54310b57cec5SDimitry Andric 54320b57cec5SDimitry Andric Message = getTok().getStringContents(); 54330b57cec5SDimitry Andric Lex(); 5434fe6060f1SDimitry Andric if (parseEOL()) 54350b57cec5SDimitry Andric return true; 54360b57cec5SDimitry Andric } 54370b57cec5SDimitry Andric 54380b57cec5SDimitry Andric return Warning(L, Message); 54390b57cec5SDimitry Andric } 54400b57cec5SDimitry Andric 54410b57cec5SDimitry Andric /// parseDirectiveEndIf 54420b57cec5SDimitry Andric /// ::= .endif 54430b57cec5SDimitry Andric bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) { 5444fe6060f1SDimitry Andric if (parseEOL()) 54450b57cec5SDimitry Andric return true; 54460b57cec5SDimitry Andric 54470b57cec5SDimitry Andric if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty()) 54480b57cec5SDimitry Andric return Error(DirectiveLoc, "Encountered a .endif that doesn't follow " 54490b57cec5SDimitry Andric "an .if or .else"); 54500b57cec5SDimitry Andric if (!TheCondStack.empty()) { 54510b57cec5SDimitry Andric TheCondState = TheCondStack.back(); 54520b57cec5SDimitry Andric TheCondStack.pop_back(); 54530b57cec5SDimitry Andric } 54540b57cec5SDimitry Andric 54550b57cec5SDimitry Andric return false; 54560b57cec5SDimitry Andric } 54570b57cec5SDimitry Andric 54580b57cec5SDimitry Andric void AsmParser::initializeDirectiveKindMap() { 54595ffd83dbSDimitry Andric /* Lookup will be done with the directive 54605ffd83dbSDimitry Andric * converted to lower case, so all these 54615ffd83dbSDimitry Andric * keys should be lower case. 54625ffd83dbSDimitry Andric * (target specific directives are handled 54635ffd83dbSDimitry Andric * elsewhere) 54645ffd83dbSDimitry Andric */ 54650b57cec5SDimitry Andric DirectiveKindMap[".set"] = DK_SET; 54660b57cec5SDimitry Andric DirectiveKindMap[".equ"] = DK_EQU; 54670b57cec5SDimitry Andric DirectiveKindMap[".equiv"] = DK_EQUIV; 54680b57cec5SDimitry Andric DirectiveKindMap[".ascii"] = DK_ASCII; 54690b57cec5SDimitry Andric DirectiveKindMap[".asciz"] = DK_ASCIZ; 54700b57cec5SDimitry Andric DirectiveKindMap[".string"] = DK_STRING; 54710b57cec5SDimitry Andric DirectiveKindMap[".byte"] = DK_BYTE; 54720b57cec5SDimitry Andric DirectiveKindMap[".short"] = DK_SHORT; 54730b57cec5SDimitry Andric DirectiveKindMap[".value"] = DK_VALUE; 54740b57cec5SDimitry Andric DirectiveKindMap[".2byte"] = DK_2BYTE; 54750b57cec5SDimitry Andric DirectiveKindMap[".long"] = DK_LONG; 54760b57cec5SDimitry Andric DirectiveKindMap[".int"] = DK_INT; 54770b57cec5SDimitry Andric DirectiveKindMap[".4byte"] = DK_4BYTE; 54780b57cec5SDimitry Andric DirectiveKindMap[".quad"] = DK_QUAD; 54790b57cec5SDimitry Andric DirectiveKindMap[".8byte"] = DK_8BYTE; 54800b57cec5SDimitry Andric DirectiveKindMap[".octa"] = DK_OCTA; 54810b57cec5SDimitry Andric DirectiveKindMap[".single"] = DK_SINGLE; 54820b57cec5SDimitry Andric DirectiveKindMap[".float"] = DK_FLOAT; 54830b57cec5SDimitry Andric DirectiveKindMap[".double"] = DK_DOUBLE; 54840b57cec5SDimitry Andric DirectiveKindMap[".align"] = DK_ALIGN; 54850b57cec5SDimitry Andric DirectiveKindMap[".align32"] = DK_ALIGN32; 54860b57cec5SDimitry Andric DirectiveKindMap[".balign"] = DK_BALIGN; 54870b57cec5SDimitry Andric DirectiveKindMap[".balignw"] = DK_BALIGNW; 54880b57cec5SDimitry Andric DirectiveKindMap[".balignl"] = DK_BALIGNL; 54890b57cec5SDimitry Andric DirectiveKindMap[".p2align"] = DK_P2ALIGN; 54900b57cec5SDimitry Andric DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW; 54910b57cec5SDimitry Andric DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL; 54920b57cec5SDimitry Andric DirectiveKindMap[".org"] = DK_ORG; 54930b57cec5SDimitry Andric DirectiveKindMap[".fill"] = DK_FILL; 54940b57cec5SDimitry Andric DirectiveKindMap[".zero"] = DK_ZERO; 54950b57cec5SDimitry Andric DirectiveKindMap[".extern"] = DK_EXTERN; 54960b57cec5SDimitry Andric DirectiveKindMap[".globl"] = DK_GLOBL; 54970b57cec5SDimitry Andric DirectiveKindMap[".global"] = DK_GLOBAL; 54980b57cec5SDimitry Andric DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE; 54990b57cec5SDimitry Andric DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP; 55000b57cec5SDimitry Andric DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER; 55010b57cec5SDimitry Andric DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN; 55020b57cec5SDimitry Andric DirectiveKindMap[".reference"] = DK_REFERENCE; 55030b57cec5SDimitry Andric DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION; 55040b57cec5SDimitry Andric DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE; 55050b57cec5SDimitry Andric DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN; 55060b57cec5SDimitry Andric DirectiveKindMap[".cold"] = DK_COLD; 55070b57cec5SDimitry Andric DirectiveKindMap[".comm"] = DK_COMM; 55080b57cec5SDimitry Andric DirectiveKindMap[".common"] = DK_COMMON; 55090b57cec5SDimitry Andric DirectiveKindMap[".lcomm"] = DK_LCOMM; 55100b57cec5SDimitry Andric DirectiveKindMap[".abort"] = DK_ABORT; 55110b57cec5SDimitry Andric DirectiveKindMap[".include"] = DK_INCLUDE; 55120b57cec5SDimitry Andric DirectiveKindMap[".incbin"] = DK_INCBIN; 55130b57cec5SDimitry Andric DirectiveKindMap[".code16"] = DK_CODE16; 55140b57cec5SDimitry Andric DirectiveKindMap[".code16gcc"] = DK_CODE16GCC; 55150b57cec5SDimitry Andric DirectiveKindMap[".rept"] = DK_REPT; 55160b57cec5SDimitry Andric DirectiveKindMap[".rep"] = DK_REPT; 55170b57cec5SDimitry Andric DirectiveKindMap[".irp"] = DK_IRP; 55180b57cec5SDimitry Andric DirectiveKindMap[".irpc"] = DK_IRPC; 55190b57cec5SDimitry Andric DirectiveKindMap[".endr"] = DK_ENDR; 55200b57cec5SDimitry Andric DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE; 55210b57cec5SDimitry Andric DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK; 55220b57cec5SDimitry Andric DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK; 55230b57cec5SDimitry Andric DirectiveKindMap[".if"] = DK_IF; 55240b57cec5SDimitry Andric DirectiveKindMap[".ifeq"] = DK_IFEQ; 55250b57cec5SDimitry Andric DirectiveKindMap[".ifge"] = DK_IFGE; 55260b57cec5SDimitry Andric DirectiveKindMap[".ifgt"] = DK_IFGT; 55270b57cec5SDimitry Andric DirectiveKindMap[".ifle"] = DK_IFLE; 55280b57cec5SDimitry Andric DirectiveKindMap[".iflt"] = DK_IFLT; 55290b57cec5SDimitry Andric DirectiveKindMap[".ifne"] = DK_IFNE; 55300b57cec5SDimitry Andric DirectiveKindMap[".ifb"] = DK_IFB; 55310b57cec5SDimitry Andric DirectiveKindMap[".ifnb"] = DK_IFNB; 55320b57cec5SDimitry Andric DirectiveKindMap[".ifc"] = DK_IFC; 55330b57cec5SDimitry Andric DirectiveKindMap[".ifeqs"] = DK_IFEQS; 55340b57cec5SDimitry Andric DirectiveKindMap[".ifnc"] = DK_IFNC; 55350b57cec5SDimitry Andric DirectiveKindMap[".ifnes"] = DK_IFNES; 55360b57cec5SDimitry Andric DirectiveKindMap[".ifdef"] = DK_IFDEF; 55370b57cec5SDimitry Andric DirectiveKindMap[".ifndef"] = DK_IFNDEF; 55380b57cec5SDimitry Andric DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF; 55390b57cec5SDimitry Andric DirectiveKindMap[".elseif"] = DK_ELSEIF; 55400b57cec5SDimitry Andric DirectiveKindMap[".else"] = DK_ELSE; 55410b57cec5SDimitry Andric DirectiveKindMap[".end"] = DK_END; 55420b57cec5SDimitry Andric DirectiveKindMap[".endif"] = DK_ENDIF; 55430b57cec5SDimitry Andric DirectiveKindMap[".skip"] = DK_SKIP; 55440b57cec5SDimitry Andric DirectiveKindMap[".space"] = DK_SPACE; 55450b57cec5SDimitry Andric DirectiveKindMap[".file"] = DK_FILE; 55460b57cec5SDimitry Andric DirectiveKindMap[".line"] = DK_LINE; 55470b57cec5SDimitry Andric DirectiveKindMap[".loc"] = DK_LOC; 55480b57cec5SDimitry Andric DirectiveKindMap[".stabs"] = DK_STABS; 55490b57cec5SDimitry Andric DirectiveKindMap[".cv_file"] = DK_CV_FILE; 55500b57cec5SDimitry Andric DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID; 55510b57cec5SDimitry Andric DirectiveKindMap[".cv_loc"] = DK_CV_LOC; 55520b57cec5SDimitry Andric DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE; 55530b57cec5SDimitry Andric DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE; 55540b57cec5SDimitry Andric DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID; 55550b57cec5SDimitry Andric DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE; 55560b57cec5SDimitry Andric DirectiveKindMap[".cv_string"] = DK_CV_STRING; 55570b57cec5SDimitry Andric DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE; 55580b57cec5SDimitry Andric DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS; 55590b57cec5SDimitry Andric DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET; 55600b57cec5SDimitry Andric DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA; 55610b57cec5SDimitry Andric DirectiveKindMap[".sleb128"] = DK_SLEB128; 55620b57cec5SDimitry Andric DirectiveKindMap[".uleb128"] = DK_ULEB128; 55630b57cec5SDimitry Andric DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS; 55640b57cec5SDimitry Andric DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC; 55650b57cec5SDimitry Andric DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC; 55660b57cec5SDimitry Andric DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA; 55670b57cec5SDimitry Andric DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET; 55680b57cec5SDimitry Andric DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET; 55690b57cec5SDimitry Andric DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER; 5570fe6060f1SDimitry Andric DirectiveKindMap[".cfi_llvm_def_aspace_cfa"] = DK_CFI_LLVM_DEF_ASPACE_CFA; 55710b57cec5SDimitry Andric DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET; 55720b57cec5SDimitry Andric DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET; 55730b57cec5SDimitry Andric DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY; 55740b57cec5SDimitry Andric DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA; 55750b57cec5SDimitry Andric DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE; 55760b57cec5SDimitry Andric DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE; 55770b57cec5SDimitry Andric DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE; 55780b57cec5SDimitry Andric DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE; 55790b57cec5SDimitry Andric DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE; 55800b57cec5SDimitry Andric DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN; 55810b57cec5SDimitry Andric DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME; 55820b57cec5SDimitry Andric DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED; 55830b57cec5SDimitry Andric DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER; 55840b57cec5SDimitry Andric DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE; 5585*0fca6ea1SDimitry Andric DirectiveKindMap[".cfi_label"] = DK_CFI_LABEL; 55860b57cec5SDimitry Andric DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME; 558781ad6265SDimitry Andric DirectiveKindMap[".cfi_mte_tagged_frame"] = DK_CFI_MTE_TAGGED_FRAME; 55880b57cec5SDimitry Andric DirectiveKindMap[".macros_on"] = DK_MACROS_ON; 55890b57cec5SDimitry Andric DirectiveKindMap[".macros_off"] = DK_MACROS_OFF; 55900b57cec5SDimitry Andric DirectiveKindMap[".macro"] = DK_MACRO; 55910b57cec5SDimitry Andric DirectiveKindMap[".exitm"] = DK_EXITM; 55920b57cec5SDimitry Andric DirectiveKindMap[".endm"] = DK_ENDM; 55930b57cec5SDimitry Andric DirectiveKindMap[".endmacro"] = DK_ENDMACRO; 55940b57cec5SDimitry Andric DirectiveKindMap[".purgem"] = DK_PURGEM; 55950b57cec5SDimitry Andric DirectiveKindMap[".err"] = DK_ERR; 55960b57cec5SDimitry Andric DirectiveKindMap[".error"] = DK_ERROR; 55970b57cec5SDimitry Andric DirectiveKindMap[".warning"] = DK_WARNING; 55980b57cec5SDimitry Andric DirectiveKindMap[".altmacro"] = DK_ALTMACRO; 55990b57cec5SDimitry Andric DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO; 56000b57cec5SDimitry Andric DirectiveKindMap[".reloc"] = DK_RELOC; 56010b57cec5SDimitry Andric DirectiveKindMap[".dc"] = DK_DC; 56020b57cec5SDimitry Andric DirectiveKindMap[".dc.a"] = DK_DC_A; 56030b57cec5SDimitry Andric DirectiveKindMap[".dc.b"] = DK_DC_B; 56040b57cec5SDimitry Andric DirectiveKindMap[".dc.d"] = DK_DC_D; 56050b57cec5SDimitry Andric DirectiveKindMap[".dc.l"] = DK_DC_L; 56060b57cec5SDimitry Andric DirectiveKindMap[".dc.s"] = DK_DC_S; 56070b57cec5SDimitry Andric DirectiveKindMap[".dc.w"] = DK_DC_W; 56080b57cec5SDimitry Andric DirectiveKindMap[".dc.x"] = DK_DC_X; 56090b57cec5SDimitry Andric DirectiveKindMap[".dcb"] = DK_DCB; 56100b57cec5SDimitry Andric DirectiveKindMap[".dcb.b"] = DK_DCB_B; 56110b57cec5SDimitry Andric DirectiveKindMap[".dcb.d"] = DK_DCB_D; 56120b57cec5SDimitry Andric DirectiveKindMap[".dcb.l"] = DK_DCB_L; 56130b57cec5SDimitry Andric DirectiveKindMap[".dcb.s"] = DK_DCB_S; 56140b57cec5SDimitry Andric DirectiveKindMap[".dcb.w"] = DK_DCB_W; 56150b57cec5SDimitry Andric DirectiveKindMap[".dcb.x"] = DK_DCB_X; 56160b57cec5SDimitry Andric DirectiveKindMap[".ds"] = DK_DS; 56170b57cec5SDimitry Andric DirectiveKindMap[".ds.b"] = DK_DS_B; 56180b57cec5SDimitry Andric DirectiveKindMap[".ds.d"] = DK_DS_D; 56190b57cec5SDimitry Andric DirectiveKindMap[".ds.l"] = DK_DS_L; 56200b57cec5SDimitry Andric DirectiveKindMap[".ds.p"] = DK_DS_P; 56210b57cec5SDimitry Andric DirectiveKindMap[".ds.s"] = DK_DS_S; 56220b57cec5SDimitry Andric DirectiveKindMap[".ds.w"] = DK_DS_W; 56230b57cec5SDimitry Andric DirectiveKindMap[".ds.x"] = DK_DS_X; 56240b57cec5SDimitry Andric DirectiveKindMap[".print"] = DK_PRINT; 56250b57cec5SDimitry Andric DirectiveKindMap[".addrsig"] = DK_ADDRSIG; 56260b57cec5SDimitry Andric DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM; 5627e8d8bef9SDimitry Andric DirectiveKindMap[".pseudoprobe"] = DK_PSEUDO_PROBE; 5628fe6060f1SDimitry Andric DirectiveKindMap[".lto_discard"] = DK_LTO_DISCARD; 56290eae32dcSDimitry Andric DirectiveKindMap[".lto_set_conditional"] = DK_LTO_SET_CONDITIONAL; 5630bdd1243dSDimitry Andric DirectiveKindMap[".memtag"] = DK_MEMTAG; 56310b57cec5SDimitry Andric } 56320b57cec5SDimitry Andric 56330b57cec5SDimitry Andric MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { 56340b57cec5SDimitry Andric AsmToken EndToken, StartToken = getTok(); 56350b57cec5SDimitry Andric 56360b57cec5SDimitry Andric unsigned NestLevel = 0; 56370b57cec5SDimitry Andric while (true) { 56380b57cec5SDimitry Andric // Check whether we have reached the end of the file. 56390b57cec5SDimitry Andric if (getLexer().is(AsmToken::Eof)) { 56400b57cec5SDimitry Andric printError(DirectiveLoc, "no matching '.endr' in definition"); 56410b57cec5SDimitry Andric return nullptr; 56420b57cec5SDimitry Andric } 56430b57cec5SDimitry Andric 5644*0fca6ea1SDimitry Andric if (Lexer.is(AsmToken::Identifier)) { 5645*0fca6ea1SDimitry Andric StringRef Ident = getTok().getIdentifier(); 5646*0fca6ea1SDimitry Andric if (Ident == ".rep" || Ident == ".rept" || Ident == ".irp" || 5647*0fca6ea1SDimitry Andric Ident == ".irpc") { 56480b57cec5SDimitry Andric ++NestLevel; 5649*0fca6ea1SDimitry Andric } else if (Ident == ".endr") { 56500b57cec5SDimitry Andric if (NestLevel == 0) { 56510b57cec5SDimitry Andric EndToken = getTok(); 56520b57cec5SDimitry Andric Lex(); 5653*0fca6ea1SDimitry Andric if (Lexer.is(AsmToken::EndOfStatement)) 5654*0fca6ea1SDimitry Andric break; 5655*0fca6ea1SDimitry Andric printError(getTok().getLoc(), "expected newline"); 56560b57cec5SDimitry Andric return nullptr; 56570b57cec5SDimitry Andric } 56580b57cec5SDimitry Andric --NestLevel; 56590b57cec5SDimitry Andric } 5660*0fca6ea1SDimitry Andric } 56610b57cec5SDimitry Andric 56620b57cec5SDimitry Andric // Otherwise, scan till the end of the statement. 56630b57cec5SDimitry Andric eatToEndOfStatement(); 56640b57cec5SDimitry Andric } 56650b57cec5SDimitry Andric 56660b57cec5SDimitry Andric const char *BodyStart = StartToken.getLoc().getPointer(); 56670b57cec5SDimitry Andric const char *BodyEnd = EndToken.getLoc().getPointer(); 56680b57cec5SDimitry Andric StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); 56690b57cec5SDimitry Andric 56700b57cec5SDimitry Andric // We Are Anonymous. 56710b57cec5SDimitry Andric MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters()); 56720b57cec5SDimitry Andric return &MacroLikeBodies.back(); 56730b57cec5SDimitry Andric } 56740b57cec5SDimitry Andric 56750b57cec5SDimitry Andric void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, 56760b57cec5SDimitry Andric raw_svector_ostream &OS) { 56770b57cec5SDimitry Andric OS << ".endr\n"; 56780b57cec5SDimitry Andric 56790b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> Instantiation = 56800b57cec5SDimitry Andric MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>"); 56810b57cec5SDimitry Andric 56820b57cec5SDimitry Andric // Create the macro instantiation object and add to the current macro 56830b57cec5SDimitry Andric // instantiation stack. 5684480093f4SDimitry Andric MacroInstantiation *MI = new MacroInstantiation{ 5685480093f4SDimitry Andric DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()}; 56860b57cec5SDimitry Andric ActiveMacros.push_back(MI); 56870b57cec5SDimitry Andric 56880b57cec5SDimitry Andric // Jump to the macro instantiation and prime the lexer. 56890b57cec5SDimitry Andric CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc()); 56900b57cec5SDimitry Andric Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); 56910b57cec5SDimitry Andric Lex(); 56920b57cec5SDimitry Andric } 56930b57cec5SDimitry Andric 56940b57cec5SDimitry Andric /// parseDirectiveRept 56950b57cec5SDimitry Andric /// ::= .rep | .rept count 56960b57cec5SDimitry Andric bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) { 56970b57cec5SDimitry Andric const MCExpr *CountExpr; 56980b57cec5SDimitry Andric SMLoc CountLoc = getTok().getLoc(); 56990b57cec5SDimitry Andric if (parseExpression(CountExpr)) 57000b57cec5SDimitry Andric return true; 57010b57cec5SDimitry Andric 57020b57cec5SDimitry Andric int64_t Count; 57030b57cec5SDimitry Andric if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) { 57040b57cec5SDimitry Andric return Error(CountLoc, "unexpected token in '" + Dir + "' directive"); 57050b57cec5SDimitry Andric } 57060b57cec5SDimitry Andric 5707fe6060f1SDimitry Andric if (check(Count < 0, CountLoc, "Count is negative") || parseEOL()) 57080b57cec5SDimitry Andric return true; 57090b57cec5SDimitry Andric 57100b57cec5SDimitry Andric // Lex the rept definition. 57110b57cec5SDimitry Andric MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); 57120b57cec5SDimitry Andric if (!M) 57130b57cec5SDimitry Andric return true; 57140b57cec5SDimitry Andric 57150b57cec5SDimitry Andric // Macro instantiation is lexical, unfortunately. We construct a new buffer 57160b57cec5SDimitry Andric // to hold the macro body with substitutions. 57170b57cec5SDimitry Andric SmallString<256> Buf; 57180b57cec5SDimitry Andric raw_svector_ostream OS(Buf); 57190b57cec5SDimitry Andric while (Count--) { 57200b57cec5SDimitry Andric // Note that the AtPseudoVariable is disabled for instantiations of .rep(t). 5721*0fca6ea1SDimitry Andric if (expandMacro(OS, *M, std::nullopt, std::nullopt, false)) 57220b57cec5SDimitry Andric return true; 57230b57cec5SDimitry Andric } 57240b57cec5SDimitry Andric instantiateMacroLikeBody(M, DirectiveLoc, OS); 57250b57cec5SDimitry Andric 57260b57cec5SDimitry Andric return false; 57270b57cec5SDimitry Andric } 57280b57cec5SDimitry Andric 57290b57cec5SDimitry Andric /// parseDirectiveIrp 57300b57cec5SDimitry Andric /// ::= .irp symbol,values 57310b57cec5SDimitry Andric bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) { 57320b57cec5SDimitry Andric MCAsmMacroParameter Parameter; 57330b57cec5SDimitry Andric MCAsmMacroArguments A; 57340b57cec5SDimitry Andric if (check(parseIdentifier(Parameter.Name), 57350b57cec5SDimitry Andric "expected identifier in '.irp' directive") || 5736fe6060f1SDimitry Andric parseComma() || parseMacroArguments(nullptr, A) || parseEOL()) 57370b57cec5SDimitry Andric return true; 57380b57cec5SDimitry Andric 57390b57cec5SDimitry Andric // Lex the irp definition. 57400b57cec5SDimitry Andric MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); 57410b57cec5SDimitry Andric if (!M) 57420b57cec5SDimitry Andric return true; 57430b57cec5SDimitry Andric 57440b57cec5SDimitry Andric // Macro instantiation is lexical, unfortunately. We construct a new buffer 57450b57cec5SDimitry Andric // to hold the macro body with substitutions. 57460b57cec5SDimitry Andric SmallString<256> Buf; 57470b57cec5SDimitry Andric raw_svector_ostream OS(Buf); 57480b57cec5SDimitry Andric 57490b57cec5SDimitry Andric for (const MCAsmMacroArgument &Arg : A) { 57500b57cec5SDimitry Andric // Note that the AtPseudoVariable is enabled for instantiations of .irp. 57510b57cec5SDimitry Andric // This is undocumented, but GAS seems to support it. 5752*0fca6ea1SDimitry Andric if (expandMacro(OS, *M, Parameter, Arg, true)) 57530b57cec5SDimitry Andric return true; 57540b57cec5SDimitry Andric } 57550b57cec5SDimitry Andric 57560b57cec5SDimitry Andric instantiateMacroLikeBody(M, DirectiveLoc, OS); 57570b57cec5SDimitry Andric 57580b57cec5SDimitry Andric return false; 57590b57cec5SDimitry Andric } 57600b57cec5SDimitry Andric 57610b57cec5SDimitry Andric /// parseDirectiveIrpc 57620b57cec5SDimitry Andric /// ::= .irpc symbol,values 57630b57cec5SDimitry Andric bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) { 57640b57cec5SDimitry Andric MCAsmMacroParameter Parameter; 57650b57cec5SDimitry Andric MCAsmMacroArguments A; 57660b57cec5SDimitry Andric 57670b57cec5SDimitry Andric if (check(parseIdentifier(Parameter.Name), 57680b57cec5SDimitry Andric "expected identifier in '.irpc' directive") || 5769fe6060f1SDimitry Andric parseComma() || parseMacroArguments(nullptr, A)) 57700b57cec5SDimitry Andric return true; 57710b57cec5SDimitry Andric 57720b57cec5SDimitry Andric if (A.size() != 1 || A.front().size() != 1) 57730b57cec5SDimitry Andric return TokError("unexpected token in '.irpc' directive"); 5774fe6060f1SDimitry Andric if (parseEOL()) 57750b57cec5SDimitry Andric return true; 57760b57cec5SDimitry Andric 57770b57cec5SDimitry Andric // Lex the irpc definition. 57780b57cec5SDimitry Andric MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); 57790b57cec5SDimitry Andric if (!M) 57800b57cec5SDimitry Andric return true; 57810b57cec5SDimitry Andric 57820b57cec5SDimitry Andric // Macro instantiation is lexical, unfortunately. We construct a new buffer 57830b57cec5SDimitry Andric // to hold the macro body with substitutions. 57840b57cec5SDimitry Andric SmallString<256> Buf; 57850b57cec5SDimitry Andric raw_svector_ostream OS(Buf); 57860b57cec5SDimitry Andric 57870b57cec5SDimitry Andric StringRef Values = A.front().front().getString(); 57880b57cec5SDimitry Andric for (std::size_t I = 0, End = Values.size(); I != End; ++I) { 57890b57cec5SDimitry Andric MCAsmMacroArgument Arg; 57900b57cec5SDimitry Andric Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1)); 57910b57cec5SDimitry Andric 57920b57cec5SDimitry Andric // Note that the AtPseudoVariable is enabled for instantiations of .irpc. 57930b57cec5SDimitry Andric // This is undocumented, but GAS seems to support it. 5794*0fca6ea1SDimitry Andric if (expandMacro(OS, *M, Parameter, Arg, true)) 57950b57cec5SDimitry Andric return true; 57960b57cec5SDimitry Andric } 57970b57cec5SDimitry Andric 57980b57cec5SDimitry Andric instantiateMacroLikeBody(M, DirectiveLoc, OS); 57990b57cec5SDimitry Andric 58000b57cec5SDimitry Andric return false; 58010b57cec5SDimitry Andric } 58020b57cec5SDimitry Andric 58030b57cec5SDimitry Andric bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) { 58040b57cec5SDimitry Andric if (ActiveMacros.empty()) 58050b57cec5SDimitry Andric return TokError("unmatched '.endr' directive"); 58060b57cec5SDimitry Andric 58070b57cec5SDimitry Andric // The only .repl that should get here are the ones created by 58080b57cec5SDimitry Andric // instantiateMacroLikeBody. 58090b57cec5SDimitry Andric assert(getLexer().is(AsmToken::EndOfStatement)); 58100b57cec5SDimitry Andric 58110b57cec5SDimitry Andric handleMacroExit(); 58120b57cec5SDimitry Andric return false; 58130b57cec5SDimitry Andric } 58140b57cec5SDimitry Andric 58150b57cec5SDimitry Andric bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info, 58160b57cec5SDimitry Andric size_t Len) { 58170b57cec5SDimitry Andric const MCExpr *Value; 58180b57cec5SDimitry Andric SMLoc ExprLoc = getLexer().getLoc(); 58190b57cec5SDimitry Andric if (parseExpression(Value)) 58200b57cec5SDimitry Andric return true; 58210b57cec5SDimitry Andric const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); 58220b57cec5SDimitry Andric if (!MCE) 58230b57cec5SDimitry Andric return Error(ExprLoc, "unexpected expression in _emit"); 58240b57cec5SDimitry Andric uint64_t IntValue = MCE->getValue(); 58250b57cec5SDimitry Andric if (!isUInt<8>(IntValue) && !isInt<8>(IntValue)) 58260b57cec5SDimitry Andric return Error(ExprLoc, "literal value out of range for directive"); 58270b57cec5SDimitry Andric 58280b57cec5SDimitry Andric Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len); 58290b57cec5SDimitry Andric return false; 58300b57cec5SDimitry Andric } 58310b57cec5SDimitry Andric 58320b57cec5SDimitry Andric bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) { 58330b57cec5SDimitry Andric const MCExpr *Value; 58340b57cec5SDimitry Andric SMLoc ExprLoc = getLexer().getLoc(); 58350b57cec5SDimitry Andric if (parseExpression(Value)) 58360b57cec5SDimitry Andric return true; 58370b57cec5SDimitry Andric const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); 58380b57cec5SDimitry Andric if (!MCE) 58390b57cec5SDimitry Andric return Error(ExprLoc, "unexpected expression in align"); 58400b57cec5SDimitry Andric uint64_t IntValue = MCE->getValue(); 58410b57cec5SDimitry Andric if (!isPowerOf2_64(IntValue)) 58420b57cec5SDimitry Andric return Error(ExprLoc, "literal value not a power of two greater then zero"); 58430b57cec5SDimitry Andric 58440b57cec5SDimitry Andric Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue)); 58450b57cec5SDimitry Andric return false; 58460b57cec5SDimitry Andric } 58470b57cec5SDimitry Andric 58480b57cec5SDimitry Andric bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) { 58490b57cec5SDimitry Andric const AsmToken StrTok = getTok(); 58500b57cec5SDimitry Andric Lex(); 58510b57cec5SDimitry Andric if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"') 58520b57cec5SDimitry Andric return Error(DirectiveLoc, "expected double quoted string after .print"); 5853fe6060f1SDimitry Andric if (parseEOL()) 58540b57cec5SDimitry Andric return true; 58550b57cec5SDimitry Andric llvm::outs() << StrTok.getStringContents() << '\n'; 58560b57cec5SDimitry Andric return false; 58570b57cec5SDimitry Andric } 58580b57cec5SDimitry Andric 58590b57cec5SDimitry Andric bool AsmParser::parseDirectiveAddrsig() { 5860fe6060f1SDimitry Andric if (parseEOL()) 5861fe6060f1SDimitry Andric return true; 58625ffd83dbSDimitry Andric getStreamer().emitAddrsig(); 58630b57cec5SDimitry Andric return false; 58640b57cec5SDimitry Andric } 58650b57cec5SDimitry Andric 58660b57cec5SDimitry Andric bool AsmParser::parseDirectiveAddrsigSym() { 58670b57cec5SDimitry Andric StringRef Name; 5868fe6060f1SDimitry Andric if (check(parseIdentifier(Name), "expected identifier") || parseEOL()) 58690b57cec5SDimitry Andric return true; 58700b57cec5SDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 58715ffd83dbSDimitry Andric getStreamer().emitAddrsigSym(Sym); 58720b57cec5SDimitry Andric return false; 58730b57cec5SDimitry Andric } 58740b57cec5SDimitry Andric 5875e8d8bef9SDimitry Andric bool AsmParser::parseDirectivePseudoProbe() { 5876e8d8bef9SDimitry Andric int64_t Guid; 5877e8d8bef9SDimitry Andric int64_t Index; 5878e8d8bef9SDimitry Andric int64_t Type; 5879e8d8bef9SDimitry Andric int64_t Attr; 588006c3fb27SDimitry Andric int64_t Discriminator = 0; 5881e8d8bef9SDimitry Andric 5882e8d8bef9SDimitry Andric if (parseIntToken(Guid, "unexpected token in '.pseudoprobe' directive")) 5883e8d8bef9SDimitry Andric return true; 5884e8d8bef9SDimitry Andric 5885e8d8bef9SDimitry Andric if (parseIntToken(Index, "unexpected token in '.pseudoprobe' directive")) 5886e8d8bef9SDimitry Andric return true; 5887e8d8bef9SDimitry Andric 5888e8d8bef9SDimitry Andric if (parseIntToken(Type, "unexpected token in '.pseudoprobe' directive")) 5889e8d8bef9SDimitry Andric return true; 5890e8d8bef9SDimitry Andric 5891e8d8bef9SDimitry Andric if (parseIntToken(Attr, "unexpected token in '.pseudoprobe' directive")) 5892e8d8bef9SDimitry Andric return true; 589306c3fb27SDimitry Andric 589406c3fb27SDimitry Andric if (hasDiscriminator(Attr)) { 589506c3fb27SDimitry Andric if (parseIntToken(Discriminator, 589606c3fb27SDimitry Andric "unexpected token in '.pseudoprobe' directive")) 589706c3fb27SDimitry Andric return true; 5898e8d8bef9SDimitry Andric } 5899e8d8bef9SDimitry Andric 5900e8d8bef9SDimitry Andric // Parse inline stack like @ GUID:11:12 @ GUID:1:11 @ GUID:3:21 5901e8d8bef9SDimitry Andric MCPseudoProbeInlineStack InlineStack; 5902e8d8bef9SDimitry Andric 5903e8d8bef9SDimitry Andric while (getLexer().is(AsmToken::At)) { 5904e8d8bef9SDimitry Andric // eat @ 5905e8d8bef9SDimitry Andric Lex(); 5906e8d8bef9SDimitry Andric 5907e8d8bef9SDimitry Andric int64_t CallerGuid = 0; 5908e8d8bef9SDimitry Andric if (getLexer().is(AsmToken::Integer)) { 5909e8d8bef9SDimitry Andric if (parseIntToken(CallerGuid, 5910e8d8bef9SDimitry Andric "unexpected token in '.pseudoprobe' directive")) 5911e8d8bef9SDimitry Andric return true; 5912e8d8bef9SDimitry Andric } 5913e8d8bef9SDimitry Andric 5914e8d8bef9SDimitry Andric // eat colon 5915e8d8bef9SDimitry Andric if (getLexer().is(AsmToken::Colon)) 5916e8d8bef9SDimitry Andric Lex(); 5917e8d8bef9SDimitry Andric 5918e8d8bef9SDimitry Andric int64_t CallerProbeId = 0; 5919e8d8bef9SDimitry Andric if (getLexer().is(AsmToken::Integer)) { 5920e8d8bef9SDimitry Andric if (parseIntToken(CallerProbeId, 5921e8d8bef9SDimitry Andric "unexpected token in '.pseudoprobe' directive")) 5922e8d8bef9SDimitry Andric return true; 5923e8d8bef9SDimitry Andric } 5924e8d8bef9SDimitry Andric 5925e8d8bef9SDimitry Andric InlineSite Site(CallerGuid, CallerProbeId); 5926e8d8bef9SDimitry Andric InlineStack.push_back(Site); 5927e8d8bef9SDimitry Andric } 5928e8d8bef9SDimitry Andric 5929bdd1243dSDimitry Andric // Parse function entry name 5930bdd1243dSDimitry Andric StringRef FnName; 5931bdd1243dSDimitry Andric if (parseIdentifier(FnName)) 5932bdd1243dSDimitry Andric return Error(getLexer().getLoc(), "unexpected token in '.pseudoprobe' directive"); 5933bdd1243dSDimitry Andric MCSymbol *FnSym = getContext().lookupSymbol(FnName); 5934bdd1243dSDimitry Andric 5935fe6060f1SDimitry Andric if (parseEOL()) 5936e8d8bef9SDimitry Andric return true; 5937e8d8bef9SDimitry Andric 593806c3fb27SDimitry Andric getStreamer().emitPseudoProbe(Guid, Index, Type, Attr, Discriminator, 593906c3fb27SDimitry Andric InlineStack, FnSym); 5940e8d8bef9SDimitry Andric return false; 5941e8d8bef9SDimitry Andric } 5942e8d8bef9SDimitry Andric 5943fe6060f1SDimitry Andric /// parseDirectiveLTODiscard 5944fe6060f1SDimitry Andric /// ::= ".lto_discard" [ identifier ( , identifier )* ] 5945fe6060f1SDimitry Andric /// The LTO library emits this directive to discard non-prevailing symbols. 5946fe6060f1SDimitry Andric /// We ignore symbol assignments and attribute changes for the specified 5947fe6060f1SDimitry Andric /// symbols. 5948fe6060f1SDimitry Andric bool AsmParser::parseDirectiveLTODiscard() { 5949fe6060f1SDimitry Andric auto ParseOp = [&]() -> bool { 5950fe6060f1SDimitry Andric StringRef Name; 5951fe6060f1SDimitry Andric SMLoc Loc = getTok().getLoc(); 5952fe6060f1SDimitry Andric if (parseIdentifier(Name)) 5953fe6060f1SDimitry Andric return Error(Loc, "expected identifier"); 5954fe6060f1SDimitry Andric LTODiscardSymbols.insert(Name); 5955fe6060f1SDimitry Andric return false; 5956fe6060f1SDimitry Andric }; 5957fe6060f1SDimitry Andric 5958fe6060f1SDimitry Andric LTODiscardSymbols.clear(); 5959fe6060f1SDimitry Andric return parseMany(ParseOp); 5960fe6060f1SDimitry Andric } 5961fe6060f1SDimitry Andric 59620b57cec5SDimitry Andric // We are comparing pointers, but the pointers are relative to a single string. 59630b57cec5SDimitry Andric // Thus, this should always be deterministic. 59640b57cec5SDimitry Andric static int rewritesSort(const AsmRewrite *AsmRewriteA, 59650b57cec5SDimitry Andric const AsmRewrite *AsmRewriteB) { 59660b57cec5SDimitry Andric if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer()) 59670b57cec5SDimitry Andric return -1; 59680b57cec5SDimitry Andric if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer()) 59690b57cec5SDimitry Andric return 1; 59700b57cec5SDimitry Andric 59710b57cec5SDimitry Andric // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output 59720b57cec5SDimitry Andric // rewrite to the same location. Make sure the SizeDirective rewrite is 59730b57cec5SDimitry Andric // performed first, then the Imm/ImmPrefix and finally the Input/Output. This 59740b57cec5SDimitry Andric // ensures the sort algorithm is stable. 59750b57cec5SDimitry Andric if (AsmRewritePrecedence[AsmRewriteA->Kind] > 59760b57cec5SDimitry Andric AsmRewritePrecedence[AsmRewriteB->Kind]) 59770b57cec5SDimitry Andric return -1; 59780b57cec5SDimitry Andric 59790b57cec5SDimitry Andric if (AsmRewritePrecedence[AsmRewriteA->Kind] < 59800b57cec5SDimitry Andric AsmRewritePrecedence[AsmRewriteB->Kind]) 59810b57cec5SDimitry Andric return 1; 59820b57cec5SDimitry Andric llvm_unreachable("Unstable rewrite sort."); 59830b57cec5SDimitry Andric } 59840b57cec5SDimitry Andric 59850b57cec5SDimitry Andric bool AsmParser::parseMSInlineAsm( 5986fe6060f1SDimitry Andric std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, 5987fe6060f1SDimitry Andric SmallVectorImpl<std::pair<void *, bool>> &OpDecls, 59880b57cec5SDimitry Andric SmallVectorImpl<std::string> &Constraints, 59890b57cec5SDimitry Andric SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII, 59900b57cec5SDimitry Andric const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) { 59910b57cec5SDimitry Andric SmallVector<void *, 4> InputDecls; 59920b57cec5SDimitry Andric SmallVector<void *, 4> OutputDecls; 59930b57cec5SDimitry Andric SmallVector<bool, 4> InputDeclsAddressOf; 59940b57cec5SDimitry Andric SmallVector<bool, 4> OutputDeclsAddressOf; 59950b57cec5SDimitry Andric SmallVector<std::string, 4> InputConstraints; 59960b57cec5SDimitry Andric SmallVector<std::string, 4> OutputConstraints; 59970b57cec5SDimitry Andric SmallVector<unsigned, 4> ClobberRegs; 59980b57cec5SDimitry Andric 59990b57cec5SDimitry Andric SmallVector<AsmRewrite, 4> AsmStrRewrites; 60000b57cec5SDimitry Andric 60010b57cec5SDimitry Andric // Prime the lexer. 60020b57cec5SDimitry Andric Lex(); 60030b57cec5SDimitry Andric 60040b57cec5SDimitry Andric // While we have input, parse each statement. 60050b57cec5SDimitry Andric unsigned InputIdx = 0; 60060b57cec5SDimitry Andric unsigned OutputIdx = 0; 60070b57cec5SDimitry Andric while (getLexer().isNot(AsmToken::Eof)) { 60080b57cec5SDimitry Andric // Parse curly braces marking block start/end 60090b57cec5SDimitry Andric if (parseCurlyBlockScope(AsmStrRewrites)) 60100b57cec5SDimitry Andric continue; 60110b57cec5SDimitry Andric 60120b57cec5SDimitry Andric ParseStatementInfo Info(&AsmStrRewrites); 60130b57cec5SDimitry Andric bool StatementErr = parseStatement(Info, &SI); 60140b57cec5SDimitry Andric 60150b57cec5SDimitry Andric if (StatementErr || Info.ParseError) { 60160b57cec5SDimitry Andric // Emit pending errors if any exist. 60170b57cec5SDimitry Andric printPendingErrors(); 60180b57cec5SDimitry Andric return true; 60190b57cec5SDimitry Andric } 60200b57cec5SDimitry Andric 60210b57cec5SDimitry Andric // No pending error should exist here. 60220b57cec5SDimitry Andric assert(!hasPendingError() && "unexpected error from parseStatement"); 60230b57cec5SDimitry Andric 60240b57cec5SDimitry Andric if (Info.Opcode == ~0U) 60250b57cec5SDimitry Andric continue; 60260b57cec5SDimitry Andric 60270b57cec5SDimitry Andric const MCInstrDesc &Desc = MII->get(Info.Opcode); 60280b57cec5SDimitry Andric 60290b57cec5SDimitry Andric // Build the list of clobbers, outputs and inputs. 60300b57cec5SDimitry Andric for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) { 60310b57cec5SDimitry Andric MCParsedAsmOperand &Operand = *Info.ParsedOperands[i]; 60320b57cec5SDimitry Andric 60330b57cec5SDimitry Andric // Register operand. 60340b57cec5SDimitry Andric if (Operand.isReg() && !Operand.needAddressOf() && 60350b57cec5SDimitry Andric !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) { 60360b57cec5SDimitry Andric unsigned NumDefs = Desc.getNumDefs(); 60370b57cec5SDimitry Andric // Clobber. 60380b57cec5SDimitry Andric if (NumDefs && Operand.getMCOperandNum() < NumDefs) 60390b57cec5SDimitry Andric ClobberRegs.push_back(Operand.getReg()); 60400b57cec5SDimitry Andric continue; 60410b57cec5SDimitry Andric } 60420b57cec5SDimitry Andric 60430b57cec5SDimitry Andric // Expr/Input or Output. 60440b57cec5SDimitry Andric StringRef SymName = Operand.getSymName(); 60450b57cec5SDimitry Andric if (SymName.empty()) 60460b57cec5SDimitry Andric continue; 60470b57cec5SDimitry Andric 60480b57cec5SDimitry Andric void *OpDecl = Operand.getOpDecl(); 60490b57cec5SDimitry Andric if (!OpDecl) 60500b57cec5SDimitry Andric continue; 60510b57cec5SDimitry Andric 6052480093f4SDimitry Andric StringRef Constraint = Operand.getConstraint(); 6053480093f4SDimitry Andric if (Operand.isImm()) { 6054480093f4SDimitry Andric // Offset as immediate 6055480093f4SDimitry Andric if (Operand.isOffsetOfLocal()) 6056480093f4SDimitry Andric Constraint = "r"; 6057480093f4SDimitry Andric else 6058480093f4SDimitry Andric Constraint = "i"; 6059480093f4SDimitry Andric } 6060480093f4SDimitry Andric 60610b57cec5SDimitry Andric bool isOutput = (i == 1) && Desc.mayStore(); 606281ad6265SDimitry Andric bool Restricted = Operand.isMemUseUpRegs(); 60630b57cec5SDimitry Andric SMLoc Start = SMLoc::getFromPointer(SymName.data()); 60640b57cec5SDimitry Andric if (isOutput) { 60650b57cec5SDimitry Andric ++InputIdx; 60660b57cec5SDimitry Andric OutputDecls.push_back(OpDecl); 60670b57cec5SDimitry Andric OutputDeclsAddressOf.push_back(Operand.needAddressOf()); 6068480093f4SDimitry Andric OutputConstraints.push_back(("=" + Constraint).str()); 606981ad6265SDimitry Andric AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size(), 0, 607081ad6265SDimitry Andric Restricted); 60710b57cec5SDimitry Andric } else { 60720b57cec5SDimitry Andric InputDecls.push_back(OpDecl); 60730b57cec5SDimitry Andric InputDeclsAddressOf.push_back(Operand.needAddressOf()); 6074480093f4SDimitry Andric InputConstraints.push_back(Constraint.str()); 6075bdd1243dSDimitry Andric if (Desc.operands()[i - 1].isBranchTarget()) 607681ad6265SDimitry Andric AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size(), 0, 607781ad6265SDimitry Andric Restricted); 6078480093f4SDimitry Andric else 607981ad6265SDimitry Andric AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size(), 0, 608081ad6265SDimitry Andric Restricted); 60810b57cec5SDimitry Andric } 60820b57cec5SDimitry Andric } 60830b57cec5SDimitry Andric 60840b57cec5SDimitry Andric // Consider implicit defs to be clobbers. Think of cpuid and push. 6085bdd1243dSDimitry Andric llvm::append_range(ClobberRegs, Desc.implicit_defs()); 60860b57cec5SDimitry Andric } 60870b57cec5SDimitry Andric 60880b57cec5SDimitry Andric // Set the number of Outputs and Inputs. 60890b57cec5SDimitry Andric NumOutputs = OutputDecls.size(); 60900b57cec5SDimitry Andric NumInputs = InputDecls.size(); 60910b57cec5SDimitry Andric 60920b57cec5SDimitry Andric // Set the unique clobbers. 60930b57cec5SDimitry Andric array_pod_sort(ClobberRegs.begin(), ClobberRegs.end()); 6094*0fca6ea1SDimitry Andric ClobberRegs.erase(llvm::unique(ClobberRegs), ClobberRegs.end()); 60950b57cec5SDimitry Andric Clobbers.assign(ClobberRegs.size(), std::string()); 60960b57cec5SDimitry Andric for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) { 60970b57cec5SDimitry Andric raw_string_ostream OS(Clobbers[I]); 60980b57cec5SDimitry Andric IP->printRegName(OS, ClobberRegs[I]); 60990b57cec5SDimitry Andric } 61000b57cec5SDimitry Andric 61010b57cec5SDimitry Andric // Merge the various outputs and inputs. Output are expected first. 61020b57cec5SDimitry Andric if (NumOutputs || NumInputs) { 61030b57cec5SDimitry Andric unsigned NumExprs = NumOutputs + NumInputs; 61040b57cec5SDimitry Andric OpDecls.resize(NumExprs); 61050b57cec5SDimitry Andric Constraints.resize(NumExprs); 61060b57cec5SDimitry Andric for (unsigned i = 0; i < NumOutputs; ++i) { 61070b57cec5SDimitry Andric OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]); 61080b57cec5SDimitry Andric Constraints[i] = OutputConstraints[i]; 61090b57cec5SDimitry Andric } 61100b57cec5SDimitry Andric for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) { 61110b57cec5SDimitry Andric OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]); 61120b57cec5SDimitry Andric Constraints[j] = InputConstraints[i]; 61130b57cec5SDimitry Andric } 61140b57cec5SDimitry Andric } 61150b57cec5SDimitry Andric 61160b57cec5SDimitry Andric // Build the IR assembly string. 61170b57cec5SDimitry Andric std::string AsmStringIR; 61180b57cec5SDimitry Andric raw_string_ostream OS(AsmStringIR); 61190b57cec5SDimitry Andric StringRef ASMString = 61200b57cec5SDimitry Andric SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer(); 61210b57cec5SDimitry Andric const char *AsmStart = ASMString.begin(); 61220b57cec5SDimitry Andric const char *AsmEnd = ASMString.end(); 61230b57cec5SDimitry Andric array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort); 6124*0fca6ea1SDimitry Andric for (auto I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) { 6125*0fca6ea1SDimitry Andric const AsmRewrite &AR = *I; 6126480093f4SDimitry Andric // Check if this has already been covered by another rewrite... 6127480093f4SDimitry Andric if (AR.Done) 6128480093f4SDimitry Andric continue; 61290b57cec5SDimitry Andric AsmRewriteKind Kind = AR.Kind; 61300b57cec5SDimitry Andric 61310b57cec5SDimitry Andric const char *Loc = AR.Loc.getPointer(); 61320b57cec5SDimitry Andric assert(Loc >= AsmStart && "Expected Loc to be at or after Start!"); 61330b57cec5SDimitry Andric 61340b57cec5SDimitry Andric // Emit everything up to the immediate/expression. 61350b57cec5SDimitry Andric if (unsigned Len = Loc - AsmStart) 61360b57cec5SDimitry Andric OS << StringRef(AsmStart, Len); 61370b57cec5SDimitry Andric 61380b57cec5SDimitry Andric // Skip the original expression. 61390b57cec5SDimitry Andric if (Kind == AOK_Skip) { 61400b57cec5SDimitry Andric AsmStart = Loc + AR.Len; 61410b57cec5SDimitry Andric continue; 61420b57cec5SDimitry Andric } 61430b57cec5SDimitry Andric 61440b57cec5SDimitry Andric unsigned AdditionalSkip = 0; 61450b57cec5SDimitry Andric // Rewrite expressions in $N notation. 61460b57cec5SDimitry Andric switch (Kind) { 61470b57cec5SDimitry Andric default: 61480b57cec5SDimitry Andric break; 61490b57cec5SDimitry Andric case AOK_IntelExpr: 61500b57cec5SDimitry Andric assert(AR.IntelExp.isValid() && "cannot write invalid intel expression"); 61510b57cec5SDimitry Andric if (AR.IntelExp.NeedBracs) 61520b57cec5SDimitry Andric OS << "["; 61530b57cec5SDimitry Andric if (AR.IntelExp.hasBaseReg()) 61540b57cec5SDimitry Andric OS << AR.IntelExp.BaseReg; 61550b57cec5SDimitry Andric if (AR.IntelExp.hasIndexReg()) 61560b57cec5SDimitry Andric OS << (AR.IntelExp.hasBaseReg() ? " + " : "") 61570b57cec5SDimitry Andric << AR.IntelExp.IndexReg; 61580b57cec5SDimitry Andric if (AR.IntelExp.Scale > 1) 61590b57cec5SDimitry Andric OS << " * $$" << AR.IntelExp.Scale; 6160480093f4SDimitry Andric if (AR.IntelExp.hasOffset()) { 6161480093f4SDimitry Andric if (AR.IntelExp.hasRegs()) 6162480093f4SDimitry Andric OS << " + "; 6163480093f4SDimitry Andric // Fuse this rewrite with a rewrite of the offset name, if present. 6164480093f4SDimitry Andric StringRef OffsetName = AR.IntelExp.OffsetName; 6165480093f4SDimitry Andric SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data()); 6166480093f4SDimitry Andric size_t OffsetLen = OffsetName.size(); 6167480093f4SDimitry Andric auto rewrite_it = std::find_if( 6168*0fca6ea1SDimitry Andric I, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) { 6169480093f4SDimitry Andric return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen && 6170480093f4SDimitry Andric (FusingAR.Kind == AOK_Input || 6171480093f4SDimitry Andric FusingAR.Kind == AOK_CallInput); 6172480093f4SDimitry Andric }); 6173480093f4SDimitry Andric if (rewrite_it == AsmStrRewrites.end()) { 6174480093f4SDimitry Andric OS << "offset " << OffsetName; 6175480093f4SDimitry Andric } else if (rewrite_it->Kind == AOK_CallInput) { 6176480093f4SDimitry Andric OS << "${" << InputIdx++ << ":P}"; 6177480093f4SDimitry Andric rewrite_it->Done = true; 6178480093f4SDimitry Andric } else { 6179480093f4SDimitry Andric OS << '$' << InputIdx++; 6180480093f4SDimitry Andric rewrite_it->Done = true; 6181480093f4SDimitry Andric } 6182480093f4SDimitry Andric } 6183480093f4SDimitry Andric if (AR.IntelExp.Imm || AR.IntelExp.emitImm()) 6184480093f4SDimitry Andric OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm; 61850b57cec5SDimitry Andric if (AR.IntelExp.NeedBracs) 61860b57cec5SDimitry Andric OS << "]"; 61870b57cec5SDimitry Andric break; 61880b57cec5SDimitry Andric case AOK_Label: 61890b57cec5SDimitry Andric OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label; 61900b57cec5SDimitry Andric break; 61910b57cec5SDimitry Andric case AOK_Input: 619281ad6265SDimitry Andric if (AR.IntelExpRestricted) 619381ad6265SDimitry Andric OS << "${" << InputIdx++ << ":P}"; 619481ad6265SDimitry Andric else 619581ad6265SDimitry Andric OS << '$' << InputIdx++; 61960b57cec5SDimitry Andric break; 6197480093f4SDimitry Andric case AOK_CallInput: 6198480093f4SDimitry Andric OS << "${" << InputIdx++ << ":P}"; 6199480093f4SDimitry Andric break; 62000b57cec5SDimitry Andric case AOK_Output: 620181ad6265SDimitry Andric if (AR.IntelExpRestricted) 620281ad6265SDimitry Andric OS << "${" << OutputIdx++ << ":P}"; 620381ad6265SDimitry Andric else 620481ad6265SDimitry Andric OS << '$' << OutputIdx++; 62050b57cec5SDimitry Andric break; 62060b57cec5SDimitry Andric case AOK_SizeDirective: 62070b57cec5SDimitry Andric switch (AR.Val) { 62080b57cec5SDimitry Andric default: break; 62090b57cec5SDimitry Andric case 8: OS << "byte ptr "; break; 62100b57cec5SDimitry Andric case 16: OS << "word ptr "; break; 62110b57cec5SDimitry Andric case 32: OS << "dword ptr "; break; 62120b57cec5SDimitry Andric case 64: OS << "qword ptr "; break; 62130b57cec5SDimitry Andric case 80: OS << "xword ptr "; break; 62140b57cec5SDimitry Andric case 128: OS << "xmmword ptr "; break; 62150b57cec5SDimitry Andric case 256: OS << "ymmword ptr "; break; 62160b57cec5SDimitry Andric } 62170b57cec5SDimitry Andric break; 62180b57cec5SDimitry Andric case AOK_Emit: 62190b57cec5SDimitry Andric OS << ".byte"; 62200b57cec5SDimitry Andric break; 62210b57cec5SDimitry Andric case AOK_Align: { 62220b57cec5SDimitry Andric // MS alignment directives are measured in bytes. If the native assembler 62230b57cec5SDimitry Andric // measures alignment in bytes, we can pass it straight through. 62240b57cec5SDimitry Andric OS << ".align"; 62250b57cec5SDimitry Andric if (getContext().getAsmInfo()->getAlignmentIsInBytes()) 62260b57cec5SDimitry Andric break; 62270b57cec5SDimitry Andric 62280b57cec5SDimitry Andric // Alignment is in log2 form, so print that instead and skip the original 62290b57cec5SDimitry Andric // immediate. 62300b57cec5SDimitry Andric unsigned Val = AR.Val; 62310b57cec5SDimitry Andric OS << ' ' << Val; 62320b57cec5SDimitry Andric assert(Val < 10 && "Expected alignment less then 2^10."); 62330b57cec5SDimitry Andric AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4; 62340b57cec5SDimitry Andric break; 62350b57cec5SDimitry Andric } 62360b57cec5SDimitry Andric case AOK_EVEN: 62370b57cec5SDimitry Andric OS << ".even"; 62380b57cec5SDimitry Andric break; 62390b57cec5SDimitry Andric case AOK_EndOfStatement: 62400b57cec5SDimitry Andric OS << "\n\t"; 62410b57cec5SDimitry Andric break; 62420b57cec5SDimitry Andric } 62430b57cec5SDimitry Andric 62440b57cec5SDimitry Andric // Skip the original expression. 62450b57cec5SDimitry Andric AsmStart = Loc + AR.Len + AdditionalSkip; 62460b57cec5SDimitry Andric } 62470b57cec5SDimitry Andric 62480b57cec5SDimitry Andric // Emit the remainder of the asm string. 62490b57cec5SDimitry Andric if (AsmStart != AsmEnd) 62500b57cec5SDimitry Andric OS << StringRef(AsmStart, AsmEnd - AsmStart); 62510b57cec5SDimitry Andric 6252*0fca6ea1SDimitry Andric AsmString = AsmStringIR; 62530b57cec5SDimitry Andric return false; 62540b57cec5SDimitry Andric } 62550b57cec5SDimitry Andric 6256fe6060f1SDimitry Andric bool HLASMAsmParser::parseAsHLASMLabel(ParseStatementInfo &Info, 6257fe6060f1SDimitry Andric MCAsmParserSemaCallback *SI) { 6258fe6060f1SDimitry Andric AsmToken LabelTok = getTok(); 6259fe6060f1SDimitry Andric SMLoc LabelLoc = LabelTok.getLoc(); 6260fe6060f1SDimitry Andric StringRef LabelVal; 6261fe6060f1SDimitry Andric 6262fe6060f1SDimitry Andric if (parseIdentifier(LabelVal)) 6263fe6060f1SDimitry Andric return Error(LabelLoc, "The HLASM Label has to be an Identifier"); 6264fe6060f1SDimitry Andric 6265fe6060f1SDimitry Andric // We have validated whether the token is an Identifier. 6266fe6060f1SDimitry Andric // Now we have to validate whether the token is a 6267fe6060f1SDimitry Andric // valid HLASM Label. 6268fe6060f1SDimitry Andric if (!getTargetParser().isLabel(LabelTok) || checkForValidSection()) 6269fe6060f1SDimitry Andric return true; 6270fe6060f1SDimitry Andric 6271fe6060f1SDimitry Andric // Lex leading spaces to get to the next operand. 6272fe6060f1SDimitry Andric lexLeadingSpaces(); 6273fe6060f1SDimitry Andric 6274fe6060f1SDimitry Andric // We shouldn't emit the label if there is nothing else after the label. 6275fe6060f1SDimitry Andric // i.e asm("<token>\n") 6276fe6060f1SDimitry Andric if (getTok().is(AsmToken::EndOfStatement)) 6277fe6060f1SDimitry Andric return Error(LabelLoc, 6278fe6060f1SDimitry Andric "Cannot have just a label for an HLASM inline asm statement"); 6279fe6060f1SDimitry Andric 6280fe6060f1SDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol( 6281fe6060f1SDimitry Andric getContext().getAsmInfo()->shouldEmitLabelsInUpperCase() 6282fe6060f1SDimitry Andric ? LabelVal.upper() 6283fe6060f1SDimitry Andric : LabelVal); 6284fe6060f1SDimitry Andric 6285bdd1243dSDimitry Andric getTargetParser().doBeforeLabelEmit(Sym, LabelLoc); 6286fe6060f1SDimitry Andric 6287fe6060f1SDimitry Andric // Emit the label. 6288fe6060f1SDimitry Andric Out.emitLabel(Sym, LabelLoc); 6289fe6060f1SDimitry Andric 6290fe6060f1SDimitry Andric // If we are generating dwarf for assembly source files then gather the 6291fe6060f1SDimitry Andric // info to make a dwarf label entry for this label if needed. 6292fe6060f1SDimitry Andric if (enabledGenDwarfForAssembly()) 6293fe6060f1SDimitry Andric MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(), 6294fe6060f1SDimitry Andric LabelLoc); 6295fe6060f1SDimitry Andric 6296fe6060f1SDimitry Andric getTargetParser().onLabelParsed(Sym); 6297fe6060f1SDimitry Andric 6298fe6060f1SDimitry Andric return false; 6299fe6060f1SDimitry Andric } 6300fe6060f1SDimitry Andric 6301fe6060f1SDimitry Andric bool HLASMAsmParser::parseAsMachineInstruction(ParseStatementInfo &Info, 6302fe6060f1SDimitry Andric MCAsmParserSemaCallback *SI) { 6303fe6060f1SDimitry Andric AsmToken OperationEntryTok = Lexer.getTok(); 6304fe6060f1SDimitry Andric SMLoc OperationEntryLoc = OperationEntryTok.getLoc(); 6305fe6060f1SDimitry Andric StringRef OperationEntryVal; 6306fe6060f1SDimitry Andric 6307fe6060f1SDimitry Andric // Attempt to parse the first token as an Identifier 6308fe6060f1SDimitry Andric if (parseIdentifier(OperationEntryVal)) 6309fe6060f1SDimitry Andric return Error(OperationEntryLoc, "unexpected token at start of statement"); 6310fe6060f1SDimitry Andric 6311fe6060f1SDimitry Andric // Once we've parsed the operation entry successfully, lex 6312fe6060f1SDimitry Andric // any spaces to get to the OperandEntries. 6313fe6060f1SDimitry Andric lexLeadingSpaces(); 6314fe6060f1SDimitry Andric 6315fe6060f1SDimitry Andric return parseAndMatchAndEmitTargetInstruction( 6316fe6060f1SDimitry Andric Info, OperationEntryVal, OperationEntryTok, OperationEntryLoc); 6317fe6060f1SDimitry Andric } 6318fe6060f1SDimitry Andric 6319fe6060f1SDimitry Andric bool HLASMAsmParser::parseStatement(ParseStatementInfo &Info, 6320fe6060f1SDimitry Andric MCAsmParserSemaCallback *SI) { 6321fe6060f1SDimitry Andric assert(!hasPendingError() && "parseStatement started with pending error"); 6322fe6060f1SDimitry Andric 6323fe6060f1SDimitry Andric // Should the first token be interpreted as a HLASM Label. 6324fe6060f1SDimitry Andric bool ShouldParseAsHLASMLabel = false; 6325fe6060f1SDimitry Andric 6326fe6060f1SDimitry Andric // If a Name Entry exists, it should occur at the very 6327fe6060f1SDimitry Andric // start of the string. In this case, we should parse the 6328fe6060f1SDimitry Andric // first non-space token as a Label. 6329fe6060f1SDimitry Andric // If the Name entry is missing (i.e. there's some other 6330fe6060f1SDimitry Andric // token), then we attempt to parse the first non-space 6331fe6060f1SDimitry Andric // token as a Machine Instruction. 6332fe6060f1SDimitry Andric if (getTok().isNot(AsmToken::Space)) 6333fe6060f1SDimitry Andric ShouldParseAsHLASMLabel = true; 6334fe6060f1SDimitry Andric 6335fe6060f1SDimitry Andric // If we have an EndOfStatement (which includes the target's comment 6336fe6060f1SDimitry Andric // string) we can appropriately lex it early on) 6337fe6060f1SDimitry Andric if (Lexer.is(AsmToken::EndOfStatement)) { 6338fe6060f1SDimitry Andric // if this is a line comment we can drop it safely 6339fe6060f1SDimitry Andric if (getTok().getString().empty() || getTok().getString().front() == '\r' || 6340fe6060f1SDimitry Andric getTok().getString().front() == '\n') 634181ad6265SDimitry Andric Out.addBlankLine(); 6342fe6060f1SDimitry Andric Lex(); 6343fe6060f1SDimitry Andric return false; 6344fe6060f1SDimitry Andric } 6345fe6060f1SDimitry Andric 6346fe6060f1SDimitry Andric // We have established how to parse the inline asm statement. 6347fe6060f1SDimitry Andric // Now we can safely lex any leading spaces to get to the 6348fe6060f1SDimitry Andric // first token. 6349fe6060f1SDimitry Andric lexLeadingSpaces(); 6350fe6060f1SDimitry Andric 6351fe6060f1SDimitry Andric // If we see a new line or carriage return as the first operand, 6352fe6060f1SDimitry Andric // after lexing leading spaces, emit the new line and lex the 6353fe6060f1SDimitry Andric // EndOfStatement token. 6354fe6060f1SDimitry Andric if (Lexer.is(AsmToken::EndOfStatement)) { 6355fe6060f1SDimitry Andric if (getTok().getString().front() == '\n' || 6356fe6060f1SDimitry Andric getTok().getString().front() == '\r') { 635781ad6265SDimitry Andric Out.addBlankLine(); 6358fe6060f1SDimitry Andric Lex(); 6359fe6060f1SDimitry Andric return false; 6360fe6060f1SDimitry Andric } 6361fe6060f1SDimitry Andric } 6362fe6060f1SDimitry Andric 6363fe6060f1SDimitry Andric // Handle the label first if we have to before processing the rest 6364fe6060f1SDimitry Andric // of the tokens as a machine instruction. 6365fe6060f1SDimitry Andric if (ShouldParseAsHLASMLabel) { 6366fe6060f1SDimitry Andric // If there were any errors while handling and emitting the label, 6367fe6060f1SDimitry Andric // early return. 6368fe6060f1SDimitry Andric if (parseAsHLASMLabel(Info, SI)) { 6369fe6060f1SDimitry Andric // If we know we've failed in parsing, simply eat until end of the 6370fe6060f1SDimitry Andric // statement. This ensures that we don't process any other statements. 6371fe6060f1SDimitry Andric eatToEndOfStatement(); 6372fe6060f1SDimitry Andric return true; 6373fe6060f1SDimitry Andric } 6374fe6060f1SDimitry Andric } 6375fe6060f1SDimitry Andric 6376fe6060f1SDimitry Andric return parseAsMachineInstruction(Info, SI); 6377fe6060f1SDimitry Andric } 6378fe6060f1SDimitry Andric 63790b57cec5SDimitry Andric namespace llvm { 63800b57cec5SDimitry Andric namespace MCParserUtils { 63810b57cec5SDimitry Andric 63820b57cec5SDimitry Andric /// Returns whether the given symbol is used anywhere in the given expression, 63830b57cec5SDimitry Andric /// or subexpressions. 63840b57cec5SDimitry Andric static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) { 63850b57cec5SDimitry Andric switch (Value->getKind()) { 63860b57cec5SDimitry Andric case MCExpr::Binary: { 63870b57cec5SDimitry Andric const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value); 63880b57cec5SDimitry Andric return isSymbolUsedInExpression(Sym, BE->getLHS()) || 63890b57cec5SDimitry Andric isSymbolUsedInExpression(Sym, BE->getRHS()); 63900b57cec5SDimitry Andric } 63910b57cec5SDimitry Andric case MCExpr::Target: 63920b57cec5SDimitry Andric case MCExpr::Constant: 63930b57cec5SDimitry Andric return false; 63940b57cec5SDimitry Andric case MCExpr::SymbolRef: { 63950b57cec5SDimitry Andric const MCSymbol &S = 63960b57cec5SDimitry Andric static_cast<const MCSymbolRefExpr *>(Value)->getSymbol(); 639706c3fb27SDimitry Andric if (S.isVariable() && !S.isWeakExternal()) 63980b57cec5SDimitry Andric return isSymbolUsedInExpression(Sym, S.getVariableValue()); 63990b57cec5SDimitry Andric return &S == Sym; 64000b57cec5SDimitry Andric } 64010b57cec5SDimitry Andric case MCExpr::Unary: 64020b57cec5SDimitry Andric return isSymbolUsedInExpression( 64030b57cec5SDimitry Andric Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr()); 64040b57cec5SDimitry Andric } 64050b57cec5SDimitry Andric 64060b57cec5SDimitry Andric llvm_unreachable("Unknown expr kind!"); 64070b57cec5SDimitry Andric } 64080b57cec5SDimitry Andric 64090b57cec5SDimitry Andric bool parseAssignmentExpression(StringRef Name, bool allow_redef, 64100b57cec5SDimitry Andric MCAsmParser &Parser, MCSymbol *&Sym, 64110b57cec5SDimitry Andric const MCExpr *&Value) { 64120b57cec5SDimitry Andric 64130b57cec5SDimitry Andric // FIXME: Use better location, we should use proper tokens. 64140b57cec5SDimitry Andric SMLoc EqualLoc = Parser.getTok().getLoc(); 64150b57cec5SDimitry Andric if (Parser.parseExpression(Value)) 64160b57cec5SDimitry Andric return Parser.TokError("missing expression"); 64170b57cec5SDimitry Andric 64180b57cec5SDimitry Andric // Note: we don't count b as used in "a = b". This is to allow 64190b57cec5SDimitry Andric // a = b 64200b57cec5SDimitry Andric // b = c 64210b57cec5SDimitry Andric 6422fe6060f1SDimitry Andric if (Parser.parseEOL()) 64230b57cec5SDimitry Andric return true; 64240b57cec5SDimitry Andric 64250b57cec5SDimitry Andric // Validate that the LHS is allowed to be a variable (either it has not been 64260b57cec5SDimitry Andric // used as a symbol, or it is an absolute symbol). 64270b57cec5SDimitry Andric Sym = Parser.getContext().lookupSymbol(Name); 64280b57cec5SDimitry Andric if (Sym) { 64290b57cec5SDimitry Andric // Diagnose assignment to a label. 64300b57cec5SDimitry Andric // 64310b57cec5SDimitry Andric // FIXME: Diagnostics. Note the location of the definition as a label. 64320b57cec5SDimitry Andric // FIXME: Diagnose assignment to protected identifier (e.g., register name). 64330b57cec5SDimitry Andric if (isSymbolUsedInExpression(Sym, Value)) 64340b57cec5SDimitry Andric return Parser.Error(EqualLoc, "Recursive use of '" + Name + "'"); 64350b57cec5SDimitry Andric else if (Sym->isUndefined(/*SetUsed*/ false) && !Sym->isUsed() && 64360b57cec5SDimitry Andric !Sym->isVariable()) 64370b57cec5SDimitry Andric ; // Allow redefinitions of undefined symbols only used in directives. 64380b57cec5SDimitry Andric else if (Sym->isVariable() && !Sym->isUsed() && allow_redef) 64390b57cec5SDimitry Andric ; // Allow redefinitions of variables that haven't yet been used. 64400b57cec5SDimitry Andric else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef)) 64410b57cec5SDimitry Andric return Parser.Error(EqualLoc, "redefinition of '" + Name + "'"); 64420b57cec5SDimitry Andric else if (!Sym->isVariable()) 64430b57cec5SDimitry Andric return Parser.Error(EqualLoc, "invalid assignment to '" + Name + "'"); 64440b57cec5SDimitry Andric else if (!isa<MCConstantExpr>(Sym->getVariableValue())) 64450b57cec5SDimitry Andric return Parser.Error(EqualLoc, 64460b57cec5SDimitry Andric "invalid reassignment of non-absolute variable '" + 64470b57cec5SDimitry Andric Name + "'"); 64480b57cec5SDimitry Andric } else if (Name == ".") { 64490b57cec5SDimitry Andric Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc); 64500b57cec5SDimitry Andric return false; 64510b57cec5SDimitry Andric } else 64520b57cec5SDimitry Andric Sym = Parser.getContext().getOrCreateSymbol(Name); 64530b57cec5SDimitry Andric 64540b57cec5SDimitry Andric Sym->setRedefinable(allow_redef); 64550b57cec5SDimitry Andric 64560b57cec5SDimitry Andric return false; 64570b57cec5SDimitry Andric } 64580b57cec5SDimitry Andric 64590b57cec5SDimitry Andric } // end namespace MCParserUtils 64600b57cec5SDimitry Andric } // end namespace llvm 64610b57cec5SDimitry Andric 64620b57cec5SDimitry Andric /// Create an MCAsmParser instance. 64630b57cec5SDimitry Andric MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C, 64640b57cec5SDimitry Andric MCStreamer &Out, const MCAsmInfo &MAI, 64650b57cec5SDimitry Andric unsigned CB) { 6466fe6060f1SDimitry Andric if (C.getTargetTriple().isSystemZ() && C.getTargetTriple().isOSzOS()) 6467fe6060f1SDimitry Andric return new HLASMAsmParser(SM, C, Out, MAI, CB); 6468fe6060f1SDimitry Andric 64690b57cec5SDimitry Andric return new AsmParser(SM, C, Out, MAI, CB); 64700b57cec5SDimitry Andric } 6471