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