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