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