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