LLVM 24.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 = std::move(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] = std::move(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_PUSH2REGS,
721 DK_SAVEREG,
722 DK_SAVEXMM128,
723 DK_SETFRAME,
724 DK_RADIX,
725 };
726
727 /// Maps directive name --> DirectiveKind enum, for directives parsed by this
728 /// class.
729 StringMap<DirectiveKind> DirectiveKindMap;
730
731 bool isMacroLikeDirective();
732
733 // Generic (target and platform independent) directive parsing.
734 enum BuiltinSymbol {
735 BI_NO_SYMBOL, // Placeholder
736 BI_DATE,
737 BI_TIME,
738 BI_VERSION,
739 BI_FILECUR,
740 BI_FILENAME,
741 BI_LINE,
742 BI_CURSEG,
743 BI_CPU,
744 BI_INTERFACE,
745 BI_CODE,
746 BI_DATA,
747 BI_FARDATA,
748 BI_WORDSIZE,
749 BI_CODESIZE,
750 BI_DATASIZE,
751 BI_MODEL,
752 BI_STACK,
753 BI_UNWINDVERSION,
754 };
755
756 /// Maps builtin name --> BuiltinSymbol enum, for builtins handled by this
757 /// class.
758 StringMap<BuiltinSymbol> BuiltinSymbolMap;
759
760 const MCExpr *evaluateBuiltinValue(BuiltinSymbol Symbol, SMLoc StartLoc);
761
762 std::optional<std::string> evaluateBuiltinTextMacro(BuiltinSymbol Symbol,
763 SMLoc StartLoc);
764
765 // Generic (target and platform independent) directive parsing.
766 enum BuiltinFunction {
767 BI_NO_FUNCTION, // Placeholder
768 BI_CATSTR,
769 };
770
771 /// Maps builtin name --> BuiltinFunction enum, for builtins handled by this
772 /// class.
773 StringMap<BuiltinFunction> BuiltinFunctionMap;
774
775 bool evaluateBuiltinMacroFunction(BuiltinFunction Function, StringRef Name,
776 std::string &Res);
777
778 // ".ascii", ".asciz", ".string"
779 bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
780
781 // "byte", "word", ...
782 bool emitIntValue(const MCExpr *Value, unsigned Size);
783 bool parseScalarInitializer(unsigned Size,
784 SmallVectorImpl<const MCExpr *> &Values,
785 unsigned StringPadLength = 0);
786 bool parseScalarInstList(
787 unsigned Size, SmallVectorImpl<const MCExpr *> &Values,
789 bool emitIntegralValues(unsigned Size, unsigned *Count = nullptr);
790 bool addIntegralField(StringRef Name, unsigned Size);
791 bool parseDirectiveValue(StringRef IDVal, unsigned Size);
792 bool parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
793 StringRef Name, SMLoc NameLoc);
794
795 // "real4", "real8", "real10"
796 bool emitRealValues(const fltSemantics &Semantics, unsigned *Count = nullptr);
797 bool addRealField(StringRef Name, const fltSemantics &Semantics, size_t Size);
798 bool parseDirectiveRealValue(StringRef IDVal, const fltSemantics &Semantics,
799 size_t Size);
800 bool parseRealInstList(
801 const fltSemantics &Semantics, SmallVectorImpl<APInt> &Values,
803 bool parseDirectiveNamedRealValue(StringRef TypeName,
804 const fltSemantics &Semantics,
805 unsigned Size, StringRef Name,
806 SMLoc NameLoc);
807
808 bool parseOptionalAngleBracketOpen();
809 bool parseAngleBracketClose(const Twine &Msg = "expected '>'");
810
811 bool parseFieldInitializer(const FieldInfo &Field,
812 FieldInitializer &Initializer);
813 bool parseFieldInitializer(const FieldInfo &Field,
814 const IntFieldInfo &Contents,
815 FieldInitializer &Initializer);
816 bool parseFieldInitializer(const FieldInfo &Field,
817 const RealFieldInfo &Contents,
818 FieldInitializer &Initializer);
819 bool parseFieldInitializer(const FieldInfo &Field,
820 const StructFieldInfo &Contents,
821 FieldInitializer &Initializer);
822
823 bool parseStructInitializer(const StructInfo &Structure,
824 StructInitializer &Initializer);
825 bool parseStructInstList(
826 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
828
829 bool emitFieldValue(const FieldInfo &Field);
830 bool emitFieldValue(const FieldInfo &Field, const IntFieldInfo &Contents);
831 bool emitFieldValue(const FieldInfo &Field, const RealFieldInfo &Contents);
832 bool emitFieldValue(const FieldInfo &Field, const StructFieldInfo &Contents);
833
834 bool emitFieldInitializer(const FieldInfo &Field,
835 const FieldInitializer &Initializer);
836 bool emitFieldInitializer(const FieldInfo &Field,
837 const IntFieldInfo &Contents,
838 const IntFieldInfo &Initializer);
839 bool emitFieldInitializer(const FieldInfo &Field,
840 const RealFieldInfo &Contents,
841 const RealFieldInfo &Initializer);
842 bool emitFieldInitializer(const FieldInfo &Field,
843 const StructFieldInfo &Contents,
844 const StructFieldInfo &Initializer);
845
846 bool emitStructInitializer(const StructInfo &Structure,
847 const StructInitializer &Initializer);
848
849 // User-defined types (structs, unions):
850 bool emitStructValues(const StructInfo &Structure, unsigned *Count = nullptr);
851 bool addStructField(StringRef Name, const StructInfo &Structure);
852 bool parseDirectiveStructValue(const StructInfo &Structure,
853 StringRef Directive, SMLoc DirLoc);
854 bool parseDirectiveNamedStructValue(const StructInfo &Structure,
855 StringRef Directive, SMLoc DirLoc,
856 StringRef Name);
857
858 // "=", "equ", "textequ"
859 bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
860 DirectiveKind DirKind, SMLoc NameLoc);
861
862 bool parseDirectiveOrg(); // "org"
863
864 bool emitAlignTo(int64_t Alignment);
865 bool parseDirectiveAlign(); // "align"
866 bool parseDirectiveEven(); // "even"
867
868 // macro directives
869 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
870 bool parseDirectiveExitMacro(SMLoc DirectiveLoc, StringRef Directive,
871 std::string &Value);
872 bool parseDirectiveEndMacro(StringRef Directive);
873 bool parseDirectiveMacro(StringRef Name, SMLoc NameLoc);
874
875 bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind,
876 StringRef Name, SMLoc NameLoc);
877 bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind);
878 bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
879 bool parseDirectiveNestedEnds();
880
881 bool parseDirectiveExtern();
882
883 /// Parse a directive like ".globl" which accepts a single symbol (which
884 /// should be a label or an external).
885 bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
886
887 bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
888
889 bool parseDirectiveComment(SMLoc DirectiveLoc); // "comment"
890
891 bool parseDirectiveInclude(); // "include"
892
893 // "if" or "ife"
894 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
895 // "ifb" or "ifnb", depending on ExpectBlank.
896 bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
897 // "ifidn", "ifdif", "ifidni", or "ifdifi", depending on ExpectEqual and
898 // CaseInsensitive.
899 bool parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
900 bool CaseInsensitive);
901 // "ifdef" or "ifndef", depending on expect_defined
902 bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
903 // "elseif" or "elseife"
904 bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
905 // "elseifb" or "elseifnb", depending on ExpectBlank.
906 bool parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank);
907 // ".elseifdef" or ".elseifndef", depending on expect_defined
908 bool parseDirectiveElseIfdef(SMLoc DirectiveLoc, bool expect_defined);
909 // "elseifidn", "elseifdif", "elseifidni", or "elseifdifi", depending on
910 // ExpectEqual and CaseInsensitive.
911 bool parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
912 bool CaseInsensitive);
913 bool parseDirectiveElse(SMLoc DirectiveLoc); // "else"
914 bool parseDirectiveEndIf(SMLoc DirectiveLoc); // "endif"
915 bool parseEscapedString(std::string &Data) override;
916 bool parseAngleBracketString(std::string &Data) override;
917
918 // Macro-like directives
919 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
920 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
921 raw_svector_ostream &OS);
922 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
923 SMLoc ExitLoc, raw_svector_ostream &OS);
924 bool parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Directive);
925 bool parseDirectiveFor(SMLoc DirectiveLoc, StringRef Directive);
926 bool parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive);
927 bool parseDirectiveWhile(SMLoc DirectiveLoc);
928
929 // "_emit" or "__emit"
930 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
931 size_t Len);
932
933 // "align"
934 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
935
936 // "end"
937 bool parseDirectiveEnd(SMLoc DirectiveLoc);
938
939 // ".err"
940 bool parseDirectiveError(SMLoc DirectiveLoc);
941 // ".errb" or ".errnb", depending on ExpectBlank.
942 bool parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank);
943 // ".errdef" or ".errndef", depending on ExpectBlank.
944 bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc, bool ExpectDefined);
945 // ".erridn", ".errdif", ".erridni", or ".errdifi", depending on ExpectEqual
946 // and CaseInsensitive.
947 bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
948 bool CaseInsensitive);
949 // ".erre" or ".errnz", depending on ExpectZero.
950 bool parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero);
951
952 // ".radix"
953 bool parseDirectiveRadix(SMLoc DirectiveLoc);
954
955 // "echo"
956 bool parseDirectiveEcho(SMLoc DirectiveLoc);
957
958 void initializeDirectiveKindMap();
959 void initializeBuiltinSymbolMaps();
960};
961
962} // end anonymous namespace
963
964namespace llvm {
965
967
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(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(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 if (!Parser->SavedDiagHandler)
2402 DiagSrcMgr.printIncludeStackForDiagnostic(DiagLoc, OS);
2403
2404 // If we have not parsed a cpp hash line filename comment or the source
2405 // manager changed or buffer changed (like in a nested include) then just
2406 // print the normal diagnostic using its Filename and LineNo.
2407 if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
2408 DiagBuf != CppHashBuf) {
2409 if (Parser->SavedDiagHandler)
2410 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2411 else
2412 Diag.print(nullptr, OS);
2413 return;
2414 }
2415
2416 // Use the CppHashFilename and calculate a line number based on the
2417 // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
2418 // for the diagnostic.
2419 const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
2420
2421 int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
2422 int CppHashLocLineNo =
2423 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2424 int LineNo =
2425 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2426
2427 SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
2428 Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
2429 Diag.getLineContents(), Diag.getRanges());
2430
2431 if (Parser->SavedDiagHandler)
2432 Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
2433 else
2434 NewDiag.print(nullptr, OS);
2435}
2436
2437// This is similar to the IsIdentifierChar function in AsmLexer.cpp, but does
2438// not accept '.'.
2439static bool isMacroParameterChar(char C) {
2440 return isAlnum(C) || C == '_' || C == '$' || C == '@' || C == '?';
2441}
2442
2443bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
2446 const std::vector<std::string> &Locals, SMLoc L) {
2447 unsigned NParameters = Parameters.size();
2448 if (NParameters != A.size())
2449 return Error(L, "Wrong number of arguments");
2450 StringMap<std::string> LocalSymbols;
2451 std::string Name;
2452 Name.reserve(6);
2453 for (StringRef Local : Locals) {
2454 raw_string_ostream LocalName(Name);
2455 LocalName << "??"
2456 << format_hex_no_prefix(LocalCounter++, 4, /*Upper=*/true);
2457 LocalSymbols.insert({Local, Name});
2458 Name.clear();
2459 }
2460
2461 std::optional<char> CurrentQuote;
2462 while (!Body.empty()) {
2463 // Scan for the next substitution.
2464 std::size_t End = Body.size(), Pos = 0;
2465 std::size_t IdentifierPos = End;
2466 for (; Pos != End; ++Pos) {
2467 // Find the next possible macro parameter, including preceding a '&'
2468 // inside quotes.
2469 if (Body[Pos] == '&')
2470 break;
2471 if (isMacroParameterChar(Body[Pos])) {
2472 if (!CurrentQuote)
2473 break;
2474 if (IdentifierPos == End)
2475 IdentifierPos = Pos;
2476 } else {
2477 IdentifierPos = End;
2478 }
2479
2480 // Track quotation status
2481 if (!CurrentQuote) {
2482 if (Body[Pos] == '\'' || Body[Pos] == '"')
2483 CurrentQuote = Body[Pos];
2484 } else if (Body[Pos] == CurrentQuote) {
2485 if (Pos + 1 != End && Body[Pos + 1] == CurrentQuote) {
2486 // Escaped quote, and quotes aren't identifier chars; skip
2487 ++Pos;
2488 continue;
2489 } else {
2490 CurrentQuote.reset();
2491 }
2492 }
2493 }
2494 if (IdentifierPos != End) {
2495 // We've recognized an identifier before an apostrophe inside quotes;
2496 // check once to see if we can expand it.
2497 Pos = IdentifierPos;
2498 IdentifierPos = End;
2499 }
2500
2501 // Add the prefix.
2502 OS << Body.slice(0, Pos);
2503
2504 // Check if we reached the end.
2505 if (Pos == End)
2506 break;
2507
2508 unsigned I = Pos;
2509 bool InitialAmpersand = (Body[I] == '&');
2510 if (InitialAmpersand) {
2511 ++I;
2512 ++Pos;
2513 }
2514 while (I < End && isMacroParameterChar(Body[I]))
2515 ++I;
2516
2517 const char *Begin = Body.data() + Pos;
2518 StringRef Argument(Begin, I - Pos);
2519 const std::string ArgumentLower = Argument.lower();
2520 unsigned Index = 0;
2521
2522 for (; Index < NParameters; ++Index)
2523 if (Parameters[Index].Name.equals_insensitive(ArgumentLower))
2524 break;
2525
2526 if (Index == NParameters) {
2527 if (InitialAmpersand)
2528 OS << '&';
2529 auto it = LocalSymbols.find(ArgumentLower);
2530 if (it != LocalSymbols.end())
2531 OS << it->second;
2532 else
2533 OS << Argument;
2534 Pos = I;
2535 } else {
2536 for (const AsmToken &Token : A[Index]) {
2537 // In MASM, you can write '%expr'.
2538 // The prefix '%' evaluates the expression 'expr'
2539 // and uses the result as a string (e.g. replace %(1+2) with the
2540 // string "3").
2541 // Here, we identify the integer token which is the result of the
2542 // absolute expression evaluation and replace it with its string
2543 // representation.
2544 if (Token.getString().front() == '%' && Token.is(AsmToken::Integer))
2545 // Emit an integer value to the buffer.
2546 OS << Token.getIntVal();
2547 else
2548 OS << Token.getString();
2549 }
2550
2551 Pos += Argument.size();
2552 if (Pos < End && Body[Pos] == '&') {
2553 ++Pos;
2554 }
2555 }
2556 // Update the scan point.
2557 Body = Body.substr(Pos);
2558 }
2559
2560 return false;
2561}
2562
2563bool MasmParser::parseMacroArgument(const MCAsmMacroParameter *MP,
2564 MCAsmMacroArgument &MA,
2565 AsmToken::TokenKind EndTok) {
2566 if (MP && MP->Vararg) {
2567 if (Lexer.isNot(EndTok)) {
2568 SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok);
2569 for (StringRef S : Str) {
2570 MA.emplace_back(AsmToken::String, S);
2571 }
2572 }
2573 return false;
2574 }
2575
2576 SMLoc StrLoc = Lexer.getLoc(), EndLoc;
2577 if (Lexer.is(AsmToken::Less) && isAngleBracketString(StrLoc, EndLoc)) {
2578 const char *StrChar = StrLoc.getPointer() + 1;
2579 const char *EndChar = EndLoc.getPointer() - 1;
2580 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
2581 /// Eat from '<' to '>'.
2582 Lex();
2583 MA.emplace_back(AsmToken::String, StringRef(StrChar, EndChar - StrChar));
2584 return false;
2585 }
2586
2587 unsigned ParenLevel = 0;
2588
2589 while (true) {
2590 if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
2591 return TokError("unexpected token");
2592
2593 if (ParenLevel == 0 && Lexer.is(AsmToken::Comma))
2594 break;
2595
2596 // handleMacroEntry relies on not advancing the lexer here
2597 // to be able to fill in the remaining default parameter values
2598 if (Lexer.is(EndTok) && (EndTok != AsmToken::RParen || ParenLevel == 0))
2599 break;
2600
2601 // Adjust the current parentheses level.
2602 if (Lexer.is(AsmToken::LParen))
2603 ++ParenLevel;
2604 else if (Lexer.is(AsmToken::RParen) && ParenLevel)
2605 --ParenLevel;
2606
2607 // Append the token to the current argument list.
2608 MA.push_back(getTok());
2609 Lex();
2610 }
2611
2612 if (ParenLevel != 0)
2613 return TokError("unbalanced parentheses in argument");
2614
2615 if (MA.empty() && MP) {
2616 if (MP->Required) {
2617 return TokError("missing value for required parameter '" + MP->Name +
2618 "'");
2619 } else {
2620 MA = MP->Value;
2621 }
2622 }
2623 return false;
2624}
2625
2626// Parse the macro instantiation arguments.
2627bool MasmParser::parseMacroArguments(const MCAsmMacro *M,
2628 MCAsmMacroArguments &A,
2629 AsmToken::TokenKind EndTok) {
2630 const unsigned NParameters = M ? M->Parameters.size() : 0;
2631 bool NamedParametersFound = false;
2632 SmallVector<SMLoc, 4> FALocs;
2633
2634 A.resize(NParameters);
2635 FALocs.resize(NParameters);
2636
2637 // Parse two kinds of macro invocations:
2638 // - macros defined without any parameters accept an arbitrary number of them
2639 // - macros defined with parameters accept at most that many of them
2640 for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
2641 ++Parameter) {
2642 SMLoc IDLoc = Lexer.getLoc();
2643 MCAsmMacroParameter FA;
2644
2645 if (Lexer.is(AsmToken::Identifier) && peekTok().is(AsmToken::Equal)) {
2646 if (parseIdentifier(FA.Name))
2647 return Error(IDLoc, "invalid argument identifier for formal argument");
2648
2649 if (Lexer.isNot(AsmToken::Equal))
2650 return TokError("expected '=' after formal parameter identifier");
2651
2652 Lex();
2653
2654 NamedParametersFound = true;
2655 }
2656
2657 if (NamedParametersFound && FA.Name.empty())
2658 return Error(IDLoc, "cannot mix positional and keyword arguments");
2659
2660 unsigned PI = Parameter;
2661 if (!FA.Name.empty()) {
2662 assert(M && "expected macro to be defined");
2663 unsigned FAI = 0;
2664 for (FAI = 0; FAI < NParameters; ++FAI)
2665 if (M->Parameters[FAI].Name == FA.Name)
2666 break;
2667
2668 if (FAI >= NParameters) {
2669 return Error(IDLoc, "parameter named '" + FA.Name +
2670 "' does not exist for macro '" + M->Name + "'");
2671 }
2672 PI = FAI;
2673 }
2674 const MCAsmMacroParameter *MP = nullptr;
2675 if (M && PI < NParameters)
2676 MP = &M->Parameters[PI];
2677
2678 SMLoc StrLoc = Lexer.getLoc();
2679 SMLoc EndLoc;
2680 if (Lexer.is(AsmToken::Percent)) {
2681 const MCExpr *AbsoluteExp;
2682 int64_t Value;
2683 /// Eat '%'.
2684 Lex();
2685 if (parseExpression(AbsoluteExp, EndLoc))
2686 return false;
2687 if (!AbsoluteExp->evaluateAsAbsolute(Value,
2688 getStreamer().getAssemblerPtr()))
2689 return Error(StrLoc, "expected absolute expression");
2690 const char *StrChar = StrLoc.getPointer();
2691 const char *EndChar = EndLoc.getPointer();
2692 AsmToken newToken(AsmToken::Integer,
2693 StringRef(StrChar, EndChar - StrChar), Value);
2694 FA.Value.push_back(newToken);
2695 } else if (parseMacroArgument(MP, FA.Value, EndTok)) {
2696 if (M)
2697 return addErrorSuffix(" in '" + M->Name + "' macro");
2698 else
2699 return true;
2700 }
2701
2702 if (!FA.Value.empty()) {
2703 if (A.size() <= PI)
2704 A.resize(PI + 1);
2705 A[PI] = FA.Value;
2706
2707 if (FALocs.size() <= PI)
2708 FALocs.resize(PI + 1);
2709
2710 FALocs[PI] = Lexer.getLoc();
2711 }
2712
2713 // At the end of the statement, fill in remaining arguments that have
2714 // default values. If there aren't any, then the next argument is
2715 // required but missing
2716 if (Lexer.is(EndTok)) {
2717 bool Failure = false;
2718 for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
2719 if (A[FAI].empty()) {
2720 if (M->Parameters[FAI].Required) {
2721 Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
2722 "missing value for required parameter "
2723 "'" +
2724 M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
2725 Failure = true;
2726 }
2727
2728 if (!M->Parameters[FAI].Value.empty())
2729 A[FAI] = M->Parameters[FAI].Value;
2730 }
2731 }
2732 return Failure;
2733 }
2734
2735 if (Lexer.is(AsmToken::Comma))
2736 Lex();
2737 }
2738
2739 return TokError("too many positional arguments");
2740}
2741
2742bool MasmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc,
2743 AsmToken::TokenKind ArgumentEndTok) {
2744 // Arbitrarily limit macro nesting depth (default matches 'as'). We can
2745 // eliminate this, although we should protect against infinite loops.
2746 unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;
2747 if (ActiveMacros.size() == MaxNestingDepth) {
2748 std::ostringstream MaxNestingDepthError;
2749 MaxNestingDepthError << "macros cannot be nested more than "
2750 << MaxNestingDepth << " levels deep."
2751 << " Use -asm-macro-max-nesting-depth to increase "
2752 "this limit.";
2753 return TokError(MaxNestingDepthError.str());
2754 }
2755
2756 MCAsmMacroArguments A;
2757 if (parseMacroArguments(M, A, ArgumentEndTok) || parseToken(ArgumentEndTok))
2758 return true;
2759
2760 // Macro instantiation is lexical, unfortunately. We construct a new buffer
2761 // to hold the macro body with substitutions.
2762 SmallString<256> Buf;
2763 StringRef Body = M->Body;
2764 raw_svector_ostream OS(Buf);
2765
2766 if (expandMacro(OS, Body, M->Parameters, A, M->Locals, getTok().getLoc()))
2767 return true;
2768
2769 // We include the endm in the buffer as our cue to exit the macro
2770 // instantiation.
2771 OS << "endm\n";
2772
2773 std::unique_ptr<MemoryBuffer> Instantiation =
2774 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
2775
2776 // Create the macro instantiation object and add to the current macro
2777 // instantiation stack.
2778 MacroInstantiation *MI = new MacroInstantiation{
2779 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
2780 ActiveMacros.push_back(MI);
2781
2782 ++NumOfMacroInstantiations;
2783
2784 // Jump to the macro instantiation and prime the lexer.
2785 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
2786 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
2787 EndStatementAtEOFStack.push_back(true);
2788 Lex();
2789
2790 return false;
2791}
2792
2793void MasmParser::handleMacroExit() {
2794 // Jump to the token we should return to, and consume it.
2795 EndStatementAtEOFStack.pop_back();
2796 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer,
2797 EndStatementAtEOFStack.back());
2798 Lex();
2799
2800 // Pop the instantiation entry.
2801 delete ActiveMacros.back();
2802 ActiveMacros.pop_back();
2803}
2804
2805bool MasmParser::handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc) {
2806 if (!M->IsFunction)
2807 return Error(NameLoc, "cannot invoke macro procedure as function");
2808
2809 if (parseToken(AsmToken::LParen, "invoking macro function '" + M->Name +
2810 "' requires arguments in parentheses") ||
2811 handleMacroEntry(M, NameLoc, AsmToken::RParen))
2812 return true;
2813
2814 // Parse all statements in the macro, retrieving the exit value when it ends.
2815 std::string ExitValue;
2816 SmallVector<AsmRewrite, 4> AsmStrRewrites;
2817 while (Lexer.isNot(AsmToken::Eof)) {
2818 ParseStatementInfo Info(&AsmStrRewrites);
2819 bool HasError = parseStatement(Info, nullptr);
2820
2821 if (!HasError && Info.ExitValue) {
2822 ExitValue = std::move(*Info.ExitValue);
2823 break;
2824 }
2825
2826 // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
2827 // for printing ErrMsg via Lex() only if no (presumably better) parser error
2828 // exists.
2829 if (HasError && !hasPendingError() && Lexer.getTok().is(AsmToken::Error))
2830 Lex();
2831
2832 // parseStatement returned true so may need to emit an error.
2833 printPendingErrors();
2834
2835 // Skipping to the next line if needed.
2836 if (HasError && !getLexer().justConsumedEOL())
2837 eatToEndOfStatement();
2838 }
2839
2840 // Exit values may require lexing, unfortunately. We construct a new buffer to
2841 // hold the exit value.
2842 std::unique_ptr<MemoryBuffer> MacroValue =
2843 MemoryBuffer::getMemBufferCopy(ExitValue, "<macro-value>");
2844
2845 // Jump from this location to the instantiated exit value, and prime the
2846 // lexer.
2847 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(MacroValue), Lexer.getLoc());
2848 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), nullptr,
2849 /*EndStatementAtEOF=*/false);
2850 EndStatementAtEOFStack.push_back(false);
2851 Lex();
2852
2853 return false;
2854}
2855
2856/// parseIdentifier:
2857/// ::= identifier
2858/// ::= string
2859bool MasmParser::parseIdentifier(StringRef &Res,
2860 IdentifierPositionKind Position) {
2861 // The assembler has relaxed rules for accepting identifiers, in particular we
2862 // allow things like '.globl $foo' and '.def @feat.00', which would normally
2863 // be separate tokens. At this level, we have already lexed so we cannot
2864 // (currently) handle this as a context dependent token, instead we detect
2865 // adjacent tokens and return the combined identifier.
2866 if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
2867 SMLoc PrefixLoc = getLexer().getLoc();
2868
2869 // Consume the prefix character, and check for a following identifier.
2870
2871 AsmToken nextTok = peekTok(false);
2872
2873 if (nextTok.isNot(AsmToken::Identifier))
2874 return true;
2875
2876 // We have a '$' or '@' followed by an identifier, make sure they are adjacent.
2877 if (PrefixLoc.getPointer() + 1 != nextTok.getLoc().getPointer())
2878 return true;
2879
2880 // eat $ or @
2881 Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
2882 // Construct the joined identifier and consume the token.
2883 Res =
2884 StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1);
2885 Lex(); // Parser Lex to maintain invariants.
2886 return false;
2887 }
2888
2889 if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
2890 return true;
2891
2892 Res = getTok().getIdentifier();
2893
2894 // Consume the identifier token - but if parsing certain directives, avoid
2895 // lexical expansion of the next token.
2896 ExpandKind ExpandNextToken = ExpandMacros;
2897 if (Position == StartOfStatement &&
2898 StringSwitch<bool>(Res)
2899 .CaseLower("echo", true)
2900 .CasesLower({"ifdef", "ifndef", "elseifdef", "elseifndef"}, true)
2901 .Default(false)) {
2902 ExpandNextToken = DoNotExpandMacros;
2903 }
2904 Lex(ExpandNextToken);
2905
2906 return false;
2907}
2908
2909/// parseDirectiveEquate:
2910/// ::= name "=" expression
2911/// | name "equ" expression (not redefinable)
2912/// | name "equ" text-list
2913/// | name "textequ" text-list (redefinability unspecified)
2914bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
2915 DirectiveKind DirKind, SMLoc NameLoc) {
2916 auto BuiltinIt = BuiltinSymbolMap.find(Name.lower());
2917 if (BuiltinIt != BuiltinSymbolMap.end())
2918 return Error(NameLoc, "cannot redefine a built-in symbol");
2919
2920 Variable &Var = Variables[Name.lower()];
2921 if (Var.Name.empty()) {
2922 Var.Name = Name;
2923 }
2924
2925 SMLoc StartLoc = Lexer.getLoc();
2926 if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) {
2927 // "equ" and "textequ" both allow text expressions.
2928 std::string Value;
2929 std::string TextItem;
2930 if (!parseTextItem(TextItem)) {
2931 Value += TextItem;
2932
2933 // Accept a text-list, not just one text-item.
2934 auto parseItem = [&]() -> bool {
2935 if (parseTextItem(TextItem))
2936 return TokError("expected text item");
2937 Value += TextItem;
2938 return false;
2939 };
2940 if (parseOptionalToken(AsmToken::Comma) && parseMany(parseItem))
2941 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
2942
2943 if (!Var.IsText || Var.TextValue != Value) {
2944 switch (Var.Redefinable) {
2945 case Variable::NOT_REDEFINABLE:
2946 return Error(getTok().getLoc(), "invalid variable redefinition");
2947 case Variable::WARN_ON_REDEFINITION:
2948 if (Warning(NameLoc, "redefining '" + Name +
2949 "', already defined on the command line")) {
2950 return true;
2951 }
2952 break;
2953 default:
2954 break;
2955 }
2956 }
2957 Var.IsText = true;
2958 Var.TextValue = Value;
2959 Var.Redefinable = Variable::REDEFINABLE;
2960
2961 return false;
2962 }
2963 }
2964 if (DirKind == DK_TEXTEQU)
2965 return TokError("expected <text> in '" + Twine(IDVal) + "' directive");
2966
2967 // Parse as expression assignment.
2968 const MCExpr *Expr;
2969 SMLoc EndLoc;
2970 if (parseExpression(Expr, EndLoc))
2971 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
2972 StringRef ExprAsString = StringRef(
2973 StartLoc.getPointer(), EndLoc.getPointer() - StartLoc.getPointer());
2974
2975 int64_t Value;
2976 if (!Expr->evaluateAsAbsolute(Value, getStreamer().getAssemblerPtr())) {
2977 if (DirKind == DK_ASSIGN)
2978 return Error(
2979 StartLoc,
2980 "expected absolute expression; not all symbols have known values",
2981 {StartLoc, EndLoc});
2982
2983 // Not an absolute expression; define as a text replacement.
2984 if (!Var.IsText || Var.TextValue != ExprAsString) {
2985 switch (Var.Redefinable) {
2986 case Variable::NOT_REDEFINABLE:
2987 return Error(getTok().getLoc(), "invalid variable redefinition");
2988 case Variable::WARN_ON_REDEFINITION:
2989 if (Warning(NameLoc, "redefining '" + Name +
2990 "', already defined on the command line")) {
2991 return true;
2992 }
2993 break;
2994 default:
2995 break;
2996 }
2997 }
2998
2999 Var.IsText = true;
3000 Var.TextValue = ExprAsString.str();
3001 Var.Redefinable = Variable::REDEFINABLE;
3002
3003 return false;
3004 }
3005
3006 auto *Sym = static_cast<MCSymbolCOFF *>(getContext().parseSymbol(Var.Name));
3007 const MCConstantExpr *PrevValue =
3008 Sym->isVariable()
3010 : nullptr;
3011 if (Var.IsText || !PrevValue || PrevValue->getValue() != Value) {
3012 switch (Var.Redefinable) {
3013 case Variable::NOT_REDEFINABLE:
3014 return Error(getTok().getLoc(), "invalid variable redefinition");
3015 case Variable::WARN_ON_REDEFINITION:
3016 if (Warning(NameLoc, "redefining '" + Name +
3017 "', already defined on the command line")) {
3018 return true;
3019 }
3020 break;
3021 default:
3022 break;
3023 }
3024 }
3025
3026 Var.IsText = false;
3027 Var.TextValue.clear();
3028 Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE
3029 : Variable::NOT_REDEFINABLE;
3030
3031 Sym->setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE);
3032 Sym->setVariableValue(Expr);
3033 Sym->setExternal(false);
3034
3035 return false;
3036}
3037
3038bool MasmParser::parseEscapedString(std::string &Data) {
3039 if (check(getTok().isNot(AsmToken::String), "expected string"))
3040 return true;
3041
3042 Data = "";
3043 char Quote = getTok().getString().front();
3044 StringRef Str = getTok().getStringContents();
3045 Data.reserve(Str.size());
3046 for (size_t i = 0, e = Str.size(); i != e; ++i) {
3047 Data.push_back(Str[i]);
3048 if (Str[i] == Quote) {
3049 // MASM treats doubled delimiting quotes as an escaped delimiting quote.
3050 // If we're escaping the string's trailing delimiter, we're definitely
3051 // missing a quotation mark.
3052 if (i + 1 == Str.size())
3053 return Error(getTok().getLoc(), "missing quotation mark in string");
3054 if (Str[i + 1] == Quote)
3055 ++i;
3056 }
3057 }
3058
3059 Lex();
3060 return false;
3061}
3062
3063bool MasmParser::parseAngleBracketString(std::string &Data) {
3064 SMLoc EndLoc, StartLoc = getTok().getLoc();
3065 if (isAngleBracketString(StartLoc, EndLoc)) {
3066 const char *StartChar = StartLoc.getPointer() + 1;
3067 const char *EndChar = EndLoc.getPointer() - 1;
3068 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
3069 // Eat from '<' to '>'.
3070 Lex();
3071
3072 Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
3073 return false;
3074 }
3075 return true;
3076}
3077
3078/// textItem ::= textLiteral | textMacroID | % constExpr
3079bool MasmParser::parseTextItem(std::string &Data) {
3080 switch (getTok().getKind()) {
3081 default:
3082 return true;
3083 case AsmToken::Percent: {
3084 int64_t Res;
3085 if (parseToken(AsmToken::Percent) || parseAbsoluteExpression(Res))
3086 return true;
3087 Data = std::to_string(Res);
3088 return false;
3089 }
3090 case AsmToken::Less:
3092 case AsmToken::LessLess:
3094 return parseAngleBracketString(Data);
3095 case AsmToken::Identifier: {
3096 // This must be a text macro; we need to expand it accordingly.
3097 StringRef ID;
3098 SMLoc StartLoc = getTok().getLoc();
3099 if (parseIdentifier(ID))
3100 return true;
3101 Data = ID.str();
3102
3103 bool Expanded = false;
3104 while (true) {
3105 // Try to resolve as a built-in text macro
3106 auto BuiltinIt = BuiltinSymbolMap.find(ID.lower());
3107 if (BuiltinIt != BuiltinSymbolMap.end()) {
3108 std::optional<std::string> BuiltinText =
3109 evaluateBuiltinTextMacro(BuiltinIt->getValue(), StartLoc);
3110 if (!BuiltinText) {
3111 // Not a text macro; break without substituting
3112 break;
3113 }
3114 Data = std::move(*BuiltinText);
3115 ID = StringRef(Data);
3116 Expanded = true;
3117 continue;
3118 }
3119
3120 // Try to resolve as a built-in macro function
3121 auto BuiltinFuncIt = BuiltinFunctionMap.find(ID.lower());
3122 if (BuiltinFuncIt != BuiltinFunctionMap.end()) {
3123 Data.clear();
3124 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), ID, Data)) {
3125 return true;
3126 }
3127 ID = StringRef(Data);
3128 Expanded = true;
3129 continue;
3130 }
3131
3132 // Try to resolve as a variable text macro
3133 auto VarIt = Variables.find(ID.lower());
3134 if (VarIt != Variables.end()) {
3135 const Variable &Var = VarIt->getValue();
3136 if (!Var.IsText) {
3137 // Not a text macro; break without substituting
3138 break;
3139 }
3140 Data = Var.TextValue;
3141 ID = StringRef(Data);
3142 Expanded = true;
3143 continue;
3144 }
3145
3146 break;
3147 }
3148
3149 if (!Expanded) {
3150 // Not a text macro; not usable in TextItem context. Since we haven't used
3151 // the token, put it back for better error recovery.
3152 getLexer().UnLex(AsmToken(AsmToken::Identifier, ID));
3153 return true;
3154 }
3155 return false;
3156 }
3157 }
3158 llvm_unreachable("unhandled token kind");
3159}
3160
3161/// parseDirectiveAscii:
3162/// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
3163bool MasmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
3164 auto parseOp = [&]() -> bool {
3165 std::string Data;
3166 if (checkForValidSection() || parseEscapedString(Data))
3167 return true;
3168 getStreamer().emitBytes(Data);
3169 if (ZeroTerminated)
3170 getStreamer().emitBytes(StringRef("\0", 1));
3171 return false;
3172 };
3173
3174 if (parseMany(parseOp))
3175 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3176 return false;
3177}
3178
3179bool MasmParser::emitIntValue(const MCExpr *Value, unsigned Size) {
3180 // Special case constant expressions to match code generator.
3181 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
3182 assert(Size <= 8 && "Invalid size");
3183 int64_t IntValue = MCE->getValue();
3184 if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
3185 return Error(MCE->getLoc(), "out of range literal value");
3186 getStreamer().emitIntValue(IntValue, Size);
3187 } else {
3188 const MCSymbolRefExpr *MSE = dyn_cast<MCSymbolRefExpr>(Value);
3189 if (MSE && MSE->getSymbol().getName() == "?") {
3190 // ? initializer; treat as 0.
3191 getStreamer().emitIntValue(0, Size);
3192 } else {
3193 getStreamer().emitValue(Value, Size, Value->getLoc());
3194 }
3195 }
3196 return false;
3197}
3198
3199bool MasmParser::parseScalarInitializer(unsigned Size,
3200 SmallVectorImpl<const MCExpr *> &Values,
3201 unsigned StringPadLength) {
3202 if (Size == 1 && getTok().is(AsmToken::String)) {
3203 std::string Value;
3204 if (parseEscapedString(Value))
3205 return true;
3206 // Treat each character as an initializer.
3207 for (const unsigned char CharVal : Value)
3208 Values.push_back(MCConstantExpr::create(CharVal, getContext()));
3209
3210 // Pad the string with spaces to the specified length.
3211 for (size_t i = Value.size(); i < StringPadLength; ++i)
3212 Values.push_back(MCConstantExpr::create(' ', getContext()));
3213 } else {
3214 const MCExpr *Value;
3215 if (parseExpression(Value))
3216 return true;
3217 if (getTok().is(AsmToken::Identifier) &&
3218 getTok().getString().equals_insensitive("dup")) {
3219 Lex(); // Eat 'dup'.
3220 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
3221 if (!MCE)
3222 return Error(Value->getLoc(),
3223 "cannot repeat value a non-constant number of times");
3224 const int64_t Repetitions = MCE->getValue();
3225 if (Repetitions < 0)
3226 return Error(Value->getLoc(),
3227 "cannot repeat value a negative number of times");
3228
3229 SmallVector<const MCExpr *, 1> DuplicatedValues;
3230 if (parseToken(AsmToken::LParen,
3231 "parentheses required for 'dup' contents") ||
3232 parseScalarInstList(Size, DuplicatedValues) || parseRParen())
3233 return true;
3234
3235 for (int i = 0; i < Repetitions; ++i)
3236 Values.append(DuplicatedValues.begin(), DuplicatedValues.end());
3237 } else {
3238 Values.push_back(Value);
3239 }
3240 }
3241 return false;
3242}
3243
3244bool MasmParser::parseScalarInstList(unsigned Size,
3245 SmallVectorImpl<const MCExpr *> &Values,
3246 const AsmToken::TokenKind EndToken) {
3247 while (getTok().isNot(EndToken) &&
3248 (EndToken != AsmToken::Greater ||
3249 getTok().isNot(AsmToken::GreaterGreater))) {
3250 parseScalarInitializer(Size, Values);
3251
3252 // If we see a comma, continue, and allow line continuation.
3253 if (!parseOptionalToken(AsmToken::Comma))
3254 break;
3255 parseOptionalToken(AsmToken::EndOfStatement);
3256 }
3257 return false;
3258}
3259
3260bool MasmParser::emitIntegralValues(unsigned Size, unsigned *Count) {
3262 if (checkForValidSection() || parseScalarInstList(Size, Values))
3263 return true;
3264
3265 for (const auto *Value : Values) {
3266 emitIntValue(Value, Size);
3267 }
3268 if (Count)
3269 *Count = Values.size();
3270 return false;
3271}
3272
3273// Add a field to the current structure.
3274bool MasmParser::addIntegralField(StringRef Name, unsigned Size) {
3275 StructInfo &Struct = StructInProgress.back();
3276 FieldInfo &Field = Struct.addField(Name, FT_INTEGRAL, Size);
3277 IntFieldInfo &IntInfo = Field.Contents.IntInfo;
3278
3279 Field.Type = Size;
3280
3281 if (parseScalarInstList(Size, IntInfo.Values))
3282 return true;
3283
3284 Field.SizeOf = Field.Type * IntInfo.Values.size();
3285 Field.LengthOf = IntInfo.Values.size();
3286 const unsigned FieldEnd = Field.Offset + Field.SizeOf;
3287 if (!Struct.IsUnion) {
3288 Struct.NextOffset = FieldEnd;
3289 }
3290 Struct.Size = std::max(Struct.Size, FieldEnd);
3291 return false;
3292}
3293
3294/// parseDirectiveValue
3295/// ::= (byte | word | ... ) [ expression (, expression)* ]
3296bool MasmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
3297 if (StructInProgress.empty()) {
3298 // Initialize data value.
3299 if (emitIntegralValues(Size))
3300 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3301 } else if (addIntegralField("", Size)) {
3302 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3303 }
3304
3305 return false;
3306}
3307
3308/// parseDirectiveNamedValue
3309/// ::= name (byte | word | ... ) [ expression (, expression)* ]
3310bool MasmParser::parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
3311 StringRef Name, SMLoc NameLoc) {
3312 if (StructInProgress.empty()) {
3313 // Initialize named data value.
3314 MCSymbol *Sym = getContext().parseSymbol(Name);
3315 getStreamer().emitLabel(Sym);
3316 unsigned Count;
3317 if (emitIntegralValues(Size, &Count))
3318 return addErrorSuffix(" in '" + Twine(TypeName) + "' directive");
3319
3320 AsmTypeInfo Type;
3321 Type.Name = TypeName;
3322 Type.Size = Size * Count;
3323 Type.ElementSize = Size;
3324 Type.Length = Count;
3325 KnownType[Name.lower()] = Type;
3326 } else if (addIntegralField(Name, Size)) {
3327 return addErrorSuffix(" in '" + Twine(TypeName) + "' directive");
3328 }
3329
3330 return false;
3331}
3332
3333bool MasmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
3334 // We don't truly support arithmetic on floating point expressions, so we
3335 // have to manually parse unary prefixes.
3336 bool IsNeg = false;
3337 SMLoc SignLoc;
3338 if (getLexer().is(AsmToken::Minus)) {
3339 SignLoc = getLexer().getLoc();
3340 Lexer.Lex();
3341 IsNeg = true;
3342 } else if (getLexer().is(AsmToken::Plus)) {
3343 SignLoc = getLexer().getLoc();
3344 Lexer.Lex();
3345 }
3346
3347 if (Lexer.is(AsmToken::Error))
3348 return TokError(Lexer.getErr());
3349 if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
3350 Lexer.isNot(AsmToken::Identifier))
3351 return TokError("unexpected token in directive");
3352
3353 // Convert to an APFloat.
3354 APFloat Value(Semantics);
3355 StringRef IDVal = getTok().getString();
3356 if (getLexer().is(AsmToken::Identifier)) {
3357 if (IDVal.equals_insensitive("infinity") || IDVal.equals_insensitive("inf"))
3358 Value = APFloat::getInf(Semantics);
3359 else if (IDVal.equals_insensitive("nan"))
3360 Value = APFloat::getNaN(Semantics, false, ~0);
3361 else if (IDVal.equals_insensitive("?"))
3362 Value = APFloat::getZero(Semantics);
3363 else
3364 return TokError("invalid floating point literal");
3365 } else if (IDVal.consume_back("r") || IDVal.consume_back("R")) {
3366 // MASM hexadecimal floating-point literal; no APFloat conversion needed.
3367 // To match ML64.exe, ignore the initial sign.
3368 unsigned SizeInBits = Value.getSizeInBits(Semantics);
3369 if (SizeInBits != (IDVal.size() << 2))
3370 return TokError("invalid floating point literal");
3371
3372 // Consume the numeric token.
3373 Lex();
3374
3375 Res = APInt(SizeInBits, IDVal, 16);
3376 if (SignLoc.isValid())
3377 return Warning(SignLoc, "MASM-style hex floats ignore explicit sign");
3378 return false;
3379 } else if (errorToBool(
3380 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3381 .takeError())) {
3382 return TokError("invalid floating point literal");
3383 }
3384 if (IsNeg)
3385 Value.changeSign();
3386
3387 // Consume the numeric token.
3388 Lex();
3389
3390 Res = Value.bitcastToAPInt();
3391
3392 return false;
3393}
3394
3395bool MasmParser::parseRealInstList(const fltSemantics &Semantics,
3396 SmallVectorImpl<APInt> &ValuesAsInt,
3397 const AsmToken::TokenKind EndToken) {
3398 while (getTok().isNot(EndToken) ||
3399 (EndToken == AsmToken::Greater &&
3400 getTok().isNot(AsmToken::GreaterGreater))) {
3401 const AsmToken NextTok = peekTok();
3402 if (NextTok.is(AsmToken::Identifier) &&
3403 NextTok.getString().equals_insensitive("dup")) {
3404 const MCExpr *Value;
3405 if (parseExpression(Value) || parseToken(AsmToken::Identifier))
3406 return true;
3407 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
3408 if (!MCE)
3409 return Error(Value->getLoc(),
3410 "cannot repeat value a non-constant number of times");
3411 const int64_t Repetitions = MCE->getValue();
3412 if (Repetitions < 0)
3413 return Error(Value->getLoc(),
3414 "cannot repeat value a negative number of times");
3415
3416 SmallVector<APInt, 1> DuplicatedValues;
3417 if (parseToken(AsmToken::LParen,
3418 "parentheses required for 'dup' contents") ||
3419 parseRealInstList(Semantics, DuplicatedValues) || parseRParen())
3420 return true;
3421
3422 for (int i = 0; i < Repetitions; ++i)
3423 ValuesAsInt.append(DuplicatedValues.begin(), DuplicatedValues.end());
3424 } else {
3425 APInt AsInt;
3426 if (parseRealValue(Semantics, AsInt))
3427 return true;
3428 ValuesAsInt.push_back(AsInt);
3429 }
3430
3431 // Continue if we see a comma. (Also, allow line continuation.)
3432 if (!parseOptionalToken(AsmToken::Comma))
3433 break;
3434 parseOptionalToken(AsmToken::EndOfStatement);
3435 }
3436
3437 return false;
3438}
3439
3440// Initialize real data values.
3441bool MasmParser::emitRealValues(const fltSemantics &Semantics,
3442 unsigned *Count) {
3443 if (checkForValidSection())
3444 return true;
3445
3446 SmallVector<APInt, 1> ValuesAsInt;
3447 if (parseRealInstList(Semantics, ValuesAsInt))
3448 return true;
3449
3450 for (const APInt &AsInt : ValuesAsInt) {
3451 getStreamer().emitIntValue(AsInt);
3452 }
3453 if (Count)
3454 *Count = ValuesAsInt.size();
3455 return false;
3456}
3457
3458// Add a real field to the current struct.
3459bool MasmParser::addRealField(StringRef Name, const fltSemantics &Semantics,
3460 size_t Size) {
3461 StructInfo &Struct = StructInProgress.back();
3462 FieldInfo &Field = Struct.addField(Name, FT_REAL, Size);
3463 RealFieldInfo &RealInfo = Field.Contents.RealInfo;
3464
3465 Field.SizeOf = 0;
3466
3467 if (parseRealInstList(Semantics, RealInfo.AsIntValues))
3468 return true;
3469
3470 Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
3471 Field.LengthOf = RealInfo.AsIntValues.size();
3472 Field.SizeOf = Field.Type * Field.LengthOf;
3473
3474 const unsigned FieldEnd = Field.Offset + Field.SizeOf;
3475 if (!Struct.IsUnion) {
3476 Struct.NextOffset = FieldEnd;
3477 }
3478 Struct.Size = std::max(Struct.Size, FieldEnd);
3479 return false;
3480}
3481
3482/// parseDirectiveRealValue
3483/// ::= (real4 | real8 | real10) [ expression (, expression)* ]
3484bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
3485 const fltSemantics &Semantics,
3486 size_t Size) {
3487 if (StructInProgress.empty()) {
3488 // Initialize data value.
3489 if (emitRealValues(Semantics))
3490 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3491 } else if (addRealField("", Semantics, Size)) {
3492 return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3493 }
3494 return false;
3495}
3496
3497/// parseDirectiveNamedRealValue
3498/// ::= name (real4 | real8 | real10) [ expression (, expression)* ]
3499bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
3500 const fltSemantics &Semantics,
3501 unsigned Size, StringRef Name,
3502 SMLoc NameLoc) {
3503 if (StructInProgress.empty()) {
3504 // Initialize named data value.
3505 MCSymbol *Sym = getContext().parseSymbol(Name);
3506 getStreamer().emitLabel(Sym);
3507 unsigned Count;
3508 if (emitRealValues(Semantics, &Count))
3509 return addErrorSuffix(" in '" + TypeName + "' directive");
3510
3511 AsmTypeInfo Type;
3512 Type.Name = TypeName;
3513 Type.Size = Size * Count;
3514 Type.ElementSize = Size;
3515 Type.Length = Count;
3516 KnownType[Name.lower()] = Type;
3517 } else if (addRealField(Name, Semantics, Size)) {
3518 return addErrorSuffix(" in '" + TypeName + "' directive");
3519 }
3520 return false;
3521}
3522
3523bool MasmParser::parseOptionalAngleBracketOpen() {
3524 const AsmToken Tok = getTok();
3525 if (parseOptionalToken(AsmToken::LessLess)) {
3526 AngleBracketDepth++;
3527 Lexer.UnLex(AsmToken(AsmToken::Less, Tok.getString().substr(1)));
3528 return true;
3529 } else if (parseOptionalToken(AsmToken::LessGreater)) {
3530 AngleBracketDepth++;
3531 Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1)));
3532 return true;
3533 } else if (parseOptionalToken(AsmToken::Less)) {
3534 AngleBracketDepth++;
3535 return true;
3536 }
3537
3538 return false;
3539}
3540
3541bool MasmParser::parseAngleBracketClose(const Twine &Msg) {
3542 const AsmToken Tok = getTok();
3543 if (parseOptionalToken(AsmToken::GreaterGreater)) {
3544 Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1)));
3545 } else if (parseToken(AsmToken::Greater, Msg)) {
3546 return true;
3547 }
3548 AngleBracketDepth--;
3549 return false;
3550}
3551
3552bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
3553 const IntFieldInfo &Contents,
3554 FieldInitializer &Initializer) {
3555 SMLoc Loc = getTok().getLoc();
3556
3558 if (parseOptionalToken(AsmToken::LCurly)) {
3559 if (Field.LengthOf == 1 && Field.Type > 1)
3560 return Error(Loc, "Cannot initialize scalar field with array value");
3561 if (parseScalarInstList(Field.Type, Values, AsmToken::RCurly) ||
3562 parseToken(AsmToken::RCurly))
3563 return true;
3564 } else if (parseOptionalAngleBracketOpen()) {
3565 if (Field.LengthOf == 1 && Field.Type > 1)
3566 return Error(Loc, "Cannot initialize scalar field with array value");
3567 if (parseScalarInstList(Field.Type, Values, AsmToken::Greater) ||
3568 parseAngleBracketClose())
3569 return true;
3570 } else if (Field.LengthOf > 1 && Field.Type > 1) {
3571 return Error(Loc, "Cannot initialize array field with scalar value");
3572 } else if (parseScalarInitializer(Field.Type, Values,
3573 /*StringPadLength=*/Field.LengthOf)) {
3574 return true;
3575 }
3576
3577 if (Values.size() > Field.LengthOf) {
3578 return Error(Loc, "Initializer too long for field; expected at most " +
3579 std::to_string(Field.LengthOf) + " elements, got " +
3580 std::to_string(Values.size()));
3581 }
3582 // Default-initialize all remaining values.
3583 Values.append(Contents.Values.begin() + Values.size(), Contents.Values.end());
3584
3585 Initializer = FieldInitializer(std::move(Values));
3586 return false;
3587}
3588
3589bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
3590 const RealFieldInfo &Contents,
3591 FieldInitializer &Initializer) {
3592 const fltSemantics *Semantics;
3593 switch (Field.Type) {
3594 case 4:
3595 Semantics = &APFloat::IEEEsingle();
3596 break;
3597 case 8:
3598 Semantics = &APFloat::IEEEdouble();
3599 break;
3600 case 10:
3601 Semantics = &APFloat::x87DoubleExtended();
3602 break;
3603 default:
3604 llvm_unreachable("unknown real field type");
3605 }
3606
3607 SMLoc Loc = getTok().getLoc();
3608
3609 SmallVector<APInt, 1> AsIntValues;
3610 if (parseOptionalToken(AsmToken::LCurly)) {
3611 if (Field.LengthOf == 1)
3612 return Error(Loc, "Cannot initialize scalar field with array value");
3613 if (parseRealInstList(*Semantics, AsIntValues, AsmToken::RCurly) ||
3614 parseToken(AsmToken::RCurly))
3615 return true;
3616 } else if (parseOptionalAngleBracketOpen()) {
3617 if (Field.LengthOf == 1)
3618 return Error(Loc, "Cannot initialize scalar field with array value");
3619 if (parseRealInstList(*Semantics, AsIntValues, AsmToken::Greater) ||
3620 parseAngleBracketClose())
3621 return true;
3622 } else if (Field.LengthOf > 1) {
3623 return Error(Loc, "Cannot initialize array field with scalar value");
3624 } else {
3625 AsIntValues.emplace_back();
3626 if (parseRealValue(*Semantics, AsIntValues.back()))
3627 return true;
3628 }
3629
3630 if (AsIntValues.size() > Field.LengthOf) {
3631 return Error(Loc, "Initializer too long for field; expected at most " +
3632 std::to_string(Field.LengthOf) + " elements, got " +
3633 std::to_string(AsIntValues.size()));
3634 }
3635 // Default-initialize all remaining values.
3636 AsIntValues.append(Contents.AsIntValues.begin() + AsIntValues.size(),
3637 Contents.AsIntValues.end());
3638
3639 Initializer = FieldInitializer(std::move(AsIntValues));
3640 return false;
3641}
3642
3643bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
3644 const StructFieldInfo &Contents,
3645 FieldInitializer &Initializer) {
3646 SMLoc Loc = getTok().getLoc();
3647
3648 std::vector<StructInitializer> Initializers;
3649 if (Field.LengthOf > 1) {
3650 if (parseOptionalToken(AsmToken::LCurly)) {
3651 if (parseStructInstList(Contents.Structure, Initializers,
3653 parseToken(AsmToken::RCurly))
3654 return true;
3655 } else if (parseOptionalAngleBracketOpen()) {
3656 if (parseStructInstList(Contents.Structure, Initializers,
3658 parseAngleBracketClose())
3659 return true;
3660 } else {
3661 return Error(Loc, "Cannot initialize array field with scalar value");
3662 }
3663 } else {
3664 Initializers.emplace_back();
3665 if (parseStructInitializer(Contents.Structure, Initializers.back()))
3666 return true;
3667 }
3668
3669 if (Initializers.size() > Field.LengthOf) {
3670 return Error(Loc, "Initializer too long for field; expected at most " +
3671 std::to_string(Field.LengthOf) + " elements, got " +
3672 std::to_string(Initializers.size()));
3673 }
3674 // Default-initialize all remaining values.
3675 llvm::append_range(Initializers, llvm::drop_begin(Contents.Initializers,
3676 Initializers.size()));
3677
3678 Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
3679 return false;
3680}
3681
3682bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
3683 FieldInitializer &Initializer) {
3684 switch (Field.Contents.FT) {
3685 case FT_INTEGRAL:
3686 return parseFieldInitializer(Field, Field.Contents.IntInfo, Initializer);
3687 case FT_REAL:
3688 return parseFieldInitializer(Field, Field.Contents.RealInfo, Initializer);
3689 case FT_STRUCT:
3690 return parseFieldInitializer(Field, Field.Contents.StructInfo, Initializer);
3691 }
3692 llvm_unreachable("Unhandled FieldType enum");
3693}
3694
3695bool MasmParser::parseStructInitializer(const StructInfo &Structure,
3696 StructInitializer &Initializer) {
3697 const AsmToken FirstToken = getTok();
3698
3699 std::optional<AsmToken::TokenKind> EndToken;
3700 if (parseOptionalToken(AsmToken::LCurly)) {
3701 EndToken = AsmToken::RCurly;
3702 } else if (parseOptionalAngleBracketOpen()) {
3703 EndToken = AsmToken::Greater;
3704 AngleBracketDepth++;
3705 } else if (FirstToken.is(AsmToken::Identifier) &&
3706 FirstToken.getString() == "?") {
3707 // ? initializer; leave EndToken uninitialized to treat as empty.
3708 if (parseToken(AsmToken::Identifier))
3709 return true;
3710 } else {
3711 return Error(FirstToken.getLoc(), "Expected struct initializer");
3712 }
3713
3714 auto &FieldInitializers = Initializer.FieldInitializers;
3715 size_t FieldIndex = 0;
3716 if (EndToken) {
3717 // Initialize all fields with given initializers.
3718 while (getTok().isNot(*EndToken) && FieldIndex < Structure.Fields.size()) {
3719 const FieldInfo &Field = Structure.Fields[FieldIndex++];
3720 if (parseOptionalToken(AsmToken::Comma)) {
3721 // Empty initializer; use the default and continue. (Also, allow line
3722 // continuation.)
3723 FieldInitializers.push_back(Field.Contents);
3724 parseOptionalToken(AsmToken::EndOfStatement);
3725 continue;
3726 }
3727 FieldInitializers.emplace_back(Field.Contents.FT);
3728 if (parseFieldInitializer(Field, FieldInitializers.back()))
3729 return true;
3730
3731 // Continue if we see a comma. (Also, allow line continuation.)
3732 SMLoc CommaLoc = getTok().getLoc();
3733 if (!parseOptionalToken(AsmToken::Comma))
3734 break;
3735 if (FieldIndex == Structure.Fields.size())
3736 return Error(CommaLoc, "'" + Structure.Name +
3737 "' initializer initializes too many fields");
3738 parseOptionalToken(AsmToken::EndOfStatement);
3739 }
3740 }
3741 // Default-initialize all remaining fields.
3742 for (const FieldInfo &Field : llvm::drop_begin(Structure.Fields, FieldIndex))
3743 FieldInitializers.push_back(Field.Contents);
3744
3745 if (EndToken) {
3746 if (*EndToken == AsmToken::Greater)
3747 return parseAngleBracketClose();
3748
3749 return parseToken(*EndToken);
3750 }
3751
3752 return false;
3753}
3754
3755bool MasmParser::parseStructInstList(
3756 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
3757 const AsmToken::TokenKind EndToken) {
3758 while (getTok().isNot(EndToken) ||
3759 (EndToken == AsmToken::Greater &&
3760 getTok().isNot(AsmToken::GreaterGreater))) {
3761 const AsmToken NextTok = peekTok();
3762 if (NextTok.is(AsmToken::Identifier) &&
3763 NextTok.getString().equals_insensitive("dup")) {
3764 const MCExpr *Value;
3765 if (parseExpression(Value) || parseToken(AsmToken::Identifier))
3766 return true;
3767 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
3768 if (!MCE)
3769 return Error(Value->getLoc(),
3770 "cannot repeat value a non-constant number of times");
3771 const int64_t Repetitions = MCE->getValue();
3772 if (Repetitions < 0)
3773 return Error(Value->getLoc(),
3774 "cannot repeat value a negative number of times");
3775
3776 std::vector<StructInitializer> DuplicatedValues;
3777 if (parseToken(AsmToken::LParen,
3778 "parentheses required for 'dup' contents") ||
3779 parseStructInstList(Structure, DuplicatedValues) || parseRParen())
3780 return true;
3781
3782 for (int i = 0; i < Repetitions; ++i)
3783 llvm::append_range(Initializers, DuplicatedValues);
3784 } else {
3785 Initializers.emplace_back();
3786 if (parseStructInitializer(Structure, Initializers.back()))
3787 return true;
3788 }
3789
3790 // Continue if we see a comma. (Also, allow line continuation.)
3791 if (!parseOptionalToken(AsmToken::Comma))
3792 break;
3793 parseOptionalToken(AsmToken::EndOfStatement);
3794 }
3795
3796 return false;
3797}
3798
3799bool MasmParser::emitFieldValue(const FieldInfo &Field,
3800 const IntFieldInfo &Contents) {
3801 // Default-initialize all values.
3802 for (const MCExpr *Value : Contents.Values) {
3803 if (emitIntValue(Value, Field.Type))
3804 return true;
3805 }
3806 return false;
3807}
3808
3809bool MasmParser::emitFieldValue(const FieldInfo &Field,
3810 const RealFieldInfo &Contents) {
3811 for (const APInt &AsInt : Contents.AsIntValues) {
3812 getStreamer().emitIntValue(AsInt.getLimitedValue(),
3813 AsInt.getBitWidth() / 8);
3814 }
3815 return false;
3816}
3817
3818bool MasmParser::emitFieldValue(const FieldInfo &Field,
3819 const StructFieldInfo &Contents) {
3820 for (const auto &Initializer : Contents.Initializers) {
3821 size_t Index = 0, Offset = 0;
3822 for (const auto &SubField : Contents.Structure.Fields) {
3823 getStreamer().emitZeros(SubField.Offset - Offset);
3824 Offset = SubField.Offset + SubField.SizeOf;
3825 emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
3826 }
3827 }
3828 return false;
3829}
3830
3831bool MasmParser::emitFieldValue(const FieldInfo &Field) {
3832 switch (Field.Contents.FT) {
3833 case FT_INTEGRAL:
3834 return emitFieldValue(Field, Field.Contents.IntInfo);
3835 case FT_REAL:
3836 return emitFieldValue(Field, Field.Contents.RealInfo);
3837 case FT_STRUCT:
3838 return emitFieldValue(Field, Field.Contents.StructInfo);
3839 }
3840 llvm_unreachable("Unhandled FieldType enum");
3841}
3842
3843bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
3844 const IntFieldInfo &Contents,
3845 const IntFieldInfo &Initializer) {
3846 for (const auto &Value : Initializer.Values) {
3847 if (emitIntValue(Value, Field.Type))
3848 return true;
3849 }
3850 // Default-initialize all remaining values.
3851 for (const auto &Value :
3852 llvm::drop_begin(Contents.Values, Initializer.Values.size())) {
3853 if (emitIntValue(Value, Field.Type))
3854 return true;
3855 }
3856 return false;
3857}
3858
3859bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
3860 const RealFieldInfo &Contents,
3861 const RealFieldInfo &Initializer) {
3862 for (const auto &AsInt : Initializer.AsIntValues) {
3863 getStreamer().emitIntValue(AsInt.getLimitedValue(),
3864 AsInt.getBitWidth() / 8);
3865 }
3866 // Default-initialize all remaining values.
3867 for (const auto &AsInt :
3868 llvm::drop_begin(Contents.AsIntValues, Initializer.AsIntValues.size())) {
3869 getStreamer().emitIntValue(AsInt.getLimitedValue(),
3870 AsInt.getBitWidth() / 8);
3871 }
3872 return false;
3873}
3874
3875bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
3876 const StructFieldInfo &Contents,
3877 const StructFieldInfo &Initializer) {
3878 for (const auto &Init : Initializer.Initializers) {
3879 if (emitStructInitializer(Contents.Structure, Init))
3880 return true;
3881 }
3882 // Default-initialize all remaining values.
3883 for (const auto &Init : llvm::drop_begin(Contents.Initializers,
3884 Initializer.Initializers.size())) {
3885 if (emitStructInitializer(Contents.Structure, Init))
3886 return true;
3887 }
3888 return false;
3889}
3890
3891bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
3892 const FieldInitializer &Initializer) {
3893 switch (Field.Contents.FT) {
3894 case FT_INTEGRAL:
3895 return emitFieldInitializer(Field, Field.Contents.IntInfo,
3896 Initializer.IntInfo);
3897 case FT_REAL:
3898 return emitFieldInitializer(Field, Field.Contents.RealInfo,
3899 Initializer.RealInfo);
3900 case FT_STRUCT:
3901 return emitFieldInitializer(Field, Field.Contents.StructInfo,
3902 Initializer.StructInfo);
3903 }
3904 llvm_unreachable("Unhandled FieldType enum");
3905}
3906
3907bool MasmParser::emitStructInitializer(const StructInfo &Structure,
3908 const StructInitializer &Initializer) {
3909 if (!Structure.Initializable)
3910 return Error(getLexer().getLoc(),
3911 "cannot initialize a value of type '" + Structure.Name +
3912 "'; 'org' was used in the type's declaration");
3913 size_t Index = 0, Offset = 0;
3914 for (const auto &Init : Initializer.FieldInitializers) {
3915 const auto &Field = Structure.Fields[Index++];
3916 getStreamer().emitZeros(Field.Offset - Offset);
3917 Offset = Field.Offset + Field.SizeOf;
3918 if (emitFieldInitializer(Field, Init))
3919 return true;
3920 }
3921 // Default-initialize all remaining fields.
3922 for (const auto &Field : llvm::drop_begin(
3923 Structure.Fields, Initializer.FieldInitializers.size())) {
3924 getStreamer().emitZeros(Field.Offset - Offset);
3925 Offset = Field.Offset + Field.SizeOf;
3926 if (emitFieldValue(Field))
3927 return true;
3928 }
3929 // Add final padding.
3930 if (Offset != Structure.Size)
3931 getStreamer().emitZeros(Structure.Size - Offset);
3932 return false;
3933}
3934
3935// Set data values from initializers.
3936bool MasmParser::emitStructValues(const StructInfo &Structure,
3937 unsigned *Count) {
3938 std::vector<StructInitializer> Initializers;
3939 if (parseStructInstList(Structure, Initializers))
3940 return true;
3941
3942 for (const auto &Initializer : Initializers) {
3943 if (emitStructInitializer(Structure, Initializer))
3944 return true;
3945 }
3946
3947 if (Count)
3948 *Count = Initializers.size();
3949 return false;
3950}
3951
3952// Declare a field in the current struct.
3953bool MasmParser::addStructField(StringRef Name, const StructInfo &Structure) {
3954 StructInfo &OwningStruct = StructInProgress.back();
3955 FieldInfo &Field =
3956 OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
3957 StructFieldInfo &StructInfo = Field.Contents.StructInfo;
3958
3959 StructInfo.Structure = Structure;
3960 Field.Type = Structure.Size;
3961
3962 if (parseStructInstList(Structure, StructInfo.Initializers))
3963 return true;
3964
3965 Field.LengthOf = StructInfo.Initializers.size();
3966 Field.SizeOf = Field.Type * Field.LengthOf;
3967
3968 const unsigned FieldEnd = Field.Offset + Field.SizeOf;
3969 if (!OwningStruct.IsUnion) {
3970 OwningStruct.NextOffset = FieldEnd;
3971 }
3972 OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd);
3973
3974 return false;
3975}
3976
3977/// parseDirectiveStructValue
3978/// ::= struct-id (<struct-initializer> | {struct-initializer})
3979/// [, (<struct-initializer> | {struct-initializer})]*
3980bool MasmParser::parseDirectiveStructValue(const StructInfo &Structure,
3981 StringRef Directive, SMLoc DirLoc) {
3982 if (StructInProgress.empty()) {
3983 if (emitStructValues(Structure))
3984 return true;
3985 } else if (addStructField("", Structure)) {
3986 return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
3987 }
3988
3989 return false;
3990}
3991
3992/// parseDirectiveNamedValue
3993/// ::= name (byte | word | ... ) [ expression (, expression)* ]
3994bool MasmParser::parseDirectiveNamedStructValue(const StructInfo &Structure,
3995 StringRef Directive,
3996 SMLoc DirLoc, StringRef Name) {
3997 if (StructInProgress.empty()) {
3998 // Initialize named data value.
3999 MCSymbol *Sym = getContext().parseSymbol(Name);
4000 getStreamer().emitLabel(Sym);
4001 unsigned Count;
4002 if (emitStructValues(Structure, &Count))
4003 return true;
4004 AsmTypeInfo Type;
4005 Type.Name = Structure.Name;
4006 Type.Size = Structure.Size * Count;
4007 Type.ElementSize = Structure.Size;
4008 Type.Length = Count;
4009 KnownType[Name.lower()] = Type;
4010 } else if (addStructField(Name, Structure)) {
4011 return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
4012 }
4013
4014 return false;
4015}
4016
4017/// parseDirectiveStruct
4018/// ::= <name> (STRUC | STRUCT | UNION) [fieldAlign] [, NONUNIQUE]
4019/// (dataDir | generalDir | offsetDir | nestedStruct)+
4020/// <name> ENDS
4021////// dataDir = data declaration
4022////// offsetDir = EVEN, ORG, ALIGN
4023bool MasmParser::parseDirectiveStruct(StringRef Directive,
4024 DirectiveKind DirKind, StringRef Name,
4025 SMLoc NameLoc) {
4026 // We ignore NONUNIQUE; we do not support OPTION M510 or OPTION OLDSTRUCTS
4027 // anyway, so all field accesses must be qualified.
4028 AsmToken NextTok = getTok();
4029 int64_t AlignmentValue = 1;
4030 if (NextTok.isNot(AsmToken::Comma) &&
4032 parseAbsoluteExpression(AlignmentValue)) {
4033 return addErrorSuffix(" in alignment value for '" + Twine(Directive) +
4034 "' directive");
4035 }
4036 if (!isPowerOf2_64(AlignmentValue)) {
4037 return Error(NextTok.getLoc(), "alignment must be a power of two; was " +
4038 std::to_string(AlignmentValue));
4039 }
4040
4041 StringRef Qualifier;
4042 SMLoc QualifierLoc;
4043 if (parseOptionalToken(AsmToken::Comma)) {
4044 QualifierLoc = getTok().getLoc();
4045 if (parseIdentifier(Qualifier))
4046 return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
4047 if (!Qualifier.equals_insensitive("nonunique"))
4048 return Error(QualifierLoc, "Unrecognized qualifier for '" +
4049 Twine(Directive) +
4050 "' directive; expected none or NONUNIQUE");
4051 }
4052
4053 if (parseEOL())
4054 return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
4055
4056 StructInProgress.emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
4057 return false;
4058}
4059
4060/// parseDirectiveNestedStruct
4061/// ::= (STRUC | STRUCT | UNION) [name]
4062/// (dataDir | generalDir | offsetDir | nestedStruct)+
4063/// ENDS
4064bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
4065 DirectiveKind DirKind) {
4066 if (StructInProgress.empty())
4067 return TokError("missing name in top-level '" + Twine(Directive) +
4068 "' directive");
4069
4070 StringRef Name;
4071 if (getTok().is(AsmToken::Identifier)) {
4072 Name = getTok().getIdentifier();
4073 parseToken(AsmToken::Identifier);
4074 }
4075 if (parseEOL())
4076 return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
4077
4078 // Reserve space to ensure Alignment doesn't get invalidated when
4079 // StructInProgress grows.
4080 StructInProgress.reserve(StructInProgress.size() + 1);
4081 StructInProgress.emplace_back(Name, DirKind == DK_UNION,
4082 StructInProgress.back().Alignment);
4083 return false;
4084}
4085
4086bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
4087 if (StructInProgress.empty())
4088 return Error(NameLoc, "ENDS directive without matching STRUC/STRUCT/UNION");
4089 if (StructInProgress.size() > 1)
4090 return Error(NameLoc, "unexpected name in nested ENDS directive");
4091 if (StructInProgress.back().Name.compare_insensitive(Name))
4092 return Error(NameLoc, "mismatched name in ENDS directive; expected '" +
4093 StructInProgress.back().Name + "'");
4094 StructInfo Structure = StructInProgress.pop_back_val();
4095 // Pad to make the structure's size divisible by the smaller of its alignment
4096 // and the size of its largest field.
4097 Structure.Size = llvm::alignTo(
4098 Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
4099 Structs[Name.lower()] = std::move(Structure);
4100
4101 if (parseEOL())
4102 return addErrorSuffix(" in ENDS directive");
4103
4104 return false;
4105}
4106
4107bool MasmParser::parseDirectiveNestedEnds() {
4108 if (StructInProgress.empty())
4109 return TokError("ENDS directive without matching STRUC/STRUCT/UNION");
4110 if (StructInProgress.size() == 1)
4111 return TokError("missing name in top-level ENDS directive");
4112
4113 if (parseEOL())
4114 return addErrorSuffix(" in nested ENDS directive");
4115
4116 StructInfo Structure = StructInProgress.pop_back_val();
4117 // Pad to make the structure's size divisible by its alignment.
4118 Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment);
4119
4120 StructInfo &ParentStruct = StructInProgress.back();
4121 if (Structure.Name.empty()) {
4122 // Anonymous substructures' fields are addressed as if they belong to the
4123 // parent structure - so we transfer them to the parent here.
4124 const size_t OldFields = ParentStruct.Fields.size();
4125 ParentStruct.Fields.insert(
4126 ParentStruct.Fields.end(),
4127 std::make_move_iterator(Structure.Fields.begin()),
4128 std::make_move_iterator(Structure.Fields.end()));
4129 for (const auto &FieldByName : Structure.FieldsByName) {
4130 ParentStruct.FieldsByName[FieldByName.getKey()] =
4131 FieldByName.getValue() + OldFields;
4132 }
4133
4134 unsigned FirstFieldOffset = 0;
4135 if (!Structure.Fields.empty() && !ParentStruct.IsUnion) {
4136 FirstFieldOffset = llvm::alignTo(
4137 ParentStruct.NextOffset,
4138 std::min(ParentStruct.Alignment, Structure.AlignmentSize));
4139 }
4140
4141 if (ParentStruct.IsUnion) {
4142 ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
4143 } else {
4144 for (auto &Field : llvm::drop_begin(ParentStruct.Fields, OldFields))
4145 Field.Offset += FirstFieldOffset;
4146
4147 const unsigned StructureEnd = FirstFieldOffset + Structure.Size;
4148 if (!ParentStruct.IsUnion) {
4149 ParentStruct.NextOffset = StructureEnd;
4150 }
4151 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4152 }
4153 } else {
4154 FieldInfo &Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
4155 Structure.AlignmentSize);
4156 StructFieldInfo &StructInfo = Field.Contents.StructInfo;
4157 Field.Type = Structure.Size;
4158 Field.LengthOf = 1;
4159 Field.SizeOf = Structure.Size;
4160
4161 const unsigned StructureEnd = Field.Offset + Field.SizeOf;
4162 if (!ParentStruct.IsUnion) {
4163 ParentStruct.NextOffset = StructureEnd;
4164 }
4165 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4166
4167 StructInfo.Structure = Structure;
4168 StructInfo.Initializers.emplace_back();
4169 auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
4170 for (const auto &SubField : Structure.Fields) {
4171 FieldInitializers.push_back(SubField.Contents);
4172 }
4173 }
4174
4175 return false;
4176}
4177
4178/// parseDirectiveOrg
4179/// ::= org expression
4180bool MasmParser::parseDirectiveOrg() {
4181 const MCExpr *Offset;
4182 SMLoc OffsetLoc = Lexer.getLoc();
4183 if (checkForValidSection() || parseExpression(Offset))
4184 return true;
4185 if (parseEOL())
4186 return addErrorSuffix(" in 'org' directive");
4187
4188 if (StructInProgress.empty()) {
4189 // Not in a struct; change the offset for the next instruction or data
4190 if (checkForValidSection())
4191 return addErrorSuffix(" in 'org' directive");
4192
4193 getStreamer().emitValueToOffset(Offset, 0, OffsetLoc);
4194 } else {
4195 // Offset the next field of this struct
4196 StructInfo &Structure = StructInProgress.back();
4197 int64_t OffsetRes;
4198 if (!Offset->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr()))
4199 return Error(OffsetLoc,
4200 "expected absolute expression in 'org' directive");
4201 if (OffsetRes < 0)
4202 return Error(
4203 OffsetLoc,
4204 "expected non-negative value in struct's 'org' directive; was " +
4205 std::to_string(OffsetRes));
4206 Structure.NextOffset = static_cast<unsigned>(OffsetRes);
4207
4208 // ORG-affected structures cannot be initialized
4209 Structure.Initializable = false;
4210 }
4211
4212 return false;
4213}
4214
4215bool MasmParser::emitAlignTo(int64_t Alignment) {
4216 if (StructInProgress.empty()) {
4217 // Not in a struct; align the next instruction or data
4218 if (checkForValidSection())
4219 return true;
4220
4221 // Check whether we should use optimal code alignment for this align
4222 // directive.
4223 const MCSection *Section = getStreamer().getCurrentSectionOnly();
4224 if (MAI.useCodeAlign(*Section)) {
4225 getStreamer().emitCodeAlignment(Align(Alignment),
4226 getTargetParser().getSTI(),
4227 /*MaxBytesToEmit=*/0);
4228 } else {
4229 // FIXME: Target specific behavior about how the "extra" bytes are filled.
4230 getStreamer().emitValueToAlignment(Align(Alignment), /*Value=*/0,
4231 /*ValueSize=*/1,
4232 /*MaxBytesToEmit=*/0);
4233 }
4234 } else {
4235 // Align the next field of this struct
4236 StructInfo &Structure = StructInProgress.back();
4237 Structure.NextOffset = llvm::alignTo(Structure.NextOffset, Alignment);
4238 }
4239
4240 return false;
4241}
4242
4243/// parseDirectiveAlign
4244/// ::= align expression
4245bool MasmParser::parseDirectiveAlign() {
4246 SMLoc AlignmentLoc = getLexer().getLoc();
4247 int64_t Alignment;
4248
4249 // Ignore empty 'align' directives.
4250 if (getTok().is(AsmToken::EndOfStatement)) {
4251 return Warning(AlignmentLoc,
4252 "align directive with no operand is ignored") &&
4253 parseEOL();
4254 }
4255 if (parseAbsoluteExpression(Alignment) || parseEOL())
4256 return addErrorSuffix(" in align directive");
4257
4258 // Always emit an alignment here even if we throw an error.
4259 bool ReturnVal = false;
4260
4261 // Reject alignments that aren't either a power of two or zero, for ML.exe
4262 // compatibility. Alignment of zero is silently rounded up to one.
4263 if (Alignment == 0)
4264 Alignment = 1;
4265 if (!isPowerOf2_64(Alignment))
4266 ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2; was " +
4267 std::to_string(Alignment));
4268
4269 if (emitAlignTo(Alignment))
4270 ReturnVal |= addErrorSuffix(" in align directive");
4271
4272 return ReturnVal;
4273}
4274
4275/// parseDirectiveEven
4276/// ::= even
4277bool MasmParser::parseDirectiveEven() {
4278 if (parseEOL() || emitAlignTo(2))
4279 return addErrorSuffix(" in even directive");
4280
4281 return false;
4282}
4283
4284/// parseDirectiveMacro
4285/// ::= name macro [parameters]
4286/// ["LOCAL" identifiers]
4287/// parameters ::= parameter [, parameter]*
4288/// parameter ::= name ":" qualifier
4289/// qualifier ::= "req" | "vararg" | "=" macro_argument
4290bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
4292 while (getLexer().isNot(AsmToken::EndOfStatement)) {
4293 if (!Parameters.empty() && Parameters.back().Vararg)
4294 return Error(Lexer.getLoc(),
4295 "Vararg parameter '" + Parameters.back().Name +
4296 "' should be last in the list of parameters");
4297
4298 MCAsmMacroParameter Parameter;
4299 if (parseIdentifier(Parameter.Name))
4300 return TokError("expected identifier in 'macro' directive");
4301
4302 // Emit an error if two (or more) named parameters share the same name.
4303 for (const MCAsmMacroParameter& CurrParam : Parameters)
4304 if (CurrParam.Name.equals_insensitive(Parameter.Name))
4305 return TokError("macro '" + Name + "' has multiple parameters"
4306 " named '" + Parameter.Name + "'");
4307
4308 if (Lexer.is(AsmToken::Colon)) {
4309 Lex(); // consume ':'
4310
4311 if (parseOptionalToken(AsmToken::Equal)) {
4312 // Default value
4313 SMLoc ParamLoc;
4314
4315 ParamLoc = Lexer.getLoc();
4316 if (parseMacroArgument(nullptr, Parameter.Value))
4317 return true;
4318 } else {
4319 SMLoc QualLoc;
4320 StringRef Qualifier;
4321
4322 QualLoc = Lexer.getLoc();
4323 if (parseIdentifier(Qualifier))
4324 return Error(QualLoc, "missing parameter qualifier for "
4325 "'" +
4326 Parameter.Name + "' in macro '" + Name +
4327 "'");
4328
4329 if (Qualifier.equals_insensitive("req"))
4330 Parameter.Required = true;
4331 else if (Qualifier.equals_insensitive("vararg"))
4332 Parameter.Vararg = true;
4333 else
4334 return Error(QualLoc,
4335 Qualifier + " is not a valid parameter qualifier for '" +
4336 Parameter.Name + "' in macro '" + Name + "'");
4337 }
4338 }
4339
4340 Parameters.push_back(std::move(Parameter));
4341
4342 if (getLexer().is(AsmToken::Comma))
4343 Lex();
4344 }
4345
4346 // Eat just the end of statement.
4347 Lexer.Lex();
4348
4349 std::vector<std::string> Locals;
4350 if (getTok().is(AsmToken::Identifier) &&
4351 getTok().getIdentifier().equals_insensitive("local")) {
4352 Lex(); // Eat the LOCAL directive.
4353
4354 StringRef ID;
4355 while (true) {
4356 if (parseIdentifier(ID))
4357 return true;
4358 Locals.push_back(ID.lower());
4359
4360 // If we see a comma, continue (and allow line continuation).
4361 if (!parseOptionalToken(AsmToken::Comma))
4362 break;
4363 parseOptionalToken(AsmToken::EndOfStatement);
4364 }
4365 }
4366
4367 // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors.
4368 AsmToken EndToken, StartToken = getTok();
4369 unsigned MacroDepth = 0;
4370 bool IsMacroFunction = false;
4371 // Lex the macro definition.
4372 while (true) {
4373 // Ignore Lexing errors in macros.
4374 while (Lexer.is(AsmToken::Error)) {
4375 Lexer.Lex();
4376 }
4377
4378 // Check whether we have reached the end of the file.
4379 if (getLexer().is(AsmToken::Eof))
4380 return Error(NameLoc, "no matching 'endm' in definition");
4381
4382 // Otherwise, check whether we have reached the 'endm'... and determine if
4383 // this is a macro function.
4384 if (getLexer().is(AsmToken::Identifier)) {
4385 if (getTok().getIdentifier().equals_insensitive("endm")) {
4386 if (MacroDepth == 0) { // Outermost macro.
4387 EndToken = getTok();
4388 Lexer.Lex();
4389 if (getLexer().isNot(AsmToken::EndOfStatement))
4390 return TokError("unexpected token in '" + EndToken.getIdentifier() +
4391 "' directive");
4392 break;
4393 } else {
4394 // Otherwise we just found the end of an inner macro.
4395 --MacroDepth;
4396 }
4397 } else if (getTok().getIdentifier().equals_insensitive("exitm")) {
4398 if (MacroDepth == 0 && peekTok().isNot(AsmToken::EndOfStatement)) {
4399 IsMacroFunction = true;
4400 }
4401 } else if (isMacroLikeDirective()) {
4402 // We allow nested macros. Those aren't instantiated until the
4403 // outermost macro is expanded so just ignore them for now.
4404 ++MacroDepth;
4405 }
4406 }
4407
4408 // Otherwise, scan til the end of the statement.
4409 eatToEndOfStatement();
4410 }
4411
4412 if (getContext().lookupMacro(Name.lower())) {
4413 return Error(NameLoc, "macro '" + Name + "' is already defined");
4414 }
4415
4416 const char *BodyStart = StartToken.getLoc().getPointer();
4417 const char *BodyEnd = EndToken.getLoc().getPointer();
4418 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4419 MCAsmMacro Macro(Name, Body, std::move(Parameters), std::move(Locals),
4420 IsMacroFunction);
4421 DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
4422 Macro.dump());
4423 getContext().defineMacro(Name.lower(), std::move(Macro));
4424 return false;
4425}
4426
4427/// parseDirectiveExitMacro
4428/// ::= "exitm" [textitem]
4429bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
4430 StringRef Directive,
4431 std::string &Value) {
4432 SMLoc EndLoc = getTok().getLoc();
4433 if (getTok().isNot(AsmToken::EndOfStatement) && parseTextItem(Value))
4434 return Error(EndLoc,
4435 "unable to parse text item in '" + Directive + "' directive");
4436 eatToEndOfStatement();
4437
4438 if (!isInsideMacroInstantiation())
4439 return TokError("unexpected '" + Directive + "' in file, "
4440 "no current macro definition");
4441
4442 // Exit all conditionals that are active in the current macro.
4443 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4444 TheCondState = TheCondStack.back();
4445 TheCondStack.pop_back();
4446 }
4447
4448 handleMacroExit();
4449 return false;
4450}
4451
4452/// parseDirectiveEndMacro
4453/// ::= endm
4454bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
4455 if (getLexer().isNot(AsmToken::EndOfStatement))
4456 return TokError("unexpected token in '" + Directive + "' directive");
4457
4458 // If we are inside a macro instantiation, terminate the current
4459 // instantiation.
4460 if (isInsideMacroInstantiation()) {
4461 handleMacroExit();
4462 return false;
4463 }
4464
4465 // Otherwise, this .endmacro is a stray entry in the file; well formed
4466 // .endmacro directives are handled during the macro definition parsing.
4467 return TokError("unexpected '" + Directive + "' in file, "
4468 "no current macro definition");
4469}
4470
4471/// parseDirectivePurgeMacro
4472/// ::= purge identifier ( , identifier )*
4473bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4474 StringRef Name;
4475 while (true) {
4476 SMLoc NameLoc;
4477 if (parseTokenLoc(NameLoc) ||
4478 check(parseIdentifier(Name), NameLoc,
4479 "expected identifier in 'purge' directive"))
4480 return true;
4481
4482 DEBUG_WITH_TYPE("asm-macros", dbgs()
4483 << "Un-defining macro: " << Name << "\n");
4484 if (!getContext().lookupMacro(Name.lower()))
4485 return Error(NameLoc, "macro '" + Name + "' is not defined");
4486 getContext().undefineMacro(Name.lower());
4487
4488 if (!parseOptionalToken(AsmToken::Comma))
4489 break;
4490 parseOptionalToken(AsmToken::EndOfStatement);
4491 }
4492
4493 return false;
4494}
4495
4496bool MasmParser::parseDirectiveExtern() {
4497 // .extern is the default - but we still need to take any provided type info.
4498 auto parseOp = [&]() -> bool {
4499 MCSymbol *Sym;
4500 SMLoc NameLoc = getTok().getLoc();
4501 if (parseSymbol(Sym))
4502 return Error(NameLoc, "expected name");
4503 if (parseToken(AsmToken::Colon))
4504 return true;
4505
4506 StringRef TypeName;
4507 SMLoc TypeLoc = getTok().getLoc();
4508 if (parseIdentifier(TypeName))
4509 return Error(TypeLoc, "expected type");
4510 if (!TypeName.equals_insensitive("proc")) {
4511 AsmTypeInfo Type;
4512 if (lookUpType(TypeName, Type))
4513 return Error(TypeLoc, "unrecognized type");
4514 KnownType[Sym->getName().lower()] = Type;
4515 }
4516
4517 static_cast<MCSymbolCOFF *>(Sym)->setExternal(true);
4518 getStreamer().emitSymbolAttribute(Sym, MCSA_Extern);
4519
4520 return false;
4521 };
4522
4523 if (parseMany(parseOp))
4524 return addErrorSuffix(" in directive 'extern'");
4525 return false;
4526}
4527
4528/// parseDirectiveSymbolAttribute
4529/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
4530bool MasmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
4531 auto parseOp = [&]() -> bool {
4532 SMLoc Loc = getTok().getLoc();
4533 MCSymbol *Sym;
4534 if (parseSymbol(Sym))
4535 return Error(Loc, "expected identifier");
4536
4537 // Assembler local symbols don't make any sense here. Complain loudly.
4538 if (Sym->isTemporary())
4539 return Error(Loc, "non-local symbol required");
4540
4541 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
4542 return Error(Loc, "unable to emit symbol attribute");
4543 return false;
4544 };
4545
4546 if (parseMany(parseOp))
4547 return addErrorSuffix(" in directive");
4548 return false;
4549}
4550
4551/// parseDirectiveComm
4552/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
4553bool MasmParser::parseDirectiveComm(bool IsLocal) {
4554 if (checkForValidSection())
4555 return true;
4556
4557 SMLoc IDLoc = getLexer().getLoc();
4558 MCSymbol *Sym;
4559 if (parseSymbol(Sym))
4560 return TokError("expected identifier in directive");
4561
4562 if (getLexer().isNot(AsmToken::Comma))
4563 return TokError("unexpected token in directive");
4564 Lex();
4565
4566 int64_t Size;
4567 SMLoc SizeLoc = getLexer().getLoc();
4568 if (parseAbsoluteExpression(Size))
4569 return true;
4570
4571 int64_t Pow2Alignment = 0;
4572 SMLoc Pow2AlignmentLoc;
4573 if (getLexer().is(AsmToken::Comma)) {
4574 Lex();
4575 Pow2AlignmentLoc = getLexer().getLoc();
4576 if (parseAbsoluteExpression(Pow2Alignment))
4577 return true;
4578
4579 LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
4580 if (IsLocal && LCOMM == LCOMM::NoAlignment)
4581 return Error(Pow2AlignmentLoc, "alignment not supported on this target");
4582
4583 // If this target takes alignments in bytes (not log) validate and convert.
4584 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
4585 (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
4586 if (!isPowerOf2_64(Pow2Alignment))
4587 return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
4588 Pow2Alignment = Log2_64(Pow2Alignment);
4589 }
4590 }
4591
4592 if (parseEOL())
4593 return true;
4594
4595 // NOTE: a size of zero for a .comm should create a undefined symbol
4596 // but a size of .lcomm creates a bss symbol of size zero.
4597 if (Size < 0)
4598 return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
4599 "be less than zero");
4600
4601 // NOTE: The alignment in the directive is a power of 2 value, the assembler
4602 // may internally end up wanting an alignment in bytes.
4603 // FIXME: Diagnose overflow.
4604 if (Pow2Alignment < 0)
4605 return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
4606 "alignment, can't be less than zero");
4607
4608 Sym->redefineIfPossible();
4609 if (!Sym->isUndefined())
4610 return Error(IDLoc, "invalid symbol redefinition");
4611
4612 // Create the Symbol as a common or local common with Size and Pow2Alignment.
4613 if (IsLocal) {
4614 getStreamer().emitLocalCommonSymbol(Sym, Size,
4615 Align(1ULL << Pow2Alignment));
4616 return false;
4617 }
4618
4619 getStreamer().emitCommonSymbol(Sym, Size, Align(1ULL << Pow2Alignment));
4620 return false;
4621}
4622
4623/// parseDirectiveComment
4624/// ::= comment delimiter [[text]]
4625/// [[text]]
4626/// [[text]] delimiter [[text]]
4627bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
4628 std::string FirstLine = parseStringTo(AsmToken::EndOfStatement);
4629 size_t DelimiterEnd = FirstLine.find_first_of("\b\t\v\f\r\x1A ");
4630 assert(DelimiterEnd != std::string::npos);
4631 StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd);
4632 if (Delimiter.empty())
4633 return Error(DirectiveLoc, "no delimiter in 'comment' directive");
4634 do {
4635 if (getTok().is(AsmToken::Eof))
4636 return Error(DirectiveLoc, "unmatched delimiter in 'comment' directive");
4637 Lex(); // eat end of statement
4638 } while (
4639 !StringRef(parseStringTo(AsmToken::EndOfStatement)).contains(Delimiter));
4640 return parseEOL();
4641}
4642
4643/// parseDirectiveInclude
4644/// ::= include <filename>
4645/// | include filename
4646bool MasmParser::parseDirectiveInclude() {
4647 // Allow the strings to have escaped octal character sequence.
4648 std::string Filename;
4649 SMLoc IncludeLoc = getTok().getLoc();
4650
4651 if (parseAngleBracketString(Filename))
4652 Filename = parseStringTo(AsmToken::EndOfStatement);
4653 if (check(Filename.empty(), "missing filename in 'include' directive") ||
4654 check(getTok().isNot(AsmToken::EndOfStatement),
4655 "unexpected token in 'include' directive") ||
4656 // Attempt to switch the lexer to the included file before consuming the
4657 // end of statement to avoid losing it when we switch.
4658 check(enterIncludeFile(Filename), IncludeLoc,
4659 "Could not find include file '" + Filename + "'"))
4660 return true;
4661
4662 return false;
4663}
4664
4665/// parseDirectiveIf
4666/// ::= .if{,eq,ge,gt,le,lt,ne} expression
4667bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
4668 TheCondStack.push_back(TheCondState);
4669 TheCondState.TheCond = AsmCond::IfCond;
4670 if (TheCondState.Ignore) {
4671 eatToEndOfStatement();
4672 } else {
4673 int64_t ExprValue;
4674 if (parseAbsoluteExpression(ExprValue) || parseEOL())
4675 return true;
4676
4677 switch (DirKind) {
4678 default:
4679 llvm_unreachable("unsupported directive");
4680 case DK_IF:
4681 break;
4682 case DK_IFE:
4683 ExprValue = ExprValue == 0;
4684 break;
4685 }
4686
4687 TheCondState.CondMet = ExprValue;
4688 TheCondState.Ignore = !TheCondState.CondMet;
4689 }
4690
4691 return false;
4692}
4693
4694/// parseDirectiveIfb
4695/// ::= .ifb textitem
4696bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
4697 TheCondStack.push_back(TheCondState);
4698 TheCondState.TheCond = AsmCond::IfCond;
4699
4700 if (TheCondState.Ignore) {
4701 eatToEndOfStatement();
4702 } else {
4703 std::string Str;
4704 if (parseTextItem(Str))
4705 return TokError("expected text item parameter for 'ifb' directive");
4706
4707 if (parseEOL())
4708 return true;
4709
4710 TheCondState.CondMet = ExpectBlank == Str.empty();
4711 TheCondState.Ignore = !TheCondState.CondMet;
4712 }
4713
4714 return false;
4715}
4716
4717/// parseDirectiveIfidn
4718/// ::= ifidn textitem, textitem
4719bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
4720 bool CaseInsensitive) {
4721 std::string String1, String2;
4722
4723 if (parseTextItem(String1)) {
4724 if (ExpectEqual)
4725 return TokError("expected text item parameter for 'ifidn' directive");
4726 return TokError("expected text item parameter for 'ifdif' directive");
4727 }
4728
4729 if (Lexer.isNot(AsmToken::Comma)) {
4730 if (ExpectEqual)
4731 return TokError(
4732 "expected comma after first string for 'ifidn' directive");
4733 return TokError("expected comma after first string for 'ifdif' directive");
4734 }
4735 Lex();
4736
4737 if (parseTextItem(String2)) {
4738 if (ExpectEqual)
4739 return TokError("expected text item parameter for 'ifidn' directive");
4740 return TokError("expected text item parameter for 'ifdif' directive");
4741 }
4742
4743 TheCondStack.push_back(TheCondState);
4744 TheCondState.TheCond = AsmCond::IfCond;
4745 if (CaseInsensitive)
4746 TheCondState.CondMet =
4747 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4748 else
4749 TheCondState.CondMet = ExpectEqual == (String1 == String2);
4750 TheCondState.Ignore = !TheCondState.CondMet;
4751
4752 return false;
4753}
4754
4755/// parseDirectiveIfdef
4756/// ::= ifdef symbol
4757/// | ifdef variable
4758bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
4759 TheCondStack.push_back(TheCondState);
4760 TheCondState.TheCond = AsmCond::IfCond;
4761
4762 if (TheCondState.Ignore) {
4763 eatToEndOfStatement();
4764 } else {
4765 bool is_defined = false;
4766 MCRegister Reg;
4767 SMLoc StartLoc, EndLoc;
4768 is_defined =
4769 getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
4770 if (!is_defined) {
4771 StringRef Name;
4772 if (check(parseIdentifier(Name), "expected identifier after 'ifdef'") ||
4773 parseEOL())
4774 return true;
4775
4776 if (BuiltinSymbolMap.contains(Name.lower())) {
4777 is_defined = true;
4778 } else if (Variables.contains(Name.lower())) {
4779 is_defined = true;
4780 } else {
4781 MCSymbol *Sym = getContext().lookupSymbol(Name.lower());
4782 is_defined = (Sym && !Sym->isUndefined());
4783 }
4784 }
4785
4786 TheCondState.CondMet = (is_defined == expect_defined);
4787 TheCondState.Ignore = !TheCondState.CondMet;
4788 }
4789
4790 return false;
4791}
4792
4793/// parseDirectiveElseIf
4794/// ::= elseif expression
4795bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
4796 DirectiveKind DirKind) {
4797 if (TheCondState.TheCond != AsmCond::IfCond &&
4798 TheCondState.TheCond != AsmCond::ElseIfCond)
4799 return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
4800 " .if or an .elseif");
4801 TheCondState.TheCond = AsmCond::ElseIfCond;
4802
4803 bool LastIgnoreState = false;
4804 if (!TheCondStack.empty())
4805 LastIgnoreState = TheCondStack.back().Ignore;
4806 if (LastIgnoreState || TheCondState.CondMet) {
4807 TheCondState.Ignore = true;
4808 eatToEndOfStatement();
4809 } else {
4810 int64_t ExprValue;
4811 if (parseAbsoluteExpression(ExprValue))
4812 return true;
4813
4814 if (parseEOL())
4815 return true;
4816
4817 switch (DirKind) {
4818 default:
4819 llvm_unreachable("unsupported directive");
4820 case DK_ELSEIF:
4821 break;
4822 case DK_ELSEIFE:
4823 ExprValue = ExprValue == 0;
4824 break;
4825 }
4826
4827 TheCondState.CondMet = ExprValue;
4828 TheCondState.Ignore = !TheCondState.CondMet;
4829 }
4830
4831 return false;
4832}
4833
4834/// parseDirectiveElseIfb
4835/// ::= elseifb textitem
4836bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
4837 if (TheCondState.TheCond != AsmCond::IfCond &&
4838 TheCondState.TheCond != AsmCond::ElseIfCond)
4839 return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
4840 " if or an elseif");
4841 TheCondState.TheCond = AsmCond::ElseIfCond;
4842
4843 bool LastIgnoreState = false;
4844 if (!TheCondStack.empty())
4845 LastIgnoreState = TheCondStack.back().Ignore;
4846 if (LastIgnoreState || TheCondState.CondMet) {
4847 TheCondState.Ignore = true;
4848 eatToEndOfStatement();
4849 } else {
4850 std::string Str;
4851 if (parseTextItem(Str)) {
4852 if (ExpectBlank)
4853 return TokError("expected text item parameter for 'elseifb' directive");
4854 return TokError("expected text item parameter for 'elseifnb' directive");
4855 }
4856
4857 if (parseEOL())
4858 return true;
4859
4860 TheCondState.CondMet = ExpectBlank == Str.empty();
4861 TheCondState.Ignore = !TheCondState.CondMet;
4862 }
4863
4864 return false;
4865}
4866
4867/// parseDirectiveElseIfdef
4868/// ::= elseifdef symbol
4869/// | elseifdef variable
4870bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
4871 bool expect_defined) {
4872 if (TheCondState.TheCond != AsmCond::IfCond &&
4873 TheCondState.TheCond != AsmCond::ElseIfCond)
4874 return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
4875 " if or an elseif");
4876 TheCondState.TheCond = AsmCond::ElseIfCond;
4877
4878 bool LastIgnoreState = false;
4879 if (!TheCondStack.empty())
4880 LastIgnoreState = TheCondStack.back().Ignore;
4881 if (LastIgnoreState || TheCondState.CondMet) {
4882 TheCondState.Ignore = true;
4883 eatToEndOfStatement();
4884 } else {
4885 bool is_defined = false;
4886 MCRegister Reg;
4887 SMLoc StartLoc, EndLoc;
4888 is_defined =
4889 getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
4890 if (!is_defined) {
4891 StringRef Name;
4892 if (check(parseIdentifier(Name),
4893 "expected identifier after 'elseifdef'") ||
4894 parseEOL())
4895 return true;
4896
4897 if (BuiltinSymbolMap.contains(Name.lower())) {
4898 is_defined = true;
4899 } else if (Variables.contains(Name.lower())) {
4900 is_defined = true;
4901 } else {
4902 MCSymbol *Sym = getContext().lookupSymbol(Name);
4903 is_defined = (Sym && !Sym->isUndefined());
4904 }
4905 }
4906
4907 TheCondState.CondMet = (is_defined == expect_defined);
4908 TheCondState.Ignore = !TheCondState.CondMet;
4909 }
4910
4911 return false;
4912}
4913
4914/// parseDirectiveElseIfidn
4915/// ::= elseifidn textitem, textitem
4916bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
4917 bool CaseInsensitive) {
4918 if (TheCondState.TheCond != AsmCond::IfCond &&
4919 TheCondState.TheCond != AsmCond::ElseIfCond)
4920 return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
4921 " if or an elseif");
4922 TheCondState.TheCond = AsmCond::ElseIfCond;
4923
4924 bool LastIgnoreState = false;
4925 if (!TheCondStack.empty())
4926 LastIgnoreState = TheCondStack.back().Ignore;
4927 if (LastIgnoreState || TheCondState.CondMet) {
4928 TheCondState.Ignore = true;
4929 eatToEndOfStatement();
4930 } else {
4931 std::string String1, String2;
4932
4933 if (parseTextItem(String1)) {
4934 if (ExpectEqual)
4935 return TokError(
4936 "expected text item parameter for 'elseifidn' directive");
4937 return TokError("expected text item parameter for 'elseifdif' directive");
4938 }
4939
4940 if (Lexer.isNot(AsmToken::Comma)) {
4941 if (ExpectEqual)
4942 return TokError(
4943 "expected comma after first string for 'elseifidn' directive");
4944 return TokError(
4945 "expected comma after first string for 'elseifdif' directive");
4946 }
4947 Lex();
4948
4949 if (parseTextItem(String2)) {
4950 if (ExpectEqual)
4951 return TokError(
4952 "expected text item parameter for 'elseifidn' directive");
4953 return TokError("expected text item parameter for 'elseifdif' directive");
4954 }
4955
4956 if (CaseInsensitive)
4957 TheCondState.CondMet =
4958 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4959 else
4960 TheCondState.CondMet = ExpectEqual == (String1 == String2);
4961 TheCondState.Ignore = !TheCondState.CondMet;
4962 }
4963
4964 return false;
4965}
4966
4967/// parseDirectiveElse
4968/// ::= else
4969bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
4970 if (parseEOL())
4971 return true;
4972
4973 if (TheCondState.TheCond != AsmCond::IfCond &&
4974 TheCondState.TheCond != AsmCond::ElseIfCond)
4975 return Error(DirectiveLoc, "Encountered an else that doesn't follow an if"
4976 " or an elseif");
4977 TheCondState.TheCond = AsmCond::ElseCond;
4978 bool LastIgnoreState = false;
4979 if (!TheCondStack.empty())
4980 LastIgnoreState = TheCondStack.back().Ignore;
4981 if (LastIgnoreState || TheCondState.CondMet)
4982 TheCondState.Ignore = true;
4983 else
4984 TheCondState.Ignore = false;
4985
4986 return false;
4987}
4988
4989/// parseDirectiveEnd
4990/// ::= end
4991bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
4992 if (parseEOL())
4993 return true;
4994
4995 while (Lexer.isNot(AsmToken::Eof))
4996 Lexer.Lex();
4997
4998 return false;
4999}
5000
5001/// parseDirectiveError
5002/// ::= .err [message]
5003bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
5004 if (!TheCondStack.empty()) {
5005 if (TheCondStack.back().Ignore) {
5006 eatToEndOfStatement();
5007 return false;
5008 }
5009 }
5010
5011 std::string Message = ".err directive invoked in source file";
5012 if (Lexer.isNot(AsmToken::EndOfStatement))
5013 Message = parseStringTo(AsmToken::EndOfStatement);
5014 Lex();
5015
5016 return Error(DirectiveLoc, Message);
5017}
5018
5019/// parseDirectiveErrorIfb
5020/// ::= .errb textitem[, message]
5021bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
5022 if (!TheCondStack.empty()) {
5023 if (TheCondStack.back().Ignore) {
5024 eatToEndOfStatement();
5025 return false;
5026 }
5027 }
5028
5029 std::string Text;
5030 if (parseTextItem(Text))
5031 return Error(getTok().getLoc(), "missing text item in '.errb' directive");
5032
5033 std::string Message = ".errb directive invoked in source file";
5034 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5035 if (parseToken(AsmToken::Comma))
5036 return addErrorSuffix(" in '.errb' directive");
5037 Message = parseStringTo(AsmToken::EndOfStatement);
5038 }
5039 Lex();
5040
5041 if (Text.empty() == ExpectBlank)
5042 return Error(DirectiveLoc, Message);
5043 return false;
5044}
5045
5046/// parseDirectiveErrorIfdef
5047/// ::= .errdef name[, message]
5048bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
5049 bool ExpectDefined) {
5050 if (!TheCondStack.empty()) {
5051 if (TheCondStack.back().Ignore) {
5052 eatToEndOfStatement();
5053 return false;
5054 }
5055 }
5056
5057 bool IsDefined = false;
5058 MCRegister Reg;
5059 SMLoc StartLoc, EndLoc;
5060 IsDefined =
5061 getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
5062 if (!IsDefined) {
5063 StringRef Name;
5064 if (check(parseIdentifier(Name), "expected identifier after '.errdef'"))
5065 return true;
5066
5067 if (BuiltinSymbolMap.contains(Name.lower())) {
5068 IsDefined = true;
5069 } else if (Variables.contains(Name.lower())) {
5070 IsDefined = true;
5071 } else {
5072 MCSymbol *Sym = getContext().lookupSymbol(Name);
5073 IsDefined = (Sym && !Sym->isUndefined());
5074 }
5075 }
5076
5077 std::string Message = ".errdef directive invoked in source file";
5078 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5079 if (parseToken(AsmToken::Comma))
5080 return addErrorSuffix(" in '.errdef' directive");
5081 Message = parseStringTo(AsmToken::EndOfStatement);
5082 }
5083 Lex();
5084
5085 if (IsDefined == ExpectDefined)
5086 return Error(DirectiveLoc, Message);
5087 return false;
5088}
5089
5090/// parseDirectiveErrorIfidn
5091/// ::= .erridn textitem, textitem[, message]
5092bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
5093 bool CaseInsensitive) {
5094 if (!TheCondStack.empty()) {
5095 if (TheCondStack.back().Ignore) {
5096 eatToEndOfStatement();
5097 return false;
5098 }
5099 }
5100
5101 std::string String1, String2;
5102
5103 if (parseTextItem(String1)) {
5104 if (ExpectEqual)
5105 return TokError("expected string parameter for '.erridn' directive");
5106 return TokError("expected string parameter for '.errdif' directive");
5107 }
5108
5109 if (Lexer.isNot(AsmToken::Comma)) {
5110 if (ExpectEqual)
5111 return TokError(
5112 "expected comma after first string for '.erridn' directive");
5113 return TokError(
5114 "expected comma after first string for '.errdif' directive");
5115 }
5116 Lex();
5117
5118 if (parseTextItem(String2)) {
5119 if (ExpectEqual)
5120 return TokError("expected string parameter for '.erridn' directive");
5121 return TokError("expected string parameter for '.errdif' directive");
5122 }
5123
5124 std::string Message;
5125 if (ExpectEqual)
5126 Message = ".erridn directive invoked in source file";
5127 else
5128 Message = ".errdif directive invoked in source file";
5129 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5130 if (parseToken(AsmToken::Comma))
5131 return addErrorSuffix(" in '.erridn' directive");
5132 Message = parseStringTo(AsmToken::EndOfStatement);
5133 }
5134 Lex();
5135
5136 if (CaseInsensitive)
5137 TheCondState.CondMet =
5138 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
5139 else
5140 TheCondState.CondMet = ExpectEqual == (String1 == String2);
5141 TheCondState.Ignore = !TheCondState.CondMet;
5142
5143 if ((CaseInsensitive &&
5144 ExpectEqual == StringRef(String1).equals_insensitive(String2)) ||
5145 (ExpectEqual == (String1 == String2)))
5146 return Error(DirectiveLoc, Message);
5147 return false;
5148}
5149
5150/// parseDirectiveErrorIfe
5151/// ::= .erre expression[, message]
5152bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero) {
5153 if (!TheCondStack.empty()) {
5154 if (TheCondStack.back().Ignore) {
5155 eatToEndOfStatement();
5156 return false;
5157 }
5158 }
5159
5160 int64_t ExprValue;
5161 if (parseAbsoluteExpression(ExprValue))
5162 return addErrorSuffix(" in '.erre' directive");
5163
5164 std::string Message = ".erre directive invoked in source file";
5165 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5166 if (parseToken(AsmToken::Comma))
5167 return addErrorSuffix(" in '.erre' directive");
5168 Message = parseStringTo(AsmToken::EndOfStatement);
5169 }
5170 Lex();
5171
5172 if ((ExprValue == 0) == ExpectZero)
5173 return Error(DirectiveLoc, Message);
5174 return false;
5175}
5176
5177/// parseDirectiveEndIf
5178/// ::= .endif
5179bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5180 if (parseEOL())
5181 return true;
5182
5183 if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
5184 return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
5185 "an .if or .else");
5186 if (!TheCondStack.empty()) {
5187 TheCondState = TheCondStack.back();
5188 TheCondStack.pop_back();
5189 }
5190
5191 return false;
5192}
5193
5194void MasmParser::initializeDirectiveKindMap() {
5195 DirectiveKindMap["="] = DK_ASSIGN;
5196 DirectiveKindMap["equ"] = DK_EQU;
5197 DirectiveKindMap["textequ"] = DK_TEXTEQU;
5198 // DirectiveKindMap[".ascii"] = DK_ASCII;
5199 // DirectiveKindMap[".asciz"] = DK_ASCIZ;
5200 // DirectiveKindMap[".string"] = DK_STRING;
5201 DirectiveKindMap["byte"] = DK_BYTE;
5202 DirectiveKindMap["sbyte"] = DK_SBYTE;
5203 DirectiveKindMap["word"] = DK_WORD;
5204 DirectiveKindMap["sword"] = DK_SWORD;
5205 DirectiveKindMap["dword"] = DK_DWORD;
5206 DirectiveKindMap["sdword"] = DK_SDWORD;
5207 DirectiveKindMap["fword"] = DK_FWORD;
5208 DirectiveKindMap["qword"] = DK_QWORD;
5209 DirectiveKindMap["sqword"] = DK_SQWORD;
5210 DirectiveKindMap["real4"] = DK_REAL4;
5211 DirectiveKindMap["real8"] = DK_REAL8;
5212 DirectiveKindMap["real10"] = DK_REAL10;
5213 DirectiveKindMap["align"] = DK_ALIGN;
5214 DirectiveKindMap["even"] = DK_EVEN;
5215 DirectiveKindMap["org"] = DK_ORG;
5216 DirectiveKindMap["extern"] = DK_EXTERN;
5217 DirectiveKindMap["extrn"] = DK_EXTERN;
5218 DirectiveKindMap["public"] = DK_PUBLIC;
5219 // DirectiveKindMap[".comm"] = DK_COMM;
5220 DirectiveKindMap["comment"] = DK_COMMENT;
5221 DirectiveKindMap["include"] = DK_INCLUDE;
5222 DirectiveKindMap["repeat"] = DK_REPEAT;
5223 DirectiveKindMap["rept"] = DK_REPEAT;
5224 DirectiveKindMap["while"] = DK_WHILE;
5225 DirectiveKindMap["for"] = DK_FOR;
5226 DirectiveKindMap["irp"] = DK_FOR;
5227 DirectiveKindMap["forc"] = DK_FORC;
5228 DirectiveKindMap["irpc"] = DK_FORC;
5229 DirectiveKindMap["if"] = DK_IF;
5230 DirectiveKindMap["ife"] = DK_IFE;
5231 DirectiveKindMap["ifb"] = DK_IFB;
5232 DirectiveKindMap["ifnb"] = DK_IFNB;
5233 DirectiveKindMap["ifdef"] = DK_IFDEF;
5234 DirectiveKindMap["ifndef"] = DK_IFNDEF;
5235 DirectiveKindMap["ifdif"] = DK_IFDIF;
5236 DirectiveKindMap["ifdifi"] = DK_IFDIFI;
5237 DirectiveKindMap["ifidn"] = DK_IFIDN;
5238 DirectiveKindMap["ifidni"] = DK_IFIDNI;
5239 DirectiveKindMap["elseif"] = DK_ELSEIF;
5240 DirectiveKindMap["elseifdef"] = DK_ELSEIFDEF;
5241 DirectiveKindMap["elseifndef"] = DK_ELSEIFNDEF;
5242 DirectiveKindMap["elseifdif"] = DK_ELSEIFDIF;
5243 DirectiveKindMap["elseifidn"] = DK_ELSEIFIDN;
5244 DirectiveKindMap["else"] = DK_ELSE;
5245 DirectiveKindMap["end"] = DK_END;
5246 DirectiveKindMap["endif"] = DK_ENDIF;
5247 // DirectiveKindMap[".file"] = DK_FILE;
5248 // DirectiveKindMap[".line"] = DK_LINE;
5249 // DirectiveKindMap[".loc"] = DK_LOC;
5250 // DirectiveKindMap[".stabs"] = DK_STABS;
5251 // DirectiveKindMap[".cv_file"] = DK_CV_FILE;
5252 // DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
5253 // DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
5254 // DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
5255 // DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
5256 // DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
5257 // DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
5258 // DirectiveKindMap[".cv_string"] = DK_CV_STRING;
5259 // DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
5260 // DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
5261 // DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
5262 // DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
5263 // DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
5264 // DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
5265 // DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
5266 // DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
5267 // DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
5268 // DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
5269 // DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
5270 // DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
5271 // DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
5272 // DirectiveKindMap[".cfi_llvm_register_pair"] = DK_CFI_LLVM_REGISTER_PAIR;
5273 // DirectiveKindMap[".cfi_llvm_vector_registers"] =
5274 // DK_CFI_LLVM_VECTOR_REGISTERS;
5275 // DirectiveKindMap[".cfi_llvm_vector_offset"] = DK_CFI_LLVM_VECTOR_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[".push2reg"] = DK_PUSH2REGS;
5308 DirectiveKindMap[".pop2reg"] = DK_PUSH2REGS;
5309 DirectiveKindMap[".popreg"] = DK_PUSHREG;
5310 DirectiveKindMap[".savereg"] = DK_SAVEREG;
5311 DirectiveKindMap[".restorereg"] = DK_SAVEREG;
5312 DirectiveKindMap[".savexmm128"] = DK_SAVEXMM128;
5313 DirectiveKindMap[".restorexmm128"] = DK_SAVEXMM128;
5314 DirectiveKindMap[".setframe"] = DK_SETFRAME;
5315 DirectiveKindMap[".unsetframe"] = DK_SETFRAME;
5316 DirectiveKindMap[".radix"] = DK_RADIX;
5317 DirectiveKindMap["db"] = DK_DB;
5318 DirectiveKindMap["dd"] = DK_DD;
5319 DirectiveKindMap["df"] = DK_DF;
5320 DirectiveKindMap["dq"] = DK_DQ;
5321 DirectiveKindMap["dw"] = DK_DW;
5322 DirectiveKindMap["echo"] = DK_ECHO;
5323 DirectiveKindMap["struc"] = DK_STRUCT;
5324 DirectiveKindMap["struct"] = DK_STRUCT;
5325 DirectiveKindMap["union"] = DK_UNION;
5326 DirectiveKindMap["ends"] = DK_ENDS;
5327}
5328
5329bool MasmParser::isMacroLikeDirective() {
5330 if (getLexer().is(AsmToken::Identifier)) {
5331 bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier())
5332 .CasesLower({"repeat", "rept"}, true)
5333 .CaseLower("while", true)
5334 .CasesLower({"for", "irp"}, true)
5335 .CasesLower({"forc", "irpc"}, true)
5336 .Default(false);
5337 if (IsMacroLike)
5338 return true;
5339 }
5340 if (peekTok().is(AsmToken::Identifier) &&
5341 peekTok().getIdentifier().equals_insensitive("macro"))
5342 return true;
5343
5344 return false;
5345}
5346
5347MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5348 AsmToken EndToken, StartToken = getTok();
5349
5350 unsigned NestLevel = 0;
5351 while (true) {
5352 // Check whether we have reached the end of the file.
5353 if (getLexer().is(AsmToken::Eof)) {
5354 printError(DirectiveLoc, "no matching 'endm' in definition");
5355 return nullptr;
5356 }
5357
5358 if (isMacroLikeDirective())
5359 ++NestLevel;
5360
5361 // Otherwise, check whether we have reached the endm.
5362 if (Lexer.is(AsmToken::Identifier) &&
5363 getTok().getIdentifier().equals_insensitive("endm")) {
5364 if (NestLevel == 0) {
5365 EndToken = getTok();
5366 Lex();
5367 if (Lexer.isNot(AsmToken::EndOfStatement)) {
5368 printError(getTok().getLoc(), "unexpected token in 'endm' directive");
5369 return nullptr;
5370 }
5371 break;
5372 }
5373 --NestLevel;
5374 }
5375
5376 // Otherwise, scan till the end of the statement.
5377 eatToEndOfStatement();
5378 }
5379
5380 const char *BodyStart = StartToken.getLoc().getPointer();
5381 const char *BodyEnd = EndToken.getLoc().getPointer();
5382 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5383
5384 // We Are Anonymous.
5385 MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
5386 return &MacroLikeBodies.back();
5387}
5388
5389bool MasmParser::expandStatement(SMLoc Loc) {
5390 std::string Body = parseStringTo(AsmToken::EndOfStatement);
5391 SMLoc EndLoc = getTok().getLoc();
5392
5394 MCAsmMacroArguments Arguments;
5395
5396 StringMap<std::string> BuiltinValues;
5397 for (const auto &S : BuiltinSymbolMap) {
5398 const BuiltinSymbol &Sym = S.getValue();
5399 if (std::optional<std::string> Text = evaluateBuiltinTextMacro(Sym, Loc)) {
5400 BuiltinValues[S.getKey().lower()] = std::move(*Text);
5401 }
5402 }
5403 for (const auto &B : BuiltinValues) {
5404 MCAsmMacroParameter P;
5405 MCAsmMacroArgument A;
5406 P.Name = B.getKey();
5407 P.Required = true;
5408 A.push_back(AsmToken(AsmToken::String, B.getValue()));
5409
5410 Parameters.push_back(std::move(P));
5411 Arguments.push_back(std::move(A));
5412 }
5413
5414 for (const auto &V : Variables) {
5415 const Variable &Var = V.getValue();
5416 if (Var.IsText) {
5417 MCAsmMacroParameter P;
5418 MCAsmMacroArgument A;
5419 P.Name = Var.Name;
5420 P.Required = true;
5421 A.push_back(AsmToken(AsmToken::String, Var.TextValue));
5422
5423 Parameters.push_back(std::move(P));
5424 Arguments.push_back(std::move(A));
5425 }
5426 }
5427 MacroLikeBodies.emplace_back(StringRef(), Body, Parameters);
5428 MCAsmMacro M = MacroLikeBodies.back();
5429
5430 // Expand the statement in a new buffer.
5431 SmallString<80> Buf;
5432 raw_svector_ostream OS(Buf);
5433 if (expandMacro(OS, M.Body, M.Parameters, Arguments, M.Locals, EndLoc))
5434 return true;
5435 std::unique_ptr<MemoryBuffer> Expansion =
5436 MemoryBuffer::getMemBufferCopy(OS.str(), "<expansion>");
5437
5438 // Jump to the expanded statement and prime the lexer.
5439 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Expansion), EndLoc);
5440 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
5441 EndStatementAtEOFStack.push_back(false);
5442 Lex();
5443 return false;
5444}
5445
5446void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5447 raw_svector_ostream &OS) {
5448 instantiateMacroLikeBody(M, DirectiveLoc, /*ExitLoc=*/getTok().getLoc(), OS);
5449}
5450void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5451 SMLoc ExitLoc,
5452 raw_svector_ostream &OS) {
5453 OS << "endm\n";
5454
5455 std::unique_ptr<MemoryBuffer> Instantiation =
5456 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
5457
5458 // Create the macro instantiation object and add to the current macro
5459 // instantiation stack.
5460 MacroInstantiation *MI = new MacroInstantiation{DirectiveLoc, CurBuffer,
5461 ExitLoc, TheCondStack.size()};
5462 ActiveMacros.push_back(MI);
5463
5464 // Jump to the macro instantiation and prime the lexer.
5465 CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
5466 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
5467 EndStatementAtEOFStack.push_back(true);
5468 Lex();
5469}
5470
5471/// parseDirectiveRepeat
5472/// ::= ("repeat" | "rept") count
5473/// body
5474/// endm
5475bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) {
5476 const MCExpr *CountExpr;
5477 SMLoc CountLoc = getTok().getLoc();
5478 if (parseExpression(CountExpr))
5479 return true;
5480
5481 int64_t Count;
5482 if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
5483 return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
5484 }
5485
5486 if (check(Count < 0, CountLoc, "Count is negative") || parseEOL())
5487 return true;
5488
5489 // Lex the repeat definition.
5490 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5491 if (!M)
5492 return true;
5493
5494 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5495 // to hold the macro body with substitutions.
5496 SmallString<256> Buf;
5497 raw_svector_ostream OS(Buf);
5498 while (Count--) {
5499 if (expandMacro(OS, M->Body, {}, {}, M->Locals, getTok().getLoc()))
5500 return true;
5501 }
5502 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5503
5504 return false;
5505}
5506
5507/// parseDirectiveWhile
5508/// ::= "while" expression
5509/// body
5510/// endm
5511bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) {
5512 const MCExpr *CondExpr;
5513 SMLoc CondLoc = getTok().getLoc();
5514 if (parseExpression(CondExpr))
5515 return true;
5516
5517 // Lex the repeat definition.
5518 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5519 if (!M)
5520 return true;
5521
5522 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5523 // to hold the macro body with substitutions.
5524 SmallString<256> Buf;
5525 raw_svector_ostream OS(Buf);
5526 int64_t Condition;
5527 if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr()))
5528 return Error(CondLoc, "expected absolute expression in 'while' directive");
5529 if (Condition) {
5530 // Instantiate the macro, then resume at this directive to recheck the
5531 // condition.
5532 if (expandMacro(OS, M->Body, {}, {}, M->Locals, getTok().getLoc()))
5533 return true;
5534 instantiateMacroLikeBody(M, DirectiveLoc, /*ExitLoc=*/DirectiveLoc, OS);
5535 }
5536
5537 return false;
5538}
5539
5540/// parseDirectiveFor
5541/// ::= ("for" | "irp") symbol [":" qualifier], <values>
5542/// body
5543/// endm
5544bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
5545 MCAsmMacroParameter Parameter;
5546 MCAsmMacroArguments A;
5547 if (check(parseIdentifier(Parameter.Name),
5548 "expected identifier in '" + Dir + "' directive"))
5549 return true;
5550
5551 // Parse optional qualifier (default value, or "req")
5552 if (parseOptionalToken(AsmToken::Colon)) {
5553 if (parseOptionalToken(AsmToken::Equal)) {
5554 // Default value
5555 SMLoc ParamLoc;
5556
5557 ParamLoc = Lexer.getLoc();
5558 if (parseMacroArgument(nullptr, Parameter.Value))
5559 return true;
5560 } else {
5561 SMLoc QualLoc;
5562 StringRef Qualifier;
5563
5564 QualLoc = Lexer.getLoc();
5565 if (parseIdentifier(Qualifier))
5566 return Error(QualLoc, "missing parameter qualifier for "
5567 "'" +
5568 Parameter.Name + "' in '" + Dir +
5569 "' directive");
5570
5571 if (Qualifier.equals_insensitive("req"))
5572 Parameter.Required = true;
5573 else
5574 return Error(QualLoc,
5575 Qualifier + " is not a valid parameter qualifier for '" +
5576 Parameter.Name + "' in '" + Dir + "' directive");
5577 }
5578 }
5579
5580 if (parseToken(AsmToken::Comma,
5581 "expected comma in '" + Dir + "' directive") ||
5582 parseToken(AsmToken::Less,
5583 "values in '" + Dir +
5584 "' directive must be enclosed in angle brackets"))
5585 return true;
5586
5587 while (true) {
5588 A.emplace_back();
5589 if (parseMacroArgument(&Parameter, A.back(), /*EndTok=*/AsmToken::Greater))
5590 return addErrorSuffix(" in arguments for '" + Dir + "' directive");
5591
5592 // If we see a comma, continue, and allow line continuation.
5593 if (!parseOptionalToken(AsmToken::Comma))
5594 break;
5595 parseOptionalToken(AsmToken::EndOfStatement);
5596 }
5597
5598 if (parseToken(AsmToken::Greater,
5599 "values in '" + Dir +
5600 "' directive must be enclosed in angle brackets") ||
5601 parseEOL())
5602 return true;
5603
5604 // Lex the for definition.
5605 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5606 if (!M)
5607 return true;
5608
5609 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5610 // to hold the macro body with substitutions.
5611 SmallString<256> Buf;
5612 raw_svector_ostream OS(Buf);
5613
5614 for (const MCAsmMacroArgument &Arg : A) {
5615 if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc()))
5616 return true;
5617 }
5618
5619 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5620
5621 return false;
5622}
5623
5624/// parseDirectiveForc
5625/// ::= ("forc" | "irpc") symbol, <string>
5626/// body
5627/// endm
5628bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
5629 MCAsmMacroParameter Parameter;
5630
5631 std::string Argument;
5632 if (check(parseIdentifier(Parameter.Name),
5633 "expected identifier in '" + Directive + "' directive") ||
5634 parseToken(AsmToken::Comma,
5635 "expected comma in '" + Directive + "' directive"))
5636 return true;
5637 if (parseAngleBracketString(Argument)) {
5638 // Match ml64.exe; treat all characters to end of statement as a string,
5639 // ignoring comment markers, then discard anything following a space (using
5640 // the C locale).
5641 Argument = parseStringTo(AsmToken::EndOfStatement);
5642 if (getTok().is(AsmToken::EndOfStatement))
5643 Argument += getTok().getString();
5644 size_t End = 0;
5645 for (; End < Argument.size(); ++End) {
5646 if (isSpace(Argument[End]))
5647 break;
5648 }
5649 Argument.resize(End);
5650 }
5651 if (parseEOL())
5652 return true;
5653
5654 // Lex the irpc definition.
5655 MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
5656 if (!M)
5657 return true;
5658
5659 // Macro instantiation is lexical, unfortunately. We construct a new buffer
5660 // to hold the macro body with substitutions.
5661 SmallString<256> Buf;
5662 raw_svector_ostream OS(Buf);
5663
5664 StringRef Values(Argument);
5665 for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
5666 MCAsmMacroArgument Arg;
5667 Arg.emplace_back(AsmToken::Identifier, Values.substr(I, 1));
5668
5669 if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc()))
5670 return true;
5671 }
5672
5673 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5674
5675 return false;
5676}
5677
5678bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
5679 size_t Len) {
5680 const MCExpr *Value;
5681 SMLoc ExprLoc = getLexer().getLoc();
5682 if (parseExpression(Value))
5683 return true;
5684 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
5685 if (!MCE)
5686 return Error(ExprLoc, "unexpected expression in _emit");
5687 uint64_t IntValue = MCE->getValue();
5688 if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
5689 return Error(ExprLoc, "literal value out of range for directive");
5690
5691 Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
5692 return false;
5693}
5694
5695bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
5696 const MCExpr *Value;
5697 SMLoc ExprLoc = getLexer().getLoc();
5698 if (parseExpression(Value))
5699 return true;
5700 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
5701 if (!MCE)
5702 return Error(ExprLoc, "unexpected expression in align");
5703 uint64_t IntValue = MCE->getValue();
5704 if (!isPowerOf2_64(IntValue))
5705 return Error(ExprLoc, "literal value not a power of two greater then zero");
5706
5707 Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
5708 return false;
5709}
5710
5711bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
5712 const SMLoc Loc = getLexer().getLoc();
5713 std::string RadixStringRaw = parseStringTo(AsmToken::EndOfStatement);
5714 StringRef RadixString = StringRef(RadixStringRaw).trim();
5715 unsigned Radix;
5716 if (RadixString.getAsInteger(10, Radix)) {
5717 return Error(Loc,
5718 "radix must be a decimal number in the range 2 to 16; was " +
5719 RadixString);
5720 }
5721 if (Radix < 2 || Radix > 16)
5722 return Error(Loc, "radix must be in the range 2 to 16; was " +
5723 std::to_string(Radix));
5724 getLexer().setMasmDefaultRadix(Radix);
5725 return false;
5726}
5727
5728/// parseDirectiveEcho
5729/// ::= "echo" message
5730bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) {
5731 std::string Message = parseStringTo(AsmToken::EndOfStatement);
5732 llvm::outs() << Message;
5733 if (!StringRef(Message).ends_with("\n"))
5734 llvm::outs() << '\n';
5735 return false;
5736}
5737
5738// We are comparing pointers, but the pointers are relative to a single string.
5739// Thus, this should always be deterministic.
5740static int rewritesSort(const AsmRewrite *AsmRewriteA,
5741 const AsmRewrite *AsmRewriteB) {
5742 if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
5743 return -1;
5744 if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
5745 return 1;
5746
5747 // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
5748 // rewrite to the same location. Make sure the SizeDirective rewrite is
5749 // performed first, then the Imm/ImmPrefix and finally the Input/Output. This
5750 // ensures the sort algorithm is stable.
5751 if (AsmRewritePrecedence[AsmRewriteA->Kind] >
5752 AsmRewritePrecedence[AsmRewriteB->Kind])
5753 return -1;
5754
5755 if (AsmRewritePrecedence[AsmRewriteA->Kind] <
5756 AsmRewritePrecedence[AsmRewriteB->Kind])
5757 return 1;
5758 llvm_unreachable("Unstable rewrite sort.");
5759}
5760
5761bool MasmParser::defineMacro(StringRef Name, StringRef Value) {
5762 Variable &Var = Variables[Name.lower()];
5763 if (Var.Name.empty()) {
5764 Var.Name = Name;
5765 } else if (Var.Redefinable == Variable::NOT_REDEFINABLE) {
5766 return Error(SMLoc(), "invalid variable redefinition");
5767 } else if (Var.Redefinable == Variable::WARN_ON_REDEFINITION &&
5768 Warning(SMLoc(), "redefining '" + Name +
5769 "', already defined on the command line")) {
5770 return true;
5771 }
5772 Var.Redefinable = Variable::WARN_ON_REDEFINITION;
5773 Var.IsText = true;
5774 Var.TextValue = Value.str();
5775 return false;
5776}
5777
5778bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info) const {
5779 const std::pair<StringRef, StringRef> BaseMember = Name.split('.');
5780 const StringRef Base = BaseMember.first, Member = BaseMember.second;
5781 return lookUpField(Base, Member, Info);
5782}
5783
5784bool MasmParser::lookUpField(StringRef Base, StringRef Member,
5785 AsmFieldInfo &Info) const {
5786 if (Base.empty())
5787 return true;
5788
5789 AsmFieldInfo BaseInfo;
5790 if (Base.contains('.') && !lookUpField(Base, BaseInfo))
5791 Base = BaseInfo.Type.Name;
5792
5793 auto StructIt = Structs.find(Base.lower());
5794 auto TypeIt = KnownType.find(Base.lower());
5795 if (TypeIt != KnownType.end()) {
5796 StructIt = Structs.find(TypeIt->second.Name.lower());
5797 }
5798 if (StructIt != Structs.end())
5799 return lookUpField(StructIt->second, Member, Info);
5800
5801 return true;
5802}
5803
5804bool MasmParser::lookUpField(const StructInfo &Structure, StringRef Member,
5805 AsmFieldInfo &Info) const {
5806 if (Member.empty()) {
5807 Info.Type.Name = Structure.Name;
5808 Info.Type.Size = Structure.Size;
5809 Info.Type.ElementSize = Structure.Size;
5810 Info.Type.Length = 1;
5811 return false;
5812 }
5813
5814 std::pair<StringRef, StringRef> Split = Member.split('.');
5815 const StringRef FieldName = Split.first, FieldMember = Split.second;
5816
5817 auto StructIt = Structs.find(FieldName.lower());
5818 if (StructIt != Structs.end())
5819 return lookUpField(StructIt->second, FieldMember, Info);
5820
5821 auto FieldIt = Structure.FieldsByName.find(FieldName.lower());
5822 if (FieldIt == Structure.FieldsByName.end())
5823 return true;
5824
5825 const FieldInfo &Field = Structure.Fields[FieldIt->second];
5826 if (FieldMember.empty()) {
5827 Info.Offset += Field.Offset;
5828 Info.Type.Size = Field.SizeOf;
5829 Info.Type.ElementSize = Field.Type;
5830 Info.Type.Length = Field.LengthOf;
5831 if (Field.Contents.FT == FT_STRUCT)
5832 Info.Type.Name = Field.Contents.StructInfo.Structure.Name;
5833 else
5834 Info.Type.Name = "";
5835 return false;
5836 }
5837
5838 if (Field.Contents.FT != FT_STRUCT)
5839 return true;
5840 const StructFieldInfo &StructInfo = Field.Contents.StructInfo;
5841
5842 if (lookUpField(StructInfo.Structure, FieldMember, Info))
5843 return true;
5844
5845 Info.Offset += Field.Offset;
5846 return false;
5847}
5848
5849bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info) const {
5850 unsigned Size = StringSwitch<unsigned>(Name)
5851 .CasesLower({"byte", "db", "sbyte"}, 1)
5852 .CasesLower({"word", "dw", "sword"}, 2)
5853 .CasesLower({"dword", "dd", "sdword"}, 4)
5854 .CasesLower({"fword", "df"}, 6)
5855 .CasesLower({"qword", "dq", "sqword"}, 8)
5856 .CaseLower("real4", 4)
5857 .CaseLower("real8", 8)
5858 .CaseLower("real10", 10)
5859 .Default(0);
5860 if (Size) {
5861 Info.Name = Name;
5862 Info.ElementSize = Size;
5863 Info.Length = 1;
5864 Info.Size = Size;
5865 return false;
5866 }
5867
5868 auto StructIt = Structs.find(Name.lower());
5869 if (StructIt != Structs.end()) {
5870 const StructInfo &Structure = StructIt->second;
5871 Info.Name = Name;
5872 Info.ElementSize = Structure.Size;
5873 Info.Length = 1;
5874 Info.Size = Structure.Size;
5875 return false;
5876 }
5877
5878 return true;
5879}
5880
5881bool MasmParser::parseMSInlineAsm(
5882 std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs,
5883 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5884 SmallVectorImpl<std::string> &Constraints,
5885 SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
5886 MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
5887 SmallVector<void *, 4> InputDecls;
5888 SmallVector<void *, 4> OutputDecls;
5889 SmallVector<bool, 4> InputDeclsAddressOf;
5890 SmallVector<bool, 4> OutputDeclsAddressOf;
5891 SmallVector<std::string, 4> InputConstraints;
5892 SmallVector<std::string, 4> OutputConstraints;
5893 SmallVector<MCRegister, 4> ClobberRegs;
5894
5895 SmallVector<AsmRewrite, 4> AsmStrRewrites;
5896
5897 // Prime the lexer.
5898 Lex();
5899
5900 // While we have input, parse each statement.
5901 unsigned InputIdx = 0;
5902 unsigned OutputIdx = 0;
5903 while (getLexer().isNot(AsmToken::Eof)) {
5904 // Parse curly braces marking block start/end.
5905 if (parseCurlyBlockScope(AsmStrRewrites))
5906 continue;
5907
5908 ParseStatementInfo Info(&AsmStrRewrites);
5909 bool StatementErr = parseStatement(Info, &SI);
5910
5911 if (StatementErr || Info.ParseError) {
5912 // Emit pending errors if any exist.
5913 printPendingErrors();
5914 return true;
5915 }
5916
5917 // No pending error should exist here.
5918 assert(!hasPendingError() && "unexpected error from parseStatement");
5919
5920 if (Info.Opcode == ~0U)
5921 continue;
5922
5923 const MCInstrDesc &Desc = MII->get(Info.Opcode);
5924
5925 // Build the list of clobbers, outputs and inputs.
5926 for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
5927 MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
5928
5929 // Register operand.
5930 if (Operand.isReg() && !Operand.needAddressOf() &&
5931 !getTargetParser().omitRegisterFromClobberLists(Operand.getReg())) {
5932 unsigned NumDefs = Desc.getNumDefs();
5933 // Clobber.
5934 if (NumDefs && Operand.getMCOperandNum() < NumDefs)
5935 ClobberRegs.push_back(Operand.getReg());
5936 continue;
5937 }
5938
5939 // Expr/Input or Output.
5940 StringRef SymName = Operand.getSymName();
5941 if (SymName.empty())
5942 continue;
5943
5944 void *OpDecl = Operand.getOpDecl();
5945 if (!OpDecl)
5946 continue;
5947
5948 StringRef Constraint = Operand.getConstraint();
5949 if (Operand.isImm()) {
5950 // Offset as immediate.
5951 if (Operand.isOffsetOfLocal())
5952 Constraint = "r";
5953 else
5954 Constraint = "i";
5955 }
5956
5957 bool isOutput = (i == 1) && Desc.mayStore();
5958 SMLoc Start = SMLoc::getFromPointer(SymName.data());
5959 if (isOutput) {
5960 ++InputIdx;
5961 OutputDecls.push_back(OpDecl);
5962 OutputDeclsAddressOf.push_back(Operand.needAddressOf());
5963 OutputConstraints.push_back(("=" + Constraint).str());
5964 AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size());
5965 } else {
5966 InputDecls.push_back(OpDecl);
5967 InputDeclsAddressOf.push_back(Operand.needAddressOf());
5968 InputConstraints.push_back(Constraint.str());
5969 if (Desc.operands()[i - 1].isBranchTarget())
5970 AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size());
5971 else
5972 AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
5973 }
5974 }
5975
5976 // Consider implicit defs to be clobbers. Think of cpuid and push.
5977 llvm::append_range(ClobberRegs, Desc.implicit_defs());
5978 }
5979
5980 // Set the number of Outputs and Inputs.
5981 NumOutputs = OutputDecls.size();
5982 NumInputs = InputDecls.size();
5983
5984 // Set the unique clobbers.
5985 array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
5986 ClobberRegs.erase(llvm::unique(ClobberRegs), ClobberRegs.end());
5987 Clobbers.assign(ClobberRegs.size(), std::string());
5988 for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
5989 raw_string_ostream OS(Clobbers[I]);
5990 IP->printRegName(OS, ClobberRegs[I]);
5991 }
5992
5993 // Merge the various outputs and inputs. Output are expected first.
5994 if (NumOutputs || NumInputs) {
5995 unsigned NumExprs = NumOutputs + NumInputs;
5996 OpDecls.resize(NumExprs);
5997 Constraints.resize(NumExprs);
5998 for (unsigned i = 0; i < NumOutputs; ++i) {
5999 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
6000 Constraints[i] = OutputConstraints[i];
6001 }
6002 for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
6003 OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
6004 Constraints[j] = InputConstraints[i];
6005 }
6006 }
6007
6008 // Build the IR assembly string.
6009 std::string AsmStringIR;
6010 raw_string_ostream OS(AsmStringIR);
6011 StringRef ASMString =
6013 const char *AsmStart = ASMString.begin();
6014 const char *AsmEnd = ASMString.end();
6015 array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
6016 for (auto I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) {
6017 const AsmRewrite &AR = *I;
6018 // Check if this has already been covered by another rewrite...
6019 if (AR.Done)
6020 continue;
6022
6023 const char *Loc = AR.Loc.getPointer();
6024 assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
6025
6026 // Emit everything up to the immediate/expression.
6027 if (unsigned Len = Loc - AsmStart)
6028 OS << StringRef(AsmStart, Len);
6029
6030 // Skip the original expression.
6031 if (Kind == AOK_Skip) {
6032 AsmStart = Loc + AR.Len;
6033 continue;
6034 }
6035
6036 unsigned AdditionalSkip = 0;
6037 // Rewrite expressions in $N notation.
6038 switch (Kind) {
6039 default:
6040 break;
6041 case AOK_IntelExpr:
6042 assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
6043 if (AR.IntelExp.NeedBracs)
6044 OS << "[";
6045 if (AR.IntelExp.hasBaseReg())
6046 OS << AR.IntelExp.BaseReg;
6047 if (AR.IntelExp.hasIndexReg())
6048 OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
6049 << AR.IntelExp.IndexReg;
6050 if (AR.IntelExp.Scale > 1)
6051 OS << " * $$" << AR.IntelExp.Scale;
6052 if (AR.IntelExp.hasOffset()) {
6053 if (AR.IntelExp.hasRegs())
6054 OS << " + ";
6055 // Fuse this rewrite with a rewrite of the offset name, if present.
6056 StringRef OffsetName = AR.IntelExp.OffsetName;
6057 SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());
6058 size_t OffsetLen = OffsetName.size();
6059 auto rewrite_it = std::find_if(
6060 I, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
6061 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6062 (FusingAR.Kind == AOK_Input ||
6063 FusingAR.Kind == AOK_CallInput);
6064 });
6065 if (rewrite_it == AsmStrRewrites.end()) {
6066 OS << "offset " << OffsetName;
6067 } else if (rewrite_it->Kind == AOK_CallInput) {
6068 OS << "${" << InputIdx++ << ":P}";
6069 rewrite_it->Done = true;
6070 } else {
6071 OS << '$' << InputIdx++;
6072 rewrite_it->Done = true;
6073 }
6074 }
6075 if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
6076 OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
6077 if (AR.IntelExp.NeedBracs)
6078 OS << "]";
6079 break;
6080 case AOK_Label:
6081 OS << Ctx.getAsmInfo().getInternalSymbolPrefix() << AR.Label;
6082 break;
6083 case AOK_Input:
6084 OS << '$' << InputIdx++;
6085 break;
6086 case AOK_CallInput:
6087 OS << "${" << InputIdx++ << ":P}";
6088 break;
6089 case AOK_Output:
6090 OS << '$' << OutputIdx++;
6091 break;
6092 case AOK_SizeDirective:
6093 switch (AR.Val) {
6094 default: break;
6095 case 8: OS << "byte ptr "; break;
6096 case 16: OS << "word ptr "; break;
6097 case 32: OS << "dword ptr "; break;
6098 case 64: OS << "qword ptr "; break;
6099 case 80: OS << "xword ptr "; break;
6100 case 128: OS << "xmmword ptr "; break;
6101 case 256: OS << "ymmword ptr "; break;
6102 }
6103 break;
6104 case AOK_Emit:
6105 OS << ".byte";
6106 break;
6107 case AOK_Align: {
6108 // MS alignment directives are measured in bytes. If the native assembler
6109 // measures alignment in bytes, we can pass it straight through.
6110 OS << ".align";
6111 if (getContext().getAsmInfo().getAlignmentIsInBytes())
6112 break;
6113
6114 // Alignment is in log2 form, so print that instead and skip the original
6115 // immediate.
6116 unsigned Val = AR.Val;
6117 OS << ' ' << Val;
6118 assert(Val < 10 && "Expected alignment less then 2^10.");
6119 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6120 break;
6121 }
6122 case AOK_EVEN:
6123 OS << ".even";
6124 break;
6125 case AOK_EndOfStatement:
6126 OS << "\n\t";
6127 break;
6128 }
6129
6130 // Skip the original expression.
6131 AsmStart = Loc + AR.Len + AdditionalSkip;
6132 }
6133
6134 // Emit the remainder of the asm string.
6135 if (AsmStart != AsmEnd)
6136 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6137
6138 AsmString = OS.str();
6139 return false;
6140}
6141
6142void MasmParser::initializeBuiltinSymbolMaps() {
6143 // Numeric built-ins (supported in all versions)
6144 BuiltinSymbolMap["@version"] = BI_VERSION;
6145 BuiltinSymbolMap["@line"] = BI_LINE;
6146 BuiltinSymbolMap["@unwindversion"] = BI_UNWINDVERSION;
6147
6148 // Text built-ins (supported in all versions)
6149 BuiltinSymbolMap["@date"] = BI_DATE;
6150 BuiltinSymbolMap["@time"] = BI_TIME;
6151 BuiltinSymbolMap["@filecur"] = BI_FILECUR;
6152 BuiltinSymbolMap["@filename"] = BI_FILENAME;
6153 BuiltinSymbolMap["@curseg"] = BI_CURSEG;
6154
6155 // Function built-ins (supported in all versions)
6156 BuiltinFunctionMap["@catstr"] = BI_CATSTR;
6157
6158 // Some built-ins exist only for MASM32 (32-bit x86)
6159 if (getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
6160 Triple::x86) {
6161 // Numeric built-ins
6162 // BuiltinSymbolMap["@cpu"] = BI_CPU;
6163 // BuiltinSymbolMap["@interface"] = BI_INTERFACE;
6164 // BuiltinSymbolMap["@wordsize"] = BI_WORDSIZE;
6165 // BuiltinSymbolMap["@codesize"] = BI_CODESIZE;
6166 // BuiltinSymbolMap["@datasize"] = BI_DATASIZE;
6167 // BuiltinSymbolMap["@model"] = BI_MODEL;
6168
6169 // Text built-ins
6170 // BuiltinSymbolMap["@code"] = BI_CODE;
6171 // BuiltinSymbolMap["@data"] = BI_DATA;
6172 // BuiltinSymbolMap["@fardata?"] = BI_FARDATA;
6173 // BuiltinSymbolMap["@stack"] = BI_STACK;
6174 }
6175}
6176
6177const MCExpr *MasmParser::evaluateBuiltinValue(BuiltinSymbol Symbol,
6178 SMLoc StartLoc) {
6179 switch (Symbol) {
6180 default:
6181 return nullptr;
6182 case BI_VERSION:
6183 // Match a recent version of ML.EXE.
6184 return MCConstantExpr::create(1427, getContext());
6185 case BI_LINE: {
6186 int64_t Line;
6187 if (ActiveMacros.empty())
6188 Line = SrcMgr.FindLineNumber(StartLoc, CurBuffer);
6189 else
6190 Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
6191 ActiveMacros.front()->ExitBuffer);
6192 return MCConstantExpr::create(Line, getContext());
6193 }
6194 case BI_UNWINDVERSION:
6195 return MCConstantExpr::create(getStreamer().getDefaultWinCFIUnwindVersion(),
6196 getContext());
6197 }
6198 llvm_unreachable("unhandled built-in symbol");
6199}
6200
6201std::optional<std::string>
6202MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
6203 switch (Symbol) {
6204 default:
6205 return {};
6206 case BI_DATE: {
6207 // Current local date, formatted MM/DD/YY
6208 char TmpBuffer[sizeof("mm/dd/yy")];
6209 const size_t Len = strftime(TmpBuffer, sizeof(TmpBuffer), "%D", &TM);
6210 return std::string(TmpBuffer, Len);
6211 }
6212 case BI_TIME: {
6213 // Current local time, formatted HH:MM:SS (24-hour clock)
6214 char TmpBuffer[sizeof("hh:mm:ss")];
6215 const size_t Len = strftime(TmpBuffer, sizeof(TmpBuffer), "%T", &TM);
6216 return std::string(TmpBuffer, Len);
6217 }
6218 case BI_FILECUR:
6219 return SrcMgr
6221 ActiveMacros.empty() ? CurBuffer : ActiveMacros.front()->ExitBuffer)
6223 .str();
6224 case BI_FILENAME:
6227 .upper();
6228 case BI_CURSEG:
6229 return getStreamer().getCurrentSectionOnly()->getName().str();
6230 }
6231 llvm_unreachable("unhandled built-in symbol");
6232}
6233
6234bool MasmParser::evaluateBuiltinMacroFunction(BuiltinFunction Function,
6235 StringRef Name,
6236 std::string &Res) {
6237 if (parseToken(AsmToken::LParen, "invoking macro function '" + Name +
6238 "' requires arguments in parentheses")) {
6239 return true;
6240 }
6241
6243 switch (Function) {
6244 default:
6245 return true;
6246 case BI_CATSTR:
6247 break;
6248 }
6249 MCAsmMacro M(Name, "", P, {}, true);
6250
6251 MCAsmMacroArguments A;
6252 if (parseMacroArguments(&M, A, AsmToken::RParen) || parseRParen()) {
6253 return true;
6254 }
6255
6256 switch (Function) {
6257 default:
6258 llvm_unreachable("unhandled built-in function");
6259 case BI_CATSTR: {
6260 for (const MCAsmMacroArgument &Arg : A) {
6261 for (const AsmToken &Tok : Arg) {
6262 if (Tok.is(AsmToken::String)) {
6263 Res.append(Tok.getStringContents());
6264 } else {
6265 Res.append(Tok.getString());
6266 }
6267 }
6268 }
6269 return false;
6270 }
6271 }
6272 llvm_unreachable("unhandled built-in function");
6273 return true;
6274}
6275
6276/// Create an MCAsmParser instance.
6278 MCStreamer &Out, const MCAsmInfo &MAI,
6279 struct tm TM, unsigned CB) {
6280 return new MasmParser(SM, C, Out, MAI, TM, CB);
6281}
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")
DXIL Intrinsic Expansion
@ Default
Value * getPointer(Value *Ptr)
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
const std::string FatArchTraits< MachO::fat_arch >::StructName
Register Reg
static bool isMacroParameterChar(char C)
@ DEFAULT_ADDRSPACE
static constexpr unsigned SM(unsigned Version)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static constexpr StringLiteral Filename
OptimizedStructLayoutField Field
#define P(N)
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
const char * Msg
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:484
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:1184
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Definition APFloat.h:1195
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Definition APFloat.h:1165
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1513
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
Definition APInt.h:476
ConditionalAssemblyType TheCond
Definition AsmCond.h:30
bool Ignore
Definition AsmCond.h:32
bool CondMet
Definition AsmCond.h:31
LLVM_ABI SMLoc getLoc() const
Definition AsmLexer.cpp:31
bool isNot(TokenKind K) const
Definition MCAsmMacro.h:76
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition MCAsmMacro.h:103
StringRef getStringContents() const
Get the contents of a string token (without quotes).
Definition MCAsmMacro.h:83
bool is(TokenKind K) const
Definition MCAsmMacro.h:75
LLVM_ABI SMLoc getEndLoc() const
Definition AsmLexer.cpp:33
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
Definition MCAsmMacro.h:92
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition MCAsmInfo.h:66
bool preserveAsmComments() const
Return true if assembly (inline or otherwise) should be parsed.
Definition MCAsmInfo.h:731
bool shouldUseLogicalShr() const
Definition MCAsmInfo.h:736
StringRef getInternalSymbolPrefix() const
Definition MCAsmInfo.h:564
virtual bool useCodeAlign(const MCSection &Sec) const
Definition MCAsmInfo.h:522
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:303
@ Shl
Shift left.
Definition MCExpr.h:320
@ AShr
Arithmetic shift right.
Definition MCExpr.h:321
@ LShr
Logical shift right.
Definition MCExpr.h:322
@ GTE
Signed greater than or equal comparison (result is either 0 or some target-specific non-zero value).
Definition MCExpr.h:307
@ EQ
Equality comparison.
Definition MCExpr.h:304
@ Sub
Subtraction.
Definition MCExpr.h:323
@ Mul
Multiplication.
Definition MCExpr.h:316
@ GT
Signed greater than comparison (result is either 0 or some target-specific non-zero value)
Definition MCExpr.h:305
@ Mod
Signed remainder.
Definition MCExpr.h:315
@ And
Bitwise and.
Definition MCExpr.h:302
@ Or
Bitwise or.
Definition MCExpr.h:318
@ Xor
Bitwise exclusive or.
Definition MCExpr.h:324
@ LAnd
Logical and.
Definition MCExpr.h:309
@ LOr
Logical or.
Definition MCExpr.h:310
@ LT
Signed less than comparison (result is either 0 or some target-specific non-zero value).
Definition MCExpr.h:311
@ Add
Addition.
Definition MCExpr.h:301
@ LTE
Signed less than or equal comparison (result is either 0 or some target-specific non-zero value).
Definition MCExpr.h:313
@ NE
Inequality comparison.
Definition MCExpr.h:317
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:409
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:89
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:222
virtual void addBlankLine()
Emit a blank line to a .s file to pretty it up.
Definition MCStreamer.h:425
virtual void addExplicitComment(const Twine &T)
Add explicit comment T.
virtual void initSections(const MCSubtargetInfo &STI)
Create the default sections and set the initial one.
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:226
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
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:264
static const MCUnaryExpr * createPlus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:276
static const MCUnaryExpr * createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:272
static const MCUnaryExpr * createMinus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:268
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:338
StringRef getLineContents() const
Definition SourceMgr.h:340
SMLoc getLoc() const
Definition SourceMgr.h:334
StringRef getMessage() const
Definition SourceMgr.h:339
ArrayRef< std::pair< unsigned, unsigned > > getRanges() const
Definition SourceMgr.h:341
const SourceMgr * getSourceMgr() const
Definition SourceMgr.h:333
int getColumnNo() const
Definition SourceMgr.h:337
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
LLVM_ABI void printIncludeStackForDiagnostic(SMLoc Loc, raw_ostream &OS) const
Prints the include stack of a buffer unless it is a macro instantiation buffer.
unsigned getMainFileID() const
Definition SourceMgr.h:151
const MemoryBuffer * getMemoryBuffer(unsigned i) const
Definition SourceMgr.h:144
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:156
LLVM_ABI unsigned FindBufferContainingLoc(SMLoc Loc) const
Return the ID of the buffer containing the specified location.
Definition SourceMgr.cpp:97
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:131
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:217
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
Definition SourceMgr.h:163
iterator end()
Definition StringMap.h:213
iterator find(StringRef Key)
Definition StringMap.h:226
bool contains(StringRef Key) const
contains - Return true if the element is in the map, false otherwise.
Definition StringMap.h:269
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
Definition StringMap.h:274
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:249
StringMapIterBase< ValueTy, true > const_iterator
Definition StringMap.h:207
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Definition StringMap.h:310
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
Definition StringRef.h:691
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition StringRef.h:490
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:597
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
iterator begin() const
Definition StringRef.h:114
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:720
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:138
iterator end() const
Definition StringRef.h:116
LLVM_ABI std::string lower() const
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
Definition StringRef.h:170
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
@ IsUnion
Definition Types.h:256
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:1134
bool empty() const
Definition BasicBlock.h:101
LLVM_ABI Instruction & front() const
LLVM_ABI StringRef stem(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get stem.
Definition Path.cpp:596
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:315
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
Definition Error.h:1129
@ Offset
Definition DWP.cpp:578
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:1669
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
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:2208
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:244
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
std::vector< MCAsmMacroParameter > MCAsmMacroParameters
Definition MCAsmMacro.h:134
auto unique(Range &&R, Predicate P)
Definition STLExtras.h:2134
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:338
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
LLVM_ABI SourceMgr SrcMgr
Definition Error.cpp:24
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
cl::opt< unsigned > AsmMacroMaxNestingDepth
const char AsmRewritePrecedence[]
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
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:169
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
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:249
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:1596
@ 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.