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