LLVM: lib/MC/MCParser/MasmParser.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
55#include
56#include
57#include
58#include
59#include
60#include
61#include
62#include
63#include
64#include
65#include
66#include
67#include
68#include
69
70using namespace llvm;
71
72namespace {
73
74
75typedef std::vector MCAsmMacroArgument;
76typedef std::vector MCAsmMacroArguments;
77
78
79struct MacroInstantiation {
80
81 SMLoc InstantiationLoc;
82
83
84 unsigned ExitBuffer;
85
86
87 SMLoc ExitLoc;
88
89
90 size_t CondStackDepth;
91};
92
93struct ParseStatementInfo {
94
96
97
98 unsigned Opcode = ~0U;
99
100
101 bool ParseError = false;
102
103
104 std::optionalstd::string ExitValue;
105
106 SmallVectorImpl *AsmRewrites = nullptr;
107
108 ParseStatementInfo() = delete;
109 ParseStatementInfo(SmallVectorImpl *rewrites)
110 : AsmRewrites(rewrites) {}
111};
112
113enum FieldType {
114 FT_INTEGRAL,
115 FT_REAL,
116 FT_STRUCT
117};
118
119struct FieldInfo;
120struct StructInfo {
121 StringRef Name;
122 bool IsUnion = false;
123 bool Initializable = true;
124 unsigned Alignment = 0;
125 unsigned AlignmentSize = 0;
126 unsigned NextOffset = 0;
127 unsigned Size = 0;
128 std::vector Fields;
129 StringMap<size_t> FieldsByName;
130
131 FieldInfo &addField(StringRef FieldName, FieldType FT,
132 unsigned FieldAlignmentSize);
133
134 StructInfo() = default;
135 StructInfo(StringRef StructName, bool Union, unsigned AlignmentValue);
136};
137
138
139
140
141
142
143struct StructInitializer;
144struct IntFieldInfo {
146
147 IntFieldInfo() = default;
150};
151struct RealFieldInfo {
153
154 RealFieldInfo() = default;
157};
158struct StructFieldInfo {
159 std::vector Initializers;
160 StructInfo Structure;
161
162 StructFieldInfo() = default;
163 StructFieldInfo(std::vector V, StructInfo S);
164};
165
166class FieldInitializer {
167public:
168 FieldType FT;
169 union {
170 IntFieldInfo IntInfo;
171 RealFieldInfo RealInfo;
172 StructFieldInfo StructInfo;
173 };
174
175 ~FieldInitializer();
176 FieldInitializer(FieldType FT);
177
180 FieldInitializer(std::vector &&Initializers,
181 struct StructInfo Structure);
182
183 FieldInitializer(const FieldInitializer &Initializer);
184 FieldInitializer(FieldInitializer &&Initializer);
185
186 FieldInitializer &operator=(const FieldInitializer &Initializer);
187 FieldInitializer &operator=(FieldInitializer &&Initializer);
188};
189
190struct StructInitializer {
191 std::vector FieldInitializers;
192};
193
194struct FieldInfo {
195
196 unsigned Offset = 0;
197
198
199 unsigned SizeOf = 0;
200
201
202 unsigned LengthOf = 0;
203
204
205 unsigned Type = 0;
206
207 FieldInitializer Contents;
208
209 FieldInfo(FieldType FT) : Contents(FT) {}
210};
211
212StructFieldInfo::StructFieldInfo(std::vector V,
213 StructInfo S) {
214 Initializers = std::move(V);
215 Structure = S;
216}
217
218StructInfo::StructInfo(StringRef StructName, bool Union,
219 unsigned AlignmentValue)
221
222FieldInfo &StructInfo::addField(StringRef FieldName, FieldType FT,
223 unsigned FieldAlignmentSize) {
224 if (!FieldName.empty())
225 FieldsByName[FieldName.lower()] = Fields.size();
226 Fields.emplace_back(FT);
227 FieldInfo &Field = Fields.back();
229 llvm::alignTo(NextOffset, std::min(Alignment, FieldAlignmentSize));
230 if (!IsUnion) {
231 NextOffset = std::max(NextOffset, Field.Offset);
232 }
233 AlignmentSize = std::max(AlignmentSize, FieldAlignmentSize);
235}
236
237FieldInitializer::~FieldInitializer() {
238 switch (FT) {
239 case FT_INTEGRAL:
240 IntInfo.~IntFieldInfo();
241 break;
242 case FT_REAL:
243 RealInfo.~RealFieldInfo();
244 break;
245 case FT_STRUCT:
246 StructInfo.~StructFieldInfo();
247 break;
248 }
249}
250
251FieldInitializer::FieldInitializer(FieldType FT) : FT(FT) {
252 switch (FT) {
253 case FT_INTEGRAL:
254 new (&IntInfo) IntFieldInfo();
255 break;
256 case FT_REAL:
257 new (&RealInfo) RealFieldInfo();
258 break;
259 case FT_STRUCT:
260 new (&StructInfo) StructFieldInfo();
261 break;
262 }
263}
264
266 : FT(FT_INTEGRAL) {
267 new (&IntInfo) IntFieldInfo(std::move(Values));
268}
269
271 : FT(FT_REAL) {
272 new (&RealInfo) RealFieldInfo(std::move(AsIntValues));
273}
274
275FieldInitializer::FieldInitializer(
276 std::vector &&Initializers, struct StructInfo Structure)
277 : FT(FT_STRUCT) {
278 new (&StructInfo) StructFieldInfo(std::move(Initializers), Structure);
279}
280
281FieldInitializer::FieldInitializer(const FieldInitializer &Initializer)
282 : FT(Initializer.FT) {
283 switch (FT) {
284 case FT_INTEGRAL:
285 new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
286 break;
287 case FT_REAL:
288 new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
289 break;
290 case FT_STRUCT:
291 new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
292 break;
293 }
294}
295
296FieldInitializer::FieldInitializer(FieldInitializer &&Initializer)
297 : FT(Initializer.FT) {
298 switch (FT) {
299 case FT_INTEGRAL:
300 new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
301 break;
302 case FT_REAL:
303 new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
304 break;
305 case FT_STRUCT:
306 new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
307 break;
308 }
309}
310
311FieldInitializer &
312FieldInitializer::operator=(const FieldInitializer &Initializer) {
313 if (FT != Initializer.FT) {
314 switch (FT) {
315 case FT_INTEGRAL:
316 IntInfo.~IntFieldInfo();
317 break;
318 case FT_REAL:
319 RealInfo.~RealFieldInfo();
320 break;
321 case FT_STRUCT:
322 StructInfo.~StructFieldInfo();
323 break;
324 }
325 }
326 FT = Initializer.FT;
327 switch (FT) {
328 case FT_INTEGRAL:
329 IntInfo = Initializer.IntInfo;
330 break;
331 case FT_REAL:
332 RealInfo = Initializer.RealInfo;
333 break;
334 case FT_STRUCT:
335 StructInfo = Initializer.StructInfo;
336 break;
337 }
338 return *this;
339}
340
341FieldInitializer &FieldInitializer::operator=(FieldInitializer &&Initializer) {
342 if (FT != Initializer.FT) {
343 switch (FT) {
344 case FT_INTEGRAL:
345 IntInfo.~IntFieldInfo();
346 break;
347 case FT_REAL:
348 RealInfo.~RealFieldInfo();
349 break;
350 case FT_STRUCT:
351 StructInfo.~StructFieldInfo();
352 break;
353 }
354 }
355 FT = Initializer.FT;
356 switch (FT) {
357 case FT_INTEGRAL:
358 IntInfo = Initializer.IntInfo;
359 break;
360 case FT_REAL:
361 RealInfo = Initializer.RealInfo;
362 break;
363 case FT_STRUCT:
364 StructInfo = Initializer.StructInfo;
365 break;
366 }
367 return *this;
368}
369
370
371
372
373class MasmParser : public MCAsmParser {
374private:
376 void *SavedDiagContext;
377 std::unique_ptr PlatformParser;
378
379
380
381 unsigned CurBuffer;
382
383
384 struct tm TM;
385
386 BitVector EndStatementAtEOFStack;
387
388 AsmCond TheCondState;
389 std::vector TheCondStack;
390
391
392
393
394 StringMap ExtensionDirectiveMap;
395
396
398 enum RedefinableKind { NOT_REDEFINABLE, WARN_ON_REDEFINITION, REDEFINABLE };
399
400 StringRef Name;
401 RedefinableKind Redefinable = REDEFINABLE;
402 bool IsText = false;
403 std::string TextValue;
404 };
405 StringMap Variables;
406
407
409
410
411 StringMap Structs;
412
413
414 StringMap KnownType;
415
416
417 std::vector<MacroInstantiation*> ActiveMacros;
418
419
420 std::deque MacroLikeBodies;
421
422
423 unsigned NumOfMacroInstantiations;
424
425
426 struct CppHashInfoTy {
427 StringRef Filename;
428 int64_t LineNumber;
429 SMLoc Loc;
430 unsigned Buf;
431 CppHashInfoTy() : LineNumber(0), Buf(0) {}
432 };
433 CppHashInfoTy CppHashInfo;
434
435
436 StringRef FirstCppHashFilename;
437
438
440
441
442
443 unsigned AssemblerDialect = 1U;
444
445
446 bool ParsingMSInlineAsm = false;
447
448
449 unsigned AngleBracketDepth = 0U;
450
451
452 uint16_t LocalCounter = 0;
453
454public:
455 MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
456 const MCAsmInfo &MAI, struct tm TM, unsigned CB = 0);
457 MasmParser(const MasmParser &) = delete;
458 MasmParser &operator=(const MasmParser &) = delete;
459 ~MasmParser() override;
460
461 bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
462
463 void addDirectiveHandler(StringRef Directive,
464 ExtensionDirectiveHandler Handler) override {
465 ExtensionDirectiveMap[Directive] = Handler;
466 DirectiveKindMap.try_emplace(Directive, DK_HANDLER_DIRECTIVE);
467 }
468
469 void addAliasForDirective(StringRef Directive, StringRef Alias) override {
470 DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
471 }
472
473
474
475
476 unsigned getAssemblerDialect() override {
477 if (AssemblerDialect == ~0U)
478 return MAI.getAssemblerDialect();
479 else
480 return AssemblerDialect;
481 }
482 void setAssemblerDialect(unsigned i) override {
483 AssemblerDialect = i;
484 }
485
486 void Note(SMLoc L, const Twine &Msg, SMRange Range = {}) override;
487 bool Warning(SMLoc L, const Twine &Msg, SMRange Range = {}) override;
488 bool printError(SMLoc L, const Twine &Msg, SMRange Range = {}) override;
489
490 enum ExpandKind { ExpandMacros, DoNotExpandMacros };
491 const AsmToken &Lex(ExpandKind ExpandNextToken);
492 const AsmToken &Lex() override { return Lex(ExpandMacros); }
493
494 void setParsingMSInlineAsm(bool V) override {
495 ParsingMSInlineAsm = V;
496
497
498 Lexer.setLexMasmIntegers(V);
499 }
500 bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
501
502 bool isParsingMasm() const override { return true; }
503
504 bool defineMacro(StringRef Name, StringRef Value) override;
505
506 bool lookUpField(StringRef Name, AsmFieldInfo &Info) const override;
507 bool lookUpField(StringRef Base, StringRef Member,
508 AsmFieldInfo &Info) const override;
509
510 bool lookUpType(StringRef Name, AsmTypeInfo &Info) const override;
511
512 bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs,
513 unsigned &NumInputs,
514 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
515 SmallVectorImplstd::string &Constraints,
516 SmallVectorImplstd::string &Clobbers,
517 const MCInstrInfo *MII, MCInstPrinter *IP,
518 MCAsmParserSemaCallback &SI) override;
519
520 bool parseExpression(const MCExpr *&Res);
521 bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
522 bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
523 AsmTypeInfo *TypeInfo) override;
524 bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
525 bool parseAbsoluteExpression(int64_t &Res) override;
526
527
528
529 bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
530
531
532
533 enum IdentifierPositionKind { StandardPosition, StartOfStatement };
534 bool parseIdentifier(StringRef &Res, IdentifierPositionKind Position);
535 bool parseIdentifier(StringRef &Res) override {
536 return parseIdentifier(Res, StandardPosition);
537 }
538 void eatToEndOfStatement() override;
539
540 bool checkForValidSection() override;
541
542
543
544private:
545 bool expandMacros();
546 const AsmToken peekTok(bool ShouldSkipSpace = true);
547
548 bool parseStatement(ParseStatementInfo &Info,
549 MCAsmParserSemaCallback *SI);
550 bool parseCurlyBlockScope(SmallVectorImpl& AsmStrRewrites);
551 bool parseCppHashLineFilenameComment(SMLoc L);
552
553 bool expandMacro(raw_svector_ostream &OS, StringRef Body,
556 const std::vectorstd::string &Locals, SMLoc L);
557
558
559 bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
560
561
562
563
564
565 bool handleMacroEntry(
566 const MCAsmMacro *M, SMLoc NameLoc,
568
569
570
571
572
573 bool handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc);
574
575
576 void handleMacroExit();
577
578
579 bool
580 parseMacroArgument(const MCAsmMacroParameter *MP, MCAsmMacroArgument &MA,
582
583
584 bool
585 parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A,
587
588 void printMacroInstantiations();
589
590 bool expandStatement(SMLoc Loc);
591
593 SMRange Range = {}) const {
596 }
598
599 bool lookUpField(const StructInfo &Structure, StringRef Member,
600 AsmFieldInfo &Info) const;
601
602
603 bool enterIncludeFile(const std::string &Filename);
604
605
606
607
608
609
610
611 void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0,
612 bool EndStatementAtEOF = true);
613
614
615
616
617
620
621
622
623
624 StringRef parseStringToEndOfStatement() override;
625
626 bool parseTextItem(std::string &Data);
627
630
631 bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
632 bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
633 bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
634
635
636 enum DirectiveKind {
637 DK_NO_DIRECTIVE,
638 DK_HANDLER_DIRECTIVE,
639 DK_ASSIGN,
640 DK_EQU,
641 DK_TEXTEQU,
642 DK_ASCII,
643 DK_ASCIZ,
644 DK_STRING,
645 DK_BYTE,
646 DK_SBYTE,
647 DK_WORD,
648 DK_SWORD,
649 DK_DWORD,
650 DK_SDWORD,
651 DK_FWORD,
652 DK_QWORD,
653 DK_SQWORD,
654 DK_DB,
655 DK_DD,
656 DK_DF,
657 DK_DQ,
658 DK_DW,
659 DK_REAL4,
660 DK_REAL8,
661 DK_REAL10,
662 DK_ALIGN,
663 DK_EVEN,
664 DK_ORG,
665 DK_ENDR,
666 DK_EXTERN,
667 DK_PUBLIC,
668 DK_COMM,
669 DK_COMMENT,
670 DK_INCLUDE,
671 DK_REPEAT,
672 DK_WHILE,
673 DK_FOR,
674 DK_FORC,
675 DK_IF,
676 DK_IFE,
677 DK_IFB,
678 DK_IFNB,
679 DK_IFDEF,
680 DK_IFNDEF,
681 DK_IFDIF,
682 DK_IFDIFI,
683 DK_IFIDN,
684 DK_IFIDNI,
685 DK_ELSEIF,
686 DK_ELSEIFE,
687 DK_ELSEIFB,
688 DK_ELSEIFNB,
689 DK_ELSEIFDEF,
690 DK_ELSEIFNDEF,
691 DK_ELSEIFDIF,
692 DK_ELSEIFDIFI,
693 DK_ELSEIFIDN,
694 DK_ELSEIFIDNI,
695 DK_ELSE,
696 DK_ENDIF,
697
698 DK_MACRO,
699 DK_EXITM,
700 DK_ENDM,
701 DK_PURGE,
702 DK_ERR,
703 DK_ERRB,
704 DK_ERRNB,
705 DK_ERRDEF,
706 DK_ERRNDEF,
707 DK_ERRDIF,
708 DK_ERRDIFI,
709 DK_ERRIDN,
710 DK_ERRIDNI,
711 DK_ERRE,
712 DK_ERRNZ,
713 DK_ECHO,
714 DK_STRUCT,
715 DK_UNION,
716 DK_ENDS,
717 DK_END,
718 DK_PUSHFRAME,
719 DK_PUSHREG,
720 DK_SAVEREG,
721 DK_SAVEXMM128,
722 DK_SETFRAME,
723 DK_RADIX,
724 };
725
726
727
728 StringMap DirectiveKindMap;
729
730 bool isMacroLikeDirective();
731
732
733 enum BuiltinSymbol {
734 BI_NO_SYMBOL,
735 BI_DATE,
736 BI_TIME,
737 BI_VERSION,
738 BI_FILECUR,
739 BI_FILENAME,
740 BI_LINE,
741 BI_CURSEG,
742 BI_CPU,
743 BI_INTERFACE,
744 BI_CODE,
745 BI_DATA,
746 BI_FARDATA,
747 BI_WORDSIZE,
748 BI_CODESIZE,
749 BI_DATASIZE,
750 BI_MODEL,
751 BI_STACK,
752 };
753
754
755
756 StringMap BuiltinSymbolMap;
757
758 const MCExpr *evaluateBuiltinValue(BuiltinSymbol Symbol, SMLoc StartLoc);
759
760 std::optionalstd::string evaluateBuiltinTextMacro(BuiltinSymbol Symbol,
761 SMLoc StartLoc);
762
763
764 enum BuiltinFunction {
765 BI_NO_FUNCTION,
766 BI_CATSTR,
767 };
768
769
770
771 StringMap BuiltinFunctionMap;
772
773 bool evaluateBuiltinMacroFunction(BuiltinFunction Function, StringRef Name,
774 std::string &Res);
775
776
777 bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
778
779
780 bool emitIntValue(const MCExpr *Value, unsigned Size);
781 bool parseScalarInitializer(unsigned Size,
782 SmallVectorImpl<const MCExpr *> &Values,
783 unsigned StringPadLength = 0);
784 bool parseScalarInstList(
785 unsigned Size, SmallVectorImpl<const MCExpr *> &Values,
787 bool emitIntegralValues(unsigned Size, unsigned *Count = nullptr);
788 bool addIntegralField(StringRef Name, unsigned Size);
789 bool parseDirectiveValue(StringRef IDVal, unsigned Size);
790 bool parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
791 StringRef Name, SMLoc NameLoc);
792
793
794 bool emitRealValues(const fltSemantics &Semantics, unsigned *Count = nullptr);
795 bool addRealField(StringRef Name, const fltSemantics &Semantics, size_t Size);
796 bool parseDirectiveRealValue(StringRef IDVal, const fltSemantics &Semantics,
797 size_t Size);
798 bool parseRealInstList(
799 const fltSemantics &Semantics, SmallVectorImpl &Values,
801 bool parseDirectiveNamedRealValue(StringRef TypeName,
802 const fltSemantics &Semantics,
803 unsigned Size, StringRef Name,
804 SMLoc NameLoc);
805
806 bool parseOptionalAngleBracketOpen();
807 bool parseAngleBracketClose(const Twine &Msg = "expected '>'");
808
809 bool parseFieldInitializer(const FieldInfo &Field,
810 FieldInitializer &Initializer);
811 bool parseFieldInitializer(const FieldInfo &Field,
812 const IntFieldInfo &Contents,
813 FieldInitializer &Initializer);
814 bool parseFieldInitializer(const FieldInfo &Field,
815 const RealFieldInfo &Contents,
816 FieldInitializer &Initializer);
817 bool parseFieldInitializer(const FieldInfo &Field,
818 const StructFieldInfo &Contents,
819 FieldInitializer &Initializer);
820
821 bool parseStructInitializer(const StructInfo &Structure,
822 StructInitializer &Initializer);
823 bool parseStructInstList(
824 const StructInfo &Structure, std::vector &Initializers,
826
827 bool emitFieldValue(const FieldInfo &Field);
828 bool emitFieldValue(const FieldInfo &Field, const IntFieldInfo &Contents);
829 bool emitFieldValue(const FieldInfo &Field, const RealFieldInfo &Contents);
830 bool emitFieldValue(const FieldInfo &Field, const StructFieldInfo &Contents);
831
832 bool emitFieldInitializer(const FieldInfo &Field,
833 const FieldInitializer &Initializer);
834 bool emitFieldInitializer(const FieldInfo &Field,
835 const IntFieldInfo &Contents,
836 const IntFieldInfo &Initializer);
837 bool emitFieldInitializer(const FieldInfo &Field,
838 const RealFieldInfo &Contents,
839 const RealFieldInfo &Initializer);
840 bool emitFieldInitializer(const FieldInfo &Field,
841 const StructFieldInfo &Contents,
842 const StructFieldInfo &Initializer);
843
844 bool emitStructInitializer(const StructInfo &Structure,
845 const StructInitializer &Initializer);
846
847
848 bool emitStructValues(const StructInfo &Structure, unsigned *Count = nullptr);
849 bool addStructField(StringRef Name, const StructInfo &Structure);
850 bool parseDirectiveStructValue(const StructInfo &Structure,
851 StringRef Directive, SMLoc DirLoc);
852 bool parseDirectiveNamedStructValue(const StructInfo &Structure,
853 StringRef Directive, SMLoc DirLoc,
854 StringRef Name);
855
856
857 bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
858 DirectiveKind DirKind, SMLoc NameLoc);
859
860 bool parseDirectiveOrg();
861
862 bool emitAlignTo(int64_t Alignment);
863 bool parseDirectiveAlign();
864 bool parseDirectiveEven();
865
866
867 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
868 bool parseDirectiveExitMacro(SMLoc DirectiveLoc, StringRef Directive,
869 std::string &Value);
870 bool parseDirectiveEndMacro(StringRef Directive);
871 bool parseDirectiveMacro(StringRef Name, SMLoc NameLoc);
872
873 bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind,
874 StringRef Name, SMLoc NameLoc);
875 bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind);
876 bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
877 bool parseDirectiveNestedEnds();
878
879 bool parseDirectiveExtern();
880
881
882
883 bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
884
885 bool parseDirectiveComm(bool IsLocal);
886
887 bool parseDirectiveComment(SMLoc DirectiveLoc);
888
889 bool parseDirectiveInclude();
890
891
892 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
893
894 bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
895
896
897 bool parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
898 bool CaseInsensitive);
899
900 bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
901
902 bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
903
904 bool parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank);
905
906 bool parseDirectiveElseIfdef(SMLoc DirectiveLoc, bool expect_defined);
907
908
909 bool parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
910 bool CaseInsensitive);
911 bool parseDirectiveElse(SMLoc DirectiveLoc);
912 bool parseDirectiveEndIf(SMLoc DirectiveLoc);
913 bool parseEscapedString(std::string &Data) override;
914 bool parseAngleBracketString(std::string &Data) override;
915
916
917 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
918 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
919 raw_svector_ostream &OS);
920 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
921 SMLoc ExitLoc, raw_svector_ostream &OS);
922 bool parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Directive);
923 bool parseDirectiveFor(SMLoc DirectiveLoc, StringRef Directive);
924 bool parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive);
925 bool parseDirectiveWhile(SMLoc DirectiveLoc);
926
927
928 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
929 size_t Len);
930
931
932 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
933
934
935 bool parseDirectiveEnd(SMLoc DirectiveLoc);
936
937
938 bool parseDirectiveError(SMLoc DirectiveLoc);
939
940 bool parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank);
941
942 bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc, bool ExpectDefined);
943
944
945 bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
946 bool CaseInsensitive);
947
948 bool parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero);
949
950
951 bool parseDirectiveRadix(SMLoc DirectiveLoc);
952
953
954 bool parseDirectiveEcho(SMLoc DirectiveLoc);
955
956 void initializeDirectiveKindMap();
957 void initializeBuiltinSymbolMaps();
958};
959
960}
961
962namespace llvm {
963
965
966}
967
969
970MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
971 const MCAsmInfo &MAI, struct tm TM, unsigned CB)
972 : MCAsmParser(Ctx, Out, SM, MAI), CurBuffer(CB ? CB : SM.getMainFileID()),
973 TM(TM) {
974 HadError = false;
975
976 SavedDiagHandler = SrcMgr.getDiagHandler();
977 SavedDiagContext = SrcMgr.getDiagContext();
978
980 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
981 EndStatementAtEOFStack.push_back(true);
982
983
984 switch (Ctx.getObjectFileType()) {
985 case MCContext::IsCOFF:
986 PlatformParser.reset(createCOFFMasmParser());
987 break;
988 default:
989 report_fatal_error("llvm-ml currently supports only COFF output.");
990 break;
991 }
992
993 initializeDirectiveKindMap();
994 PlatformParser->Initialize(*this);
995 initializeBuiltinSymbolMaps();
996
997 NumOfMacroInstantiations = 0;
998}
999
1000MasmParser::~MasmParser() {
1001 assert((HadError || ActiveMacros.empty()) &&
1002 "Unexpected active macro instantiation!");
1003
1004
1005
1007}
1008
1009void MasmParser::printMacroInstantiations() {
1010
1011 for (std::vector<MacroInstantiation *>::const_reverse_iterator
1012 it = ActiveMacros.rbegin(),
1013 ie = ActiveMacros.rend();
1014 it != ie; ++it)
1016 "while in macro instantiation");
1017}
1018
1019void MasmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
1020 printPendingErrors();
1022 printMacroInstantiations();
1023}
1024
1025bool MasmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
1026 if (getTargetParser().getTargetOptions().MCNoWarn)
1027 return false;
1028 if (getTargetParser().getTargetOptions().MCFatalWarnings)
1031 printMacroInstantiations();
1032 return false;
1033}
1034
1035bool MasmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
1036 HadError = true;
1038 printMacroInstantiations();
1039 return true;
1040}
1041
1042bool MasmParser::enterIncludeFile(const std::string &Filename) {
1043 std::string IncludedFile;
1044 unsigned NewBuf =
1046 if (!NewBuf)
1047 return true;
1048
1049 CurBuffer = NewBuf;
1051 EndStatementAtEOFStack.push_back(true);
1052 return false;
1053}
1054
1055void MasmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer,
1056 bool EndStatementAtEOF) {
1059 Loc.getPointer(), EndStatementAtEOF);
1060}
1061
1062bool MasmParser::expandMacros() {
1063 const AsmToken &Tok = getTok();
1065
1066 const llvm::MCAsmMacro *M = getContext().lookupMacro(IDLower);
1068
1069 const SMLoc MacroLoc = Tok.getLoc();
1071 Lexer.Lex();
1072 if (handleMacroInvocation(M, MacroLoc)) {
1074 Lexer.Lex();
1075 }
1076 return false;
1077 }
1078
1079 std::optionalstd::string ExpandedValue;
1080
1081 if (auto BuiltinIt = BuiltinSymbolMap.find(IDLower);
1082 BuiltinIt != BuiltinSymbolMap.end()) {
1083 ExpandedValue =
1084 evaluateBuiltinTextMacro(BuiltinIt->getValue(), Tok.getLoc());
1085 } else if (auto BuiltinFuncIt = BuiltinFunctionMap.find(IDLower);
1086 BuiltinFuncIt != BuiltinFunctionMap.end()) {
1087 StringRef Name;
1088 if (parseIdentifier(Name)) {
1089 return true;
1090 }
1091 std::string Res;
1092 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), Name, Res)) {
1093 return true;
1094 }
1095 ExpandedValue = Res;
1096 } else if (auto VarIt = Variables.find(IDLower);
1097 VarIt != Variables.end() && VarIt->getValue().IsText) {
1098 ExpandedValue = VarIt->getValue().TextValue;
1099 }
1100
1101 if (!ExpandedValue)
1102 return true;
1103 std::unique_ptr Instantiation =
1105
1106
1107 CurBuffer =
1110 false);
1111 EndStatementAtEOFStack.push_back(false);
1112 Lexer.Lex();
1113 return false;
1114}
1115
1116const AsmToken &MasmParser::Lex(ExpandKind ExpandNextToken) {
1118 Error(Lexer.getErrLoc(), Lexer.getErr());
1119 bool StartOfStatement = false;
1120
1121
1123
1124 if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
1127 StartOfStatement = true;
1128 }
1129
1130 const AsmToken *tok = &Lexer.Lex();
1131
1133 if (StartOfStatement) {
1134 AsmToken NextTok;
1136 size_t ReadCount = Lexer.peekTokens(Buf);
1140
1141
1142 break;
1143 }
1144 }
1145 if (expandMacros())
1146 break;
1147 }
1148
1149
1153 tok = &Lexer.Lex();
1154 }
1155
1156
1159
1160 Lexer.Lex();
1161 tok = &Lexer.Lex();
1162 }
1163
1165
1166
1168 if (ParentIncludeLoc != SMLoc()) {
1169 EndStatementAtEOFStack.pop_back();
1170 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1171 return Lex();
1172 }
1173 EndStatementAtEOFStack.pop_back();
1174 assert(EndStatementAtEOFStack.empty());
1175 }
1176
1177 return *tok;
1178}
1179
1180const AsmToken MasmParser::peekTok(bool ShouldSkipSpace) {
1181 AsmToken Tok;
1182
1184 size_t ReadCount = Lexer.peekTokens(Buf, ShouldSkipSpace);
1185
1186 if (ReadCount == 0) {
1187
1188
1190 if (ParentIncludeLoc != SMLoc()) {
1191 EndStatementAtEOFStack.pop_back();
1192 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1193 return peekTok(ShouldSkipSpace);
1194 }
1195 EndStatementAtEOFStack.pop_back();
1196 assert(EndStatementAtEOFStack.empty());
1197 }
1198
1199 assert(ReadCount == 1);
1200 return Tok;
1201}
1202
1203bool MasmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
1204
1205 if (!NoInitialTextSection)
1206 Out.initSections(false, getTargetParser().getSTI());
1207
1208
1209 Lex();
1210
1211 HadError = false;
1212 AsmCond StartingCondState = TheCondState;
1214
1215
1218
1220 Lex();
1221
1222 ParseStatementInfo Info(&AsmStrRewrites);
1223 bool HasError = parseStatement(Info, nullptr);
1224
1225
1226
1227
1228 if (HasError && !hasPendingError() && Lexer.getTok().is(AsmToken::Error))
1229 Lex();
1230
1231
1232 printPendingErrors();
1233
1234
1235 if (HasError && !getLexer().justConsumedEOL())
1236 eatToEndOfStatement();
1237 }
1238
1239 printPendingErrors();
1240
1241
1242 assert(!hasPendingError() && "unexpected error from parseStatement");
1243
1244 if (TheCondState.TheCond != StartingCondState.TheCond ||
1245 TheCondState.Ignore != StartingCondState.Ignore)
1246 printError(getTok().getLoc(), "unmatched .ifs or .elses");
1247
1248
1249
1250
1251
1252 if (!NoFinalize) {
1253
1254
1255 for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
1256 if (std::get<2>(LocSym)->isUndefined()) {
1257
1258
1259 CppHashInfo = std::get<1>(LocSym);
1260 printError(std::get<0>(LocSym), "directional label undefined");
1261 }
1262 }
1263 }
1264
1265
1266
1267 if (!HadError && !NoFinalize)
1268 Out.finish(Lexer.getLoc());
1269
1270 return HadError || getContext().hadError();
1271}
1272
1273bool MasmParser::checkForValidSection() {
1274 if (!ParsingMSInlineAsm && !(getStreamer().getCurrentFragment() &&
1275 getStreamer().getCurrentSectionOnly())) {
1276 Out.initSections(false, getTargetParser().getSTI());
1277 return Error(getTok().getLoc(),
1278 "expected section directive before assembly directive");
1279 }
1280 return false;
1281}
1282
1283
1284void MasmParser::eatToEndOfStatement() {
1288 if (ParentIncludeLoc == SMLoc()) {
1289 break;
1290 }
1291
1292 EndStatementAtEOFStack.pop_back();
1293 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1294 }
1295
1296 Lexer.Lex();
1297 }
1298
1299
1301 Lexer.Lex();
1302}
1303
1304SmallVector<StringRef, 1>
1306 SmallVector<StringRef, 1> Refs;
1307 const char *Start = getTok().getLoc().getPointer();
1308 while (Lexer.isNot(EndTok)) {
1311 if (ParentIncludeLoc == SMLoc()) {
1312 break;
1313 }
1315
1316 EndStatementAtEOFStack.pop_back();
1317 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1318 Lexer.Lex();
1319 Start = getTok().getLoc().getPointer();
1320 } else {
1321 Lexer.Lex();
1322 }
1323 }
1325 return Refs;
1326}
1327
1329 SmallVector<StringRef, 1> Refs = parseStringRefsTo(EndTok);
1330 std::string Str;
1331 for (StringRef S : Refs) {
1332 Str.append(S.str());
1333 }
1334 return Str;
1335}
1336
1337StringRef MasmParser::parseStringToEndOfStatement() {
1338 const char *Start = getTok().getLoc().getPointer();
1339
1341 Lexer.Lex();
1342
1343 const char *End = getTok().getLoc().getPointer();
1344 return StringRef(Start, End - Start);
1345}
1346
1347
1348
1349
1350
1351
1352bool MasmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
1353 if (parseExpression(Res))
1354 return true;
1355 EndLoc = Lexer.getTok().getEndLoc();
1356 return parseRParen();
1357}
1358
1359
1360
1361
1362
1363
1364bool MasmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
1365 if (parseExpression(Res))
1366 return true;
1367 EndLoc = getTok().getEndLoc();
1368 if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
1369 return true;
1370 return false;
1371}
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
1382 AsmTypeInfo *TypeInfo) {
1383 SMLoc FirstTokenLoc = getLexer().getLoc();
1385 switch (FirstTokenKind) {
1386 default:
1387 return TokError("unknown token in expression");
1388
1390 return true;
1392 Lex();
1393 if (parsePrimaryExpr(Res, EndLoc, nullptr))
1394 return true;
1396 return false;
1401 if (parseIdentifier(Identifier)) {
1402
1404 if (Lexer.getMAI().getDollarIsPC()) {
1405 Lex();
1406
1407
1411 EndLoc = FirstTokenLoc;
1412 return false;
1413 }
1414 return Error(FirstTokenLoc, "invalid token in expression");
1415 }
1416 }
1417
1418 if (Identifier.equals_insensitive("not")) {
1419 if (parsePrimaryExpr(Res, EndLoc, nullptr))
1420 return true;
1422 return false;
1423 }
1424
1425 if (Identifier.equals_insensitive("@b") ||
1426 Identifier.equals_insensitive("@f")) {
1427 bool Before = Identifier.equals_insensitive("@b");
1430 return Error(FirstTokenLoc, "Expected @@ label before @B reference");
1432 return false;
1433 }
1434
1436
1437
1440 return Error(getLexer().getLoc(), "expected a symbol reference");
1441
1442
1443 AsmFieldInfo Info;
1445 if (Split.second.empty()) {
1446 } else {
1448 if (lookUpField(SymbolName, Split.second, Info)) {
1449 std::pair<StringRef, StringRef> BaseMember = Split.second.split('.');
1450 StringRef Base = BaseMember.first, Member = BaseMember.second;
1451 lookUpField(Base, Member, Info);
1453
1455 return false;
1456 }
1457 }
1458
1460 if (!Sym) {
1461
1462 auto BuiltinIt = BuiltinSymbolMap.find(SymbolName.lower());
1463 const BuiltinSymbol Symbol = (BuiltinIt == BuiltinSymbolMap.end())
1464 ? BI_NO_SYMBOL
1465 : BuiltinIt->getValue();
1466 if (Symbol != BI_NO_SYMBOL) {
1467 const MCExpr *Value = evaluateBuiltinValue(Symbol, FirstTokenLoc);
1470 return false;
1471 }
1472 }
1473
1474
1475
1477 if (VarIt != Variables.end())
1479 Sym = getContext().parseSymbol(SymbolName);
1480 }
1481
1482
1483
1488 DoInline = TV->inlineAssignedExpr();
1489 if (DoInline) {
1491 return false;
1492 }
1493 }
1494
1495
1496 const MCExpr *SymRef =
1498 if (Info.Offset) {
1502 } else {
1503 Res = SymRef;
1504 }
1505 if (TypeInfo) {
1506 if (Info.Type.Name.empty()) {
1508 if (TypeIt != KnownType.end()) {
1509 Info.Type = TypeIt->second;
1510 }
1511 }
1512
1513 *TypeInfo = Info.Type;
1514 }
1515 return false;
1516 }
1518 return TokError("literal value out of range for directive");
1520 int64_t IntVal = getTok().getIntVal();
1522 EndLoc = Lexer.getTok().getEndLoc();
1523 Lex();
1524 return false;
1525 }
1527
1528 SMLoc ValueLoc = getTok().getLoc();
1529 std::string Value;
1530 if (parseEscapedString(Value))
1531 return true;
1532 if (Value.size() > 8)
1533 return Error(ValueLoc, "literal value out of range");
1534 uint64_t IntValue = 0;
1535 for (const unsigned char CharVal : Value)
1536 IntValue = (IntValue << 8) | CharVal;
1538 return false;
1539 }
1541 APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
1542 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
1544 EndLoc = Lexer.getTok().getEndLoc();
1545 Lex();
1546 return false;
1547 }
1549
1550
1554 EndLoc = Lexer.getTok().getEndLoc();
1555 Lex();
1556 return false;
1557 }
1559 Lex();
1560 return parseParenExpr(Res, EndLoc);
1562 if (!PlatformParser->HasBracketExpressions())
1563 return TokError("brackets expression not supported on this target");
1564 Lex();
1565 return parseBracketExpr(Res, EndLoc);
1567 Lex();
1568 if (parsePrimaryExpr(Res, EndLoc, nullptr))
1569 return true;
1571 return false;
1573 Lex();
1574 if (parsePrimaryExpr(Res, EndLoc, nullptr))
1575 return true;
1577 return false;
1579 Lex();
1580 if (parsePrimaryExpr(Res, EndLoc, nullptr))
1581 return true;
1583 return false;
1584 }
1585}
1586
1587bool MasmParser::parseExpression(const MCExpr *&Res) {
1588 SMLoc EndLoc;
1589 return parseExpression(Res, EndLoc);
1590}
1591
1592
1593
1594
1595
1596
1597
1600 "Argument to the function cannot be a NULL value");
1601 const char *CharPtr = StrLoc.getPointer();
1602 while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
1603 (*CharPtr != '\0')) {
1604 if (*CharPtr == '!')
1605 CharPtr++;
1606 CharPtr++;
1607 }
1608 if (*CharPtr == '>') {
1610 return true;
1611 }
1612 return false;
1613}
1614
1615
1617 std::string Res;
1618 for (size_t Pos = 0; Pos < BracketContents.size(); Pos++) {
1619 if (BracketContents[Pos] == '!')
1620 Pos++;
1621 Res += BracketContents[Pos];
1622 }
1623 return Res;
1624}
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636bool MasmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
1637
1638 Res = nullptr;
1639 if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
1640 parseBinOpRHS(1, Res, EndLoc))
1641 return true;
1642
1643
1644
1646 if (Res->evaluateAsAbsolute(Value))
1648
1649 return false;
1650}
1651
1652bool MasmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
1653 Res = nullptr;
1654 return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
1655}
1656
1657bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
1658 const MCExpr *Expr;
1659
1660 SMLoc StartLoc = Lexer.getLoc();
1661 if (parseExpression(Expr))
1662 return true;
1663
1664 if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
1665 return Error(StartLoc, "expected absolute expression");
1666
1667 return false;
1668}
1669
1672 bool ShouldUseLogicalShr,
1673 bool EndExpressionAtGreater) {
1674 switch (K) {
1675 default:
1676 return 0;
1677
1678
1681 return 2;
1684 return 1;
1685
1686
1689 return 3;
1693 return 3;
1696 return 3;
1699 return 3;
1701 if (EndExpressionAtGreater)
1702 return 0;
1704 return 3;
1707 return 3;
1708
1709
1712 return 4;
1715 return 4;
1716
1717
1720 return 5;
1723 return 5;
1726 return 5;
1727
1728
1731 return 6;
1734 return 6;
1737 return 6;
1740 return 6;
1742 if (EndExpressionAtGreater)
1743 return 0;
1745 return 6;
1746 }
1747}
1748
1753 AngleBracketDepth > 0);
1754}
1755
1756
1757
1758bool MasmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
1759 SMLoc &EndLoc) {
1760 SMLoc StartLoc = Lexer.getLoc();
1761 while (true) {
1764 TokKind = StringSwitchAsmToken::TokenKind(Lexer.getTok().getString())
1777 .Default(TokKind);
1778 }
1780 unsigned TokPrec = getBinOpPrecedence(TokKind, Kind);
1781
1782
1783
1784 if (TokPrec < Precedence)
1785 return false;
1786
1787 Lex();
1788
1789
1790 const MCExpr *RHS;
1791 if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
1792 return true;
1793
1794
1795
1797 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
1798 if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
1799 return true;
1800
1801
1803 }
1804}
1805
1806
1807
1808
1809
1810
1811bool MasmParser::parseStatement(ParseStatementInfo &Info,
1812 MCAsmParserSemaCallback *SI) {
1813 assert(!hasPendingError() && "parseStatement started with pending error");
1814
1816 Lex();
1818
1819 if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
1820 getTok().getString().front() == '\n')
1822 Lex();
1823 return false;
1824 }
1825
1826
1827
1829 SMLoc ExpansionLoc = getTok().getLoc();
1830 if (parseToken(AsmToken::Percent) || expandStatement(ExpansionLoc))
1831 return true;
1832 }
1833
1834
1835
1836 AsmToken ID = getTok();
1837 SMLoc IDLoc = ID.getLoc();
1838 StringRef IDVal;
1840 return parseCppHashLineFilenameComment(IDLoc);
1842
1843 Lex();
1844 IDVal = ".";
1846
1847 IDVal = getTok().getString();
1848 Lex();
1850 return Error(IDLoc, "unexpected token at start of statement");
1851 } else if (parseIdentifier(IDVal, StartOfStatement)) {
1852 if (!TheCondState.Ignore) {
1853 Lex();
1854 return Error(IDLoc, "unexpected token at start of statement");
1855 }
1856 IDVal = "";
1857 }
1858
1859
1860
1861
1863 DirectiveKindMap.find(IDVal.lower());
1864 DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
1865 ? DK_NO_DIRECTIVE
1866 : DirKindIt->getValue();
1867 switch (DirKind) {
1868 default:
1869 break;
1870 case DK_IF:
1871 case DK_IFE:
1872 return parseDirectiveIf(IDLoc, DirKind);
1873 case DK_IFB:
1874 return parseDirectiveIfb(IDLoc, true);
1875 case DK_IFNB:
1876 return parseDirectiveIfb(IDLoc, false);
1877 case DK_IFDEF:
1878 return parseDirectiveIfdef(IDLoc, true);
1879 case DK_IFNDEF:
1880 return parseDirectiveIfdef(IDLoc, false);
1881 case DK_IFDIF:
1882 return parseDirectiveIfidn(IDLoc, false,
1883 false);
1884 case DK_IFDIFI:
1885 return parseDirectiveIfidn(IDLoc, false,
1886 true);
1887 case DK_IFIDN:
1888 return parseDirectiveIfidn(IDLoc, true,
1889 false);
1890 case DK_IFIDNI:
1891 return parseDirectiveIfidn(IDLoc, true,
1892 true);
1893 case DK_ELSEIF:
1894 case DK_ELSEIFE:
1895 return parseDirectiveElseIf(IDLoc, DirKind);
1896 case DK_ELSEIFB:
1897 return parseDirectiveElseIfb(IDLoc, true);
1898 case DK_ELSEIFNB:
1899 return parseDirectiveElseIfb(IDLoc, false);
1900 case DK_ELSEIFDEF:
1901 return parseDirectiveElseIfdef(IDLoc, true);
1902 case DK_ELSEIFNDEF:
1903 return parseDirectiveElseIfdef(IDLoc, false);
1904 case DK_ELSEIFDIF:
1905 return parseDirectiveElseIfidn(IDLoc, false,
1906 false);
1907 case DK_ELSEIFDIFI:
1908 return parseDirectiveElseIfidn(IDLoc, false,
1909 true);
1910 case DK_ELSEIFIDN:
1911 return parseDirectiveElseIfidn(IDLoc, true,
1912 false);
1913 case DK_ELSEIFIDNI:
1914 return parseDirectiveElseIfidn(IDLoc, true,
1915 true);
1916 case DK_ELSE:
1917 return parseDirectiveElse(IDLoc);
1918 case DK_ENDIF:
1919 return parseDirectiveEndIf(IDLoc);
1920 }
1921
1922
1923
1924 if (TheCondState.Ignore) {
1925 eatToEndOfStatement();
1926 return false;
1927 }
1928
1929
1930
1931
1932
1933
1934 if (Lexer.is(AsmToken::Colon) && getTargetParser().isLabel(ID)) {
1935 if (checkForValidSection())
1936 return true;
1937
1938
1939 Lex();
1940
1941
1942 if (IDVal == ".")
1943 return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
1944
1945
1946
1947
1948
1949
1951 if (ParsingMSInlineAsm && SI) {
1952 StringRef RewrittenLabel =
1953 SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
1955 "We should have an internal name here.");
1957 RewrittenLabel);
1958 IDVal = RewrittenLabel;
1959 }
1960
1961 if (IDVal == "@@") {
1963 } else {
1964 Sym = getContext().parseSymbol(IDVal);
1965 }
1966
1967
1968
1969
1970
1973 Lexer.Lex();
1975 }
1976
1977
1978
1980 Lex();
1981 }
1982
1983
1984 if (!getTargetParser().isParsingMSInlineAsm())
1986 return false;
1987 }
1988
1989
1990 if (const MCAsmMacro *M = getContext().lookupMacro(IDVal.lower())) {
1994 return handleMacroEntry(M, IDLoc, ArgumentEndTok);
1995 }
1996
1997
1998
1999 if (DirKind != DK_NO_DIRECTIVE) {
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2015 return parseDirectiveNestedEnds();
2016 }
2017
2018
2019
2020 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2021 ExtensionDirectiveMap.lookup(IDVal.lower());
2022 if (Handler.first)
2023 return (*Handler.second)(Handler.first, IDVal, IDLoc);
2024
2025
2027 return false;
2028
2029 ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(ID);
2030 assert(TPDirectiveReturn.isFailure() == hasPendingError() &&
2031 "Should only return Failure iff there was an error");
2032 if (TPDirectiveReturn.isFailure())
2033 return true;
2034 if (TPDirectiveReturn.isSuccess())
2035 return false;
2036
2037
2038
2039 switch (DirKind) {
2040 default:
2041 break;
2042 case DK_ASCII:
2043 return parseDirectiveAscii(IDVal, false);
2044 case DK_ASCIZ:
2045 case DK_STRING:
2046 return parseDirectiveAscii(IDVal, true);
2047 case DK_BYTE:
2048 case DK_SBYTE:
2049 case DK_DB:
2050 return parseDirectiveValue(IDVal, 1);
2051 case DK_WORD:
2052 case DK_SWORD:
2053 case DK_DW:
2054 return parseDirectiveValue(IDVal, 2);
2055 case DK_DWORD:
2056 case DK_SDWORD:
2057 case DK_DD:
2058 return parseDirectiveValue(IDVal, 4);
2059 case DK_FWORD:
2060 case DK_DF:
2061 return parseDirectiveValue(IDVal, 6);
2062 case DK_QWORD:
2063 case DK_SQWORD:
2064 case DK_DQ:
2065 return parseDirectiveValue(IDVal, 8);
2066 case DK_REAL4:
2067 return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4);
2068 case DK_REAL8:
2069 return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8);
2070 case DK_REAL10:
2071 return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10);
2072 case DK_STRUCT:
2073 case DK_UNION:
2074 return parseDirectiveNestedStruct(IDVal, DirKind);
2075 case DK_ENDS:
2076 return parseDirectiveNestedEnds();
2077 case DK_ALIGN:
2078 return parseDirectiveAlign();
2079 case DK_EVEN:
2080 return parseDirectiveEven();
2081 case DK_ORG:
2082 return parseDirectiveOrg();
2083 case DK_EXTERN:
2084 return parseDirectiveExtern();
2085 case DK_PUBLIC:
2086 return parseDirectiveSymbolAttribute(MCSA_Global);
2087 case DK_COMM:
2088 return parseDirectiveComm(false);
2089 case DK_COMMENT:
2090 return parseDirectiveComment(IDLoc);
2091 case DK_INCLUDE:
2092 return parseDirectiveInclude();
2093 case DK_REPEAT:
2094 return parseDirectiveRepeat(IDLoc, IDVal);
2095 case DK_WHILE:
2096 return parseDirectiveWhile(IDLoc);
2097 case DK_FOR:
2098 return parseDirectiveFor(IDLoc, IDVal);
2099 case DK_FORC:
2100 return parseDirectiveForc(IDLoc, IDVal);
2101 case DK_EXITM:
2102 Info.ExitValue = "";
2103 return parseDirectiveExitMacro(IDLoc, IDVal, *Info.ExitValue);
2104 case DK_ENDM:
2105 Info.ExitValue = "";
2106 return parseDirectiveEndMacro(IDVal);
2107 case DK_PURGE:
2108 return parseDirectivePurgeMacro(IDLoc);
2109 case DK_END:
2110 return parseDirectiveEnd(IDLoc);
2111 case DK_ERR:
2112 return parseDirectiveError(IDLoc);
2113 case DK_ERRB:
2114 return parseDirectiveErrorIfb(IDLoc, true);
2115 case DK_ERRNB:
2116 return parseDirectiveErrorIfb(IDLoc, false);
2117 case DK_ERRDEF:
2118 return parseDirectiveErrorIfdef(IDLoc, true);
2119 case DK_ERRNDEF:
2120 return parseDirectiveErrorIfdef(IDLoc, false);
2121 case DK_ERRDIF:
2122 return parseDirectiveErrorIfidn(IDLoc, false,
2123 false);
2124 case DK_ERRDIFI:
2125 return parseDirectiveErrorIfidn(IDLoc, false,
2126 true);
2127 case DK_ERRIDN:
2128 return parseDirectiveErrorIfidn(IDLoc, true,
2129 false);
2130 case DK_ERRIDNI:
2131 return parseDirectiveErrorIfidn(IDLoc, true,
2132 true);
2133 case DK_ERRE:
2134 return parseDirectiveErrorIfe(IDLoc, true);
2135 case DK_ERRNZ:
2136 return parseDirectiveErrorIfe(IDLoc, false);
2137 case DK_RADIX:
2138 return parseDirectiveRadix(IDLoc);
2139 case DK_ECHO:
2140 return parseDirectiveEcho(IDLoc);
2141 }
2142
2143 return Error(IDLoc, "unknown directive");
2144 }
2145
2146
2147 auto IDIt = Structs.find(IDVal.lower());
2148 if (IDIt != Structs.end())
2149 return parseDirectiveStructValue(IDIt->getValue(), IDVal,
2150 IDLoc);
2151
2152
2153 const AsmToken nextTok = getTok();
2154 const StringRef nextVal = nextTok.getString();
2155 const SMLoc nextLoc = nextTok.getLoc();
2156
2157 const AsmToken afterNextTok = peekTok();
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168 getTargetParser().flushPendingInstructions(getStreamer());
2169
2170
2171
2173 Lex();
2174 return parseDirectiveEnds(IDVal, IDLoc);
2175 }
2176
2177
2178
2179 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2180 ExtensionDirectiveMap.lookup(nextVal.lower());
2181 if (Handler.first) {
2182 Lex();
2183 Lexer.UnLex(ID);
2184 return (*Handler.second)(Handler.first, nextVal, nextLoc);
2185 }
2186
2187
2188
2189 DirKindIt = DirectiveKindMap.find(nextVal.lower());
2190 DirKind = (DirKindIt == DirectiveKindMap.end())
2191 ? DK_NO_DIRECTIVE
2192 : DirKindIt->getValue();
2193 switch (DirKind) {
2194 default:
2195 break;
2196 case DK_ASSIGN:
2197 case DK_EQU:
2198 case DK_TEXTEQU:
2199 Lex();
2200 return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
2201 case DK_BYTE:
2204
2205 break;
2206 }
2207 [[fallthrough]];
2208 case DK_SBYTE:
2209 case DK_DB:
2210 Lex();
2211 return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc);
2212 case DK_WORD:
2215
2216 break;
2217 }
2218 [[fallthrough]];
2219 case DK_SWORD:
2220 case DK_DW:
2221 Lex();
2222 return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc);
2223 case DK_DWORD:
2226
2227 break;
2228 }
2229 [[fallthrough]];
2230 case DK_SDWORD:
2231 case DK_DD:
2232 Lex();
2233 return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc);
2234 case DK_FWORD:
2237
2238 break;
2239 }
2240 [[fallthrough]];
2241 case DK_DF:
2242 Lex();
2243 return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc);
2244 case DK_QWORD:
2247
2248 break;
2249 }
2250 [[fallthrough]];
2251 case DK_SQWORD:
2252 case DK_DQ:
2253 Lex();
2254 return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc);
2255 case DK_REAL4:
2256 Lex();
2257 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), 4,
2258 IDVal, IDLoc);
2259 case DK_REAL8:
2260 Lex();
2261 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8,
2262 IDVal, IDLoc);
2263 case DK_REAL10:
2264 Lex();
2265 return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(),
2266 10, IDVal, IDLoc);
2267 case DK_STRUCT:
2268 case DK_UNION:
2269 Lex();
2270 return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc);
2271 case DK_ENDS:
2272 Lex();
2273 return parseDirectiveEnds(IDVal, IDLoc);
2274 case DK_MACRO:
2275 Lex();
2276 return parseDirectiveMacro(IDVal, IDLoc);
2277 }
2278
2279
2280 auto NextIt = Structs.find(nextVal.lower());
2281 if (NextIt != Structs.end()) {
2282 Lex();
2283 return parseDirectiveNamedStructValue(NextIt->getValue(),
2284 nextVal, nextLoc, IDVal);
2285 }
2286
2287
2288 if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
2289 IDVal == "_EMIT" || IDVal == "__EMIT"))
2290 return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
2291
2292
2293 if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
2294 return parseDirectiveMSAlign(IDLoc, Info);
2295
2296 if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
2297 Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
2298 if (checkForValidSection())
2299 return true;
2300
2301
2302 std::string OpcodeStr = IDVal.lower();
2303 ParseInstructionInfo IInfo(Info.AsmRewrites);
2304 bool ParseHadError = getTargetParser().parseInstruction(IInfo, OpcodeStr, ID,
2305 Info.ParsedOperands);
2306 Info.ParseError = ParseHadError;
2307
2308
2309 if (getShowParsedOperands()) {
2310 SmallString<256> Str;
2311 raw_svector_ostream OS(Str);
2312 OS << "parsed instruction: [";
2313 for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
2314 if (i != 0)
2315 OS << ", ";
2316 Info.ParsedOperands[i]->print(OS, MAI);
2317 }
2318 OS << "]";
2319
2321 }
2322
2323
2324 if (hasPendingError() || ParseHadError)
2325 return true;
2326
2327
2328 if (!ParseHadError) {
2329 uint64_t ErrorInfo;
2330 if (getTargetParser().matchAndEmitInstruction(
2331 IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
2332 getTargetParser().isParsingMSInlineAsm()))
2333 return true;
2334 }
2335 return false;
2336}
2337
2338
2339bool MasmParser::parseCurlyBlockScope(
2340 SmallVectorImpl &AsmStrRewrites) {
2341
2343 return false;
2344
2345 SMLoc StartLoc = Lexer.getLoc();
2346 Lex();
2348 Lex();
2349
2350
2351 AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
2353 return true;
2354}
2355
2356
2357
2358bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
2359 Lex();
2360
2361
2363 "Lexing Cpp line comment: Expected Integer");
2364 int64_t LineNumber = getTok().getIntVal();
2365 Lex();
2367 "Lexing Cpp line comment: Expected String");
2368 StringRef Filename = getTok().getString();
2369 Lex();
2370
2371
2373
2374
2375
2376 CppHashInfo.Loc = L;
2377 CppHashInfo.Filename = Filename;
2378 CppHashInfo.LineNumber = LineNumber;
2379 CppHashInfo.Buf = CurBuffer;
2380 if (FirstCppHashFilename.empty())
2381 FirstCppHashFilename = Filename;
2382 return false;
2383}
2384
2385
2386
2387void MasmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
2388 const MasmParser *Parser = static_cast<const MasmParser *>(Context);
2389 raw_ostream &OS = errs();
2390
2391 const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
2392 SMLoc DiagLoc = Diag.getLoc();
2394 unsigned CppHashBuf =
2395 Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
2396
2397
2398
2400 if (!Parser->SavedDiagHandler && DiagCurBuffer &&
2404 }
2405
2406
2407
2408
2409 if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
2410 DiagBuf != CppHashBuf) {
2411 if (Parser->SavedDiagHandler)
2412 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2413 else
2414 Diag.print(nullptr, OS);
2415 return;
2416 }
2417
2418
2419
2420
2421 const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
2422
2423 int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
2424 int CppHashLocLineNo =
2425 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2426 int LineNo =
2427 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2428
2429 SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
2432
2433 if (Parser->SavedDiagHandler)
2434 Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
2435 else
2436 NewDiag.print(nullptr, OS);
2437}
2438
2439
2440
2442 return isAlnum(C) || C == '_' || C == '$' || C == '@' || C == '?';
2443}
2444
2445bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
2448 const std::vectorstd::string &Locals, SMLoc L) {
2449 unsigned NParameters = Parameters.size();
2450 if (NParameters != A.size())
2451 return Error(L, "Wrong number of arguments");
2452 StringMapstd::string LocalSymbols;
2453 std::string Name;
2454 Name.reserve(6);
2455 for (StringRef Local : Locals) {
2456 raw_string_ostream LocalName(Name);
2457 LocalName << "??"
2460 Name.clear();
2461 }
2462
2463 std::optional CurrentQuote;
2464 while (!Body.empty()) {
2465
2466 std::size_t End = Body.size(), Pos = 0;
2467 std::size_t IdentifierPos = End;
2468 for (; Pos != End; ++Pos) {
2469
2470
2471 if (Body[Pos] == '&')
2472 break;
2474 if (!CurrentQuote)
2475 break;
2476 if (IdentifierPos == End)
2477 IdentifierPos = Pos;
2478 } else {
2479 IdentifierPos = End;
2480 }
2481
2482
2483 if (!CurrentQuote) {
2484 if (Body[Pos] == '\'' || Body[Pos] == '"')
2485 CurrentQuote = Body[Pos];
2486 } else if (Body[Pos] == CurrentQuote) {
2487 if (Pos + 1 != End && Body[Pos + 1] == CurrentQuote) {
2488
2489 ++Pos;
2490 continue;
2491 } else {
2492 CurrentQuote.reset();
2493 }
2494 }
2495 }
2496 if (IdentifierPos != End) {
2497
2498
2499 Pos = IdentifierPos;
2500 IdentifierPos = End;
2501 }
2502
2503
2504 OS << Body.slice(0, Pos);
2505
2506
2507 if (Pos == End)
2508 break;
2509
2510 unsigned I = Pos;
2511 bool InitialAmpersand = (Body[I] == '&');
2512 if (InitialAmpersand) {
2513 ++I;
2514 ++Pos;
2515 }
2517 ++I;
2518
2519 const char *Begin = Body.data() + Pos;
2520 StringRef Argument(Begin, I - Pos);
2521 const std::string ArgumentLower = Argument.lower();
2522 unsigned Index = 0;
2523
2524 for (; Index < NParameters; ++Index)
2525 if (Parameters[Index].Name.equals_insensitive(ArgumentLower))
2526 break;
2527
2528 if (Index == NParameters) {
2529 if (InitialAmpersand)
2530 OS << '&';
2531 auto it = LocalSymbols.find(ArgumentLower);
2532 if (it != LocalSymbols.end())
2533 OS << it->second;
2534 else
2536 Pos = I;
2537 } else {
2538 for (const AsmToken &Token : A[Index]) {
2539
2540
2541
2542
2543
2544
2545
2546 if (Token.getString().front() == '%' && Token.is(AsmToken::Integer))
2547
2548 OS << Token.getIntVal();
2549 else
2550 OS << Token.getString();
2551 }
2552
2554 if (Pos < End && Body[Pos] == '&') {
2555 ++Pos;
2556 }
2557 }
2558
2559 Body = Body.substr(Pos);
2560 }
2561
2562 return false;
2563}
2564
2565bool MasmParser::parseMacroArgument(const MCAsmMacroParameter *MP,
2566 MCAsmMacroArgument &MA,
2568 if (MP && MP->Vararg) {
2569 if (Lexer.isNot(EndTok)) {
2570 SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok);
2571 for (StringRef S : Str) {
2573 }
2574 }
2575 return false;
2576 }
2577
2578 SMLoc StrLoc = Lexer.getLoc(), EndLoc;
2580 const char *StrChar = StrLoc.getPointer() + 1;
2581 const char *EndChar = EndLoc.getPointer() - 1;
2582 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
2583
2584 Lex();
2585 MA.emplace_back(AsmToken::String, StringRef(StrChar, EndChar - StrChar));
2586 return false;
2587 }
2588
2589 unsigned ParenLevel = 0;
2590
2591 while (true) {
2593 return TokError("unexpected token");
2594
2596 break;
2597
2598
2599
2600 if (Lexer.is(EndTok) && (EndTok != AsmToken::RParen || ParenLevel == 0))
2601 break;
2602
2603
2605 ++ParenLevel;
2607 --ParenLevel;
2608
2609
2610 MA.push_back(getTok());
2611 Lex();
2612 }
2613
2614 if (ParenLevel != 0)
2615 return TokError("unbalanced parentheses in argument");
2616
2617 if (MA.empty() && MP) {
2619 return TokError("missing value for required parameter '" + MP->Name +
2620 "'");
2621 } else {
2623 }
2624 }
2625 return false;
2626}
2627
2628
2629bool MasmParser::parseMacroArguments(const MCAsmMacro *M,
2630 MCAsmMacroArguments &A,
2632 const unsigned NParameters = M ? M->Parameters.size() : 0;
2633 bool NamedParametersFound = false;
2634 SmallVector<SMLoc, 4> FALocs;
2635
2636 A.resize(NParameters);
2637 FALocs.resize(NParameters);
2638
2639
2640
2641
2642 for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
2644 SMLoc IDLoc = Lexer.getLoc();
2645 MCAsmMacroParameter FA;
2646
2648 if (parseIdentifier(FA.Name))
2649 return Error(IDLoc, "invalid argument identifier for formal argument");
2650
2652 return TokError("expected '=' after formal parameter identifier");
2653
2654 Lex();
2655
2656 NamedParametersFound = true;
2657 }
2658
2659 if (NamedParametersFound && FA.Name.empty())
2660 return Error(IDLoc, "cannot mix positional and keyword arguments");
2661
2664 assert(M && "expected macro to be defined");
2665 unsigned FAI = 0;
2666 for (FAI = 0; FAI < NParameters; ++FAI)
2667 if (M->Parameters[FAI].Name == FA.Name)
2668 break;
2669
2670 if (FAI >= NParameters) {
2671 return Error(IDLoc, "parameter named '" + FA.Name +
2672 "' does not exist for macro '" + M->Name + "'");
2673 }
2674 PI = FAI;
2675 }
2676 const MCAsmMacroParameter *MP = nullptr;
2677 if (M && PI < NParameters)
2678 MP = &M->Parameters[PI];
2679
2680 SMLoc StrLoc = Lexer.getLoc();
2681 SMLoc EndLoc;
2683 const MCExpr *AbsoluteExp;
2685
2686 Lex();
2687 if (parseExpression(AbsoluteExp, EndLoc))
2688 return false;
2689 if (!AbsoluteExp->evaluateAsAbsolute(Value,
2690 getStreamer().getAssemblerPtr()))
2691 return Error(StrLoc, "expected absolute expression");
2692 const char *StrChar = StrLoc.getPointer();
2693 const char *EndChar = EndLoc.getPointer();
2695 StringRef(StrChar, EndChar - StrChar), Value);
2696 FA.Value.push_back(newToken);
2697 } else if (parseMacroArgument(MP, FA.Value, EndTok)) {
2698 if (M)
2699 return addErrorSuffix(" in '" + M->Name + "' macro");
2700 else
2701 return true;
2702 }
2703
2704 if (!FA.Value.empty()) {
2705 if (A.size() <= PI)
2706 A.resize(PI + 1);
2708
2709 if (FALocs.size() <= PI)
2710 FALocs.resize(PI + 1);
2711
2712 FALocs[PI] = Lexer.getLoc();
2713 }
2714
2715
2716
2717
2718 if (Lexer.is(EndTok)) {
2720 for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
2722 if (M->Parameters[FAI].Required) {
2723 Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
2724 "missing value for required parameter "
2725 "'" +
2726 M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
2728 }
2729
2730 if (->Parameters[FAI].Value.empty())
2731 A[FAI] = M->Parameters[FAI].Value;
2732 }
2733 }
2735 }
2736
2738 Lex();
2739 }
2740
2741 return TokError("too many positional arguments");
2742}
2743
2744bool MasmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc,
2746
2747
2749 if (ActiveMacros.size() == MaxNestingDepth) {
2750 std::ostringstream MaxNestingDepthError;
2751 MaxNestingDepthError << "macros cannot be nested more than "
2752 << MaxNestingDepth << " levels deep."
2753 << " Use -asm-macro-max-nesting-depth to increase "
2754 "this limit.";
2755 return TokError(MaxNestingDepthError.str());
2756 }
2757
2758 MCAsmMacroArguments A;
2759 if (parseMacroArguments(M, A, ArgumentEndTok) || parseToken(ArgumentEndTok))
2760 return true;
2761
2762
2763
2764 SmallString<256> Buf;
2765 StringRef Body = M->Body;
2766 raw_svector_ostream OS(Buf);
2767
2768 if (expandMacro(OS, Body, M->Parameters, A, M->Locals, getTok().getLoc()))
2769 return true;
2770
2771
2772
2773 OS << "endm\n";
2774
2775 std::unique_ptr Instantiation =
2777
2778
2779
2780 MacroInstantiation *MI = new MacroInstantiation{
2781 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
2782 ActiveMacros.push_back(MI);
2783
2784 ++NumOfMacroInstantiations;
2785
2786
2789 EndStatementAtEOFStack.push_back(true);
2790 Lex();
2791
2792 return false;
2793}
2794
2795void MasmParser::handleMacroExit() {
2796
2797 EndStatementAtEOFStack.pop_back();
2798 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer,
2799 EndStatementAtEOFStack.back());
2800 Lex();
2801
2802
2803 delete ActiveMacros.back();
2804 ActiveMacros.pop_back();
2805}
2806
2807bool MasmParser::handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc) {
2808 if (->IsFunction)
2809 return Error(NameLoc, "cannot invoke macro procedure as function");
2810
2811 if (parseToken(AsmToken::LParen, "invoking macro function '" + M->Name +
2812 "' requires arguments in parentheses") ||
2814 return true;
2815
2816
2817 std::string ExitValue;
2820 ParseStatementInfo Info(&AsmStrRewrites);
2821 bool HasError = parseStatement(Info, nullptr);
2822
2823 if (!HasError && Info.ExitValue) {
2824 ExitValue = std::move(*Info.ExitValue);
2825 break;
2826 }
2827
2828
2829
2830
2831 if (HasError && !hasPendingError() && Lexer.getTok().is(AsmToken::Error))
2832 Lex();
2833
2834
2835 printPendingErrors();
2836
2837
2838 if (HasError && !getLexer().justConsumedEOL())
2839 eatToEndOfStatement();
2840 }
2841
2842
2843
2844 std::unique_ptr MacroValue =
2846
2847
2848
2851 false);
2852 EndStatementAtEOFStack.push_back(false);
2853 Lex();
2854
2855 return false;
2856}
2857
2858
2859
2860
2861bool MasmParser::parseIdentifier(StringRef &Res,
2862 IdentifierPositionKind Position) {
2863
2864
2865
2866
2867
2869 SMLoc PrefixLoc = getLexer().getLoc();
2870
2871
2872
2873 AsmToken nextTok = peekTok(false);
2874
2876 return true;
2877
2878
2880 return true;
2881
2882
2883 Lexer.Lex();
2884
2885 Res =
2886 StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1);
2887 Lex();
2888 return false;
2889 }
2890
2892 return true;
2893
2894 Res = getTok().getIdentifier();
2895
2896
2897
2898 ExpandKind ExpandNextToken = ExpandMacros;
2899 if (Position == StartOfStatement &&
2900 StringSwitch(Res)
2901 .CaseLower("echo", true)
2902 .CasesLower({"ifdef", "ifndef", "elseifdef", "elseifndef"}, true)
2903 .Default(false)) {
2904 ExpandNextToken = DoNotExpandMacros;
2905 }
2906 Lex(ExpandNextToken);
2907
2908 return false;
2909}
2910
2911
2912
2913
2914
2915
2916bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
2917 DirectiveKind DirKind, SMLoc NameLoc) {
2918 auto BuiltinIt = BuiltinSymbolMap.find(Name.lower());
2919 if (BuiltinIt != BuiltinSymbolMap.end())
2920 return Error(NameLoc, "cannot redefine a built-in symbol");
2921
2923 if (Var.Name.empty()) {
2924 Var.Name = Name;
2925 }
2926
2927 SMLoc StartLoc = Lexer.getLoc();
2928 if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) {
2929
2930 std::string Value;
2931 std::string TextItem;
2932 if (!parseTextItem(TextItem)) {
2933 Value += TextItem;
2934
2935
2936 auto parseItem = [&]() -> bool {
2937 if (parseTextItem(TextItem))
2938 return TokError("expected text item");
2939 Value += TextItem;
2940 return false;
2941 };
2942 if (parseOptionalToken(AsmToken::Comma) && parseMany(parseItem))
2943 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
2944
2945 if (!Var.IsText || Var.TextValue != Value) {
2946 switch (Var.Redefinable) {
2947 case Variable::NOT_REDEFINABLE:
2948 return Error(getTok().getLoc(), "invalid variable redefinition");
2949 case Variable::WARN_ON_REDEFINITION:
2950 if (Warning(NameLoc, "redefining '" + Name +
2951 "', already defined on the command line")) {
2952 return true;
2953 }
2954 break;
2955 default:
2956 break;
2957 }
2958 }
2959 Var.IsText = true;
2960 Var.TextValue = Value;
2961 Var.Redefinable = Variable::REDEFINABLE;
2962
2963 return false;
2964 }
2965 }
2966 if (DirKind == DK_TEXTEQU)
2967 return TokError("expected in '" + Twine(IDVal) + "' directive");
2968
2969
2970 const MCExpr *Expr;
2971 SMLoc EndLoc;
2972 if (parseExpression(Expr, EndLoc))
2973 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
2974 StringRef ExprAsString = StringRef(
2976
2978 if (!Expr->evaluateAsAbsolute(Value, getStreamer().getAssemblerPtr())) {
2979 if (DirKind == DK_ASSIGN)
2981 StartLoc,
2982 "expected absolute expression; not all symbols have known values",
2983 {StartLoc, EndLoc});
2984
2985
2986 if (!Var.IsText || Var.TextValue != ExprAsString) {
2987 switch (Var.Redefinable) {
2988 case Variable::NOT_REDEFINABLE:
2989 return Error(getTok().getLoc(), "invalid variable redefinition");
2990 case Variable::WARN_ON_REDEFINITION:
2991 if (Warning(NameLoc, "redefining '" + Name +
2992 "', already defined on the command line")) {
2993 return true;
2994 }
2995 break;
2996 default:
2997 break;
2998 }
2999 }
3000
3001 Var.IsText = true;
3002 Var.TextValue = ExprAsString.str();
3003 Var.Redefinable = Variable::REDEFINABLE;
3004
3005 return false;
3006 }
3007
3008 auto *Sym = static_cast<MCSymbolCOFF *>(getContext().parseSymbol(Var.Name));
3009 const MCConstantExpr *PrevValue =
3012 : nullptr;
3013 if (Var.IsText || !PrevValue || PrevValue->getValue() != Value) {
3014 switch (Var.Redefinable) {
3015 case Variable::NOT_REDEFINABLE:
3016 return Error(getTok().getLoc(), "invalid variable redefinition");
3017 case Variable::WARN_ON_REDEFINITION:
3018 if (Warning(NameLoc, "redefining '" + Name +
3019 "', already defined on the command line")) {
3020 return true;
3021 }
3022 break;
3023 default:
3024 break;
3025 }
3026 }
3027
3028 Var.IsText = false;
3029 Var.TextValue.clear();
3030 Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE
3031 : Variable::NOT_REDEFINABLE;
3032
3033 Sym->setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE);
3035 Sym->setExternal(false);
3036
3037 return false;
3038}
3039
3040bool MasmParser::parseEscapedString(std::string &Data) {
3042 return true;
3043
3045 char Quote = getTok().getString().front();
3046 StringRef Str = getTok().getStringContents();
3047 Data.reserve(Str.size());
3048 for (size_t i = 0, e = Str.size(); i != e; ++i) {
3049 Data.push_back(Str[i]);
3050 if (Str[i] == Quote) {
3051
3052
3053
3054 if (i + 1 == Str.size())
3055 return Error(getTok().getLoc(), "missing quotation mark in string");
3056 if (Str[i + 1] == Quote)
3057 ++i;
3058 }
3059 }
3060
3061 Lex();
3062 return false;
3063}
3064
3065bool MasmParser::parseAngleBracketString(std::string &Data) {
3066 SMLoc EndLoc, StartLoc = getTok().getLoc();
3068 const char *StartChar = StartLoc.getPointer() + 1;
3069 const char *EndChar = EndLoc.getPointer() - 1;
3070 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
3071
3072 Lex();
3073
3075 return false;
3076 }
3077 return true;
3078}
3079
3080
3081bool MasmParser::parseTextItem(std::string &Data) {
3082 switch (getTok().getKind()) {
3083 default:
3084 return true;
3086 int64_t Res;
3087 if (parseToken(AsmToken::Percent) || parseAbsoluteExpression(Res))
3088 return true;
3089 Data = std::to_string(Res);
3090 return false;
3091 }
3096 return parseAngleBracketString(Data);
3098
3099 StringRef ID;
3100 SMLoc StartLoc = getTok().getLoc();
3101 if (parseIdentifier(ID))
3102 return true;
3104
3105 bool Expanded = false;
3106 while (true) {
3107
3108 auto BuiltinIt = BuiltinSymbolMap.find(ID.lower());
3109 if (BuiltinIt != BuiltinSymbolMap.end()) {
3110 std::optionalstd::string BuiltinText =
3111 evaluateBuiltinTextMacro(BuiltinIt->getValue(), StartLoc);
3112 if (!BuiltinText) {
3113
3114 break;
3115 }
3116 Data = std::move(*BuiltinText);
3118 Expanded = true;
3119 continue;
3120 }
3121
3122
3123 auto BuiltinFuncIt = BuiltinFunctionMap.find(ID.lower());
3124 if (BuiltinFuncIt != BuiltinFunctionMap.end()) {
3125 Data.clear();
3126 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), ID, Data)) {
3127 return true;
3128 }
3130 Expanded = true;
3131 continue;
3132 }
3133
3134
3135 auto VarIt = Variables.find(ID.lower());
3136 if (VarIt != Variables.end()) {
3137 const Variable &Var = VarIt->getValue();
3138 if (!Var.IsText) {
3139
3140 break;
3141 }
3142 Data = Var.TextValue;
3144 Expanded = true;
3145 continue;
3146 }
3147
3148 break;
3149 }
3150
3151 if (!Expanded) {
3152
3153
3155 return true;
3156 }
3157 return false;
3158 }
3159 }
3161}
3162
3163
3164
3165bool MasmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
3166 auto parseOp = [&]() -> bool {
3167 std::string Data;
3168 if (checkForValidSection() || parseEscapedString(Data))
3169 return true;
3170 getStreamer().emitBytes(Data);
3171 if (ZeroTerminated)
3172 getStreamer().emitBytes(StringRef("\0", 1));
3173 return false;
3174 };
3175
3176 if (parseMany(parseOp))
3177 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3178 return false;
3179}
3180
3181bool MasmParser::emitIntValue(const MCExpr *Value, unsigned Size) {
3182
3184 assert(Size <= 8 && "Invalid size");
3185 int64_t IntValue = MCE->getValue();
3187 return Error(MCE->getLoc(), "out of range literal value");
3188 getStreamer().emitIntValue(IntValue, Size);
3189 } else {
3192
3193 getStreamer().emitIntValue(0, Size);
3194 } else {
3195 getStreamer().emitValue(Value, Size, Value->getLoc());
3196 }
3197 }
3198 return false;
3199}
3200
3201bool MasmParser::parseScalarInitializer(unsigned Size,
3202 SmallVectorImpl<const MCExpr *> &Values,
3203 unsigned StringPadLength) {
3205 std::string Value;
3206 if (parseEscapedString(Value))
3207 return true;
3208
3209 for (const unsigned char CharVal : Value)
3211
3212
3213 for (size_t i = Value.size(); i < StringPadLength; ++i)
3215 } else {
3216 const MCExpr *Value;
3217 if (parseExpression(Value))
3218 return true;
3220 getTok().getString().equals_insensitive("dup")) {
3221 Lex();
3223 if (!MCE)
3225 "cannot repeat value a non-constant number of times");
3226 const int64_t Repetitions = MCE->getValue();
3227 if (Repetitions < 0)
3229 "cannot repeat value a negative number of times");
3230
3233 "parentheses required for 'dup' contents") ||
3234 parseScalarInstList(Size, DuplicatedValues) || parseRParen())
3235 return true;
3236
3237 for (int i = 0; i < Repetitions; ++i)
3238 Values.append(DuplicatedValues.begin(), DuplicatedValues.end());
3239 } else {
3241 }
3242 }
3243 return false;
3244}
3245
3246bool MasmParser::parseScalarInstList(unsigned Size,
3247 SmallVectorImpl<const MCExpr *> &Values,
3249 while (getTok().isNot(EndToken) &&
3252 parseScalarInitializer(Size, Values);
3253
3254
3256 break;
3258 }
3259 return false;
3260}
3261
3262bool MasmParser::emitIntegralValues(unsigned Size, unsigned *Count) {
3264 if (checkForValidSection() || parseScalarInstList(Size, Values))
3265 return true;
3266
3267 for (const auto *Value : Values) {
3269 }
3271 *Count = Values.size();
3272 return false;
3273}
3274
3275
3276bool MasmParser::addIntegralField(StringRef Name, unsigned Size) {
3277 StructInfo &Struct = StructInProgress.back();
3278 FieldInfo &Field = Struct.addField(Name, FT_INTEGRAL, Size);
3279 IntFieldInfo &IntInfo = Field.Contents.IntInfo;
3280
3282
3283 if (parseScalarInstList(Size, IntInfo.Values))
3284 return true;
3285
3286 Field.SizeOf = Field.Type * IntInfo.Values.size();
3287 Field.LengthOf = IntInfo.Values.size();
3289 if (.IsUnion) {
3290 Struct.NextOffset = FieldEnd;
3291 }
3292 Struct.Size = std::max(Struct.Size, FieldEnd);
3293 return false;
3294}
3295
3296
3297
3298bool MasmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
3299 if (StructInProgress.empty()) {
3300
3301 if (emitIntegralValues(Size))
3302 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3303 } else if (addIntegralField("", Size)) {
3304 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3305 }
3306
3307 return false;
3308}
3309
3310
3311
3312bool MasmParser::parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
3313 StringRef Name, SMLoc NameLoc) {
3314 if (StructInProgress.empty()) {
3315
3317 getStreamer().emitLabel(Sym);
3319 if (emitIntegralValues(Size, &Count))
3320 return addErrorSuffix(" in '" + Twine(TypeName) + "' directive");
3321
3322 AsmTypeInfo Type;
3327 KnownType[Name.lower()] = Type;
3328 } else if (addIntegralField(Name, Size)) {
3329 return addErrorSuffix(" in '" + Twine(TypeName) + "' directive");
3330 }
3331
3332 return false;
3333}
3334
3335bool MasmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
3336
3337
3338 bool IsNeg = false;
3339 SMLoc SignLoc;
3341 SignLoc = getLexer().getLoc();
3342 Lexer.Lex();
3343 IsNeg = true;
3345 SignLoc = getLexer().getLoc();
3346 Lexer.Lex();
3347 }
3348
3350 return TokError(Lexer.getErr());
3353 return TokError("unexpected token in directive");
3354
3355
3357 StringRef IDVal = getTok().getString();
3365 else
3366 return TokError("invalid floating point literal");
3368
3369
3370 unsigned SizeInBits = Value.getSizeInBits(Semantics);
3371 if (SizeInBits != (IDVal.size() << 2))
3372 return TokError("invalid floating point literal");
3373
3374
3375 Lex();
3376
3377 Res = APInt(SizeInBits, IDVal, 16);
3379 return Warning(SignLoc, "MASM-style hex floats ignore explicit sign");
3380 return false;
3382 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3383 .takeError())) {
3384 return TokError("invalid floating point literal");
3385 }
3386 if (IsNeg)
3387 Value.changeSign();
3388
3389
3390 Lex();
3391
3392 Res = Value.bitcastToAPInt();
3393
3394 return false;
3395}
3396
3397bool MasmParser::parseRealInstList(const fltSemantics &Semantics,
3398 SmallVectorImpl &ValuesAsInt,
3400 while (getTok().isNot(EndToken) ||
3403 const AsmToken NextTok = peekTok();
3406 const MCExpr *Value;
3408 return true;
3410 if (!MCE)
3412 "cannot repeat value a non-constant number of times");
3413 const int64_t Repetitions = MCE->getValue();
3414 if (Repetitions < 0)
3416 "cannot repeat value a negative number of times");
3417
3420 "parentheses required for 'dup' contents") ||
3421 parseRealInstList(Semantics, DuplicatedValues) || parseRParen())
3422 return true;
3423
3424 for (int i = 0; i < Repetitions; ++i)
3425 ValuesAsInt.append(DuplicatedValues.begin(), DuplicatedValues.end());
3426 } else {
3427 APInt AsInt;
3428 if (parseRealValue(Semantics, AsInt))
3429 return true;
3431 }
3432
3433
3435 break;
3437 }
3438
3439 return false;
3440}
3441
3442
3443bool MasmParser::emitRealValues(const fltSemantics &Semantics,
3444 unsigned *Count) {
3445 if (checkForValidSection())
3446 return true;
3447
3449 if (parseRealInstList(Semantics, ValuesAsInt))
3450 return true;
3451
3452 for (const APInt &AsInt : ValuesAsInt) {
3453 getStreamer().emitIntValue(AsInt);
3454 }
3456 *Count = ValuesAsInt.size();
3457 return false;
3458}
3459
3460
3461bool MasmParser::addRealField(StringRef Name, const fltSemantics &Semantics,
3462 size_t Size) {
3463 StructInfo &Struct = StructInProgress.back();
3464 FieldInfo &Field = Struct.addField(Name, FT_REAL, Size);
3465 RealFieldInfo &RealInfo = Field.Contents.RealInfo;
3466
3467 Field.SizeOf = 0;
3468
3469 if (parseRealInstList(Semantics, RealInfo.AsIntValues))
3470 return true;
3471
3472 Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
3473 Field.LengthOf = RealInfo.AsIntValues.size();
3475
3477 if (.IsUnion) {
3478 Struct.NextOffset = FieldEnd;
3479 }
3480 Struct.Size = std::max(Struct.Size, FieldEnd);
3481 return false;
3482}
3483
3484
3485
3486bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
3487 const fltSemantics &Semantics,
3488 size_t Size) {
3489 if (StructInProgress.empty()) {
3490
3491 if (emitRealValues(Semantics))
3492 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3493 } else if (addRealField("", Semantics, Size)) {
3494 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3495 }
3496 return false;
3497}
3498
3499
3500
3501bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
3502 const fltSemantics &Semantics,
3503 unsigned Size, StringRef Name,
3504 SMLoc NameLoc) {
3505 if (StructInProgress.empty()) {
3506
3508 getStreamer().emitLabel(Sym);
3510 if (emitRealValues(Semantics, &Count))
3511 return addErrorSuffix(" in '" + TypeName + "' directive");
3512
3513 AsmTypeInfo Type;
3518 KnownType[Name.lower()] = Type;
3519 } else if (addRealField(Name, Semantics, Size)) {
3520 return addErrorSuffix(" in '" + TypeName + "' directive");
3521 }
3522 return false;
3523}
3524
3525bool MasmParser::parseOptionalAngleBracketOpen() {
3526 const AsmToken Tok = getTok();
3528 AngleBracketDepth++;
3530 return true;
3532 AngleBracketDepth++;
3534 return true;
3536 AngleBracketDepth++;
3537 return true;
3538 }
3539
3540 return false;
3541}
3542
3543bool MasmParser::parseAngleBracketClose(const Twine &Msg) {
3544 const AsmToken Tok = getTok();
3548 return true;
3549 }
3550 AngleBracketDepth--;
3551 return false;
3552}
3553
3554bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
3555 const IntFieldInfo &Contents,
3556 FieldInitializer &Initializer) {
3557 SMLoc Loc = getTok().getLoc();
3558
3561 if (Field.LengthOf == 1 && Field.Type > 1)
3562 return Error(Loc, "Cannot initialize scalar field with array value");
3565 return true;
3566 } else if (parseOptionalAngleBracketOpen()) {
3567 if (Field.LengthOf == 1 && Field.Type > 1)
3568 return Error(Loc, "Cannot initialize scalar field with array value");
3570 parseAngleBracketClose())
3571 return true;
3572 } else if (Field.LengthOf > 1 && Field.Type > 1) {
3573 return Error(Loc, "Cannot initialize array field with scalar value");
3574 } else if (parseScalarInitializer(Field.Type, Values,
3575 Field.LengthOf)) {
3576 return true;
3577 }
3578
3579 if (Values.size() > Field.LengthOf) {
3580 return Error(Loc, "Initializer too long for field; expected at most " +
3581 std::to_string(Field.LengthOf) + " elements, got " +
3582 std::to_string(Values.size()));
3583 }
3584
3585 Values.append(Contents.Values.begin() + Values.size(), Contents.Values.end());
3586
3587 Initializer = FieldInitializer(std::move(Values));
3588 return false;
3589}
3590
3591bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
3592 const RealFieldInfo &Contents,
3593 FieldInitializer &Initializer) {
3594 const fltSemantics *Semantics;
3595 switch (Field.Type) {
3596 case 4:
3597 Semantics = &APFloat::IEEEsingle();
3598 break;
3599 case 8:
3600 Semantics = &APFloat::IEEEdouble();
3601 break;
3602 case 10:
3603 Semantics = &APFloat::x87DoubleExtended();
3604 break;
3605 default:
3607 }
3608
3609 SMLoc Loc = getTok().getLoc();
3610
3613 if (Field.LengthOf == 1)
3614 return Error(Loc, "Cannot initialize scalar field with array value");
3615 if (parseRealInstList(*Semantics, AsIntValues, AsmToken::RCurly) ||
3617 return true;
3618 } else if (parseOptionalAngleBracketOpen()) {
3619 if (Field.LengthOf == 1)
3620 return Error(Loc, "Cannot initialize scalar field with array value");
3621 if (parseRealInstList(*Semantics, AsIntValues, AsmToken::Greater) ||
3622 parseAngleBracketClose())
3623 return true;
3624 } else if (Field.LengthOf > 1) {
3625 return Error(Loc, "Cannot initialize array field with scalar value");
3626 } else {
3628 if (parseRealValue(*Semantics, AsIntValues.back()))
3629 return true;
3630 }
3631
3632 if (AsIntValues.size() > Field.LengthOf) {
3633 return Error(Loc, "Initializer too long for field; expected at most " +
3634 std::to_string(Field.LengthOf) + " elements, got " +
3635 std::to_string(AsIntValues.size()));
3636 }
3637
3638 AsIntValues.append(Contents.AsIntValues.begin() + AsIntValues.size(),
3639 Contents.AsIntValues.end());
3640
3641 Initializer = FieldInitializer(std::move(AsIntValues));
3642 return false;
3643}
3644
3645bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
3646 const StructFieldInfo &Contents,
3647 FieldInitializer &Initializer) {
3648 SMLoc Loc = getTok().getLoc();
3649
3650 std::vector Initializers;
3651 if (Field.LengthOf > 1) {
3653 if (parseStructInstList(Contents.Structure, Initializers,
3656 return true;
3657 } else if (parseOptionalAngleBracketOpen()) {
3658 if (parseStructInstList(Contents.Structure, Initializers,
3660 parseAngleBracketClose())
3661 return true;
3662 } else {
3663 return Error(Loc, "Cannot initialize array field with scalar value");
3664 }
3665 } else {
3666 Initializers.emplace_back();
3667 if (parseStructInitializer(Contents.Structure, Initializers.back()))
3668 return true;
3669 }
3670
3671 if (Initializers.size() > Field.LengthOf) {
3672 return Error(Loc, "Initializer too long for field; expected at most " +
3673 std::to_string(Field.LengthOf) + " elements, got " +
3674 std::to_string(Initializers.size()));
3675 }
3676
3678 Initializers.size()));
3679
3680 Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
3681 return false;
3682}
3683
3684bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
3685 FieldInitializer &Initializer) {
3686 switch (Field.Contents.FT) {
3687 case FT_INTEGRAL:
3688 return parseFieldInitializer(Field, Field.Contents.IntInfo, Initializer);
3689 case FT_REAL:
3690 return parseFieldInitializer(Field, Field.Contents.RealInfo, Initializer);
3691 case FT_STRUCT:
3692 return parseFieldInitializer(Field, Field.Contents.StructInfo, Initializer);
3693 }
3695}
3696
3697bool MasmParser::parseStructInitializer(const StructInfo &Structure,
3698 StructInitializer &Initializer) {
3699 const AsmToken FirstToken = getTok();
3700
3701 std::optionalAsmToken::TokenKind EndToken;
3704 } else if (parseOptionalAngleBracketOpen()) {
3706 AngleBracketDepth++;
3708 FirstToken.getString() == "?") {
3709
3711 return true;
3712 } else {
3713 return Error(FirstToken.getLoc(), "Expected struct initializer");
3714 }
3715
3716 auto &FieldInitializers = Initializer.FieldInitializers;
3717 size_t FieldIndex = 0;
3718 if (EndToken) {
3719
3720 while (getTok().isNot(*EndToken) && FieldIndex < Structure.Fields.size()) {
3721 const FieldInfo &Field = Structure.Fields[FieldIndex++];
3723
3724
3725 FieldInitializers.push_back(Field.Contents);
3727 continue;
3728 }
3729 FieldInitializers.emplace_back(Field.Contents.FT);
3730 if (parseFieldInitializer(Field, FieldInitializers.back()))
3731 return true;
3732
3733
3734 SMLoc CommaLoc = getTok().getLoc();
3736 break;
3737 if (FieldIndex == Structure.Fields.size())
3738 return Error(CommaLoc, "'" + Structure.Name +
3739 "' initializer initializes too many fields");
3741 }
3742 }
3743
3745 FieldInitializers.push_back(Field.Contents);
3746
3747 if (EndToken) {
3749 return parseAngleBracketClose();
3750
3751 return parseToken(*EndToken);
3752 }
3753
3754 return false;
3755}
3756
3757bool MasmParser::parseStructInstList(
3758 const StructInfo &Structure, std::vector &Initializers,
3760 while (getTok().isNot(EndToken) ||
3763 const AsmToken NextTok = peekTok();
3766 const MCExpr *Value;
3768 return true;
3770 if (!MCE)
3772 "cannot repeat value a non-constant number of times");
3773 const int64_t Repetitions = MCE->getValue();
3774 if (Repetitions < 0)
3776 "cannot repeat value a negative number of times");
3777
3778 std::vector DuplicatedValues;
3780 "parentheses required for 'dup' contents") ||
3781 parseStructInstList(Structure, DuplicatedValues) || parseRParen())
3782 return true;
3783
3784 for (int i = 0; i < Repetitions; ++i)
3786 } else {
3787 Initializers.emplace_back();
3788 if (parseStructInitializer(Structure, Initializers.back()))
3789 return true;
3790 }
3791
3792
3794 break;
3796 }
3797
3798 return false;
3799}
3800
3801bool MasmParser::emitFieldValue(const FieldInfo &Field,
3802 const IntFieldInfo &Contents) {
3803
3804 for (const MCExpr *Value : Contents.Values) {
3805 if (emitIntValue(Value, Field.Type))
3806 return true;
3807 }
3808 return false;
3809}
3810
3811bool MasmParser::emitFieldValue(const FieldInfo &Field,
3812 const RealFieldInfo &Contents) {
3813 for (const APInt &AsInt : Contents.AsIntValues) {
3816 }
3817 return false;
3818}
3819
3820bool MasmParser::emitFieldValue(const FieldInfo &Field,
3821 const StructFieldInfo &Contents) {
3822 for (const auto &Initializer : Contents.Initializers) {
3824 for (const auto &SubField : Contents.Structure.Fields) {
3825 getStreamer().emitZeros(SubField.Offset - Offset);
3826 Offset = SubField.Offset + SubField.SizeOf;
3827 emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
3828 }
3829 }
3830 return false;
3831}
3832
3833bool MasmParser::emitFieldValue(const FieldInfo &Field) {
3834 switch (Field.Contents.FT) {
3835 case FT_INTEGRAL:
3836 return emitFieldValue(Field, Field.Contents.IntInfo);
3837 case FT_REAL:
3838 return emitFieldValue(Field, Field.Contents.RealInfo);
3839 case FT_STRUCT:
3840 return emitFieldValue(Field, Field.Contents.StructInfo);
3841 }
3843}
3844
3845bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
3846 const IntFieldInfo &Contents,
3847 const IntFieldInfo &Initializer) {
3848 for (const auto &Value : Initializer.Values) {
3849 if (emitIntValue(Value, Field.Type))
3850 return true;
3851 }
3852
3853 for (const auto &Value :
3854 llvm::drop_begin(Contents.Values, Initializer.Values.size())) {
3855 if (emitIntValue(Value, Field.Type))
3856 return true;
3857 }
3858 return false;
3859}
3860
3861bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
3862 const RealFieldInfo &Contents,
3863 const RealFieldInfo &Initializer) {
3864 for (const auto &AsInt : Initializer.AsIntValues) {
3867 }
3868
3869 for (const auto &AsInt :
3870 llvm::drop_begin(Contents.AsIntValues, Initializer.AsIntValues.size())) {
3873 }
3874 return false;
3875}
3876
3877bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
3878 const StructFieldInfo &Contents,
3879 const StructFieldInfo &Initializer) {
3880 for (const auto &Init : Initializer.Initializers) {
3881 if (emitStructInitializer(Contents.Structure, Init))
3882 return true;
3883 }
3884
3885 for (const auto &Init : llvm::drop_begin(Contents.Initializers,
3886 Initializer.Initializers.size())) {
3887 if (emitStructInitializer(Contents.Structure, Init))
3888 return true;
3889 }
3890 return false;
3891}
3892
3893bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
3894 const FieldInitializer &Initializer) {
3895 switch (Field.Contents.FT) {
3896 case FT_INTEGRAL:
3897 return emitFieldInitializer(Field, Field.Contents.IntInfo,
3898 Initializer.IntInfo);
3899 case FT_REAL:
3900 return emitFieldInitializer(Field, Field.Contents.RealInfo,
3901 Initializer.RealInfo);
3902 case FT_STRUCT:
3903 return emitFieldInitializer(Field, Field.Contents.StructInfo,
3904 Initializer.StructInfo);
3905 }
3907}
3908
3909bool MasmParser::emitStructInitializer(const StructInfo &Structure,
3910 const StructInitializer &Initializer) {
3911 if (!Structure.Initializable)
3912 return Error(getLexer().getLoc(),
3913 "cannot initialize a value of type '" + Structure.Name +
3914 "'; 'org' was used in the type's declaration");
3916 for (const auto &Init : Initializer.FieldInitializers) {
3917 const auto &Field = Structure.Fields[Index++];
3920 if (emitFieldInitializer(Field, Init))
3921 return true;
3922 }
3923
3925 Structure.Fields, Initializer.FieldInitializers.size())) {
3928 if (emitFieldValue(Field))
3929 return true;
3930 }
3931
3932 if (Offset != Structure.Size)
3933 getStreamer().emitZeros(Structure.Size - Offset);
3934 return false;
3935}
3936
3937
3938bool MasmParser::emitStructValues(const StructInfo &Structure,
3939 unsigned *Count) {
3940 std::vector Initializers;
3941 if (parseStructInstList(Structure, Initializers))
3942 return true;
3943
3944 for (const auto &Initializer : Initializers) {
3945 if (emitStructInitializer(Structure, Initializer))
3946 return true;
3947 }
3948
3950 *Count = Initializers.size();
3951 return false;
3952}
3953
3954
3955bool MasmParser::addStructField(StringRef Name, const StructInfo &Structure) {
3956 StructInfo &OwningStruct = StructInProgress.back();
3957 FieldInfo &Field =
3958 OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
3959 StructFieldInfo &StructInfo = Field.Contents.StructInfo;
3960
3961 StructInfo.Structure = Structure;
3962 Field.Type = Structure.Size;
3963
3964 if (parseStructInstList(Structure, StructInfo.Initializers))
3965 return true;
3966
3967 Field.LengthOf = StructInfo.Initializers.size();
3969
3971 if (!OwningStruct.IsUnion) {
3972 OwningStruct.NextOffset = FieldEnd;
3973 }
3974 OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd);
3975
3976 return false;
3977}
3978
3979
3980
3981
3982bool MasmParser::parseDirectiveStructValue(const StructInfo &Structure,
3983 StringRef Directive, SMLoc DirLoc) {
3984 if (StructInProgress.empty()) {
3985 if (emitStructValues(Structure))
3986 return true;
3987 } else if (addStructField("", Structure)) {
3988 return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
3989 }
3990
3991 return false;
3992}
3993
3994
3995
3996bool MasmParser::parseDirectiveNamedStructValue(const StructInfo &Structure,
3997 StringRef Directive,
3998 SMLoc DirLoc, StringRef Name) {
3999 if (StructInProgress.empty()) {
4000
4002 getStreamer().emitLabel(Sym);
4004 if (emitStructValues(Structure, &Count))
4005 return true;
4006 AsmTypeInfo Type;
4007 Type.Name = Structure.Name;
4008 Type.Size = Structure.Size * Count;
4009 Type.ElementSize = Structure.Size;
4011 KnownType[Name.lower()] = Type;
4012 } else if (addStructField(Name, Structure)) {
4013 return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
4014 }
4015
4016 return false;
4017}
4018
4019
4020
4021
4022
4023
4024
4025bool MasmParser::parseDirectiveStruct(StringRef Directive,
4026 DirectiveKind DirKind, StringRef Name,
4027 SMLoc NameLoc) {
4028
4029
4030 AsmToken NextTok = getTok();
4031 int64_t AlignmentValue = 1;
4034 parseAbsoluteExpression(AlignmentValue)) {
4035 return addErrorSuffix(" in alignment value for '" + Twine(Directive) +
4036 "' directive");
4037 }
4039 return Error(NextTok.getLoc(), "alignment must be a power of two; was " +
4040 std::to_string(AlignmentValue));
4041 }
4042
4044 SMLoc QualifierLoc;
4046 QualifierLoc = getTok().getLoc();
4047 if (parseIdentifier(Qualifier))
4048 return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
4049 if (.equals_insensitive("nonunique"))
4050 return Error(QualifierLoc, "Unrecognized qualifier for '" +
4051 Twine(Directive) +
4052 "' directive; expected none or NONUNIQUE");
4053 }
4054
4055 if (parseEOL())
4056 return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
4057
4058 StructInProgress.emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
4059 return false;
4060}
4061
4062
4063
4064
4065
4066bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
4067 DirectiveKind DirKind) {
4068 if (StructInProgress.empty())
4069 return TokError("missing name in top-level '" + Twine(Directive) +
4070 "' directive");
4071
4072 StringRef Name;
4074 Name = getTok().getIdentifier();
4076 }
4077 if (parseEOL())
4078 return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
4079
4080
4081
4082 StructInProgress.reserve(StructInProgress.size() + 1);
4083 StructInProgress.emplace_back(Name, DirKind == DK_UNION,
4084 StructInProgress.back().Alignment);
4085 return false;
4086}
4087
4088bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
4089 if (StructInProgress.empty())
4090 return Error(NameLoc, "ENDS directive without matching STRUC/STRUCT/UNION");
4091 if (StructInProgress.size() > 1)
4092 return Error(NameLoc, "unexpected name in nested ENDS directive");
4093 if (StructInProgress.back().Name.compare_insensitive(Name))
4094 return Error(NameLoc, "mismatched name in ENDS directive; expected '" +
4095 StructInProgress.back().Name + "'");
4096 StructInfo Structure = StructInProgress.pop_back_val();
4097
4098
4100 Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
4101 Structs[Name.lower()] = Structure;
4102
4103 if (parseEOL())
4104 return addErrorSuffix(" in ENDS directive");
4105
4106 return false;
4107}
4108
4109bool MasmParser::parseDirectiveNestedEnds() {
4110 if (StructInProgress.empty())
4111 return TokError("ENDS directive without matching STRUC/STRUCT/UNION");
4112 if (StructInProgress.size() == 1)
4113 return TokError("missing name in top-level ENDS directive");
4114
4115 if (parseEOL())
4116 return addErrorSuffix(" in nested ENDS directive");
4117
4118 StructInfo Structure = StructInProgress.pop_back_val();
4119
4120 Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment);
4121
4122 StructInfo &ParentStruct = StructInProgress.back();
4123 if (Structure.Name.empty()) {
4124
4125
4126 const size_t OldFields = ParentStruct.Fields.size();
4127 ParentStruct.Fields.insert(
4128 ParentStruct.Fields.end(),
4129 std::make_move_iterator(Structure.Fields.begin()),
4130 std::make_move_iterator(Structure.Fields.end()));
4131 for (const auto &FieldByName : Structure.FieldsByName) {
4132 ParentStruct.FieldsByName[FieldByName.getKey()] =
4133 FieldByName.getValue() + OldFields;
4134 }
4135
4136 unsigned FirstFieldOffset = 0;
4137 if (!Structure.Fields.empty() && !ParentStruct.IsUnion) {
4139 ParentStruct.NextOffset,
4140 std::min(ParentStruct.Alignment, Structure.AlignmentSize));
4141 }
4142
4143 if (ParentStruct.IsUnion) {
4144 ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
4145 } else {
4148
4149 const unsigned StructureEnd = FirstFieldOffset + Structure.Size;
4150 if (!ParentStruct.IsUnion) {
4151 ParentStruct.NextOffset = StructureEnd;
4152 }
4153 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4154 }
4155 } else {
4156 FieldInfo &Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
4157 Structure.AlignmentSize);
4158 StructFieldInfo &StructInfo = Field.Contents.StructInfo;
4159 Field.Type = Structure.Size;
4160 Field.LengthOf = 1;
4161 Field.SizeOf = Structure.Size;
4162
4164 if (!ParentStruct.IsUnion) {
4165 ParentStruct.NextOffset = StructureEnd;
4166 }
4167 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4168
4169 StructInfo.Structure = Structure;
4170 StructInfo.Initializers.emplace_back();
4171 auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
4172 for (const auto &SubField : Structure.Fields) {
4173 FieldInitializers.push_back(SubField.Contents);
4174 }
4175 }
4176
4177 return false;
4178}
4179
4180
4181
4182bool MasmParser::parseDirectiveOrg() {
4183 const MCExpr *Offset;
4184 SMLoc OffsetLoc = Lexer.getLoc();
4185 if (checkForValidSection() || parseExpression(Offset))
4186 return true;
4187 if (parseEOL())
4188 return addErrorSuffix(" in 'org' directive");
4189
4190 if (StructInProgress.empty()) {
4191
4192 if (checkForValidSection())
4193 return addErrorSuffix(" in 'org' directive");
4194
4195 getStreamer().emitValueToOffset(Offset, 0, OffsetLoc);
4196 } else {
4197
4198 StructInfo &Structure = StructInProgress.back();
4199 int64_t OffsetRes;
4200 if (->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr()))
4201 return Error(OffsetLoc,
4202 "expected absolute expression in 'org' directive");
4203 if (OffsetRes < 0)
4205 OffsetLoc,
4206 "expected non-negative value in struct's 'org' directive; was " +
4207 std::to_string(OffsetRes));
4208 Structure.NextOffset = static_cast<unsigned>(OffsetRes);
4209
4210
4211 Structure.Initializable = false;
4212 }
4213
4214 return false;
4215}
4216
4217bool MasmParser::emitAlignTo(int64_t Alignment) {
4218 if (StructInProgress.empty()) {
4219
4220 if (checkForValidSection())
4221 return true;
4222
4223
4224
4225 const MCSection *Section = getStreamer().getCurrentSectionOnly();
4227 getStreamer().emitCodeAlignment(Align(Alignment),
4228 &getTargetParser().getSTI(),
4229 0);
4230 } else {
4231
4232 getStreamer().emitValueToAlignment(Align(Alignment), 0,
4233 1,
4234 0);
4235 }
4236 } else {
4237
4238 StructInfo &Structure = StructInProgress.back();
4239 Structure.NextOffset = llvm::alignTo(Structure.NextOffset, Alignment);
4240 }
4241
4242 return false;
4243}
4244
4245
4246
4247bool MasmParser::parseDirectiveAlign() {
4248 SMLoc AlignmentLoc = getLexer().getLoc();
4249 int64_t Alignment;
4250
4251
4253 return Warning(AlignmentLoc,
4254 "align directive with no operand is ignored") &&
4255 parseEOL();
4256 }
4257 if (parseAbsoluteExpression(Alignment) || parseEOL())
4258 return addErrorSuffix(" in align directive");
4259
4260
4261 bool ReturnVal = false;
4262
4263
4264
4265 if (Alignment == 0)
4266 Alignment = 1;
4268 ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2; was " +
4269 std::to_string(Alignment));
4270
4271 if (emitAlignTo(Alignment))
4272 ReturnVal |= addErrorSuffix(" in align directive");
4273
4274 return ReturnVal;
4275}
4276
4277
4278
4279bool MasmParser::parseDirectiveEven() {
4280 if (parseEOL() || emitAlignTo(2))
4281 return addErrorSuffix(" in even directive");
4282
4283 return false;
4284}
4285
4286
4287
4288
4289
4290
4291
4292bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
4296 return Error(Lexer.getLoc(),
4297 "Vararg parameter '" + Parameters.back().Name +
4298 "' should be last in the list of parameters");
4299
4301 if (parseIdentifier(Parameter.Name))
4302 return TokError("expected identifier in 'macro' directive");
4303
4304
4305 for (const MCAsmMacroParameter& CurrParam : Parameters)
4306 if (CurrParam.Name.equals_insensitive(Parameter.Name))
4307 return TokError("macro '" + Name + "' has multiple parameters"
4308 " named '" + Parameter.Name + "'");
4309
4311 Lex();
4312
4314
4315 SMLoc ParamLoc;
4316
4317 ParamLoc = Lexer.getLoc();
4318 if (parseMacroArgument(nullptr, Parameter.Value))
4319 return true;
4320 } else {
4321 SMLoc QualLoc;
4323
4324 QualLoc = Lexer.getLoc();
4325 if (parseIdentifier(Qualifier))
4326 return Error(QualLoc, "missing parameter qualifier for "
4327 "'" +
4328 Parameter.Name + "' in macro '" + Name +
4329 "'");
4330
4331 if (Qualifier.equals_insensitive("req"))
4333 else if (Qualifier.equals_insensitive("vararg"))
4335 else
4336 return Error(QualLoc,
4337 Qualifier + " is not a valid parameter qualifier for '" +
4338 Parameter.Name + "' in macro '" + Name + "'");
4339 }
4340 }
4341
4342 Parameters.push_back(std::move(Parameter));
4343
4345 Lex();
4346 }
4347
4348
4349 Lexer.Lex();
4350
4351 std::vectorstd::string Locals;
4353 getTok().getIdentifier().equals_insensitive("local")) {
4354 Lex();
4355
4356 StringRef ID;
4357 while (true) {
4358 if (parseIdentifier(ID))
4359 return true;
4360 Locals.push_back(ID.lower());
4361
4362
4364 break;
4366 }
4367 }
4368
4369
4370 AsmToken EndToken, StartToken = getTok();
4371 unsigned MacroDepth = 0;
4372 bool IsMacroFunction = false;
4373
4374 while (true) {
4375
4377 Lexer.Lex();
4378 }
4379
4380
4382 return Error(NameLoc, "no matching 'endm' in definition");
4383
4384
4385
4387 if (getTok().getIdentifier().equals_insensitive("endm")) {
4388 if (MacroDepth == 0) {
4389 EndToken = getTok();
4390 Lexer.Lex();
4392 return TokError("unexpected token in '" + EndToken.getIdentifier() +
4393 "' directive");
4394 break;
4395 } else {
4396
4397 --MacroDepth;
4398 }
4399 } else if (getTok().getIdentifier().equals_insensitive("exitm")) {
4401 IsMacroFunction = true;
4402 }
4403 } else if (isMacroLikeDirective()) {
4404
4405
4406 ++MacroDepth;
4407 }
4408 }
4409
4410
4411 eatToEndOfStatement();
4412 }
4413
4415 return Error(NameLoc, "macro '" + Name + "' is already defined");
4416 }
4417
4420 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4421 MCAsmMacro Macro(Name, Body, std::move(Parameters), std::move(Locals),
4422 IsMacroFunction);
4426 return false;
4427}
4428
4429
4430
4431bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
4432 StringRef Directive,
4433 std::string &Value) {
4434 SMLoc EndLoc = getTok().getLoc();
4436 return Error(EndLoc,
4437 "unable to parse text item in '" + Directive + "' directive");
4438 eatToEndOfStatement();
4439
4440 if (!isInsideMacroInstantiation())
4441 return TokError("unexpected '" + Directive + "' in file, "
4442 "no current macro definition");
4443
4444
4445 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4446 TheCondState = TheCondStack.back();
4447 TheCondStack.pop_back();
4448 }
4449
4450 handleMacroExit();
4451 return false;
4452}
4453
4454
4455
4456bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
4458 return TokError("unexpected token in '" + Directive + "' directive");
4459
4460
4461
4462 if (isInsideMacroInstantiation()) {
4463 handleMacroExit();
4464 return false;
4465 }
4466
4467
4468
4469 return TokError("unexpected '" + Directive + "' in file, "
4470 "no current macro definition");
4471}
4472
4473
4474
4475bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4476 StringRef Name;
4477 while (true) {
4478 SMLoc NameLoc;
4479 if (parseTokenLoc(NameLoc) ||
4480 check(parseIdentifier(Name), NameLoc,
4481 "expected identifier in 'purge' directive"))
4482 return true;
4483
4485 << "Un-defining macro: " << Name << "\n");
4487 return Error(NameLoc, "macro '" + Name + "' is not defined");
4489
4491 break;
4493 }
4494
4495 return false;
4496}
4497
4498bool MasmParser::parseDirectiveExtern() {
4499
4500 auto parseOp = [&]() -> bool {
4502 SMLoc NameLoc = getTok().getLoc();
4504 return Error(NameLoc, "expected name");
4506 return true;
4507
4509 SMLoc TypeLoc = getTok().getLoc();
4510 if (parseIdentifier(TypeName))
4511 return Error(TypeLoc, "expected type");
4512 if (.equals_insensitive("proc")) {
4513 AsmTypeInfo Type;
4514 if (lookUpType(TypeName, Type))
4515 return Error(TypeLoc, "unrecognized type");
4517 }
4518
4519 static_cast<MCSymbolCOFF *>(Sym)->setExternal(true);
4520 getStreamer().emitSymbolAttribute(Sym, MCSA_Extern);
4521
4522 return false;
4523 };
4524
4525 if (parseMany(parseOp))
4526 return addErrorSuffix(" in directive 'extern'");
4527 return false;
4528}
4529
4530
4531
4532bool MasmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
4533 auto parseOp = [&]() -> bool {
4534 SMLoc Loc = getTok().getLoc();
4537 return Error(Loc, "expected identifier");
4538
4539
4541 return Error(Loc, "non-local symbol required");
4542
4543 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
4544 return Error(Loc, "unable to emit symbol attribute");
4545 return false;
4546 };
4547
4548 if (parseMany(parseOp))
4549 return addErrorSuffix(" in directive");
4550 return false;
4551}
4552
4553
4554
4555bool MasmParser::parseDirectiveComm(bool IsLocal) {
4556 if (checkForValidSection())
4557 return true;
4558
4559 SMLoc IDLoc = getLexer().getLoc();
4562 return TokError("expected identifier in directive");
4563
4565 return TokError("unexpected token in directive");
4566 Lex();
4567
4568 int64_t Size;
4569 SMLoc SizeLoc = getLexer().getLoc();
4570 if (parseAbsoluteExpression(Size))
4571 return true;
4572
4573 int64_t Pow2Alignment = 0;
4574 SMLoc Pow2AlignmentLoc;
4576 Lex();
4577 Pow2AlignmentLoc = getLexer().getLoc();
4578 if (parseAbsoluteExpression(Pow2Alignment))
4579 return true;
4580
4581 LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
4583 return Error(Pow2AlignmentLoc, "alignment not supported on this target");
4584
4585
4586 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
4589 return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
4590 Pow2Alignment = Log2_64(Pow2Alignment);
4591 }
4592 }
4593
4594 if (parseEOL())
4595 return true;
4596
4597
4598
4599 if (Size < 0)
4600 return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
4601 "be less than zero");
4602
4603
4604
4605
4606 if (Pow2Alignment < 0)
4607 return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
4608 "alignment, can't be less than zero");
4609
4612 return Error(IDLoc, "invalid symbol redefinition");
4613
4614
4615 if (IsLocal) {
4616 getStreamer().emitLocalCommonSymbol(Sym, Size,
4617 Align(1ULL << Pow2Alignment));
4618 return false;
4619 }
4620
4621 getStreamer().emitCommonSymbol(Sym, Size, Align(1ULL << Pow2Alignment));
4622 return false;
4623}
4624
4625
4626
4627
4628
4629bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
4631 size_t DelimiterEnd = FirstLine.find_first_of("\b\t\v\f\r\x1A ");
4632 assert(DelimiterEnd != std:🧵:npos);
4633 StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd);
4634 if (Delimiter.empty())
4635 return Error(DirectiveLoc, "no delimiter in 'comment' directive");
4636 do {
4638 return Error(DirectiveLoc, "unmatched delimiter in 'comment' directive");
4639 Lex();
4640 } while (
4642 return parseEOL();
4643}
4644
4645
4646
4647
4648bool MasmParser::parseDirectiveInclude() {
4649
4651 SMLoc IncludeLoc = getTok().getLoc();
4652
4653 if (parseAngleBracketString(Filename))
4655 if (check(Filename.empty(), "missing filename in 'include' directive") ||
4657 "unexpected token in 'include' directive") ||
4658
4659
4660 check(enterIncludeFile(Filename), IncludeLoc,
4661 "Could not find include file '" + Filename + "'"))
4662 return true;
4663
4664 return false;
4665}
4666
4667
4668
4669bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
4670 TheCondStack.push_back(TheCondState);
4672 if (TheCondState.Ignore) {
4673 eatToEndOfStatement();
4674 } else {
4675 int64_t ExprValue;
4676 if (parseAbsoluteExpression(ExprValue) || parseEOL())
4677 return true;
4678
4679 switch (DirKind) {
4680 default:
4682 case DK_IF:
4683 break;
4684 case DK_IFE:
4685 ExprValue = ExprValue == 0;
4686 break;
4687 }
4688
4689 TheCondState.CondMet = ExprValue;
4691 }
4692
4693 return false;
4694}
4695
4696
4697
4698bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
4699 TheCondStack.push_back(TheCondState);
4701
4702 if (TheCondState.Ignore) {
4703 eatToEndOfStatement();
4704 } else {
4705 std::string Str;
4706 if (parseTextItem(Str))
4707 return TokError("expected text item parameter for 'ifb' directive");
4708
4709 if (parseEOL())
4710 return true;
4711
4712 TheCondState.CondMet = ExpectBlank == Str.empty();
4714 }
4715
4716 return false;
4717}
4718
4719
4720
4721bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
4722 bool CaseInsensitive) {
4723 std::string String1, String2;
4724
4725 if (parseTextItem(String1)) {
4726 if (ExpectEqual)
4727 return TokError("expected text item parameter for 'ifidn' directive");
4728 return TokError("expected text item parameter for 'ifdif' directive");
4729 }
4730
4732 if (ExpectEqual)
4733 return TokError(
4734 "expected comma after first string for 'ifidn' directive");
4735 return TokError("expected comma after first string for 'ifdif' directive");
4736 }
4737 Lex();
4738
4739 if (parseTextItem(String2)) {
4740 if (ExpectEqual)
4741 return TokError("expected text item parameter for 'ifidn' directive");
4742 return TokError("expected text item parameter for 'ifdif' directive");
4743 }
4744
4745 TheCondStack.push_back(TheCondState);
4747 if (CaseInsensitive)
4749 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4750 else
4751 TheCondState.CondMet = ExpectEqual == (String1 == String2);
4753
4754 return false;
4755}
4756
4757
4758
4759
4760bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
4761 TheCondStack.push_back(TheCondState);
4763
4764 if (TheCondState.Ignore) {
4765 eatToEndOfStatement();
4766 } else {
4767 bool is_defined = false;
4768 MCRegister Reg;
4769 SMLoc StartLoc, EndLoc;
4770 is_defined =
4771 getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
4772 if (!is_defined) {
4773 StringRef Name;
4774 if (check(parseIdentifier(Name), "expected identifier after 'ifdef'") ||
4775 parseEOL())
4776 return true;
4777
4778 if (BuiltinSymbolMap.contains(Name.lower())) {
4779 is_defined = true;
4780 } else if (Variables.contains(Name.lower())) {
4781 is_defined = true;
4782 } else {
4784 is_defined = (Sym && !Sym->isUndefined());
4785 }
4786 }
4787
4788 TheCondState.CondMet = (is_defined == expect_defined);
4790 }
4791
4792 return false;
4793}
4794
4795
4796
4797bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
4798 DirectiveKind DirKind) {
4801 return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
4802 " .if or an .elseif");
4804
4805 bool LastIgnoreState = false;
4806 if (!TheCondStack.empty())
4807 LastIgnoreState = TheCondStack.back().Ignore;
4808 if (LastIgnoreState || TheCondState.CondMet) {
4809 TheCondState.Ignore = true;
4810 eatToEndOfStatement();
4811 } else {
4812 int64_t ExprValue;
4813 if (parseAbsoluteExpression(ExprValue))
4814 return true;
4815
4816 if (parseEOL())
4817 return true;
4818
4819 switch (DirKind) {
4820 default:
4822 case DK_ELSEIF:
4823 break;
4824 case DK_ELSEIFE:
4825 ExprValue = ExprValue == 0;
4826 break;
4827 }
4828
4829 TheCondState.CondMet = ExprValue;
4831 }
4832
4833 return false;
4834}
4835
4836
4837
4838bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
4841 return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
4842 " if or an elseif");
4844
4845 bool LastIgnoreState = false;
4846 if (!TheCondStack.empty())
4847 LastIgnoreState = TheCondStack.back().Ignore;
4848 if (LastIgnoreState || TheCondState.CondMet) {
4849 TheCondState.Ignore = true;
4850 eatToEndOfStatement();
4851 } else {
4852 std::string Str;
4853 if (parseTextItem(Str)) {
4854 if (ExpectBlank)
4855 return TokError("expected text item parameter for 'elseifb' directive");
4856 return TokError("expected text item parameter for 'elseifnb' directive");
4857 }
4858
4859 if (parseEOL())
4860 return true;
4861
4862 TheCondState.CondMet = ExpectBlank == Str.empty();
4864 }
4865
4866 return false;
4867}
4868
4869
4870
4871
4872bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
4873 bool expect_defined) {
4876 return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
4877 " if or an elseif");
4879
4880 bool LastIgnoreState = false;
4881 if (!TheCondStack.empty())
4882 LastIgnoreState = TheCondStack.back().Ignore;
4883 if (LastIgnoreState || TheCondState.CondMet) {
4884 TheCondState.Ignore = true;
4885 eatToEndOfStatement();
4886 } else {
4887 bool is_defined = false;
4888 MCRegister Reg;
4889 SMLoc StartLoc, EndLoc;
4890 is_defined =
4891 getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
4892 if (!is_defined) {
4893 StringRef Name;
4894 if (check(parseIdentifier(Name),
4895 "expected identifier after 'elseifdef'") ||
4896 parseEOL())
4897 return true;
4898
4899 if (BuiltinSymbolMap.contains(Name.lower())) {
4900 is_defined = true;
4901 } else if (Variables.contains(Name.lower())) {
4902 is_defined = true;
4903 } else {
4905 is_defined = (Sym && !Sym->isUndefined());
4906 }
4907 }
4908
4909 TheCondState.CondMet = (is_defined == expect_defined);
4911 }
4912
4913 return false;
4914}
4915
4916
4917
4918bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
4919 bool CaseInsensitive) {
4922 return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
4923 " if or an elseif");
4925
4926 bool LastIgnoreState = false;
4927 if (!TheCondStack.empty())
4928 LastIgnoreState = TheCondStack.back().Ignore;
4929 if (LastIgnoreState || TheCondState.CondMet) {
4930 TheCondState.Ignore = true;
4931 eatToEndOfStatement();
4932 } else {
4933 std::string String1, String2;
4934
4935 if (parseTextItem(String1)) {
4936 if (ExpectEqual)
4937 return TokError(
4938 "expected text item parameter for 'elseifidn' directive");
4939 return TokError("expected text item parameter for 'elseifdif' directive");
4940 }
4941
4943 if (ExpectEqual)
4944 return TokError(
4945 "expected comma after first string for 'elseifidn' directive");
4946 return TokError(
4947 "expected comma after first string for 'elseifdif' directive");
4948 }
4949 Lex();
4950
4951 if (parseTextItem(String2)) {
4952 if (ExpectEqual)
4953 return TokError(
4954 "expected text item parameter for 'elseifidn' directive");
4955 return TokError("expected text item parameter for 'elseifdif' directive");
4956 }
4957
4958 if (CaseInsensitive)
4960 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4961 else
4962 TheCondState.CondMet = ExpectEqual == (String1 == String2);
4964 }
4965
4966 return false;
4967}
4968
4969
4970
4971bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
4972 if (parseEOL())
4973 return true;
4974
4977 return Error(DirectiveLoc, "Encountered an else that doesn't follow an if"
4978 " or an elseif");
4980 bool LastIgnoreState = false;
4981 if (!TheCondStack.empty())
4982 LastIgnoreState = TheCondStack.back().Ignore;
4983 if (LastIgnoreState || TheCondState.CondMet)
4984 TheCondState.Ignore = true;
4985 else
4986 TheCondState.Ignore = false;
4987
4988 return false;
4989}
4990
4991
4992
4993bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
4994 if (parseEOL())
4995 return true;
4996
4998 Lexer.Lex();
4999
5000 return false;
5001}
5002
5003
5004
5005bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
5006 if (!TheCondStack.empty()) {
5007 if (TheCondStack.back().Ignore) {
5008 eatToEndOfStatement();
5009 return false;
5010 }
5011 }
5012
5013 std::string Message = ".err directive invoked in source file";
5016 Lex();
5017
5018 return Error(DirectiveLoc, Message);
5019}
5020
5021
5022
5023bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
5024 if (!TheCondStack.empty()) {
5025 if (TheCondStack.back().Ignore) {
5026 eatToEndOfStatement();
5027 return false;
5028 }
5029 }
5030
5031 std::string Text;
5032 if (parseTextItem(Text))
5033 return Error(getTok().getLoc(), "missing text item in '.errb' directive");
5034
5035 std::string Message = ".errb directive invoked in source file";
5038 return addErrorSuffix(" in '.errb' directive");
5040 }
5041 Lex();
5042
5043 if (Text.empty() == ExpectBlank)
5044 return Error(DirectiveLoc, Message);
5045 return false;
5046}
5047
5048
5049
5050bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
5051 bool ExpectDefined) {
5052 if (!TheCondStack.empty()) {
5053 if (TheCondStack.back().Ignore) {
5054 eatToEndOfStatement();
5055 return false;
5056 }
5057 }
5058
5059 bool IsDefined = false;
5060 MCRegister Reg;
5061 SMLoc StartLoc, EndLoc;
5062 IsDefined =
5063 getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
5064 if (!IsDefined) {
5065 StringRef Name;
5066 if (check(parseIdentifier(Name), "expected identifier after '.errdef'"))
5067 return true;
5068
5069 if (BuiltinSymbolMap.contains(Name.lower())) {
5070 IsDefined = true;
5071 } else if (Variables.contains(Name.lower())) {
5072 IsDefined = true;
5073 } else {
5075 IsDefined = (Sym && !Sym->isUndefined());
5076 }
5077 }
5078
5079 std::string Message = ".errdef directive invoked in source file";
5082 return addErrorSuffix(" in '.errdef' directive");
5084 }
5085 Lex();
5086
5087 if (IsDefined == ExpectDefined)
5088 return Error(DirectiveLoc, Message);
5089 return false;
5090}
5091
5092
5093
5094bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
5095 bool CaseInsensitive) {
5096 if (!TheCondStack.empty()) {
5097 if (TheCondStack.back().Ignore) {
5098 eatToEndOfStatement();
5099 return false;
5100 }
5101 }
5102
5103 std::string String1, String2;
5104
5105 if (parseTextItem(String1)) {
5106 if (ExpectEqual)
5107 return TokError("expected string parameter for '.erridn' directive");
5108 return TokError("expected string parameter for '.errdif' directive");
5109 }
5110
5112 if (ExpectEqual)
5113 return TokError(
5114 "expected comma after first string for '.erridn' directive");
5115 return TokError(
5116 "expected comma after first string for '.errdif' directive");
5117 }
5118 Lex();
5119
5120 if (parseTextItem(String2)) {
5121 if (ExpectEqual)
5122 return TokError("expected string parameter for '.erridn' directive");
5123 return TokError("expected string parameter for '.errdif' directive");
5124 }
5125
5126 std::string Message;
5127 if (ExpectEqual)
5128 Message = ".erridn directive invoked in source file";
5129 else
5130 Message = ".errdif directive invoked in source file";
5133 return addErrorSuffix(" in '.erridn' directive");
5135 }
5136 Lex();
5137
5138 if (CaseInsensitive)
5140 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
5141 else
5142 TheCondState.CondMet = ExpectEqual == (String1 == String2);
5144
5145 if ((CaseInsensitive &&
5146 ExpectEqual == StringRef(String1).equals_insensitive(String2)) ||
5147 (ExpectEqual == (String1 == String2)))
5148 return Error(DirectiveLoc, Message);
5149 return false;
5150}
5151
5152
5153
5154bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero) {
5155 if (!TheCondStack.empty()) {
5156 if (TheCondStack.back().Ignore) {
5157 eatToEndOfStatement();
5158 return false;
5159 }
5160 }
5161
5162 int64_t ExprValue;
5163 if (parseAbsoluteExpression(ExprValue))
5164 return addErrorSuffix(" in '.erre' directive");
5165
5166 std::string Message = ".erre directive invoked in source file";
5169 return addErrorSuffix(" in '.erre' directive");
5171 }
5172 Lex();
5173
5174 if ((ExprValue == 0) == ExpectZero)
5175 return Error(DirectiveLoc, Message);
5176 return false;
5177}
5178
5179
5180
5181bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5182 if (parseEOL())
5183 return true;
5184
5186 return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
5187 "an .if or .else");
5188 if (!TheCondStack.empty()) {
5189 TheCondState = TheCondStack.back();
5190 TheCondStack.pop_back();
5191 }
5192
5193 return false;
5194}
5195
5196void MasmParser::initializeDirectiveKindMap() {
5197 DirectiveKindMap["="] = DK_ASSIGN;
5198 DirectiveKindMap["equ"] = DK_EQU;
5199 DirectiveKindMap["textequ"] = DK_TEXTEQU;
5200
5201
5202
5203 DirectiveKindMap["byte"] = DK_BYTE;
5204 DirectiveKindMap["sbyte"] = DK_SBYTE;
5205 DirectiveKindMap["word"] = DK_WORD;
5206 DirectiveKindMap["sword"] = DK_SWORD;
5207 DirectiveKindMap["dword"] = DK_DWORD;
5208 DirectiveKindMap["sdword"] = DK_SDWORD;
5209 DirectiveKindMap["fword"] = DK_FWORD;
5210 DirectiveKindMap["qword"] = DK_QWORD;
5211 DirectiveKindMap["sqword"] = DK_SQWORD;
5212 DirectiveKindMap["real4"] = DK_REAL4;
5213 DirectiveKindMap["real8"] = DK_REAL8;
5214 DirectiveKindMap["real10"] = DK_REAL10;
5215 DirectiveKindMap["align"] = DK_ALIGN;
5216 DirectiveKindMap["even"] = DK_EVEN;
5217 DirectiveKindMap["org"] = DK_ORG;
5218 DirectiveKindMap["extern"] = DK_EXTERN;
5219 DirectiveKindMap["extrn"] = DK_EXTERN;
5220 DirectiveKindMap["public"] = DK_PUBLIC;
5221
5222 DirectiveKindMap["comment"] = DK_COMMENT;
5223 DirectiveKindMap["include"] = DK_INCLUDE;
5224 DirectiveKindMap["repeat"] = DK_REPEAT;
5225 DirectiveKindMap["rept"] = DK_REPEAT;
5226 DirectiveKindMap["while"] = DK_WHILE;
5227 DirectiveKindMap["for"] = DK_FOR;
5228 DirectiveKindMap["irp"] = DK_FOR;
5229 DirectiveKindMap["forc"] = DK_FORC;
5230 DirectiveKindMap["irpc"] = DK_FORC;
5231 DirectiveKindMap["if"] = DK_IF;
5232 DirectiveKindMap["ife"] = DK_IFE;
5233 DirectiveKindMap["ifb"] = DK_IFB;
5234 DirectiveKindMap["ifnb"] = DK_IFNB;
5235 DirectiveKindMap["ifdef"] = DK_IFDEF;
5236 DirectiveKindMap["ifndef"] = DK_IFNDEF;
5237 DirectiveKindMap["ifdif"] = DK_IFDIF;
5238 DirectiveKindMap["ifdifi"] = DK_IFDIFI;
5239 DirectiveKindMap["ifidn"] = DK_IFIDN;
5240 DirectiveKindMap["ifidni"] = DK_IFIDNI;
5241 DirectiveKindMap["elseif"] = DK_ELSEIF;
5242 DirectiveKindMap["elseifdef"] = DK_ELSEIFDEF;
5243 DirectiveKindMap["elseifndef"] = DK_ELSEIFNDEF;
5244 DirectiveKindMap["elseifdif"] = DK_ELSEIFDIF;
5245 DirectiveKindMap["elseifidn"] = DK_ELSEIFIDN;
5246 DirectiveKindMap["else"] = DK_ELSE;
5247 DirectiveKindMap["end"] = DK_END;
5248 DirectiveKindMap["endif"] = DK_ENDIF;
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288 DirectiveKindMap["macro"] = DK_MACRO;
5289 DirectiveKindMap["exitm"] = DK_EXITM;
5290 DirectiveKindMap["endm"] = DK_ENDM;
5291 DirectiveKindMap["purge"] = DK_PURGE;
5292 DirectiveKindMap[".err"] = DK_ERR;
5293 DirectiveKindMap[".errb"] = DK_ERRB;
5294 DirectiveKindMap[".errnb"] = DK_ERRNB;
5295 DirectiveKindMap[".errdef"] = DK_ERRDEF;
5296 DirectiveKindMap[".errndef"] = DK_ERRNDEF;
5297 DirectiveKindMap[".errdif"] = DK_ERRDIF;
5298 DirectiveKindMap[".errdifi"] = DK_ERRDIFI;
5299 DirectiveKindMap[".erridn"] = DK_ERRIDN;
5300 DirectiveKindMap[".erridni"] = DK_ERRIDNI;
5301 DirectiveKindMap[".erre"] = DK_ERRE;
5302 DirectiveKindMap[".errnz"] = DK_ERRNZ;
5303 DirectiveKindMap[".pushframe"] = DK_PUSHFRAME;
5304 DirectiveKindMap[".pushreg"] = DK_PUSHREG;
5305 DirectiveKindMap[".savereg"] = DK_SAVEREG;
5306 DirectiveKindMap[".savexmm128"] = DK_SAVEXMM128;
5307 DirectiveKindMap[".setframe"] = DK_SETFRAME;
5308 DirectiveKindMap[".radix"] = DK_RADIX;
5309 DirectiveKindMap["db"] = DK_DB;
5310 DirectiveKindMap["dd"] = DK_DD;
5311 DirectiveKindMap["df"] = DK_DF;
5312 DirectiveKindMap["dq"] = DK_DQ;
5313 DirectiveKindMap["dw"] = DK_DW;
5314 DirectiveKindMap["echo"] = DK_ECHO;
5315 DirectiveKindMap["struc"] = DK_STRUCT;
5316 DirectiveKindMap["struct"] = DK_STRUCT;
5317 DirectiveKindMap["union"] = DK_UNION;
5318 DirectiveKindMap["ends"] = DK_ENDS;
5319}
5320
5321bool MasmParser::isMacroLikeDirective() {
5323 bool IsMacroLike = StringSwitch(getTok().getIdentifier())
5324 .CasesLower({"repeat", "rept"}, true)
5325 .CaseLower("while", true)
5326 .CasesLower({"for", "irp"}, true)
5327 .CasesLower({"forc", "irpc"}, true)
5329 if (IsMacroLike)
5330 return true;
5331 }
5333 peekTok().getIdentifier().equals_insensitive("macro"))
5334 return true;
5335
5336 return false;
5337}
5338
5339MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5340 AsmToken EndToken, StartToken = getTok();
5341
5342 unsigned NestLevel = 0;
5343 while (true) {
5344
5346 printError(DirectiveLoc, "no matching 'endm' in definition");
5347 return nullptr;
5348 }
5349
5350 if (isMacroLikeDirective())
5351 ++NestLevel;
5352
5353
5355 getTok().getIdentifier().equals_insensitive("endm")) {
5356 if (NestLevel == 0) {
5357 EndToken = getTok();
5358 Lex();
5360 printError(getTok().getLoc(), "unexpected token in 'endm' directive");
5361 return nullptr;
5362 }
5363 break;
5364 }
5365 --NestLevel;
5366 }
5367
5368
5369 eatToEndOfStatement();
5370 }
5371
5374 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5375
5376
5378 return &MacroLikeBodies.back();
5379}
5380
5381bool MasmParser::expandStatement(SMLoc Loc) {
5383 SMLoc EndLoc = getTok().getLoc();
5384
5387
5388 StringMapstd::string BuiltinValues;
5389 for (const auto &S : BuiltinSymbolMap) {
5390 const BuiltinSymbol &Sym = S.getValue();
5391 if (std::optionalstd::string Text = evaluateBuiltinTextMacro(Sym, Loc)) {
5392 BuiltinValues[S.getKey().lower()] = std::move(*Text);
5393 }
5394 }
5395 for (const auto &B : BuiltinValues) {
5396 MCAsmMacroParameter P;
5397 MCAsmMacroArgument A;
5399 P.Required = true;
5401
5404 }
5405
5406 for (const auto &V : Variables) {
5407 const Variable &Var = V.getValue();
5408 if (Var.IsText) {
5409 MCAsmMacroParameter P;
5410 MCAsmMacroArgument A;
5411 P.Name = Var.Name;
5412 P.Required = true;
5414
5417 }
5418 }
5419 MacroLikeBodies.emplace_back(StringRef(), Body, Parameters);
5420 MCAsmMacro M = MacroLikeBodies.back();
5421
5422
5423 SmallString<80> Buf;
5424 raw_svector_ostream OS(Buf);
5425 if (expandMacro(OS, M.Body, M.Parameters, Arguments, M.Locals, EndLoc))
5426 return true;
5427 std::unique_ptr Expansion =
5429
5430
5433 EndStatementAtEOFStack.push_back(false);
5434 Lex();
5435 return false;
5436}
5437
5438void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5439 raw_svector_ostream &OS) {
5440 instantiateMacroLikeBody(M, DirectiveLoc, getTok().getLoc(), OS);
5441}
5442void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5443 SMLoc ExitLoc,
5444 raw_svector_ostream &OS) {
5445 OS << "endm\n";
5446
5447 std::unique_ptr Instantiation =
5449
5450
5451
5452 MacroInstantiation *MI = new MacroInstantiation{DirectiveLoc, CurBuffer,
5453 ExitLoc, TheCondStack.size()};
5454 ActiveMacros.push_back(MI);
5455
5456
5459 EndStatementAtEOFStack.push_back(true);
5460 Lex();
5461}
5462
5463
5464
5465
5466
5467bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) {
5468 const MCExpr *CountExpr;
5469 SMLoc CountLoc = getTok().getLoc();
5470 if (parseExpression(CountExpr))
5471 return true;
5472
5474 if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
5475 return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
5476 }
5477
5478 if (check(Count < 0, CountLoc, "Count is negative") || parseEOL())
5479 return true;
5480
5481
5482 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5483 if (!M)
5484 return true;
5485
5486
5487
5488 SmallString<256> Buf;
5489 raw_svector_ostream OS(Buf);
5490 while (Count--) {
5491 if (expandMacro(OS, M->Body, {}, {}, M->Locals, getTok().getLoc()))
5492 return true;
5493 }
5494 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5495
5496 return false;
5497}
5498
5499
5500
5501
5502
5503bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) {
5504 const MCExpr *CondExpr;
5505 SMLoc CondLoc = getTok().getLoc();
5506 if (parseExpression(CondExpr))
5507 return true;
5508
5509
5510 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5511 if (!M)
5512 return true;
5513
5514
5515
5516 SmallString<256> Buf;
5517 raw_svector_ostream OS(Buf);
5518 int64_t Condition;
5519 if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr()))
5520 return Error(CondLoc, "expected absolute expression in 'while' directive");
5521 if (Condition) {
5522
5523
5524 if (expandMacro(OS, M->Body, {}, {}, M->Locals, getTok().getLoc()))
5525 return true;
5526 instantiateMacroLikeBody(M, DirectiveLoc, DirectiveLoc, OS);
5527 }
5528
5529 return false;
5530}
5531
5532
5533
5534
5535
5536bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
5538 MCAsmMacroArguments A;
5539 if (check(parseIdentifier(Parameter.Name),
5540 "expected identifier in '" + Dir + "' directive"))
5541 return true;
5542
5543
5546
5547 SMLoc ParamLoc;
5548
5549 ParamLoc = Lexer.getLoc();
5550 if (parseMacroArgument(nullptr, Parameter.Value))
5551 return true;
5552 } else {
5553 SMLoc QualLoc;
5555
5556 QualLoc = Lexer.getLoc();
5557 if (parseIdentifier(Qualifier))
5558 return Error(QualLoc, "missing parameter qualifier for "
5559 "'" +
5560 Parameter.Name + "' in '" + Dir +
5561 "' directive");
5562
5563 if (Qualifier.equals_insensitive("req"))
5565 else
5566 return Error(QualLoc,
5567 Qualifier + " is not a valid parameter qualifier for '" +
5568 Parameter.Name + "' in '" + Dir + "' directive");
5569 }
5570 }
5571
5573 "expected comma in '" + Dir + "' directive") ||
5575 "values in '" + Dir +
5576 "' directive must be enclosed in angle brackets"))
5577 return true;
5578
5579 while (true) {
5580 A.emplace_back();
5581 if (parseMacroArgument(&Parameter, A.back(), AsmToken::Greater))
5582 return addErrorSuffix(" in arguments for '" + Dir + "' directive");
5583
5584
5586 break;
5588 }
5589
5591 "values in '" + Dir +
5592 "' directive must be enclosed in angle brackets") ||
5593 parseEOL())
5594 return true;
5595
5596
5597 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5598 if (!M)
5599 return true;
5600
5601
5602
5603 SmallString<256> Buf;
5604 raw_svector_ostream OS(Buf);
5605
5606 for (const MCAsmMacroArgument &Arg : A) {
5607 if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc()))
5608 return true;
5609 }
5610
5611 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5612
5613 return false;
5614}
5615
5616
5617
5618
5619
5620bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
5622
5624 if (check(parseIdentifier(Parameter.Name),
5625 "expected identifier in '" + Directive + "' directive") ||
5627 "expected comma in '" + Directive + "' directive"))
5628 return true;
5629 if (parseAngleBracketString(Argument)) {
5630
5631
5632
5635 Argument += getTok().getString();
5636 size_t End = 0;
5637 for (; End < Argument.size(); ++End) {
5638 if (isSpace(Argument[End]))
5639 break;
5640 }
5642 }
5643 if (parseEOL())
5644 return true;
5645
5646
5647 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5648 if (!M)
5649 return true;
5650
5651
5652
5653 SmallString<256> Buf;
5654 raw_svector_ostream OS(Buf);
5655
5656 StringRef Values(Argument);
5657 for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
5658 MCAsmMacroArgument Arg;
5660
5661 if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc()))
5662 return true;
5663 }
5664
5665 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5666
5667 return false;
5668}
5669
5670bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
5671 size_t Len) {
5672 const MCExpr *Value;
5673 SMLoc ExprLoc = getLexer().getLoc();
5674 if (parseExpression(Value))
5675 return true;
5677 if (!MCE)
5678 return Error(ExprLoc, "unexpected expression in _emit");
5679 uint64_t IntValue = MCE->getValue();
5681 return Error(ExprLoc, "literal value out of range for directive");
5682
5683 Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
5684 return false;
5685}
5686
5687bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
5688 const MCExpr *Value;
5689 SMLoc ExprLoc = getLexer().getLoc();
5690 if (parseExpression(Value))
5691 return true;
5693 if (!MCE)
5694 return Error(ExprLoc, "unexpected expression in align");
5695 uint64_t IntValue = MCE->getValue();
5697 return Error(ExprLoc, "literal value not a power of two greater then zero");
5698
5700 return false;
5701}
5702
5703bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
5704 const SMLoc Loc = getLexer().getLoc();
5706 StringRef RadixString = StringRef(RadixStringRaw).trim();
5707 unsigned Radix;
5709 return Error(Loc,
5710 "radix must be a decimal number in the range 2 to 16; was " +
5711 RadixString);
5712 }
5713 if (Radix < 2 || Radix > 16)
5714 return Error(Loc, "radix must be in the range 2 to 16; was " +
5715 std::to_string(Radix));
5716 getLexer().setMasmDefaultRadix(Radix);
5717 return false;
5718}
5719
5720
5721
5722bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) {
5725 if (!StringRef(Message).ends_with("\n"))
5727 return false;
5728}
5729
5730
5731
5735 return -1;
5737 return 1;
5738
5739
5740
5741
5742
5745 return -1;
5746
5749 return 1;
5751}
5752
5753bool MasmParser::defineMacro(StringRef Name, StringRef Value) {
5755 if (Var.Name.empty()) {
5756 Var.Name = Name;
5757 } else if (Var.Redefinable == Variable::NOT_REDEFINABLE) {
5758 return Error(SMLoc(), "invalid variable redefinition");
5759 } else if (Var.Redefinable == Variable::WARN_ON_REDEFINITION &&
5760 Warning(SMLoc(), "redefining '" + Name +
5761 "', already defined on the command line")) {
5762 return true;
5763 }
5764 Var.Redefinable = Variable::WARN_ON_REDEFINITION;
5765 Var.IsText = true;
5766 Var.TextValue = Value.str();
5767 return false;
5768}
5769
5770bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info) const {
5771 const std::pair<StringRef, StringRef> BaseMember = Name.split('.');
5772 const StringRef Base = BaseMember.first, Member = BaseMember.second;
5773 return lookUpField(Base, Member, Info);
5774}
5775
5776bool MasmParser::lookUpField(StringRef Base, StringRef Member,
5777 AsmFieldInfo &Info) const {
5778 if (Base.empty())
5779 return true;
5780
5781 AsmFieldInfo BaseInfo;
5782 if (Base.contains('.') && !lookUpField(Base, BaseInfo))
5784
5785 auto StructIt = Structs.find(Base.lower());
5786 auto TypeIt = KnownType.find(Base.lower());
5787 if (TypeIt != KnownType.end()) {
5788 StructIt = Structs.find(TypeIt->second.Name.lower());
5789 }
5790 if (StructIt != Structs.end())
5791 return lookUpField(StructIt->second, Member, Info);
5792
5793 return true;
5794}
5795
5796bool MasmParser::lookUpField(const StructInfo &Structure, StringRef Member,
5797 AsmFieldInfo &Info) const {
5798 if (Member.empty()) {
5799 Info.Type.Name = Structure.Name;
5800 Info.Type.Size = Structure.Size;
5801 Info.Type.ElementSize = Structure.Size;
5802 Info.Type.Length = 1;
5803 return false;
5804 }
5805
5806 std::pair<StringRef, StringRef> Split = Member.split('.');
5807 const StringRef FieldName = Split.first, FieldMember = Split.second;
5808
5809 auto StructIt = Structs.find(FieldName.lower());
5810 if (StructIt != Structs.end())
5811 return lookUpField(StructIt->second, FieldMember, Info);
5812
5813 auto FieldIt = Structure.FieldsByName.find(FieldName.lower());
5814 if (FieldIt == Structure.FieldsByName.end())
5815 return true;
5816
5817 const FieldInfo &Field = Structure.Fields[FieldIt->second];
5818 if (FieldMember.empty()) {
5821 Info.Type.ElementSize = Field.Type;
5822 Info.Type.Length = Field.LengthOf;
5823 if (Field.Contents.FT == FT_STRUCT)
5824 Info.Type.Name = Field.Contents.StructInfo.Structure.Name;
5825 else
5826 Info.Type.Name = "";
5827 return false;
5828 }
5829
5830 if (Field.Contents.FT != FT_STRUCT)
5831 return true;
5832 const StructFieldInfo &StructInfo = Field.Contents.StructInfo;
5833
5834 if (lookUpField(StructInfo.Structure, FieldMember, Info))
5835 return true;
5836
5838 return false;
5839}
5840
5841bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info) const {
5842 unsigned Size = StringSwitch(Name)
5843 .CasesLower({"byte", "db", "sbyte"}, 1)
5844 .CasesLower({"word", "dw", "sword"}, 2)
5845 .CasesLower({"dword", "dd", "sdword"}, 4)
5846 .CasesLower({"fword", "df"}, 6)
5847 .CasesLower({"qword", "dq", "sqword"}, 8)
5848 .CaseLower("real4", 4)
5849 .CaseLower("real8", 8)
5850 .CaseLower("real10", 10)
5851 .Default(0);
5855 Info.Length = 1;
5857 return false;
5858 }
5859
5860 auto StructIt = Structs.find(Name.lower());
5861 if (StructIt != Structs.end()) {
5862 const StructInfo &Structure = StructIt->second;
5864 Info.ElementSize = Structure.Size;
5865 Info.Length = 1;
5866 Info.Size = Structure.Size;
5867 return false;
5868 }
5869
5870 return true;
5871}
5872
5873bool MasmParser::parseMSInlineAsm(
5874 std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs,
5875 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5876 SmallVectorImplstd::string &Constraints,
5877 SmallVectorImplstd::string &Clobbers, const MCInstrInfo *MII,
5878 MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
5879 SmallVector<void *, 4> InputDecls;
5880 SmallVector<void *, 4> OutputDecls;
5883 SmallVector<std::string, 4> InputConstraints;
5884 SmallVector<std::string, 4> OutputConstraints;
5886
5888
5889
5890 Lex();
5891
5892
5893 unsigned InputIdx = 0;
5894 unsigned OutputIdx = 0;
5896
5897 if (parseCurlyBlockScope(AsmStrRewrites))
5898 continue;
5899
5900 ParseStatementInfo Info(&AsmStrRewrites);
5901 bool StatementErr = parseStatement(Info, &SI);
5902
5903 if (StatementErr || Info.ParseError) {
5904
5905 printPendingErrors();
5906 return true;
5907 }
5908
5909
5910 assert(!hasPendingError() && "unexpected error from parseStatement");
5911
5912 if (Info.Opcode == ~0U)
5913 continue;
5914
5915 const MCInstrDesc &Desc = MII->get(Info.Opcode);
5916
5917
5918 for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
5919 MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
5920
5921
5923 !getTargetParser().omitRegisterFromClobberLists(Operand.getReg())) {
5924 unsigned NumDefs = Desc.getNumDefs();
5925
5928 continue;
5929 }
5930
5931
5932 StringRef SymName = Operand.getSymName();
5933 if (SymName.empty())
5934 continue;
5935
5936 void *OpDecl = Operand.getOpDecl();
5937 if (!OpDecl)
5938 continue;
5939
5941 if (Operand.isImm()) {
5942
5944 Constraint = "r";
5945 else
5946 Constraint = "i";
5947 }
5948
5949 bool isOutput = (i == 1) && Desc.mayStore();
5951 if (isOutput) {
5952 ++InputIdx;
5955 OutputConstraints.push_back(("=" + Constraint).str());
5957 } else {
5960 InputConstraints.push_back(Constraint.str());
5961 if (Desc.operands()[i - 1].isBranchTarget())
5963 else
5965 }
5966 }
5967
5968
5970 }
5971
5972
5973 NumOutputs = OutputDecls.size();
5974 NumInputs = InputDecls.size();
5975
5976
5979 Clobbers.assign(ClobberRegs.size(), std::string());
5980 for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
5981 raw_string_ostream OS(Clobbers[I]);
5983 }
5984
5985
5986 if (NumOutputs || NumInputs) {
5987 unsigned NumExprs = NumOutputs + NumInputs;
5988 OpDecls.resize(NumExprs);
5989 Constraints.resize(NumExprs);
5990 for (unsigned i = 0; i < NumOutputs; ++i) {
5991 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
5992 Constraints[i] = OutputConstraints[i];
5993 }
5994 for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
5995 OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
5996 Constraints[j] = InputConstraints[i];
5997 }
5998 }
5999
6000
6001 std::string AsmStringIR;
6002 raw_string_ostream OS(AsmStringIR);
6003 StringRef ASMString =
6005 const char *AsmStart = ASMString.begin();
6006 const char *AsmEnd = ASMString.end();
6008 for (auto I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) {
6009 const AsmRewrite &AR = *I;
6010
6011 if (AR.Done)
6012 continue;
6014
6016 assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
6017
6018
6019 if (unsigned Len = Loc - AsmStart)
6020 OS << StringRef(AsmStart, Len);
6021
6022
6024 AsmStart = Loc + AR.Len;
6025 continue;
6026 }
6027
6028 unsigned AdditionalSkip = 0;
6029
6030 switch (Kind) {
6031 default:
6032 break;
6036 OS << "[";
6046 OS << " + ";
6047
6050 size_t OffsetLen = OffsetName.size();
6051 auto rewrite_it = std::find_if(
6052 I, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
6053 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6054 (FusingAR.Kind == AOK_Input ||
6055 FusingAR.Kind == AOK_CallInput);
6056 });
6057 if (rewrite_it == AsmStrRewrites.end()) {
6058 OS << "offset " << OffsetName;
6060 OS << "${" << InputIdx++ << ":P}";
6061 rewrite_it->Done = true;
6062 } else {
6063 OS << '$' << InputIdx++;
6064 rewrite_it->Done = true;
6065 }
6066 }
6070 OS << "]";
6071 break;
6074 break;
6076 OS << '$' << InputIdx++;
6077 break;
6079 OS << "${" << InputIdx++ << ":P}";
6080 break;
6082 OS << '$' << OutputIdx++;
6083 break;
6085 switch (AR.Val) {
6086 default: break;
6087 case 8: OS << "byte ptr "; break;
6088 case 16: OS << "word ptr "; break;
6089 case 32: OS << "dword ptr "; break;
6090 case 64: OS << "qword ptr "; break;
6091 case 80: OS << "xword ptr "; break;
6092 case 128: OS << "xmmword ptr "; break;
6093 case 256: OS << "ymmword ptr "; break;
6094 }
6095 break;
6097 OS << ".byte";
6098 break;
6100
6101
6102 OS << ".align";
6103 if (getContext().getAsmInfo()->getAlignmentIsInBytes())
6104 break;
6105
6106
6107
6108 unsigned Val = AR.Val;
6109 OS << ' ' << Val;
6110 assert(Val < 10 && "Expected alignment less then 2^10.");
6111 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6112 break;
6113 }
6115 OS << ".even";
6116 break;
6118 OS << "\n\t";
6119 break;
6120 }
6121
6122
6123 AsmStart = Loc + AR.Len + AdditionalSkip;
6124 }
6125
6126
6127 if (AsmStart != AsmEnd)
6128 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6129
6130 AsmString = OS.str();
6131 return false;
6132}
6133
6134void MasmParser::initializeBuiltinSymbolMaps() {
6135
6136 BuiltinSymbolMap["@version"] = BI_VERSION;
6137 BuiltinSymbolMap["@line"] = BI_LINE;
6138
6139
6140 BuiltinSymbolMap["@date"] = BI_DATE;
6141 BuiltinSymbolMap["@time"] = BI_TIME;
6142 BuiltinSymbolMap["@filecur"] = BI_FILECUR;
6143 BuiltinSymbolMap["@filename"] = BI_FILENAME;
6144 BuiltinSymbolMap["@curseg"] = BI_CURSEG;
6145
6146
6147 BuiltinFunctionMap["@catstr"] = BI_CATSTR;
6148
6149
6150 if (getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165 }
6166}
6167
6168const MCExpr *MasmParser::evaluateBuiltinValue(BuiltinSymbol Symbol,
6169 SMLoc StartLoc) {
6170 switch (Symbol) {
6171 default:
6172 return nullptr;
6173 case BI_VERSION:
6174
6176 case BI_LINE: {
6177 int64_t Line;
6178 if (ActiveMacros.empty())
6180 else
6182 ActiveMacros.front()->ExitBuffer);
6184 }
6185 }
6187}
6188
6189std::optionalstd::string
6190MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
6191 switch (Symbol) {
6192 default:
6193 return {};
6194 case BI_DATE: {
6195
6196 char TmpBuffer[sizeof("mm/dd/yy")];
6197 const size_t Len = strftime(TmpBuffer, sizeof(TmpBuffer), "%D", &TM);
6198 return std::string(TmpBuffer, Len);
6199 }
6200 case BI_TIME: {
6201
6202 char TmpBuffer[sizeof("hh:mm:ss")];
6203 const size_t Len = strftime(TmpBuffer, sizeof(TmpBuffer), "%T", &TM);
6204 return std::string(TmpBuffer, Len);
6205 }
6206 case BI_FILECUR:
6209 ActiveMacros.empty() ? CurBuffer : ActiveMacros.front()->ExitBuffer)
6212 case BI_FILENAME:
6216 case BI_CURSEG:
6217 return getStreamer().getCurrentSectionOnly()->getName().str();
6218 }
6220}
6221
6222bool MasmParser::evaluateBuiltinMacroFunction(BuiltinFunction Function,
6223 StringRef Name,
6224 std::string &Res) {
6225 if (parseToken(AsmToken::LParen, "invoking macro function '" + Name +
6226 "' requires arguments in parentheses")) {
6227 return true;
6228 }
6229
6231 switch (Function) {
6232 default:
6233 return true;
6234 case BI_CATSTR:
6235 break;
6236 }
6237 MCAsmMacro M(Name, "", P, {}, true);
6238
6239 MCAsmMacroArguments A;
6240 if (parseMacroArguments(&M, A, AsmToken::RParen) || parseRParen()) {
6241 return true;
6242 }
6243
6244 switch (Function) {
6245 default:
6247 case BI_CATSTR: {
6248 for (const MCAsmMacroArgument &Arg : A) {
6249 for (const AsmToken &Tok : Arg) {
6252 } else {
6254 }
6255 }
6256 }
6257 return false;
6258 }
6259 }
6261 return true;
6262}
6263
6264
6267 struct tm TM, unsigned CB) {
6268 return new MasmParser(SM, C, Out, MAI, TM, CB);
6269}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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 bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc)
This function checks if the next token is type or arithmetic.
static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI, AsmToken::TokenKind K, MCBinaryExpr::Opcode &Kind, bool ShouldUseLogicalShr)
static std::string angleBracketString(StringRef AltMacroStr)
creating a string without the escape characters '!'.
static int rewritesSort(const AsmRewrite *AsmRewriteA, const AsmRewrite *AsmRewriteB)
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
Value * getPointer(Value *Ptr)
const std::string FatArchTraits< MachO::fat_arch >::StructName
static bool isMacroParameterChar(char C)
Definition MasmParser.cpp:2441
@ DEFAULT_ADDRSPACE
Definition MasmParser.cpp:968
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
OptimizedStructLayoutField Field
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallString class.
This file defines the SmallVector class.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
unsigned getBitWidth() const
Return the number of bits in the APInt.
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.
ConditionalAssemblyType TheCond
LLVM_ABI SMLoc getLoc() const
bool isNot(TokenKind K) const
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
StringRef getStringContents() const
Get the contents of a string token (without quotes).
bool is(TokenKind K) const
LLVM_ABI SMLoc getEndLoc() const
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
This class is intended to be used as a base class for asm properties and features specific to the tar...
bool preserveAsmComments() const
Return true if assembly (inline or otherwise) should be parsed.
StringRef getPrivateLabelPrefix() const
bool shouldUseLogicalShr() const
virtual bool useCodeAlign(const MCSection &Sec) const
Generic assembler parser interface, for use by target specific assembly parsers.
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
@ AShr
Arithmetic shift right.
@ LShr
Logical shift right.
@ GTE
Signed greater than or equal comparison (result is either 0 or some target-specific non-zero value).
@ GT
Signed greater than comparison (result is either 0 or some target-specific non-zero value)
@ Xor
Bitwise exclusive or.
@ LT
Signed less than comparison (result is either 0 or some target-specific non-zero value).
@ LTE
Signed less than or equal comparison (result is either 0 or some target-specific non-zero value).
@ NE
Inequality comparison.
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
LLVM_ABI MCSymbol * createDirectionalLocalSymbol(unsigned LocalLabelVal)
Create the definition of a directional local symbol for numbered label (used for "1:" definitions).
const MCAsmInfo * getAsmInfo() const
virtual void printRegName(raw_ostream &OS, MCRegister Reg)
Print the assembler register name.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
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?
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?
unsigned getMCOperandNum()
StringRef getConstraint()
virtual void * getOpDecl()
Streaming machine code generation interface.
virtual void addBlankLine()
Emit a blank line to a .s file to pretty it up.
virtual void initSections(bool NoExecStack, const MCSubtargetInfo &STI)
Create the default sections and set the initial one.
virtual void addExplicitComment(const Twine &T)
Add explicit comment T.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
void finish(SMLoc EndLoc=SMLoc())
Finish emission of machine code.
const MCSymbol & getSymbol() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
bool isUndefined() const
isUndefined - Check if this symbol undefined (i.e., implicitly defined).
StringRef getName() const
getName - Get the symbol name.
bool isVariable() const
isVariable - Check if this is a variable symbol.
LLVM_ABI void setVariableValue(const MCExpr *Value)
void setRedefinable(bool Value)
Mark this symbol as redefinable.
void redefineIfPossible()
Prepare this symbol to be redefined.
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
static const MCUnaryExpr * createLNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createPlus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createMinus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
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
constexpr bool isFailure() const
constexpr bool isSuccess() const
LLVM_ABI void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true, bool ShowLocation=true) const
SourceMgr::DiagKind getKind() const
StringRef getLineContents() const
StringRef getMessage() const
ArrayRef< std::pair< unsigned, unsigned > > getRanges() const
const SourceMgr * getSourceMgr() const
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
constexpr const char * getPointer() const
constexpr bool isValid() const
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
unsigned getMainFileID() const
const MemoryBuffer * getMemoryBuffer(unsigned i) const
LLVM_ABI 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.
SMLoc getParentIncludeLoc(unsigned i) const
LLVM_ABI void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const
Prints the names of included files and the line of the file they were included from.
LLVM_ABI unsigned FindBufferContainingLoc(SMLoc Loc) const
Return the ID of the buffer containing the specified location.
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
void setDiagHandler(DiagHandlerTy DH, void *Ctx=nullptr)
Specify a diagnostic handler to be invoked every time PrintMessage is called.
LLVM_ABI 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.
unsigned FindLineNumber(SMLoc Loc, unsigned BufferID=0) const
Find the line number for the specified location in the specified file.
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
iterator find(StringRef Key)
bool contains(StringRef Key) const
contains - Return true if the element is in the map, false otherwise.
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
ValueTy lookup(StringRef Key) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
StringMapIterBase< ValueTy, true > const_iterator
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
StringRef - Represent a constant reference to a string, i.e.
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
std::string str() const
str - Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
LLVM_ABI std::string upper() const
Convert the given ASCII string to uppercase.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
LLVM_ABI std::string lower() const
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
StringRef str() const
Return a StringRef for the vector contents.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
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.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI SimpleSymbol parseSymbol(StringRef SymName)
Get symbol classification by parsing the name of a symbol.
std::variant< std::monostate, DecisionParameters, BranchParameters > Parameters
The type of MC/DC-specific parameters.
@ Parameter
An inlay hint that is for a parameter.
Context & getContext() const
LLVM_ABI Instruction & front() const
LLVM_ABI StringRef stem(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get stem.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
FunctionAddr VTableAddr Value
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.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
LLVM_ABI 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.
LLVM_ABI MCAsmParser * createMCMasmParser(SourceMgr &, MCContext &, MCStreamer &, const MCAsmInfo &, struct tm, unsigned CB=0)
Create an MCAsmParser instance for parsing Microsoft MASM-style assembly.
Definition MasmParser.cpp:6265
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
std::vector< MCAsmMacroParameter > MCAsmMacroParameters
auto unique(Range &&R, Predicate P)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto dyn_cast_or_null(const Y &Val)
cl::opt< unsigned > AsmMacroMaxNestingDepth
Definition MasmParser.cpp:964
const char AsmRewritePrecedence[]
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool isAlnum(char C)
Checks whether character C is either a decimal digit or an uppercase or lowercase letter as classifie...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, bool Upper=false)
format_hex_no_prefix - Output N as a fixed width hexadecimal.
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
bool isSpace(char C)
Checks whether character C is whitespace in the "C" locale.
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
@ MCSA_Global
.type _foo, @gnu_unique_object
@ MCSA_Extern
.extern (XCOFF)
std::vector< AsmToken > Value
uint64_t Offset
The offset of this field in the final layout.