1 //===- AsmParser.cpp - Parser for Assembly Files --------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This class implements the parser for assembly files. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/ADT/APFloat.h" 14 #include "llvm/ADT/APInt.h" 15 #include "llvm/ADT/ArrayRef.h" 16 #include "llvm/ADT/None.h" 17 #include "llvm/ADT/Optional.h" 18 #include "llvm/ADT/STLExtras.h" 19 #include "llvm/ADT/SmallString.h" 20 #include "llvm/ADT/SmallVector.h" 21 #include "llvm/ADT/StringExtras.h" 22 #include "llvm/ADT/StringMap.h" 23 #include "llvm/ADT/StringRef.h" 24 #include "llvm/ADT/StringSwitch.h" 25 #include "llvm/ADT/Twine.h" 26 #include "llvm/BinaryFormat/Dwarf.h" 27 #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 28 #include "llvm/MC/MCAsmInfo.h" 29 #include "llvm/MC/MCCodeView.h" 30 #include "llvm/MC/MCContext.h" 31 #include "llvm/MC/MCDirectives.h" 32 #include "llvm/MC/MCDwarf.h" 33 #include "llvm/MC/MCExpr.h" 34 #include "llvm/MC/MCInstPrinter.h" 35 #include "llvm/MC/MCInstrDesc.h" 36 #include "llvm/MC/MCInstrInfo.h" 37 #include "llvm/MC/MCObjectFileInfo.h" 38 #include "llvm/MC/MCParser/AsmCond.h" 39 #include "llvm/MC/MCParser/AsmLexer.h" 40 #include "llvm/MC/MCParser/MCAsmLexer.h" 41 #include "llvm/MC/MCParser/MCAsmParser.h" 42 #include "llvm/MC/MCParser/MCAsmParserExtension.h" 43 #include "llvm/MC/MCParser/MCAsmParserUtils.h" 44 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 45 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 46 #include "llvm/MC/MCRegisterInfo.h" 47 #include "llvm/MC/MCSection.h" 48 #include "llvm/MC/MCStreamer.h" 49 #include "llvm/MC/MCSymbol.h" 50 #include "llvm/MC/MCTargetOptions.h" 51 #include "llvm/MC/MCValue.h" 52 #include "llvm/Support/Casting.h" 53 #include "llvm/Support/CommandLine.h" 54 #include "llvm/Support/ErrorHandling.h" 55 #include "llvm/Support/Format.h" 56 #include "llvm/Support/MD5.h" 57 #include "llvm/Support/MathExtras.h" 58 #include "llvm/Support/MemoryBuffer.h" 59 #include "llvm/Support/SMLoc.h" 60 #include "llvm/Support/SourceMgr.h" 61 #include "llvm/Support/raw_ostream.h" 62 #include <algorithm> 63 #include <cassert> 64 #include <cctype> 65 #include <climits> 66 #include <cstddef> 67 #include <cstdint> 68 #include <deque> 69 #include <memory> 70 #include <sstream> 71 #include <string> 72 #include <tuple> 73 #include <utility> 74 #include <vector> 75 76 using namespace llvm; 77 78 extern cl::opt<unsigned> AsmMacroMaxNestingDepth; 79 80 namespace { 81 82 /// Helper types for tracking macro definitions. 83 typedef std::vector<AsmToken> MCAsmMacroArgument; 84 typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments; 85 86 /// Helper class for storing information about an active macro instantiation. 87 struct MacroInstantiation { 88 /// The location of the instantiation. 89 SMLoc InstantiationLoc; 90 91 /// The buffer where parsing should resume upon instantiation completion. 92 unsigned ExitBuffer; 93 94 /// The location where parsing should resume upon instantiation completion. 95 SMLoc ExitLoc; 96 97 /// The depth of TheCondStack at the start of the instantiation. 98 size_t CondStackDepth; 99 }; 100 101 struct ParseStatementInfo { 102 /// The parsed operands from the last parsed statement. 103 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands; 104 105 /// The opcode from the last parsed instruction. 106 unsigned Opcode = ~0U; 107 108 /// Was there an error parsing the inline assembly? 109 bool ParseError = false; 110 111 /// The value associated with a macro exit. 112 Optional<std::string> ExitValue; 113 114 SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr; 115 116 ParseStatementInfo() = delete; 117 ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites) 118 : AsmRewrites(rewrites) {} 119 }; 120 121 enum FieldType { 122 FT_INTEGRAL, // Initializer: integer expression, stored as an MCExpr. 123 FT_REAL, // Initializer: real number, stored as an APInt. 124 FT_STRUCT // Initializer: struct initializer, stored recursively. 125 }; 126 127 struct FieldInfo; 128 struct StructInfo { 129 StringRef Name; 130 bool IsUnion = false; 131 bool Initializable = true; 132 unsigned Alignment = 0; 133 unsigned AlignmentSize = 0; 134 unsigned NextOffset = 0; 135 unsigned Size = 0; 136 std::vector<FieldInfo> Fields; 137 StringMap<size_t> FieldsByName; 138 139 FieldInfo &addField(StringRef FieldName, FieldType FT, 140 unsigned FieldAlignmentSize); 141 142 StructInfo() = default; 143 144 StructInfo(StringRef StructName, bool Union, unsigned AlignmentValue) 145 : Name(StructName), IsUnion(Union), Alignment(AlignmentValue) {} 146 }; 147 148 // FIXME: This should probably use a class hierarchy, raw pointers between the 149 // objects, and dynamic type resolution instead of a union. On the other hand, 150 // ownership then becomes much more complicated; the obvious thing would be to 151 // use BumpPtrAllocator, but the lack of a destructor makes that messy. 152 153 struct StructInitializer; 154 struct IntFieldInfo { 155 SmallVector<const MCExpr *, 1> Values; 156 157 IntFieldInfo() = default; 158 IntFieldInfo(const SmallVector<const MCExpr *, 1> &V) { Values = V; } 159 IntFieldInfo(SmallVector<const MCExpr *, 1> &&V) { Values = V; } 160 }; 161 struct RealFieldInfo { 162 SmallVector<APInt, 1> AsIntValues; 163 164 RealFieldInfo() = default; 165 RealFieldInfo(const SmallVector<APInt, 1> &V) { AsIntValues = V; } 166 RealFieldInfo(SmallVector<APInt, 1> &&V) { AsIntValues = V; } 167 }; 168 struct StructFieldInfo { 169 std::vector<StructInitializer> Initializers; 170 StructInfo Structure; 171 172 StructFieldInfo() = default; 173 StructFieldInfo(const std::vector<StructInitializer> &V, StructInfo S) { 174 Initializers = V; 175 Structure = S; 176 } 177 StructFieldInfo(std::vector<StructInitializer> &&V, StructInfo S) { 178 Initializers = V; 179 Structure = S; 180 } 181 }; 182 183 class FieldInitializer { 184 public: 185 FieldType FT; 186 union { 187 IntFieldInfo IntInfo; 188 RealFieldInfo RealInfo; 189 StructFieldInfo StructInfo; 190 }; 191 192 ~FieldInitializer() { 193 switch (FT) { 194 case FT_INTEGRAL: 195 IntInfo.~IntFieldInfo(); 196 break; 197 case FT_REAL: 198 RealInfo.~RealFieldInfo(); 199 break; 200 case FT_STRUCT: 201 StructInfo.~StructFieldInfo(); 202 break; 203 } 204 } 205 206 FieldInitializer(FieldType FT) : FT(FT) { 207 switch (FT) { 208 case FT_INTEGRAL: 209 new (&IntInfo) IntFieldInfo(); 210 break; 211 case FT_REAL: 212 new (&RealInfo) RealFieldInfo(); 213 break; 214 case FT_STRUCT: 215 new (&StructInfo) StructFieldInfo(); 216 break; 217 } 218 } 219 220 FieldInitializer(SmallVector<const MCExpr *, 1> &&Values) : FT(FT_INTEGRAL) { 221 new (&IntInfo) IntFieldInfo(Values); 222 } 223 224 FieldInitializer(SmallVector<APInt, 1> &&AsIntValues) : FT(FT_REAL) { 225 new (&RealInfo) RealFieldInfo(AsIntValues); 226 } 227 228 FieldInitializer(std::vector<StructInitializer> &&Initializers, 229 struct StructInfo Structure) 230 : FT(FT_STRUCT) { 231 new (&StructInfo) StructFieldInfo(Initializers, Structure); 232 } 233 234 FieldInitializer(const FieldInitializer &Initializer) : FT(Initializer.FT) { 235 switch (FT) { 236 case FT_INTEGRAL: 237 new (&IntInfo) IntFieldInfo(Initializer.IntInfo); 238 break; 239 case FT_REAL: 240 new (&RealInfo) RealFieldInfo(Initializer.RealInfo); 241 break; 242 case FT_STRUCT: 243 new (&StructInfo) StructFieldInfo(Initializer.StructInfo); 244 break; 245 } 246 } 247 248 FieldInitializer(FieldInitializer &&Initializer) : FT(Initializer.FT) { 249 switch (FT) { 250 case FT_INTEGRAL: 251 new (&IntInfo) IntFieldInfo(Initializer.IntInfo); 252 break; 253 case FT_REAL: 254 new (&RealInfo) RealFieldInfo(Initializer.RealInfo); 255 break; 256 case FT_STRUCT: 257 new (&StructInfo) StructFieldInfo(Initializer.StructInfo); 258 break; 259 } 260 } 261 262 FieldInitializer &operator=(const FieldInitializer &Initializer) { 263 if (FT != Initializer.FT) { 264 switch (FT) { 265 case FT_INTEGRAL: 266 IntInfo.~IntFieldInfo(); 267 break; 268 case FT_REAL: 269 RealInfo.~RealFieldInfo(); 270 break; 271 case FT_STRUCT: 272 StructInfo.~StructFieldInfo(); 273 break; 274 } 275 } 276 FT = Initializer.FT; 277 switch (FT) { 278 case FT_INTEGRAL: 279 IntInfo = Initializer.IntInfo; 280 break; 281 case FT_REAL: 282 RealInfo = Initializer.RealInfo; 283 break; 284 case FT_STRUCT: 285 StructInfo = Initializer.StructInfo; 286 break; 287 } 288 return *this; 289 } 290 291 FieldInitializer &operator=(FieldInitializer &&Initializer) { 292 if (FT != Initializer.FT) { 293 switch (FT) { 294 case FT_INTEGRAL: 295 IntInfo.~IntFieldInfo(); 296 break; 297 case FT_REAL: 298 RealInfo.~RealFieldInfo(); 299 break; 300 case FT_STRUCT: 301 StructInfo.~StructFieldInfo(); 302 break; 303 } 304 } 305 FT = Initializer.FT; 306 switch (FT) { 307 case FT_INTEGRAL: 308 IntInfo = Initializer.IntInfo; 309 break; 310 case FT_REAL: 311 RealInfo = Initializer.RealInfo; 312 break; 313 case FT_STRUCT: 314 StructInfo = Initializer.StructInfo; 315 break; 316 } 317 return *this; 318 } 319 }; 320 321 struct StructInitializer { 322 std::vector<FieldInitializer> FieldInitializers; 323 }; 324 325 struct FieldInfo { 326 // Offset of the field within the containing STRUCT. 327 unsigned Offset = 0; 328 329 // Total size of the field (= LengthOf * Type). 330 unsigned SizeOf = 0; 331 332 // Number of elements in the field (1 if scalar, >1 if an array). 333 unsigned LengthOf = 0; 334 335 // Size of a single entry in this field, in bytes ("type" in MASM standards). 336 unsigned Type = 0; 337 338 FieldInitializer Contents; 339 340 FieldInfo(FieldType FT) : Contents(FT) {} 341 }; 342 343 FieldInfo &StructInfo::addField(StringRef FieldName, FieldType FT, 344 unsigned FieldAlignmentSize) { 345 if (!FieldName.empty()) 346 FieldsByName[FieldName.lower()] = Fields.size(); 347 Fields.emplace_back(FT); 348 FieldInfo &Field = Fields.back(); 349 Field.Offset = 350 llvm::alignTo(NextOffset, std::min(Alignment, FieldAlignmentSize)); 351 if (!IsUnion) { 352 NextOffset = std::max(NextOffset, Field.Offset); 353 } 354 AlignmentSize = std::max(AlignmentSize, FieldAlignmentSize); 355 return Field; 356 } 357 358 /// The concrete assembly parser instance. 359 // Note that this is a full MCAsmParser, not an MCAsmParserExtension! 360 // It's a peer of AsmParser, not of COFFAsmParser, WasmAsmParser, etc. 361 class MasmParser : public MCAsmParser { 362 private: 363 AsmLexer Lexer; 364 MCContext &Ctx; 365 MCStreamer &Out; 366 const MCAsmInfo &MAI; 367 SourceMgr &SrcMgr; 368 SourceMgr::DiagHandlerTy SavedDiagHandler; 369 void *SavedDiagContext; 370 std::unique_ptr<MCAsmParserExtension> PlatformParser; 371 372 /// This is the current buffer index we're lexing from as managed by the 373 /// SourceMgr object. 374 unsigned CurBuffer; 375 std::vector<bool> EndStatementAtEOFStack; 376 377 AsmCond TheCondState; 378 std::vector<AsmCond> TheCondStack; 379 380 /// maps directive names to handler methods in parser 381 /// extensions. Extensions register themselves in this map by calling 382 /// addDirectiveHandler. 383 StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap; 384 385 /// maps assembly-time variable names to variables. 386 struct Variable { 387 enum RedefinableKind { NOT_REDEFINABLE, WARN_ON_REDEFINITION, REDEFINABLE }; 388 389 StringRef Name; 390 RedefinableKind Redefinable = REDEFINABLE; 391 bool IsText = false; 392 int64_t NumericValue = 0; 393 std::string TextValue; 394 }; 395 StringMap<Variable> Variables; 396 397 /// Stack of active struct definitions. 398 SmallVector<StructInfo, 1> StructInProgress; 399 400 /// Maps struct tags to struct definitions. 401 StringMap<StructInfo> Structs; 402 403 /// Maps data location names to types. 404 StringMap<AsmTypeInfo> KnownType; 405 406 /// Stack of active macro instantiations. 407 std::vector<MacroInstantiation*> ActiveMacros; 408 409 /// List of bodies of anonymous macros. 410 std::deque<MCAsmMacro> MacroLikeBodies; 411 412 /// Keeps track of how many .macro's have been instantiated. 413 unsigned NumOfMacroInstantiations; 414 415 /// The values from the last parsed cpp hash file line comment if any. 416 struct CppHashInfoTy { 417 StringRef Filename; 418 int64_t LineNumber; 419 SMLoc Loc; 420 unsigned Buf; 421 CppHashInfoTy() : Filename(), LineNumber(0), Loc(), Buf(0) {} 422 }; 423 CppHashInfoTy CppHashInfo; 424 425 /// The filename from the first cpp hash file line comment, if any. 426 StringRef FirstCppHashFilename; 427 428 /// List of forward directional labels for diagnosis at the end. 429 SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels; 430 431 /// AssemblerDialect. ~OU means unset value and use value provided by MAI. 432 /// Defaults to 1U, meaning Intel. 433 unsigned AssemblerDialect = 1U; 434 435 /// is Darwin compatibility enabled? 436 bool IsDarwin = false; 437 438 /// Are we parsing ms-style inline assembly? 439 bool ParsingMSInlineAsm = false; 440 441 /// Did we already inform the user about inconsistent MD5 usage? 442 bool ReportedInconsistentMD5 = false; 443 444 // Current <...> expression depth. 445 unsigned AngleBracketDepth = 0U; 446 447 // Number of locals defined. 448 uint16_t LocalCounter = 0; 449 450 public: 451 MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, 452 const MCAsmInfo &MAI, unsigned CB); 453 MasmParser(const MasmParser &) = delete; 454 MasmParser &operator=(const MasmParser &) = delete; 455 ~MasmParser() override; 456 457 bool Run(bool NoInitialTextSection, bool NoFinalize = false) override; 458 459 void addDirectiveHandler(StringRef Directive, 460 ExtensionDirectiveHandler Handler) override { 461 ExtensionDirectiveMap[Directive] = Handler; 462 if (DirectiveKindMap.find(Directive) == DirectiveKindMap.end()) { 463 DirectiveKindMap[Directive] = DK_HANDLER_DIRECTIVE; 464 } 465 } 466 467 void addAliasForDirective(StringRef Directive, StringRef Alias) override { 468 DirectiveKindMap[Directive] = DirectiveKindMap[Alias]; 469 } 470 471 /// @name MCAsmParser Interface 472 /// { 473 474 SourceMgr &getSourceManager() override { return SrcMgr; } 475 MCAsmLexer &getLexer() override { return Lexer; } 476 MCContext &getContext() override { return Ctx; } 477 MCStreamer &getStreamer() override { return Out; } 478 479 CodeViewContext &getCVContext() { return Ctx.getCVContext(); } 480 481 unsigned getAssemblerDialect() override { 482 if (AssemblerDialect == ~0U) 483 return MAI.getAssemblerDialect(); 484 else 485 return AssemblerDialect; 486 } 487 void setAssemblerDialect(unsigned i) override { 488 AssemblerDialect = i; 489 } 490 491 void Note(SMLoc L, const Twine &Msg, SMRange Range = None) override; 492 bool Warning(SMLoc L, const Twine &Msg, SMRange Range = None) override; 493 bool printError(SMLoc L, const Twine &Msg, SMRange Range = None) override; 494 495 enum ExpandKind { ExpandMacros, DoNotExpandMacros }; 496 const AsmToken &Lex(ExpandKind ExpandNextToken); 497 const AsmToken &Lex() override { return Lex(ExpandMacros); } 498 499 void setParsingMSInlineAsm(bool V) override { 500 ParsingMSInlineAsm = V; 501 // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and 502 // hex integer literals. 503 Lexer.setLexMasmIntegers(V); 504 } 505 bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; } 506 507 bool isParsingMasm() const override { return true; } 508 509 bool defineMacro(StringRef Name, StringRef Value) override; 510 511 bool lookUpField(StringRef Name, AsmFieldInfo &Info) const override; 512 bool lookUpField(StringRef Base, StringRef Member, 513 AsmFieldInfo &Info) const override; 514 515 bool lookUpType(StringRef Name, AsmTypeInfo &Info) const override; 516 517 bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, 518 unsigned &NumOutputs, unsigned &NumInputs, 519 SmallVectorImpl<std::pair<void *,bool>> &OpDecls, 520 SmallVectorImpl<std::string> &Constraints, 521 SmallVectorImpl<std::string> &Clobbers, 522 const MCInstrInfo *MII, const MCInstPrinter *IP, 523 MCAsmParserSemaCallback &SI) override; 524 525 bool parseExpression(const MCExpr *&Res); 526 bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override; 527 bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc, 528 AsmTypeInfo *TypeInfo) override; 529 bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override; 530 bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res, 531 SMLoc &EndLoc) override; 532 bool parseAbsoluteExpression(int64_t &Res) override; 533 534 /// Parse a floating point expression using the float \p Semantics 535 /// and set \p Res to the value. 536 bool parseRealValue(const fltSemantics &Semantics, APInt &Res); 537 538 /// Parse an identifier or string (as a quoted identifier) 539 /// and set \p Res to the identifier contents. 540 enum IdentifierPositionKind { StandardPosition, StartOfStatement }; 541 bool parseIdentifier(StringRef &Res, IdentifierPositionKind Position); 542 bool parseIdentifier(StringRef &Res) override { 543 return parseIdentifier(Res, StandardPosition); 544 } 545 void eatToEndOfStatement() override; 546 547 bool checkForValidSection() override; 548 549 /// } 550 551 private: 552 bool expandMacros(); 553 const AsmToken peekTok(bool ShouldSkipSpace = true); 554 555 bool parseStatement(ParseStatementInfo &Info, 556 MCAsmParserSemaCallback *SI); 557 bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites); 558 bool parseCppHashLineFilenameComment(SMLoc L); 559 560 bool expandMacro(raw_svector_ostream &OS, StringRef Body, 561 ArrayRef<MCAsmMacroParameter> Parameters, 562 ArrayRef<MCAsmMacroArgument> A, 563 const std::vector<std::string> &Locals, SMLoc L); 564 565 /// Are we inside a macro instantiation? 566 bool isInsideMacroInstantiation() {return !ActiveMacros.empty();} 567 568 /// Handle entry to macro instantiation. 569 /// 570 /// \param M The macro. 571 /// \param NameLoc Instantiation location. 572 bool handleMacroEntry( 573 const MCAsmMacro *M, SMLoc NameLoc, 574 AsmToken::TokenKind ArgumentEndTok = AsmToken::EndOfStatement); 575 576 /// Handle invocation of macro function. 577 /// 578 /// \param M The macro. 579 /// \param NameLoc Invocation location. 580 bool handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc); 581 582 /// Handle exit from macro instantiation. 583 void handleMacroExit(); 584 585 /// Extract AsmTokens for a macro argument. 586 bool 587 parseMacroArgument(const MCAsmMacroParameter *MP, MCAsmMacroArgument &MA, 588 AsmToken::TokenKind EndTok = AsmToken::EndOfStatement); 589 590 /// Parse all macro arguments for a given macro. 591 bool 592 parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A, 593 AsmToken::TokenKind EndTok = AsmToken::EndOfStatement); 594 595 void printMacroInstantiations(); 596 597 bool expandStatement(SMLoc Loc); 598 599 void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg, 600 SMRange Range = None) const { 601 ArrayRef<SMRange> Ranges(Range); 602 SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges); 603 } 604 static void DiagHandler(const SMDiagnostic &Diag, void *Context); 605 606 bool lookUpField(const StructInfo &Structure, StringRef Member, 607 AsmFieldInfo &Info) const; 608 609 /// Should we emit DWARF describing this assembler source? (Returns false if 610 /// the source has .file directives, which means we don't want to generate 611 /// info describing the assembler source itself.) 612 bool enabledGenDwarfForAssembly(); 613 614 /// Enter the specified file. This returns true on failure. 615 bool enterIncludeFile(const std::string &Filename); 616 617 /// Reset the current lexer position to that given by \p Loc. The 618 /// current token is not set; clients should ensure Lex() is called 619 /// subsequently. 620 /// 621 /// \param InBuffer If not 0, should be the known buffer id that contains the 622 /// location. 623 void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0, 624 bool EndStatementAtEOF = true); 625 626 /// Parse up to a token of kind \p EndTok and return the contents from the 627 /// current token up to (but not including) this token; the current token on 628 /// exit will be either this kind or EOF. Reads through instantiated macro 629 /// functions and text macros. 630 SmallVector<StringRef, 1> parseStringRefsTo(AsmToken::TokenKind EndTok); 631 std::string parseStringTo(AsmToken::TokenKind EndTok); 632 633 /// Parse up to the end of statement and return the contents from the current 634 /// token until the end of the statement; the current token on exit will be 635 /// either the EndOfStatement or EOF. 636 StringRef parseStringToEndOfStatement() override; 637 638 bool parseTextItem(std::string &Data); 639 640 unsigned getBinOpPrecedence(AsmToken::TokenKind K, 641 MCBinaryExpr::Opcode &Kind); 642 643 bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc); 644 bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc); 645 bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc); 646 647 bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc); 648 649 bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName); 650 bool parseCVFileId(int64_t &FileId, StringRef DirectiveName); 651 652 // Generic (target and platform independent) directive parsing. 653 enum DirectiveKind { 654 DK_NO_DIRECTIVE, // Placeholder 655 DK_HANDLER_DIRECTIVE, 656 DK_ASSIGN, 657 DK_EQU, 658 DK_TEXTEQU, 659 DK_ASCII, 660 DK_ASCIZ, 661 DK_STRING, 662 DK_BYTE, 663 DK_SBYTE, 664 DK_WORD, 665 DK_SWORD, 666 DK_DWORD, 667 DK_SDWORD, 668 DK_FWORD, 669 DK_QWORD, 670 DK_SQWORD, 671 DK_DB, 672 DK_DD, 673 DK_DF, 674 DK_DQ, 675 DK_DW, 676 DK_REAL4, 677 DK_REAL8, 678 DK_REAL10, 679 DK_ALIGN, 680 DK_EVEN, 681 DK_ORG, 682 DK_ENDR, 683 DK_EXTERN, 684 DK_PUBLIC, 685 DK_COMM, 686 DK_COMMENT, 687 DK_INCLUDE, 688 DK_REPEAT, 689 DK_WHILE, 690 DK_FOR, 691 DK_FORC, 692 DK_IF, 693 DK_IFE, 694 DK_IFB, 695 DK_IFNB, 696 DK_IFDEF, 697 DK_IFNDEF, 698 DK_IFDIF, 699 DK_IFDIFI, 700 DK_IFIDN, 701 DK_IFIDNI, 702 DK_ELSEIF, 703 DK_ELSEIFE, 704 DK_ELSEIFB, 705 DK_ELSEIFNB, 706 DK_ELSEIFDEF, 707 DK_ELSEIFNDEF, 708 DK_ELSEIFDIF, 709 DK_ELSEIFDIFI, 710 DK_ELSEIFIDN, 711 DK_ELSEIFIDNI, 712 DK_ELSE, 713 DK_ENDIF, 714 DK_FILE, 715 DK_LINE, 716 DK_LOC, 717 DK_STABS, 718 DK_CV_FILE, 719 DK_CV_FUNC_ID, 720 DK_CV_INLINE_SITE_ID, 721 DK_CV_LOC, 722 DK_CV_LINETABLE, 723 DK_CV_INLINE_LINETABLE, 724 DK_CV_DEF_RANGE, 725 DK_CV_STRINGTABLE, 726 DK_CV_STRING, 727 DK_CV_FILECHECKSUMS, 728 DK_CV_FILECHECKSUM_OFFSET, 729 DK_CV_FPO_DATA, 730 DK_CFI_SECTIONS, 731 DK_CFI_STARTPROC, 732 DK_CFI_ENDPROC, 733 DK_CFI_DEF_CFA, 734 DK_CFI_DEF_CFA_OFFSET, 735 DK_CFI_ADJUST_CFA_OFFSET, 736 DK_CFI_DEF_CFA_REGISTER, 737 DK_CFI_OFFSET, 738 DK_CFI_REL_OFFSET, 739 DK_CFI_PERSONALITY, 740 DK_CFI_LSDA, 741 DK_CFI_REMEMBER_STATE, 742 DK_CFI_RESTORE_STATE, 743 DK_CFI_SAME_VALUE, 744 DK_CFI_RESTORE, 745 DK_CFI_ESCAPE, 746 DK_CFI_RETURN_COLUMN, 747 DK_CFI_SIGNAL_FRAME, 748 DK_CFI_UNDEFINED, 749 DK_CFI_REGISTER, 750 DK_CFI_WINDOW_SAVE, 751 DK_CFI_B_KEY_FRAME, 752 DK_MACRO, 753 DK_EXITM, 754 DK_ENDM, 755 DK_PURGE, 756 DK_ERR, 757 DK_ERRB, 758 DK_ERRNB, 759 DK_ERRDEF, 760 DK_ERRNDEF, 761 DK_ERRDIF, 762 DK_ERRDIFI, 763 DK_ERRIDN, 764 DK_ERRIDNI, 765 DK_ERRE, 766 DK_ERRNZ, 767 DK_ECHO, 768 DK_STRUCT, 769 DK_UNION, 770 DK_ENDS, 771 DK_END, 772 DK_PUSHFRAME, 773 DK_PUSHREG, 774 DK_SAVEREG, 775 DK_SAVEXMM128, 776 DK_SETFRAME, 777 DK_RADIX, 778 }; 779 780 /// Maps directive name --> DirectiveKind enum, for directives parsed by this 781 /// class. 782 StringMap<DirectiveKind> DirectiveKindMap; 783 784 bool isMacroLikeDirective(); 785 786 // Codeview def_range type parsing. 787 enum CVDefRangeType { 788 CVDR_DEFRANGE = 0, // Placeholder 789 CVDR_DEFRANGE_REGISTER, 790 CVDR_DEFRANGE_FRAMEPOINTER_REL, 791 CVDR_DEFRANGE_SUBFIELD_REGISTER, 792 CVDR_DEFRANGE_REGISTER_REL 793 }; 794 795 /// Maps Codeview def_range types --> CVDefRangeType enum, for Codeview 796 /// def_range types parsed by this class. 797 StringMap<CVDefRangeType> CVDefRangeTypeMap; 798 799 // ".ascii", ".asciz", ".string" 800 bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated); 801 802 // "byte", "word", ... 803 bool emitIntValue(const MCExpr *Value, unsigned Size); 804 bool parseScalarInitializer(unsigned Size, 805 SmallVectorImpl<const MCExpr *> &Values, 806 unsigned StringPadLength = 0); 807 bool parseScalarInstList( 808 unsigned Size, SmallVectorImpl<const MCExpr *> &Values, 809 const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement); 810 bool emitIntegralValues(unsigned Size, unsigned *Count = nullptr); 811 bool addIntegralField(StringRef Name, unsigned Size); 812 bool parseDirectiveValue(StringRef IDVal, unsigned Size); 813 bool parseDirectiveNamedValue(StringRef TypeName, unsigned Size, 814 StringRef Name, SMLoc NameLoc); 815 816 // "real4", "real8", "real10" 817 bool emitRealValues(const fltSemantics &Semantics, unsigned *Count = nullptr); 818 bool addRealField(StringRef Name, const fltSemantics &Semantics, size_t Size); 819 bool parseDirectiveRealValue(StringRef IDVal, const fltSemantics &Semantics, 820 size_t Size); 821 bool parseRealInstList( 822 const fltSemantics &Semantics, SmallVectorImpl<APInt> &Values, 823 const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement); 824 bool parseDirectiveNamedRealValue(StringRef TypeName, 825 const fltSemantics &Semantics, 826 unsigned Size, StringRef Name, 827 SMLoc NameLoc); 828 829 bool parseOptionalAngleBracketOpen(); 830 bool parseAngleBracketClose(const Twine &Msg = "expected '>'"); 831 832 bool parseFieldInitializer(const FieldInfo &Field, 833 FieldInitializer &Initializer); 834 bool parseFieldInitializer(const FieldInfo &Field, 835 const IntFieldInfo &Contents, 836 FieldInitializer &Initializer); 837 bool parseFieldInitializer(const FieldInfo &Field, 838 const RealFieldInfo &Contents, 839 FieldInitializer &Initializer); 840 bool parseFieldInitializer(const FieldInfo &Field, 841 const StructFieldInfo &Contents, 842 FieldInitializer &Initializer); 843 844 bool parseStructInitializer(const StructInfo &Structure, 845 StructInitializer &Initializer); 846 bool parseStructInstList( 847 const StructInfo &Structure, std::vector<StructInitializer> &Initializers, 848 const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement); 849 850 bool emitFieldValue(const FieldInfo &Field); 851 bool emitFieldValue(const FieldInfo &Field, const IntFieldInfo &Contents); 852 bool emitFieldValue(const FieldInfo &Field, const RealFieldInfo &Contents); 853 bool emitFieldValue(const FieldInfo &Field, const StructFieldInfo &Contents); 854 855 bool emitFieldInitializer(const FieldInfo &Field, 856 const FieldInitializer &Initializer); 857 bool emitFieldInitializer(const FieldInfo &Field, 858 const IntFieldInfo &Contents, 859 const IntFieldInfo &Initializer); 860 bool emitFieldInitializer(const FieldInfo &Field, 861 const RealFieldInfo &Contents, 862 const RealFieldInfo &Initializer); 863 bool emitFieldInitializer(const FieldInfo &Field, 864 const StructFieldInfo &Contents, 865 const StructFieldInfo &Initializer); 866 867 bool emitStructInitializer(const StructInfo &Structure, 868 const StructInitializer &Initializer); 869 870 // User-defined types (structs, unions): 871 bool emitStructValues(const StructInfo &Structure, unsigned *Count = nullptr); 872 bool addStructField(StringRef Name, const StructInfo &Structure); 873 bool parseDirectiveStructValue(const StructInfo &Structure, 874 StringRef Directive, SMLoc DirLoc); 875 bool parseDirectiveNamedStructValue(const StructInfo &Structure, 876 StringRef Directive, SMLoc DirLoc, 877 StringRef Name); 878 879 // "=", "equ", "textequ" 880 bool parseDirectiveEquate(StringRef IDVal, StringRef Name, 881 DirectiveKind DirKind, SMLoc NameLoc); 882 883 bool parseDirectiveOrg(); // "org" 884 885 bool emitAlignTo(int64_t Alignment); 886 bool parseDirectiveAlign(); // "align" 887 bool parseDirectiveEven(); // "even" 888 889 // ".file", ".line", ".loc", ".stabs" 890 bool parseDirectiveFile(SMLoc DirectiveLoc); 891 bool parseDirectiveLine(); 892 bool parseDirectiveLoc(); 893 bool parseDirectiveStabs(); 894 895 // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable", 896 // ".cv_inline_linetable", ".cv_def_range", ".cv_string" 897 bool parseDirectiveCVFile(); 898 bool parseDirectiveCVFuncId(); 899 bool parseDirectiveCVInlineSiteId(); 900 bool parseDirectiveCVLoc(); 901 bool parseDirectiveCVLinetable(); 902 bool parseDirectiveCVInlineLinetable(); 903 bool parseDirectiveCVDefRange(); 904 bool parseDirectiveCVString(); 905 bool parseDirectiveCVStringTable(); 906 bool parseDirectiveCVFileChecksums(); 907 bool parseDirectiveCVFileChecksumOffset(); 908 bool parseDirectiveCVFPOData(); 909 910 // .cfi directives 911 bool parseDirectiveCFIRegister(SMLoc DirectiveLoc); 912 bool parseDirectiveCFIWindowSave(); 913 bool parseDirectiveCFISections(); 914 bool parseDirectiveCFIStartProc(); 915 bool parseDirectiveCFIEndProc(); 916 bool parseDirectiveCFIDefCfaOffset(); 917 bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc); 918 bool parseDirectiveCFIAdjustCfaOffset(); 919 bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc); 920 bool parseDirectiveCFIOffset(SMLoc DirectiveLoc); 921 bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc); 922 bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality); 923 bool parseDirectiveCFIRememberState(); 924 bool parseDirectiveCFIRestoreState(); 925 bool parseDirectiveCFISameValue(SMLoc DirectiveLoc); 926 bool parseDirectiveCFIRestore(SMLoc DirectiveLoc); 927 bool parseDirectiveCFIEscape(); 928 bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc); 929 bool parseDirectiveCFISignalFrame(); 930 bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc); 931 932 // macro directives 933 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc); 934 bool parseDirectiveExitMacro(SMLoc DirectiveLoc, StringRef Directive, 935 std::string &Value); 936 bool parseDirectiveEndMacro(StringRef Directive); 937 bool parseDirectiveMacro(StringRef Name, SMLoc NameLoc); 938 939 bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind, 940 StringRef Name, SMLoc NameLoc); 941 bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind); 942 bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc); 943 bool parseDirectiveNestedEnds(); 944 945 /// Parse a directive like ".globl" which accepts a single symbol (which 946 /// should be a label or an external). 947 bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr); 948 949 bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm" 950 951 bool parseDirectiveComment(SMLoc DirectiveLoc); // "comment" 952 953 bool parseDirectiveInclude(); // "include" 954 955 // "if" or "ife" 956 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind); 957 // "ifb" or "ifnb", depending on ExpectBlank. 958 bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank); 959 // "ifidn", "ifdif", "ifidni", or "ifdifi", depending on ExpectEqual and 960 // CaseInsensitive. 961 bool parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual, 962 bool CaseInsensitive); 963 // "ifdef" or "ifndef", depending on expect_defined 964 bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined); 965 // "elseif" or "elseife" 966 bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind); 967 // "elseifb" or "elseifnb", depending on ExpectBlank. 968 bool parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank); 969 // ".elseifdef" or ".elseifndef", depending on expect_defined 970 bool parseDirectiveElseIfdef(SMLoc DirectiveLoc, bool expect_defined); 971 // "elseifidn", "elseifdif", "elseifidni", or "elseifdifi", depending on 972 // ExpectEqual and CaseInsensitive. 973 bool parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual, 974 bool CaseInsensitive); 975 bool parseDirectiveElse(SMLoc DirectiveLoc); // "else" 976 bool parseDirectiveEndIf(SMLoc DirectiveLoc); // "endif" 977 bool parseEscapedString(std::string &Data) override; 978 bool parseAngleBracketString(std::string &Data) override; 979 980 // Macro-like directives 981 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc); 982 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, 983 raw_svector_ostream &OS); 984 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, 985 SMLoc ExitLoc, raw_svector_ostream &OS); 986 bool parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Directive); 987 bool parseDirectiveFor(SMLoc DirectiveLoc, StringRef Directive); 988 bool parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive); 989 bool parseDirectiveWhile(SMLoc DirectiveLoc); 990 991 // "_emit" or "__emit" 992 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info, 993 size_t Len); 994 995 // "align" 996 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info); 997 998 // "end" 999 bool parseDirectiveEnd(SMLoc DirectiveLoc); 1000 1001 // ".err" 1002 bool parseDirectiveError(SMLoc DirectiveLoc); 1003 // ".errb" or ".errnb", depending on ExpectBlank. 1004 bool parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank); 1005 // ".errdef" or ".errndef", depending on ExpectBlank. 1006 bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc, bool ExpectDefined); 1007 // ".erridn", ".errdif", ".erridni", or ".errdifi", depending on ExpectEqual 1008 // and CaseInsensitive. 1009 bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual, 1010 bool CaseInsensitive); 1011 // ".erre" or ".errnz", depending on ExpectZero. 1012 bool parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero); 1013 1014 // ".radix" 1015 bool parseDirectiveRadix(SMLoc DirectiveLoc); 1016 1017 // "echo" 1018 bool parseDirectiveEcho(SMLoc DirectiveLoc); 1019 1020 void initializeDirectiveKindMap(); 1021 void initializeCVDefRangeTypeMap(); 1022 }; 1023 1024 } // end anonymous namespace 1025 1026 namespace llvm { 1027 1028 extern MCAsmParserExtension *createCOFFMasmParser(); 1029 1030 } // end namespace llvm 1031 1032 enum { DEFAULT_ADDRSPACE = 0 }; 1033 1034 MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, 1035 const MCAsmInfo &MAI, unsigned CB = 0) 1036 : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM), 1037 CurBuffer(CB ? CB : SM.getMainFileID()) { 1038 HadError = false; 1039 // Save the old handler. 1040 SavedDiagHandler = SrcMgr.getDiagHandler(); 1041 SavedDiagContext = SrcMgr.getDiagContext(); 1042 // Set our own handler which calls the saved handler. 1043 SrcMgr.setDiagHandler(DiagHandler, this); 1044 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); 1045 EndStatementAtEOFStack.push_back(true); 1046 1047 // Initialize the platform / file format parser. 1048 switch (Ctx.getObjectFileType()) { 1049 case MCContext::IsCOFF: 1050 PlatformParser.reset(createCOFFMasmParser()); 1051 break; 1052 default: 1053 report_fatal_error("llvm-ml currently supports only COFF output."); 1054 break; 1055 } 1056 1057 initializeDirectiveKindMap(); 1058 PlatformParser->Initialize(*this); 1059 initializeCVDefRangeTypeMap(); 1060 1061 NumOfMacroInstantiations = 0; 1062 } 1063 1064 MasmParser::~MasmParser() { 1065 assert((HadError || ActiveMacros.empty()) && 1066 "Unexpected active macro instantiation!"); 1067 1068 // Restore the saved diagnostics handler and context for use during 1069 // finalization. 1070 SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext); 1071 } 1072 1073 void MasmParser::printMacroInstantiations() { 1074 // Print the active macro instantiation stack. 1075 for (std::vector<MacroInstantiation *>::const_reverse_iterator 1076 it = ActiveMacros.rbegin(), 1077 ie = ActiveMacros.rend(); 1078 it != ie; ++it) 1079 printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note, 1080 "while in macro instantiation"); 1081 } 1082 1083 void MasmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) { 1084 printPendingErrors(); 1085 printMessage(L, SourceMgr::DK_Note, Msg, Range); 1086 printMacroInstantiations(); 1087 } 1088 1089 bool MasmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) { 1090 if (getTargetParser().getTargetOptions().MCNoWarn) 1091 return false; 1092 if (getTargetParser().getTargetOptions().MCFatalWarnings) 1093 return Error(L, Msg, Range); 1094 printMessage(L, SourceMgr::DK_Warning, Msg, Range); 1095 printMacroInstantiations(); 1096 return false; 1097 } 1098 1099 bool MasmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) { 1100 HadError = true; 1101 printMessage(L, SourceMgr::DK_Error, Msg, Range); 1102 printMacroInstantiations(); 1103 return true; 1104 } 1105 1106 bool MasmParser::enterIncludeFile(const std::string &Filename) { 1107 std::string IncludedFile; 1108 unsigned NewBuf = 1109 SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); 1110 if (!NewBuf) 1111 return true; 1112 1113 CurBuffer = NewBuf; 1114 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); 1115 EndStatementAtEOFStack.push_back(true); 1116 return false; 1117 } 1118 1119 void MasmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer, 1120 bool EndStatementAtEOF) { 1121 CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc); 1122 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), 1123 Loc.getPointer(), EndStatementAtEOF); 1124 } 1125 1126 bool MasmParser::expandMacros() { 1127 const AsmToken &Tok = getTok(); 1128 1129 auto VarIt = Variables.find(Tok.getIdentifier().lower()); 1130 if (VarIt != Variables.end() && VarIt->second.IsText) { 1131 std::unique_ptr<MemoryBuffer> Instantiation = 1132 MemoryBuffer::getMemBufferCopy(VarIt->second.TextValue, 1133 "<instantiation>"); 1134 1135 // Jump to the macro instantiation and prime the lexer. 1136 CurBuffer = 1137 SrcMgr.AddNewSourceBuffer(std::move(Instantiation), Tok.getEndLoc()); 1138 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), nullptr, 1139 /*EndStatementAtEOF=*/false); 1140 EndStatementAtEOFStack.push_back(false); 1141 Lexer.Lex(); 1142 return false; 1143 } 1144 1145 const llvm::MCAsmMacro *M = 1146 getContext().lookupMacro(Tok.getIdentifier().lower()); 1147 if (M && M->IsFunction && peekTok().is(AsmToken::LParen)) { 1148 // This is a macro function invocation; expand it in place. 1149 const SMLoc MacroLoc = Tok.getLoc(); 1150 const StringRef MacroId = Tok.getIdentifier(); 1151 Lexer.Lex(); 1152 if (handleMacroInvocation(M, MacroLoc)) { 1153 Lexer.UnLex(AsmToken(AsmToken::Error, MacroId)); 1154 Lexer.Lex(); 1155 } 1156 return false; 1157 } 1158 1159 return true; 1160 } 1161 1162 const AsmToken &MasmParser::Lex(ExpandKind ExpandNextToken) { 1163 if (Lexer.getTok().is(AsmToken::Error)) 1164 Error(Lexer.getErrLoc(), Lexer.getErr()); 1165 1166 // if it's a end of statement with a comment in it 1167 if (getTok().is(AsmToken::EndOfStatement)) { 1168 // if this is a line comment output it. 1169 if (!getTok().getString().empty() && getTok().getString().front() != '\n' && 1170 getTok().getString().front() != '\r' && MAI.preserveAsmComments()) 1171 Out.addExplicitComment(Twine(getTok().getString())); 1172 } 1173 1174 const AsmToken *tok = &Lexer.Lex(); 1175 bool StartOfStatement = Lexer.isAtStartOfStatement(); 1176 1177 while (ExpandNextToken == ExpandMacros && tok->is(AsmToken::Identifier)) { 1178 if (StartOfStatement) { 1179 AsmToken NextTok; 1180 MutableArrayRef<AsmToken> Buf(NextTok); 1181 size_t ReadCount = Lexer.peekTokens(Buf); 1182 if (ReadCount && NextTok.is(AsmToken::Identifier) && 1183 (NextTok.getString().equals_insensitive("equ") || 1184 NextTok.getString().equals_insensitive("textequ"))) { 1185 // This looks like an EQU or TEXTEQU directive; don't expand the 1186 // identifier, allowing for redefinitions. 1187 break; 1188 } 1189 } 1190 if (expandMacros()) 1191 break; 1192 } 1193 1194 // Parse comments here to be deferred until end of next statement. 1195 while (tok->is(AsmToken::Comment)) { 1196 if (MAI.preserveAsmComments()) 1197 Out.addExplicitComment(Twine(tok->getString())); 1198 tok = &Lexer.Lex(); 1199 } 1200 1201 // Recognize and bypass line continuations. 1202 while (tok->is(AsmToken::BackSlash) && 1203 peekTok().is(AsmToken::EndOfStatement)) { 1204 // Eat both the backslash and the end of statement. 1205 Lexer.Lex(); 1206 tok = &Lexer.Lex(); 1207 } 1208 1209 if (tok->is(AsmToken::Eof)) { 1210 // If this is the end of an included file, pop the parent file off the 1211 // include stack. 1212 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); 1213 if (ParentIncludeLoc != SMLoc()) { 1214 EndStatementAtEOFStack.pop_back(); 1215 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back()); 1216 return Lex(); 1217 } 1218 EndStatementAtEOFStack.pop_back(); 1219 assert(EndStatementAtEOFStack.empty()); 1220 } 1221 1222 return *tok; 1223 } 1224 1225 const AsmToken MasmParser::peekTok(bool ShouldSkipSpace) { 1226 AsmToken Tok; 1227 1228 MutableArrayRef<AsmToken> Buf(Tok); 1229 size_t ReadCount = Lexer.peekTokens(Buf, ShouldSkipSpace); 1230 1231 if (ReadCount == 0) { 1232 // If this is the end of an included file, pop the parent file off the 1233 // include stack. 1234 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); 1235 if (ParentIncludeLoc != SMLoc()) { 1236 EndStatementAtEOFStack.pop_back(); 1237 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back()); 1238 return peekTok(ShouldSkipSpace); 1239 } 1240 EndStatementAtEOFStack.pop_back(); 1241 assert(EndStatementAtEOFStack.empty()); 1242 } 1243 1244 assert(ReadCount == 1); 1245 return Tok; 1246 } 1247 1248 bool MasmParser::enabledGenDwarfForAssembly() { 1249 // Check whether the user specified -g. 1250 if (!getContext().getGenDwarfForAssembly()) 1251 return false; 1252 // If we haven't encountered any .file directives (which would imply that 1253 // the assembler source was produced with debug info already) then emit one 1254 // describing the assembler source file itself. 1255 if (getContext().getGenDwarfFileNumber() == 0) { 1256 // Use the first #line directive for this, if any. It's preprocessed, so 1257 // there is no checksum, and of course no source directive. 1258 if (!FirstCppHashFilename.empty()) 1259 getContext().setMCLineTableRootFile(/*CUID=*/0, 1260 getContext().getCompilationDir(), 1261 FirstCppHashFilename, 1262 /*Cksum=*/None, /*Source=*/None); 1263 const MCDwarfFile &RootFile = 1264 getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile(); 1265 getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective( 1266 /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name, 1267 RootFile.Checksum, RootFile.Source)); 1268 } 1269 return true; 1270 } 1271 1272 bool MasmParser::Run(bool NoInitialTextSection, bool NoFinalize) { 1273 // Create the initial section, if requested. 1274 if (!NoInitialTextSection) 1275 Out.InitSections(false); 1276 1277 // Prime the lexer. 1278 Lex(); 1279 1280 HadError = false; 1281 AsmCond StartingCondState = TheCondState; 1282 SmallVector<AsmRewrite, 4> AsmStrRewrites; 1283 1284 // If we are generating dwarf for assembly source files save the initial text 1285 // section. (Don't use enabledGenDwarfForAssembly() here, as we aren't 1286 // emitting any actual debug info yet and haven't had a chance to parse any 1287 // embedded .file directives.) 1288 if (getContext().getGenDwarfForAssembly()) { 1289 MCSection *Sec = getStreamer().getCurrentSectionOnly(); 1290 if (!Sec->getBeginSymbol()) { 1291 MCSymbol *SectionStartSym = getContext().createTempSymbol(); 1292 getStreamer().emitLabel(SectionStartSym); 1293 Sec->setBeginSymbol(SectionStartSym); 1294 } 1295 bool InsertResult = getContext().addGenDwarfSection(Sec); 1296 assert(InsertResult && ".text section should not have debug info yet"); 1297 (void)InsertResult; 1298 } 1299 1300 getTargetParser().onBeginOfFile(); 1301 1302 // While we have input, parse each statement. 1303 while (Lexer.isNot(AsmToken::Eof) || 1304 SrcMgr.getParentIncludeLoc(CurBuffer) != SMLoc()) { 1305 // Skip through the EOF at the end of an inclusion. 1306 if (Lexer.is(AsmToken::Eof)) 1307 Lex(); 1308 1309 ParseStatementInfo Info(&AsmStrRewrites); 1310 bool Parsed = parseStatement(Info, nullptr); 1311 1312 // If we have a Lexer Error we are on an Error Token. Load in Lexer Error 1313 // for printing ErrMsg via Lex() only if no (presumably better) parser error 1314 // exists. 1315 if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) { 1316 Lex(); 1317 } 1318 1319 // parseStatement returned true so may need to emit an error. 1320 printPendingErrors(); 1321 1322 // Skipping to the next line if needed. 1323 if (Parsed && !getLexer().isAtStartOfStatement()) 1324 eatToEndOfStatement(); 1325 } 1326 1327 getTargetParser().onEndOfFile(); 1328 printPendingErrors(); 1329 1330 // All errors should have been emitted. 1331 assert(!hasPendingError() && "unexpected error from parseStatement"); 1332 1333 getTargetParser().flushPendingInstructions(getStreamer()); 1334 1335 if (TheCondState.TheCond != StartingCondState.TheCond || 1336 TheCondState.Ignore != StartingCondState.Ignore) 1337 printError(getTok().getLoc(), "unmatched .ifs or .elses"); 1338 // Check to see there are no empty DwarfFile slots. 1339 const auto &LineTables = getContext().getMCDwarfLineTables(); 1340 if (!LineTables.empty()) { 1341 unsigned Index = 0; 1342 for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) { 1343 if (File.Name.empty() && Index != 0) 1344 printError(getTok().getLoc(), "unassigned file number: " + 1345 Twine(Index) + 1346 " for .file directives"); 1347 ++Index; 1348 } 1349 } 1350 1351 // Check to see that all assembler local symbols were actually defined. 1352 // Targets that don't do subsections via symbols may not want this, though, 1353 // so conservatively exclude them. Only do this if we're finalizing, though, 1354 // as otherwise we won't necessarilly have seen everything yet. 1355 if (!NoFinalize) { 1356 if (MAI.hasSubsectionsViaSymbols()) { 1357 for (const auto &TableEntry : getContext().getSymbols()) { 1358 MCSymbol *Sym = TableEntry.getValue(); 1359 // Variable symbols may not be marked as defined, so check those 1360 // explicitly. If we know it's a variable, we have a definition for 1361 // the purposes of this check. 1362 if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined()) 1363 // FIXME: We would really like to refer back to where the symbol was 1364 // first referenced for a source location. We need to add something 1365 // to track that. Currently, we just point to the end of the file. 1366 printError(getTok().getLoc(), "assembler local symbol '" + 1367 Sym->getName() + "' not defined"); 1368 } 1369 } 1370 1371 // Temporary symbols like the ones for directional jumps don't go in the 1372 // symbol table. They also need to be diagnosed in all (final) cases. 1373 for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) { 1374 if (std::get<2>(LocSym)->isUndefined()) { 1375 // Reset the state of any "# line file" directives we've seen to the 1376 // context as it was at the diagnostic site. 1377 CppHashInfo = std::get<1>(LocSym); 1378 printError(std::get<0>(LocSym), "directional label undefined"); 1379 } 1380 } 1381 } 1382 1383 // Finalize the output stream if there are no errors and if the client wants 1384 // us to. 1385 if (!HadError && !NoFinalize) 1386 Out.Finish(Lexer.getLoc()); 1387 1388 return HadError || getContext().hadError(); 1389 } 1390 1391 bool MasmParser::checkForValidSection() { 1392 if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) { 1393 Out.InitSections(false); 1394 return Error(getTok().getLoc(), 1395 "expected section directive before assembly directive"); 1396 } 1397 return false; 1398 } 1399 1400 /// Throw away the rest of the line for testing purposes. 1401 void MasmParser::eatToEndOfStatement() { 1402 while (Lexer.isNot(AsmToken::EndOfStatement)) { 1403 if (Lexer.is(AsmToken::Eof)) { 1404 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); 1405 if (ParentIncludeLoc == SMLoc()) { 1406 break; 1407 } 1408 1409 EndStatementAtEOFStack.pop_back(); 1410 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back()); 1411 } 1412 1413 Lexer.Lex(); 1414 } 1415 1416 // Eat EOL. 1417 if (Lexer.is(AsmToken::EndOfStatement)) 1418 Lexer.Lex(); 1419 } 1420 1421 SmallVector<StringRef, 1> 1422 MasmParser::parseStringRefsTo(AsmToken::TokenKind EndTok) { 1423 SmallVector<StringRef, 1> Refs; 1424 const char *Start = getTok().getLoc().getPointer(); 1425 while (Lexer.isNot(EndTok)) { 1426 if (Lexer.is(AsmToken::Eof)) { 1427 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); 1428 if (ParentIncludeLoc == SMLoc()) { 1429 break; 1430 } 1431 Refs.emplace_back(Start, getTok().getLoc().getPointer() - Start); 1432 1433 EndStatementAtEOFStack.pop_back(); 1434 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back()); 1435 Lexer.Lex(); 1436 Start = getTok().getLoc().getPointer(); 1437 } else { 1438 Lexer.Lex(); 1439 } 1440 } 1441 Refs.emplace_back(Start, getTok().getLoc().getPointer() - Start); 1442 return Refs; 1443 } 1444 1445 std::string MasmParser::parseStringTo(AsmToken::TokenKind EndTok) { 1446 SmallVector<StringRef, 1> Refs = parseStringRefsTo(EndTok); 1447 std::string Str; 1448 for (StringRef S : Refs) { 1449 Str.append(S.str()); 1450 } 1451 return Str; 1452 } 1453 1454 StringRef MasmParser::parseStringToEndOfStatement() { 1455 const char *Start = getTok().getLoc().getPointer(); 1456 1457 while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof)) 1458 Lexer.Lex(); 1459 1460 const char *End = getTok().getLoc().getPointer(); 1461 return StringRef(Start, End - Start); 1462 } 1463 1464 /// Parse a paren expression and return it. 1465 /// NOTE: This assumes the leading '(' has already been consumed. 1466 /// 1467 /// parenexpr ::= expr) 1468 /// 1469 bool MasmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) { 1470 if (parseExpression(Res)) 1471 return true; 1472 if (Lexer.isNot(AsmToken::RParen)) 1473 return TokError("expected ')' in parentheses expression"); 1474 EndLoc = Lexer.getTok().getEndLoc(); 1475 Lex(); 1476 return false; 1477 } 1478 1479 /// Parse a bracket expression and return it. 1480 /// NOTE: This assumes the leading '[' has already been consumed. 1481 /// 1482 /// bracketexpr ::= expr] 1483 /// 1484 bool MasmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) { 1485 if (parseExpression(Res)) 1486 return true; 1487 EndLoc = getTok().getEndLoc(); 1488 if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression")) 1489 return true; 1490 return false; 1491 } 1492 1493 /// Parse a primary expression and return it. 1494 /// primaryexpr ::= (parenexpr 1495 /// primaryexpr ::= symbol 1496 /// primaryexpr ::= number 1497 /// primaryexpr ::= '.' 1498 /// primaryexpr ::= ~,+,-,'not' primaryexpr 1499 /// primaryexpr ::= string 1500 /// (a string is interpreted as a 64-bit number in big-endian base-256) 1501 bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc, 1502 AsmTypeInfo *TypeInfo) { 1503 SMLoc FirstTokenLoc = getLexer().getLoc(); 1504 AsmToken::TokenKind FirstTokenKind = Lexer.getKind(); 1505 switch (FirstTokenKind) { 1506 default: 1507 return TokError("unknown token in expression"); 1508 // If we have an error assume that we've already handled it. 1509 case AsmToken::Error: 1510 return true; 1511 case AsmToken::Exclaim: 1512 Lex(); // Eat the operator. 1513 if (parsePrimaryExpr(Res, EndLoc, nullptr)) 1514 return true; 1515 Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc); 1516 return false; 1517 case AsmToken::Dollar: 1518 case AsmToken::At: 1519 case AsmToken::Identifier: { 1520 StringRef Identifier; 1521 if (parseIdentifier(Identifier)) { 1522 // We may have failed but $ may be a valid token. 1523 if (getTok().is(AsmToken::Dollar)) { 1524 if (Lexer.getMAI().getDollarIsPC()) { 1525 Lex(); 1526 // This is a '$' reference, which references the current PC. Emit a 1527 // temporary label to the streamer and refer to it. 1528 MCSymbol *Sym = Ctx.createTempSymbol(); 1529 Out.emitLabel(Sym); 1530 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, 1531 getContext()); 1532 EndLoc = FirstTokenLoc; 1533 return false; 1534 } 1535 return Error(FirstTokenLoc, "invalid token in expression"); 1536 } 1537 } 1538 // Parse named bitwise negation. 1539 if (Identifier.equals_insensitive("not")) { 1540 if (parsePrimaryExpr(Res, EndLoc, nullptr)) 1541 return true; 1542 Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc); 1543 return false; 1544 } 1545 // Parse symbol variant. 1546 std::pair<StringRef, StringRef> Split; 1547 if (!MAI.useParensForSymbolVariant()) { 1548 if (FirstTokenKind == AsmToken::String) { 1549 if (Lexer.is(AsmToken::At)) { 1550 Lex(); // eat @ 1551 SMLoc AtLoc = getLexer().getLoc(); 1552 StringRef VName; 1553 if (parseIdentifier(VName)) 1554 return Error(AtLoc, "expected symbol variant after '@'"); 1555 1556 Split = std::make_pair(Identifier, VName); 1557 } 1558 } else { 1559 Split = Identifier.split('@'); 1560 } 1561 } else if (Lexer.is(AsmToken::LParen)) { 1562 Lex(); // eat '('. 1563 StringRef VName; 1564 parseIdentifier(VName); 1565 // eat ')'. 1566 if (parseToken(AsmToken::RParen, 1567 "unexpected token in variant, expected ')'")) 1568 return true; 1569 Split = std::make_pair(Identifier, VName); 1570 } 1571 1572 EndLoc = SMLoc::getFromPointer(Identifier.end()); 1573 1574 // This is a symbol reference. 1575 StringRef SymbolName = Identifier; 1576 if (SymbolName.empty()) 1577 return Error(getLexer().getLoc(), "expected a symbol reference"); 1578 1579 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; 1580 1581 // Look up the symbol variant if used. 1582 if (!Split.second.empty()) { 1583 Variant = MCSymbolRefExpr::getVariantKindForName(Split.second); 1584 if (Variant != MCSymbolRefExpr::VK_Invalid) { 1585 SymbolName = Split.first; 1586 } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) { 1587 Variant = MCSymbolRefExpr::VK_None; 1588 } else { 1589 return Error(SMLoc::getFromPointer(Split.second.begin()), 1590 "invalid variant '" + Split.second + "'"); 1591 } 1592 } 1593 1594 // Find the field offset if used. 1595 AsmFieldInfo Info; 1596 Split = SymbolName.split('.'); 1597 if (Split.second.empty()) { 1598 } else { 1599 SymbolName = Split.first; 1600 if (lookUpField(SymbolName, Split.second, Info)) { 1601 std::pair<StringRef, StringRef> BaseMember = Split.second.split('.'); 1602 StringRef Base = BaseMember.first, Member = BaseMember.second; 1603 lookUpField(Base, Member, Info); 1604 } else if (Structs.count(SymbolName.lower())) { 1605 // This is actually a reference to a field offset. 1606 Res = MCConstantExpr::create(Info.Offset, getContext()); 1607 return false; 1608 } 1609 } 1610 1611 MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName); 1612 if (!Sym) { 1613 // Variables use case-insensitive symbol names; if this is a variable, we 1614 // find the symbol using its canonical name. 1615 auto VarIt = Variables.find(SymbolName.lower()); 1616 if (VarIt != Variables.end()) 1617 SymbolName = VarIt->second.Name; 1618 Sym = getContext().getOrCreateSymbol(SymbolName); 1619 } 1620 1621 // If this is an absolute variable reference, substitute it now to preserve 1622 // semantics in the face of reassignment. 1623 if (Sym->isVariable()) { 1624 auto V = Sym->getVariableValue(/*SetUsed*/ false); 1625 bool DoInline = isa<MCConstantExpr>(V) && !Variant; 1626 if (auto TV = dyn_cast<MCTargetExpr>(V)) 1627 DoInline = TV->inlineAssignedExpr(); 1628 if (DoInline) { 1629 if (Variant) 1630 return Error(EndLoc, "unexpected modifier on variable reference"); 1631 Res = Sym->getVariableValue(/*SetUsed*/ false); 1632 return false; 1633 } 1634 } 1635 1636 // Otherwise create a symbol ref. 1637 const MCExpr *SymRef = 1638 MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc); 1639 if (Info.Offset) { 1640 Res = MCBinaryExpr::create( 1641 MCBinaryExpr::Add, SymRef, 1642 MCConstantExpr::create(Info.Offset, getContext()), getContext()); 1643 } else { 1644 Res = SymRef; 1645 } 1646 if (TypeInfo) { 1647 if (Info.Type.Name.empty()) { 1648 auto TypeIt = KnownType.find(Identifier.lower()); 1649 if (TypeIt != KnownType.end()) { 1650 Info.Type = TypeIt->second; 1651 } 1652 } 1653 1654 *TypeInfo = Info.Type; 1655 } 1656 return false; 1657 } 1658 case AsmToken::BigNum: 1659 return TokError("literal value out of range for directive"); 1660 case AsmToken::Integer: { 1661 SMLoc Loc = getTok().getLoc(); 1662 int64_t IntVal = getTok().getIntVal(); 1663 Res = MCConstantExpr::create(IntVal, getContext()); 1664 EndLoc = Lexer.getTok().getEndLoc(); 1665 Lex(); // Eat token. 1666 // Look for 'b' or 'f' following an Integer as a directional label. 1667 if (Lexer.getKind() == AsmToken::Identifier) { 1668 StringRef IDVal = getTok().getString(); 1669 // Look up the symbol variant if used. 1670 std::pair<StringRef, StringRef> Split = IDVal.split('@'); 1671 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; 1672 if (Split.first.size() != IDVal.size()) { 1673 Variant = MCSymbolRefExpr::getVariantKindForName(Split.second); 1674 if (Variant == MCSymbolRefExpr::VK_Invalid) 1675 return TokError("invalid variant '" + Split.second + "'"); 1676 IDVal = Split.first; 1677 } 1678 if (IDVal == "f" || IDVal == "b") { 1679 MCSymbol *Sym = 1680 Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b"); 1681 Res = MCSymbolRefExpr::create(Sym, Variant, getContext()); 1682 if (IDVal == "b" && Sym->isUndefined()) 1683 return Error(Loc, "directional label undefined"); 1684 DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym)); 1685 EndLoc = Lexer.getTok().getEndLoc(); 1686 Lex(); // Eat identifier. 1687 } 1688 } 1689 return false; 1690 } 1691 case AsmToken::String: { 1692 // MASM strings (used as constants) are interpreted as big-endian base-256. 1693 SMLoc ValueLoc = getTok().getLoc(); 1694 std::string Value; 1695 if (parseEscapedString(Value)) 1696 return true; 1697 if (Value.size() > 8) 1698 return Error(ValueLoc, "literal value out of range"); 1699 uint64_t IntValue = 0; 1700 for (const unsigned char CharVal : Value) 1701 IntValue = (IntValue << 8) | CharVal; 1702 Res = MCConstantExpr::create(IntValue, getContext()); 1703 return false; 1704 } 1705 case AsmToken::Real: { 1706 APFloat RealVal(APFloat::IEEEdouble(), getTok().getString()); 1707 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue(); 1708 Res = MCConstantExpr::create(IntVal, getContext()); 1709 EndLoc = Lexer.getTok().getEndLoc(); 1710 Lex(); // Eat token. 1711 return false; 1712 } 1713 case AsmToken::Dot: { 1714 // This is a '.' reference, which references the current PC. Emit a 1715 // temporary label to the streamer and refer to it. 1716 MCSymbol *Sym = Ctx.createTempSymbol(); 1717 Out.emitLabel(Sym); 1718 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 1719 EndLoc = Lexer.getTok().getEndLoc(); 1720 Lex(); // Eat identifier. 1721 return false; 1722 } 1723 case AsmToken::LParen: 1724 Lex(); // Eat the '('. 1725 return parseParenExpr(Res, EndLoc); 1726 case AsmToken::LBrac: 1727 if (!PlatformParser->HasBracketExpressions()) 1728 return TokError("brackets expression not supported on this target"); 1729 Lex(); // Eat the '['. 1730 return parseBracketExpr(Res, EndLoc); 1731 case AsmToken::Minus: 1732 Lex(); // Eat the operator. 1733 if (parsePrimaryExpr(Res, EndLoc, nullptr)) 1734 return true; 1735 Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc); 1736 return false; 1737 case AsmToken::Plus: 1738 Lex(); // Eat the operator. 1739 if (parsePrimaryExpr(Res, EndLoc, nullptr)) 1740 return true; 1741 Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc); 1742 return false; 1743 case AsmToken::Tilde: 1744 Lex(); // Eat the operator. 1745 if (parsePrimaryExpr(Res, EndLoc, nullptr)) 1746 return true; 1747 Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc); 1748 return false; 1749 // MIPS unary expression operators. The lexer won't generate these tokens if 1750 // MCAsmInfo::HasMipsExpressions is false for the target. 1751 case AsmToken::PercentCall16: 1752 case AsmToken::PercentCall_Hi: 1753 case AsmToken::PercentCall_Lo: 1754 case AsmToken::PercentDtprel_Hi: 1755 case AsmToken::PercentDtprel_Lo: 1756 case AsmToken::PercentGot: 1757 case AsmToken::PercentGot_Disp: 1758 case AsmToken::PercentGot_Hi: 1759 case AsmToken::PercentGot_Lo: 1760 case AsmToken::PercentGot_Ofst: 1761 case AsmToken::PercentGot_Page: 1762 case AsmToken::PercentGottprel: 1763 case AsmToken::PercentGp_Rel: 1764 case AsmToken::PercentHi: 1765 case AsmToken::PercentHigher: 1766 case AsmToken::PercentHighest: 1767 case AsmToken::PercentLo: 1768 case AsmToken::PercentNeg: 1769 case AsmToken::PercentPcrel_Hi: 1770 case AsmToken::PercentPcrel_Lo: 1771 case AsmToken::PercentTlsgd: 1772 case AsmToken::PercentTlsldm: 1773 case AsmToken::PercentTprel_Hi: 1774 case AsmToken::PercentTprel_Lo: 1775 Lex(); // Eat the operator. 1776 if (Lexer.isNot(AsmToken::LParen)) 1777 return TokError("expected '(' after operator"); 1778 Lex(); // Eat the operator. 1779 if (parseExpression(Res, EndLoc)) 1780 return true; 1781 if (Lexer.isNot(AsmToken::RParen)) 1782 return TokError("expected ')'"); 1783 Lex(); // Eat the operator. 1784 Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx); 1785 return !Res; 1786 } 1787 } 1788 1789 bool MasmParser::parseExpression(const MCExpr *&Res) { 1790 SMLoc EndLoc; 1791 return parseExpression(Res, EndLoc); 1792 } 1793 1794 /// This function checks if the next token is <string> type or arithmetic. 1795 /// string that begin with character '<' must end with character '>'. 1796 /// otherwise it is arithmetics. 1797 /// If the function returns a 'true' value, 1798 /// the End argument will be filled with the last location pointed to the '>' 1799 /// character. 1800 static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) { 1801 assert((StrLoc.getPointer() != nullptr) && 1802 "Argument to the function cannot be a NULL value"); 1803 const char *CharPtr = StrLoc.getPointer(); 1804 while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') && 1805 (*CharPtr != '\0')) { 1806 if (*CharPtr == '!') 1807 CharPtr++; 1808 CharPtr++; 1809 } 1810 if (*CharPtr == '>') { 1811 EndLoc = StrLoc.getFromPointer(CharPtr + 1); 1812 return true; 1813 } 1814 return false; 1815 } 1816 1817 /// creating a string without the escape characters '!'. 1818 static std::string angleBracketString(StringRef BracketContents) { 1819 std::string Res; 1820 for (size_t Pos = 0; Pos < BracketContents.size(); Pos++) { 1821 if (BracketContents[Pos] == '!') 1822 Pos++; 1823 Res += BracketContents[Pos]; 1824 } 1825 return Res; 1826 } 1827 1828 /// Parse an expression and return it. 1829 /// 1830 /// expr ::= expr &&,|| expr -> lowest. 1831 /// expr ::= expr |,^,&,! expr 1832 /// expr ::= expr ==,!=,<>,<,<=,>,>= expr 1833 /// expr ::= expr <<,>> expr 1834 /// expr ::= expr +,- expr 1835 /// expr ::= expr *,/,% expr -> highest. 1836 /// expr ::= primaryexpr 1837 /// 1838 bool MasmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) { 1839 // Parse the expression. 1840 Res = nullptr; 1841 if (getTargetParser().parsePrimaryExpr(Res, EndLoc) || 1842 parseBinOpRHS(1, Res, EndLoc)) 1843 return true; 1844 1845 // Try to constant fold it up front, if possible. Do not exploit 1846 // assembler here. 1847 int64_t Value; 1848 if (Res->evaluateAsAbsolute(Value)) 1849 Res = MCConstantExpr::create(Value, getContext()); 1850 1851 return false; 1852 } 1853 1854 bool MasmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) { 1855 Res = nullptr; 1856 return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc); 1857 } 1858 1859 bool MasmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res, 1860 SMLoc &EndLoc) { 1861 if (parseParenExpr(Res, EndLoc)) 1862 return true; 1863 1864 for (; ParenDepth > 0; --ParenDepth) { 1865 if (parseBinOpRHS(1, Res, EndLoc)) 1866 return true; 1867 1868 // We don't Lex() the last RParen. 1869 // This is the same behavior as parseParenExpression(). 1870 if (ParenDepth - 1 > 0) { 1871 EndLoc = getTok().getEndLoc(); 1872 if (parseToken(AsmToken::RParen, 1873 "expected ')' in parentheses expression")) 1874 return true; 1875 } 1876 } 1877 return false; 1878 } 1879 1880 bool MasmParser::parseAbsoluteExpression(int64_t &Res) { 1881 const MCExpr *Expr; 1882 1883 SMLoc StartLoc = Lexer.getLoc(); 1884 if (parseExpression(Expr)) 1885 return true; 1886 1887 if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr())) 1888 return Error(StartLoc, "expected absolute expression"); 1889 1890 return false; 1891 } 1892 1893 static unsigned getGNUBinOpPrecedence(AsmToken::TokenKind K, 1894 MCBinaryExpr::Opcode &Kind, 1895 bool ShouldUseLogicalShr, 1896 bool EndExpressionAtGreater) { 1897 switch (K) { 1898 default: 1899 return 0; // not a binop. 1900 1901 // Lowest Precedence: &&, || 1902 case AsmToken::AmpAmp: 1903 Kind = MCBinaryExpr::LAnd; 1904 return 2; 1905 case AsmToken::PipePipe: 1906 Kind = MCBinaryExpr::LOr; 1907 return 1; 1908 1909 // Low Precedence: ==, !=, <>, <, <=, >, >= 1910 case AsmToken::EqualEqual: 1911 Kind = MCBinaryExpr::EQ; 1912 return 3; 1913 case AsmToken::ExclaimEqual: 1914 case AsmToken::LessGreater: 1915 Kind = MCBinaryExpr::NE; 1916 return 3; 1917 case AsmToken::Less: 1918 Kind = MCBinaryExpr::LT; 1919 return 3; 1920 case AsmToken::LessEqual: 1921 Kind = MCBinaryExpr::LTE; 1922 return 3; 1923 case AsmToken::Greater: 1924 if (EndExpressionAtGreater) 1925 return 0; 1926 Kind = MCBinaryExpr::GT; 1927 return 3; 1928 case AsmToken::GreaterEqual: 1929 Kind = MCBinaryExpr::GTE; 1930 return 3; 1931 1932 // Low Intermediate Precedence: +, - 1933 case AsmToken::Plus: 1934 Kind = MCBinaryExpr::Add; 1935 return 4; 1936 case AsmToken::Minus: 1937 Kind = MCBinaryExpr::Sub; 1938 return 4; 1939 1940 // High Intermediate Precedence: |, &, ^ 1941 case AsmToken::Pipe: 1942 Kind = MCBinaryExpr::Or; 1943 return 5; 1944 case AsmToken::Caret: 1945 Kind = MCBinaryExpr::Xor; 1946 return 5; 1947 case AsmToken::Amp: 1948 Kind = MCBinaryExpr::And; 1949 return 5; 1950 1951 // Highest Precedence: *, /, %, <<, >> 1952 case AsmToken::Star: 1953 Kind = MCBinaryExpr::Mul; 1954 return 6; 1955 case AsmToken::Slash: 1956 Kind = MCBinaryExpr::Div; 1957 return 6; 1958 case AsmToken::Percent: 1959 Kind = MCBinaryExpr::Mod; 1960 return 6; 1961 case AsmToken::LessLess: 1962 Kind = MCBinaryExpr::Shl; 1963 return 6; 1964 case AsmToken::GreaterGreater: 1965 if (EndExpressionAtGreater) 1966 return 0; 1967 Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr; 1968 return 6; 1969 } 1970 } 1971 1972 unsigned MasmParser::getBinOpPrecedence(AsmToken::TokenKind K, 1973 MCBinaryExpr::Opcode &Kind) { 1974 bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr(); 1975 return getGNUBinOpPrecedence(K, Kind, ShouldUseLogicalShr, 1976 AngleBracketDepth > 0); 1977 } 1978 1979 /// Parse all binary operators with precedence >= 'Precedence'. 1980 /// Res contains the LHS of the expression on input. 1981 bool MasmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, 1982 SMLoc &EndLoc) { 1983 SMLoc StartLoc = Lexer.getLoc(); 1984 while (true) { 1985 AsmToken::TokenKind TokKind = Lexer.getKind(); 1986 if (Lexer.getKind() == AsmToken::Identifier) { 1987 TokKind = StringSwitch<AsmToken::TokenKind>(Lexer.getTok().getString()) 1988 .CaseLower("and", AsmToken::Amp) 1989 .CaseLower("not", AsmToken::Exclaim) 1990 .CaseLower("or", AsmToken::Pipe) 1991 .CaseLower("eq", AsmToken::EqualEqual) 1992 .CaseLower("ne", AsmToken::ExclaimEqual) 1993 .CaseLower("lt", AsmToken::Less) 1994 .CaseLower("le", AsmToken::LessEqual) 1995 .CaseLower("gt", AsmToken::Greater) 1996 .CaseLower("ge", AsmToken::GreaterEqual) 1997 .Default(TokKind); 1998 } 1999 MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add; 2000 unsigned TokPrec = getBinOpPrecedence(TokKind, Kind); 2001 2002 // If the next token is lower precedence than we are allowed to eat, return 2003 // successfully with what we ate already. 2004 if (TokPrec < Precedence) 2005 return false; 2006 2007 Lex(); 2008 2009 // Eat the next primary expression. 2010 const MCExpr *RHS; 2011 if (getTargetParser().parsePrimaryExpr(RHS, EndLoc)) 2012 return true; 2013 2014 // If BinOp binds less tightly with RHS than the operator after RHS, let 2015 // the pending operator take RHS as its LHS. 2016 MCBinaryExpr::Opcode Dummy; 2017 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy); 2018 if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc)) 2019 return true; 2020 2021 // Merge LHS and RHS according to operator. 2022 Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc); 2023 } 2024 } 2025 2026 /// ParseStatement: 2027 /// ::= % statement 2028 /// ::= EndOfStatement 2029 /// ::= Label* Directive ...Operands... EndOfStatement 2030 /// ::= Label* Identifier OperandList* EndOfStatement 2031 bool MasmParser::parseStatement(ParseStatementInfo &Info, 2032 MCAsmParserSemaCallback *SI) { 2033 assert(!hasPendingError() && "parseStatement started with pending error"); 2034 // Eat initial spaces and comments. 2035 while (Lexer.is(AsmToken::Space)) 2036 Lex(); 2037 if (Lexer.is(AsmToken::EndOfStatement)) { 2038 // If this is a line comment we can drop it safely. 2039 if (getTok().getString().empty() || getTok().getString().front() == '\r' || 2040 getTok().getString().front() == '\n') 2041 Out.AddBlankLine(); 2042 Lex(); 2043 return false; 2044 } 2045 2046 // If preceded by an expansion operator, first expand all text macros and 2047 // macro functions. 2048 if (getTok().is(AsmToken::Percent)) { 2049 SMLoc ExpansionLoc = getTok().getLoc(); 2050 if (parseToken(AsmToken::Percent) || expandStatement(ExpansionLoc)) 2051 return true; 2052 } 2053 2054 // Statements always start with an identifier, unless we're dealing with a 2055 // processor directive (.386, .686, etc.) that lexes as a real. 2056 AsmToken ID = getTok(); 2057 SMLoc IDLoc = ID.getLoc(); 2058 StringRef IDVal; 2059 int64_t LocalLabelVal = -1; 2060 if (Lexer.is(AsmToken::HashDirective)) 2061 return parseCppHashLineFilenameComment(IDLoc); 2062 // Allow an integer followed by a ':' as a directional local label. 2063 if (Lexer.is(AsmToken::Integer)) { 2064 LocalLabelVal = getTok().getIntVal(); 2065 if (LocalLabelVal < 0) { 2066 if (!TheCondState.Ignore) { 2067 Lex(); // always eat a token 2068 return Error(IDLoc, "unexpected token at start of statement"); 2069 } 2070 IDVal = ""; 2071 } else { 2072 IDVal = getTok().getString(); 2073 Lex(); // Consume the integer token to be used as an identifier token. 2074 if (Lexer.getKind() != AsmToken::Colon) { 2075 if (!TheCondState.Ignore) { 2076 Lex(); // always eat a token 2077 return Error(IDLoc, "unexpected token at start of statement"); 2078 } 2079 } 2080 } 2081 } else if (Lexer.is(AsmToken::Dot)) { 2082 // Treat '.' as a valid identifier in this context. 2083 Lex(); 2084 IDVal = "."; 2085 } else if (Lexer.is(AsmToken::LCurly)) { 2086 // Treat '{' as a valid identifier in this context. 2087 Lex(); 2088 IDVal = "{"; 2089 2090 } else if (Lexer.is(AsmToken::RCurly)) { 2091 // Treat '}' as a valid identifier in this context. 2092 Lex(); 2093 IDVal = "}"; 2094 } else if (Lexer.is(AsmToken::Star) && 2095 getTargetParser().starIsStartOfStatement()) { 2096 // Accept '*' as a valid start of statement. 2097 Lex(); 2098 IDVal = "*"; 2099 } else if (Lexer.is(AsmToken::Real)) { 2100 // Treat ".<number>" as a valid identifier in this context. 2101 IDVal = getTok().getString(); 2102 Lex(); // always eat a token 2103 if (!IDVal.startswith(".")) 2104 return Error(IDLoc, "unexpected token at start of statement"); 2105 } else if (parseIdentifier(IDVal, StartOfStatement)) { 2106 if (!TheCondState.Ignore) { 2107 Lex(); // always eat a token 2108 return Error(IDLoc, "unexpected token at start of statement"); 2109 } 2110 IDVal = ""; 2111 } 2112 2113 // Handle conditional assembly here before checking for skipping. We 2114 // have to do this so that .endif isn't skipped in a ".if 0" block for 2115 // example. 2116 StringMap<DirectiveKind>::const_iterator DirKindIt = 2117 DirectiveKindMap.find(IDVal.lower()); 2118 DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end()) 2119 ? DK_NO_DIRECTIVE 2120 : DirKindIt->getValue(); 2121 switch (DirKind) { 2122 default: 2123 break; 2124 case DK_IF: 2125 case DK_IFE: 2126 return parseDirectiveIf(IDLoc, DirKind); 2127 case DK_IFB: 2128 return parseDirectiveIfb(IDLoc, true); 2129 case DK_IFNB: 2130 return parseDirectiveIfb(IDLoc, false); 2131 case DK_IFDEF: 2132 return parseDirectiveIfdef(IDLoc, true); 2133 case DK_IFNDEF: 2134 return parseDirectiveIfdef(IDLoc, false); 2135 case DK_IFDIF: 2136 return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false, 2137 /*CaseInsensitive=*/false); 2138 case DK_IFDIFI: 2139 return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false, 2140 /*CaseInsensitive=*/true); 2141 case DK_IFIDN: 2142 return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true, 2143 /*CaseInsensitive=*/false); 2144 case DK_IFIDNI: 2145 return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true, 2146 /*CaseInsensitive=*/true); 2147 case DK_ELSEIF: 2148 case DK_ELSEIFE: 2149 return parseDirectiveElseIf(IDLoc, DirKind); 2150 case DK_ELSEIFB: 2151 return parseDirectiveElseIfb(IDLoc, true); 2152 case DK_ELSEIFNB: 2153 return parseDirectiveElseIfb(IDLoc, false); 2154 case DK_ELSEIFDEF: 2155 return parseDirectiveElseIfdef(IDLoc, true); 2156 case DK_ELSEIFNDEF: 2157 return parseDirectiveElseIfdef(IDLoc, false); 2158 case DK_ELSEIFDIF: 2159 return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false, 2160 /*CaseInsensitive=*/false); 2161 case DK_ELSEIFDIFI: 2162 return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false, 2163 /*CaseInsensitive=*/true); 2164 case DK_ELSEIFIDN: 2165 return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true, 2166 /*CaseInsensitive=*/false); 2167 case DK_ELSEIFIDNI: 2168 return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true, 2169 /*CaseInsensitive=*/true); 2170 case DK_ELSE: 2171 return parseDirectiveElse(IDLoc); 2172 case DK_ENDIF: 2173 return parseDirectiveEndIf(IDLoc); 2174 } 2175 2176 // Ignore the statement if in the middle of inactive conditional 2177 // (e.g. ".if 0"). 2178 if (TheCondState.Ignore) { 2179 eatToEndOfStatement(); 2180 return false; 2181 } 2182 2183 // FIXME: Recurse on local labels? 2184 2185 // See what kind of statement we have. 2186 switch (Lexer.getKind()) { 2187 case AsmToken::Colon: { 2188 if (!getTargetParser().isLabel(ID)) 2189 break; 2190 if (checkForValidSection()) 2191 return true; 2192 2193 // identifier ':' -> Label. 2194 Lex(); 2195 2196 // Diagnose attempt to use '.' as a label. 2197 if (IDVal == ".") 2198 return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label"); 2199 2200 // Diagnose attempt to use a variable as a label. 2201 // 2202 // FIXME: Diagnostics. Note the location of the definition as a label. 2203 // FIXME: This doesn't diagnose assignment to a symbol which has been 2204 // implicitly marked as external. 2205 MCSymbol *Sym; 2206 if (LocalLabelVal == -1) { 2207 if (ParsingMSInlineAsm && SI) { 2208 StringRef RewrittenLabel = 2209 SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true); 2210 assert(!RewrittenLabel.empty() && 2211 "We should have an internal name here."); 2212 Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(), 2213 RewrittenLabel); 2214 IDVal = RewrittenLabel; 2215 } 2216 Sym = getContext().getOrCreateSymbol(IDVal); 2217 } else 2218 Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal); 2219 // End of Labels should be treated as end of line for lexing 2220 // purposes but that information is not available to the Lexer who 2221 // does not understand Labels. This may cause us to see a Hash 2222 // here instead of a preprocessor line comment. 2223 if (getTok().is(AsmToken::Hash)) { 2224 std::string CommentStr = parseStringTo(AsmToken::EndOfStatement); 2225 Lexer.Lex(); 2226 Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr)); 2227 } 2228 2229 // Consume any end of statement token, if present, to avoid spurious 2230 // AddBlankLine calls(). 2231 if (getTok().is(AsmToken::EndOfStatement)) { 2232 Lex(); 2233 } 2234 2235 getTargetParser().doBeforeLabelEmit(Sym); 2236 2237 // Emit the label. 2238 if (!getTargetParser().isParsingMSInlineAsm()) 2239 Out.emitLabel(Sym, IDLoc); 2240 2241 // If we are generating dwarf for assembly source files then gather the 2242 // info to make a dwarf label entry for this label if needed. 2243 if (enabledGenDwarfForAssembly()) 2244 MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(), 2245 IDLoc); 2246 2247 getTargetParser().onLabelParsed(Sym); 2248 2249 return false; 2250 } 2251 2252 default: // Normal instruction or directive. 2253 break; 2254 } 2255 2256 // If macros are enabled, check to see if this is a macro instantiation. 2257 if (const MCAsmMacro *M = getContext().lookupMacro(IDVal.lower())) { 2258 return handleMacroEntry(M, IDLoc); 2259 } 2260 2261 // Otherwise, we have a normal instruction or directive. 2262 2263 if (DirKind != DK_NO_DIRECTIVE) { 2264 // There are several entities interested in parsing directives: 2265 // 2266 // 1. Asm parser extensions. For example, platform-specific parsers 2267 // (like the ELF parser) register themselves as extensions. 2268 // 2. The target-specific assembly parser. Some directives are target 2269 // specific or may potentially behave differently on certain targets. 2270 // 3. The generic directive parser implemented by this class. These are 2271 // all the directives that behave in a target and platform independent 2272 // manner, or at least have a default behavior that's shared between 2273 // all targets and platforms. 2274 2275 getTargetParser().flushPendingInstructions(getStreamer()); 2276 2277 // Special-case handling of structure-end directives at higher priority, 2278 // since ENDS is overloaded as a segment-end directive. 2279 if (IDVal.equals_insensitive("ends") && StructInProgress.size() > 1 && 2280 getTok().is(AsmToken::EndOfStatement)) { 2281 return parseDirectiveNestedEnds(); 2282 } 2283 2284 // First, check the extension directive map to see if any extension has 2285 // registered itself to parse this directive. 2286 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler = 2287 ExtensionDirectiveMap.lookup(IDVal.lower()); 2288 if (Handler.first) 2289 return (*Handler.second)(Handler.first, IDVal, IDLoc); 2290 2291 // Next, let the target-specific assembly parser try. 2292 SMLoc StartTokLoc = getTok().getLoc(); 2293 bool TPDirectiveReturn = 2294 ID.is(AsmToken::Identifier) && getTargetParser().ParseDirective(ID); 2295 2296 if (hasPendingError()) 2297 return true; 2298 // Currently the return value should be true if we are 2299 // uninterested but as this is at odds with the standard parsing 2300 // convention (return true = error) we have instances of a parsed 2301 // directive that fails returning true as an error. Catch these 2302 // cases as best as possible errors here. 2303 if (TPDirectiveReturn && StartTokLoc != getTok().getLoc()) 2304 return true; 2305 // Return if we did some parsing or believe we succeeded. 2306 if (!TPDirectiveReturn || StartTokLoc != getTok().getLoc()) 2307 return false; 2308 2309 // Finally, if no one else is interested in this directive, it must be 2310 // generic and familiar to this class. 2311 switch (DirKind) { 2312 default: 2313 break; 2314 case DK_ASCII: 2315 return parseDirectiveAscii(IDVal, false); 2316 case DK_ASCIZ: 2317 case DK_STRING: 2318 return parseDirectiveAscii(IDVal, true); 2319 case DK_BYTE: 2320 case DK_SBYTE: 2321 case DK_DB: 2322 return parseDirectiveValue(IDVal, 1); 2323 case DK_WORD: 2324 case DK_SWORD: 2325 case DK_DW: 2326 return parseDirectiveValue(IDVal, 2); 2327 case DK_DWORD: 2328 case DK_SDWORD: 2329 case DK_DD: 2330 return parseDirectiveValue(IDVal, 4); 2331 case DK_FWORD: 2332 case DK_DF: 2333 return parseDirectiveValue(IDVal, 6); 2334 case DK_QWORD: 2335 case DK_SQWORD: 2336 case DK_DQ: 2337 return parseDirectiveValue(IDVal, 8); 2338 case DK_REAL4: 2339 return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4); 2340 case DK_REAL8: 2341 return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8); 2342 case DK_REAL10: 2343 return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10); 2344 case DK_STRUCT: 2345 case DK_UNION: 2346 return parseDirectiveNestedStruct(IDVal, DirKind); 2347 case DK_ENDS: 2348 return parseDirectiveNestedEnds(); 2349 case DK_ALIGN: 2350 return parseDirectiveAlign(); 2351 case DK_EVEN: 2352 return parseDirectiveEven(); 2353 case DK_ORG: 2354 return parseDirectiveOrg(); 2355 case DK_EXTERN: 2356 eatToEndOfStatement(); // .extern is the default, ignore it. 2357 return false; 2358 case DK_PUBLIC: 2359 return parseDirectiveSymbolAttribute(MCSA_Global); 2360 case DK_COMM: 2361 return parseDirectiveComm(/*IsLocal=*/false); 2362 case DK_COMMENT: 2363 return parseDirectiveComment(IDLoc); 2364 case DK_INCLUDE: 2365 return parseDirectiveInclude(); 2366 case DK_REPEAT: 2367 return parseDirectiveRepeat(IDLoc, IDVal); 2368 case DK_WHILE: 2369 return parseDirectiveWhile(IDLoc); 2370 case DK_FOR: 2371 return parseDirectiveFor(IDLoc, IDVal); 2372 case DK_FORC: 2373 return parseDirectiveForc(IDLoc, IDVal); 2374 case DK_FILE: 2375 return parseDirectiveFile(IDLoc); 2376 case DK_LINE: 2377 return parseDirectiveLine(); 2378 case DK_LOC: 2379 return parseDirectiveLoc(); 2380 case DK_STABS: 2381 return parseDirectiveStabs(); 2382 case DK_CV_FILE: 2383 return parseDirectiveCVFile(); 2384 case DK_CV_FUNC_ID: 2385 return parseDirectiveCVFuncId(); 2386 case DK_CV_INLINE_SITE_ID: 2387 return parseDirectiveCVInlineSiteId(); 2388 case DK_CV_LOC: 2389 return parseDirectiveCVLoc(); 2390 case DK_CV_LINETABLE: 2391 return parseDirectiveCVLinetable(); 2392 case DK_CV_INLINE_LINETABLE: 2393 return parseDirectiveCVInlineLinetable(); 2394 case DK_CV_DEF_RANGE: 2395 return parseDirectiveCVDefRange(); 2396 case DK_CV_STRING: 2397 return parseDirectiveCVString(); 2398 case DK_CV_STRINGTABLE: 2399 return parseDirectiveCVStringTable(); 2400 case DK_CV_FILECHECKSUMS: 2401 return parseDirectiveCVFileChecksums(); 2402 case DK_CV_FILECHECKSUM_OFFSET: 2403 return parseDirectiveCVFileChecksumOffset(); 2404 case DK_CV_FPO_DATA: 2405 return parseDirectiveCVFPOData(); 2406 case DK_CFI_SECTIONS: 2407 return parseDirectiveCFISections(); 2408 case DK_CFI_STARTPROC: 2409 return parseDirectiveCFIStartProc(); 2410 case DK_CFI_ENDPROC: 2411 return parseDirectiveCFIEndProc(); 2412 case DK_CFI_DEF_CFA: 2413 return parseDirectiveCFIDefCfa(IDLoc); 2414 case DK_CFI_DEF_CFA_OFFSET: 2415 return parseDirectiveCFIDefCfaOffset(); 2416 case DK_CFI_ADJUST_CFA_OFFSET: 2417 return parseDirectiveCFIAdjustCfaOffset(); 2418 case DK_CFI_DEF_CFA_REGISTER: 2419 return parseDirectiveCFIDefCfaRegister(IDLoc); 2420 case DK_CFI_OFFSET: 2421 return parseDirectiveCFIOffset(IDLoc); 2422 case DK_CFI_REL_OFFSET: 2423 return parseDirectiveCFIRelOffset(IDLoc); 2424 case DK_CFI_PERSONALITY: 2425 return parseDirectiveCFIPersonalityOrLsda(true); 2426 case DK_CFI_LSDA: 2427 return parseDirectiveCFIPersonalityOrLsda(false); 2428 case DK_CFI_REMEMBER_STATE: 2429 return parseDirectiveCFIRememberState(); 2430 case DK_CFI_RESTORE_STATE: 2431 return parseDirectiveCFIRestoreState(); 2432 case DK_CFI_SAME_VALUE: 2433 return parseDirectiveCFISameValue(IDLoc); 2434 case DK_CFI_RESTORE: 2435 return parseDirectiveCFIRestore(IDLoc); 2436 case DK_CFI_ESCAPE: 2437 return parseDirectiveCFIEscape(); 2438 case DK_CFI_RETURN_COLUMN: 2439 return parseDirectiveCFIReturnColumn(IDLoc); 2440 case DK_CFI_SIGNAL_FRAME: 2441 return parseDirectiveCFISignalFrame(); 2442 case DK_CFI_UNDEFINED: 2443 return parseDirectiveCFIUndefined(IDLoc); 2444 case DK_CFI_REGISTER: 2445 return parseDirectiveCFIRegister(IDLoc); 2446 case DK_CFI_WINDOW_SAVE: 2447 return parseDirectiveCFIWindowSave(); 2448 case DK_EXITM: 2449 Info.ExitValue = ""; 2450 return parseDirectiveExitMacro(IDLoc, IDVal, *Info.ExitValue); 2451 case DK_ENDM: 2452 Info.ExitValue = ""; 2453 return parseDirectiveEndMacro(IDVal); 2454 case DK_PURGE: 2455 return parseDirectivePurgeMacro(IDLoc); 2456 case DK_END: 2457 return parseDirectiveEnd(IDLoc); 2458 case DK_ERR: 2459 return parseDirectiveError(IDLoc); 2460 case DK_ERRB: 2461 return parseDirectiveErrorIfb(IDLoc, true); 2462 case DK_ERRNB: 2463 return parseDirectiveErrorIfb(IDLoc, false); 2464 case DK_ERRDEF: 2465 return parseDirectiveErrorIfdef(IDLoc, true); 2466 case DK_ERRNDEF: 2467 return parseDirectiveErrorIfdef(IDLoc, false); 2468 case DK_ERRDIF: 2469 return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false, 2470 /*CaseInsensitive=*/false); 2471 case DK_ERRDIFI: 2472 return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false, 2473 /*CaseInsensitive=*/true); 2474 case DK_ERRIDN: 2475 return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true, 2476 /*CaseInsensitive=*/false); 2477 case DK_ERRIDNI: 2478 return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true, 2479 /*CaseInsensitive=*/true); 2480 case DK_ERRE: 2481 return parseDirectiveErrorIfe(IDLoc, true); 2482 case DK_ERRNZ: 2483 return parseDirectiveErrorIfe(IDLoc, false); 2484 case DK_RADIX: 2485 return parseDirectiveRadix(IDLoc); 2486 case DK_ECHO: 2487 return parseDirectiveEcho(IDLoc); 2488 } 2489 2490 return Error(IDLoc, "unknown directive"); 2491 } 2492 2493 // We also check if this is allocating memory with user-defined type. 2494 auto IDIt = Structs.find(IDVal.lower()); 2495 if (IDIt != Structs.end()) 2496 return parseDirectiveStructValue(/*Structure=*/IDIt->getValue(), IDVal, 2497 IDLoc); 2498 2499 // Non-conditional Microsoft directives sometimes follow their first argument. 2500 const AsmToken nextTok = getTok(); 2501 const StringRef nextVal = nextTok.getString(); 2502 const SMLoc nextLoc = nextTok.getLoc(); 2503 2504 const AsmToken afterNextTok = peekTok(); 2505 2506 // There are several entities interested in parsing infix directives: 2507 // 2508 // 1. Asm parser extensions. For example, platform-specific parsers 2509 // (like the ELF parser) register themselves as extensions. 2510 // 2. The generic directive parser implemented by this class. These are 2511 // all the directives that behave in a target and platform independent 2512 // manner, or at least have a default behavior that's shared between 2513 // all targets and platforms. 2514 2515 getTargetParser().flushPendingInstructions(getStreamer()); 2516 2517 // Special-case handling of structure-end directives at higher priority, since 2518 // ENDS is overloaded as a segment-end directive. 2519 if (nextVal.equals_insensitive("ends") && StructInProgress.size() == 1) { 2520 Lex(); 2521 return parseDirectiveEnds(IDVal, IDLoc); 2522 } 2523 2524 // First, check the extension directive map to see if any extension has 2525 // registered itself to parse this directive. 2526 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler = 2527 ExtensionDirectiveMap.lookup(nextVal.lower()); 2528 if (Handler.first) { 2529 Lex(); 2530 Lexer.UnLex(ID); 2531 return (*Handler.second)(Handler.first, nextVal, nextLoc); 2532 } 2533 2534 // If no one else is interested in this directive, it must be 2535 // generic and familiar to this class. 2536 DirKindIt = DirectiveKindMap.find(nextVal.lower()); 2537 DirKind = (DirKindIt == DirectiveKindMap.end()) 2538 ? DK_NO_DIRECTIVE 2539 : DirKindIt->getValue(); 2540 switch (DirKind) { 2541 default: 2542 break; 2543 case DK_ASSIGN: 2544 case DK_EQU: 2545 case DK_TEXTEQU: 2546 Lex(); 2547 return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc); 2548 case DK_BYTE: 2549 if (afterNextTok.is(AsmToken::Identifier) && 2550 afterNextTok.getString().equals_insensitive("ptr")) { 2551 // Size directive; part of an instruction. 2552 break; 2553 } 2554 LLVM_FALLTHROUGH; 2555 case DK_SBYTE: 2556 case DK_DB: 2557 Lex(); 2558 return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc); 2559 case DK_WORD: 2560 if (afterNextTok.is(AsmToken::Identifier) && 2561 afterNextTok.getString().equals_insensitive("ptr")) { 2562 // Size directive; part of an instruction. 2563 break; 2564 } 2565 LLVM_FALLTHROUGH; 2566 case DK_SWORD: 2567 case DK_DW: 2568 Lex(); 2569 return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc); 2570 case DK_DWORD: 2571 if (afterNextTok.is(AsmToken::Identifier) && 2572 afterNextTok.getString().equals_insensitive("ptr")) { 2573 // Size directive; part of an instruction. 2574 break; 2575 } 2576 LLVM_FALLTHROUGH; 2577 case DK_SDWORD: 2578 case DK_DD: 2579 Lex(); 2580 return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc); 2581 case DK_FWORD: 2582 if (afterNextTok.is(AsmToken::Identifier) && 2583 afterNextTok.getString().equals_insensitive("ptr")) { 2584 // Size directive; part of an instruction. 2585 break; 2586 } 2587 LLVM_FALLTHROUGH; 2588 case DK_DF: 2589 Lex(); 2590 return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc); 2591 case DK_QWORD: 2592 if (afterNextTok.is(AsmToken::Identifier) && 2593 afterNextTok.getString().equals_insensitive("ptr")) { 2594 // Size directive; part of an instruction. 2595 break; 2596 } 2597 LLVM_FALLTHROUGH; 2598 case DK_SQWORD: 2599 case DK_DQ: 2600 Lex(); 2601 return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc); 2602 case DK_REAL4: 2603 Lex(); 2604 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), 4, 2605 IDVal, IDLoc); 2606 case DK_REAL8: 2607 Lex(); 2608 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8, 2609 IDVal, IDLoc); 2610 case DK_REAL10: 2611 Lex(); 2612 return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(), 2613 10, IDVal, IDLoc); 2614 case DK_STRUCT: 2615 case DK_UNION: 2616 Lex(); 2617 return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc); 2618 case DK_ENDS: 2619 Lex(); 2620 return parseDirectiveEnds(IDVal, IDLoc); 2621 case DK_MACRO: 2622 Lex(); 2623 return parseDirectiveMacro(IDVal, IDLoc); 2624 } 2625 2626 // Finally, we check if this is allocating a variable with user-defined type. 2627 auto NextIt = Structs.find(nextVal.lower()); 2628 if (NextIt != Structs.end()) { 2629 Lex(); 2630 return parseDirectiveNamedStructValue(/*Structure=*/NextIt->getValue(), 2631 nextVal, nextLoc, IDVal); 2632 } 2633 2634 // __asm _emit or __asm __emit 2635 if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" || 2636 IDVal == "_EMIT" || IDVal == "__EMIT")) 2637 return parseDirectiveMSEmit(IDLoc, Info, IDVal.size()); 2638 2639 // __asm align 2640 if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN")) 2641 return parseDirectiveMSAlign(IDLoc, Info); 2642 2643 if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN")) 2644 Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4); 2645 if (checkForValidSection()) 2646 return true; 2647 2648 // Canonicalize the opcode to lower case. 2649 std::string OpcodeStr = IDVal.lower(); 2650 ParseInstructionInfo IInfo(Info.AsmRewrites); 2651 bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID, 2652 Info.ParsedOperands); 2653 Info.ParseError = ParseHadError; 2654 2655 // Dump the parsed representation, if requested. 2656 if (getShowParsedOperands()) { 2657 SmallString<256> Str; 2658 raw_svector_ostream OS(Str); 2659 OS << "parsed instruction: ["; 2660 for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) { 2661 if (i != 0) 2662 OS << ", "; 2663 Info.ParsedOperands[i]->print(OS); 2664 } 2665 OS << "]"; 2666 2667 printMessage(IDLoc, SourceMgr::DK_Note, OS.str()); 2668 } 2669 2670 // Fail even if ParseInstruction erroneously returns false. 2671 if (hasPendingError() || ParseHadError) 2672 return true; 2673 2674 // If we are generating dwarf for the current section then generate a .loc 2675 // directive for the instruction. 2676 if (!ParseHadError && enabledGenDwarfForAssembly() && 2677 getContext().getGenDwarfSectionSyms().count( 2678 getStreamer().getCurrentSectionOnly())) { 2679 unsigned Line; 2680 if (ActiveMacros.empty()) 2681 Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer); 2682 else 2683 Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc, 2684 ActiveMacros.front()->ExitBuffer); 2685 2686 // If we previously parsed a cpp hash file line comment then make sure the 2687 // current Dwarf File is for the CppHashFilename if not then emit the 2688 // Dwarf File table for it and adjust the line number for the .loc. 2689 if (!CppHashInfo.Filename.empty()) { 2690 unsigned FileNumber = getStreamer().emitDwarfFileDirective( 2691 0, StringRef(), CppHashInfo.Filename); 2692 getContext().setGenDwarfFileNumber(FileNumber); 2693 2694 unsigned CppHashLocLineNo = 2695 SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf); 2696 Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo); 2697 } 2698 2699 getStreamer().emitDwarfLocDirective( 2700 getContext().getGenDwarfFileNumber(), Line, 0, 2701 DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0, 2702 StringRef()); 2703 } 2704 2705 // If parsing succeeded, match the instruction. 2706 if (!ParseHadError) { 2707 uint64_t ErrorInfo; 2708 if (getTargetParser().MatchAndEmitInstruction( 2709 IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo, 2710 getTargetParser().isParsingMSInlineAsm())) 2711 return true; 2712 } 2713 return false; 2714 } 2715 2716 // Parse and erase curly braces marking block start/end. 2717 bool MasmParser::parseCurlyBlockScope( 2718 SmallVectorImpl<AsmRewrite> &AsmStrRewrites) { 2719 // Identify curly brace marking block start/end. 2720 if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly)) 2721 return false; 2722 2723 SMLoc StartLoc = Lexer.getLoc(); 2724 Lex(); // Eat the brace. 2725 if (Lexer.is(AsmToken::EndOfStatement)) 2726 Lex(); // Eat EndOfStatement following the brace. 2727 2728 // Erase the block start/end brace from the output asm string. 2729 AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() - 2730 StartLoc.getPointer()); 2731 return true; 2732 } 2733 2734 /// parseCppHashLineFilenameComment as this: 2735 /// ::= # number "filename" 2736 bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) { 2737 Lex(); // Eat the hash token. 2738 // Lexer only ever emits HashDirective if it fully formed if it's 2739 // done the checking already so this is an internal error. 2740 assert(getTok().is(AsmToken::Integer) && 2741 "Lexing Cpp line comment: Expected Integer"); 2742 int64_t LineNumber = getTok().getIntVal(); 2743 Lex(); 2744 assert(getTok().is(AsmToken::String) && 2745 "Lexing Cpp line comment: Expected String"); 2746 StringRef Filename = getTok().getString(); 2747 Lex(); 2748 2749 // Get rid of the enclosing quotes. 2750 Filename = Filename.substr(1, Filename.size() - 2); 2751 2752 // Save the SMLoc, Filename and LineNumber for later use by diagnostics 2753 // and possibly DWARF file info. 2754 CppHashInfo.Loc = L; 2755 CppHashInfo.Filename = Filename; 2756 CppHashInfo.LineNumber = LineNumber; 2757 CppHashInfo.Buf = CurBuffer; 2758 if (FirstCppHashFilename.empty()) 2759 FirstCppHashFilename = Filename; 2760 return false; 2761 } 2762 2763 /// will use the last parsed cpp hash line filename comment 2764 /// for the Filename and LineNo if any in the diagnostic. 2765 void MasmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { 2766 const MasmParser *Parser = static_cast<const MasmParser *>(Context); 2767 raw_ostream &OS = errs(); 2768 2769 const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr(); 2770 SMLoc DiagLoc = Diag.getLoc(); 2771 unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); 2772 unsigned CppHashBuf = 2773 Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc); 2774 2775 // Like SourceMgr::printMessage() we need to print the include stack if any 2776 // before printing the message. 2777 unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); 2778 if (!Parser->SavedDiagHandler && DiagCurBuffer && 2779 DiagCurBuffer != DiagSrcMgr.getMainFileID()) { 2780 SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer); 2781 DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS); 2782 } 2783 2784 // If we have not parsed a cpp hash line filename comment or the source 2785 // manager changed or buffer changed (like in a nested include) then just 2786 // print the normal diagnostic using its Filename and LineNo. 2787 if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr || 2788 DiagBuf != CppHashBuf) { 2789 if (Parser->SavedDiagHandler) 2790 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext); 2791 else 2792 Diag.print(nullptr, OS); 2793 return; 2794 } 2795 2796 // Use the CppHashFilename and calculate a line number based on the 2797 // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc 2798 // for the diagnostic. 2799 const std::string &Filename = std::string(Parser->CppHashInfo.Filename); 2800 2801 int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf); 2802 int CppHashLocLineNo = 2803 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf); 2804 int LineNo = 2805 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo); 2806 2807 SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo, 2808 Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(), 2809 Diag.getLineContents(), Diag.getRanges()); 2810 2811 if (Parser->SavedDiagHandler) 2812 Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext); 2813 else 2814 NewDiag.print(nullptr, OS); 2815 } 2816 2817 // This is similar to the IsIdentifierChar function in AsmLexer.cpp, but does 2818 // not accept '.'. 2819 static bool isMacroParameterChar(char C) { 2820 return isAlnum(C) || C == '_' || C == '$' || C == '@' || C == '?'; 2821 } 2822 2823 bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, 2824 ArrayRef<MCAsmMacroParameter> Parameters, 2825 ArrayRef<MCAsmMacroArgument> A, 2826 const std::vector<std::string> &Locals, SMLoc L) { 2827 unsigned NParameters = Parameters.size(); 2828 if (NParameters != A.size()) 2829 return Error(L, "Wrong number of arguments"); 2830 StringMap<std::string> LocalSymbols; 2831 std::string Name; 2832 Name.reserve(6); 2833 for (StringRef Local : Locals) { 2834 raw_string_ostream LocalName(Name); 2835 LocalName << "??" 2836 << format_hex_no_prefix(LocalCounter++, 4, /*Upper=*/true); 2837 LocalSymbols.insert({Local, LocalName.str()}); 2838 Name.clear(); 2839 } 2840 2841 Optional<char> CurrentQuote; 2842 while (!Body.empty()) { 2843 // Scan for the next substitution. 2844 std::size_t End = Body.size(), Pos = 0; 2845 std::size_t IdentifierPos = End; 2846 for (; Pos != End; ++Pos) { 2847 // Find the next possible macro parameter, including preceding a '&' 2848 // inside quotes. 2849 if (Body[Pos] == '&') 2850 break; 2851 if (isMacroParameterChar(Body[Pos])) { 2852 if (!CurrentQuote.hasValue()) 2853 break; 2854 if (IdentifierPos == End) 2855 IdentifierPos = Pos; 2856 } else { 2857 IdentifierPos = End; 2858 } 2859 2860 // Track quotation status 2861 if (!CurrentQuote.hasValue()) { 2862 if (Body[Pos] == '\'' || Body[Pos] == '"') 2863 CurrentQuote = Body[Pos]; 2864 } else if (Body[Pos] == CurrentQuote) { 2865 if (Pos + 1 != End && Body[Pos + 1] == CurrentQuote) { 2866 // Escaped quote, and quotes aren't identifier chars; skip 2867 ++Pos; 2868 continue; 2869 } else { 2870 CurrentQuote.reset(); 2871 } 2872 } 2873 } 2874 if (IdentifierPos != End) { 2875 // We've recognized an identifier before an apostrophe inside quotes; 2876 // check once to see if we can expand it. 2877 Pos = IdentifierPos; 2878 IdentifierPos = End; 2879 } 2880 2881 // Add the prefix. 2882 OS << Body.slice(0, Pos); 2883 2884 // Check if we reached the end. 2885 if (Pos == End) 2886 break; 2887 2888 unsigned I = Pos; 2889 bool InitialAmpersand = (Body[I] == '&'); 2890 if (InitialAmpersand) { 2891 ++I; 2892 ++Pos; 2893 } 2894 while (I < End && isMacroParameterChar(Body[I])) 2895 ++I; 2896 2897 const char *Begin = Body.data() + Pos; 2898 StringRef Argument(Begin, I - Pos); 2899 unsigned Index = 0; 2900 2901 for (; Index < NParameters; ++Index) 2902 if (Parameters[Index].Name == Argument) 2903 break; 2904 2905 if (Index == NParameters) { 2906 if (InitialAmpersand) 2907 OS << '&'; 2908 auto it = LocalSymbols.find(Argument.lower()); 2909 if (it != LocalSymbols.end()) 2910 OS << it->second; 2911 else 2912 OS << Argument; 2913 Pos = I; 2914 } else { 2915 for (const AsmToken &Token : A[Index]) { 2916 // In MASM, you can write '%expr'. 2917 // The prefix '%' evaluates the expression 'expr' 2918 // and uses the result as a string (e.g. replace %(1+2) with the 2919 // string "3"). 2920 // Here, we identify the integer token which is the result of the 2921 // absolute expression evaluation and replace it with its string 2922 // representation. 2923 if (Token.getString().front() == '%' && Token.is(AsmToken::Integer)) 2924 // Emit an integer value to the buffer. 2925 OS << Token.getIntVal(); 2926 else 2927 OS << Token.getString(); 2928 } 2929 2930 Pos += Argument.size(); 2931 if (Pos < End && Body[Pos] == '&') { 2932 ++Pos; 2933 } 2934 } 2935 // Update the scan point. 2936 Body = Body.substr(Pos); 2937 } 2938 2939 return false; 2940 } 2941 2942 static bool isOperator(AsmToken::TokenKind kind) { 2943 switch (kind) { 2944 default: 2945 return false; 2946 case AsmToken::Plus: 2947 case AsmToken::Minus: 2948 case AsmToken::Tilde: 2949 case AsmToken::Slash: 2950 case AsmToken::Star: 2951 case AsmToken::Dot: 2952 case AsmToken::Equal: 2953 case AsmToken::EqualEqual: 2954 case AsmToken::Pipe: 2955 case AsmToken::PipePipe: 2956 case AsmToken::Caret: 2957 case AsmToken::Amp: 2958 case AsmToken::AmpAmp: 2959 case AsmToken::Exclaim: 2960 case AsmToken::ExclaimEqual: 2961 case AsmToken::Less: 2962 case AsmToken::LessEqual: 2963 case AsmToken::LessLess: 2964 case AsmToken::LessGreater: 2965 case AsmToken::Greater: 2966 case AsmToken::GreaterEqual: 2967 case AsmToken::GreaterGreater: 2968 return true; 2969 } 2970 } 2971 2972 namespace { 2973 2974 class AsmLexerSkipSpaceRAII { 2975 public: 2976 AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) { 2977 Lexer.setSkipSpace(SkipSpace); 2978 } 2979 2980 ~AsmLexerSkipSpaceRAII() { 2981 Lexer.setSkipSpace(true); 2982 } 2983 2984 private: 2985 AsmLexer &Lexer; 2986 }; 2987 2988 } // end anonymous namespace 2989 2990 bool MasmParser::parseMacroArgument(const MCAsmMacroParameter *MP, 2991 MCAsmMacroArgument &MA, 2992 AsmToken::TokenKind EndTok) { 2993 if (MP && MP->Vararg) { 2994 if (Lexer.isNot(EndTok)) { 2995 SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok); 2996 for (StringRef S : Str) { 2997 MA.emplace_back(AsmToken::String, S); 2998 } 2999 } 3000 return false; 3001 } 3002 3003 SMLoc StrLoc = Lexer.getLoc(), EndLoc; 3004 if (Lexer.is(AsmToken::Less) && isAngleBracketString(StrLoc, EndLoc)) { 3005 const char *StrChar = StrLoc.getPointer() + 1; 3006 const char *EndChar = EndLoc.getPointer() - 1; 3007 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back()); 3008 /// Eat from '<' to '>'. 3009 Lex(); 3010 MA.emplace_back(AsmToken::String, StringRef(StrChar, EndChar - StrChar)); 3011 return false; 3012 } 3013 3014 unsigned ParenLevel = 0; 3015 3016 // Darwin doesn't use spaces to delmit arguments. 3017 AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin); 3018 3019 bool SpaceEaten; 3020 3021 while (true) { 3022 SpaceEaten = false; 3023 if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal)) 3024 return TokError("unexpected token"); 3025 3026 if (ParenLevel == 0) { 3027 if (Lexer.is(AsmToken::Comma)) 3028 break; 3029 3030 if (Lexer.is(AsmToken::Space)) { 3031 SpaceEaten = true; 3032 Lex(); // Eat spaces. 3033 } 3034 3035 // Spaces can delimit parameters, but could also be part an expression. 3036 // If the token after a space is an operator, add the token and the next 3037 // one into this argument 3038 if (!IsDarwin) { 3039 if (isOperator(Lexer.getKind()) && Lexer.isNot(EndTok)) { 3040 MA.push_back(getTok()); 3041 Lex(); 3042 3043 // Whitespace after an operator can be ignored. 3044 if (Lexer.is(AsmToken::Space)) 3045 Lex(); 3046 3047 continue; 3048 } 3049 } 3050 if (SpaceEaten) 3051 break; 3052 } 3053 3054 // handleMacroEntry relies on not advancing the lexer here 3055 // to be able to fill in the remaining default parameter values 3056 if (Lexer.is(EndTok) && (EndTok != AsmToken::RParen || ParenLevel == 0)) 3057 break; 3058 3059 // Adjust the current parentheses level. 3060 if (Lexer.is(AsmToken::LParen)) 3061 ++ParenLevel; 3062 else if (Lexer.is(AsmToken::RParen) && ParenLevel) 3063 --ParenLevel; 3064 3065 // Append the token to the current argument list. 3066 MA.push_back(getTok()); 3067 Lex(); 3068 } 3069 3070 if (ParenLevel != 0) 3071 return TokError("unbalanced parentheses in argument"); 3072 3073 if (MA.empty() && MP) { 3074 if (MP->Required) { 3075 return TokError("missing value for required parameter '" + MP->Name + 3076 "'"); 3077 } else { 3078 MA = MP->Value; 3079 } 3080 } 3081 return false; 3082 } 3083 3084 // Parse the macro instantiation arguments. 3085 bool MasmParser::parseMacroArguments(const MCAsmMacro *M, 3086 MCAsmMacroArguments &A, 3087 AsmToken::TokenKind EndTok) { 3088 const unsigned NParameters = M ? M->Parameters.size() : 0; 3089 bool NamedParametersFound = false; 3090 SmallVector<SMLoc, 4> FALocs; 3091 3092 A.resize(NParameters); 3093 FALocs.resize(NParameters); 3094 3095 // Parse two kinds of macro invocations: 3096 // - macros defined without any parameters accept an arbitrary number of them 3097 // - macros defined with parameters accept at most that many of them 3098 for (unsigned Parameter = 0; !NParameters || Parameter < NParameters; 3099 ++Parameter) { 3100 SMLoc IDLoc = Lexer.getLoc(); 3101 MCAsmMacroParameter FA; 3102 3103 if (Lexer.is(AsmToken::Identifier) && peekTok().is(AsmToken::Equal)) { 3104 if (parseIdentifier(FA.Name)) 3105 return Error(IDLoc, "invalid argument identifier for formal argument"); 3106 3107 if (Lexer.isNot(AsmToken::Equal)) 3108 return TokError("expected '=' after formal parameter identifier"); 3109 3110 Lex(); 3111 3112 NamedParametersFound = true; 3113 } 3114 3115 if (NamedParametersFound && FA.Name.empty()) 3116 return Error(IDLoc, "cannot mix positional and keyword arguments"); 3117 3118 unsigned PI = Parameter; 3119 if (!FA.Name.empty()) { 3120 assert(M && "expected macro to be defined"); 3121 unsigned FAI = 0; 3122 for (FAI = 0; FAI < NParameters; ++FAI) 3123 if (M->Parameters[FAI].Name == FA.Name) 3124 break; 3125 3126 if (FAI >= NParameters) { 3127 return Error(IDLoc, "parameter named '" + FA.Name + 3128 "' does not exist for macro '" + M->Name + "'"); 3129 } 3130 PI = FAI; 3131 } 3132 const MCAsmMacroParameter *MP = nullptr; 3133 if (M && PI < NParameters) 3134 MP = &M->Parameters[PI]; 3135 3136 SMLoc StrLoc = Lexer.getLoc(); 3137 SMLoc EndLoc; 3138 if (Lexer.is(AsmToken::Percent)) { 3139 const MCExpr *AbsoluteExp; 3140 int64_t Value; 3141 /// Eat '%'. 3142 Lex(); 3143 if (parseExpression(AbsoluteExp, EndLoc)) 3144 return false; 3145 if (!AbsoluteExp->evaluateAsAbsolute(Value, 3146 getStreamer().getAssemblerPtr())) 3147 return Error(StrLoc, "expected absolute expression"); 3148 const char *StrChar = StrLoc.getPointer(); 3149 const char *EndChar = EndLoc.getPointer(); 3150 AsmToken newToken(AsmToken::Integer, 3151 StringRef(StrChar, EndChar - StrChar), Value); 3152 FA.Value.push_back(newToken); 3153 } else if (parseMacroArgument(MP, FA.Value, EndTok)) { 3154 if (M) 3155 return addErrorSuffix(" in '" + M->Name + "' macro"); 3156 else 3157 return true; 3158 } 3159 3160 if (!FA.Value.empty()) { 3161 if (A.size() <= PI) 3162 A.resize(PI + 1); 3163 A[PI] = FA.Value; 3164 3165 if (FALocs.size() <= PI) 3166 FALocs.resize(PI + 1); 3167 3168 FALocs[PI] = Lexer.getLoc(); 3169 } 3170 3171 // At the end of the statement, fill in remaining arguments that have 3172 // default values. If there aren't any, then the next argument is 3173 // required but missing 3174 if (Lexer.is(EndTok)) { 3175 bool Failure = false; 3176 for (unsigned FAI = 0; FAI < NParameters; ++FAI) { 3177 if (A[FAI].empty()) { 3178 if (M->Parameters[FAI].Required) { 3179 Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(), 3180 "missing value for required parameter " 3181 "'" + 3182 M->Parameters[FAI].Name + "' in macro '" + M->Name + "'"); 3183 Failure = true; 3184 } 3185 3186 if (!M->Parameters[FAI].Value.empty()) 3187 A[FAI] = M->Parameters[FAI].Value; 3188 } 3189 } 3190 return Failure; 3191 } 3192 3193 if (Lexer.is(AsmToken::Comma)) 3194 Lex(); 3195 } 3196 3197 return TokError("too many positional arguments"); 3198 } 3199 3200 bool MasmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc, 3201 AsmToken::TokenKind ArgumentEndTok) { 3202 // Arbitrarily limit macro nesting depth (default matches 'as'). We can 3203 // eliminate this, although we should protect against infinite loops. 3204 unsigned MaxNestingDepth = AsmMacroMaxNestingDepth; 3205 if (ActiveMacros.size() == MaxNestingDepth) { 3206 std::ostringstream MaxNestingDepthError; 3207 MaxNestingDepthError << "macros cannot be nested more than " 3208 << MaxNestingDepth << " levels deep." 3209 << " Use -asm-macro-max-nesting-depth to increase " 3210 "this limit."; 3211 return TokError(MaxNestingDepthError.str()); 3212 } 3213 3214 MCAsmMacroArguments A; 3215 if (parseMacroArguments(M, A, ArgumentEndTok)) 3216 return true; 3217 3218 // Macro instantiation is lexical, unfortunately. We construct a new buffer 3219 // to hold the macro body with substitutions. 3220 SmallString<256> Buf; 3221 StringRef Body = M->Body; 3222 raw_svector_ostream OS(Buf); 3223 3224 if (expandMacro(OS, Body, M->Parameters, A, M->Locals, getTok().getLoc())) 3225 return true; 3226 3227 // We include the endm in the buffer as our cue to exit the macro 3228 // instantiation. 3229 OS << "endm\n"; 3230 3231 std::unique_ptr<MemoryBuffer> Instantiation = 3232 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>"); 3233 3234 // Create the macro instantiation object and add to the current macro 3235 // instantiation stack. 3236 MacroInstantiation *MI = new MacroInstantiation{ 3237 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()}; 3238 ActiveMacros.push_back(MI); 3239 3240 ++NumOfMacroInstantiations; 3241 3242 // Jump to the macro instantiation and prime the lexer. 3243 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc()); 3244 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); 3245 EndStatementAtEOFStack.push_back(true); 3246 Lex(); 3247 3248 return false; 3249 } 3250 3251 void MasmParser::handleMacroExit() { 3252 // Jump to the token we should return to, and consume it. 3253 EndStatementAtEOFStack.pop_back(); 3254 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer, 3255 EndStatementAtEOFStack.back()); 3256 Lex(); 3257 3258 // Pop the instantiation entry. 3259 delete ActiveMacros.back(); 3260 ActiveMacros.pop_back(); 3261 } 3262 3263 bool MasmParser::handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc) { 3264 if (!M->IsFunction) 3265 return Error(NameLoc, "cannot invoke macro procedure as function"); 3266 3267 if (parseToken(AsmToken::LParen, "invoking macro function '" + M->Name + 3268 "' requires arguments in parentheses") || 3269 handleMacroEntry(M, NameLoc, AsmToken::RParen)) 3270 return true; 3271 3272 // Parse all statements in the macro, retrieving the exit value when it ends. 3273 std::string ExitValue; 3274 SmallVector<AsmRewrite, 4> AsmStrRewrites; 3275 while (Lexer.isNot(AsmToken::Eof)) { 3276 ParseStatementInfo Info(&AsmStrRewrites); 3277 bool Parsed = parseStatement(Info, nullptr); 3278 3279 if (!Parsed && Info.ExitValue.hasValue()) { 3280 ExitValue = std::move(*Info.ExitValue); 3281 break; 3282 } 3283 3284 // If we have a Lexer Error we are on an Error Token. Load in Lexer Error 3285 // for printing ErrMsg via Lex() only if no (presumably better) parser error 3286 // exists. 3287 if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) { 3288 Lex(); 3289 } 3290 3291 // parseStatement returned true so may need to emit an error. 3292 printPendingErrors(); 3293 3294 // Skipping to the next line if needed. 3295 if (Parsed && !getLexer().isAtStartOfStatement()) 3296 eatToEndOfStatement(); 3297 } 3298 3299 // Consume the right-parenthesis on the other side of the arguments. 3300 if (parseToken(AsmToken::RParen, "invoking macro function '" + M->Name + 3301 "' requires arguments in parentheses")) 3302 return true; 3303 3304 // Exit values may require lexing, unfortunately. We construct a new buffer to 3305 // hold the exit value. 3306 std::unique_ptr<MemoryBuffer> MacroValue = 3307 MemoryBuffer::getMemBufferCopy(ExitValue, "<macro-value>"); 3308 3309 // Jump from this location to the instantiated exit value, and prime the 3310 // lexer. 3311 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(MacroValue), Lexer.getLoc()); 3312 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), nullptr, 3313 /*EndStatementAtEOF=*/false); 3314 EndStatementAtEOFStack.push_back(false); 3315 Lex(); 3316 3317 return false; 3318 } 3319 3320 /// parseIdentifier: 3321 /// ::= identifier 3322 /// ::= string 3323 bool MasmParser::parseIdentifier(StringRef &Res, 3324 IdentifierPositionKind Position) { 3325 // The assembler has relaxed rules for accepting identifiers, in particular we 3326 // allow things like '.globl $foo' and '.def @feat.00', which would normally 3327 // be separate tokens. At this level, we have already lexed so we cannot 3328 // (currently) handle this as a context dependent token, instead we detect 3329 // adjacent tokens and return the combined identifier. 3330 if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) { 3331 SMLoc PrefixLoc = getLexer().getLoc(); 3332 3333 // Consume the prefix character, and check for a following identifier. 3334 3335 AsmToken nextTok = peekTok(false); 3336 3337 if (nextTok.isNot(AsmToken::Identifier)) 3338 return true; 3339 3340 // We have a '$' or '@' followed by an identifier, make sure they are adjacent. 3341 if (PrefixLoc.getPointer() + 1 != nextTok.getLoc().getPointer()) 3342 return true; 3343 3344 // eat $ or @ 3345 Lexer.Lex(); // Lexer's Lex guarantees consecutive token. 3346 // Construct the joined identifier and consume the token. 3347 Res = 3348 StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1); 3349 Lex(); // Parser Lex to maintain invariants. 3350 return false; 3351 } 3352 3353 if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String)) 3354 return true; 3355 3356 Res = getTok().getIdentifier(); 3357 3358 // Consume the identifier token - but if parsing certain directives, avoid 3359 // lexical expansion of the next token. 3360 ExpandKind ExpandNextToken = ExpandMacros; 3361 if (Position == StartOfStatement && 3362 StringSwitch<bool>(Res) 3363 .CaseLower("echo", true) 3364 .CasesLower("ifdef", "ifndef", "elseifdef", "elseifndef", true) 3365 .Default(false)) { 3366 ExpandNextToken = DoNotExpandMacros; 3367 } 3368 Lex(ExpandNextToken); 3369 3370 return false; 3371 } 3372 3373 /// parseDirectiveEquate: 3374 /// ::= name "=" expression 3375 /// | name "equ" expression (not redefinable) 3376 /// | name "equ" text-list 3377 /// | name "textequ" text-list (redefinability unspecified) 3378 bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name, 3379 DirectiveKind DirKind, SMLoc NameLoc) { 3380 Variable &Var = Variables[Name.lower()]; 3381 if (Var.Name.empty()) { 3382 Var.Name = Name; 3383 } 3384 3385 SMLoc StartLoc = Lexer.getLoc(); 3386 if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) { 3387 // "equ" and "textequ" both allow text expressions. 3388 std::string Value; 3389 std::string TextItem; 3390 if (!parseTextItem(TextItem)) { 3391 Value += TextItem; 3392 3393 // Accept a text-list, not just one text-item. 3394 auto parseItem = [&]() -> bool { 3395 if (parseTextItem(TextItem)) 3396 return TokError("expected text item"); 3397 Value += TextItem; 3398 return false; 3399 }; 3400 if (parseOptionalToken(AsmToken::Comma) && parseMany(parseItem)) 3401 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); 3402 3403 if (!Var.IsText || Var.TextValue != Value) { 3404 switch (Var.Redefinable) { 3405 case Variable::NOT_REDEFINABLE: 3406 return Error(getTok().getLoc(), "invalid variable redefinition"); 3407 case Variable::WARN_ON_REDEFINITION: 3408 if (Warning(NameLoc, "redefining '" + Name + 3409 "', already defined on the command line")) { 3410 return true; 3411 } 3412 break; 3413 default: 3414 break; 3415 } 3416 } 3417 Var.IsText = true; 3418 Var.TextValue = Value; 3419 Var.Redefinable = Variable::REDEFINABLE; 3420 3421 return false; 3422 } 3423 } 3424 if (DirKind == DK_TEXTEQU) 3425 return TokError("expected <text> in '" + Twine(IDVal) + "' directive"); 3426 3427 // Parse as expression assignment. 3428 const MCExpr *Expr; 3429 SMLoc EndLoc; 3430 if (parseExpression(Expr, EndLoc)) 3431 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); 3432 3433 int64_t Value; 3434 if (!Expr->evaluateAsAbsolute(Value, getStreamer().getAssemblerPtr())) { 3435 // Not an absolute expression; define as a text replacement. 3436 StringRef ExprAsString = StringRef( 3437 StartLoc.getPointer(), EndLoc.getPointer() - StartLoc.getPointer()); 3438 if (!Var.IsText || Var.TextValue != ExprAsString) { 3439 switch (Var.Redefinable) { 3440 case Variable::NOT_REDEFINABLE: 3441 return Error(getTok().getLoc(), "invalid variable redefinition"); 3442 case Variable::WARN_ON_REDEFINITION: 3443 if (Warning(NameLoc, "redefining '" + Name + 3444 "', already defined on the command line")) { 3445 return true; 3446 } 3447 break; 3448 default: 3449 break; 3450 } 3451 } 3452 Var.IsText = true; 3453 Var.TextValue = ExprAsString.str(); 3454 } else { 3455 if (Var.IsText || Var.NumericValue != Value) { 3456 switch (Var.Redefinable) { 3457 case Variable::NOT_REDEFINABLE: 3458 return Error(getTok().getLoc(), "invalid variable redefinition"); 3459 case Variable::WARN_ON_REDEFINITION: 3460 if (Warning(NameLoc, "redefining '" + Name + 3461 "', already defined on the command line")) { 3462 return true; 3463 } 3464 break; 3465 default: 3466 break; 3467 } 3468 } 3469 Var.NumericValue = Value; 3470 } 3471 Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE 3472 : Variable::NOT_REDEFINABLE; 3473 3474 MCSymbol *Sym = getContext().getOrCreateSymbol(Var.Name); 3475 Sym->setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE); 3476 Sym->setVariableValue(Expr); 3477 Sym->setExternal(false); 3478 3479 return false; 3480 } 3481 3482 bool MasmParser::parseEscapedString(std::string &Data) { 3483 if (check(getTok().isNot(AsmToken::String), "expected string")) 3484 return true; 3485 3486 Data = ""; 3487 char Quote = getTok().getString().front(); 3488 StringRef Str = getTok().getStringContents(); 3489 Data.reserve(Str.size()); 3490 for (size_t i = 0, e = Str.size(); i != e; ++i) { 3491 Data.push_back(Str[i]); 3492 if (Str[i] == Quote) { 3493 // MASM treats doubled delimiting quotes as an escaped delimiting quote. 3494 // If we're escaping the string's trailing delimiter, we're definitely 3495 // missing a quotation mark. 3496 if (i + 1 == Str.size()) 3497 return Error(getTok().getLoc(), "missing quotation mark in string"); 3498 if (Str[i + 1] == Quote) 3499 ++i; 3500 } 3501 } 3502 3503 Lex(); 3504 return false; 3505 } 3506 3507 bool MasmParser::parseAngleBracketString(std::string &Data) { 3508 SMLoc EndLoc, StartLoc = getTok().getLoc(); 3509 if (isAngleBracketString(StartLoc, EndLoc)) { 3510 const char *StartChar = StartLoc.getPointer() + 1; 3511 const char *EndChar = EndLoc.getPointer() - 1; 3512 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back()); 3513 // Eat from '<' to '>'. 3514 Lex(); 3515 3516 Data = angleBracketString(StringRef(StartChar, EndChar - StartChar)); 3517 return false; 3518 } 3519 return true; 3520 } 3521 3522 /// textItem ::= textLiteral | textMacroID | % constExpr 3523 bool MasmParser::parseTextItem(std::string &Data) { 3524 switch (getTok().getKind()) { 3525 default: 3526 return true; 3527 case AsmToken::Percent: { 3528 int64_t Res; 3529 if (parseToken(AsmToken::Percent) || parseAbsoluteExpression(Res)) 3530 return true; 3531 Data = std::to_string(Res); 3532 return false; 3533 } 3534 case AsmToken::Less: 3535 case AsmToken::LessEqual: 3536 case AsmToken::LessLess: 3537 case AsmToken::LessGreater: 3538 return parseAngleBracketString(Data); 3539 case AsmToken::Identifier: { 3540 // This must be a text macro; we need to expand it accordingly. 3541 StringRef ID; 3542 if (parseIdentifier(ID)) 3543 return true; 3544 Data = ID.str(); 3545 3546 auto it = Variables.find(ID.lower()); 3547 if (it == Variables.end()) { 3548 // Not a variable; since we haven't used the token, put it back for better 3549 // error recovery. 3550 getLexer().UnLex(AsmToken(AsmToken::Identifier, ID)); 3551 return true; 3552 } 3553 3554 while (it != Variables.end()) { 3555 const Variable &Var = it->second; 3556 if (!Var.IsText) { 3557 // Not a text macro; not usable in TextItem context. Since we haven't 3558 // used the token, put it back for better error recovery. 3559 getLexer().UnLex(AsmToken(AsmToken::Identifier, ID)); 3560 return true; 3561 } 3562 Data = Var.TextValue; 3563 it = Variables.find(StringRef(Data).lower()); 3564 } 3565 return false; 3566 } 3567 } 3568 llvm_unreachable("unhandled token kind"); 3569 } 3570 3571 /// parseDirectiveAscii: 3572 /// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ] 3573 bool MasmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) { 3574 auto parseOp = [&]() -> bool { 3575 std::string Data; 3576 if (checkForValidSection() || parseEscapedString(Data)) 3577 return true; 3578 getStreamer().emitBytes(Data); 3579 if (ZeroTerminated) 3580 getStreamer().emitBytes(StringRef("\0", 1)); 3581 return false; 3582 }; 3583 3584 if (parseMany(parseOp)) 3585 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); 3586 return false; 3587 } 3588 3589 bool MasmParser::emitIntValue(const MCExpr *Value, unsigned Size) { 3590 // Special case constant expressions to match code generator. 3591 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { 3592 assert(Size <= 8 && "Invalid size"); 3593 int64_t IntValue = MCE->getValue(); 3594 if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue)) 3595 return Error(MCE->getLoc(), "out of range literal value"); 3596 getStreamer().emitIntValue(IntValue, Size); 3597 } else { 3598 const MCSymbolRefExpr *MSE = dyn_cast<MCSymbolRefExpr>(Value); 3599 if (MSE && MSE->getSymbol().getName() == "?") { 3600 // ? initializer; treat as 0. 3601 getStreamer().emitIntValue(0, Size); 3602 } else { 3603 getStreamer().emitValue(Value, Size, Value->getLoc()); 3604 } 3605 } 3606 return false; 3607 } 3608 3609 bool MasmParser::parseScalarInitializer(unsigned Size, 3610 SmallVectorImpl<const MCExpr *> &Values, 3611 unsigned StringPadLength) { 3612 if (Size == 1 && getTok().is(AsmToken::String)) { 3613 std::string Value; 3614 if (parseEscapedString(Value)) 3615 return true; 3616 // Treat each character as an initializer. 3617 for (const unsigned char CharVal : Value) 3618 Values.push_back(MCConstantExpr::create(CharVal, getContext())); 3619 3620 // Pad the string with spaces to the specified length. 3621 for (size_t i = Value.size(); i < StringPadLength; ++i) 3622 Values.push_back(MCConstantExpr::create(' ', getContext())); 3623 } else { 3624 const MCExpr *Value; 3625 if (parseExpression(Value)) 3626 return true; 3627 if (getTok().is(AsmToken::Identifier) && 3628 getTok().getString().equals_insensitive("dup")) { 3629 Lex(); // Eat 'dup'. 3630 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); 3631 if (!MCE) 3632 return Error(Value->getLoc(), 3633 "cannot repeat value a non-constant number of times"); 3634 const int64_t Repetitions = MCE->getValue(); 3635 if (Repetitions < 0) 3636 return Error(Value->getLoc(), 3637 "cannot repeat value a negative number of times"); 3638 3639 SmallVector<const MCExpr *, 1> DuplicatedValues; 3640 if (parseToken(AsmToken::LParen, 3641 "parentheses required for 'dup' contents") || 3642 parseScalarInstList(Size, DuplicatedValues) || 3643 parseToken(AsmToken::RParen, "unmatched parentheses")) 3644 return true; 3645 3646 for (int i = 0; i < Repetitions; ++i) 3647 Values.append(DuplicatedValues.begin(), DuplicatedValues.end()); 3648 } else { 3649 Values.push_back(Value); 3650 } 3651 } 3652 return false; 3653 } 3654 3655 bool MasmParser::parseScalarInstList(unsigned Size, 3656 SmallVectorImpl<const MCExpr *> &Values, 3657 const AsmToken::TokenKind EndToken) { 3658 while (getTok().isNot(EndToken) && 3659 (EndToken != AsmToken::Greater || 3660 getTok().isNot(AsmToken::GreaterGreater))) { 3661 parseScalarInitializer(Size, Values); 3662 3663 // If we see a comma, continue, and allow line continuation. 3664 if (!parseOptionalToken(AsmToken::Comma)) 3665 break; 3666 parseOptionalToken(AsmToken::EndOfStatement); 3667 } 3668 return false; 3669 } 3670 3671 bool MasmParser::emitIntegralValues(unsigned Size, unsigned *Count) { 3672 SmallVector<const MCExpr *, 1> Values; 3673 if (checkForValidSection() || parseScalarInstList(Size, Values)) 3674 return true; 3675 3676 for (auto Value : Values) { 3677 emitIntValue(Value, Size); 3678 } 3679 if (Count) 3680 *Count = Values.size(); 3681 return false; 3682 } 3683 3684 // Add a field to the current structure. 3685 bool MasmParser::addIntegralField(StringRef Name, unsigned Size) { 3686 StructInfo &Struct = StructInProgress.back(); 3687 FieldInfo &Field = Struct.addField(Name, FT_INTEGRAL, Size); 3688 IntFieldInfo &IntInfo = Field.Contents.IntInfo; 3689 3690 Field.Type = Size; 3691 3692 if (parseScalarInstList(Size, IntInfo.Values)) 3693 return true; 3694 3695 Field.SizeOf = Field.Type * IntInfo.Values.size(); 3696 Field.LengthOf = IntInfo.Values.size(); 3697 const unsigned FieldEnd = Field.Offset + Field.SizeOf; 3698 if (!Struct.IsUnion) { 3699 Struct.NextOffset = FieldEnd; 3700 } 3701 Struct.Size = std::max(Struct.Size, FieldEnd); 3702 return false; 3703 } 3704 3705 /// parseDirectiveValue 3706 /// ::= (byte | word | ... ) [ expression (, expression)* ] 3707 bool MasmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) { 3708 if (StructInProgress.empty()) { 3709 // Initialize data value. 3710 if (emitIntegralValues(Size)) 3711 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); 3712 } else if (addIntegralField("", Size)) { 3713 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); 3714 } 3715 3716 return false; 3717 } 3718 3719 /// parseDirectiveNamedValue 3720 /// ::= name (byte | word | ... ) [ expression (, expression)* ] 3721 bool MasmParser::parseDirectiveNamedValue(StringRef TypeName, unsigned Size, 3722 StringRef Name, SMLoc NameLoc) { 3723 if (StructInProgress.empty()) { 3724 // Initialize named data value. 3725 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 3726 getStreamer().emitLabel(Sym); 3727 unsigned Count; 3728 if (emitIntegralValues(Size, &Count)) 3729 return addErrorSuffix(" in '" + Twine(TypeName) + "' directive"); 3730 3731 AsmTypeInfo Type; 3732 Type.Name = TypeName; 3733 Type.Size = Size * Count; 3734 Type.ElementSize = Size; 3735 Type.Length = Count; 3736 KnownType[Name.lower()] = Type; 3737 } else if (addIntegralField(Name, Size)) { 3738 return addErrorSuffix(" in '" + Twine(TypeName) + "' directive"); 3739 } 3740 3741 return false; 3742 } 3743 3744 static bool parseHexOcta(MasmParser &Asm, uint64_t &hi, uint64_t &lo) { 3745 if (Asm.getTok().isNot(AsmToken::Integer) && 3746 Asm.getTok().isNot(AsmToken::BigNum)) 3747 return Asm.TokError("unknown token in expression"); 3748 SMLoc ExprLoc = Asm.getTok().getLoc(); 3749 APInt IntValue = Asm.getTok().getAPIntVal(); 3750 Asm.Lex(); 3751 if (!IntValue.isIntN(128)) 3752 return Asm.Error(ExprLoc, "out of range literal value"); 3753 if (!IntValue.isIntN(64)) { 3754 hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue(); 3755 lo = IntValue.getLoBits(64).getZExtValue(); 3756 } else { 3757 hi = 0; 3758 lo = IntValue.getZExtValue(); 3759 } 3760 return false; 3761 } 3762 3763 bool MasmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) { 3764 // We don't truly support arithmetic on floating point expressions, so we 3765 // have to manually parse unary prefixes. 3766 bool IsNeg = false; 3767 SMLoc SignLoc; 3768 if (getLexer().is(AsmToken::Minus)) { 3769 SignLoc = getLexer().getLoc(); 3770 Lexer.Lex(); 3771 IsNeg = true; 3772 } else if (getLexer().is(AsmToken::Plus)) { 3773 SignLoc = getLexer().getLoc(); 3774 Lexer.Lex(); 3775 } 3776 3777 if (Lexer.is(AsmToken::Error)) 3778 return TokError(Lexer.getErr()); 3779 if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) && 3780 Lexer.isNot(AsmToken::Identifier)) 3781 return TokError("unexpected token in directive"); 3782 3783 // Convert to an APFloat. 3784 APFloat Value(Semantics); 3785 StringRef IDVal = getTok().getString(); 3786 if (getLexer().is(AsmToken::Identifier)) { 3787 if (IDVal.equals_insensitive("infinity") || IDVal.equals_insensitive("inf")) 3788 Value = APFloat::getInf(Semantics); 3789 else if (IDVal.equals_insensitive("nan")) 3790 Value = APFloat::getNaN(Semantics, false, ~0); 3791 else if (IDVal.equals_insensitive("?")) 3792 Value = APFloat::getZero(Semantics); 3793 else 3794 return TokError("invalid floating point literal"); 3795 } else if (IDVal.consume_back("r") || IDVal.consume_back("R")) { 3796 // MASM hexadecimal floating-point literal; no APFloat conversion needed. 3797 // To match ML64.exe, ignore the initial sign. 3798 unsigned SizeInBits = Value.getSizeInBits(Semantics); 3799 if (SizeInBits != (IDVal.size() << 2)) 3800 return TokError("invalid floating point literal"); 3801 3802 // Consume the numeric token. 3803 Lex(); 3804 3805 Res = APInt(SizeInBits, IDVal, 16); 3806 if (SignLoc.isValid()) 3807 return Warning(SignLoc, "MASM-style hex floats ignore explicit sign"); 3808 return false; 3809 } else if (errorToBool( 3810 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) 3811 .takeError())) { 3812 return TokError("invalid floating point literal"); 3813 } 3814 if (IsNeg) 3815 Value.changeSign(); 3816 3817 // Consume the numeric token. 3818 Lex(); 3819 3820 Res = Value.bitcastToAPInt(); 3821 3822 return false; 3823 } 3824 3825 bool MasmParser::parseRealInstList(const fltSemantics &Semantics, 3826 SmallVectorImpl<APInt> &ValuesAsInt, 3827 const AsmToken::TokenKind EndToken) { 3828 while (getTok().isNot(EndToken) || 3829 (EndToken == AsmToken::Greater && 3830 getTok().isNot(AsmToken::GreaterGreater))) { 3831 const AsmToken NextTok = peekTok(); 3832 if (NextTok.is(AsmToken::Identifier) && 3833 NextTok.getString().equals_insensitive("dup")) { 3834 const MCExpr *Value; 3835 if (parseExpression(Value) || parseToken(AsmToken::Identifier)) 3836 return true; 3837 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); 3838 if (!MCE) 3839 return Error(Value->getLoc(), 3840 "cannot repeat value a non-constant number of times"); 3841 const int64_t Repetitions = MCE->getValue(); 3842 if (Repetitions < 0) 3843 return Error(Value->getLoc(), 3844 "cannot repeat value a negative number of times"); 3845 3846 SmallVector<APInt, 1> DuplicatedValues; 3847 if (parseToken(AsmToken::LParen, 3848 "parentheses required for 'dup' contents") || 3849 parseRealInstList(Semantics, DuplicatedValues) || 3850 parseToken(AsmToken::RParen, "unmatched parentheses")) 3851 return true; 3852 3853 for (int i = 0; i < Repetitions; ++i) 3854 ValuesAsInt.append(DuplicatedValues.begin(), DuplicatedValues.end()); 3855 } else { 3856 APInt AsInt; 3857 if (parseRealValue(Semantics, AsInt)) 3858 return true; 3859 ValuesAsInt.push_back(AsInt); 3860 } 3861 3862 // Continue if we see a comma. (Also, allow line continuation.) 3863 if (!parseOptionalToken(AsmToken::Comma)) 3864 break; 3865 parseOptionalToken(AsmToken::EndOfStatement); 3866 } 3867 3868 return false; 3869 } 3870 3871 // Initialize real data values. 3872 bool MasmParser::emitRealValues(const fltSemantics &Semantics, 3873 unsigned *Count) { 3874 if (checkForValidSection()) 3875 return true; 3876 3877 SmallVector<APInt, 1> ValuesAsInt; 3878 if (parseRealInstList(Semantics, ValuesAsInt)) 3879 return true; 3880 3881 for (const APInt &AsInt : ValuesAsInt) { 3882 getStreamer().emitIntValue(AsInt); 3883 } 3884 if (Count) 3885 *Count = ValuesAsInt.size(); 3886 return false; 3887 } 3888 3889 // Add a real field to the current struct. 3890 bool MasmParser::addRealField(StringRef Name, const fltSemantics &Semantics, 3891 size_t Size) { 3892 StructInfo &Struct = StructInProgress.back(); 3893 FieldInfo &Field = Struct.addField(Name, FT_REAL, Size); 3894 RealFieldInfo &RealInfo = Field.Contents.RealInfo; 3895 3896 Field.SizeOf = 0; 3897 3898 if (parseRealInstList(Semantics, RealInfo.AsIntValues)) 3899 return true; 3900 3901 Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8; 3902 Field.LengthOf = RealInfo.AsIntValues.size(); 3903 Field.SizeOf = Field.Type * Field.LengthOf; 3904 3905 const unsigned FieldEnd = Field.Offset + Field.SizeOf; 3906 if (!Struct.IsUnion) { 3907 Struct.NextOffset = FieldEnd; 3908 } 3909 Struct.Size = std::max(Struct.Size, FieldEnd); 3910 return false; 3911 } 3912 3913 /// parseDirectiveRealValue 3914 /// ::= (real4 | real8 | real10) [ expression (, expression)* ] 3915 bool MasmParser::parseDirectiveRealValue(StringRef IDVal, 3916 const fltSemantics &Semantics, 3917 size_t Size) { 3918 if (StructInProgress.empty()) { 3919 // Initialize data value. 3920 if (emitRealValues(Semantics)) 3921 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); 3922 } else if (addRealField("", Semantics, Size)) { 3923 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); 3924 } 3925 return false; 3926 } 3927 3928 /// parseDirectiveNamedRealValue 3929 /// ::= name (real4 | real8 | real10) [ expression (, expression)* ] 3930 bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName, 3931 const fltSemantics &Semantics, 3932 unsigned Size, StringRef Name, 3933 SMLoc NameLoc) { 3934 if (StructInProgress.empty()) { 3935 // Initialize named data value. 3936 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 3937 getStreamer().emitLabel(Sym); 3938 unsigned Count; 3939 if (emitRealValues(Semantics, &Count)) 3940 return addErrorSuffix(" in '" + TypeName + "' directive"); 3941 3942 AsmTypeInfo Type; 3943 Type.Name = TypeName; 3944 Type.Size = Size * Count; 3945 Type.ElementSize = Size; 3946 Type.Length = Count; 3947 KnownType[Name.lower()] = Type; 3948 } else if (addRealField(Name, Semantics, Size)) { 3949 return addErrorSuffix(" in '" + TypeName + "' directive"); 3950 } 3951 return false; 3952 } 3953 3954 bool MasmParser::parseOptionalAngleBracketOpen() { 3955 const AsmToken Tok = getTok(); 3956 if (parseOptionalToken(AsmToken::LessLess)) { 3957 AngleBracketDepth++; 3958 Lexer.UnLex(AsmToken(AsmToken::Less, Tok.getString().substr(1))); 3959 return true; 3960 } else if (parseOptionalToken(AsmToken::LessGreater)) { 3961 AngleBracketDepth++; 3962 Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1))); 3963 return true; 3964 } else if (parseOptionalToken(AsmToken::Less)) { 3965 AngleBracketDepth++; 3966 return true; 3967 } 3968 3969 return false; 3970 } 3971 3972 bool MasmParser::parseAngleBracketClose(const Twine &Msg) { 3973 const AsmToken Tok = getTok(); 3974 if (parseOptionalToken(AsmToken::GreaterGreater)) { 3975 Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1))); 3976 } else if (parseToken(AsmToken::Greater, Msg)) { 3977 return true; 3978 } 3979 AngleBracketDepth--; 3980 return false; 3981 } 3982 3983 bool MasmParser::parseFieldInitializer(const FieldInfo &Field, 3984 const IntFieldInfo &Contents, 3985 FieldInitializer &Initializer) { 3986 SMLoc Loc = getTok().getLoc(); 3987 3988 SmallVector<const MCExpr *, 1> Values; 3989 if (parseOptionalToken(AsmToken::LCurly)) { 3990 if (Field.LengthOf == 1 && Field.Type > 1) 3991 return Error(Loc, "Cannot initialize scalar field with array value"); 3992 if (parseScalarInstList(Field.Type, Values, AsmToken::RCurly) || 3993 parseToken(AsmToken::RCurly)) 3994 return true; 3995 } else if (parseOptionalAngleBracketOpen()) { 3996 if (Field.LengthOf == 1 && Field.Type > 1) 3997 return Error(Loc, "Cannot initialize scalar field with array value"); 3998 if (parseScalarInstList(Field.Type, Values, AsmToken::Greater) || 3999 parseAngleBracketClose()) 4000 return true; 4001 } else if (Field.LengthOf > 1 && Field.Type > 1) { 4002 return Error(Loc, "Cannot initialize array field with scalar value"); 4003 } else if (parseScalarInitializer(Field.Type, Values, 4004 /*StringPadLength=*/Field.LengthOf)) { 4005 return true; 4006 } 4007 4008 if (Values.size() > Field.LengthOf) { 4009 return Error(Loc, "Initializer too long for field; expected at most " + 4010 std::to_string(Field.LengthOf) + " elements, got " + 4011 std::to_string(Values.size())); 4012 } 4013 // Default-initialize all remaining values. 4014 Values.append(Contents.Values.begin() + Values.size(), Contents.Values.end()); 4015 4016 Initializer = FieldInitializer(std::move(Values)); 4017 return false; 4018 } 4019 4020 bool MasmParser::parseFieldInitializer(const FieldInfo &Field, 4021 const RealFieldInfo &Contents, 4022 FieldInitializer &Initializer) { 4023 const fltSemantics *Semantics; 4024 switch (Field.Type) { 4025 case 4: 4026 Semantics = &APFloat::IEEEsingle(); 4027 break; 4028 case 8: 4029 Semantics = &APFloat::IEEEdouble(); 4030 break; 4031 case 10: 4032 Semantics = &APFloat::x87DoubleExtended(); 4033 break; 4034 default: 4035 llvm_unreachable("unknown real field type"); 4036 } 4037 4038 SMLoc Loc = getTok().getLoc(); 4039 4040 SmallVector<APInt, 1> AsIntValues; 4041 if (parseOptionalToken(AsmToken::LCurly)) { 4042 if (Field.LengthOf == 1) 4043 return Error(Loc, "Cannot initialize scalar field with array value"); 4044 if (parseRealInstList(*Semantics, AsIntValues, AsmToken::RCurly) || 4045 parseToken(AsmToken::RCurly)) 4046 return true; 4047 } else if (parseOptionalAngleBracketOpen()) { 4048 if (Field.LengthOf == 1) 4049 return Error(Loc, "Cannot initialize scalar field with array value"); 4050 if (parseRealInstList(*Semantics, AsIntValues, AsmToken::Greater) || 4051 parseAngleBracketClose()) 4052 return true; 4053 } else if (Field.LengthOf > 1) { 4054 return Error(Loc, "Cannot initialize array field with scalar value"); 4055 } else { 4056 AsIntValues.emplace_back(); 4057 if (parseRealValue(*Semantics, AsIntValues.back())) 4058 return true; 4059 } 4060 4061 if (AsIntValues.size() > Field.LengthOf) { 4062 return Error(Loc, "Initializer too long for field; expected at most " + 4063 std::to_string(Field.LengthOf) + " elements, got " + 4064 std::to_string(AsIntValues.size())); 4065 } 4066 // Default-initialize all remaining values. 4067 AsIntValues.append(Contents.AsIntValues.begin() + AsIntValues.size(), 4068 Contents.AsIntValues.end()); 4069 4070 Initializer = FieldInitializer(std::move(AsIntValues)); 4071 return false; 4072 } 4073 4074 bool MasmParser::parseFieldInitializer(const FieldInfo &Field, 4075 const StructFieldInfo &Contents, 4076 FieldInitializer &Initializer) { 4077 SMLoc Loc = getTok().getLoc(); 4078 4079 std::vector<StructInitializer> Initializers; 4080 if (Field.LengthOf > 1) { 4081 if (parseOptionalToken(AsmToken::LCurly)) { 4082 if (parseStructInstList(Contents.Structure, Initializers, 4083 AsmToken::RCurly) || 4084 parseToken(AsmToken::RCurly)) 4085 return true; 4086 } else if (parseOptionalAngleBracketOpen()) { 4087 if (parseStructInstList(Contents.Structure, Initializers, 4088 AsmToken::Greater) || 4089 parseAngleBracketClose()) 4090 return true; 4091 } else { 4092 return Error(Loc, "Cannot initialize array field with scalar value"); 4093 } 4094 } else { 4095 Initializers.emplace_back(); 4096 if (parseStructInitializer(Contents.Structure, Initializers.back())) 4097 return true; 4098 } 4099 4100 if (Initializers.size() > Field.LengthOf) { 4101 return Error(Loc, "Initializer too long for field; expected at most " + 4102 std::to_string(Field.LengthOf) + " elements, got " + 4103 std::to_string(Initializers.size())); 4104 } 4105 // Default-initialize all remaining values. 4106 Initializers.insert(Initializers.end(), 4107 Contents.Initializers.begin() + Initializers.size(), 4108 Contents.Initializers.end()); 4109 4110 Initializer = FieldInitializer(std::move(Initializers), Contents.Structure); 4111 return false; 4112 } 4113 4114 bool MasmParser::parseFieldInitializer(const FieldInfo &Field, 4115 FieldInitializer &Initializer) { 4116 switch (Field.Contents.FT) { 4117 case FT_INTEGRAL: 4118 return parseFieldInitializer(Field, Field.Contents.IntInfo, Initializer); 4119 case FT_REAL: 4120 return parseFieldInitializer(Field, Field.Contents.RealInfo, Initializer); 4121 case FT_STRUCT: 4122 return parseFieldInitializer(Field, Field.Contents.StructInfo, Initializer); 4123 } 4124 llvm_unreachable("Unhandled FieldType enum"); 4125 } 4126 4127 bool MasmParser::parseStructInitializer(const StructInfo &Structure, 4128 StructInitializer &Initializer) { 4129 const AsmToken FirstToken = getTok(); 4130 4131 Optional<AsmToken::TokenKind> EndToken; 4132 if (parseOptionalToken(AsmToken::LCurly)) { 4133 EndToken = AsmToken::RCurly; 4134 } else if (parseOptionalAngleBracketOpen()) { 4135 EndToken = AsmToken::Greater; 4136 AngleBracketDepth++; 4137 } else if (FirstToken.is(AsmToken::Identifier) && 4138 FirstToken.getString() == "?") { 4139 // ? initializer; leave EndToken uninitialized to treat as empty. 4140 if (parseToken(AsmToken::Identifier)) 4141 return true; 4142 } else { 4143 return Error(FirstToken.getLoc(), "Expected struct initializer"); 4144 } 4145 4146 auto &FieldInitializers = Initializer.FieldInitializers; 4147 size_t FieldIndex = 0; 4148 if (EndToken.hasValue()) { 4149 // Initialize all fields with given initializers. 4150 while (getTok().isNot(EndToken.getValue()) && 4151 FieldIndex < Structure.Fields.size()) { 4152 const FieldInfo &Field = Structure.Fields[FieldIndex++]; 4153 if (parseOptionalToken(AsmToken::Comma)) { 4154 // Empty initializer; use the default and continue. (Also, allow line 4155 // continuation.) 4156 FieldInitializers.push_back(Field.Contents); 4157 parseOptionalToken(AsmToken::EndOfStatement); 4158 continue; 4159 } 4160 FieldInitializers.emplace_back(Field.Contents.FT); 4161 if (parseFieldInitializer(Field, FieldInitializers.back())) 4162 return true; 4163 4164 // Continue if we see a comma. (Also, allow line continuation.) 4165 SMLoc CommaLoc = getTok().getLoc(); 4166 if (!parseOptionalToken(AsmToken::Comma)) 4167 break; 4168 if (FieldIndex == Structure.Fields.size()) 4169 return Error(CommaLoc, "'" + Structure.Name + 4170 "' initializer initializes too many fields"); 4171 parseOptionalToken(AsmToken::EndOfStatement); 4172 } 4173 } 4174 // Default-initialize all remaining fields. 4175 for (auto It = Structure.Fields.begin() + FieldIndex; 4176 It != Structure.Fields.end(); ++It) { 4177 const FieldInfo &Field = *It; 4178 FieldInitializers.push_back(Field.Contents); 4179 } 4180 4181 if (EndToken.hasValue()) { 4182 if (EndToken.getValue() == AsmToken::Greater) 4183 return parseAngleBracketClose(); 4184 4185 return parseToken(EndToken.getValue()); 4186 } 4187 4188 return false; 4189 } 4190 4191 bool MasmParser::parseStructInstList( 4192 const StructInfo &Structure, std::vector<StructInitializer> &Initializers, 4193 const AsmToken::TokenKind EndToken) { 4194 while (getTok().isNot(EndToken) || 4195 (EndToken == AsmToken::Greater && 4196 getTok().isNot(AsmToken::GreaterGreater))) { 4197 const AsmToken NextTok = peekTok(); 4198 if (NextTok.is(AsmToken::Identifier) && 4199 NextTok.getString().equals_insensitive("dup")) { 4200 const MCExpr *Value; 4201 if (parseExpression(Value) || parseToken(AsmToken::Identifier)) 4202 return true; 4203 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); 4204 if (!MCE) 4205 return Error(Value->getLoc(), 4206 "cannot repeat value a non-constant number of times"); 4207 const int64_t Repetitions = MCE->getValue(); 4208 if (Repetitions < 0) 4209 return Error(Value->getLoc(), 4210 "cannot repeat value a negative number of times"); 4211 4212 std::vector<StructInitializer> DuplicatedValues; 4213 if (parseToken(AsmToken::LParen, 4214 "parentheses required for 'dup' contents") || 4215 parseStructInstList(Structure, DuplicatedValues) || 4216 parseToken(AsmToken::RParen, "unmatched parentheses")) 4217 return true; 4218 4219 for (int i = 0; i < Repetitions; ++i) 4220 llvm::append_range(Initializers, DuplicatedValues); 4221 } else { 4222 Initializers.emplace_back(); 4223 if (parseStructInitializer(Structure, Initializers.back())) 4224 return true; 4225 } 4226 4227 // Continue if we see a comma. (Also, allow line continuation.) 4228 if (!parseOptionalToken(AsmToken::Comma)) 4229 break; 4230 parseOptionalToken(AsmToken::EndOfStatement); 4231 } 4232 4233 return false; 4234 } 4235 4236 bool MasmParser::emitFieldValue(const FieldInfo &Field, 4237 const IntFieldInfo &Contents) { 4238 // Default-initialize all values. 4239 for (const MCExpr *Value : Contents.Values) { 4240 if (emitIntValue(Value, Field.Type)) 4241 return true; 4242 } 4243 return false; 4244 } 4245 4246 bool MasmParser::emitFieldValue(const FieldInfo &Field, 4247 const RealFieldInfo &Contents) { 4248 for (const APInt &AsInt : Contents.AsIntValues) { 4249 getStreamer().emitIntValue(AsInt.getLimitedValue(), 4250 AsInt.getBitWidth() / 8); 4251 } 4252 return false; 4253 } 4254 4255 bool MasmParser::emitFieldValue(const FieldInfo &Field, 4256 const StructFieldInfo &Contents) { 4257 for (const auto &Initializer : Contents.Initializers) { 4258 size_t Index = 0, Offset = 0; 4259 for (const auto &SubField : Contents.Structure.Fields) { 4260 getStreamer().emitZeros(SubField.Offset - Offset); 4261 Offset = SubField.Offset + SubField.SizeOf; 4262 emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]); 4263 } 4264 } 4265 return false; 4266 } 4267 4268 bool MasmParser::emitFieldValue(const FieldInfo &Field) { 4269 switch (Field.Contents.FT) { 4270 case FT_INTEGRAL: 4271 return emitFieldValue(Field, Field.Contents.IntInfo); 4272 case FT_REAL: 4273 return emitFieldValue(Field, Field.Contents.RealInfo); 4274 case FT_STRUCT: 4275 return emitFieldValue(Field, Field.Contents.StructInfo); 4276 } 4277 llvm_unreachable("Unhandled FieldType enum"); 4278 } 4279 4280 bool MasmParser::emitFieldInitializer(const FieldInfo &Field, 4281 const IntFieldInfo &Contents, 4282 const IntFieldInfo &Initializer) { 4283 for (const auto &Value : Initializer.Values) { 4284 if (emitIntValue(Value, Field.Type)) 4285 return true; 4286 } 4287 // Default-initialize all remaining values. 4288 for (auto it = Contents.Values.begin() + Initializer.Values.size(); 4289 it != Contents.Values.end(); ++it) { 4290 const auto &Value = *it; 4291 if (emitIntValue(Value, Field.Type)) 4292 return true; 4293 } 4294 return false; 4295 } 4296 4297 bool MasmParser::emitFieldInitializer(const FieldInfo &Field, 4298 const RealFieldInfo &Contents, 4299 const RealFieldInfo &Initializer) { 4300 for (const auto &AsInt : Initializer.AsIntValues) { 4301 getStreamer().emitIntValue(AsInt.getLimitedValue(), 4302 AsInt.getBitWidth() / 8); 4303 } 4304 // Default-initialize all remaining values. 4305 for (auto It = Contents.AsIntValues.begin() + Initializer.AsIntValues.size(); 4306 It != Contents.AsIntValues.end(); ++It) { 4307 const auto &AsInt = *It; 4308 getStreamer().emitIntValue(AsInt.getLimitedValue(), 4309 AsInt.getBitWidth() / 8); 4310 } 4311 return false; 4312 } 4313 4314 bool MasmParser::emitFieldInitializer(const FieldInfo &Field, 4315 const StructFieldInfo &Contents, 4316 const StructFieldInfo &Initializer) { 4317 for (const auto &Init : Initializer.Initializers) { 4318 if (emitStructInitializer(Contents.Structure, Init)) 4319 return true; 4320 } 4321 // Default-initialize all remaining values. 4322 for (auto It = 4323 Contents.Initializers.begin() + Initializer.Initializers.size(); 4324 It != Contents.Initializers.end(); ++It) { 4325 const auto &Init = *It; 4326 if (emitStructInitializer(Contents.Structure, Init)) 4327 return true; 4328 } 4329 return false; 4330 } 4331 4332 bool MasmParser::emitFieldInitializer(const FieldInfo &Field, 4333 const FieldInitializer &Initializer) { 4334 switch (Field.Contents.FT) { 4335 case FT_INTEGRAL: 4336 return emitFieldInitializer(Field, Field.Contents.IntInfo, 4337 Initializer.IntInfo); 4338 case FT_REAL: 4339 return emitFieldInitializer(Field, Field.Contents.RealInfo, 4340 Initializer.RealInfo); 4341 case FT_STRUCT: 4342 return emitFieldInitializer(Field, Field.Contents.StructInfo, 4343 Initializer.StructInfo); 4344 } 4345 llvm_unreachable("Unhandled FieldType enum"); 4346 } 4347 4348 bool MasmParser::emitStructInitializer(const StructInfo &Structure, 4349 const StructInitializer &Initializer) { 4350 if (!Structure.Initializable) 4351 return Error(getLexer().getLoc(), 4352 "cannot initialize a value of type '" + Structure.Name + 4353 "'; 'org' was used in the type's declaration"); 4354 size_t Index = 0, Offset = 0; 4355 for (const auto &Init : Initializer.FieldInitializers) { 4356 const auto &Field = Structure.Fields[Index++]; 4357 getStreamer().emitZeros(Field.Offset - Offset); 4358 Offset = Field.Offset + Field.SizeOf; 4359 if (emitFieldInitializer(Field, Init)) 4360 return true; 4361 } 4362 // Default-initialize all remaining fields. 4363 for (auto It = 4364 Structure.Fields.begin() + Initializer.FieldInitializers.size(); 4365 It != Structure.Fields.end(); ++It) { 4366 const auto &Field = *It; 4367 getStreamer().emitZeros(Field.Offset - Offset); 4368 Offset = Field.Offset + Field.SizeOf; 4369 if (emitFieldValue(Field)) 4370 return true; 4371 } 4372 // Add final padding. 4373 if (Offset != Structure.Size) 4374 getStreamer().emitZeros(Structure.Size - Offset); 4375 return false; 4376 } 4377 4378 // Set data values from initializers. 4379 bool MasmParser::emitStructValues(const StructInfo &Structure, 4380 unsigned *Count) { 4381 std::vector<StructInitializer> Initializers; 4382 if (parseStructInstList(Structure, Initializers)) 4383 return true; 4384 4385 for (const auto &Initializer : Initializers) { 4386 if (emitStructInitializer(Structure, Initializer)) 4387 return true; 4388 } 4389 4390 if (Count) 4391 *Count = Initializers.size(); 4392 return false; 4393 } 4394 4395 // Declare a field in the current struct. 4396 bool MasmParser::addStructField(StringRef Name, const StructInfo &Structure) { 4397 StructInfo &OwningStruct = StructInProgress.back(); 4398 FieldInfo &Field = 4399 OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize); 4400 StructFieldInfo &StructInfo = Field.Contents.StructInfo; 4401 4402 StructInfo.Structure = Structure; 4403 Field.Type = Structure.Size; 4404 4405 if (parseStructInstList(Structure, StructInfo.Initializers)) 4406 return true; 4407 4408 Field.LengthOf = StructInfo.Initializers.size(); 4409 Field.SizeOf = Field.Type * Field.LengthOf; 4410 4411 const unsigned FieldEnd = Field.Offset + Field.SizeOf; 4412 if (!OwningStruct.IsUnion) { 4413 OwningStruct.NextOffset = FieldEnd; 4414 } 4415 OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd); 4416 4417 return false; 4418 } 4419 4420 /// parseDirectiveStructValue 4421 /// ::= struct-id (<struct-initializer> | {struct-initializer}) 4422 /// [, (<struct-initializer> | {struct-initializer})]* 4423 bool MasmParser::parseDirectiveStructValue(const StructInfo &Structure, 4424 StringRef Directive, SMLoc DirLoc) { 4425 if (StructInProgress.empty()) { 4426 if (emitStructValues(Structure)) 4427 return true; 4428 } else if (addStructField("", Structure)) { 4429 return addErrorSuffix(" in '" + Twine(Directive) + "' directive"); 4430 } 4431 4432 return false; 4433 } 4434 4435 /// parseDirectiveNamedValue 4436 /// ::= name (byte | word | ... ) [ expression (, expression)* ] 4437 bool MasmParser::parseDirectiveNamedStructValue(const StructInfo &Structure, 4438 StringRef Directive, 4439 SMLoc DirLoc, StringRef Name) { 4440 if (StructInProgress.empty()) { 4441 // Initialize named data value. 4442 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 4443 getStreamer().emitLabel(Sym); 4444 unsigned Count; 4445 if (emitStructValues(Structure, &Count)) 4446 return true; 4447 AsmTypeInfo Type; 4448 Type.Name = Structure.Name; 4449 Type.Size = Structure.Size * Count; 4450 Type.ElementSize = Structure.Size; 4451 Type.Length = Count; 4452 KnownType[Name.lower()] = Type; 4453 } else if (addStructField(Name, Structure)) { 4454 return addErrorSuffix(" in '" + Twine(Directive) + "' directive"); 4455 } 4456 4457 return false; 4458 } 4459 4460 /// parseDirectiveStruct 4461 /// ::= <name> (STRUC | STRUCT | UNION) [fieldAlign] [, NONUNIQUE] 4462 /// (dataDir | generalDir | offsetDir | nestedStruct)+ 4463 /// <name> ENDS 4464 ////// dataDir = data declaration 4465 ////// offsetDir = EVEN, ORG, ALIGN 4466 bool MasmParser::parseDirectiveStruct(StringRef Directive, 4467 DirectiveKind DirKind, StringRef Name, 4468 SMLoc NameLoc) { 4469 // We ignore NONUNIQUE; we do not support OPTION M510 or OPTION OLDSTRUCTS 4470 // anyway, so all field accesses must be qualified. 4471 AsmToken NextTok = getTok(); 4472 int64_t AlignmentValue = 1; 4473 if (NextTok.isNot(AsmToken::Comma) && 4474 NextTok.isNot(AsmToken::EndOfStatement) && 4475 parseAbsoluteExpression(AlignmentValue)) { 4476 return addErrorSuffix(" in alignment value for '" + Twine(Directive) + 4477 "' directive"); 4478 } 4479 if (!isPowerOf2_64(AlignmentValue)) { 4480 return Error(NextTok.getLoc(), "alignment must be a power of two; was " + 4481 std::to_string(AlignmentValue)); 4482 } 4483 4484 StringRef Qualifier; 4485 SMLoc QualifierLoc; 4486 if (parseOptionalToken(AsmToken::Comma)) { 4487 QualifierLoc = getTok().getLoc(); 4488 if (parseIdentifier(Qualifier)) 4489 return addErrorSuffix(" in '" + Twine(Directive) + "' directive"); 4490 if (!Qualifier.equals_insensitive("nonunique")) 4491 return Error(QualifierLoc, "Unrecognized qualifier for '" + 4492 Twine(Directive) + 4493 "' directive; expected none or NONUNIQUE"); 4494 } 4495 4496 if (parseToken(AsmToken::EndOfStatement)) 4497 return addErrorSuffix(" in '" + Twine(Directive) + "' directive"); 4498 4499 StructInProgress.emplace_back(Name, DirKind == DK_UNION, AlignmentValue); 4500 return false; 4501 } 4502 4503 /// parseDirectiveNestedStruct 4504 /// ::= (STRUC | STRUCT | UNION) [name] 4505 /// (dataDir | generalDir | offsetDir | nestedStruct)+ 4506 /// ENDS 4507 bool MasmParser::parseDirectiveNestedStruct(StringRef Directive, 4508 DirectiveKind DirKind) { 4509 if (StructInProgress.empty()) 4510 return TokError("missing name in top-level '" + Twine(Directive) + 4511 "' directive"); 4512 4513 StringRef Name; 4514 if (getTok().is(AsmToken::Identifier)) { 4515 Name = getTok().getIdentifier(); 4516 parseToken(AsmToken::Identifier); 4517 } 4518 if (parseToken(AsmToken::EndOfStatement)) 4519 return addErrorSuffix(" in '" + Twine(Directive) + "' directive"); 4520 4521 // Reserve space to ensure Alignment doesn't get invalidated when 4522 // StructInProgress grows. 4523 StructInProgress.reserve(StructInProgress.size() + 1); 4524 StructInProgress.emplace_back(Name, DirKind == DK_UNION, 4525 StructInProgress.back().Alignment); 4526 return false; 4527 } 4528 4529 bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) { 4530 if (StructInProgress.empty()) 4531 return Error(NameLoc, "ENDS directive without matching STRUC/STRUCT/UNION"); 4532 if (StructInProgress.size() > 1) 4533 return Error(NameLoc, "unexpected name in nested ENDS directive"); 4534 if (StructInProgress.back().Name.compare_insensitive(Name)) 4535 return Error(NameLoc, "mismatched name in ENDS directive; expected '" + 4536 StructInProgress.back().Name + "'"); 4537 StructInfo Structure = StructInProgress.pop_back_val(); 4538 // Pad to make the structure's size divisible by the smaller of its alignment 4539 // and the size of its largest field. 4540 Structure.Size = llvm::alignTo( 4541 Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize)); 4542 Structs[Name.lower()] = Structure; 4543 4544 if (parseToken(AsmToken::EndOfStatement)) 4545 return addErrorSuffix(" in ENDS directive"); 4546 4547 return false; 4548 } 4549 4550 bool MasmParser::parseDirectiveNestedEnds() { 4551 if (StructInProgress.empty()) 4552 return TokError("ENDS directive without matching STRUC/STRUCT/UNION"); 4553 if (StructInProgress.size() == 1) 4554 return TokError("missing name in top-level ENDS directive"); 4555 4556 if (parseToken(AsmToken::EndOfStatement)) 4557 return addErrorSuffix(" in nested ENDS directive"); 4558 4559 StructInfo Structure = StructInProgress.pop_back_val(); 4560 // Pad to make the structure's size divisible by its alignment. 4561 Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment); 4562 4563 StructInfo &ParentStruct = StructInProgress.back(); 4564 if (Structure.Name.empty()) { 4565 // Anonymous substructures' fields are addressed as if they belong to the 4566 // parent structure - so we transfer them to the parent here. 4567 const size_t OldFields = ParentStruct.Fields.size(); 4568 ParentStruct.Fields.insert( 4569 ParentStruct.Fields.end(), 4570 std::make_move_iterator(Structure.Fields.begin()), 4571 std::make_move_iterator(Structure.Fields.end())); 4572 for (const auto &FieldByName : Structure.FieldsByName) { 4573 ParentStruct.FieldsByName[FieldByName.getKey()] = 4574 FieldByName.getValue() + OldFields; 4575 } 4576 4577 unsigned FirstFieldOffset = 0; 4578 if (!Structure.Fields.empty() && !ParentStruct.IsUnion) { 4579 FirstFieldOffset = llvm::alignTo( 4580 ParentStruct.NextOffset, 4581 std::min(ParentStruct.Alignment, Structure.AlignmentSize)); 4582 } 4583 4584 if (ParentStruct.IsUnion) { 4585 ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size); 4586 } else { 4587 for (auto FieldIter = ParentStruct.Fields.begin() + OldFields; 4588 FieldIter != ParentStruct.Fields.end(); ++FieldIter) { 4589 FieldIter->Offset += FirstFieldOffset; 4590 } 4591 4592 const unsigned StructureEnd = FirstFieldOffset + Structure.Size; 4593 if (!ParentStruct.IsUnion) { 4594 ParentStruct.NextOffset = StructureEnd; 4595 } 4596 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd); 4597 } 4598 } else { 4599 FieldInfo &Field = ParentStruct.addField(Structure.Name, FT_STRUCT, 4600 Structure.AlignmentSize); 4601 StructFieldInfo &StructInfo = Field.Contents.StructInfo; 4602 Field.Type = Structure.Size; 4603 Field.LengthOf = 1; 4604 Field.SizeOf = Structure.Size; 4605 4606 const unsigned StructureEnd = Field.Offset + Field.SizeOf; 4607 if (!ParentStruct.IsUnion) { 4608 ParentStruct.NextOffset = StructureEnd; 4609 } 4610 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd); 4611 4612 StructInfo.Structure = Structure; 4613 StructInfo.Initializers.emplace_back(); 4614 auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers; 4615 for (const auto &SubField : Structure.Fields) { 4616 FieldInitializers.push_back(SubField.Contents); 4617 } 4618 } 4619 4620 return false; 4621 } 4622 4623 /// parseDirectiveOrg 4624 /// ::= org expression 4625 bool MasmParser::parseDirectiveOrg() { 4626 const MCExpr *Offset; 4627 SMLoc OffsetLoc = Lexer.getLoc(); 4628 if (checkForValidSection() || parseExpression(Offset)) 4629 return true; 4630 if (parseToken(AsmToken::EndOfStatement)) 4631 return addErrorSuffix(" in 'org' directive"); 4632 4633 if (StructInProgress.empty()) { 4634 // Not in a struct; change the offset for the next instruction or data 4635 if (checkForValidSection()) 4636 return addErrorSuffix(" in 'org' directive"); 4637 4638 getStreamer().emitValueToOffset(Offset, 0, OffsetLoc); 4639 } else { 4640 // Offset the next field of this struct 4641 StructInfo &Structure = StructInProgress.back(); 4642 int64_t OffsetRes; 4643 if (!Offset->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr())) 4644 return Error(OffsetLoc, 4645 "expected absolute expression in 'org' directive"); 4646 if (OffsetRes < 0) 4647 return Error( 4648 OffsetLoc, 4649 "expected non-negative value in struct's 'org' directive; was " + 4650 std::to_string(OffsetRes)); 4651 Structure.NextOffset = static_cast<unsigned>(OffsetRes); 4652 4653 // ORG-affected structures cannot be initialized 4654 Structure.Initializable = false; 4655 } 4656 4657 return false; 4658 } 4659 4660 bool MasmParser::emitAlignTo(int64_t Alignment) { 4661 if (StructInProgress.empty()) { 4662 // Not in a struct; align the next instruction or data 4663 if (checkForValidSection()) 4664 return true; 4665 4666 // Check whether we should use optimal code alignment for this align 4667 // directive. 4668 const MCSection *Section = getStreamer().getCurrentSectionOnly(); 4669 assert(Section && "must have section to emit alignment"); 4670 if (Section->UseCodeAlign()) { 4671 getStreamer().emitCodeAlignment(Alignment, /*MaxBytesToEmit=*/0); 4672 } else { 4673 // FIXME: Target specific behavior about how the "extra" bytes are filled. 4674 getStreamer().emitValueToAlignment(Alignment, /*Value=*/0, 4675 /*ValueSize=*/1, 4676 /*MaxBytesToEmit=*/0); 4677 } 4678 } else { 4679 // Align the next field of this struct 4680 StructInfo &Structure = StructInProgress.back(); 4681 Structure.NextOffset = llvm::alignTo(Structure.NextOffset, Alignment); 4682 } 4683 4684 return false; 4685 } 4686 4687 /// parseDirectiveAlign 4688 /// ::= align expression 4689 bool MasmParser::parseDirectiveAlign() { 4690 SMLoc AlignmentLoc = getLexer().getLoc(); 4691 int64_t Alignment; 4692 4693 // Ignore empty 'align' directives. 4694 if (getTok().is(AsmToken::EndOfStatement)) { 4695 return Warning(AlignmentLoc, 4696 "align directive with no operand is ignored") && 4697 parseToken(AsmToken::EndOfStatement); 4698 } 4699 if (parseAbsoluteExpression(Alignment) || 4700 parseToken(AsmToken::EndOfStatement)) 4701 return addErrorSuffix(" in align directive"); 4702 4703 // Always emit an alignment here even if we throw an error. 4704 bool ReturnVal = false; 4705 4706 // Reject alignments that aren't either a power of two or zero, for ML.exe 4707 // compatibility. Alignment of zero is silently rounded up to one. 4708 if (Alignment == 0) 4709 Alignment = 1; 4710 if (!isPowerOf2_64(Alignment)) 4711 ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2; was " + 4712 std::to_string(Alignment)); 4713 4714 if (emitAlignTo(Alignment)) 4715 ReturnVal |= addErrorSuffix(" in align directive"); 4716 4717 return ReturnVal; 4718 } 4719 4720 /// parseDirectiveEven 4721 /// ::= even 4722 bool MasmParser::parseDirectiveEven() { 4723 if (parseToken(AsmToken::EndOfStatement) || emitAlignTo(2)) 4724 return addErrorSuffix(" in even directive"); 4725 4726 return false; 4727 } 4728 4729 /// parseDirectiveFile 4730 /// ::= .file filename 4731 /// ::= .file number [directory] filename [md5 checksum] [source source-text] 4732 bool MasmParser::parseDirectiveFile(SMLoc DirectiveLoc) { 4733 // FIXME: I'm not sure what this is. 4734 int64_t FileNumber = -1; 4735 if (getLexer().is(AsmToken::Integer)) { 4736 FileNumber = getTok().getIntVal(); 4737 Lex(); 4738 4739 if (FileNumber < 0) 4740 return TokError("negative file number"); 4741 } 4742 4743 std::string Path; 4744 4745 // Usually the directory and filename together, otherwise just the directory. 4746 // Allow the strings to have escaped octal character sequence. 4747 if (check(getTok().isNot(AsmToken::String), 4748 "unexpected token in '.file' directive") || 4749 parseEscapedString(Path)) 4750 return true; 4751 4752 StringRef Directory; 4753 StringRef Filename; 4754 std::string FilenameData; 4755 if (getLexer().is(AsmToken::String)) { 4756 if (check(FileNumber == -1, 4757 "explicit path specified, but no file number") || 4758 parseEscapedString(FilenameData)) 4759 return true; 4760 Filename = FilenameData; 4761 Directory = Path; 4762 } else { 4763 Filename = Path; 4764 } 4765 4766 uint64_t MD5Hi, MD5Lo; 4767 bool HasMD5 = false; 4768 4769 Optional<StringRef> Source; 4770 bool HasSource = false; 4771 std::string SourceString; 4772 4773 while (!parseOptionalToken(AsmToken::EndOfStatement)) { 4774 StringRef Keyword; 4775 if (check(getTok().isNot(AsmToken::Identifier), 4776 "unexpected token in '.file' directive") || 4777 parseIdentifier(Keyword)) 4778 return true; 4779 if (Keyword == "md5") { 4780 HasMD5 = true; 4781 if (check(FileNumber == -1, 4782 "MD5 checksum specified, but no file number") || 4783 parseHexOcta(*this, MD5Hi, MD5Lo)) 4784 return true; 4785 } else if (Keyword == "source") { 4786 HasSource = true; 4787 if (check(FileNumber == -1, 4788 "source specified, but no file number") || 4789 check(getTok().isNot(AsmToken::String), 4790 "unexpected token in '.file' directive") || 4791 parseEscapedString(SourceString)) 4792 return true; 4793 } else { 4794 return TokError("unexpected token in '.file' directive"); 4795 } 4796 } 4797 4798 if (FileNumber == -1) { 4799 // Ignore the directive if there is no number and the target doesn't support 4800 // numberless .file directives. This allows some portability of assembler 4801 // between different object file formats. 4802 if (getContext().getAsmInfo()->hasSingleParameterDotFile()) 4803 getStreamer().emitFileDirective(Filename); 4804 } else { 4805 // In case there is a -g option as well as debug info from directive .file, 4806 // we turn off the -g option, directly use the existing debug info instead. 4807 // Throw away any implicit file table for the assembler source. 4808 if (Ctx.getGenDwarfForAssembly()) { 4809 Ctx.getMCDwarfLineTable(0).resetFileTable(); 4810 Ctx.setGenDwarfForAssembly(false); 4811 } 4812 4813 Optional<MD5::MD5Result> CKMem; 4814 if (HasMD5) { 4815 MD5::MD5Result Sum; 4816 for (unsigned i = 0; i != 8; ++i) { 4817 Sum.Bytes[i] = uint8_t(MD5Hi >> ((7 - i) * 8)); 4818 Sum.Bytes[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8)); 4819 } 4820 CKMem = Sum; 4821 } 4822 if (HasSource) { 4823 char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size())); 4824 memcpy(SourceBuf, SourceString.data(), SourceString.size()); 4825 Source = StringRef(SourceBuf, SourceString.size()); 4826 } 4827 if (FileNumber == 0) { 4828 if (Ctx.getDwarfVersion() < 5) 4829 return Warning(DirectiveLoc, "file 0 not supported prior to DWARF-5"); 4830 getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source); 4831 } else { 4832 Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective( 4833 FileNumber, Directory, Filename, CKMem, Source); 4834 if (!FileNumOrErr) 4835 return Error(DirectiveLoc, toString(FileNumOrErr.takeError())); 4836 } 4837 // Alert the user if there are some .file directives with MD5 and some not. 4838 // But only do that once. 4839 if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) { 4840 ReportedInconsistentMD5 = true; 4841 return Warning(DirectiveLoc, "inconsistent use of MD5 checksums"); 4842 } 4843 } 4844 4845 return false; 4846 } 4847 4848 /// parseDirectiveLine 4849 /// ::= .line [number] 4850 bool MasmParser::parseDirectiveLine() { 4851 int64_t LineNumber; 4852 if (getLexer().is(AsmToken::Integer)) { 4853 if (parseIntToken(LineNumber, "unexpected token in '.line' directive")) 4854 return true; 4855 (void)LineNumber; 4856 // FIXME: Do something with the .line. 4857 } 4858 if (parseToken(AsmToken::EndOfStatement, 4859 "unexpected token in '.line' directive")) 4860 return true; 4861 4862 return false; 4863 } 4864 4865 /// parseDirectiveLoc 4866 /// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end] 4867 /// [epilogue_begin] [is_stmt VALUE] [isa VALUE] 4868 /// The first number is a file number, must have been previously assigned with 4869 /// a .file directive, the second number is the line number and optionally the 4870 /// third number is a column position (zero if not specified). The remaining 4871 /// optional items are .loc sub-directives. 4872 bool MasmParser::parseDirectiveLoc() { 4873 int64_t FileNumber = 0, LineNumber = 0; 4874 SMLoc Loc = getTok().getLoc(); 4875 if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") || 4876 check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc, 4877 "file number less than one in '.loc' directive") || 4878 check(!getContext().isValidDwarfFileNumber(FileNumber), Loc, 4879 "unassigned file number in '.loc' directive")) 4880 return true; 4881 4882 // optional 4883 if (getLexer().is(AsmToken::Integer)) { 4884 LineNumber = getTok().getIntVal(); 4885 if (LineNumber < 0) 4886 return TokError("line number less than zero in '.loc' directive"); 4887 Lex(); 4888 } 4889 4890 int64_t ColumnPos = 0; 4891 if (getLexer().is(AsmToken::Integer)) { 4892 ColumnPos = getTok().getIntVal(); 4893 if (ColumnPos < 0) 4894 return TokError("column position less than zero in '.loc' directive"); 4895 Lex(); 4896 } 4897 4898 auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags(); 4899 unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT; 4900 unsigned Isa = 0; 4901 int64_t Discriminator = 0; 4902 4903 auto parseLocOp = [&]() -> bool { 4904 StringRef Name; 4905 SMLoc Loc = getTok().getLoc(); 4906 if (parseIdentifier(Name)) 4907 return TokError("unexpected token in '.loc' directive"); 4908 4909 if (Name == "basic_block") 4910 Flags |= DWARF2_FLAG_BASIC_BLOCK; 4911 else if (Name == "prologue_end") 4912 Flags |= DWARF2_FLAG_PROLOGUE_END; 4913 else if (Name == "epilogue_begin") 4914 Flags |= DWARF2_FLAG_EPILOGUE_BEGIN; 4915 else if (Name == "is_stmt") { 4916 Loc = getTok().getLoc(); 4917 const MCExpr *Value; 4918 if (parseExpression(Value)) 4919 return true; 4920 // The expression must be the constant 0 or 1. 4921 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { 4922 int Value = MCE->getValue(); 4923 if (Value == 0) 4924 Flags &= ~DWARF2_FLAG_IS_STMT; 4925 else if (Value == 1) 4926 Flags |= DWARF2_FLAG_IS_STMT; 4927 else 4928 return Error(Loc, "is_stmt value not 0 or 1"); 4929 } else { 4930 return Error(Loc, "is_stmt value not the constant value of 0 or 1"); 4931 } 4932 } else if (Name == "isa") { 4933 Loc = getTok().getLoc(); 4934 const MCExpr *Value; 4935 if (parseExpression(Value)) 4936 return true; 4937 // The expression must be a constant greater or equal to 0. 4938 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { 4939 int Value = MCE->getValue(); 4940 if (Value < 0) 4941 return Error(Loc, "isa number less than zero"); 4942 Isa = Value; 4943 } else { 4944 return Error(Loc, "isa number not a constant value"); 4945 } 4946 } else if (Name == "discriminator") { 4947 if (parseAbsoluteExpression(Discriminator)) 4948 return true; 4949 } else { 4950 return Error(Loc, "unknown sub-directive in '.loc' directive"); 4951 } 4952 return false; 4953 }; 4954 4955 if (parseMany(parseLocOp, false /*hasComma*/)) 4956 return true; 4957 4958 getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags, 4959 Isa, Discriminator, StringRef()); 4960 4961 return false; 4962 } 4963 4964 /// parseDirectiveStabs 4965 /// ::= .stabs string, number, number, number 4966 bool MasmParser::parseDirectiveStabs() { 4967 return TokError("unsupported directive '.stabs'"); 4968 } 4969 4970 /// parseDirectiveCVFile 4971 /// ::= .cv_file number filename [checksum] [checksumkind] 4972 bool MasmParser::parseDirectiveCVFile() { 4973 SMLoc FileNumberLoc = getTok().getLoc(); 4974 int64_t FileNumber; 4975 std::string Filename; 4976 std::string Checksum; 4977 int64_t ChecksumKind = 0; 4978 4979 if (parseIntToken(FileNumber, 4980 "expected file number in '.cv_file' directive") || 4981 check(FileNumber < 1, FileNumberLoc, "file number less than one") || 4982 check(getTok().isNot(AsmToken::String), 4983 "unexpected token in '.cv_file' directive") || 4984 parseEscapedString(Filename)) 4985 return true; 4986 if (!parseOptionalToken(AsmToken::EndOfStatement)) { 4987 if (check(getTok().isNot(AsmToken::String), 4988 "unexpected token in '.cv_file' directive") || 4989 parseEscapedString(Checksum) || 4990 parseIntToken(ChecksumKind, 4991 "expected checksum kind in '.cv_file' directive") || 4992 parseToken(AsmToken::EndOfStatement, 4993 "unexpected token in '.cv_file' directive")) 4994 return true; 4995 } 4996 4997 Checksum = fromHex(Checksum); 4998 void *CKMem = Ctx.allocate(Checksum.size(), 1); 4999 memcpy(CKMem, Checksum.data(), Checksum.size()); 5000 ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem), 5001 Checksum.size()); 5002 5003 if (!getStreamer().EmitCVFileDirective(FileNumber, Filename, ChecksumAsBytes, 5004 static_cast<uint8_t>(ChecksumKind))) 5005 return Error(FileNumberLoc, "file number already allocated"); 5006 5007 return false; 5008 } 5009 5010 bool MasmParser::parseCVFunctionId(int64_t &FunctionId, 5011 StringRef DirectiveName) { 5012 SMLoc Loc; 5013 return parseTokenLoc(Loc) || 5014 parseIntToken(FunctionId, "expected function id in '" + DirectiveName + 5015 "' directive") || 5016 check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc, 5017 "expected function id within range [0, UINT_MAX)"); 5018 } 5019 5020 bool MasmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) { 5021 SMLoc Loc; 5022 return parseTokenLoc(Loc) || 5023 parseIntToken(FileNumber, "expected integer in '" + DirectiveName + 5024 "' directive") || 5025 check(FileNumber < 1, Loc, "file number less than one in '" + 5026 DirectiveName + "' directive") || 5027 check(!getCVContext().isValidFileNumber(FileNumber), Loc, 5028 "unassigned file number in '" + DirectiveName + "' directive"); 5029 } 5030 5031 /// parseDirectiveCVFuncId 5032 /// ::= .cv_func_id FunctionId 5033 /// 5034 /// Introduces a function ID that can be used with .cv_loc. 5035 bool MasmParser::parseDirectiveCVFuncId() { 5036 SMLoc FunctionIdLoc = getTok().getLoc(); 5037 int64_t FunctionId; 5038 5039 if (parseCVFunctionId(FunctionId, ".cv_func_id") || 5040 parseToken(AsmToken::EndOfStatement, 5041 "unexpected token in '.cv_func_id' directive")) 5042 return true; 5043 5044 if (!getStreamer().EmitCVFuncIdDirective(FunctionId)) 5045 return Error(FunctionIdLoc, "function id already allocated"); 5046 5047 return false; 5048 } 5049 5050 /// parseDirectiveCVInlineSiteId 5051 /// ::= .cv_inline_site_id FunctionId 5052 /// "within" IAFunc 5053 /// "inlined_at" IAFile IALine [IACol] 5054 /// 5055 /// Introduces a function ID that can be used with .cv_loc. Includes "inlined 5056 /// at" source location information for use in the line table of the caller, 5057 /// whether the caller is a real function or another inlined call site. 5058 bool MasmParser::parseDirectiveCVInlineSiteId() { 5059 SMLoc FunctionIdLoc = getTok().getLoc(); 5060 int64_t FunctionId; 5061 int64_t IAFunc; 5062 int64_t IAFile; 5063 int64_t IALine; 5064 int64_t IACol = 0; 5065 5066 // FunctionId 5067 if (parseCVFunctionId(FunctionId, ".cv_inline_site_id")) 5068 return true; 5069 5070 // "within" 5071 if (check((getLexer().isNot(AsmToken::Identifier) || 5072 getTok().getIdentifier() != "within"), 5073 "expected 'within' identifier in '.cv_inline_site_id' directive")) 5074 return true; 5075 Lex(); 5076 5077 // IAFunc 5078 if (parseCVFunctionId(IAFunc, ".cv_inline_site_id")) 5079 return true; 5080 5081 // "inlined_at" 5082 if (check((getLexer().isNot(AsmToken::Identifier) || 5083 getTok().getIdentifier() != "inlined_at"), 5084 "expected 'inlined_at' identifier in '.cv_inline_site_id' " 5085 "directive") ) 5086 return true; 5087 Lex(); 5088 5089 // IAFile IALine 5090 if (parseCVFileId(IAFile, ".cv_inline_site_id") || 5091 parseIntToken(IALine, "expected line number after 'inlined_at'")) 5092 return true; 5093 5094 // [IACol] 5095 if (getLexer().is(AsmToken::Integer)) { 5096 IACol = getTok().getIntVal(); 5097 Lex(); 5098 } 5099 5100 if (parseToken(AsmToken::EndOfStatement, 5101 "unexpected token in '.cv_inline_site_id' directive")) 5102 return true; 5103 5104 if (!getStreamer().EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile, 5105 IALine, IACol, FunctionIdLoc)) 5106 return Error(FunctionIdLoc, "function id already allocated"); 5107 5108 return false; 5109 } 5110 5111 /// parseDirectiveCVLoc 5112 /// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end] 5113 /// [is_stmt VALUE] 5114 /// The first number is a file number, must have been previously assigned with 5115 /// a .file directive, the second number is the line number and optionally the 5116 /// third number is a column position (zero if not specified). The remaining 5117 /// optional items are .loc sub-directives. 5118 bool MasmParser::parseDirectiveCVLoc() { 5119 SMLoc DirectiveLoc = getTok().getLoc(); 5120 int64_t FunctionId, FileNumber; 5121 if (parseCVFunctionId(FunctionId, ".cv_loc") || 5122 parseCVFileId(FileNumber, ".cv_loc")) 5123 return true; 5124 5125 int64_t LineNumber = 0; 5126 if (getLexer().is(AsmToken::Integer)) { 5127 LineNumber = getTok().getIntVal(); 5128 if (LineNumber < 0) 5129 return TokError("line number less than zero in '.cv_loc' directive"); 5130 Lex(); 5131 } 5132 5133 int64_t ColumnPos = 0; 5134 if (getLexer().is(AsmToken::Integer)) { 5135 ColumnPos = getTok().getIntVal(); 5136 if (ColumnPos < 0) 5137 return TokError("column position less than zero in '.cv_loc' directive"); 5138 Lex(); 5139 } 5140 5141 bool PrologueEnd = false; 5142 uint64_t IsStmt = 0; 5143 5144 auto parseOp = [&]() -> bool { 5145 StringRef Name; 5146 SMLoc Loc = getTok().getLoc(); 5147 if (parseIdentifier(Name)) 5148 return TokError("unexpected token in '.cv_loc' directive"); 5149 if (Name == "prologue_end") 5150 PrologueEnd = true; 5151 else if (Name == "is_stmt") { 5152 Loc = getTok().getLoc(); 5153 const MCExpr *Value; 5154 if (parseExpression(Value)) 5155 return true; 5156 // The expression must be the constant 0 or 1. 5157 IsStmt = ~0ULL; 5158 if (const auto *MCE = dyn_cast<MCConstantExpr>(Value)) 5159 IsStmt = MCE->getValue(); 5160 5161 if (IsStmt > 1) 5162 return Error(Loc, "is_stmt value not 0 or 1"); 5163 } else { 5164 return Error(Loc, "unknown sub-directive in '.cv_loc' directive"); 5165 } 5166 return false; 5167 }; 5168 5169 if (parseMany(parseOp, false /*hasComma*/)) 5170 return true; 5171 5172 getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber, 5173 ColumnPos, PrologueEnd, IsStmt, StringRef(), 5174 DirectiveLoc); 5175 return false; 5176 } 5177 5178 /// parseDirectiveCVLinetable 5179 /// ::= .cv_linetable FunctionId, FnStart, FnEnd 5180 bool MasmParser::parseDirectiveCVLinetable() { 5181 int64_t FunctionId; 5182 StringRef FnStartName, FnEndName; 5183 SMLoc Loc = getTok().getLoc(); 5184 if (parseCVFunctionId(FunctionId, ".cv_linetable") || 5185 parseToken(AsmToken::Comma, 5186 "unexpected token in '.cv_linetable' directive") || 5187 parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc, 5188 "expected identifier in directive") || 5189 parseToken(AsmToken::Comma, 5190 "unexpected token in '.cv_linetable' directive") || 5191 parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc, 5192 "expected identifier in directive")) 5193 return true; 5194 5195 MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName); 5196 MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName); 5197 5198 getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym); 5199 return false; 5200 } 5201 5202 /// parseDirectiveCVInlineLinetable 5203 /// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd 5204 bool MasmParser::parseDirectiveCVInlineLinetable() { 5205 int64_t PrimaryFunctionId, SourceFileId, SourceLineNum; 5206 StringRef FnStartName, FnEndName; 5207 SMLoc Loc = getTok().getLoc(); 5208 if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") || 5209 parseTokenLoc(Loc) || 5210 parseIntToken( 5211 SourceFileId, 5212 "expected SourceField in '.cv_inline_linetable' directive") || 5213 check(SourceFileId <= 0, Loc, 5214 "File id less than zero in '.cv_inline_linetable' directive") || 5215 parseTokenLoc(Loc) || 5216 parseIntToken( 5217 SourceLineNum, 5218 "expected SourceLineNum in '.cv_inline_linetable' directive") || 5219 check(SourceLineNum < 0, Loc, 5220 "Line number less than zero in '.cv_inline_linetable' directive") || 5221 parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc, 5222 "expected identifier in directive") || 5223 parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc, 5224 "expected identifier in directive")) 5225 return true; 5226 5227 if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement")) 5228 return true; 5229 5230 MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName); 5231 MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName); 5232 getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId, 5233 SourceLineNum, FnStartSym, 5234 FnEndSym); 5235 return false; 5236 } 5237 5238 void MasmParser::initializeCVDefRangeTypeMap() { 5239 CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER; 5240 CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL; 5241 CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER; 5242 CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL; 5243 } 5244 5245 /// parseDirectiveCVDefRange 5246 /// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes* 5247 bool MasmParser::parseDirectiveCVDefRange() { 5248 SMLoc Loc; 5249 std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges; 5250 while (getLexer().is(AsmToken::Identifier)) { 5251 Loc = getLexer().getLoc(); 5252 StringRef GapStartName; 5253 if (parseIdentifier(GapStartName)) 5254 return Error(Loc, "expected identifier in directive"); 5255 MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName); 5256 5257 Loc = getLexer().getLoc(); 5258 StringRef GapEndName; 5259 if (parseIdentifier(GapEndName)) 5260 return Error(Loc, "expected identifier in directive"); 5261 MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName); 5262 5263 Ranges.push_back({GapStartSym, GapEndSym}); 5264 } 5265 5266 StringRef CVDefRangeTypeStr; 5267 if (parseToken( 5268 AsmToken::Comma, 5269 "expected comma before def_range type in .cv_def_range directive") || 5270 parseIdentifier(CVDefRangeTypeStr)) 5271 return Error(Loc, "expected def_range type in directive"); 5272 5273 StringMap<CVDefRangeType>::const_iterator CVTypeIt = 5274 CVDefRangeTypeMap.find(CVDefRangeTypeStr); 5275 CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end()) 5276 ? CVDR_DEFRANGE 5277 : CVTypeIt->getValue(); 5278 switch (CVDRType) { 5279 case CVDR_DEFRANGE_REGISTER: { 5280 int64_t DRRegister; 5281 if (parseToken(AsmToken::Comma, "expected comma before register number in " 5282 ".cv_def_range directive") || 5283 parseAbsoluteExpression(DRRegister)) 5284 return Error(Loc, "expected register number"); 5285 5286 codeview::DefRangeRegisterHeader DRHdr; 5287 DRHdr.Register = DRRegister; 5288 DRHdr.MayHaveNoName = 0; 5289 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr); 5290 break; 5291 } 5292 case CVDR_DEFRANGE_FRAMEPOINTER_REL: { 5293 int64_t DROffset; 5294 if (parseToken(AsmToken::Comma, 5295 "expected comma before offset in .cv_def_range directive") || 5296 parseAbsoluteExpression(DROffset)) 5297 return Error(Loc, "expected offset value"); 5298 5299 codeview::DefRangeFramePointerRelHeader DRHdr; 5300 DRHdr.Offset = DROffset; 5301 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr); 5302 break; 5303 } 5304 case CVDR_DEFRANGE_SUBFIELD_REGISTER: { 5305 int64_t DRRegister; 5306 int64_t DROffsetInParent; 5307 if (parseToken(AsmToken::Comma, "expected comma before register number in " 5308 ".cv_def_range directive") || 5309 parseAbsoluteExpression(DRRegister)) 5310 return Error(Loc, "expected register number"); 5311 if (parseToken(AsmToken::Comma, 5312 "expected comma before offset in .cv_def_range directive") || 5313 parseAbsoluteExpression(DROffsetInParent)) 5314 return Error(Loc, "expected offset value"); 5315 5316 codeview::DefRangeSubfieldRegisterHeader DRHdr; 5317 DRHdr.Register = DRRegister; 5318 DRHdr.MayHaveNoName = 0; 5319 DRHdr.OffsetInParent = DROffsetInParent; 5320 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr); 5321 break; 5322 } 5323 case CVDR_DEFRANGE_REGISTER_REL: { 5324 int64_t DRRegister; 5325 int64_t DRFlags; 5326 int64_t DRBasePointerOffset; 5327 if (parseToken(AsmToken::Comma, "expected comma before register number in " 5328 ".cv_def_range directive") || 5329 parseAbsoluteExpression(DRRegister)) 5330 return Error(Loc, "expected register value"); 5331 if (parseToken( 5332 AsmToken::Comma, 5333 "expected comma before flag value in .cv_def_range directive") || 5334 parseAbsoluteExpression(DRFlags)) 5335 return Error(Loc, "expected flag value"); 5336 if (parseToken(AsmToken::Comma, "expected comma before base pointer offset " 5337 "in .cv_def_range directive") || 5338 parseAbsoluteExpression(DRBasePointerOffset)) 5339 return Error(Loc, "expected base pointer offset value"); 5340 5341 codeview::DefRangeRegisterRelHeader DRHdr; 5342 DRHdr.Register = DRRegister; 5343 DRHdr.Flags = DRFlags; 5344 DRHdr.BasePointerOffset = DRBasePointerOffset; 5345 getStreamer().emitCVDefRangeDirective(Ranges, DRHdr); 5346 break; 5347 } 5348 default: 5349 return Error(Loc, "unexpected def_range type in .cv_def_range directive"); 5350 } 5351 return true; 5352 } 5353 5354 /// parseDirectiveCVString 5355 /// ::= .cv_stringtable "string" 5356 bool MasmParser::parseDirectiveCVString() { 5357 std::string Data; 5358 if (checkForValidSection() || parseEscapedString(Data)) 5359 return addErrorSuffix(" in '.cv_string' directive"); 5360 5361 // Put the string in the table and emit the offset. 5362 std::pair<StringRef, unsigned> Insertion = 5363 getCVContext().addToStringTable(Data); 5364 getStreamer().emitIntValue(Insertion.second, 4); 5365 return false; 5366 } 5367 5368 /// parseDirectiveCVStringTable 5369 /// ::= .cv_stringtable 5370 bool MasmParser::parseDirectiveCVStringTable() { 5371 getStreamer().emitCVStringTableDirective(); 5372 return false; 5373 } 5374 5375 /// parseDirectiveCVFileChecksums 5376 /// ::= .cv_filechecksums 5377 bool MasmParser::parseDirectiveCVFileChecksums() { 5378 getStreamer().emitCVFileChecksumsDirective(); 5379 return false; 5380 } 5381 5382 /// parseDirectiveCVFileChecksumOffset 5383 /// ::= .cv_filechecksumoffset fileno 5384 bool MasmParser::parseDirectiveCVFileChecksumOffset() { 5385 int64_t FileNo; 5386 if (parseIntToken(FileNo, "expected identifier in directive")) 5387 return true; 5388 if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement")) 5389 return true; 5390 getStreamer().emitCVFileChecksumOffsetDirective(FileNo); 5391 return false; 5392 } 5393 5394 /// parseDirectiveCVFPOData 5395 /// ::= .cv_fpo_data procsym 5396 bool MasmParser::parseDirectiveCVFPOData() { 5397 SMLoc DirLoc = getLexer().getLoc(); 5398 StringRef ProcName; 5399 if (parseIdentifier(ProcName)) 5400 return TokError("expected symbol name"); 5401 if (parseEOL("unexpected tokens")) 5402 return addErrorSuffix(" in '.cv_fpo_data' directive"); 5403 MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName); 5404 getStreamer().EmitCVFPOData(ProcSym, DirLoc); 5405 return false; 5406 } 5407 5408 /// parseDirectiveCFISections 5409 /// ::= .cfi_sections section [, section] 5410 bool MasmParser::parseDirectiveCFISections() { 5411 StringRef Name; 5412 bool EH = false; 5413 bool Debug = false; 5414 5415 if (parseIdentifier(Name)) 5416 return TokError("Expected an identifier"); 5417 5418 if (Name == ".eh_frame") 5419 EH = true; 5420 else if (Name == ".debug_frame") 5421 Debug = true; 5422 5423 if (getLexer().is(AsmToken::Comma)) { 5424 Lex(); 5425 5426 if (parseIdentifier(Name)) 5427 return TokError("Expected an identifier"); 5428 5429 if (Name == ".eh_frame") 5430 EH = true; 5431 else if (Name == ".debug_frame") 5432 Debug = true; 5433 } 5434 5435 getStreamer().emitCFISections(EH, Debug); 5436 return false; 5437 } 5438 5439 /// parseDirectiveCFIStartProc 5440 /// ::= .cfi_startproc [simple] 5441 bool MasmParser::parseDirectiveCFIStartProc() { 5442 StringRef Simple; 5443 if (!parseOptionalToken(AsmToken::EndOfStatement)) { 5444 if (check(parseIdentifier(Simple) || Simple != "simple", 5445 "unexpected token") || 5446 parseToken(AsmToken::EndOfStatement)) 5447 return addErrorSuffix(" in '.cfi_startproc' directive"); 5448 } 5449 5450 // TODO(kristina): Deal with a corner case of incorrect diagnostic context 5451 // being produced if this directive is emitted as part of preprocessor macro 5452 // expansion which can *ONLY* happen if Clang's cc1as is the API consumer. 5453 // Tools like llvm-mc on the other hand are not affected by it, and report 5454 // correct context information. 5455 getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc()); 5456 return false; 5457 } 5458 5459 /// parseDirectiveCFIEndProc 5460 /// ::= .cfi_endproc 5461 bool MasmParser::parseDirectiveCFIEndProc() { 5462 getStreamer().emitCFIEndProc(); 5463 return false; 5464 } 5465 5466 /// parse register name or number. 5467 bool MasmParser::parseRegisterOrRegisterNumber(int64_t &Register, 5468 SMLoc DirectiveLoc) { 5469 unsigned RegNo; 5470 5471 if (getLexer().isNot(AsmToken::Integer)) { 5472 if (getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc)) 5473 return true; 5474 Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true); 5475 } else 5476 return parseAbsoluteExpression(Register); 5477 5478 return false; 5479 } 5480 5481 /// parseDirectiveCFIDefCfa 5482 /// ::= .cfi_def_cfa register, offset 5483 bool MasmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) { 5484 int64_t Register = 0, Offset = 0; 5485 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || 5486 parseToken(AsmToken::Comma, "unexpected token in directive") || 5487 parseAbsoluteExpression(Offset)) 5488 return true; 5489 5490 getStreamer().emitCFIDefCfa(Register, Offset); 5491 return false; 5492 } 5493 5494 /// parseDirectiveCFIDefCfaOffset 5495 /// ::= .cfi_def_cfa_offset offset 5496 bool MasmParser::parseDirectiveCFIDefCfaOffset() { 5497 int64_t Offset = 0; 5498 if (parseAbsoluteExpression(Offset)) 5499 return true; 5500 5501 getStreamer().emitCFIDefCfaOffset(Offset); 5502 return false; 5503 } 5504 5505 /// parseDirectiveCFIRegister 5506 /// ::= .cfi_register register, register 5507 bool MasmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) { 5508 int64_t Register1 = 0, Register2 = 0; 5509 if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || 5510 parseToken(AsmToken::Comma, "unexpected token in directive") || 5511 parseRegisterOrRegisterNumber(Register2, DirectiveLoc)) 5512 return true; 5513 5514 getStreamer().emitCFIRegister(Register1, Register2); 5515 return false; 5516 } 5517 5518 /// parseDirectiveCFIWindowSave 5519 /// ::= .cfi_window_save 5520 bool MasmParser::parseDirectiveCFIWindowSave() { 5521 getStreamer().emitCFIWindowSave(); 5522 return false; 5523 } 5524 5525 /// parseDirectiveCFIAdjustCfaOffset 5526 /// ::= .cfi_adjust_cfa_offset adjustment 5527 bool MasmParser::parseDirectiveCFIAdjustCfaOffset() { 5528 int64_t Adjustment = 0; 5529 if (parseAbsoluteExpression(Adjustment)) 5530 return true; 5531 5532 getStreamer().emitCFIAdjustCfaOffset(Adjustment); 5533 return false; 5534 } 5535 5536 /// parseDirectiveCFIDefCfaRegister 5537 /// ::= .cfi_def_cfa_register register 5538 bool MasmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) { 5539 int64_t Register = 0; 5540 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) 5541 return true; 5542 5543 getStreamer().emitCFIDefCfaRegister(Register); 5544 return false; 5545 } 5546 5547 /// parseDirectiveCFIOffset 5548 /// ::= .cfi_offset register, offset 5549 bool MasmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) { 5550 int64_t Register = 0; 5551 int64_t Offset = 0; 5552 5553 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || 5554 parseToken(AsmToken::Comma, "unexpected token in directive") || 5555 parseAbsoluteExpression(Offset)) 5556 return true; 5557 5558 getStreamer().emitCFIOffset(Register, Offset); 5559 return false; 5560 } 5561 5562 /// parseDirectiveCFIRelOffset 5563 /// ::= .cfi_rel_offset register, offset 5564 bool MasmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) { 5565 int64_t Register = 0, Offset = 0; 5566 5567 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || 5568 parseToken(AsmToken::Comma, "unexpected token in directive") || 5569 parseAbsoluteExpression(Offset)) 5570 return true; 5571 5572 getStreamer().emitCFIRelOffset(Register, Offset); 5573 return false; 5574 } 5575 5576 static bool isValidEncoding(int64_t Encoding) { 5577 if (Encoding & ~0xff) 5578 return false; 5579 5580 if (Encoding == dwarf::DW_EH_PE_omit) 5581 return true; 5582 5583 const unsigned Format = Encoding & 0xf; 5584 if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 && 5585 Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 && 5586 Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 && 5587 Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed) 5588 return false; 5589 5590 const unsigned Application = Encoding & 0x70; 5591 if (Application != dwarf::DW_EH_PE_absptr && 5592 Application != dwarf::DW_EH_PE_pcrel) 5593 return false; 5594 5595 return true; 5596 } 5597 5598 /// parseDirectiveCFIPersonalityOrLsda 5599 /// IsPersonality true for cfi_personality, false for cfi_lsda 5600 /// ::= .cfi_personality encoding, [symbol_name] 5601 /// ::= .cfi_lsda encoding, [symbol_name] 5602 bool MasmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) { 5603 int64_t Encoding = 0; 5604 if (parseAbsoluteExpression(Encoding)) 5605 return true; 5606 if (Encoding == dwarf::DW_EH_PE_omit) 5607 return false; 5608 5609 StringRef Name; 5610 if (check(!isValidEncoding(Encoding), "unsupported encoding.") || 5611 parseToken(AsmToken::Comma, "unexpected token in directive") || 5612 check(parseIdentifier(Name), "expected identifier in directive")) 5613 return true; 5614 5615 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 5616 5617 if (IsPersonality) 5618 getStreamer().emitCFIPersonality(Sym, Encoding); 5619 else 5620 getStreamer().emitCFILsda(Sym, Encoding); 5621 return false; 5622 } 5623 5624 /// parseDirectiveCFIRememberState 5625 /// ::= .cfi_remember_state 5626 bool MasmParser::parseDirectiveCFIRememberState() { 5627 getStreamer().emitCFIRememberState(); 5628 return false; 5629 } 5630 5631 /// parseDirectiveCFIRestoreState 5632 /// ::= .cfi_remember_state 5633 bool MasmParser::parseDirectiveCFIRestoreState() { 5634 getStreamer().emitCFIRestoreState(); 5635 return false; 5636 } 5637 5638 /// parseDirectiveCFISameValue 5639 /// ::= .cfi_same_value register 5640 bool MasmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) { 5641 int64_t Register = 0; 5642 5643 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) 5644 return true; 5645 5646 getStreamer().emitCFISameValue(Register); 5647 return false; 5648 } 5649 5650 /// parseDirectiveCFIRestore 5651 /// ::= .cfi_restore register 5652 bool MasmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) { 5653 int64_t Register = 0; 5654 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) 5655 return true; 5656 5657 getStreamer().emitCFIRestore(Register); 5658 return false; 5659 } 5660 5661 /// parseDirectiveCFIEscape 5662 /// ::= .cfi_escape expression[,...] 5663 bool MasmParser::parseDirectiveCFIEscape() { 5664 std::string Values; 5665 int64_t CurrValue; 5666 if (parseAbsoluteExpression(CurrValue)) 5667 return true; 5668 5669 Values.push_back((uint8_t)CurrValue); 5670 5671 while (getLexer().is(AsmToken::Comma)) { 5672 Lex(); 5673 5674 if (parseAbsoluteExpression(CurrValue)) 5675 return true; 5676 5677 Values.push_back((uint8_t)CurrValue); 5678 } 5679 5680 getStreamer().emitCFIEscape(Values); 5681 return false; 5682 } 5683 5684 /// parseDirectiveCFIReturnColumn 5685 /// ::= .cfi_return_column register 5686 bool MasmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) { 5687 int64_t Register = 0; 5688 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) 5689 return true; 5690 getStreamer().emitCFIReturnColumn(Register); 5691 return false; 5692 } 5693 5694 /// parseDirectiveCFISignalFrame 5695 /// ::= .cfi_signal_frame 5696 bool MasmParser::parseDirectiveCFISignalFrame() { 5697 if (parseToken(AsmToken::EndOfStatement, 5698 "unexpected token in '.cfi_signal_frame'")) 5699 return true; 5700 5701 getStreamer().emitCFISignalFrame(); 5702 return false; 5703 } 5704 5705 /// parseDirectiveCFIUndefined 5706 /// ::= .cfi_undefined register 5707 bool MasmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) { 5708 int64_t Register = 0; 5709 5710 if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) 5711 return true; 5712 5713 getStreamer().emitCFIUndefined(Register); 5714 return false; 5715 } 5716 5717 /// parseDirectiveMacro 5718 /// ::= name macro [parameters] 5719 /// ["LOCAL" identifiers] 5720 /// parameters ::= parameter [, parameter]* 5721 /// parameter ::= name ":" qualifier 5722 /// qualifier ::= "req" | "vararg" | "=" macro_argument 5723 bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) { 5724 MCAsmMacroParameters Parameters; 5725 while (getLexer().isNot(AsmToken::EndOfStatement)) { 5726 if (!Parameters.empty() && Parameters.back().Vararg) 5727 return Error(Lexer.getLoc(), 5728 "Vararg parameter '" + Parameters.back().Name + 5729 "' should be last in the list of parameters"); 5730 5731 MCAsmMacroParameter Parameter; 5732 if (parseIdentifier(Parameter.Name)) 5733 return TokError("expected identifier in 'macro' directive"); 5734 5735 // Emit an error if two (or more) named parameters share the same name. 5736 for (const MCAsmMacroParameter& CurrParam : Parameters) 5737 if (CurrParam.Name.equals_insensitive(Parameter.Name)) 5738 return TokError("macro '" + Name + "' has multiple parameters" 5739 " named '" + Parameter.Name + "'"); 5740 5741 if (Lexer.is(AsmToken::Colon)) { 5742 Lex(); // consume ':' 5743 5744 if (parseOptionalToken(AsmToken::Equal)) { 5745 // Default value 5746 SMLoc ParamLoc; 5747 5748 ParamLoc = Lexer.getLoc(); 5749 if (parseMacroArgument(nullptr, Parameter.Value)) 5750 return true; 5751 } else { 5752 SMLoc QualLoc; 5753 StringRef Qualifier; 5754 5755 QualLoc = Lexer.getLoc(); 5756 if (parseIdentifier(Qualifier)) 5757 return Error(QualLoc, "missing parameter qualifier for " 5758 "'" + 5759 Parameter.Name + "' in macro '" + Name + 5760 "'"); 5761 5762 if (Qualifier.equals_insensitive("req")) 5763 Parameter.Required = true; 5764 else if (Qualifier.equals_insensitive("vararg")) 5765 Parameter.Vararg = true; 5766 else 5767 return Error(QualLoc, 5768 Qualifier + " is not a valid parameter qualifier for '" + 5769 Parameter.Name + "' in macro '" + Name + "'"); 5770 } 5771 } 5772 5773 Parameters.push_back(std::move(Parameter)); 5774 5775 if (getLexer().is(AsmToken::Comma)) 5776 Lex(); 5777 } 5778 5779 // Eat just the end of statement. 5780 Lexer.Lex(); 5781 5782 std::vector<std::string> Locals; 5783 if (getTok().is(AsmToken::Identifier) && 5784 getTok().getIdentifier().equals_insensitive("local")) { 5785 Lex(); // Eat the LOCAL directive. 5786 5787 StringRef ID; 5788 while (true) { 5789 if (parseIdentifier(ID)) 5790 return true; 5791 Locals.push_back(ID.lower()); 5792 5793 // If we see a comma, continue (and allow line continuation). 5794 if (!parseOptionalToken(AsmToken::Comma)) 5795 break; 5796 parseOptionalToken(AsmToken::EndOfStatement); 5797 } 5798 } 5799 5800 // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors. 5801 AsmToken EndToken, StartToken = getTok(); 5802 unsigned MacroDepth = 0; 5803 bool IsMacroFunction = false; 5804 // Lex the macro definition. 5805 while (true) { 5806 // Ignore Lexing errors in macros. 5807 while (Lexer.is(AsmToken::Error)) { 5808 Lexer.Lex(); 5809 } 5810 5811 // Check whether we have reached the end of the file. 5812 if (getLexer().is(AsmToken::Eof)) 5813 return Error(NameLoc, "no matching 'endm' in definition"); 5814 5815 // Otherwise, check whether we have reached the 'endm'... and determine if 5816 // this is a macro function. 5817 if (getLexer().is(AsmToken::Identifier)) { 5818 if (getTok().getIdentifier().equals_insensitive("endm")) { 5819 if (MacroDepth == 0) { // Outermost macro. 5820 EndToken = getTok(); 5821 Lexer.Lex(); 5822 if (getLexer().isNot(AsmToken::EndOfStatement)) 5823 return TokError("unexpected token in '" + EndToken.getIdentifier() + 5824 "' directive"); 5825 break; 5826 } else { 5827 // Otherwise we just found the end of an inner macro. 5828 --MacroDepth; 5829 } 5830 } else if (getTok().getIdentifier().equals_insensitive("exitm")) { 5831 if (MacroDepth == 0 && peekTok().isNot(AsmToken::EndOfStatement)) { 5832 IsMacroFunction = true; 5833 } 5834 } else if (isMacroLikeDirective()) { 5835 // We allow nested macros. Those aren't instantiated until the 5836 // outermost macro is expanded so just ignore them for now. 5837 ++MacroDepth; 5838 } 5839 } 5840 5841 // Otherwise, scan til the end of the statement. 5842 eatToEndOfStatement(); 5843 } 5844 5845 if (getContext().lookupMacro(Name.lower())) { 5846 return Error(NameLoc, "macro '" + Name + "' is already defined"); 5847 } 5848 5849 const char *BodyStart = StartToken.getLoc().getPointer(); 5850 const char *BodyEnd = EndToken.getLoc().getPointer(); 5851 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); 5852 MCAsmMacro Macro(Name, Body, std::move(Parameters), std::move(Locals), 5853 IsMacroFunction); 5854 DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n"; 5855 Macro.dump()); 5856 getContext().defineMacro(Name, std::move(Macro)); 5857 return false; 5858 } 5859 5860 /// parseDirectiveExitMacro 5861 /// ::= "exitm" [textitem] 5862 bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc, 5863 StringRef Directive, 5864 std::string &Value) { 5865 SMLoc EndLoc = getTok().getLoc(); 5866 if (getTok().isNot(AsmToken::EndOfStatement) && parseTextItem(Value)) 5867 return Error(EndLoc, 5868 "unable to parse text item in '" + Directive + "' directive"); 5869 eatToEndOfStatement(); 5870 5871 if (!isInsideMacroInstantiation()) 5872 return TokError("unexpected '" + Directive + "' in file, " 5873 "no current macro definition"); 5874 5875 // Exit all conditionals that are active in the current macro. 5876 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) { 5877 TheCondState = TheCondStack.back(); 5878 TheCondStack.pop_back(); 5879 } 5880 5881 handleMacroExit(); 5882 return false; 5883 } 5884 5885 /// parseDirectiveEndMacro 5886 /// ::= endm 5887 bool MasmParser::parseDirectiveEndMacro(StringRef Directive) { 5888 if (getLexer().isNot(AsmToken::EndOfStatement)) 5889 return TokError("unexpected token in '" + Directive + "' directive"); 5890 5891 // If we are inside a macro instantiation, terminate the current 5892 // instantiation. 5893 if (isInsideMacroInstantiation()) { 5894 handleMacroExit(); 5895 return false; 5896 } 5897 5898 // Otherwise, this .endmacro is a stray entry in the file; well formed 5899 // .endmacro directives are handled during the macro definition parsing. 5900 return TokError("unexpected '" + Directive + "' in file, " 5901 "no current macro definition"); 5902 } 5903 5904 /// parseDirectivePurgeMacro 5905 /// ::= purge identifier ( , identifier )* 5906 bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) { 5907 StringRef Name; 5908 while (true) { 5909 SMLoc NameLoc; 5910 if (parseTokenLoc(NameLoc) || 5911 check(parseIdentifier(Name), NameLoc, 5912 "expected identifier in 'purge' directive")) 5913 return true; 5914 5915 DEBUG_WITH_TYPE("asm-macros", dbgs() 5916 << "Un-defining macro: " << Name << "\n"); 5917 if (!getContext().lookupMacro(Name.lower())) 5918 return Error(NameLoc, "macro '" + Name + "' is not defined"); 5919 getContext().undefineMacro(Name.lower()); 5920 5921 if (!parseOptionalToken(AsmToken::Comma)) 5922 break; 5923 parseOptionalToken(AsmToken::EndOfStatement); 5924 } 5925 5926 return false; 5927 } 5928 5929 /// parseDirectiveSymbolAttribute 5930 /// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ] 5931 bool MasmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) { 5932 auto parseOp = [&]() -> bool { 5933 StringRef Name; 5934 SMLoc Loc = getTok().getLoc(); 5935 if (parseIdentifier(Name)) 5936 return Error(Loc, "expected identifier"); 5937 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 5938 5939 // Assembler local symbols don't make any sense here. Complain loudly. 5940 if (Sym->isTemporary()) 5941 return Error(Loc, "non-local symbol required"); 5942 5943 if (!getStreamer().emitSymbolAttribute(Sym, Attr)) 5944 return Error(Loc, "unable to emit symbol attribute"); 5945 return false; 5946 }; 5947 5948 if (parseMany(parseOp)) 5949 return addErrorSuffix(" in directive"); 5950 return false; 5951 } 5952 5953 /// parseDirectiveComm 5954 /// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ] 5955 bool MasmParser::parseDirectiveComm(bool IsLocal) { 5956 if (checkForValidSection()) 5957 return true; 5958 5959 SMLoc IDLoc = getLexer().getLoc(); 5960 StringRef Name; 5961 if (parseIdentifier(Name)) 5962 return TokError("expected identifier in directive"); 5963 5964 // Handle the identifier as the key symbol. 5965 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 5966 5967 if (getLexer().isNot(AsmToken::Comma)) 5968 return TokError("unexpected token in directive"); 5969 Lex(); 5970 5971 int64_t Size; 5972 SMLoc SizeLoc = getLexer().getLoc(); 5973 if (parseAbsoluteExpression(Size)) 5974 return true; 5975 5976 int64_t Pow2Alignment = 0; 5977 SMLoc Pow2AlignmentLoc; 5978 if (getLexer().is(AsmToken::Comma)) { 5979 Lex(); 5980 Pow2AlignmentLoc = getLexer().getLoc(); 5981 if (parseAbsoluteExpression(Pow2Alignment)) 5982 return true; 5983 5984 LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType(); 5985 if (IsLocal && LCOMM == LCOMM::NoAlignment) 5986 return Error(Pow2AlignmentLoc, "alignment not supported on this target"); 5987 5988 // If this target takes alignments in bytes (not log) validate and convert. 5989 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) || 5990 (IsLocal && LCOMM == LCOMM::ByteAlignment)) { 5991 if (!isPowerOf2_64(Pow2Alignment)) 5992 return Error(Pow2AlignmentLoc, "alignment must be a power of 2"); 5993 Pow2Alignment = Log2_64(Pow2Alignment); 5994 } 5995 } 5996 5997 if (parseToken(AsmToken::EndOfStatement, 5998 "unexpected token in '.comm' or '.lcomm' directive")) 5999 return true; 6000 6001 // NOTE: a size of zero for a .comm should create a undefined symbol 6002 // but a size of .lcomm creates a bss symbol of size zero. 6003 if (Size < 0) 6004 return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't " 6005 "be less than zero"); 6006 6007 // NOTE: The alignment in the directive is a power of 2 value, the assembler 6008 // may internally end up wanting an alignment in bytes. 6009 // FIXME: Diagnose overflow. 6010 if (Pow2Alignment < 0) 6011 return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive " 6012 "alignment, can't be less than zero"); 6013 6014 Sym->redefineIfPossible(); 6015 if (!Sym->isUndefined()) 6016 return Error(IDLoc, "invalid symbol redefinition"); 6017 6018 // Create the Symbol as a common or local common with Size and Pow2Alignment. 6019 if (IsLocal) { 6020 getStreamer().emitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment); 6021 return false; 6022 } 6023 6024 getStreamer().emitCommonSymbol(Sym, Size, 1 << Pow2Alignment); 6025 return false; 6026 } 6027 6028 /// parseDirectiveComment 6029 /// ::= comment delimiter [[text]] 6030 /// [[text]] 6031 /// [[text]] delimiter [[text]] 6032 bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) { 6033 std::string FirstLine = parseStringTo(AsmToken::EndOfStatement); 6034 size_t DelimiterEnd = FirstLine.find_first_of("\b\t\v\f\r\x1A "); 6035 StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd); 6036 if (Delimiter.empty()) 6037 return Error(DirectiveLoc, "no delimiter in 'comment' directive"); 6038 do { 6039 if (getTok().is(AsmToken::Eof)) 6040 return Error(DirectiveLoc, "unmatched delimiter in 'comment' directive"); 6041 Lex(); // eat end of statement 6042 } while ( 6043 !StringRef(parseStringTo(AsmToken::EndOfStatement)).contains(Delimiter)); 6044 return parseToken(AsmToken::EndOfStatement, 6045 "unexpected token in 'comment' directive"); 6046 } 6047 6048 /// parseDirectiveInclude 6049 /// ::= include <filename> 6050 /// | include filename 6051 bool MasmParser::parseDirectiveInclude() { 6052 // Allow the strings to have escaped octal character sequence. 6053 std::string Filename; 6054 SMLoc IncludeLoc = getTok().getLoc(); 6055 6056 if (parseAngleBracketString(Filename)) 6057 Filename = parseStringTo(AsmToken::EndOfStatement); 6058 if (check(Filename.empty(), "missing filename in 'include' directive") || 6059 check(getTok().isNot(AsmToken::EndOfStatement), 6060 "unexpected token in 'include' directive") || 6061 // Attempt to switch the lexer to the included file before consuming the 6062 // end of statement to avoid losing it when we switch. 6063 check(enterIncludeFile(Filename), IncludeLoc, 6064 "Could not find include file '" + Filename + "'")) 6065 return true; 6066 6067 return false; 6068 } 6069 6070 /// parseDirectiveIf 6071 /// ::= .if{,eq,ge,gt,le,lt,ne} expression 6072 bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) { 6073 TheCondStack.push_back(TheCondState); 6074 TheCondState.TheCond = AsmCond::IfCond; 6075 if (TheCondState.Ignore) { 6076 eatToEndOfStatement(); 6077 } else { 6078 int64_t ExprValue; 6079 if (parseAbsoluteExpression(ExprValue) || 6080 parseToken(AsmToken::EndOfStatement, 6081 "unexpected token in '.if' directive")) 6082 return true; 6083 6084 switch (DirKind) { 6085 default: 6086 llvm_unreachable("unsupported directive"); 6087 case DK_IF: 6088 break; 6089 case DK_IFE: 6090 ExprValue = ExprValue == 0; 6091 break; 6092 } 6093 6094 TheCondState.CondMet = ExprValue; 6095 TheCondState.Ignore = !TheCondState.CondMet; 6096 } 6097 6098 return false; 6099 } 6100 6101 /// parseDirectiveIfb 6102 /// ::= .ifb textitem 6103 bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { 6104 TheCondStack.push_back(TheCondState); 6105 TheCondState.TheCond = AsmCond::IfCond; 6106 6107 if (TheCondState.Ignore) { 6108 eatToEndOfStatement(); 6109 } else { 6110 std::string Str; 6111 if (parseTextItem(Str)) 6112 return TokError("expected text item parameter for 'ifb' directive"); 6113 6114 if (parseToken(AsmToken::EndOfStatement, 6115 "unexpected token in 'ifb' directive")) 6116 return true; 6117 6118 TheCondState.CondMet = ExpectBlank == Str.empty(); 6119 TheCondState.Ignore = !TheCondState.CondMet; 6120 } 6121 6122 return false; 6123 } 6124 6125 /// parseDirectiveIfidn 6126 /// ::= ifidn textitem, textitem 6127 bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual, 6128 bool CaseInsensitive) { 6129 std::string String1, String2; 6130 6131 if (parseTextItem(String1)) { 6132 if (ExpectEqual) 6133 return TokError("expected text item parameter for 'ifidn' directive"); 6134 return TokError("expected text item parameter for 'ifdif' directive"); 6135 } 6136 6137 if (Lexer.isNot(AsmToken::Comma)) { 6138 if (ExpectEqual) 6139 return TokError( 6140 "expected comma after first string for 'ifidn' directive"); 6141 return TokError("expected comma after first string for 'ifdif' directive"); 6142 } 6143 Lex(); 6144 6145 if (parseTextItem(String2)) { 6146 if (ExpectEqual) 6147 return TokError("expected text item parameter for 'ifidn' directive"); 6148 return TokError("expected text item parameter for 'ifdif' directive"); 6149 } 6150 6151 TheCondStack.push_back(TheCondState); 6152 TheCondState.TheCond = AsmCond::IfCond; 6153 if (CaseInsensitive) 6154 TheCondState.CondMet = 6155 ExpectEqual == (StringRef(String1).equals_insensitive(String2)); 6156 else 6157 TheCondState.CondMet = ExpectEqual == (String1 == String2); 6158 TheCondState.Ignore = !TheCondState.CondMet; 6159 6160 return false; 6161 } 6162 6163 /// parseDirectiveIfdef 6164 /// ::= ifdef symbol 6165 /// | ifdef variable 6166 bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { 6167 TheCondStack.push_back(TheCondState); 6168 TheCondState.TheCond = AsmCond::IfCond; 6169 6170 if (TheCondState.Ignore) { 6171 eatToEndOfStatement(); 6172 } else { 6173 bool is_defined = false; 6174 unsigned RegNo; 6175 SMLoc StartLoc, EndLoc; 6176 is_defined = (getTargetParser().tryParseRegister( 6177 RegNo, StartLoc, EndLoc) == MatchOperand_Success); 6178 if (!is_defined) { 6179 StringRef Name; 6180 if (check(parseIdentifier(Name), "expected identifier after 'ifdef'") || 6181 parseToken(AsmToken::EndOfStatement, "unexpected token in 'ifdef'")) 6182 return true; 6183 6184 if (Variables.find(Name.lower()) != Variables.end()) { 6185 is_defined = true; 6186 } else { 6187 MCSymbol *Sym = getContext().lookupSymbol(Name.lower()); 6188 is_defined = (Sym && !Sym->isUndefined(false)); 6189 } 6190 } 6191 6192 TheCondState.CondMet = (is_defined == expect_defined); 6193 TheCondState.Ignore = !TheCondState.CondMet; 6194 } 6195 6196 return false; 6197 } 6198 6199 /// parseDirectiveElseIf 6200 /// ::= elseif expression 6201 bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc, 6202 DirectiveKind DirKind) { 6203 if (TheCondState.TheCond != AsmCond::IfCond && 6204 TheCondState.TheCond != AsmCond::ElseIfCond) 6205 return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an" 6206 " .if or an .elseif"); 6207 TheCondState.TheCond = AsmCond::ElseIfCond; 6208 6209 bool LastIgnoreState = false; 6210 if (!TheCondStack.empty()) 6211 LastIgnoreState = TheCondStack.back().Ignore; 6212 if (LastIgnoreState || TheCondState.CondMet) { 6213 TheCondState.Ignore = true; 6214 eatToEndOfStatement(); 6215 } else { 6216 int64_t ExprValue; 6217 if (parseAbsoluteExpression(ExprValue)) 6218 return true; 6219 6220 if (parseToken(AsmToken::EndOfStatement, 6221 "unexpected token in '.elseif' directive")) 6222 return true; 6223 6224 switch (DirKind) { 6225 default: 6226 llvm_unreachable("unsupported directive"); 6227 case DK_ELSEIF: 6228 break; 6229 case DK_ELSEIFE: 6230 ExprValue = ExprValue == 0; 6231 break; 6232 } 6233 6234 TheCondState.CondMet = ExprValue; 6235 TheCondState.Ignore = !TheCondState.CondMet; 6236 } 6237 6238 return false; 6239 } 6240 6241 /// parseDirectiveElseIfb 6242 /// ::= elseifb textitem 6243 bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank) { 6244 if (TheCondState.TheCond != AsmCond::IfCond && 6245 TheCondState.TheCond != AsmCond::ElseIfCond) 6246 return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an" 6247 " if or an elseif"); 6248 TheCondState.TheCond = AsmCond::ElseIfCond; 6249 6250 bool LastIgnoreState = false; 6251 if (!TheCondStack.empty()) 6252 LastIgnoreState = TheCondStack.back().Ignore; 6253 if (LastIgnoreState || TheCondState.CondMet) { 6254 TheCondState.Ignore = true; 6255 eatToEndOfStatement(); 6256 } else { 6257 std::string Str; 6258 if (parseTextItem(Str)) { 6259 if (ExpectBlank) 6260 return TokError("expected text item parameter for 'elseifb' directive"); 6261 return TokError("expected text item parameter for 'elseifnb' directive"); 6262 } 6263 6264 if (parseToken(AsmToken::EndOfStatement, 6265 "unexpected token in 'elseifb' directive")) 6266 return true; 6267 6268 TheCondState.CondMet = ExpectBlank == Str.empty(); 6269 TheCondState.Ignore = !TheCondState.CondMet; 6270 } 6271 6272 return false; 6273 } 6274 6275 /// parseDirectiveElseIfdef 6276 /// ::= elseifdef symbol 6277 /// | elseifdef variable 6278 bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc, 6279 bool expect_defined) { 6280 if (TheCondState.TheCond != AsmCond::IfCond && 6281 TheCondState.TheCond != AsmCond::ElseIfCond) 6282 return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an" 6283 " if or an elseif"); 6284 TheCondState.TheCond = AsmCond::ElseIfCond; 6285 6286 bool LastIgnoreState = false; 6287 if (!TheCondStack.empty()) 6288 LastIgnoreState = TheCondStack.back().Ignore; 6289 if (LastIgnoreState || TheCondState.CondMet) { 6290 TheCondState.Ignore = true; 6291 eatToEndOfStatement(); 6292 } else { 6293 bool is_defined = false; 6294 unsigned RegNo; 6295 SMLoc StartLoc, EndLoc; 6296 is_defined = (getTargetParser().tryParseRegister(RegNo, StartLoc, EndLoc) == 6297 MatchOperand_Success); 6298 if (!is_defined) { 6299 StringRef Name; 6300 if (check(parseIdentifier(Name), 6301 "expected identifier after 'elseifdef'") || 6302 parseToken(AsmToken::EndOfStatement, 6303 "unexpected token in 'elseifdef'")) 6304 return true; 6305 6306 if (Variables.find(Name.lower()) != Variables.end()) { 6307 is_defined = true; 6308 } else { 6309 MCSymbol *Sym = getContext().lookupSymbol(Name); 6310 is_defined = (Sym && !Sym->isUndefined(false)); 6311 } 6312 } 6313 6314 TheCondState.CondMet = (is_defined == expect_defined); 6315 TheCondState.Ignore = !TheCondState.CondMet; 6316 } 6317 6318 return false; 6319 } 6320 6321 /// parseDirectiveElseIfidn 6322 /// ::= elseifidn textitem, textitem 6323 bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual, 6324 bool CaseInsensitive) { 6325 if (TheCondState.TheCond != AsmCond::IfCond && 6326 TheCondState.TheCond != AsmCond::ElseIfCond) 6327 return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an" 6328 " if or an elseif"); 6329 TheCondState.TheCond = AsmCond::ElseIfCond; 6330 6331 bool LastIgnoreState = false; 6332 if (!TheCondStack.empty()) 6333 LastIgnoreState = TheCondStack.back().Ignore; 6334 if (LastIgnoreState || TheCondState.CondMet) { 6335 TheCondState.Ignore = true; 6336 eatToEndOfStatement(); 6337 } else { 6338 std::string String1, String2; 6339 6340 if (parseTextItem(String1)) { 6341 if (ExpectEqual) 6342 return TokError( 6343 "expected text item parameter for 'elseifidn' directive"); 6344 return TokError("expected text item parameter for 'elseifdif' directive"); 6345 } 6346 6347 if (Lexer.isNot(AsmToken::Comma)) { 6348 if (ExpectEqual) 6349 return TokError( 6350 "expected comma after first string for 'elseifidn' directive"); 6351 return TokError( 6352 "expected comma after first string for 'elseifdif' directive"); 6353 } 6354 Lex(); 6355 6356 if (parseTextItem(String2)) { 6357 if (ExpectEqual) 6358 return TokError( 6359 "expected text item parameter for 'elseifidn' directive"); 6360 return TokError("expected text item parameter for 'elseifdif' directive"); 6361 } 6362 6363 if (CaseInsensitive) 6364 TheCondState.CondMet = 6365 ExpectEqual == (StringRef(String1).equals_insensitive(String2)); 6366 else 6367 TheCondState.CondMet = ExpectEqual == (String1 == String2); 6368 TheCondState.Ignore = !TheCondState.CondMet; 6369 } 6370 6371 return false; 6372 } 6373 6374 /// parseDirectiveElse 6375 /// ::= else 6376 bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) { 6377 if (parseToken(AsmToken::EndOfStatement, 6378 "unexpected token in 'else' directive")) 6379 return true; 6380 6381 if (TheCondState.TheCond != AsmCond::IfCond && 6382 TheCondState.TheCond != AsmCond::ElseIfCond) 6383 return Error(DirectiveLoc, "Encountered an else that doesn't follow an if" 6384 " or an elseif"); 6385 TheCondState.TheCond = AsmCond::ElseCond; 6386 bool LastIgnoreState = false; 6387 if (!TheCondStack.empty()) 6388 LastIgnoreState = TheCondStack.back().Ignore; 6389 if (LastIgnoreState || TheCondState.CondMet) 6390 TheCondState.Ignore = true; 6391 else 6392 TheCondState.Ignore = false; 6393 6394 return false; 6395 } 6396 6397 /// parseDirectiveEnd 6398 /// ::= end 6399 bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) { 6400 if (parseToken(AsmToken::EndOfStatement, 6401 "unexpected token in 'end' directive")) 6402 return true; 6403 6404 while (Lexer.isNot(AsmToken::Eof)) 6405 Lexer.Lex(); 6406 6407 return false; 6408 } 6409 6410 /// parseDirectiveError 6411 /// ::= .err [message] 6412 bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) { 6413 if (!TheCondStack.empty()) { 6414 if (TheCondStack.back().Ignore) { 6415 eatToEndOfStatement(); 6416 return false; 6417 } 6418 } 6419 6420 std::string Message = ".err directive invoked in source file"; 6421 if (Lexer.isNot(AsmToken::EndOfStatement)) 6422 Message = parseStringTo(AsmToken::EndOfStatement); 6423 Lex(); 6424 6425 return Error(DirectiveLoc, Message); 6426 } 6427 6428 /// parseDirectiveErrorIfb 6429 /// ::= .errb textitem[, message] 6430 bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank) { 6431 if (!TheCondStack.empty()) { 6432 if (TheCondStack.back().Ignore) { 6433 eatToEndOfStatement(); 6434 return false; 6435 } 6436 } 6437 6438 std::string Text; 6439 if (parseTextItem(Text)) 6440 return Error(getTok().getLoc(), "missing text item in '.errb' directive"); 6441 6442 std::string Message = ".errb directive invoked in source file"; 6443 if (Lexer.isNot(AsmToken::EndOfStatement)) { 6444 if (parseToken(AsmToken::Comma)) 6445 return addErrorSuffix(" in '.errb' directive"); 6446 Message = parseStringTo(AsmToken::EndOfStatement); 6447 } 6448 Lex(); 6449 6450 if (Text.empty() == ExpectBlank) 6451 return Error(DirectiveLoc, Message); 6452 return false; 6453 } 6454 6455 /// parseDirectiveErrorIfdef 6456 /// ::= .errdef name[, message] 6457 bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc, 6458 bool ExpectDefined) { 6459 if (!TheCondStack.empty()) { 6460 if (TheCondStack.back().Ignore) { 6461 eatToEndOfStatement(); 6462 return false; 6463 } 6464 } 6465 6466 bool IsDefined = false; 6467 unsigned RegNo; 6468 SMLoc StartLoc, EndLoc; 6469 IsDefined = (getTargetParser().tryParseRegister(RegNo, StartLoc, EndLoc) == 6470 MatchOperand_Success); 6471 if (!IsDefined) { 6472 StringRef Name; 6473 if (check(parseIdentifier(Name), "expected identifier after '.errdef'")) 6474 return true; 6475 6476 if (Variables.find(Name.lower()) != Variables.end()) { 6477 IsDefined = true; 6478 } else { 6479 MCSymbol *Sym = getContext().lookupSymbol(Name); 6480 IsDefined = (Sym && !Sym->isUndefined(false)); 6481 } 6482 } 6483 6484 std::string Message = ".errdef directive invoked in source file"; 6485 if (Lexer.isNot(AsmToken::EndOfStatement)) { 6486 if (parseToken(AsmToken::Comma)) 6487 return addErrorSuffix(" in '.errdef' directive"); 6488 Message = parseStringTo(AsmToken::EndOfStatement); 6489 } 6490 Lex(); 6491 6492 if (IsDefined == ExpectDefined) 6493 return Error(DirectiveLoc, Message); 6494 return false; 6495 } 6496 6497 /// parseDirectiveErrorIfidn 6498 /// ::= .erridn textitem, textitem[, message] 6499 bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual, 6500 bool CaseInsensitive) { 6501 if (!TheCondStack.empty()) { 6502 if (TheCondStack.back().Ignore) { 6503 eatToEndOfStatement(); 6504 return false; 6505 } 6506 } 6507 6508 std::string String1, String2; 6509 6510 if (parseTextItem(String1)) { 6511 if (ExpectEqual) 6512 return TokError("expected string parameter for '.erridn' directive"); 6513 return TokError("expected string parameter for '.errdif' directive"); 6514 } 6515 6516 if (Lexer.isNot(AsmToken::Comma)) { 6517 if (ExpectEqual) 6518 return TokError( 6519 "expected comma after first string for '.erridn' directive"); 6520 return TokError( 6521 "expected comma after first string for '.errdif' directive"); 6522 } 6523 Lex(); 6524 6525 if (parseTextItem(String2)) { 6526 if (ExpectEqual) 6527 return TokError("expected string parameter for '.erridn' directive"); 6528 return TokError("expected string parameter for '.errdif' directive"); 6529 } 6530 6531 std::string Message; 6532 if (ExpectEqual) 6533 Message = ".erridn directive invoked in source file"; 6534 else 6535 Message = ".errdif directive invoked in source file"; 6536 if (Lexer.isNot(AsmToken::EndOfStatement)) { 6537 if (parseToken(AsmToken::Comma)) 6538 return addErrorSuffix(" in '.erridn' directive"); 6539 Message = parseStringTo(AsmToken::EndOfStatement); 6540 } 6541 Lex(); 6542 6543 if (CaseInsensitive) 6544 TheCondState.CondMet = 6545 ExpectEqual == (StringRef(String1).equals_insensitive(String2)); 6546 else 6547 TheCondState.CondMet = ExpectEqual == (String1 == String2); 6548 TheCondState.Ignore = !TheCondState.CondMet; 6549 6550 if ((CaseInsensitive && 6551 ExpectEqual == StringRef(String1).equals_insensitive(String2)) || 6552 (ExpectEqual == (String1 == String2))) 6553 return Error(DirectiveLoc, Message); 6554 return false; 6555 } 6556 6557 /// parseDirectiveErrorIfe 6558 /// ::= .erre expression[, message] 6559 bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero) { 6560 if (!TheCondStack.empty()) { 6561 if (TheCondStack.back().Ignore) { 6562 eatToEndOfStatement(); 6563 return false; 6564 } 6565 } 6566 6567 int64_t ExprValue; 6568 if (parseAbsoluteExpression(ExprValue)) 6569 return addErrorSuffix(" in '.erre' directive"); 6570 6571 std::string Message = ".erre directive invoked in source file"; 6572 if (Lexer.isNot(AsmToken::EndOfStatement)) { 6573 if (parseToken(AsmToken::Comma)) 6574 return addErrorSuffix(" in '.erre' directive"); 6575 Message = parseStringTo(AsmToken::EndOfStatement); 6576 } 6577 Lex(); 6578 6579 if ((ExprValue == 0) == ExpectZero) 6580 return Error(DirectiveLoc, Message); 6581 return false; 6582 } 6583 6584 /// parseDirectiveEndIf 6585 /// ::= .endif 6586 bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) { 6587 if (parseToken(AsmToken::EndOfStatement, 6588 "unexpected token in '.endif' directive")) 6589 return true; 6590 6591 if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty()) 6592 return Error(DirectiveLoc, "Encountered a .endif that doesn't follow " 6593 "an .if or .else"); 6594 if (!TheCondStack.empty()) { 6595 TheCondState = TheCondStack.back(); 6596 TheCondStack.pop_back(); 6597 } 6598 6599 return false; 6600 } 6601 6602 void MasmParser::initializeDirectiveKindMap() { 6603 DirectiveKindMap["="] = DK_ASSIGN; 6604 DirectiveKindMap["equ"] = DK_EQU; 6605 DirectiveKindMap["textequ"] = DK_TEXTEQU; 6606 // DirectiveKindMap[".ascii"] = DK_ASCII; 6607 // DirectiveKindMap[".asciz"] = DK_ASCIZ; 6608 // DirectiveKindMap[".string"] = DK_STRING; 6609 DirectiveKindMap["byte"] = DK_BYTE; 6610 DirectiveKindMap["sbyte"] = DK_SBYTE; 6611 DirectiveKindMap["word"] = DK_WORD; 6612 DirectiveKindMap["sword"] = DK_SWORD; 6613 DirectiveKindMap["dword"] = DK_DWORD; 6614 DirectiveKindMap["sdword"] = DK_SDWORD; 6615 DirectiveKindMap["fword"] = DK_FWORD; 6616 DirectiveKindMap["qword"] = DK_QWORD; 6617 DirectiveKindMap["sqword"] = DK_SQWORD; 6618 DirectiveKindMap["real4"] = DK_REAL4; 6619 DirectiveKindMap["real8"] = DK_REAL8; 6620 DirectiveKindMap["real10"] = DK_REAL10; 6621 DirectiveKindMap["align"] = DK_ALIGN; 6622 DirectiveKindMap["even"] = DK_EVEN; 6623 DirectiveKindMap["org"] = DK_ORG; 6624 DirectiveKindMap["extern"] = DK_EXTERN; 6625 DirectiveKindMap["public"] = DK_PUBLIC; 6626 // DirectiveKindMap[".comm"] = DK_COMM; 6627 DirectiveKindMap["comment"] = DK_COMMENT; 6628 DirectiveKindMap["include"] = DK_INCLUDE; 6629 DirectiveKindMap["repeat"] = DK_REPEAT; 6630 DirectiveKindMap["rept"] = DK_REPEAT; 6631 DirectiveKindMap["while"] = DK_WHILE; 6632 DirectiveKindMap["for"] = DK_FOR; 6633 DirectiveKindMap["irp"] = DK_FOR; 6634 DirectiveKindMap["forc"] = DK_FORC; 6635 DirectiveKindMap["irpc"] = DK_FORC; 6636 DirectiveKindMap["if"] = DK_IF; 6637 DirectiveKindMap["ife"] = DK_IFE; 6638 DirectiveKindMap["ifb"] = DK_IFB; 6639 DirectiveKindMap["ifnb"] = DK_IFNB; 6640 DirectiveKindMap["ifdef"] = DK_IFDEF; 6641 DirectiveKindMap["ifndef"] = DK_IFNDEF; 6642 DirectiveKindMap["ifdif"] = DK_IFDIF; 6643 DirectiveKindMap["ifdifi"] = DK_IFDIFI; 6644 DirectiveKindMap["ifidn"] = DK_IFIDN; 6645 DirectiveKindMap["ifidni"] = DK_IFIDNI; 6646 DirectiveKindMap["elseif"] = DK_ELSEIF; 6647 DirectiveKindMap["elseifdef"] = DK_ELSEIFDEF; 6648 DirectiveKindMap["elseifndef"] = DK_ELSEIFNDEF; 6649 DirectiveKindMap["elseifdif"] = DK_ELSEIFDIF; 6650 DirectiveKindMap["elseifidn"] = DK_ELSEIFIDN; 6651 DirectiveKindMap["else"] = DK_ELSE; 6652 DirectiveKindMap["end"] = DK_END; 6653 DirectiveKindMap["endif"] = DK_ENDIF; 6654 // DirectiveKindMap[".file"] = DK_FILE; 6655 // DirectiveKindMap[".line"] = DK_LINE; 6656 // DirectiveKindMap[".loc"] = DK_LOC; 6657 // DirectiveKindMap[".stabs"] = DK_STABS; 6658 // DirectiveKindMap[".cv_file"] = DK_CV_FILE; 6659 // DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID; 6660 // DirectiveKindMap[".cv_loc"] = DK_CV_LOC; 6661 // DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE; 6662 // DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE; 6663 // DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID; 6664 // DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE; 6665 // DirectiveKindMap[".cv_string"] = DK_CV_STRING; 6666 // DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE; 6667 // DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS; 6668 // DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET; 6669 // DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA; 6670 // DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS; 6671 // DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC; 6672 // DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC; 6673 // DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA; 6674 // DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET; 6675 // DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET; 6676 // DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER; 6677 // DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET; 6678 // DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET; 6679 // DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY; 6680 // DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA; 6681 // DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE; 6682 // DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE; 6683 // DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE; 6684 // DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE; 6685 // DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE; 6686 // DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN; 6687 // DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME; 6688 // DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED; 6689 // DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER; 6690 // DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE; 6691 // DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME; 6692 DirectiveKindMap["macro"] = DK_MACRO; 6693 DirectiveKindMap["exitm"] = DK_EXITM; 6694 DirectiveKindMap["endm"] = DK_ENDM; 6695 DirectiveKindMap["purge"] = DK_PURGE; 6696 DirectiveKindMap[".err"] = DK_ERR; 6697 DirectiveKindMap[".errb"] = DK_ERRB; 6698 DirectiveKindMap[".errnb"] = DK_ERRNB; 6699 DirectiveKindMap[".errdef"] = DK_ERRDEF; 6700 DirectiveKindMap[".errndef"] = DK_ERRNDEF; 6701 DirectiveKindMap[".errdif"] = DK_ERRDIF; 6702 DirectiveKindMap[".errdifi"] = DK_ERRDIFI; 6703 DirectiveKindMap[".erridn"] = DK_ERRIDN; 6704 DirectiveKindMap[".erridni"] = DK_ERRIDNI; 6705 DirectiveKindMap[".erre"] = DK_ERRE; 6706 DirectiveKindMap[".errnz"] = DK_ERRNZ; 6707 DirectiveKindMap[".pushframe"] = DK_PUSHFRAME; 6708 DirectiveKindMap[".pushreg"] = DK_PUSHREG; 6709 DirectiveKindMap[".savereg"] = DK_SAVEREG; 6710 DirectiveKindMap[".savexmm128"] = DK_SAVEXMM128; 6711 DirectiveKindMap[".setframe"] = DK_SETFRAME; 6712 DirectiveKindMap[".radix"] = DK_RADIX; 6713 DirectiveKindMap["db"] = DK_DB; 6714 DirectiveKindMap["dd"] = DK_DD; 6715 DirectiveKindMap["df"] = DK_DF; 6716 DirectiveKindMap["dq"] = DK_DQ; 6717 DirectiveKindMap["dw"] = DK_DW; 6718 DirectiveKindMap["echo"] = DK_ECHO; 6719 DirectiveKindMap["struc"] = DK_STRUCT; 6720 DirectiveKindMap["struct"] = DK_STRUCT; 6721 DirectiveKindMap["union"] = DK_UNION; 6722 DirectiveKindMap["ends"] = DK_ENDS; 6723 } 6724 6725 bool MasmParser::isMacroLikeDirective() { 6726 if (getLexer().is(AsmToken::Identifier)) { 6727 bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier()) 6728 .CasesLower("repeat", "rept", true) 6729 .CaseLower("while", true) 6730 .CasesLower("for", "irp", true) 6731 .CasesLower("forc", "irpc", true) 6732 .Default(false); 6733 if (IsMacroLike) 6734 return true; 6735 } 6736 if (peekTok().is(AsmToken::Identifier) && 6737 peekTok().getIdentifier().equals_insensitive("macro")) 6738 return true; 6739 6740 return false; 6741 } 6742 6743 MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { 6744 AsmToken EndToken, StartToken = getTok(); 6745 6746 unsigned NestLevel = 0; 6747 while (true) { 6748 // Check whether we have reached the end of the file. 6749 if (getLexer().is(AsmToken::Eof)) { 6750 printError(DirectiveLoc, "no matching 'endm' in definition"); 6751 return nullptr; 6752 } 6753 6754 if (isMacroLikeDirective()) 6755 ++NestLevel; 6756 6757 // Otherwise, check whether we have reached the endm. 6758 if (Lexer.is(AsmToken::Identifier) && 6759 getTok().getIdentifier().equals_insensitive("endm")) { 6760 if (NestLevel == 0) { 6761 EndToken = getTok(); 6762 Lex(); 6763 if (Lexer.isNot(AsmToken::EndOfStatement)) { 6764 printError(getTok().getLoc(), "unexpected token in 'endm' directive"); 6765 return nullptr; 6766 } 6767 break; 6768 } 6769 --NestLevel; 6770 } 6771 6772 // Otherwise, scan till the end of the statement. 6773 eatToEndOfStatement(); 6774 } 6775 6776 const char *BodyStart = StartToken.getLoc().getPointer(); 6777 const char *BodyEnd = EndToken.getLoc().getPointer(); 6778 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); 6779 6780 // We Are Anonymous. 6781 MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters()); 6782 return &MacroLikeBodies.back(); 6783 } 6784 6785 bool MasmParser::expandStatement(SMLoc Loc) { 6786 std::string Body = parseStringTo(AsmToken::EndOfStatement); 6787 SMLoc EndLoc = getTok().getLoc(); 6788 6789 MCAsmMacroParameters Parameters; 6790 MCAsmMacroArguments Arguments; 6791 for (const auto &V : Variables) { 6792 const Variable &Var = V.getValue(); 6793 if (Var.IsText) { 6794 Parameters.emplace_back(); 6795 Arguments.emplace_back(); 6796 MCAsmMacroParameter &P = Parameters.back(); 6797 MCAsmMacroArgument &A = Arguments.back(); 6798 P.Name = Var.Name; 6799 P.Required = true; 6800 A.push_back(AsmToken(AsmToken::String, Var.TextValue)); 6801 } 6802 } 6803 MacroLikeBodies.emplace_back(StringRef(), Body, Parameters); 6804 MCAsmMacro M = MacroLikeBodies.back(); 6805 6806 // Expand the statement in a new buffer. 6807 SmallString<80> Buf; 6808 raw_svector_ostream OS(Buf); 6809 if (expandMacro(OS, M.Body, M.Parameters, Arguments, M.Locals, EndLoc)) 6810 return true; 6811 std::unique_ptr<MemoryBuffer> Expansion = 6812 MemoryBuffer::getMemBufferCopy(OS.str(), "<expansion>"); 6813 6814 // Jump to the expanded statement and prime the lexer. 6815 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Expansion), EndLoc); 6816 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); 6817 EndStatementAtEOFStack.push_back(false); 6818 Lex(); 6819 return false; 6820 } 6821 6822 void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, 6823 raw_svector_ostream &OS) { 6824 instantiateMacroLikeBody(M, DirectiveLoc, /*ExitLoc=*/getTok().getLoc(), OS); 6825 } 6826 void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, 6827 SMLoc ExitLoc, 6828 raw_svector_ostream &OS) { 6829 OS << "endm\n"; 6830 6831 std::unique_ptr<MemoryBuffer> Instantiation = 6832 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>"); 6833 6834 // Create the macro instantiation object and add to the current macro 6835 // instantiation stack. 6836 MacroInstantiation *MI = new MacroInstantiation{DirectiveLoc, CurBuffer, 6837 ExitLoc, TheCondStack.size()}; 6838 ActiveMacros.push_back(MI); 6839 6840 // Jump to the macro instantiation and prime the lexer. 6841 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc()); 6842 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); 6843 EndStatementAtEOFStack.push_back(true); 6844 Lex(); 6845 } 6846 6847 /// parseDirectiveRepeat 6848 /// ::= ("repeat" | "rept") count 6849 /// body 6850 /// endm 6851 bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) { 6852 const MCExpr *CountExpr; 6853 SMLoc CountLoc = getTok().getLoc(); 6854 if (parseExpression(CountExpr)) 6855 return true; 6856 6857 int64_t Count; 6858 if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) { 6859 return Error(CountLoc, "unexpected token in '" + Dir + "' directive"); 6860 } 6861 6862 if (check(Count < 0, CountLoc, "Count is negative") || 6863 parseToken(AsmToken::EndOfStatement, 6864 "unexpected token in '" + Dir + "' directive")) 6865 return true; 6866 6867 // Lex the repeat definition. 6868 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); 6869 if (!M) 6870 return true; 6871 6872 // Macro instantiation is lexical, unfortunately. We construct a new buffer 6873 // to hold the macro body with substitutions. 6874 SmallString<256> Buf; 6875 raw_svector_ostream OS(Buf); 6876 while (Count--) { 6877 if (expandMacro(OS, M->Body, None, None, M->Locals, getTok().getLoc())) 6878 return true; 6879 } 6880 instantiateMacroLikeBody(M, DirectiveLoc, OS); 6881 6882 return false; 6883 } 6884 6885 /// parseDirectiveWhile 6886 /// ::= "while" expression 6887 /// body 6888 /// endm 6889 bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) { 6890 const MCExpr *CondExpr; 6891 SMLoc CondLoc = getTok().getLoc(); 6892 if (parseExpression(CondExpr)) 6893 return true; 6894 6895 // Lex the repeat definition. 6896 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); 6897 if (!M) 6898 return true; 6899 6900 // Macro instantiation is lexical, unfortunately. We construct a new buffer 6901 // to hold the macro body with substitutions. 6902 SmallString<256> Buf; 6903 raw_svector_ostream OS(Buf); 6904 int64_t Condition; 6905 if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr())) 6906 return Error(CondLoc, "expected absolute expression in 'while' directive"); 6907 if (Condition) { 6908 // Instantiate the macro, then resume at this directive to recheck the 6909 // condition. 6910 if (expandMacro(OS, M->Body, None, None, M->Locals, getTok().getLoc())) 6911 return true; 6912 instantiateMacroLikeBody(M, DirectiveLoc, /*ExitLoc=*/DirectiveLoc, OS); 6913 } 6914 6915 return false; 6916 } 6917 6918 /// parseDirectiveFor 6919 /// ::= ("for" | "irp") symbol [":" qualifier], <values> 6920 /// body 6921 /// endm 6922 bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) { 6923 MCAsmMacroParameter Parameter; 6924 MCAsmMacroArguments A; 6925 if (check(parseIdentifier(Parameter.Name), 6926 "expected identifier in '" + Dir + "' directive")) 6927 return true; 6928 6929 // Parse optional qualifier (default value, or "req") 6930 if (parseOptionalToken(AsmToken::Colon)) { 6931 if (parseOptionalToken(AsmToken::Equal)) { 6932 // Default value 6933 SMLoc ParamLoc; 6934 6935 ParamLoc = Lexer.getLoc(); 6936 if (parseMacroArgument(nullptr, Parameter.Value)) 6937 return true; 6938 } else { 6939 SMLoc QualLoc; 6940 StringRef Qualifier; 6941 6942 QualLoc = Lexer.getLoc(); 6943 if (parseIdentifier(Qualifier)) 6944 return Error(QualLoc, "missing parameter qualifier for " 6945 "'" + 6946 Parameter.Name + "' in '" + Dir + 6947 "' directive"); 6948 6949 if (Qualifier.equals_insensitive("req")) 6950 Parameter.Required = true; 6951 else 6952 return Error(QualLoc, 6953 Qualifier + " is not a valid parameter qualifier for '" + 6954 Parameter.Name + "' in '" + Dir + "' directive"); 6955 } 6956 } 6957 6958 if (parseToken(AsmToken::Comma, 6959 "expected comma in '" + Dir + "' directive") || 6960 parseToken(AsmToken::Less, 6961 "values in '" + Dir + 6962 "' directive must be enclosed in angle brackets")) 6963 return true; 6964 6965 while (true) { 6966 A.emplace_back(); 6967 if (parseMacroArgument(&Parameter, A.back(), /*EndTok=*/AsmToken::Greater)) 6968 return addErrorSuffix(" in arguments for '" + Dir + "' directive"); 6969 6970 // If we see a comma, continue, and allow line continuation. 6971 if (!parseOptionalToken(AsmToken::Comma)) 6972 break; 6973 parseOptionalToken(AsmToken::EndOfStatement); 6974 } 6975 6976 if (parseToken(AsmToken::Greater, 6977 "values in '" + Dir + 6978 "' directive must be enclosed in angle brackets") || 6979 parseToken(AsmToken::EndOfStatement, "expected End of Statement")) 6980 return true; 6981 6982 // Lex the for definition. 6983 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); 6984 if (!M) 6985 return true; 6986 6987 // Macro instantiation is lexical, unfortunately. We construct a new buffer 6988 // to hold the macro body with substitutions. 6989 SmallString<256> Buf; 6990 raw_svector_ostream OS(Buf); 6991 6992 for (const MCAsmMacroArgument &Arg : A) { 6993 if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc())) 6994 return true; 6995 } 6996 6997 instantiateMacroLikeBody(M, DirectiveLoc, OS); 6998 6999 return false; 7000 } 7001 7002 /// parseDirectiveForc 7003 /// ::= ("forc" | "irpc") symbol, <string> 7004 /// body 7005 /// endm 7006 bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) { 7007 MCAsmMacroParameter Parameter; 7008 7009 std::string Argument; 7010 if (check(parseIdentifier(Parameter.Name), 7011 "expected identifier in '" + Directive + "' directive") || 7012 parseToken(AsmToken::Comma, 7013 "expected comma in '" + Directive + "' directive")) 7014 return true; 7015 if (parseAngleBracketString(Argument)) { 7016 // Match ml64.exe; treat all characters to end of statement as a string, 7017 // ignoring comment markers, then discard anything following a space (using 7018 // the C locale). 7019 Argument = parseStringTo(AsmToken::EndOfStatement); 7020 if (getTok().is(AsmToken::EndOfStatement)) 7021 Argument += getTok().getString(); 7022 size_t End = 0; 7023 for (; End < Argument.size(); ++End) { 7024 if (isSpace(Argument[End])) 7025 break; 7026 } 7027 Argument.resize(End); 7028 } 7029 if (parseToken(AsmToken::EndOfStatement, "expected end of statement")) 7030 return true; 7031 7032 // Lex the irpc definition. 7033 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); 7034 if (!M) 7035 return true; 7036 7037 // Macro instantiation is lexical, unfortunately. We construct a new buffer 7038 // to hold the macro body with substitutions. 7039 SmallString<256> Buf; 7040 raw_svector_ostream OS(Buf); 7041 7042 StringRef Values(Argument); 7043 for (std::size_t I = 0, End = Values.size(); I != End; ++I) { 7044 MCAsmMacroArgument Arg; 7045 Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1)); 7046 7047 if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc())) 7048 return true; 7049 } 7050 7051 instantiateMacroLikeBody(M, DirectiveLoc, OS); 7052 7053 return false; 7054 } 7055 7056 bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info, 7057 size_t Len) { 7058 const MCExpr *Value; 7059 SMLoc ExprLoc = getLexer().getLoc(); 7060 if (parseExpression(Value)) 7061 return true; 7062 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); 7063 if (!MCE) 7064 return Error(ExprLoc, "unexpected expression in _emit"); 7065 uint64_t IntValue = MCE->getValue(); 7066 if (!isUInt<8>(IntValue) && !isInt<8>(IntValue)) 7067 return Error(ExprLoc, "literal value out of range for directive"); 7068 7069 Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len); 7070 return false; 7071 } 7072 7073 bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) { 7074 const MCExpr *Value; 7075 SMLoc ExprLoc = getLexer().getLoc(); 7076 if (parseExpression(Value)) 7077 return true; 7078 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); 7079 if (!MCE) 7080 return Error(ExprLoc, "unexpected expression in align"); 7081 uint64_t IntValue = MCE->getValue(); 7082 if (!isPowerOf2_64(IntValue)) 7083 return Error(ExprLoc, "literal value not a power of two greater then zero"); 7084 7085 Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue)); 7086 return false; 7087 } 7088 7089 bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) { 7090 const SMLoc Loc = getLexer().getLoc(); 7091 std::string RadixStringRaw = parseStringTo(AsmToken::EndOfStatement); 7092 StringRef RadixString = StringRef(RadixStringRaw).trim(); 7093 unsigned Radix; 7094 if (RadixString.getAsInteger(10, Radix)) { 7095 return Error(Loc, 7096 "radix must be a decimal number in the range 2 to 16; was " + 7097 RadixString); 7098 } 7099 if (Radix < 2 || Radix > 16) 7100 return Error(Loc, "radix must be in the range 2 to 16; was " + 7101 std::to_string(Radix)); 7102 getLexer().setMasmDefaultRadix(Radix); 7103 return false; 7104 } 7105 7106 /// parseDirectiveEcho 7107 /// ::= "echo" message 7108 bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) { 7109 std::string Message = parseStringTo(AsmToken::EndOfStatement); 7110 llvm::outs() << Message; 7111 if (!StringRef(Message).endswith("\n")) 7112 llvm::outs() << '\n'; 7113 return false; 7114 } 7115 7116 // We are comparing pointers, but the pointers are relative to a single string. 7117 // Thus, this should always be deterministic. 7118 static int rewritesSort(const AsmRewrite *AsmRewriteA, 7119 const AsmRewrite *AsmRewriteB) { 7120 if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer()) 7121 return -1; 7122 if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer()) 7123 return 1; 7124 7125 // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output 7126 // rewrite to the same location. Make sure the SizeDirective rewrite is 7127 // performed first, then the Imm/ImmPrefix and finally the Input/Output. This 7128 // ensures the sort algorithm is stable. 7129 if (AsmRewritePrecedence[AsmRewriteA->Kind] > 7130 AsmRewritePrecedence[AsmRewriteB->Kind]) 7131 return -1; 7132 7133 if (AsmRewritePrecedence[AsmRewriteA->Kind] < 7134 AsmRewritePrecedence[AsmRewriteB->Kind]) 7135 return 1; 7136 llvm_unreachable("Unstable rewrite sort."); 7137 } 7138 7139 bool MasmParser::defineMacro(StringRef Name, StringRef Value) { 7140 Variable &Var = Variables[Name.lower()]; 7141 if (Var.Name.empty()) { 7142 Var.Name = Name; 7143 } else if (Var.Redefinable == Variable::NOT_REDEFINABLE) { 7144 return Error(SMLoc(), "invalid variable redefinition"); 7145 } else if (Var.Redefinable == Variable::WARN_ON_REDEFINITION && 7146 Warning(SMLoc(), "redefining '" + Name + 7147 "', already defined on the command line")) { 7148 return true; 7149 } 7150 Var.Redefinable = Variable::WARN_ON_REDEFINITION; 7151 Var.IsText = true; 7152 Var.TextValue = Value.str(); 7153 return false; 7154 } 7155 7156 bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info) const { 7157 const std::pair<StringRef, StringRef> BaseMember = Name.split('.'); 7158 const StringRef Base = BaseMember.first, Member = BaseMember.second; 7159 return lookUpField(Base, Member, Info); 7160 } 7161 7162 bool MasmParser::lookUpField(StringRef Base, StringRef Member, 7163 AsmFieldInfo &Info) const { 7164 if (Base.empty()) 7165 return true; 7166 7167 AsmFieldInfo BaseInfo; 7168 if (Base.contains('.') && !lookUpField(Base, BaseInfo)) 7169 Base = BaseInfo.Type.Name; 7170 7171 auto StructIt = Structs.find(Base.lower()); 7172 auto TypeIt = KnownType.find(Base.lower()); 7173 if (TypeIt != KnownType.end()) { 7174 StructIt = Structs.find(TypeIt->second.Name.lower()); 7175 } 7176 if (StructIt != Structs.end()) 7177 return lookUpField(StructIt->second, Member, Info); 7178 7179 return true; 7180 } 7181 7182 bool MasmParser::lookUpField(const StructInfo &Structure, StringRef Member, 7183 AsmFieldInfo &Info) const { 7184 if (Member.empty()) { 7185 Info.Type.Name = Structure.Name; 7186 Info.Type.Size = Structure.Size; 7187 Info.Type.ElementSize = Structure.Size; 7188 Info.Type.Length = 1; 7189 return false; 7190 } 7191 7192 std::pair<StringRef, StringRef> Split = Member.split('.'); 7193 const StringRef FieldName = Split.first, FieldMember = Split.second; 7194 7195 auto StructIt = Structs.find(FieldName.lower()); 7196 if (StructIt != Structs.end()) 7197 return lookUpField(StructIt->second, FieldMember, Info); 7198 7199 auto FieldIt = Structure.FieldsByName.find(FieldName.lower()); 7200 if (FieldIt == Structure.FieldsByName.end()) 7201 return true; 7202 7203 const FieldInfo &Field = Structure.Fields[FieldIt->second]; 7204 if (FieldMember.empty()) { 7205 Info.Offset += Field.Offset; 7206 Info.Type.Size = Field.SizeOf; 7207 Info.Type.ElementSize = Field.Type; 7208 Info.Type.Length = Field.LengthOf; 7209 if (Field.Contents.FT == FT_STRUCT) 7210 Info.Type.Name = Field.Contents.StructInfo.Structure.Name; 7211 else 7212 Info.Type.Name = ""; 7213 return false; 7214 } 7215 7216 if (Field.Contents.FT != FT_STRUCT) 7217 return true; 7218 const StructFieldInfo &StructInfo = Field.Contents.StructInfo; 7219 7220 if (lookUpField(StructInfo.Structure, FieldMember, Info)) 7221 return true; 7222 7223 Info.Offset += Field.Offset; 7224 return false; 7225 } 7226 7227 bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info) const { 7228 unsigned Size = StringSwitch<unsigned>(Name) 7229 .CasesLower("byte", "db", "sbyte", 1) 7230 .CasesLower("word", "dw", "sword", 2) 7231 .CasesLower("dword", "dd", "sdword", 4) 7232 .CasesLower("fword", "df", 6) 7233 .CasesLower("qword", "dq", "sqword", 8) 7234 .CaseLower("real4", 4) 7235 .CaseLower("real8", 8) 7236 .CaseLower("real10", 10) 7237 .Default(0); 7238 if (Size) { 7239 Info.Name = Name; 7240 Info.ElementSize = Size; 7241 Info.Length = 1; 7242 Info.Size = Size; 7243 return false; 7244 } 7245 7246 auto StructIt = Structs.find(Name.lower()); 7247 if (StructIt != Structs.end()) { 7248 const StructInfo &Structure = StructIt->second; 7249 Info.Name = Name; 7250 Info.ElementSize = Structure.Size; 7251 Info.Length = 1; 7252 Info.Size = Structure.Size; 7253 return false; 7254 } 7255 7256 return true; 7257 } 7258 7259 bool MasmParser::parseMSInlineAsm( 7260 void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, 7261 unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls, 7262 SmallVectorImpl<std::string> &Constraints, 7263 SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII, 7264 const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) { 7265 SmallVector<void *, 4> InputDecls; 7266 SmallVector<void *, 4> OutputDecls; 7267 SmallVector<bool, 4> InputDeclsAddressOf; 7268 SmallVector<bool, 4> OutputDeclsAddressOf; 7269 SmallVector<std::string, 4> InputConstraints; 7270 SmallVector<std::string, 4> OutputConstraints; 7271 SmallVector<unsigned, 4> ClobberRegs; 7272 7273 SmallVector<AsmRewrite, 4> AsmStrRewrites; 7274 7275 // Prime the lexer. 7276 Lex(); 7277 7278 // While we have input, parse each statement. 7279 unsigned InputIdx = 0; 7280 unsigned OutputIdx = 0; 7281 while (getLexer().isNot(AsmToken::Eof)) { 7282 // Parse curly braces marking block start/end. 7283 if (parseCurlyBlockScope(AsmStrRewrites)) 7284 continue; 7285 7286 ParseStatementInfo Info(&AsmStrRewrites); 7287 bool StatementErr = parseStatement(Info, &SI); 7288 7289 if (StatementErr || Info.ParseError) { 7290 // Emit pending errors if any exist. 7291 printPendingErrors(); 7292 return true; 7293 } 7294 7295 // No pending error should exist here. 7296 assert(!hasPendingError() && "unexpected error from parseStatement"); 7297 7298 if (Info.Opcode == ~0U) 7299 continue; 7300 7301 const MCInstrDesc &Desc = MII->get(Info.Opcode); 7302 7303 // Build the list of clobbers, outputs and inputs. 7304 for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) { 7305 MCParsedAsmOperand &Operand = *Info.ParsedOperands[i]; 7306 7307 // Register operand. 7308 if (Operand.isReg() && !Operand.needAddressOf() && 7309 !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) { 7310 unsigned NumDefs = Desc.getNumDefs(); 7311 // Clobber. 7312 if (NumDefs && Operand.getMCOperandNum() < NumDefs) 7313 ClobberRegs.push_back(Operand.getReg()); 7314 continue; 7315 } 7316 7317 // Expr/Input or Output. 7318 StringRef SymName = Operand.getSymName(); 7319 if (SymName.empty()) 7320 continue; 7321 7322 void *OpDecl = Operand.getOpDecl(); 7323 if (!OpDecl) 7324 continue; 7325 7326 StringRef Constraint = Operand.getConstraint(); 7327 if (Operand.isImm()) { 7328 // Offset as immediate. 7329 if (Operand.isOffsetOfLocal()) 7330 Constraint = "r"; 7331 else 7332 Constraint = "i"; 7333 } 7334 7335 bool isOutput = (i == 1) && Desc.mayStore(); 7336 SMLoc Start = SMLoc::getFromPointer(SymName.data()); 7337 if (isOutput) { 7338 ++InputIdx; 7339 OutputDecls.push_back(OpDecl); 7340 OutputDeclsAddressOf.push_back(Operand.needAddressOf()); 7341 OutputConstraints.push_back(("=" + Constraint).str()); 7342 AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size()); 7343 } else { 7344 InputDecls.push_back(OpDecl); 7345 InputDeclsAddressOf.push_back(Operand.needAddressOf()); 7346 InputConstraints.push_back(Constraint.str()); 7347 if (Desc.OpInfo[i - 1].isBranchTarget()) 7348 AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size()); 7349 else 7350 AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size()); 7351 } 7352 } 7353 7354 // Consider implicit defs to be clobbers. Think of cpuid and push. 7355 ArrayRef<MCPhysReg> ImpDefs(Desc.getImplicitDefs(), 7356 Desc.getNumImplicitDefs()); 7357 llvm::append_range(ClobberRegs, ImpDefs); 7358 } 7359 7360 // Set the number of Outputs and Inputs. 7361 NumOutputs = OutputDecls.size(); 7362 NumInputs = InputDecls.size(); 7363 7364 // Set the unique clobbers. 7365 array_pod_sort(ClobberRegs.begin(), ClobberRegs.end()); 7366 ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()), 7367 ClobberRegs.end()); 7368 Clobbers.assign(ClobberRegs.size(), std::string()); 7369 for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) { 7370 raw_string_ostream OS(Clobbers[I]); 7371 IP->printRegName(OS, ClobberRegs[I]); 7372 } 7373 7374 // Merge the various outputs and inputs. Output are expected first. 7375 if (NumOutputs || NumInputs) { 7376 unsigned NumExprs = NumOutputs + NumInputs; 7377 OpDecls.resize(NumExprs); 7378 Constraints.resize(NumExprs); 7379 for (unsigned i = 0; i < NumOutputs; ++i) { 7380 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]); 7381 Constraints[i] = OutputConstraints[i]; 7382 } 7383 for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) { 7384 OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]); 7385 Constraints[j] = InputConstraints[i]; 7386 } 7387 } 7388 7389 // Build the IR assembly string. 7390 std::string AsmStringIR; 7391 raw_string_ostream OS(AsmStringIR); 7392 StringRef ASMString = 7393 SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer(); 7394 const char *AsmStart = ASMString.begin(); 7395 const char *AsmEnd = ASMString.end(); 7396 array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort); 7397 for (auto it = AsmStrRewrites.begin(); it != AsmStrRewrites.end(); ++it) { 7398 const AsmRewrite &AR = *it; 7399 // Check if this has already been covered by another rewrite... 7400 if (AR.Done) 7401 continue; 7402 AsmRewriteKind Kind = AR.Kind; 7403 7404 const char *Loc = AR.Loc.getPointer(); 7405 assert(Loc >= AsmStart && "Expected Loc to be at or after Start!"); 7406 7407 // Emit everything up to the immediate/expression. 7408 if (unsigned Len = Loc - AsmStart) 7409 OS << StringRef(AsmStart, Len); 7410 7411 // Skip the original expression. 7412 if (Kind == AOK_Skip) { 7413 AsmStart = Loc + AR.Len; 7414 continue; 7415 } 7416 7417 unsigned AdditionalSkip = 0; 7418 // Rewrite expressions in $N notation. 7419 switch (Kind) { 7420 default: 7421 break; 7422 case AOK_IntelExpr: 7423 assert(AR.IntelExp.isValid() && "cannot write invalid intel expression"); 7424 if (AR.IntelExp.NeedBracs) 7425 OS << "["; 7426 if (AR.IntelExp.hasBaseReg()) 7427 OS << AR.IntelExp.BaseReg; 7428 if (AR.IntelExp.hasIndexReg()) 7429 OS << (AR.IntelExp.hasBaseReg() ? " + " : "") 7430 << AR.IntelExp.IndexReg; 7431 if (AR.IntelExp.Scale > 1) 7432 OS << " * $$" << AR.IntelExp.Scale; 7433 if (AR.IntelExp.hasOffset()) { 7434 if (AR.IntelExp.hasRegs()) 7435 OS << " + "; 7436 // Fuse this rewrite with a rewrite of the offset name, if present. 7437 StringRef OffsetName = AR.IntelExp.OffsetName; 7438 SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data()); 7439 size_t OffsetLen = OffsetName.size(); 7440 auto rewrite_it = std::find_if( 7441 it, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) { 7442 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen && 7443 (FusingAR.Kind == AOK_Input || 7444 FusingAR.Kind == AOK_CallInput); 7445 }); 7446 if (rewrite_it == AsmStrRewrites.end()) { 7447 OS << "offset " << OffsetName; 7448 } else if (rewrite_it->Kind == AOK_CallInput) { 7449 OS << "${" << InputIdx++ << ":P}"; 7450 rewrite_it->Done = true; 7451 } else { 7452 OS << '$' << InputIdx++; 7453 rewrite_it->Done = true; 7454 } 7455 } 7456 if (AR.IntelExp.Imm || AR.IntelExp.emitImm()) 7457 OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm; 7458 if (AR.IntelExp.NeedBracs) 7459 OS << "]"; 7460 break; 7461 case AOK_Label: 7462 OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label; 7463 break; 7464 case AOK_Input: 7465 OS << '$' << InputIdx++; 7466 break; 7467 case AOK_CallInput: 7468 OS << "${" << InputIdx++ << ":P}"; 7469 break; 7470 case AOK_Output: 7471 OS << '$' << OutputIdx++; 7472 break; 7473 case AOK_SizeDirective: 7474 switch (AR.Val) { 7475 default: break; 7476 case 8: OS << "byte ptr "; break; 7477 case 16: OS << "word ptr "; break; 7478 case 32: OS << "dword ptr "; break; 7479 case 64: OS << "qword ptr "; break; 7480 case 80: OS << "xword ptr "; break; 7481 case 128: OS << "xmmword ptr "; break; 7482 case 256: OS << "ymmword ptr "; break; 7483 } 7484 break; 7485 case AOK_Emit: 7486 OS << ".byte"; 7487 break; 7488 case AOK_Align: { 7489 // MS alignment directives are measured in bytes. If the native assembler 7490 // measures alignment in bytes, we can pass it straight through. 7491 OS << ".align"; 7492 if (getContext().getAsmInfo()->getAlignmentIsInBytes()) 7493 break; 7494 7495 // Alignment is in log2 form, so print that instead and skip the original 7496 // immediate. 7497 unsigned Val = AR.Val; 7498 OS << ' ' << Val; 7499 assert(Val < 10 && "Expected alignment less then 2^10."); 7500 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4; 7501 break; 7502 } 7503 case AOK_EVEN: 7504 OS << ".even"; 7505 break; 7506 case AOK_EndOfStatement: 7507 OS << "\n\t"; 7508 break; 7509 } 7510 7511 // Skip the original expression. 7512 AsmStart = Loc + AR.Len + AdditionalSkip; 7513 } 7514 7515 // Emit the remainder of the asm string. 7516 if (AsmStart != AsmEnd) 7517 OS << StringRef(AsmStart, AsmEnd - AsmStart); 7518 7519 AsmString = OS.str(); 7520 return false; 7521 } 7522 7523 /// Create an MCAsmParser instance. 7524 MCAsmParser *llvm::createMCMasmParser(SourceMgr &SM, MCContext &C, 7525 MCStreamer &Out, const MCAsmInfo &MAI, 7526 unsigned CB) { 7527 return new MasmParser(SM, C, Out, MAI, CB); 7528 } 7529