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