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