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