LLVM 22.0.0git
MasmParser.cpp
Go to the documentation of this file.
1//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This class implements the parser for assembly files.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/ADT/APFloat.h"
14#include "llvm/ADT/APInt.h"
15#include "llvm/ADT/ArrayRef.h"
16#include "llvm/ADT/BitVector.h"
17#include "llvm/ADT/STLExtras.h"
21#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
24#include "llvm/ADT/Twine.h"
25#include "llvm/MC/MCAsmInfo.h"
26#include "llvm/MC/MCCodeView.h"
27#include "llvm/MC/MCContext.h"
29#include "llvm/MC/MCExpr.h"
31#include "llvm/MC/MCInstrDesc.h"
32#include "llvm/MC/MCInstrInfo.h"
39#include "llvm/MC/MCSection.h"
40#include "llvm/MC/MCStreamer.h"
47#include "llvm/Support/Format.h"
48#include "llvm/Support/MD5.h"
51#include "llvm/Support/Path.h"
52#include "llvm/Support/SMLoc.h"
55#include <algorithm>
56#include <cassert>
57#include <climits>
58#include <cstddef>
59#include <cstdint>
60#include <ctime>
61#include <deque>
62#include <memory>
63#include <optional>
64#include <sstream>
65#include <string>
66#include <tuple>
67#include <utility>
68#include <vector>
69
70using namespace llvm;
71
72namespace {
73
74/// Helper types for tracking macro definitions.
75typedef std::vector<AsmToken> MCAsmMacroArgument;
76typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
77
78/// Helper class for storing information about an active macro instantiation.
79struct MacroInstantiation {
80 /// The location of the instantiation.
81 SMLoc InstantiationLoc;
82
83 /// The buffer where parsing should resume upon instantiation completion.
84 unsigned ExitBuffer;
85
86 /// The location where parsing should resume upon instantiation completion.
87 SMLoc ExitLoc;
88
89 /// The depth of TheCondStack at the start of the instantiation.
90 size_t CondStackDepth;
91};
92
93struct ParseStatementInfo {
94 /// The parsed operands from the last parsed statement.
96
97 /// The opcode from the last parsed instruction.
98 unsigned Opcode = ~0U;
99
100 /// Was there an error parsing the inline assembly?
101 bool ParseError = false;
102
103 /// The value associated with a macro exit.
104 std::optional<std::string> ExitValue;
105
106 SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
107
108 ParseStatementInfo() = delete;
109 ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
110 : AsmRewrites(rewrites) {}
111};
112
113enum FieldType {
114 FT_INTEGRAL, // Initializer: integer expression, stored as an MCExpr.
115 FT_REAL, // Initializer: real number, stored as an APInt.
116 FT_STRUCT // Initializer: struct initializer, stored recursively.
117};
118
119struct FieldInfo;
120struct StructInfo {
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<FieldInfo> 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// FIXME: This should probably use a class hierarchy, raw pointers between the
139// objects, and dynamic type resolution instead of a union. On the other hand,
140// ownership then becomes much more complicated; the obvious thing would be to
141// use BumpPtrAllocator, but the lack of a destructor makes that messy.
142
143struct StructInitializer;
144struct IntFieldInfo {
146
147 IntFieldInfo() = default;
148 IntFieldInfo(const SmallVector<const MCExpr *, 1> &V) { Values = V; }
149 IntFieldInfo(SmallVector<const MCExpr *, 1> &&V) { Values = std::move(V); }
150};
151struct RealFieldInfo {
152 SmallVector<APInt, 1> AsIntValues;
153
154 RealFieldInfo() = default;
155 RealFieldInfo(const SmallVector<APInt, 1> &V) { AsIntValues = V; }
156 RealFieldInfo(SmallVector<APInt, 1> &&V) { AsIntValues = std::move(V); }
157};
158struct StructFieldInfo {
159 std::vector<StructInitializer> Initializers;
160 StructInfo Structure;
161
162 StructFieldInfo() = default;
163 StructFieldInfo(std::vector<StructInitializer> 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
178 FieldInitializer(SmallVector<const MCExpr *, 1> &&Values);
179 FieldInitializer(SmallVector<APInt, 1> &&AsIntValues);
180 FieldInitializer(std::vector<StructInitializer> &&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<FieldInitializer> FieldInitializers;
192};
193
194struct FieldInfo {
195 // Offset of the field within the containing STRUCT.
196 unsigned Offset = 0;
197
198 // Total size of the field (= LengthOf * Type).
199 unsigned SizeOf = 0;
200
201 // Number of elements in the field (1 if scalar, >1 if an array).
202 unsigned LengthOf = 0;
203
204 // Size of a single entry in this field, in bytes ("type" in MASM standards).
205 unsigned Type = 0;
206
207 FieldInitializer Contents;
208
209 FieldInfo(FieldType FT) : Contents(FT) {}
210};
211
212StructFieldInfo::StructFieldInfo(std::vector<StructInitializer> V,
213 StructInfo S) {
214 Initializers = std::move(V);
215 Structure = S;
216}
217
218StructInfo::StructInfo(StringRef StructName, bool Union,
219 unsigned AlignmentValue)
220 : Name(StructName), IsUnion(Union), Alignment(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();
228 Field.Offset =
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);
234 return Field;
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
265FieldInitializer::FieldInitializer(SmallVector<const MCExpr *, 1> &&Values)
266 : FT(FT_INTEGRAL) {
267 new (&IntInfo) IntFieldInfo(std::move(Values));
268}
269
270FieldInitializer::FieldInitializer(SmallVector<APInt, 1> &&AsIntValues)
271 : FT(FT_REAL) {
272 new (&RealInfo) RealFieldInfo(std::move(AsIntValues));
273}
274
275FieldInitializer::FieldInitializer(
276 std::vector<StructInitializer> &&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/// The concrete assembly parser instance.
371// Note that this is a full MCAsmParser, not an MCAsmParserExtension!
372// It's a peer of AsmParser, not of COFFAsmParser, WasmAsmParser, etc.
373class MasmParser : public MCAsmParser {
374private:
375 SourceMgr::DiagHandlerTy SavedDiagHandler;
376 void *SavedDiagContext;
377 std::unique_ptr<MCAsmParserExtension> PlatformParser;
378
379 /// This is the current buffer index we're lexing from as managed by the
380 /// SourceMgr object.
381 unsigned CurBuffer;
382
383 /// time of assembly
384 struct tm TM;
385
386 BitVector EndStatementAtEOFStack;
387
388 AsmCond TheCondState;
389 std::vector<AsmCond> TheCondStack;
390
391 /// maps directive names to handler methods in parser
392 /// extensions. Extensions register themselves in this map by calling
393 /// addDirectiveHandler.
394 StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
395
396 /// maps assembly-time variable names to variables.
397 struct Variable {
398 enum RedefinableKind { NOT_REDEFINABLE, WARN_ON_REDEFINITION, REDEFINABLE };
399
401 RedefinableKind Redefinable = REDEFINABLE;
402 bool IsText = false;
403 std::string TextValue;
404 };
405 StringMap<Variable> Variables;
406
407 /// Stack of active struct definitions.
408 SmallVector<StructInfo, 1> StructInProgress;
409
410 /// Maps struct tags to struct definitions.
411 StringMap<StructInfo> Structs;
412
413 /// Maps data location names to types.
414 StringMap<AsmTypeInfo> KnownType;
415
416 /// Stack of active macro instantiations.
417 std::vector<MacroInstantiation*> ActiveMacros;
418
419 /// List of bodies of anonymous macros.
420 std::deque<MCAsmMacro> MacroLikeBodies;
421
422 /// Keeps track of how many .macro's have been instantiated.
423 unsigned NumOfMacroInstantiations;
424
425 /// The values from the last parsed cpp hash file line comment if any.
426 struct CppHashInfoTy {
428 int64_t LineNumber;
429 SMLoc Loc;
430 unsigned Buf;
431 CppHashInfoTy() : LineNumber(0), Buf(0) {}
432 };
433 CppHashInfoTy CppHashInfo;
434
435 /// The filename from the first cpp hash file line comment, if any.
436 StringRef FirstCppHashFilename;
437
438 /// List of forward directional labels for diagnosis at the end.
440
441 /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
442 /// Defaults to 1U, meaning Intel.
443 unsigned AssemblerDialect = 1U;
444
445 /// Are we parsing ms-style inline assembly?
446 bool ParsingMSInlineAsm = false;
447
448 // Current <...> expression depth.
449 unsigned AngleBracketDepth = 0U;
450
451 // Number of locals defined.
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
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 /// @name MCAsmParser Interface
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 = std::nullopt) override;
487 bool Warning(SMLoc L, const Twine &Msg,
488 SMRange Range = std::nullopt) override;
489 bool printError(SMLoc L, const Twine &Msg,
490 SMRange Range = std::nullopt) override;
491
492 enum ExpandKind { ExpandMacros, DoNotExpandMacros };
493 const AsmToken &Lex(ExpandKind ExpandNextToken);
494 const AsmToken &Lex() override { return Lex(ExpandMacros); }
495
496 void setParsingMSInlineAsm(bool V) override {
497 ParsingMSInlineAsm = V;
498 // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
499 // hex integer literals.
500 Lexer.setLexMasmIntegers(V);
501 }
502 bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
503
504 bool isParsingMasm() const override { return true; }
505
506 bool defineMacro(StringRef Name, StringRef Value) override;
507
508 bool lookUpField(StringRef Name, AsmFieldInfo &Info) const override;
509 bool lookUpField(StringRef Base, StringRef Member,
510 AsmFieldInfo &Info) const override;
511
512 bool lookUpType(StringRef Name, AsmTypeInfo &Info) const override;
513
514 bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs,
515 unsigned &NumInputs,
516 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
517 SmallVectorImpl<std::string> &Constraints,
519 const MCInstrInfo *MII, MCInstPrinter *IP,
520 MCAsmParserSemaCallback &SI) override;
521
522 bool parseExpression(const MCExpr *&Res);
523 bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
524 bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
525 AsmTypeInfo *TypeInfo) override;
526 bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
527 bool parseAbsoluteExpression(int64_t &Res) override;
528
529 /// Parse a floating point expression using the float \p Semantics
530 /// and set \p Res to the value.
531 bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
532
533 /// Parse an identifier or string (as a quoted identifier)
534 /// and set \p Res to the identifier contents.
535 enum IdentifierPositionKind { StandardPosition, StartOfStatement };
536 bool parseIdentifier(StringRef &Res, IdentifierPositionKind Position);
537 bool parseIdentifier(StringRef &Res) override {
538 return parseIdentifier(Res, StandardPosition);
539 }
540 void eatToEndOfStatement() override;
541
542 bool checkForValidSection() override;
543
544 /// }
545
546private:
547 bool expandMacros();
548 const AsmToken peekTok(bool ShouldSkipSpace = true);
549
550 bool parseStatement(ParseStatementInfo &Info,
552 bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
553 bool parseCppHashLineFilenameComment(SMLoc L);
554
555 bool expandMacro(raw_svector_ostream &OS, StringRef Body,
558 const std::vector<std::string> &Locals, SMLoc L);
559
560 /// Are we inside a macro instantiation?
561 bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
562
563 /// Handle entry to macro instantiation.
564 ///
565 /// \param M The macro.
566 /// \param NameLoc Instantiation location.
567 bool handleMacroEntry(
568 const MCAsmMacro *M, SMLoc NameLoc,
570
571 /// Handle invocation of macro function.
572 ///
573 /// \param M The macro.
574 /// \param NameLoc Invocation location.
575 bool handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc);
576
577 /// Handle exit from macro instantiation.
578 void handleMacroExit();
579
580 /// Extract AsmTokens for a macro argument.
581 bool
582 parseMacroArgument(const MCAsmMacroParameter *MP, MCAsmMacroArgument &MA,
584
585 /// Parse all macro arguments for a given macro.
586 bool
587 parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A,
589
590 void printMacroInstantiations();
591
592 bool expandStatement(SMLoc Loc);
593
594 void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
595 SMRange Range = std::nullopt) const {
597 SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
598 }
599 static void DiagHandler(const SMDiagnostic &Diag, void *Context);
600
601 bool lookUpField(const StructInfo &Structure, StringRef Member,
602 AsmFieldInfo &Info) const;
603
604 /// Enter the specified file. This returns true on failure.
605 bool enterIncludeFile(const std::string &Filename);
606
607 /// Reset the current lexer position to that given by \p Loc. The
608 /// current token is not set; clients should ensure Lex() is called
609 /// subsequently.
610 ///
611 /// \param InBuffer If not 0, should be the known buffer id that contains the
612 /// location.
613 void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0,
614 bool EndStatementAtEOF = true);
615
616 /// Parse up to a token of kind \p EndTok and return the contents from the
617 /// current token up to (but not including) this token; the current token on
618 /// exit will be either this kind or EOF. Reads through instantiated macro
619 /// functions and text macros.
620 SmallVector<StringRef, 1> parseStringRefsTo(AsmToken::TokenKind EndTok);
621 std::string parseStringTo(AsmToken::TokenKind EndTok);
622
623 /// Parse up to the end of statement and return the contents from the current
624 /// token until the end of the statement; the current token on exit will be
625 /// either the EndOfStatement or EOF.
627
628 bool parseTextItem(std::string &Data);
629
630 unsigned getBinOpPrecedence(AsmToken::TokenKind K,
632
633 bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
634 bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
635 bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
636
637 // Generic (target and platform independent) directive parsing.
638 enum DirectiveKind {
639 DK_NO_DIRECTIVE, // Placeholder
640 DK_HANDLER_DIRECTIVE,
641 DK_ASSIGN,
642 DK_EQU,
643 DK_TEXTEQU,
644 DK_ASCII,
645 DK_ASCIZ,
646 DK_STRING,
647 DK_BYTE,
648 DK_SBYTE,
649 DK_WORD,
650 DK_SWORD,
651 DK_DWORD,
652 DK_SDWORD,
653 DK_FWORD,
654 DK_QWORD,
655 DK_SQWORD,
656 DK_DB,
657 DK_DD,
658 DK_DF,
659 DK_DQ,
660 DK_DW,
661 DK_REAL4,
662 DK_REAL8,
663 DK_REAL10,
664 DK_ALIGN,
665 DK_EVEN,
666 DK_ORG,
667 DK_ENDR,
668 DK_EXTERN,
669 DK_PUBLIC,
670 DK_COMM,
671 DK_COMMENT,
672 DK_INCLUDE,
673 DK_REPEAT,
674 DK_WHILE,
675 DK_FOR,
676 DK_FORC,
677 DK_IF,
678 DK_IFE,
679 DK_IFB,
680 DK_IFNB,
681 DK_IFDEF,
682 DK_IFNDEF,
683 DK_IFDIF,
684 DK_IFDIFI,
685 DK_IFIDN,
686 DK_IFIDNI,
687 DK_ELSEIF,
688 DK_ELSEIFE,
689 DK_ELSEIFB,
690 DK_ELSEIFNB,
691 DK_ELSEIFDEF,
692 DK_ELSEIFNDEF,
693 DK_ELSEIFDIF,
694 DK_ELSEIFDIFI,
695 DK_ELSEIFIDN,
696 DK_ELSEIFIDNI,
697 DK_ELSE,
698 DK_ENDIF,
699
700 DK_MACRO,
701 DK_EXITM,
702 DK_ENDM,
703 DK_PURGE,
704 DK_ERR,
705 DK_ERRB,
706 DK_ERRNB,
707 DK_ERRDEF,
708 DK_ERRNDEF,
709 DK_ERRDIF,
710 DK_ERRDIFI,
711 DK_ERRIDN,
712 DK_ERRIDNI,
713 DK_ERRE,
714 DK_ERRNZ,
715 DK_ECHO,
716 DK_STRUCT,
717 DK_UNION,
718 DK_ENDS,
719 DK_END,
720 DK_PUSHFRAME,
721 DK_PUSHREG,
722 DK_SAVEREG,
723 DK_SAVEXMM128,
724 DK_SETFRAME,
725 DK_RADIX,
726 };
727
728 /// Maps directive name --> DirectiveKind enum, for directives parsed by this
729 /// class.
730 StringMap<DirectiveKind> DirectiveKindMap;
731
732 bool isMacroLikeDirective();
733
734 // Generic (target and platform independent) directive parsing.
735 enum BuiltinSymbol {
736 BI_NO_SYMBOL, // Placeholder
737 BI_DATE,
738 BI_TIME,
739 BI_VERSION,
740 BI_FILECUR,
741 BI_FILENAME,
742 BI_LINE,
743 BI_CURSEG,
744 BI_CPU,
745 BI_INTERFACE,
746 BI_CODE,
747 BI_DATA,
748 BI_FARDATA,
749 BI_WORDSIZE,
750 BI_CODESIZE,
751 BI_DATASIZE,
752 BI_MODEL,
753 BI_STACK,
754 };
755
756 /// Maps builtin name --> BuiltinSymbol enum, for builtins handled by this
757 /// class.
758 StringMap<BuiltinSymbol> BuiltinSymbolMap;
759
760 const MCExpr *evaluateBuiltinValue(BuiltinSymbol Symbol, SMLoc StartLoc);
761
762 std::optional<std::string> evaluateBuiltinTextMacro(BuiltinSymbol Symbol,
763 SMLoc StartLoc);
764
765 // Generic (target and platform independent) directive parsing.
766 enum BuiltinFunction {
767 BI_NO_FUNCTION, // Placeholder
768 BI_CATSTR,
769 };
770
771 /// Maps builtin name --> BuiltinFunction enum, for builtins handled by this
772 /// class.
773 StringMap<BuiltinFunction> BuiltinFunctionMap;
774
775 bool evaluateBuiltinMacroFunction(BuiltinFunction Function, StringRef Name,
776 std::string &Res);
777
778 // ".ascii", ".asciz", ".string"
779 bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
780
781 // "byte", "word", ...
782 bool emitIntValue(const MCExpr *Value, unsigned Size);
783 bool parseScalarInitializer(unsigned Size,
785 unsigned StringPadLength = 0);
786 bool parseScalarInstList(
787 unsigned Size, SmallVectorImpl<const MCExpr *> &Values,
789 bool emitIntegralValues(unsigned Size, unsigned *Count = nullptr);
790 bool addIntegralField(StringRef Name, unsigned Size);
791 bool parseDirectiveValue(StringRef IDVal, unsigned Size);
792 bool parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
793 StringRef Name, SMLoc NameLoc);
794
795 // "real4", "real8", "real10"
796 bool emitRealValues(const fltSemantics &Semantics, unsigned *Count = nullptr);
797 bool addRealField(StringRef Name, const fltSemantics &Semantics, size_t Size);
798 bool parseDirectiveRealValue(StringRef IDVal, const fltSemantics &Semantics,
799 size_t Size);
800 bool parseRealInstList(
801 const fltSemantics &Semantics, SmallVectorImpl<APInt> &Values,
803 bool parseDirectiveNamedRealValue(StringRef TypeName,
804 const fltSemantics &Semantics,
805 unsigned Size, StringRef Name,
806 SMLoc NameLoc);
807
808 bool parseOptionalAngleBracketOpen();
809 bool parseAngleBracketClose(const Twine &Msg = "expected '>'");
810
811 bool parseFieldInitializer(const FieldInfo &Field,
812 FieldInitializer &Initializer);
813 bool parseFieldInitializer(const FieldInfo &Field,
814 const IntFieldInfo &Contents,
815 FieldInitializer &Initializer);
816 bool parseFieldInitializer(const FieldInfo &Field,
817 const RealFieldInfo &Contents,
818 FieldInitializer &Initializer);
819 bool parseFieldInitializer(const FieldInfo &Field,
820 const StructFieldInfo &Contents,
821 FieldInitializer &Initializer);
822
823 bool parseStructInitializer(const StructInfo &Structure,
824 StructInitializer &Initializer);
825 bool parseStructInstList(
826 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
828
829 bool emitFieldValue(const FieldInfo &Field);
830 bool emitFieldValue(const FieldInfo &Field, const IntFieldInfo &Contents);
831 bool emitFieldValue(const FieldInfo &Field, const RealFieldInfo &Contents);
832 bool emitFieldValue(const FieldInfo &Field, const StructFieldInfo &Contents);
833
834 bool emitFieldInitializer(const FieldInfo &Field,
835 const FieldInitializer &Initializer);
836 bool emitFieldInitializer(const FieldInfo &Field,
837 const IntFieldInfo &Contents,
838 const IntFieldInfo &Initializer);
839 bool emitFieldInitializer(const FieldInfo &Field,
840 const RealFieldInfo &Contents,
841 const RealFieldInfo &Initializer);
842 bool emitFieldInitializer(const FieldInfo &Field,
843 const StructFieldInfo &Contents,
844 const StructFieldInfo &Initializer);
845
846 bool emitStructInitializer(const StructInfo &Structure,
847 const StructInitializer &Initializer);
848
849 // User-defined types (structs, unions):
850 bool emitStructValues(const StructInfo &Structure, unsigned *Count = nullptr);
851 bool addStructField(StringRef Name, const StructInfo &Structure);
852 bool parseDirectiveStructValue(const StructInfo &Structure,
853 StringRef Directive, SMLoc DirLoc);
854 bool parseDirectiveNamedStructValue(const StructInfo &Structure,
855 StringRef Directive, SMLoc DirLoc,
857
858 // "=", "equ", "textequ"
859 bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
860 DirectiveKind DirKind, SMLoc NameLoc);
861
862 bool parseDirectiveOrg(); // "org"
863
864 bool emitAlignTo(int64_t Alignment);
865 bool parseDirectiveAlign(); // "align"
866 bool parseDirectiveEven(); // "even"
867
868 // macro directives
869 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
870 bool parseDirectiveExitMacro(SMLoc DirectiveLoc, StringRef Directive,
871 std::string &Value);
872 bool parseDirectiveEndMacro(StringRef Directive);
873 bool parseDirectiveMacro(StringRef Name, SMLoc NameLoc);
874
875 bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind,
876 StringRef Name, SMLoc NameLoc);
877 bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind);
878 bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
879 bool parseDirectiveNestedEnds();
880
881 bool parseDirectiveExtern();
882
883 /// Parse a directive like ".globl" which accepts a single symbol (which
884 /// should be a label or an external).
885 bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
886
887 bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
888
889 bool parseDirectiveComment(SMLoc DirectiveLoc); // "comment"
890
891 bool parseDirectiveInclude(); // "include"
892
893 // "if" or "ife"
894 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
895 // "ifb" or "ifnb", depending on ExpectBlank.
896 bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
897 // "ifidn", "ifdif", "ifidni", or "ifdifi", depending on ExpectEqual and
898 // CaseInsensitive.
899 bool parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
900 bool CaseInsensitive);
901 // "ifdef" or "ifndef", depending on expect_defined
902 bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
903 // "elseif" or "elseife"
904 bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
905 // "elseifb" or "elseifnb", depending on ExpectBlank.
906 bool parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank);
907 // ".elseifdef" or ".elseifndef", depending on expect_defined
908 bool parseDirectiveElseIfdef(SMLoc DirectiveLoc, bool expect_defined);
909 // "elseifidn", "elseifdif", "elseifidni", or "elseifdifi", depending on
910 // ExpectEqual and CaseInsensitive.
911 bool parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
912 bool CaseInsensitive);
913 bool parseDirectiveElse(SMLoc DirectiveLoc); // "else"
914 bool parseDirectiveEndIf(SMLoc DirectiveLoc); // "endif"
915 bool parseEscapedString(std::string &Data) override;
916 bool parseAngleBracketString(std::string &Data) override;
917
918 // Macro-like directives
919 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
920 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
922 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
923 SMLoc ExitLoc, raw_svector_ostream &OS);
924 bool parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Directive);
925 bool parseDirectiveFor(SMLoc DirectiveLoc, StringRef Directive);
926 bool parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive);
927 bool parseDirectiveWhile(SMLoc DirectiveLoc);
928
929 // "_emit" or "__emit"
930 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
931 size_t Len);
932
933 // "align"
934 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
935
936 // "end"
937 bool parseDirectiveEnd(SMLoc DirectiveLoc);
938
939 // ".err"
940 bool parseDirectiveError(SMLoc DirectiveLoc);
941 // ".errb" or ".errnb", depending on ExpectBlank.
942 bool parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank);
943 // ".errdef" or ".errndef", depending on ExpectBlank.
944 bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc, bool ExpectDefined);
945 // ".erridn", ".errdif", ".erridni", or ".errdifi", depending on ExpectEqual
946 // and CaseInsensitive.
947 bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
948 bool CaseInsensitive);
949 // ".erre" or ".errnz", depending on ExpectZero.
950 bool parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero);
951
952 // ".radix"
953 bool parseDirectiveRadix(SMLoc DirectiveLoc);
954
955 // "echo"
956 bool parseDirectiveEcho(SMLoc DirectiveLoc);
957
958 void initializeDirectiveKindMap();
959 void initializeBuiltinSymbolMaps();
960};
961
962} // end anonymous namespace
963
964namespace llvm {
965
967
969
970} // end namespace llvm
971
972enum { DEFAULT_ADDRSPACE = 0 };
973
974MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
975 const MCAsmInfo &MAI, struct tm TM, unsigned CB)
976 : MCAsmParser(Ctx, Out, SM, MAI), CurBuffer(CB ? CB : SM.getMainFileID()),
977 TM(TM) {
978 HadError = false;
979 // Save the old handler.
980 SavedDiagHandler = SrcMgr.getDiagHandler();
981 SavedDiagContext = SrcMgr.getDiagContext();
982 // Set our own handler which calls the saved handler.
984 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
985 EndStatementAtEOFStack.push_back(true);
986
987 // Initialize the platform / file format parser.
988 switch (Ctx.getObjectFileType()) {
990 PlatformParser.reset(createCOFFMasmParser());
991 break;
992 default:
993 report_fatal_error("llvm-ml currently supports only COFF output.");
994 break;
995 }
996
997 initializeDirectiveKindMap();
998 PlatformParser->Initialize(*this);
999 initializeBuiltinSymbolMaps();
1000
1001 NumOfMacroInstantiations = 0;
1002}
1003
1004MasmParser::~MasmParser() {
1005 assert((HadError || ActiveMacros.empty()) &&
1006 "Unexpected active macro instantiation!");
1007
1008 // Restore the saved diagnostics handler and context for use during
1009 // finalization.
1010 SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
1011}
1012
1013void MasmParser::printMacroInstantiations() {
1014 // Print the active macro instantiation stack.
1015 for (std::vector<MacroInstantiation *>::const_reverse_iterator
1016 it = ActiveMacros.rbegin(),
1017 ie = ActiveMacros.rend();
1018 it != ie; ++it)
1019 printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note,
1020 "while in macro instantiation");
1021}
1022
1023void MasmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
1024 printPendingErrors();
1025 printMessage(L, SourceMgr::DK_Note, Msg, Range);
1026 printMacroInstantiations();
1027}
1028
1029bool MasmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
1030 if (getTargetParser().getTargetOptions().MCNoWarn)
1031 return false;
1032 if (getTargetParser().getTargetOptions().MCFatalWarnings)
1033 return Error(L, Msg, Range);
1034 printMessage(L, SourceMgr::DK_Warning, Msg, Range);
1035 printMacroInstantiations();
1036 return false;
1037}
1038
1039bool MasmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
1040 HadError = true;
1041 printMessage(L, SourceMgr::DK_Error, Msg, Range);
1042 printMacroInstantiations();
1043 return true;
1044}
1045
1046bool MasmParser::enterIncludeFile(const std::string &Filename) {
1047 std::string IncludedFile;
1048 unsigned NewBuf =
1049 SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
1050 if (!NewBuf)
1051 return true;
1052
1053 CurBuffer = NewBuf;
1054 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
1055 EndStatementAtEOFStack.push_back(true);
1056 return false;
1057}
1058
1059void MasmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer,
1060 bool EndStatementAtEOF) {
1061 CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
1062 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
1063 Loc.getPointer(), EndStatementAtEOF);
1064}
1065
1066bool MasmParser::expandMacros() {
1067 const AsmToken &Tok = getTok();
1068 const std::string IDLower = Tok.getIdentifier().lower();
1069
1070 const llvm::MCAsmMacro *M = getContext().lookupMacro(IDLower);
1071 if (M && M->IsFunction && peekTok().is(AsmToken::LParen)) {
1072 // This is a macro function invocation; expand it in place.
1073 const SMLoc MacroLoc = Tok.getLoc();
1074 const StringRef MacroId = Tok.getIdentifier();
1075 Lexer.Lex();
1076 if (handleMacroInvocation(M, MacroLoc)) {
1077 Lexer.UnLex(AsmToken(AsmToken::Error, MacroId));
1078 Lexer.Lex();
1079 }
1080 return false;
1081 }
1082
1083 std::optional<std::string> ExpandedValue;
1084
1085 if (auto BuiltinIt = BuiltinSymbolMap.find(IDLower);
1086 BuiltinIt != BuiltinSymbolMap.end()) {
1087 ExpandedValue =
1088 evaluateBuiltinTextMacro(BuiltinIt->getValue(), Tok.getLoc());
1089 } else if (auto BuiltinFuncIt = BuiltinFunctionMap.find(IDLower);
1090 BuiltinFuncIt != BuiltinFunctionMap.end()) {
1092 if (parseIdentifier(Name)) {
1093 return true;
1094 }
1095 std::string Res;
1096 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), Name, Res)) {
1097 return true;
1098 }
1099 ExpandedValue = Res;
1100 } else if (auto VarIt = Variables.find(IDLower);
1101 VarIt != Variables.end() && VarIt->getValue().IsText) {
1102 ExpandedValue = VarIt->getValue().TextValue;
1103 }
1104
1105 if (!ExpandedValue)
1106 return true;
1107 std::unique_ptr<MemoryBuffer> Instantiation =
1108 MemoryBuffer::getMemBufferCopy(*ExpandedValue, "<instantiation>");
1109
1110 // Jump to the macro instantiation and prime the lexer.
1111 CurBuffer =
1112 SrcMgr.AddNewSourceBuffer(std::move(Instantiation), Tok.getEndLoc());
1113 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), nullptr,
1114 /*EndStatementAtEOF=*/false);
1115 EndStatementAtEOFStack.push_back(false);
1116 Lexer.Lex();
1117 return false;
1118}
1119
1120const AsmToken &MasmParser::Lex(ExpandKind ExpandNextToken) {
1121 if (Lexer.getTok().is(AsmToken::Error))
1122 Error(Lexer.getErrLoc(), Lexer.getErr());
1123 bool StartOfStatement = false;
1124
1125 // if it's a end of statement with a comment in it
1126 if (getTok().is(AsmToken::EndOfStatement)) {
1127 // if this is a line comment output it.
1128 if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
1129 getTok().getString().front() != '\r' && MAI.preserveAsmComments())
1130 Out.addExplicitComment(Twine(getTok().getString()));
1131 StartOfStatement = true;
1132 }
1133
1134 const AsmToken *tok = &Lexer.Lex();
1135
1136 while (ExpandNextToken == ExpandMacros && tok->is(AsmToken::Identifier)) {
1137 if (StartOfStatement) {
1138 AsmToken NextTok;
1139 MutableArrayRef<AsmToken> Buf(NextTok);
1140 size_t ReadCount = Lexer.peekTokens(Buf);
1141 if (ReadCount && NextTok.is(AsmToken::Identifier) &&
1142 (NextTok.getString().equals_insensitive("equ") ||
1143 NextTok.getString().equals_insensitive("textequ"))) {
1144 // This looks like an EQU or TEXTEQU directive; don't expand the
1145 // identifier, allowing for redefinitions.
1146 break;
1147 }
1148 }
1149 if (expandMacros())
1150 break;
1151 }
1152
1153 // Parse comments here to be deferred until end of next statement.
1154 while (tok->is(AsmToken::Comment)) {
1155 if (MAI.preserveAsmComments())
1156 Out.addExplicitComment(Twine(tok->getString()));
1157 tok = &Lexer.Lex();
1158 }
1159
1160 // Recognize and bypass line continuations.
1161 while (tok->is(AsmToken::BackSlash) &&
1162 peekTok().is(AsmToken::EndOfStatement)) {
1163 // Eat both the backslash and the end of statement.
1164 Lexer.Lex();
1165 tok = &Lexer.Lex();
1166 }
1167
1168 if (tok->is(AsmToken::Eof)) {
1169 // If this is the end of an included file, pop the parent file off the
1170 // include stack.
1171 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
1172 if (ParentIncludeLoc != SMLoc()) {
1173 EndStatementAtEOFStack.pop_back();
1174 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1175 return Lex();
1176 }
1177 EndStatementAtEOFStack.pop_back();
1178 assert(EndStatementAtEOFStack.empty());
1179 }
1180
1181 return *tok;
1182}
1183
1184const AsmToken MasmParser::peekTok(bool ShouldSkipSpace) {
1185 AsmToken Tok;
1186
1188 size_t ReadCount = Lexer.peekTokens(Buf, ShouldSkipSpace);
1189
1190 if (ReadCount == 0) {
1191 // If this is the end of an included file, pop the parent file off the
1192 // include stack.
1193 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
1194 if (ParentIncludeLoc != SMLoc()) {
1195 EndStatementAtEOFStack.pop_back();
1196 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1197 return peekTok(ShouldSkipSpace);
1198 }
1199 EndStatementAtEOFStack.pop_back();
1200 assert(EndStatementAtEOFStack.empty());
1201 }
1202
1203 assert(ReadCount == 1);
1204 return Tok;
1205}
1206
1207bool MasmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
1208 // Create the initial section, if requested.
1209 if (!NoInitialTextSection)
1210 Out.initSections(false, getTargetParser().getSTI());
1211
1212 // Prime the lexer.
1213 Lex();
1214
1215 HadError = false;
1216 AsmCond StartingCondState = TheCondState;
1217 SmallVector<AsmRewrite, 4> AsmStrRewrites;
1218
1219 // While we have input, parse each statement.
1220 while (Lexer.isNot(AsmToken::Eof) ||
1221 SrcMgr.getParentIncludeLoc(CurBuffer) != SMLoc()) {
1222 // Skip through the EOF at the end of an inclusion.
1223 if (Lexer.is(AsmToken::Eof))
1224 Lex();
1225
1226 ParseStatementInfo Info(&AsmStrRewrites);
1227 bool HasError = parseStatement(Info, nullptr);
1228
1229 // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
1230 // for printing ErrMsg via Lex() only if no (presumably better) parser error
1231 // exists.
1232 if (HasError && !hasPendingError() && Lexer.getTok().is(AsmToken::Error))
1233 Lex();
1234
1235 // parseStatement returned true so may need to emit an error.
1236 printPendingErrors();
1237
1238 // Skipping to the next line if needed.
1239 if (HasError && !getLexer().justConsumedEOL())
1240 eatToEndOfStatement();
1241 }
1242
1243 printPendingErrors();
1244
1245 // All errors should have been emitted.
1246 assert(!hasPendingError() && "unexpected error from parseStatement");
1247
1248 if (TheCondState.TheCond != StartingCondState.TheCond ||
1249 TheCondState.Ignore != StartingCondState.Ignore)
1250 printError(getTok().getLoc(), "unmatched .ifs or .elses");
1251
1252 // Check to see that all assembler local symbols were actually defined.
1253 // Targets that don't do subsections via symbols may not want this, though,
1254 // so conservatively exclude them. Only do this if we're finalizing, though,
1255 // as otherwise we won't necessarily have seen everything yet.
1256 if (!NoFinalize) {
1257 // Temporary symbols like the ones for directional jumps don't go in the
1258 // symbol table. They also need to be diagnosed in all (final) cases.
1259 for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
1260 if (std::get<2>(LocSym)->isUndefined()) {
1261 // Reset the state of any "# line file" directives we've seen to the
1262 // context as it was at the diagnostic site.
1263 CppHashInfo = std::get<1>(LocSym);
1264 printError(std::get<0>(LocSym), "directional label undefined");
1265 }
1266 }
1267 }
1268
1269 // Finalize the output stream if there are no errors and if the client wants
1270 // us to.
1271 if (!HadError && !NoFinalize)
1272 Out.finish(Lexer.getLoc());
1273
1274 return HadError || getContext().hadError();
1275}
1276
1277bool MasmParser::checkForValidSection() {
1278 if (!ParsingMSInlineAsm && !(getStreamer().getCurrentFragment() &&
1279 getStreamer().getCurrentSectionOnly())) {
1280 Out.initSections(false, getTargetParser().getSTI());
1281 return Error(getTok().getLoc(),
1282 "expected section directive before assembly directive");
1283 }
1284 return false;
1285}
1286
1287/// Throw away the rest of the line for testing purposes.
1288void MasmParser::eatToEndOfStatement() {
1289 while (Lexer.isNot(AsmToken::EndOfStatement)) {
1290 if (Lexer.is(AsmToken::Eof)) {
1291 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
1292 if (ParentIncludeLoc == SMLoc()) {
1293 break;
1294 }
1295
1296 EndStatementAtEOFStack.pop_back();
1297 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1298 }
1299
1300 Lexer.Lex();
1301 }
1302
1303 // Eat EOL.
1304 if (Lexer.is(AsmToken::EndOfStatement))
1305 Lexer.Lex();
1306}
1307
1309MasmParser::parseStringRefsTo(AsmToken::TokenKind EndTok) {
1311 const char *Start = getTok().getLoc().getPointer();
1312 while (Lexer.isNot(EndTok)) {
1313 if (Lexer.is(AsmToken::Eof)) {
1314 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
1315 if (ParentIncludeLoc == SMLoc()) {
1316 break;
1317 }
1318 Refs.emplace_back(Start, getTok().getLoc().getPointer() - Start);
1319
1320 EndStatementAtEOFStack.pop_back();
1321 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1322 Lexer.Lex();
1323 Start = getTok().getLoc().getPointer();
1324 } else {
1325 Lexer.Lex();
1326 }
1327 }
1328 Refs.emplace_back(Start, getTok().getLoc().getPointer() - Start);
1329 return Refs;
1330}
1331
1332std::string MasmParser::parseStringTo(AsmToken::TokenKind EndTok) {
1333 SmallVector<StringRef, 1> Refs = parseStringRefsTo(EndTok);
1334 std::string Str;
1335 for (StringRef S : Refs) {
1336 Str.append(S.str());
1337 }
1338 return Str;
1339}
1340
1341StringRef MasmParser::parseStringToEndOfStatement() {
1342 const char *Start = getTok().getLoc().getPointer();
1343
1344 while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
1345 Lexer.Lex();
1346
1347 const char *End = getTok().getLoc().getPointer();
1348 return StringRef(Start, End - Start);
1349}
1350
1351/// Parse a paren expression and return it.
1352/// NOTE: This assumes the leading '(' has already been consumed.
1353///
1354/// parenexpr ::= expr)
1355///
1356bool MasmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
1357 if (parseExpression(Res))
1358 return true;
1359 EndLoc = Lexer.getTok().getEndLoc();
1360 return parseRParen();
1361}
1362
1363/// Parse a bracket expression and return it.
1364/// NOTE: This assumes the leading '[' has already been consumed.
1365///
1366/// bracketexpr ::= expr]
1367///
1368bool MasmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
1369 if (parseExpression(Res))
1370 return true;
1371 EndLoc = getTok().getEndLoc();
1372 if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
1373 return true;
1374 return false;
1375}
1376
1377/// Parse a primary expression and return it.
1378/// primaryexpr ::= (parenexpr
1379/// primaryexpr ::= symbol
1380/// primaryexpr ::= number
1381/// primaryexpr ::= '.'
1382/// primaryexpr ::= ~,+,-,'not' primaryexpr
1383/// primaryexpr ::= string
1384/// (a string is interpreted as a 64-bit number in big-endian base-256)
1385bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
1386 AsmTypeInfo *TypeInfo) {
1387 SMLoc FirstTokenLoc = getLexer().getLoc();
1388 AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
1389 switch (FirstTokenKind) {
1390 default:
1391 return TokError("unknown token in expression");
1392 // If we have an error assume that we've already handled it.
1393 case AsmToken::Error:
1394 return true;
1395 case AsmToken::Exclaim:
1396 Lex(); // Eat the operator.
1397 if (parsePrimaryExpr(Res, EndLoc, nullptr))
1398 return true;
1399 Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
1400 return false;
1401 case AsmToken::Dollar:
1402 case AsmToken::At:
1403 case AsmToken::Identifier: {
1405 if (parseIdentifier(Identifier)) {
1406 // We may have failed but $ may be a valid token.
1407 if (getTok().is(AsmToken::Dollar)) {
1408 if (Lexer.getMAI().getDollarIsPC()) {
1409 Lex();
1410 // This is a '$' reference, which references the current PC. Emit a
1411 // temporary label to the streamer and refer to it.
1412 MCSymbol *Sym = Ctx.createTempSymbol();
1413 Out.emitLabel(Sym);
1414 Res = MCSymbolRefExpr::create(Sym, getContext());
1415 EndLoc = FirstTokenLoc;
1416 return false;
1417 }
1418 return Error(FirstTokenLoc, "invalid token in expression");
1419 }
1420 }
1421 // Parse named bitwise negation.
1422 if (Identifier.equals_insensitive("not")) {
1423 if (parsePrimaryExpr(Res, EndLoc, nullptr))
1424 return true;
1425 Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
1426 return false;
1427 }
1428 // Parse directional local label references.
1429 if (Identifier.equals_insensitive("@b") ||
1430 Identifier.equals_insensitive("@f")) {
1431 bool Before = Identifier.equals_insensitive("@b");
1432 MCSymbol *Sym = getContext().getDirectionalLocalSymbol(0, Before);
1433 if (Before && Sym->isUndefined())
1434 return Error(FirstTokenLoc, "Expected @@ label before @B reference");
1435 Res = MCSymbolRefExpr::create(Sym, getContext());
1436 return false;
1437 }
1438
1439 EndLoc = SMLoc::getFromPointer(Identifier.end());
1440
1441 // This is a symbol reference.
1443 if (SymbolName.empty())
1444 return Error(getLexer().getLoc(), "expected a symbol reference");
1445
1446 // Find the field offset if used.
1448 auto Split = SymbolName.split('.');
1449 if (Split.second.empty()) {
1450 } else {
1451 SymbolName = Split.first;
1452 if (lookUpField(SymbolName, Split.second, Info)) {
1453 std::pair<StringRef, StringRef> BaseMember = Split.second.split('.');
1454 StringRef Base = BaseMember.first, Member = BaseMember.second;
1455 lookUpField(Base, Member, Info);
1456 } else if (Structs.count(SymbolName.lower())) {
1457 // This is actually a reference to a field offset.
1458 Res = MCConstantExpr::create(Info.Offset, getContext());
1459 return false;
1460 }
1461 }
1462
1463 MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
1464 if (!Sym) {
1465 // If this is a built-in numeric value, treat it as a constant.
1466 auto BuiltinIt = BuiltinSymbolMap.find(SymbolName.lower());
1467 const BuiltinSymbol Symbol = (BuiltinIt == BuiltinSymbolMap.end())
1468 ? BI_NO_SYMBOL
1469 : BuiltinIt->getValue();
1470 if (Symbol != BI_NO_SYMBOL) {
1471 const MCExpr *Value = evaluateBuiltinValue(Symbol, FirstTokenLoc);
1472 if (Value) {
1473 Res = Value;
1474 return false;
1475 }
1476 }
1477
1478 // Variables use case-insensitive symbol names; if this is a variable, we
1479 // find the symbol using its canonical name.
1480 auto VarIt = Variables.find(SymbolName.lower());
1481 if (VarIt != Variables.end())
1482 SymbolName = VarIt->second.Name;
1483 Sym = getContext().getOrCreateSymbol(SymbolName);
1484 }
1485
1486 // If this is an absolute variable reference, substitute it now to preserve
1487 // semantics in the face of reassignment.
1488 if (Sym->isVariable()) {
1489 auto V = Sym->getVariableValue();
1490 bool DoInline = isa<MCConstantExpr>(V);
1491 if (auto TV = dyn_cast<MCTargetExpr>(V))
1492 DoInline = TV->inlineAssignedExpr();
1493 if (DoInline) {
1494 Res = Sym->getVariableValue();
1495 return false;
1496 }
1497 }
1498
1499 // Otherwise create a symbol ref.
1500 const MCExpr *SymRef =
1501 MCSymbolRefExpr::create(Sym, getContext(), FirstTokenLoc);
1502 if (Info.Offset) {
1504 MCBinaryExpr::Add, SymRef,
1505 MCConstantExpr::create(Info.Offset, getContext()), getContext());
1506 } else {
1507 Res = SymRef;
1508 }
1509 if (TypeInfo) {
1510 if (Info.Type.Name.empty()) {
1511 auto TypeIt = KnownType.find(Identifier.lower());
1512 if (TypeIt != KnownType.end()) {
1513 Info.Type = TypeIt->second;
1514 }
1515 }
1516
1517 *TypeInfo = Info.Type;
1518 }
1519 return false;
1520 }
1521 case AsmToken::BigNum:
1522 return TokError("literal value out of range for directive");
1523 case AsmToken::Integer: {
1524 int64_t IntVal = getTok().getIntVal();
1525 Res = MCConstantExpr::create(IntVal, getContext());
1526 EndLoc = Lexer.getTok().getEndLoc();
1527 Lex(); // Eat token.
1528 return false;
1529 }
1530 case AsmToken::String: {
1531 // MASM strings (used as constants) are interpreted as big-endian base-256.
1532 SMLoc ValueLoc = getTok().getLoc();
1533 std::string Value;
1534 if (parseEscapedString(Value))
1535 return true;
1536 if (Value.size() > 8)
1537 return Error(ValueLoc, "literal value out of range");
1538 uint64_t IntValue = 0;
1539 for (const unsigned char CharVal : Value)
1540 IntValue = (IntValue << 8) | CharVal;
1541 Res = MCConstantExpr::create(IntValue, getContext());
1542 return false;
1543 }
1544 case AsmToken::Real: {
1545 APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
1546 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
1547 Res = MCConstantExpr::create(IntVal, getContext());
1548 EndLoc = Lexer.getTok().getEndLoc();
1549 Lex(); // Eat token.
1550 return false;
1551 }
1552 case AsmToken::Dot: {
1553 // This is a '.' reference, which references the current PC. Emit a
1554 // temporary label to the streamer and refer to it.
1555 MCSymbol *Sym = Ctx.createTempSymbol();
1556 Out.emitLabel(Sym);
1557 Res = MCSymbolRefExpr::create(Sym, getContext());
1558 EndLoc = Lexer.getTok().getEndLoc();
1559 Lex(); // Eat identifier.
1560 return false;
1561 }
1562 case AsmToken::LParen:
1563 Lex(); // Eat the '('.
1564 return parseParenExpr(Res, EndLoc);
1565 case AsmToken::LBrac:
1566 if (!PlatformParser->HasBracketExpressions())
1567 return TokError("brackets expression not supported on this target");
1568 Lex(); // Eat the '['.
1569 return parseBracketExpr(Res, EndLoc);
1570 case AsmToken::Minus:
1571 Lex(); // Eat the operator.
1572 if (parsePrimaryExpr(Res, EndLoc, nullptr))
1573 return true;
1574 Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
1575 return false;
1576 case AsmToken::Plus:
1577 Lex(); // Eat the operator.
1578 if (parsePrimaryExpr(Res, EndLoc, nullptr))
1579 return true;
1580 Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
1581 return false;
1582 case AsmToken::Tilde:
1583 Lex(); // Eat the operator.
1584 if (parsePrimaryExpr(Res, EndLoc, nullptr))
1585 return true;
1586 Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
1587 return false;
1588 }
1589}
1590
1591bool MasmParser::parseExpression(const MCExpr *&Res) {
1592 SMLoc EndLoc;
1593 return parseExpression(Res, EndLoc);
1594}
1595
1596/// This function checks if the next token is <string> type or arithmetic.
1597/// string that begin with character '<' must end with character '>'.
1598/// otherwise it is arithmetics.
1599/// If the function returns a 'true' value,
1600/// the End argument will be filled with the last location pointed to the '>'
1601/// character.
1602static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
1603 assert((StrLoc.getPointer() != nullptr) &&
1604 "Argument to the function cannot be a NULL value");
1605 const char *CharPtr = StrLoc.getPointer();
1606 while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
1607 (*CharPtr != '\0')) {
1608 if (*CharPtr == '!')
1609 CharPtr++;
1610 CharPtr++;
1611 }
1612 if (*CharPtr == '>') {
1613 EndLoc = StrLoc.getFromPointer(CharPtr + 1);
1614 return true;
1615 }
1616 return false;
1617}
1618
1619/// creating a string without the escape characters '!'.
1620static std::string angleBracketString(StringRef BracketContents) {
1621 std::string Res;
1622 for (size_t Pos = 0; Pos < BracketContents.size(); Pos++) {
1623 if (BracketContents[Pos] == '!')
1624 Pos++;
1625 Res += BracketContents[Pos];
1626 }
1627 return Res;
1628}
1629
1630/// Parse an expression and return it.
1631///
1632/// expr ::= expr &&,|| expr -> lowest.
1633/// expr ::= expr |,^,&,! expr
1634/// expr ::= expr ==,!=,<>,<,<=,>,>= expr
1635/// expr ::= expr <<,>> expr
1636/// expr ::= expr +,- expr
1637/// expr ::= expr *,/,% expr -> highest.
1638/// expr ::= primaryexpr
1639///
1640bool MasmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
1641 // Parse the expression.
1642 Res = nullptr;
1643 if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
1644 parseBinOpRHS(1, Res, EndLoc))
1645 return true;
1646
1647 // Try to constant fold it up front, if possible. Do not exploit
1648 // assembler here.
1649 int64_t Value;
1650 if (Res->evaluateAsAbsolute(Value))
1651 Res = MCConstantExpr::create(Value, getContext());
1652
1653 return false;
1654}
1655
1656bool MasmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
1657 Res = nullptr;
1658 return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
1659}
1660
1661bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
1662 const MCExpr *Expr;
1663
1664 SMLoc StartLoc = Lexer.getLoc();
1665 if (parseExpression(Expr))
1666 return true;
1667
1668 if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
1669 return Error(StartLoc, "expected absolute expression");
1670
1671 return false;
1672}
1673
1676 bool ShouldUseLogicalShr,
1677 bool EndExpressionAtGreater) {
1678 switch (K) {
1679 default:
1680 return 0; // not a binop.
1681
1682 // Lowest Precedence: &&, ||
1683 case AsmToken::AmpAmp:
1684 Kind = MCBinaryExpr::LAnd;
1685 return 2;
1686 case AsmToken::PipePipe:
1687 Kind = MCBinaryExpr::LOr;
1688 return 1;
1689
1690 // Low Precedence: ==, !=, <>, <, <=, >, >=
1692 Kind = MCBinaryExpr::EQ;
1693 return 3;
1696 Kind = MCBinaryExpr::NE;
1697 return 3;
1698 case AsmToken::Less:
1699 Kind = MCBinaryExpr::LT;
1700 return 3;
1702 Kind = MCBinaryExpr::LTE;
1703 return 3;
1704 case AsmToken::Greater:
1705 if (EndExpressionAtGreater)
1706 return 0;
1707 Kind = MCBinaryExpr::GT;
1708 return 3;
1710 Kind = MCBinaryExpr::GTE;
1711 return 3;
1712
1713 // Low Intermediate Precedence: +, -
1714 case AsmToken::Plus:
1715 Kind = MCBinaryExpr::Add;
1716 return 4;
1717 case AsmToken::Minus:
1718 Kind = MCBinaryExpr::Sub;
1719 return 4;
1720
1721 // High Intermediate Precedence: |, &, ^
1722 case AsmToken::Pipe:
1723 Kind = MCBinaryExpr::Or;
1724 return 5;
1725 case AsmToken::Caret:
1726 Kind = MCBinaryExpr::Xor;
1727 return 5;
1728 case AsmToken::Amp:
1729 Kind = MCBinaryExpr::And;
1730 return 5;
1731
1732 // Highest Precedence: *, /, %, <<, >>
1733 case AsmToken::Star:
1734 Kind = MCBinaryExpr::Mul;
1735 return 6;
1736 case AsmToken::Slash:
1737 Kind = MCBinaryExpr::Div;
1738 return 6;
1739 case AsmToken::Percent:
1740 Kind = MCBinaryExpr::Mod;
1741 return 6;
1742 case AsmToken::LessLess:
1743 Kind = MCBinaryExpr::Shl;
1744 return 6;
1746 if (EndExpressionAtGreater)
1747 return 0;
1748 Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
1749 return 6;
1750 }
1751}
1752
1753unsigned MasmParser::getBinOpPrecedence(AsmToken::TokenKind K,
1754 MCBinaryExpr::Opcode &Kind) {
1755 bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
1756 return getGNUBinOpPrecedence(K, Kind, ShouldUseLogicalShr,
1757 AngleBracketDepth > 0);
1758}
1759
1760/// Parse all binary operators with precedence >= 'Precedence'.
1761/// Res contains the LHS of the expression on input.
1762bool MasmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
1763 SMLoc &EndLoc) {
1764 SMLoc StartLoc = Lexer.getLoc();
1765 while (true) {
1766 AsmToken::TokenKind TokKind = Lexer.getKind();
1767 if (Lexer.getKind() == AsmToken::Identifier) {
1768 TokKind = StringSwitch<AsmToken::TokenKind>(Lexer.getTok().getString())
1769 .CaseLower("and", AsmToken::Amp)
1772 .CaseLower("xor", AsmToken::Caret)
1781 .Default(TokKind);
1782 }
1784 unsigned TokPrec = getBinOpPrecedence(TokKind, Kind);
1785
1786 // If the next token is lower precedence than we are allowed to eat, return
1787 // successfully with what we ate already.
1788 if (TokPrec < Precedence)
1789 return false;
1790
1791 Lex();
1792
1793 // Eat the next primary expression.
1794 const MCExpr *RHS;
1795 if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
1796 return true;
1797
1798 // If BinOp binds less tightly with RHS than the operator after RHS, let
1799 // the pending operator take RHS as its LHS.
1801 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
1802 if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
1803 return true;
1804
1805 // Merge LHS and RHS according to operator.
1806 Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);
1807 }
1808}
1809
1810/// ParseStatement:
1811/// ::= % statement
1812/// ::= EndOfStatement
1813/// ::= Label* Directive ...Operands... EndOfStatement
1814/// ::= Label* Identifier OperandList* EndOfStatement
1815bool MasmParser::parseStatement(ParseStatementInfo &Info,
1817 assert(!hasPendingError() && "parseStatement started with pending error");
1818 // Eat initial spaces and comments.
1819 while (Lexer.is(AsmToken::Space))
1820 Lex();
1821 if (Lexer.is(AsmToken::EndOfStatement)) {
1822 // If this is a line comment we can drop it safely.
1823 if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
1824 getTok().getString().front() == '\n')
1825 Out.addBlankLine();
1826 Lex();
1827 return false;
1828 }
1829
1830 // If preceded by an expansion operator, first expand all text macros and
1831 // macro functions.
1832 if (getTok().is(AsmToken::Percent)) {
1833 SMLoc ExpansionLoc = getTok().getLoc();
1834 if (parseToken(AsmToken::Percent) || expandStatement(ExpansionLoc))
1835 return true;
1836 }
1837
1838 // Statements always start with an identifier, unless we're dealing with a
1839 // processor directive (.386, .686, etc.) that lexes as a real.
1840 AsmToken ID = getTok();
1841 SMLoc IDLoc = ID.getLoc();
1842 StringRef IDVal;
1843 if (Lexer.is(AsmToken::HashDirective))
1844 return parseCppHashLineFilenameComment(IDLoc);
1845 if (Lexer.is(AsmToken::Dot)) {
1846 // Treat '.' as a valid identifier in this context.
1847 Lex();
1848 IDVal = ".";
1849 } else if (Lexer.is(AsmToken::Real)) {
1850 // Treat ".<number>" as a valid identifier in this context.
1851 IDVal = getTok().getString();
1852 Lex(); // always eat a token
1853 if (!IDVal.starts_with("."))
1854 return Error(IDLoc, "unexpected token at start of statement");
1855 } else if (parseIdentifier(IDVal, StartOfStatement)) {
1856 if (!TheCondState.Ignore) {
1857 Lex(); // always eat a token
1858 return Error(IDLoc, "unexpected token at start of statement");
1859 }
1860 IDVal = "";
1861 }
1862
1863 // Handle conditional assembly here before checking for skipping. We
1864 // have to do this so that .endif isn't skipped in a ".if 0" block for
1865 // example.
1867 DirectiveKindMap.find(IDVal.lower());
1868 DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
1869 ? DK_NO_DIRECTIVE
1870 : DirKindIt->getValue();
1871 switch (DirKind) {
1872 default:
1873 break;
1874 case DK_IF:
1875 case DK_IFE:
1876 return parseDirectiveIf(IDLoc, DirKind);
1877 case DK_IFB:
1878 return parseDirectiveIfb(IDLoc, true);
1879 case DK_IFNB:
1880 return parseDirectiveIfb(IDLoc, false);
1881 case DK_IFDEF:
1882 return parseDirectiveIfdef(IDLoc, true);
1883 case DK_IFNDEF:
1884 return parseDirectiveIfdef(IDLoc, false);
1885 case DK_IFDIF:
1886 return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false,
1887 /*CaseInsensitive=*/false);
1888 case DK_IFDIFI:
1889 return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false,
1890 /*CaseInsensitive=*/true);
1891 case DK_IFIDN:
1892 return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true,
1893 /*CaseInsensitive=*/false);
1894 case DK_IFIDNI:
1895 return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true,
1896 /*CaseInsensitive=*/true);
1897 case DK_ELSEIF:
1898 case DK_ELSEIFE:
1899 return parseDirectiveElseIf(IDLoc, DirKind);
1900 case DK_ELSEIFB:
1901 return parseDirectiveElseIfb(IDLoc, true);
1902 case DK_ELSEIFNB:
1903 return parseDirectiveElseIfb(IDLoc, false);
1904 case DK_ELSEIFDEF:
1905 return parseDirectiveElseIfdef(IDLoc, true);
1906 case DK_ELSEIFNDEF:
1907 return parseDirectiveElseIfdef(IDLoc, false);
1908 case DK_ELSEIFDIF:
1909 return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false,
1910 /*CaseInsensitive=*/false);
1911 case DK_ELSEIFDIFI:
1912 return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false,
1913 /*CaseInsensitive=*/true);
1914 case DK_ELSEIFIDN:
1915 return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true,
1916 /*CaseInsensitive=*/false);
1917 case DK_ELSEIFIDNI:
1918 return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true,
1919 /*CaseInsensitive=*/true);
1920 case DK_ELSE:
1921 return parseDirectiveElse(IDLoc);
1922 case DK_ENDIF:
1923 return parseDirectiveEndIf(IDLoc);
1924 }
1925
1926 // Ignore the statement if in the middle of inactive conditional
1927 // (e.g. ".if 0").
1928 if (TheCondState.Ignore) {
1929 eatToEndOfStatement();
1930 return false;
1931 }
1932
1933 // FIXME: Recurse on local labels?
1934
1935 // Check for a label.
1936 // ::= identifier ':'
1937 // ::= number ':'
1938 if (Lexer.is(AsmToken::Colon) && getTargetParser().isLabel(ID)) {
1939 if (checkForValidSection())
1940 return true;
1941
1942 // identifier ':' -> Label.
1943 Lex();
1944
1945 // Diagnose attempt to use '.' as a label.
1946 if (IDVal == ".")
1947 return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
1948
1949 // Diagnose attempt to use a variable as a label.
1950 //
1951 // FIXME: Diagnostics. Note the location of the definition as a label.
1952 // FIXME: This doesn't diagnose assignment to a symbol which has been
1953 // implicitly marked as external.
1954 MCSymbol *Sym;
1955 if (ParsingMSInlineAsm && SI) {
1956 StringRef RewrittenLabel =
1957 SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
1958 assert(!RewrittenLabel.empty() &&
1959 "We should have an internal name here.");
1960 Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),
1961 RewrittenLabel);
1962 IDVal = RewrittenLabel;
1963 }
1964 // Handle directional local labels
1965 if (IDVal == "@@") {
1967 } else {
1968 Sym = getContext().getOrCreateSymbol(IDVal);
1969 }
1970
1971 // End of Labels should be treated as end of line for lexing
1972 // purposes but that information is not available to the Lexer who
1973 // does not understand Labels. This may cause us to see a Hash
1974 // here instead of a preprocessor line comment.
1975 if (getTok().is(AsmToken::Hash)) {
1976 std::string CommentStr = parseStringTo(AsmToken::EndOfStatement);
1977 Lexer.Lex();
1978 Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
1979 }
1980
1981 // Consume any end of statement token, if present, to avoid spurious
1982 // addBlankLine calls().
1983 if (getTok().is(AsmToken::EndOfStatement)) {
1984 Lex();
1985 }
1986
1987 // Emit the label.
1988 if (!getTargetParser().isParsingMSInlineAsm())
1989 Out.emitLabel(Sym, IDLoc);
1990 return false;
1991 }
1992
1993 // If macros are enabled, check to see if this is a macro instantiation.
1994 if (const MCAsmMacro *M = getContext().lookupMacro(IDVal.lower())) {
1995 AsmToken::TokenKind ArgumentEndTok = parseOptionalToken(AsmToken::LParen)
1998 return handleMacroEntry(M, IDLoc, ArgumentEndTok);
1999 }
2000
2001 // Otherwise, we have a normal instruction or directive.
2002
2003 if (DirKind != DK_NO_DIRECTIVE) {
2004 // There are several entities interested in parsing directives:
2005 //
2006 // 1. Asm parser extensions. For example, platform-specific parsers
2007 // (like the ELF parser) register themselves as extensions.
2008 // 2. The target-specific assembly parser. Some directives are target
2009 // specific or may potentially behave differently on certain targets.
2010 // 3. The generic directive parser implemented by this class. These are
2011 // all the directives that behave in a target and platform independent
2012 // manner, or at least have a default behavior that's shared between
2013 // all targets and platforms.
2014
2015 // Special-case handling of structure-end directives at higher priority,
2016 // since ENDS is overloaded as a segment-end directive.
2017 if (IDVal.equals_insensitive("ends") && StructInProgress.size() > 1 &&
2018 getTok().is(AsmToken::EndOfStatement)) {
2019 return parseDirectiveNestedEnds();
2020 }
2021
2022 // First, check the extension directive map to see if any extension has
2023 // registered itself to parse this directive.
2024 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2025 ExtensionDirectiveMap.lookup(IDVal.lower());
2026 if (Handler.first)
2027 return (*Handler.second)(Handler.first, IDVal, IDLoc);
2028
2029 // Next, let the target-specific assembly parser try.
2030 if (ID.isNot(AsmToken::Identifier))
2031 return false;
2032
2033 ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(ID);
2034 assert(TPDirectiveReturn.isFailure() == hasPendingError() &&
2035 "Should only return Failure iff there was an error");
2036 if (TPDirectiveReturn.isFailure())
2037 return true;
2038 if (TPDirectiveReturn.isSuccess())
2039 return false;
2040
2041 // Finally, if no one else is interested in this directive, it must be
2042 // generic and familiar to this class.
2043 switch (DirKind) {
2044 default:
2045 break;
2046 case DK_ASCII:
2047 return parseDirectiveAscii(IDVal, false);
2048 case DK_ASCIZ:
2049 case DK_STRING:
2050 return parseDirectiveAscii(IDVal, true);
2051 case DK_BYTE:
2052 case DK_SBYTE:
2053 case DK_DB:
2054 return parseDirectiveValue(IDVal, 1);
2055 case DK_WORD:
2056 case DK_SWORD:
2057 case DK_DW:
2058 return parseDirectiveValue(IDVal, 2);
2059 case DK_DWORD:
2060 case DK_SDWORD:
2061 case DK_DD:
2062 return parseDirectiveValue(IDVal, 4);
2063 case DK_FWORD:
2064 case DK_DF:
2065 return parseDirectiveValue(IDVal, 6);
2066 case DK_QWORD:
2067 case DK_SQWORD:
2068 case DK_DQ:
2069 return parseDirectiveValue(IDVal, 8);
2070 case DK_REAL4:
2071 return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4);
2072 case DK_REAL8:
2073 return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8);
2074 case DK_REAL10:
2075 return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10);
2076 case DK_STRUCT:
2077 case DK_UNION:
2078 return parseDirectiveNestedStruct(IDVal, DirKind);
2079 case DK_ENDS:
2080 return parseDirectiveNestedEnds();
2081 case DK_ALIGN:
2082 return parseDirectiveAlign();
2083 case DK_EVEN:
2084 return parseDirectiveEven();
2085 case DK_ORG:
2086 return parseDirectiveOrg();
2087 case DK_EXTERN:
2088 return parseDirectiveExtern();
2089 case DK_PUBLIC:
2090 return parseDirectiveSymbolAttribute(MCSA_Global);
2091 case DK_COMM:
2092 return parseDirectiveComm(/*IsLocal=*/false);
2093 case DK_COMMENT:
2094 return parseDirectiveComment(IDLoc);
2095 case DK_INCLUDE:
2096 return parseDirectiveInclude();
2097 case DK_REPEAT:
2098 return parseDirectiveRepeat(IDLoc, IDVal);
2099 case DK_WHILE:
2100 return parseDirectiveWhile(IDLoc);
2101 case DK_FOR:
2102 return parseDirectiveFor(IDLoc, IDVal);
2103 case DK_FORC:
2104 return parseDirectiveForc(IDLoc, IDVal);
2105 case DK_EXITM:
2106 Info.ExitValue = "";
2107 return parseDirectiveExitMacro(IDLoc, IDVal, *Info.ExitValue);
2108 case DK_ENDM:
2109 Info.ExitValue = "";
2110 return parseDirectiveEndMacro(IDVal);
2111 case DK_PURGE:
2112 return parseDirectivePurgeMacro(IDLoc);
2113 case DK_END:
2114 return parseDirectiveEnd(IDLoc);
2115 case DK_ERR:
2116 return parseDirectiveError(IDLoc);
2117 case DK_ERRB:
2118 return parseDirectiveErrorIfb(IDLoc, true);
2119 case DK_ERRNB:
2120 return parseDirectiveErrorIfb(IDLoc, false);
2121 case DK_ERRDEF:
2122 return parseDirectiveErrorIfdef(IDLoc, true);
2123 case DK_ERRNDEF:
2124 return parseDirectiveErrorIfdef(IDLoc, false);
2125 case DK_ERRDIF:
2126 return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false,
2127 /*CaseInsensitive=*/false);
2128 case DK_ERRDIFI:
2129 return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false,
2130 /*CaseInsensitive=*/true);
2131 case DK_ERRIDN:
2132 return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true,
2133 /*CaseInsensitive=*/false);
2134 case DK_ERRIDNI:
2135 return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true,
2136 /*CaseInsensitive=*/true);
2137 case DK_ERRE:
2138 return parseDirectiveErrorIfe(IDLoc, true);
2139 case DK_ERRNZ:
2140 return parseDirectiveErrorIfe(IDLoc, false);
2141 case DK_RADIX:
2142 return parseDirectiveRadix(IDLoc);
2143 case DK_ECHO:
2144 return parseDirectiveEcho(IDLoc);
2145 }
2146
2147 return Error(IDLoc, "unknown directive");
2148 }
2149
2150 // We also check if this is allocating memory with user-defined type.
2151 auto IDIt = Structs.find(IDVal.lower());
2152 if (IDIt != Structs.end())
2153 return parseDirectiveStructValue(/*Structure=*/IDIt->getValue(), IDVal,
2154 IDLoc);
2155
2156 // Non-conditional Microsoft directives sometimes follow their first argument.
2157 const AsmToken nextTok = getTok();
2158 const StringRef nextVal = nextTok.getString();
2159 const SMLoc nextLoc = nextTok.getLoc();
2160
2161 const AsmToken afterNextTok = peekTok();
2162
2163 // There are several entities interested in parsing infix directives:
2164 //
2165 // 1. Asm parser extensions. For example, platform-specific parsers
2166 // (like the ELF parser) register themselves as extensions.
2167 // 2. The generic directive parser implemented by this class. These are
2168 // all the directives that behave in a target and platform independent
2169 // manner, or at least have a default behavior that's shared between
2170 // all targets and platforms.
2171
2172 getTargetParser().flushPendingInstructions(getStreamer());
2173
2174 // Special-case handling of structure-end directives at higher priority, since
2175 // ENDS is overloaded as a segment-end directive.
2176 if (nextVal.equals_insensitive("ends") && StructInProgress.size() == 1) {
2177 Lex();
2178 return parseDirectiveEnds(IDVal, IDLoc);
2179 }
2180
2181 // First, check the extension directive map to see if any extension has
2182 // registered itself to parse this directive.
2183 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2184 ExtensionDirectiveMap.lookup(nextVal.lower());
2185 if (Handler.first) {
2186 Lex();
2187 Lexer.UnLex(ID);
2188 return (*Handler.second)(Handler.first, nextVal, nextLoc);
2189 }
2190
2191 // If no one else is interested in this directive, it must be
2192 // generic and familiar to this class.
2193 DirKindIt = DirectiveKindMap.find(nextVal.lower());
2194 DirKind = (DirKindIt == DirectiveKindMap.end())
2195 ? DK_NO_DIRECTIVE
2196 : DirKindIt->getValue();
2197 switch (DirKind) {
2198 default:
2199 break;
2200 case DK_ASSIGN:
2201 case DK_EQU:
2202 case DK_TEXTEQU:
2203 Lex();
2204 return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
2205 case DK_BYTE:
2206 if (afterNextTok.is(AsmToken::Identifier) &&
2207 afterNextTok.getString().equals_insensitive("ptr")) {
2208 // Size directive; part of an instruction.
2209 break;
2210 }
2211 [[fallthrough]];
2212 case DK_SBYTE:
2213 case DK_DB:
2214 Lex();
2215 return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc);
2216 case DK_WORD:
2217 if (afterNextTok.is(AsmToken::Identifier) &&
2218 afterNextTok.getString().equals_insensitive("ptr")) {
2219 // Size directive; part of an instruction.
2220 break;
2221 }
2222 [[fallthrough]];
2223 case DK_SWORD:
2224 case DK_DW:
2225 Lex();
2226 return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc);
2227 case DK_DWORD:
2228 if (afterNextTok.is(AsmToken::Identifier) &&
2229 afterNextTok.getString().equals_insensitive("ptr")) {
2230 // Size directive; part of an instruction.
2231 break;
2232 }
2233 [[fallthrough]];
2234 case DK_SDWORD:
2235 case DK_DD:
2236 Lex();
2237 return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc);
2238 case DK_FWORD:
2239 if (afterNextTok.is(AsmToken::Identifier) &&
2240 afterNextTok.getString().equals_insensitive("ptr")) {
2241 // Size directive; part of an instruction.
2242 break;
2243 }
2244 [[fallthrough]];
2245 case DK_DF:
2246 Lex();
2247 return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc);
2248 case DK_QWORD:
2249 if (afterNextTok.is(AsmToken::Identifier) &&
2250 afterNextTok.getString().equals_insensitive("ptr")) {
2251 // Size directive; part of an instruction.
2252 break;
2253 }
2254 [[fallthrough]];
2255 case DK_SQWORD:
2256 case DK_DQ:
2257 Lex();
2258 return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc);
2259 case DK_REAL4:
2260 Lex();
2261 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), 4,
2262 IDVal, IDLoc);
2263 case DK_REAL8:
2264 Lex();
2265 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8,
2266 IDVal, IDLoc);
2267 case DK_REAL10:
2268 Lex();
2269 return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(),
2270 10, IDVal, IDLoc);
2271 case DK_STRUCT:
2272 case DK_UNION:
2273 Lex();
2274 return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc);
2275 case DK_ENDS:
2276 Lex();
2277 return parseDirectiveEnds(IDVal, IDLoc);
2278 case DK_MACRO:
2279 Lex();
2280 return parseDirectiveMacro(IDVal, IDLoc);
2281 }
2282
2283 // Finally, we check if this is allocating a variable with user-defined type.
2284 auto NextIt = Structs.find(nextVal.lower());
2285 if (NextIt != Structs.end()) {
2286 Lex();
2287 return parseDirectiveNamedStructValue(/*Structure=*/NextIt->getValue(),
2288 nextVal, nextLoc, IDVal);
2289 }
2290
2291 // __asm _emit or __asm __emit
2292 if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
2293 IDVal == "_EMIT" || IDVal == "__EMIT"))
2294 return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
2295
2296 // __asm align
2297 if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
2298 return parseDirectiveMSAlign(IDLoc, Info);
2299
2300 if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
2301 Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
2302 if (checkForValidSection())
2303 return true;
2304
2305 // Canonicalize the opcode to lower case.
2306 std::string OpcodeStr = IDVal.lower();
2307 ParseInstructionInfo IInfo(Info.AsmRewrites);
2308 bool ParseHadError = getTargetParser().parseInstruction(IInfo, OpcodeStr, ID,
2309 Info.ParsedOperands);
2310 Info.ParseError = ParseHadError;
2311
2312 // Dump the parsed representation, if requested.
2313 if (getShowParsedOperands()) {
2314 SmallString<256> Str;
2316 OS << "parsed instruction: [";
2317 for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
2318 if (i != 0)
2319 OS << ", ";
2320 Info.ParsedOperands[i]->print(OS, MAI);
2321 }
2322 OS << "]";
2323
2324 printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
2325 }
2326
2327 // Fail even if ParseInstruction erroneously returns false.
2328 if (hasPendingError() || ParseHadError)
2329 return true;
2330
2331 // If parsing succeeded, match the instruction.
2332 if (!ParseHadError) {
2334 if (getTargetParser().matchAndEmitInstruction(
2335 IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
2336 getTargetParser().isParsingMSInlineAsm()))
2337 return true;
2338 }
2339 return false;
2340}
2341
2342// Parse and erase curly braces marking block start/end.
2343bool MasmParser::parseCurlyBlockScope(
2344 SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
2345 // Identify curly brace marking block start/end.
2346 if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
2347 return false;
2348
2349 SMLoc StartLoc = Lexer.getLoc();
2350 Lex(); // Eat the brace.
2351 if (Lexer.is(AsmToken::EndOfStatement))
2352 Lex(); // Eat EndOfStatement following the brace.
2353
2354 // Erase the block start/end brace from the output asm string.
2355 AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
2356 StartLoc.getPointer());
2357 return true;
2358}
2359
2360/// parseCppHashLineFilenameComment as this:
2361/// ::= # number "filename"
2362bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
2363 Lex(); // Eat the hash token.
2364 // Lexer only ever emits HashDirective if it fully formed if it's
2365 // done the checking already so this is an internal error.
2366 assert(getTok().is(AsmToken::Integer) &&
2367 "Lexing Cpp line comment: Expected Integer");
2368 int64_t LineNumber = getTok().getIntVal();
2369 Lex();
2370 assert(getTok().is(AsmToken::String) &&
2371 "Lexing Cpp line comment: Expected String");
2372 StringRef Filename = getTok().getString();
2373 Lex();
2374
2375 // Get rid of the enclosing quotes.
2376 Filename = Filename.substr(1, Filename.size() - 2);
2377
2378 // Save the SMLoc, Filename and LineNumber for later use by diagnostics
2379 // and possibly DWARF file info.
2380 CppHashInfo.Loc = L;
2381 CppHashInfo.Filename = Filename;
2382 CppHashInfo.LineNumber = LineNumber;
2383 CppHashInfo.Buf = CurBuffer;
2384 if (FirstCppHashFilename.empty())
2385 FirstCppHashFilename = Filename;
2386 return false;
2387}
2388
2389/// will use the last parsed cpp hash line filename comment
2390/// for the Filename and LineNo if any in the diagnostic.
2391void MasmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
2392 const MasmParser *Parser = static_cast<const MasmParser *>(Context);
2393 raw_ostream &OS = errs();
2394
2395 const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
2396 SMLoc DiagLoc = Diag.getLoc();
2397 unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
2398 unsigned CppHashBuf =
2399 Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
2400
2401 // Like SourceMgr::printMessage() we need to print the include stack if any
2402 // before printing the message.
2403 unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
2404 if (!Parser->SavedDiagHandler && DiagCurBuffer &&
2405 DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
2406 SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
2407 DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
2408 }
2409
2410 // If we have not parsed a cpp hash line filename comment or the source
2411 // manager changed or buffer changed (like in a nested include) then just
2412 // print the normal diagnostic using its Filename and LineNo.
2413 if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
2414 DiagBuf != CppHashBuf) {
2415 if (Parser->SavedDiagHandler)
2416 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2417 else
2418 Diag.print(nullptr, OS);
2419 return;
2420 }
2421
2422 // Use the CppHashFilename and calculate a line number based on the
2423 // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
2424 // for the diagnostic.
2425 const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
2426
2427 int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
2428 int CppHashLocLineNo =
2429 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2430 int LineNo =
2431 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2432
2433 SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
2434 Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
2435 Diag.getLineContents(), Diag.getRanges());
2436
2437 if (Parser->SavedDiagHandler)
2438 Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
2439 else
2440 NewDiag.print(nullptr, OS);
2441}
2442
2443// This is similar to the IsIdentifierChar function in AsmLexer.cpp, but does
2444// not accept '.'.
2445static bool isMacroParameterChar(char C) {
2446 return isAlnum(C) || C == '_' || C == '$' || C == '@' || C == '?';
2447}
2448
2449bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
2452 const std::vector<std::string> &Locals, SMLoc L) {
2453 unsigned NParameters = Parameters.size();
2454 if (NParameters != A.size())
2455 return Error(L, "Wrong number of arguments");
2456 StringMap<std::string> LocalSymbols;
2457 std::string Name;
2458 Name.reserve(6);
2459 for (StringRef Local : Locals) {
2461 LocalName << "??"
2462 << format_hex_no_prefix(LocalCounter++, 4, /*Upper=*/true);
2463 LocalSymbols.insert({Local, Name});
2464 Name.clear();
2465 }
2466
2467 std::optional<char> CurrentQuote;
2468 while (!Body.empty()) {
2469 // Scan for the next substitution.
2470 std::size_t End = Body.size(), Pos = 0;
2471 std::size_t IdentifierPos = End;
2472 for (; Pos != End; ++Pos) {
2473 // Find the next possible macro parameter, including preceding a '&'
2474 // inside quotes.
2475 if (Body[Pos] == '&')
2476 break;
2477 if (isMacroParameterChar(Body[Pos])) {
2478 if (!CurrentQuote)
2479 break;
2480 if (IdentifierPos == End)
2481 IdentifierPos = Pos;
2482 } else {
2483 IdentifierPos = End;
2484 }
2485
2486 // Track quotation status
2487 if (!CurrentQuote) {
2488 if (Body[Pos] == '\'' || Body[Pos] == '"')
2489 CurrentQuote = Body[Pos];
2490 } else if (Body[Pos] == CurrentQuote) {
2491 if (Pos + 1 != End && Body[Pos + 1] == CurrentQuote) {
2492 // Escaped quote, and quotes aren't identifier chars; skip
2493 ++Pos;
2494 continue;
2495 } else {
2496 CurrentQuote.reset();
2497 }
2498 }
2499 }
2500 if (IdentifierPos != End) {
2501 // We've recognized an identifier before an apostrophe inside quotes;
2502 // check once to see if we can expand it.
2503 Pos = IdentifierPos;
2504 IdentifierPos = End;
2505 }
2506
2507 // Add the prefix.
2508 OS << Body.slice(0, Pos);
2509
2510 // Check if we reached the end.
2511 if (Pos == End)
2512 break;
2513
2514 unsigned I = Pos;
2515 bool InitialAmpersand = (Body[I] == '&');
2516 if (InitialAmpersand) {
2517 ++I;
2518 ++Pos;
2519 }
2520 while (I < End && isMacroParameterChar(Body[I]))
2521 ++I;
2522
2523 const char *Begin = Body.data() + Pos;
2524 StringRef Argument(Begin, I - Pos);
2525 const std::string ArgumentLower = Argument.lower();
2526 unsigned Index = 0;
2527
2528 for (; Index < NParameters; ++Index)
2529 if (Parameters[Index].Name.equals_insensitive(ArgumentLower))
2530 break;
2531
2532 if (Index == NParameters) {
2533 if (InitialAmpersand)
2534 OS << '&';
2535 auto it = LocalSymbols.find(ArgumentLower);
2536 if (it != LocalSymbols.end())
2537 OS << it->second;
2538 else
2539 OS << Argument;
2540 Pos = I;
2541 } else {
2542 for (const AsmToken &Token : A[Index]) {
2543 // In MASM, you can write '%expr'.
2544 // The prefix '%' evaluates the expression 'expr'
2545 // and uses the result as a string (e.g. replace %(1+2) with the
2546 // string "3").
2547 // Here, we identify the integer token which is the result of the
2548 // absolute expression evaluation and replace it with its string
2549 // representation.
2550 if (Token.getString().front() == '%' && Token.is(AsmToken::Integer))
2551 // Emit an integer value to the buffer.
2552 OS << Token.getIntVal();
2553 else
2554 OS << Token.getString();
2555 }
2556
2557 Pos += Argument.size();
2558 if (Pos < End && Body[Pos] == '&') {
2559 ++Pos;
2560 }
2561 }
2562 // Update the scan point.
2563 Body = Body.substr(Pos);
2564 }
2565
2566 return false;
2567}
2568
2569bool MasmParser::parseMacroArgument(const MCAsmMacroParameter *MP,
2570 MCAsmMacroArgument &MA,
2571 AsmToken::TokenKind EndTok) {
2572 if (MP && MP->Vararg) {
2573 if (Lexer.isNot(EndTok)) {
2574 SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok);
2575 for (StringRef S : Str) {
2576 MA.emplace_back(AsmToken::String, S);
2577 }
2578 }
2579 return false;
2580 }
2581
2582 SMLoc StrLoc = Lexer.getLoc(), EndLoc;
2583 if (Lexer.is(AsmToken::Less) && isAngleBracketString(StrLoc, EndLoc)) {
2584 const char *StrChar = StrLoc.getPointer() + 1;
2585 const char *EndChar = EndLoc.getPointer() - 1;
2586 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
2587 /// Eat from '<' to '>'.
2588 Lex();
2589 MA.emplace_back(AsmToken::String, StringRef(StrChar, EndChar - StrChar));
2590 return false;
2591 }
2592
2593 unsigned ParenLevel = 0;
2594
2595 while (true) {
2596 if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
2597 return TokError("unexpected token");
2598
2599 if (ParenLevel == 0 && Lexer.is(AsmToken::Comma))
2600 break;
2601
2602 // handleMacroEntry relies on not advancing the lexer here
2603 // to be able to fill in the remaining default parameter values
2604 if (Lexer.is(EndTok) && (EndTok != AsmToken::RParen || ParenLevel == 0))
2605 break;
2606
2607 // Adjust the current parentheses level.
2608 if (Lexer.is(AsmToken::LParen))
2609 ++ParenLevel;
2610 else if (Lexer.is(AsmToken::RParen) && ParenLevel)
2611 --ParenLevel;
2612
2613 // Append the token to the current argument list.
2614 MA.push_back(getTok());
2615 Lex();
2616 }
2617
2618 if (ParenLevel != 0)
2619 return TokError("unbalanced parentheses in argument");
2620
2621 if (MA.empty() && MP) {
2622 if (MP->Required) {
2623 return TokError("missing value for required parameter '" + MP->Name +
2624 "'");
2625 } else {
2626 MA = MP->Value;
2627 }
2628 }
2629 return false;
2630}
2631
2632// Parse the macro instantiation arguments.
2633bool MasmParser::parseMacroArguments(const MCAsmMacro *M,
2634 MCAsmMacroArguments &A,
2635 AsmToken::TokenKind EndTok) {
2636 const unsigned NParameters = M ? M->Parameters.size() : 0;
2637 bool NamedParametersFound = false;
2638 SmallVector<SMLoc, 4> FALocs;
2639
2640 A.resize(NParameters);
2641 FALocs.resize(NParameters);
2642
2643 // Parse two kinds of macro invocations:
2644 // - macros defined without any parameters accept an arbitrary number of them
2645 // - macros defined with parameters accept at most that many of them
2646 for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
2647 ++Parameter) {
2648 SMLoc IDLoc = Lexer.getLoc();
2650
2651 if (Lexer.is(AsmToken::Identifier) && peekTok().is(AsmToken::Equal)) {
2652 if (parseIdentifier(FA.Name))
2653 return Error(IDLoc, "invalid argument identifier for formal argument");
2654
2655 if (Lexer.isNot(AsmToken::Equal))
2656 return TokError("expected '=' after formal parameter identifier");
2657
2658 Lex();
2659
2660 NamedParametersFound = true;
2661 }
2662
2663 if (NamedParametersFound && FA.Name.empty())
2664 return Error(IDLoc, "cannot mix positional and keyword arguments");
2665
2666 unsigned PI = Parameter;
2667 if (!FA.Name.empty()) {
2668 assert(M && "expected macro to be defined");
2669 unsigned FAI = 0;
2670 for (FAI = 0; FAI < NParameters; ++FAI)
2671 if (M->Parameters[FAI].Name == FA.Name)
2672 break;
2673
2674 if (FAI >= NParameters) {
2675 return Error(IDLoc, "parameter named '" + FA.Name +
2676 "' does not exist for macro '" + M->Name + "'");
2677 }
2678 PI = FAI;
2679 }
2680 const MCAsmMacroParameter *MP = nullptr;
2681 if (M && PI < NParameters)
2682 MP = &M->Parameters[PI];
2683
2684 SMLoc StrLoc = Lexer.getLoc();
2685 SMLoc EndLoc;
2686 if (Lexer.is(AsmToken::Percent)) {
2687 const MCExpr *AbsoluteExp;
2688 int64_t Value;
2689 /// Eat '%'.
2690 Lex();
2691 if (parseExpression(AbsoluteExp, EndLoc))
2692 return false;
2693 if (!AbsoluteExp->evaluateAsAbsolute(Value,
2694 getStreamer().getAssemblerPtr()))
2695 return Error(StrLoc, "expected absolute expression");
2696 const char *StrChar = StrLoc.getPointer();
2697 const char *EndChar = EndLoc.getPointer();
2698 AsmToken newToken(AsmToken::Integer,
2699 StringRef(StrChar, EndChar - StrChar), Value);
2700 FA.Value.push_back(newToken);
2701 } else if (parseMacroArgument(MP, FA.Value, EndTok)) {
2702 if (M)
2703 return addErrorSuffix(" in '" + M->Name + "' macro");
2704 else
2705 return true;
2706 }
2707
2708 if (!FA.Value.empty()) {
2709 if (A.size() <= PI)
2710 A.resize(PI + 1);
2711 A[PI] = FA.Value;
2712
2713 if (FALocs.size() <= PI)
2714 FALocs.resize(PI + 1);
2715
2716 FALocs[PI] = Lexer.getLoc();
2717 }
2718
2719 // At the end of the statement, fill in remaining arguments that have
2720 // default values. If there aren't any, then the next argument is
2721 // required but missing
2722 if (Lexer.is(EndTok)) {
2723 bool Failure = false;
2724 for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
2725 if (A[FAI].empty()) {
2726 if (M->Parameters[FAI].Required) {
2727 Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
2728 "missing value for required parameter "
2729 "'" +
2730 M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
2731 Failure = true;
2732 }
2733
2734 if (!M->Parameters[FAI].Value.empty())
2735 A[FAI] = M->Parameters[FAI].Value;
2736 }
2737 }
2738 return Failure;
2739 }
2740
2741 if (Lexer.is(AsmToken::Comma))
2742 Lex();
2743 }
2744
2745 return TokError("too many positional arguments");
2746}
2747
2748bool MasmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc,
2749 AsmToken::TokenKind ArgumentEndTok) {
2750 // Arbitrarily limit macro nesting depth (default matches 'as'). We can
2751 // eliminate this, although we should protect against infinite loops.
2752 unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;
2753 if (ActiveMacros.size() == MaxNestingDepth) {
2754 std::ostringstream MaxNestingDepthError;
2755 MaxNestingDepthError << "macros cannot be nested more than "
2756 << MaxNestingDepth << " levels deep."
2757 << " Use -asm-macro-max-nesting-depth to increase "
2758 "this limit.";
2759 return TokError(MaxNestingDepthError.str());
2760 }
2761
2762 MCAsmMacroArguments A;
2763 if (parseMacroArguments(M, A, ArgumentEndTok) || parseToken(ArgumentEndTok))
2764 return true;
2765
2766 // Macro instantiation is lexical, unfortunately. We construct a new buffer
2767 // to hold the macro body with substitutions.
2768 SmallString<256> Buf;
2769 StringRef Body = M->Body;
2771
2772 if (expandMacro(OS, Body, M->Parameters, A, M->Locals, getTok().getLoc()))
2773 return true;
2774
2775 // We include the endm in the buffer as our cue to exit the macro
2776 // instantiation.
2777 OS << "endm\n";
2778
2779 std::unique_ptr<MemoryBuffer> Instantiation =
2780 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
2781
2782 // Create the macro instantiation object and add to the current macro
2783 // instantiation stack.
2784 MacroInstantiation *MI = new MacroInstantiation{
2785 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
2786 ActiveMacros.push_back(MI);
2787
2788 ++NumOfMacroInstantiations;
2789
2790 // Jump to the macro instantiation and prime the lexer.
2791 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
2792 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
2793 EndStatementAtEOFStack.push_back(true);
2794 Lex();
2795
2796 return false;
2797}
2798
2799void MasmParser::handleMacroExit() {
2800 // Jump to the token we should return to, and consume it.
2801 EndStatementAtEOFStack.pop_back();
2802 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer,
2803 EndStatementAtEOFStack.back());
2804 Lex();
2805
2806 // Pop the instantiation entry.
2807 delete ActiveMacros.back();
2808 ActiveMacros.pop_back();
2809}
2810
2811bool MasmParser::handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc) {
2812 if (!M->IsFunction)
2813 return Error(NameLoc, "cannot invoke macro procedure as function");
2814
2815 if (parseToken(AsmToken::LParen, "invoking macro function '" + M->Name +
2816 "' requires arguments in parentheses") ||
2817 handleMacroEntry(M, NameLoc, AsmToken::RParen))
2818 return true;
2819
2820 // Parse all statements in the macro, retrieving the exit value when it ends.
2821 std::string ExitValue;
2822 SmallVector<AsmRewrite, 4> AsmStrRewrites;
2823 while (Lexer.isNot(AsmToken::Eof)) {
2824 ParseStatementInfo Info(&AsmStrRewrites);
2825 bool HasError = parseStatement(Info, nullptr);
2826
2827 if (!HasError && Info.ExitValue) {
2828 ExitValue = std::move(*Info.ExitValue);
2829 break;
2830 }
2831
2832 // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
2833 // for printing ErrMsg via Lex() only if no (presumably better) parser error
2834 // exists.
2835 if (HasError && !hasPendingError() && Lexer.getTok().is(AsmToken::Error))
2836 Lex();
2837
2838 // parseStatement returned true so may need to emit an error.
2839 printPendingErrors();
2840
2841 // Skipping to the next line if needed.
2842 if (HasError && !getLexer().justConsumedEOL())
2843 eatToEndOfStatement();
2844 }
2845
2846 // Exit values may require lexing, unfortunately. We construct a new buffer to
2847 // hold the exit value.
2848 std::unique_ptr<MemoryBuffer> MacroValue =
2849 MemoryBuffer::getMemBufferCopy(ExitValue, "<macro-value>");
2850
2851 // Jump from this location to the instantiated exit value, and prime the
2852 // lexer.
2853 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(MacroValue), Lexer.getLoc());
2854 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), nullptr,
2855 /*EndStatementAtEOF=*/false);
2856 EndStatementAtEOFStack.push_back(false);
2857 Lex();
2858
2859 return false;
2860}
2861
2862/// parseIdentifier:
2863/// ::= identifier
2864/// ::= string
2865bool MasmParser::parseIdentifier(StringRef &Res,
2866 IdentifierPositionKind Position) {
2867 // The assembler has relaxed rules for accepting identifiers, in particular we
2868 // allow things like '.globl $foo' and '.def @feat.00', which would normally
2869 // be separate tokens. At this level, we have already lexed so we cannot
2870 // (currently) handle this as a context dependent token, instead we detect
2871 // adjacent tokens and return the combined identifier.
2872 if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
2873 SMLoc PrefixLoc = getLexer().getLoc();
2874
2875 // Consume the prefix character, and check for a following identifier.
2876
2877 AsmToken nextTok = peekTok(false);
2878
2879 if (nextTok.isNot(AsmToken::Identifier))
2880 return true;
2881
2882 // We have a '$' or '@' followed by an identifier, make sure they are adjacent.
2883 if (PrefixLoc.getPointer() + 1 != nextTok.getLoc().getPointer())
2884 return true;
2885
2886 // eat $ or @
2887 Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
2888 // Construct the joined identifier and consume the token.
2889 Res =
2890 StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1);
2891 Lex(); // Parser Lex to maintain invariants.
2892 return false;
2893 }
2894
2895 if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
2896 return true;
2897
2898 Res = getTok().getIdentifier();
2899
2900 // Consume the identifier token - but if parsing certain directives, avoid
2901 // lexical expansion of the next token.
2902 ExpandKind ExpandNextToken = ExpandMacros;
2903 if (Position == StartOfStatement &&
2905 .CaseLower("echo", true)
2906 .CasesLower("ifdef", "ifndef", "elseifdef", "elseifndef", true)
2907 .Default(false)) {
2908 ExpandNextToken = DoNotExpandMacros;
2909 }
2910 Lex(ExpandNextToken);
2911
2912 return false;
2913}
2914
2915/// parseDirectiveEquate:
2916/// ::= name "=" expression
2917/// | name "equ" expression (not redefinable)
2918/// | name "equ" text-list
2919/// | name "textequ" text-list (redefinability unspecified)
2920bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
2921 DirectiveKind DirKind, SMLoc NameLoc) {
2922 auto BuiltinIt = BuiltinSymbolMap.find(Name.lower());
2923 if (BuiltinIt != BuiltinSymbolMap.end())
2924 return Error(NameLoc, "cannot redefine a built-in symbol");
2925
2926 Variable &Var = Variables[Name.lower()];
2927 if (Var.Name.empty()) {
2928 Var.Name = Name;
2929 }
2930
2931 SMLoc StartLoc = Lexer.getLoc();
2932 if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) {
2933 // "equ" and "textequ" both allow text expressions.
2934 std::string Value;
2935 std::string TextItem;
2936 if (!parseTextItem(TextItem)) {
2937 Value += TextItem;
2938
2939 // Accept a text-list, not just one text-item.
2940 auto parseItem = [&]() -> bool {
2941 if (parseTextItem(TextItem))
2942 return TokError("expected text item");
2943 Value += TextItem;
2944 return false;
2945 };
2946 if (parseOptionalToken(AsmToken::Comma) && parseMany(parseItem))
2947 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
2948
2949 if (!Var.IsText || Var.TextValue != Value) {
2950 switch (Var.Redefinable) {
2951 case Variable::NOT_REDEFINABLE:
2952 return Error(getTok().getLoc(), "invalid variable redefinition");
2953 case Variable::WARN_ON_REDEFINITION:
2954 if (Warning(NameLoc, "redefining '" + Name +
2955 "', already defined on the command line")) {
2956 return true;
2957 }
2958 break;
2959 default:
2960 break;
2961 }
2962 }
2963 Var.IsText = true;
2964 Var.TextValue = Value;
2965 Var.Redefinable = Variable::REDEFINABLE;
2966
2967 return false;
2968 }
2969 }
2970 if (DirKind == DK_TEXTEQU)
2971 return TokError("expected <text> in '" + Twine(IDVal) + "' directive");
2972
2973 // Parse as expression assignment.
2974 const MCExpr *Expr;
2975 SMLoc EndLoc;
2976 if (parseExpression(Expr, EndLoc))
2977 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
2978 StringRef ExprAsString = StringRef(
2979 StartLoc.getPointer(), EndLoc.getPointer() - StartLoc.getPointer());
2980
2981 int64_t Value;
2982 if (!Expr->evaluateAsAbsolute(Value, getStreamer().getAssemblerPtr())) {
2983 if (DirKind == DK_ASSIGN)
2984 return Error(
2985 StartLoc,
2986 "expected absolute expression; not all symbols have known values",
2987 {StartLoc, EndLoc});
2988
2989 // Not an absolute expression; define as a text replacement.
2990 if (!Var.IsText || Var.TextValue != ExprAsString) {
2991 switch (Var.Redefinable) {
2992 case Variable::NOT_REDEFINABLE:
2993 return Error(getTok().getLoc(), "invalid variable redefinition");
2994 case Variable::WARN_ON_REDEFINITION:
2995 if (Warning(NameLoc, "redefining '" + Name +
2996 "', already defined on the command line")) {
2997 return true;
2998 }
2999 break;
3000 default:
3001 break;
3002 }
3003 }
3004
3005 Var.IsText = true;
3006 Var.TextValue = ExprAsString.str();
3007 Var.Redefinable = Variable::REDEFINABLE;
3008
3009 return false;
3010 }
3011
3012 auto *Sym =
3013 static_cast<MCSymbolCOFF *>(getContext().getOrCreateSymbol(Var.Name));
3014 const MCConstantExpr *PrevValue =
3015 Sym->isVariable()
3016 ? dyn_cast_or_null<MCConstantExpr>(Sym->getVariableValue())
3017 : nullptr;
3018 if (Var.IsText || !PrevValue || PrevValue->getValue() != Value) {
3019 switch (Var.Redefinable) {
3020 case Variable::NOT_REDEFINABLE:
3021 return Error(getTok().getLoc(), "invalid variable redefinition");
3022 case Variable::WARN_ON_REDEFINITION:
3023 if (Warning(NameLoc, "redefining '" + Name +
3024 "', already defined on the command line")) {
3025 return true;
3026 }
3027 break;
3028 default:
3029 break;
3030 }
3031 }
3032
3033 Var.IsText = false;
3034 Var.TextValue.clear();
3035 Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE
3036 : Variable::NOT_REDEFINABLE;
3037
3038 Sym->setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE);
3039 Sym->setVariableValue(Expr);
3040 Sym->setExternal(false);
3041
3042 return false;
3043}
3044
3045bool MasmParser::parseEscapedString(std::string &Data) {
3046 if (check(getTok().isNot(AsmToken::String), "expected string"))
3047 return true;
3048
3049 Data = "";
3050 char Quote = getTok().getString().front();
3051 StringRef Str = getTok().getStringContents();
3052 Data.reserve(Str.size());
3053 for (size_t i = 0, e = Str.size(); i != e; ++i) {
3054 Data.push_back(Str[i]);
3055 if (Str[i] == Quote) {
3056 // MASM treats doubled delimiting quotes as an escaped delimiting quote.
3057 // If we're escaping the string's trailing delimiter, we're definitely
3058 // missing a quotation mark.
3059 if (i + 1 == Str.size())
3060 return Error(getTok().getLoc(), "missing quotation mark in string");
3061 if (Str[i + 1] == Quote)
3062 ++i;
3063 }
3064 }
3065
3066 Lex();
3067 return false;
3068}
3069
3070bool MasmParser::parseAngleBracketString(std::string &Data) {
3071 SMLoc EndLoc, StartLoc = getTok().getLoc();
3072 if (isAngleBracketString(StartLoc, EndLoc)) {
3073 const char *StartChar = StartLoc.getPointer() + 1;
3074 const char *EndChar = EndLoc.getPointer() - 1;
3075 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
3076 // Eat from '<' to '>'.
3077 Lex();
3078
3079 Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
3080 return false;
3081 }
3082 return true;
3083}
3084
3085/// textItem ::= textLiteral | textMacroID | % constExpr
3086bool MasmParser::parseTextItem(std::string &Data) {
3087 switch (getTok().getKind()) {
3088 default:
3089 return true;
3090 case AsmToken::Percent: {
3091 int64_t Res;
3092 if (parseToken(AsmToken::Percent) || parseAbsoluteExpression(Res))
3093 return true;
3094 Data = std::to_string(Res);
3095 return false;
3096 }
3097 case AsmToken::Less:
3099 case AsmToken::LessLess:
3101 return parseAngleBracketString(Data);
3102 case AsmToken::Identifier: {
3103 // This must be a text macro; we need to expand it accordingly.
3104 StringRef ID;
3105 SMLoc StartLoc = getTok().getLoc();
3106 if (parseIdentifier(ID))
3107 return true;
3108 Data = ID.str();
3109
3110 bool Expanded = false;
3111 while (true) {
3112 // Try to resolve as a built-in text macro
3113 auto BuiltinIt = BuiltinSymbolMap.find(ID.lower());
3114 if (BuiltinIt != BuiltinSymbolMap.end()) {
3115 std::optional<std::string> BuiltinText =
3116 evaluateBuiltinTextMacro(BuiltinIt->getValue(), StartLoc);
3117 if (!BuiltinText) {
3118 // Not a text macro; break without substituting
3119 break;
3120 }
3121 Data = std::move(*BuiltinText);
3122 ID = StringRef(Data);
3123 Expanded = true;
3124 continue;
3125 }
3126
3127 // Try to resolve as a built-in macro function
3128 auto BuiltinFuncIt = BuiltinFunctionMap.find(ID.lower());
3129 if (BuiltinFuncIt != BuiltinFunctionMap.end()) {
3130 Data.clear();
3131 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), ID, Data)) {
3132 return true;
3133 }
3134 ID = StringRef(Data);
3135 Expanded = true;
3136 continue;
3137 }
3138
3139 // Try to resolve as a variable text macro
3140 auto VarIt = Variables.find(ID.lower());
3141 if (VarIt != Variables.end()) {
3142 const Variable &Var = VarIt->getValue();
3143 if (!Var.IsText) {
3144 // Not a text macro; break without substituting
3145 break;
3146 }
3147 Data = Var.TextValue;
3148 ID = StringRef(Data);
3149 Expanded = true;
3150 continue;
3151 }
3152
3153 break;
3154 }
3155
3156 if (!Expanded) {
3157 // Not a text macro; not usable in TextItem context. Since we haven't used
3158 // the token, put it back for better error recovery.
3159 getLexer().UnLex(AsmToken(AsmToken::Identifier, ID));
3160 return true;
3161 }
3162 return false;
3163 }
3164 }
3165 llvm_unreachable("unhandled token kind");
3166}
3167
3168/// parseDirectiveAscii:
3169/// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
3170bool MasmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
3171 auto parseOp = [&]() -> bool {
3172 std::string Data;
3173 if (checkForValidSection() || parseEscapedString(Data))
3174 return true;
3175 getStreamer().emitBytes(Data);
3176 if (ZeroTerminated)
3177 getStreamer().emitBytes(StringRef("\0", 1));
3178 return false;
3179 };
3180
3181 if (parseMany(parseOp))
3182 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3183 return false;
3184}
3185
3186bool MasmParser::emitIntValue(const MCExpr *Value, unsigned Size) {
3187 // Special case constant expressions to match code generator.
3188 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3189 assert(Size <= 8 && "Invalid size");
3190 int64_t IntValue = MCE->getValue();
3191 if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
3192 return Error(MCE->getLoc(), "out of range literal value");
3193 getStreamer().emitIntValue(IntValue, Size);
3194 } else {
3195 const MCSymbolRefExpr *MSE = dyn_cast<MCSymbolRefExpr>(Value);
3196 if (MSE && MSE->getSymbol().getName() == "?") {
3197 // ? initializer; treat as 0.
3198 getStreamer().emitIntValue(0, Size);
3199 } else {
3200 getStreamer().emitValue(Value, Size, Value->getLoc());
3201 }
3202 }
3203 return false;
3204}
3205
3206bool MasmParser::parseScalarInitializer(unsigned Size,
3208 unsigned StringPadLength) {
3209 if (Size == 1 && getTok().is(AsmToken::String)) {
3210 std::string Value;
3211 if (parseEscapedString(Value))
3212 return true;
3213 // Treat each character as an initializer.
3214 for (const unsigned char CharVal : Value)
3215 Values.push_back(MCConstantExpr::create(CharVal, getContext()));
3216
3217 // Pad the string with spaces to the specified length.
3218 for (size_t i = Value.size(); i < StringPadLength; ++i)
3219 Values.push_back(MCConstantExpr::create(' ', getContext()));
3220 } else {
3221 const MCExpr *Value;
3222 if (parseExpression(Value))
3223 return true;
3224 if (getTok().is(AsmToken::Identifier) &&
3225 getTok().getString().equals_insensitive("dup")) {
3226 Lex(); // Eat 'dup'.
3227 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
3228 if (!MCE)
3229 return Error(Value->getLoc(),
3230 "cannot repeat value a non-constant number of times");
3231 const int64_t Repetitions = MCE->getValue();
3232 if (Repetitions < 0)
3233 return Error(Value->getLoc(),
3234 "cannot repeat value a negative number of times");
3235
3236 SmallVector<const MCExpr *, 1> DuplicatedValues;
3237 if (parseToken(AsmToken::LParen,
3238 "parentheses required for 'dup' contents") ||
3239 parseScalarInstList(Size, DuplicatedValues) || parseRParen())
3240 return true;
3241
3242 for (int i = 0; i < Repetitions; ++i)
3243 Values.append(DuplicatedValues.begin(), DuplicatedValues.end());
3244 } else {
3245 Values.push_back(Value);
3246 }
3247 }
3248 return false;
3249}
3250
3251bool MasmParser::parseScalarInstList(unsigned Size,
3253 const AsmToken::TokenKind EndToken) {
3254 while (getTok().isNot(EndToken) &&
3255 (EndToken != AsmToken::Greater ||
3256 getTok().isNot(AsmToken::GreaterGreater))) {
3257 parseScalarInitializer(Size, Values);
3258
3259 // If we see a comma, continue, and allow line continuation.
3260 if (!parseOptionalToken(AsmToken::Comma))
3261 break;
3262 parseOptionalToken(AsmToken::EndOfStatement);
3263 }
3264 return false;
3265}
3266
3267bool MasmParser::emitIntegralValues(unsigned Size, unsigned *Count) {
3269 if (checkForValidSection() || parseScalarInstList(Size, Values))
3270 return true;
3271
3272 for (const auto *Value : Values) {
3273 emitIntValue(Value, Size);
3274 }
3275 if (Count)
3276 *Count = Values.size();
3277 return false;
3278}
3279
3280// Add a field to the current structure.
3281bool MasmParser::addIntegralField(StringRef Name, unsigned Size) {
3282 StructInfo &Struct = StructInProgress.back();
3283 FieldInfo &Field = Struct.addField(Name, FT_INTEGRAL, Size);
3284 IntFieldInfo &IntInfo = Field.Contents.IntInfo;
3285
3286 Field.Type = Size;
3287
3288 if (parseScalarInstList(Size, IntInfo.Values))
3289 return true;
3290
3291 Field.SizeOf = Field.Type * IntInfo.Values.size();
3292 Field.LengthOf = IntInfo.Values.size();
3293 const unsigned FieldEnd = Field.Offset + Field.SizeOf;
3294 if (!Struct.IsUnion) {
3295 Struct.NextOffset = FieldEnd;
3296 }
3297 Struct.Size = std::max(Struct.Size, FieldEnd);
3298 return false;
3299}
3300
3301/// parseDirectiveValue
3302/// ::= (byte | word | ... ) [ expression (, expression)* ]
3303bool MasmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
3304 if (StructInProgress.empty()) {
3305 // Initialize data value.
3306 if (emitIntegralValues(Size))
3307 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3308 } else if (addIntegralField("", Size)) {
3309 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3310 }
3311
3312 return false;
3313}
3314
3315/// parseDirectiveNamedValue
3316/// ::= name (byte | word | ... ) [ expression (, expression)* ]
3317bool MasmParser::parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
3318 StringRef Name, SMLoc NameLoc) {
3319 if (StructInProgress.empty()) {
3320 // Initialize named data value.
3321 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
3322 getStreamer().emitLabel(Sym);
3323 unsigned Count;
3324 if (emitIntegralValues(Size, &Count))
3325 return addErrorSuffix(" in '" + Twine(TypeName) + "' directive");
3326
3328 Type.Name = TypeName;
3329 Type.Size = Size * Count;
3330 Type.ElementSize = Size;
3331 Type.Length = Count;
3332 KnownType[Name.lower()] = Type;
3333 } else if (addIntegralField(Name, Size)) {
3334 return addErrorSuffix(" in '" + Twine(TypeName) + "' directive");
3335 }
3336
3337 return false;
3338}
3339
3340bool MasmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
3341 // We don't truly support arithmetic on floating point expressions, so we
3342 // have to manually parse unary prefixes.
3343 bool IsNeg = false;
3344 SMLoc SignLoc;
3345 if (getLexer().is(AsmToken::Minus)) {
3346 SignLoc = getLexer().getLoc();
3347 Lexer.Lex();
3348 IsNeg = true;
3349 } else if (getLexer().is(AsmToken::Plus)) {
3350 SignLoc = getLexer().getLoc();
3351 Lexer.Lex();
3352 }
3353
3354 if (Lexer.is(AsmToken::Error))
3355 return TokError(Lexer.getErr());
3356 if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
3357 Lexer.isNot(AsmToken::Identifier))
3358 return TokError("unexpected token in directive");
3359
3360 // Convert to an APFloat.
3361 APFloat Value(Semantics);
3362 StringRef IDVal = getTok().getString();
3363 if (getLexer().is(AsmToken::Identifier)) {
3364 if (IDVal.equals_insensitive("infinity") || IDVal.equals_insensitive("inf"))
3365 Value = APFloat::getInf(Semantics);
3366 else if (IDVal.equals_insensitive("nan"))
3367 Value = APFloat::getNaN(Semantics, false, ~0);
3368 else if (IDVal.equals_insensitive("?"))
3369 Value = APFloat::getZero(Semantics);
3370 else
3371 return TokError("invalid floating point literal");
3372 } else if (IDVal.consume_back("r") || IDVal.consume_back("R")) {
3373 // MASM hexadecimal floating-point literal; no APFloat conversion needed.
3374 // To match ML64.exe, ignore the initial sign.
3375 unsigned SizeInBits = Value.getSizeInBits(Semantics);
3376 if (SizeInBits != (IDVal.size() << 2))
3377 return TokError("invalid floating point literal");
3378
3379 // Consume the numeric token.
3380 Lex();
3381
3382 Res = APInt(SizeInBits, IDVal, 16);
3383 if (SignLoc.isValid())
3384 return Warning(SignLoc, "MASM-style hex floats ignore explicit sign");
3385 return false;
3386 } else if (errorToBool(
3387 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3388 .takeError())) {
3389 return TokError("invalid floating point literal");
3390 }
3391 if (IsNeg)
3392 Value.changeSign();
3393
3394 // Consume the numeric token.
3395 Lex();
3396
3397 Res = Value.bitcastToAPInt();
3398
3399 return false;
3400}
3401
3402bool MasmParser::parseRealInstList(const fltSemantics &Semantics,
3403 SmallVectorImpl<APInt> &ValuesAsInt,
3404 const AsmToken::TokenKind EndToken) {
3405 while (getTok().isNot(EndToken) ||
3406 (EndToken == AsmToken::Greater &&
3407 getTok().isNot(AsmToken::GreaterGreater))) {
3408 const AsmToken NextTok = peekTok();
3409 if (NextTok.is(AsmToken::Identifier) &&
3410 NextTok.getString().equals_insensitive("dup")) {
3411 const MCExpr *Value;
3412 if (parseExpression(Value) || parseToken(AsmToken::Identifier))
3413 return true;
3414 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
3415 if (!MCE)
3416 return Error(Value->getLoc(),
3417 "cannot repeat value a non-constant number of times");
3418 const int64_t Repetitions = MCE->getValue();
3419 if (Repetitions < 0)
3420 return Error(Value->getLoc(),
3421 "cannot repeat value a negative number of times");
3422
3423 SmallVector<APInt, 1> DuplicatedValues;
3424 if (parseToken(AsmToken::LParen,
3425 "parentheses required for 'dup' contents") ||
3426 parseRealInstList(Semantics, DuplicatedValues) || parseRParen())
3427 return true;
3428
3429 for (int i = 0; i < Repetitions; ++i)
3430 ValuesAsInt.append(DuplicatedValues.begin(), DuplicatedValues.end());
3431 } else {
3432 APInt AsInt;
3433 if (parseRealValue(Semantics, AsInt))
3434 return true;
3435 ValuesAsInt.push_back(AsInt);
3436 }
3437
3438 // Continue if we see a comma. (Also, allow line continuation.)
3439 if (!parseOptionalToken(AsmToken::Comma))
3440 break;
3441 parseOptionalToken(AsmToken::EndOfStatement);
3442 }
3443
3444 return false;
3445}
3446
3447// Initialize real data values.
3448bool MasmParser::emitRealValues(const fltSemantics &Semantics,
3449 unsigned *Count) {
3450 if (checkForValidSection())
3451 return true;
3452
3453 SmallVector<APInt, 1> ValuesAsInt;
3454 if (parseRealInstList(Semantics, ValuesAsInt))
3455 return true;
3456
3457 for (const APInt &AsInt : ValuesAsInt) {
3458 getStreamer().emitIntValue(AsInt);
3459 }
3460 if (Count)
3461 *Count = ValuesAsInt.size();
3462 return false;
3463}
3464
3465// Add a real field to the current struct.
3466bool MasmParser::addRealField(StringRef Name, const fltSemantics &Semantics,
3467 size_t Size) {
3468 StructInfo &Struct = StructInProgress.back();
3469 FieldInfo &Field = Struct.addField(Name, FT_REAL, Size);
3470 RealFieldInfo &RealInfo = Field.Contents.RealInfo;
3471
3472 Field.SizeOf = 0;
3473
3474 if (parseRealInstList(Semantics, RealInfo.AsIntValues))
3475 return true;
3476
3477 Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
3478 Field.LengthOf = RealInfo.AsIntValues.size();
3479 Field.SizeOf = Field.Type * Field.LengthOf;
3480
3481 const unsigned FieldEnd = Field.Offset + Field.SizeOf;
3482 if (!Struct.IsUnion) {
3483 Struct.NextOffset = FieldEnd;
3484 }
3485 Struct.Size = std::max(Struct.Size, FieldEnd);
3486 return false;
3487}
3488
3489/// parseDirectiveRealValue
3490/// ::= (real4 | real8 | real10) [ expression (, expression)* ]
3491bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
3492 const fltSemantics &Semantics,
3493 size_t Size) {
3494 if (StructInProgress.empty()) {
3495 // Initialize data value.
3496 if (emitRealValues(Semantics))
3497 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3498 } else if (addRealField("", Semantics, Size)) {
3499 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3500 }
3501 return false;
3502}
3503
3504/// parseDirectiveNamedRealValue
3505/// ::= name (real4 | real8 | real10) [ expression (, expression)* ]
3506bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
3507 const fltSemantics &Semantics,
3508 unsigned Size, StringRef Name,
3509 SMLoc NameLoc) {
3510 if (StructInProgress.empty()) {
3511 // Initialize named data value.
3512 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
3513 getStreamer().emitLabel(Sym);
3514 unsigned Count;
3515 if (emitRealValues(Semantics, &Count))
3516 return addErrorSuffix(" in '" + TypeName + "' directive");
3517
3519 Type.Name = TypeName;
3520 Type.Size = Size * Count;
3521 Type.ElementSize = Size;
3522 Type.Length = Count;
3523 KnownType[Name.lower()] = Type;
3524 } else if (addRealField(Name, Semantics, Size)) {
3525 return addErrorSuffix(" in '" + TypeName + "' directive");
3526 }
3527 return false;
3528}
3529
3530bool MasmParser::parseOptionalAngleBracketOpen() {
3531 const AsmToken Tok = getTok();
3532 if (parseOptionalToken(AsmToken::LessLess)) {
3533 AngleBracketDepth++;
3534 Lexer.UnLex(AsmToken(AsmToken::Less, Tok.getString().substr(1)));
3535 return true;
3536 } else if (parseOptionalToken(AsmToken::LessGreater)) {
3537 AngleBracketDepth++;
3538 Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1)));
3539 return true;
3540 } else if (parseOptionalToken(AsmToken::Less)) {
3541 AngleBracketDepth++;
3542 return true;
3543 }
3544
3545 return false;
3546}
3547
3548bool MasmParser::parseAngleBracketClose(const Twine &Msg) {
3549 const AsmToken Tok = getTok();
3550 if (parseOptionalToken(AsmToken::GreaterGreater)) {
3551 Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1)));
3552 } else if (parseToken(AsmToken::Greater, Msg)) {
3553 return true;
3554 }
3555 AngleBracketDepth--;
3556 return false;
3557}
3558
3559bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
3560 const IntFieldInfo &Contents,
3561 FieldInitializer &Initializer) {
3562 SMLoc Loc = getTok().getLoc();
3563
3565 if (parseOptionalToken(AsmToken::LCurly)) {
3566 if (Field.LengthOf == 1 && Field.Type > 1)
3567 return Error(Loc, "Cannot initialize scalar field with array value");
3568 if (parseScalarInstList(Field.Type, Values, AsmToken::RCurly) ||
3569 parseToken(AsmToken::RCurly))
3570 return true;
3571 } else if (parseOptionalAngleBracketOpen()) {
3572 if (Field.LengthOf == 1 && Field.Type > 1)
3573 return Error(Loc, "Cannot initialize scalar field with array value");
3574 if (parseScalarInstList(Field.Type, Values, AsmToken::Greater) ||
3575 parseAngleBracketClose())
3576 return true;
3577 } else if (Field.LengthOf > 1 && Field.Type > 1) {
3578 return Error(Loc, "Cannot initialize array field with scalar value");
3579 } else if (parseScalarInitializer(Field.Type, Values,
3580 /*StringPadLength=*/Field.LengthOf)) {
3581 return true;
3582 }
3583
3584 if (Values.size() > Field.LengthOf) {
3585 return Error(Loc, "Initializer too long for field; expected at most " +
3586 std::to_string(Field.LengthOf) + " elements, got " +
3587 std::to_string(Values.size()));
3588 }
3589 // Default-initialize all remaining values.
3590 Values.append(Contents.Values.begin() + Values.size(), Contents.Values.end());
3591
3592 Initializer = FieldInitializer(std::move(Values));
3593 return false;
3594}
3595
3596bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
3597 const RealFieldInfo &Contents,
3598 FieldInitializer &Initializer) {
3599 const fltSemantics *Semantics;
3600 switch (Field.Type) {
3601 case 4:
3602 Semantics = &APFloat::IEEEsingle();
3603 break;
3604 case 8:
3605 Semantics = &APFloat::IEEEdouble();
3606 break;
3607 case 10:
3608 Semantics = &APFloat::x87DoubleExtended();
3609 break;
3610 default:
3611 llvm_unreachable("unknown real field type");
3612 }
3613
3614 SMLoc Loc = getTok().getLoc();
3615
3616 SmallVector<APInt, 1> AsIntValues;
3617 if (parseOptionalToken(AsmToken::LCurly)) {
3618 if (Field.LengthOf == 1)
3619 return Error(Loc, "Cannot initialize scalar field with array value");
3620 if (parseRealInstList(*Semantics, AsIntValues, AsmToken::RCurly) ||
3621 parseToken(AsmToken::RCurly))
3622 return true;
3623 } else if (parseOptionalAngleBracketOpen()) {
3624 if (Field.LengthOf == 1)
3625 return Error(Loc, "Cannot initialize scalar field with array value");
3626 if (parseRealInstList(*Semantics, AsIntValues, AsmToken::Greater) ||
3627 parseAngleBracketClose())
3628 return true;
3629 } else if (Field.LengthOf > 1) {
3630 return Error(Loc, "Cannot initialize array field with scalar value");
3631 } else {
3632 AsIntValues.emplace_back();
3633 if (parseRealValue(*Semantics, AsIntValues.back()))
3634 return true;
3635 }
3636
3637 if (AsIntValues.size() > Field.LengthOf) {
3638 return Error(Loc, "Initializer too long for field; expected at most " +
3639 std::to_string(Field.LengthOf) + " elements, got " +
3640 std::to_string(AsIntValues.size()));
3641 }
3642 // Default-initialize all remaining values.
3643 AsIntValues.append(Contents.AsIntValues.begin() + AsIntValues.size(),
3644 Contents.AsIntValues.end());
3645
3646 Initializer = FieldInitializer(std::move(AsIntValues));
3647 return false;
3648}
3649
3650bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
3651 const StructFieldInfo &Contents,
3652 FieldInitializer &Initializer) {
3653 SMLoc Loc = getTok().getLoc();
3654
3655 std::vector<StructInitializer> Initializers;
3656 if (Field.LengthOf > 1) {
3657 if (parseOptionalToken(AsmToken::LCurly)) {
3658 if (parseStructInstList(Contents.Structure, Initializers,
3660 parseToken(AsmToken::RCurly))
3661 return true;
3662 } else if (parseOptionalAngleBracketOpen()) {
3663 if (parseStructInstList(Contents.Structure, Initializers,
3665 parseAngleBracketClose())
3666 return true;
3667 } else {
3668 return Error(Loc, "Cannot initialize array field with scalar value");
3669 }
3670 } else {
3671 Initializers.emplace_back();
3672 if (parseStructInitializer(Contents.Structure, Initializers.back()))
3673 return true;
3674 }
3675
3676 if (Initializers.size() > Field.LengthOf) {
3677 return Error(Loc, "Initializer too long for field; expected at most " +
3678 std::to_string(Field.LengthOf) + " elements, got " +
3679 std::to_string(Initializers.size()));
3680 }
3681 // Default-initialize all remaining values.
3682 llvm::append_range(Initializers, llvm::drop_begin(Contents.Initializers,
3683 Initializers.size()));
3684
3685 Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
3686 return false;
3687}
3688
3689bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
3690 FieldInitializer &Initializer) {
3691 switch (Field.Contents.FT) {
3692 case FT_INTEGRAL:
3693 return parseFieldInitializer(Field, Field.Contents.IntInfo, Initializer);
3694 case FT_REAL:
3695 return parseFieldInitializer(Field, Field.Contents.RealInfo, Initializer);
3696 case FT_STRUCT:
3697 return parseFieldInitializer(Field, Field.Contents.StructInfo, Initializer);
3698 }
3699 llvm_unreachable("Unhandled FieldType enum");
3700}
3701
3702bool MasmParser::parseStructInitializer(const StructInfo &Structure,
3703 StructInitializer &Initializer) {
3704 const AsmToken FirstToken = getTok();
3705
3706 std::optional<AsmToken::TokenKind> EndToken;
3707 if (parseOptionalToken(AsmToken::LCurly)) {
3708 EndToken = AsmToken::RCurly;
3709 } else if (parseOptionalAngleBracketOpen()) {
3710 EndToken = AsmToken::Greater;
3711 AngleBracketDepth++;
3712 } else if (FirstToken.is(AsmToken::Identifier) &&
3713 FirstToken.getString() == "?") {
3714 // ? initializer; leave EndToken uninitialized to treat as empty.
3715 if (parseToken(AsmToken::Identifier))
3716 return true;
3717 } else {
3718 return Error(FirstToken.getLoc(), "Expected struct initializer");
3719 }
3720
3721 auto &FieldInitializers = Initializer.FieldInitializers;
3722 size_t FieldIndex = 0;
3723 if (EndToken) {
3724 // Initialize all fields with given initializers.
3725 while (getTok().isNot(*EndToken) && FieldIndex < Structure.Fields.size()) {
3726 const FieldInfo &Field = Structure.Fields[FieldIndex++];
3727 if (parseOptionalToken(AsmToken::Comma)) {
3728 // Empty initializer; use the default and continue. (Also, allow line
3729 // continuation.)
3730 FieldInitializers.push_back(Field.Contents);
3731 parseOptionalToken(AsmToken::EndOfStatement);
3732 continue;
3733 }
3734 FieldInitializers.emplace_back(Field.Contents.FT);
3735 if (parseFieldInitializer(Field, FieldInitializers.back()))
3736 return true;
3737
3738 // Continue if we see a comma. (Also, allow line continuation.)
3739 SMLoc CommaLoc = getTok().getLoc();
3740 if (!parseOptionalToken(AsmToken::Comma))
3741 break;
3742 if (FieldIndex == Structure.Fields.size())
3743 return Error(CommaLoc, "'" + Structure.Name +
3744 "' initializer initializes too many fields");
3745 parseOptionalToken(AsmToken::EndOfStatement);
3746 }
3747 }
3748 // Default-initialize all remaining fields.
3749 for (const FieldInfo &Field : llvm::drop_begin(Structure.Fields, FieldIndex))
3750 FieldInitializers.push_back(Field.Contents);
3751
3752 if (EndToken) {
3753 if (*EndToken == AsmToken::Greater)
3754 return parseAngleBracketClose();
3755
3756 return parseToken(*EndToken);
3757 }
3758
3759 return false;
3760}
3761
3762bool MasmParser::parseStructInstList(
3763 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
3764 const AsmToken::TokenKind EndToken) {
3765 while (getTok().isNot(EndToken) ||
3766 (EndToken == AsmToken::Greater &&
3767 getTok().isNot(AsmToken::GreaterGreater))) {
3768 const AsmToken NextTok = peekTok();
3769 if (NextTok.is(AsmToken::Identifier) &&
3770 NextTok.getString().equals_insensitive("dup")) {
3771 const MCExpr *Value;
3772 if (parseExpression(Value) || parseToken(AsmToken::Identifier))
3773 return true;
3774 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
3775 if (!MCE)
3776 return Error(Value->getLoc(),
3777 "cannot repeat value a non-constant number of times");
3778 const int64_t Repetitions = MCE->getValue();
3779 if (Repetitions < 0)
3780 return Error(Value->getLoc(),
3781 "cannot repeat value a negative number of times");
3782
3783 std::vector<StructInitializer> DuplicatedValues;
3784 if (parseToken(AsmToken::LParen,
3785 "parentheses required for 'dup' contents") ||
3786 parseStructInstList(Structure, DuplicatedValues) || parseRParen())
3787 return true;
3788
3789 for (int i = 0; i < Repetitions; ++i)
3790 llvm::append_range(Initializers, DuplicatedValues);
3791 } else {
3792 Initializers.emplace_back();
3793 if (parseStructInitializer(Structure, Initializers.back()))
3794 return true;
3795 }
3796
3797 // Continue if we see a comma. (Also, allow line continuation.)
3798 if (!parseOptionalToken(AsmToken::Comma))
3799 break;
3800 parseOptionalToken(AsmToken::EndOfStatement);
3801 }
3802
3803 return false;
3804}
3805
3806bool MasmParser::emitFieldValue(const FieldInfo &Field,
3807 const IntFieldInfo &Contents) {
3808 // Default-initialize all values.
3809 for (const MCExpr *Value : Contents.Values) {
3810 if (emitIntValue(Value, Field.Type))
3811 return true;
3812 }
3813 return false;
3814}
3815
3816bool MasmParser::emitFieldValue(const FieldInfo &Field,
3817 const RealFieldInfo &Contents) {
3818 for (const APInt &AsInt : Contents.AsIntValues) {
3819 getStreamer().emitIntValue(AsInt.getLimitedValue(),
3820 AsInt.getBitWidth() / 8);
3821 }
3822 return false;
3823}
3824
3825bool MasmParser::emitFieldValue(const FieldInfo &Field,
3826 const StructFieldInfo &Contents) {
3827 for (const auto &Initializer : Contents.Initializers) {
3828 size_t Index = 0, Offset = 0;
3829 for (const auto &SubField : Contents.Structure.Fields) {
3830 getStreamer().emitZeros(SubField.Offset - Offset);
3831 Offset = SubField.Offset + SubField.SizeOf;
3832 emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
3833 }
3834 }
3835 return false;
3836}
3837
3838bool MasmParser::emitFieldValue(const FieldInfo &Field) {
3839 switch (Field.Contents.FT) {
3840 case FT_INTEGRAL:
3841 return emitFieldValue(Field, Field.Contents.IntInfo);
3842 case FT_REAL:
3843 return emitFieldValue(Field, Field.Contents.RealInfo);
3844 case FT_STRUCT:
3845 return emitFieldValue(Field, Field.Contents.StructInfo);
3846 }
3847 llvm_unreachable("Unhandled FieldType enum");
3848}
3849
3850bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
3851 const IntFieldInfo &Contents,
3852 const IntFieldInfo &Initializer) {
3853 for (const auto &Value : Initializer.Values) {
3854 if (emitIntValue(Value, Field.Type))
3855 return true;
3856 }
3857 // Default-initialize all remaining values.
3858 for (const auto &Value :
3859 llvm::drop_begin(Contents.Values, Initializer.Values.size())) {
3860 if (emitIntValue(Value, Field.Type))
3861 return true;
3862 }
3863 return false;
3864}
3865
3866bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
3867 const RealFieldInfo &Contents,
3868 const RealFieldInfo &Initializer) {
3869 for (const auto &AsInt : Initializer.AsIntValues) {
3870 getStreamer().emitIntValue(AsInt.getLimitedValue(),
3871 AsInt.getBitWidth() / 8);
3872 }
3873 // Default-initialize all remaining values.
3874 for (const auto &AsInt :
3875 llvm::drop_begin(Contents.AsIntValues, Initializer.AsIntValues.size())) {
3876 getStreamer().emitIntValue(AsInt.getLimitedValue(),
3877 AsInt.getBitWidth() / 8);
3878 }
3879 return false;
3880}
3881
3882bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
3883 const StructFieldInfo &Contents,
3884 const StructFieldInfo &Initializer) {
3885 for (const auto &Init : Initializer.Initializers) {
3886 if (emitStructInitializer(Contents.Structure, Init))
3887 return true;
3888 }
3889 // Default-initialize all remaining values.
3890 for (const auto &Init : llvm::drop_begin(Contents.Initializers,
3891 Initializer.Initializers.size())) {
3892 if (emitStructInitializer(Contents.Structure, Init))
3893 return true;
3894 }
3895 return false;
3896}
3897
3898bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
3899 const FieldInitializer &Initializer) {
3900 switch (Field.Contents.FT) {
3901 case FT_INTEGRAL:
3902 return emitFieldInitializer(Field, Field.Contents.IntInfo,
3903 Initializer.IntInfo);
3904 case FT_REAL:
3905 return emitFieldInitializer(Field, Field.Contents.RealInfo,
3906 Initializer.RealInfo);
3907 case FT_STRUCT:
3908 return emitFieldInitializer(Field, Field.Contents.StructInfo,
3909 Initializer.StructInfo);
3910 }
3911 llvm_unreachable("Unhandled FieldType enum");
3912}
3913
3914bool MasmParser::emitStructInitializer(const StructInfo &Structure,
3915 const StructInitializer &Initializer) {
3916 if (!Structure.Initializable)
3917 return Error(getLexer().getLoc(),
3918 "cannot initialize a value of type '" + Structure.Name +
3919 "'; 'org' was used in the type's declaration");
3920 size_t Index = 0, Offset = 0;
3921 for (const auto &Init : Initializer.FieldInitializers) {
3922 const auto &Field = Structure.Fields[Index++];
3923 getStreamer().emitZeros(Field.Offset - Offset);
3924 Offset = Field.Offset + Field.SizeOf;
3925 if (emitFieldInitializer(Field, Init))
3926 return true;
3927 }
3928 // Default-initialize all remaining fields.
3929 for (const auto &Field : llvm::drop_begin(
3930 Structure.Fields, Initializer.FieldInitializers.size())) {
3931 getStreamer().emitZeros(Field.Offset - Offset);
3932 Offset = Field.Offset + Field.SizeOf;
3933 if (emitFieldValue(Field))
3934 return true;
3935 }
3936 // Add final padding.
3937 if (Offset != Structure.Size)
3938 getStreamer().emitZeros(Structure.Size - Offset);
3939 return false;
3940}
3941
3942// Set data values from initializers.
3943bool MasmParser::emitStructValues(const StructInfo &Structure,
3944 unsigned *Count) {
3945 std::vector<StructInitializer> Initializers;
3946 if (parseStructInstList(Structure, Initializers))
3947 return true;
3948
3949 for (const auto &Initializer : Initializers) {
3950 if (emitStructInitializer(Structure, Initializer))
3951 return true;
3952 }
3953
3954 if (Count)
3955 *Count = Initializers.size();
3956 return false;
3957}
3958
3959// Declare a field in the current struct.
3960bool MasmParser::addStructField(StringRef Name, const StructInfo &Structure) {
3961 StructInfo &OwningStruct = StructInProgress.back();
3962 FieldInfo &Field =
3963 OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
3964 StructFieldInfo &StructInfo = Field.Contents.StructInfo;
3965
3966 StructInfo.Structure = Structure;
3967 Field.Type = Structure.Size;
3968
3969 if (parseStructInstList(Structure, StructInfo.Initializers))
3970 return true;
3971
3972 Field.LengthOf = StructInfo.Initializers.size();
3973 Field.SizeOf = Field.Type * Field.LengthOf;
3974
3975 const unsigned FieldEnd = Field.Offset + Field.SizeOf;
3976 if (!OwningStruct.IsUnion) {
3977 OwningStruct.NextOffset = FieldEnd;
3978 }
3979 OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd);
3980
3981 return false;
3982}
3983
3984/// parseDirectiveStructValue
3985/// ::= struct-id (<struct-initializer> | {struct-initializer})
3986/// [, (<struct-initializer> | {struct-initializer})]*
3987bool MasmParser::parseDirectiveStructValue(const StructInfo &Structure,
3988 StringRef Directive, SMLoc DirLoc) {
3989 if (StructInProgress.empty()) {
3990 if (emitStructValues(Structure))
3991 return true;
3992 } else if (addStructField("", Structure)) {
3993 return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
3994 }
3995
3996 return false;
3997}
3998
3999/// parseDirectiveNamedValue
4000/// ::= name (byte | word | ... ) [ expression (, expression)* ]
4001bool MasmParser::parseDirectiveNamedStructValue(const StructInfo &Structure,
4003 SMLoc DirLoc, StringRef Name) {
4004 if (StructInProgress.empty()) {
4005 // Initialize named data value.
4006 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4007 getStreamer().emitLabel(Sym);
4008 unsigned Count;
4009 if (emitStructValues(Structure, &Count))
4010 return true;
4012 Type.Name = Structure.Name;
4013 Type.Size = Structure.Size * Count;
4014 Type.ElementSize = Structure.Size;
4015 Type.Length = Count;
4016 KnownType[Name.lower()] = Type;
4017 } else if (addStructField(Name, Structure)) {
4018 return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
4019 }
4020
4021 return false;
4022}
4023
4024/// parseDirectiveStruct
4025/// ::= <name> (STRUC | STRUCT | UNION) [fieldAlign] [, NONUNIQUE]
4026/// (dataDir | generalDir | offsetDir | nestedStruct)+
4027/// <name> ENDS
4028////// dataDir = data declaration
4029////// offsetDir = EVEN, ORG, ALIGN
4030bool MasmParser::parseDirectiveStruct(StringRef Directive,
4031 DirectiveKind DirKind, StringRef Name,
4032 SMLoc NameLoc) {
4033 // We ignore NONUNIQUE; we do not support OPTION M510 or OPTION OLDSTRUCTS
4034 // anyway, so all field accesses must be qualified.
4035 AsmToken NextTok = getTok();
4036 int64_t AlignmentValue = 1;
4037 if (NextTok.isNot(AsmToken::Comma) &&
4039 parseAbsoluteExpression(AlignmentValue)) {
4040 return addErrorSuffix(" in alignment value for '" + Twine(Directive) +
4041 "' directive");
4042 }
4043 if (!isPowerOf2_64(AlignmentValue)) {
4044 return Error(NextTok.getLoc(), "alignment must be a power of two; was " +
4045 std::to_string(AlignmentValue));
4046 }
4047
4049 SMLoc QualifierLoc;
4050 if (parseOptionalToken(AsmToken::Comma)) {
4051 QualifierLoc = getTok().getLoc();
4052 if (parseIdentifier(Qualifier))
4053 return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
4054 if (!Qualifier.equals_insensitive("nonunique"))
4055 return Error(QualifierLoc, "Unrecognized qualifier for '" +
4056 Twine(Directive) +
4057 "' directive; expected none or NONUNIQUE");
4058 }
4059
4060 if (parseEOL())
4061 return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
4062
4063 StructInProgress.emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
4064 return false;
4065}
4066
4067/// parseDirectiveNestedStruct
4068/// ::= (STRUC | STRUCT | UNION) [name]
4069/// (dataDir | generalDir | offsetDir | nestedStruct)+
4070/// ENDS
4071bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
4072 DirectiveKind DirKind) {
4073 if (StructInProgress.empty())
4074 return TokError("missing name in top-level '" + Twine(Directive) +
4075 "' directive");
4076
4078 if (getTok().is(AsmToken::Identifier)) {
4079 Name = getTok().getIdentifier();
4080 parseToken(AsmToken::Identifier);
4081 }
4082 if (parseEOL())
4083 return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
4084
4085 // Reserve space to ensure Alignment doesn't get invalidated when
4086 // StructInProgress grows.
4087 StructInProgress.reserve(StructInProgress.size() + 1);
4088 StructInProgress.emplace_back(Name, DirKind == DK_UNION,
4089 StructInProgress.back().Alignment);
4090 return false;
4091}
4092
4093bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
4094 if (StructInProgress.empty())
4095 return Error(NameLoc, "ENDS directive without matching STRUC/STRUCT/UNION");
4096 if (StructInProgress.size() > 1)
4097 return Error(NameLoc, "unexpected name in nested ENDS directive");
4098 if (StructInProgress.back().Name.compare_insensitive(Name))
4099 return Error(NameLoc, "mismatched name in ENDS directive; expected '" +
4100 StructInProgress.back().Name + "'");
4101 StructInfo Structure = StructInProgress.pop_back_val();
4102 // Pad to make the structure's size divisible by the smaller of its alignment
4103 // and the size of its largest field.
4104 Structure.Size = llvm::alignTo(
4105 Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
4106 Structs[Name.lower()] = Structure;
4107
4108 if (parseEOL())
4109 return addErrorSuffix(" in ENDS directive");
4110
4111 return false;
4112}
4113
4114bool MasmParser::parseDirectiveNestedEnds() {
4115 if (StructInProgress.empty())
4116 return TokError("ENDS directive without matching STRUC/STRUCT/UNION");
4117 if (StructInProgress.size() == 1)
4118 return TokError("missing name in top-level ENDS directive");
4119
4120 if (parseEOL())
4121 return addErrorSuffix(" in nested ENDS directive");
4122
4123 StructInfo Structure = StructInProgress.pop_back_val();
4124 // Pad to make the structure's size divisible by its alignment.
4125 Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment);
4126
4127 StructInfo &ParentStruct = StructInProgress.back();
4128 if (Structure.Name.empty()) {
4129 // Anonymous substructures' fields are addressed as if they belong to the
4130 // parent structure - so we transfer them to the parent here.
4131 const size_t OldFields = ParentStruct.Fields.size();
4132 ParentStruct.Fields.insert(
4133 ParentStruct.Fields.end(),
4134 std::make_move_iterator(Structure.Fields.begin()),
4135 std::make_move_iterator(Structure.Fields.end()));
4136 for (const auto &FieldByName : Structure.FieldsByName) {
4137 ParentStruct.FieldsByName[FieldByName.getKey()] =
4138 FieldByName.getValue() + OldFields;
4139 }
4140
4141 unsigned FirstFieldOffset = 0;
4142 if (!Structure.Fields.empty() && !ParentStruct.IsUnion) {
4143 FirstFieldOffset = llvm::alignTo(
4144 ParentStruct.NextOffset,
4145 std::min(ParentStruct.Alignment, Structure.AlignmentSize));
4146 }
4147
4148 if (ParentStruct.IsUnion) {
4149 ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
4150 } else {
4151 for (auto &Field : llvm::drop_begin(ParentStruct.Fields, OldFields))
4152 Field.Offset += FirstFieldOffset;
4153
4154 const unsigned StructureEnd = FirstFieldOffset + Structure.Size;
4155 if (!ParentStruct.IsUnion) {
4156 ParentStruct.NextOffset = StructureEnd;
4157 }
4158 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4159 }
4160 } else {
4161 FieldInfo &Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
4162 Structure.AlignmentSize);
4163 StructFieldInfo &StructInfo = Field.Contents.StructInfo;
4164 Field.Type = Structure.Size;
4165 Field.LengthOf = 1;
4166 Field.SizeOf = Structure.Size;
4167
4168 const unsigned StructureEnd = Field.Offset + Field.SizeOf;
4169 if (!ParentStruct.IsUnion) {
4170 ParentStruct.NextOffset = StructureEnd;
4171 }
4172 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4173
4174 StructInfo.Structure = Structure;
4175 StructInfo.Initializers.emplace_back();
4176 auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
4177 for (const auto &SubField : Structure.Fields) {
4178 FieldInitializers.push_back(SubField.Contents);
4179 }
4180 }
4181
4182 return false;
4183}
4184
4185/// parseDirectiveOrg
4186/// ::= org expression
4187bool MasmParser::parseDirectiveOrg() {
4188 const MCExpr *Offset;
4189 SMLoc OffsetLoc = Lexer.getLoc();
4190 if (checkForValidSection() || parseExpression(Offset))
4191 return true;
4192 if (parseEOL())
4193 return addErrorSuffix(" in 'org' directive");
4194
4195 if (StructInProgress.empty()) {
4196 // Not in a struct; change the offset for the next instruction or data
4197 if (checkForValidSection())
4198 return addErrorSuffix(" in 'org' directive");
4199
4200 getStreamer().emitValueToOffset(Offset, 0, OffsetLoc);
4201 } else {
4202 // Offset the next field of this struct
4203 StructInfo &Structure = StructInProgress.back();
4204 int64_t OffsetRes;
4205 if (!Offset->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr()))
4206 return Error(OffsetLoc,
4207 "expected absolute expression in 'org' directive");
4208 if (OffsetRes < 0)
4209 return Error(
4210 OffsetLoc,
4211 "expected non-negative value in struct's 'org' directive; was " +
4212 std::to_string(OffsetRes));
4213 Structure.NextOffset = static_cast<unsigned>(OffsetRes);
4214
4215 // ORG-affected structures cannot be initialized
4216 Structure.Initializable = false;
4217 }
4218
4219 return false;
4220}
4221
4222bool MasmParser::emitAlignTo(int64_t Alignment) {
4223 if (StructInProgress.empty()) {
4224 // Not in a struct; align the next instruction or data
4225 if (checkForValidSection())
4226 return true;
4227
4228 // Check whether we should use optimal code alignment for this align
4229 // directive.
4230 const MCSection *Section = getStreamer().getCurrentSectionOnly();
4231 if (MAI.useCodeAlign(*Section)) {
4232 getStreamer().emitCodeAlignment(Align(Alignment),
4233 &getTargetParser().getSTI(),
4234 /*MaxBytesToEmit=*/0);
4235 } else {
4236 // FIXME: Target specific behavior about how the "extra" bytes are filled.
4237 getStreamer().emitValueToAlignment(Align(Alignment), /*Value=*/0,
4238 /*ValueSize=*/1,
4239 /*MaxBytesToEmit=*/0);
4240 }
4241 } else {
4242 // Align the next field of this struct
4243 StructInfo &Structure = StructInProgress.back();
4244 Structure.NextOffset = llvm::alignTo(Structure.NextOffset, Alignment);
4245 }
4246
4247 return false;
4248}
4249
4250/// parseDirectiveAlign
4251/// ::= align expression
4252bool MasmParser::parseDirectiveAlign() {
4253 SMLoc AlignmentLoc = getLexer().getLoc();
4254 int64_t Alignment;
4255
4256 // Ignore empty 'align' directives.
4257 if (getTok().is(AsmToken::EndOfStatement)) {
4258 return Warning(AlignmentLoc,
4259 "align directive with no operand is ignored") &&
4260 parseEOL();
4261 }
4262 if (parseAbsoluteExpression(Alignment) || parseEOL())
4263 return addErrorSuffix(" in align directive");
4264
4265 // Always emit an alignment here even if we throw an error.
4266 bool ReturnVal = false;
4267
4268 // Reject alignments that aren't either a power of two or zero, for ML.exe
4269 // compatibility. Alignment of zero is silently rounded up to one.
4270 if (Alignment == 0)
4271 Alignment = 1;
4272 if (!isPowerOf2_64(Alignment))
4273 ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2; was " +
4274 std::to_string(Alignment));
4275
4276 if (emitAlignTo(Alignment))
4277 ReturnVal |= addErrorSuffix(" in align directive");
4278
4279 return ReturnVal;
4280}
4281
4282/// parseDirectiveEven
4283/// ::= even
4284bool MasmParser::parseDirectiveEven() {
4285 if (parseEOL() || emitAlignTo(2))
4286 return addErrorSuffix(" in even directive");
4287
4288 return false;
4289}
4290
4291/// parseDirectiveMacro
4292/// ::= name macro [parameters]
4293/// ["LOCAL" identifiers]
4294/// parameters ::= parameter [, parameter]*
4295/// parameter ::= name ":" qualifier
4296/// qualifier ::= "req" | "vararg" | "=" macro_argument
4297bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
4299 while (getLexer().isNot(AsmToken::EndOfStatement)) {
4300 if (!Parameters.empty() && Parameters.back().Vararg)
4301 return Error(Lexer.getLoc(),
4302 "Vararg parameter '" + Parameters.back().Name +
4303 "' should be last in the list of parameters");
4304
4305 MCAsmMacroParameter Parameter;
4306 if (parseIdentifier(Parameter.Name))
4307 return TokError("expected identifier in 'macro' directive");
4308
4309 // Emit an error if two (or more) named parameters share the same name.
4310 for (const MCAsmMacroParameter& CurrParam : Parameters)
4311 if (CurrParam.Name.equals_insensitive(Parameter.Name))
4312 return TokError("macro '" + Name + "' has multiple parameters"
4313 " named '" + Parameter.Name + "'");
4314
4315 if (Lexer.is(AsmToken::Colon)) {
4316 Lex(); // consume ':'
4317
4318 if (parseOptionalToken(AsmToken::Equal)) {
4319 // Default value
4320 SMLoc ParamLoc;
4321
4322 ParamLoc = Lexer.getLoc();
4323 if (parseMacroArgument(nullptr, Parameter.Value))
4324 return true;
4325 } else {
4326 SMLoc QualLoc;
4328
4329 QualLoc = Lexer.getLoc();
4330 if (parseIdentifier(Qualifier))
4331 return Error(QualLoc, "missing parameter qualifier for "
4332 "'" +
4333 Parameter.Name + "' in macro '" + Name +
4334 "'");
4335
4336 if (Qualifier.equals_insensitive("req"))
4337 Parameter.Required = true;
4338 else if (Qualifier.equals_insensitive("vararg"))
4339 Parameter.Vararg = true;
4340 else
4341 return Error(QualLoc,
4342 Qualifier + " is not a valid parameter qualifier for '" +
4343 Parameter.Name + "' in macro '" + Name + "'");
4344 }
4345 }
4346
4347 Parameters.push_back(std::move(Parameter));
4348
4349 if (getLexer().is(AsmToken::Comma))
4350 Lex();
4351 }
4352
4353 // Eat just the end of statement.
4354 Lexer.Lex();
4355
4356 std::vector<std::string> Locals;
4357 if (getTok().is(AsmToken::Identifier) &&
4358 getTok().getIdentifier().equals_insensitive("local")) {
4359 Lex(); // Eat the LOCAL directive.
4360
4361 StringRef ID;
4362 while (true) {
4363 if (parseIdentifier(ID))
4364 return true;
4365 Locals.push_back(ID.lower());
4366
4367 // If we see a comma, continue (and allow line continuation).
4368 if (!parseOptionalToken(AsmToken::Comma))
4369 break;
4370 parseOptionalToken(AsmToken::EndOfStatement);
4371 }
4372 }
4373
4374 // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors.
4375 AsmToken EndToken, StartToken = getTok();
4376 unsigned MacroDepth = 0;
4377 bool IsMacroFunction = false;
4378 // Lex the macro definition.
4379 while (true) {
4380 // Ignore Lexing errors in macros.
4381 while (Lexer.is(AsmToken::Error)) {
4382 Lexer.Lex();
4383 }
4384
4385 // Check whether we have reached the end of the file.
4386 if (getLexer().is(AsmToken::Eof))
4387 return Error(NameLoc, "no matching 'endm' in definition");
4388
4389 // Otherwise, check whether we have reached the 'endm'... and determine if
4390 // this is a macro function.
4391 if (getLexer().is(AsmToken::Identifier)) {
4392 if (getTok().getIdentifier().equals_insensitive("endm")) {
4393 if (MacroDepth == 0) { // Outermost macro.
4394 EndToken = getTok();
4395 Lexer.Lex();
4396 if (getLexer().isNot(AsmToken::EndOfStatement))
4397 return TokError("unexpected token in '" + EndToken.getIdentifier() +
4398 "' directive");
4399 break;
4400 } else {
4401 // Otherwise we just found the end of an inner macro.
4402 --MacroDepth;
4403 }
4404 } else if (getTok().getIdentifier().equals_insensitive("exitm")) {
4405 if (MacroDepth == 0 && peekTok().isNot(AsmToken::EndOfStatement)) {
4406 IsMacroFunction = true;
4407 }
4408 } else if (isMacroLikeDirective()) {
4409 // We allow nested macros. Those aren't instantiated until the
4410 // outermost macro is expanded so just ignore them for now.
4411 ++MacroDepth;
4412 }
4413 }
4414
4415 // Otherwise, scan til the end of the statement.
4416 eatToEndOfStatement();
4417 }
4418
4419 if (getContext().lookupMacro(Name.lower())) {
4420 return Error(NameLoc, "macro '" + Name + "' is already defined");
4421 }
4422
4423 const char *BodyStart = StartToken.getLoc().getPointer();
4424 const char *BodyEnd = EndToken.getLoc().getPointer();
4425 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4426 MCAsmMacro Macro(Name, Body, std::move(Parameters), std::move(Locals),
4427 IsMacroFunction);
4428 DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
4429 Macro.dump());
4430 getContext().defineMacro(Name.lower(), std::move(Macro));
4431 return false;
4432}
4433
4434/// parseDirectiveExitMacro
4435/// ::= "exitm" [textitem]
4436bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
4438 std::string &Value) {
4439 SMLoc EndLoc = getTok().getLoc();
4440 if (getTok().isNot(AsmToken::EndOfStatement) && parseTextItem(Value))
4441 return Error(EndLoc,
4442 "unable to parse text item in '" + Directive + "' directive");
4443 eatToEndOfStatement();
4444
4445 if (!isInsideMacroInstantiation())
4446 return TokError("unexpected '" + Directive + "' in file, "
4447 "no current macro definition");
4448
4449 // Exit all conditionals that are active in the current macro.
4450 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4451 TheCondState = TheCondStack.back();
4452 TheCondStack.pop_back();
4453 }
4454
4455 handleMacroExit();
4456 return false;
4457}
4458
4459/// parseDirectiveEndMacro
4460/// ::= endm
4461bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
4462 if (getLexer().isNot(AsmToken::EndOfStatement))
4463 return TokError("unexpected token in '" + Directive + "' directive");
4464
4465 // If we are inside a macro instantiation, terminate the current
4466 // instantiation.
4467 if (isInsideMacroInstantiation()) {
4468 handleMacroExit();
4469 return false;
4470 }
4471
4472 // Otherwise, this .endmacro is a stray entry in the file; well formed
4473 // .endmacro directives are handled during the macro definition parsing.
4474 return TokError("unexpected '" + Directive + "' in file, "
4475 "no current macro definition");
4476}
4477
4478/// parseDirectivePurgeMacro
4479/// ::= purge identifier ( , identifier )*
4480bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4482 while (true) {
4483 SMLoc NameLoc;
4484 if (parseTokenLoc(NameLoc) ||
4485 check(parseIdentifier(Name), NameLoc,
4486 "expected identifier in 'purge' directive"))
4487 return true;
4488
4489 DEBUG_WITH_TYPE("asm-macros", dbgs()
4490 << "Un-defining macro: " << Name << "\n");
4491 if (!getContext().lookupMacro(Name.lower()))
4492 return Error(NameLoc, "macro '" + Name + "' is not defined");
4493 getContext().undefineMacro(Name.lower());
4494
4495 if (!parseOptionalToken(AsmToken::Comma))
4496 break;
4497 parseOptionalToken(AsmToken::EndOfStatement);
4498 }
4499
4500 return false;
4501}
4502
4503bool MasmParser::parseDirectiveExtern() {
4504 // .extern is the default - but we still need to take any provided type info.
4505 auto parseOp = [&]() -> bool {
4507 SMLoc NameLoc = getTok().getLoc();
4508 if (parseIdentifier(Name))
4509 return Error(NameLoc, "expected name");
4510 if (parseToken(AsmToken::Colon))
4511 return true;
4512
4514 SMLoc TypeLoc = getTok().getLoc();
4515 if (parseIdentifier(TypeName))
4516 return Error(TypeLoc, "expected type");
4517 if (!TypeName.equals_insensitive("proc")) {
4519 if (lookUpType(TypeName, Type))
4520 return Error(TypeLoc, "unrecognized type");
4521 KnownType[Name.lower()] = Type;
4522 }
4523
4524 auto *Sym =
4525 static_cast<MCSymbolCOFF *>(getContext().getOrCreateSymbol(Name));
4526 Sym->setExternal(true);
4527 getStreamer().emitSymbolAttribute(Sym, MCSA_Extern);
4528
4529 return false;
4530 };
4531
4532 if (parseMany(parseOp))
4533 return addErrorSuffix(" in directive 'extern'");
4534 return false;
4535}
4536
4537/// parseDirectiveSymbolAttribute
4538/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
4539bool MasmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
4540 auto parseOp = [&]() -> bool {
4542 SMLoc Loc = getTok().getLoc();
4543 if (parseIdentifier(Name))
4544 return Error(Loc, "expected identifier");
4545 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4546
4547 // Assembler local symbols don't make any sense here. Complain loudly.
4548 if (Sym->isTemporary())
4549 return Error(Loc, "non-local symbol required");
4550
4551 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
4552 return Error(Loc, "unable to emit symbol attribute");
4553 return false;
4554 };
4555
4556 if (parseMany(parseOp))
4557 return addErrorSuffix(" in directive");
4558 return false;
4559}
4560
4561/// parseDirectiveComm
4562/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
4563bool MasmParser::parseDirectiveComm(bool IsLocal) {
4564 if (checkForValidSection())
4565 return true;
4566
4567 SMLoc IDLoc = getLexer().getLoc();
4569 if (parseIdentifier(Name))
4570 return TokError("expected identifier in directive");
4571
4572 // Handle the identifier as the key symbol.
4573 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4574
4575 if (getLexer().isNot(AsmToken::Comma))
4576 return TokError("unexpected token in directive");
4577 Lex();
4578
4579 int64_t Size;
4580 SMLoc SizeLoc = getLexer().getLoc();
4581 if (parseAbsoluteExpression(Size))
4582 return true;
4583
4584 int64_t Pow2Alignment = 0;
4585 SMLoc Pow2AlignmentLoc;
4586 if (getLexer().is(AsmToken::Comma)) {
4587 Lex();
4588 Pow2AlignmentLoc = getLexer().getLoc();
4589 if (parseAbsoluteExpression(Pow2Alignment))
4590 return true;
4591
4592 LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
4593 if (IsLocal && LCOMM == LCOMM::NoAlignment)
4594 return Error(Pow2AlignmentLoc, "alignment not supported on this target");
4595
4596 // If this target takes alignments in bytes (not log) validate and convert.
4597 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
4598 (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
4599 if (!isPowerOf2_64(Pow2Alignment))
4600 return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
4601 Pow2Alignment = Log2_64(Pow2Alignment);
4602 }
4603 }
4604
4605 if (parseEOL())
4606 return true;
4607
4608 // NOTE: a size of zero for a .comm should create a undefined symbol
4609 // but a size of .lcomm creates a bss symbol of size zero.
4610 if (Size < 0)
4611 return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
4612 "be less than zero");
4613
4614 // NOTE: The alignment in the directive is a power of 2 value, the assembler
4615 // may internally end up wanting an alignment in bytes.
4616 // FIXME: Diagnose overflow.
4617 if (Pow2Alignment < 0)
4618 return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
4619 "alignment, can't be less than zero");
4620
4621 Sym->redefineIfPossible();
4622 if (!Sym->isUndefined())
4623 return Error(IDLoc, "invalid symbol redefinition");
4624
4625 // Create the Symbol as a common or local common with Size and Pow2Alignment.
4626 if (IsLocal) {
4627 getStreamer().emitLocalCommonSymbol(Sym, Size,
4628 Align(1ULL << Pow2Alignment));
4629 return false;
4630 }
4631
4632 getStreamer().emitCommonSymbol(Sym, Size, Align(1ULL << Pow2Alignment));
4633 return false;
4634}
4635
4636/// parseDirectiveComment
4637/// ::= comment delimiter [[text]]
4638/// [[text]]
4639/// [[text]] delimiter [[text]]
4640bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
4641 std::string FirstLine = parseStringTo(AsmToken::EndOfStatement);
4642 size_t DelimiterEnd = FirstLine.find_first_of("\b\t\v\f\r\x1A ");
4643 assert(DelimiterEnd != std::string::npos);
4644 StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd);
4645 if (Delimiter.empty())
4646 return Error(DirectiveLoc, "no delimiter in 'comment' directive");
4647 do {
4648 if (getTok().is(AsmToken::Eof))
4649 return Error(DirectiveLoc, "unmatched delimiter in 'comment' directive");
4650 Lex(); // eat end of statement
4651 } while (
4652 !StringRef(parseStringTo(AsmToken::EndOfStatement)).contains(Delimiter));
4653 return parseEOL();
4654}
4655
4656/// parseDirectiveInclude
4657/// ::= include <filename>
4658/// | include filename
4659bool MasmParser::parseDirectiveInclude() {
4660 // Allow the strings to have escaped octal character sequence.
4661 std::string Filename;
4662 SMLoc IncludeLoc = getTok().getLoc();
4663
4664 if (parseAngleBracketString(Filename))
4665 Filename = parseStringTo(AsmToken::EndOfStatement);
4666 if (check(Filename.empty(), "missing filename in 'include' directive") ||
4667 check(getTok().isNot(AsmToken::EndOfStatement),
4668 "unexpected token in 'include' directive") ||
4669 // Attempt to switch the lexer to the included file before consuming the
4670 // end of statement to avoid losing it when we switch.
4671 check(enterIncludeFile(Filename), IncludeLoc,
4672 "Could not find include file '" + Filename + "'"))
4673 return true;
4674
4675 return false;
4676}
4677
4678/// parseDirectiveIf
4679/// ::= .if{,eq,ge,gt,le,lt,ne} expression
4680bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
4681 TheCondStack.push_back(TheCondState);
4682 TheCondState.TheCond = AsmCond::IfCond;
4683 if (TheCondState.Ignore) {
4684 eatToEndOfStatement();
4685 } else {
4686 int64_t ExprValue;
4687 if (parseAbsoluteExpression(ExprValue) || parseEOL())
4688 return true;
4689
4690 switch (DirKind) {
4691 default:
4692 llvm_unreachable("unsupported directive");
4693 case DK_IF:
4694 break;
4695 case DK_IFE:
4696 ExprValue = ExprValue == 0;
4697 break;
4698 }
4699
4700 TheCondState.CondMet = ExprValue;
4701 TheCondState.Ignore = !TheCondState.CondMet;
4702 }
4703
4704 return false;
4705}
4706
4707/// parseDirectiveIfb
4708/// ::= .ifb textitem
4709bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
4710 TheCondStack.push_back(TheCondState);
4711 TheCondState.TheCond = AsmCond::IfCond;
4712
4713 if (TheCondState.Ignore) {
4714 eatToEndOfStatement();
4715 } else {
4716 std::string Str;
4717 if (parseTextItem(Str))
4718 return TokError("expected text item parameter for 'ifb' directive");
4719
4720 if (parseEOL())
4721 return true;
4722
4723 TheCondState.CondMet = ExpectBlank == Str.empty();
4724 TheCondState.Ignore = !TheCondState.CondMet;
4725 }
4726
4727 return false;
4728}
4729
4730/// parseDirectiveIfidn
4731/// ::= ifidn textitem, textitem
4732bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
4733 bool CaseInsensitive) {
4734 std::string String1, String2;
4735
4736 if (parseTextItem(String1)) {
4737 if (ExpectEqual)
4738 return TokError("expected text item parameter for 'ifidn' directive");
4739 return TokError("expected text item parameter for 'ifdif' directive");
4740 }
4741
4742 if (Lexer.isNot(AsmToken::Comma)) {
4743 if (ExpectEqual)
4744 return TokError(
4745 "expected comma after first string for 'ifidn' directive");
4746 return TokError("expected comma after first string for 'ifdif' directive");
4747 }
4748 Lex();
4749
4750 if (parseTextItem(String2)) {
4751 if (ExpectEqual)
4752 return TokError("expected text item parameter for 'ifidn' directive");
4753 return TokError("expected text item parameter for 'ifdif' directive");
4754 }
4755
4756 TheCondStack.push_back(TheCondState);
4757 TheCondState.TheCond = AsmCond::IfCond;
4758 if (CaseInsensitive)
4759 TheCondState.CondMet =
4760 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4761 else
4762 TheCondState.CondMet = ExpectEqual == (String1 == String2);
4763 TheCondState.Ignore = !TheCondState.CondMet;
4764
4765 return false;
4766}
4767
4768/// parseDirectiveIfdef
4769/// ::= ifdef symbol
4770/// | ifdef variable
4771bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
4772 TheCondStack.push_back(TheCondState);
4773 TheCondState.TheCond = AsmCond::IfCond;
4774
4775 if (TheCondState.Ignore) {
4776 eatToEndOfStatement();
4777 } else {
4778 bool is_defined = false;
4780 SMLoc StartLoc, EndLoc;
4781 is_defined =
4782 getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
4783 if (!is_defined) {
4785 if (check(parseIdentifier(Name), "expected identifier after 'ifdef'") ||
4786 parseEOL())
4787 return true;
4788
4789 if (BuiltinSymbolMap.contains(Name.lower())) {
4790 is_defined = true;
4791 } else if (Variables.contains(Name.lower())) {
4792 is_defined = true;
4793 } else {
4794 MCSymbol *Sym = getContext().lookupSymbol(Name.lower());
4795 is_defined = (Sym && !Sym->isUndefined());
4796 }
4797 }
4798
4799 TheCondState.CondMet = (is_defined == expect_defined);
4800 TheCondState.Ignore = !TheCondState.CondMet;
4801 }
4802
4803 return false;
4804}
4805
4806/// parseDirectiveElseIf
4807/// ::= elseif expression
4808bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
4809 DirectiveKind DirKind) {
4810 if (TheCondState.TheCond != AsmCond::IfCond &&
4811 TheCondState.TheCond != AsmCond::ElseIfCond)
4812 return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
4813 " .if or an .elseif");
4814 TheCondState.TheCond = AsmCond::ElseIfCond;
4815
4816 bool LastIgnoreState = false;
4817 if (!TheCondStack.empty())
4818 LastIgnoreState = TheCondStack.back().Ignore;
4819 if (LastIgnoreState || TheCondState.CondMet) {
4820 TheCondState.Ignore = true;
4821 eatToEndOfStatement();
4822 } else {
4823 int64_t ExprValue;
4824 if (parseAbsoluteExpression(ExprValue))
4825 return true;
4826
4827 if (parseEOL())
4828 return true;
4829
4830 switch (DirKind) {
4831 default:
4832 llvm_unreachable("unsupported directive");
4833 case DK_ELSEIF:
4834 break;
4835 case DK_ELSEIFE:
4836 ExprValue = ExprValue == 0;
4837 break;
4838 }
4839
4840 TheCondState.CondMet = ExprValue;
4841 TheCondState.Ignore = !TheCondState.CondMet;
4842 }
4843
4844 return false;
4845}
4846
4847/// parseDirectiveElseIfb
4848/// ::= elseifb textitem
4849bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
4850 if (TheCondState.TheCond != AsmCond::IfCond &&
4851 TheCondState.TheCond != AsmCond::ElseIfCond)
4852 return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
4853 " if or an elseif");
4854 TheCondState.TheCond = AsmCond::ElseIfCond;
4855
4856 bool LastIgnoreState = false;
4857 if (!TheCondStack.empty())
4858 LastIgnoreState = TheCondStack.back().Ignore;
4859 if (LastIgnoreState || TheCondState.CondMet) {
4860 TheCondState.Ignore = true;
4861 eatToEndOfStatement();
4862 } else {
4863 std::string Str;
4864 if (parseTextItem(Str)) {
4865 if (ExpectBlank)
4866 return TokError("expected text item parameter for 'elseifb' directive");
4867 return TokError("expected text item parameter for 'elseifnb' directive");
4868 }
4869
4870 if (parseEOL())
4871 return true;
4872
4873 TheCondState.CondMet = ExpectBlank == Str.empty();
4874 TheCondState.Ignore = !TheCondState.CondMet;
4875 }
4876
4877 return false;
4878}
4879
4880/// parseDirectiveElseIfdef
4881/// ::= elseifdef symbol
4882/// | elseifdef variable
4883bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
4884 bool expect_defined) {
4885 if (TheCondState.TheCond != AsmCond::IfCond &&
4886 TheCondState.TheCond != AsmCond::ElseIfCond)
4887 return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
4888 " if or an elseif");
4889 TheCondState.TheCond = AsmCond::ElseIfCond;
4890
4891 bool LastIgnoreState = false;
4892 if (!TheCondStack.empty())
4893 LastIgnoreState = TheCondStack.back().Ignore;
4894 if (LastIgnoreState || TheCondState.CondMet) {
4895 TheCondState.Ignore = true;
4896 eatToEndOfStatement();
4897 } else {
4898 bool is_defined = false;
4900 SMLoc StartLoc, EndLoc;
4901 is_defined =
4902 getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
4903 if (!is_defined) {
4905 if (check(parseIdentifier(Name),
4906 "expected identifier after 'elseifdef'") ||
4907 parseEOL())
4908 return true;
4909
4910 if (BuiltinSymbolMap.contains(Name.lower())) {
4911 is_defined = true;
4912 } else if (Variables.contains(Name.lower())) {
4913 is_defined = true;
4914 } else {
4915 MCSymbol *Sym = getContext().lookupSymbol(Name);
4916 is_defined = (Sym && !Sym->isUndefined());
4917 }
4918 }
4919
4920 TheCondState.CondMet = (is_defined == expect_defined);
4921 TheCondState.Ignore = !TheCondState.CondMet;
4922 }
4923
4924 return false;
4925}
4926
4927/// parseDirectiveElseIfidn
4928/// ::= elseifidn textitem, textitem
4929bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
4930 bool CaseInsensitive) {
4931 if (TheCondState.TheCond != AsmCond::IfCond &&
4932 TheCondState.TheCond != AsmCond::ElseIfCond)
4933 return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
4934 " if or an elseif");
4935 TheCondState.TheCond = AsmCond::ElseIfCond;
4936
4937 bool LastIgnoreState = false;
4938 if (!TheCondStack.empty())
4939 LastIgnoreState = TheCondStack.back().Ignore;
4940 if (LastIgnoreState || TheCondState.CondMet) {
4941 TheCondState.Ignore = true;
4942 eatToEndOfStatement();
4943 } else {
4944 std::string String1, String2;
4945
4946 if (parseTextItem(String1)) {
4947 if (ExpectEqual)
4948 return TokError(
4949 "expected text item parameter for 'elseifidn' directive");
4950 return TokError("expected text item parameter for 'elseifdif' directive");
4951 }
4952
4953 if (Lexer.isNot(AsmToken::Comma)) {
4954 if (ExpectEqual)
4955 return TokError(
4956 "expected comma after first string for 'elseifidn' directive");
4957 return TokError(
4958 "expected comma after first string for 'elseifdif' directive");
4959 }
4960 Lex();
4961
4962 if (parseTextItem(String2)) {
4963 if (ExpectEqual)
4964 return TokError(
4965 "expected text item parameter for 'elseifidn' directive");
4966 return TokError("expected text item parameter for 'elseifdif' directive");
4967 }
4968
4969 if (CaseInsensitive)
4970 TheCondState.CondMet =
4971 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4972 else
4973 TheCondState.CondMet = ExpectEqual == (String1 == String2);
4974 TheCondState.Ignore = !TheCondState.CondMet;
4975 }
4976
4977 return false;
4978}
4979
4980/// parseDirectiveElse
4981/// ::= else
4982bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
4983 if (parseEOL())
4984 return true;
4985
4986 if (TheCondState.TheCond != AsmCond::IfCond &&
4987 TheCondState.TheCond != AsmCond::ElseIfCond)
4988 return Error(DirectiveLoc, "Encountered an else that doesn't follow an if"
4989 " or an elseif");
4990 TheCondState.TheCond = AsmCond::ElseCond;
4991 bool LastIgnoreState = false;
4992 if (!TheCondStack.empty())
4993 LastIgnoreState = TheCondStack.back().Ignore;
4994 if (LastIgnoreState || TheCondState.CondMet)
4995 TheCondState.Ignore = true;
4996 else
4997 TheCondState.Ignore = false;
4998
4999 return false;
5000}
5001
5002/// parseDirectiveEnd
5003/// ::= end
5004bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5005 if (parseEOL())
5006 return true;
5007
5008 while (Lexer.isNot(AsmToken::Eof))
5009 Lexer.Lex();
5010
5011 return false;
5012}
5013
5014/// parseDirectiveError
5015/// ::= .err [message]
5016bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
5017 if (!TheCondStack.empty()) {
5018 if (TheCondStack.back().Ignore) {
5019 eatToEndOfStatement();
5020 return false;
5021 }
5022 }
5023
5024 std::string Message = ".err directive invoked in source file";
5025 if (Lexer.isNot(AsmToken::EndOfStatement))
5026 Message = parseStringTo(AsmToken::EndOfStatement);
5027 Lex();
5028
5029 return Error(DirectiveLoc, Message);
5030}
5031
5032/// parseDirectiveErrorIfb
5033/// ::= .errb textitem[, message]
5034bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
5035 if (!TheCondStack.empty()) {
5036 if (TheCondStack.back().Ignore) {
5037 eatToEndOfStatement();
5038 return false;
5039 }
5040 }
5041
5042 std::string Text;
5043 if (parseTextItem(Text))
5044 return Error(getTok().getLoc(), "missing text item in '.errb' directive");
5045
5046 std::string Message = ".errb directive invoked in source file";
5047 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5048 if (parseToken(AsmToken::Comma))
5049 return addErrorSuffix(" in '.errb' directive");
5050 Message = parseStringTo(AsmToken::EndOfStatement);
5051 }
5052 Lex();
5053
5054 if (Text.empty() == ExpectBlank)
5055 return Error(DirectiveLoc, Message);
5056 return false;
5057}
5058
5059/// parseDirectiveErrorIfdef
5060/// ::= .errdef name[, message]
5061bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
5062 bool ExpectDefined) {
5063 if (!TheCondStack.empty()) {
5064 if (TheCondStack.back().Ignore) {
5065 eatToEndOfStatement();
5066 return false;
5067 }
5068 }
5069
5070 bool IsDefined = false;
5072 SMLoc StartLoc, EndLoc;
5073 IsDefined =
5074 getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
5075 if (!IsDefined) {
5077 if (check(parseIdentifier(Name), "expected identifier after '.errdef'"))
5078 return true;
5079
5080 if (BuiltinSymbolMap.contains(Name.lower())) {
5081 IsDefined = true;
5082 } else if (Variables.contains(Name.lower())) {
5083 IsDefined = true;
5084 } else {
5085 MCSymbol *Sym = getContext().lookupSymbol(Name);
5086 IsDefined = (Sym && !Sym->isUndefined());
5087 }
5088 }
5089
5090 std::string Message = ".errdef directive invoked in source file";
5091 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5092 if (parseToken(AsmToken::Comma))
5093 return addErrorSuffix(" in '.errdef' directive");
5094 Message = parseStringTo(AsmToken::EndOfStatement);
5095 }
5096 Lex();
5097
5098 if (IsDefined == ExpectDefined)
5099 return Error(DirectiveLoc, Message);
5100 return false;
5101}
5102
5103/// parseDirectiveErrorIfidn
5104/// ::= .erridn textitem, textitem[, message]
5105bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
5106 bool CaseInsensitive) {
5107 if (!TheCondStack.empty()) {
5108 if (TheCondStack.back().Ignore) {
5109 eatToEndOfStatement();
5110 return false;
5111 }
5112 }
5113
5114 std::string String1, String2;
5115
5116 if (parseTextItem(String1)) {
5117 if (ExpectEqual)
5118 return TokError("expected string parameter for '.erridn' directive");
5119 return TokError("expected string parameter for '.errdif' directive");
5120 }
5121
5122 if (Lexer.isNot(AsmToken::Comma)) {
5123 if (ExpectEqual)
5124 return TokError(
5125 "expected comma after first string for '.erridn' directive");
5126 return TokError(
5127 "expected comma after first string for '.errdif' directive");
5128 }
5129 Lex();
5130
5131 if (parseTextItem(String2)) {
5132 if (ExpectEqual)
5133 return TokError("expected string parameter for '.erridn' directive");
5134 return TokError("expected string parameter for '.errdif' directive");
5135 }
5136
5137 std::string Message;
5138 if (ExpectEqual)
5139 Message = ".erridn directive invoked in source file";
5140 else
5141 Message = ".errdif directive invoked in source file";
5142 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5143 if (parseToken(AsmToken::Comma))
5144 return addErrorSuffix(" in '.erridn' directive");
5145 Message = parseStringTo(AsmToken::EndOfStatement);
5146 }
5147 Lex();
5148
5149 if (CaseInsensitive)
5150 TheCondState.CondMet =
5151 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
5152 else
5153 TheCondState.CondMet = ExpectEqual == (String1 == String2);
5154 TheCondState.Ignore = !TheCondState.CondMet;
5155
5156 if ((CaseInsensitive &&
5157 ExpectEqual == StringRef(String1).equals_insensitive(String2)) ||
5158 (ExpectEqual == (String1 == String2)))
5159 return Error(DirectiveLoc, Message);
5160 return false;
5161}
5162
5163/// parseDirectiveErrorIfe
5164/// ::= .erre expression[, message]
5165bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero) {
5166 if (!TheCondStack.empty()) {
5167 if (TheCondStack.back().Ignore) {
5168 eatToEndOfStatement();
5169 return false;
5170 }
5171 }
5172
5173 int64_t ExprValue;
5174 if (parseAbsoluteExpression(ExprValue))
5175 return addErrorSuffix(" in '.erre' directive");
5176
5177 std::string Message = ".erre directive invoked in source file";
5178 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5179 if (parseToken(AsmToken::Comma))
5180 return addErrorSuffix(" in '.erre' directive");
5181 Message = parseStringTo(AsmToken::EndOfStatement);
5182 }
5183 Lex();
5184
5185 if ((ExprValue == 0) == ExpectZero)
5186 return Error(DirectiveLoc, Message);
5187 return false;
5188}
5189
5190/// parseDirectiveEndIf
5191/// ::= .endif
5192bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5193 if (parseEOL())
5194 return true;
5195
5196 if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
5197 return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
5198 "an .if or .else");
5199 if (!TheCondStack.empty()) {
5200 TheCondState = TheCondStack.back();
5201 TheCondStack.pop_back();
5202 }
5203
5204 return false;
5205}
5206
5207void MasmParser::initializeDirectiveKindMap() {
5208 DirectiveKindMap["="] = DK_ASSIGN;
5209 DirectiveKindMap["equ"] = DK_EQU;
5210 DirectiveKindMap["textequ"] = DK_TEXTEQU;
5211 // DirectiveKindMap[".ascii"] = DK_ASCII;
5212 // DirectiveKindMap[".asciz"] = DK_ASCIZ;
5213 // DirectiveKindMap[".string"] = DK_STRING;
5214 DirectiveKindMap["byte"] = DK_BYTE;
5215 DirectiveKindMap["sbyte"] = DK_SBYTE;
5216 DirectiveKindMap["word"] = DK_WORD;
5217 DirectiveKindMap["sword"] = DK_SWORD;
5218 DirectiveKindMap["dword"] = DK_DWORD;
5219 DirectiveKindMap["sdword"] = DK_SDWORD;
5220 DirectiveKindMap["fword"] = DK_FWORD;
5221 DirectiveKindMap["qword"] = DK_QWORD;
5222 DirectiveKindMap["sqword"] = DK_SQWORD;
5223 DirectiveKindMap["real4"] = DK_REAL4;
5224 DirectiveKindMap["real8"] = DK_REAL8;
5225 DirectiveKindMap["real10"] = DK_REAL10;
5226 DirectiveKindMap["align"] = DK_ALIGN;
5227 DirectiveKindMap["even"] = DK_EVEN;
5228 DirectiveKindMap["org"] = DK_ORG;
5229 DirectiveKindMap["extern"] = DK_EXTERN;
5230 DirectiveKindMap["extrn"] = DK_EXTERN;
5231 DirectiveKindMap["public"] = DK_PUBLIC;
5232 // DirectiveKindMap[".comm"] = DK_COMM;
5233 DirectiveKindMap["comment"] = DK_COMMENT;
5234 DirectiveKindMap["include"] = DK_INCLUDE;
5235 DirectiveKindMap["repeat"] = DK_REPEAT;
5236 DirectiveKindMap["rept"] = DK_REPEAT;
5237 DirectiveKindMap["while"] = DK_WHILE;
5238 DirectiveKindMap["for"] = DK_FOR;
5239 DirectiveKindMap["irp"] = DK_FOR;
5240 DirectiveKindMap["forc"] = DK_FORC;
5241 DirectiveKindMap["irpc"] = DK_FORC;
5242 DirectiveKindMap["if"] = DK_IF;
5243 DirectiveKindMap["ife"] = DK_IFE;
5244 DirectiveKindMap["ifb"] = DK_IFB;
5245 DirectiveKindMap["ifnb"] = DK_IFNB;
5246 DirectiveKindMap["ifdef"] = DK_IFDEF;
5247 DirectiveKindMap["ifndef"] = DK_IFNDEF;
5248 DirectiveKindMap["ifdif"] = DK_IFDIF;
5249 DirectiveKindMap["ifdifi"] = DK_IFDIFI;
5250 DirectiveKindMap["ifidn"] = DK_IFIDN;
5251 DirectiveKindMap["ifidni"] = DK_IFIDNI;
5252 DirectiveKindMap["elseif"] = DK_ELSEIF;
5253 DirectiveKindMap["elseifdef"] = DK_ELSEIFDEF;
5254 DirectiveKindMap["elseifndef"] = DK_ELSEIFNDEF;
5255 DirectiveKindMap["elseifdif"] = DK_ELSEIFDIF;
5256 DirectiveKindMap["elseifidn"] = DK_ELSEIFIDN;
5257 DirectiveKindMap["else"] = DK_ELSE;
5258 DirectiveKindMap["end"] = DK_END;
5259 DirectiveKindMap["endif"] = DK_ENDIF;
5260 // DirectiveKindMap[".file"] = DK_FILE;
5261 // DirectiveKindMap[".line"] = DK_LINE;
5262 // DirectiveKindMap[".loc"] = DK_LOC;
5263 // DirectiveKindMap[".stabs"] = DK_STABS;
5264 // DirectiveKindMap[".cv_file"] = DK_CV_FILE;
5265 // DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
5266 // DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
5267 // DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
5268 // DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
5269 // DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
5270 // DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
5271 // DirectiveKindMap[".cv_string"] = DK_CV_STRING;
5272 // DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
5273 // DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
5274 // DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
5275 // DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
5276 // DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
5277 // DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
5278 // DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
5279 // DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
5280 // DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
5281 // DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
5282 // DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
5283 // DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
5284 // DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
5285 // DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
5286 // DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
5287 // DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
5288 // DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
5289 // DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
5290 // DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
5291 // DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
5292 // DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
5293 // DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
5294 // DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
5295 // DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
5296 // DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
5297 // DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
5298 // DirectiveKindMap[".cfi_val_offset"] = DK_CFI_VAL_OFFSET;
5299 DirectiveKindMap["macro"] = DK_MACRO;
5300 DirectiveKindMap["exitm"] = DK_EXITM;
5301 DirectiveKindMap["endm"] = DK_ENDM;
5302 DirectiveKindMap["purge"] = DK_PURGE;
5303 DirectiveKindMap[".err"] = DK_ERR;
5304 DirectiveKindMap[".errb"] = DK_ERRB;
5305 DirectiveKindMap[".errnb"] = DK_ERRNB;
5306 DirectiveKindMap[".errdef"] = DK_ERRDEF;
5307 DirectiveKindMap[".errndef"] = DK_ERRNDEF;
5308 DirectiveKindMap[".errdif"] = DK_ERRDIF;
5309 DirectiveKindMap[".errdifi"] = DK_ERRDIFI;
5310 DirectiveKindMap[".erridn"] = DK_ERRIDN;
5311 DirectiveKindMap[".erridni"] = DK_ERRIDNI;
5312 DirectiveKindMap[".erre"] = DK_ERRE;
5313 DirectiveKindMap[".errnz"] = DK_ERRNZ;
5314 DirectiveKindMap[".pushframe"] = DK_PUSHFRAME;
5315 DirectiveKindMap[".pushreg"] = DK_PUSHREG;
5316 DirectiveKindMap[".savereg"] = DK_SAVEREG;
5317 DirectiveKindMap[".savexmm128"] = DK_SAVEXMM128;
5318 DirectiveKindMap[".setframe"] = DK_SETFRAME;
5319 DirectiveKindMap[".radix"] = DK_RADIX;
5320 DirectiveKindMap["db"] = DK_DB;
5321 DirectiveKindMap["dd"] = DK_DD;
5322 DirectiveKindMap["df"] = DK_DF;
5323 DirectiveKindMap["dq"] = DK_DQ;
5324 DirectiveKindMap["dw"] = DK_DW;
5325 DirectiveKindMap["echo"] = DK_ECHO;
5326 DirectiveKindMap["struc"] = DK_STRUCT;
5327 DirectiveKindMap["struct"] = DK_STRUCT;
5328 DirectiveKindMap["union"] = DK_UNION;
5329 DirectiveKindMap["ends"] = DK_ENDS;
5330}
5331
5332bool MasmParser::isMacroLikeDirective() {
5333 if (getLexer().is(AsmToken::Identifier)) {
5334 bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier())
5335 .CasesLower("repeat", "rept", true)
5336 .CaseLower("while", true)
5337 .CasesLower("for", "irp", true)
5338 .CasesLower("forc", "irpc", true)
5339 .Default(false);
5340 if (IsMacroLike)
5341 return true;
5342 }
5343 if (peekTok().is(AsmToken::Identifier) &&
5344 peekTok().getIdentifier().equals_insensitive("macro"))
5345 return true;
5346
5347 return false;
5348}
5349
5350MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5351 AsmToken EndToken, StartToken = getTok();
5352
5353 unsigned NestLevel = 0;
5354 while (true) {
5355 // Check whether we have reached the end of the file.
5356 if (getLexer().is(AsmToken::Eof)) {
5357 printError(DirectiveLoc, "no matching 'endm' in definition");
5358 return nullptr;
5359 }
5360
5361 if (isMacroLikeDirective())
5362 ++NestLevel;
5363
5364 // Otherwise, check whether we have reached the endm.
5365 if (Lexer.is(AsmToken::Identifier) &&
5366 getTok().getIdentifier().equals_insensitive("endm")) {
5367 if (NestLevel == 0) {
5368 EndToken = getTok();
5369 Lex();
5370 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5371 printError(getTok().getLoc(), "unexpected token in 'endm' directive");
5372 return nullptr;
5373 }
5374 break;
5375 }
5376 --NestLevel;
5377 }
5378
5379 // Otherwise, scan till the end of the statement.
5380 eatToEndOfStatement();
5381 }
5382
5383 const char *BodyStart = StartToken.getLoc().getPointer();
5384 const char *BodyEnd = EndToken.getLoc().getPointer();
5385 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5386
5387 // We Are Anonymous.
5388 MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
5389 return &MacroLikeBodies.back();
5390}
5391
5392bool MasmParser::expandStatement(SMLoc Loc) {
5393 std::string Body = parseStringTo(AsmToken::EndOfStatement);
5394 SMLoc EndLoc = getTok().getLoc();
5395
5397 MCAsmMacroArguments Arguments;
5398
5399 StringMap<std::string> BuiltinValues;
5400 for (const auto &S : BuiltinSymbolMap) {
5401 const BuiltinSymbol &Sym = S.getValue();
5402 if (std::optional<std::string> Text = evaluateBuiltinTextMacro(Sym, Loc)) {
5403 BuiltinValues[S.getKey().lower()] = std::move(*Text);
5404 }
5405 }
5406 for (const auto &B : BuiltinValues) {
5408 MCAsmMacroArgument A;
5409 P.Name = B.getKey();
5410 P.Required = true;
5411 A.push_back(AsmToken(AsmToken::String, B.getValue()));
5412
5413 Parameters.push_back(std::move(P));
5414 Arguments.push_back(std::move(A));
5415 }
5416
5417 for (const auto &V : Variables) {
5418 const Variable &Var = V.getValue();
5419 if (Var.IsText) {
5421 MCAsmMacroArgument A;
5422 P.Name = Var.Name;
5423 P.Required = true;
5424 A.push_back(AsmToken(AsmToken::String, Var.TextValue));
5425
5426 Parameters.push_back(std::move(P));
5427 Arguments.push_back(std::move(A));
5428 }
5429 }
5430 MacroLikeBodies.emplace_back(StringRef(), Body, Parameters);
5431 MCAsmMacro M = MacroLikeBodies.back();
5432
5433 // Expand the statement in a new buffer.
5434 SmallString<80> Buf;
5436 if (expandMacro(OS, M.Body, M.Parameters, Arguments, M.Locals, EndLoc))
5437 return true;
5438 std::unique_ptr<MemoryBuffer> Expansion =
5439 MemoryBuffer::getMemBufferCopy(OS.str(), "<expansion>");
5440
5441 // Jump to the expanded statement and prime the lexer.
5442 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Expansion), EndLoc);
5443 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
5444 EndStatementAtEOFStack.push_back(false);
5445 Lex();
5446 return false;
5447}
5448
5449void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5451 instantiateMacroLikeBody(M, DirectiveLoc, /*ExitLoc=*/getTok().getLoc(), OS);
5452}
5453void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5454 SMLoc ExitLoc,
5456 OS << "endm\n";
5457
5458 std::unique_ptr<MemoryBuffer> Instantiation =
5459 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
5460
5461 // Create the macro instantiation object and add to the current macro
5462 // instantiation stack.
5463 MacroInstantiation *MI = new MacroInstantiation{DirectiveLoc, CurBuffer,
5464 ExitLoc, TheCondStack.size()};
5465 ActiveMacros.push_back(MI);
5466
5467 // Jump to the macro instantiation and prime the lexer.
5468 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
5469 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
5470 EndStatementAtEOFStack.push_back(true);
5471 Lex();
5472}
5473
5474/// parseDirectiveRepeat
5475/// ::= ("repeat" | "rept") count
5476/// body
5477/// endm
5478bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) {
5479 const MCExpr *CountExpr;
5480 SMLoc CountLoc = getTok().getLoc();
5481 if (parseExpression(CountExpr))
5482 return true;
5483
5484 int64_t Count;
5485 if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
5486 return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
5487 }
5488
5489 if (check(Count < 0, CountLoc, "Count is negative") || parseEOL())
5490 return true;
5491
5492 // Lex the repeat definition.
5493 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5494 if (!M)
5495 return true;
5496
5497 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5498 // to hold the macro body with substitutions.
5499 SmallString<256> Buf;
5501 while (Count--) {
5502 if (expandMacro(OS, M->Body, {}, {}, M->Locals, getTok().getLoc()))
5503 return true;
5504 }
5505 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5506
5507 return false;
5508}
5509
5510/// parseDirectiveWhile
5511/// ::= "while" expression
5512/// body
5513/// endm
5514bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) {
5515 const MCExpr *CondExpr;
5516 SMLoc CondLoc = getTok().getLoc();
5517 if (parseExpression(CondExpr))
5518 return true;
5519
5520 // Lex the repeat definition.
5521 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5522 if (!M)
5523 return true;
5524
5525 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5526 // to hold the macro body with substitutions.
5527 SmallString<256> Buf;
5529 int64_t Condition;
5530 if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr()))
5531 return Error(CondLoc, "expected absolute expression in 'while' directive");
5532 if (Condition) {
5533 // Instantiate the macro, then resume at this directive to recheck the
5534 // condition.
5535 if (expandMacro(OS, M->Body, {}, {}, M->Locals, getTok().getLoc()))
5536 return true;
5537 instantiateMacroLikeBody(M, DirectiveLoc, /*ExitLoc=*/DirectiveLoc, OS);
5538 }
5539
5540 return false;
5541}
5542
5543/// parseDirectiveFor
5544/// ::= ("for" | "irp") symbol [":" qualifier], <values>
5545/// body
5546/// endm
5547bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
5548 MCAsmMacroParameter Parameter;
5549 MCAsmMacroArguments A;
5550 if (check(parseIdentifier(Parameter.Name),
5551 "expected identifier in '" + Dir + "' directive"))
5552 return true;
5553
5554 // Parse optional qualifier (default value, or "req")
5555 if (parseOptionalToken(AsmToken::Colon)) {
5556 if (parseOptionalToken(AsmToken::Equal)) {
5557 // Default value
5558 SMLoc ParamLoc;
5559
5560 ParamLoc = Lexer.getLoc();
5561 if (parseMacroArgument(nullptr, Parameter.Value))
5562 return true;
5563 } else {
5564 SMLoc QualLoc;
5566
5567 QualLoc = Lexer.getLoc();
5568 if (parseIdentifier(Qualifier))
5569 return Error(QualLoc, "missing parameter qualifier for "
5570 "'" +
5571 Parameter.Name + "' in '" + Dir +
5572 "' directive");
5573
5574 if (Qualifier.equals_insensitive("req"))
5575 Parameter.Required = true;
5576 else
5577 return Error(QualLoc,
5578 Qualifier + " is not a valid parameter qualifier for '" +
5579 Parameter.Name + "' in '" + Dir + "' directive");
5580 }
5581 }
5582
5583 if (parseToken(AsmToken::Comma,
5584 "expected comma in '" + Dir + "' directive") ||
5585 parseToken(AsmToken::Less,
5586 "values in '" + Dir +
5587 "' directive must be enclosed in angle brackets"))
5588 return true;
5589
5590 while (true) {
5591 A.emplace_back();
5592 if (parseMacroArgument(&Parameter, A.back(), /*EndTok=*/AsmToken::Greater))
5593 return addErrorSuffix(" in arguments for '" + Dir + "' directive");
5594
5595 // If we see a comma, continue, and allow line continuation.
5596 if (!parseOptionalToken(AsmToken::Comma))
5597 break;
5598 parseOptionalToken(AsmToken::EndOfStatement);
5599 }
5600
5601 if (parseToken(AsmToken::Greater,
5602 "values in '" + Dir +
5603 "' directive must be enclosed in angle brackets") ||
5604 parseEOL())
5605 return true;
5606
5607 // Lex the for definition.
5608 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5609 if (!M)
5610 return true;
5611
5612 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5613 // to hold the macro body with substitutions.
5614 SmallString<256> Buf;
5616
5617 for (const MCAsmMacroArgument &Arg : A) {
5618 if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc()))
5619 return true;
5620 }
5621
5622 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5623
5624 return false;
5625}
5626
5627/// parseDirectiveForc
5628/// ::= ("forc" | "irpc") symbol, <string>
5629/// body
5630/// endm
5631bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
5632 MCAsmMacroParameter Parameter;
5633
5634 std::string Argument;
5635 if (check(parseIdentifier(Parameter.Name),
5636 "expected identifier in '" + Directive + "' directive") ||
5637 parseToken(AsmToken::Comma,
5638 "expected comma in '" + Directive + "' directive"))
5639 return true;
5640 if (parseAngleBracketString(Argument)) {
5641 // Match ml64.exe; treat all characters to end of statement as a string,
5642 // ignoring comment markers, then discard anything following a space (using
5643 // the C locale).
5644 Argument = parseStringTo(AsmToken::EndOfStatement);
5645 if (getTok().is(AsmToken::EndOfStatement))
5646 Argument += getTok().getString();
5647 size_t End = 0;
5648 for (; End < Argument.size(); ++End) {
5649 if (isSpace(Argument[End]))
5650 break;
5651 }
5652 Argument.resize(End);
5653 }
5654 if (parseEOL())
5655 return true;
5656
5657 // Lex the irpc definition.
5658 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5659 if (!M)
5660 return true;
5661
5662 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5663 // to hold the macro body with substitutions.
5664 SmallString<256> Buf;
5666
5667 StringRef Values(Argument);
5668 for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
5669 MCAsmMacroArgument Arg;
5670 Arg.emplace_back(AsmToken::Identifier, Values.substr(I, 1));
5671
5672 if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc()))
5673 return true;
5674 }
5675
5676 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5677
5678 return false;
5679}
5680
5681bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
5682 size_t Len) {
5683 const MCExpr *Value;
5684 SMLoc ExprLoc = getLexer().getLoc();
5685 if (parseExpression(Value))
5686 return true;
5687 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
5688 if (!MCE)
5689 return Error(ExprLoc, "unexpected expression in _emit");
5690 uint64_t IntValue = MCE->getValue();
5691 if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
5692 return Error(ExprLoc, "literal value out of range for directive");
5693
5694 Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
5695 return false;
5696}
5697
5698bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
5699 const MCExpr *Value;
5700 SMLoc ExprLoc = getLexer().getLoc();
5701 if (parseExpression(Value))
5702 return true;
5703 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
5704 if (!MCE)
5705 return Error(ExprLoc, "unexpected expression in align");
5706 uint64_t IntValue = MCE->getValue();
5707 if (!isPowerOf2_64(IntValue))
5708 return Error(ExprLoc, "literal value not a power of two greater then zero");
5709
5710 Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
5711 return false;
5712}
5713
5714bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
5715 const SMLoc Loc = getLexer().getLoc();
5716 std::string RadixStringRaw = parseStringTo(AsmToken::EndOfStatement);
5717 StringRef RadixString = StringRef(RadixStringRaw).trim();
5718 unsigned Radix;
5719 if (RadixString.getAsInteger(10, Radix)) {
5720 return Error(Loc,
5721 "radix must be a decimal number in the range 2 to 16; was " +
5722 RadixString);
5723 }
5724 if (Radix < 2 || Radix > 16)
5725 return Error(Loc, "radix must be in the range 2 to 16; was " +
5726 std::to_string(Radix));
5727 getLexer().setMasmDefaultRadix(Radix);
5728 return false;
5729}
5730
5731/// parseDirectiveEcho
5732/// ::= "echo" message
5733bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) {
5734 std::string Message = parseStringTo(AsmToken::EndOfStatement);
5735 llvm::outs() << Message;
5736 if (!StringRef(Message).ends_with("\n"))
5737 llvm::outs() << '\n';
5738 return false;
5739}
5740
5741// We are comparing pointers, but the pointers are relative to a single string.
5742// Thus, this should always be deterministic.
5743static int rewritesSort(const AsmRewrite *AsmRewriteA,
5744 const AsmRewrite *AsmRewriteB) {
5745 if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
5746 return -1;
5747 if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
5748 return 1;
5749
5750 // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
5751 // rewrite to the same location. Make sure the SizeDirective rewrite is
5752 // performed first, then the Imm/ImmPrefix and finally the Input/Output. This
5753 // ensures the sort algorithm is stable.
5754 if (AsmRewritePrecedence[AsmRewriteA->Kind] >
5755 AsmRewritePrecedence[AsmRewriteB->Kind])
5756 return -1;
5757
5758 if (AsmRewritePrecedence[AsmRewriteA->Kind] <
5759 AsmRewritePrecedence[AsmRewriteB->Kind])
5760 return 1;
5761 llvm_unreachable("Unstable rewrite sort.");
5762}
5763
5764bool MasmParser::defineMacro(StringRef Name, StringRef Value) {
5765 Variable &Var = Variables[Name.lower()];
5766 if (Var.Name.empty()) {
5767 Var.Name = Name;
5768 } else if (Var.Redefinable == Variable::NOT_REDEFINABLE) {
5769 return Error(SMLoc(), "invalid variable redefinition");
5770 } else if (Var.Redefinable == Variable::WARN_ON_REDEFINITION &&
5771 Warning(SMLoc(), "redefining '" + Name +
5772 "', already defined on the command line")) {
5773 return true;
5774 }
5775 Var.Redefinable = Variable::WARN_ON_REDEFINITION;
5776 Var.IsText = true;
5777 Var.TextValue = Value.str();
5778 return false;
5779}
5780
5781bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info) const {
5782 const std::pair<StringRef, StringRef> BaseMember = Name.split('.');
5783 const StringRef Base = BaseMember.first, Member = BaseMember.second;
5784 return lookUpField(Base, Member, Info);
5785}
5786
5787bool MasmParser::lookUpField(StringRef Base, StringRef Member,
5788 AsmFieldInfo &Info) const {
5789 if (Base.empty())
5790 return true;
5791
5792 AsmFieldInfo BaseInfo;
5793 if (Base.contains('.') && !lookUpField(Base, BaseInfo))
5794 Base = BaseInfo.Type.Name;
5795
5796 auto StructIt = Structs.find(Base.lower());
5797 auto TypeIt = KnownType.find(Base.lower());
5798 if (TypeIt != KnownType.end()) {
5799 StructIt = Structs.find(TypeIt->second.Name.lower());
5800 }
5801 if (StructIt != Structs.end())
5802 return lookUpField(StructIt->second, Member, Info);
5803
5804 return true;
5805}
5806
5807bool MasmParser::lookUpField(const StructInfo &Structure, StringRef Member,
5808 AsmFieldInfo &Info) const {
5809 if (Member.empty()) {
5810 Info.Type.Name = Structure.Name;
5811 Info.Type.Size = Structure.Size;
5812 Info.Type.ElementSize = Structure.Size;
5813 Info.Type.Length = 1;
5814 return false;
5815 }
5816
5817 std::pair<StringRef, StringRef> Split = Member.split('.');
5818 const StringRef FieldName = Split.first, FieldMember = Split.second;
5819
5820 auto StructIt = Structs.find(FieldName.lower());
5821 if (StructIt != Structs.end())
5822 return lookUpField(StructIt->second, FieldMember, Info);
5823
5824 auto FieldIt = Structure.FieldsByName.find(FieldName.lower());
5825 if (FieldIt == Structure.FieldsByName.end())
5826 return true;
5827
5828 const FieldInfo &Field = Structure.Fields[FieldIt->second];
5829 if (FieldMember.empty()) {
5830 Info.Offset += Field.Offset;
5831 Info.Type.Size = Field.SizeOf;
5832 Info.Type.ElementSize = Field.Type;
5833 Info.Type.Length = Field.LengthOf;
5834 if (Field.Contents.FT == FT_STRUCT)
5835 Info.Type.Name = Field.Contents.StructInfo.Structure.Name;
5836 else
5837 Info.Type.Name = "";
5838 return false;
5839 }
5840
5841 if (Field.Contents.FT != FT_STRUCT)
5842 return true;
5843 const StructFieldInfo &StructInfo = Field.Contents.StructInfo;
5844
5845 if (lookUpField(StructInfo.Structure, FieldMember, Info))
5846 return true;
5847
5848 Info.Offset += Field.Offset;
5849 return false;
5850}
5851
5852bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info) const {
5853 unsigned Size = StringSwitch<unsigned>(Name)
5854 .CasesLower("byte", "db", "sbyte", 1)
5855 .CasesLower("word", "dw", "sword", 2)
5856 .CasesLower("dword", "dd", "sdword", 4)
5857 .CasesLower("fword", "df", 6)
5858 .CasesLower("qword", "dq", "sqword", 8)
5859 .CaseLower("real4", 4)
5860 .CaseLower("real8", 8)
5861 .CaseLower("real10", 10)
5862 .Default(0);
5863 if (Size) {
5864 Info.Name = Name;
5865 Info.ElementSize = Size;
5866 Info.Length = 1;
5867 Info.Size = Size;
5868 return false;
5869 }
5870
5871 auto StructIt = Structs.find(Name.lower());
5872 if (StructIt != Structs.end()) {
5873 const StructInfo &Structure = StructIt->second;
5874 Info.Name = Name;
5875 Info.ElementSize = Structure.Size;
5876 Info.Length = 1;
5877 Info.Size = Structure.Size;
5878 return false;
5879 }
5880
5881 return true;
5882}
5883
5884bool MasmParser::parseMSInlineAsm(
5885 std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs,
5886 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5887 SmallVectorImpl<std::string> &Constraints,
5888 SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
5890 SmallVector<void *, 4> InputDecls;
5891 SmallVector<void *, 4> OutputDecls;
5892 SmallVector<bool, 4> InputDeclsAddressOf;
5893 SmallVector<bool, 4> OutputDeclsAddressOf;
5894 SmallVector<std::string, 4> InputConstraints;
5895 SmallVector<std::string, 4> OutputConstraints;
5896 SmallVector<MCRegister, 4> ClobberRegs;
5897
5898 SmallVector<AsmRewrite, 4> AsmStrRewrites;
5899
5900 // Prime the lexer.
5901 Lex();
5902
5903 // While we have input, parse each statement.
5904 unsigned InputIdx = 0;
5905 unsigned OutputIdx = 0;
5906 while (getLexer().isNot(AsmToken::Eof)) {
5907 // Parse curly braces marking block start/end.
5908 if (parseCurlyBlockScope(AsmStrRewrites))
5909 continue;
5910
5911 ParseStatementInfo Info(&AsmStrRewrites);
5912 bool StatementErr = parseStatement(Info, &SI);
5913
5914 if (StatementErr || Info.ParseError) {
5915 // Emit pending errors if any exist.
5916 printPendingErrors();
5917 return true;
5918 }
5919
5920 // No pending error should exist here.
5921 assert(!hasPendingError() && "unexpected error from parseStatement");
5922
5923 if (Info.Opcode == ~0U)
5924 continue;
5925
5926 const MCInstrDesc &Desc = MII->get(Info.Opcode);
5927
5928 // Build the list of clobbers, outputs and inputs.
5929 for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
5930 MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
5931
5932 // Register operand.
5933 if (Operand.isReg() && !Operand.needAddressOf() &&
5934 !getTargetParser().omitRegisterFromClobberLists(Operand.getReg())) {
5935 unsigned NumDefs = Desc.getNumDefs();
5936 // Clobber.
5937 if (NumDefs && Operand.getMCOperandNum() < NumDefs)
5938 ClobberRegs.push_back(Operand.getReg());
5939 continue;
5940 }
5941
5942 // Expr/Input or Output.
5943 StringRef SymName = Operand.getSymName();
5944 if (SymName.empty())
5945 continue;
5946
5947 void *OpDecl = Operand.getOpDecl();
5948 if (!OpDecl)
5949 continue;
5950
5951 StringRef Constraint = Operand.getConstraint();
5952 if (Operand.isImm()) {
5953 // Offset as immediate.
5954 if (Operand.isOffsetOfLocal())
5955 Constraint = "r";
5956 else
5957 Constraint = "i";
5958 }
5959
5960 bool isOutput = (i == 1) && Desc.mayStore();
5961 SMLoc Start = SMLoc::getFromPointer(SymName.data());
5962 if (isOutput) {
5963 ++InputIdx;
5964 OutputDecls.push_back(OpDecl);
5965 OutputDeclsAddressOf.push_back(Operand.needAddressOf());
5966 OutputConstraints.push_back(("=" + Constraint).str());
5967 AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size());
5968 } else {
5969 InputDecls.push_back(OpDecl);
5970 InputDeclsAddressOf.push_back(Operand.needAddressOf());
5971 InputConstraints.push_back(Constraint.str());
5972 if (Desc.operands()[i - 1].isBranchTarget())
5973 AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size());
5974 else
5975 AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
5976 }
5977 }
5978
5979 // Consider implicit defs to be clobbers. Think of cpuid and push.
5980 llvm::append_range(ClobberRegs, Desc.implicit_defs());
5981 }
5982
5983 // Set the number of Outputs and Inputs.
5984 NumOutputs = OutputDecls.size();
5985 NumInputs = InputDecls.size();
5986
5987 // Set the unique clobbers.
5988 array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
5989 ClobberRegs.erase(llvm::unique(ClobberRegs), ClobberRegs.end());
5990 Clobbers.assign(ClobberRegs.size(), std::string());
5991 for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
5992 raw_string_ostream OS(Clobbers[I]);
5993 IP->printRegName(OS, ClobberRegs[I]);
5994 }
5995
5996 // Merge the various outputs and inputs. Output are expected first.
5997 if (NumOutputs || NumInputs) {
5998 unsigned NumExprs = NumOutputs + NumInputs;
5999 OpDecls.resize(NumExprs);
6000 Constraints.resize(NumExprs);
6001 for (unsigned i = 0; i < NumOutputs; ++i) {
6002 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
6003 Constraints[i] = OutputConstraints[i];
6004 }
6005 for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
6006 OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
6007 Constraints[j] = InputConstraints[i];
6008 }
6009 }
6010
6011 // Build the IR assembly string.
6012 std::string AsmStringIR;
6013 raw_string_ostream OS(AsmStringIR);
6014 StringRef ASMString =
6016 const char *AsmStart = ASMString.begin();
6017 const char *AsmEnd = ASMString.end();
6018 array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
6019 for (auto I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) {
6020 const AsmRewrite &AR = *I;
6021 // Check if this has already been covered by another rewrite...
6022 if (AR.Done)
6023 continue;
6025
6026 const char *Loc = AR.Loc.getPointer();
6027 assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
6028
6029 // Emit everything up to the immediate/expression.
6030 if (unsigned Len = Loc - AsmStart)
6031 OS << StringRef(AsmStart, Len);
6032
6033 // Skip the original expression.
6034 if (Kind == AOK_Skip) {
6035 AsmStart = Loc + AR.Len;
6036 continue;
6037 }
6038
6039 unsigned AdditionalSkip = 0;
6040 // Rewrite expressions in $N notation.
6041 switch (Kind) {
6042 default:
6043 break;
6044 case AOK_IntelExpr:
6045 assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
6046 if (AR.IntelExp.NeedBracs)
6047 OS << "[";
6048 if (AR.IntelExp.hasBaseReg())
6049 OS << AR.IntelExp.BaseReg;
6050 if (AR.IntelExp.hasIndexReg())
6051 OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
6052 << AR.IntelExp.IndexReg;
6053 if (AR.IntelExp.Scale > 1)
6054 OS << " * $$" << AR.IntelExp.Scale;
6055 if (AR.IntelExp.hasOffset()) {
6056 if (AR.IntelExp.hasRegs())
6057 OS << " + ";
6058 // Fuse this rewrite with a rewrite of the offset name, if present.
6059 StringRef OffsetName = AR.IntelExp.OffsetName;
6061 size_t OffsetLen = OffsetName.size();
6062 auto rewrite_it = std::find_if(
6063 I, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
6064 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6065 (FusingAR.Kind == AOK_Input ||
6066 FusingAR.Kind == AOK_CallInput);
6067 });
6068 if (rewrite_it == AsmStrRewrites.end()) {
6069 OS << "offset " << OffsetName;
6070 } else if (rewrite_it->Kind == AOK_CallInput) {
6071 OS << "${" << InputIdx++ << ":P}";
6072 rewrite_it->Done = true;
6073 } else {
6074 OS << '$' << InputIdx++;
6075 rewrite_it->Done = true;
6076 }
6077 }
6078 if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
6079 OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
6080 if (AR.IntelExp.NeedBracs)
6081 OS << "]";
6082 break;
6083 case AOK_Label:
6084 OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
6085 break;
6086 case AOK_Input:
6087 OS << '$' << InputIdx++;
6088 break;
6089 case AOK_CallInput:
6090 OS << "${" << InputIdx++ << ":P}";
6091 break;
6092 case AOK_Output:
6093 OS << '$' << OutputIdx++;
6094 break;
6095 case AOK_SizeDirective:
6096 switch (AR.Val) {
6097 default: break;
6098 case 8: OS << "byte ptr "; break;
6099 case 16: OS << "word ptr "; break;
6100 case 32: OS << "dword ptr "; break;
6101 case 64: OS << "qword ptr "; break;
6102 case 80: OS << "xword ptr "; break;
6103 case 128: OS << "xmmword ptr "; break;
6104 case 256: OS << "ymmword ptr "; break;
6105 }
6106 break;
6107 case AOK_Emit:
6108 OS << ".byte";
6109 break;
6110 case AOK_Align: {
6111 // MS alignment directives are measured in bytes. If the native assembler
6112 // measures alignment in bytes, we can pass it straight through.
6113 OS << ".align";
6114 if (getContext().getAsmInfo()->getAlignmentIsInBytes())
6115 break;
6116
6117 // Alignment is in log2 form, so print that instead and skip the original
6118 // immediate.
6119 unsigned Val = AR.Val;
6120 OS << ' ' << Val;
6121 assert(Val < 10 && "Expected alignment less then 2^10.");
6122 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6123 break;
6124 }
6125 case AOK_EVEN:
6126 OS << ".even";
6127 break;
6128 case AOK_EndOfStatement:
6129 OS << "\n\t";
6130 break;
6131 }
6132
6133 // Skip the original expression.
6134 AsmStart = Loc + AR.Len + AdditionalSkip;
6135 }
6136
6137 // Emit the remainder of the asm string.
6138 if (AsmStart != AsmEnd)
6139 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6140
6141 AsmString = OS.str();
6142 return false;
6143}
6144
6145void MasmParser::initializeBuiltinSymbolMaps() {
6146 // Numeric built-ins (supported in all versions)
6147 BuiltinSymbolMap["@version"] = BI_VERSION;
6148 BuiltinSymbolMap["@line"] = BI_LINE;
6149
6150 // Text built-ins (supported in all versions)
6151 BuiltinSymbolMap["@date"] = BI_DATE;
6152 BuiltinSymbolMap["@time"] = BI_TIME;
6153 BuiltinSymbolMap["@filecur"] = BI_FILECUR;
6154 BuiltinSymbolMap["@filename"] = BI_FILENAME;
6155 BuiltinSymbolMap["@curseg"] = BI_CURSEG;
6156
6157 // Function built-ins (supported in all versions)
6158 BuiltinFunctionMap["@catstr"] = BI_CATSTR;
6159
6160 // Some built-ins exist only for MASM32 (32-bit x86)
6161 if (getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
6162 Triple::x86) {
6163 // Numeric built-ins
6164 // BuiltinSymbolMap["@cpu"] = BI_CPU;
6165 // BuiltinSymbolMap["@interface"] = BI_INTERFACE;
6166 // BuiltinSymbolMap["@wordsize"] = BI_WORDSIZE;
6167 // BuiltinSymbolMap["@codesize"] = BI_CODESIZE;
6168 // BuiltinSymbolMap["@datasize"] = BI_DATASIZE;
6169 // BuiltinSymbolMap["@model"] = BI_MODEL;
6170
6171 // Text built-ins
6172 // BuiltinSymbolMap["@code"] = BI_CODE;
6173 // BuiltinSymbolMap["@data"] = BI_DATA;
6174 // BuiltinSymbolMap["@fardata?"] = BI_FARDATA;
6175 // BuiltinSymbolMap["@stack"] = BI_STACK;
6176 }
6177}
6178
6179const MCExpr *MasmParser::evaluateBuiltinValue(BuiltinSymbol Symbol,
6180 SMLoc StartLoc) {
6181 switch (Symbol) {
6182 default:
6183 return nullptr;
6184 case BI_VERSION:
6185 // Match a recent version of ML.EXE.
6186 return MCConstantExpr::create(1427, getContext());
6187 case BI_LINE: {
6188 int64_t Line;
6189 if (ActiveMacros.empty())
6190 Line = SrcMgr.FindLineNumber(StartLoc, CurBuffer);
6191 else
6192 Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
6193 ActiveMacros.front()->ExitBuffer);
6194 return MCConstantExpr::create(Line, getContext());
6195 }
6196 }
6197 llvm_unreachable("unhandled built-in symbol");
6198}
6199
6200std::optional<std::string>
6201MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
6202 switch (Symbol) {
6203 default:
6204 return {};
6205 case BI_DATE: {
6206 // Current local date, formatted MM/DD/YY
6207 char TmpBuffer[sizeof("mm/dd/yy")];
6208 const size_t Len = strftime(TmpBuffer, sizeof(TmpBuffer), "%D", &TM);
6209 return std::string(TmpBuffer, Len);
6210 }
6211 case BI_TIME: {
6212 // Current local time, formatted HH:MM:SS (24-hour clock)
6213 char TmpBuffer[sizeof("hh:mm:ss")];
6214 const size_t Len = strftime(TmpBuffer, sizeof(TmpBuffer), "%T", &TM);
6215 return std::string(TmpBuffer, Len);
6216 }
6217 case BI_FILECUR:
6218 return SrcMgr
6220 ActiveMacros.empty() ? CurBuffer : ActiveMacros.front()->ExitBuffer)
6222 .str();
6223 case BI_FILENAME:
6226 .upper();
6227 case BI_CURSEG:
6228 return getStreamer().getCurrentSectionOnly()->getName().str();
6229 }
6230 llvm_unreachable("unhandled built-in symbol");
6231}
6232
6233bool MasmParser::evaluateBuiltinMacroFunction(BuiltinFunction Function,
6235 std::string &Res) {
6236 if (parseToken(AsmToken::LParen, "invoking macro function '" + Name +
6237 "' requires arguments in parentheses")) {
6238 return true;
6239 }
6240
6242 switch (Function) {
6243 default:
6244 return true;
6245 case BI_CATSTR:
6246 break;
6247 }
6248 MCAsmMacro M(Name, "", P, {}, true);
6249
6250 MCAsmMacroArguments A;
6251 if (parseMacroArguments(&M, A, AsmToken::RParen) || parseRParen()) {
6252 return true;
6253 }
6254
6255 switch (Function) {
6256 default:
6257 llvm_unreachable("unhandled built-in function");
6258 case BI_CATSTR: {
6259 for (const MCAsmMacroArgument &Arg : A) {
6260 for (const AsmToken &Tok : Arg) {
6261 if (Tok.is(AsmToken::String)) {
6262 Res.append(Tok.getStringContents());
6263 } else {
6264 Res.append(Tok.getString());
6265 }
6266 }
6267 }
6268 return false;
6269 }
6270 }
6271 llvm_unreachable("unhandled built-in function");
6272 return true;
6273}
6274
6275/// Create an MCAsmParser instance.
6277 MCStreamer &Out, const MCAsmInfo &MAI,
6278 struct tm TM, unsigned CB) {
6279 return new MasmParser(SM, C, Out, MAI, TM, CB);
6280}
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...
This file implements the BitVector class.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
DXIL Intrinsic Expansion
@ Default
Definition: DwarfDebug.cpp:86
std::string Name
uint64_t Size
bool End
Definition: ELF_riscv.cpp:480
Symbol * Sym
Definition: ELF_riscv.cpp:479
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
static bool isMacroParameterChar(char C)
static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc)
This function checks if the next token is <string> type or arithmetic.
@ DEFAULT_ADDRSPACE
Definition: MasmParser.cpp:972
static unsigned getGNUBinOpPrecedence(AsmToken::TokenKind K, MCBinaryExpr::Opcode &Kind, bool ShouldUseLogicalShr, bool EndExpressionAtGreater)
static int rewritesSort(const AsmRewrite *AsmRewriteA, const AsmRewrite *AsmRewriteB)
static std::string angleBracketString(StringRef BracketContents)
creating a string without the escape characters '!'.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
OptimizedStructLayoutField Field
#define P(N)
if(PassOpts->AAPipeline)
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
This file contains some templates that are useful if you are working with the STL at all.
raw_pwrite_stream & OS
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:480
This file defines the SmallString class.
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
Definition: Debug.h:77
@ Struct
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
Definition: TextStub.cpp:1059
Value * RHS
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Definition: APFloat.h:1098
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Definition: APFloat.h:1109
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Definition: APFloat.h:1079
Class for arbitrary precision integers.
Definition: APInt.h:78
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition: APInt.h:1488
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
Definition: APInt.h:475
This class represents an incoming formal argument to a Function.
Definition: Argument.h:32
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
AsmCond - Class to support conditional assembly.
Definition: AsmCond.h:21
ConditionalAssemblyType TheCond
Definition: AsmCond.h:30
bool Ignore
Definition: AsmCond.h:32
bool CondMet
Definition: AsmCond.h:31
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:22
LLVM_ABI SMLoc getLoc() const
Definition: AsmLexer.cpp:32
bool isNot(TokenKind K) const
Definition: MCAsmMacro.h:76
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition: MCAsmMacro.h:103
StringRef getStringContents() const
Get the contents of a string token (without quotes).
Definition: MCAsmMacro.h:83
bool is(TokenKind K) const
Definition: MCAsmMacro.h:75
LLVM_ABI SMLoc getEndLoc() const
Definition: AsmLexer.cpp:34
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
Definition: MCAsmMacro.h:92
Base class for user error types.
Definition: Error.h:354
Lightweight error class with error context and mandatory checking.
Definition: Error.h:159
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition: MCAsmInfo.h:64
bool preserveAsmComments() const
Return true if assembly (inline or otherwise) should be parsed.
Definition: MCAsmInfo.h:709
StringRef getPrivateLabelPrefix() const
Definition: MCAsmInfo.h:546
bool shouldUseLogicalShr() const
Definition: MCAsmInfo.h:717
virtual bool useCodeAlign(const MCSection &Sec) const
Definition: MCAsmInfo.h:503
Generic interface for extending the MCAsmParser, which is implemented by target and object file assem...
Generic Sema callback for assembly parser.
Definition: MCAsmParser.h:109
Generic assembler parser interface, for use by target specific assembly parsers.
Definition: MCAsmParser.h:124
virtual void eatToEndOfStatement()=0
Skip to the end of the current statement, for error recovery.
virtual bool printError(SMLoc L, const Twine &Msg, SMRange Range=std::nullopt)=0
Emit an error at the location L, with the message Msg.
virtual bool parseEscapedString(std::string &Data)=0
Parse the current token as a string which may include escaped characters and return the string conten...
virtual bool defineMacro(StringRef Name, StringRef Value)
Definition: MCAsmParser.h:189
virtual StringRef parseStringToEndOfStatement()=0
Parse up to the end of statement and return the contents from the current token until the end of the ...
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression.
virtual bool checkForValidSection()=0
Ensure that we have a valid section set in the streamer.
virtual bool isParsingMasm() const
Definition: MCAsmParser.h:187
virtual bool parseIdentifier(StringRef &Res)=0
Parse an identifier or string (as a quoted identifier) and set Res to the identifier contents.
MCAsmParser & operator=(const MCAsmParser &)=delete
virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression, assuming that an initial '(' has already been consumed.
virtual bool isParsingMSInlineAsm()=0
virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc, AsmTypeInfo *TypeInfo=nullptr)=0
Parse a primary expression.
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
virtual unsigned getAssemblerDialect()
Definition: MCAsmParser.h:173
virtual void addAliasForDirective(StringRef Directive, StringRef Alias)=0
virtual bool parseAngleBracketString(std::string &Data)=0
Parse an angle-bracket delimited string at the current position if one is present,...
virtual bool lookUpType(StringRef Name, AsmTypeInfo &Info) const
Definition: MCAsmParser.h:199
virtual bool parseAbsoluteExpression(int64_t &Res)=0
Parse an expression which must evaluate to an absolute value.
virtual bool lookUpField(StringRef Name, AsmFieldInfo &Info) const
Definition: MCAsmParser.h:191
virtual void setAssemblerDialect(unsigned i)
Definition: MCAsmParser.h:174
virtual void setParsingMSInlineAsm(bool V)=0
virtual bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, SmallVectorImpl< std::pair< void *, bool > > &OpDecls, SmallVectorImpl< std::string > &Constraints, SmallVectorImpl< std::string > &Clobbers, const MCInstrInfo *MII, MCInstPrinter *IP, MCAsmParserSemaCallback &SI)=0
Parse MS-style inline assembly.
virtual void addDirectiveHandler(StringRef Directive, ExtensionDirectiveHandler Handler)=0
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.cpp:201
@ Div
Signed division.
Definition: MCExpr.h:304
@ Shl
Shift left.
Definition: MCExpr.h:321
@ AShr
Arithmetic shift right.
Definition: MCExpr.h:322
@ LShr
Logical shift right.
Definition: MCExpr.h:323
@ GTE
Signed greater than or equal comparison (result is either 0 or some target-specific non-zero value).
Definition: MCExpr.h:308
@ EQ
Equality comparison.
Definition: MCExpr.h:305
@ Sub
Subtraction.
Definition: MCExpr.h:324
@ Mul
Multiplication.
Definition: MCExpr.h:317
@ GT
Signed greater than comparison (result is either 0 or some target-specific non-zero value)
Definition: MCExpr.h:306
@ Mod
Signed remainder.
Definition: MCExpr.h:316
@ And
Bitwise and.
Definition: MCExpr.h:303
@ Or
Bitwise or.
Definition: MCExpr.h:319
@ Xor
Bitwise exclusive or.
Definition: MCExpr.h:325
@ LAnd
Logical and.
Definition: MCExpr.h:310
@ LOr
Logical or.
Definition: MCExpr.h:311
@ LT
Signed less than comparison (result is either 0 or some target-specific non-zero value).
Definition: MCExpr.h:312
@ Add
Addition.
Definition: MCExpr.h:302
@ LTE
Signed less than or equal comparison (result is either 0 or some target-specific non-zero value).
Definition: MCExpr.h:314
@ NE
Inequality comparison.
Definition: MCExpr.h:318
int64_t getValue() const
Definition: MCExpr.h:171
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:212
Context object for machine code objects.
Definition: MCContext.h:83
Environment getObjectFileType() const
Definition: MCContext.h:392
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:386
LLVM_ABI MCSymbol * createDirectionalLocalSymbol(unsigned LocalLabelVal)
Create the definition of a directional local symbol for numbered label (used for "1:" definitions).
Definition: MCContext.cpp:419
const MCAsmInfo * getAsmInfo() const
Definition: MCContext.h:412
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
This is an instance of a target assembly language printer that converts an MCInst to valid target ass...
Definition: MCInstPrinter.h:46
virtual void printRegName(raw_ostream &OS, MCRegister Reg)
Print the assembler register name.
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:199
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:27
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:64
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
virtual bool isReg() const =0
isReg - Is this a register operand?
virtual bool needAddressOf() const
needAddressOf - Do we need to emit code to get the address of the variable/label? Only valid when par...
virtual MCRegister getReg() const =0
virtual bool isOffsetOfLocal() const
isOffsetOfLocal - Do we need to emit code to get the offset of the local variable,...
virtual StringRef getSymName()
virtual bool isImm() const =0
isImm - Is this an immediate operand?
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition: MCSection.h:496
Streaming machine code generation interface.
Definition: MCStreamer.h:220
virtual void addBlankLine()
Emit a blank line to a .s file to pretty it up.
Definition: MCStreamer.h:408
virtual void initSections(bool NoExecStack, const MCSubtargetInfo &STI)
Create the default sections and set the initial one.
Definition: MCStreamer.cpp:391
virtual void addExplicitComment(const Twine &T)
Add explicit comment T.
Definition: MCStreamer.cpp:121
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Definition: MCStreamer.cpp:395
void finish(SMLoc EndLoc=SMLoc())
Finish emission of machine code.
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:190
const MCSymbol & getSymbol() const
Definition: MCExpr.h:227
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:214
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:188
static const MCUnaryExpr * createLNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:265
static const MCUnaryExpr * createPlus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:277
static const MCUnaryExpr * createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:273
static const MCUnaryExpr * createMinus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:269
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
Definition: MemoryBuffer.h:77
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
StringRef getBuffer() const
Definition: MemoryBuffer.h:71
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:303
Ternary parse status returned by various parse* methods.
constexpr bool isFailure() const
constexpr bool isSuccess() const
Instances of this class encapsulate one diagnostic report, allowing printing to a raw_ostream as a ca...
Definition: SourceMgr.h:282
LLVM_ABI void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true, bool ShowLocation=true) const
Definition: SourceMgr.cpp:484
SourceMgr::DiagKind getKind() const
Definition: SourceMgr.h:312
StringRef getLineContents() const
Definition: SourceMgr.h:314
SMLoc getLoc() const
Definition: SourceMgr.h:308
StringRef getMessage() const
Definition: SourceMgr.h:313
ArrayRef< std::pair< unsigned, unsigned > > getRanges() const
Definition: SourceMgr.h:315
const SourceMgr * getSourceMgr() const
Definition: SourceMgr.h:307
int getColumnNo() const
Definition: SourceMgr.h:311
Represents a location in source code.
Definition: SMLoc.h:23
static SMLoc getFromPointer(const char *Ptr)
Definition: SMLoc.h:36
constexpr const char * getPointer() const
Definition: SMLoc.h:34
constexpr bool isValid() const
Definition: SMLoc.h:29
Represents a range in source code.
Definition: SMLoc.h:48
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
bool empty() const
Definition: SmallVector.h:82
size_t size() const
Definition: SmallVector.h:79
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:574
void assign(size_type NumElts, ValueParamT Elt)
Definition: SmallVector.h:705
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:938
void reserve(size_type N)
Definition: SmallVector.h:664
iterator erase(const_iterator CI)
Definition: SmallVector.h:738
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:684
void resize(size_type N)
Definition: SmallVector.h:639
void push_back(const T &Elt)
Definition: SmallVector.h:414
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
Definition: SourceMgr.h:32
void * getDiagContext() const
Definition: SourceMgr.h:119
unsigned getMainFileID() const
Definition: SourceMgr.h:133
DiagHandlerTy getDiagHandler() const
Definition: SourceMgr.h:118
const MemoryBuffer * getMemoryBuffer(unsigned i) const
Definition: SourceMgr.h:126
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.
Definition: SourceMgr.cpp:352
SMLoc getParentIncludeLoc(unsigned i) const
Definition: SourceMgr.h:138
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.
Definition: SourceMgr.cpp:261
LLVM_ABI unsigned FindBufferContainingLoc(SMLoc Loc) const
Return the ID of the buffer containing the specified location.
Definition: SourceMgr.cpp:73
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
Definition: SourceMgr.h:44
void setDiagHandler(DiagHandlerTy DH, void *Ctx=nullptr)
Specify a diagnostic handler to be invoked every time PrintMessage is called.
Definition: SourceMgr.h:113
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.
Definition: SourceMgr.cpp:41
unsigned FindLineNumber(SMLoc Loc, unsigned BufferID=0) const
Find the line number for the specified location in the specified file.
Definition: SourceMgr.h:197
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
Definition: SourceMgr.h:145
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:133
iterator end()
Definition: StringMap.h:224
iterator find(StringRef Key)
Definition: StringMap.h:237
bool contains(StringRef Key) const
contains - Return true if the element is in the map, false otherwise.
Definition: StringMap.h:277
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
Definition: StringMap.h:280
ValueTy lookup(StringRef Key) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Definition: StringMap.h:257
std::pair< iterator, bool > try_emplace(StringRef Key, ArgsTy &&...Args)
Emplace a new element for the specified key into the map if the key isn't already in the map.
Definition: StringMap.h:372
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Definition: StringMap.h:312
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
Definition: StringRef.h:665
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:480
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:233
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:581
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:269
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:151
iterator begin() const
Definition: StringRef.h:120
LLVM_ABI std::string upper() const
Convert the given ASCII string to uppercase.
Definition: StringRef.cpp:117
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition: StringRef.h:694
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:154
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:148
iterator end() const
Definition: StringRef.h:122
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
Definition: StringRef.h:590
StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
Definition: StringRef.h:824
LLVM_ABI std::string lower() const
Definition: StringRef.cpp:112
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
Definition: StringRef.h:180
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:43
StringSwitch & CaseLower(StringLiteral S, T Value)
Definition: StringSwitch.h:139
StringSwitch & CasesLower(StringLiteral S0, StringLiteral S1, T Value)
Definition: StringSwitch.h:158
R Default(T Value)
Definition: StringSwitch.h:177
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:75
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:662
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:692
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ ByteAlignment
Definition: MCAsmInfo.h:58
Reg
All possible values of the reg field in the ModR/M byte.
std::variant< std::monostate, DecisionParameters, BranchParameters > Parameters
The type of MC/DC-specific parameters.
Definition: MCDCTypes.h:57
LLVM_ABI StringRef stem(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get stem.
Definition: Path.cpp:579
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition: STLExtras.h:338
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
Definition: Error.h:1113
@ Offset
Definition: DWP.cpp:477
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition: STLExtras.h:1702
@ AOK_EndOfStatement
@ AOK_SizeDirective
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.
Definition: STLExtras.h:2155
LLVM_ABI MCAsmParser * createMCMasmParser(SourceMgr &, MCContext &, MCStreamer &, const MCAsmInfo &, struct tm, unsigned CB=0)
Create an MCAsmParser instance for parsing Microsoft MASM-style assembly.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:252
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition: MathExtras.h:293
std::vector< MCAsmMacroParameter > MCAsmMacroParameters
Definition: MCAsmMacro.h:134
auto unique(Range &&R, Predicate P)
Definition: STLExtras.h:2095
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition: MathExtras.h:342
SourceMgr SrcMgr
Definition: Error.cpp:24
cl::opt< unsigned > AsmMacroMaxNestingDepth
Definition: MasmParser.cpp:966
MCAsmParserExtension * createCOFFMasmParser()
const char AsmRewritePrecedence[]
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:207
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition: Error.cpp:167
FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, bool Upper=false)
format_hex_no_prefix - Output N as a fixed width hexadecimal.
Definition: Format.h:201
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:257
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
Definition: STLExtras.h:1629
MCSymbolAttr
Definition: MCDirectives.h:18
@ MCSA_Global
.type _foo, @gnu_unique_object
Definition: MCDirectives.h:30
@ MCSA_Extern
.extern (XCOFF)
Definition: MCDirectives.h:32
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
AsmTypeInfo Type
Definition: MCAsmParser.h:104
AsmRewriteKind Kind
StringRef Name
Definition: MCAsmParser.h:97
Description of the encoding of one expression Op.
bool hasIndexReg() const
bool hasRegs() const
bool hasOffset() const
bool hasBaseReg() const
bool emitImm() const
bool isValid() const
std::vector< AsmToken > Value
Definition: MCAsmMacro.h:124
uint64_t Offset
The offset of this field in the final layout.
uint64_t Size
The required size of this field in bytes.