xref: /freebsd/contrib/llvm-project/llvm/lib/MC/MCParser/MasmParser.cpp (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
15ffd83dbSDimitry Andric //===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric //
95ffd83dbSDimitry Andric // This class implements the parser for assembly files.
105ffd83dbSDimitry Andric //
115ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
125ffd83dbSDimitry Andric 
135ffd83dbSDimitry Andric #include "llvm/ADT/APFloat.h"
145ffd83dbSDimitry Andric #include "llvm/ADT/APInt.h"
155ffd83dbSDimitry Andric #include "llvm/ADT/ArrayRef.h"
16*04eeddc0SDimitry Andric #include "llvm/ADT/BitVector.h"
17fe6060f1SDimitry Andric #include "llvm/ADT/DenseMap.h"
185ffd83dbSDimitry Andric #include "llvm/ADT/None.h"
19e8d8bef9SDimitry Andric #include "llvm/ADT/Optional.h"
205ffd83dbSDimitry Andric #include "llvm/ADT/STLExtras.h"
215ffd83dbSDimitry Andric #include "llvm/ADT/SmallString.h"
225ffd83dbSDimitry Andric #include "llvm/ADT/SmallVector.h"
235ffd83dbSDimitry Andric #include "llvm/ADT/StringExtras.h"
245ffd83dbSDimitry Andric #include "llvm/ADT/StringMap.h"
255ffd83dbSDimitry Andric #include "llvm/ADT/StringRef.h"
26e8d8bef9SDimitry Andric #include "llvm/ADT/StringSwitch.h"
275ffd83dbSDimitry Andric #include "llvm/ADT/Twine.h"
285ffd83dbSDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
295ffd83dbSDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
305ffd83dbSDimitry Andric #include "llvm/MC/MCAsmInfo.h"
315ffd83dbSDimitry Andric #include "llvm/MC/MCCodeView.h"
325ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h"
335ffd83dbSDimitry Andric #include "llvm/MC/MCDirectives.h"
345ffd83dbSDimitry Andric #include "llvm/MC/MCDwarf.h"
355ffd83dbSDimitry Andric #include "llvm/MC/MCExpr.h"
365ffd83dbSDimitry Andric #include "llvm/MC/MCInstPrinter.h"
375ffd83dbSDimitry Andric #include "llvm/MC/MCInstrDesc.h"
385ffd83dbSDimitry Andric #include "llvm/MC/MCInstrInfo.h"
395ffd83dbSDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
405ffd83dbSDimitry Andric #include "llvm/MC/MCParser/AsmCond.h"
415ffd83dbSDimitry Andric #include "llvm/MC/MCParser/AsmLexer.h"
425ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
435ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmParser.h"
445ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmParserExtension.h"
455ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmParserUtils.h"
465ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
475ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
485ffd83dbSDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
495ffd83dbSDimitry Andric #include "llvm/MC/MCSection.h"
505ffd83dbSDimitry Andric #include "llvm/MC/MCStreamer.h"
515ffd83dbSDimitry Andric #include "llvm/MC/MCSymbol.h"
525ffd83dbSDimitry Andric #include "llvm/MC/MCTargetOptions.h"
535ffd83dbSDimitry Andric #include "llvm/MC/MCValue.h"
545ffd83dbSDimitry Andric #include "llvm/Support/Casting.h"
555ffd83dbSDimitry Andric #include "llvm/Support/CommandLine.h"
565ffd83dbSDimitry Andric #include "llvm/Support/ErrorHandling.h"
57e8d8bef9SDimitry Andric #include "llvm/Support/Format.h"
585ffd83dbSDimitry Andric #include "llvm/Support/MD5.h"
595ffd83dbSDimitry Andric #include "llvm/Support/MathExtras.h"
605ffd83dbSDimitry Andric #include "llvm/Support/MemoryBuffer.h"
61fe6060f1SDimitry Andric #include "llvm/Support/Path.h"
625ffd83dbSDimitry Andric #include "llvm/Support/SMLoc.h"
635ffd83dbSDimitry Andric #include "llvm/Support/SourceMgr.h"
645ffd83dbSDimitry Andric #include "llvm/Support/raw_ostream.h"
655ffd83dbSDimitry Andric #include <algorithm>
665ffd83dbSDimitry Andric #include <cassert>
675ffd83dbSDimitry Andric #include <cctype>
685ffd83dbSDimitry Andric #include <climits>
695ffd83dbSDimitry Andric #include <cstddef>
705ffd83dbSDimitry Andric #include <cstdint>
71fe6060f1SDimitry Andric #include <ctime>
725ffd83dbSDimitry Andric #include <deque>
735ffd83dbSDimitry Andric #include <memory>
745ffd83dbSDimitry Andric #include <sstream>
755ffd83dbSDimitry Andric #include <string>
765ffd83dbSDimitry Andric #include <tuple>
775ffd83dbSDimitry Andric #include <utility>
785ffd83dbSDimitry Andric #include <vector>
795ffd83dbSDimitry Andric 
805ffd83dbSDimitry Andric using namespace llvm;
815ffd83dbSDimitry Andric 
825ffd83dbSDimitry Andric extern cl::opt<unsigned> AsmMacroMaxNestingDepth;
835ffd83dbSDimitry Andric 
845ffd83dbSDimitry Andric namespace {
855ffd83dbSDimitry Andric 
865ffd83dbSDimitry Andric /// Helper types for tracking macro definitions.
875ffd83dbSDimitry Andric typedef std::vector<AsmToken> MCAsmMacroArgument;
885ffd83dbSDimitry Andric typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
895ffd83dbSDimitry Andric 
905ffd83dbSDimitry Andric /// Helper class for storing information about an active macro instantiation.
915ffd83dbSDimitry Andric struct MacroInstantiation {
925ffd83dbSDimitry Andric   /// The location of the instantiation.
935ffd83dbSDimitry Andric   SMLoc InstantiationLoc;
945ffd83dbSDimitry Andric 
955ffd83dbSDimitry Andric   /// The buffer where parsing should resume upon instantiation completion.
965ffd83dbSDimitry Andric   unsigned ExitBuffer;
975ffd83dbSDimitry Andric 
985ffd83dbSDimitry Andric   /// The location where parsing should resume upon instantiation completion.
995ffd83dbSDimitry Andric   SMLoc ExitLoc;
1005ffd83dbSDimitry Andric 
1015ffd83dbSDimitry Andric   /// The depth of TheCondStack at the start of the instantiation.
1025ffd83dbSDimitry Andric   size_t CondStackDepth;
1035ffd83dbSDimitry Andric };
1045ffd83dbSDimitry Andric 
1055ffd83dbSDimitry Andric struct ParseStatementInfo {
1065ffd83dbSDimitry Andric   /// The parsed operands from the last parsed statement.
1075ffd83dbSDimitry Andric   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;
1085ffd83dbSDimitry Andric 
1095ffd83dbSDimitry Andric   /// The opcode from the last parsed instruction.
1105ffd83dbSDimitry Andric   unsigned Opcode = ~0U;
1115ffd83dbSDimitry Andric 
1125ffd83dbSDimitry Andric   /// Was there an error parsing the inline assembly?
1135ffd83dbSDimitry Andric   bool ParseError = false;
1145ffd83dbSDimitry Andric 
115e8d8bef9SDimitry Andric   /// The value associated with a macro exit.
116e8d8bef9SDimitry Andric   Optional<std::string> ExitValue;
117e8d8bef9SDimitry Andric 
1185ffd83dbSDimitry Andric   SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
1195ffd83dbSDimitry Andric 
1205ffd83dbSDimitry Andric   ParseStatementInfo() = delete;
1215ffd83dbSDimitry Andric   ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
1225ffd83dbSDimitry Andric       : AsmRewrites(rewrites) {}
1235ffd83dbSDimitry Andric };
1245ffd83dbSDimitry Andric 
1255ffd83dbSDimitry Andric enum FieldType {
1265ffd83dbSDimitry Andric   FT_INTEGRAL, // Initializer: integer expression, stored as an MCExpr.
1275ffd83dbSDimitry Andric   FT_REAL,     // Initializer: real number, stored as an APInt.
1285ffd83dbSDimitry Andric   FT_STRUCT    // Initializer: struct initializer, stored recursively.
1295ffd83dbSDimitry Andric };
1305ffd83dbSDimitry Andric 
1315ffd83dbSDimitry Andric struct FieldInfo;
1325ffd83dbSDimitry Andric struct StructInfo {
1335ffd83dbSDimitry Andric   StringRef Name;
1345ffd83dbSDimitry Andric   bool IsUnion = false;
135fe6060f1SDimitry Andric   bool Initializable = true;
136e8d8bef9SDimitry Andric   unsigned Alignment = 0;
137e8d8bef9SDimitry Andric   unsigned AlignmentSize = 0;
138fe6060f1SDimitry Andric   unsigned NextOffset = 0;
139fe6060f1SDimitry Andric   unsigned Size = 0;
1405ffd83dbSDimitry Andric   std::vector<FieldInfo> Fields;
1415ffd83dbSDimitry Andric   StringMap<size_t> FieldsByName;
1425ffd83dbSDimitry Andric 
143e8d8bef9SDimitry Andric   FieldInfo &addField(StringRef FieldName, FieldType FT,
144e8d8bef9SDimitry Andric                       unsigned FieldAlignmentSize);
1455ffd83dbSDimitry Andric 
1465ffd83dbSDimitry Andric   StructInfo() = default;
1475ffd83dbSDimitry Andric 
1485ffd83dbSDimitry Andric   StructInfo(StringRef StructName, bool Union, unsigned AlignmentValue)
1495ffd83dbSDimitry Andric       : Name(StructName), IsUnion(Union), Alignment(AlignmentValue) {}
1505ffd83dbSDimitry Andric };
1515ffd83dbSDimitry Andric 
1525ffd83dbSDimitry Andric // FIXME: This should probably use a class hierarchy, raw pointers between the
1535ffd83dbSDimitry Andric // objects, and dynamic type resolution instead of a union. On the other hand,
1545ffd83dbSDimitry Andric // ownership then becomes much more complicated; the obvious thing would be to
1555ffd83dbSDimitry Andric // use BumpPtrAllocator, but the lack of a destructor makes that messy.
1565ffd83dbSDimitry Andric 
1575ffd83dbSDimitry Andric struct StructInitializer;
1585ffd83dbSDimitry Andric struct IntFieldInfo {
1595ffd83dbSDimitry Andric   SmallVector<const MCExpr *, 1> Values;
1605ffd83dbSDimitry Andric 
1615ffd83dbSDimitry Andric   IntFieldInfo() = default;
1625ffd83dbSDimitry Andric   IntFieldInfo(const SmallVector<const MCExpr *, 1> &V) { Values = V; }
1635ffd83dbSDimitry Andric   IntFieldInfo(SmallVector<const MCExpr *, 1> &&V) { Values = V; }
1645ffd83dbSDimitry Andric };
1655ffd83dbSDimitry Andric struct RealFieldInfo {
1665ffd83dbSDimitry Andric   SmallVector<APInt, 1> AsIntValues;
1675ffd83dbSDimitry Andric 
1685ffd83dbSDimitry Andric   RealFieldInfo() = default;
1695ffd83dbSDimitry Andric   RealFieldInfo(const SmallVector<APInt, 1> &V) { AsIntValues = V; }
1705ffd83dbSDimitry Andric   RealFieldInfo(SmallVector<APInt, 1> &&V) { AsIntValues = V; }
1715ffd83dbSDimitry Andric };
1725ffd83dbSDimitry Andric struct StructFieldInfo {
1735ffd83dbSDimitry Andric   std::vector<StructInitializer> Initializers;
1745ffd83dbSDimitry Andric   StructInfo Structure;
1755ffd83dbSDimitry Andric 
1765ffd83dbSDimitry Andric   StructFieldInfo() = default;
1775ffd83dbSDimitry Andric   StructFieldInfo(const std::vector<StructInitializer> &V, StructInfo S) {
1785ffd83dbSDimitry Andric     Initializers = V;
1795ffd83dbSDimitry Andric     Structure = S;
1805ffd83dbSDimitry Andric   }
1815ffd83dbSDimitry Andric   StructFieldInfo(std::vector<StructInitializer> &&V, StructInfo S) {
1825ffd83dbSDimitry Andric     Initializers = V;
1835ffd83dbSDimitry Andric     Structure = S;
1845ffd83dbSDimitry Andric   }
1855ffd83dbSDimitry Andric };
1865ffd83dbSDimitry Andric 
1875ffd83dbSDimitry Andric class FieldInitializer {
1885ffd83dbSDimitry Andric public:
1895ffd83dbSDimitry Andric   FieldType FT;
1905ffd83dbSDimitry Andric   union {
1915ffd83dbSDimitry Andric     IntFieldInfo IntInfo;
1925ffd83dbSDimitry Andric     RealFieldInfo RealInfo;
1935ffd83dbSDimitry Andric     StructFieldInfo StructInfo;
1945ffd83dbSDimitry Andric   };
1955ffd83dbSDimitry Andric 
1965ffd83dbSDimitry Andric   ~FieldInitializer() {
1975ffd83dbSDimitry Andric     switch (FT) {
1985ffd83dbSDimitry Andric     case FT_INTEGRAL:
1995ffd83dbSDimitry Andric       IntInfo.~IntFieldInfo();
2005ffd83dbSDimitry Andric       break;
2015ffd83dbSDimitry Andric     case FT_REAL:
2025ffd83dbSDimitry Andric       RealInfo.~RealFieldInfo();
2035ffd83dbSDimitry Andric       break;
2045ffd83dbSDimitry Andric     case FT_STRUCT:
2055ffd83dbSDimitry Andric       StructInfo.~StructFieldInfo();
2065ffd83dbSDimitry Andric       break;
2075ffd83dbSDimitry Andric     }
2085ffd83dbSDimitry Andric   }
2095ffd83dbSDimitry Andric 
2105ffd83dbSDimitry Andric   FieldInitializer(FieldType FT) : FT(FT) {
2115ffd83dbSDimitry Andric     switch (FT) {
2125ffd83dbSDimitry Andric     case FT_INTEGRAL:
2135ffd83dbSDimitry Andric       new (&IntInfo) IntFieldInfo();
2145ffd83dbSDimitry Andric       break;
2155ffd83dbSDimitry Andric     case FT_REAL:
2165ffd83dbSDimitry Andric       new (&RealInfo) RealFieldInfo();
2175ffd83dbSDimitry Andric       break;
2185ffd83dbSDimitry Andric     case FT_STRUCT:
2195ffd83dbSDimitry Andric       new (&StructInfo) StructFieldInfo();
2205ffd83dbSDimitry Andric       break;
2215ffd83dbSDimitry Andric     }
2225ffd83dbSDimitry Andric   }
2235ffd83dbSDimitry Andric 
2245ffd83dbSDimitry Andric   FieldInitializer(SmallVector<const MCExpr *, 1> &&Values) : FT(FT_INTEGRAL) {
2255ffd83dbSDimitry Andric     new (&IntInfo) IntFieldInfo(Values);
2265ffd83dbSDimitry Andric   }
2275ffd83dbSDimitry Andric 
2285ffd83dbSDimitry Andric   FieldInitializer(SmallVector<APInt, 1> &&AsIntValues) : FT(FT_REAL) {
2295ffd83dbSDimitry Andric     new (&RealInfo) RealFieldInfo(AsIntValues);
2305ffd83dbSDimitry Andric   }
2315ffd83dbSDimitry Andric 
2325ffd83dbSDimitry Andric   FieldInitializer(std::vector<StructInitializer> &&Initializers,
2335ffd83dbSDimitry Andric                    struct StructInfo Structure)
2345ffd83dbSDimitry Andric       : FT(FT_STRUCT) {
2355ffd83dbSDimitry Andric     new (&StructInfo) StructFieldInfo(Initializers, Structure);
2365ffd83dbSDimitry Andric   }
2375ffd83dbSDimitry Andric 
2385ffd83dbSDimitry Andric   FieldInitializer(const FieldInitializer &Initializer) : FT(Initializer.FT) {
2395ffd83dbSDimitry Andric     switch (FT) {
2405ffd83dbSDimitry Andric     case FT_INTEGRAL:
2415ffd83dbSDimitry Andric       new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
2425ffd83dbSDimitry Andric       break;
2435ffd83dbSDimitry Andric     case FT_REAL:
2445ffd83dbSDimitry Andric       new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
2455ffd83dbSDimitry Andric       break;
2465ffd83dbSDimitry Andric     case FT_STRUCT:
2475ffd83dbSDimitry Andric       new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
2485ffd83dbSDimitry Andric       break;
2495ffd83dbSDimitry Andric     }
2505ffd83dbSDimitry Andric   }
2515ffd83dbSDimitry Andric 
2525ffd83dbSDimitry Andric   FieldInitializer(FieldInitializer &&Initializer) : FT(Initializer.FT) {
2535ffd83dbSDimitry Andric     switch (FT) {
2545ffd83dbSDimitry Andric     case FT_INTEGRAL:
2555ffd83dbSDimitry Andric       new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
2565ffd83dbSDimitry Andric       break;
2575ffd83dbSDimitry Andric     case FT_REAL:
2585ffd83dbSDimitry Andric       new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
2595ffd83dbSDimitry Andric       break;
2605ffd83dbSDimitry Andric     case FT_STRUCT:
2615ffd83dbSDimitry Andric       new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
2625ffd83dbSDimitry Andric       break;
2635ffd83dbSDimitry Andric     }
2645ffd83dbSDimitry Andric   }
2655ffd83dbSDimitry Andric 
2665ffd83dbSDimitry Andric   FieldInitializer &operator=(const FieldInitializer &Initializer) {
2675ffd83dbSDimitry Andric     if (FT != Initializer.FT) {
2685ffd83dbSDimitry Andric       switch (FT) {
2695ffd83dbSDimitry Andric       case FT_INTEGRAL:
2705ffd83dbSDimitry Andric         IntInfo.~IntFieldInfo();
2715ffd83dbSDimitry Andric         break;
2725ffd83dbSDimitry Andric       case FT_REAL:
2735ffd83dbSDimitry Andric         RealInfo.~RealFieldInfo();
2745ffd83dbSDimitry Andric         break;
2755ffd83dbSDimitry Andric       case FT_STRUCT:
2765ffd83dbSDimitry Andric         StructInfo.~StructFieldInfo();
2775ffd83dbSDimitry Andric         break;
2785ffd83dbSDimitry Andric       }
2795ffd83dbSDimitry Andric     }
2805ffd83dbSDimitry Andric     FT = Initializer.FT;
2815ffd83dbSDimitry Andric     switch (FT) {
2825ffd83dbSDimitry Andric     case FT_INTEGRAL:
2835ffd83dbSDimitry Andric       IntInfo = Initializer.IntInfo;
2845ffd83dbSDimitry Andric       break;
2855ffd83dbSDimitry Andric     case FT_REAL:
2865ffd83dbSDimitry Andric       RealInfo = Initializer.RealInfo;
2875ffd83dbSDimitry Andric       break;
2885ffd83dbSDimitry Andric     case FT_STRUCT:
2895ffd83dbSDimitry Andric       StructInfo = Initializer.StructInfo;
2905ffd83dbSDimitry Andric       break;
2915ffd83dbSDimitry Andric     }
2925ffd83dbSDimitry Andric     return *this;
2935ffd83dbSDimitry Andric   }
2945ffd83dbSDimitry Andric 
2955ffd83dbSDimitry Andric   FieldInitializer &operator=(FieldInitializer &&Initializer) {
2965ffd83dbSDimitry Andric     if (FT != Initializer.FT) {
2975ffd83dbSDimitry Andric       switch (FT) {
2985ffd83dbSDimitry Andric       case FT_INTEGRAL:
2995ffd83dbSDimitry Andric         IntInfo.~IntFieldInfo();
3005ffd83dbSDimitry Andric         break;
3015ffd83dbSDimitry Andric       case FT_REAL:
3025ffd83dbSDimitry Andric         RealInfo.~RealFieldInfo();
3035ffd83dbSDimitry Andric         break;
3045ffd83dbSDimitry Andric       case FT_STRUCT:
3055ffd83dbSDimitry Andric         StructInfo.~StructFieldInfo();
3065ffd83dbSDimitry Andric         break;
3075ffd83dbSDimitry Andric       }
3085ffd83dbSDimitry Andric     }
3095ffd83dbSDimitry Andric     FT = Initializer.FT;
3105ffd83dbSDimitry Andric     switch (FT) {
3115ffd83dbSDimitry Andric     case FT_INTEGRAL:
3125ffd83dbSDimitry Andric       IntInfo = Initializer.IntInfo;
3135ffd83dbSDimitry Andric       break;
3145ffd83dbSDimitry Andric     case FT_REAL:
3155ffd83dbSDimitry Andric       RealInfo = Initializer.RealInfo;
3165ffd83dbSDimitry Andric       break;
3175ffd83dbSDimitry Andric     case FT_STRUCT:
3185ffd83dbSDimitry Andric       StructInfo = Initializer.StructInfo;
3195ffd83dbSDimitry Andric       break;
3205ffd83dbSDimitry Andric     }
3215ffd83dbSDimitry Andric     return *this;
3225ffd83dbSDimitry Andric   }
3235ffd83dbSDimitry Andric };
3245ffd83dbSDimitry Andric 
3255ffd83dbSDimitry Andric struct StructInitializer {
3265ffd83dbSDimitry Andric   std::vector<FieldInitializer> FieldInitializers;
3275ffd83dbSDimitry Andric };
3285ffd83dbSDimitry Andric 
3295ffd83dbSDimitry Andric struct FieldInfo {
3305ffd83dbSDimitry Andric   // Offset of the field within the containing STRUCT.
331fe6060f1SDimitry Andric   unsigned Offset = 0;
3325ffd83dbSDimitry Andric 
3335ffd83dbSDimitry Andric   // Total size of the field (= LengthOf * Type).
334e8d8bef9SDimitry Andric   unsigned SizeOf = 0;
3355ffd83dbSDimitry Andric 
3365ffd83dbSDimitry Andric   // Number of elements in the field (1 if scalar, >1 if an array).
337e8d8bef9SDimitry Andric   unsigned LengthOf = 0;
3385ffd83dbSDimitry Andric 
3395ffd83dbSDimitry Andric   // Size of a single entry in this field, in bytes ("type" in MASM standards).
340e8d8bef9SDimitry Andric   unsigned Type = 0;
3415ffd83dbSDimitry Andric 
3425ffd83dbSDimitry Andric   FieldInitializer Contents;
3435ffd83dbSDimitry Andric 
3445ffd83dbSDimitry Andric   FieldInfo(FieldType FT) : Contents(FT) {}
3455ffd83dbSDimitry Andric };
3465ffd83dbSDimitry Andric 
347e8d8bef9SDimitry Andric FieldInfo &StructInfo::addField(StringRef FieldName, FieldType FT,
348e8d8bef9SDimitry Andric                                 unsigned FieldAlignmentSize) {
3495ffd83dbSDimitry Andric   if (!FieldName.empty())
350e8d8bef9SDimitry Andric     FieldsByName[FieldName.lower()] = Fields.size();
3515ffd83dbSDimitry Andric   Fields.emplace_back(FT);
3525ffd83dbSDimitry Andric   FieldInfo &Field = Fields.back();
353fe6060f1SDimitry Andric   Field.Offset =
354fe6060f1SDimitry Andric       llvm::alignTo(NextOffset, std::min(Alignment, FieldAlignmentSize));
355fe6060f1SDimitry Andric   if (!IsUnion) {
356fe6060f1SDimitry Andric     NextOffset = std::max(NextOffset, Field.Offset);
3575ffd83dbSDimitry Andric   }
358e8d8bef9SDimitry Andric   AlignmentSize = std::max(AlignmentSize, FieldAlignmentSize);
3595ffd83dbSDimitry Andric   return Field;
3605ffd83dbSDimitry Andric }
3615ffd83dbSDimitry Andric 
3625ffd83dbSDimitry Andric /// The concrete assembly parser instance.
3635ffd83dbSDimitry Andric // Note that this is a full MCAsmParser, not an MCAsmParserExtension!
3645ffd83dbSDimitry Andric // It's a peer of AsmParser, not of COFFAsmParser, WasmAsmParser, etc.
3655ffd83dbSDimitry Andric class MasmParser : public MCAsmParser {
3665ffd83dbSDimitry Andric private:
3675ffd83dbSDimitry Andric   AsmLexer Lexer;
3685ffd83dbSDimitry Andric   MCContext &Ctx;
3695ffd83dbSDimitry Andric   MCStreamer &Out;
3705ffd83dbSDimitry Andric   const MCAsmInfo &MAI;
3715ffd83dbSDimitry Andric   SourceMgr &SrcMgr;
3725ffd83dbSDimitry Andric   SourceMgr::DiagHandlerTy SavedDiagHandler;
3735ffd83dbSDimitry Andric   void *SavedDiagContext;
3745ffd83dbSDimitry Andric   std::unique_ptr<MCAsmParserExtension> PlatformParser;
3755ffd83dbSDimitry Andric 
3765ffd83dbSDimitry Andric   /// This is the current buffer index we're lexing from as managed by the
3775ffd83dbSDimitry Andric   /// SourceMgr object.
3785ffd83dbSDimitry Andric   unsigned CurBuffer;
379fe6060f1SDimitry Andric 
380fe6060f1SDimitry Andric   /// time of assembly
381fe6060f1SDimitry Andric   struct tm TM;
382fe6060f1SDimitry Andric 
383*04eeddc0SDimitry Andric   BitVector EndStatementAtEOFStack;
3845ffd83dbSDimitry Andric 
3855ffd83dbSDimitry Andric   AsmCond TheCondState;
3865ffd83dbSDimitry Andric   std::vector<AsmCond> TheCondStack;
3875ffd83dbSDimitry Andric 
3885ffd83dbSDimitry Andric   /// maps directive names to handler methods in parser
3895ffd83dbSDimitry Andric   /// extensions. Extensions register themselves in this map by calling
3905ffd83dbSDimitry Andric   /// addDirectiveHandler.
3915ffd83dbSDimitry Andric   StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
3925ffd83dbSDimitry Andric 
3935ffd83dbSDimitry Andric   /// maps assembly-time variable names to variables.
3945ffd83dbSDimitry Andric   struct Variable {
395fe6060f1SDimitry Andric     enum RedefinableKind { NOT_REDEFINABLE, WARN_ON_REDEFINITION, REDEFINABLE };
396fe6060f1SDimitry Andric 
3975ffd83dbSDimitry Andric     StringRef Name;
398fe6060f1SDimitry Andric     RedefinableKind Redefinable = REDEFINABLE;
3995ffd83dbSDimitry Andric     bool IsText = false;
4005ffd83dbSDimitry Andric     std::string TextValue;
4015ffd83dbSDimitry Andric   };
4025ffd83dbSDimitry Andric   StringMap<Variable> Variables;
4035ffd83dbSDimitry Andric 
4045ffd83dbSDimitry Andric   /// Stack of active struct definitions.
4055ffd83dbSDimitry Andric   SmallVector<StructInfo, 1> StructInProgress;
4065ffd83dbSDimitry Andric 
4075ffd83dbSDimitry Andric   /// Maps struct tags to struct definitions.
4085ffd83dbSDimitry Andric   StringMap<StructInfo> Structs;
4095ffd83dbSDimitry Andric 
410e8d8bef9SDimitry Andric   /// Maps data location names to types.
411e8d8bef9SDimitry Andric   StringMap<AsmTypeInfo> KnownType;
4125ffd83dbSDimitry Andric 
4135ffd83dbSDimitry Andric   /// Stack of active macro instantiations.
4145ffd83dbSDimitry Andric   std::vector<MacroInstantiation*> ActiveMacros;
4155ffd83dbSDimitry Andric 
4165ffd83dbSDimitry Andric   /// List of bodies of anonymous macros.
4175ffd83dbSDimitry Andric   std::deque<MCAsmMacro> MacroLikeBodies;
4185ffd83dbSDimitry Andric 
4195ffd83dbSDimitry Andric   /// Keeps track of how many .macro's have been instantiated.
4205ffd83dbSDimitry Andric   unsigned NumOfMacroInstantiations;
4215ffd83dbSDimitry Andric 
4225ffd83dbSDimitry Andric   /// The values from the last parsed cpp hash file line comment if any.
4235ffd83dbSDimitry Andric   struct CppHashInfoTy {
4245ffd83dbSDimitry Andric     StringRef Filename;
4255ffd83dbSDimitry Andric     int64_t LineNumber;
4265ffd83dbSDimitry Andric     SMLoc Loc;
4275ffd83dbSDimitry Andric     unsigned Buf;
428*04eeddc0SDimitry Andric     CppHashInfoTy() : LineNumber(0), Buf(0) {}
4295ffd83dbSDimitry Andric   };
4305ffd83dbSDimitry Andric   CppHashInfoTy CppHashInfo;
4315ffd83dbSDimitry Andric 
4325ffd83dbSDimitry Andric   /// The filename from the first cpp hash file line comment, if any.
4335ffd83dbSDimitry Andric   StringRef FirstCppHashFilename;
4345ffd83dbSDimitry Andric 
4355ffd83dbSDimitry Andric   /// List of forward directional labels for diagnosis at the end.
4365ffd83dbSDimitry Andric   SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;
4375ffd83dbSDimitry Andric 
4385ffd83dbSDimitry Andric   /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
4395ffd83dbSDimitry Andric   /// Defaults to 1U, meaning Intel.
4405ffd83dbSDimitry Andric   unsigned AssemblerDialect = 1U;
4415ffd83dbSDimitry Andric 
4425ffd83dbSDimitry Andric   /// is Darwin compatibility enabled?
4435ffd83dbSDimitry Andric   bool IsDarwin = false;
4445ffd83dbSDimitry Andric 
4455ffd83dbSDimitry Andric   /// Are we parsing ms-style inline assembly?
4465ffd83dbSDimitry Andric   bool ParsingMSInlineAsm = false;
4475ffd83dbSDimitry Andric 
4485ffd83dbSDimitry Andric   /// Did we already inform the user about inconsistent MD5 usage?
4495ffd83dbSDimitry Andric   bool ReportedInconsistentMD5 = false;
4505ffd83dbSDimitry Andric 
4515ffd83dbSDimitry Andric   // Current <...> expression depth.
4525ffd83dbSDimitry Andric   unsigned AngleBracketDepth = 0U;
4535ffd83dbSDimitry Andric 
454e8d8bef9SDimitry Andric   // Number of locals defined.
455e8d8bef9SDimitry Andric   uint16_t LocalCounter = 0;
456e8d8bef9SDimitry Andric 
4575ffd83dbSDimitry Andric public:
4585ffd83dbSDimitry Andric   MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
459fe6060f1SDimitry Andric              const MCAsmInfo &MAI, struct tm TM, unsigned CB = 0);
4605ffd83dbSDimitry Andric   MasmParser(const MasmParser &) = delete;
4615ffd83dbSDimitry Andric   MasmParser &operator=(const MasmParser &) = delete;
4625ffd83dbSDimitry Andric   ~MasmParser() override;
4635ffd83dbSDimitry Andric 
4645ffd83dbSDimitry Andric   bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
4655ffd83dbSDimitry Andric 
4665ffd83dbSDimitry Andric   void addDirectiveHandler(StringRef Directive,
4675ffd83dbSDimitry Andric                            ExtensionDirectiveHandler Handler) override {
4685ffd83dbSDimitry Andric     ExtensionDirectiveMap[Directive] = Handler;
4695ffd83dbSDimitry Andric     if (DirectiveKindMap.find(Directive) == DirectiveKindMap.end()) {
4705ffd83dbSDimitry Andric       DirectiveKindMap[Directive] = DK_HANDLER_DIRECTIVE;
4715ffd83dbSDimitry Andric     }
4725ffd83dbSDimitry Andric   }
4735ffd83dbSDimitry Andric 
4745ffd83dbSDimitry Andric   void addAliasForDirective(StringRef Directive, StringRef Alias) override {
4755ffd83dbSDimitry Andric     DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
4765ffd83dbSDimitry Andric   }
4775ffd83dbSDimitry Andric 
4785ffd83dbSDimitry Andric   /// @name MCAsmParser Interface
4795ffd83dbSDimitry Andric   /// {
4805ffd83dbSDimitry Andric 
4815ffd83dbSDimitry Andric   SourceMgr &getSourceManager() override { return SrcMgr; }
4825ffd83dbSDimitry Andric   MCAsmLexer &getLexer() override { return Lexer; }
4835ffd83dbSDimitry Andric   MCContext &getContext() override { return Ctx; }
4845ffd83dbSDimitry Andric   MCStreamer &getStreamer() override { return Out; }
4855ffd83dbSDimitry Andric 
4865ffd83dbSDimitry Andric   CodeViewContext &getCVContext() { return Ctx.getCVContext(); }
4875ffd83dbSDimitry Andric 
4885ffd83dbSDimitry Andric   unsigned getAssemblerDialect() override {
4895ffd83dbSDimitry Andric     if (AssemblerDialect == ~0U)
4905ffd83dbSDimitry Andric       return MAI.getAssemblerDialect();
4915ffd83dbSDimitry Andric     else
4925ffd83dbSDimitry Andric       return AssemblerDialect;
4935ffd83dbSDimitry Andric   }
4945ffd83dbSDimitry Andric   void setAssemblerDialect(unsigned i) override {
4955ffd83dbSDimitry Andric     AssemblerDialect = i;
4965ffd83dbSDimitry Andric   }
4975ffd83dbSDimitry Andric 
4985ffd83dbSDimitry Andric   void Note(SMLoc L, const Twine &Msg, SMRange Range = None) override;
4995ffd83dbSDimitry Andric   bool Warning(SMLoc L, const Twine &Msg, SMRange Range = None) override;
5005ffd83dbSDimitry Andric   bool printError(SMLoc L, const Twine &Msg, SMRange Range = None) override;
5015ffd83dbSDimitry Andric 
502fe6060f1SDimitry Andric   enum ExpandKind { ExpandMacros, DoNotExpandMacros };
503fe6060f1SDimitry Andric   const AsmToken &Lex(ExpandKind ExpandNextToken);
504fe6060f1SDimitry Andric   const AsmToken &Lex() override { return Lex(ExpandMacros); }
5055ffd83dbSDimitry Andric 
5065ffd83dbSDimitry Andric   void setParsingMSInlineAsm(bool V) override {
5075ffd83dbSDimitry Andric     ParsingMSInlineAsm = V;
5085ffd83dbSDimitry Andric     // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
5095ffd83dbSDimitry Andric     // hex integer literals.
5105ffd83dbSDimitry Andric     Lexer.setLexMasmIntegers(V);
5115ffd83dbSDimitry Andric   }
5125ffd83dbSDimitry Andric   bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
5135ffd83dbSDimitry Andric 
5145ffd83dbSDimitry Andric   bool isParsingMasm() const override { return true; }
5155ffd83dbSDimitry Andric 
516e8d8bef9SDimitry Andric   bool defineMacro(StringRef Name, StringRef Value) override;
517e8d8bef9SDimitry Andric 
518e8d8bef9SDimitry Andric   bool lookUpField(StringRef Name, AsmFieldInfo &Info) const override;
519e8d8bef9SDimitry Andric   bool lookUpField(StringRef Base, StringRef Member,
520e8d8bef9SDimitry Andric                    AsmFieldInfo &Info) const override;
521e8d8bef9SDimitry Andric 
522e8d8bef9SDimitry Andric   bool lookUpType(StringRef Name, AsmTypeInfo &Info) const override;
5235ffd83dbSDimitry Andric 
524fe6060f1SDimitry Andric   bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs,
525fe6060f1SDimitry Andric                         unsigned &NumInputs,
5265ffd83dbSDimitry Andric                         SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5275ffd83dbSDimitry Andric                         SmallVectorImpl<std::string> &Constraints,
5285ffd83dbSDimitry Andric                         SmallVectorImpl<std::string> &Clobbers,
5295ffd83dbSDimitry Andric                         const MCInstrInfo *MII, const MCInstPrinter *IP,
5305ffd83dbSDimitry Andric                         MCAsmParserSemaCallback &SI) override;
5315ffd83dbSDimitry Andric 
5325ffd83dbSDimitry Andric   bool parseExpression(const MCExpr *&Res);
5335ffd83dbSDimitry Andric   bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
534e8d8bef9SDimitry Andric   bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
535e8d8bef9SDimitry Andric                         AsmTypeInfo *TypeInfo) override;
5365ffd83dbSDimitry Andric   bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
5375ffd83dbSDimitry Andric   bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
5385ffd83dbSDimitry Andric                              SMLoc &EndLoc) override;
5395ffd83dbSDimitry Andric   bool parseAbsoluteExpression(int64_t &Res) override;
5405ffd83dbSDimitry Andric 
5415ffd83dbSDimitry Andric   /// Parse a floating point expression using the float \p Semantics
5425ffd83dbSDimitry Andric   /// and set \p Res to the value.
5435ffd83dbSDimitry Andric   bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
5445ffd83dbSDimitry Andric 
5455ffd83dbSDimitry Andric   /// Parse an identifier or string (as a quoted identifier)
5465ffd83dbSDimitry Andric   /// and set \p Res to the identifier contents.
547fe6060f1SDimitry Andric   enum IdentifierPositionKind { StandardPosition, StartOfStatement };
548fe6060f1SDimitry Andric   bool parseIdentifier(StringRef &Res, IdentifierPositionKind Position);
549fe6060f1SDimitry Andric   bool parseIdentifier(StringRef &Res) override {
550fe6060f1SDimitry Andric     return parseIdentifier(Res, StandardPosition);
551fe6060f1SDimitry Andric   }
5525ffd83dbSDimitry Andric   void eatToEndOfStatement() override;
5535ffd83dbSDimitry Andric 
5545ffd83dbSDimitry Andric   bool checkForValidSection() override;
5555ffd83dbSDimitry Andric 
5565ffd83dbSDimitry Andric   /// }
5575ffd83dbSDimitry Andric 
5585ffd83dbSDimitry Andric private:
559fe6060f1SDimitry Andric   bool expandMacros();
560fe6060f1SDimitry Andric   const AsmToken peekTok(bool ShouldSkipSpace = true);
561fe6060f1SDimitry Andric 
5625ffd83dbSDimitry Andric   bool parseStatement(ParseStatementInfo &Info,
5635ffd83dbSDimitry Andric                       MCAsmParserSemaCallback *SI);
5645ffd83dbSDimitry Andric   bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
5655ffd83dbSDimitry Andric   bool parseCppHashLineFilenameComment(SMLoc L);
5665ffd83dbSDimitry Andric 
5675ffd83dbSDimitry Andric   bool expandMacro(raw_svector_ostream &OS, StringRef Body,
5685ffd83dbSDimitry Andric                    ArrayRef<MCAsmMacroParameter> Parameters,
569e8d8bef9SDimitry Andric                    ArrayRef<MCAsmMacroArgument> A,
570e8d8bef9SDimitry Andric                    const std::vector<std::string> &Locals, SMLoc L);
5715ffd83dbSDimitry Andric 
5725ffd83dbSDimitry Andric   /// Are we inside a macro instantiation?
5735ffd83dbSDimitry Andric   bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
5745ffd83dbSDimitry Andric 
5755ffd83dbSDimitry Andric   /// Handle entry to macro instantiation.
5765ffd83dbSDimitry Andric   ///
5775ffd83dbSDimitry Andric   /// \param M The macro.
5785ffd83dbSDimitry Andric   /// \param NameLoc Instantiation location.
579e8d8bef9SDimitry Andric   bool handleMacroEntry(
580e8d8bef9SDimitry Andric       const MCAsmMacro *M, SMLoc NameLoc,
581e8d8bef9SDimitry Andric       AsmToken::TokenKind ArgumentEndTok = AsmToken::EndOfStatement);
582e8d8bef9SDimitry Andric 
583e8d8bef9SDimitry Andric   /// Handle invocation of macro function.
584e8d8bef9SDimitry Andric   ///
585e8d8bef9SDimitry Andric   /// \param M The macro.
586e8d8bef9SDimitry Andric   /// \param NameLoc Invocation location.
587e8d8bef9SDimitry Andric   bool handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc);
5885ffd83dbSDimitry Andric 
5895ffd83dbSDimitry Andric   /// Handle exit from macro instantiation.
5905ffd83dbSDimitry Andric   void handleMacroExit();
5915ffd83dbSDimitry Andric 
5925ffd83dbSDimitry Andric   /// Extract AsmTokens for a macro argument.
593e8d8bef9SDimitry Andric   bool
594e8d8bef9SDimitry Andric   parseMacroArgument(const MCAsmMacroParameter *MP, MCAsmMacroArgument &MA,
595e8d8bef9SDimitry Andric                      AsmToken::TokenKind EndTok = AsmToken::EndOfStatement);
5965ffd83dbSDimitry Andric 
5975ffd83dbSDimitry Andric   /// Parse all macro arguments for a given macro.
598e8d8bef9SDimitry Andric   bool
599e8d8bef9SDimitry Andric   parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A,
600e8d8bef9SDimitry Andric                       AsmToken::TokenKind EndTok = AsmToken::EndOfStatement);
6015ffd83dbSDimitry Andric 
6025ffd83dbSDimitry Andric   void printMacroInstantiations();
603e8d8bef9SDimitry Andric 
604e8d8bef9SDimitry Andric   bool expandStatement(SMLoc Loc);
605e8d8bef9SDimitry Andric 
6065ffd83dbSDimitry Andric   void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
6075ffd83dbSDimitry Andric                     SMRange Range = None) const {
6085ffd83dbSDimitry Andric     ArrayRef<SMRange> Ranges(Range);
6095ffd83dbSDimitry Andric     SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
6105ffd83dbSDimitry Andric   }
6115ffd83dbSDimitry Andric   static void DiagHandler(const SMDiagnostic &Diag, void *Context);
6125ffd83dbSDimitry Andric 
6135ffd83dbSDimitry Andric   bool lookUpField(const StructInfo &Structure, StringRef Member,
614e8d8bef9SDimitry Andric                    AsmFieldInfo &Info) const;
6155ffd83dbSDimitry Andric 
6165ffd83dbSDimitry Andric   /// Should we emit DWARF describing this assembler source?  (Returns false if
6175ffd83dbSDimitry Andric   /// the source has .file directives, which means we don't want to generate
6185ffd83dbSDimitry Andric   /// info describing the assembler source itself.)
6195ffd83dbSDimitry Andric   bool enabledGenDwarfForAssembly();
6205ffd83dbSDimitry Andric 
6215ffd83dbSDimitry Andric   /// Enter the specified file. This returns true on failure.
6225ffd83dbSDimitry Andric   bool enterIncludeFile(const std::string &Filename);
6235ffd83dbSDimitry Andric 
6245ffd83dbSDimitry Andric   /// Reset the current lexer position to that given by \p Loc. The
6255ffd83dbSDimitry Andric   /// current token is not set; clients should ensure Lex() is called
6265ffd83dbSDimitry Andric   /// subsequently.
6275ffd83dbSDimitry Andric   ///
6285ffd83dbSDimitry Andric   /// \param InBuffer If not 0, should be the known buffer id that contains the
6295ffd83dbSDimitry Andric   /// location.
630e8d8bef9SDimitry Andric   void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0,
631e8d8bef9SDimitry Andric                  bool EndStatementAtEOF = true);
6325ffd83dbSDimitry Andric 
633e8d8bef9SDimitry Andric   /// Parse up to a token of kind \p EndTok and return the contents from the
634e8d8bef9SDimitry Andric   /// current token up to (but not including) this token; the current token on
635e8d8bef9SDimitry Andric   /// exit will be either this kind or EOF. Reads through instantiated macro
636e8d8bef9SDimitry Andric   /// functions and text macros.
637e8d8bef9SDimitry Andric   SmallVector<StringRef, 1> parseStringRefsTo(AsmToken::TokenKind EndTok);
638e8d8bef9SDimitry Andric   std::string parseStringTo(AsmToken::TokenKind EndTok);
639e8d8bef9SDimitry Andric 
640e8d8bef9SDimitry Andric   /// Parse up to the end of statement and return the contents from the current
641e8d8bef9SDimitry Andric   /// token until the end of the statement; the current token on exit will be
642e8d8bef9SDimitry Andric   /// either the EndOfStatement or EOF.
6435ffd83dbSDimitry Andric   StringRef parseStringToEndOfStatement() override;
6445ffd83dbSDimitry Andric 
6455ffd83dbSDimitry Andric   bool parseTextItem(std::string &Data);
6465ffd83dbSDimitry Andric 
6475ffd83dbSDimitry Andric   unsigned getBinOpPrecedence(AsmToken::TokenKind K,
6485ffd83dbSDimitry Andric                               MCBinaryExpr::Opcode &Kind);
6495ffd83dbSDimitry Andric 
6505ffd83dbSDimitry Andric   bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
6515ffd83dbSDimitry Andric   bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
6525ffd83dbSDimitry Andric   bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
6535ffd83dbSDimitry Andric 
6545ffd83dbSDimitry Andric   bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc);
6555ffd83dbSDimitry Andric 
6565ffd83dbSDimitry Andric   bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName);
6575ffd83dbSDimitry Andric   bool parseCVFileId(int64_t &FileId, StringRef DirectiveName);
6585ffd83dbSDimitry Andric 
6595ffd83dbSDimitry Andric   // Generic (target and platform independent) directive parsing.
6605ffd83dbSDimitry Andric   enum DirectiveKind {
6615ffd83dbSDimitry Andric     DK_NO_DIRECTIVE, // Placeholder
6625ffd83dbSDimitry Andric     DK_HANDLER_DIRECTIVE,
6635ffd83dbSDimitry Andric     DK_ASSIGN,
6645ffd83dbSDimitry Andric     DK_EQU,
6655ffd83dbSDimitry Andric     DK_TEXTEQU,
6665ffd83dbSDimitry Andric     DK_ASCII,
6675ffd83dbSDimitry Andric     DK_ASCIZ,
6685ffd83dbSDimitry Andric     DK_STRING,
6695ffd83dbSDimitry Andric     DK_BYTE,
6705ffd83dbSDimitry Andric     DK_SBYTE,
6715ffd83dbSDimitry Andric     DK_WORD,
6725ffd83dbSDimitry Andric     DK_SWORD,
6735ffd83dbSDimitry Andric     DK_DWORD,
6745ffd83dbSDimitry Andric     DK_SDWORD,
6755ffd83dbSDimitry Andric     DK_FWORD,
6765ffd83dbSDimitry Andric     DK_QWORD,
6775ffd83dbSDimitry Andric     DK_SQWORD,
6785ffd83dbSDimitry Andric     DK_DB,
6795ffd83dbSDimitry Andric     DK_DD,
680e8d8bef9SDimitry Andric     DK_DF,
6815ffd83dbSDimitry Andric     DK_DQ,
6825ffd83dbSDimitry Andric     DK_DW,
6835ffd83dbSDimitry Andric     DK_REAL4,
6845ffd83dbSDimitry Andric     DK_REAL8,
685e8d8bef9SDimitry Andric     DK_REAL10,
6865ffd83dbSDimitry Andric     DK_ALIGN,
687fe6060f1SDimitry Andric     DK_EVEN,
6885ffd83dbSDimitry Andric     DK_ORG,
6895ffd83dbSDimitry Andric     DK_ENDR,
6905ffd83dbSDimitry Andric     DK_EXTERN,
6915ffd83dbSDimitry Andric     DK_PUBLIC,
6925ffd83dbSDimitry Andric     DK_COMM,
6935ffd83dbSDimitry Andric     DK_COMMENT,
6945ffd83dbSDimitry Andric     DK_INCLUDE,
695e8d8bef9SDimitry Andric     DK_REPEAT,
696e8d8bef9SDimitry Andric     DK_WHILE,
697e8d8bef9SDimitry Andric     DK_FOR,
698e8d8bef9SDimitry Andric     DK_FORC,
6995ffd83dbSDimitry Andric     DK_IF,
7005ffd83dbSDimitry Andric     DK_IFE,
7015ffd83dbSDimitry Andric     DK_IFB,
7025ffd83dbSDimitry Andric     DK_IFNB,
7035ffd83dbSDimitry Andric     DK_IFDEF,
7045ffd83dbSDimitry Andric     DK_IFNDEF,
7055ffd83dbSDimitry Andric     DK_IFDIF,
7065ffd83dbSDimitry Andric     DK_IFDIFI,
7075ffd83dbSDimitry Andric     DK_IFIDN,
7085ffd83dbSDimitry Andric     DK_IFIDNI,
7095ffd83dbSDimitry Andric     DK_ELSEIF,
7105ffd83dbSDimitry Andric     DK_ELSEIFE,
7115ffd83dbSDimitry Andric     DK_ELSEIFB,
7125ffd83dbSDimitry Andric     DK_ELSEIFNB,
7135ffd83dbSDimitry Andric     DK_ELSEIFDEF,
7145ffd83dbSDimitry Andric     DK_ELSEIFNDEF,
7155ffd83dbSDimitry Andric     DK_ELSEIFDIF,
7165ffd83dbSDimitry Andric     DK_ELSEIFDIFI,
7175ffd83dbSDimitry Andric     DK_ELSEIFIDN,
7185ffd83dbSDimitry Andric     DK_ELSEIFIDNI,
7195ffd83dbSDimitry Andric     DK_ELSE,
7205ffd83dbSDimitry Andric     DK_ENDIF,
7215ffd83dbSDimitry Andric     DK_FILE,
7225ffd83dbSDimitry Andric     DK_LINE,
7235ffd83dbSDimitry Andric     DK_LOC,
7245ffd83dbSDimitry Andric     DK_STABS,
7255ffd83dbSDimitry Andric     DK_CV_FILE,
7265ffd83dbSDimitry Andric     DK_CV_FUNC_ID,
7275ffd83dbSDimitry Andric     DK_CV_INLINE_SITE_ID,
7285ffd83dbSDimitry Andric     DK_CV_LOC,
7295ffd83dbSDimitry Andric     DK_CV_LINETABLE,
7305ffd83dbSDimitry Andric     DK_CV_INLINE_LINETABLE,
7315ffd83dbSDimitry Andric     DK_CV_DEF_RANGE,
7325ffd83dbSDimitry Andric     DK_CV_STRINGTABLE,
7335ffd83dbSDimitry Andric     DK_CV_STRING,
7345ffd83dbSDimitry Andric     DK_CV_FILECHECKSUMS,
7355ffd83dbSDimitry Andric     DK_CV_FILECHECKSUM_OFFSET,
7365ffd83dbSDimitry Andric     DK_CV_FPO_DATA,
7375ffd83dbSDimitry Andric     DK_CFI_SECTIONS,
7385ffd83dbSDimitry Andric     DK_CFI_STARTPROC,
7395ffd83dbSDimitry Andric     DK_CFI_ENDPROC,
7405ffd83dbSDimitry Andric     DK_CFI_DEF_CFA,
7415ffd83dbSDimitry Andric     DK_CFI_DEF_CFA_OFFSET,
7425ffd83dbSDimitry Andric     DK_CFI_ADJUST_CFA_OFFSET,
7435ffd83dbSDimitry Andric     DK_CFI_DEF_CFA_REGISTER,
7445ffd83dbSDimitry Andric     DK_CFI_OFFSET,
7455ffd83dbSDimitry Andric     DK_CFI_REL_OFFSET,
7465ffd83dbSDimitry Andric     DK_CFI_PERSONALITY,
7475ffd83dbSDimitry Andric     DK_CFI_LSDA,
7485ffd83dbSDimitry Andric     DK_CFI_REMEMBER_STATE,
7495ffd83dbSDimitry Andric     DK_CFI_RESTORE_STATE,
7505ffd83dbSDimitry Andric     DK_CFI_SAME_VALUE,
7515ffd83dbSDimitry Andric     DK_CFI_RESTORE,
7525ffd83dbSDimitry Andric     DK_CFI_ESCAPE,
7535ffd83dbSDimitry Andric     DK_CFI_RETURN_COLUMN,
7545ffd83dbSDimitry Andric     DK_CFI_SIGNAL_FRAME,
7555ffd83dbSDimitry Andric     DK_CFI_UNDEFINED,
7565ffd83dbSDimitry Andric     DK_CFI_REGISTER,
7575ffd83dbSDimitry Andric     DK_CFI_WINDOW_SAVE,
7585ffd83dbSDimitry Andric     DK_CFI_B_KEY_FRAME,
7595ffd83dbSDimitry Andric     DK_MACRO,
7605ffd83dbSDimitry Andric     DK_EXITM,
7615ffd83dbSDimitry Andric     DK_ENDM,
762e8d8bef9SDimitry Andric     DK_PURGE,
7635ffd83dbSDimitry Andric     DK_ERR,
7645ffd83dbSDimitry Andric     DK_ERRB,
7655ffd83dbSDimitry Andric     DK_ERRNB,
7665ffd83dbSDimitry Andric     DK_ERRDEF,
7675ffd83dbSDimitry Andric     DK_ERRNDEF,
7685ffd83dbSDimitry Andric     DK_ERRDIF,
7695ffd83dbSDimitry Andric     DK_ERRDIFI,
7705ffd83dbSDimitry Andric     DK_ERRIDN,
7715ffd83dbSDimitry Andric     DK_ERRIDNI,
7725ffd83dbSDimitry Andric     DK_ERRE,
7735ffd83dbSDimitry Andric     DK_ERRNZ,
7745ffd83dbSDimitry Andric     DK_ECHO,
7755ffd83dbSDimitry Andric     DK_STRUCT,
7765ffd83dbSDimitry Andric     DK_UNION,
7775ffd83dbSDimitry Andric     DK_ENDS,
778e8d8bef9SDimitry Andric     DK_END,
779e8d8bef9SDimitry Andric     DK_PUSHFRAME,
780e8d8bef9SDimitry Andric     DK_PUSHREG,
781e8d8bef9SDimitry Andric     DK_SAVEREG,
782e8d8bef9SDimitry Andric     DK_SAVEXMM128,
783e8d8bef9SDimitry Andric     DK_SETFRAME,
784e8d8bef9SDimitry Andric     DK_RADIX,
7855ffd83dbSDimitry Andric   };
7865ffd83dbSDimitry Andric 
7875ffd83dbSDimitry Andric   /// Maps directive name --> DirectiveKind enum, for directives parsed by this
7885ffd83dbSDimitry Andric   /// class.
7895ffd83dbSDimitry Andric   StringMap<DirectiveKind> DirectiveKindMap;
7905ffd83dbSDimitry Andric 
791e8d8bef9SDimitry Andric   bool isMacroLikeDirective();
792e8d8bef9SDimitry Andric 
7935ffd83dbSDimitry Andric   // Codeview def_range type parsing.
7945ffd83dbSDimitry Andric   enum CVDefRangeType {
7955ffd83dbSDimitry Andric     CVDR_DEFRANGE = 0, // Placeholder
7965ffd83dbSDimitry Andric     CVDR_DEFRANGE_REGISTER,
7975ffd83dbSDimitry Andric     CVDR_DEFRANGE_FRAMEPOINTER_REL,
7985ffd83dbSDimitry Andric     CVDR_DEFRANGE_SUBFIELD_REGISTER,
7995ffd83dbSDimitry Andric     CVDR_DEFRANGE_REGISTER_REL
8005ffd83dbSDimitry Andric   };
8015ffd83dbSDimitry Andric 
8025ffd83dbSDimitry Andric   /// Maps Codeview def_range types --> CVDefRangeType enum, for Codeview
8035ffd83dbSDimitry Andric   /// def_range types parsed by this class.
8045ffd83dbSDimitry Andric   StringMap<CVDefRangeType> CVDefRangeTypeMap;
8055ffd83dbSDimitry Andric 
806fe6060f1SDimitry Andric   // Generic (target and platform independent) directive parsing.
807fe6060f1SDimitry Andric   enum BuiltinSymbol {
808fe6060f1SDimitry Andric     BI_NO_SYMBOL, // Placeholder
809fe6060f1SDimitry Andric     BI_DATE,
810fe6060f1SDimitry Andric     BI_TIME,
811fe6060f1SDimitry Andric     BI_VERSION,
812fe6060f1SDimitry Andric     BI_FILECUR,
813fe6060f1SDimitry Andric     BI_FILENAME,
814fe6060f1SDimitry Andric     BI_LINE,
815fe6060f1SDimitry Andric     BI_CURSEG,
816fe6060f1SDimitry Andric     BI_CPU,
817fe6060f1SDimitry Andric     BI_INTERFACE,
818fe6060f1SDimitry Andric     BI_CODE,
819fe6060f1SDimitry Andric     BI_DATA,
820fe6060f1SDimitry Andric     BI_FARDATA,
821fe6060f1SDimitry Andric     BI_WORDSIZE,
822fe6060f1SDimitry Andric     BI_CODESIZE,
823fe6060f1SDimitry Andric     BI_DATASIZE,
824fe6060f1SDimitry Andric     BI_MODEL,
825fe6060f1SDimitry Andric     BI_STACK,
826fe6060f1SDimitry Andric   };
827fe6060f1SDimitry Andric 
828fe6060f1SDimitry Andric   /// Maps builtin name --> BuiltinSymbol enum, for builtins handled by this
829fe6060f1SDimitry Andric   /// class.
830fe6060f1SDimitry Andric   StringMap<BuiltinSymbol> BuiltinSymbolMap;
831fe6060f1SDimitry Andric 
832fe6060f1SDimitry Andric   const MCExpr *evaluateBuiltinValue(BuiltinSymbol Symbol, SMLoc StartLoc);
833fe6060f1SDimitry Andric 
834fe6060f1SDimitry Andric   llvm::Optional<std::string> evaluateBuiltinTextMacro(BuiltinSymbol Symbol,
835fe6060f1SDimitry Andric                                                        SMLoc StartLoc);
836fe6060f1SDimitry Andric 
8375ffd83dbSDimitry Andric   // ".ascii", ".asciz", ".string"
8385ffd83dbSDimitry Andric   bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
8395ffd83dbSDimitry Andric 
8405ffd83dbSDimitry Andric   // "byte", "word", ...
8415ffd83dbSDimitry Andric   bool emitIntValue(const MCExpr *Value, unsigned Size);
8425ffd83dbSDimitry Andric   bool parseScalarInitializer(unsigned Size,
8435ffd83dbSDimitry Andric                               SmallVectorImpl<const MCExpr *> &Values,
8445ffd83dbSDimitry Andric                               unsigned StringPadLength = 0);
8455ffd83dbSDimitry Andric   bool parseScalarInstList(
8465ffd83dbSDimitry Andric       unsigned Size, SmallVectorImpl<const MCExpr *> &Values,
8475ffd83dbSDimitry Andric       const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
848e8d8bef9SDimitry Andric   bool emitIntegralValues(unsigned Size, unsigned *Count = nullptr);
8495ffd83dbSDimitry Andric   bool addIntegralField(StringRef Name, unsigned Size);
8505ffd83dbSDimitry Andric   bool parseDirectiveValue(StringRef IDVal, unsigned Size);
851e8d8bef9SDimitry Andric   bool parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
852e8d8bef9SDimitry Andric                                 StringRef Name, SMLoc NameLoc);
8535ffd83dbSDimitry Andric 
854e8d8bef9SDimitry Andric   // "real4", "real8", "real10"
855e8d8bef9SDimitry Andric   bool emitRealValues(const fltSemantics &Semantics, unsigned *Count = nullptr);
856e8d8bef9SDimitry Andric   bool addRealField(StringRef Name, const fltSemantics &Semantics, size_t Size);
857e8d8bef9SDimitry Andric   bool parseDirectiveRealValue(StringRef IDVal, const fltSemantics &Semantics,
858e8d8bef9SDimitry Andric                                size_t Size);
8595ffd83dbSDimitry Andric   bool parseRealInstList(
8605ffd83dbSDimitry Andric       const fltSemantics &Semantics, SmallVectorImpl<APInt> &Values,
8615ffd83dbSDimitry Andric       const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
862e8d8bef9SDimitry Andric   bool parseDirectiveNamedRealValue(StringRef TypeName,
8635ffd83dbSDimitry Andric                                     const fltSemantics &Semantics,
864e8d8bef9SDimitry Andric                                     unsigned Size, StringRef Name,
865e8d8bef9SDimitry Andric                                     SMLoc NameLoc);
8665ffd83dbSDimitry Andric 
8675ffd83dbSDimitry Andric   bool parseOptionalAngleBracketOpen();
8685ffd83dbSDimitry Andric   bool parseAngleBracketClose(const Twine &Msg = "expected '>'");
8695ffd83dbSDimitry Andric 
8705ffd83dbSDimitry Andric   bool parseFieldInitializer(const FieldInfo &Field,
8715ffd83dbSDimitry Andric                              FieldInitializer &Initializer);
8725ffd83dbSDimitry Andric   bool parseFieldInitializer(const FieldInfo &Field,
8735ffd83dbSDimitry Andric                              const IntFieldInfo &Contents,
8745ffd83dbSDimitry Andric                              FieldInitializer &Initializer);
8755ffd83dbSDimitry Andric   bool parseFieldInitializer(const FieldInfo &Field,
8765ffd83dbSDimitry Andric                              const RealFieldInfo &Contents,
8775ffd83dbSDimitry Andric                              FieldInitializer &Initializer);
8785ffd83dbSDimitry Andric   bool parseFieldInitializer(const FieldInfo &Field,
8795ffd83dbSDimitry Andric                              const StructFieldInfo &Contents,
8805ffd83dbSDimitry Andric                              FieldInitializer &Initializer);
8815ffd83dbSDimitry Andric 
8825ffd83dbSDimitry Andric   bool parseStructInitializer(const StructInfo &Structure,
8835ffd83dbSDimitry Andric                               StructInitializer &Initializer);
8845ffd83dbSDimitry Andric   bool parseStructInstList(
8855ffd83dbSDimitry Andric       const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
8865ffd83dbSDimitry Andric       const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
8875ffd83dbSDimitry Andric 
8885ffd83dbSDimitry Andric   bool emitFieldValue(const FieldInfo &Field);
8895ffd83dbSDimitry Andric   bool emitFieldValue(const FieldInfo &Field, const IntFieldInfo &Contents);
8905ffd83dbSDimitry Andric   bool emitFieldValue(const FieldInfo &Field, const RealFieldInfo &Contents);
8915ffd83dbSDimitry Andric   bool emitFieldValue(const FieldInfo &Field, const StructFieldInfo &Contents);
8925ffd83dbSDimitry Andric 
8935ffd83dbSDimitry Andric   bool emitFieldInitializer(const FieldInfo &Field,
8945ffd83dbSDimitry Andric                             const FieldInitializer &Initializer);
8955ffd83dbSDimitry Andric   bool emitFieldInitializer(const FieldInfo &Field,
8965ffd83dbSDimitry Andric                             const IntFieldInfo &Contents,
8975ffd83dbSDimitry Andric                             const IntFieldInfo &Initializer);
8985ffd83dbSDimitry Andric   bool emitFieldInitializer(const FieldInfo &Field,
8995ffd83dbSDimitry Andric                             const RealFieldInfo &Contents,
9005ffd83dbSDimitry Andric                             const RealFieldInfo &Initializer);
9015ffd83dbSDimitry Andric   bool emitFieldInitializer(const FieldInfo &Field,
9025ffd83dbSDimitry Andric                             const StructFieldInfo &Contents,
9035ffd83dbSDimitry Andric                             const StructFieldInfo &Initializer);
9045ffd83dbSDimitry Andric 
9055ffd83dbSDimitry Andric   bool emitStructInitializer(const StructInfo &Structure,
9065ffd83dbSDimitry Andric                              const StructInitializer &Initializer);
9075ffd83dbSDimitry Andric 
9085ffd83dbSDimitry Andric   // User-defined types (structs, unions):
909e8d8bef9SDimitry Andric   bool emitStructValues(const StructInfo &Structure, unsigned *Count = nullptr);
9105ffd83dbSDimitry Andric   bool addStructField(StringRef Name, const StructInfo &Structure);
9115ffd83dbSDimitry Andric   bool parseDirectiveStructValue(const StructInfo &Structure,
9125ffd83dbSDimitry Andric                                  StringRef Directive, SMLoc DirLoc);
9135ffd83dbSDimitry Andric   bool parseDirectiveNamedStructValue(const StructInfo &Structure,
9145ffd83dbSDimitry Andric                                       StringRef Directive, SMLoc DirLoc,
9155ffd83dbSDimitry Andric                                       StringRef Name);
9165ffd83dbSDimitry Andric 
9175ffd83dbSDimitry Andric   // "=", "equ", "textequ"
9185ffd83dbSDimitry Andric   bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
919fe6060f1SDimitry Andric                             DirectiveKind DirKind, SMLoc NameLoc);
9205ffd83dbSDimitry Andric 
921fe6060f1SDimitry Andric   bool parseDirectiveOrg(); // "org"
922fe6060f1SDimitry Andric 
923fe6060f1SDimitry Andric   bool emitAlignTo(int64_t Alignment);
9245ffd83dbSDimitry Andric   bool parseDirectiveAlign();  // "align"
925fe6060f1SDimitry Andric   bool parseDirectiveEven();   // "even"
9265ffd83dbSDimitry Andric 
9275ffd83dbSDimitry Andric   // ".file", ".line", ".loc", ".stabs"
9285ffd83dbSDimitry Andric   bool parseDirectiveFile(SMLoc DirectiveLoc);
9295ffd83dbSDimitry Andric   bool parseDirectiveLine();
9305ffd83dbSDimitry Andric   bool parseDirectiveLoc();
9315ffd83dbSDimitry Andric   bool parseDirectiveStabs();
9325ffd83dbSDimitry Andric 
9335ffd83dbSDimitry Andric   // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
9345ffd83dbSDimitry Andric   // ".cv_inline_linetable", ".cv_def_range", ".cv_string"
9355ffd83dbSDimitry Andric   bool parseDirectiveCVFile();
9365ffd83dbSDimitry Andric   bool parseDirectiveCVFuncId();
9375ffd83dbSDimitry Andric   bool parseDirectiveCVInlineSiteId();
9385ffd83dbSDimitry Andric   bool parseDirectiveCVLoc();
9395ffd83dbSDimitry Andric   bool parseDirectiveCVLinetable();
9405ffd83dbSDimitry Andric   bool parseDirectiveCVInlineLinetable();
9415ffd83dbSDimitry Andric   bool parseDirectiveCVDefRange();
9425ffd83dbSDimitry Andric   bool parseDirectiveCVString();
9435ffd83dbSDimitry Andric   bool parseDirectiveCVStringTable();
9445ffd83dbSDimitry Andric   bool parseDirectiveCVFileChecksums();
9455ffd83dbSDimitry Andric   bool parseDirectiveCVFileChecksumOffset();
9465ffd83dbSDimitry Andric   bool parseDirectiveCVFPOData();
9475ffd83dbSDimitry Andric 
9485ffd83dbSDimitry Andric   // .cfi directives
9495ffd83dbSDimitry Andric   bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
9505ffd83dbSDimitry Andric   bool parseDirectiveCFIWindowSave();
9515ffd83dbSDimitry Andric   bool parseDirectiveCFISections();
9525ffd83dbSDimitry Andric   bool parseDirectiveCFIStartProc();
9535ffd83dbSDimitry Andric   bool parseDirectiveCFIEndProc();
9545ffd83dbSDimitry Andric   bool parseDirectiveCFIDefCfaOffset();
9555ffd83dbSDimitry Andric   bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
9565ffd83dbSDimitry Andric   bool parseDirectiveCFIAdjustCfaOffset();
9575ffd83dbSDimitry Andric   bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
9585ffd83dbSDimitry Andric   bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);
9595ffd83dbSDimitry Andric   bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
9605ffd83dbSDimitry Andric   bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
9615ffd83dbSDimitry Andric   bool parseDirectiveCFIRememberState();
9625ffd83dbSDimitry Andric   bool parseDirectiveCFIRestoreState();
9635ffd83dbSDimitry Andric   bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
9645ffd83dbSDimitry Andric   bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
9655ffd83dbSDimitry Andric   bool parseDirectiveCFIEscape();
9665ffd83dbSDimitry Andric   bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
9675ffd83dbSDimitry Andric   bool parseDirectiveCFISignalFrame();
9685ffd83dbSDimitry Andric   bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
9695ffd83dbSDimitry Andric 
9705ffd83dbSDimitry Andric   // macro directives
9715ffd83dbSDimitry Andric   bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
972e8d8bef9SDimitry Andric   bool parseDirectiveExitMacro(SMLoc DirectiveLoc, StringRef Directive,
973e8d8bef9SDimitry Andric                                std::string &Value);
9745ffd83dbSDimitry Andric   bool parseDirectiveEndMacro(StringRef Directive);
975e8d8bef9SDimitry Andric   bool parseDirectiveMacro(StringRef Name, SMLoc NameLoc);
9765ffd83dbSDimitry Andric 
9775ffd83dbSDimitry Andric   bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind,
9785ffd83dbSDimitry Andric                             StringRef Name, SMLoc NameLoc);
9795ffd83dbSDimitry Andric   bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind);
9805ffd83dbSDimitry Andric   bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
9815ffd83dbSDimitry Andric   bool parseDirectiveNestedEnds();
9825ffd83dbSDimitry Andric 
9835ffd83dbSDimitry Andric   /// Parse a directive like ".globl" which accepts a single symbol (which
9845ffd83dbSDimitry Andric   /// should be a label or an external).
9855ffd83dbSDimitry Andric   bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
9865ffd83dbSDimitry Andric 
9875ffd83dbSDimitry Andric   bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
9885ffd83dbSDimitry Andric 
9895ffd83dbSDimitry Andric   bool parseDirectiveComment(SMLoc DirectiveLoc); // "comment"
9905ffd83dbSDimitry Andric 
9915ffd83dbSDimitry Andric   bool parseDirectiveInclude(); // "include"
9925ffd83dbSDimitry Andric 
9935ffd83dbSDimitry Andric   // "if" or "ife"
9945ffd83dbSDimitry Andric   bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
9955ffd83dbSDimitry Andric   // "ifb" or "ifnb", depending on ExpectBlank.
9965ffd83dbSDimitry Andric   bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
9975ffd83dbSDimitry Andric   // "ifidn", "ifdif", "ifidni", or "ifdifi", depending on ExpectEqual and
9985ffd83dbSDimitry Andric   // CaseInsensitive.
9995ffd83dbSDimitry Andric   bool parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
10005ffd83dbSDimitry Andric                            bool CaseInsensitive);
10015ffd83dbSDimitry Andric   // "ifdef" or "ifndef", depending on expect_defined
10025ffd83dbSDimitry Andric   bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
10035ffd83dbSDimitry Andric   // "elseif" or "elseife"
10045ffd83dbSDimitry Andric   bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
10055ffd83dbSDimitry Andric   // "elseifb" or "elseifnb", depending on ExpectBlank.
10065ffd83dbSDimitry Andric   bool parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank);
10075ffd83dbSDimitry Andric   // ".elseifdef" or ".elseifndef", depending on expect_defined
10085ffd83dbSDimitry Andric   bool parseDirectiveElseIfdef(SMLoc DirectiveLoc, bool expect_defined);
10095ffd83dbSDimitry Andric   // "elseifidn", "elseifdif", "elseifidni", or "elseifdifi", depending on
10105ffd83dbSDimitry Andric   // ExpectEqual and CaseInsensitive.
10115ffd83dbSDimitry Andric   bool parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
10125ffd83dbSDimitry Andric                                bool CaseInsensitive);
10135ffd83dbSDimitry Andric   bool parseDirectiveElse(SMLoc DirectiveLoc);   // "else"
10145ffd83dbSDimitry Andric   bool parseDirectiveEndIf(SMLoc DirectiveLoc);  // "endif"
10155ffd83dbSDimitry Andric   bool parseEscapedString(std::string &Data) override;
10165ffd83dbSDimitry Andric   bool parseAngleBracketString(std::string &Data) override;
10175ffd83dbSDimitry Andric 
10185ffd83dbSDimitry Andric   // Macro-like directives
10195ffd83dbSDimitry Andric   MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
10205ffd83dbSDimitry Andric   void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
10215ffd83dbSDimitry Andric                                 raw_svector_ostream &OS);
1022e8d8bef9SDimitry Andric   void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
1023e8d8bef9SDimitry Andric                                 SMLoc ExitLoc, raw_svector_ostream &OS);
1024e8d8bef9SDimitry Andric   bool parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Directive);
1025e8d8bef9SDimitry Andric   bool parseDirectiveFor(SMLoc DirectiveLoc, StringRef Directive);
1026e8d8bef9SDimitry Andric   bool parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive);
1027e8d8bef9SDimitry Andric   bool parseDirectiveWhile(SMLoc DirectiveLoc);
10285ffd83dbSDimitry Andric 
10295ffd83dbSDimitry Andric   // "_emit" or "__emit"
10305ffd83dbSDimitry Andric   bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
10315ffd83dbSDimitry Andric                             size_t Len);
10325ffd83dbSDimitry Andric 
10335ffd83dbSDimitry Andric   // "align"
10345ffd83dbSDimitry Andric   bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
10355ffd83dbSDimitry Andric 
10365ffd83dbSDimitry Andric   // "end"
10375ffd83dbSDimitry Andric   bool parseDirectiveEnd(SMLoc DirectiveLoc);
10385ffd83dbSDimitry Andric 
10395ffd83dbSDimitry Andric   // ".err"
10405ffd83dbSDimitry Andric   bool parseDirectiveError(SMLoc DirectiveLoc);
10415ffd83dbSDimitry Andric   // ".errb" or ".errnb", depending on ExpectBlank.
10425ffd83dbSDimitry Andric   bool parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank);
10435ffd83dbSDimitry Andric   // ".errdef" or ".errndef", depending on ExpectBlank.
10445ffd83dbSDimitry Andric   bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc, bool ExpectDefined);
10455ffd83dbSDimitry Andric   // ".erridn", ".errdif", ".erridni", or ".errdifi", depending on ExpectEqual
10465ffd83dbSDimitry Andric   // and CaseInsensitive.
10475ffd83dbSDimitry Andric   bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
10485ffd83dbSDimitry Andric                                 bool CaseInsensitive);
10495ffd83dbSDimitry Andric   // ".erre" or ".errnz", depending on ExpectZero.
10505ffd83dbSDimitry Andric   bool parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero);
10515ffd83dbSDimitry Andric 
1052e8d8bef9SDimitry Andric   // ".radix"
1053e8d8bef9SDimitry Andric   bool parseDirectiveRadix(SMLoc DirectiveLoc);
1054e8d8bef9SDimitry Andric 
10555ffd83dbSDimitry Andric   // "echo"
1056fe6060f1SDimitry Andric   bool parseDirectiveEcho(SMLoc DirectiveLoc);
10575ffd83dbSDimitry Andric 
10585ffd83dbSDimitry Andric   void initializeDirectiveKindMap();
10595ffd83dbSDimitry Andric   void initializeCVDefRangeTypeMap();
1060fe6060f1SDimitry Andric   void initializeBuiltinSymbolMap();
10615ffd83dbSDimitry Andric };
10625ffd83dbSDimitry Andric 
10635ffd83dbSDimitry Andric } // end anonymous namespace
10645ffd83dbSDimitry Andric 
10655ffd83dbSDimitry Andric namespace llvm {
10665ffd83dbSDimitry Andric 
10675ffd83dbSDimitry Andric extern MCAsmParserExtension *createCOFFMasmParser();
10685ffd83dbSDimitry Andric 
10695ffd83dbSDimitry Andric } // end namespace llvm
10705ffd83dbSDimitry Andric 
10715ffd83dbSDimitry Andric enum { DEFAULT_ADDRSPACE = 0 };
10725ffd83dbSDimitry Andric 
10735ffd83dbSDimitry Andric MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
1074fe6060f1SDimitry Andric                        const MCAsmInfo &MAI, struct tm TM, unsigned CB)
10755ffd83dbSDimitry Andric     : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
1076fe6060f1SDimitry Andric       CurBuffer(CB ? CB : SM.getMainFileID()), TM(TM) {
10775ffd83dbSDimitry Andric   HadError = false;
10785ffd83dbSDimitry Andric   // Save the old handler.
10795ffd83dbSDimitry Andric   SavedDiagHandler = SrcMgr.getDiagHandler();
10805ffd83dbSDimitry Andric   SavedDiagContext = SrcMgr.getDiagContext();
10815ffd83dbSDimitry Andric   // Set our own handler which calls the saved handler.
10825ffd83dbSDimitry Andric   SrcMgr.setDiagHandler(DiagHandler, this);
10835ffd83dbSDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
1084e8d8bef9SDimitry Andric   EndStatementAtEOFStack.push_back(true);
10855ffd83dbSDimitry Andric 
10865ffd83dbSDimitry Andric   // Initialize the platform / file format parser.
1087fe6060f1SDimitry Andric   switch (Ctx.getObjectFileType()) {
1088fe6060f1SDimitry Andric   case MCContext::IsCOFF:
10895ffd83dbSDimitry Andric     PlatformParser.reset(createCOFFMasmParser());
10905ffd83dbSDimitry Andric     break;
10915ffd83dbSDimitry Andric   default:
10925ffd83dbSDimitry Andric     report_fatal_error("llvm-ml currently supports only COFF output.");
10935ffd83dbSDimitry Andric     break;
10945ffd83dbSDimitry Andric   }
10955ffd83dbSDimitry Andric 
10965ffd83dbSDimitry Andric   initializeDirectiveKindMap();
10975ffd83dbSDimitry Andric   PlatformParser->Initialize(*this);
10985ffd83dbSDimitry Andric   initializeCVDefRangeTypeMap();
1099fe6060f1SDimitry Andric   initializeBuiltinSymbolMap();
11005ffd83dbSDimitry Andric 
11015ffd83dbSDimitry Andric   NumOfMacroInstantiations = 0;
11025ffd83dbSDimitry Andric }
11035ffd83dbSDimitry Andric 
11045ffd83dbSDimitry Andric MasmParser::~MasmParser() {
11055ffd83dbSDimitry Andric   assert((HadError || ActiveMacros.empty()) &&
11065ffd83dbSDimitry Andric          "Unexpected active macro instantiation!");
11075ffd83dbSDimitry Andric 
11085ffd83dbSDimitry Andric   // Restore the saved diagnostics handler and context for use during
11095ffd83dbSDimitry Andric   // finalization.
11105ffd83dbSDimitry Andric   SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
11115ffd83dbSDimitry Andric }
11125ffd83dbSDimitry Andric 
11135ffd83dbSDimitry Andric void MasmParser::printMacroInstantiations() {
11145ffd83dbSDimitry Andric   // Print the active macro instantiation stack.
11155ffd83dbSDimitry Andric   for (std::vector<MacroInstantiation *>::const_reverse_iterator
11165ffd83dbSDimitry Andric            it = ActiveMacros.rbegin(),
11175ffd83dbSDimitry Andric            ie = ActiveMacros.rend();
11185ffd83dbSDimitry Andric        it != ie; ++it)
11195ffd83dbSDimitry Andric     printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note,
11205ffd83dbSDimitry Andric                  "while in macro instantiation");
11215ffd83dbSDimitry Andric }
11225ffd83dbSDimitry Andric 
11235ffd83dbSDimitry Andric void MasmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
11245ffd83dbSDimitry Andric   printPendingErrors();
11255ffd83dbSDimitry Andric   printMessage(L, SourceMgr::DK_Note, Msg, Range);
11265ffd83dbSDimitry Andric   printMacroInstantiations();
11275ffd83dbSDimitry Andric }
11285ffd83dbSDimitry Andric 
11295ffd83dbSDimitry Andric bool MasmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
11305ffd83dbSDimitry Andric   if (getTargetParser().getTargetOptions().MCNoWarn)
11315ffd83dbSDimitry Andric     return false;
11325ffd83dbSDimitry Andric   if (getTargetParser().getTargetOptions().MCFatalWarnings)
11335ffd83dbSDimitry Andric     return Error(L, Msg, Range);
11345ffd83dbSDimitry Andric   printMessage(L, SourceMgr::DK_Warning, Msg, Range);
11355ffd83dbSDimitry Andric   printMacroInstantiations();
11365ffd83dbSDimitry Andric   return false;
11375ffd83dbSDimitry Andric }
11385ffd83dbSDimitry Andric 
11395ffd83dbSDimitry Andric bool MasmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
11405ffd83dbSDimitry Andric   HadError = true;
11415ffd83dbSDimitry Andric   printMessage(L, SourceMgr::DK_Error, Msg, Range);
11425ffd83dbSDimitry Andric   printMacroInstantiations();
11435ffd83dbSDimitry Andric   return true;
11445ffd83dbSDimitry Andric }
11455ffd83dbSDimitry Andric 
11465ffd83dbSDimitry Andric bool MasmParser::enterIncludeFile(const std::string &Filename) {
11475ffd83dbSDimitry Andric   std::string IncludedFile;
11485ffd83dbSDimitry Andric   unsigned NewBuf =
11495ffd83dbSDimitry Andric       SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
11505ffd83dbSDimitry Andric   if (!NewBuf)
11515ffd83dbSDimitry Andric     return true;
11525ffd83dbSDimitry Andric 
11535ffd83dbSDimitry Andric   CurBuffer = NewBuf;
11545ffd83dbSDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
1155e8d8bef9SDimitry Andric   EndStatementAtEOFStack.push_back(true);
11565ffd83dbSDimitry Andric   return false;
11575ffd83dbSDimitry Andric }
11585ffd83dbSDimitry Andric 
1159e8d8bef9SDimitry Andric void MasmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer,
1160e8d8bef9SDimitry Andric                            bool EndStatementAtEOF) {
11615ffd83dbSDimitry Andric   CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
11625ffd83dbSDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
1163e8d8bef9SDimitry Andric                   Loc.getPointer(), EndStatementAtEOF);
11645ffd83dbSDimitry Andric }
11655ffd83dbSDimitry Andric 
1166fe6060f1SDimitry Andric bool MasmParser::expandMacros() {
1167fe6060f1SDimitry Andric   const AsmToken &Tok = getTok();
1168fe6060f1SDimitry Andric   const std::string IDLower = Tok.getIdentifier().lower();
1169fe6060f1SDimitry Andric 
1170fe6060f1SDimitry Andric   const llvm::MCAsmMacro *M = getContext().lookupMacro(IDLower);
1171fe6060f1SDimitry Andric   if (M && M->IsFunction && peekTok().is(AsmToken::LParen)) {
1172fe6060f1SDimitry Andric     // This is a macro function invocation; expand it in place.
1173fe6060f1SDimitry Andric     const SMLoc MacroLoc = Tok.getLoc();
1174fe6060f1SDimitry Andric     const StringRef MacroId = Tok.getIdentifier();
1175fe6060f1SDimitry Andric     Lexer.Lex();
1176fe6060f1SDimitry Andric     if (handleMacroInvocation(M, MacroLoc)) {
1177fe6060f1SDimitry Andric       Lexer.UnLex(AsmToken(AsmToken::Error, MacroId));
1178fe6060f1SDimitry Andric       Lexer.Lex();
1179fe6060f1SDimitry Andric     }
1180fe6060f1SDimitry Andric     return false;
1181fe6060f1SDimitry Andric   }
1182fe6060f1SDimitry Andric 
1183fe6060f1SDimitry Andric   llvm::Optional<std::string> ExpandedValue;
1184fe6060f1SDimitry Andric   auto BuiltinIt = BuiltinSymbolMap.find(IDLower);
1185fe6060f1SDimitry Andric   if (BuiltinIt != BuiltinSymbolMap.end()) {
1186fe6060f1SDimitry Andric     ExpandedValue =
1187fe6060f1SDimitry Andric         evaluateBuiltinTextMacro(BuiltinIt->getValue(), Tok.getLoc());
1188fe6060f1SDimitry Andric   } else {
1189fe6060f1SDimitry Andric     auto VarIt = Variables.find(IDLower);
1190fe6060f1SDimitry Andric     if (VarIt != Variables.end() && VarIt->getValue().IsText) {
1191fe6060f1SDimitry Andric       ExpandedValue = VarIt->getValue().TextValue;
1192fe6060f1SDimitry Andric     }
1193fe6060f1SDimitry Andric   }
1194fe6060f1SDimitry Andric 
1195fe6060f1SDimitry Andric   if (!ExpandedValue.hasValue())
1196fe6060f1SDimitry Andric     return true;
1197fe6060f1SDimitry Andric   std::unique_ptr<MemoryBuffer> Instantiation =
1198fe6060f1SDimitry Andric       MemoryBuffer::getMemBufferCopy(*ExpandedValue, "<instantiation>");
1199fe6060f1SDimitry Andric 
1200fe6060f1SDimitry Andric   // Jump to the macro instantiation and prime the lexer.
1201fe6060f1SDimitry Andric   CurBuffer =
1202fe6060f1SDimitry Andric       SrcMgr.AddNewSourceBuffer(std::move(Instantiation), Tok.getEndLoc());
1203fe6060f1SDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), nullptr,
1204fe6060f1SDimitry Andric                   /*EndStatementAtEOF=*/false);
1205fe6060f1SDimitry Andric   EndStatementAtEOFStack.push_back(false);
1206fe6060f1SDimitry Andric   Lexer.Lex();
1207fe6060f1SDimitry Andric   return false;
1208fe6060f1SDimitry Andric }
1209fe6060f1SDimitry Andric 
1210fe6060f1SDimitry Andric const AsmToken &MasmParser::Lex(ExpandKind ExpandNextToken) {
12115ffd83dbSDimitry Andric   if (Lexer.getTok().is(AsmToken::Error))
12125ffd83dbSDimitry Andric     Error(Lexer.getErrLoc(), Lexer.getErr());
12135ffd83dbSDimitry Andric 
12145ffd83dbSDimitry Andric   // if it's a end of statement with a comment in it
12155ffd83dbSDimitry Andric   if (getTok().is(AsmToken::EndOfStatement)) {
12165ffd83dbSDimitry Andric     // if this is a line comment output it.
12175ffd83dbSDimitry Andric     if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
12185ffd83dbSDimitry Andric         getTok().getString().front() != '\r' && MAI.preserveAsmComments())
12195ffd83dbSDimitry Andric       Out.addExplicitComment(Twine(getTok().getString()));
12205ffd83dbSDimitry Andric   }
12215ffd83dbSDimitry Andric 
12225ffd83dbSDimitry Andric   const AsmToken *tok = &Lexer.Lex();
1223fe6060f1SDimitry Andric   bool StartOfStatement = Lexer.isAtStartOfStatement();
12245ffd83dbSDimitry Andric 
1225fe6060f1SDimitry Andric   while (ExpandNextToken == ExpandMacros && tok->is(AsmToken::Identifier)) {
1226fe6060f1SDimitry Andric     if (StartOfStatement) {
1227fe6060f1SDimitry Andric       AsmToken NextTok;
1228fe6060f1SDimitry Andric       MutableArrayRef<AsmToken> Buf(NextTok);
1229fe6060f1SDimitry Andric       size_t ReadCount = Lexer.peekTokens(Buf);
1230fe6060f1SDimitry Andric       if (ReadCount && NextTok.is(AsmToken::Identifier) &&
1231fe6060f1SDimitry Andric           (NextTok.getString().equals_insensitive("equ") ||
1232fe6060f1SDimitry Andric            NextTok.getString().equals_insensitive("textequ"))) {
1233fe6060f1SDimitry Andric         // This looks like an EQU or TEXTEQU directive; don't expand the
1234fe6060f1SDimitry Andric         // identifier, allowing for redefinitions.
12355ffd83dbSDimitry Andric         break;
12365ffd83dbSDimitry Andric       }
12375ffd83dbSDimitry Andric     }
1238fe6060f1SDimitry Andric     if (expandMacros())
1239fe6060f1SDimitry Andric       break;
1240fe6060f1SDimitry Andric   }
12415ffd83dbSDimitry Andric 
12425ffd83dbSDimitry Andric   // Parse comments here to be deferred until end of next statement.
12435ffd83dbSDimitry Andric   while (tok->is(AsmToken::Comment)) {
12445ffd83dbSDimitry Andric     if (MAI.preserveAsmComments())
12455ffd83dbSDimitry Andric       Out.addExplicitComment(Twine(tok->getString()));
12465ffd83dbSDimitry Andric     tok = &Lexer.Lex();
12475ffd83dbSDimitry Andric   }
12485ffd83dbSDimitry Andric 
1249e8d8bef9SDimitry Andric   // Recognize and bypass line continuations.
1250e8d8bef9SDimitry Andric   while (tok->is(AsmToken::BackSlash) &&
1251fe6060f1SDimitry Andric          peekTok().is(AsmToken::EndOfStatement)) {
1252e8d8bef9SDimitry Andric     // Eat both the backslash and the end of statement.
1253e8d8bef9SDimitry Andric     Lexer.Lex();
1254e8d8bef9SDimitry Andric     tok = &Lexer.Lex();
1255e8d8bef9SDimitry Andric   }
1256e8d8bef9SDimitry Andric 
12575ffd83dbSDimitry Andric   if (tok->is(AsmToken::Eof)) {
12585ffd83dbSDimitry Andric     // If this is the end of an included file, pop the parent file off the
12595ffd83dbSDimitry Andric     // include stack.
12605ffd83dbSDimitry Andric     SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
12615ffd83dbSDimitry Andric     if (ParentIncludeLoc != SMLoc()) {
1262e8d8bef9SDimitry Andric       EndStatementAtEOFStack.pop_back();
1263e8d8bef9SDimitry Andric       jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
12645ffd83dbSDimitry Andric       return Lex();
12655ffd83dbSDimitry Andric     }
1266e8d8bef9SDimitry Andric     EndStatementAtEOFStack.pop_back();
1267e8d8bef9SDimitry Andric     assert(EndStatementAtEOFStack.empty());
12685ffd83dbSDimitry Andric   }
12695ffd83dbSDimitry Andric 
12705ffd83dbSDimitry Andric   return *tok;
12715ffd83dbSDimitry Andric }
12725ffd83dbSDimitry Andric 
1273fe6060f1SDimitry Andric const AsmToken MasmParser::peekTok(bool ShouldSkipSpace) {
1274fe6060f1SDimitry Andric   AsmToken Tok;
1275fe6060f1SDimitry Andric 
1276fe6060f1SDimitry Andric   MutableArrayRef<AsmToken> Buf(Tok);
1277fe6060f1SDimitry Andric   size_t ReadCount = Lexer.peekTokens(Buf, ShouldSkipSpace);
1278fe6060f1SDimitry Andric 
1279fe6060f1SDimitry Andric   if (ReadCount == 0) {
1280fe6060f1SDimitry Andric     // If this is the end of an included file, pop the parent file off the
1281fe6060f1SDimitry Andric     // include stack.
1282fe6060f1SDimitry Andric     SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
1283fe6060f1SDimitry Andric     if (ParentIncludeLoc != SMLoc()) {
1284fe6060f1SDimitry Andric       EndStatementAtEOFStack.pop_back();
1285fe6060f1SDimitry Andric       jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1286fe6060f1SDimitry Andric       return peekTok(ShouldSkipSpace);
1287fe6060f1SDimitry Andric     }
1288fe6060f1SDimitry Andric     EndStatementAtEOFStack.pop_back();
1289fe6060f1SDimitry Andric     assert(EndStatementAtEOFStack.empty());
1290fe6060f1SDimitry Andric   }
1291fe6060f1SDimitry Andric 
1292fe6060f1SDimitry Andric   assert(ReadCount == 1);
1293fe6060f1SDimitry Andric   return Tok;
1294fe6060f1SDimitry Andric }
1295fe6060f1SDimitry Andric 
12965ffd83dbSDimitry Andric bool MasmParser::enabledGenDwarfForAssembly() {
12975ffd83dbSDimitry Andric   // Check whether the user specified -g.
12985ffd83dbSDimitry Andric   if (!getContext().getGenDwarfForAssembly())
12995ffd83dbSDimitry Andric     return false;
13005ffd83dbSDimitry Andric   // If we haven't encountered any .file directives (which would imply that
13015ffd83dbSDimitry Andric   // the assembler source was produced with debug info already) then emit one
13025ffd83dbSDimitry Andric   // describing the assembler source file itself.
13035ffd83dbSDimitry Andric   if (getContext().getGenDwarfFileNumber() == 0) {
13045ffd83dbSDimitry Andric     // Use the first #line directive for this, if any. It's preprocessed, so
13055ffd83dbSDimitry Andric     // there is no checksum, and of course no source directive.
13065ffd83dbSDimitry Andric     if (!FirstCppHashFilename.empty())
13075ffd83dbSDimitry Andric       getContext().setMCLineTableRootFile(/*CUID=*/0,
13085ffd83dbSDimitry Andric                                           getContext().getCompilationDir(),
13095ffd83dbSDimitry Andric                                           FirstCppHashFilename,
13105ffd83dbSDimitry Andric                                           /*Cksum=*/None, /*Source=*/None);
13115ffd83dbSDimitry Andric     const MCDwarfFile &RootFile =
13125ffd83dbSDimitry Andric         getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile();
13135ffd83dbSDimitry Andric     getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective(
13145ffd83dbSDimitry Andric         /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name,
13155ffd83dbSDimitry Andric         RootFile.Checksum, RootFile.Source));
13165ffd83dbSDimitry Andric   }
13175ffd83dbSDimitry Andric   return true;
13185ffd83dbSDimitry Andric }
13195ffd83dbSDimitry Andric 
13205ffd83dbSDimitry Andric bool MasmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
13215ffd83dbSDimitry Andric   // Create the initial section, if requested.
13225ffd83dbSDimitry Andric   if (!NoInitialTextSection)
1323349cc55cSDimitry Andric     Out.initSections(false, getTargetParser().getSTI());
13245ffd83dbSDimitry Andric 
13255ffd83dbSDimitry Andric   // Prime the lexer.
13265ffd83dbSDimitry Andric   Lex();
13275ffd83dbSDimitry Andric 
13285ffd83dbSDimitry Andric   HadError = false;
13295ffd83dbSDimitry Andric   AsmCond StartingCondState = TheCondState;
13305ffd83dbSDimitry Andric   SmallVector<AsmRewrite, 4> AsmStrRewrites;
13315ffd83dbSDimitry Andric 
13325ffd83dbSDimitry Andric   // If we are generating dwarf for assembly source files save the initial text
13335ffd83dbSDimitry Andric   // section.  (Don't use enabledGenDwarfForAssembly() here, as we aren't
13345ffd83dbSDimitry Andric   // emitting any actual debug info yet and haven't had a chance to parse any
13355ffd83dbSDimitry Andric   // embedded .file directives.)
13365ffd83dbSDimitry Andric   if (getContext().getGenDwarfForAssembly()) {
13375ffd83dbSDimitry Andric     MCSection *Sec = getStreamer().getCurrentSectionOnly();
13385ffd83dbSDimitry Andric     if (!Sec->getBeginSymbol()) {
13395ffd83dbSDimitry Andric       MCSymbol *SectionStartSym = getContext().createTempSymbol();
13405ffd83dbSDimitry Andric       getStreamer().emitLabel(SectionStartSym);
13415ffd83dbSDimitry Andric       Sec->setBeginSymbol(SectionStartSym);
13425ffd83dbSDimitry Andric     }
13435ffd83dbSDimitry Andric     bool InsertResult = getContext().addGenDwarfSection(Sec);
13445ffd83dbSDimitry Andric     assert(InsertResult && ".text section should not have debug info yet");
13455ffd83dbSDimitry Andric     (void)InsertResult;
13465ffd83dbSDimitry Andric   }
13475ffd83dbSDimitry Andric 
1348fe6060f1SDimitry Andric   getTargetParser().onBeginOfFile();
1349fe6060f1SDimitry Andric 
13505ffd83dbSDimitry Andric   // While we have input, parse each statement.
1351e8d8bef9SDimitry Andric   while (Lexer.isNot(AsmToken::Eof) ||
1352e8d8bef9SDimitry Andric          SrcMgr.getParentIncludeLoc(CurBuffer) != SMLoc()) {
1353e8d8bef9SDimitry Andric     // Skip through the EOF at the end of an inclusion.
1354e8d8bef9SDimitry Andric     if (Lexer.is(AsmToken::Eof))
1355e8d8bef9SDimitry Andric       Lex();
1356e8d8bef9SDimitry Andric 
13575ffd83dbSDimitry Andric     ParseStatementInfo Info(&AsmStrRewrites);
13585ffd83dbSDimitry Andric     bool Parsed = parseStatement(Info, nullptr);
13595ffd83dbSDimitry Andric 
13605ffd83dbSDimitry Andric     // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
13615ffd83dbSDimitry Andric     // for printing ErrMsg via Lex() only if no (presumably better) parser error
13625ffd83dbSDimitry Andric     // exists.
13635ffd83dbSDimitry Andric     if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
13645ffd83dbSDimitry Andric       Lex();
13655ffd83dbSDimitry Andric     }
13665ffd83dbSDimitry Andric 
13675ffd83dbSDimitry Andric     // parseStatement returned true so may need to emit an error.
13685ffd83dbSDimitry Andric     printPendingErrors();
13695ffd83dbSDimitry Andric 
13705ffd83dbSDimitry Andric     // Skipping to the next line if needed.
13715ffd83dbSDimitry Andric     if (Parsed && !getLexer().isAtStartOfStatement())
13725ffd83dbSDimitry Andric       eatToEndOfStatement();
13735ffd83dbSDimitry Andric   }
13745ffd83dbSDimitry Andric 
13755ffd83dbSDimitry Andric   getTargetParser().onEndOfFile();
13765ffd83dbSDimitry Andric   printPendingErrors();
13775ffd83dbSDimitry Andric 
13785ffd83dbSDimitry Andric   // All errors should have been emitted.
13795ffd83dbSDimitry Andric   assert(!hasPendingError() && "unexpected error from parseStatement");
13805ffd83dbSDimitry Andric 
13815ffd83dbSDimitry Andric   getTargetParser().flushPendingInstructions(getStreamer());
13825ffd83dbSDimitry Andric 
13835ffd83dbSDimitry Andric   if (TheCondState.TheCond != StartingCondState.TheCond ||
13845ffd83dbSDimitry Andric       TheCondState.Ignore != StartingCondState.Ignore)
13855ffd83dbSDimitry Andric     printError(getTok().getLoc(), "unmatched .ifs or .elses");
13865ffd83dbSDimitry Andric   // Check to see there are no empty DwarfFile slots.
13875ffd83dbSDimitry Andric   const auto &LineTables = getContext().getMCDwarfLineTables();
13885ffd83dbSDimitry Andric   if (!LineTables.empty()) {
13895ffd83dbSDimitry Andric     unsigned Index = 0;
13905ffd83dbSDimitry Andric     for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) {
13915ffd83dbSDimitry Andric       if (File.Name.empty() && Index != 0)
13925ffd83dbSDimitry Andric         printError(getTok().getLoc(), "unassigned file number: " +
13935ffd83dbSDimitry Andric                                           Twine(Index) +
13945ffd83dbSDimitry Andric                                           " for .file directives");
13955ffd83dbSDimitry Andric       ++Index;
13965ffd83dbSDimitry Andric     }
13975ffd83dbSDimitry Andric   }
13985ffd83dbSDimitry Andric 
13995ffd83dbSDimitry Andric   // Check to see that all assembler local symbols were actually defined.
14005ffd83dbSDimitry Andric   // Targets that don't do subsections via symbols may not want this, though,
14015ffd83dbSDimitry Andric   // so conservatively exclude them. Only do this if we're finalizing, though,
14025ffd83dbSDimitry Andric   // as otherwise we won't necessarilly have seen everything yet.
14035ffd83dbSDimitry Andric   if (!NoFinalize) {
14045ffd83dbSDimitry Andric     if (MAI.hasSubsectionsViaSymbols()) {
14055ffd83dbSDimitry Andric       for (const auto &TableEntry : getContext().getSymbols()) {
14065ffd83dbSDimitry Andric         MCSymbol *Sym = TableEntry.getValue();
14075ffd83dbSDimitry Andric         // Variable symbols may not be marked as defined, so check those
14085ffd83dbSDimitry Andric         // explicitly. If we know it's a variable, we have a definition for
14095ffd83dbSDimitry Andric         // the purposes of this check.
14105ffd83dbSDimitry Andric         if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
14115ffd83dbSDimitry Andric           // FIXME: We would really like to refer back to where the symbol was
14125ffd83dbSDimitry Andric           // first referenced for a source location. We need to add something
14135ffd83dbSDimitry Andric           // to track that. Currently, we just point to the end of the file.
14145ffd83dbSDimitry Andric           printError(getTok().getLoc(), "assembler local symbol '" +
14155ffd83dbSDimitry Andric                                             Sym->getName() + "' not defined");
14165ffd83dbSDimitry Andric       }
14175ffd83dbSDimitry Andric     }
14185ffd83dbSDimitry Andric 
14195ffd83dbSDimitry Andric     // Temporary symbols like the ones for directional jumps don't go in the
14205ffd83dbSDimitry Andric     // symbol table. They also need to be diagnosed in all (final) cases.
14215ffd83dbSDimitry Andric     for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
14225ffd83dbSDimitry Andric       if (std::get<2>(LocSym)->isUndefined()) {
14235ffd83dbSDimitry Andric         // Reset the state of any "# line file" directives we've seen to the
14245ffd83dbSDimitry Andric         // context as it was at the diagnostic site.
14255ffd83dbSDimitry Andric         CppHashInfo = std::get<1>(LocSym);
14265ffd83dbSDimitry Andric         printError(std::get<0>(LocSym), "directional label undefined");
14275ffd83dbSDimitry Andric       }
14285ffd83dbSDimitry Andric     }
14295ffd83dbSDimitry Andric   }
14305ffd83dbSDimitry Andric 
14315ffd83dbSDimitry Andric   // Finalize the output stream if there are no errors and if the client wants
14325ffd83dbSDimitry Andric   // us to.
14335ffd83dbSDimitry Andric   if (!HadError && !NoFinalize)
1434e8d8bef9SDimitry Andric     Out.Finish(Lexer.getLoc());
14355ffd83dbSDimitry Andric 
14365ffd83dbSDimitry Andric   return HadError || getContext().hadError();
14375ffd83dbSDimitry Andric }
14385ffd83dbSDimitry Andric 
14395ffd83dbSDimitry Andric bool MasmParser::checkForValidSection() {
14405ffd83dbSDimitry Andric   if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) {
1441349cc55cSDimitry Andric     Out.initSections(false, getTargetParser().getSTI());
14425ffd83dbSDimitry Andric     return Error(getTok().getLoc(),
14435ffd83dbSDimitry Andric                  "expected section directive before assembly directive");
14445ffd83dbSDimitry Andric   }
14455ffd83dbSDimitry Andric   return false;
14465ffd83dbSDimitry Andric }
14475ffd83dbSDimitry Andric 
14485ffd83dbSDimitry Andric /// Throw away the rest of the line for testing purposes.
14495ffd83dbSDimitry Andric void MasmParser::eatToEndOfStatement() {
1450e8d8bef9SDimitry Andric   while (Lexer.isNot(AsmToken::EndOfStatement)) {
1451e8d8bef9SDimitry Andric     if (Lexer.is(AsmToken::Eof)) {
1452e8d8bef9SDimitry Andric       SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
1453e8d8bef9SDimitry Andric       if (ParentIncludeLoc == SMLoc()) {
1454e8d8bef9SDimitry Andric         break;
1455e8d8bef9SDimitry Andric       }
1456e8d8bef9SDimitry Andric 
1457e8d8bef9SDimitry Andric       EndStatementAtEOFStack.pop_back();
1458e8d8bef9SDimitry Andric       jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1459e8d8bef9SDimitry Andric     }
1460e8d8bef9SDimitry Andric 
14615ffd83dbSDimitry Andric     Lexer.Lex();
1462e8d8bef9SDimitry Andric   }
14635ffd83dbSDimitry Andric 
14645ffd83dbSDimitry Andric   // Eat EOL.
14655ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::EndOfStatement))
14665ffd83dbSDimitry Andric     Lexer.Lex();
14675ffd83dbSDimitry Andric }
14685ffd83dbSDimitry Andric 
1469e8d8bef9SDimitry Andric SmallVector<StringRef, 1>
1470e8d8bef9SDimitry Andric MasmParser::parseStringRefsTo(AsmToken::TokenKind EndTok) {
1471e8d8bef9SDimitry Andric   SmallVector<StringRef, 1> Refs;
1472e8d8bef9SDimitry Andric   const char *Start = getTok().getLoc().getPointer();
1473e8d8bef9SDimitry Andric   while (Lexer.isNot(EndTok)) {
1474e8d8bef9SDimitry Andric     if (Lexer.is(AsmToken::Eof)) {
1475e8d8bef9SDimitry Andric       SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
1476e8d8bef9SDimitry Andric       if (ParentIncludeLoc == SMLoc()) {
1477e8d8bef9SDimitry Andric         break;
1478e8d8bef9SDimitry Andric       }
1479e8d8bef9SDimitry Andric       Refs.emplace_back(Start, getTok().getLoc().getPointer() - Start);
1480e8d8bef9SDimitry Andric 
1481e8d8bef9SDimitry Andric       EndStatementAtEOFStack.pop_back();
1482e8d8bef9SDimitry Andric       jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1483e8d8bef9SDimitry Andric       Lexer.Lex();
1484e8d8bef9SDimitry Andric       Start = getTok().getLoc().getPointer();
1485e8d8bef9SDimitry Andric     } else {
1486e8d8bef9SDimitry Andric       Lexer.Lex();
1487e8d8bef9SDimitry Andric     }
1488e8d8bef9SDimitry Andric   }
1489e8d8bef9SDimitry Andric   Refs.emplace_back(Start, getTok().getLoc().getPointer() - Start);
1490e8d8bef9SDimitry Andric   return Refs;
1491e8d8bef9SDimitry Andric }
1492e8d8bef9SDimitry Andric 
1493e8d8bef9SDimitry Andric std::string MasmParser::parseStringTo(AsmToken::TokenKind EndTok) {
1494e8d8bef9SDimitry Andric   SmallVector<StringRef, 1> Refs = parseStringRefsTo(EndTok);
1495e8d8bef9SDimitry Andric   std::string Str;
1496e8d8bef9SDimitry Andric   for (StringRef S : Refs) {
1497e8d8bef9SDimitry Andric     Str.append(S.str());
1498e8d8bef9SDimitry Andric   }
1499e8d8bef9SDimitry Andric   return Str;
1500e8d8bef9SDimitry Andric }
1501e8d8bef9SDimitry Andric 
15025ffd83dbSDimitry Andric StringRef MasmParser::parseStringToEndOfStatement() {
15035ffd83dbSDimitry Andric   const char *Start = getTok().getLoc().getPointer();
15045ffd83dbSDimitry Andric 
15055ffd83dbSDimitry Andric   while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
15065ffd83dbSDimitry Andric     Lexer.Lex();
15075ffd83dbSDimitry Andric 
15085ffd83dbSDimitry Andric   const char *End = getTok().getLoc().getPointer();
15095ffd83dbSDimitry Andric   return StringRef(Start, End - Start);
15105ffd83dbSDimitry Andric }
15115ffd83dbSDimitry Andric 
15125ffd83dbSDimitry Andric /// Parse a paren expression and return it.
15135ffd83dbSDimitry Andric /// NOTE: This assumes the leading '(' has already been consumed.
15145ffd83dbSDimitry Andric ///
15155ffd83dbSDimitry Andric /// parenexpr ::= expr)
15165ffd83dbSDimitry Andric ///
15175ffd83dbSDimitry Andric bool MasmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
15185ffd83dbSDimitry Andric   if (parseExpression(Res))
15195ffd83dbSDimitry Andric     return true;
15205ffd83dbSDimitry Andric   EndLoc = Lexer.getTok().getEndLoc();
1521*04eeddc0SDimitry Andric   return parseRParen();
15225ffd83dbSDimitry Andric }
15235ffd83dbSDimitry Andric 
15245ffd83dbSDimitry Andric /// Parse a bracket expression and return it.
15255ffd83dbSDimitry Andric /// NOTE: This assumes the leading '[' has already been consumed.
15265ffd83dbSDimitry Andric ///
15275ffd83dbSDimitry Andric /// bracketexpr ::= expr]
15285ffd83dbSDimitry Andric ///
15295ffd83dbSDimitry Andric bool MasmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
15305ffd83dbSDimitry Andric   if (parseExpression(Res))
15315ffd83dbSDimitry Andric     return true;
15325ffd83dbSDimitry Andric   EndLoc = getTok().getEndLoc();
15335ffd83dbSDimitry Andric   if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
15345ffd83dbSDimitry Andric     return true;
15355ffd83dbSDimitry Andric   return false;
15365ffd83dbSDimitry Andric }
15375ffd83dbSDimitry Andric 
15385ffd83dbSDimitry Andric /// Parse a primary expression and return it.
15395ffd83dbSDimitry Andric ///  primaryexpr ::= (parenexpr
15405ffd83dbSDimitry Andric ///  primaryexpr ::= symbol
15415ffd83dbSDimitry Andric ///  primaryexpr ::= number
15425ffd83dbSDimitry Andric ///  primaryexpr ::= '.'
1543e8d8bef9SDimitry Andric ///  primaryexpr ::= ~,+,-,'not' primaryexpr
1544e8d8bef9SDimitry Andric ///  primaryexpr ::= string
1545e8d8bef9SDimitry Andric ///          (a string is interpreted as a 64-bit number in big-endian base-256)
1546e8d8bef9SDimitry Andric bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
1547e8d8bef9SDimitry Andric                                   AsmTypeInfo *TypeInfo) {
15485ffd83dbSDimitry Andric   SMLoc FirstTokenLoc = getLexer().getLoc();
15495ffd83dbSDimitry Andric   AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
15505ffd83dbSDimitry Andric   switch (FirstTokenKind) {
15515ffd83dbSDimitry Andric   default:
15525ffd83dbSDimitry Andric     return TokError("unknown token in expression");
15535ffd83dbSDimitry Andric   // If we have an error assume that we've already handled it.
15545ffd83dbSDimitry Andric   case AsmToken::Error:
15555ffd83dbSDimitry Andric     return true;
15565ffd83dbSDimitry Andric   case AsmToken::Exclaim:
15575ffd83dbSDimitry Andric     Lex(); // Eat the operator.
1558e8d8bef9SDimitry Andric     if (parsePrimaryExpr(Res, EndLoc, nullptr))
15595ffd83dbSDimitry Andric       return true;
15605ffd83dbSDimitry Andric     Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
15615ffd83dbSDimitry Andric     return false;
15625ffd83dbSDimitry Andric   case AsmToken::Dollar:
15635ffd83dbSDimitry Andric   case AsmToken::At:
15645ffd83dbSDimitry Andric   case AsmToken::Identifier: {
15655ffd83dbSDimitry Andric     StringRef Identifier;
15665ffd83dbSDimitry Andric     if (parseIdentifier(Identifier)) {
15675ffd83dbSDimitry Andric       // We may have failed but $ may be a valid token.
15685ffd83dbSDimitry Andric       if (getTok().is(AsmToken::Dollar)) {
15695ffd83dbSDimitry Andric         if (Lexer.getMAI().getDollarIsPC()) {
15705ffd83dbSDimitry Andric           Lex();
15715ffd83dbSDimitry Andric           // This is a '$' reference, which references the current PC.  Emit a
15725ffd83dbSDimitry Andric           // temporary label to the streamer and refer to it.
15735ffd83dbSDimitry Andric           MCSymbol *Sym = Ctx.createTempSymbol();
15745ffd83dbSDimitry Andric           Out.emitLabel(Sym);
15755ffd83dbSDimitry Andric           Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
15765ffd83dbSDimitry Andric                                         getContext());
15775ffd83dbSDimitry Andric           EndLoc = FirstTokenLoc;
15785ffd83dbSDimitry Andric           return false;
15795ffd83dbSDimitry Andric         }
15805ffd83dbSDimitry Andric         return Error(FirstTokenLoc, "invalid token in expression");
15815ffd83dbSDimitry Andric       }
15825ffd83dbSDimitry Andric     }
1583e8d8bef9SDimitry Andric     // Parse named bitwise negation.
1584fe6060f1SDimitry Andric     if (Identifier.equals_insensitive("not")) {
1585e8d8bef9SDimitry Andric       if (parsePrimaryExpr(Res, EndLoc, nullptr))
1586e8d8bef9SDimitry Andric         return true;
1587e8d8bef9SDimitry Andric       Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
1588e8d8bef9SDimitry Andric       return false;
1589e8d8bef9SDimitry Andric     }
15905ffd83dbSDimitry Andric     // Parse symbol variant.
15915ffd83dbSDimitry Andric     std::pair<StringRef, StringRef> Split;
15925ffd83dbSDimitry Andric     if (!MAI.useParensForSymbolVariant()) {
15935ffd83dbSDimitry Andric       if (FirstTokenKind == AsmToken::String) {
15945ffd83dbSDimitry Andric         if (Lexer.is(AsmToken::At)) {
15955ffd83dbSDimitry Andric           Lex(); // eat @
15965ffd83dbSDimitry Andric           SMLoc AtLoc = getLexer().getLoc();
15975ffd83dbSDimitry Andric           StringRef VName;
15985ffd83dbSDimitry Andric           if (parseIdentifier(VName))
15995ffd83dbSDimitry Andric             return Error(AtLoc, "expected symbol variant after '@'");
16005ffd83dbSDimitry Andric 
16015ffd83dbSDimitry Andric           Split = std::make_pair(Identifier, VName);
16025ffd83dbSDimitry Andric         }
16035ffd83dbSDimitry Andric       } else {
16045ffd83dbSDimitry Andric         Split = Identifier.split('@');
16055ffd83dbSDimitry Andric       }
16065ffd83dbSDimitry Andric     } else if (Lexer.is(AsmToken::LParen)) {
16075ffd83dbSDimitry Andric       Lex(); // eat '('.
16085ffd83dbSDimitry Andric       StringRef VName;
16095ffd83dbSDimitry Andric       parseIdentifier(VName);
16105ffd83dbSDimitry Andric       // eat ')'.
16115ffd83dbSDimitry Andric       if (parseToken(AsmToken::RParen,
16125ffd83dbSDimitry Andric                      "unexpected token in variant, expected ')'"))
16135ffd83dbSDimitry Andric         return true;
16145ffd83dbSDimitry Andric       Split = std::make_pair(Identifier, VName);
16155ffd83dbSDimitry Andric     }
16165ffd83dbSDimitry Andric 
16175ffd83dbSDimitry Andric     EndLoc = SMLoc::getFromPointer(Identifier.end());
16185ffd83dbSDimitry Andric 
16195ffd83dbSDimitry Andric     // This is a symbol reference.
16205ffd83dbSDimitry Andric     StringRef SymbolName = Identifier;
16215ffd83dbSDimitry Andric     if (SymbolName.empty())
16225ffd83dbSDimitry Andric       return Error(getLexer().getLoc(), "expected a symbol reference");
16235ffd83dbSDimitry Andric 
16245ffd83dbSDimitry Andric     MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
16255ffd83dbSDimitry Andric 
16265ffd83dbSDimitry Andric     // Look up the symbol variant if used.
16275ffd83dbSDimitry Andric     if (!Split.second.empty()) {
16285ffd83dbSDimitry Andric       Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
16295ffd83dbSDimitry Andric       if (Variant != MCSymbolRefExpr::VK_Invalid) {
16305ffd83dbSDimitry Andric         SymbolName = Split.first;
16315ffd83dbSDimitry Andric       } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
16325ffd83dbSDimitry Andric         Variant = MCSymbolRefExpr::VK_None;
16335ffd83dbSDimitry Andric       } else {
16345ffd83dbSDimitry Andric         return Error(SMLoc::getFromPointer(Split.second.begin()),
16355ffd83dbSDimitry Andric                      "invalid variant '" + Split.second + "'");
16365ffd83dbSDimitry Andric       }
16375ffd83dbSDimitry Andric     }
16385ffd83dbSDimitry Andric 
16395ffd83dbSDimitry Andric     // Find the field offset if used.
1640e8d8bef9SDimitry Andric     AsmFieldInfo Info;
16415ffd83dbSDimitry Andric     Split = SymbolName.split('.');
1642e8d8bef9SDimitry Andric     if (Split.second.empty()) {
1643e8d8bef9SDimitry Andric     } else {
16445ffd83dbSDimitry Andric       SymbolName = Split.first;
1645e8d8bef9SDimitry Andric       if (lookUpField(SymbolName, Split.second, Info)) {
16465ffd83dbSDimitry Andric         std::pair<StringRef, StringRef> BaseMember = Split.second.split('.');
16475ffd83dbSDimitry Andric         StringRef Base = BaseMember.first, Member = BaseMember.second;
1648e8d8bef9SDimitry Andric         lookUpField(Base, Member, Info);
1649e8d8bef9SDimitry Andric       } else if (Structs.count(SymbolName.lower())) {
1650e8d8bef9SDimitry Andric         // This is actually a reference to a field offset.
1651e8d8bef9SDimitry Andric         Res = MCConstantExpr::create(Info.Offset, getContext());
1652e8d8bef9SDimitry Andric         return false;
16535ffd83dbSDimitry Andric       }
16545ffd83dbSDimitry Andric     }
16555ffd83dbSDimitry Andric 
16565ffd83dbSDimitry Andric     MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
1657fe6060f1SDimitry Andric     if (!Sym) {
1658fe6060f1SDimitry Andric       // If this is a built-in numeric value, treat it as a constant.
1659fe6060f1SDimitry Andric       auto BuiltinIt = BuiltinSymbolMap.find(SymbolName.lower());
1660fe6060f1SDimitry Andric       const BuiltinSymbol Symbol = (BuiltinIt == BuiltinSymbolMap.end())
1661fe6060f1SDimitry Andric                                        ? BI_NO_SYMBOL
1662fe6060f1SDimitry Andric                                        : BuiltinIt->getValue();
1663fe6060f1SDimitry Andric       if (Symbol != BI_NO_SYMBOL) {
1664fe6060f1SDimitry Andric         const MCExpr *Value = evaluateBuiltinValue(Symbol, FirstTokenLoc);
1665fe6060f1SDimitry Andric         if (Value) {
1666fe6060f1SDimitry Andric           Res = Value;
1667fe6060f1SDimitry Andric           return false;
1668fe6060f1SDimitry Andric         }
1669fe6060f1SDimitry Andric       }
1670fe6060f1SDimitry Andric 
1671fe6060f1SDimitry Andric       // Variables use case-insensitive symbol names; if this is a variable, we
1672fe6060f1SDimitry Andric       // find the symbol using its canonical name.
1673fe6060f1SDimitry Andric       auto VarIt = Variables.find(SymbolName.lower());
1674fe6060f1SDimitry Andric       if (VarIt != Variables.end())
1675fe6060f1SDimitry Andric         SymbolName = VarIt->second.Name;
16765ffd83dbSDimitry Andric       Sym = getContext().getOrCreateSymbol(SymbolName);
1677fe6060f1SDimitry Andric     }
16785ffd83dbSDimitry Andric 
16795ffd83dbSDimitry Andric     // If this is an absolute variable reference, substitute it now to preserve
16805ffd83dbSDimitry Andric     // semantics in the face of reassignment.
16815ffd83dbSDimitry Andric     if (Sym->isVariable()) {
1682fe6060f1SDimitry Andric       auto V = Sym->getVariableValue(/*SetUsed=*/false);
16835ffd83dbSDimitry Andric       bool DoInline = isa<MCConstantExpr>(V) && !Variant;
16845ffd83dbSDimitry Andric       if (auto TV = dyn_cast<MCTargetExpr>(V))
16855ffd83dbSDimitry Andric         DoInline = TV->inlineAssignedExpr();
16865ffd83dbSDimitry Andric       if (DoInline) {
16875ffd83dbSDimitry Andric         if (Variant)
16885ffd83dbSDimitry Andric           return Error(EndLoc, "unexpected modifier on variable reference");
1689fe6060f1SDimitry Andric         Res = Sym->getVariableValue(/*SetUsed=*/false);
16905ffd83dbSDimitry Andric         return false;
16915ffd83dbSDimitry Andric       }
16925ffd83dbSDimitry Andric     }
16935ffd83dbSDimitry Andric 
16945ffd83dbSDimitry Andric     // Otherwise create a symbol ref.
16955ffd83dbSDimitry Andric     const MCExpr *SymRef =
16965ffd83dbSDimitry Andric         MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);
1697e8d8bef9SDimitry Andric     if (Info.Offset) {
1698e8d8bef9SDimitry Andric       Res = MCBinaryExpr::create(
1699e8d8bef9SDimitry Andric           MCBinaryExpr::Add, SymRef,
1700e8d8bef9SDimitry Andric           MCConstantExpr::create(Info.Offset, getContext()), getContext());
17015ffd83dbSDimitry Andric     } else {
17025ffd83dbSDimitry Andric       Res = SymRef;
17035ffd83dbSDimitry Andric     }
1704e8d8bef9SDimitry Andric     if (TypeInfo) {
1705e8d8bef9SDimitry Andric       if (Info.Type.Name.empty()) {
1706e8d8bef9SDimitry Andric         auto TypeIt = KnownType.find(Identifier.lower());
1707e8d8bef9SDimitry Andric         if (TypeIt != KnownType.end()) {
1708e8d8bef9SDimitry Andric           Info.Type = TypeIt->second;
1709e8d8bef9SDimitry Andric         }
1710e8d8bef9SDimitry Andric       }
1711e8d8bef9SDimitry Andric 
1712e8d8bef9SDimitry Andric       *TypeInfo = Info.Type;
1713e8d8bef9SDimitry Andric     }
17145ffd83dbSDimitry Andric     return false;
17155ffd83dbSDimitry Andric   }
17165ffd83dbSDimitry Andric   case AsmToken::BigNum:
17175ffd83dbSDimitry Andric     return TokError("literal value out of range for directive");
17185ffd83dbSDimitry Andric   case AsmToken::Integer: {
17195ffd83dbSDimitry Andric     SMLoc Loc = getTok().getLoc();
17205ffd83dbSDimitry Andric     int64_t IntVal = getTok().getIntVal();
17215ffd83dbSDimitry Andric     Res = MCConstantExpr::create(IntVal, getContext());
17225ffd83dbSDimitry Andric     EndLoc = Lexer.getTok().getEndLoc();
17235ffd83dbSDimitry Andric     Lex(); // Eat token.
17245ffd83dbSDimitry Andric     // Look for 'b' or 'f' following an Integer as a directional label.
17255ffd83dbSDimitry Andric     if (Lexer.getKind() == AsmToken::Identifier) {
17265ffd83dbSDimitry Andric       StringRef IDVal = getTok().getString();
17275ffd83dbSDimitry Andric       // Look up the symbol variant if used.
17285ffd83dbSDimitry Andric       std::pair<StringRef, StringRef> Split = IDVal.split('@');
17295ffd83dbSDimitry Andric       MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
17305ffd83dbSDimitry Andric       if (Split.first.size() != IDVal.size()) {
17315ffd83dbSDimitry Andric         Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
17325ffd83dbSDimitry Andric         if (Variant == MCSymbolRefExpr::VK_Invalid)
17335ffd83dbSDimitry Andric           return TokError("invalid variant '" + Split.second + "'");
17345ffd83dbSDimitry Andric         IDVal = Split.first;
17355ffd83dbSDimitry Andric       }
17365ffd83dbSDimitry Andric       if (IDVal == "f" || IDVal == "b") {
17375ffd83dbSDimitry Andric         MCSymbol *Sym =
17385ffd83dbSDimitry Andric             Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");
17395ffd83dbSDimitry Andric         Res = MCSymbolRefExpr::create(Sym, Variant, getContext());
17405ffd83dbSDimitry Andric         if (IDVal == "b" && Sym->isUndefined())
17415ffd83dbSDimitry Andric           return Error(Loc, "directional label undefined");
17425ffd83dbSDimitry Andric         DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym));
17435ffd83dbSDimitry Andric         EndLoc = Lexer.getTok().getEndLoc();
17445ffd83dbSDimitry Andric         Lex(); // Eat identifier.
17455ffd83dbSDimitry Andric       }
17465ffd83dbSDimitry Andric     }
17475ffd83dbSDimitry Andric     return false;
17485ffd83dbSDimitry Andric   }
1749e8d8bef9SDimitry Andric   case AsmToken::String: {
1750e8d8bef9SDimitry Andric     // MASM strings (used as constants) are interpreted as big-endian base-256.
1751e8d8bef9SDimitry Andric     SMLoc ValueLoc = getTok().getLoc();
1752e8d8bef9SDimitry Andric     std::string Value;
1753e8d8bef9SDimitry Andric     if (parseEscapedString(Value))
1754e8d8bef9SDimitry Andric       return true;
1755e8d8bef9SDimitry Andric     if (Value.size() > 8)
1756e8d8bef9SDimitry Andric       return Error(ValueLoc, "literal value out of range");
1757e8d8bef9SDimitry Andric     uint64_t IntValue = 0;
1758e8d8bef9SDimitry Andric     for (const unsigned char CharVal : Value)
1759e8d8bef9SDimitry Andric       IntValue = (IntValue << 8) | CharVal;
1760e8d8bef9SDimitry Andric     Res = MCConstantExpr::create(IntValue, getContext());
1761e8d8bef9SDimitry Andric     return false;
1762e8d8bef9SDimitry Andric   }
17635ffd83dbSDimitry Andric   case AsmToken::Real: {
17645ffd83dbSDimitry Andric     APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
17655ffd83dbSDimitry Andric     uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
17665ffd83dbSDimitry Andric     Res = MCConstantExpr::create(IntVal, getContext());
17675ffd83dbSDimitry Andric     EndLoc = Lexer.getTok().getEndLoc();
17685ffd83dbSDimitry Andric     Lex(); // Eat token.
17695ffd83dbSDimitry Andric     return false;
17705ffd83dbSDimitry Andric   }
17715ffd83dbSDimitry Andric   case AsmToken::Dot: {
17725ffd83dbSDimitry Andric     // This is a '.' reference, which references the current PC.  Emit a
17735ffd83dbSDimitry Andric     // temporary label to the streamer and refer to it.
17745ffd83dbSDimitry Andric     MCSymbol *Sym = Ctx.createTempSymbol();
17755ffd83dbSDimitry Andric     Out.emitLabel(Sym);
17765ffd83dbSDimitry Andric     Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
17775ffd83dbSDimitry Andric     EndLoc = Lexer.getTok().getEndLoc();
17785ffd83dbSDimitry Andric     Lex(); // Eat identifier.
17795ffd83dbSDimitry Andric     return false;
17805ffd83dbSDimitry Andric   }
17815ffd83dbSDimitry Andric   case AsmToken::LParen:
17825ffd83dbSDimitry Andric     Lex(); // Eat the '('.
17835ffd83dbSDimitry Andric     return parseParenExpr(Res, EndLoc);
17845ffd83dbSDimitry Andric   case AsmToken::LBrac:
17855ffd83dbSDimitry Andric     if (!PlatformParser->HasBracketExpressions())
17865ffd83dbSDimitry Andric       return TokError("brackets expression not supported on this target");
17875ffd83dbSDimitry Andric     Lex(); // Eat the '['.
17885ffd83dbSDimitry Andric     return parseBracketExpr(Res, EndLoc);
17895ffd83dbSDimitry Andric   case AsmToken::Minus:
17905ffd83dbSDimitry Andric     Lex(); // Eat the operator.
1791e8d8bef9SDimitry Andric     if (parsePrimaryExpr(Res, EndLoc, nullptr))
17925ffd83dbSDimitry Andric       return true;
17935ffd83dbSDimitry Andric     Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
17945ffd83dbSDimitry Andric     return false;
17955ffd83dbSDimitry Andric   case AsmToken::Plus:
17965ffd83dbSDimitry Andric     Lex(); // Eat the operator.
1797e8d8bef9SDimitry Andric     if (parsePrimaryExpr(Res, EndLoc, nullptr))
17985ffd83dbSDimitry Andric       return true;
17995ffd83dbSDimitry Andric     Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
18005ffd83dbSDimitry Andric     return false;
18015ffd83dbSDimitry Andric   case AsmToken::Tilde:
18025ffd83dbSDimitry Andric     Lex(); // Eat the operator.
1803e8d8bef9SDimitry Andric     if (parsePrimaryExpr(Res, EndLoc, nullptr))
18045ffd83dbSDimitry Andric       return true;
18055ffd83dbSDimitry Andric     Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
18065ffd83dbSDimitry Andric     return false;
18075ffd83dbSDimitry Andric   // MIPS unary expression operators. The lexer won't generate these tokens if
18085ffd83dbSDimitry Andric   // MCAsmInfo::HasMipsExpressions is false for the target.
18095ffd83dbSDimitry Andric   case AsmToken::PercentCall16:
18105ffd83dbSDimitry Andric   case AsmToken::PercentCall_Hi:
18115ffd83dbSDimitry Andric   case AsmToken::PercentCall_Lo:
18125ffd83dbSDimitry Andric   case AsmToken::PercentDtprel_Hi:
18135ffd83dbSDimitry Andric   case AsmToken::PercentDtprel_Lo:
18145ffd83dbSDimitry Andric   case AsmToken::PercentGot:
18155ffd83dbSDimitry Andric   case AsmToken::PercentGot_Disp:
18165ffd83dbSDimitry Andric   case AsmToken::PercentGot_Hi:
18175ffd83dbSDimitry Andric   case AsmToken::PercentGot_Lo:
18185ffd83dbSDimitry Andric   case AsmToken::PercentGot_Ofst:
18195ffd83dbSDimitry Andric   case AsmToken::PercentGot_Page:
18205ffd83dbSDimitry Andric   case AsmToken::PercentGottprel:
18215ffd83dbSDimitry Andric   case AsmToken::PercentGp_Rel:
18225ffd83dbSDimitry Andric   case AsmToken::PercentHi:
18235ffd83dbSDimitry Andric   case AsmToken::PercentHigher:
18245ffd83dbSDimitry Andric   case AsmToken::PercentHighest:
18255ffd83dbSDimitry Andric   case AsmToken::PercentLo:
18265ffd83dbSDimitry Andric   case AsmToken::PercentNeg:
18275ffd83dbSDimitry Andric   case AsmToken::PercentPcrel_Hi:
18285ffd83dbSDimitry Andric   case AsmToken::PercentPcrel_Lo:
18295ffd83dbSDimitry Andric   case AsmToken::PercentTlsgd:
18305ffd83dbSDimitry Andric   case AsmToken::PercentTlsldm:
18315ffd83dbSDimitry Andric   case AsmToken::PercentTprel_Hi:
18325ffd83dbSDimitry Andric   case AsmToken::PercentTprel_Lo:
18335ffd83dbSDimitry Andric     Lex(); // Eat the operator.
18345ffd83dbSDimitry Andric     if (Lexer.isNot(AsmToken::LParen))
18355ffd83dbSDimitry Andric       return TokError("expected '(' after operator");
18365ffd83dbSDimitry Andric     Lex(); // Eat the operator.
18375ffd83dbSDimitry Andric     if (parseExpression(Res, EndLoc))
18385ffd83dbSDimitry Andric       return true;
1839*04eeddc0SDimitry Andric     if (parseRParen())
1840*04eeddc0SDimitry Andric       return true;
18415ffd83dbSDimitry Andric     Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx);
18425ffd83dbSDimitry Andric     return !Res;
18435ffd83dbSDimitry Andric   }
18445ffd83dbSDimitry Andric }
18455ffd83dbSDimitry Andric 
18465ffd83dbSDimitry Andric bool MasmParser::parseExpression(const MCExpr *&Res) {
18475ffd83dbSDimitry Andric   SMLoc EndLoc;
18485ffd83dbSDimitry Andric   return parseExpression(Res, EndLoc);
18495ffd83dbSDimitry Andric }
18505ffd83dbSDimitry Andric 
18515ffd83dbSDimitry Andric /// This function checks if the next token is <string> type or arithmetic.
18525ffd83dbSDimitry Andric /// string that begin with character '<' must end with character '>'.
18535ffd83dbSDimitry Andric /// otherwise it is arithmetics.
18545ffd83dbSDimitry Andric /// If the function returns a 'true' value,
18555ffd83dbSDimitry Andric /// the End argument will be filled with the last location pointed to the '>'
18565ffd83dbSDimitry Andric /// character.
18575ffd83dbSDimitry Andric static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
18585ffd83dbSDimitry Andric   assert((StrLoc.getPointer() != nullptr) &&
18595ffd83dbSDimitry Andric          "Argument to the function cannot be a NULL value");
18605ffd83dbSDimitry Andric   const char *CharPtr = StrLoc.getPointer();
18615ffd83dbSDimitry Andric   while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
18625ffd83dbSDimitry Andric          (*CharPtr != '\0')) {
18635ffd83dbSDimitry Andric     if (*CharPtr == '!')
18645ffd83dbSDimitry Andric       CharPtr++;
18655ffd83dbSDimitry Andric     CharPtr++;
18665ffd83dbSDimitry Andric   }
18675ffd83dbSDimitry Andric   if (*CharPtr == '>') {
18685ffd83dbSDimitry Andric     EndLoc = StrLoc.getFromPointer(CharPtr + 1);
18695ffd83dbSDimitry Andric     return true;
18705ffd83dbSDimitry Andric   }
18715ffd83dbSDimitry Andric   return false;
18725ffd83dbSDimitry Andric }
18735ffd83dbSDimitry Andric 
18745ffd83dbSDimitry Andric /// creating a string without the escape characters '!'.
1875e8d8bef9SDimitry Andric static std::string angleBracketString(StringRef BracketContents) {
18765ffd83dbSDimitry Andric   std::string Res;
1877e8d8bef9SDimitry Andric   for (size_t Pos = 0; Pos < BracketContents.size(); Pos++) {
1878e8d8bef9SDimitry Andric     if (BracketContents[Pos] == '!')
18795ffd83dbSDimitry Andric       Pos++;
1880e8d8bef9SDimitry Andric     Res += BracketContents[Pos];
18815ffd83dbSDimitry Andric   }
18825ffd83dbSDimitry Andric   return Res;
18835ffd83dbSDimitry Andric }
18845ffd83dbSDimitry Andric 
18855ffd83dbSDimitry Andric /// Parse an expression and return it.
18865ffd83dbSDimitry Andric ///
18875ffd83dbSDimitry Andric ///  expr ::= expr &&,|| expr               -> lowest.
18885ffd83dbSDimitry Andric ///  expr ::= expr |,^,&,! expr
18895ffd83dbSDimitry Andric ///  expr ::= expr ==,!=,<>,<,<=,>,>= expr
18905ffd83dbSDimitry Andric ///  expr ::= expr <<,>> expr
18915ffd83dbSDimitry Andric ///  expr ::= expr +,- expr
18925ffd83dbSDimitry Andric ///  expr ::= expr *,/,% expr               -> highest.
18935ffd83dbSDimitry Andric ///  expr ::= primaryexpr
18945ffd83dbSDimitry Andric ///
18955ffd83dbSDimitry Andric bool MasmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
18965ffd83dbSDimitry Andric   // Parse the expression.
18975ffd83dbSDimitry Andric   Res = nullptr;
18985ffd83dbSDimitry Andric   if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
18995ffd83dbSDimitry Andric       parseBinOpRHS(1, Res, EndLoc))
19005ffd83dbSDimitry Andric     return true;
19015ffd83dbSDimitry Andric 
19025ffd83dbSDimitry Andric   // Try to constant fold it up front, if possible. Do not exploit
19035ffd83dbSDimitry Andric   // assembler here.
19045ffd83dbSDimitry Andric   int64_t Value;
19055ffd83dbSDimitry Andric   if (Res->evaluateAsAbsolute(Value))
19065ffd83dbSDimitry Andric     Res = MCConstantExpr::create(Value, getContext());
19075ffd83dbSDimitry Andric 
19085ffd83dbSDimitry Andric   return false;
19095ffd83dbSDimitry Andric }
19105ffd83dbSDimitry Andric 
19115ffd83dbSDimitry Andric bool MasmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
19125ffd83dbSDimitry Andric   Res = nullptr;
19135ffd83dbSDimitry Andric   return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
19145ffd83dbSDimitry Andric }
19155ffd83dbSDimitry Andric 
19165ffd83dbSDimitry Andric bool MasmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
19175ffd83dbSDimitry Andric                                        SMLoc &EndLoc) {
19185ffd83dbSDimitry Andric   if (parseParenExpr(Res, EndLoc))
19195ffd83dbSDimitry Andric     return true;
19205ffd83dbSDimitry Andric 
19215ffd83dbSDimitry Andric   for (; ParenDepth > 0; --ParenDepth) {
19225ffd83dbSDimitry Andric     if (parseBinOpRHS(1, Res, EndLoc))
19235ffd83dbSDimitry Andric       return true;
19245ffd83dbSDimitry Andric 
19255ffd83dbSDimitry Andric     // We don't Lex() the last RParen.
19265ffd83dbSDimitry Andric     // This is the same behavior as parseParenExpression().
19275ffd83dbSDimitry Andric     if (ParenDepth - 1 > 0) {
19285ffd83dbSDimitry Andric       EndLoc = getTok().getEndLoc();
1929*04eeddc0SDimitry Andric       if (parseRParen())
19305ffd83dbSDimitry Andric         return true;
19315ffd83dbSDimitry Andric     }
19325ffd83dbSDimitry Andric   }
19335ffd83dbSDimitry Andric   return false;
19345ffd83dbSDimitry Andric }
19355ffd83dbSDimitry Andric 
19365ffd83dbSDimitry Andric bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
19375ffd83dbSDimitry Andric   const MCExpr *Expr;
19385ffd83dbSDimitry Andric 
19395ffd83dbSDimitry Andric   SMLoc StartLoc = Lexer.getLoc();
19405ffd83dbSDimitry Andric   if (parseExpression(Expr))
19415ffd83dbSDimitry Andric     return true;
19425ffd83dbSDimitry Andric 
19435ffd83dbSDimitry Andric   if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
19445ffd83dbSDimitry Andric     return Error(StartLoc, "expected absolute expression");
19455ffd83dbSDimitry Andric 
19465ffd83dbSDimitry Andric   return false;
19475ffd83dbSDimitry Andric }
19485ffd83dbSDimitry Andric 
19495ffd83dbSDimitry Andric static unsigned getGNUBinOpPrecedence(AsmToken::TokenKind K,
19505ffd83dbSDimitry Andric                                       MCBinaryExpr::Opcode &Kind,
19515ffd83dbSDimitry Andric                                       bool ShouldUseLogicalShr,
19525ffd83dbSDimitry Andric                                       bool EndExpressionAtGreater) {
19535ffd83dbSDimitry Andric   switch (K) {
19545ffd83dbSDimitry Andric   default:
19555ffd83dbSDimitry Andric     return 0; // not a binop.
19565ffd83dbSDimitry Andric 
19575ffd83dbSDimitry Andric   // Lowest Precedence: &&, ||
19585ffd83dbSDimitry Andric   case AsmToken::AmpAmp:
19595ffd83dbSDimitry Andric     Kind = MCBinaryExpr::LAnd;
19605ffd83dbSDimitry Andric     return 2;
19615ffd83dbSDimitry Andric   case AsmToken::PipePipe:
19625ffd83dbSDimitry Andric     Kind = MCBinaryExpr::LOr;
19635ffd83dbSDimitry Andric     return 1;
19645ffd83dbSDimitry Andric 
19655ffd83dbSDimitry Andric   // Low Precedence: ==, !=, <>, <, <=, >, >=
19665ffd83dbSDimitry Andric   case AsmToken::EqualEqual:
19675ffd83dbSDimitry Andric     Kind = MCBinaryExpr::EQ;
19685ffd83dbSDimitry Andric     return 3;
19695ffd83dbSDimitry Andric   case AsmToken::ExclaimEqual:
19705ffd83dbSDimitry Andric   case AsmToken::LessGreater:
19715ffd83dbSDimitry Andric     Kind = MCBinaryExpr::NE;
19725ffd83dbSDimitry Andric     return 3;
19735ffd83dbSDimitry Andric   case AsmToken::Less:
19745ffd83dbSDimitry Andric     Kind = MCBinaryExpr::LT;
19755ffd83dbSDimitry Andric     return 3;
19765ffd83dbSDimitry Andric   case AsmToken::LessEqual:
19775ffd83dbSDimitry Andric     Kind = MCBinaryExpr::LTE;
19785ffd83dbSDimitry Andric     return 3;
19795ffd83dbSDimitry Andric   case AsmToken::Greater:
19805ffd83dbSDimitry Andric     if (EndExpressionAtGreater)
19815ffd83dbSDimitry Andric       return 0;
19825ffd83dbSDimitry Andric     Kind = MCBinaryExpr::GT;
19835ffd83dbSDimitry Andric     return 3;
19845ffd83dbSDimitry Andric   case AsmToken::GreaterEqual:
19855ffd83dbSDimitry Andric     Kind = MCBinaryExpr::GTE;
19865ffd83dbSDimitry Andric     return 3;
19875ffd83dbSDimitry Andric 
19885ffd83dbSDimitry Andric   // Low Intermediate Precedence: +, -
19895ffd83dbSDimitry Andric   case AsmToken::Plus:
19905ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Add;
19915ffd83dbSDimitry Andric     return 4;
19925ffd83dbSDimitry Andric   case AsmToken::Minus:
19935ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Sub;
19945ffd83dbSDimitry Andric     return 4;
19955ffd83dbSDimitry Andric 
19965ffd83dbSDimitry Andric   // High Intermediate Precedence: |, &, ^
19975ffd83dbSDimitry Andric   case AsmToken::Pipe:
19985ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Or;
19995ffd83dbSDimitry Andric     return 5;
20005ffd83dbSDimitry Andric   case AsmToken::Caret:
20015ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Xor;
20025ffd83dbSDimitry Andric     return 5;
20035ffd83dbSDimitry Andric   case AsmToken::Amp:
20045ffd83dbSDimitry Andric     Kind = MCBinaryExpr::And;
20055ffd83dbSDimitry Andric     return 5;
20065ffd83dbSDimitry Andric 
20075ffd83dbSDimitry Andric   // Highest Precedence: *, /, %, <<, >>
20085ffd83dbSDimitry Andric   case AsmToken::Star:
20095ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Mul;
20105ffd83dbSDimitry Andric     return 6;
20115ffd83dbSDimitry Andric   case AsmToken::Slash:
20125ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Div;
20135ffd83dbSDimitry Andric     return 6;
20145ffd83dbSDimitry Andric   case AsmToken::Percent:
20155ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Mod;
20165ffd83dbSDimitry Andric     return 6;
20175ffd83dbSDimitry Andric   case AsmToken::LessLess:
20185ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Shl;
20195ffd83dbSDimitry Andric     return 6;
20205ffd83dbSDimitry Andric   case AsmToken::GreaterGreater:
20215ffd83dbSDimitry Andric     if (EndExpressionAtGreater)
20225ffd83dbSDimitry Andric       return 0;
20235ffd83dbSDimitry Andric     Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
20245ffd83dbSDimitry Andric     return 6;
20255ffd83dbSDimitry Andric   }
20265ffd83dbSDimitry Andric }
20275ffd83dbSDimitry Andric 
20285ffd83dbSDimitry Andric unsigned MasmParser::getBinOpPrecedence(AsmToken::TokenKind K,
20295ffd83dbSDimitry Andric                                         MCBinaryExpr::Opcode &Kind) {
20305ffd83dbSDimitry Andric   bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
20315ffd83dbSDimitry Andric   return getGNUBinOpPrecedence(K, Kind, ShouldUseLogicalShr,
20325ffd83dbSDimitry Andric                                AngleBracketDepth > 0);
20335ffd83dbSDimitry Andric }
20345ffd83dbSDimitry Andric 
20355ffd83dbSDimitry Andric /// Parse all binary operators with precedence >= 'Precedence'.
20365ffd83dbSDimitry Andric /// Res contains the LHS of the expression on input.
20375ffd83dbSDimitry Andric bool MasmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
20385ffd83dbSDimitry Andric                                SMLoc &EndLoc) {
20395ffd83dbSDimitry Andric   SMLoc StartLoc = Lexer.getLoc();
20405ffd83dbSDimitry Andric   while (true) {
2041e8d8bef9SDimitry Andric     AsmToken::TokenKind TokKind = Lexer.getKind();
2042e8d8bef9SDimitry Andric     if (Lexer.getKind() == AsmToken::Identifier) {
2043e8d8bef9SDimitry Andric       TokKind = StringSwitch<AsmToken::TokenKind>(Lexer.getTok().getString())
2044e8d8bef9SDimitry Andric                     .CaseLower("and", AsmToken::Amp)
2045e8d8bef9SDimitry Andric                     .CaseLower("not", AsmToken::Exclaim)
2046e8d8bef9SDimitry Andric                     .CaseLower("or", AsmToken::Pipe)
2047e8d8bef9SDimitry Andric                     .CaseLower("eq", AsmToken::EqualEqual)
2048e8d8bef9SDimitry Andric                     .CaseLower("ne", AsmToken::ExclaimEqual)
2049e8d8bef9SDimitry Andric                     .CaseLower("lt", AsmToken::Less)
2050e8d8bef9SDimitry Andric                     .CaseLower("le", AsmToken::LessEqual)
2051e8d8bef9SDimitry Andric                     .CaseLower("gt", AsmToken::Greater)
2052e8d8bef9SDimitry Andric                     .CaseLower("ge", AsmToken::GreaterEqual)
2053e8d8bef9SDimitry Andric                     .Default(TokKind);
2054e8d8bef9SDimitry Andric     }
20555ffd83dbSDimitry Andric     MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
2056e8d8bef9SDimitry Andric     unsigned TokPrec = getBinOpPrecedence(TokKind, Kind);
20575ffd83dbSDimitry Andric 
20585ffd83dbSDimitry Andric     // If the next token is lower precedence than we are allowed to eat, return
20595ffd83dbSDimitry Andric     // successfully with what we ate already.
20605ffd83dbSDimitry Andric     if (TokPrec < Precedence)
20615ffd83dbSDimitry Andric       return false;
20625ffd83dbSDimitry Andric 
20635ffd83dbSDimitry Andric     Lex();
20645ffd83dbSDimitry Andric 
20655ffd83dbSDimitry Andric     // Eat the next primary expression.
20665ffd83dbSDimitry Andric     const MCExpr *RHS;
20675ffd83dbSDimitry Andric     if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
20685ffd83dbSDimitry Andric       return true;
20695ffd83dbSDimitry Andric 
20705ffd83dbSDimitry Andric     // If BinOp binds less tightly with RHS than the operator after RHS, let
20715ffd83dbSDimitry Andric     // the pending operator take RHS as its LHS.
20725ffd83dbSDimitry Andric     MCBinaryExpr::Opcode Dummy;
20735ffd83dbSDimitry Andric     unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
20745ffd83dbSDimitry Andric     if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
20755ffd83dbSDimitry Andric       return true;
20765ffd83dbSDimitry Andric 
20775ffd83dbSDimitry Andric     // Merge LHS and RHS according to operator.
20785ffd83dbSDimitry Andric     Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);
20795ffd83dbSDimitry Andric   }
20805ffd83dbSDimitry Andric }
20815ffd83dbSDimitry Andric 
20825ffd83dbSDimitry Andric /// ParseStatement:
2083e8d8bef9SDimitry Andric ///   ::= % statement
20845ffd83dbSDimitry Andric ///   ::= EndOfStatement
20855ffd83dbSDimitry Andric ///   ::= Label* Directive ...Operands... EndOfStatement
20865ffd83dbSDimitry Andric ///   ::= Label* Identifier OperandList* EndOfStatement
20875ffd83dbSDimitry Andric bool MasmParser::parseStatement(ParseStatementInfo &Info,
20885ffd83dbSDimitry Andric                                 MCAsmParserSemaCallback *SI) {
20895ffd83dbSDimitry Andric   assert(!hasPendingError() && "parseStatement started with pending error");
20905ffd83dbSDimitry Andric   // Eat initial spaces and comments.
20915ffd83dbSDimitry Andric   while (Lexer.is(AsmToken::Space))
20925ffd83dbSDimitry Andric     Lex();
20935ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::EndOfStatement)) {
20945ffd83dbSDimitry Andric     // If this is a line comment we can drop it safely.
20955ffd83dbSDimitry Andric     if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
20965ffd83dbSDimitry Andric         getTok().getString().front() == '\n')
20975ffd83dbSDimitry Andric       Out.AddBlankLine();
20985ffd83dbSDimitry Andric     Lex();
20995ffd83dbSDimitry Andric     return false;
21005ffd83dbSDimitry Andric   }
2101e8d8bef9SDimitry Andric 
2102e8d8bef9SDimitry Andric   // If preceded by an expansion operator, first expand all text macros and
2103e8d8bef9SDimitry Andric   // macro functions.
2104e8d8bef9SDimitry Andric   if (getTok().is(AsmToken::Percent)) {
2105e8d8bef9SDimitry Andric     SMLoc ExpansionLoc = getTok().getLoc();
2106e8d8bef9SDimitry Andric     if (parseToken(AsmToken::Percent) || expandStatement(ExpansionLoc))
2107e8d8bef9SDimitry Andric       return true;
2108e8d8bef9SDimitry Andric   }
2109e8d8bef9SDimitry Andric 
21105ffd83dbSDimitry Andric   // Statements always start with an identifier, unless we're dealing with a
21115ffd83dbSDimitry Andric   // processor directive (.386, .686, etc.) that lexes as a real.
21125ffd83dbSDimitry Andric   AsmToken ID = getTok();
21135ffd83dbSDimitry Andric   SMLoc IDLoc = ID.getLoc();
21145ffd83dbSDimitry Andric   StringRef IDVal;
21155ffd83dbSDimitry Andric   int64_t LocalLabelVal = -1;
21165ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::HashDirective))
21175ffd83dbSDimitry Andric     return parseCppHashLineFilenameComment(IDLoc);
21185ffd83dbSDimitry Andric   // Allow an integer followed by a ':' as a directional local label.
21195ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::Integer)) {
21205ffd83dbSDimitry Andric     LocalLabelVal = getTok().getIntVal();
21215ffd83dbSDimitry Andric     if (LocalLabelVal < 0) {
21225ffd83dbSDimitry Andric       if (!TheCondState.Ignore) {
21235ffd83dbSDimitry Andric         Lex(); // always eat a token
21245ffd83dbSDimitry Andric         return Error(IDLoc, "unexpected token at start of statement");
21255ffd83dbSDimitry Andric       }
21265ffd83dbSDimitry Andric       IDVal = "";
21275ffd83dbSDimitry Andric     } else {
21285ffd83dbSDimitry Andric       IDVal = getTok().getString();
21295ffd83dbSDimitry Andric       Lex(); // Consume the integer token to be used as an identifier token.
21305ffd83dbSDimitry Andric       if (Lexer.getKind() != AsmToken::Colon) {
21315ffd83dbSDimitry Andric         if (!TheCondState.Ignore) {
21325ffd83dbSDimitry Andric           Lex(); // always eat a token
21335ffd83dbSDimitry Andric           return Error(IDLoc, "unexpected token at start of statement");
21345ffd83dbSDimitry Andric         }
21355ffd83dbSDimitry Andric       }
21365ffd83dbSDimitry Andric     }
21375ffd83dbSDimitry Andric   } else if (Lexer.is(AsmToken::Dot)) {
21385ffd83dbSDimitry Andric     // Treat '.' as a valid identifier in this context.
21395ffd83dbSDimitry Andric     Lex();
21405ffd83dbSDimitry Andric     IDVal = ".";
21415ffd83dbSDimitry Andric   } else if (Lexer.is(AsmToken::LCurly)) {
21425ffd83dbSDimitry Andric     // Treat '{' as a valid identifier in this context.
21435ffd83dbSDimitry Andric     Lex();
21445ffd83dbSDimitry Andric     IDVal = "{";
21455ffd83dbSDimitry Andric 
21465ffd83dbSDimitry Andric   } else if (Lexer.is(AsmToken::RCurly)) {
21475ffd83dbSDimitry Andric     // Treat '}' as a valid identifier in this context.
21485ffd83dbSDimitry Andric     Lex();
21495ffd83dbSDimitry Andric     IDVal = "}";
21505ffd83dbSDimitry Andric   } else if (Lexer.is(AsmToken::Star) &&
21515ffd83dbSDimitry Andric              getTargetParser().starIsStartOfStatement()) {
21525ffd83dbSDimitry Andric     // Accept '*' as a valid start of statement.
21535ffd83dbSDimitry Andric     Lex();
21545ffd83dbSDimitry Andric     IDVal = "*";
21555ffd83dbSDimitry Andric   } else if (Lexer.is(AsmToken::Real)) {
21565ffd83dbSDimitry Andric     // Treat ".<number>" as a valid identifier in this context.
21575ffd83dbSDimitry Andric     IDVal = getTok().getString();
21585ffd83dbSDimitry Andric     Lex(); // always eat a token
21595ffd83dbSDimitry Andric     if (!IDVal.startswith("."))
21605ffd83dbSDimitry Andric       return Error(IDLoc, "unexpected token at start of statement");
2161fe6060f1SDimitry Andric   } else if (parseIdentifier(IDVal, StartOfStatement)) {
21625ffd83dbSDimitry Andric     if (!TheCondState.Ignore) {
21635ffd83dbSDimitry Andric       Lex(); // always eat a token
21645ffd83dbSDimitry Andric       return Error(IDLoc, "unexpected token at start of statement");
21655ffd83dbSDimitry Andric     }
21665ffd83dbSDimitry Andric     IDVal = "";
21675ffd83dbSDimitry Andric   }
21685ffd83dbSDimitry Andric 
21695ffd83dbSDimitry Andric   // Handle conditional assembly here before checking for skipping.  We
21705ffd83dbSDimitry Andric   // have to do this so that .endif isn't skipped in a ".if 0" block for
21715ffd83dbSDimitry Andric   // example.
21725ffd83dbSDimitry Andric   StringMap<DirectiveKind>::const_iterator DirKindIt =
21735ffd83dbSDimitry Andric       DirectiveKindMap.find(IDVal.lower());
21745ffd83dbSDimitry Andric   DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
21755ffd83dbSDimitry Andric                               ? DK_NO_DIRECTIVE
21765ffd83dbSDimitry Andric                               : DirKindIt->getValue();
21775ffd83dbSDimitry Andric   switch (DirKind) {
21785ffd83dbSDimitry Andric   default:
21795ffd83dbSDimitry Andric     break;
21805ffd83dbSDimitry Andric   case DK_IF:
21815ffd83dbSDimitry Andric   case DK_IFE:
21825ffd83dbSDimitry Andric     return parseDirectiveIf(IDLoc, DirKind);
21835ffd83dbSDimitry Andric   case DK_IFB:
21845ffd83dbSDimitry Andric     return parseDirectiveIfb(IDLoc, true);
21855ffd83dbSDimitry Andric   case DK_IFNB:
21865ffd83dbSDimitry Andric     return parseDirectiveIfb(IDLoc, false);
21875ffd83dbSDimitry Andric   case DK_IFDEF:
21885ffd83dbSDimitry Andric     return parseDirectiveIfdef(IDLoc, true);
21895ffd83dbSDimitry Andric   case DK_IFNDEF:
21905ffd83dbSDimitry Andric     return parseDirectiveIfdef(IDLoc, false);
21915ffd83dbSDimitry Andric   case DK_IFDIF:
21925ffd83dbSDimitry Andric     return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false,
21935ffd83dbSDimitry Andric                                /*CaseInsensitive=*/false);
21945ffd83dbSDimitry Andric   case DK_IFDIFI:
21955ffd83dbSDimitry Andric     return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false,
21965ffd83dbSDimitry Andric                                /*CaseInsensitive=*/true);
21975ffd83dbSDimitry Andric   case DK_IFIDN:
21985ffd83dbSDimitry Andric     return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true,
21995ffd83dbSDimitry Andric                                /*CaseInsensitive=*/false);
22005ffd83dbSDimitry Andric   case DK_IFIDNI:
22015ffd83dbSDimitry Andric     return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true,
22025ffd83dbSDimitry Andric                                /*CaseInsensitive=*/true);
22035ffd83dbSDimitry Andric   case DK_ELSEIF:
22045ffd83dbSDimitry Andric   case DK_ELSEIFE:
22055ffd83dbSDimitry Andric     return parseDirectiveElseIf(IDLoc, DirKind);
22065ffd83dbSDimitry Andric   case DK_ELSEIFB:
22075ffd83dbSDimitry Andric     return parseDirectiveElseIfb(IDLoc, true);
22085ffd83dbSDimitry Andric   case DK_ELSEIFNB:
22095ffd83dbSDimitry Andric     return parseDirectiveElseIfb(IDLoc, false);
22105ffd83dbSDimitry Andric   case DK_ELSEIFDEF:
22115ffd83dbSDimitry Andric     return parseDirectiveElseIfdef(IDLoc, true);
22125ffd83dbSDimitry Andric   case DK_ELSEIFNDEF:
22135ffd83dbSDimitry Andric     return parseDirectiveElseIfdef(IDLoc, false);
22145ffd83dbSDimitry Andric   case DK_ELSEIFDIF:
22155ffd83dbSDimitry Andric     return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false,
22165ffd83dbSDimitry Andric                                    /*CaseInsensitive=*/false);
22175ffd83dbSDimitry Andric   case DK_ELSEIFDIFI:
22185ffd83dbSDimitry Andric     return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false,
22195ffd83dbSDimitry Andric                                    /*CaseInsensitive=*/true);
22205ffd83dbSDimitry Andric   case DK_ELSEIFIDN:
22215ffd83dbSDimitry Andric     return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true,
22225ffd83dbSDimitry Andric                                    /*CaseInsensitive=*/false);
22235ffd83dbSDimitry Andric   case DK_ELSEIFIDNI:
22245ffd83dbSDimitry Andric     return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true,
22255ffd83dbSDimitry Andric                                    /*CaseInsensitive=*/true);
22265ffd83dbSDimitry Andric   case DK_ELSE:
22275ffd83dbSDimitry Andric     return parseDirectiveElse(IDLoc);
22285ffd83dbSDimitry Andric   case DK_ENDIF:
22295ffd83dbSDimitry Andric     return parseDirectiveEndIf(IDLoc);
22305ffd83dbSDimitry Andric   }
22315ffd83dbSDimitry Andric 
22325ffd83dbSDimitry Andric   // Ignore the statement if in the middle of inactive conditional
22335ffd83dbSDimitry Andric   // (e.g. ".if 0").
22345ffd83dbSDimitry Andric   if (TheCondState.Ignore) {
22355ffd83dbSDimitry Andric     eatToEndOfStatement();
22365ffd83dbSDimitry Andric     return false;
22375ffd83dbSDimitry Andric   }
22385ffd83dbSDimitry Andric 
22395ffd83dbSDimitry Andric   // FIXME: Recurse on local labels?
22405ffd83dbSDimitry Andric 
22415ffd83dbSDimitry Andric   // See what kind of statement we have.
22425ffd83dbSDimitry Andric   switch (Lexer.getKind()) {
22435ffd83dbSDimitry Andric   case AsmToken::Colon: {
22445ffd83dbSDimitry Andric     if (!getTargetParser().isLabel(ID))
22455ffd83dbSDimitry Andric       break;
22465ffd83dbSDimitry Andric     if (checkForValidSection())
22475ffd83dbSDimitry Andric       return true;
22485ffd83dbSDimitry Andric 
22495ffd83dbSDimitry Andric     // identifier ':'   -> Label.
22505ffd83dbSDimitry Andric     Lex();
22515ffd83dbSDimitry Andric 
22525ffd83dbSDimitry Andric     // Diagnose attempt to use '.' as a label.
22535ffd83dbSDimitry Andric     if (IDVal == ".")
22545ffd83dbSDimitry Andric       return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
22555ffd83dbSDimitry Andric 
22565ffd83dbSDimitry Andric     // Diagnose attempt to use a variable as a label.
22575ffd83dbSDimitry Andric     //
22585ffd83dbSDimitry Andric     // FIXME: Diagnostics. Note the location of the definition as a label.
22595ffd83dbSDimitry Andric     // FIXME: This doesn't diagnose assignment to a symbol which has been
22605ffd83dbSDimitry Andric     // implicitly marked as external.
22615ffd83dbSDimitry Andric     MCSymbol *Sym;
22625ffd83dbSDimitry Andric     if (LocalLabelVal == -1) {
22635ffd83dbSDimitry Andric       if (ParsingMSInlineAsm && SI) {
22645ffd83dbSDimitry Andric         StringRef RewrittenLabel =
22655ffd83dbSDimitry Andric             SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
22665ffd83dbSDimitry Andric         assert(!RewrittenLabel.empty() &&
22675ffd83dbSDimitry Andric                "We should have an internal name here.");
22685ffd83dbSDimitry Andric         Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),
22695ffd83dbSDimitry Andric                                        RewrittenLabel);
22705ffd83dbSDimitry Andric         IDVal = RewrittenLabel;
22715ffd83dbSDimitry Andric       }
22725ffd83dbSDimitry Andric       Sym = getContext().getOrCreateSymbol(IDVal);
22735ffd83dbSDimitry Andric     } else
22745ffd83dbSDimitry Andric       Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal);
22755ffd83dbSDimitry Andric     // End of Labels should be treated as end of line for lexing
22765ffd83dbSDimitry Andric     // purposes but that information is not available to the Lexer who
22775ffd83dbSDimitry Andric     // does not understand Labels. This may cause us to see a Hash
22785ffd83dbSDimitry Andric     // here instead of a preprocessor line comment.
22795ffd83dbSDimitry Andric     if (getTok().is(AsmToken::Hash)) {
2280e8d8bef9SDimitry Andric       std::string CommentStr = parseStringTo(AsmToken::EndOfStatement);
22815ffd83dbSDimitry Andric       Lexer.Lex();
22825ffd83dbSDimitry Andric       Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
22835ffd83dbSDimitry Andric     }
22845ffd83dbSDimitry Andric 
22855ffd83dbSDimitry Andric     // Consume any end of statement token, if present, to avoid spurious
22865ffd83dbSDimitry Andric     // AddBlankLine calls().
22875ffd83dbSDimitry Andric     if (getTok().is(AsmToken::EndOfStatement)) {
22885ffd83dbSDimitry Andric       Lex();
22895ffd83dbSDimitry Andric     }
22905ffd83dbSDimitry Andric 
22915ffd83dbSDimitry Andric     getTargetParser().doBeforeLabelEmit(Sym);
22925ffd83dbSDimitry Andric 
22935ffd83dbSDimitry Andric     // Emit the label.
22945ffd83dbSDimitry Andric     if (!getTargetParser().isParsingMSInlineAsm())
22955ffd83dbSDimitry Andric       Out.emitLabel(Sym, IDLoc);
22965ffd83dbSDimitry Andric 
22975ffd83dbSDimitry Andric     // If we are generating dwarf for assembly source files then gather the
22985ffd83dbSDimitry Andric     // info to make a dwarf label entry for this label if needed.
22995ffd83dbSDimitry Andric     if (enabledGenDwarfForAssembly())
23005ffd83dbSDimitry Andric       MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
23015ffd83dbSDimitry Andric                                  IDLoc);
23025ffd83dbSDimitry Andric 
23035ffd83dbSDimitry Andric     getTargetParser().onLabelParsed(Sym);
23045ffd83dbSDimitry Andric 
23055ffd83dbSDimitry Andric     return false;
23065ffd83dbSDimitry Andric   }
23075ffd83dbSDimitry Andric 
23085ffd83dbSDimitry Andric   default: // Normal instruction or directive.
23095ffd83dbSDimitry Andric     break;
23105ffd83dbSDimitry Andric   }
23115ffd83dbSDimitry Andric 
23125ffd83dbSDimitry Andric   // If macros are enabled, check to see if this is a macro instantiation.
2313e8d8bef9SDimitry Andric   if (const MCAsmMacro *M = getContext().lookupMacro(IDVal.lower())) {
23145ffd83dbSDimitry Andric     return handleMacroEntry(M, IDLoc);
23155ffd83dbSDimitry Andric   }
23165ffd83dbSDimitry Andric 
23175ffd83dbSDimitry Andric   // Otherwise, we have a normal instruction or directive.
23185ffd83dbSDimitry Andric 
23195ffd83dbSDimitry Andric   if (DirKind != DK_NO_DIRECTIVE) {
23205ffd83dbSDimitry Andric     // There are several entities interested in parsing directives:
23215ffd83dbSDimitry Andric     //
23225ffd83dbSDimitry Andric     // 1. Asm parser extensions. For example, platform-specific parsers
23235ffd83dbSDimitry Andric     //    (like the ELF parser) register themselves as extensions.
23245ffd83dbSDimitry Andric     // 2. The target-specific assembly parser. Some directives are target
23255ffd83dbSDimitry Andric     //    specific or may potentially behave differently on certain targets.
23265ffd83dbSDimitry Andric     // 3. The generic directive parser implemented by this class. These are
23275ffd83dbSDimitry Andric     //    all the directives that behave in a target and platform independent
23285ffd83dbSDimitry Andric     //    manner, or at least have a default behavior that's shared between
23295ffd83dbSDimitry Andric     //    all targets and platforms.
23305ffd83dbSDimitry Andric 
23315ffd83dbSDimitry Andric     getTargetParser().flushPendingInstructions(getStreamer());
23325ffd83dbSDimitry Andric 
23335ffd83dbSDimitry Andric     // Special-case handling of structure-end directives at higher priority,
23345ffd83dbSDimitry Andric     // since ENDS is overloaded as a segment-end directive.
2335fe6060f1SDimitry Andric     if (IDVal.equals_insensitive("ends") && StructInProgress.size() > 1 &&
23365ffd83dbSDimitry Andric         getTok().is(AsmToken::EndOfStatement)) {
23375ffd83dbSDimitry Andric       return parseDirectiveNestedEnds();
23385ffd83dbSDimitry Andric     }
23395ffd83dbSDimitry Andric 
23405ffd83dbSDimitry Andric     // First, check the extension directive map to see if any extension has
23415ffd83dbSDimitry Andric     // registered itself to parse this directive.
23425ffd83dbSDimitry Andric     std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
23435ffd83dbSDimitry Andric         ExtensionDirectiveMap.lookup(IDVal.lower());
23445ffd83dbSDimitry Andric     if (Handler.first)
23455ffd83dbSDimitry Andric       return (*Handler.second)(Handler.first, IDVal, IDLoc);
23465ffd83dbSDimitry Andric 
23475ffd83dbSDimitry Andric     // Next, let the target-specific assembly parser try.
23485ffd83dbSDimitry Andric     SMLoc StartTokLoc = getTok().getLoc();
23495ffd83dbSDimitry Andric     bool TPDirectiveReturn =
23505ffd83dbSDimitry Andric         ID.is(AsmToken::Identifier) && getTargetParser().ParseDirective(ID);
23515ffd83dbSDimitry Andric 
23525ffd83dbSDimitry Andric     if (hasPendingError())
23535ffd83dbSDimitry Andric       return true;
23545ffd83dbSDimitry Andric     // Currently the return value should be true if we are
23555ffd83dbSDimitry Andric     // uninterested but as this is at odds with the standard parsing
23565ffd83dbSDimitry Andric     // convention (return true = error) we have instances of a parsed
23575ffd83dbSDimitry Andric     // directive that fails returning true as an error. Catch these
23585ffd83dbSDimitry Andric     // cases as best as possible errors here.
23595ffd83dbSDimitry Andric     if (TPDirectiveReturn && StartTokLoc != getTok().getLoc())
23605ffd83dbSDimitry Andric       return true;
23615ffd83dbSDimitry Andric     // Return if we did some parsing or believe we succeeded.
23625ffd83dbSDimitry Andric     if (!TPDirectiveReturn || StartTokLoc != getTok().getLoc())
23635ffd83dbSDimitry Andric       return false;
23645ffd83dbSDimitry Andric 
23655ffd83dbSDimitry Andric     // Finally, if no one else is interested in this directive, it must be
23665ffd83dbSDimitry Andric     // generic and familiar to this class.
23675ffd83dbSDimitry Andric     switch (DirKind) {
23685ffd83dbSDimitry Andric     default:
23695ffd83dbSDimitry Andric       break;
23705ffd83dbSDimitry Andric     case DK_ASCII:
23715ffd83dbSDimitry Andric       return parseDirectiveAscii(IDVal, false);
23725ffd83dbSDimitry Andric     case DK_ASCIZ:
23735ffd83dbSDimitry Andric     case DK_STRING:
23745ffd83dbSDimitry Andric       return parseDirectiveAscii(IDVal, true);
23755ffd83dbSDimitry Andric     case DK_BYTE:
23765ffd83dbSDimitry Andric     case DK_SBYTE:
23775ffd83dbSDimitry Andric     case DK_DB:
23785ffd83dbSDimitry Andric       return parseDirectiveValue(IDVal, 1);
23795ffd83dbSDimitry Andric     case DK_WORD:
23805ffd83dbSDimitry Andric     case DK_SWORD:
23815ffd83dbSDimitry Andric     case DK_DW:
23825ffd83dbSDimitry Andric       return parseDirectiveValue(IDVal, 2);
23835ffd83dbSDimitry Andric     case DK_DWORD:
23845ffd83dbSDimitry Andric     case DK_SDWORD:
23855ffd83dbSDimitry Andric     case DK_DD:
23865ffd83dbSDimitry Andric       return parseDirectiveValue(IDVal, 4);
23875ffd83dbSDimitry Andric     case DK_FWORD:
2388e8d8bef9SDimitry Andric     case DK_DF:
23895ffd83dbSDimitry Andric       return parseDirectiveValue(IDVal, 6);
23905ffd83dbSDimitry Andric     case DK_QWORD:
23915ffd83dbSDimitry Andric     case DK_SQWORD:
23925ffd83dbSDimitry Andric     case DK_DQ:
23935ffd83dbSDimitry Andric       return parseDirectiveValue(IDVal, 8);
23945ffd83dbSDimitry Andric     case DK_REAL4:
2395e8d8bef9SDimitry Andric       return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4);
23965ffd83dbSDimitry Andric     case DK_REAL8:
2397e8d8bef9SDimitry Andric       return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8);
2398e8d8bef9SDimitry Andric     case DK_REAL10:
2399e8d8bef9SDimitry Andric       return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10);
24005ffd83dbSDimitry Andric     case DK_STRUCT:
24015ffd83dbSDimitry Andric     case DK_UNION:
24025ffd83dbSDimitry Andric       return parseDirectiveNestedStruct(IDVal, DirKind);
24035ffd83dbSDimitry Andric     case DK_ENDS:
24045ffd83dbSDimitry Andric       return parseDirectiveNestedEnds();
24055ffd83dbSDimitry Andric     case DK_ALIGN:
24065ffd83dbSDimitry Andric       return parseDirectiveAlign();
2407fe6060f1SDimitry Andric     case DK_EVEN:
2408fe6060f1SDimitry Andric       return parseDirectiveEven();
24095ffd83dbSDimitry Andric     case DK_ORG:
24105ffd83dbSDimitry Andric       return parseDirectiveOrg();
24115ffd83dbSDimitry Andric     case DK_EXTERN:
24125ffd83dbSDimitry Andric       eatToEndOfStatement(); // .extern is the default, ignore it.
24135ffd83dbSDimitry Andric       return false;
24145ffd83dbSDimitry Andric     case DK_PUBLIC:
24155ffd83dbSDimitry Andric       return parseDirectiveSymbolAttribute(MCSA_Global);
24165ffd83dbSDimitry Andric     case DK_COMM:
24175ffd83dbSDimitry Andric       return parseDirectiveComm(/*IsLocal=*/false);
24185ffd83dbSDimitry Andric     case DK_COMMENT:
24195ffd83dbSDimitry Andric       return parseDirectiveComment(IDLoc);
24205ffd83dbSDimitry Andric     case DK_INCLUDE:
24215ffd83dbSDimitry Andric       return parseDirectiveInclude();
2422e8d8bef9SDimitry Andric     case DK_REPEAT:
2423e8d8bef9SDimitry Andric       return parseDirectiveRepeat(IDLoc, IDVal);
2424e8d8bef9SDimitry Andric     case DK_WHILE:
2425e8d8bef9SDimitry Andric       return parseDirectiveWhile(IDLoc);
2426e8d8bef9SDimitry Andric     case DK_FOR:
2427e8d8bef9SDimitry Andric       return parseDirectiveFor(IDLoc, IDVal);
2428e8d8bef9SDimitry Andric     case DK_FORC:
2429e8d8bef9SDimitry Andric       return parseDirectiveForc(IDLoc, IDVal);
24305ffd83dbSDimitry Andric     case DK_FILE:
24315ffd83dbSDimitry Andric       return parseDirectiveFile(IDLoc);
24325ffd83dbSDimitry Andric     case DK_LINE:
24335ffd83dbSDimitry Andric       return parseDirectiveLine();
24345ffd83dbSDimitry Andric     case DK_LOC:
24355ffd83dbSDimitry Andric       return parseDirectiveLoc();
24365ffd83dbSDimitry Andric     case DK_STABS:
24375ffd83dbSDimitry Andric       return parseDirectiveStabs();
24385ffd83dbSDimitry Andric     case DK_CV_FILE:
24395ffd83dbSDimitry Andric       return parseDirectiveCVFile();
24405ffd83dbSDimitry Andric     case DK_CV_FUNC_ID:
24415ffd83dbSDimitry Andric       return parseDirectiveCVFuncId();
24425ffd83dbSDimitry Andric     case DK_CV_INLINE_SITE_ID:
24435ffd83dbSDimitry Andric       return parseDirectiveCVInlineSiteId();
24445ffd83dbSDimitry Andric     case DK_CV_LOC:
24455ffd83dbSDimitry Andric       return parseDirectiveCVLoc();
24465ffd83dbSDimitry Andric     case DK_CV_LINETABLE:
24475ffd83dbSDimitry Andric       return parseDirectiveCVLinetable();
24485ffd83dbSDimitry Andric     case DK_CV_INLINE_LINETABLE:
24495ffd83dbSDimitry Andric       return parseDirectiveCVInlineLinetable();
24505ffd83dbSDimitry Andric     case DK_CV_DEF_RANGE:
24515ffd83dbSDimitry Andric       return parseDirectiveCVDefRange();
24525ffd83dbSDimitry Andric     case DK_CV_STRING:
24535ffd83dbSDimitry Andric       return parseDirectiveCVString();
24545ffd83dbSDimitry Andric     case DK_CV_STRINGTABLE:
24555ffd83dbSDimitry Andric       return parseDirectiveCVStringTable();
24565ffd83dbSDimitry Andric     case DK_CV_FILECHECKSUMS:
24575ffd83dbSDimitry Andric       return parseDirectiveCVFileChecksums();
24585ffd83dbSDimitry Andric     case DK_CV_FILECHECKSUM_OFFSET:
24595ffd83dbSDimitry Andric       return parseDirectiveCVFileChecksumOffset();
24605ffd83dbSDimitry Andric     case DK_CV_FPO_DATA:
24615ffd83dbSDimitry Andric       return parseDirectiveCVFPOData();
24625ffd83dbSDimitry Andric     case DK_CFI_SECTIONS:
24635ffd83dbSDimitry Andric       return parseDirectiveCFISections();
24645ffd83dbSDimitry Andric     case DK_CFI_STARTPROC:
24655ffd83dbSDimitry Andric       return parseDirectiveCFIStartProc();
24665ffd83dbSDimitry Andric     case DK_CFI_ENDPROC:
24675ffd83dbSDimitry Andric       return parseDirectiveCFIEndProc();
24685ffd83dbSDimitry Andric     case DK_CFI_DEF_CFA:
24695ffd83dbSDimitry Andric       return parseDirectiveCFIDefCfa(IDLoc);
24705ffd83dbSDimitry Andric     case DK_CFI_DEF_CFA_OFFSET:
24715ffd83dbSDimitry Andric       return parseDirectiveCFIDefCfaOffset();
24725ffd83dbSDimitry Andric     case DK_CFI_ADJUST_CFA_OFFSET:
24735ffd83dbSDimitry Andric       return parseDirectiveCFIAdjustCfaOffset();
24745ffd83dbSDimitry Andric     case DK_CFI_DEF_CFA_REGISTER:
24755ffd83dbSDimitry Andric       return parseDirectiveCFIDefCfaRegister(IDLoc);
24765ffd83dbSDimitry Andric     case DK_CFI_OFFSET:
24775ffd83dbSDimitry Andric       return parseDirectiveCFIOffset(IDLoc);
24785ffd83dbSDimitry Andric     case DK_CFI_REL_OFFSET:
24795ffd83dbSDimitry Andric       return parseDirectiveCFIRelOffset(IDLoc);
24805ffd83dbSDimitry Andric     case DK_CFI_PERSONALITY:
24815ffd83dbSDimitry Andric       return parseDirectiveCFIPersonalityOrLsda(true);
24825ffd83dbSDimitry Andric     case DK_CFI_LSDA:
24835ffd83dbSDimitry Andric       return parseDirectiveCFIPersonalityOrLsda(false);
24845ffd83dbSDimitry Andric     case DK_CFI_REMEMBER_STATE:
24855ffd83dbSDimitry Andric       return parseDirectiveCFIRememberState();
24865ffd83dbSDimitry Andric     case DK_CFI_RESTORE_STATE:
24875ffd83dbSDimitry Andric       return parseDirectiveCFIRestoreState();
24885ffd83dbSDimitry Andric     case DK_CFI_SAME_VALUE:
24895ffd83dbSDimitry Andric       return parseDirectiveCFISameValue(IDLoc);
24905ffd83dbSDimitry Andric     case DK_CFI_RESTORE:
24915ffd83dbSDimitry Andric       return parseDirectiveCFIRestore(IDLoc);
24925ffd83dbSDimitry Andric     case DK_CFI_ESCAPE:
24935ffd83dbSDimitry Andric       return parseDirectiveCFIEscape();
24945ffd83dbSDimitry Andric     case DK_CFI_RETURN_COLUMN:
24955ffd83dbSDimitry Andric       return parseDirectiveCFIReturnColumn(IDLoc);
24965ffd83dbSDimitry Andric     case DK_CFI_SIGNAL_FRAME:
24975ffd83dbSDimitry Andric       return parseDirectiveCFISignalFrame();
24985ffd83dbSDimitry Andric     case DK_CFI_UNDEFINED:
24995ffd83dbSDimitry Andric       return parseDirectiveCFIUndefined(IDLoc);
25005ffd83dbSDimitry Andric     case DK_CFI_REGISTER:
25015ffd83dbSDimitry Andric       return parseDirectiveCFIRegister(IDLoc);
25025ffd83dbSDimitry Andric     case DK_CFI_WINDOW_SAVE:
25035ffd83dbSDimitry Andric       return parseDirectiveCFIWindowSave();
25045ffd83dbSDimitry Andric     case DK_EXITM:
2505e8d8bef9SDimitry Andric       Info.ExitValue = "";
2506e8d8bef9SDimitry Andric       return parseDirectiveExitMacro(IDLoc, IDVal, *Info.ExitValue);
25075ffd83dbSDimitry Andric     case DK_ENDM:
2508e8d8bef9SDimitry Andric       Info.ExitValue = "";
25095ffd83dbSDimitry Andric       return parseDirectiveEndMacro(IDVal);
2510e8d8bef9SDimitry Andric     case DK_PURGE:
25115ffd83dbSDimitry Andric       return parseDirectivePurgeMacro(IDLoc);
25125ffd83dbSDimitry Andric     case DK_END:
25135ffd83dbSDimitry Andric       return parseDirectiveEnd(IDLoc);
25145ffd83dbSDimitry Andric     case DK_ERR:
25155ffd83dbSDimitry Andric       return parseDirectiveError(IDLoc);
25165ffd83dbSDimitry Andric     case DK_ERRB:
25175ffd83dbSDimitry Andric       return parseDirectiveErrorIfb(IDLoc, true);
25185ffd83dbSDimitry Andric     case DK_ERRNB:
25195ffd83dbSDimitry Andric       return parseDirectiveErrorIfb(IDLoc, false);
25205ffd83dbSDimitry Andric     case DK_ERRDEF:
25215ffd83dbSDimitry Andric       return parseDirectiveErrorIfdef(IDLoc, true);
25225ffd83dbSDimitry Andric     case DK_ERRNDEF:
25235ffd83dbSDimitry Andric       return parseDirectiveErrorIfdef(IDLoc, false);
25245ffd83dbSDimitry Andric     case DK_ERRDIF:
25255ffd83dbSDimitry Andric       return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false,
25265ffd83dbSDimitry Andric                                       /*CaseInsensitive=*/false);
25275ffd83dbSDimitry Andric     case DK_ERRDIFI:
25285ffd83dbSDimitry Andric       return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false,
25295ffd83dbSDimitry Andric                                       /*CaseInsensitive=*/true);
25305ffd83dbSDimitry Andric     case DK_ERRIDN:
25315ffd83dbSDimitry Andric       return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true,
25325ffd83dbSDimitry Andric                                       /*CaseInsensitive=*/false);
25335ffd83dbSDimitry Andric     case DK_ERRIDNI:
25345ffd83dbSDimitry Andric       return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true,
25355ffd83dbSDimitry Andric                                       /*CaseInsensitive=*/true);
25365ffd83dbSDimitry Andric     case DK_ERRE:
25375ffd83dbSDimitry Andric       return parseDirectiveErrorIfe(IDLoc, true);
25385ffd83dbSDimitry Andric     case DK_ERRNZ:
25395ffd83dbSDimitry Andric       return parseDirectiveErrorIfe(IDLoc, false);
2540e8d8bef9SDimitry Andric     case DK_RADIX:
2541e8d8bef9SDimitry Andric       return parseDirectiveRadix(IDLoc);
2542fe6060f1SDimitry Andric     case DK_ECHO:
2543fe6060f1SDimitry Andric       return parseDirectiveEcho(IDLoc);
25445ffd83dbSDimitry Andric     }
25455ffd83dbSDimitry Andric 
25465ffd83dbSDimitry Andric     return Error(IDLoc, "unknown directive");
25475ffd83dbSDimitry Andric   }
25485ffd83dbSDimitry Andric 
25495ffd83dbSDimitry Andric   // We also check if this is allocating memory with user-defined type.
25505ffd83dbSDimitry Andric   auto IDIt = Structs.find(IDVal.lower());
25515ffd83dbSDimitry Andric   if (IDIt != Structs.end())
25525ffd83dbSDimitry Andric     return parseDirectiveStructValue(/*Structure=*/IDIt->getValue(), IDVal,
25535ffd83dbSDimitry Andric                                      IDLoc);
25545ffd83dbSDimitry Andric 
25555ffd83dbSDimitry Andric   // Non-conditional Microsoft directives sometimes follow their first argument.
25565ffd83dbSDimitry Andric   const AsmToken nextTok = getTok();
25575ffd83dbSDimitry Andric   const StringRef nextVal = nextTok.getString();
25585ffd83dbSDimitry Andric   const SMLoc nextLoc = nextTok.getLoc();
25595ffd83dbSDimitry Andric 
2560fe6060f1SDimitry Andric   const AsmToken afterNextTok = peekTok();
2561fe6060f1SDimitry Andric 
25625ffd83dbSDimitry Andric   // There are several entities interested in parsing infix directives:
25635ffd83dbSDimitry Andric   //
25645ffd83dbSDimitry Andric   // 1. Asm parser extensions. For example, platform-specific parsers
25655ffd83dbSDimitry Andric   //    (like the ELF parser) register themselves as extensions.
25665ffd83dbSDimitry Andric   // 2. The generic directive parser implemented by this class. These are
25675ffd83dbSDimitry Andric   //    all the directives that behave in a target and platform independent
25685ffd83dbSDimitry Andric   //    manner, or at least have a default behavior that's shared between
25695ffd83dbSDimitry Andric   //    all targets and platforms.
25705ffd83dbSDimitry Andric 
25715ffd83dbSDimitry Andric   getTargetParser().flushPendingInstructions(getStreamer());
25725ffd83dbSDimitry Andric 
25735ffd83dbSDimitry Andric   // Special-case handling of structure-end directives at higher priority, since
25745ffd83dbSDimitry Andric   // ENDS is overloaded as a segment-end directive.
2575fe6060f1SDimitry Andric   if (nextVal.equals_insensitive("ends") && StructInProgress.size() == 1) {
25765ffd83dbSDimitry Andric     Lex();
25775ffd83dbSDimitry Andric     return parseDirectiveEnds(IDVal, IDLoc);
25785ffd83dbSDimitry Andric   }
25795ffd83dbSDimitry Andric 
25805ffd83dbSDimitry Andric   // First, check the extension directive map to see if any extension has
25815ffd83dbSDimitry Andric   // registered itself to parse this directive.
25825ffd83dbSDimitry Andric   std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
25835ffd83dbSDimitry Andric       ExtensionDirectiveMap.lookup(nextVal.lower());
25845ffd83dbSDimitry Andric   if (Handler.first) {
25855ffd83dbSDimitry Andric     Lex();
25865ffd83dbSDimitry Andric     Lexer.UnLex(ID);
25875ffd83dbSDimitry Andric     return (*Handler.second)(Handler.first, nextVal, nextLoc);
25885ffd83dbSDimitry Andric   }
25895ffd83dbSDimitry Andric 
25905ffd83dbSDimitry Andric   // If no one else is interested in this directive, it must be
25915ffd83dbSDimitry Andric   // generic and familiar to this class.
25925ffd83dbSDimitry Andric   DirKindIt = DirectiveKindMap.find(nextVal.lower());
25935ffd83dbSDimitry Andric   DirKind = (DirKindIt == DirectiveKindMap.end())
25945ffd83dbSDimitry Andric                 ? DK_NO_DIRECTIVE
25955ffd83dbSDimitry Andric                 : DirKindIt->getValue();
25965ffd83dbSDimitry Andric   switch (DirKind) {
25975ffd83dbSDimitry Andric   default:
25985ffd83dbSDimitry Andric     break;
25995ffd83dbSDimitry Andric   case DK_ASSIGN:
26005ffd83dbSDimitry Andric   case DK_EQU:
26015ffd83dbSDimitry Andric   case DK_TEXTEQU:
26025ffd83dbSDimitry Andric     Lex();
2603fe6060f1SDimitry Andric     return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
26045ffd83dbSDimitry Andric   case DK_BYTE:
2605fe6060f1SDimitry Andric     if (afterNextTok.is(AsmToken::Identifier) &&
2606fe6060f1SDimitry Andric         afterNextTok.getString().equals_insensitive("ptr")) {
2607fe6060f1SDimitry Andric       // Size directive; part of an instruction.
2608fe6060f1SDimitry Andric       break;
2609fe6060f1SDimitry Andric     }
2610fe6060f1SDimitry Andric     LLVM_FALLTHROUGH;
2611e8d8bef9SDimitry Andric   case DK_SBYTE:
26125ffd83dbSDimitry Andric   case DK_DB:
26135ffd83dbSDimitry Andric     Lex();
26145ffd83dbSDimitry Andric     return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc);
26155ffd83dbSDimitry Andric   case DK_WORD:
2616fe6060f1SDimitry Andric     if (afterNextTok.is(AsmToken::Identifier) &&
2617fe6060f1SDimitry Andric         afterNextTok.getString().equals_insensitive("ptr")) {
2618fe6060f1SDimitry Andric       // Size directive; part of an instruction.
2619fe6060f1SDimitry Andric       break;
2620fe6060f1SDimitry Andric     }
2621fe6060f1SDimitry Andric     LLVM_FALLTHROUGH;
2622e8d8bef9SDimitry Andric   case DK_SWORD:
26235ffd83dbSDimitry Andric   case DK_DW:
26245ffd83dbSDimitry Andric     Lex();
26255ffd83dbSDimitry Andric     return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc);
26265ffd83dbSDimitry Andric   case DK_DWORD:
2627fe6060f1SDimitry Andric     if (afterNextTok.is(AsmToken::Identifier) &&
2628fe6060f1SDimitry Andric         afterNextTok.getString().equals_insensitive("ptr")) {
2629fe6060f1SDimitry Andric       // Size directive; part of an instruction.
2630fe6060f1SDimitry Andric       break;
2631fe6060f1SDimitry Andric     }
2632fe6060f1SDimitry Andric     LLVM_FALLTHROUGH;
2633e8d8bef9SDimitry Andric   case DK_SDWORD:
26345ffd83dbSDimitry Andric   case DK_DD:
26355ffd83dbSDimitry Andric     Lex();
26365ffd83dbSDimitry Andric     return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc);
26375ffd83dbSDimitry Andric   case DK_FWORD:
2638fe6060f1SDimitry Andric     if (afterNextTok.is(AsmToken::Identifier) &&
2639fe6060f1SDimitry Andric         afterNextTok.getString().equals_insensitive("ptr")) {
2640fe6060f1SDimitry Andric       // Size directive; part of an instruction.
2641fe6060f1SDimitry Andric       break;
2642fe6060f1SDimitry Andric     }
2643fe6060f1SDimitry Andric     LLVM_FALLTHROUGH;
2644e8d8bef9SDimitry Andric   case DK_DF:
26455ffd83dbSDimitry Andric     Lex();
26465ffd83dbSDimitry Andric     return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc);
26475ffd83dbSDimitry Andric   case DK_QWORD:
2648fe6060f1SDimitry Andric     if (afterNextTok.is(AsmToken::Identifier) &&
2649fe6060f1SDimitry Andric         afterNextTok.getString().equals_insensitive("ptr")) {
2650fe6060f1SDimitry Andric       // Size directive; part of an instruction.
2651fe6060f1SDimitry Andric       break;
2652fe6060f1SDimitry Andric     }
2653fe6060f1SDimitry Andric     LLVM_FALLTHROUGH;
2654e8d8bef9SDimitry Andric   case DK_SQWORD:
26555ffd83dbSDimitry Andric   case DK_DQ:
26565ffd83dbSDimitry Andric     Lex();
26575ffd83dbSDimitry Andric     return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc);
26585ffd83dbSDimitry Andric   case DK_REAL4:
26595ffd83dbSDimitry Andric     Lex();
2660e8d8bef9SDimitry Andric     return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), 4,
2661e8d8bef9SDimitry Andric                                         IDVal, IDLoc);
26625ffd83dbSDimitry Andric   case DK_REAL8:
26635ffd83dbSDimitry Andric     Lex();
2664e8d8bef9SDimitry Andric     return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8,
2665e8d8bef9SDimitry Andric                                         IDVal, IDLoc);
2666e8d8bef9SDimitry Andric   case DK_REAL10:
2667e8d8bef9SDimitry Andric     Lex();
2668e8d8bef9SDimitry Andric     return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(),
2669e8d8bef9SDimitry Andric                                         10, IDVal, IDLoc);
26705ffd83dbSDimitry Andric   case DK_STRUCT:
26715ffd83dbSDimitry Andric   case DK_UNION:
26725ffd83dbSDimitry Andric     Lex();
26735ffd83dbSDimitry Andric     return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc);
26745ffd83dbSDimitry Andric   case DK_ENDS:
26755ffd83dbSDimitry Andric     Lex();
26765ffd83dbSDimitry Andric     return parseDirectiveEnds(IDVal, IDLoc);
2677e8d8bef9SDimitry Andric   case DK_MACRO:
2678e8d8bef9SDimitry Andric     Lex();
2679e8d8bef9SDimitry Andric     return parseDirectiveMacro(IDVal, IDLoc);
26805ffd83dbSDimitry Andric   }
26815ffd83dbSDimitry Andric 
26825ffd83dbSDimitry Andric   // Finally, we check if this is allocating a variable with user-defined type.
26835ffd83dbSDimitry Andric   auto NextIt = Structs.find(nextVal.lower());
26845ffd83dbSDimitry Andric   if (NextIt != Structs.end()) {
26855ffd83dbSDimitry Andric     Lex();
26865ffd83dbSDimitry Andric     return parseDirectiveNamedStructValue(/*Structure=*/NextIt->getValue(),
26875ffd83dbSDimitry Andric                                           nextVal, nextLoc, IDVal);
26885ffd83dbSDimitry Andric   }
26895ffd83dbSDimitry Andric 
26905ffd83dbSDimitry Andric   // __asm _emit or __asm __emit
26915ffd83dbSDimitry Andric   if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
26925ffd83dbSDimitry Andric                              IDVal == "_EMIT" || IDVal == "__EMIT"))
26935ffd83dbSDimitry Andric     return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
26945ffd83dbSDimitry Andric 
26955ffd83dbSDimitry Andric   // __asm align
26965ffd83dbSDimitry Andric   if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
26975ffd83dbSDimitry Andric     return parseDirectiveMSAlign(IDLoc, Info);
26985ffd83dbSDimitry Andric 
26995ffd83dbSDimitry Andric   if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
27005ffd83dbSDimitry Andric     Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
27015ffd83dbSDimitry Andric   if (checkForValidSection())
27025ffd83dbSDimitry Andric     return true;
27035ffd83dbSDimitry Andric 
27045ffd83dbSDimitry Andric   // Canonicalize the opcode to lower case.
27055ffd83dbSDimitry Andric   std::string OpcodeStr = IDVal.lower();
27065ffd83dbSDimitry Andric   ParseInstructionInfo IInfo(Info.AsmRewrites);
27075ffd83dbSDimitry Andric   bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,
27085ffd83dbSDimitry Andric                                                           Info.ParsedOperands);
27095ffd83dbSDimitry Andric   Info.ParseError = ParseHadError;
27105ffd83dbSDimitry Andric 
27115ffd83dbSDimitry Andric   // Dump the parsed representation, if requested.
27125ffd83dbSDimitry Andric   if (getShowParsedOperands()) {
27135ffd83dbSDimitry Andric     SmallString<256> Str;
27145ffd83dbSDimitry Andric     raw_svector_ostream OS(Str);
27155ffd83dbSDimitry Andric     OS << "parsed instruction: [";
27165ffd83dbSDimitry Andric     for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
27175ffd83dbSDimitry Andric       if (i != 0)
27185ffd83dbSDimitry Andric         OS << ", ";
27195ffd83dbSDimitry Andric       Info.ParsedOperands[i]->print(OS);
27205ffd83dbSDimitry Andric     }
27215ffd83dbSDimitry Andric     OS << "]";
27225ffd83dbSDimitry Andric 
27235ffd83dbSDimitry Andric     printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
27245ffd83dbSDimitry Andric   }
27255ffd83dbSDimitry Andric 
27265ffd83dbSDimitry Andric   // Fail even if ParseInstruction erroneously returns false.
27275ffd83dbSDimitry Andric   if (hasPendingError() || ParseHadError)
27285ffd83dbSDimitry Andric     return true;
27295ffd83dbSDimitry Andric 
27305ffd83dbSDimitry Andric   // If we are generating dwarf for the current section then generate a .loc
27315ffd83dbSDimitry Andric   // directive for the instruction.
27325ffd83dbSDimitry Andric   if (!ParseHadError && enabledGenDwarfForAssembly() &&
27335ffd83dbSDimitry Andric       getContext().getGenDwarfSectionSyms().count(
27345ffd83dbSDimitry Andric           getStreamer().getCurrentSectionOnly())) {
27355ffd83dbSDimitry Andric     unsigned Line;
27365ffd83dbSDimitry Andric     if (ActiveMacros.empty())
27375ffd83dbSDimitry Andric       Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
27385ffd83dbSDimitry Andric     else
27395ffd83dbSDimitry Andric       Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
27405ffd83dbSDimitry Andric                                    ActiveMacros.front()->ExitBuffer);
27415ffd83dbSDimitry Andric 
27425ffd83dbSDimitry Andric     // If we previously parsed a cpp hash file line comment then make sure the
27435ffd83dbSDimitry Andric     // current Dwarf File is for the CppHashFilename if not then emit the
27445ffd83dbSDimitry Andric     // Dwarf File table for it and adjust the line number for the .loc.
27455ffd83dbSDimitry Andric     if (!CppHashInfo.Filename.empty()) {
27465ffd83dbSDimitry Andric       unsigned FileNumber = getStreamer().emitDwarfFileDirective(
27475ffd83dbSDimitry Andric           0, StringRef(), CppHashInfo.Filename);
27485ffd83dbSDimitry Andric       getContext().setGenDwarfFileNumber(FileNumber);
27495ffd83dbSDimitry Andric 
27505ffd83dbSDimitry Andric       unsigned CppHashLocLineNo =
27515ffd83dbSDimitry Andric         SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
27525ffd83dbSDimitry Andric       Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
27535ffd83dbSDimitry Andric     }
27545ffd83dbSDimitry Andric 
27555ffd83dbSDimitry Andric     getStreamer().emitDwarfLocDirective(
27565ffd83dbSDimitry Andric         getContext().getGenDwarfFileNumber(), Line, 0,
27575ffd83dbSDimitry Andric         DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0,
27585ffd83dbSDimitry Andric         StringRef());
27595ffd83dbSDimitry Andric   }
27605ffd83dbSDimitry Andric 
27615ffd83dbSDimitry Andric   // If parsing succeeded, match the instruction.
27625ffd83dbSDimitry Andric   if (!ParseHadError) {
27635ffd83dbSDimitry Andric     uint64_t ErrorInfo;
27645ffd83dbSDimitry Andric     if (getTargetParser().MatchAndEmitInstruction(
27655ffd83dbSDimitry Andric             IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
27665ffd83dbSDimitry Andric             getTargetParser().isParsingMSInlineAsm()))
27675ffd83dbSDimitry Andric       return true;
27685ffd83dbSDimitry Andric   }
27695ffd83dbSDimitry Andric   return false;
27705ffd83dbSDimitry Andric }
27715ffd83dbSDimitry Andric 
27725ffd83dbSDimitry Andric // Parse and erase curly braces marking block start/end.
27735ffd83dbSDimitry Andric bool MasmParser::parseCurlyBlockScope(
27745ffd83dbSDimitry Andric     SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
27755ffd83dbSDimitry Andric   // Identify curly brace marking block start/end.
27765ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
27775ffd83dbSDimitry Andric     return false;
27785ffd83dbSDimitry Andric 
27795ffd83dbSDimitry Andric   SMLoc StartLoc = Lexer.getLoc();
27805ffd83dbSDimitry Andric   Lex(); // Eat the brace.
27815ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::EndOfStatement))
27825ffd83dbSDimitry Andric     Lex(); // Eat EndOfStatement following the brace.
27835ffd83dbSDimitry Andric 
27845ffd83dbSDimitry Andric   // Erase the block start/end brace from the output asm string.
27855ffd83dbSDimitry Andric   AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
27865ffd83dbSDimitry Andric                                                   StartLoc.getPointer());
27875ffd83dbSDimitry Andric   return true;
27885ffd83dbSDimitry Andric }
27895ffd83dbSDimitry Andric 
27905ffd83dbSDimitry Andric /// parseCppHashLineFilenameComment as this:
27915ffd83dbSDimitry Andric ///   ::= # number "filename"
27925ffd83dbSDimitry Andric bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
27935ffd83dbSDimitry Andric   Lex(); // Eat the hash token.
27945ffd83dbSDimitry Andric   // Lexer only ever emits HashDirective if it fully formed if it's
27955ffd83dbSDimitry Andric   // done the checking already so this is an internal error.
27965ffd83dbSDimitry Andric   assert(getTok().is(AsmToken::Integer) &&
27975ffd83dbSDimitry Andric          "Lexing Cpp line comment: Expected Integer");
27985ffd83dbSDimitry Andric   int64_t LineNumber = getTok().getIntVal();
27995ffd83dbSDimitry Andric   Lex();
28005ffd83dbSDimitry Andric   assert(getTok().is(AsmToken::String) &&
28015ffd83dbSDimitry Andric          "Lexing Cpp line comment: Expected String");
28025ffd83dbSDimitry Andric   StringRef Filename = getTok().getString();
28035ffd83dbSDimitry Andric   Lex();
28045ffd83dbSDimitry Andric 
28055ffd83dbSDimitry Andric   // Get rid of the enclosing quotes.
28065ffd83dbSDimitry Andric   Filename = Filename.substr(1, Filename.size() - 2);
28075ffd83dbSDimitry Andric 
28085ffd83dbSDimitry Andric   // Save the SMLoc, Filename and LineNumber for later use by diagnostics
28095ffd83dbSDimitry Andric   // and possibly DWARF file info.
28105ffd83dbSDimitry Andric   CppHashInfo.Loc = L;
28115ffd83dbSDimitry Andric   CppHashInfo.Filename = Filename;
28125ffd83dbSDimitry Andric   CppHashInfo.LineNumber = LineNumber;
28135ffd83dbSDimitry Andric   CppHashInfo.Buf = CurBuffer;
28145ffd83dbSDimitry Andric   if (FirstCppHashFilename.empty())
28155ffd83dbSDimitry Andric     FirstCppHashFilename = Filename;
28165ffd83dbSDimitry Andric   return false;
28175ffd83dbSDimitry Andric }
28185ffd83dbSDimitry Andric 
28195ffd83dbSDimitry Andric /// will use the last parsed cpp hash line filename comment
28205ffd83dbSDimitry Andric /// for the Filename and LineNo if any in the diagnostic.
28215ffd83dbSDimitry Andric void MasmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
28225ffd83dbSDimitry Andric   const MasmParser *Parser = static_cast<const MasmParser *>(Context);
28235ffd83dbSDimitry Andric   raw_ostream &OS = errs();
28245ffd83dbSDimitry Andric 
28255ffd83dbSDimitry Andric   const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
28265ffd83dbSDimitry Andric   SMLoc DiagLoc = Diag.getLoc();
28275ffd83dbSDimitry Andric   unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
28285ffd83dbSDimitry Andric   unsigned CppHashBuf =
28295ffd83dbSDimitry Andric       Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
28305ffd83dbSDimitry Andric 
28315ffd83dbSDimitry Andric   // Like SourceMgr::printMessage() we need to print the include stack if any
28325ffd83dbSDimitry Andric   // before printing the message.
28335ffd83dbSDimitry Andric   unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
28345ffd83dbSDimitry Andric   if (!Parser->SavedDiagHandler && DiagCurBuffer &&
28355ffd83dbSDimitry Andric       DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
28365ffd83dbSDimitry Andric     SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
28375ffd83dbSDimitry Andric     DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
28385ffd83dbSDimitry Andric   }
28395ffd83dbSDimitry Andric 
28405ffd83dbSDimitry Andric   // If we have not parsed a cpp hash line filename comment or the source
28415ffd83dbSDimitry Andric   // manager changed or buffer changed (like in a nested include) then just
28425ffd83dbSDimitry Andric   // print the normal diagnostic using its Filename and LineNo.
28435ffd83dbSDimitry Andric   if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
28445ffd83dbSDimitry Andric       DiagBuf != CppHashBuf) {
28455ffd83dbSDimitry Andric     if (Parser->SavedDiagHandler)
28465ffd83dbSDimitry Andric       Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
28475ffd83dbSDimitry Andric     else
28485ffd83dbSDimitry Andric       Diag.print(nullptr, OS);
28495ffd83dbSDimitry Andric     return;
28505ffd83dbSDimitry Andric   }
28515ffd83dbSDimitry Andric 
28525ffd83dbSDimitry Andric   // Use the CppHashFilename and calculate a line number based on the
28535ffd83dbSDimitry Andric   // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
28545ffd83dbSDimitry Andric   // for the diagnostic.
28555ffd83dbSDimitry Andric   const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
28565ffd83dbSDimitry Andric 
28575ffd83dbSDimitry Andric   int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
28585ffd83dbSDimitry Andric   int CppHashLocLineNo =
28595ffd83dbSDimitry Andric       Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
28605ffd83dbSDimitry Andric   int LineNo =
28615ffd83dbSDimitry Andric       Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
28625ffd83dbSDimitry Andric 
28635ffd83dbSDimitry Andric   SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
28645ffd83dbSDimitry Andric                        Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
28655ffd83dbSDimitry Andric                        Diag.getLineContents(), Diag.getRanges());
28665ffd83dbSDimitry Andric 
28675ffd83dbSDimitry Andric   if (Parser->SavedDiagHandler)
28685ffd83dbSDimitry Andric     Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
28695ffd83dbSDimitry Andric   else
28705ffd83dbSDimitry Andric     NewDiag.print(nullptr, OS);
28715ffd83dbSDimitry Andric }
28725ffd83dbSDimitry Andric 
2873e8d8bef9SDimitry Andric // This is similar to the IsIdentifierChar function in AsmLexer.cpp, but does
2874e8d8bef9SDimitry Andric // not accept '.'.
2875e8d8bef9SDimitry Andric static bool isMacroParameterChar(char C) {
2876e8d8bef9SDimitry Andric   return isAlnum(C) || C == '_' || C == '$' || C == '@' || C == '?';
28775ffd83dbSDimitry Andric }
28785ffd83dbSDimitry Andric 
28795ffd83dbSDimitry Andric bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
28805ffd83dbSDimitry Andric                              ArrayRef<MCAsmMacroParameter> Parameters,
28815ffd83dbSDimitry Andric                              ArrayRef<MCAsmMacroArgument> A,
2882e8d8bef9SDimitry Andric                              const std::vector<std::string> &Locals, SMLoc L) {
28835ffd83dbSDimitry Andric   unsigned NParameters = Parameters.size();
2884e8d8bef9SDimitry Andric   if (NParameters != A.size())
28855ffd83dbSDimitry Andric     return Error(L, "Wrong number of arguments");
2886e8d8bef9SDimitry Andric   StringMap<std::string> LocalSymbols;
2887e8d8bef9SDimitry Andric   std::string Name;
2888e8d8bef9SDimitry Andric   Name.reserve(6);
2889e8d8bef9SDimitry Andric   for (StringRef Local : Locals) {
2890e8d8bef9SDimitry Andric     raw_string_ostream LocalName(Name);
2891e8d8bef9SDimitry Andric     LocalName << "??"
2892e8d8bef9SDimitry Andric               << format_hex_no_prefix(LocalCounter++, 4, /*Upper=*/true);
2893e8d8bef9SDimitry Andric     LocalSymbols.insert({Local, LocalName.str()});
2894e8d8bef9SDimitry Andric     Name.clear();
2895e8d8bef9SDimitry Andric   }
28965ffd83dbSDimitry Andric 
2897e8d8bef9SDimitry Andric   Optional<char> CurrentQuote;
28985ffd83dbSDimitry Andric   while (!Body.empty()) {
28995ffd83dbSDimitry Andric     // Scan for the next substitution.
29005ffd83dbSDimitry Andric     std::size_t End = Body.size(), Pos = 0;
2901e8d8bef9SDimitry Andric     std::size_t IdentifierPos = End;
29025ffd83dbSDimitry Andric     for (; Pos != End; ++Pos) {
2903e8d8bef9SDimitry Andric       // Find the next possible macro parameter, including preceding a '&'
2904e8d8bef9SDimitry Andric       // inside quotes.
2905e8d8bef9SDimitry Andric       if (Body[Pos] == '&')
29065ffd83dbSDimitry Andric         break;
2907e8d8bef9SDimitry Andric       if (isMacroParameterChar(Body[Pos])) {
2908e8d8bef9SDimitry Andric         if (!CurrentQuote.hasValue())
2909e8d8bef9SDimitry Andric           break;
2910e8d8bef9SDimitry Andric         if (IdentifierPos == End)
2911e8d8bef9SDimitry Andric           IdentifierPos = Pos;
29125ffd83dbSDimitry Andric       } else {
2913e8d8bef9SDimitry Andric         IdentifierPos = End;
29145ffd83dbSDimitry Andric       }
2915e8d8bef9SDimitry Andric 
2916e8d8bef9SDimitry Andric       // Track quotation status
2917e8d8bef9SDimitry Andric       if (!CurrentQuote.hasValue()) {
2918e8d8bef9SDimitry Andric         if (Body[Pos] == '\'' || Body[Pos] == '"')
2919e8d8bef9SDimitry Andric           CurrentQuote = Body[Pos];
2920e8d8bef9SDimitry Andric       } else if (Body[Pos] == CurrentQuote) {
2921e8d8bef9SDimitry Andric         if (Pos + 1 != End && Body[Pos + 1] == CurrentQuote) {
2922e8d8bef9SDimitry Andric           // Escaped quote, and quotes aren't identifier chars; skip
2923e8d8bef9SDimitry Andric           ++Pos;
2924e8d8bef9SDimitry Andric           continue;
2925e8d8bef9SDimitry Andric         } else {
2926e8d8bef9SDimitry Andric           CurrentQuote.reset();
2927e8d8bef9SDimitry Andric         }
2928e8d8bef9SDimitry Andric       }
2929e8d8bef9SDimitry Andric     }
2930e8d8bef9SDimitry Andric     if (IdentifierPos != End) {
2931e8d8bef9SDimitry Andric       // We've recognized an identifier before an apostrophe inside quotes;
2932e8d8bef9SDimitry Andric       // check once to see if we can expand it.
2933e8d8bef9SDimitry Andric       Pos = IdentifierPos;
2934e8d8bef9SDimitry Andric       IdentifierPos = End;
29355ffd83dbSDimitry Andric     }
29365ffd83dbSDimitry Andric 
29375ffd83dbSDimitry Andric     // Add the prefix.
29385ffd83dbSDimitry Andric     OS << Body.slice(0, Pos);
29395ffd83dbSDimitry Andric 
29405ffd83dbSDimitry Andric     // Check if we reached the end.
29415ffd83dbSDimitry Andric     if (Pos == End)
29425ffd83dbSDimitry Andric       break;
29435ffd83dbSDimitry Andric 
2944e8d8bef9SDimitry Andric     unsigned I = Pos;
2945e8d8bef9SDimitry Andric     bool InitialAmpersand = (Body[I] == '&');
2946e8d8bef9SDimitry Andric     if (InitialAmpersand) {
29475ffd83dbSDimitry Andric       ++I;
2948e8d8bef9SDimitry Andric       ++Pos;
2949e8d8bef9SDimitry Andric     }
2950e8d8bef9SDimitry Andric     while (I < End && isMacroParameterChar(Body[I]))
29515ffd83dbSDimitry Andric       ++I;
29525ffd83dbSDimitry Andric 
2953e8d8bef9SDimitry Andric     const char *Begin = Body.data() + Pos;
2954e8d8bef9SDimitry Andric     StringRef Argument(Begin, I - Pos);
2955fe6060f1SDimitry Andric     const std::string ArgumentLower = Argument.lower();
29565ffd83dbSDimitry Andric     unsigned Index = 0;
29575ffd83dbSDimitry Andric 
29585ffd83dbSDimitry Andric     for (; Index < NParameters; ++Index)
2959fe6060f1SDimitry Andric       if (Parameters[Index].Name.equals_insensitive(ArgumentLower))
29605ffd83dbSDimitry Andric         break;
29615ffd83dbSDimitry Andric 
29625ffd83dbSDimitry Andric     if (Index == NParameters) {
2963e8d8bef9SDimitry Andric       if (InitialAmpersand)
2964e8d8bef9SDimitry Andric         OS << '&';
2965fe6060f1SDimitry Andric       auto it = LocalSymbols.find(ArgumentLower);
2966e8d8bef9SDimitry Andric       if (it != LocalSymbols.end())
2967e8d8bef9SDimitry Andric         OS << it->second;
2968e8d8bef9SDimitry Andric       else
2969e8d8bef9SDimitry Andric         OS << Argument;
29705ffd83dbSDimitry Andric       Pos = I;
29715ffd83dbSDimitry Andric     } else {
2972e8d8bef9SDimitry Andric       for (const AsmToken &Token : A[Index]) {
2973e8d8bef9SDimitry Andric         // In MASM, you can write '%expr'.
29745ffd83dbSDimitry Andric         // The prefix '%' evaluates the expression 'expr'
29755ffd83dbSDimitry Andric         // and uses the result as a string (e.g. replace %(1+2) with the
29765ffd83dbSDimitry Andric         // string "3").
29775ffd83dbSDimitry Andric         // Here, we identify the integer token which is the result of the
29785ffd83dbSDimitry Andric         // absolute expression evaluation and replace it with its string
29795ffd83dbSDimitry Andric         // representation.
2980e8d8bef9SDimitry Andric         if (Token.getString().front() == '%' && Token.is(AsmToken::Integer))
29815ffd83dbSDimitry Andric           // Emit an integer value to the buffer.
29825ffd83dbSDimitry Andric           OS << Token.getIntVal();
29835ffd83dbSDimitry Andric         else
2984e8d8bef9SDimitry Andric           OS << Token.getString();
29855ffd83dbSDimitry Andric       }
2986e8d8bef9SDimitry Andric 
2987e8d8bef9SDimitry Andric       Pos += Argument.size();
2988e8d8bef9SDimitry Andric       if (Pos < End && Body[Pos] == '&') {
2989e8d8bef9SDimitry Andric         ++Pos;
29905ffd83dbSDimitry Andric       }
29915ffd83dbSDimitry Andric     }
29925ffd83dbSDimitry Andric     // Update the scan point.
29935ffd83dbSDimitry Andric     Body = Body.substr(Pos);
29945ffd83dbSDimitry Andric   }
29955ffd83dbSDimitry Andric 
29965ffd83dbSDimitry Andric   return false;
29975ffd83dbSDimitry Andric }
29985ffd83dbSDimitry Andric 
29995ffd83dbSDimitry Andric static bool isOperator(AsmToken::TokenKind kind) {
30005ffd83dbSDimitry Andric   switch (kind) {
30015ffd83dbSDimitry Andric   default:
30025ffd83dbSDimitry Andric     return false;
30035ffd83dbSDimitry Andric   case AsmToken::Plus:
30045ffd83dbSDimitry Andric   case AsmToken::Minus:
30055ffd83dbSDimitry Andric   case AsmToken::Tilde:
30065ffd83dbSDimitry Andric   case AsmToken::Slash:
30075ffd83dbSDimitry Andric   case AsmToken::Star:
30085ffd83dbSDimitry Andric   case AsmToken::Dot:
30095ffd83dbSDimitry Andric   case AsmToken::Equal:
30105ffd83dbSDimitry Andric   case AsmToken::EqualEqual:
30115ffd83dbSDimitry Andric   case AsmToken::Pipe:
30125ffd83dbSDimitry Andric   case AsmToken::PipePipe:
30135ffd83dbSDimitry Andric   case AsmToken::Caret:
30145ffd83dbSDimitry Andric   case AsmToken::Amp:
30155ffd83dbSDimitry Andric   case AsmToken::AmpAmp:
30165ffd83dbSDimitry Andric   case AsmToken::Exclaim:
30175ffd83dbSDimitry Andric   case AsmToken::ExclaimEqual:
30185ffd83dbSDimitry Andric   case AsmToken::Less:
30195ffd83dbSDimitry Andric   case AsmToken::LessEqual:
30205ffd83dbSDimitry Andric   case AsmToken::LessLess:
30215ffd83dbSDimitry Andric   case AsmToken::LessGreater:
30225ffd83dbSDimitry Andric   case AsmToken::Greater:
30235ffd83dbSDimitry Andric   case AsmToken::GreaterEqual:
30245ffd83dbSDimitry Andric   case AsmToken::GreaterGreater:
30255ffd83dbSDimitry Andric     return true;
30265ffd83dbSDimitry Andric   }
30275ffd83dbSDimitry Andric }
30285ffd83dbSDimitry Andric 
30295ffd83dbSDimitry Andric namespace {
30305ffd83dbSDimitry Andric 
30315ffd83dbSDimitry Andric class AsmLexerSkipSpaceRAII {
30325ffd83dbSDimitry Andric public:
30335ffd83dbSDimitry Andric   AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
30345ffd83dbSDimitry Andric     Lexer.setSkipSpace(SkipSpace);
30355ffd83dbSDimitry Andric   }
30365ffd83dbSDimitry Andric 
30375ffd83dbSDimitry Andric   ~AsmLexerSkipSpaceRAII() {
30385ffd83dbSDimitry Andric     Lexer.setSkipSpace(true);
30395ffd83dbSDimitry Andric   }
30405ffd83dbSDimitry Andric 
30415ffd83dbSDimitry Andric private:
30425ffd83dbSDimitry Andric   AsmLexer &Lexer;
30435ffd83dbSDimitry Andric };
30445ffd83dbSDimitry Andric 
30455ffd83dbSDimitry Andric } // end anonymous namespace
30465ffd83dbSDimitry Andric 
3047e8d8bef9SDimitry Andric bool MasmParser::parseMacroArgument(const MCAsmMacroParameter *MP,
3048e8d8bef9SDimitry Andric                                     MCAsmMacroArgument &MA,
3049e8d8bef9SDimitry Andric                                     AsmToken::TokenKind EndTok) {
3050e8d8bef9SDimitry Andric   if (MP && MP->Vararg) {
3051e8d8bef9SDimitry Andric     if (Lexer.isNot(EndTok)) {
3052e8d8bef9SDimitry Andric       SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok);
3053e8d8bef9SDimitry Andric       for (StringRef S : Str) {
3054e8d8bef9SDimitry Andric         MA.emplace_back(AsmToken::String, S);
30555ffd83dbSDimitry Andric       }
3056e8d8bef9SDimitry Andric     }
3057e8d8bef9SDimitry Andric     return false;
3058e8d8bef9SDimitry Andric   }
3059e8d8bef9SDimitry Andric 
3060e8d8bef9SDimitry Andric   SMLoc StrLoc = Lexer.getLoc(), EndLoc;
3061e8d8bef9SDimitry Andric   if (Lexer.is(AsmToken::Less) && isAngleBracketString(StrLoc, EndLoc)) {
3062e8d8bef9SDimitry Andric     const char *StrChar = StrLoc.getPointer() + 1;
3063e8d8bef9SDimitry Andric     const char *EndChar = EndLoc.getPointer() - 1;
3064e8d8bef9SDimitry Andric     jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
3065e8d8bef9SDimitry Andric     /// Eat from '<' to '>'.
3066e8d8bef9SDimitry Andric     Lex();
3067e8d8bef9SDimitry Andric     MA.emplace_back(AsmToken::String, StringRef(StrChar, EndChar - StrChar));
30685ffd83dbSDimitry Andric     return false;
30695ffd83dbSDimitry Andric   }
30705ffd83dbSDimitry Andric 
30715ffd83dbSDimitry Andric   unsigned ParenLevel = 0;
30725ffd83dbSDimitry Andric 
30735ffd83dbSDimitry Andric   // Darwin doesn't use spaces to delmit arguments.
30745ffd83dbSDimitry Andric   AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);
30755ffd83dbSDimitry Andric 
30765ffd83dbSDimitry Andric   bool SpaceEaten;
30775ffd83dbSDimitry Andric 
30785ffd83dbSDimitry Andric   while (true) {
30795ffd83dbSDimitry Andric     SpaceEaten = false;
30805ffd83dbSDimitry Andric     if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
3081e8d8bef9SDimitry Andric       return TokError("unexpected token");
30825ffd83dbSDimitry Andric 
30835ffd83dbSDimitry Andric     if (ParenLevel == 0) {
30845ffd83dbSDimitry Andric       if (Lexer.is(AsmToken::Comma))
30855ffd83dbSDimitry Andric         break;
30865ffd83dbSDimitry Andric 
30875ffd83dbSDimitry Andric       if (Lexer.is(AsmToken::Space)) {
30885ffd83dbSDimitry Andric         SpaceEaten = true;
3089e8d8bef9SDimitry Andric         Lex(); // Eat spaces.
30905ffd83dbSDimitry Andric       }
30915ffd83dbSDimitry Andric 
30925ffd83dbSDimitry Andric       // Spaces can delimit parameters, but could also be part an expression.
30935ffd83dbSDimitry Andric       // If the token after a space is an operator, add the token and the next
30945ffd83dbSDimitry Andric       // one into this argument
30955ffd83dbSDimitry Andric       if (!IsDarwin) {
3096e8d8bef9SDimitry Andric         if (isOperator(Lexer.getKind()) && Lexer.isNot(EndTok)) {
30975ffd83dbSDimitry Andric           MA.push_back(getTok());
3098e8d8bef9SDimitry Andric           Lex();
30995ffd83dbSDimitry Andric 
31005ffd83dbSDimitry Andric           // Whitespace after an operator can be ignored.
31015ffd83dbSDimitry Andric           if (Lexer.is(AsmToken::Space))
3102e8d8bef9SDimitry Andric             Lex();
31035ffd83dbSDimitry Andric 
31045ffd83dbSDimitry Andric           continue;
31055ffd83dbSDimitry Andric         }
31065ffd83dbSDimitry Andric       }
31075ffd83dbSDimitry Andric       if (SpaceEaten)
31085ffd83dbSDimitry Andric         break;
31095ffd83dbSDimitry Andric     }
31105ffd83dbSDimitry Andric 
31115ffd83dbSDimitry Andric     // handleMacroEntry relies on not advancing the lexer here
31125ffd83dbSDimitry Andric     // to be able to fill in the remaining default parameter values
3113e8d8bef9SDimitry Andric     if (Lexer.is(EndTok) && (EndTok != AsmToken::RParen || ParenLevel == 0))
31145ffd83dbSDimitry Andric       break;
31155ffd83dbSDimitry Andric 
31165ffd83dbSDimitry Andric     // Adjust the current parentheses level.
31175ffd83dbSDimitry Andric     if (Lexer.is(AsmToken::LParen))
31185ffd83dbSDimitry Andric       ++ParenLevel;
31195ffd83dbSDimitry Andric     else if (Lexer.is(AsmToken::RParen) && ParenLevel)
31205ffd83dbSDimitry Andric       --ParenLevel;
31215ffd83dbSDimitry Andric 
31225ffd83dbSDimitry Andric     // Append the token to the current argument list.
31235ffd83dbSDimitry Andric     MA.push_back(getTok());
3124e8d8bef9SDimitry Andric     Lex();
31255ffd83dbSDimitry Andric   }
31265ffd83dbSDimitry Andric 
31275ffd83dbSDimitry Andric   if (ParenLevel != 0)
3128e8d8bef9SDimitry Andric     return TokError("unbalanced parentheses in argument");
3129e8d8bef9SDimitry Andric 
3130e8d8bef9SDimitry Andric   if (MA.empty() && MP) {
3131e8d8bef9SDimitry Andric     if (MP->Required) {
3132e8d8bef9SDimitry Andric       return TokError("missing value for required parameter '" + MP->Name +
3133e8d8bef9SDimitry Andric                       "'");
3134e8d8bef9SDimitry Andric     } else {
3135e8d8bef9SDimitry Andric       MA = MP->Value;
3136e8d8bef9SDimitry Andric     }
3137e8d8bef9SDimitry Andric   }
31385ffd83dbSDimitry Andric   return false;
31395ffd83dbSDimitry Andric }
31405ffd83dbSDimitry Andric 
31415ffd83dbSDimitry Andric // Parse the macro instantiation arguments.
31425ffd83dbSDimitry Andric bool MasmParser::parseMacroArguments(const MCAsmMacro *M,
3143e8d8bef9SDimitry Andric                                      MCAsmMacroArguments &A,
3144e8d8bef9SDimitry Andric                                      AsmToken::TokenKind EndTok) {
31455ffd83dbSDimitry Andric   const unsigned NParameters = M ? M->Parameters.size() : 0;
31465ffd83dbSDimitry Andric   bool NamedParametersFound = false;
31475ffd83dbSDimitry Andric   SmallVector<SMLoc, 4> FALocs;
31485ffd83dbSDimitry Andric 
31495ffd83dbSDimitry Andric   A.resize(NParameters);
31505ffd83dbSDimitry Andric   FALocs.resize(NParameters);
31515ffd83dbSDimitry Andric 
31525ffd83dbSDimitry Andric   // Parse two kinds of macro invocations:
31535ffd83dbSDimitry Andric   // - macros defined without any parameters accept an arbitrary number of them
31545ffd83dbSDimitry Andric   // - macros defined with parameters accept at most that many of them
31555ffd83dbSDimitry Andric   for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
31565ffd83dbSDimitry Andric        ++Parameter) {
31575ffd83dbSDimitry Andric     SMLoc IDLoc = Lexer.getLoc();
31585ffd83dbSDimitry Andric     MCAsmMacroParameter FA;
31595ffd83dbSDimitry Andric 
3160fe6060f1SDimitry Andric     if (Lexer.is(AsmToken::Identifier) && peekTok().is(AsmToken::Equal)) {
31615ffd83dbSDimitry Andric       if (parseIdentifier(FA.Name))
31625ffd83dbSDimitry Andric         return Error(IDLoc, "invalid argument identifier for formal argument");
31635ffd83dbSDimitry Andric 
31645ffd83dbSDimitry Andric       if (Lexer.isNot(AsmToken::Equal))
31655ffd83dbSDimitry Andric         return TokError("expected '=' after formal parameter identifier");
31665ffd83dbSDimitry Andric 
31675ffd83dbSDimitry Andric       Lex();
31685ffd83dbSDimitry Andric 
31695ffd83dbSDimitry Andric       NamedParametersFound = true;
31705ffd83dbSDimitry Andric     }
31715ffd83dbSDimitry Andric 
31725ffd83dbSDimitry Andric     if (NamedParametersFound && FA.Name.empty())
31735ffd83dbSDimitry Andric       return Error(IDLoc, "cannot mix positional and keyword arguments");
31745ffd83dbSDimitry Andric 
3175e8d8bef9SDimitry Andric     unsigned PI = Parameter;
3176e8d8bef9SDimitry Andric     if (!FA.Name.empty()) {
3177e8d8bef9SDimitry Andric       assert(M && "expected macro to be defined");
3178e8d8bef9SDimitry Andric       unsigned FAI = 0;
3179e8d8bef9SDimitry Andric       for (FAI = 0; FAI < NParameters; ++FAI)
3180e8d8bef9SDimitry Andric         if (M->Parameters[FAI].Name == FA.Name)
3181e8d8bef9SDimitry Andric           break;
3182e8d8bef9SDimitry Andric 
3183e8d8bef9SDimitry Andric       if (FAI >= NParameters) {
3184e8d8bef9SDimitry Andric         return Error(IDLoc, "parameter named '" + FA.Name +
3185e8d8bef9SDimitry Andric                                 "' does not exist for macro '" + M->Name + "'");
3186e8d8bef9SDimitry Andric       }
3187e8d8bef9SDimitry Andric       PI = FAI;
3188e8d8bef9SDimitry Andric     }
3189e8d8bef9SDimitry Andric     const MCAsmMacroParameter *MP = nullptr;
3190e8d8bef9SDimitry Andric     if (M && PI < NParameters)
3191e8d8bef9SDimitry Andric       MP = &M->Parameters[PI];
3192e8d8bef9SDimitry Andric 
31935ffd83dbSDimitry Andric     SMLoc StrLoc = Lexer.getLoc();
31945ffd83dbSDimitry Andric     SMLoc EndLoc;
3195e8d8bef9SDimitry Andric     if (Lexer.is(AsmToken::Percent)) {
31965ffd83dbSDimitry Andric       const MCExpr *AbsoluteExp;
31975ffd83dbSDimitry Andric       int64_t Value;
31985ffd83dbSDimitry Andric       /// Eat '%'.
31995ffd83dbSDimitry Andric       Lex();
32005ffd83dbSDimitry Andric       if (parseExpression(AbsoluteExp, EndLoc))
32015ffd83dbSDimitry Andric         return false;
32025ffd83dbSDimitry Andric       if (!AbsoluteExp->evaluateAsAbsolute(Value,
32035ffd83dbSDimitry Andric                                            getStreamer().getAssemblerPtr()))
32045ffd83dbSDimitry Andric         return Error(StrLoc, "expected absolute expression");
32055ffd83dbSDimitry Andric       const char *StrChar = StrLoc.getPointer();
32065ffd83dbSDimitry Andric       const char *EndChar = EndLoc.getPointer();
32075ffd83dbSDimitry Andric       AsmToken newToken(AsmToken::Integer,
32085ffd83dbSDimitry Andric                         StringRef(StrChar, EndChar - StrChar), Value);
32095ffd83dbSDimitry Andric       FA.Value.push_back(newToken);
3210e8d8bef9SDimitry Andric     } else if (parseMacroArgument(MP, FA.Value, EndTok)) {
3211e8d8bef9SDimitry Andric       if (M)
3212e8d8bef9SDimitry Andric         return addErrorSuffix(" in '" + M->Name + "' macro");
3213e8d8bef9SDimitry Andric       else
32145ffd83dbSDimitry Andric         return true;
32155ffd83dbSDimitry Andric     }
32165ffd83dbSDimitry Andric 
32175ffd83dbSDimitry Andric     if (!FA.Value.empty()) {
32185ffd83dbSDimitry Andric       if (A.size() <= PI)
32195ffd83dbSDimitry Andric         A.resize(PI + 1);
32205ffd83dbSDimitry Andric       A[PI] = FA.Value;
32215ffd83dbSDimitry Andric 
32225ffd83dbSDimitry Andric       if (FALocs.size() <= PI)
32235ffd83dbSDimitry Andric         FALocs.resize(PI + 1);
32245ffd83dbSDimitry Andric 
32255ffd83dbSDimitry Andric       FALocs[PI] = Lexer.getLoc();
32265ffd83dbSDimitry Andric     }
32275ffd83dbSDimitry Andric 
32285ffd83dbSDimitry Andric     // At the end of the statement, fill in remaining arguments that have
32295ffd83dbSDimitry Andric     // default values. If there aren't any, then the next argument is
32305ffd83dbSDimitry Andric     // required but missing
3231e8d8bef9SDimitry Andric     if (Lexer.is(EndTok)) {
32325ffd83dbSDimitry Andric       bool Failure = false;
32335ffd83dbSDimitry Andric       for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
32345ffd83dbSDimitry Andric         if (A[FAI].empty()) {
32355ffd83dbSDimitry Andric           if (M->Parameters[FAI].Required) {
32365ffd83dbSDimitry Andric             Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
32375ffd83dbSDimitry Andric                   "missing value for required parameter "
3238e8d8bef9SDimitry Andric                   "'" +
3239e8d8bef9SDimitry Andric                       M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
32405ffd83dbSDimitry Andric             Failure = true;
32415ffd83dbSDimitry Andric           }
32425ffd83dbSDimitry Andric 
32435ffd83dbSDimitry Andric           if (!M->Parameters[FAI].Value.empty())
32445ffd83dbSDimitry Andric             A[FAI] = M->Parameters[FAI].Value;
32455ffd83dbSDimitry Andric         }
32465ffd83dbSDimitry Andric       }
32475ffd83dbSDimitry Andric       return Failure;
32485ffd83dbSDimitry Andric     }
32495ffd83dbSDimitry Andric 
32505ffd83dbSDimitry Andric     if (Lexer.is(AsmToken::Comma))
32515ffd83dbSDimitry Andric       Lex();
32525ffd83dbSDimitry Andric   }
32535ffd83dbSDimitry Andric 
32545ffd83dbSDimitry Andric   return TokError("too many positional arguments");
32555ffd83dbSDimitry Andric }
32565ffd83dbSDimitry Andric 
3257e8d8bef9SDimitry Andric bool MasmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc,
3258e8d8bef9SDimitry Andric                                   AsmToken::TokenKind ArgumentEndTok) {
32595ffd83dbSDimitry Andric   // Arbitrarily limit macro nesting depth (default matches 'as'). We can
32605ffd83dbSDimitry Andric   // eliminate this, although we should protect against infinite loops.
32615ffd83dbSDimitry Andric   unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;
32625ffd83dbSDimitry Andric   if (ActiveMacros.size() == MaxNestingDepth) {
32635ffd83dbSDimitry Andric     std::ostringstream MaxNestingDepthError;
32645ffd83dbSDimitry Andric     MaxNestingDepthError << "macros cannot be nested more than "
32655ffd83dbSDimitry Andric                          << MaxNestingDepth << " levels deep."
32665ffd83dbSDimitry Andric                          << " Use -asm-macro-max-nesting-depth to increase "
32675ffd83dbSDimitry Andric                             "this limit.";
32685ffd83dbSDimitry Andric     return TokError(MaxNestingDepthError.str());
32695ffd83dbSDimitry Andric   }
32705ffd83dbSDimitry Andric 
32715ffd83dbSDimitry Andric   MCAsmMacroArguments A;
3272e8d8bef9SDimitry Andric   if (parseMacroArguments(M, A, ArgumentEndTok))
32735ffd83dbSDimitry Andric     return true;
32745ffd83dbSDimitry Andric 
32755ffd83dbSDimitry Andric   // Macro instantiation is lexical, unfortunately. We construct a new buffer
32765ffd83dbSDimitry Andric   // to hold the macro body with substitutions.
32775ffd83dbSDimitry Andric   SmallString<256> Buf;
32785ffd83dbSDimitry Andric   StringRef Body = M->Body;
32795ffd83dbSDimitry Andric   raw_svector_ostream OS(Buf);
32805ffd83dbSDimitry Andric 
3281e8d8bef9SDimitry Andric   if (expandMacro(OS, Body, M->Parameters, A, M->Locals, getTok().getLoc()))
32825ffd83dbSDimitry Andric     return true;
32835ffd83dbSDimitry Andric 
3284e8d8bef9SDimitry Andric   // We include the endm in the buffer as our cue to exit the macro
32855ffd83dbSDimitry Andric   // instantiation.
3286e8d8bef9SDimitry Andric   OS << "endm\n";
32875ffd83dbSDimitry Andric 
32885ffd83dbSDimitry Andric   std::unique_ptr<MemoryBuffer> Instantiation =
32895ffd83dbSDimitry Andric       MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
32905ffd83dbSDimitry Andric 
32915ffd83dbSDimitry Andric   // Create the macro instantiation object and add to the current macro
32925ffd83dbSDimitry Andric   // instantiation stack.
32935ffd83dbSDimitry Andric   MacroInstantiation *MI = new MacroInstantiation{
32945ffd83dbSDimitry Andric       NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
32955ffd83dbSDimitry Andric   ActiveMacros.push_back(MI);
32965ffd83dbSDimitry Andric 
32975ffd83dbSDimitry Andric   ++NumOfMacroInstantiations;
32985ffd83dbSDimitry Andric 
32995ffd83dbSDimitry Andric   // Jump to the macro instantiation and prime the lexer.
33005ffd83dbSDimitry Andric   CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
33015ffd83dbSDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
3302e8d8bef9SDimitry Andric   EndStatementAtEOFStack.push_back(true);
33035ffd83dbSDimitry Andric   Lex();
33045ffd83dbSDimitry Andric 
33055ffd83dbSDimitry Andric   return false;
33065ffd83dbSDimitry Andric }
33075ffd83dbSDimitry Andric 
33085ffd83dbSDimitry Andric void MasmParser::handleMacroExit() {
3309e8d8bef9SDimitry Andric   // Jump to the token we should return to, and consume it.
3310e8d8bef9SDimitry Andric   EndStatementAtEOFStack.pop_back();
3311e8d8bef9SDimitry Andric   jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer,
3312e8d8bef9SDimitry Andric             EndStatementAtEOFStack.back());
33135ffd83dbSDimitry Andric   Lex();
33145ffd83dbSDimitry Andric 
33155ffd83dbSDimitry Andric   // Pop the instantiation entry.
33165ffd83dbSDimitry Andric   delete ActiveMacros.back();
33175ffd83dbSDimitry Andric   ActiveMacros.pop_back();
33185ffd83dbSDimitry Andric }
33195ffd83dbSDimitry Andric 
3320e8d8bef9SDimitry Andric bool MasmParser::handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc) {
3321e8d8bef9SDimitry Andric   if (!M->IsFunction)
3322e8d8bef9SDimitry Andric     return Error(NameLoc, "cannot invoke macro procedure as function");
3323e8d8bef9SDimitry Andric 
3324e8d8bef9SDimitry Andric   if (parseToken(AsmToken::LParen, "invoking macro function '" + M->Name +
3325e8d8bef9SDimitry Andric                                        "' requires arguments in parentheses") ||
3326e8d8bef9SDimitry Andric       handleMacroEntry(M, NameLoc, AsmToken::RParen))
3327e8d8bef9SDimitry Andric     return true;
3328e8d8bef9SDimitry Andric 
3329e8d8bef9SDimitry Andric   // Parse all statements in the macro, retrieving the exit value when it ends.
3330e8d8bef9SDimitry Andric   std::string ExitValue;
3331e8d8bef9SDimitry Andric   SmallVector<AsmRewrite, 4> AsmStrRewrites;
3332e8d8bef9SDimitry Andric   while (Lexer.isNot(AsmToken::Eof)) {
3333e8d8bef9SDimitry Andric     ParseStatementInfo Info(&AsmStrRewrites);
3334e8d8bef9SDimitry Andric     bool Parsed = parseStatement(Info, nullptr);
3335e8d8bef9SDimitry Andric 
3336e8d8bef9SDimitry Andric     if (!Parsed && Info.ExitValue.hasValue()) {
3337e8d8bef9SDimitry Andric       ExitValue = std::move(*Info.ExitValue);
3338e8d8bef9SDimitry Andric       break;
3339e8d8bef9SDimitry Andric     }
3340e8d8bef9SDimitry Andric 
3341e8d8bef9SDimitry Andric     // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
3342e8d8bef9SDimitry Andric     // for printing ErrMsg via Lex() only if no (presumably better) parser error
3343e8d8bef9SDimitry Andric     // exists.
3344e8d8bef9SDimitry Andric     if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
3345e8d8bef9SDimitry Andric       Lex();
3346e8d8bef9SDimitry Andric     }
3347e8d8bef9SDimitry Andric 
3348e8d8bef9SDimitry Andric     // parseStatement returned true so may need to emit an error.
3349e8d8bef9SDimitry Andric     printPendingErrors();
3350e8d8bef9SDimitry Andric 
3351e8d8bef9SDimitry Andric     // Skipping to the next line if needed.
3352e8d8bef9SDimitry Andric     if (Parsed && !getLexer().isAtStartOfStatement())
3353e8d8bef9SDimitry Andric       eatToEndOfStatement();
3354e8d8bef9SDimitry Andric   }
3355e8d8bef9SDimitry Andric 
3356e8d8bef9SDimitry Andric   // Consume the right-parenthesis on the other side of the arguments.
3357*04eeddc0SDimitry Andric   if (parseRParen())
3358e8d8bef9SDimitry Andric     return true;
3359e8d8bef9SDimitry Andric 
3360e8d8bef9SDimitry Andric   // Exit values may require lexing, unfortunately. We construct a new buffer to
3361e8d8bef9SDimitry Andric   // hold the exit value.
3362e8d8bef9SDimitry Andric   std::unique_ptr<MemoryBuffer> MacroValue =
3363e8d8bef9SDimitry Andric       MemoryBuffer::getMemBufferCopy(ExitValue, "<macro-value>");
3364e8d8bef9SDimitry Andric 
3365e8d8bef9SDimitry Andric   // Jump from this location to the instantiated exit value, and prime the
3366e8d8bef9SDimitry Andric   // lexer.
3367e8d8bef9SDimitry Andric   CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(MacroValue), Lexer.getLoc());
3368e8d8bef9SDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), nullptr,
3369e8d8bef9SDimitry Andric                   /*EndStatementAtEOF=*/false);
3370e8d8bef9SDimitry Andric   EndStatementAtEOFStack.push_back(false);
3371e8d8bef9SDimitry Andric   Lex();
3372e8d8bef9SDimitry Andric 
3373e8d8bef9SDimitry Andric   return false;
3374e8d8bef9SDimitry Andric }
3375e8d8bef9SDimitry Andric 
33765ffd83dbSDimitry Andric /// parseIdentifier:
33775ffd83dbSDimitry Andric ///   ::= identifier
33785ffd83dbSDimitry Andric ///   ::= string
3379fe6060f1SDimitry Andric bool MasmParser::parseIdentifier(StringRef &Res,
3380fe6060f1SDimitry Andric                                  IdentifierPositionKind Position) {
33815ffd83dbSDimitry Andric   // The assembler has relaxed rules for accepting identifiers, in particular we
33825ffd83dbSDimitry Andric   // allow things like '.globl $foo' and '.def @feat.00', which would normally
33835ffd83dbSDimitry Andric   // be separate tokens. At this level, we have already lexed so we cannot
33845ffd83dbSDimitry Andric   // (currently) handle this as a context dependent token, instead we detect
33855ffd83dbSDimitry Andric   // adjacent tokens and return the combined identifier.
33865ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
33875ffd83dbSDimitry Andric     SMLoc PrefixLoc = getLexer().getLoc();
33885ffd83dbSDimitry Andric 
33895ffd83dbSDimitry Andric     // Consume the prefix character, and check for a following identifier.
33905ffd83dbSDimitry Andric 
3391fe6060f1SDimitry Andric     AsmToken nextTok = peekTok(false);
33925ffd83dbSDimitry Andric 
3393fe6060f1SDimitry Andric     if (nextTok.isNot(AsmToken::Identifier))
33945ffd83dbSDimitry Andric       return true;
33955ffd83dbSDimitry Andric 
33965ffd83dbSDimitry Andric     // We have a '$' or '@' followed by an identifier, make sure they are adjacent.
3397fe6060f1SDimitry Andric     if (PrefixLoc.getPointer() + 1 != nextTok.getLoc().getPointer())
33985ffd83dbSDimitry Andric       return true;
33995ffd83dbSDimitry Andric 
34005ffd83dbSDimitry Andric     // eat $ or @
34015ffd83dbSDimitry Andric     Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
34025ffd83dbSDimitry Andric     // Construct the joined identifier and consume the token.
34035ffd83dbSDimitry Andric     Res =
34045ffd83dbSDimitry Andric         StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1);
34055ffd83dbSDimitry Andric     Lex(); // Parser Lex to maintain invariants.
34065ffd83dbSDimitry Andric     return false;
34075ffd83dbSDimitry Andric   }
34085ffd83dbSDimitry Andric 
34095ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
34105ffd83dbSDimitry Andric     return true;
34115ffd83dbSDimitry Andric 
34125ffd83dbSDimitry Andric   Res = getTok().getIdentifier();
34135ffd83dbSDimitry Andric 
3414fe6060f1SDimitry Andric   // Consume the identifier token - but if parsing certain directives, avoid
3415fe6060f1SDimitry Andric   // lexical expansion of the next token.
3416fe6060f1SDimitry Andric   ExpandKind ExpandNextToken = ExpandMacros;
3417fe6060f1SDimitry Andric   if (Position == StartOfStatement &&
3418fe6060f1SDimitry Andric       StringSwitch<bool>(Res)
3419fe6060f1SDimitry Andric           .CaseLower("echo", true)
3420fe6060f1SDimitry Andric           .CasesLower("ifdef", "ifndef", "elseifdef", "elseifndef", true)
3421fe6060f1SDimitry Andric           .Default(false)) {
3422fe6060f1SDimitry Andric     ExpandNextToken = DoNotExpandMacros;
3423fe6060f1SDimitry Andric   }
3424fe6060f1SDimitry Andric   Lex(ExpandNextToken);
34255ffd83dbSDimitry Andric 
34265ffd83dbSDimitry Andric   return false;
34275ffd83dbSDimitry Andric }
34285ffd83dbSDimitry Andric 
34295ffd83dbSDimitry Andric /// parseDirectiveEquate:
34305ffd83dbSDimitry Andric ///  ::= name "=" expression
34315ffd83dbSDimitry Andric ///    | name "equ" expression    (not redefinable)
34325ffd83dbSDimitry Andric ///    | name "equ" text-list
3433fe6060f1SDimitry Andric ///    | name "textequ" text-list (redefinability unspecified)
34345ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
3435fe6060f1SDimitry Andric                                       DirectiveKind DirKind, SMLoc NameLoc) {
3436fe6060f1SDimitry Andric   auto BuiltinIt = BuiltinSymbolMap.find(Name.lower());
3437fe6060f1SDimitry Andric   if (BuiltinIt != BuiltinSymbolMap.end())
3438fe6060f1SDimitry Andric     return Error(NameLoc, "cannot redefine a built-in symbol");
3439fe6060f1SDimitry Andric 
3440fe6060f1SDimitry Andric   Variable &Var = Variables[Name.lower()];
34415ffd83dbSDimitry Andric   if (Var.Name.empty()) {
34425ffd83dbSDimitry Andric     Var.Name = Name;
34435ffd83dbSDimitry Andric   }
34445ffd83dbSDimitry Andric 
3445fe6060f1SDimitry Andric   SMLoc StartLoc = Lexer.getLoc();
34465ffd83dbSDimitry Andric   if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) {
34475ffd83dbSDimitry Andric     // "equ" and "textequ" both allow text expressions.
34485ffd83dbSDimitry Andric     std::string Value;
3449fe6060f1SDimitry Andric     std::string TextItem;
3450fe6060f1SDimitry Andric     if (!parseTextItem(TextItem)) {
3451fe6060f1SDimitry Andric       Value += TextItem;
34525ffd83dbSDimitry Andric 
34535ffd83dbSDimitry Andric       // Accept a text-list, not just one text-item.
34545ffd83dbSDimitry Andric       auto parseItem = [&]() -> bool {
3455fe6060f1SDimitry Andric         if (parseTextItem(TextItem))
3456e8d8bef9SDimitry Andric           return TokError("expected text item");
3457fe6060f1SDimitry Andric         Value += TextItem;
34585ffd83dbSDimitry Andric         return false;
34595ffd83dbSDimitry Andric       };
34605ffd83dbSDimitry Andric       if (parseOptionalToken(AsmToken::Comma) && parseMany(parseItem))
34615ffd83dbSDimitry Andric         return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
34625ffd83dbSDimitry Andric 
3463fe6060f1SDimitry Andric       if (!Var.IsText || Var.TextValue != Value) {
3464fe6060f1SDimitry Andric         switch (Var.Redefinable) {
3465fe6060f1SDimitry Andric         case Variable::NOT_REDEFINABLE:
3466fe6060f1SDimitry Andric           return Error(getTok().getLoc(), "invalid variable redefinition");
3467fe6060f1SDimitry Andric         case Variable::WARN_ON_REDEFINITION:
3468fe6060f1SDimitry Andric           if (Warning(NameLoc, "redefining '" + Name +
3469fe6060f1SDimitry Andric                                    "', already defined on the command line")) {
3470fe6060f1SDimitry Andric             return true;
3471fe6060f1SDimitry Andric           }
3472fe6060f1SDimitry Andric           break;
3473fe6060f1SDimitry Andric         default:
3474fe6060f1SDimitry Andric           break;
3475fe6060f1SDimitry Andric         }
3476fe6060f1SDimitry Andric       }
3477fe6060f1SDimitry Andric       Var.IsText = true;
3478fe6060f1SDimitry Andric       Var.TextValue = Value;
3479fe6060f1SDimitry Andric       Var.Redefinable = Variable::REDEFINABLE;
3480fe6060f1SDimitry Andric 
34815ffd83dbSDimitry Andric       return false;
34825ffd83dbSDimitry Andric     }
34835ffd83dbSDimitry Andric   }
34845ffd83dbSDimitry Andric   if (DirKind == DK_TEXTEQU)
34855ffd83dbSDimitry Andric     return TokError("expected <text> in '" + Twine(IDVal) + "' directive");
34865ffd83dbSDimitry Andric 
34875ffd83dbSDimitry Andric   // Parse as expression assignment.
34885ffd83dbSDimitry Andric   const MCExpr *Expr;
3489fe6060f1SDimitry Andric   SMLoc EndLoc;
34905ffd83dbSDimitry Andric   if (parseExpression(Expr, EndLoc))
34915ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3492fe6060f1SDimitry Andric   StringRef ExprAsString = StringRef(
3493fe6060f1SDimitry Andric       StartLoc.getPointer(), EndLoc.getPointer() - StartLoc.getPointer());
3494fe6060f1SDimitry Andric 
3495fe6060f1SDimitry Andric   int64_t Value;
3496fe6060f1SDimitry Andric   if (!Expr->evaluateAsAbsolute(Value, getStreamer().getAssemblerPtr())) {
3497fe6060f1SDimitry Andric     if (DirKind == DK_ASSIGN)
3498fe6060f1SDimitry Andric       return Error(
3499fe6060f1SDimitry Andric           StartLoc,
3500fe6060f1SDimitry Andric           "expected absolute expression; not all symbols have known values",
3501fe6060f1SDimitry Andric           {StartLoc, EndLoc});
3502fe6060f1SDimitry Andric 
3503fe6060f1SDimitry Andric     // Not an absolute expression; define as a text replacement.
3504fe6060f1SDimitry Andric     if (!Var.IsText || Var.TextValue != ExprAsString) {
3505fe6060f1SDimitry Andric       switch (Var.Redefinable) {
3506fe6060f1SDimitry Andric       case Variable::NOT_REDEFINABLE:
3507fe6060f1SDimitry Andric         return Error(getTok().getLoc(), "invalid variable redefinition");
3508fe6060f1SDimitry Andric       case Variable::WARN_ON_REDEFINITION:
3509fe6060f1SDimitry Andric         if (Warning(NameLoc, "redefining '" + Name +
3510fe6060f1SDimitry Andric                                  "', already defined on the command line")) {
3511fe6060f1SDimitry Andric           return true;
3512fe6060f1SDimitry Andric         }
3513fe6060f1SDimitry Andric         break;
3514fe6060f1SDimitry Andric       default:
3515fe6060f1SDimitry Andric         break;
3516fe6060f1SDimitry Andric       }
3517fe6060f1SDimitry Andric     }
3518fe6060f1SDimitry Andric 
3519fe6060f1SDimitry Andric     Var.IsText = true;
3520fe6060f1SDimitry Andric     Var.TextValue = ExprAsString.str();
3521fe6060f1SDimitry Andric     Var.Redefinable = Variable::REDEFINABLE;
3522fe6060f1SDimitry Andric 
3523fe6060f1SDimitry Andric     return false;
3524fe6060f1SDimitry Andric   }
3525fe6060f1SDimitry Andric 
3526e8d8bef9SDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Var.Name);
3527fe6060f1SDimitry Andric 
3528fe6060f1SDimitry Andric   const MCConstantExpr *PrevValue =
3529fe6060f1SDimitry Andric       Sym->isVariable() ? dyn_cast_or_null<MCConstantExpr>(
3530fe6060f1SDimitry Andric                               Sym->getVariableValue(/*SetUsed=*/false))
3531fe6060f1SDimitry Andric                         : nullptr;
3532fe6060f1SDimitry Andric   if (Var.IsText || !PrevValue || PrevValue->getValue() != Value) {
3533fe6060f1SDimitry Andric     switch (Var.Redefinable) {
3534fe6060f1SDimitry Andric     case Variable::NOT_REDEFINABLE:
3535fe6060f1SDimitry Andric       return Error(getTok().getLoc(), "invalid variable redefinition");
3536fe6060f1SDimitry Andric     case Variable::WARN_ON_REDEFINITION:
3537fe6060f1SDimitry Andric       if (Warning(NameLoc, "redefining '" + Name +
3538fe6060f1SDimitry Andric                                "', already defined on the command line")) {
3539fe6060f1SDimitry Andric         return true;
3540fe6060f1SDimitry Andric       }
3541fe6060f1SDimitry Andric       break;
3542fe6060f1SDimitry Andric     default:
3543fe6060f1SDimitry Andric       break;
3544fe6060f1SDimitry Andric     }
3545fe6060f1SDimitry Andric   }
3546fe6060f1SDimitry Andric 
3547fe6060f1SDimitry Andric   Var.IsText = false;
3548fe6060f1SDimitry Andric   Var.TextValue.clear();
3549fe6060f1SDimitry Andric   Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE
3550fe6060f1SDimitry Andric                                            : Variable::NOT_REDEFINABLE;
3551fe6060f1SDimitry Andric 
3552fe6060f1SDimitry Andric   Sym->setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE);
3553e8d8bef9SDimitry Andric   Sym->setVariableValue(Expr);
3554e8d8bef9SDimitry Andric   Sym->setExternal(false);
3555e8d8bef9SDimitry Andric 
35565ffd83dbSDimitry Andric   return false;
35575ffd83dbSDimitry Andric }
35585ffd83dbSDimitry Andric 
35595ffd83dbSDimitry Andric bool MasmParser::parseEscapedString(std::string &Data) {
35605ffd83dbSDimitry Andric   if (check(getTok().isNot(AsmToken::String), "expected string"))
35615ffd83dbSDimitry Andric     return true;
35625ffd83dbSDimitry Andric 
35635ffd83dbSDimitry Andric   Data = "";
3564e8d8bef9SDimitry Andric   char Quote = getTok().getString().front();
35655ffd83dbSDimitry Andric   StringRef Str = getTok().getStringContents();
3566e8d8bef9SDimitry Andric   Data.reserve(Str.size());
3567e8d8bef9SDimitry Andric   for (size_t i = 0, e = Str.size(); i != e; ++i) {
3568e8d8bef9SDimitry Andric     Data.push_back(Str[i]);
3569e8d8bef9SDimitry Andric     if (Str[i] == Quote) {
3570e8d8bef9SDimitry Andric       // MASM treats doubled delimiting quotes as an escaped delimiting quote.
3571e8d8bef9SDimitry Andric       // If we're escaping the string's trailing delimiter, we're definitely
3572e8d8bef9SDimitry Andric       // missing a quotation mark.
3573e8d8bef9SDimitry Andric       if (i + 1 == Str.size())
3574e8d8bef9SDimitry Andric         return Error(getTok().getLoc(), "missing quotation mark in string");
3575e8d8bef9SDimitry Andric       if (Str[i + 1] == Quote)
35765ffd83dbSDimitry Andric         ++i;
35775ffd83dbSDimitry Andric     }
35785ffd83dbSDimitry Andric   }
35795ffd83dbSDimitry Andric 
35805ffd83dbSDimitry Andric   Lex();
35815ffd83dbSDimitry Andric   return false;
35825ffd83dbSDimitry Andric }
35835ffd83dbSDimitry Andric 
35845ffd83dbSDimitry Andric bool MasmParser::parseAngleBracketString(std::string &Data) {
35855ffd83dbSDimitry Andric   SMLoc EndLoc, StartLoc = getTok().getLoc();
35865ffd83dbSDimitry Andric   if (isAngleBracketString(StartLoc, EndLoc)) {
35875ffd83dbSDimitry Andric     const char *StartChar = StartLoc.getPointer() + 1;
35885ffd83dbSDimitry Andric     const char *EndChar = EndLoc.getPointer() - 1;
3589e8d8bef9SDimitry Andric     jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
35905ffd83dbSDimitry Andric     // Eat from '<' to '>'.
35915ffd83dbSDimitry Andric     Lex();
35925ffd83dbSDimitry Andric 
35935ffd83dbSDimitry Andric     Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
35945ffd83dbSDimitry Andric     return false;
35955ffd83dbSDimitry Andric   }
35965ffd83dbSDimitry Andric   return true;
35975ffd83dbSDimitry Andric }
35985ffd83dbSDimitry Andric 
35995ffd83dbSDimitry Andric /// textItem ::= textLiteral | textMacroID | % constExpr
36005ffd83dbSDimitry Andric bool MasmParser::parseTextItem(std::string &Data) {
3601e8d8bef9SDimitry Andric   switch (getTok().getKind()) {
3602e8d8bef9SDimitry Andric   default:
3603e8d8bef9SDimitry Andric     return true;
3604e8d8bef9SDimitry Andric   case AsmToken::Percent: {
3605e8d8bef9SDimitry Andric     int64_t Res;
3606e8d8bef9SDimitry Andric     if (parseToken(AsmToken::Percent) || parseAbsoluteExpression(Res))
3607e8d8bef9SDimitry Andric       return true;
3608e8d8bef9SDimitry Andric     Data = std::to_string(Res);
3609e8d8bef9SDimitry Andric     return false;
3610e8d8bef9SDimitry Andric   }
3611e8d8bef9SDimitry Andric   case AsmToken::Less:
3612e8d8bef9SDimitry Andric   case AsmToken::LessEqual:
3613e8d8bef9SDimitry Andric   case AsmToken::LessLess:
3614e8d8bef9SDimitry Andric   case AsmToken::LessGreater:
36155ffd83dbSDimitry Andric     return parseAngleBracketString(Data);
3616e8d8bef9SDimitry Andric   case AsmToken::Identifier: {
3617fe6060f1SDimitry Andric     // This must be a text macro; we need to expand it accordingly.
3618e8d8bef9SDimitry Andric     StringRef ID;
3619fe6060f1SDimitry Andric     SMLoc StartLoc = getTok().getLoc();
3620e8d8bef9SDimitry Andric     if (parseIdentifier(ID))
3621e8d8bef9SDimitry Andric       return true;
3622e8d8bef9SDimitry Andric     Data = ID.str();
3623e8d8bef9SDimitry Andric 
3624fe6060f1SDimitry Andric     bool Expanded = false;
3625fe6060f1SDimitry Andric     while (true) {
3626fe6060f1SDimitry Andric       // Try to resolve as a built-in text macro
3627fe6060f1SDimitry Andric       auto BuiltinIt = BuiltinSymbolMap.find(ID.lower());
3628fe6060f1SDimitry Andric       if (BuiltinIt != BuiltinSymbolMap.end()) {
3629fe6060f1SDimitry Andric         llvm::Optional<std::string> BuiltinText =
3630fe6060f1SDimitry Andric             evaluateBuiltinTextMacro(BuiltinIt->getValue(), StartLoc);
3631fe6060f1SDimitry Andric         if (!BuiltinText.hasValue()) {
3632fe6060f1SDimitry Andric           // Not a text macro; break without substituting
3633fe6060f1SDimitry Andric           break;
3634fe6060f1SDimitry Andric         }
3635fe6060f1SDimitry Andric         Data = std::move(*BuiltinText);
3636fe6060f1SDimitry Andric         ID = StringRef(Data);
3637fe6060f1SDimitry Andric         Expanded = true;
3638fe6060f1SDimitry Andric         continue;
3639fe6060f1SDimitry Andric       }
3640e8d8bef9SDimitry Andric 
3641fe6060f1SDimitry Andric       // Try to resolve as a variable text macro
3642fe6060f1SDimitry Andric       auto VarIt = Variables.find(ID.lower());
3643fe6060f1SDimitry Andric       if (VarIt != Variables.end()) {
3644fe6060f1SDimitry Andric         const Variable &Var = VarIt->getValue();
3645fe6060f1SDimitry Andric         if (!Var.IsText) {
3646fe6060f1SDimitry Andric           // Not a text macro; break without substituting
3647fe6060f1SDimitry Andric           break;
3648fe6060f1SDimitry Andric         }
3649e8d8bef9SDimitry Andric         Data = Var.TextValue;
3650fe6060f1SDimitry Andric         ID = StringRef(Data);
3651fe6060f1SDimitry Andric         Expanded = true;
3652fe6060f1SDimitry Andric         continue;
3653fe6060f1SDimitry Andric       }
3654fe6060f1SDimitry Andric 
3655fe6060f1SDimitry Andric       break;
3656fe6060f1SDimitry Andric     }
3657fe6060f1SDimitry Andric 
3658fe6060f1SDimitry Andric     if (!Expanded) {
3659fe6060f1SDimitry Andric       // Not a text macro; not usable in TextItem context. Since we haven't used
3660fe6060f1SDimitry Andric       // the token, put it back for better error recovery.
3661fe6060f1SDimitry Andric       getLexer().UnLex(AsmToken(AsmToken::Identifier, ID));
3662fe6060f1SDimitry Andric       return true;
3663e8d8bef9SDimitry Andric     }
3664e8d8bef9SDimitry Andric     return false;
3665e8d8bef9SDimitry Andric   }
3666e8d8bef9SDimitry Andric   }
3667e8d8bef9SDimitry Andric   llvm_unreachable("unhandled token kind");
36685ffd83dbSDimitry Andric }
36695ffd83dbSDimitry Andric 
36705ffd83dbSDimitry Andric /// parseDirectiveAscii:
36715ffd83dbSDimitry Andric ///   ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
36725ffd83dbSDimitry Andric bool MasmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
36735ffd83dbSDimitry Andric   auto parseOp = [&]() -> bool {
36745ffd83dbSDimitry Andric     std::string Data;
36755ffd83dbSDimitry Andric     if (checkForValidSection() || parseEscapedString(Data))
36765ffd83dbSDimitry Andric       return true;
36775ffd83dbSDimitry Andric     getStreamer().emitBytes(Data);
36785ffd83dbSDimitry Andric     if (ZeroTerminated)
36795ffd83dbSDimitry Andric       getStreamer().emitBytes(StringRef("\0", 1));
36805ffd83dbSDimitry Andric     return false;
36815ffd83dbSDimitry Andric   };
36825ffd83dbSDimitry Andric 
36835ffd83dbSDimitry Andric   if (parseMany(parseOp))
36845ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
36855ffd83dbSDimitry Andric   return false;
36865ffd83dbSDimitry Andric }
36875ffd83dbSDimitry Andric 
36885ffd83dbSDimitry Andric bool MasmParser::emitIntValue(const MCExpr *Value, unsigned Size) {
36895ffd83dbSDimitry Andric   // Special case constant expressions to match code generator.
36905ffd83dbSDimitry Andric   if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
36915ffd83dbSDimitry Andric     assert(Size <= 8 && "Invalid size");
36925ffd83dbSDimitry Andric     int64_t IntValue = MCE->getValue();
36935ffd83dbSDimitry Andric     if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
36945ffd83dbSDimitry Andric       return Error(MCE->getLoc(), "out of range literal value");
36955ffd83dbSDimitry Andric     getStreamer().emitIntValue(IntValue, Size);
36965ffd83dbSDimitry Andric   } else {
36975ffd83dbSDimitry Andric     const MCSymbolRefExpr *MSE = dyn_cast<MCSymbolRefExpr>(Value);
36985ffd83dbSDimitry Andric     if (MSE && MSE->getSymbol().getName() == "?") {
36995ffd83dbSDimitry Andric       // ? initializer; treat as 0.
37005ffd83dbSDimitry Andric       getStreamer().emitIntValue(0, Size);
37015ffd83dbSDimitry Andric     } else {
37025ffd83dbSDimitry Andric       getStreamer().emitValue(Value, Size, Value->getLoc());
37035ffd83dbSDimitry Andric     }
37045ffd83dbSDimitry Andric   }
37055ffd83dbSDimitry Andric   return false;
37065ffd83dbSDimitry Andric }
37075ffd83dbSDimitry Andric 
37085ffd83dbSDimitry Andric bool MasmParser::parseScalarInitializer(unsigned Size,
37095ffd83dbSDimitry Andric                                         SmallVectorImpl<const MCExpr *> &Values,
37105ffd83dbSDimitry Andric                                         unsigned StringPadLength) {
3711e8d8bef9SDimitry Andric   if (Size == 1 && getTok().is(AsmToken::String)) {
3712e8d8bef9SDimitry Andric     std::string Value;
3713e8d8bef9SDimitry Andric     if (parseEscapedString(Value))
3714e8d8bef9SDimitry Andric       return true;
37155ffd83dbSDimitry Andric     // Treat each character as an initializer.
3716e8d8bef9SDimitry Andric     for (const unsigned char CharVal : Value)
37175ffd83dbSDimitry Andric       Values.push_back(MCConstantExpr::create(CharVal, getContext()));
37185ffd83dbSDimitry Andric 
37195ffd83dbSDimitry Andric     // Pad the string with spaces to the specified length.
37205ffd83dbSDimitry Andric     for (size_t i = Value.size(); i < StringPadLength; ++i)
37215ffd83dbSDimitry Andric       Values.push_back(MCConstantExpr::create(' ', getContext()));
37225ffd83dbSDimitry Andric   } else {
37235ffd83dbSDimitry Andric     const MCExpr *Value;
3724e8d8bef9SDimitry Andric     if (parseExpression(Value))
37255ffd83dbSDimitry Andric       return true;
37265ffd83dbSDimitry Andric     if (getTok().is(AsmToken::Identifier) &&
3727fe6060f1SDimitry Andric         getTok().getString().equals_insensitive("dup")) {
37285ffd83dbSDimitry Andric       Lex(); // Eat 'dup'.
37295ffd83dbSDimitry Andric       const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
37305ffd83dbSDimitry Andric       if (!MCE)
37315ffd83dbSDimitry Andric         return Error(Value->getLoc(),
37325ffd83dbSDimitry Andric                      "cannot repeat value a non-constant number of times");
37335ffd83dbSDimitry Andric       const int64_t Repetitions = MCE->getValue();
37345ffd83dbSDimitry Andric       if (Repetitions < 0)
37355ffd83dbSDimitry Andric         return Error(Value->getLoc(),
37365ffd83dbSDimitry Andric                      "cannot repeat value a negative number of times");
37375ffd83dbSDimitry Andric 
37385ffd83dbSDimitry Andric       SmallVector<const MCExpr *, 1> DuplicatedValues;
37395ffd83dbSDimitry Andric       if (parseToken(AsmToken::LParen,
37405ffd83dbSDimitry Andric                      "parentheses required for 'dup' contents") ||
3741*04eeddc0SDimitry Andric           parseScalarInstList(Size, DuplicatedValues) || parseRParen())
37425ffd83dbSDimitry Andric         return true;
37435ffd83dbSDimitry Andric 
37445ffd83dbSDimitry Andric       for (int i = 0; i < Repetitions; ++i)
37455ffd83dbSDimitry Andric         Values.append(DuplicatedValues.begin(), DuplicatedValues.end());
37465ffd83dbSDimitry Andric     } else {
37475ffd83dbSDimitry Andric       Values.push_back(Value);
37485ffd83dbSDimitry Andric     }
37495ffd83dbSDimitry Andric   }
37505ffd83dbSDimitry Andric   return false;
37515ffd83dbSDimitry Andric }
37525ffd83dbSDimitry Andric 
37535ffd83dbSDimitry Andric bool MasmParser::parseScalarInstList(unsigned Size,
37545ffd83dbSDimitry Andric                                      SmallVectorImpl<const MCExpr *> &Values,
37555ffd83dbSDimitry Andric                                      const AsmToken::TokenKind EndToken) {
37565ffd83dbSDimitry Andric   while (getTok().isNot(EndToken) &&
37575ffd83dbSDimitry Andric          (EndToken != AsmToken::Greater ||
37585ffd83dbSDimitry Andric           getTok().isNot(AsmToken::GreaterGreater))) {
37595ffd83dbSDimitry Andric     parseScalarInitializer(Size, Values);
37605ffd83dbSDimitry Andric 
37615ffd83dbSDimitry Andric     // If we see a comma, continue, and allow line continuation.
37625ffd83dbSDimitry Andric     if (!parseOptionalToken(AsmToken::Comma))
37635ffd83dbSDimitry Andric       break;
37645ffd83dbSDimitry Andric     parseOptionalToken(AsmToken::EndOfStatement);
37655ffd83dbSDimitry Andric   }
37665ffd83dbSDimitry Andric   return false;
37675ffd83dbSDimitry Andric }
37685ffd83dbSDimitry Andric 
3769e8d8bef9SDimitry Andric bool MasmParser::emitIntegralValues(unsigned Size, unsigned *Count) {
37705ffd83dbSDimitry Andric   SmallVector<const MCExpr *, 1> Values;
37715ffd83dbSDimitry Andric   if (checkForValidSection() || parseScalarInstList(Size, Values))
37725ffd83dbSDimitry Andric     return true;
37735ffd83dbSDimitry Andric 
37745ffd83dbSDimitry Andric   for (auto Value : Values) {
37755ffd83dbSDimitry Andric     emitIntValue(Value, Size);
37765ffd83dbSDimitry Andric   }
3777e8d8bef9SDimitry Andric   if (Count)
3778e8d8bef9SDimitry Andric     *Count = Values.size();
37795ffd83dbSDimitry Andric   return false;
37805ffd83dbSDimitry Andric }
37815ffd83dbSDimitry Andric 
37825ffd83dbSDimitry Andric // Add a field to the current structure.
37835ffd83dbSDimitry Andric bool MasmParser::addIntegralField(StringRef Name, unsigned Size) {
37845ffd83dbSDimitry Andric   StructInfo &Struct = StructInProgress.back();
3785e8d8bef9SDimitry Andric   FieldInfo &Field = Struct.addField(Name, FT_INTEGRAL, Size);
37865ffd83dbSDimitry Andric   IntFieldInfo &IntInfo = Field.Contents.IntInfo;
37875ffd83dbSDimitry Andric 
37885ffd83dbSDimitry Andric   Field.Type = Size;
37895ffd83dbSDimitry Andric 
37905ffd83dbSDimitry Andric   if (parseScalarInstList(Size, IntInfo.Values))
37915ffd83dbSDimitry Andric     return true;
37925ffd83dbSDimitry Andric 
37935ffd83dbSDimitry Andric   Field.SizeOf = Field.Type * IntInfo.Values.size();
37945ffd83dbSDimitry Andric   Field.LengthOf = IntInfo.Values.size();
3795fe6060f1SDimitry Andric   const unsigned FieldEnd = Field.Offset + Field.SizeOf;
3796fe6060f1SDimitry Andric   if (!Struct.IsUnion) {
3797fe6060f1SDimitry Andric     Struct.NextOffset = FieldEnd;
3798fe6060f1SDimitry Andric   }
3799fe6060f1SDimitry Andric   Struct.Size = std::max(Struct.Size, FieldEnd);
38005ffd83dbSDimitry Andric   return false;
38015ffd83dbSDimitry Andric }
38025ffd83dbSDimitry Andric 
38035ffd83dbSDimitry Andric /// parseDirectiveValue
38045ffd83dbSDimitry Andric ///  ::= (byte | word | ... ) [ expression (, expression)* ]
38055ffd83dbSDimitry Andric bool MasmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
38065ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
38075ffd83dbSDimitry Andric     // Initialize data value.
38085ffd83dbSDimitry Andric     if (emitIntegralValues(Size))
38095ffd83dbSDimitry Andric       return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
38105ffd83dbSDimitry Andric   } else if (addIntegralField("", Size)) {
38115ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
38125ffd83dbSDimitry Andric   }
38135ffd83dbSDimitry Andric 
38145ffd83dbSDimitry Andric   return false;
38155ffd83dbSDimitry Andric }
38165ffd83dbSDimitry Andric 
38175ffd83dbSDimitry Andric /// parseDirectiveNamedValue
38185ffd83dbSDimitry Andric ///  ::= name (byte | word | ... ) [ expression (, expression)* ]
3819e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
38205ffd83dbSDimitry Andric                                           StringRef Name, SMLoc NameLoc) {
38215ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
38225ffd83dbSDimitry Andric     // Initialize named data value.
38235ffd83dbSDimitry Andric     MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
38245ffd83dbSDimitry Andric     getStreamer().emitLabel(Sym);
3825e8d8bef9SDimitry Andric     unsigned Count;
3826e8d8bef9SDimitry Andric     if (emitIntegralValues(Size, &Count))
3827e8d8bef9SDimitry Andric       return addErrorSuffix(" in '" + Twine(TypeName) + "' directive");
3828e8d8bef9SDimitry Andric 
3829e8d8bef9SDimitry Andric     AsmTypeInfo Type;
3830e8d8bef9SDimitry Andric     Type.Name = TypeName;
3831e8d8bef9SDimitry Andric     Type.Size = Size * Count;
3832e8d8bef9SDimitry Andric     Type.ElementSize = Size;
3833e8d8bef9SDimitry Andric     Type.Length = Count;
3834e8d8bef9SDimitry Andric     KnownType[Name.lower()] = Type;
38355ffd83dbSDimitry Andric   } else if (addIntegralField(Name, Size)) {
3836e8d8bef9SDimitry Andric     return addErrorSuffix(" in '" + Twine(TypeName) + "' directive");
38375ffd83dbSDimitry Andric   }
38385ffd83dbSDimitry Andric 
38395ffd83dbSDimitry Andric   return false;
38405ffd83dbSDimitry Andric }
38415ffd83dbSDimitry Andric 
38425ffd83dbSDimitry Andric static bool parseHexOcta(MasmParser &Asm, uint64_t &hi, uint64_t &lo) {
38435ffd83dbSDimitry Andric   if (Asm.getTok().isNot(AsmToken::Integer) &&
38445ffd83dbSDimitry Andric       Asm.getTok().isNot(AsmToken::BigNum))
38455ffd83dbSDimitry Andric     return Asm.TokError("unknown token in expression");
38465ffd83dbSDimitry Andric   SMLoc ExprLoc = Asm.getTok().getLoc();
38475ffd83dbSDimitry Andric   APInt IntValue = Asm.getTok().getAPIntVal();
38485ffd83dbSDimitry Andric   Asm.Lex();
38495ffd83dbSDimitry Andric   if (!IntValue.isIntN(128))
38505ffd83dbSDimitry Andric     return Asm.Error(ExprLoc, "out of range literal value");
38515ffd83dbSDimitry Andric   if (!IntValue.isIntN(64)) {
38525ffd83dbSDimitry Andric     hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();
38535ffd83dbSDimitry Andric     lo = IntValue.getLoBits(64).getZExtValue();
38545ffd83dbSDimitry Andric   } else {
38555ffd83dbSDimitry Andric     hi = 0;
38565ffd83dbSDimitry Andric     lo = IntValue.getZExtValue();
38575ffd83dbSDimitry Andric   }
38585ffd83dbSDimitry Andric   return false;
38595ffd83dbSDimitry Andric }
38605ffd83dbSDimitry Andric 
38615ffd83dbSDimitry Andric bool MasmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
38625ffd83dbSDimitry Andric   // We don't truly support arithmetic on floating point expressions, so we
38635ffd83dbSDimitry Andric   // have to manually parse unary prefixes.
38645ffd83dbSDimitry Andric   bool IsNeg = false;
3865e8d8bef9SDimitry Andric   SMLoc SignLoc;
38665ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Minus)) {
3867e8d8bef9SDimitry Andric     SignLoc = getLexer().getLoc();
38685ffd83dbSDimitry Andric     Lexer.Lex();
38695ffd83dbSDimitry Andric     IsNeg = true;
38705ffd83dbSDimitry Andric   } else if (getLexer().is(AsmToken::Plus)) {
3871e8d8bef9SDimitry Andric     SignLoc = getLexer().getLoc();
38725ffd83dbSDimitry Andric     Lexer.Lex();
38735ffd83dbSDimitry Andric   }
38745ffd83dbSDimitry Andric 
38755ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::Error))
38765ffd83dbSDimitry Andric     return TokError(Lexer.getErr());
38775ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
38785ffd83dbSDimitry Andric       Lexer.isNot(AsmToken::Identifier))
38795ffd83dbSDimitry Andric     return TokError("unexpected token in directive");
38805ffd83dbSDimitry Andric 
38815ffd83dbSDimitry Andric   // Convert to an APFloat.
38825ffd83dbSDimitry Andric   APFloat Value(Semantics);
38835ffd83dbSDimitry Andric   StringRef IDVal = getTok().getString();
38845ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Identifier)) {
3885fe6060f1SDimitry Andric     if (IDVal.equals_insensitive("infinity") || IDVal.equals_insensitive("inf"))
38865ffd83dbSDimitry Andric       Value = APFloat::getInf(Semantics);
3887fe6060f1SDimitry Andric     else if (IDVal.equals_insensitive("nan"))
38885ffd83dbSDimitry Andric       Value = APFloat::getNaN(Semantics, false, ~0);
3889fe6060f1SDimitry Andric     else if (IDVal.equals_insensitive("?"))
38905ffd83dbSDimitry Andric       Value = APFloat::getZero(Semantics);
38915ffd83dbSDimitry Andric     else
38925ffd83dbSDimitry Andric       return TokError("invalid floating point literal");
3893e8d8bef9SDimitry Andric   } else if (IDVal.consume_back("r") || IDVal.consume_back("R")) {
3894e8d8bef9SDimitry Andric     // MASM hexadecimal floating-point literal; no APFloat conversion needed.
3895e8d8bef9SDimitry Andric     // To match ML64.exe, ignore the initial sign.
3896e8d8bef9SDimitry Andric     unsigned SizeInBits = Value.getSizeInBits(Semantics);
3897e8d8bef9SDimitry Andric     if (SizeInBits != (IDVal.size() << 2))
3898e8d8bef9SDimitry Andric       return TokError("invalid floating point literal");
3899e8d8bef9SDimitry Andric 
3900e8d8bef9SDimitry Andric     // Consume the numeric token.
3901e8d8bef9SDimitry Andric     Lex();
3902e8d8bef9SDimitry Andric 
3903e8d8bef9SDimitry Andric     Res = APInt(SizeInBits, IDVal, 16);
3904e8d8bef9SDimitry Andric     if (SignLoc.isValid())
3905e8d8bef9SDimitry Andric       return Warning(SignLoc, "MASM-style hex floats ignore explicit sign");
3906e8d8bef9SDimitry Andric     return false;
39075ffd83dbSDimitry Andric   } else if (errorToBool(
39085ffd83dbSDimitry Andric                  Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
39095ffd83dbSDimitry Andric                      .takeError())) {
39105ffd83dbSDimitry Andric     return TokError("invalid floating point literal");
39115ffd83dbSDimitry Andric   }
39125ffd83dbSDimitry Andric   if (IsNeg)
39135ffd83dbSDimitry Andric     Value.changeSign();
39145ffd83dbSDimitry Andric 
39155ffd83dbSDimitry Andric   // Consume the numeric token.
39165ffd83dbSDimitry Andric   Lex();
39175ffd83dbSDimitry Andric 
39185ffd83dbSDimitry Andric   Res = Value.bitcastToAPInt();
39195ffd83dbSDimitry Andric 
39205ffd83dbSDimitry Andric   return false;
39215ffd83dbSDimitry Andric }
39225ffd83dbSDimitry Andric 
39235ffd83dbSDimitry Andric bool MasmParser::parseRealInstList(const fltSemantics &Semantics,
39245ffd83dbSDimitry Andric                                    SmallVectorImpl<APInt> &ValuesAsInt,
39255ffd83dbSDimitry Andric                                    const AsmToken::TokenKind EndToken) {
39265ffd83dbSDimitry Andric   while (getTok().isNot(EndToken) ||
39275ffd83dbSDimitry Andric          (EndToken == AsmToken::Greater &&
39285ffd83dbSDimitry Andric           getTok().isNot(AsmToken::GreaterGreater))) {
3929fe6060f1SDimitry Andric     const AsmToken NextTok = peekTok();
39305ffd83dbSDimitry Andric     if (NextTok.is(AsmToken::Identifier) &&
3931fe6060f1SDimitry Andric         NextTok.getString().equals_insensitive("dup")) {
39325ffd83dbSDimitry Andric       const MCExpr *Value;
39335ffd83dbSDimitry Andric       if (parseExpression(Value) || parseToken(AsmToken::Identifier))
39345ffd83dbSDimitry Andric         return true;
39355ffd83dbSDimitry Andric       const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
39365ffd83dbSDimitry Andric       if (!MCE)
39375ffd83dbSDimitry Andric         return Error(Value->getLoc(),
39385ffd83dbSDimitry Andric                      "cannot repeat value a non-constant number of times");
39395ffd83dbSDimitry Andric       const int64_t Repetitions = MCE->getValue();
39405ffd83dbSDimitry Andric       if (Repetitions < 0)
39415ffd83dbSDimitry Andric         return Error(Value->getLoc(),
39425ffd83dbSDimitry Andric                      "cannot repeat value a negative number of times");
39435ffd83dbSDimitry Andric 
39445ffd83dbSDimitry Andric       SmallVector<APInt, 1> DuplicatedValues;
39455ffd83dbSDimitry Andric       if (parseToken(AsmToken::LParen,
39465ffd83dbSDimitry Andric                      "parentheses required for 'dup' contents") ||
3947*04eeddc0SDimitry Andric           parseRealInstList(Semantics, DuplicatedValues) || parseRParen())
39485ffd83dbSDimitry Andric         return true;
39495ffd83dbSDimitry Andric 
39505ffd83dbSDimitry Andric       for (int i = 0; i < Repetitions; ++i)
39515ffd83dbSDimitry Andric         ValuesAsInt.append(DuplicatedValues.begin(), DuplicatedValues.end());
39525ffd83dbSDimitry Andric     } else {
39535ffd83dbSDimitry Andric       APInt AsInt;
39545ffd83dbSDimitry Andric       if (parseRealValue(Semantics, AsInt))
39555ffd83dbSDimitry Andric         return true;
39565ffd83dbSDimitry Andric       ValuesAsInt.push_back(AsInt);
39575ffd83dbSDimitry Andric     }
39585ffd83dbSDimitry Andric 
39595ffd83dbSDimitry Andric     // Continue if we see a comma. (Also, allow line continuation.)
39605ffd83dbSDimitry Andric     if (!parseOptionalToken(AsmToken::Comma))
39615ffd83dbSDimitry Andric       break;
39625ffd83dbSDimitry Andric     parseOptionalToken(AsmToken::EndOfStatement);
39635ffd83dbSDimitry Andric   }
39645ffd83dbSDimitry Andric 
39655ffd83dbSDimitry Andric   return false;
39665ffd83dbSDimitry Andric }
39675ffd83dbSDimitry Andric 
39685ffd83dbSDimitry Andric // Initialize real data values.
3969e8d8bef9SDimitry Andric bool MasmParser::emitRealValues(const fltSemantics &Semantics,
3970e8d8bef9SDimitry Andric                                 unsigned *Count) {
3971e8d8bef9SDimitry Andric   if (checkForValidSection())
3972e8d8bef9SDimitry Andric     return true;
3973e8d8bef9SDimitry Andric 
39745ffd83dbSDimitry Andric   SmallVector<APInt, 1> ValuesAsInt;
39755ffd83dbSDimitry Andric   if (parseRealInstList(Semantics, ValuesAsInt))
39765ffd83dbSDimitry Andric     return true;
39775ffd83dbSDimitry Andric 
39785ffd83dbSDimitry Andric   for (const APInt &AsInt : ValuesAsInt) {
3979e8d8bef9SDimitry Andric     getStreamer().emitIntValue(AsInt);
39805ffd83dbSDimitry Andric   }
3981e8d8bef9SDimitry Andric   if (Count)
3982e8d8bef9SDimitry Andric     *Count = ValuesAsInt.size();
39835ffd83dbSDimitry Andric   return false;
39845ffd83dbSDimitry Andric }
39855ffd83dbSDimitry Andric 
39865ffd83dbSDimitry Andric // Add a real field to the current struct.
3987e8d8bef9SDimitry Andric bool MasmParser::addRealField(StringRef Name, const fltSemantics &Semantics,
3988e8d8bef9SDimitry Andric                               size_t Size) {
39895ffd83dbSDimitry Andric   StructInfo &Struct = StructInProgress.back();
3990e8d8bef9SDimitry Andric   FieldInfo &Field = Struct.addField(Name, FT_REAL, Size);
39915ffd83dbSDimitry Andric   RealFieldInfo &RealInfo = Field.Contents.RealInfo;
39925ffd83dbSDimitry Andric 
39935ffd83dbSDimitry Andric   Field.SizeOf = 0;
39945ffd83dbSDimitry Andric 
3995e8d8bef9SDimitry Andric   if (parseRealInstList(Semantics, RealInfo.AsIntValues))
39965ffd83dbSDimitry Andric     return true;
39975ffd83dbSDimitry Andric 
39985ffd83dbSDimitry Andric   Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
39995ffd83dbSDimitry Andric   Field.LengthOf = RealInfo.AsIntValues.size();
40005ffd83dbSDimitry Andric   Field.SizeOf = Field.Type * Field.LengthOf;
4001fe6060f1SDimitry Andric 
4002fe6060f1SDimitry Andric   const unsigned FieldEnd = Field.Offset + Field.SizeOf;
4003fe6060f1SDimitry Andric   if (!Struct.IsUnion) {
4004fe6060f1SDimitry Andric     Struct.NextOffset = FieldEnd;
4005fe6060f1SDimitry Andric   }
4006fe6060f1SDimitry Andric   Struct.Size = std::max(Struct.Size, FieldEnd);
40075ffd83dbSDimitry Andric   return false;
40085ffd83dbSDimitry Andric }
40095ffd83dbSDimitry Andric 
40105ffd83dbSDimitry Andric /// parseDirectiveRealValue
4011e8d8bef9SDimitry Andric ///  ::= (real4 | real8 | real10) [ expression (, expression)* ]
40125ffd83dbSDimitry Andric bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
4013e8d8bef9SDimitry Andric                                          const fltSemantics &Semantics,
4014e8d8bef9SDimitry Andric                                          size_t Size) {
40155ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
40165ffd83dbSDimitry Andric     // Initialize data value.
40175ffd83dbSDimitry Andric     if (emitRealValues(Semantics))
40185ffd83dbSDimitry Andric       return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
4019e8d8bef9SDimitry Andric   } else if (addRealField("", Semantics, Size)) {
40205ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
40215ffd83dbSDimitry Andric   }
40225ffd83dbSDimitry Andric   return false;
40235ffd83dbSDimitry Andric }
40245ffd83dbSDimitry Andric 
40255ffd83dbSDimitry Andric /// parseDirectiveNamedRealValue
4026e8d8bef9SDimitry Andric ///  ::= name (real4 | real8 | real10) [ expression (, expression)* ]
4027e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
40285ffd83dbSDimitry Andric                                               const fltSemantics &Semantics,
4029e8d8bef9SDimitry Andric                                               unsigned Size, StringRef Name,
4030e8d8bef9SDimitry Andric                                               SMLoc NameLoc) {
40315ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
40325ffd83dbSDimitry Andric     // Initialize named data value.
40335ffd83dbSDimitry Andric     MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
40345ffd83dbSDimitry Andric     getStreamer().emitLabel(Sym);
4035e8d8bef9SDimitry Andric     unsigned Count;
4036e8d8bef9SDimitry Andric     if (emitRealValues(Semantics, &Count))
4037e8d8bef9SDimitry Andric       return addErrorSuffix(" in '" + TypeName + "' directive");
4038e8d8bef9SDimitry Andric 
4039e8d8bef9SDimitry Andric     AsmTypeInfo Type;
4040e8d8bef9SDimitry Andric     Type.Name = TypeName;
4041e8d8bef9SDimitry Andric     Type.Size = Size * Count;
4042e8d8bef9SDimitry Andric     Type.ElementSize = Size;
4043e8d8bef9SDimitry Andric     Type.Length = Count;
4044e8d8bef9SDimitry Andric     KnownType[Name.lower()] = Type;
4045e8d8bef9SDimitry Andric   } else if (addRealField(Name, Semantics, Size)) {
4046e8d8bef9SDimitry Andric     return addErrorSuffix(" in '" + TypeName + "' directive");
40475ffd83dbSDimitry Andric   }
40485ffd83dbSDimitry Andric   return false;
40495ffd83dbSDimitry Andric }
40505ffd83dbSDimitry Andric 
40515ffd83dbSDimitry Andric bool MasmParser::parseOptionalAngleBracketOpen() {
40525ffd83dbSDimitry Andric   const AsmToken Tok = getTok();
40535ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::LessLess)) {
40545ffd83dbSDimitry Andric     AngleBracketDepth++;
40555ffd83dbSDimitry Andric     Lexer.UnLex(AsmToken(AsmToken::Less, Tok.getString().substr(1)));
40565ffd83dbSDimitry Andric     return true;
40575ffd83dbSDimitry Andric   } else if (parseOptionalToken(AsmToken::LessGreater)) {
40585ffd83dbSDimitry Andric     AngleBracketDepth++;
40595ffd83dbSDimitry Andric     Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1)));
40605ffd83dbSDimitry Andric     return true;
40615ffd83dbSDimitry Andric   } else if (parseOptionalToken(AsmToken::Less)) {
40625ffd83dbSDimitry Andric     AngleBracketDepth++;
40635ffd83dbSDimitry Andric     return true;
40645ffd83dbSDimitry Andric   }
40655ffd83dbSDimitry Andric 
40665ffd83dbSDimitry Andric   return false;
40675ffd83dbSDimitry Andric }
40685ffd83dbSDimitry Andric 
40695ffd83dbSDimitry Andric bool MasmParser::parseAngleBracketClose(const Twine &Msg) {
40705ffd83dbSDimitry Andric   const AsmToken Tok = getTok();
40715ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::GreaterGreater)) {
40725ffd83dbSDimitry Andric     Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1)));
40735ffd83dbSDimitry Andric   } else if (parseToken(AsmToken::Greater, Msg)) {
40745ffd83dbSDimitry Andric     return true;
40755ffd83dbSDimitry Andric   }
40765ffd83dbSDimitry Andric   AngleBracketDepth--;
40775ffd83dbSDimitry Andric   return false;
40785ffd83dbSDimitry Andric }
40795ffd83dbSDimitry Andric 
40805ffd83dbSDimitry Andric bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
40815ffd83dbSDimitry Andric                                        const IntFieldInfo &Contents,
40825ffd83dbSDimitry Andric                                        FieldInitializer &Initializer) {
40835ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
40845ffd83dbSDimitry Andric 
40855ffd83dbSDimitry Andric   SmallVector<const MCExpr *, 1> Values;
40865ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::LCurly)) {
40875ffd83dbSDimitry Andric     if (Field.LengthOf == 1 && Field.Type > 1)
40885ffd83dbSDimitry Andric       return Error(Loc, "Cannot initialize scalar field with array value");
40895ffd83dbSDimitry Andric     if (parseScalarInstList(Field.Type, Values, AsmToken::RCurly) ||
40905ffd83dbSDimitry Andric         parseToken(AsmToken::RCurly))
40915ffd83dbSDimitry Andric       return true;
40925ffd83dbSDimitry Andric   } else if (parseOptionalAngleBracketOpen()) {
40935ffd83dbSDimitry Andric     if (Field.LengthOf == 1 && Field.Type > 1)
40945ffd83dbSDimitry Andric       return Error(Loc, "Cannot initialize scalar field with array value");
40955ffd83dbSDimitry Andric     if (parseScalarInstList(Field.Type, Values, AsmToken::Greater) ||
40965ffd83dbSDimitry Andric         parseAngleBracketClose())
40975ffd83dbSDimitry Andric       return true;
40985ffd83dbSDimitry Andric   } else if (Field.LengthOf > 1 && Field.Type > 1) {
40995ffd83dbSDimitry Andric     return Error(Loc, "Cannot initialize array field with scalar value");
41005ffd83dbSDimitry Andric   } else if (parseScalarInitializer(Field.Type, Values,
41015ffd83dbSDimitry Andric                                     /*StringPadLength=*/Field.LengthOf)) {
41025ffd83dbSDimitry Andric     return true;
41035ffd83dbSDimitry Andric   }
41045ffd83dbSDimitry Andric 
41055ffd83dbSDimitry Andric   if (Values.size() > Field.LengthOf) {
41065ffd83dbSDimitry Andric     return Error(Loc, "Initializer too long for field; expected at most " +
41075ffd83dbSDimitry Andric                           std::to_string(Field.LengthOf) + " elements, got " +
41085ffd83dbSDimitry Andric                           std::to_string(Values.size()));
41095ffd83dbSDimitry Andric   }
41105ffd83dbSDimitry Andric   // Default-initialize all remaining values.
41115ffd83dbSDimitry Andric   Values.append(Contents.Values.begin() + Values.size(), Contents.Values.end());
41125ffd83dbSDimitry Andric 
41135ffd83dbSDimitry Andric   Initializer = FieldInitializer(std::move(Values));
41145ffd83dbSDimitry Andric   return false;
41155ffd83dbSDimitry Andric }
41165ffd83dbSDimitry Andric 
41175ffd83dbSDimitry Andric bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
41185ffd83dbSDimitry Andric                                        const RealFieldInfo &Contents,
41195ffd83dbSDimitry Andric                                        FieldInitializer &Initializer) {
4120e8d8bef9SDimitry Andric   const fltSemantics *Semantics;
4121e8d8bef9SDimitry Andric   switch (Field.Type) {
4122e8d8bef9SDimitry Andric   case 4:
4123e8d8bef9SDimitry Andric     Semantics = &APFloat::IEEEsingle();
4124e8d8bef9SDimitry Andric     break;
4125e8d8bef9SDimitry Andric   case 8:
4126e8d8bef9SDimitry Andric     Semantics = &APFloat::IEEEdouble();
4127e8d8bef9SDimitry Andric     break;
4128e8d8bef9SDimitry Andric   case 10:
4129e8d8bef9SDimitry Andric     Semantics = &APFloat::x87DoubleExtended();
4130e8d8bef9SDimitry Andric     break;
4131e8d8bef9SDimitry Andric   default:
4132e8d8bef9SDimitry Andric     llvm_unreachable("unknown real field type");
4133e8d8bef9SDimitry Andric   }
41345ffd83dbSDimitry Andric 
41355ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
41365ffd83dbSDimitry Andric 
41375ffd83dbSDimitry Andric   SmallVector<APInt, 1> AsIntValues;
41385ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::LCurly)) {
41395ffd83dbSDimitry Andric     if (Field.LengthOf == 1)
41405ffd83dbSDimitry Andric       return Error(Loc, "Cannot initialize scalar field with array value");
4141e8d8bef9SDimitry Andric     if (parseRealInstList(*Semantics, AsIntValues, AsmToken::RCurly) ||
41425ffd83dbSDimitry Andric         parseToken(AsmToken::RCurly))
41435ffd83dbSDimitry Andric       return true;
41445ffd83dbSDimitry Andric   } else if (parseOptionalAngleBracketOpen()) {
41455ffd83dbSDimitry Andric     if (Field.LengthOf == 1)
41465ffd83dbSDimitry Andric       return Error(Loc, "Cannot initialize scalar field with array value");
4147e8d8bef9SDimitry Andric     if (parseRealInstList(*Semantics, AsIntValues, AsmToken::Greater) ||
41485ffd83dbSDimitry Andric         parseAngleBracketClose())
41495ffd83dbSDimitry Andric       return true;
41505ffd83dbSDimitry Andric   } else if (Field.LengthOf > 1) {
41515ffd83dbSDimitry Andric     return Error(Loc, "Cannot initialize array field with scalar value");
41525ffd83dbSDimitry Andric   } else {
41535ffd83dbSDimitry Andric     AsIntValues.emplace_back();
4154e8d8bef9SDimitry Andric     if (parseRealValue(*Semantics, AsIntValues.back()))
41555ffd83dbSDimitry Andric       return true;
41565ffd83dbSDimitry Andric   }
41575ffd83dbSDimitry Andric 
41585ffd83dbSDimitry Andric   if (AsIntValues.size() > Field.LengthOf) {
41595ffd83dbSDimitry Andric     return Error(Loc, "Initializer too long for field; expected at most " +
41605ffd83dbSDimitry Andric                           std::to_string(Field.LengthOf) + " elements, got " +
41615ffd83dbSDimitry Andric                           std::to_string(AsIntValues.size()));
41625ffd83dbSDimitry Andric   }
41635ffd83dbSDimitry Andric   // Default-initialize all remaining values.
41645ffd83dbSDimitry Andric   AsIntValues.append(Contents.AsIntValues.begin() + AsIntValues.size(),
41655ffd83dbSDimitry Andric                      Contents.AsIntValues.end());
41665ffd83dbSDimitry Andric 
41675ffd83dbSDimitry Andric   Initializer = FieldInitializer(std::move(AsIntValues));
41685ffd83dbSDimitry Andric   return false;
41695ffd83dbSDimitry Andric }
41705ffd83dbSDimitry Andric 
41715ffd83dbSDimitry Andric bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
41725ffd83dbSDimitry Andric                                        const StructFieldInfo &Contents,
41735ffd83dbSDimitry Andric                                        FieldInitializer &Initializer) {
41745ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
41755ffd83dbSDimitry Andric 
41765ffd83dbSDimitry Andric   std::vector<StructInitializer> Initializers;
41775ffd83dbSDimitry Andric   if (Field.LengthOf > 1) {
41785ffd83dbSDimitry Andric     if (parseOptionalToken(AsmToken::LCurly)) {
41795ffd83dbSDimitry Andric       if (parseStructInstList(Contents.Structure, Initializers,
41805ffd83dbSDimitry Andric                               AsmToken::RCurly) ||
41815ffd83dbSDimitry Andric           parseToken(AsmToken::RCurly))
41825ffd83dbSDimitry Andric         return true;
41835ffd83dbSDimitry Andric     } else if (parseOptionalAngleBracketOpen()) {
41845ffd83dbSDimitry Andric       if (parseStructInstList(Contents.Structure, Initializers,
41855ffd83dbSDimitry Andric                               AsmToken::Greater) ||
41865ffd83dbSDimitry Andric           parseAngleBracketClose())
41875ffd83dbSDimitry Andric         return true;
41885ffd83dbSDimitry Andric     } else {
41895ffd83dbSDimitry Andric       return Error(Loc, "Cannot initialize array field with scalar value");
41905ffd83dbSDimitry Andric     }
41915ffd83dbSDimitry Andric   } else {
41925ffd83dbSDimitry Andric     Initializers.emplace_back();
41935ffd83dbSDimitry Andric     if (parseStructInitializer(Contents.Structure, Initializers.back()))
41945ffd83dbSDimitry Andric       return true;
41955ffd83dbSDimitry Andric   }
41965ffd83dbSDimitry Andric 
41975ffd83dbSDimitry Andric   if (Initializers.size() > Field.LengthOf) {
41985ffd83dbSDimitry Andric     return Error(Loc, "Initializer too long for field; expected at most " +
41995ffd83dbSDimitry Andric                           std::to_string(Field.LengthOf) + " elements, got " +
42005ffd83dbSDimitry Andric                           std::to_string(Initializers.size()));
42015ffd83dbSDimitry Andric   }
42025ffd83dbSDimitry Andric   // Default-initialize all remaining values.
42035ffd83dbSDimitry Andric   Initializers.insert(Initializers.end(),
42045ffd83dbSDimitry Andric                       Contents.Initializers.begin() + Initializers.size(),
42055ffd83dbSDimitry Andric                       Contents.Initializers.end());
42065ffd83dbSDimitry Andric 
42075ffd83dbSDimitry Andric   Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
42085ffd83dbSDimitry Andric   return false;
42095ffd83dbSDimitry Andric }
42105ffd83dbSDimitry Andric 
42115ffd83dbSDimitry Andric bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
42125ffd83dbSDimitry Andric                                        FieldInitializer &Initializer) {
42135ffd83dbSDimitry Andric   switch (Field.Contents.FT) {
42145ffd83dbSDimitry Andric   case FT_INTEGRAL:
42155ffd83dbSDimitry Andric     return parseFieldInitializer(Field, Field.Contents.IntInfo, Initializer);
42165ffd83dbSDimitry Andric   case FT_REAL:
42175ffd83dbSDimitry Andric     return parseFieldInitializer(Field, Field.Contents.RealInfo, Initializer);
42185ffd83dbSDimitry Andric   case FT_STRUCT:
42195ffd83dbSDimitry Andric     return parseFieldInitializer(Field, Field.Contents.StructInfo, Initializer);
42205ffd83dbSDimitry Andric   }
42215ffd83dbSDimitry Andric   llvm_unreachable("Unhandled FieldType enum");
42225ffd83dbSDimitry Andric }
42235ffd83dbSDimitry Andric 
42245ffd83dbSDimitry Andric bool MasmParser::parseStructInitializer(const StructInfo &Structure,
42255ffd83dbSDimitry Andric                                         StructInitializer &Initializer) {
42265ffd83dbSDimitry Andric   const AsmToken FirstToken = getTok();
42275ffd83dbSDimitry Andric 
42285ffd83dbSDimitry Andric   Optional<AsmToken::TokenKind> EndToken;
42295ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::LCurly)) {
42305ffd83dbSDimitry Andric     EndToken = AsmToken::RCurly;
42315ffd83dbSDimitry Andric   } else if (parseOptionalAngleBracketOpen()) {
42325ffd83dbSDimitry Andric     EndToken = AsmToken::Greater;
42335ffd83dbSDimitry Andric     AngleBracketDepth++;
42345ffd83dbSDimitry Andric   } else if (FirstToken.is(AsmToken::Identifier) &&
42355ffd83dbSDimitry Andric              FirstToken.getString() == "?") {
42365ffd83dbSDimitry Andric     // ? initializer; leave EndToken uninitialized to treat as empty.
42375ffd83dbSDimitry Andric     if (parseToken(AsmToken::Identifier))
42385ffd83dbSDimitry Andric       return true;
42395ffd83dbSDimitry Andric   } else {
42405ffd83dbSDimitry Andric     return Error(FirstToken.getLoc(), "Expected struct initializer");
42415ffd83dbSDimitry Andric   }
42425ffd83dbSDimitry Andric 
42435ffd83dbSDimitry Andric   auto &FieldInitializers = Initializer.FieldInitializers;
42445ffd83dbSDimitry Andric   size_t FieldIndex = 0;
42455ffd83dbSDimitry Andric   if (EndToken.hasValue()) {
42465ffd83dbSDimitry Andric     // Initialize all fields with given initializers.
42475ffd83dbSDimitry Andric     while (getTok().isNot(EndToken.getValue()) &&
42485ffd83dbSDimitry Andric            FieldIndex < Structure.Fields.size()) {
42495ffd83dbSDimitry Andric       const FieldInfo &Field = Structure.Fields[FieldIndex++];
42505ffd83dbSDimitry Andric       if (parseOptionalToken(AsmToken::Comma)) {
42515ffd83dbSDimitry Andric         // Empty initializer; use the default and continue. (Also, allow line
42525ffd83dbSDimitry Andric         // continuation.)
42535ffd83dbSDimitry Andric         FieldInitializers.push_back(Field.Contents);
42545ffd83dbSDimitry Andric         parseOptionalToken(AsmToken::EndOfStatement);
42555ffd83dbSDimitry Andric         continue;
42565ffd83dbSDimitry Andric       }
42575ffd83dbSDimitry Andric       FieldInitializers.emplace_back(Field.Contents.FT);
42585ffd83dbSDimitry Andric       if (parseFieldInitializer(Field, FieldInitializers.back()))
42595ffd83dbSDimitry Andric         return true;
42605ffd83dbSDimitry Andric 
42615ffd83dbSDimitry Andric       // Continue if we see a comma. (Also, allow line continuation.)
42625ffd83dbSDimitry Andric       SMLoc CommaLoc = getTok().getLoc();
42635ffd83dbSDimitry Andric       if (!parseOptionalToken(AsmToken::Comma))
42645ffd83dbSDimitry Andric         break;
42655ffd83dbSDimitry Andric       if (FieldIndex == Structure.Fields.size())
42665ffd83dbSDimitry Andric         return Error(CommaLoc, "'" + Structure.Name +
42675ffd83dbSDimitry Andric                                    "' initializer initializes too many fields");
42685ffd83dbSDimitry Andric       parseOptionalToken(AsmToken::EndOfStatement);
42695ffd83dbSDimitry Andric     }
42705ffd83dbSDimitry Andric   }
42715ffd83dbSDimitry Andric   // Default-initialize all remaining fields.
42725ffd83dbSDimitry Andric   for (auto It = Structure.Fields.begin() + FieldIndex;
42735ffd83dbSDimitry Andric        It != Structure.Fields.end(); ++It) {
42745ffd83dbSDimitry Andric     const FieldInfo &Field = *It;
42755ffd83dbSDimitry Andric     FieldInitializers.push_back(Field.Contents);
42765ffd83dbSDimitry Andric   }
42775ffd83dbSDimitry Andric 
42785ffd83dbSDimitry Andric   if (EndToken.hasValue()) {
42795ffd83dbSDimitry Andric     if (EndToken.getValue() == AsmToken::Greater)
42805ffd83dbSDimitry Andric       return parseAngleBracketClose();
42815ffd83dbSDimitry Andric 
42825ffd83dbSDimitry Andric     return parseToken(EndToken.getValue());
42835ffd83dbSDimitry Andric   }
42845ffd83dbSDimitry Andric 
42855ffd83dbSDimitry Andric   return false;
42865ffd83dbSDimitry Andric }
42875ffd83dbSDimitry Andric 
42885ffd83dbSDimitry Andric bool MasmParser::parseStructInstList(
42895ffd83dbSDimitry Andric     const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
42905ffd83dbSDimitry Andric     const AsmToken::TokenKind EndToken) {
42915ffd83dbSDimitry Andric   while (getTok().isNot(EndToken) ||
42925ffd83dbSDimitry Andric          (EndToken == AsmToken::Greater &&
42935ffd83dbSDimitry Andric           getTok().isNot(AsmToken::GreaterGreater))) {
4294fe6060f1SDimitry Andric     const AsmToken NextTok = peekTok();
42955ffd83dbSDimitry Andric     if (NextTok.is(AsmToken::Identifier) &&
4296fe6060f1SDimitry Andric         NextTok.getString().equals_insensitive("dup")) {
42975ffd83dbSDimitry Andric       const MCExpr *Value;
42985ffd83dbSDimitry Andric       if (parseExpression(Value) || parseToken(AsmToken::Identifier))
42995ffd83dbSDimitry Andric         return true;
43005ffd83dbSDimitry Andric       const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
43015ffd83dbSDimitry Andric       if (!MCE)
43025ffd83dbSDimitry Andric         return Error(Value->getLoc(),
43035ffd83dbSDimitry Andric                      "cannot repeat value a non-constant number of times");
43045ffd83dbSDimitry Andric       const int64_t Repetitions = MCE->getValue();
43055ffd83dbSDimitry Andric       if (Repetitions < 0)
43065ffd83dbSDimitry Andric         return Error(Value->getLoc(),
43075ffd83dbSDimitry Andric                      "cannot repeat value a negative number of times");
43085ffd83dbSDimitry Andric 
43095ffd83dbSDimitry Andric       std::vector<StructInitializer> DuplicatedValues;
43105ffd83dbSDimitry Andric       if (parseToken(AsmToken::LParen,
43115ffd83dbSDimitry Andric                      "parentheses required for 'dup' contents") ||
4312*04eeddc0SDimitry Andric           parseStructInstList(Structure, DuplicatedValues) || parseRParen())
43135ffd83dbSDimitry Andric         return true;
43145ffd83dbSDimitry Andric 
43155ffd83dbSDimitry Andric       for (int i = 0; i < Repetitions; ++i)
4316e8d8bef9SDimitry Andric         llvm::append_range(Initializers, DuplicatedValues);
43175ffd83dbSDimitry Andric     } else {
43185ffd83dbSDimitry Andric       Initializers.emplace_back();
43195ffd83dbSDimitry Andric       if (parseStructInitializer(Structure, Initializers.back()))
43205ffd83dbSDimitry Andric         return true;
43215ffd83dbSDimitry Andric     }
43225ffd83dbSDimitry Andric 
43235ffd83dbSDimitry Andric     // Continue if we see a comma. (Also, allow line continuation.)
43245ffd83dbSDimitry Andric     if (!parseOptionalToken(AsmToken::Comma))
43255ffd83dbSDimitry Andric       break;
43265ffd83dbSDimitry Andric     parseOptionalToken(AsmToken::EndOfStatement);
43275ffd83dbSDimitry Andric   }
43285ffd83dbSDimitry Andric 
43295ffd83dbSDimitry Andric   return false;
43305ffd83dbSDimitry Andric }
43315ffd83dbSDimitry Andric 
43325ffd83dbSDimitry Andric bool MasmParser::emitFieldValue(const FieldInfo &Field,
43335ffd83dbSDimitry Andric                                 const IntFieldInfo &Contents) {
43345ffd83dbSDimitry Andric   // Default-initialize all values.
43355ffd83dbSDimitry Andric   for (const MCExpr *Value : Contents.Values) {
43365ffd83dbSDimitry Andric     if (emitIntValue(Value, Field.Type))
43375ffd83dbSDimitry Andric       return true;
43385ffd83dbSDimitry Andric   }
43395ffd83dbSDimitry Andric   return false;
43405ffd83dbSDimitry Andric }
43415ffd83dbSDimitry Andric 
43425ffd83dbSDimitry Andric bool MasmParser::emitFieldValue(const FieldInfo &Field,
43435ffd83dbSDimitry Andric                                 const RealFieldInfo &Contents) {
43445ffd83dbSDimitry Andric   for (const APInt &AsInt : Contents.AsIntValues) {
43455ffd83dbSDimitry Andric     getStreamer().emitIntValue(AsInt.getLimitedValue(),
43465ffd83dbSDimitry Andric                                AsInt.getBitWidth() / 8);
43475ffd83dbSDimitry Andric   }
43485ffd83dbSDimitry Andric   return false;
43495ffd83dbSDimitry Andric }
43505ffd83dbSDimitry Andric 
43515ffd83dbSDimitry Andric bool MasmParser::emitFieldValue(const FieldInfo &Field,
43525ffd83dbSDimitry Andric                                 const StructFieldInfo &Contents) {
43535ffd83dbSDimitry Andric   for (const auto &Initializer : Contents.Initializers) {
43545ffd83dbSDimitry Andric     size_t Index = 0, Offset = 0;
43555ffd83dbSDimitry Andric     for (const auto &SubField : Contents.Structure.Fields) {
43565ffd83dbSDimitry Andric       getStreamer().emitZeros(SubField.Offset - Offset);
43575ffd83dbSDimitry Andric       Offset = SubField.Offset + SubField.SizeOf;
43585ffd83dbSDimitry Andric       emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
43595ffd83dbSDimitry Andric     }
43605ffd83dbSDimitry Andric   }
43615ffd83dbSDimitry Andric   return false;
43625ffd83dbSDimitry Andric }
43635ffd83dbSDimitry Andric 
43645ffd83dbSDimitry Andric bool MasmParser::emitFieldValue(const FieldInfo &Field) {
43655ffd83dbSDimitry Andric   switch (Field.Contents.FT) {
43665ffd83dbSDimitry Andric   case FT_INTEGRAL:
43675ffd83dbSDimitry Andric     return emitFieldValue(Field, Field.Contents.IntInfo);
43685ffd83dbSDimitry Andric   case FT_REAL:
43695ffd83dbSDimitry Andric     return emitFieldValue(Field, Field.Contents.RealInfo);
43705ffd83dbSDimitry Andric   case FT_STRUCT:
43715ffd83dbSDimitry Andric     return emitFieldValue(Field, Field.Contents.StructInfo);
43725ffd83dbSDimitry Andric   }
43735ffd83dbSDimitry Andric   llvm_unreachable("Unhandled FieldType enum");
43745ffd83dbSDimitry Andric }
43755ffd83dbSDimitry Andric 
43765ffd83dbSDimitry Andric bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
43775ffd83dbSDimitry Andric                                       const IntFieldInfo &Contents,
43785ffd83dbSDimitry Andric                                       const IntFieldInfo &Initializer) {
43795ffd83dbSDimitry Andric   for (const auto &Value : Initializer.Values) {
43805ffd83dbSDimitry Andric     if (emitIntValue(Value, Field.Type))
43815ffd83dbSDimitry Andric       return true;
43825ffd83dbSDimitry Andric   }
43835ffd83dbSDimitry Andric   // Default-initialize all remaining values.
43845ffd83dbSDimitry Andric   for (auto it = Contents.Values.begin() + Initializer.Values.size();
43855ffd83dbSDimitry Andric        it != Contents.Values.end(); ++it) {
43865ffd83dbSDimitry Andric     const auto &Value = *it;
43875ffd83dbSDimitry Andric     if (emitIntValue(Value, Field.Type))
43885ffd83dbSDimitry Andric       return true;
43895ffd83dbSDimitry Andric   }
43905ffd83dbSDimitry Andric   return false;
43915ffd83dbSDimitry Andric }
43925ffd83dbSDimitry Andric 
43935ffd83dbSDimitry Andric bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
43945ffd83dbSDimitry Andric                                       const RealFieldInfo &Contents,
43955ffd83dbSDimitry Andric                                       const RealFieldInfo &Initializer) {
43965ffd83dbSDimitry Andric   for (const auto &AsInt : Initializer.AsIntValues) {
43975ffd83dbSDimitry Andric     getStreamer().emitIntValue(AsInt.getLimitedValue(),
43985ffd83dbSDimitry Andric                                AsInt.getBitWidth() / 8);
43995ffd83dbSDimitry Andric   }
44005ffd83dbSDimitry Andric   // Default-initialize all remaining values.
44015ffd83dbSDimitry Andric   for (auto It = Contents.AsIntValues.begin() + Initializer.AsIntValues.size();
44025ffd83dbSDimitry Andric        It != Contents.AsIntValues.end(); ++It) {
44035ffd83dbSDimitry Andric     const auto &AsInt = *It;
44045ffd83dbSDimitry Andric     getStreamer().emitIntValue(AsInt.getLimitedValue(),
44055ffd83dbSDimitry Andric                                AsInt.getBitWidth() / 8);
44065ffd83dbSDimitry Andric   }
44075ffd83dbSDimitry Andric   return false;
44085ffd83dbSDimitry Andric }
44095ffd83dbSDimitry Andric 
44105ffd83dbSDimitry Andric bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
44115ffd83dbSDimitry Andric                                       const StructFieldInfo &Contents,
44125ffd83dbSDimitry Andric                                       const StructFieldInfo &Initializer) {
44135ffd83dbSDimitry Andric   for (const auto &Init : Initializer.Initializers) {
4414fe6060f1SDimitry Andric     if (emitStructInitializer(Contents.Structure, Init))
4415fe6060f1SDimitry Andric       return true;
44165ffd83dbSDimitry Andric   }
44175ffd83dbSDimitry Andric   // Default-initialize all remaining values.
44185ffd83dbSDimitry Andric   for (auto It =
44195ffd83dbSDimitry Andric            Contents.Initializers.begin() + Initializer.Initializers.size();
44205ffd83dbSDimitry Andric        It != Contents.Initializers.end(); ++It) {
44215ffd83dbSDimitry Andric     const auto &Init = *It;
4422fe6060f1SDimitry Andric     if (emitStructInitializer(Contents.Structure, Init))
4423fe6060f1SDimitry Andric       return true;
44245ffd83dbSDimitry Andric   }
44255ffd83dbSDimitry Andric   return false;
44265ffd83dbSDimitry Andric }
44275ffd83dbSDimitry Andric 
44285ffd83dbSDimitry Andric bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
44295ffd83dbSDimitry Andric                                       const FieldInitializer &Initializer) {
44305ffd83dbSDimitry Andric   switch (Field.Contents.FT) {
44315ffd83dbSDimitry Andric   case FT_INTEGRAL:
44325ffd83dbSDimitry Andric     return emitFieldInitializer(Field, Field.Contents.IntInfo,
44335ffd83dbSDimitry Andric                                 Initializer.IntInfo);
44345ffd83dbSDimitry Andric   case FT_REAL:
44355ffd83dbSDimitry Andric     return emitFieldInitializer(Field, Field.Contents.RealInfo,
44365ffd83dbSDimitry Andric                                 Initializer.RealInfo);
44375ffd83dbSDimitry Andric   case FT_STRUCT:
44385ffd83dbSDimitry Andric     return emitFieldInitializer(Field, Field.Contents.StructInfo,
44395ffd83dbSDimitry Andric                                 Initializer.StructInfo);
44405ffd83dbSDimitry Andric   }
44415ffd83dbSDimitry Andric   llvm_unreachable("Unhandled FieldType enum");
44425ffd83dbSDimitry Andric }
44435ffd83dbSDimitry Andric 
44445ffd83dbSDimitry Andric bool MasmParser::emitStructInitializer(const StructInfo &Structure,
44455ffd83dbSDimitry Andric                                        const StructInitializer &Initializer) {
4446fe6060f1SDimitry Andric   if (!Structure.Initializable)
4447fe6060f1SDimitry Andric     return Error(getLexer().getLoc(),
4448fe6060f1SDimitry Andric                  "cannot initialize a value of type '" + Structure.Name +
4449fe6060f1SDimitry Andric                      "'; 'org' was used in the type's declaration");
44505ffd83dbSDimitry Andric   size_t Index = 0, Offset = 0;
44515ffd83dbSDimitry Andric   for (const auto &Init : Initializer.FieldInitializers) {
44525ffd83dbSDimitry Andric     const auto &Field = Structure.Fields[Index++];
44535ffd83dbSDimitry Andric     getStreamer().emitZeros(Field.Offset - Offset);
44545ffd83dbSDimitry Andric     Offset = Field.Offset + Field.SizeOf;
44555ffd83dbSDimitry Andric     if (emitFieldInitializer(Field, Init))
44565ffd83dbSDimitry Andric       return true;
44575ffd83dbSDimitry Andric   }
44585ffd83dbSDimitry Andric   // Default-initialize all remaining fields.
44595ffd83dbSDimitry Andric   for (auto It =
44605ffd83dbSDimitry Andric            Structure.Fields.begin() + Initializer.FieldInitializers.size();
44615ffd83dbSDimitry Andric        It != Structure.Fields.end(); ++It) {
44625ffd83dbSDimitry Andric     const auto &Field = *It;
44635ffd83dbSDimitry Andric     getStreamer().emitZeros(Field.Offset - Offset);
44645ffd83dbSDimitry Andric     Offset = Field.Offset + Field.SizeOf;
44655ffd83dbSDimitry Andric     if (emitFieldValue(Field))
44665ffd83dbSDimitry Andric       return true;
44675ffd83dbSDimitry Andric   }
44685ffd83dbSDimitry Andric   // Add final padding.
44695ffd83dbSDimitry Andric   if (Offset != Structure.Size)
44705ffd83dbSDimitry Andric     getStreamer().emitZeros(Structure.Size - Offset);
44715ffd83dbSDimitry Andric   return false;
44725ffd83dbSDimitry Andric }
44735ffd83dbSDimitry Andric 
44745ffd83dbSDimitry Andric // Set data values from initializers.
4475e8d8bef9SDimitry Andric bool MasmParser::emitStructValues(const StructInfo &Structure,
4476e8d8bef9SDimitry Andric                                   unsigned *Count) {
44775ffd83dbSDimitry Andric   std::vector<StructInitializer> Initializers;
44785ffd83dbSDimitry Andric   if (parseStructInstList(Structure, Initializers))
44795ffd83dbSDimitry Andric     return true;
44805ffd83dbSDimitry Andric 
44815ffd83dbSDimitry Andric   for (const auto &Initializer : Initializers) {
44825ffd83dbSDimitry Andric     if (emitStructInitializer(Structure, Initializer))
44835ffd83dbSDimitry Andric       return true;
44845ffd83dbSDimitry Andric   }
44855ffd83dbSDimitry Andric 
4486e8d8bef9SDimitry Andric   if (Count)
4487e8d8bef9SDimitry Andric     *Count = Initializers.size();
44885ffd83dbSDimitry Andric   return false;
44895ffd83dbSDimitry Andric }
44905ffd83dbSDimitry Andric 
44915ffd83dbSDimitry Andric // Declare a field in the current struct.
44925ffd83dbSDimitry Andric bool MasmParser::addStructField(StringRef Name, const StructInfo &Structure) {
44935ffd83dbSDimitry Andric   StructInfo &OwningStruct = StructInProgress.back();
4494e8d8bef9SDimitry Andric   FieldInfo &Field =
4495e8d8bef9SDimitry Andric       OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
44965ffd83dbSDimitry Andric   StructFieldInfo &StructInfo = Field.Contents.StructInfo;
44975ffd83dbSDimitry Andric 
44985ffd83dbSDimitry Andric   StructInfo.Structure = Structure;
44995ffd83dbSDimitry Andric   Field.Type = Structure.Size;
45005ffd83dbSDimitry Andric 
45015ffd83dbSDimitry Andric   if (parseStructInstList(Structure, StructInfo.Initializers))
45025ffd83dbSDimitry Andric     return true;
45035ffd83dbSDimitry Andric 
45045ffd83dbSDimitry Andric   Field.LengthOf = StructInfo.Initializers.size();
45055ffd83dbSDimitry Andric   Field.SizeOf = Field.Type * Field.LengthOf;
4506fe6060f1SDimitry Andric 
4507fe6060f1SDimitry Andric   const unsigned FieldEnd = Field.Offset + Field.SizeOf;
4508fe6060f1SDimitry Andric   if (!OwningStruct.IsUnion) {
4509fe6060f1SDimitry Andric     OwningStruct.NextOffset = FieldEnd;
4510fe6060f1SDimitry Andric   }
4511fe6060f1SDimitry Andric   OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd);
45125ffd83dbSDimitry Andric 
45135ffd83dbSDimitry Andric   return false;
45145ffd83dbSDimitry Andric }
45155ffd83dbSDimitry Andric 
45165ffd83dbSDimitry Andric /// parseDirectiveStructValue
45175ffd83dbSDimitry Andric ///  ::= struct-id (<struct-initializer> | {struct-initializer})
45185ffd83dbSDimitry Andric ///                [, (<struct-initializer> | {struct-initializer})]*
45195ffd83dbSDimitry Andric bool MasmParser::parseDirectiveStructValue(const StructInfo &Structure,
45205ffd83dbSDimitry Andric                                            StringRef Directive, SMLoc DirLoc) {
45215ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
45225ffd83dbSDimitry Andric     if (emitStructValues(Structure))
45235ffd83dbSDimitry Andric       return true;
45245ffd83dbSDimitry Andric   } else if (addStructField("", Structure)) {
45255ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
45265ffd83dbSDimitry Andric   }
45275ffd83dbSDimitry Andric 
45285ffd83dbSDimitry Andric   return false;
45295ffd83dbSDimitry Andric }
45305ffd83dbSDimitry Andric 
45315ffd83dbSDimitry Andric /// parseDirectiveNamedValue
45325ffd83dbSDimitry Andric ///  ::= name (byte | word | ... ) [ expression (, expression)* ]
45335ffd83dbSDimitry Andric bool MasmParser::parseDirectiveNamedStructValue(const StructInfo &Structure,
45345ffd83dbSDimitry Andric                                                 StringRef Directive,
45355ffd83dbSDimitry Andric                                                 SMLoc DirLoc, StringRef Name) {
45365ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
45375ffd83dbSDimitry Andric     // Initialize named data value.
45385ffd83dbSDimitry Andric     MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
45395ffd83dbSDimitry Andric     getStreamer().emitLabel(Sym);
4540e8d8bef9SDimitry Andric     unsigned Count;
4541e8d8bef9SDimitry Andric     if (emitStructValues(Structure, &Count))
45425ffd83dbSDimitry Andric       return true;
4543e8d8bef9SDimitry Andric     AsmTypeInfo Type;
4544e8d8bef9SDimitry Andric     Type.Name = Structure.Name;
4545e8d8bef9SDimitry Andric     Type.Size = Structure.Size * Count;
4546e8d8bef9SDimitry Andric     Type.ElementSize = Structure.Size;
4547e8d8bef9SDimitry Andric     Type.Length = Count;
4548e8d8bef9SDimitry Andric     KnownType[Name.lower()] = Type;
45495ffd83dbSDimitry Andric   } else if (addStructField(Name, Structure)) {
45505ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
45515ffd83dbSDimitry Andric   }
45525ffd83dbSDimitry Andric 
45535ffd83dbSDimitry Andric   return false;
45545ffd83dbSDimitry Andric }
45555ffd83dbSDimitry Andric 
45565ffd83dbSDimitry Andric /// parseDirectiveStruct
45575ffd83dbSDimitry Andric ///  ::= <name> (STRUC | STRUCT | UNION) [fieldAlign] [, NONUNIQUE]
45585ffd83dbSDimitry Andric ///      (dataDir | generalDir | offsetDir | nestedStruct)+
45595ffd83dbSDimitry Andric ///      <name> ENDS
45605ffd83dbSDimitry Andric ////// dataDir = data declaration
45615ffd83dbSDimitry Andric ////// offsetDir = EVEN, ORG, ALIGN
45625ffd83dbSDimitry Andric bool MasmParser::parseDirectiveStruct(StringRef Directive,
45635ffd83dbSDimitry Andric                                       DirectiveKind DirKind, StringRef Name,
45645ffd83dbSDimitry Andric                                       SMLoc NameLoc) {
45655ffd83dbSDimitry Andric   // We ignore NONUNIQUE; we do not support OPTION M510 or OPTION OLDSTRUCTS
45665ffd83dbSDimitry Andric   // anyway, so all field accesses must be qualified.
45675ffd83dbSDimitry Andric   AsmToken NextTok = getTok();
45685ffd83dbSDimitry Andric   int64_t AlignmentValue = 1;
45695ffd83dbSDimitry Andric   if (NextTok.isNot(AsmToken::Comma) &&
45705ffd83dbSDimitry Andric       NextTok.isNot(AsmToken::EndOfStatement) &&
45715ffd83dbSDimitry Andric       parseAbsoluteExpression(AlignmentValue)) {
45725ffd83dbSDimitry Andric     return addErrorSuffix(" in alignment value for '" + Twine(Directive) +
45735ffd83dbSDimitry Andric                           "' directive");
45745ffd83dbSDimitry Andric   }
45755ffd83dbSDimitry Andric   if (!isPowerOf2_64(AlignmentValue)) {
45765ffd83dbSDimitry Andric     return Error(NextTok.getLoc(), "alignment must be a power of two; was " +
45775ffd83dbSDimitry Andric                                        std::to_string(AlignmentValue));
45785ffd83dbSDimitry Andric   }
45795ffd83dbSDimitry Andric 
45805ffd83dbSDimitry Andric   StringRef Qualifier;
45815ffd83dbSDimitry Andric   SMLoc QualifierLoc;
45825ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::Comma)) {
45835ffd83dbSDimitry Andric     QualifierLoc = getTok().getLoc();
45845ffd83dbSDimitry Andric     if (parseIdentifier(Qualifier))
45855ffd83dbSDimitry Andric       return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
4586fe6060f1SDimitry Andric     if (!Qualifier.equals_insensitive("nonunique"))
45875ffd83dbSDimitry Andric       return Error(QualifierLoc, "Unrecognized qualifier for '" +
45885ffd83dbSDimitry Andric                                      Twine(Directive) +
45895ffd83dbSDimitry Andric                                      "' directive; expected none or NONUNIQUE");
45905ffd83dbSDimitry Andric   }
45915ffd83dbSDimitry Andric 
45925ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement))
45935ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
45945ffd83dbSDimitry Andric 
45955ffd83dbSDimitry Andric   StructInProgress.emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
45965ffd83dbSDimitry Andric   return false;
45975ffd83dbSDimitry Andric }
45985ffd83dbSDimitry Andric 
45995ffd83dbSDimitry Andric /// parseDirectiveNestedStruct
46005ffd83dbSDimitry Andric ///  ::= (STRUC | STRUCT | UNION) [name]
46015ffd83dbSDimitry Andric ///      (dataDir | generalDir | offsetDir | nestedStruct)+
46025ffd83dbSDimitry Andric ///      ENDS
46035ffd83dbSDimitry Andric bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
46045ffd83dbSDimitry Andric                                             DirectiveKind DirKind) {
46055ffd83dbSDimitry Andric   if (StructInProgress.empty())
46065ffd83dbSDimitry Andric     return TokError("missing name in top-level '" + Twine(Directive) +
46075ffd83dbSDimitry Andric                     "' directive");
46085ffd83dbSDimitry Andric 
46095ffd83dbSDimitry Andric   StringRef Name;
46105ffd83dbSDimitry Andric   if (getTok().is(AsmToken::Identifier)) {
46115ffd83dbSDimitry Andric     Name = getTok().getIdentifier();
46125ffd83dbSDimitry Andric     parseToken(AsmToken::Identifier);
46135ffd83dbSDimitry Andric   }
46145ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement))
46155ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
46165ffd83dbSDimitry Andric 
4617e8d8bef9SDimitry Andric   // Reserve space to ensure Alignment doesn't get invalidated when
4618e8d8bef9SDimitry Andric   // StructInProgress grows.
4619e8d8bef9SDimitry Andric   StructInProgress.reserve(StructInProgress.size() + 1);
46205ffd83dbSDimitry Andric   StructInProgress.emplace_back(Name, DirKind == DK_UNION,
46215ffd83dbSDimitry Andric                                 StructInProgress.back().Alignment);
46225ffd83dbSDimitry Andric   return false;
46235ffd83dbSDimitry Andric }
46245ffd83dbSDimitry Andric 
46255ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
46265ffd83dbSDimitry Andric   if (StructInProgress.empty())
46275ffd83dbSDimitry Andric     return Error(NameLoc, "ENDS directive without matching STRUC/STRUCT/UNION");
46285ffd83dbSDimitry Andric   if (StructInProgress.size() > 1)
46295ffd83dbSDimitry Andric     return Error(NameLoc, "unexpected name in nested ENDS directive");
4630fe6060f1SDimitry Andric   if (StructInProgress.back().Name.compare_insensitive(Name))
46315ffd83dbSDimitry Andric     return Error(NameLoc, "mismatched name in ENDS directive; expected '" +
46325ffd83dbSDimitry Andric                               StructInProgress.back().Name + "'");
46335ffd83dbSDimitry Andric   StructInfo Structure = StructInProgress.pop_back_val();
4634e8d8bef9SDimitry Andric   // Pad to make the structure's size divisible by the smaller of its alignment
4635e8d8bef9SDimitry Andric   // and the size of its largest field.
4636e8d8bef9SDimitry Andric   Structure.Size = llvm::alignTo(
4637e8d8bef9SDimitry Andric       Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
46385ffd83dbSDimitry Andric   Structs[Name.lower()] = Structure;
46395ffd83dbSDimitry Andric 
46405ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement))
46415ffd83dbSDimitry Andric     return addErrorSuffix(" in ENDS directive");
46425ffd83dbSDimitry Andric 
46435ffd83dbSDimitry Andric   return false;
46445ffd83dbSDimitry Andric }
46455ffd83dbSDimitry Andric 
46465ffd83dbSDimitry Andric bool MasmParser::parseDirectiveNestedEnds() {
46475ffd83dbSDimitry Andric   if (StructInProgress.empty())
46485ffd83dbSDimitry Andric     return TokError("ENDS directive without matching STRUC/STRUCT/UNION");
46495ffd83dbSDimitry Andric   if (StructInProgress.size() == 1)
46505ffd83dbSDimitry Andric     return TokError("missing name in top-level ENDS directive");
46515ffd83dbSDimitry Andric 
46525ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement))
46535ffd83dbSDimitry Andric     return addErrorSuffix(" in nested ENDS directive");
46545ffd83dbSDimitry Andric 
46555ffd83dbSDimitry Andric   StructInfo Structure = StructInProgress.pop_back_val();
46565ffd83dbSDimitry Andric   // Pad to make the structure's size divisible by its alignment.
46575ffd83dbSDimitry Andric   Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment);
46585ffd83dbSDimitry Andric 
46595ffd83dbSDimitry Andric   StructInfo &ParentStruct = StructInProgress.back();
46605ffd83dbSDimitry Andric   if (Structure.Name.empty()) {
4661fe6060f1SDimitry Andric     // Anonymous substructures' fields are addressed as if they belong to the
4662fe6060f1SDimitry Andric     // parent structure - so we transfer them to the parent here.
46635ffd83dbSDimitry Andric     const size_t OldFields = ParentStruct.Fields.size();
46645ffd83dbSDimitry Andric     ParentStruct.Fields.insert(
46655ffd83dbSDimitry Andric         ParentStruct.Fields.end(),
46665ffd83dbSDimitry Andric         std::make_move_iterator(Structure.Fields.begin()),
46675ffd83dbSDimitry Andric         std::make_move_iterator(Structure.Fields.end()));
46685ffd83dbSDimitry Andric     for (const auto &FieldByName : Structure.FieldsByName) {
46695ffd83dbSDimitry Andric       ParentStruct.FieldsByName[FieldByName.getKey()] =
46705ffd83dbSDimitry Andric           FieldByName.getValue() + OldFields;
46715ffd83dbSDimitry Andric     }
4672fe6060f1SDimitry Andric 
4673fe6060f1SDimitry Andric     unsigned FirstFieldOffset = 0;
4674fe6060f1SDimitry Andric     if (!Structure.Fields.empty() && !ParentStruct.IsUnion) {
4675fe6060f1SDimitry Andric       FirstFieldOffset = llvm::alignTo(
4676fe6060f1SDimitry Andric           ParentStruct.NextOffset,
4677fe6060f1SDimitry Andric           std::min(ParentStruct.Alignment, Structure.AlignmentSize));
46785ffd83dbSDimitry Andric     }
46795ffd83dbSDimitry Andric 
4680fe6060f1SDimitry Andric     if (ParentStruct.IsUnion) {
46815ffd83dbSDimitry Andric       ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
4682fe6060f1SDimitry Andric     } else {
4683fe6060f1SDimitry Andric       for (auto FieldIter = ParentStruct.Fields.begin() + OldFields;
4684fe6060f1SDimitry Andric            FieldIter != ParentStruct.Fields.end(); ++FieldIter) {
4685fe6060f1SDimitry Andric         FieldIter->Offset += FirstFieldOffset;
4686fe6060f1SDimitry Andric       }
4687fe6060f1SDimitry Andric 
4688fe6060f1SDimitry Andric       const unsigned StructureEnd = FirstFieldOffset + Structure.Size;
4689fe6060f1SDimitry Andric       if (!ParentStruct.IsUnion) {
4690fe6060f1SDimitry Andric         ParentStruct.NextOffset = StructureEnd;
4691fe6060f1SDimitry Andric       }
4692fe6060f1SDimitry Andric       ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4693fe6060f1SDimitry Andric     }
46945ffd83dbSDimitry Andric   } else {
4695e8d8bef9SDimitry Andric     FieldInfo &Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
4696e8d8bef9SDimitry Andric                                              Structure.AlignmentSize);
46975ffd83dbSDimitry Andric     StructFieldInfo &StructInfo = Field.Contents.StructInfo;
46985ffd83dbSDimitry Andric     Field.Type = Structure.Size;
46995ffd83dbSDimitry Andric     Field.LengthOf = 1;
47005ffd83dbSDimitry Andric     Field.SizeOf = Structure.Size;
47015ffd83dbSDimitry Andric 
4702fe6060f1SDimitry Andric     const unsigned StructureEnd = Field.Offset + Field.SizeOf;
4703fe6060f1SDimitry Andric     if (!ParentStruct.IsUnion) {
4704fe6060f1SDimitry Andric       ParentStruct.NextOffset = StructureEnd;
4705fe6060f1SDimitry Andric     }
4706fe6060f1SDimitry Andric     ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
47075ffd83dbSDimitry Andric 
47085ffd83dbSDimitry Andric     StructInfo.Structure = Structure;
47095ffd83dbSDimitry Andric     StructInfo.Initializers.emplace_back();
47105ffd83dbSDimitry Andric     auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
47115ffd83dbSDimitry Andric     for (const auto &SubField : Structure.Fields) {
47125ffd83dbSDimitry Andric       FieldInitializers.push_back(SubField.Contents);
47135ffd83dbSDimitry Andric     }
47145ffd83dbSDimitry Andric   }
47155ffd83dbSDimitry Andric 
47165ffd83dbSDimitry Andric   return false;
47175ffd83dbSDimitry Andric }
47185ffd83dbSDimitry Andric 
47195ffd83dbSDimitry Andric /// parseDirectiveOrg
4720fe6060f1SDimitry Andric ///  ::= org expression
47215ffd83dbSDimitry Andric bool MasmParser::parseDirectiveOrg() {
47225ffd83dbSDimitry Andric   const MCExpr *Offset;
47235ffd83dbSDimitry Andric   SMLoc OffsetLoc = Lexer.getLoc();
47245ffd83dbSDimitry Andric   if (checkForValidSection() || parseExpression(Offset))
47255ffd83dbSDimitry Andric     return true;
47265ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement))
4727fe6060f1SDimitry Andric     return addErrorSuffix(" in 'org' directive");
47285ffd83dbSDimitry Andric 
4729fe6060f1SDimitry Andric   if (StructInProgress.empty()) {
4730fe6060f1SDimitry Andric     // Not in a struct; change the offset for the next instruction or data
4731fe6060f1SDimitry Andric     if (checkForValidSection())
4732fe6060f1SDimitry Andric       return addErrorSuffix(" in 'org' directive");
4733fe6060f1SDimitry Andric 
4734fe6060f1SDimitry Andric     getStreamer().emitValueToOffset(Offset, 0, OffsetLoc);
4735fe6060f1SDimitry Andric   } else {
4736fe6060f1SDimitry Andric     // Offset the next field of this struct
4737fe6060f1SDimitry Andric     StructInfo &Structure = StructInProgress.back();
4738fe6060f1SDimitry Andric     int64_t OffsetRes;
4739fe6060f1SDimitry Andric     if (!Offset->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr()))
4740fe6060f1SDimitry Andric       return Error(OffsetLoc,
4741fe6060f1SDimitry Andric                    "expected absolute expression in 'org' directive");
4742fe6060f1SDimitry Andric     if (OffsetRes < 0)
4743fe6060f1SDimitry Andric       return Error(
4744fe6060f1SDimitry Andric           OffsetLoc,
4745fe6060f1SDimitry Andric           "expected non-negative value in struct's 'org' directive; was " +
4746fe6060f1SDimitry Andric               std::to_string(OffsetRes));
4747fe6060f1SDimitry Andric     Structure.NextOffset = static_cast<unsigned>(OffsetRes);
4748fe6060f1SDimitry Andric 
4749fe6060f1SDimitry Andric     // ORG-affected structures cannot be initialized
4750fe6060f1SDimitry Andric     Structure.Initializable = false;
4751fe6060f1SDimitry Andric   }
4752fe6060f1SDimitry Andric 
47535ffd83dbSDimitry Andric   return false;
47545ffd83dbSDimitry Andric }
47555ffd83dbSDimitry Andric 
4756fe6060f1SDimitry Andric bool MasmParser::emitAlignTo(int64_t Alignment) {
4757fe6060f1SDimitry Andric   if (StructInProgress.empty()) {
4758fe6060f1SDimitry Andric     // Not in a struct; align the next instruction or data
47595ffd83dbSDimitry Andric     if (checkForValidSection())
4760fe6060f1SDimitry Andric       return true;
47615ffd83dbSDimitry Andric 
47625ffd83dbSDimitry Andric     // Check whether we should use optimal code alignment for this align
47635ffd83dbSDimitry Andric     // directive.
47645ffd83dbSDimitry Andric     const MCSection *Section = getStreamer().getCurrentSectionOnly();
47655ffd83dbSDimitry Andric     assert(Section && "must have section to emit alignment");
47665ffd83dbSDimitry Andric     if (Section->UseCodeAlign()) {
4767349cc55cSDimitry Andric       getStreamer().emitCodeAlignment(Alignment, &getTargetParser().getSTI(),
4768349cc55cSDimitry Andric                                       /*MaxBytesToEmit=*/0);
47695ffd83dbSDimitry Andric     } else {
47705ffd83dbSDimitry Andric       // FIXME: Target specific behavior about how the "extra" bytes are filled.
4771fe6060f1SDimitry Andric       getStreamer().emitValueToAlignment(Alignment, /*Value=*/0,
4772fe6060f1SDimitry Andric                                          /*ValueSize=*/1,
47735ffd83dbSDimitry Andric                                          /*MaxBytesToEmit=*/0);
47745ffd83dbSDimitry Andric     }
4775fe6060f1SDimitry Andric   } else {
4776fe6060f1SDimitry Andric     // Align the next field of this struct
4777fe6060f1SDimitry Andric     StructInfo &Structure = StructInProgress.back();
4778fe6060f1SDimitry Andric     Structure.NextOffset = llvm::alignTo(Structure.NextOffset, Alignment);
4779fe6060f1SDimitry Andric   }
4780fe6060f1SDimitry Andric 
4781fe6060f1SDimitry Andric   return false;
4782fe6060f1SDimitry Andric }
4783fe6060f1SDimitry Andric 
4784fe6060f1SDimitry Andric /// parseDirectiveAlign
4785fe6060f1SDimitry Andric ///  ::= align expression
4786fe6060f1SDimitry Andric bool MasmParser::parseDirectiveAlign() {
4787fe6060f1SDimitry Andric   SMLoc AlignmentLoc = getLexer().getLoc();
4788fe6060f1SDimitry Andric   int64_t Alignment;
4789fe6060f1SDimitry Andric 
4790fe6060f1SDimitry Andric   // Ignore empty 'align' directives.
4791fe6060f1SDimitry Andric   if (getTok().is(AsmToken::EndOfStatement)) {
4792fe6060f1SDimitry Andric     return Warning(AlignmentLoc,
4793fe6060f1SDimitry Andric                    "align directive with no operand is ignored") &&
4794fe6060f1SDimitry Andric            parseToken(AsmToken::EndOfStatement);
4795fe6060f1SDimitry Andric   }
4796fe6060f1SDimitry Andric   if (parseAbsoluteExpression(Alignment) ||
4797fe6060f1SDimitry Andric       parseToken(AsmToken::EndOfStatement))
4798fe6060f1SDimitry Andric     return addErrorSuffix(" in align directive");
4799fe6060f1SDimitry Andric 
4800fe6060f1SDimitry Andric   // Always emit an alignment here even if we throw an error.
4801fe6060f1SDimitry Andric   bool ReturnVal = false;
4802fe6060f1SDimitry Andric 
4803fe6060f1SDimitry Andric   // Reject alignments that aren't either a power of two or zero, for ML.exe
4804fe6060f1SDimitry Andric   // compatibility. Alignment of zero is silently rounded up to one.
4805fe6060f1SDimitry Andric   if (Alignment == 0)
4806fe6060f1SDimitry Andric     Alignment = 1;
4807fe6060f1SDimitry Andric   if (!isPowerOf2_64(Alignment))
4808fe6060f1SDimitry Andric     ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2; was " +
4809fe6060f1SDimitry Andric                                          std::to_string(Alignment));
4810fe6060f1SDimitry Andric 
4811fe6060f1SDimitry Andric   if (emitAlignTo(Alignment))
4812fe6060f1SDimitry Andric     ReturnVal |= addErrorSuffix(" in align directive");
48135ffd83dbSDimitry Andric 
48145ffd83dbSDimitry Andric   return ReturnVal;
48155ffd83dbSDimitry Andric }
48165ffd83dbSDimitry Andric 
4817fe6060f1SDimitry Andric /// parseDirectiveEven
4818fe6060f1SDimitry Andric ///  ::= even
4819fe6060f1SDimitry Andric bool MasmParser::parseDirectiveEven() {
4820fe6060f1SDimitry Andric   if (parseToken(AsmToken::EndOfStatement) || emitAlignTo(2))
4821fe6060f1SDimitry Andric     return addErrorSuffix(" in even directive");
4822fe6060f1SDimitry Andric 
4823fe6060f1SDimitry Andric   return false;
4824fe6060f1SDimitry Andric }
4825fe6060f1SDimitry Andric 
48265ffd83dbSDimitry Andric /// parseDirectiveFile
48275ffd83dbSDimitry Andric /// ::= .file filename
48285ffd83dbSDimitry Andric /// ::= .file number [directory] filename [md5 checksum] [source source-text]
48295ffd83dbSDimitry Andric bool MasmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
48305ffd83dbSDimitry Andric   // FIXME: I'm not sure what this is.
48315ffd83dbSDimitry Andric   int64_t FileNumber = -1;
48325ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
48335ffd83dbSDimitry Andric     FileNumber = getTok().getIntVal();
48345ffd83dbSDimitry Andric     Lex();
48355ffd83dbSDimitry Andric 
48365ffd83dbSDimitry Andric     if (FileNumber < 0)
48375ffd83dbSDimitry Andric       return TokError("negative file number");
48385ffd83dbSDimitry Andric   }
48395ffd83dbSDimitry Andric 
48405ffd83dbSDimitry Andric   std::string Path;
48415ffd83dbSDimitry Andric 
48425ffd83dbSDimitry Andric   // Usually the directory and filename together, otherwise just the directory.
48435ffd83dbSDimitry Andric   // Allow the strings to have escaped octal character sequence.
48445ffd83dbSDimitry Andric   if (check(getTok().isNot(AsmToken::String),
48455ffd83dbSDimitry Andric             "unexpected token in '.file' directive") ||
48465ffd83dbSDimitry Andric       parseEscapedString(Path))
48475ffd83dbSDimitry Andric     return true;
48485ffd83dbSDimitry Andric 
48495ffd83dbSDimitry Andric   StringRef Directory;
48505ffd83dbSDimitry Andric   StringRef Filename;
48515ffd83dbSDimitry Andric   std::string FilenameData;
48525ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::String)) {
48535ffd83dbSDimitry Andric     if (check(FileNumber == -1,
48545ffd83dbSDimitry Andric               "explicit path specified, but no file number") ||
48555ffd83dbSDimitry Andric         parseEscapedString(FilenameData))
48565ffd83dbSDimitry Andric       return true;
48575ffd83dbSDimitry Andric     Filename = FilenameData;
48585ffd83dbSDimitry Andric     Directory = Path;
48595ffd83dbSDimitry Andric   } else {
48605ffd83dbSDimitry Andric     Filename = Path;
48615ffd83dbSDimitry Andric   }
48625ffd83dbSDimitry Andric 
48635ffd83dbSDimitry Andric   uint64_t MD5Hi, MD5Lo;
48645ffd83dbSDimitry Andric   bool HasMD5 = false;
48655ffd83dbSDimitry Andric 
48665ffd83dbSDimitry Andric   Optional<StringRef> Source;
48675ffd83dbSDimitry Andric   bool HasSource = false;
48685ffd83dbSDimitry Andric   std::string SourceString;
48695ffd83dbSDimitry Andric 
48705ffd83dbSDimitry Andric   while (!parseOptionalToken(AsmToken::EndOfStatement)) {
48715ffd83dbSDimitry Andric     StringRef Keyword;
48725ffd83dbSDimitry Andric     if (check(getTok().isNot(AsmToken::Identifier),
48735ffd83dbSDimitry Andric               "unexpected token in '.file' directive") ||
48745ffd83dbSDimitry Andric         parseIdentifier(Keyword))
48755ffd83dbSDimitry Andric       return true;
48765ffd83dbSDimitry Andric     if (Keyword == "md5") {
48775ffd83dbSDimitry Andric       HasMD5 = true;
48785ffd83dbSDimitry Andric       if (check(FileNumber == -1,
48795ffd83dbSDimitry Andric                 "MD5 checksum specified, but no file number") ||
48805ffd83dbSDimitry Andric           parseHexOcta(*this, MD5Hi, MD5Lo))
48815ffd83dbSDimitry Andric         return true;
48825ffd83dbSDimitry Andric     } else if (Keyword == "source") {
48835ffd83dbSDimitry Andric       HasSource = true;
48845ffd83dbSDimitry Andric       if (check(FileNumber == -1,
48855ffd83dbSDimitry Andric                 "source specified, but no file number") ||
48865ffd83dbSDimitry Andric           check(getTok().isNot(AsmToken::String),
48875ffd83dbSDimitry Andric                 "unexpected token in '.file' directive") ||
48885ffd83dbSDimitry Andric           parseEscapedString(SourceString))
48895ffd83dbSDimitry Andric         return true;
48905ffd83dbSDimitry Andric     } else {
48915ffd83dbSDimitry Andric       return TokError("unexpected token in '.file' directive");
48925ffd83dbSDimitry Andric     }
48935ffd83dbSDimitry Andric   }
48945ffd83dbSDimitry Andric 
48955ffd83dbSDimitry Andric   if (FileNumber == -1) {
48965ffd83dbSDimitry Andric     // Ignore the directive if there is no number and the target doesn't support
48975ffd83dbSDimitry Andric     // numberless .file directives. This allows some portability of assembler
48985ffd83dbSDimitry Andric     // between different object file formats.
48995ffd83dbSDimitry Andric     if (getContext().getAsmInfo()->hasSingleParameterDotFile())
49005ffd83dbSDimitry Andric       getStreamer().emitFileDirective(Filename);
49015ffd83dbSDimitry Andric   } else {
49025ffd83dbSDimitry Andric     // In case there is a -g option as well as debug info from directive .file,
49035ffd83dbSDimitry Andric     // we turn off the -g option, directly use the existing debug info instead.
49045ffd83dbSDimitry Andric     // Throw away any implicit file table for the assembler source.
49055ffd83dbSDimitry Andric     if (Ctx.getGenDwarfForAssembly()) {
49065ffd83dbSDimitry Andric       Ctx.getMCDwarfLineTable(0).resetFileTable();
49075ffd83dbSDimitry Andric       Ctx.setGenDwarfForAssembly(false);
49085ffd83dbSDimitry Andric     }
49095ffd83dbSDimitry Andric 
49105ffd83dbSDimitry Andric     Optional<MD5::MD5Result> CKMem;
49115ffd83dbSDimitry Andric     if (HasMD5) {
49125ffd83dbSDimitry Andric       MD5::MD5Result Sum;
49135ffd83dbSDimitry Andric       for (unsigned i = 0; i != 8; ++i) {
49145ffd83dbSDimitry Andric         Sum.Bytes[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
49155ffd83dbSDimitry Andric         Sum.Bytes[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
49165ffd83dbSDimitry Andric       }
49175ffd83dbSDimitry Andric       CKMem = Sum;
49185ffd83dbSDimitry Andric     }
49195ffd83dbSDimitry Andric     if (HasSource) {
49205ffd83dbSDimitry Andric       char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
49215ffd83dbSDimitry Andric       memcpy(SourceBuf, SourceString.data(), SourceString.size());
49225ffd83dbSDimitry Andric       Source = StringRef(SourceBuf, SourceString.size());
49235ffd83dbSDimitry Andric     }
49245ffd83dbSDimitry Andric     if (FileNumber == 0) {
49255ffd83dbSDimitry Andric       if (Ctx.getDwarfVersion() < 5)
49265ffd83dbSDimitry Andric         return Warning(DirectiveLoc, "file 0 not supported prior to DWARF-5");
49275ffd83dbSDimitry Andric       getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
49285ffd83dbSDimitry Andric     } else {
49295ffd83dbSDimitry Andric       Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
49305ffd83dbSDimitry Andric           FileNumber, Directory, Filename, CKMem, Source);
49315ffd83dbSDimitry Andric       if (!FileNumOrErr)
49325ffd83dbSDimitry Andric         return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
49335ffd83dbSDimitry Andric     }
49345ffd83dbSDimitry Andric     // Alert the user if there are some .file directives with MD5 and some not.
49355ffd83dbSDimitry Andric     // But only do that once.
49365ffd83dbSDimitry Andric     if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
49375ffd83dbSDimitry Andric       ReportedInconsistentMD5 = true;
49385ffd83dbSDimitry Andric       return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
49395ffd83dbSDimitry Andric     }
49405ffd83dbSDimitry Andric   }
49415ffd83dbSDimitry Andric 
49425ffd83dbSDimitry Andric   return false;
49435ffd83dbSDimitry Andric }
49445ffd83dbSDimitry Andric 
49455ffd83dbSDimitry Andric /// parseDirectiveLine
49465ffd83dbSDimitry Andric /// ::= .line [number]
49475ffd83dbSDimitry Andric bool MasmParser::parseDirectiveLine() {
49485ffd83dbSDimitry Andric   int64_t LineNumber;
49495ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
49505ffd83dbSDimitry Andric     if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
49515ffd83dbSDimitry Andric       return true;
49525ffd83dbSDimitry Andric     (void)LineNumber;
49535ffd83dbSDimitry Andric     // FIXME: Do something with the .line.
49545ffd83dbSDimitry Andric   }
49555ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement,
49565ffd83dbSDimitry Andric                  "unexpected token in '.line' directive"))
49575ffd83dbSDimitry Andric     return true;
49585ffd83dbSDimitry Andric 
49595ffd83dbSDimitry Andric   return false;
49605ffd83dbSDimitry Andric }
49615ffd83dbSDimitry Andric 
49625ffd83dbSDimitry Andric /// parseDirectiveLoc
49635ffd83dbSDimitry Andric /// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
49645ffd83dbSDimitry Andric ///                                [epilogue_begin] [is_stmt VALUE] [isa VALUE]
49655ffd83dbSDimitry Andric /// The first number is a file number, must have been previously assigned with
49665ffd83dbSDimitry Andric /// a .file directive, the second number is the line number and optionally the
49675ffd83dbSDimitry Andric /// third number is a column position (zero if not specified).  The remaining
49685ffd83dbSDimitry Andric /// optional items are .loc sub-directives.
49695ffd83dbSDimitry Andric bool MasmParser::parseDirectiveLoc() {
49705ffd83dbSDimitry Andric   int64_t FileNumber = 0, LineNumber = 0;
49715ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
49725ffd83dbSDimitry Andric   if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
49735ffd83dbSDimitry Andric       check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
49745ffd83dbSDimitry Andric             "file number less than one in '.loc' directive") ||
49755ffd83dbSDimitry Andric       check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
49765ffd83dbSDimitry Andric             "unassigned file number in '.loc' directive"))
49775ffd83dbSDimitry Andric     return true;
49785ffd83dbSDimitry Andric 
49795ffd83dbSDimitry Andric   // optional
49805ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
49815ffd83dbSDimitry Andric     LineNumber = getTok().getIntVal();
49825ffd83dbSDimitry Andric     if (LineNumber < 0)
49835ffd83dbSDimitry Andric       return TokError("line number less than zero in '.loc' directive");
49845ffd83dbSDimitry Andric     Lex();
49855ffd83dbSDimitry Andric   }
49865ffd83dbSDimitry Andric 
49875ffd83dbSDimitry Andric   int64_t ColumnPos = 0;
49885ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
49895ffd83dbSDimitry Andric     ColumnPos = getTok().getIntVal();
49905ffd83dbSDimitry Andric     if (ColumnPos < 0)
49915ffd83dbSDimitry Andric       return TokError("column position less than zero in '.loc' directive");
49925ffd83dbSDimitry Andric     Lex();
49935ffd83dbSDimitry Andric   }
49945ffd83dbSDimitry Andric 
49955ffd83dbSDimitry Andric   auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();
49965ffd83dbSDimitry Andric   unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;
49975ffd83dbSDimitry Andric   unsigned Isa = 0;
49985ffd83dbSDimitry Andric   int64_t Discriminator = 0;
49995ffd83dbSDimitry Andric 
50005ffd83dbSDimitry Andric   auto parseLocOp = [&]() -> bool {
50015ffd83dbSDimitry Andric     StringRef Name;
50025ffd83dbSDimitry Andric     SMLoc Loc = getTok().getLoc();
50035ffd83dbSDimitry Andric     if (parseIdentifier(Name))
50045ffd83dbSDimitry Andric       return TokError("unexpected token in '.loc' directive");
50055ffd83dbSDimitry Andric 
50065ffd83dbSDimitry Andric     if (Name == "basic_block")
50075ffd83dbSDimitry Andric       Flags |= DWARF2_FLAG_BASIC_BLOCK;
50085ffd83dbSDimitry Andric     else if (Name == "prologue_end")
50095ffd83dbSDimitry Andric       Flags |= DWARF2_FLAG_PROLOGUE_END;
50105ffd83dbSDimitry Andric     else if (Name == "epilogue_begin")
50115ffd83dbSDimitry Andric       Flags |= DWARF2_FLAG_EPILOGUE_BEGIN;
50125ffd83dbSDimitry Andric     else if (Name == "is_stmt") {
50135ffd83dbSDimitry Andric       Loc = getTok().getLoc();
50145ffd83dbSDimitry Andric       const MCExpr *Value;
50155ffd83dbSDimitry Andric       if (parseExpression(Value))
50165ffd83dbSDimitry Andric         return true;
50175ffd83dbSDimitry Andric       // The expression must be the constant 0 or 1.
50185ffd83dbSDimitry Andric       if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
50195ffd83dbSDimitry Andric         int Value = MCE->getValue();
50205ffd83dbSDimitry Andric         if (Value == 0)
50215ffd83dbSDimitry Andric           Flags &= ~DWARF2_FLAG_IS_STMT;
50225ffd83dbSDimitry Andric         else if (Value == 1)
50235ffd83dbSDimitry Andric           Flags |= DWARF2_FLAG_IS_STMT;
50245ffd83dbSDimitry Andric         else
50255ffd83dbSDimitry Andric           return Error(Loc, "is_stmt value not 0 or 1");
50265ffd83dbSDimitry Andric       } else {
50275ffd83dbSDimitry Andric         return Error(Loc, "is_stmt value not the constant value of 0 or 1");
50285ffd83dbSDimitry Andric       }
50295ffd83dbSDimitry Andric     } else if (Name == "isa") {
50305ffd83dbSDimitry Andric       Loc = getTok().getLoc();
50315ffd83dbSDimitry Andric       const MCExpr *Value;
50325ffd83dbSDimitry Andric       if (parseExpression(Value))
50335ffd83dbSDimitry Andric         return true;
50345ffd83dbSDimitry Andric       // The expression must be a constant greater or equal to 0.
50355ffd83dbSDimitry Andric       if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
50365ffd83dbSDimitry Andric         int Value = MCE->getValue();
50375ffd83dbSDimitry Andric         if (Value < 0)
50385ffd83dbSDimitry Andric           return Error(Loc, "isa number less than zero");
50395ffd83dbSDimitry Andric         Isa = Value;
50405ffd83dbSDimitry Andric       } else {
50415ffd83dbSDimitry Andric         return Error(Loc, "isa number not a constant value");
50425ffd83dbSDimitry Andric       }
50435ffd83dbSDimitry Andric     } else if (Name == "discriminator") {
50445ffd83dbSDimitry Andric       if (parseAbsoluteExpression(Discriminator))
50455ffd83dbSDimitry Andric         return true;
50465ffd83dbSDimitry Andric     } else {
50475ffd83dbSDimitry Andric       return Error(Loc, "unknown sub-directive in '.loc' directive");
50485ffd83dbSDimitry Andric     }
50495ffd83dbSDimitry Andric     return false;
50505ffd83dbSDimitry Andric   };
50515ffd83dbSDimitry Andric 
50525ffd83dbSDimitry Andric   if (parseMany(parseLocOp, false /*hasComma*/))
50535ffd83dbSDimitry Andric     return true;
50545ffd83dbSDimitry Andric 
50555ffd83dbSDimitry Andric   getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
50565ffd83dbSDimitry Andric                                       Isa, Discriminator, StringRef());
50575ffd83dbSDimitry Andric 
50585ffd83dbSDimitry Andric   return false;
50595ffd83dbSDimitry Andric }
50605ffd83dbSDimitry Andric 
50615ffd83dbSDimitry Andric /// parseDirectiveStabs
50625ffd83dbSDimitry Andric /// ::= .stabs string, number, number, number
50635ffd83dbSDimitry Andric bool MasmParser::parseDirectiveStabs() {
50645ffd83dbSDimitry Andric   return TokError("unsupported directive '.stabs'");
50655ffd83dbSDimitry Andric }
50665ffd83dbSDimitry Andric 
50675ffd83dbSDimitry Andric /// parseDirectiveCVFile
50685ffd83dbSDimitry Andric /// ::= .cv_file number filename [checksum] [checksumkind]
50695ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFile() {
50705ffd83dbSDimitry Andric   SMLoc FileNumberLoc = getTok().getLoc();
50715ffd83dbSDimitry Andric   int64_t FileNumber;
50725ffd83dbSDimitry Andric   std::string Filename;
50735ffd83dbSDimitry Andric   std::string Checksum;
50745ffd83dbSDimitry Andric   int64_t ChecksumKind = 0;
50755ffd83dbSDimitry Andric 
50765ffd83dbSDimitry Andric   if (parseIntToken(FileNumber,
50775ffd83dbSDimitry Andric                     "expected file number in '.cv_file' directive") ||
50785ffd83dbSDimitry Andric       check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
50795ffd83dbSDimitry Andric       check(getTok().isNot(AsmToken::String),
50805ffd83dbSDimitry Andric             "unexpected token in '.cv_file' directive") ||
50815ffd83dbSDimitry Andric       parseEscapedString(Filename))
50825ffd83dbSDimitry Andric     return true;
50835ffd83dbSDimitry Andric   if (!parseOptionalToken(AsmToken::EndOfStatement)) {
50845ffd83dbSDimitry Andric     if (check(getTok().isNot(AsmToken::String),
50855ffd83dbSDimitry Andric               "unexpected token in '.cv_file' directive") ||
50865ffd83dbSDimitry Andric         parseEscapedString(Checksum) ||
50875ffd83dbSDimitry Andric         parseIntToken(ChecksumKind,
50885ffd83dbSDimitry Andric                       "expected checksum kind in '.cv_file' directive") ||
50895ffd83dbSDimitry Andric         parseToken(AsmToken::EndOfStatement,
50905ffd83dbSDimitry Andric                    "unexpected token in '.cv_file' directive"))
50915ffd83dbSDimitry Andric       return true;
50925ffd83dbSDimitry Andric   }
50935ffd83dbSDimitry Andric 
50945ffd83dbSDimitry Andric   Checksum = fromHex(Checksum);
50955ffd83dbSDimitry Andric   void *CKMem = Ctx.allocate(Checksum.size(), 1);
50965ffd83dbSDimitry Andric   memcpy(CKMem, Checksum.data(), Checksum.size());
50975ffd83dbSDimitry Andric   ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
50985ffd83dbSDimitry Andric                                     Checksum.size());
50995ffd83dbSDimitry Andric 
51005ffd83dbSDimitry Andric   if (!getStreamer().EmitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
51015ffd83dbSDimitry Andric                                          static_cast<uint8_t>(ChecksumKind)))
51025ffd83dbSDimitry Andric     return Error(FileNumberLoc, "file number already allocated");
51035ffd83dbSDimitry Andric 
51045ffd83dbSDimitry Andric   return false;
51055ffd83dbSDimitry Andric }
51065ffd83dbSDimitry Andric 
51075ffd83dbSDimitry Andric bool MasmParser::parseCVFunctionId(int64_t &FunctionId,
51085ffd83dbSDimitry Andric                                    StringRef DirectiveName) {
51095ffd83dbSDimitry Andric   SMLoc Loc;
51105ffd83dbSDimitry Andric   return parseTokenLoc(Loc) ||
51115ffd83dbSDimitry Andric          parseIntToken(FunctionId, "expected function id in '" + DirectiveName +
51125ffd83dbSDimitry Andric                                        "' directive") ||
51135ffd83dbSDimitry Andric          check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,
51145ffd83dbSDimitry Andric                "expected function id within range [0, UINT_MAX)");
51155ffd83dbSDimitry Andric }
51165ffd83dbSDimitry Andric 
51175ffd83dbSDimitry Andric bool MasmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
51185ffd83dbSDimitry Andric   SMLoc Loc;
51195ffd83dbSDimitry Andric   return parseTokenLoc(Loc) ||
51205ffd83dbSDimitry Andric          parseIntToken(FileNumber, "expected integer in '" + DirectiveName +
51215ffd83dbSDimitry Andric                                        "' directive") ||
51225ffd83dbSDimitry Andric          check(FileNumber < 1, Loc, "file number less than one in '" +
51235ffd83dbSDimitry Andric                                         DirectiveName + "' directive") ||
51245ffd83dbSDimitry Andric          check(!getCVContext().isValidFileNumber(FileNumber), Loc,
51255ffd83dbSDimitry Andric                "unassigned file number in '" + DirectiveName + "' directive");
51265ffd83dbSDimitry Andric }
51275ffd83dbSDimitry Andric 
51285ffd83dbSDimitry Andric /// parseDirectiveCVFuncId
51295ffd83dbSDimitry Andric /// ::= .cv_func_id FunctionId
51305ffd83dbSDimitry Andric ///
51315ffd83dbSDimitry Andric /// Introduces a function ID that can be used with .cv_loc.
51325ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFuncId() {
51335ffd83dbSDimitry Andric   SMLoc FunctionIdLoc = getTok().getLoc();
51345ffd83dbSDimitry Andric   int64_t FunctionId;
51355ffd83dbSDimitry Andric 
51365ffd83dbSDimitry Andric   if (parseCVFunctionId(FunctionId, ".cv_func_id") ||
51375ffd83dbSDimitry Andric       parseToken(AsmToken::EndOfStatement,
51385ffd83dbSDimitry Andric                  "unexpected token in '.cv_func_id' directive"))
51395ffd83dbSDimitry Andric     return true;
51405ffd83dbSDimitry Andric 
51415ffd83dbSDimitry Andric   if (!getStreamer().EmitCVFuncIdDirective(FunctionId))
51425ffd83dbSDimitry Andric     return Error(FunctionIdLoc, "function id already allocated");
51435ffd83dbSDimitry Andric 
51445ffd83dbSDimitry Andric   return false;
51455ffd83dbSDimitry Andric }
51465ffd83dbSDimitry Andric 
51475ffd83dbSDimitry Andric /// parseDirectiveCVInlineSiteId
51485ffd83dbSDimitry Andric /// ::= .cv_inline_site_id FunctionId
51495ffd83dbSDimitry Andric ///         "within" IAFunc
51505ffd83dbSDimitry Andric ///         "inlined_at" IAFile IALine [IACol]
51515ffd83dbSDimitry Andric ///
51525ffd83dbSDimitry Andric /// Introduces a function ID that can be used with .cv_loc. Includes "inlined
51535ffd83dbSDimitry Andric /// at" source location information for use in the line table of the caller,
51545ffd83dbSDimitry Andric /// whether the caller is a real function or another inlined call site.
51555ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVInlineSiteId() {
51565ffd83dbSDimitry Andric   SMLoc FunctionIdLoc = getTok().getLoc();
51575ffd83dbSDimitry Andric   int64_t FunctionId;
51585ffd83dbSDimitry Andric   int64_t IAFunc;
51595ffd83dbSDimitry Andric   int64_t IAFile;
51605ffd83dbSDimitry Andric   int64_t IALine;
51615ffd83dbSDimitry Andric   int64_t IACol = 0;
51625ffd83dbSDimitry Andric 
51635ffd83dbSDimitry Andric   // FunctionId
51645ffd83dbSDimitry Andric   if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))
51655ffd83dbSDimitry Andric     return true;
51665ffd83dbSDimitry Andric 
51675ffd83dbSDimitry Andric   // "within"
51685ffd83dbSDimitry Andric   if (check((getLexer().isNot(AsmToken::Identifier) ||
51695ffd83dbSDimitry Andric              getTok().getIdentifier() != "within"),
51705ffd83dbSDimitry Andric             "expected 'within' identifier in '.cv_inline_site_id' directive"))
51715ffd83dbSDimitry Andric     return true;
51725ffd83dbSDimitry Andric   Lex();
51735ffd83dbSDimitry Andric 
51745ffd83dbSDimitry Andric   // IAFunc
51755ffd83dbSDimitry Andric   if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))
51765ffd83dbSDimitry Andric     return true;
51775ffd83dbSDimitry Andric 
51785ffd83dbSDimitry Andric   // "inlined_at"
51795ffd83dbSDimitry Andric   if (check((getLexer().isNot(AsmToken::Identifier) ||
51805ffd83dbSDimitry Andric              getTok().getIdentifier() != "inlined_at"),
51815ffd83dbSDimitry Andric             "expected 'inlined_at' identifier in '.cv_inline_site_id' "
51825ffd83dbSDimitry Andric             "directive") )
51835ffd83dbSDimitry Andric     return true;
51845ffd83dbSDimitry Andric   Lex();
51855ffd83dbSDimitry Andric 
51865ffd83dbSDimitry Andric   // IAFile IALine
51875ffd83dbSDimitry Andric   if (parseCVFileId(IAFile, ".cv_inline_site_id") ||
51885ffd83dbSDimitry Andric       parseIntToken(IALine, "expected line number after 'inlined_at'"))
51895ffd83dbSDimitry Andric     return true;
51905ffd83dbSDimitry Andric 
51915ffd83dbSDimitry Andric   // [IACol]
51925ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
51935ffd83dbSDimitry Andric     IACol = getTok().getIntVal();
51945ffd83dbSDimitry Andric     Lex();
51955ffd83dbSDimitry Andric   }
51965ffd83dbSDimitry Andric 
51975ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement,
51985ffd83dbSDimitry Andric                  "unexpected token in '.cv_inline_site_id' directive"))
51995ffd83dbSDimitry Andric     return true;
52005ffd83dbSDimitry Andric 
52015ffd83dbSDimitry Andric   if (!getStreamer().EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
52025ffd83dbSDimitry Andric                                                  IALine, IACol, FunctionIdLoc))
52035ffd83dbSDimitry Andric     return Error(FunctionIdLoc, "function id already allocated");
52045ffd83dbSDimitry Andric 
52055ffd83dbSDimitry Andric   return false;
52065ffd83dbSDimitry Andric }
52075ffd83dbSDimitry Andric 
52085ffd83dbSDimitry Andric /// parseDirectiveCVLoc
52095ffd83dbSDimitry Andric /// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
52105ffd83dbSDimitry Andric ///                                [is_stmt VALUE]
52115ffd83dbSDimitry Andric /// The first number is a file number, must have been previously assigned with
52125ffd83dbSDimitry Andric /// a .file directive, the second number is the line number and optionally the
52135ffd83dbSDimitry Andric /// third number is a column position (zero if not specified).  The remaining
52145ffd83dbSDimitry Andric /// optional items are .loc sub-directives.
52155ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVLoc() {
52165ffd83dbSDimitry Andric   SMLoc DirectiveLoc = getTok().getLoc();
52175ffd83dbSDimitry Andric   int64_t FunctionId, FileNumber;
52185ffd83dbSDimitry Andric   if (parseCVFunctionId(FunctionId, ".cv_loc") ||
52195ffd83dbSDimitry Andric       parseCVFileId(FileNumber, ".cv_loc"))
52205ffd83dbSDimitry Andric     return true;
52215ffd83dbSDimitry Andric 
52225ffd83dbSDimitry Andric   int64_t LineNumber = 0;
52235ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
52245ffd83dbSDimitry Andric     LineNumber = getTok().getIntVal();
52255ffd83dbSDimitry Andric     if (LineNumber < 0)
52265ffd83dbSDimitry Andric       return TokError("line number less than zero in '.cv_loc' directive");
52275ffd83dbSDimitry Andric     Lex();
52285ffd83dbSDimitry Andric   }
52295ffd83dbSDimitry Andric 
52305ffd83dbSDimitry Andric   int64_t ColumnPos = 0;
52315ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
52325ffd83dbSDimitry Andric     ColumnPos = getTok().getIntVal();
52335ffd83dbSDimitry Andric     if (ColumnPos < 0)
52345ffd83dbSDimitry Andric       return TokError("column position less than zero in '.cv_loc' directive");
52355ffd83dbSDimitry Andric     Lex();
52365ffd83dbSDimitry Andric   }
52375ffd83dbSDimitry Andric 
52385ffd83dbSDimitry Andric   bool PrologueEnd = false;
52395ffd83dbSDimitry Andric   uint64_t IsStmt = 0;
52405ffd83dbSDimitry Andric 
52415ffd83dbSDimitry Andric   auto parseOp = [&]() -> bool {
52425ffd83dbSDimitry Andric     StringRef Name;
52435ffd83dbSDimitry Andric     SMLoc Loc = getTok().getLoc();
52445ffd83dbSDimitry Andric     if (parseIdentifier(Name))
52455ffd83dbSDimitry Andric       return TokError("unexpected token in '.cv_loc' directive");
52465ffd83dbSDimitry Andric     if (Name == "prologue_end")
52475ffd83dbSDimitry Andric       PrologueEnd = true;
52485ffd83dbSDimitry Andric     else if (Name == "is_stmt") {
52495ffd83dbSDimitry Andric       Loc = getTok().getLoc();
52505ffd83dbSDimitry Andric       const MCExpr *Value;
52515ffd83dbSDimitry Andric       if (parseExpression(Value))
52525ffd83dbSDimitry Andric         return true;
52535ffd83dbSDimitry Andric       // The expression must be the constant 0 or 1.
52545ffd83dbSDimitry Andric       IsStmt = ~0ULL;
52555ffd83dbSDimitry Andric       if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
52565ffd83dbSDimitry Andric         IsStmt = MCE->getValue();
52575ffd83dbSDimitry Andric 
52585ffd83dbSDimitry Andric       if (IsStmt > 1)
52595ffd83dbSDimitry Andric         return Error(Loc, "is_stmt value not 0 or 1");
52605ffd83dbSDimitry Andric     } else {
52615ffd83dbSDimitry Andric       return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
52625ffd83dbSDimitry Andric     }
52635ffd83dbSDimitry Andric     return false;
52645ffd83dbSDimitry Andric   };
52655ffd83dbSDimitry Andric 
52665ffd83dbSDimitry Andric   if (parseMany(parseOp, false /*hasComma*/))
52675ffd83dbSDimitry Andric     return true;
52685ffd83dbSDimitry Andric 
52695ffd83dbSDimitry Andric   getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,
52705ffd83dbSDimitry Andric                                    ColumnPos, PrologueEnd, IsStmt, StringRef(),
52715ffd83dbSDimitry Andric                                    DirectiveLoc);
52725ffd83dbSDimitry Andric   return false;
52735ffd83dbSDimitry Andric }
52745ffd83dbSDimitry Andric 
52755ffd83dbSDimitry Andric /// parseDirectiveCVLinetable
52765ffd83dbSDimitry Andric /// ::= .cv_linetable FunctionId, FnStart, FnEnd
52775ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVLinetable() {
52785ffd83dbSDimitry Andric   int64_t FunctionId;
52795ffd83dbSDimitry Andric   StringRef FnStartName, FnEndName;
52805ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
52815ffd83dbSDimitry Andric   if (parseCVFunctionId(FunctionId, ".cv_linetable") ||
52825ffd83dbSDimitry Andric       parseToken(AsmToken::Comma,
52835ffd83dbSDimitry Andric                  "unexpected token in '.cv_linetable' directive") ||
52845ffd83dbSDimitry Andric       parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
52855ffd83dbSDimitry Andric                                   "expected identifier in directive") ||
52865ffd83dbSDimitry Andric       parseToken(AsmToken::Comma,
52875ffd83dbSDimitry Andric                  "unexpected token in '.cv_linetable' directive") ||
52885ffd83dbSDimitry Andric       parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
52895ffd83dbSDimitry Andric                                   "expected identifier in directive"))
52905ffd83dbSDimitry Andric     return true;
52915ffd83dbSDimitry Andric 
52925ffd83dbSDimitry Andric   MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
52935ffd83dbSDimitry Andric   MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
52945ffd83dbSDimitry Andric 
52955ffd83dbSDimitry Andric   getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
52965ffd83dbSDimitry Andric   return false;
52975ffd83dbSDimitry Andric }
52985ffd83dbSDimitry Andric 
52995ffd83dbSDimitry Andric /// parseDirectiveCVInlineLinetable
53005ffd83dbSDimitry Andric /// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
53015ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVInlineLinetable() {
53025ffd83dbSDimitry Andric   int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
53035ffd83dbSDimitry Andric   StringRef FnStartName, FnEndName;
53045ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
53055ffd83dbSDimitry Andric   if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||
53065ffd83dbSDimitry Andric       parseTokenLoc(Loc) ||
53075ffd83dbSDimitry Andric       parseIntToken(
53085ffd83dbSDimitry Andric           SourceFileId,
53095ffd83dbSDimitry Andric           "expected SourceField in '.cv_inline_linetable' directive") ||
53105ffd83dbSDimitry Andric       check(SourceFileId <= 0, Loc,
53115ffd83dbSDimitry Andric             "File id less than zero in '.cv_inline_linetable' directive") ||
53125ffd83dbSDimitry Andric       parseTokenLoc(Loc) ||
53135ffd83dbSDimitry Andric       parseIntToken(
53145ffd83dbSDimitry Andric           SourceLineNum,
53155ffd83dbSDimitry Andric           "expected SourceLineNum in '.cv_inline_linetable' directive") ||
53165ffd83dbSDimitry Andric       check(SourceLineNum < 0, Loc,
53175ffd83dbSDimitry Andric             "Line number less than zero in '.cv_inline_linetable' directive") ||
53185ffd83dbSDimitry Andric       parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
53195ffd83dbSDimitry Andric                                   "expected identifier in directive") ||
53205ffd83dbSDimitry Andric       parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
53215ffd83dbSDimitry Andric                                   "expected identifier in directive"))
53225ffd83dbSDimitry Andric     return true;
53235ffd83dbSDimitry Andric 
53245ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
53255ffd83dbSDimitry Andric     return true;
53265ffd83dbSDimitry Andric 
53275ffd83dbSDimitry Andric   MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
53285ffd83dbSDimitry Andric   MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
53295ffd83dbSDimitry Andric   getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
53305ffd83dbSDimitry Andric                                                SourceLineNum, FnStartSym,
53315ffd83dbSDimitry Andric                                                FnEndSym);
53325ffd83dbSDimitry Andric   return false;
53335ffd83dbSDimitry Andric }
53345ffd83dbSDimitry Andric 
53355ffd83dbSDimitry Andric void MasmParser::initializeCVDefRangeTypeMap() {
53365ffd83dbSDimitry Andric   CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
53375ffd83dbSDimitry Andric   CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
53385ffd83dbSDimitry Andric   CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
53395ffd83dbSDimitry Andric   CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
53405ffd83dbSDimitry Andric }
53415ffd83dbSDimitry Andric 
53425ffd83dbSDimitry Andric /// parseDirectiveCVDefRange
53435ffd83dbSDimitry Andric /// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
53445ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVDefRange() {
53455ffd83dbSDimitry Andric   SMLoc Loc;
53465ffd83dbSDimitry Andric   std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
53475ffd83dbSDimitry Andric   while (getLexer().is(AsmToken::Identifier)) {
53485ffd83dbSDimitry Andric     Loc = getLexer().getLoc();
53495ffd83dbSDimitry Andric     StringRef GapStartName;
53505ffd83dbSDimitry Andric     if (parseIdentifier(GapStartName))
53515ffd83dbSDimitry Andric       return Error(Loc, "expected identifier in directive");
53525ffd83dbSDimitry Andric     MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
53535ffd83dbSDimitry Andric 
53545ffd83dbSDimitry Andric     Loc = getLexer().getLoc();
53555ffd83dbSDimitry Andric     StringRef GapEndName;
53565ffd83dbSDimitry Andric     if (parseIdentifier(GapEndName))
53575ffd83dbSDimitry Andric       return Error(Loc, "expected identifier in directive");
53585ffd83dbSDimitry Andric     MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
53595ffd83dbSDimitry Andric 
53605ffd83dbSDimitry Andric     Ranges.push_back({GapStartSym, GapEndSym});
53615ffd83dbSDimitry Andric   }
53625ffd83dbSDimitry Andric 
53635ffd83dbSDimitry Andric   StringRef CVDefRangeTypeStr;
53645ffd83dbSDimitry Andric   if (parseToken(
53655ffd83dbSDimitry Andric           AsmToken::Comma,
53665ffd83dbSDimitry Andric           "expected comma before def_range type in .cv_def_range directive") ||
53675ffd83dbSDimitry Andric       parseIdentifier(CVDefRangeTypeStr))
53685ffd83dbSDimitry Andric     return Error(Loc, "expected def_range type in directive");
53695ffd83dbSDimitry Andric 
53705ffd83dbSDimitry Andric   StringMap<CVDefRangeType>::const_iterator CVTypeIt =
53715ffd83dbSDimitry Andric       CVDefRangeTypeMap.find(CVDefRangeTypeStr);
53725ffd83dbSDimitry Andric   CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
53735ffd83dbSDimitry Andric                                 ? CVDR_DEFRANGE
53745ffd83dbSDimitry Andric                                 : CVTypeIt->getValue();
53755ffd83dbSDimitry Andric   switch (CVDRType) {
53765ffd83dbSDimitry Andric   case CVDR_DEFRANGE_REGISTER: {
53775ffd83dbSDimitry Andric     int64_t DRRegister;
53785ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma, "expected comma before register number in "
53795ffd83dbSDimitry Andric                                     ".cv_def_range directive") ||
53805ffd83dbSDimitry Andric         parseAbsoluteExpression(DRRegister))
53815ffd83dbSDimitry Andric       return Error(Loc, "expected register number");
53825ffd83dbSDimitry Andric 
53835ffd83dbSDimitry Andric     codeview::DefRangeRegisterHeader DRHdr;
53845ffd83dbSDimitry Andric     DRHdr.Register = DRRegister;
53855ffd83dbSDimitry Andric     DRHdr.MayHaveNoName = 0;
53865ffd83dbSDimitry Andric     getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
53875ffd83dbSDimitry Andric     break;
53885ffd83dbSDimitry Andric   }
53895ffd83dbSDimitry Andric   case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
53905ffd83dbSDimitry Andric     int64_t DROffset;
53915ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma,
53925ffd83dbSDimitry Andric                    "expected comma before offset in .cv_def_range directive") ||
53935ffd83dbSDimitry Andric         parseAbsoluteExpression(DROffset))
53945ffd83dbSDimitry Andric       return Error(Loc, "expected offset value");
53955ffd83dbSDimitry Andric 
53965ffd83dbSDimitry Andric     codeview::DefRangeFramePointerRelHeader DRHdr;
53975ffd83dbSDimitry Andric     DRHdr.Offset = DROffset;
53985ffd83dbSDimitry Andric     getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
53995ffd83dbSDimitry Andric     break;
54005ffd83dbSDimitry Andric   }
54015ffd83dbSDimitry Andric   case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
54025ffd83dbSDimitry Andric     int64_t DRRegister;
54035ffd83dbSDimitry Andric     int64_t DROffsetInParent;
54045ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma, "expected comma before register number in "
54055ffd83dbSDimitry Andric                                     ".cv_def_range directive") ||
54065ffd83dbSDimitry Andric         parseAbsoluteExpression(DRRegister))
54075ffd83dbSDimitry Andric       return Error(Loc, "expected register number");
54085ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma,
54095ffd83dbSDimitry Andric                    "expected comma before offset in .cv_def_range directive") ||
54105ffd83dbSDimitry Andric         parseAbsoluteExpression(DROffsetInParent))
54115ffd83dbSDimitry Andric       return Error(Loc, "expected offset value");
54125ffd83dbSDimitry Andric 
54135ffd83dbSDimitry Andric     codeview::DefRangeSubfieldRegisterHeader DRHdr;
54145ffd83dbSDimitry Andric     DRHdr.Register = DRRegister;
54155ffd83dbSDimitry Andric     DRHdr.MayHaveNoName = 0;
54165ffd83dbSDimitry Andric     DRHdr.OffsetInParent = DROffsetInParent;
54175ffd83dbSDimitry Andric     getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
54185ffd83dbSDimitry Andric     break;
54195ffd83dbSDimitry Andric   }
54205ffd83dbSDimitry Andric   case CVDR_DEFRANGE_REGISTER_REL: {
54215ffd83dbSDimitry Andric     int64_t DRRegister;
54225ffd83dbSDimitry Andric     int64_t DRFlags;
54235ffd83dbSDimitry Andric     int64_t DRBasePointerOffset;
54245ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma, "expected comma before register number in "
54255ffd83dbSDimitry Andric                                     ".cv_def_range directive") ||
54265ffd83dbSDimitry Andric         parseAbsoluteExpression(DRRegister))
54275ffd83dbSDimitry Andric       return Error(Loc, "expected register value");
54285ffd83dbSDimitry Andric     if (parseToken(
54295ffd83dbSDimitry Andric             AsmToken::Comma,
54305ffd83dbSDimitry Andric             "expected comma before flag value in .cv_def_range directive") ||
54315ffd83dbSDimitry Andric         parseAbsoluteExpression(DRFlags))
54325ffd83dbSDimitry Andric       return Error(Loc, "expected flag value");
54335ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
54345ffd83dbSDimitry Andric                                     "in .cv_def_range directive") ||
54355ffd83dbSDimitry Andric         parseAbsoluteExpression(DRBasePointerOffset))
54365ffd83dbSDimitry Andric       return Error(Loc, "expected base pointer offset value");
54375ffd83dbSDimitry Andric 
54385ffd83dbSDimitry Andric     codeview::DefRangeRegisterRelHeader DRHdr;
54395ffd83dbSDimitry Andric     DRHdr.Register = DRRegister;
54405ffd83dbSDimitry Andric     DRHdr.Flags = DRFlags;
54415ffd83dbSDimitry Andric     DRHdr.BasePointerOffset = DRBasePointerOffset;
54425ffd83dbSDimitry Andric     getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
54435ffd83dbSDimitry Andric     break;
54445ffd83dbSDimitry Andric   }
54455ffd83dbSDimitry Andric   default:
54465ffd83dbSDimitry Andric     return Error(Loc, "unexpected def_range type in .cv_def_range directive");
54475ffd83dbSDimitry Andric   }
54485ffd83dbSDimitry Andric   return true;
54495ffd83dbSDimitry Andric }
54505ffd83dbSDimitry Andric 
54515ffd83dbSDimitry Andric /// parseDirectiveCVString
54525ffd83dbSDimitry Andric /// ::= .cv_stringtable "string"
54535ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVString() {
54545ffd83dbSDimitry Andric   std::string Data;
54555ffd83dbSDimitry Andric   if (checkForValidSection() || parseEscapedString(Data))
54565ffd83dbSDimitry Andric     return addErrorSuffix(" in '.cv_string' directive");
54575ffd83dbSDimitry Andric 
54585ffd83dbSDimitry Andric   // Put the string in the table and emit the offset.
54595ffd83dbSDimitry Andric   std::pair<StringRef, unsigned> Insertion =
54605ffd83dbSDimitry Andric       getCVContext().addToStringTable(Data);
54615ffd83dbSDimitry Andric   getStreamer().emitIntValue(Insertion.second, 4);
54625ffd83dbSDimitry Andric   return false;
54635ffd83dbSDimitry Andric }
54645ffd83dbSDimitry Andric 
54655ffd83dbSDimitry Andric /// parseDirectiveCVStringTable
54665ffd83dbSDimitry Andric /// ::= .cv_stringtable
54675ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVStringTable() {
54685ffd83dbSDimitry Andric   getStreamer().emitCVStringTableDirective();
54695ffd83dbSDimitry Andric   return false;
54705ffd83dbSDimitry Andric }
54715ffd83dbSDimitry Andric 
54725ffd83dbSDimitry Andric /// parseDirectiveCVFileChecksums
54735ffd83dbSDimitry Andric /// ::= .cv_filechecksums
54745ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFileChecksums() {
54755ffd83dbSDimitry Andric   getStreamer().emitCVFileChecksumsDirective();
54765ffd83dbSDimitry Andric   return false;
54775ffd83dbSDimitry Andric }
54785ffd83dbSDimitry Andric 
54795ffd83dbSDimitry Andric /// parseDirectiveCVFileChecksumOffset
54805ffd83dbSDimitry Andric /// ::= .cv_filechecksumoffset fileno
54815ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFileChecksumOffset() {
54825ffd83dbSDimitry Andric   int64_t FileNo;
54835ffd83dbSDimitry Andric   if (parseIntToken(FileNo, "expected identifier in directive"))
54845ffd83dbSDimitry Andric     return true;
54855ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
54865ffd83dbSDimitry Andric     return true;
54875ffd83dbSDimitry Andric   getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
54885ffd83dbSDimitry Andric   return false;
54895ffd83dbSDimitry Andric }
54905ffd83dbSDimitry Andric 
54915ffd83dbSDimitry Andric /// parseDirectiveCVFPOData
54925ffd83dbSDimitry Andric /// ::= .cv_fpo_data procsym
54935ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFPOData() {
54945ffd83dbSDimitry Andric   SMLoc DirLoc = getLexer().getLoc();
54955ffd83dbSDimitry Andric   StringRef ProcName;
54965ffd83dbSDimitry Andric   if (parseIdentifier(ProcName))
54975ffd83dbSDimitry Andric     return TokError("expected symbol name");
54985ffd83dbSDimitry Andric   if (parseEOL("unexpected tokens"))
54995ffd83dbSDimitry Andric     return addErrorSuffix(" in '.cv_fpo_data' directive");
55005ffd83dbSDimitry Andric   MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
55015ffd83dbSDimitry Andric   getStreamer().EmitCVFPOData(ProcSym, DirLoc);
55025ffd83dbSDimitry Andric   return false;
55035ffd83dbSDimitry Andric }
55045ffd83dbSDimitry Andric 
55055ffd83dbSDimitry Andric /// parseDirectiveCFISections
55065ffd83dbSDimitry Andric /// ::= .cfi_sections section [, section]
55075ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFISections() {
55085ffd83dbSDimitry Andric   StringRef Name;
55095ffd83dbSDimitry Andric   bool EH = false;
55105ffd83dbSDimitry Andric   bool Debug = false;
55115ffd83dbSDimitry Andric 
55125ffd83dbSDimitry Andric   if (parseIdentifier(Name))
55135ffd83dbSDimitry Andric     return TokError("Expected an identifier");
55145ffd83dbSDimitry Andric 
55155ffd83dbSDimitry Andric   if (Name == ".eh_frame")
55165ffd83dbSDimitry Andric     EH = true;
55175ffd83dbSDimitry Andric   else if (Name == ".debug_frame")
55185ffd83dbSDimitry Andric     Debug = true;
55195ffd83dbSDimitry Andric 
55205ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Comma)) {
55215ffd83dbSDimitry Andric     Lex();
55225ffd83dbSDimitry Andric 
55235ffd83dbSDimitry Andric     if (parseIdentifier(Name))
55245ffd83dbSDimitry Andric       return TokError("Expected an identifier");
55255ffd83dbSDimitry Andric 
55265ffd83dbSDimitry Andric     if (Name == ".eh_frame")
55275ffd83dbSDimitry Andric       EH = true;
55285ffd83dbSDimitry Andric     else if (Name == ".debug_frame")
55295ffd83dbSDimitry Andric       Debug = true;
55305ffd83dbSDimitry Andric   }
55315ffd83dbSDimitry Andric 
55325ffd83dbSDimitry Andric   getStreamer().emitCFISections(EH, Debug);
55335ffd83dbSDimitry Andric   return false;
55345ffd83dbSDimitry Andric }
55355ffd83dbSDimitry Andric 
55365ffd83dbSDimitry Andric /// parseDirectiveCFIStartProc
55375ffd83dbSDimitry Andric /// ::= .cfi_startproc [simple]
55385ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIStartProc() {
55395ffd83dbSDimitry Andric   StringRef Simple;
55405ffd83dbSDimitry Andric   if (!parseOptionalToken(AsmToken::EndOfStatement)) {
55415ffd83dbSDimitry Andric     if (check(parseIdentifier(Simple) || Simple != "simple",
55425ffd83dbSDimitry Andric               "unexpected token") ||
55435ffd83dbSDimitry Andric         parseToken(AsmToken::EndOfStatement))
55445ffd83dbSDimitry Andric       return addErrorSuffix(" in '.cfi_startproc' directive");
55455ffd83dbSDimitry Andric   }
55465ffd83dbSDimitry Andric 
55475ffd83dbSDimitry Andric   // TODO(kristina): Deal with a corner case of incorrect diagnostic context
55485ffd83dbSDimitry Andric   // being produced if this directive is emitted as part of preprocessor macro
55495ffd83dbSDimitry Andric   // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
55505ffd83dbSDimitry Andric   // Tools like llvm-mc on the other hand are not affected by it, and report
55515ffd83dbSDimitry Andric   // correct context information.
55525ffd83dbSDimitry Andric   getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
55535ffd83dbSDimitry Andric   return false;
55545ffd83dbSDimitry Andric }
55555ffd83dbSDimitry Andric 
55565ffd83dbSDimitry Andric /// parseDirectiveCFIEndProc
55575ffd83dbSDimitry Andric /// ::= .cfi_endproc
55585ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIEndProc() {
55595ffd83dbSDimitry Andric   getStreamer().emitCFIEndProc();
55605ffd83dbSDimitry Andric   return false;
55615ffd83dbSDimitry Andric }
55625ffd83dbSDimitry Andric 
55635ffd83dbSDimitry Andric /// parse register name or number.
55645ffd83dbSDimitry Andric bool MasmParser::parseRegisterOrRegisterNumber(int64_t &Register,
55655ffd83dbSDimitry Andric                                                SMLoc DirectiveLoc) {
55665ffd83dbSDimitry Andric   unsigned RegNo;
55675ffd83dbSDimitry Andric 
55685ffd83dbSDimitry Andric   if (getLexer().isNot(AsmToken::Integer)) {
55695ffd83dbSDimitry Andric     if (getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc))
55705ffd83dbSDimitry Andric       return true;
55715ffd83dbSDimitry Andric     Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
55725ffd83dbSDimitry Andric   } else
55735ffd83dbSDimitry Andric     return parseAbsoluteExpression(Register);
55745ffd83dbSDimitry Andric 
55755ffd83dbSDimitry Andric   return false;
55765ffd83dbSDimitry Andric }
55775ffd83dbSDimitry Andric 
55785ffd83dbSDimitry Andric /// parseDirectiveCFIDefCfa
55795ffd83dbSDimitry Andric /// ::= .cfi_def_cfa register,  offset
55805ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
55815ffd83dbSDimitry Andric   int64_t Register = 0, Offset = 0;
55825ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
55835ffd83dbSDimitry Andric       parseToken(AsmToken::Comma, "unexpected token in directive") ||
55845ffd83dbSDimitry Andric       parseAbsoluteExpression(Offset))
55855ffd83dbSDimitry Andric     return true;
55865ffd83dbSDimitry Andric 
55875ffd83dbSDimitry Andric   getStreamer().emitCFIDefCfa(Register, Offset);
55885ffd83dbSDimitry Andric   return false;
55895ffd83dbSDimitry Andric }
55905ffd83dbSDimitry Andric 
55915ffd83dbSDimitry Andric /// parseDirectiveCFIDefCfaOffset
55925ffd83dbSDimitry Andric /// ::= .cfi_def_cfa_offset offset
55935ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIDefCfaOffset() {
55945ffd83dbSDimitry Andric   int64_t Offset = 0;
55955ffd83dbSDimitry Andric   if (parseAbsoluteExpression(Offset))
55965ffd83dbSDimitry Andric     return true;
55975ffd83dbSDimitry Andric 
55985ffd83dbSDimitry Andric   getStreamer().emitCFIDefCfaOffset(Offset);
55995ffd83dbSDimitry Andric   return false;
56005ffd83dbSDimitry Andric }
56015ffd83dbSDimitry Andric 
56025ffd83dbSDimitry Andric /// parseDirectiveCFIRegister
56035ffd83dbSDimitry Andric /// ::= .cfi_register register, register
56045ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
56055ffd83dbSDimitry Andric   int64_t Register1 = 0, Register2 = 0;
56065ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) ||
56075ffd83dbSDimitry Andric       parseToken(AsmToken::Comma, "unexpected token in directive") ||
56085ffd83dbSDimitry Andric       parseRegisterOrRegisterNumber(Register2, DirectiveLoc))
56095ffd83dbSDimitry Andric     return true;
56105ffd83dbSDimitry Andric 
56115ffd83dbSDimitry Andric   getStreamer().emitCFIRegister(Register1, Register2);
56125ffd83dbSDimitry Andric   return false;
56135ffd83dbSDimitry Andric }
56145ffd83dbSDimitry Andric 
56155ffd83dbSDimitry Andric /// parseDirectiveCFIWindowSave
56165ffd83dbSDimitry Andric /// ::= .cfi_window_save
56175ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIWindowSave() {
56185ffd83dbSDimitry Andric   getStreamer().emitCFIWindowSave();
56195ffd83dbSDimitry Andric   return false;
56205ffd83dbSDimitry Andric }
56215ffd83dbSDimitry Andric 
56225ffd83dbSDimitry Andric /// parseDirectiveCFIAdjustCfaOffset
56235ffd83dbSDimitry Andric /// ::= .cfi_adjust_cfa_offset adjustment
56245ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIAdjustCfaOffset() {
56255ffd83dbSDimitry Andric   int64_t Adjustment = 0;
56265ffd83dbSDimitry Andric   if (parseAbsoluteExpression(Adjustment))
56275ffd83dbSDimitry Andric     return true;
56285ffd83dbSDimitry Andric 
56295ffd83dbSDimitry Andric   getStreamer().emitCFIAdjustCfaOffset(Adjustment);
56305ffd83dbSDimitry Andric   return false;
56315ffd83dbSDimitry Andric }
56325ffd83dbSDimitry Andric 
56335ffd83dbSDimitry Andric /// parseDirectiveCFIDefCfaRegister
56345ffd83dbSDimitry Andric /// ::= .cfi_def_cfa_register register
56355ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
56365ffd83dbSDimitry Andric   int64_t Register = 0;
56375ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
56385ffd83dbSDimitry Andric     return true;
56395ffd83dbSDimitry Andric 
56405ffd83dbSDimitry Andric   getStreamer().emitCFIDefCfaRegister(Register);
56415ffd83dbSDimitry Andric   return false;
56425ffd83dbSDimitry Andric }
56435ffd83dbSDimitry Andric 
56445ffd83dbSDimitry Andric /// parseDirectiveCFIOffset
56455ffd83dbSDimitry Andric /// ::= .cfi_offset register, offset
56465ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
56475ffd83dbSDimitry Andric   int64_t Register = 0;
56485ffd83dbSDimitry Andric   int64_t Offset = 0;
56495ffd83dbSDimitry Andric 
56505ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
56515ffd83dbSDimitry Andric       parseToken(AsmToken::Comma, "unexpected token in directive") ||
56525ffd83dbSDimitry Andric       parseAbsoluteExpression(Offset))
56535ffd83dbSDimitry Andric     return true;
56545ffd83dbSDimitry Andric 
56555ffd83dbSDimitry Andric   getStreamer().emitCFIOffset(Register, Offset);
56565ffd83dbSDimitry Andric   return false;
56575ffd83dbSDimitry Andric }
56585ffd83dbSDimitry Andric 
56595ffd83dbSDimitry Andric /// parseDirectiveCFIRelOffset
56605ffd83dbSDimitry Andric /// ::= .cfi_rel_offset register, offset
56615ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
56625ffd83dbSDimitry Andric   int64_t Register = 0, Offset = 0;
56635ffd83dbSDimitry Andric 
56645ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
56655ffd83dbSDimitry Andric       parseToken(AsmToken::Comma, "unexpected token in directive") ||
56665ffd83dbSDimitry Andric       parseAbsoluteExpression(Offset))
56675ffd83dbSDimitry Andric     return true;
56685ffd83dbSDimitry Andric 
56695ffd83dbSDimitry Andric   getStreamer().emitCFIRelOffset(Register, Offset);
56705ffd83dbSDimitry Andric   return false;
56715ffd83dbSDimitry Andric }
56725ffd83dbSDimitry Andric 
56735ffd83dbSDimitry Andric static bool isValidEncoding(int64_t Encoding) {
56745ffd83dbSDimitry Andric   if (Encoding & ~0xff)
56755ffd83dbSDimitry Andric     return false;
56765ffd83dbSDimitry Andric 
56775ffd83dbSDimitry Andric   if (Encoding == dwarf::DW_EH_PE_omit)
56785ffd83dbSDimitry Andric     return true;
56795ffd83dbSDimitry Andric 
56805ffd83dbSDimitry Andric   const unsigned Format = Encoding & 0xf;
56815ffd83dbSDimitry Andric   if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
56825ffd83dbSDimitry Andric       Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
56835ffd83dbSDimitry Andric       Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
56845ffd83dbSDimitry Andric       Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
56855ffd83dbSDimitry Andric     return false;
56865ffd83dbSDimitry Andric 
56875ffd83dbSDimitry Andric   const unsigned Application = Encoding & 0x70;
56885ffd83dbSDimitry Andric   if (Application != dwarf::DW_EH_PE_absptr &&
56895ffd83dbSDimitry Andric       Application != dwarf::DW_EH_PE_pcrel)
56905ffd83dbSDimitry Andric     return false;
56915ffd83dbSDimitry Andric 
56925ffd83dbSDimitry Andric   return true;
56935ffd83dbSDimitry Andric }
56945ffd83dbSDimitry Andric 
56955ffd83dbSDimitry Andric /// parseDirectiveCFIPersonalityOrLsda
56965ffd83dbSDimitry Andric /// IsPersonality true for cfi_personality, false for cfi_lsda
56975ffd83dbSDimitry Andric /// ::= .cfi_personality encoding, [symbol_name]
56985ffd83dbSDimitry Andric /// ::= .cfi_lsda encoding, [symbol_name]
56995ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
57005ffd83dbSDimitry Andric   int64_t Encoding = 0;
57015ffd83dbSDimitry Andric   if (parseAbsoluteExpression(Encoding))
57025ffd83dbSDimitry Andric     return true;
57035ffd83dbSDimitry Andric   if (Encoding == dwarf::DW_EH_PE_omit)
57045ffd83dbSDimitry Andric     return false;
57055ffd83dbSDimitry Andric 
57065ffd83dbSDimitry Andric   StringRef Name;
57075ffd83dbSDimitry Andric   if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
57085ffd83dbSDimitry Andric       parseToken(AsmToken::Comma, "unexpected token in directive") ||
57095ffd83dbSDimitry Andric       check(parseIdentifier(Name), "expected identifier in directive"))
57105ffd83dbSDimitry Andric     return true;
57115ffd83dbSDimitry Andric 
57125ffd83dbSDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
57135ffd83dbSDimitry Andric 
57145ffd83dbSDimitry Andric   if (IsPersonality)
57155ffd83dbSDimitry Andric     getStreamer().emitCFIPersonality(Sym, Encoding);
57165ffd83dbSDimitry Andric   else
57175ffd83dbSDimitry Andric     getStreamer().emitCFILsda(Sym, Encoding);
57185ffd83dbSDimitry Andric   return false;
57195ffd83dbSDimitry Andric }
57205ffd83dbSDimitry Andric 
57215ffd83dbSDimitry Andric /// parseDirectiveCFIRememberState
57225ffd83dbSDimitry Andric /// ::= .cfi_remember_state
57235ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIRememberState() {
57245ffd83dbSDimitry Andric   getStreamer().emitCFIRememberState();
57255ffd83dbSDimitry Andric   return false;
57265ffd83dbSDimitry Andric }
57275ffd83dbSDimitry Andric 
57285ffd83dbSDimitry Andric /// parseDirectiveCFIRestoreState
57295ffd83dbSDimitry Andric /// ::= .cfi_remember_state
57305ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIRestoreState() {
57315ffd83dbSDimitry Andric   getStreamer().emitCFIRestoreState();
57325ffd83dbSDimitry Andric   return false;
57335ffd83dbSDimitry Andric }
57345ffd83dbSDimitry Andric 
57355ffd83dbSDimitry Andric /// parseDirectiveCFISameValue
57365ffd83dbSDimitry Andric /// ::= .cfi_same_value register
57375ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
57385ffd83dbSDimitry Andric   int64_t Register = 0;
57395ffd83dbSDimitry Andric 
57405ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
57415ffd83dbSDimitry Andric     return true;
57425ffd83dbSDimitry Andric 
57435ffd83dbSDimitry Andric   getStreamer().emitCFISameValue(Register);
57445ffd83dbSDimitry Andric   return false;
57455ffd83dbSDimitry Andric }
57465ffd83dbSDimitry Andric 
57475ffd83dbSDimitry Andric /// parseDirectiveCFIRestore
57485ffd83dbSDimitry Andric /// ::= .cfi_restore register
57495ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
57505ffd83dbSDimitry Andric   int64_t Register = 0;
57515ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
57525ffd83dbSDimitry Andric     return true;
57535ffd83dbSDimitry Andric 
57545ffd83dbSDimitry Andric   getStreamer().emitCFIRestore(Register);
57555ffd83dbSDimitry Andric   return false;
57565ffd83dbSDimitry Andric }
57575ffd83dbSDimitry Andric 
57585ffd83dbSDimitry Andric /// parseDirectiveCFIEscape
57595ffd83dbSDimitry Andric /// ::= .cfi_escape expression[,...]
57605ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIEscape() {
57615ffd83dbSDimitry Andric   std::string Values;
57625ffd83dbSDimitry Andric   int64_t CurrValue;
57635ffd83dbSDimitry Andric   if (parseAbsoluteExpression(CurrValue))
57645ffd83dbSDimitry Andric     return true;
57655ffd83dbSDimitry Andric 
57665ffd83dbSDimitry Andric   Values.push_back((uint8_t)CurrValue);
57675ffd83dbSDimitry Andric 
57685ffd83dbSDimitry Andric   while (getLexer().is(AsmToken::Comma)) {
57695ffd83dbSDimitry Andric     Lex();
57705ffd83dbSDimitry Andric 
57715ffd83dbSDimitry Andric     if (parseAbsoluteExpression(CurrValue))
57725ffd83dbSDimitry Andric       return true;
57735ffd83dbSDimitry Andric 
57745ffd83dbSDimitry Andric     Values.push_back((uint8_t)CurrValue);
57755ffd83dbSDimitry Andric   }
57765ffd83dbSDimitry Andric 
57775ffd83dbSDimitry Andric   getStreamer().emitCFIEscape(Values);
57785ffd83dbSDimitry Andric   return false;
57795ffd83dbSDimitry Andric }
57805ffd83dbSDimitry Andric 
57815ffd83dbSDimitry Andric /// parseDirectiveCFIReturnColumn
57825ffd83dbSDimitry Andric /// ::= .cfi_return_column register
57835ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
57845ffd83dbSDimitry Andric   int64_t Register = 0;
57855ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
57865ffd83dbSDimitry Andric     return true;
57875ffd83dbSDimitry Andric   getStreamer().emitCFIReturnColumn(Register);
57885ffd83dbSDimitry Andric   return false;
57895ffd83dbSDimitry Andric }
57905ffd83dbSDimitry Andric 
57915ffd83dbSDimitry Andric /// parseDirectiveCFISignalFrame
57925ffd83dbSDimitry Andric /// ::= .cfi_signal_frame
57935ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFISignalFrame() {
57945ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement,
57955ffd83dbSDimitry Andric                  "unexpected token in '.cfi_signal_frame'"))
57965ffd83dbSDimitry Andric     return true;
57975ffd83dbSDimitry Andric 
57985ffd83dbSDimitry Andric   getStreamer().emitCFISignalFrame();
57995ffd83dbSDimitry Andric   return false;
58005ffd83dbSDimitry Andric }
58015ffd83dbSDimitry Andric 
58025ffd83dbSDimitry Andric /// parseDirectiveCFIUndefined
58035ffd83dbSDimitry Andric /// ::= .cfi_undefined register
58045ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
58055ffd83dbSDimitry Andric   int64_t Register = 0;
58065ffd83dbSDimitry Andric 
58075ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
58085ffd83dbSDimitry Andric     return true;
58095ffd83dbSDimitry Andric 
58105ffd83dbSDimitry Andric   getStreamer().emitCFIUndefined(Register);
58115ffd83dbSDimitry Andric   return false;
58125ffd83dbSDimitry Andric }
58135ffd83dbSDimitry Andric 
58145ffd83dbSDimitry Andric /// parseDirectiveMacro
5815e8d8bef9SDimitry Andric /// ::= name macro [parameters]
5816e8d8bef9SDimitry Andric ///     ["LOCAL" identifiers]
5817e8d8bef9SDimitry Andric ///   parameters ::= parameter [, parameter]*
5818e8d8bef9SDimitry Andric ///   parameter ::= name ":" qualifier
5819e8d8bef9SDimitry Andric ///   qualifier ::= "req" | "vararg" | "=" macro_argument
5820e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
58215ffd83dbSDimitry Andric   MCAsmMacroParameters Parameters;
58225ffd83dbSDimitry Andric   while (getLexer().isNot(AsmToken::EndOfStatement)) {
58235ffd83dbSDimitry Andric     if (!Parameters.empty() && Parameters.back().Vararg)
58245ffd83dbSDimitry Andric       return Error(Lexer.getLoc(),
58255ffd83dbSDimitry Andric                    "Vararg parameter '" + Parameters.back().Name +
5826e8d8bef9SDimitry Andric                        "' should be last in the list of parameters");
58275ffd83dbSDimitry Andric 
58285ffd83dbSDimitry Andric     MCAsmMacroParameter Parameter;
58295ffd83dbSDimitry Andric     if (parseIdentifier(Parameter.Name))
5830e8d8bef9SDimitry Andric       return TokError("expected identifier in 'macro' directive");
58315ffd83dbSDimitry Andric 
58325ffd83dbSDimitry Andric     // Emit an error if two (or more) named parameters share the same name.
58335ffd83dbSDimitry Andric     for (const MCAsmMacroParameter& CurrParam : Parameters)
5834fe6060f1SDimitry Andric       if (CurrParam.Name.equals_insensitive(Parameter.Name))
58355ffd83dbSDimitry Andric         return TokError("macro '" + Name + "' has multiple parameters"
58365ffd83dbSDimitry Andric                         " named '" + Parameter.Name + "'");
58375ffd83dbSDimitry Andric 
58385ffd83dbSDimitry Andric     if (Lexer.is(AsmToken::Colon)) {
58395ffd83dbSDimitry Andric       Lex();  // consume ':'
58405ffd83dbSDimitry Andric 
5841e8d8bef9SDimitry Andric       if (parseOptionalToken(AsmToken::Equal)) {
5842e8d8bef9SDimitry Andric         // Default value
5843e8d8bef9SDimitry Andric         SMLoc ParamLoc;
5844e8d8bef9SDimitry Andric 
5845e8d8bef9SDimitry Andric         ParamLoc = Lexer.getLoc();
5846e8d8bef9SDimitry Andric         if (parseMacroArgument(nullptr, Parameter.Value))
5847e8d8bef9SDimitry Andric           return true;
5848e8d8bef9SDimitry Andric       } else {
58495ffd83dbSDimitry Andric         SMLoc QualLoc;
58505ffd83dbSDimitry Andric         StringRef Qualifier;
58515ffd83dbSDimitry Andric 
58525ffd83dbSDimitry Andric         QualLoc = Lexer.getLoc();
58535ffd83dbSDimitry Andric         if (parseIdentifier(Qualifier))
58545ffd83dbSDimitry Andric           return Error(QualLoc, "missing parameter qualifier for "
5855e8d8bef9SDimitry Andric                                 "'" +
5856e8d8bef9SDimitry Andric                                     Parameter.Name + "' in macro '" + Name +
5857e8d8bef9SDimitry Andric                                     "'");
58585ffd83dbSDimitry Andric 
5859fe6060f1SDimitry Andric         if (Qualifier.equals_insensitive("req"))
58605ffd83dbSDimitry Andric           Parameter.Required = true;
5861fe6060f1SDimitry Andric         else if (Qualifier.equals_insensitive("vararg"))
58625ffd83dbSDimitry Andric           Parameter.Vararg = true;
58635ffd83dbSDimitry Andric         else
5864e8d8bef9SDimitry Andric           return Error(QualLoc,
5865e8d8bef9SDimitry Andric                        Qualifier + " is not a valid parameter qualifier for '" +
5866e8d8bef9SDimitry Andric                            Parameter.Name + "' in macro '" + Name + "'");
58675ffd83dbSDimitry Andric       }
58685ffd83dbSDimitry Andric     }
58695ffd83dbSDimitry Andric 
58705ffd83dbSDimitry Andric     Parameters.push_back(std::move(Parameter));
58715ffd83dbSDimitry Andric 
58725ffd83dbSDimitry Andric     if (getLexer().is(AsmToken::Comma))
58735ffd83dbSDimitry Andric       Lex();
58745ffd83dbSDimitry Andric   }
58755ffd83dbSDimitry Andric 
58765ffd83dbSDimitry Andric   // Eat just the end of statement.
58775ffd83dbSDimitry Andric   Lexer.Lex();
58785ffd83dbSDimitry Andric 
5879e8d8bef9SDimitry Andric   std::vector<std::string> Locals;
5880e8d8bef9SDimitry Andric   if (getTok().is(AsmToken::Identifier) &&
5881fe6060f1SDimitry Andric       getTok().getIdentifier().equals_insensitive("local")) {
5882e8d8bef9SDimitry Andric     Lex(); // Eat the LOCAL directive.
5883e8d8bef9SDimitry Andric 
5884e8d8bef9SDimitry Andric     StringRef ID;
5885e8d8bef9SDimitry Andric     while (true) {
5886e8d8bef9SDimitry Andric       if (parseIdentifier(ID))
5887e8d8bef9SDimitry Andric         return true;
5888e8d8bef9SDimitry Andric       Locals.push_back(ID.lower());
5889e8d8bef9SDimitry Andric 
5890e8d8bef9SDimitry Andric       // If we see a comma, continue (and allow line continuation).
5891e8d8bef9SDimitry Andric       if (!parseOptionalToken(AsmToken::Comma))
5892e8d8bef9SDimitry Andric         break;
5893e8d8bef9SDimitry Andric       parseOptionalToken(AsmToken::EndOfStatement);
5894e8d8bef9SDimitry Andric     }
5895e8d8bef9SDimitry Andric   }
5896e8d8bef9SDimitry Andric 
58975ffd83dbSDimitry Andric   // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors.
58985ffd83dbSDimitry Andric   AsmToken EndToken, StartToken = getTok();
58995ffd83dbSDimitry Andric   unsigned MacroDepth = 0;
5900e8d8bef9SDimitry Andric   bool IsMacroFunction = false;
59015ffd83dbSDimitry Andric   // Lex the macro definition.
59025ffd83dbSDimitry Andric   while (true) {
59035ffd83dbSDimitry Andric     // Ignore Lexing errors in macros.
59045ffd83dbSDimitry Andric     while (Lexer.is(AsmToken::Error)) {
59055ffd83dbSDimitry Andric       Lexer.Lex();
59065ffd83dbSDimitry Andric     }
59075ffd83dbSDimitry Andric 
59085ffd83dbSDimitry Andric     // Check whether we have reached the end of the file.
59095ffd83dbSDimitry Andric     if (getLexer().is(AsmToken::Eof))
5910e8d8bef9SDimitry Andric       return Error(NameLoc, "no matching 'endm' in definition");
59115ffd83dbSDimitry Andric 
5912e8d8bef9SDimitry Andric     // Otherwise, check whether we have reached the 'endm'... and determine if
5913e8d8bef9SDimitry Andric     // this is a macro function.
59145ffd83dbSDimitry Andric     if (getLexer().is(AsmToken::Identifier)) {
5915fe6060f1SDimitry Andric       if (getTok().getIdentifier().equals_insensitive("endm")) {
59165ffd83dbSDimitry Andric         if (MacroDepth == 0) { // Outermost macro.
59175ffd83dbSDimitry Andric           EndToken = getTok();
59185ffd83dbSDimitry Andric           Lexer.Lex();
59195ffd83dbSDimitry Andric           if (getLexer().isNot(AsmToken::EndOfStatement))
59205ffd83dbSDimitry Andric             return TokError("unexpected token in '" + EndToken.getIdentifier() +
59215ffd83dbSDimitry Andric                             "' directive");
59225ffd83dbSDimitry Andric           break;
59235ffd83dbSDimitry Andric         } else {
59245ffd83dbSDimitry Andric           // Otherwise we just found the end of an inner macro.
59255ffd83dbSDimitry Andric           --MacroDepth;
59265ffd83dbSDimitry Andric         }
5927fe6060f1SDimitry Andric       } else if (getTok().getIdentifier().equals_insensitive("exitm")) {
5928fe6060f1SDimitry Andric         if (MacroDepth == 0 && peekTok().isNot(AsmToken::EndOfStatement)) {
5929e8d8bef9SDimitry Andric           IsMacroFunction = true;
5930e8d8bef9SDimitry Andric         }
5931e8d8bef9SDimitry Andric       } else if (isMacroLikeDirective()) {
5932e8d8bef9SDimitry Andric         // We allow nested macros. Those aren't instantiated until the
5933e8d8bef9SDimitry Andric         // outermost macro is expanded so just ignore them for now.
59345ffd83dbSDimitry Andric         ++MacroDepth;
59355ffd83dbSDimitry Andric       }
59365ffd83dbSDimitry Andric     }
59375ffd83dbSDimitry Andric 
59385ffd83dbSDimitry Andric     // Otherwise, scan til the end of the statement.
59395ffd83dbSDimitry Andric     eatToEndOfStatement();
59405ffd83dbSDimitry Andric   }
59415ffd83dbSDimitry Andric 
5942e8d8bef9SDimitry Andric   if (getContext().lookupMacro(Name.lower())) {
5943e8d8bef9SDimitry Andric     return Error(NameLoc, "macro '" + Name + "' is already defined");
59445ffd83dbSDimitry Andric   }
59455ffd83dbSDimitry Andric 
59465ffd83dbSDimitry Andric   const char *BodyStart = StartToken.getLoc().getPointer();
59475ffd83dbSDimitry Andric   const char *BodyEnd = EndToken.getLoc().getPointer();
59485ffd83dbSDimitry Andric   StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5949e8d8bef9SDimitry Andric   MCAsmMacro Macro(Name, Body, std::move(Parameters), std::move(Locals),
5950e8d8bef9SDimitry Andric                    IsMacroFunction);
59515ffd83dbSDimitry Andric   DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
59525ffd83dbSDimitry Andric                   Macro.dump());
5953fe6060f1SDimitry Andric   getContext().defineMacro(Name.lower(), std::move(Macro));
59545ffd83dbSDimitry Andric   return false;
59555ffd83dbSDimitry Andric }
59565ffd83dbSDimitry Andric 
59575ffd83dbSDimitry Andric /// parseDirectiveExitMacro
5958e8d8bef9SDimitry Andric /// ::= "exitm" [textitem]
5959e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
5960e8d8bef9SDimitry Andric                                          StringRef Directive,
5961e8d8bef9SDimitry Andric                                          std::string &Value) {
5962e8d8bef9SDimitry Andric   SMLoc EndLoc = getTok().getLoc();
5963e8d8bef9SDimitry Andric   if (getTok().isNot(AsmToken::EndOfStatement) && parseTextItem(Value))
5964e8d8bef9SDimitry Andric     return Error(EndLoc,
5965e8d8bef9SDimitry Andric                  "unable to parse text item in '" + Directive + "' directive");
5966e8d8bef9SDimitry Andric   eatToEndOfStatement();
59675ffd83dbSDimitry Andric 
59685ffd83dbSDimitry Andric   if (!isInsideMacroInstantiation())
59695ffd83dbSDimitry Andric     return TokError("unexpected '" + Directive + "' in file, "
59705ffd83dbSDimitry Andric                                                  "no current macro definition");
59715ffd83dbSDimitry Andric 
59725ffd83dbSDimitry Andric   // Exit all conditionals that are active in the current macro.
59735ffd83dbSDimitry Andric   while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
59745ffd83dbSDimitry Andric     TheCondState = TheCondStack.back();
59755ffd83dbSDimitry Andric     TheCondStack.pop_back();
59765ffd83dbSDimitry Andric   }
59775ffd83dbSDimitry Andric 
59785ffd83dbSDimitry Andric   handleMacroExit();
59795ffd83dbSDimitry Andric   return false;
59805ffd83dbSDimitry Andric }
59815ffd83dbSDimitry Andric 
59825ffd83dbSDimitry Andric /// parseDirectiveEndMacro
5983e8d8bef9SDimitry Andric /// ::= endm
59845ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
59855ffd83dbSDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
59865ffd83dbSDimitry Andric     return TokError("unexpected token in '" + Directive + "' directive");
59875ffd83dbSDimitry Andric 
59885ffd83dbSDimitry Andric   // If we are inside a macro instantiation, terminate the current
59895ffd83dbSDimitry Andric   // instantiation.
59905ffd83dbSDimitry Andric   if (isInsideMacroInstantiation()) {
59915ffd83dbSDimitry Andric     handleMacroExit();
59925ffd83dbSDimitry Andric     return false;
59935ffd83dbSDimitry Andric   }
59945ffd83dbSDimitry Andric 
59955ffd83dbSDimitry Andric   // Otherwise, this .endmacro is a stray entry in the file; well formed
59965ffd83dbSDimitry Andric   // .endmacro directives are handled during the macro definition parsing.
59975ffd83dbSDimitry Andric   return TokError("unexpected '" + Directive + "' in file, "
59985ffd83dbSDimitry Andric                                                "no current macro definition");
59995ffd83dbSDimitry Andric }
60005ffd83dbSDimitry Andric 
60015ffd83dbSDimitry Andric /// parseDirectivePurgeMacro
6002e8d8bef9SDimitry Andric /// ::= purge identifier ( , identifier )*
60035ffd83dbSDimitry Andric bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
60045ffd83dbSDimitry Andric   StringRef Name;
6005e8d8bef9SDimitry Andric   while (true) {
6006e8d8bef9SDimitry Andric     SMLoc NameLoc;
6007e8d8bef9SDimitry Andric     if (parseTokenLoc(NameLoc) ||
6008e8d8bef9SDimitry Andric         check(parseIdentifier(Name), NameLoc,
6009e8d8bef9SDimitry Andric               "expected identifier in 'purge' directive"))
60105ffd83dbSDimitry Andric       return true;
60115ffd83dbSDimitry Andric 
60125ffd83dbSDimitry Andric     DEBUG_WITH_TYPE("asm-macros", dbgs()
60135ffd83dbSDimitry Andric                                       << "Un-defining macro: " << Name << "\n");
6014e8d8bef9SDimitry Andric     if (!getContext().lookupMacro(Name.lower()))
6015e8d8bef9SDimitry Andric       return Error(NameLoc, "macro '" + Name + "' is not defined");
6016e8d8bef9SDimitry Andric     getContext().undefineMacro(Name.lower());
6017e8d8bef9SDimitry Andric 
6018e8d8bef9SDimitry Andric     if (!parseOptionalToken(AsmToken::Comma))
6019e8d8bef9SDimitry Andric       break;
6020e8d8bef9SDimitry Andric     parseOptionalToken(AsmToken::EndOfStatement);
6021e8d8bef9SDimitry Andric   }
6022e8d8bef9SDimitry Andric 
60235ffd83dbSDimitry Andric   return false;
60245ffd83dbSDimitry Andric }
60255ffd83dbSDimitry Andric 
60265ffd83dbSDimitry Andric /// parseDirectiveSymbolAttribute
60275ffd83dbSDimitry Andric ///  ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
60285ffd83dbSDimitry Andric bool MasmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
60295ffd83dbSDimitry Andric   auto parseOp = [&]() -> bool {
60305ffd83dbSDimitry Andric     StringRef Name;
60315ffd83dbSDimitry Andric     SMLoc Loc = getTok().getLoc();
60325ffd83dbSDimitry Andric     if (parseIdentifier(Name))
60335ffd83dbSDimitry Andric       return Error(Loc, "expected identifier");
60345ffd83dbSDimitry Andric     MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
60355ffd83dbSDimitry Andric 
60365ffd83dbSDimitry Andric     // Assembler local symbols don't make any sense here. Complain loudly.
60375ffd83dbSDimitry Andric     if (Sym->isTemporary())
60385ffd83dbSDimitry Andric       return Error(Loc, "non-local symbol required");
60395ffd83dbSDimitry Andric 
60405ffd83dbSDimitry Andric     if (!getStreamer().emitSymbolAttribute(Sym, Attr))
60415ffd83dbSDimitry Andric       return Error(Loc, "unable to emit symbol attribute");
60425ffd83dbSDimitry Andric     return false;
60435ffd83dbSDimitry Andric   };
60445ffd83dbSDimitry Andric 
60455ffd83dbSDimitry Andric   if (parseMany(parseOp))
60465ffd83dbSDimitry Andric     return addErrorSuffix(" in directive");
60475ffd83dbSDimitry Andric   return false;
60485ffd83dbSDimitry Andric }
60495ffd83dbSDimitry Andric 
60505ffd83dbSDimitry Andric /// parseDirectiveComm
60515ffd83dbSDimitry Andric ///  ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
60525ffd83dbSDimitry Andric bool MasmParser::parseDirectiveComm(bool IsLocal) {
60535ffd83dbSDimitry Andric   if (checkForValidSection())
60545ffd83dbSDimitry Andric     return true;
60555ffd83dbSDimitry Andric 
60565ffd83dbSDimitry Andric   SMLoc IDLoc = getLexer().getLoc();
60575ffd83dbSDimitry Andric   StringRef Name;
60585ffd83dbSDimitry Andric   if (parseIdentifier(Name))
60595ffd83dbSDimitry Andric     return TokError("expected identifier in directive");
60605ffd83dbSDimitry Andric 
60615ffd83dbSDimitry Andric   // Handle the identifier as the key symbol.
60625ffd83dbSDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
60635ffd83dbSDimitry Andric 
60645ffd83dbSDimitry Andric   if (getLexer().isNot(AsmToken::Comma))
60655ffd83dbSDimitry Andric     return TokError("unexpected token in directive");
60665ffd83dbSDimitry Andric   Lex();
60675ffd83dbSDimitry Andric 
60685ffd83dbSDimitry Andric   int64_t Size;
60695ffd83dbSDimitry Andric   SMLoc SizeLoc = getLexer().getLoc();
60705ffd83dbSDimitry Andric   if (parseAbsoluteExpression(Size))
60715ffd83dbSDimitry Andric     return true;
60725ffd83dbSDimitry Andric 
60735ffd83dbSDimitry Andric   int64_t Pow2Alignment = 0;
60745ffd83dbSDimitry Andric   SMLoc Pow2AlignmentLoc;
60755ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Comma)) {
60765ffd83dbSDimitry Andric     Lex();
60775ffd83dbSDimitry Andric     Pow2AlignmentLoc = getLexer().getLoc();
60785ffd83dbSDimitry Andric     if (parseAbsoluteExpression(Pow2Alignment))
60795ffd83dbSDimitry Andric       return true;
60805ffd83dbSDimitry Andric 
60815ffd83dbSDimitry Andric     LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
60825ffd83dbSDimitry Andric     if (IsLocal && LCOMM == LCOMM::NoAlignment)
60835ffd83dbSDimitry Andric       return Error(Pow2AlignmentLoc, "alignment not supported on this target");
60845ffd83dbSDimitry Andric 
60855ffd83dbSDimitry Andric     // If this target takes alignments in bytes (not log) validate and convert.
60865ffd83dbSDimitry Andric     if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
60875ffd83dbSDimitry Andric         (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
60885ffd83dbSDimitry Andric       if (!isPowerOf2_64(Pow2Alignment))
60895ffd83dbSDimitry Andric         return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
60905ffd83dbSDimitry Andric       Pow2Alignment = Log2_64(Pow2Alignment);
60915ffd83dbSDimitry Andric     }
60925ffd83dbSDimitry Andric   }
60935ffd83dbSDimitry Andric 
60945ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement,
60955ffd83dbSDimitry Andric                  "unexpected token in '.comm' or '.lcomm' directive"))
60965ffd83dbSDimitry Andric     return true;
60975ffd83dbSDimitry Andric 
60985ffd83dbSDimitry Andric   // NOTE: a size of zero for a .comm should create a undefined symbol
60995ffd83dbSDimitry Andric   // but a size of .lcomm creates a bss symbol of size zero.
61005ffd83dbSDimitry Andric   if (Size < 0)
61015ffd83dbSDimitry Andric     return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
61025ffd83dbSDimitry Andric                           "be less than zero");
61035ffd83dbSDimitry Andric 
61045ffd83dbSDimitry Andric   // NOTE: The alignment in the directive is a power of 2 value, the assembler
61055ffd83dbSDimitry Andric   // may internally end up wanting an alignment in bytes.
61065ffd83dbSDimitry Andric   // FIXME: Diagnose overflow.
61075ffd83dbSDimitry Andric   if (Pow2Alignment < 0)
61085ffd83dbSDimitry Andric     return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
61095ffd83dbSDimitry Andric                                    "alignment, can't be less than zero");
61105ffd83dbSDimitry Andric 
61115ffd83dbSDimitry Andric   Sym->redefineIfPossible();
61125ffd83dbSDimitry Andric   if (!Sym->isUndefined())
61135ffd83dbSDimitry Andric     return Error(IDLoc, "invalid symbol redefinition");
61145ffd83dbSDimitry Andric 
61155ffd83dbSDimitry Andric   // Create the Symbol as a common or local common with Size and Pow2Alignment.
61165ffd83dbSDimitry Andric   if (IsLocal) {
61175ffd83dbSDimitry Andric     getStreamer().emitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment);
61185ffd83dbSDimitry Andric     return false;
61195ffd83dbSDimitry Andric   }
61205ffd83dbSDimitry Andric 
61215ffd83dbSDimitry Andric   getStreamer().emitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
61225ffd83dbSDimitry Andric   return false;
61235ffd83dbSDimitry Andric }
61245ffd83dbSDimitry Andric 
61255ffd83dbSDimitry Andric /// parseDirectiveComment
61265ffd83dbSDimitry Andric ///  ::= comment delimiter [[text]]
61275ffd83dbSDimitry Andric ///              [[text]]
61285ffd83dbSDimitry Andric ///              [[text]] delimiter [[text]]
61295ffd83dbSDimitry Andric bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
6130e8d8bef9SDimitry Andric   std::string FirstLine = parseStringTo(AsmToken::EndOfStatement);
61315ffd83dbSDimitry Andric   size_t DelimiterEnd = FirstLine.find_first_of("\b\t\v\f\r\x1A ");
6132e8d8bef9SDimitry Andric   StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd);
61335ffd83dbSDimitry Andric   if (Delimiter.empty())
61345ffd83dbSDimitry Andric     return Error(DirectiveLoc, "no delimiter in 'comment' directive");
61355ffd83dbSDimitry Andric   do {
61365ffd83dbSDimitry Andric     if (getTok().is(AsmToken::Eof))
61375ffd83dbSDimitry Andric       return Error(DirectiveLoc, "unmatched delimiter in 'comment' directive");
61385ffd83dbSDimitry Andric     Lex();  // eat end of statement
6139e8d8bef9SDimitry Andric   } while (
6140e8d8bef9SDimitry Andric       !StringRef(parseStringTo(AsmToken::EndOfStatement)).contains(Delimiter));
61415ffd83dbSDimitry Andric   return parseToken(AsmToken::EndOfStatement,
61425ffd83dbSDimitry Andric                     "unexpected token in 'comment' directive");
61435ffd83dbSDimitry Andric }
61445ffd83dbSDimitry Andric 
61455ffd83dbSDimitry Andric /// parseDirectiveInclude
61465ffd83dbSDimitry Andric ///  ::= include <filename>
61475ffd83dbSDimitry Andric ///    | include filename
61485ffd83dbSDimitry Andric bool MasmParser::parseDirectiveInclude() {
61495ffd83dbSDimitry Andric   // Allow the strings to have escaped octal character sequence.
61505ffd83dbSDimitry Andric   std::string Filename;
61515ffd83dbSDimitry Andric   SMLoc IncludeLoc = getTok().getLoc();
61525ffd83dbSDimitry Andric 
6153fe6060f1SDimitry Andric   if (parseAngleBracketString(Filename))
6154e8d8bef9SDimitry Andric     Filename = parseStringTo(AsmToken::EndOfStatement);
6155fe6060f1SDimitry Andric   if (check(Filename.empty(), "missing filename in 'include' directive") ||
61565ffd83dbSDimitry Andric       check(getTok().isNot(AsmToken::EndOfStatement),
61575ffd83dbSDimitry Andric             "unexpected token in 'include' directive") ||
61585ffd83dbSDimitry Andric       // Attempt to switch the lexer to the included file before consuming the
61595ffd83dbSDimitry Andric       // end of statement to avoid losing it when we switch.
61605ffd83dbSDimitry Andric       check(enterIncludeFile(Filename), IncludeLoc,
61615ffd83dbSDimitry Andric             "Could not find include file '" + Filename + "'"))
61625ffd83dbSDimitry Andric     return true;
61635ffd83dbSDimitry Andric 
61645ffd83dbSDimitry Andric   return false;
61655ffd83dbSDimitry Andric }
61665ffd83dbSDimitry Andric 
61675ffd83dbSDimitry Andric /// parseDirectiveIf
61685ffd83dbSDimitry Andric /// ::= .if{,eq,ge,gt,le,lt,ne} expression
61695ffd83dbSDimitry Andric bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
61705ffd83dbSDimitry Andric   TheCondStack.push_back(TheCondState);
61715ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::IfCond;
61725ffd83dbSDimitry Andric   if (TheCondState.Ignore) {
61735ffd83dbSDimitry Andric     eatToEndOfStatement();
61745ffd83dbSDimitry Andric   } else {
61755ffd83dbSDimitry Andric     int64_t ExprValue;
61765ffd83dbSDimitry Andric     if (parseAbsoluteExpression(ExprValue) ||
61775ffd83dbSDimitry Andric         parseToken(AsmToken::EndOfStatement,
61785ffd83dbSDimitry Andric                    "unexpected token in '.if' directive"))
61795ffd83dbSDimitry Andric       return true;
61805ffd83dbSDimitry Andric 
61815ffd83dbSDimitry Andric     switch (DirKind) {
61825ffd83dbSDimitry Andric     default:
61835ffd83dbSDimitry Andric       llvm_unreachable("unsupported directive");
61845ffd83dbSDimitry Andric     case DK_IF:
61855ffd83dbSDimitry Andric       break;
61865ffd83dbSDimitry Andric     case DK_IFE:
61875ffd83dbSDimitry Andric       ExprValue = ExprValue == 0;
61885ffd83dbSDimitry Andric       break;
61895ffd83dbSDimitry Andric     }
61905ffd83dbSDimitry Andric 
61915ffd83dbSDimitry Andric     TheCondState.CondMet = ExprValue;
61925ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
61935ffd83dbSDimitry Andric   }
61945ffd83dbSDimitry Andric 
61955ffd83dbSDimitry Andric   return false;
61965ffd83dbSDimitry Andric }
61975ffd83dbSDimitry Andric 
61985ffd83dbSDimitry Andric /// parseDirectiveIfb
6199e8d8bef9SDimitry Andric /// ::= .ifb textitem
62005ffd83dbSDimitry Andric bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
62015ffd83dbSDimitry Andric   TheCondStack.push_back(TheCondState);
62025ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::IfCond;
62035ffd83dbSDimitry Andric 
62045ffd83dbSDimitry Andric   if (TheCondState.Ignore) {
62055ffd83dbSDimitry Andric     eatToEndOfStatement();
62065ffd83dbSDimitry Andric   } else {
62075ffd83dbSDimitry Andric     std::string Str;
62085ffd83dbSDimitry Andric     if (parseTextItem(Str))
6209e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'ifb' directive");
62105ffd83dbSDimitry Andric 
62115ffd83dbSDimitry Andric     if (parseToken(AsmToken::EndOfStatement,
62125ffd83dbSDimitry Andric                    "unexpected token in 'ifb' directive"))
62135ffd83dbSDimitry Andric       return true;
62145ffd83dbSDimitry Andric 
62155ffd83dbSDimitry Andric     TheCondState.CondMet = ExpectBlank == Str.empty();
62165ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
62175ffd83dbSDimitry Andric   }
62185ffd83dbSDimitry Andric 
62195ffd83dbSDimitry Andric   return false;
62205ffd83dbSDimitry Andric }
62215ffd83dbSDimitry Andric 
62225ffd83dbSDimitry Andric /// parseDirectiveIfidn
6223e8d8bef9SDimitry Andric ///   ::= ifidn textitem, textitem
6224e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
6225e8d8bef9SDimitry Andric                                      bool CaseInsensitive) {
62265ffd83dbSDimitry Andric   std::string String1, String2;
62275ffd83dbSDimitry Andric 
62285ffd83dbSDimitry Andric   if (parseTextItem(String1)) {
62295ffd83dbSDimitry Andric     if (ExpectEqual)
6230e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'ifidn' directive");
6231e8d8bef9SDimitry Andric     return TokError("expected text item parameter for 'ifdif' directive");
62325ffd83dbSDimitry Andric   }
62335ffd83dbSDimitry Andric 
62345ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::Comma)) {
62355ffd83dbSDimitry Andric     if (ExpectEqual)
62365ffd83dbSDimitry Andric       return TokError(
62375ffd83dbSDimitry Andric           "expected comma after first string for 'ifidn' directive");
62385ffd83dbSDimitry Andric     return TokError("expected comma after first string for 'ifdif' directive");
62395ffd83dbSDimitry Andric   }
62405ffd83dbSDimitry Andric   Lex();
62415ffd83dbSDimitry Andric 
62425ffd83dbSDimitry Andric   if (parseTextItem(String2)) {
62435ffd83dbSDimitry Andric     if (ExpectEqual)
6244e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'ifidn' directive");
6245e8d8bef9SDimitry Andric     return TokError("expected text item parameter for 'ifdif' directive");
62465ffd83dbSDimitry Andric   }
62475ffd83dbSDimitry Andric 
62485ffd83dbSDimitry Andric   TheCondStack.push_back(TheCondState);
62495ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::IfCond;
62505ffd83dbSDimitry Andric   if (CaseInsensitive)
62515ffd83dbSDimitry Andric     TheCondState.CondMet =
6252fe6060f1SDimitry Andric         ExpectEqual == (StringRef(String1).equals_insensitive(String2));
62535ffd83dbSDimitry Andric   else
62545ffd83dbSDimitry Andric     TheCondState.CondMet = ExpectEqual == (String1 == String2);
62555ffd83dbSDimitry Andric   TheCondState.Ignore = !TheCondState.CondMet;
62565ffd83dbSDimitry Andric 
62575ffd83dbSDimitry Andric   return false;
62585ffd83dbSDimitry Andric }
62595ffd83dbSDimitry Andric 
62605ffd83dbSDimitry Andric /// parseDirectiveIfdef
62615ffd83dbSDimitry Andric /// ::= ifdef symbol
62625ffd83dbSDimitry Andric ///   | ifdef variable
62635ffd83dbSDimitry Andric bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
62645ffd83dbSDimitry Andric   TheCondStack.push_back(TheCondState);
62655ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::IfCond;
62665ffd83dbSDimitry Andric 
62675ffd83dbSDimitry Andric   if (TheCondState.Ignore) {
62685ffd83dbSDimitry Andric     eatToEndOfStatement();
62695ffd83dbSDimitry Andric   } else {
62705ffd83dbSDimitry Andric     bool is_defined = false;
62715ffd83dbSDimitry Andric     unsigned RegNo;
62725ffd83dbSDimitry Andric     SMLoc StartLoc, EndLoc;
62735ffd83dbSDimitry Andric     is_defined = (getTargetParser().tryParseRegister(
62745ffd83dbSDimitry Andric                       RegNo, StartLoc, EndLoc) == MatchOperand_Success);
62755ffd83dbSDimitry Andric     if (!is_defined) {
62765ffd83dbSDimitry Andric       StringRef Name;
62775ffd83dbSDimitry Andric       if (check(parseIdentifier(Name), "expected identifier after 'ifdef'") ||
62785ffd83dbSDimitry Andric           parseToken(AsmToken::EndOfStatement, "unexpected token in 'ifdef'"))
62795ffd83dbSDimitry Andric         return true;
62805ffd83dbSDimitry Andric 
6281fe6060f1SDimitry Andric       if (BuiltinSymbolMap.find(Name.lower()) != BuiltinSymbolMap.end()) {
6282fe6060f1SDimitry Andric         is_defined = true;
6283fe6060f1SDimitry Andric       } else if (Variables.find(Name.lower()) != Variables.end()) {
62845ffd83dbSDimitry Andric         is_defined = true;
62855ffd83dbSDimitry Andric       } else {
6286fe6060f1SDimitry Andric         MCSymbol *Sym = getContext().lookupSymbol(Name.lower());
62875ffd83dbSDimitry Andric         is_defined = (Sym && !Sym->isUndefined(false));
62885ffd83dbSDimitry Andric       }
62895ffd83dbSDimitry Andric     }
62905ffd83dbSDimitry Andric 
62915ffd83dbSDimitry Andric     TheCondState.CondMet = (is_defined == expect_defined);
62925ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
62935ffd83dbSDimitry Andric   }
62945ffd83dbSDimitry Andric 
62955ffd83dbSDimitry Andric   return false;
62965ffd83dbSDimitry Andric }
62975ffd83dbSDimitry Andric 
62985ffd83dbSDimitry Andric /// parseDirectiveElseIf
62995ffd83dbSDimitry Andric /// ::= elseif expression
63005ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
63015ffd83dbSDimitry Andric                                       DirectiveKind DirKind) {
63025ffd83dbSDimitry Andric   if (TheCondState.TheCond != AsmCond::IfCond &&
63035ffd83dbSDimitry Andric       TheCondState.TheCond != AsmCond::ElseIfCond)
63045ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
63055ffd83dbSDimitry Andric                                " .if or  an .elseif");
63065ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::ElseIfCond;
63075ffd83dbSDimitry Andric 
63085ffd83dbSDimitry Andric   bool LastIgnoreState = false;
63095ffd83dbSDimitry Andric   if (!TheCondStack.empty())
63105ffd83dbSDimitry Andric     LastIgnoreState = TheCondStack.back().Ignore;
63115ffd83dbSDimitry Andric   if (LastIgnoreState || TheCondState.CondMet) {
63125ffd83dbSDimitry Andric     TheCondState.Ignore = true;
63135ffd83dbSDimitry Andric     eatToEndOfStatement();
63145ffd83dbSDimitry Andric   } else {
63155ffd83dbSDimitry Andric     int64_t ExprValue;
63165ffd83dbSDimitry Andric     if (parseAbsoluteExpression(ExprValue))
63175ffd83dbSDimitry Andric       return true;
63185ffd83dbSDimitry Andric 
63195ffd83dbSDimitry Andric     if (parseToken(AsmToken::EndOfStatement,
63205ffd83dbSDimitry Andric                    "unexpected token in '.elseif' directive"))
63215ffd83dbSDimitry Andric       return true;
63225ffd83dbSDimitry Andric 
63235ffd83dbSDimitry Andric     switch (DirKind) {
63245ffd83dbSDimitry Andric     default:
63255ffd83dbSDimitry Andric       llvm_unreachable("unsupported directive");
63265ffd83dbSDimitry Andric     case DK_ELSEIF:
63275ffd83dbSDimitry Andric       break;
63285ffd83dbSDimitry Andric     case DK_ELSEIFE:
63295ffd83dbSDimitry Andric       ExprValue = ExprValue == 0;
63305ffd83dbSDimitry Andric       break;
63315ffd83dbSDimitry Andric     }
63325ffd83dbSDimitry Andric 
63335ffd83dbSDimitry Andric     TheCondState.CondMet = ExprValue;
63345ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
63355ffd83dbSDimitry Andric   }
63365ffd83dbSDimitry Andric 
63375ffd83dbSDimitry Andric   return false;
63385ffd83dbSDimitry Andric }
63395ffd83dbSDimitry Andric 
63405ffd83dbSDimitry Andric /// parseDirectiveElseIfb
6341e8d8bef9SDimitry Andric /// ::= elseifb textitem
63425ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
63435ffd83dbSDimitry Andric   if (TheCondState.TheCond != AsmCond::IfCond &&
63445ffd83dbSDimitry Andric       TheCondState.TheCond != AsmCond::ElseIfCond)
63455ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
63465ffd83dbSDimitry Andric                                " if or an elseif");
63475ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::ElseIfCond;
63485ffd83dbSDimitry Andric 
63495ffd83dbSDimitry Andric   bool LastIgnoreState = false;
63505ffd83dbSDimitry Andric   if (!TheCondStack.empty())
63515ffd83dbSDimitry Andric     LastIgnoreState = TheCondStack.back().Ignore;
63525ffd83dbSDimitry Andric   if (LastIgnoreState || TheCondState.CondMet) {
63535ffd83dbSDimitry Andric     TheCondState.Ignore = true;
63545ffd83dbSDimitry Andric     eatToEndOfStatement();
63555ffd83dbSDimitry Andric   } else {
63565ffd83dbSDimitry Andric     std::string Str;
6357e8d8bef9SDimitry Andric     if (parseTextItem(Str)) {
6358e8d8bef9SDimitry Andric       if (ExpectBlank)
6359e8d8bef9SDimitry Andric         return TokError("expected text item parameter for 'elseifb' directive");
6360e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'elseifnb' directive");
6361e8d8bef9SDimitry Andric     }
63625ffd83dbSDimitry Andric 
63635ffd83dbSDimitry Andric     if (parseToken(AsmToken::EndOfStatement,
63645ffd83dbSDimitry Andric                    "unexpected token in 'elseifb' directive"))
63655ffd83dbSDimitry Andric       return true;
63665ffd83dbSDimitry Andric 
63675ffd83dbSDimitry Andric     TheCondState.CondMet = ExpectBlank == Str.empty();
63685ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
63695ffd83dbSDimitry Andric   }
63705ffd83dbSDimitry Andric 
63715ffd83dbSDimitry Andric   return false;
63725ffd83dbSDimitry Andric }
63735ffd83dbSDimitry Andric 
63745ffd83dbSDimitry Andric /// parseDirectiveElseIfdef
63755ffd83dbSDimitry Andric /// ::= elseifdef symbol
63765ffd83dbSDimitry Andric ///   | elseifdef variable
63775ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
63785ffd83dbSDimitry Andric                                          bool expect_defined) {
63795ffd83dbSDimitry Andric   if (TheCondState.TheCond != AsmCond::IfCond &&
63805ffd83dbSDimitry Andric       TheCondState.TheCond != AsmCond::ElseIfCond)
63815ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
63825ffd83dbSDimitry Andric                                " if or an elseif");
63835ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::ElseIfCond;
63845ffd83dbSDimitry Andric 
63855ffd83dbSDimitry Andric   bool LastIgnoreState = false;
63865ffd83dbSDimitry Andric   if (!TheCondStack.empty())
63875ffd83dbSDimitry Andric     LastIgnoreState = TheCondStack.back().Ignore;
63885ffd83dbSDimitry Andric   if (LastIgnoreState || TheCondState.CondMet) {
63895ffd83dbSDimitry Andric     TheCondState.Ignore = true;
63905ffd83dbSDimitry Andric     eatToEndOfStatement();
63915ffd83dbSDimitry Andric   } else {
63925ffd83dbSDimitry Andric     bool is_defined = false;
63935ffd83dbSDimitry Andric     unsigned RegNo;
63945ffd83dbSDimitry Andric     SMLoc StartLoc, EndLoc;
63955ffd83dbSDimitry Andric     is_defined = (getTargetParser().tryParseRegister(RegNo, StartLoc, EndLoc) ==
63965ffd83dbSDimitry Andric                   MatchOperand_Success);
63975ffd83dbSDimitry Andric     if (!is_defined) {
63985ffd83dbSDimitry Andric       StringRef Name;
63995ffd83dbSDimitry Andric       if (check(parseIdentifier(Name),
64005ffd83dbSDimitry Andric                 "expected identifier after 'elseifdef'") ||
64015ffd83dbSDimitry Andric           parseToken(AsmToken::EndOfStatement,
64025ffd83dbSDimitry Andric                      "unexpected token in 'elseifdef'"))
64035ffd83dbSDimitry Andric         return true;
64045ffd83dbSDimitry Andric 
6405fe6060f1SDimitry Andric       if (BuiltinSymbolMap.find(Name.lower()) != BuiltinSymbolMap.end()) {
6406fe6060f1SDimitry Andric         is_defined = true;
6407fe6060f1SDimitry Andric       } else if (Variables.find(Name.lower()) != Variables.end()) {
64085ffd83dbSDimitry Andric         is_defined = true;
64095ffd83dbSDimitry Andric       } else {
64105ffd83dbSDimitry Andric         MCSymbol *Sym = getContext().lookupSymbol(Name);
64115ffd83dbSDimitry Andric         is_defined = (Sym && !Sym->isUndefined(false));
64125ffd83dbSDimitry Andric       }
64135ffd83dbSDimitry Andric     }
64145ffd83dbSDimitry Andric 
64155ffd83dbSDimitry Andric     TheCondState.CondMet = (is_defined == expect_defined);
64165ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
64175ffd83dbSDimitry Andric   }
64185ffd83dbSDimitry Andric 
64195ffd83dbSDimitry Andric   return false;
64205ffd83dbSDimitry Andric }
64215ffd83dbSDimitry Andric 
64225ffd83dbSDimitry Andric /// parseDirectiveElseIfidn
6423e8d8bef9SDimitry Andric /// ::= elseifidn textitem, textitem
64245ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
64255ffd83dbSDimitry Andric                                          bool CaseInsensitive) {
64265ffd83dbSDimitry Andric   if (TheCondState.TheCond != AsmCond::IfCond &&
64275ffd83dbSDimitry Andric       TheCondState.TheCond != AsmCond::ElseIfCond)
64285ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
64295ffd83dbSDimitry Andric                                " if or an elseif");
64305ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::ElseIfCond;
64315ffd83dbSDimitry Andric 
64325ffd83dbSDimitry Andric   bool LastIgnoreState = false;
64335ffd83dbSDimitry Andric   if (!TheCondStack.empty())
64345ffd83dbSDimitry Andric     LastIgnoreState = TheCondStack.back().Ignore;
64355ffd83dbSDimitry Andric   if (LastIgnoreState || TheCondState.CondMet) {
64365ffd83dbSDimitry Andric     TheCondState.Ignore = true;
64375ffd83dbSDimitry Andric     eatToEndOfStatement();
64385ffd83dbSDimitry Andric   } else {
64395ffd83dbSDimitry Andric     std::string String1, String2;
64405ffd83dbSDimitry Andric 
64415ffd83dbSDimitry Andric     if (parseTextItem(String1)) {
64425ffd83dbSDimitry Andric       if (ExpectEqual)
6443e8d8bef9SDimitry Andric         return TokError(
6444e8d8bef9SDimitry Andric             "expected text item parameter for 'elseifidn' directive");
6445e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'elseifdif' directive");
64465ffd83dbSDimitry Andric     }
64475ffd83dbSDimitry Andric 
64485ffd83dbSDimitry Andric     if (Lexer.isNot(AsmToken::Comma)) {
64495ffd83dbSDimitry Andric       if (ExpectEqual)
64505ffd83dbSDimitry Andric         return TokError(
64515ffd83dbSDimitry Andric             "expected comma after first string for 'elseifidn' directive");
64525ffd83dbSDimitry Andric       return TokError(
64535ffd83dbSDimitry Andric           "expected comma after first string for 'elseifdif' directive");
64545ffd83dbSDimitry Andric     }
64555ffd83dbSDimitry Andric     Lex();
64565ffd83dbSDimitry Andric 
64575ffd83dbSDimitry Andric     if (parseTextItem(String2)) {
64585ffd83dbSDimitry Andric       if (ExpectEqual)
6459e8d8bef9SDimitry Andric         return TokError(
6460e8d8bef9SDimitry Andric             "expected text item parameter for 'elseifidn' directive");
6461e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'elseifdif' directive");
64625ffd83dbSDimitry Andric     }
64635ffd83dbSDimitry Andric 
64645ffd83dbSDimitry Andric     if (CaseInsensitive)
64655ffd83dbSDimitry Andric       TheCondState.CondMet =
6466fe6060f1SDimitry Andric           ExpectEqual == (StringRef(String1).equals_insensitive(String2));
64675ffd83dbSDimitry Andric     else
64685ffd83dbSDimitry Andric       TheCondState.CondMet = ExpectEqual == (String1 == String2);
64695ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
64705ffd83dbSDimitry Andric   }
64715ffd83dbSDimitry Andric 
64725ffd83dbSDimitry Andric   return false;
64735ffd83dbSDimitry Andric }
64745ffd83dbSDimitry Andric 
64755ffd83dbSDimitry Andric /// parseDirectiveElse
64765ffd83dbSDimitry Andric /// ::= else
64775ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
64785ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement,
64795ffd83dbSDimitry Andric                  "unexpected token in 'else' directive"))
64805ffd83dbSDimitry Andric     return true;
64815ffd83dbSDimitry Andric 
64825ffd83dbSDimitry Andric   if (TheCondState.TheCond != AsmCond::IfCond &&
64835ffd83dbSDimitry Andric       TheCondState.TheCond != AsmCond::ElseIfCond)
64845ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered an else that doesn't follow an if"
64855ffd83dbSDimitry Andric                                " or an elseif");
64865ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::ElseCond;
64875ffd83dbSDimitry Andric   bool LastIgnoreState = false;
64885ffd83dbSDimitry Andric   if (!TheCondStack.empty())
64895ffd83dbSDimitry Andric     LastIgnoreState = TheCondStack.back().Ignore;
64905ffd83dbSDimitry Andric   if (LastIgnoreState || TheCondState.CondMet)
64915ffd83dbSDimitry Andric     TheCondState.Ignore = true;
64925ffd83dbSDimitry Andric   else
64935ffd83dbSDimitry Andric     TheCondState.Ignore = false;
64945ffd83dbSDimitry Andric 
64955ffd83dbSDimitry Andric   return false;
64965ffd83dbSDimitry Andric }
64975ffd83dbSDimitry Andric 
64985ffd83dbSDimitry Andric /// parseDirectiveEnd
64995ffd83dbSDimitry Andric /// ::= end
65005ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
65015ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement,
65025ffd83dbSDimitry Andric                  "unexpected token in 'end' directive"))
65035ffd83dbSDimitry Andric     return true;
65045ffd83dbSDimitry Andric 
65055ffd83dbSDimitry Andric   while (Lexer.isNot(AsmToken::Eof))
65065ffd83dbSDimitry Andric     Lexer.Lex();
65075ffd83dbSDimitry Andric 
65085ffd83dbSDimitry Andric   return false;
65095ffd83dbSDimitry Andric }
65105ffd83dbSDimitry Andric 
65115ffd83dbSDimitry Andric /// parseDirectiveError
65125ffd83dbSDimitry Andric ///   ::= .err [message]
65135ffd83dbSDimitry Andric bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
65145ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
65155ffd83dbSDimitry Andric     if (TheCondStack.back().Ignore) {
65165ffd83dbSDimitry Andric       eatToEndOfStatement();
65175ffd83dbSDimitry Andric       return false;
65185ffd83dbSDimitry Andric     }
65195ffd83dbSDimitry Andric   }
65205ffd83dbSDimitry Andric 
6521e8d8bef9SDimitry Andric   std::string Message = ".err directive invoked in source file";
65225ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::EndOfStatement))
6523e8d8bef9SDimitry Andric     Message = parseStringTo(AsmToken::EndOfStatement);
65245ffd83dbSDimitry Andric   Lex();
65255ffd83dbSDimitry Andric 
65265ffd83dbSDimitry Andric   return Error(DirectiveLoc, Message);
65275ffd83dbSDimitry Andric }
65285ffd83dbSDimitry Andric 
65295ffd83dbSDimitry Andric /// parseDirectiveErrorIfb
65305ffd83dbSDimitry Andric ///   ::= .errb textitem[, message]
65315ffd83dbSDimitry Andric bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
65325ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
65335ffd83dbSDimitry Andric     if (TheCondStack.back().Ignore) {
65345ffd83dbSDimitry Andric       eatToEndOfStatement();
65355ffd83dbSDimitry Andric       return false;
65365ffd83dbSDimitry Andric     }
65375ffd83dbSDimitry Andric   }
65385ffd83dbSDimitry Andric 
65395ffd83dbSDimitry Andric   std::string Text;
65405ffd83dbSDimitry Andric   if (parseTextItem(Text))
65415ffd83dbSDimitry Andric     return Error(getTok().getLoc(), "missing text item in '.errb' directive");
65425ffd83dbSDimitry Andric 
6543e8d8bef9SDimitry Andric   std::string Message = ".errb directive invoked in source file";
65445ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::EndOfStatement)) {
65455ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma))
65465ffd83dbSDimitry Andric       return addErrorSuffix(" in '.errb' directive");
6547e8d8bef9SDimitry Andric     Message = parseStringTo(AsmToken::EndOfStatement);
65485ffd83dbSDimitry Andric   }
65495ffd83dbSDimitry Andric   Lex();
65505ffd83dbSDimitry Andric 
65515ffd83dbSDimitry Andric   if (Text.empty() == ExpectBlank)
65525ffd83dbSDimitry Andric     return Error(DirectiveLoc, Message);
65535ffd83dbSDimitry Andric   return false;
65545ffd83dbSDimitry Andric }
65555ffd83dbSDimitry Andric 
65565ffd83dbSDimitry Andric /// parseDirectiveErrorIfdef
65575ffd83dbSDimitry Andric ///   ::= .errdef name[, message]
65585ffd83dbSDimitry Andric bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
65595ffd83dbSDimitry Andric                                           bool ExpectDefined) {
65605ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
65615ffd83dbSDimitry Andric     if (TheCondStack.back().Ignore) {
65625ffd83dbSDimitry Andric       eatToEndOfStatement();
65635ffd83dbSDimitry Andric       return false;
65645ffd83dbSDimitry Andric     }
65655ffd83dbSDimitry Andric   }
65665ffd83dbSDimitry Andric 
65675ffd83dbSDimitry Andric   bool IsDefined = false;
65685ffd83dbSDimitry Andric   unsigned RegNo;
65695ffd83dbSDimitry Andric   SMLoc StartLoc, EndLoc;
65705ffd83dbSDimitry Andric   IsDefined = (getTargetParser().tryParseRegister(RegNo, StartLoc, EndLoc) ==
65715ffd83dbSDimitry Andric                MatchOperand_Success);
65725ffd83dbSDimitry Andric   if (!IsDefined) {
65735ffd83dbSDimitry Andric     StringRef Name;
65745ffd83dbSDimitry Andric     if (check(parseIdentifier(Name), "expected identifier after '.errdef'"))
65755ffd83dbSDimitry Andric       return true;
65765ffd83dbSDimitry Andric 
6577fe6060f1SDimitry Andric     if (BuiltinSymbolMap.find(Name.lower()) != BuiltinSymbolMap.end()) {
6578fe6060f1SDimitry Andric       IsDefined = true;
6579fe6060f1SDimitry Andric     } else if (Variables.find(Name.lower()) != Variables.end()) {
65805ffd83dbSDimitry Andric       IsDefined = true;
65815ffd83dbSDimitry Andric     } else {
65825ffd83dbSDimitry Andric       MCSymbol *Sym = getContext().lookupSymbol(Name);
65835ffd83dbSDimitry Andric       IsDefined = (Sym && !Sym->isUndefined(false));
65845ffd83dbSDimitry Andric     }
65855ffd83dbSDimitry Andric   }
65865ffd83dbSDimitry Andric 
6587e8d8bef9SDimitry Andric   std::string Message = ".errdef directive invoked in source file";
65885ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::EndOfStatement)) {
65895ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma))
65905ffd83dbSDimitry Andric       return addErrorSuffix(" in '.errdef' directive");
6591e8d8bef9SDimitry Andric     Message = parseStringTo(AsmToken::EndOfStatement);
65925ffd83dbSDimitry Andric   }
65935ffd83dbSDimitry Andric   Lex();
65945ffd83dbSDimitry Andric 
65955ffd83dbSDimitry Andric   if (IsDefined == ExpectDefined)
65965ffd83dbSDimitry Andric     return Error(DirectiveLoc, Message);
65975ffd83dbSDimitry Andric   return false;
65985ffd83dbSDimitry Andric }
65995ffd83dbSDimitry Andric 
66005ffd83dbSDimitry Andric /// parseDirectiveErrorIfidn
6601e8d8bef9SDimitry Andric ///   ::= .erridn textitem, textitem[, message]
66025ffd83dbSDimitry Andric bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
66035ffd83dbSDimitry Andric                                           bool CaseInsensitive) {
66045ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
66055ffd83dbSDimitry Andric     if (TheCondStack.back().Ignore) {
66065ffd83dbSDimitry Andric       eatToEndOfStatement();
66075ffd83dbSDimitry Andric       return false;
66085ffd83dbSDimitry Andric     }
66095ffd83dbSDimitry Andric   }
66105ffd83dbSDimitry Andric 
66115ffd83dbSDimitry Andric   std::string String1, String2;
66125ffd83dbSDimitry Andric 
66135ffd83dbSDimitry Andric   if (parseTextItem(String1)) {
66145ffd83dbSDimitry Andric     if (ExpectEqual)
66155ffd83dbSDimitry Andric       return TokError("expected string parameter for '.erridn' directive");
66165ffd83dbSDimitry Andric     return TokError("expected string parameter for '.errdif' directive");
66175ffd83dbSDimitry Andric   }
66185ffd83dbSDimitry Andric 
66195ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::Comma)) {
66205ffd83dbSDimitry Andric     if (ExpectEqual)
66215ffd83dbSDimitry Andric       return TokError(
66225ffd83dbSDimitry Andric           "expected comma after first string for '.erridn' directive");
66235ffd83dbSDimitry Andric     return TokError(
66245ffd83dbSDimitry Andric         "expected comma after first string for '.errdif' directive");
66255ffd83dbSDimitry Andric   }
66265ffd83dbSDimitry Andric   Lex();
66275ffd83dbSDimitry Andric 
66285ffd83dbSDimitry Andric   if (parseTextItem(String2)) {
66295ffd83dbSDimitry Andric     if (ExpectEqual)
66305ffd83dbSDimitry Andric       return TokError("expected string parameter for '.erridn' directive");
66315ffd83dbSDimitry Andric     return TokError("expected string parameter for '.errdif' directive");
66325ffd83dbSDimitry Andric   }
66335ffd83dbSDimitry Andric 
6634e8d8bef9SDimitry Andric   std::string Message;
66355ffd83dbSDimitry Andric   if (ExpectEqual)
66365ffd83dbSDimitry Andric     Message = ".erridn directive invoked in source file";
66375ffd83dbSDimitry Andric   else
66385ffd83dbSDimitry Andric     Message = ".errdif directive invoked in source file";
66395ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::EndOfStatement)) {
66405ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma))
66415ffd83dbSDimitry Andric       return addErrorSuffix(" in '.erridn' directive");
6642e8d8bef9SDimitry Andric     Message = parseStringTo(AsmToken::EndOfStatement);
66435ffd83dbSDimitry Andric   }
66445ffd83dbSDimitry Andric   Lex();
66455ffd83dbSDimitry Andric 
66465ffd83dbSDimitry Andric   if (CaseInsensitive)
66475ffd83dbSDimitry Andric     TheCondState.CondMet =
6648fe6060f1SDimitry Andric         ExpectEqual == (StringRef(String1).equals_insensitive(String2));
66495ffd83dbSDimitry Andric   else
66505ffd83dbSDimitry Andric     TheCondState.CondMet = ExpectEqual == (String1 == String2);
66515ffd83dbSDimitry Andric   TheCondState.Ignore = !TheCondState.CondMet;
66525ffd83dbSDimitry Andric 
66535ffd83dbSDimitry Andric   if ((CaseInsensitive &&
6654fe6060f1SDimitry Andric        ExpectEqual == StringRef(String1).equals_insensitive(String2)) ||
66555ffd83dbSDimitry Andric       (ExpectEqual == (String1 == String2)))
66565ffd83dbSDimitry Andric     return Error(DirectiveLoc, Message);
66575ffd83dbSDimitry Andric   return false;
66585ffd83dbSDimitry Andric }
66595ffd83dbSDimitry Andric 
66605ffd83dbSDimitry Andric /// parseDirectiveErrorIfe
66615ffd83dbSDimitry Andric ///   ::= .erre expression[, message]
66625ffd83dbSDimitry Andric bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero) {
66635ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
66645ffd83dbSDimitry Andric     if (TheCondStack.back().Ignore) {
66655ffd83dbSDimitry Andric       eatToEndOfStatement();
66665ffd83dbSDimitry Andric       return false;
66675ffd83dbSDimitry Andric     }
66685ffd83dbSDimitry Andric   }
66695ffd83dbSDimitry Andric 
66705ffd83dbSDimitry Andric   int64_t ExprValue;
66715ffd83dbSDimitry Andric   if (parseAbsoluteExpression(ExprValue))
66725ffd83dbSDimitry Andric     return addErrorSuffix(" in '.erre' directive");
66735ffd83dbSDimitry Andric 
6674e8d8bef9SDimitry Andric   std::string Message = ".erre directive invoked in source file";
66755ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::EndOfStatement)) {
66765ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma))
66775ffd83dbSDimitry Andric       return addErrorSuffix(" in '.erre' directive");
6678e8d8bef9SDimitry Andric     Message = parseStringTo(AsmToken::EndOfStatement);
66795ffd83dbSDimitry Andric   }
66805ffd83dbSDimitry Andric   Lex();
66815ffd83dbSDimitry Andric 
66825ffd83dbSDimitry Andric   if ((ExprValue == 0) == ExpectZero)
66835ffd83dbSDimitry Andric     return Error(DirectiveLoc, Message);
66845ffd83dbSDimitry Andric   return false;
66855ffd83dbSDimitry Andric }
66865ffd83dbSDimitry Andric 
66875ffd83dbSDimitry Andric /// parseDirectiveEndIf
66885ffd83dbSDimitry Andric /// ::= .endif
66895ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
66905ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement,
66915ffd83dbSDimitry Andric                  "unexpected token in '.endif' directive"))
66925ffd83dbSDimitry Andric     return true;
66935ffd83dbSDimitry Andric 
66945ffd83dbSDimitry Andric   if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
66955ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
66965ffd83dbSDimitry Andric                                "an .if or .else");
66975ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
66985ffd83dbSDimitry Andric     TheCondState = TheCondStack.back();
66995ffd83dbSDimitry Andric     TheCondStack.pop_back();
67005ffd83dbSDimitry Andric   }
67015ffd83dbSDimitry Andric 
67025ffd83dbSDimitry Andric   return false;
67035ffd83dbSDimitry Andric }
67045ffd83dbSDimitry Andric 
67055ffd83dbSDimitry Andric void MasmParser::initializeDirectiveKindMap() {
67065ffd83dbSDimitry Andric   DirectiveKindMap["="] = DK_ASSIGN;
67075ffd83dbSDimitry Andric   DirectiveKindMap["equ"] = DK_EQU;
67085ffd83dbSDimitry Andric   DirectiveKindMap["textequ"] = DK_TEXTEQU;
67095ffd83dbSDimitry Andric   // DirectiveKindMap[".ascii"] = DK_ASCII;
67105ffd83dbSDimitry Andric   // DirectiveKindMap[".asciz"] = DK_ASCIZ;
67115ffd83dbSDimitry Andric   // DirectiveKindMap[".string"] = DK_STRING;
67125ffd83dbSDimitry Andric   DirectiveKindMap["byte"] = DK_BYTE;
67135ffd83dbSDimitry Andric   DirectiveKindMap["sbyte"] = DK_SBYTE;
67145ffd83dbSDimitry Andric   DirectiveKindMap["word"] = DK_WORD;
67155ffd83dbSDimitry Andric   DirectiveKindMap["sword"] = DK_SWORD;
67165ffd83dbSDimitry Andric   DirectiveKindMap["dword"] = DK_DWORD;
67175ffd83dbSDimitry Andric   DirectiveKindMap["sdword"] = DK_SDWORD;
67185ffd83dbSDimitry Andric   DirectiveKindMap["fword"] = DK_FWORD;
67195ffd83dbSDimitry Andric   DirectiveKindMap["qword"] = DK_QWORD;
67205ffd83dbSDimitry Andric   DirectiveKindMap["sqword"] = DK_SQWORD;
67215ffd83dbSDimitry Andric   DirectiveKindMap["real4"] = DK_REAL4;
67225ffd83dbSDimitry Andric   DirectiveKindMap["real8"] = DK_REAL8;
6723e8d8bef9SDimitry Andric   DirectiveKindMap["real10"] = DK_REAL10;
67245ffd83dbSDimitry Andric   DirectiveKindMap["align"] = DK_ALIGN;
6725fe6060f1SDimitry Andric   DirectiveKindMap["even"] = DK_EVEN;
6726fe6060f1SDimitry Andric   DirectiveKindMap["org"] = DK_ORG;
67275ffd83dbSDimitry Andric   DirectiveKindMap["extern"] = DK_EXTERN;
67285ffd83dbSDimitry Andric   DirectiveKindMap["public"] = DK_PUBLIC;
67295ffd83dbSDimitry Andric   // DirectiveKindMap[".comm"] = DK_COMM;
67305ffd83dbSDimitry Andric   DirectiveKindMap["comment"] = DK_COMMENT;
67315ffd83dbSDimitry Andric   DirectiveKindMap["include"] = DK_INCLUDE;
6732e8d8bef9SDimitry Andric   DirectiveKindMap["repeat"] = DK_REPEAT;
6733e8d8bef9SDimitry Andric   DirectiveKindMap["rept"] = DK_REPEAT;
6734e8d8bef9SDimitry Andric   DirectiveKindMap["while"] = DK_WHILE;
6735e8d8bef9SDimitry Andric   DirectiveKindMap["for"] = DK_FOR;
6736e8d8bef9SDimitry Andric   DirectiveKindMap["irp"] = DK_FOR;
6737e8d8bef9SDimitry Andric   DirectiveKindMap["forc"] = DK_FORC;
6738e8d8bef9SDimitry Andric   DirectiveKindMap["irpc"] = DK_FORC;
67395ffd83dbSDimitry Andric   DirectiveKindMap["if"] = DK_IF;
67405ffd83dbSDimitry Andric   DirectiveKindMap["ife"] = DK_IFE;
67415ffd83dbSDimitry Andric   DirectiveKindMap["ifb"] = DK_IFB;
67425ffd83dbSDimitry Andric   DirectiveKindMap["ifnb"] = DK_IFNB;
67435ffd83dbSDimitry Andric   DirectiveKindMap["ifdef"] = DK_IFDEF;
67445ffd83dbSDimitry Andric   DirectiveKindMap["ifndef"] = DK_IFNDEF;
67455ffd83dbSDimitry Andric   DirectiveKindMap["ifdif"] = DK_IFDIF;
67465ffd83dbSDimitry Andric   DirectiveKindMap["ifdifi"] = DK_IFDIFI;
67475ffd83dbSDimitry Andric   DirectiveKindMap["ifidn"] = DK_IFIDN;
67485ffd83dbSDimitry Andric   DirectiveKindMap["ifidni"] = DK_IFIDNI;
67495ffd83dbSDimitry Andric   DirectiveKindMap["elseif"] = DK_ELSEIF;
67505ffd83dbSDimitry Andric   DirectiveKindMap["elseifdef"] = DK_ELSEIFDEF;
67515ffd83dbSDimitry Andric   DirectiveKindMap["elseifndef"] = DK_ELSEIFNDEF;
67525ffd83dbSDimitry Andric   DirectiveKindMap["elseifdif"] = DK_ELSEIFDIF;
67535ffd83dbSDimitry Andric   DirectiveKindMap["elseifidn"] = DK_ELSEIFIDN;
67545ffd83dbSDimitry Andric   DirectiveKindMap["else"] = DK_ELSE;
67555ffd83dbSDimitry Andric   DirectiveKindMap["end"] = DK_END;
67565ffd83dbSDimitry Andric   DirectiveKindMap["endif"] = DK_ENDIF;
67575ffd83dbSDimitry Andric   // DirectiveKindMap[".file"] = DK_FILE;
67585ffd83dbSDimitry Andric   // DirectiveKindMap[".line"] = DK_LINE;
67595ffd83dbSDimitry Andric   // DirectiveKindMap[".loc"] = DK_LOC;
67605ffd83dbSDimitry Andric   // DirectiveKindMap[".stabs"] = DK_STABS;
67615ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_file"] = DK_CV_FILE;
67625ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
67635ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
67645ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
67655ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
67665ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
67675ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
67685ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_string"] = DK_CV_STRING;
67695ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
67705ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
67715ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
67725ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
67735ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
67745ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
67755ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
67765ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
67775ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
67785ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
67795ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
67805ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
67815ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
67825ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
67835ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
67845ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
67855ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
67865ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
67875ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
67885ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
67895ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
67905ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
67915ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
67925ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
67935ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
67945ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
6795e8d8bef9SDimitry Andric   DirectiveKindMap["macro"] = DK_MACRO;
6796e8d8bef9SDimitry Andric   DirectiveKindMap["exitm"] = DK_EXITM;
6797e8d8bef9SDimitry Andric   DirectiveKindMap["endm"] = DK_ENDM;
6798e8d8bef9SDimitry Andric   DirectiveKindMap["purge"] = DK_PURGE;
67995ffd83dbSDimitry Andric   DirectiveKindMap[".err"] = DK_ERR;
68005ffd83dbSDimitry Andric   DirectiveKindMap[".errb"] = DK_ERRB;
68015ffd83dbSDimitry Andric   DirectiveKindMap[".errnb"] = DK_ERRNB;
68025ffd83dbSDimitry Andric   DirectiveKindMap[".errdef"] = DK_ERRDEF;
68035ffd83dbSDimitry Andric   DirectiveKindMap[".errndef"] = DK_ERRNDEF;
68045ffd83dbSDimitry Andric   DirectiveKindMap[".errdif"] = DK_ERRDIF;
68055ffd83dbSDimitry Andric   DirectiveKindMap[".errdifi"] = DK_ERRDIFI;
68065ffd83dbSDimitry Andric   DirectiveKindMap[".erridn"] = DK_ERRIDN;
68075ffd83dbSDimitry Andric   DirectiveKindMap[".erridni"] = DK_ERRIDNI;
68085ffd83dbSDimitry Andric   DirectiveKindMap[".erre"] = DK_ERRE;
68095ffd83dbSDimitry Andric   DirectiveKindMap[".errnz"] = DK_ERRNZ;
6810e8d8bef9SDimitry Andric   DirectiveKindMap[".pushframe"] = DK_PUSHFRAME;
6811e8d8bef9SDimitry Andric   DirectiveKindMap[".pushreg"] = DK_PUSHREG;
6812e8d8bef9SDimitry Andric   DirectiveKindMap[".savereg"] = DK_SAVEREG;
6813e8d8bef9SDimitry Andric   DirectiveKindMap[".savexmm128"] = DK_SAVEXMM128;
6814e8d8bef9SDimitry Andric   DirectiveKindMap[".setframe"] = DK_SETFRAME;
6815e8d8bef9SDimitry Andric   DirectiveKindMap[".radix"] = DK_RADIX;
68165ffd83dbSDimitry Andric   DirectiveKindMap["db"] = DK_DB;
68175ffd83dbSDimitry Andric   DirectiveKindMap["dd"] = DK_DD;
6818e8d8bef9SDimitry Andric   DirectiveKindMap["df"] = DK_DF;
68195ffd83dbSDimitry Andric   DirectiveKindMap["dq"] = DK_DQ;
68205ffd83dbSDimitry Andric   DirectiveKindMap["dw"] = DK_DW;
68215ffd83dbSDimitry Andric   DirectiveKindMap["echo"] = DK_ECHO;
68225ffd83dbSDimitry Andric   DirectiveKindMap["struc"] = DK_STRUCT;
68235ffd83dbSDimitry Andric   DirectiveKindMap["struct"] = DK_STRUCT;
68245ffd83dbSDimitry Andric   DirectiveKindMap["union"] = DK_UNION;
68255ffd83dbSDimitry Andric   DirectiveKindMap["ends"] = DK_ENDS;
68265ffd83dbSDimitry Andric }
68275ffd83dbSDimitry Andric 
6828e8d8bef9SDimitry Andric bool MasmParser::isMacroLikeDirective() {
6829e8d8bef9SDimitry Andric   if (getLexer().is(AsmToken::Identifier)) {
6830e8d8bef9SDimitry Andric     bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier())
6831e8d8bef9SDimitry Andric                            .CasesLower("repeat", "rept", true)
6832e8d8bef9SDimitry Andric                            .CaseLower("while", true)
6833e8d8bef9SDimitry Andric                            .CasesLower("for", "irp", true)
6834e8d8bef9SDimitry Andric                            .CasesLower("forc", "irpc", true)
6835e8d8bef9SDimitry Andric                            .Default(false);
6836e8d8bef9SDimitry Andric     if (IsMacroLike)
6837e8d8bef9SDimitry Andric       return true;
6838e8d8bef9SDimitry Andric   }
6839fe6060f1SDimitry Andric   if (peekTok().is(AsmToken::Identifier) &&
6840fe6060f1SDimitry Andric       peekTok().getIdentifier().equals_insensitive("macro"))
6841e8d8bef9SDimitry Andric     return true;
6842e8d8bef9SDimitry Andric 
6843e8d8bef9SDimitry Andric   return false;
6844e8d8bef9SDimitry Andric }
6845e8d8bef9SDimitry Andric 
68465ffd83dbSDimitry Andric MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
68475ffd83dbSDimitry Andric   AsmToken EndToken, StartToken = getTok();
68485ffd83dbSDimitry Andric 
68495ffd83dbSDimitry Andric   unsigned NestLevel = 0;
68505ffd83dbSDimitry Andric   while (true) {
68515ffd83dbSDimitry Andric     // Check whether we have reached the end of the file.
68525ffd83dbSDimitry Andric     if (getLexer().is(AsmToken::Eof)) {
6853e8d8bef9SDimitry Andric       printError(DirectiveLoc, "no matching 'endm' in definition");
68545ffd83dbSDimitry Andric       return nullptr;
68555ffd83dbSDimitry Andric     }
68565ffd83dbSDimitry Andric 
6857e8d8bef9SDimitry Andric     if (isMacroLikeDirective())
68585ffd83dbSDimitry Andric       ++NestLevel;
68595ffd83dbSDimitry Andric 
6860e8d8bef9SDimitry Andric     // Otherwise, check whether we have reached the endm.
6861e8d8bef9SDimitry Andric     if (Lexer.is(AsmToken::Identifier) &&
6862fe6060f1SDimitry Andric         getTok().getIdentifier().equals_insensitive("endm")) {
68635ffd83dbSDimitry Andric       if (NestLevel == 0) {
68645ffd83dbSDimitry Andric         EndToken = getTok();
68655ffd83dbSDimitry Andric         Lex();
68665ffd83dbSDimitry Andric         if (Lexer.isNot(AsmToken::EndOfStatement)) {
6867e8d8bef9SDimitry Andric           printError(getTok().getLoc(), "unexpected token in 'endm' directive");
68685ffd83dbSDimitry Andric           return nullptr;
68695ffd83dbSDimitry Andric         }
68705ffd83dbSDimitry Andric         break;
68715ffd83dbSDimitry Andric       }
68725ffd83dbSDimitry Andric       --NestLevel;
68735ffd83dbSDimitry Andric     }
68745ffd83dbSDimitry Andric 
68755ffd83dbSDimitry Andric     // Otherwise, scan till the end of the statement.
68765ffd83dbSDimitry Andric     eatToEndOfStatement();
68775ffd83dbSDimitry Andric   }
68785ffd83dbSDimitry Andric 
68795ffd83dbSDimitry Andric   const char *BodyStart = StartToken.getLoc().getPointer();
68805ffd83dbSDimitry Andric   const char *BodyEnd = EndToken.getLoc().getPointer();
68815ffd83dbSDimitry Andric   StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
68825ffd83dbSDimitry Andric 
68835ffd83dbSDimitry Andric   // We Are Anonymous.
68845ffd83dbSDimitry Andric   MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
68855ffd83dbSDimitry Andric   return &MacroLikeBodies.back();
68865ffd83dbSDimitry Andric }
68875ffd83dbSDimitry Andric 
6888e8d8bef9SDimitry Andric bool MasmParser::expandStatement(SMLoc Loc) {
6889e8d8bef9SDimitry Andric   std::string Body = parseStringTo(AsmToken::EndOfStatement);
6890e8d8bef9SDimitry Andric   SMLoc EndLoc = getTok().getLoc();
6891e8d8bef9SDimitry Andric 
6892e8d8bef9SDimitry Andric   MCAsmMacroParameters Parameters;
6893e8d8bef9SDimitry Andric   MCAsmMacroArguments Arguments;
6894fe6060f1SDimitry Andric 
6895fe6060f1SDimitry Andric   StringMap<std::string> BuiltinValues;
6896fe6060f1SDimitry Andric   for (const auto &S : BuiltinSymbolMap) {
6897fe6060f1SDimitry Andric     const BuiltinSymbol &Sym = S.getValue();
6898fe6060f1SDimitry Andric     if (llvm::Optional<std::string> Text = evaluateBuiltinTextMacro(Sym, Loc)) {
6899fe6060f1SDimitry Andric       BuiltinValues[S.getKey().lower()] = std::move(*Text);
6900fe6060f1SDimitry Andric     }
6901fe6060f1SDimitry Andric   }
6902fe6060f1SDimitry Andric   for (const auto &B : BuiltinValues) {
6903fe6060f1SDimitry Andric     MCAsmMacroParameter P;
6904fe6060f1SDimitry Andric     MCAsmMacroArgument A;
6905fe6060f1SDimitry Andric     P.Name = B.getKey();
6906fe6060f1SDimitry Andric     P.Required = true;
6907fe6060f1SDimitry Andric     A.push_back(AsmToken(AsmToken::String, B.getValue()));
6908fe6060f1SDimitry Andric 
6909fe6060f1SDimitry Andric     Parameters.push_back(std::move(P));
6910fe6060f1SDimitry Andric     Arguments.push_back(std::move(A));
6911fe6060f1SDimitry Andric   }
6912fe6060f1SDimitry Andric 
6913e8d8bef9SDimitry Andric   for (const auto &V : Variables) {
6914e8d8bef9SDimitry Andric     const Variable &Var = V.getValue();
6915e8d8bef9SDimitry Andric     if (Var.IsText) {
6916fe6060f1SDimitry Andric       MCAsmMacroParameter P;
6917fe6060f1SDimitry Andric       MCAsmMacroArgument A;
6918e8d8bef9SDimitry Andric       P.Name = Var.Name;
6919e8d8bef9SDimitry Andric       P.Required = true;
6920e8d8bef9SDimitry Andric       A.push_back(AsmToken(AsmToken::String, Var.TextValue));
6921fe6060f1SDimitry Andric 
6922fe6060f1SDimitry Andric       Parameters.push_back(std::move(P));
6923fe6060f1SDimitry Andric       Arguments.push_back(std::move(A));
6924e8d8bef9SDimitry Andric     }
6925e8d8bef9SDimitry Andric   }
6926e8d8bef9SDimitry Andric   MacroLikeBodies.emplace_back(StringRef(), Body, Parameters);
6927e8d8bef9SDimitry Andric   MCAsmMacro M = MacroLikeBodies.back();
6928e8d8bef9SDimitry Andric 
6929e8d8bef9SDimitry Andric   // Expand the statement in a new buffer.
6930e8d8bef9SDimitry Andric   SmallString<80> Buf;
6931e8d8bef9SDimitry Andric   raw_svector_ostream OS(Buf);
6932e8d8bef9SDimitry Andric   if (expandMacro(OS, M.Body, M.Parameters, Arguments, M.Locals, EndLoc))
6933e8d8bef9SDimitry Andric     return true;
6934e8d8bef9SDimitry Andric   std::unique_ptr<MemoryBuffer> Expansion =
6935e8d8bef9SDimitry Andric       MemoryBuffer::getMemBufferCopy(OS.str(), "<expansion>");
6936e8d8bef9SDimitry Andric 
6937e8d8bef9SDimitry Andric   // Jump to the expanded statement and prime the lexer.
6938e8d8bef9SDimitry Andric   CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Expansion), EndLoc);
6939e8d8bef9SDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
6940e8d8bef9SDimitry Andric   EndStatementAtEOFStack.push_back(false);
6941e8d8bef9SDimitry Andric   Lex();
6942e8d8bef9SDimitry Andric   return false;
6943e8d8bef9SDimitry Andric }
6944e8d8bef9SDimitry Andric 
69455ffd83dbSDimitry Andric void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
69465ffd83dbSDimitry Andric                                           raw_svector_ostream &OS) {
6947e8d8bef9SDimitry Andric   instantiateMacroLikeBody(M, DirectiveLoc, /*ExitLoc=*/getTok().getLoc(), OS);
6948e8d8bef9SDimitry Andric }
6949e8d8bef9SDimitry Andric void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
6950e8d8bef9SDimitry Andric                                           SMLoc ExitLoc,
6951e8d8bef9SDimitry Andric                                           raw_svector_ostream &OS) {
6952e8d8bef9SDimitry Andric   OS << "endm\n";
69535ffd83dbSDimitry Andric 
69545ffd83dbSDimitry Andric   std::unique_ptr<MemoryBuffer> Instantiation =
69555ffd83dbSDimitry Andric       MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
69565ffd83dbSDimitry Andric 
69575ffd83dbSDimitry Andric   // Create the macro instantiation object and add to the current macro
69585ffd83dbSDimitry Andric   // instantiation stack.
6959e8d8bef9SDimitry Andric   MacroInstantiation *MI = new MacroInstantiation{DirectiveLoc, CurBuffer,
6960e8d8bef9SDimitry Andric                                                   ExitLoc, TheCondStack.size()};
69615ffd83dbSDimitry Andric   ActiveMacros.push_back(MI);
69625ffd83dbSDimitry Andric 
69635ffd83dbSDimitry Andric   // Jump to the macro instantiation and prime the lexer.
69645ffd83dbSDimitry Andric   CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
69655ffd83dbSDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
6966e8d8bef9SDimitry Andric   EndStatementAtEOFStack.push_back(true);
69675ffd83dbSDimitry Andric   Lex();
69685ffd83dbSDimitry Andric }
69695ffd83dbSDimitry Andric 
6970e8d8bef9SDimitry Andric /// parseDirectiveRepeat
6971e8d8bef9SDimitry Andric ///   ::= ("repeat" | "rept") count
6972e8d8bef9SDimitry Andric ///       body
6973e8d8bef9SDimitry Andric ///     endm
6974e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) {
69755ffd83dbSDimitry Andric   const MCExpr *CountExpr;
69765ffd83dbSDimitry Andric   SMLoc CountLoc = getTok().getLoc();
69775ffd83dbSDimitry Andric   if (parseExpression(CountExpr))
69785ffd83dbSDimitry Andric     return true;
69795ffd83dbSDimitry Andric 
69805ffd83dbSDimitry Andric   int64_t Count;
69815ffd83dbSDimitry Andric   if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
69825ffd83dbSDimitry Andric     return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
69835ffd83dbSDimitry Andric   }
69845ffd83dbSDimitry Andric 
69855ffd83dbSDimitry Andric   if (check(Count < 0, CountLoc, "Count is negative") ||
69865ffd83dbSDimitry Andric       parseToken(AsmToken::EndOfStatement,
69875ffd83dbSDimitry Andric                  "unexpected token in '" + Dir + "' directive"))
69885ffd83dbSDimitry Andric     return true;
69895ffd83dbSDimitry Andric 
6990e8d8bef9SDimitry Andric   // Lex the repeat definition.
69915ffd83dbSDimitry Andric   MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
69925ffd83dbSDimitry Andric   if (!M)
69935ffd83dbSDimitry Andric     return true;
69945ffd83dbSDimitry Andric 
69955ffd83dbSDimitry Andric   // Macro instantiation is lexical, unfortunately. We construct a new buffer
69965ffd83dbSDimitry Andric   // to hold the macro body with substitutions.
69975ffd83dbSDimitry Andric   SmallString<256> Buf;
69985ffd83dbSDimitry Andric   raw_svector_ostream OS(Buf);
69995ffd83dbSDimitry Andric   while (Count--) {
7000e8d8bef9SDimitry Andric     if (expandMacro(OS, M->Body, None, None, M->Locals, getTok().getLoc()))
70015ffd83dbSDimitry Andric       return true;
70025ffd83dbSDimitry Andric   }
70035ffd83dbSDimitry Andric   instantiateMacroLikeBody(M, DirectiveLoc, OS);
70045ffd83dbSDimitry Andric 
70055ffd83dbSDimitry Andric   return false;
70065ffd83dbSDimitry Andric }
70075ffd83dbSDimitry Andric 
7008e8d8bef9SDimitry Andric /// parseDirectiveWhile
7009e8d8bef9SDimitry Andric /// ::= "while" expression
7010e8d8bef9SDimitry Andric ///       body
7011e8d8bef9SDimitry Andric ///     endm
7012e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) {
7013e8d8bef9SDimitry Andric   const MCExpr *CondExpr;
7014e8d8bef9SDimitry Andric   SMLoc CondLoc = getTok().getLoc();
7015e8d8bef9SDimitry Andric   if (parseExpression(CondExpr))
7016e8d8bef9SDimitry Andric     return true;
7017e8d8bef9SDimitry Andric 
7018e8d8bef9SDimitry Andric   // Lex the repeat definition.
7019e8d8bef9SDimitry Andric   MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
7020e8d8bef9SDimitry Andric   if (!M)
7021e8d8bef9SDimitry Andric     return true;
7022e8d8bef9SDimitry Andric 
7023e8d8bef9SDimitry Andric   // Macro instantiation is lexical, unfortunately. We construct a new buffer
7024e8d8bef9SDimitry Andric   // to hold the macro body with substitutions.
7025e8d8bef9SDimitry Andric   SmallString<256> Buf;
7026e8d8bef9SDimitry Andric   raw_svector_ostream OS(Buf);
7027e8d8bef9SDimitry Andric   int64_t Condition;
7028e8d8bef9SDimitry Andric   if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr()))
7029e8d8bef9SDimitry Andric     return Error(CondLoc, "expected absolute expression in 'while' directive");
7030e8d8bef9SDimitry Andric   if (Condition) {
7031e8d8bef9SDimitry Andric     // Instantiate the macro, then resume at this directive to recheck the
7032e8d8bef9SDimitry Andric     // condition.
7033e8d8bef9SDimitry Andric     if (expandMacro(OS, M->Body, None, None, M->Locals, getTok().getLoc()))
7034e8d8bef9SDimitry Andric       return true;
7035e8d8bef9SDimitry Andric     instantiateMacroLikeBody(M, DirectiveLoc, /*ExitLoc=*/DirectiveLoc, OS);
7036e8d8bef9SDimitry Andric   }
7037e8d8bef9SDimitry Andric 
7038e8d8bef9SDimitry Andric   return false;
7039e8d8bef9SDimitry Andric }
7040e8d8bef9SDimitry Andric 
7041e8d8bef9SDimitry Andric /// parseDirectiveFor
7042e8d8bef9SDimitry Andric /// ::= ("for" | "irp") symbol [":" qualifier], <values>
7043e8d8bef9SDimitry Andric ///       body
7044e8d8bef9SDimitry Andric ///     endm
7045e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
70465ffd83dbSDimitry Andric   MCAsmMacroParameter Parameter;
70475ffd83dbSDimitry Andric   MCAsmMacroArguments A;
70485ffd83dbSDimitry Andric   if (check(parseIdentifier(Parameter.Name),
7049e8d8bef9SDimitry Andric             "expected identifier in '" + Dir + "' directive"))
7050e8d8bef9SDimitry Andric     return true;
7051e8d8bef9SDimitry Andric 
7052e8d8bef9SDimitry Andric   // Parse optional qualifier (default value, or "req")
7053e8d8bef9SDimitry Andric   if (parseOptionalToken(AsmToken::Colon)) {
7054e8d8bef9SDimitry Andric     if (parseOptionalToken(AsmToken::Equal)) {
7055e8d8bef9SDimitry Andric       // Default value
7056e8d8bef9SDimitry Andric       SMLoc ParamLoc;
7057e8d8bef9SDimitry Andric 
7058e8d8bef9SDimitry Andric       ParamLoc = Lexer.getLoc();
7059e8d8bef9SDimitry Andric       if (parseMacroArgument(nullptr, Parameter.Value))
7060e8d8bef9SDimitry Andric         return true;
7061e8d8bef9SDimitry Andric     } else {
7062e8d8bef9SDimitry Andric       SMLoc QualLoc;
7063e8d8bef9SDimitry Andric       StringRef Qualifier;
7064e8d8bef9SDimitry Andric 
7065e8d8bef9SDimitry Andric       QualLoc = Lexer.getLoc();
7066e8d8bef9SDimitry Andric       if (parseIdentifier(Qualifier))
7067e8d8bef9SDimitry Andric         return Error(QualLoc, "missing parameter qualifier for "
7068e8d8bef9SDimitry Andric                               "'" +
7069e8d8bef9SDimitry Andric                                   Parameter.Name + "' in '" + Dir +
7070e8d8bef9SDimitry Andric                                   "' directive");
7071e8d8bef9SDimitry Andric 
7072fe6060f1SDimitry Andric       if (Qualifier.equals_insensitive("req"))
7073e8d8bef9SDimitry Andric         Parameter.Required = true;
7074e8d8bef9SDimitry Andric       else
7075e8d8bef9SDimitry Andric         return Error(QualLoc,
7076e8d8bef9SDimitry Andric                      Qualifier + " is not a valid parameter qualifier for '" +
7077e8d8bef9SDimitry Andric                          Parameter.Name + "' in '" + Dir + "' directive");
7078e8d8bef9SDimitry Andric     }
7079e8d8bef9SDimitry Andric   }
7080e8d8bef9SDimitry Andric 
7081e8d8bef9SDimitry Andric   if (parseToken(AsmToken::Comma,
7082e8d8bef9SDimitry Andric                  "expected comma in '" + Dir + "' directive") ||
7083e8d8bef9SDimitry Andric       parseToken(AsmToken::Less,
7084e8d8bef9SDimitry Andric                  "values in '" + Dir +
7085e8d8bef9SDimitry Andric                      "' directive must be enclosed in angle brackets"))
7086e8d8bef9SDimitry Andric     return true;
7087e8d8bef9SDimitry Andric 
7088e8d8bef9SDimitry Andric   while (true) {
7089e8d8bef9SDimitry Andric     A.emplace_back();
7090e8d8bef9SDimitry Andric     if (parseMacroArgument(&Parameter, A.back(), /*EndTok=*/AsmToken::Greater))
7091e8d8bef9SDimitry Andric       return addErrorSuffix(" in arguments for '" + Dir + "' directive");
7092e8d8bef9SDimitry Andric 
7093e8d8bef9SDimitry Andric     // If we see a comma, continue, and allow line continuation.
7094e8d8bef9SDimitry Andric     if (!parseOptionalToken(AsmToken::Comma))
7095e8d8bef9SDimitry Andric       break;
7096e8d8bef9SDimitry Andric     parseOptionalToken(AsmToken::EndOfStatement);
7097e8d8bef9SDimitry Andric   }
7098e8d8bef9SDimitry Andric 
7099e8d8bef9SDimitry Andric   if (parseToken(AsmToken::Greater,
7100e8d8bef9SDimitry Andric                  "values in '" + Dir +
7101e8d8bef9SDimitry Andric                      "' directive must be enclosed in angle brackets") ||
71025ffd83dbSDimitry Andric       parseToken(AsmToken::EndOfStatement, "expected End of Statement"))
71035ffd83dbSDimitry Andric     return true;
71045ffd83dbSDimitry Andric 
7105e8d8bef9SDimitry Andric   // Lex the for definition.
71065ffd83dbSDimitry Andric   MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
71075ffd83dbSDimitry Andric   if (!M)
71085ffd83dbSDimitry Andric     return true;
71095ffd83dbSDimitry Andric 
71105ffd83dbSDimitry Andric   // Macro instantiation is lexical, unfortunately. We construct a new buffer
71115ffd83dbSDimitry Andric   // to hold the macro body with substitutions.
71125ffd83dbSDimitry Andric   SmallString<256> Buf;
71135ffd83dbSDimitry Andric   raw_svector_ostream OS(Buf);
71145ffd83dbSDimitry Andric 
71155ffd83dbSDimitry Andric   for (const MCAsmMacroArgument &Arg : A) {
7116e8d8bef9SDimitry Andric     if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc()))
71175ffd83dbSDimitry Andric       return true;
71185ffd83dbSDimitry Andric   }
71195ffd83dbSDimitry Andric 
71205ffd83dbSDimitry Andric   instantiateMacroLikeBody(M, DirectiveLoc, OS);
71215ffd83dbSDimitry Andric 
71225ffd83dbSDimitry Andric   return false;
71235ffd83dbSDimitry Andric }
71245ffd83dbSDimitry Andric 
7125e8d8bef9SDimitry Andric /// parseDirectiveForc
7126e8d8bef9SDimitry Andric /// ::= ("forc" | "irpc") symbol, <string>
7127e8d8bef9SDimitry Andric ///       body
7128e8d8bef9SDimitry Andric ///     endm
7129e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
71305ffd83dbSDimitry Andric   MCAsmMacroParameter Parameter;
71315ffd83dbSDimitry Andric 
7132e8d8bef9SDimitry Andric   std::string Argument;
71335ffd83dbSDimitry Andric   if (check(parseIdentifier(Parameter.Name),
7134e8d8bef9SDimitry Andric             "expected identifier in '" + Directive + "' directive") ||
7135e8d8bef9SDimitry Andric       parseToken(AsmToken::Comma,
7136e8d8bef9SDimitry Andric                  "expected comma in '" + Directive + "' directive"))
71375ffd83dbSDimitry Andric     return true;
7138e8d8bef9SDimitry Andric   if (parseAngleBracketString(Argument)) {
7139e8d8bef9SDimitry Andric     // Match ml64.exe; treat all characters to end of statement as a string,
7140e8d8bef9SDimitry Andric     // ignoring comment markers, then discard anything following a space (using
7141e8d8bef9SDimitry Andric     // the C locale).
7142e8d8bef9SDimitry Andric     Argument = parseStringTo(AsmToken::EndOfStatement);
7143e8d8bef9SDimitry Andric     if (getTok().is(AsmToken::EndOfStatement))
7144e8d8bef9SDimitry Andric       Argument += getTok().getString();
7145e8d8bef9SDimitry Andric     size_t End = 0;
7146e8d8bef9SDimitry Andric     for (; End < Argument.size(); ++End) {
7147e8d8bef9SDimitry Andric       if (isSpace(Argument[End]))
7148e8d8bef9SDimitry Andric         break;
7149e8d8bef9SDimitry Andric     }
7150e8d8bef9SDimitry Andric     Argument.resize(End);
7151e8d8bef9SDimitry Andric   }
71525ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement, "expected end of statement"))
71535ffd83dbSDimitry Andric     return true;
71545ffd83dbSDimitry Andric 
71555ffd83dbSDimitry Andric   // Lex the irpc definition.
71565ffd83dbSDimitry Andric   MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
71575ffd83dbSDimitry Andric   if (!M)
71585ffd83dbSDimitry Andric     return true;
71595ffd83dbSDimitry Andric 
71605ffd83dbSDimitry Andric   // Macro instantiation is lexical, unfortunately. We construct a new buffer
71615ffd83dbSDimitry Andric   // to hold the macro body with substitutions.
71625ffd83dbSDimitry Andric   SmallString<256> Buf;
71635ffd83dbSDimitry Andric   raw_svector_ostream OS(Buf);
71645ffd83dbSDimitry Andric 
7165e8d8bef9SDimitry Andric   StringRef Values(Argument);
71665ffd83dbSDimitry Andric   for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
71675ffd83dbSDimitry Andric     MCAsmMacroArgument Arg;
71685ffd83dbSDimitry Andric     Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1));
71695ffd83dbSDimitry Andric 
7170e8d8bef9SDimitry Andric     if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc()))
71715ffd83dbSDimitry Andric       return true;
71725ffd83dbSDimitry Andric   }
71735ffd83dbSDimitry Andric 
71745ffd83dbSDimitry Andric   instantiateMacroLikeBody(M, DirectiveLoc, OS);
71755ffd83dbSDimitry Andric 
71765ffd83dbSDimitry Andric   return false;
71775ffd83dbSDimitry Andric }
71785ffd83dbSDimitry Andric 
71795ffd83dbSDimitry Andric bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
71805ffd83dbSDimitry Andric                                       size_t Len) {
71815ffd83dbSDimitry Andric   const MCExpr *Value;
71825ffd83dbSDimitry Andric   SMLoc ExprLoc = getLexer().getLoc();
71835ffd83dbSDimitry Andric   if (parseExpression(Value))
71845ffd83dbSDimitry Andric     return true;
71855ffd83dbSDimitry Andric   const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
71865ffd83dbSDimitry Andric   if (!MCE)
71875ffd83dbSDimitry Andric     return Error(ExprLoc, "unexpected expression in _emit");
71885ffd83dbSDimitry Andric   uint64_t IntValue = MCE->getValue();
71895ffd83dbSDimitry Andric   if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
71905ffd83dbSDimitry Andric     return Error(ExprLoc, "literal value out of range for directive");
71915ffd83dbSDimitry Andric 
71925ffd83dbSDimitry Andric   Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
71935ffd83dbSDimitry Andric   return false;
71945ffd83dbSDimitry Andric }
71955ffd83dbSDimitry Andric 
71965ffd83dbSDimitry Andric bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
71975ffd83dbSDimitry Andric   const MCExpr *Value;
71985ffd83dbSDimitry Andric   SMLoc ExprLoc = getLexer().getLoc();
71995ffd83dbSDimitry Andric   if (parseExpression(Value))
72005ffd83dbSDimitry Andric     return true;
72015ffd83dbSDimitry Andric   const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
72025ffd83dbSDimitry Andric   if (!MCE)
72035ffd83dbSDimitry Andric     return Error(ExprLoc, "unexpected expression in align");
72045ffd83dbSDimitry Andric   uint64_t IntValue = MCE->getValue();
72055ffd83dbSDimitry Andric   if (!isPowerOf2_64(IntValue))
72065ffd83dbSDimitry Andric     return Error(ExprLoc, "literal value not a power of two greater then zero");
72075ffd83dbSDimitry Andric 
72085ffd83dbSDimitry Andric   Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
72095ffd83dbSDimitry Andric   return false;
72105ffd83dbSDimitry Andric }
72115ffd83dbSDimitry Andric 
7212e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
7213e8d8bef9SDimitry Andric   const SMLoc Loc = getLexer().getLoc();
7214e8d8bef9SDimitry Andric   std::string RadixStringRaw = parseStringTo(AsmToken::EndOfStatement);
7215e8d8bef9SDimitry Andric   StringRef RadixString = StringRef(RadixStringRaw).trim();
7216e8d8bef9SDimitry Andric   unsigned Radix;
7217e8d8bef9SDimitry Andric   if (RadixString.getAsInteger(10, Radix)) {
7218e8d8bef9SDimitry Andric     return Error(Loc,
7219e8d8bef9SDimitry Andric                  "radix must be a decimal number in the range 2 to 16; was " +
7220e8d8bef9SDimitry Andric                      RadixString);
7221e8d8bef9SDimitry Andric   }
7222e8d8bef9SDimitry Andric   if (Radix < 2 || Radix > 16)
7223e8d8bef9SDimitry Andric     return Error(Loc, "radix must be in the range 2 to 16; was " +
7224e8d8bef9SDimitry Andric                           std::to_string(Radix));
7225e8d8bef9SDimitry Andric   getLexer().setMasmDefaultRadix(Radix);
7226e8d8bef9SDimitry Andric   return false;
7227e8d8bef9SDimitry Andric }
7228e8d8bef9SDimitry Andric 
7229e8d8bef9SDimitry Andric /// parseDirectiveEcho
7230e8d8bef9SDimitry Andric ///   ::= "echo" message
7231fe6060f1SDimitry Andric bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) {
7232e8d8bef9SDimitry Andric   std::string Message = parseStringTo(AsmToken::EndOfStatement);
7233e8d8bef9SDimitry Andric   llvm::outs() << Message;
7234e8d8bef9SDimitry Andric   if (!StringRef(Message).endswith("\n"))
7235e8d8bef9SDimitry Andric     llvm::outs() << '\n';
72365ffd83dbSDimitry Andric   return false;
72375ffd83dbSDimitry Andric }
72385ffd83dbSDimitry Andric 
72395ffd83dbSDimitry Andric // We are comparing pointers, but the pointers are relative to a single string.
72405ffd83dbSDimitry Andric // Thus, this should always be deterministic.
72415ffd83dbSDimitry Andric static int rewritesSort(const AsmRewrite *AsmRewriteA,
72425ffd83dbSDimitry Andric                         const AsmRewrite *AsmRewriteB) {
72435ffd83dbSDimitry Andric   if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
72445ffd83dbSDimitry Andric     return -1;
72455ffd83dbSDimitry Andric   if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
72465ffd83dbSDimitry Andric     return 1;
72475ffd83dbSDimitry Andric 
72485ffd83dbSDimitry Andric   // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
72495ffd83dbSDimitry Andric   // rewrite to the same location.  Make sure the SizeDirective rewrite is
72505ffd83dbSDimitry Andric   // performed first, then the Imm/ImmPrefix and finally the Input/Output.  This
72515ffd83dbSDimitry Andric   // ensures the sort algorithm is stable.
72525ffd83dbSDimitry Andric   if (AsmRewritePrecedence[AsmRewriteA->Kind] >
72535ffd83dbSDimitry Andric       AsmRewritePrecedence[AsmRewriteB->Kind])
72545ffd83dbSDimitry Andric     return -1;
72555ffd83dbSDimitry Andric 
72565ffd83dbSDimitry Andric   if (AsmRewritePrecedence[AsmRewriteA->Kind] <
72575ffd83dbSDimitry Andric       AsmRewritePrecedence[AsmRewriteB->Kind])
72585ffd83dbSDimitry Andric     return 1;
72595ffd83dbSDimitry Andric   llvm_unreachable("Unstable rewrite sort.");
72605ffd83dbSDimitry Andric }
72615ffd83dbSDimitry Andric 
7262e8d8bef9SDimitry Andric bool MasmParser::defineMacro(StringRef Name, StringRef Value) {
7263e8d8bef9SDimitry Andric   Variable &Var = Variables[Name.lower()];
7264e8d8bef9SDimitry Andric   if (Var.Name.empty()) {
7265e8d8bef9SDimitry Andric     Var.Name = Name;
7266fe6060f1SDimitry Andric   } else if (Var.Redefinable == Variable::NOT_REDEFINABLE) {
7267fe6060f1SDimitry Andric     return Error(SMLoc(), "invalid variable redefinition");
7268fe6060f1SDimitry Andric   } else if (Var.Redefinable == Variable::WARN_ON_REDEFINITION &&
7269fe6060f1SDimitry Andric              Warning(SMLoc(), "redefining '" + Name +
7270fe6060f1SDimitry Andric                                   "', already defined on the command line")) {
7271fe6060f1SDimitry Andric     return true;
7272e8d8bef9SDimitry Andric   }
7273fe6060f1SDimitry Andric   Var.Redefinable = Variable::WARN_ON_REDEFINITION;
7274e8d8bef9SDimitry Andric   Var.IsText = true;
7275e8d8bef9SDimitry Andric   Var.TextValue = Value.str();
7276e8d8bef9SDimitry Andric   return false;
72775ffd83dbSDimitry Andric }
72785ffd83dbSDimitry Andric 
7279e8d8bef9SDimitry Andric bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info) const {
7280e8d8bef9SDimitry Andric   const std::pair<StringRef, StringRef> BaseMember = Name.split('.');
7281e8d8bef9SDimitry Andric   const StringRef Base = BaseMember.first, Member = BaseMember.second;
7282e8d8bef9SDimitry Andric   return lookUpField(Base, Member, Info);
7283e8d8bef9SDimitry Andric }
7284e8d8bef9SDimitry Andric 
7285e8d8bef9SDimitry Andric bool MasmParser::lookUpField(StringRef Base, StringRef Member,
7286e8d8bef9SDimitry Andric                              AsmFieldInfo &Info) const {
72875ffd83dbSDimitry Andric   if (Base.empty())
72885ffd83dbSDimitry Andric     return true;
72895ffd83dbSDimitry Andric 
7290e8d8bef9SDimitry Andric   AsmFieldInfo BaseInfo;
7291e8d8bef9SDimitry Andric   if (Base.contains('.') && !lookUpField(Base, BaseInfo))
7292e8d8bef9SDimitry Andric     Base = BaseInfo.Type.Name;
72935ffd83dbSDimitry Andric 
72945ffd83dbSDimitry Andric   auto StructIt = Structs.find(Base.lower());
7295e8d8bef9SDimitry Andric   auto TypeIt = KnownType.find(Base.lower());
7296e8d8bef9SDimitry Andric   if (TypeIt != KnownType.end()) {
7297e8d8bef9SDimitry Andric     StructIt = Structs.find(TypeIt->second.Name.lower());
7298e8d8bef9SDimitry Andric   }
72995ffd83dbSDimitry Andric   if (StructIt != Structs.end())
7300e8d8bef9SDimitry Andric     return lookUpField(StructIt->second, Member, Info);
73015ffd83dbSDimitry Andric 
73025ffd83dbSDimitry Andric   return true;
73035ffd83dbSDimitry Andric }
73045ffd83dbSDimitry Andric 
73055ffd83dbSDimitry Andric bool MasmParser::lookUpField(const StructInfo &Structure, StringRef Member,
7306e8d8bef9SDimitry Andric                              AsmFieldInfo &Info) const {
73075ffd83dbSDimitry Andric   if (Member.empty()) {
7308e8d8bef9SDimitry Andric     Info.Type.Name = Structure.Name;
7309e8d8bef9SDimitry Andric     Info.Type.Size = Structure.Size;
7310e8d8bef9SDimitry Andric     Info.Type.ElementSize = Structure.Size;
7311e8d8bef9SDimitry Andric     Info.Type.Length = 1;
73125ffd83dbSDimitry Andric     return false;
73135ffd83dbSDimitry Andric   }
73145ffd83dbSDimitry Andric 
73155ffd83dbSDimitry Andric   std::pair<StringRef, StringRef> Split = Member.split('.');
73165ffd83dbSDimitry Andric   const StringRef FieldName = Split.first, FieldMember = Split.second;
73175ffd83dbSDimitry Andric 
73185ffd83dbSDimitry Andric   auto StructIt = Structs.find(FieldName.lower());
73195ffd83dbSDimitry Andric   if (StructIt != Structs.end())
7320e8d8bef9SDimitry Andric     return lookUpField(StructIt->second, FieldMember, Info);
73215ffd83dbSDimitry Andric 
73225ffd83dbSDimitry Andric   auto FieldIt = Structure.FieldsByName.find(FieldName.lower());
73235ffd83dbSDimitry Andric   if (FieldIt == Structure.FieldsByName.end())
73245ffd83dbSDimitry Andric     return true;
73255ffd83dbSDimitry Andric 
73265ffd83dbSDimitry Andric   const FieldInfo &Field = Structure.Fields[FieldIt->second];
73275ffd83dbSDimitry Andric   if (FieldMember.empty()) {
7328e8d8bef9SDimitry Andric     Info.Offset += Field.Offset;
7329e8d8bef9SDimitry Andric     Info.Type.Size = Field.SizeOf;
7330e8d8bef9SDimitry Andric     Info.Type.ElementSize = Field.Type;
7331e8d8bef9SDimitry Andric     Info.Type.Length = Field.LengthOf;
73325ffd83dbSDimitry Andric     if (Field.Contents.FT == FT_STRUCT)
7333e8d8bef9SDimitry Andric       Info.Type.Name = Field.Contents.StructInfo.Structure.Name;
7334e8d8bef9SDimitry Andric     else
7335e8d8bef9SDimitry Andric       Info.Type.Name = "";
73365ffd83dbSDimitry Andric     return false;
73375ffd83dbSDimitry Andric   }
73385ffd83dbSDimitry Andric 
73395ffd83dbSDimitry Andric   if (Field.Contents.FT != FT_STRUCT)
73405ffd83dbSDimitry Andric     return true;
73415ffd83dbSDimitry Andric   const StructFieldInfo &StructInfo = Field.Contents.StructInfo;
73425ffd83dbSDimitry Andric 
7343e8d8bef9SDimitry Andric   if (lookUpField(StructInfo.Structure, FieldMember, Info))
73445ffd83dbSDimitry Andric     return true;
73455ffd83dbSDimitry Andric 
7346e8d8bef9SDimitry Andric   Info.Offset += Field.Offset;
73475ffd83dbSDimitry Andric   return false;
73485ffd83dbSDimitry Andric }
73495ffd83dbSDimitry Andric 
7350e8d8bef9SDimitry Andric bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info) const {
7351e8d8bef9SDimitry Andric   unsigned Size = StringSwitch<unsigned>(Name)
7352e8d8bef9SDimitry Andric                       .CasesLower("byte", "db", "sbyte", 1)
7353e8d8bef9SDimitry Andric                       .CasesLower("word", "dw", "sword", 2)
7354e8d8bef9SDimitry Andric                       .CasesLower("dword", "dd", "sdword", 4)
7355e8d8bef9SDimitry Andric                       .CasesLower("fword", "df", 6)
7356e8d8bef9SDimitry Andric                       .CasesLower("qword", "dq", "sqword", 8)
7357e8d8bef9SDimitry Andric                       .CaseLower("real4", 4)
7358e8d8bef9SDimitry Andric                       .CaseLower("real8", 8)
7359e8d8bef9SDimitry Andric                       .CaseLower("real10", 10)
7360e8d8bef9SDimitry Andric                       .Default(0);
7361e8d8bef9SDimitry Andric   if (Size) {
7362e8d8bef9SDimitry Andric     Info.Name = Name;
7363e8d8bef9SDimitry Andric     Info.ElementSize = Size;
7364e8d8bef9SDimitry Andric     Info.Length = 1;
7365e8d8bef9SDimitry Andric     Info.Size = Size;
7366e8d8bef9SDimitry Andric     return false;
7367e8d8bef9SDimitry Andric   }
7368e8d8bef9SDimitry Andric 
7369e8d8bef9SDimitry Andric   auto StructIt = Structs.find(Name.lower());
7370e8d8bef9SDimitry Andric   if (StructIt != Structs.end()) {
7371e8d8bef9SDimitry Andric     const StructInfo &Structure = StructIt->second;
7372e8d8bef9SDimitry Andric     Info.Name = Name;
7373e8d8bef9SDimitry Andric     Info.ElementSize = Structure.Size;
7374e8d8bef9SDimitry Andric     Info.Length = 1;
7375e8d8bef9SDimitry Andric     Info.Size = Structure.Size;
7376e8d8bef9SDimitry Andric     return false;
7377e8d8bef9SDimitry Andric   }
7378e8d8bef9SDimitry Andric 
7379e8d8bef9SDimitry Andric   return true;
7380e8d8bef9SDimitry Andric }
7381e8d8bef9SDimitry Andric 
73825ffd83dbSDimitry Andric bool MasmParser::parseMSInlineAsm(
7383fe6060f1SDimitry Andric     std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs,
7384fe6060f1SDimitry Andric     SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
73855ffd83dbSDimitry Andric     SmallVectorImpl<std::string> &Constraints,
73865ffd83dbSDimitry Andric     SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
73875ffd83dbSDimitry Andric     const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
73885ffd83dbSDimitry Andric   SmallVector<void *, 4> InputDecls;
73895ffd83dbSDimitry Andric   SmallVector<void *, 4> OutputDecls;
73905ffd83dbSDimitry Andric   SmallVector<bool, 4> InputDeclsAddressOf;
73915ffd83dbSDimitry Andric   SmallVector<bool, 4> OutputDeclsAddressOf;
73925ffd83dbSDimitry Andric   SmallVector<std::string, 4> InputConstraints;
73935ffd83dbSDimitry Andric   SmallVector<std::string, 4> OutputConstraints;
73945ffd83dbSDimitry Andric   SmallVector<unsigned, 4> ClobberRegs;
73955ffd83dbSDimitry Andric 
73965ffd83dbSDimitry Andric   SmallVector<AsmRewrite, 4> AsmStrRewrites;
73975ffd83dbSDimitry Andric 
73985ffd83dbSDimitry Andric   // Prime the lexer.
73995ffd83dbSDimitry Andric   Lex();
74005ffd83dbSDimitry Andric 
74015ffd83dbSDimitry Andric   // While we have input, parse each statement.
74025ffd83dbSDimitry Andric   unsigned InputIdx = 0;
74035ffd83dbSDimitry Andric   unsigned OutputIdx = 0;
74045ffd83dbSDimitry Andric   while (getLexer().isNot(AsmToken::Eof)) {
74055ffd83dbSDimitry Andric     // Parse curly braces marking block start/end.
74065ffd83dbSDimitry Andric     if (parseCurlyBlockScope(AsmStrRewrites))
74075ffd83dbSDimitry Andric       continue;
74085ffd83dbSDimitry Andric 
74095ffd83dbSDimitry Andric     ParseStatementInfo Info(&AsmStrRewrites);
74105ffd83dbSDimitry Andric     bool StatementErr = parseStatement(Info, &SI);
74115ffd83dbSDimitry Andric 
74125ffd83dbSDimitry Andric     if (StatementErr || Info.ParseError) {
74135ffd83dbSDimitry Andric       // Emit pending errors if any exist.
74145ffd83dbSDimitry Andric       printPendingErrors();
74155ffd83dbSDimitry Andric       return true;
74165ffd83dbSDimitry Andric     }
74175ffd83dbSDimitry Andric 
74185ffd83dbSDimitry Andric     // No pending error should exist here.
74195ffd83dbSDimitry Andric     assert(!hasPendingError() && "unexpected error from parseStatement");
74205ffd83dbSDimitry Andric 
74215ffd83dbSDimitry Andric     if (Info.Opcode == ~0U)
74225ffd83dbSDimitry Andric       continue;
74235ffd83dbSDimitry Andric 
74245ffd83dbSDimitry Andric     const MCInstrDesc &Desc = MII->get(Info.Opcode);
74255ffd83dbSDimitry Andric 
74265ffd83dbSDimitry Andric     // Build the list of clobbers, outputs and inputs.
74275ffd83dbSDimitry Andric     for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
74285ffd83dbSDimitry Andric       MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
74295ffd83dbSDimitry Andric 
74305ffd83dbSDimitry Andric       // Register operand.
74315ffd83dbSDimitry Andric       if (Operand.isReg() && !Operand.needAddressOf() &&
74325ffd83dbSDimitry Andric           !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {
74335ffd83dbSDimitry Andric         unsigned NumDefs = Desc.getNumDefs();
74345ffd83dbSDimitry Andric         // Clobber.
74355ffd83dbSDimitry Andric         if (NumDefs && Operand.getMCOperandNum() < NumDefs)
74365ffd83dbSDimitry Andric           ClobberRegs.push_back(Operand.getReg());
74375ffd83dbSDimitry Andric         continue;
74385ffd83dbSDimitry Andric       }
74395ffd83dbSDimitry Andric 
74405ffd83dbSDimitry Andric       // Expr/Input or Output.
74415ffd83dbSDimitry Andric       StringRef SymName = Operand.getSymName();
74425ffd83dbSDimitry Andric       if (SymName.empty())
74435ffd83dbSDimitry Andric         continue;
74445ffd83dbSDimitry Andric 
74455ffd83dbSDimitry Andric       void *OpDecl = Operand.getOpDecl();
74465ffd83dbSDimitry Andric       if (!OpDecl)
74475ffd83dbSDimitry Andric         continue;
74485ffd83dbSDimitry Andric 
74495ffd83dbSDimitry Andric       StringRef Constraint = Operand.getConstraint();
74505ffd83dbSDimitry Andric       if (Operand.isImm()) {
74515ffd83dbSDimitry Andric         // Offset as immediate.
74525ffd83dbSDimitry Andric         if (Operand.isOffsetOfLocal())
74535ffd83dbSDimitry Andric           Constraint = "r";
74545ffd83dbSDimitry Andric         else
74555ffd83dbSDimitry Andric           Constraint = "i";
74565ffd83dbSDimitry Andric       }
74575ffd83dbSDimitry Andric 
74585ffd83dbSDimitry Andric       bool isOutput = (i == 1) && Desc.mayStore();
74595ffd83dbSDimitry Andric       SMLoc Start = SMLoc::getFromPointer(SymName.data());
74605ffd83dbSDimitry Andric       if (isOutput) {
74615ffd83dbSDimitry Andric         ++InputIdx;
74625ffd83dbSDimitry Andric         OutputDecls.push_back(OpDecl);
74635ffd83dbSDimitry Andric         OutputDeclsAddressOf.push_back(Operand.needAddressOf());
74645ffd83dbSDimitry Andric         OutputConstraints.push_back(("=" + Constraint).str());
74655ffd83dbSDimitry Andric         AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size());
74665ffd83dbSDimitry Andric       } else {
74675ffd83dbSDimitry Andric         InputDecls.push_back(OpDecl);
74685ffd83dbSDimitry Andric         InputDeclsAddressOf.push_back(Operand.needAddressOf());
74695ffd83dbSDimitry Andric         InputConstraints.push_back(Constraint.str());
74705ffd83dbSDimitry Andric         if (Desc.OpInfo[i - 1].isBranchTarget())
74715ffd83dbSDimitry Andric           AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size());
74725ffd83dbSDimitry Andric         else
74735ffd83dbSDimitry Andric           AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
74745ffd83dbSDimitry Andric       }
74755ffd83dbSDimitry Andric     }
74765ffd83dbSDimitry Andric 
74775ffd83dbSDimitry Andric     // Consider implicit defs to be clobbers.  Think of cpuid and push.
74785ffd83dbSDimitry Andric     ArrayRef<MCPhysReg> ImpDefs(Desc.getImplicitDefs(),
74795ffd83dbSDimitry Andric                                 Desc.getNumImplicitDefs());
7480e8d8bef9SDimitry Andric     llvm::append_range(ClobberRegs, ImpDefs);
74815ffd83dbSDimitry Andric   }
74825ffd83dbSDimitry Andric 
74835ffd83dbSDimitry Andric   // Set the number of Outputs and Inputs.
74845ffd83dbSDimitry Andric   NumOutputs = OutputDecls.size();
74855ffd83dbSDimitry Andric   NumInputs = InputDecls.size();
74865ffd83dbSDimitry Andric 
74875ffd83dbSDimitry Andric   // Set the unique clobbers.
74885ffd83dbSDimitry Andric   array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
74895ffd83dbSDimitry Andric   ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()),
74905ffd83dbSDimitry Andric                     ClobberRegs.end());
74915ffd83dbSDimitry Andric   Clobbers.assign(ClobberRegs.size(), std::string());
74925ffd83dbSDimitry Andric   for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
74935ffd83dbSDimitry Andric     raw_string_ostream OS(Clobbers[I]);
74945ffd83dbSDimitry Andric     IP->printRegName(OS, ClobberRegs[I]);
74955ffd83dbSDimitry Andric   }
74965ffd83dbSDimitry Andric 
74975ffd83dbSDimitry Andric   // Merge the various outputs and inputs.  Output are expected first.
74985ffd83dbSDimitry Andric   if (NumOutputs || NumInputs) {
74995ffd83dbSDimitry Andric     unsigned NumExprs = NumOutputs + NumInputs;
75005ffd83dbSDimitry Andric     OpDecls.resize(NumExprs);
75015ffd83dbSDimitry Andric     Constraints.resize(NumExprs);
75025ffd83dbSDimitry Andric     for (unsigned i = 0; i < NumOutputs; ++i) {
75035ffd83dbSDimitry Andric       OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
75045ffd83dbSDimitry Andric       Constraints[i] = OutputConstraints[i];
75055ffd83dbSDimitry Andric     }
75065ffd83dbSDimitry Andric     for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
75075ffd83dbSDimitry Andric       OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
75085ffd83dbSDimitry Andric       Constraints[j] = InputConstraints[i];
75095ffd83dbSDimitry Andric     }
75105ffd83dbSDimitry Andric   }
75115ffd83dbSDimitry Andric 
75125ffd83dbSDimitry Andric   // Build the IR assembly string.
75135ffd83dbSDimitry Andric   std::string AsmStringIR;
75145ffd83dbSDimitry Andric   raw_string_ostream OS(AsmStringIR);
75155ffd83dbSDimitry Andric   StringRef ASMString =
75165ffd83dbSDimitry Andric       SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer();
75175ffd83dbSDimitry Andric   const char *AsmStart = ASMString.begin();
75185ffd83dbSDimitry Andric   const char *AsmEnd = ASMString.end();
75195ffd83dbSDimitry Andric   array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
75205ffd83dbSDimitry Andric   for (auto it = AsmStrRewrites.begin(); it != AsmStrRewrites.end(); ++it) {
75215ffd83dbSDimitry Andric     const AsmRewrite &AR = *it;
75225ffd83dbSDimitry Andric     // Check if this has already been covered by another rewrite...
75235ffd83dbSDimitry Andric     if (AR.Done)
75245ffd83dbSDimitry Andric       continue;
75255ffd83dbSDimitry Andric     AsmRewriteKind Kind = AR.Kind;
75265ffd83dbSDimitry Andric 
75275ffd83dbSDimitry Andric     const char *Loc = AR.Loc.getPointer();
75285ffd83dbSDimitry Andric     assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
75295ffd83dbSDimitry Andric 
75305ffd83dbSDimitry Andric     // Emit everything up to the immediate/expression.
75315ffd83dbSDimitry Andric     if (unsigned Len = Loc - AsmStart)
75325ffd83dbSDimitry Andric       OS << StringRef(AsmStart, Len);
75335ffd83dbSDimitry Andric 
75345ffd83dbSDimitry Andric     // Skip the original expression.
75355ffd83dbSDimitry Andric     if (Kind == AOK_Skip) {
75365ffd83dbSDimitry Andric       AsmStart = Loc + AR.Len;
75375ffd83dbSDimitry Andric       continue;
75385ffd83dbSDimitry Andric     }
75395ffd83dbSDimitry Andric 
75405ffd83dbSDimitry Andric     unsigned AdditionalSkip = 0;
75415ffd83dbSDimitry Andric     // Rewrite expressions in $N notation.
75425ffd83dbSDimitry Andric     switch (Kind) {
75435ffd83dbSDimitry Andric     default:
75445ffd83dbSDimitry Andric       break;
75455ffd83dbSDimitry Andric     case AOK_IntelExpr:
75465ffd83dbSDimitry Andric       assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
75475ffd83dbSDimitry Andric       if (AR.IntelExp.NeedBracs)
75485ffd83dbSDimitry Andric         OS << "[";
75495ffd83dbSDimitry Andric       if (AR.IntelExp.hasBaseReg())
75505ffd83dbSDimitry Andric         OS << AR.IntelExp.BaseReg;
75515ffd83dbSDimitry Andric       if (AR.IntelExp.hasIndexReg())
75525ffd83dbSDimitry Andric         OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
75535ffd83dbSDimitry Andric            << AR.IntelExp.IndexReg;
75545ffd83dbSDimitry Andric       if (AR.IntelExp.Scale > 1)
75555ffd83dbSDimitry Andric         OS << " * $$" << AR.IntelExp.Scale;
75565ffd83dbSDimitry Andric       if (AR.IntelExp.hasOffset()) {
75575ffd83dbSDimitry Andric         if (AR.IntelExp.hasRegs())
75585ffd83dbSDimitry Andric           OS << " + ";
75595ffd83dbSDimitry Andric         // Fuse this rewrite with a rewrite of the offset name, if present.
75605ffd83dbSDimitry Andric         StringRef OffsetName = AR.IntelExp.OffsetName;
75615ffd83dbSDimitry Andric         SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());
75625ffd83dbSDimitry Andric         size_t OffsetLen = OffsetName.size();
75635ffd83dbSDimitry Andric         auto rewrite_it = std::find_if(
75645ffd83dbSDimitry Andric             it, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
75655ffd83dbSDimitry Andric               return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
75665ffd83dbSDimitry Andric                      (FusingAR.Kind == AOK_Input ||
75675ffd83dbSDimitry Andric                       FusingAR.Kind == AOK_CallInput);
75685ffd83dbSDimitry Andric             });
75695ffd83dbSDimitry Andric         if (rewrite_it == AsmStrRewrites.end()) {
75705ffd83dbSDimitry Andric           OS << "offset " << OffsetName;
75715ffd83dbSDimitry Andric         } else if (rewrite_it->Kind == AOK_CallInput) {
75725ffd83dbSDimitry Andric           OS << "${" << InputIdx++ << ":P}";
75735ffd83dbSDimitry Andric           rewrite_it->Done = true;
75745ffd83dbSDimitry Andric         } else {
75755ffd83dbSDimitry Andric           OS << '$' << InputIdx++;
75765ffd83dbSDimitry Andric           rewrite_it->Done = true;
75775ffd83dbSDimitry Andric         }
75785ffd83dbSDimitry Andric       }
75795ffd83dbSDimitry Andric       if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
75805ffd83dbSDimitry Andric         OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
75815ffd83dbSDimitry Andric       if (AR.IntelExp.NeedBracs)
75825ffd83dbSDimitry Andric         OS << "]";
75835ffd83dbSDimitry Andric       break;
75845ffd83dbSDimitry Andric     case AOK_Label:
75855ffd83dbSDimitry Andric       OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
75865ffd83dbSDimitry Andric       break;
75875ffd83dbSDimitry Andric     case AOK_Input:
75885ffd83dbSDimitry Andric       OS << '$' << InputIdx++;
75895ffd83dbSDimitry Andric       break;
75905ffd83dbSDimitry Andric     case AOK_CallInput:
75915ffd83dbSDimitry Andric       OS << "${" << InputIdx++ << ":P}";
75925ffd83dbSDimitry Andric       break;
75935ffd83dbSDimitry Andric     case AOK_Output:
75945ffd83dbSDimitry Andric       OS << '$' << OutputIdx++;
75955ffd83dbSDimitry Andric       break;
75965ffd83dbSDimitry Andric     case AOK_SizeDirective:
75975ffd83dbSDimitry Andric       switch (AR.Val) {
75985ffd83dbSDimitry Andric       default: break;
75995ffd83dbSDimitry Andric       case 8:  OS << "byte ptr "; break;
76005ffd83dbSDimitry Andric       case 16: OS << "word ptr "; break;
76015ffd83dbSDimitry Andric       case 32: OS << "dword ptr "; break;
76025ffd83dbSDimitry Andric       case 64: OS << "qword ptr "; break;
76035ffd83dbSDimitry Andric       case 80: OS << "xword ptr "; break;
76045ffd83dbSDimitry Andric       case 128: OS << "xmmword ptr "; break;
76055ffd83dbSDimitry Andric       case 256: OS << "ymmword ptr "; break;
76065ffd83dbSDimitry Andric       }
76075ffd83dbSDimitry Andric       break;
76085ffd83dbSDimitry Andric     case AOK_Emit:
76095ffd83dbSDimitry Andric       OS << ".byte";
76105ffd83dbSDimitry Andric       break;
76115ffd83dbSDimitry Andric     case AOK_Align: {
76125ffd83dbSDimitry Andric       // MS alignment directives are measured in bytes. If the native assembler
76135ffd83dbSDimitry Andric       // measures alignment in bytes, we can pass it straight through.
76145ffd83dbSDimitry Andric       OS << ".align";
76155ffd83dbSDimitry Andric       if (getContext().getAsmInfo()->getAlignmentIsInBytes())
76165ffd83dbSDimitry Andric         break;
76175ffd83dbSDimitry Andric 
76185ffd83dbSDimitry Andric       // Alignment is in log2 form, so print that instead and skip the original
76195ffd83dbSDimitry Andric       // immediate.
76205ffd83dbSDimitry Andric       unsigned Val = AR.Val;
76215ffd83dbSDimitry Andric       OS << ' ' << Val;
76225ffd83dbSDimitry Andric       assert(Val < 10 && "Expected alignment less then 2^10.");
76235ffd83dbSDimitry Andric       AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
76245ffd83dbSDimitry Andric       break;
76255ffd83dbSDimitry Andric     }
76265ffd83dbSDimitry Andric     case AOK_EVEN:
76275ffd83dbSDimitry Andric       OS << ".even";
76285ffd83dbSDimitry Andric       break;
76295ffd83dbSDimitry Andric     case AOK_EndOfStatement:
76305ffd83dbSDimitry Andric       OS << "\n\t";
76315ffd83dbSDimitry Andric       break;
76325ffd83dbSDimitry Andric     }
76335ffd83dbSDimitry Andric 
76345ffd83dbSDimitry Andric     // Skip the original expression.
76355ffd83dbSDimitry Andric     AsmStart = Loc + AR.Len + AdditionalSkip;
76365ffd83dbSDimitry Andric   }
76375ffd83dbSDimitry Andric 
76385ffd83dbSDimitry Andric   // Emit the remainder of the asm string.
76395ffd83dbSDimitry Andric   if (AsmStart != AsmEnd)
76405ffd83dbSDimitry Andric     OS << StringRef(AsmStart, AsmEnd - AsmStart);
76415ffd83dbSDimitry Andric 
76425ffd83dbSDimitry Andric   AsmString = OS.str();
76435ffd83dbSDimitry Andric   return false;
76445ffd83dbSDimitry Andric }
76455ffd83dbSDimitry Andric 
7646fe6060f1SDimitry Andric void MasmParser::initializeBuiltinSymbolMap() {
7647fe6060f1SDimitry Andric   // Numeric built-ins (supported in all versions)
7648fe6060f1SDimitry Andric   BuiltinSymbolMap["@version"] = BI_VERSION;
7649fe6060f1SDimitry Andric   BuiltinSymbolMap["@line"] = BI_LINE;
7650fe6060f1SDimitry Andric 
7651fe6060f1SDimitry Andric   // Text built-ins (supported in all versions)
7652fe6060f1SDimitry Andric   BuiltinSymbolMap["@date"] = BI_DATE;
7653fe6060f1SDimitry Andric   BuiltinSymbolMap["@time"] = BI_TIME;
7654fe6060f1SDimitry Andric   BuiltinSymbolMap["@filecur"] = BI_FILECUR;
7655fe6060f1SDimitry Andric   BuiltinSymbolMap["@filename"] = BI_FILENAME;
7656fe6060f1SDimitry Andric   BuiltinSymbolMap["@curseg"] = BI_CURSEG;
7657fe6060f1SDimitry Andric 
7658fe6060f1SDimitry Andric   // Some built-ins exist only for MASM32 (32-bit x86)
7659fe6060f1SDimitry Andric   if (getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
7660fe6060f1SDimitry Andric       Triple::x86) {
7661fe6060f1SDimitry Andric     // Numeric built-ins
7662fe6060f1SDimitry Andric     // BuiltinSymbolMap["@cpu"] = BI_CPU;
7663fe6060f1SDimitry Andric     // BuiltinSymbolMap["@interface"] = BI_INTERFACE;
7664fe6060f1SDimitry Andric     // BuiltinSymbolMap["@wordsize"] = BI_WORDSIZE;
7665fe6060f1SDimitry Andric     // BuiltinSymbolMap["@codesize"] = BI_CODESIZE;
7666fe6060f1SDimitry Andric     // BuiltinSymbolMap["@datasize"] = BI_DATASIZE;
7667fe6060f1SDimitry Andric     // BuiltinSymbolMap["@model"] = BI_MODEL;
7668fe6060f1SDimitry Andric 
7669fe6060f1SDimitry Andric     // Text built-ins
7670fe6060f1SDimitry Andric     // BuiltinSymbolMap["@code"] = BI_CODE;
7671fe6060f1SDimitry Andric     // BuiltinSymbolMap["@data"] = BI_DATA;
7672fe6060f1SDimitry Andric     // BuiltinSymbolMap["@fardata?"] = BI_FARDATA;
7673fe6060f1SDimitry Andric     // BuiltinSymbolMap["@stack"] = BI_STACK;
7674fe6060f1SDimitry Andric   }
7675fe6060f1SDimitry Andric }
7676fe6060f1SDimitry Andric 
7677fe6060f1SDimitry Andric const MCExpr *MasmParser::evaluateBuiltinValue(BuiltinSymbol Symbol,
7678fe6060f1SDimitry Andric                                                SMLoc StartLoc) {
7679fe6060f1SDimitry Andric   switch (Symbol) {
7680fe6060f1SDimitry Andric   default:
7681fe6060f1SDimitry Andric     return nullptr;
7682fe6060f1SDimitry Andric   case BI_VERSION:
7683fe6060f1SDimitry Andric     // Match a recent version of ML.EXE.
7684fe6060f1SDimitry Andric     return MCConstantExpr::create(1427, getContext());
7685fe6060f1SDimitry Andric   case BI_LINE: {
7686fe6060f1SDimitry Andric     int64_t Line;
7687fe6060f1SDimitry Andric     if (ActiveMacros.empty())
7688fe6060f1SDimitry Andric       Line = SrcMgr.FindLineNumber(StartLoc, CurBuffer);
7689fe6060f1SDimitry Andric     else
7690fe6060f1SDimitry Andric       Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
7691fe6060f1SDimitry Andric                                    ActiveMacros.front()->ExitBuffer);
7692fe6060f1SDimitry Andric     return MCConstantExpr::create(Line, getContext());
7693fe6060f1SDimitry Andric   }
7694fe6060f1SDimitry Andric   }
7695fe6060f1SDimitry Andric   llvm_unreachable("unhandled built-in symbol");
7696fe6060f1SDimitry Andric }
7697fe6060f1SDimitry Andric 
7698fe6060f1SDimitry Andric llvm::Optional<std::string>
7699fe6060f1SDimitry Andric MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
7700fe6060f1SDimitry Andric   switch (Symbol) {
7701fe6060f1SDimitry Andric   default:
7702fe6060f1SDimitry Andric     return {};
7703fe6060f1SDimitry Andric   case BI_DATE: {
7704fe6060f1SDimitry Andric     // Current local date, formatted MM/DD/YY
7705fe6060f1SDimitry Andric     char TmpBuffer[sizeof("mm/dd/yy")];
7706fe6060f1SDimitry Andric     const size_t Len = strftime(TmpBuffer, sizeof(TmpBuffer), "%D", &TM);
7707fe6060f1SDimitry Andric     return std::string(TmpBuffer, Len);
7708fe6060f1SDimitry Andric   }
7709fe6060f1SDimitry Andric   case BI_TIME: {
7710fe6060f1SDimitry Andric     // Current local time, formatted HH:MM:SS (24-hour clock)
7711fe6060f1SDimitry Andric     char TmpBuffer[sizeof("hh:mm:ss")];
7712fe6060f1SDimitry Andric     const size_t Len = strftime(TmpBuffer, sizeof(TmpBuffer), "%T", &TM);
7713fe6060f1SDimitry Andric     return std::string(TmpBuffer, Len);
7714fe6060f1SDimitry Andric   }
7715fe6060f1SDimitry Andric   case BI_FILECUR:
7716fe6060f1SDimitry Andric     return SrcMgr
7717fe6060f1SDimitry Andric         .getMemoryBuffer(
7718fe6060f1SDimitry Andric             ActiveMacros.empty() ? CurBuffer : ActiveMacros.front()->ExitBuffer)
7719fe6060f1SDimitry Andric         ->getBufferIdentifier()
7720fe6060f1SDimitry Andric         .str();
7721fe6060f1SDimitry Andric   case BI_FILENAME:
7722fe6060f1SDimitry Andric     return sys::path::stem(SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())
7723fe6060f1SDimitry Andric                                ->getBufferIdentifier())
7724fe6060f1SDimitry Andric         .upper();
7725fe6060f1SDimitry Andric   case BI_CURSEG:
7726fe6060f1SDimitry Andric     return getStreamer().getCurrentSectionOnly()->getName().str();
7727fe6060f1SDimitry Andric   }
7728fe6060f1SDimitry Andric   llvm_unreachable("unhandled built-in symbol");
7729fe6060f1SDimitry Andric }
7730fe6060f1SDimitry Andric 
77315ffd83dbSDimitry Andric /// Create an MCAsmParser instance.
77325ffd83dbSDimitry Andric MCAsmParser *llvm::createMCMasmParser(SourceMgr &SM, MCContext &C,
77335ffd83dbSDimitry Andric                                       MCStreamer &Out, const MCAsmInfo &MAI,
7734fe6060f1SDimitry Andric                                       struct tm TM, unsigned CB) {
7735fe6060f1SDimitry Andric   return new MasmParser(SM, C, Out, MAI, TM, CB);
77365ffd83dbSDimitry Andric }
7737