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