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