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