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