xref: /freebsd/contrib/llvm-project/llvm/lib/MC/MCParser/MasmParser.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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"
1604eeddc0SDimitry Andric #include "llvm/ADT/BitVector.h"
175ffd83dbSDimitry Andric #include "llvm/ADT/STLExtras.h"
185ffd83dbSDimitry Andric #include "llvm/ADT/SmallString.h"
195ffd83dbSDimitry Andric #include "llvm/ADT/SmallVector.h"
205ffd83dbSDimitry Andric #include "llvm/ADT/StringExtras.h"
215ffd83dbSDimitry Andric #include "llvm/ADT/StringMap.h"
225ffd83dbSDimitry Andric #include "llvm/ADT/StringRef.h"
23e8d8bef9SDimitry Andric #include "llvm/ADT/StringSwitch.h"
245ffd83dbSDimitry Andric #include "llvm/ADT/Twine.h"
255ffd83dbSDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
265ffd83dbSDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
275ffd83dbSDimitry Andric #include "llvm/MC/MCAsmInfo.h"
285ffd83dbSDimitry Andric #include "llvm/MC/MCCodeView.h"
295ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h"
305ffd83dbSDimitry Andric #include "llvm/MC/MCDirectives.h"
315ffd83dbSDimitry Andric #include "llvm/MC/MCDwarf.h"
325ffd83dbSDimitry Andric #include "llvm/MC/MCExpr.h"
335ffd83dbSDimitry Andric #include "llvm/MC/MCInstPrinter.h"
345ffd83dbSDimitry Andric #include "llvm/MC/MCInstrDesc.h"
355ffd83dbSDimitry Andric #include "llvm/MC/MCInstrInfo.h"
365ffd83dbSDimitry Andric #include "llvm/MC/MCParser/AsmCond.h"
375ffd83dbSDimitry Andric #include "llvm/MC/MCParser/AsmLexer.h"
385ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
395ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmParser.h"
405ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmParserExtension.h"
415ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
425ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
435ffd83dbSDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
445ffd83dbSDimitry Andric #include "llvm/MC/MCSection.h"
455ffd83dbSDimitry Andric #include "llvm/MC/MCStreamer.h"
4681ad6265SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
475ffd83dbSDimitry Andric #include "llvm/MC/MCSymbol.h"
485ffd83dbSDimitry Andric #include "llvm/MC/MCTargetOptions.h"
495ffd83dbSDimitry Andric #include "llvm/Support/Casting.h"
505ffd83dbSDimitry Andric #include "llvm/Support/CommandLine.h"
515ffd83dbSDimitry Andric #include "llvm/Support/ErrorHandling.h"
52e8d8bef9SDimitry Andric #include "llvm/Support/Format.h"
535ffd83dbSDimitry Andric #include "llvm/Support/MD5.h"
545ffd83dbSDimitry Andric #include "llvm/Support/MathExtras.h"
555ffd83dbSDimitry Andric #include "llvm/Support/MemoryBuffer.h"
56fe6060f1SDimitry Andric #include "llvm/Support/Path.h"
575ffd83dbSDimitry Andric #include "llvm/Support/SMLoc.h"
585ffd83dbSDimitry Andric #include "llvm/Support/SourceMgr.h"
595ffd83dbSDimitry Andric #include "llvm/Support/raw_ostream.h"
605ffd83dbSDimitry Andric #include <algorithm>
615ffd83dbSDimitry Andric #include <cassert>
625ffd83dbSDimitry Andric #include <climits>
635ffd83dbSDimitry Andric #include <cstddef>
645ffd83dbSDimitry Andric #include <cstdint>
65fe6060f1SDimitry Andric #include <ctime>
665ffd83dbSDimitry Andric #include <deque>
675ffd83dbSDimitry Andric #include <memory>
68*bdd1243dSDimitry Andric #include <optional>
695ffd83dbSDimitry Andric #include <sstream>
705ffd83dbSDimitry Andric #include <string>
715ffd83dbSDimitry Andric #include <tuple>
725ffd83dbSDimitry Andric #include <utility>
735ffd83dbSDimitry Andric #include <vector>
745ffd83dbSDimitry Andric 
755ffd83dbSDimitry Andric using namespace llvm;
765ffd83dbSDimitry Andric 
775ffd83dbSDimitry Andric namespace {
785ffd83dbSDimitry Andric 
795ffd83dbSDimitry Andric /// Helper types for tracking macro definitions.
805ffd83dbSDimitry Andric typedef std::vector<AsmToken> MCAsmMacroArgument;
815ffd83dbSDimitry Andric typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
825ffd83dbSDimitry Andric 
835ffd83dbSDimitry Andric /// Helper class for storing information about an active macro instantiation.
845ffd83dbSDimitry Andric struct MacroInstantiation {
855ffd83dbSDimitry Andric   /// The location of the instantiation.
865ffd83dbSDimitry Andric   SMLoc InstantiationLoc;
875ffd83dbSDimitry Andric 
885ffd83dbSDimitry Andric   /// The buffer where parsing should resume upon instantiation completion.
895ffd83dbSDimitry Andric   unsigned ExitBuffer;
905ffd83dbSDimitry Andric 
915ffd83dbSDimitry Andric   /// The location where parsing should resume upon instantiation completion.
925ffd83dbSDimitry Andric   SMLoc ExitLoc;
935ffd83dbSDimitry Andric 
945ffd83dbSDimitry Andric   /// The depth of TheCondStack at the start of the instantiation.
955ffd83dbSDimitry Andric   size_t CondStackDepth;
965ffd83dbSDimitry Andric };
975ffd83dbSDimitry Andric 
985ffd83dbSDimitry Andric struct ParseStatementInfo {
995ffd83dbSDimitry Andric   /// The parsed operands from the last parsed statement.
1005ffd83dbSDimitry Andric   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;
1015ffd83dbSDimitry Andric 
1025ffd83dbSDimitry Andric   /// The opcode from the last parsed instruction.
1035ffd83dbSDimitry Andric   unsigned Opcode = ~0U;
1045ffd83dbSDimitry Andric 
1055ffd83dbSDimitry Andric   /// Was there an error parsing the inline assembly?
1065ffd83dbSDimitry Andric   bool ParseError = false;
1075ffd83dbSDimitry Andric 
108e8d8bef9SDimitry Andric   /// The value associated with a macro exit.
109*bdd1243dSDimitry Andric   std::optional<std::string> ExitValue;
110e8d8bef9SDimitry Andric 
1115ffd83dbSDimitry Andric   SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
1125ffd83dbSDimitry Andric 
1135ffd83dbSDimitry Andric   ParseStatementInfo() = delete;
1145ffd83dbSDimitry Andric   ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
1155ffd83dbSDimitry Andric       : AsmRewrites(rewrites) {}
1165ffd83dbSDimitry Andric };
1175ffd83dbSDimitry Andric 
1185ffd83dbSDimitry Andric enum FieldType {
1195ffd83dbSDimitry Andric   FT_INTEGRAL, // Initializer: integer expression, stored as an MCExpr.
1205ffd83dbSDimitry Andric   FT_REAL,     // Initializer: real number, stored as an APInt.
1215ffd83dbSDimitry Andric   FT_STRUCT    // Initializer: struct initializer, stored recursively.
1225ffd83dbSDimitry Andric };
1235ffd83dbSDimitry Andric 
1245ffd83dbSDimitry Andric struct FieldInfo;
1255ffd83dbSDimitry Andric struct StructInfo {
1265ffd83dbSDimitry Andric   StringRef Name;
1275ffd83dbSDimitry Andric   bool IsUnion = false;
128fe6060f1SDimitry Andric   bool Initializable = true;
129e8d8bef9SDimitry Andric   unsigned Alignment = 0;
130e8d8bef9SDimitry Andric   unsigned AlignmentSize = 0;
131fe6060f1SDimitry Andric   unsigned NextOffset = 0;
132fe6060f1SDimitry Andric   unsigned Size = 0;
1335ffd83dbSDimitry Andric   std::vector<FieldInfo> Fields;
1345ffd83dbSDimitry Andric   StringMap<size_t> FieldsByName;
1355ffd83dbSDimitry Andric 
136e8d8bef9SDimitry Andric   FieldInfo &addField(StringRef FieldName, FieldType FT,
137e8d8bef9SDimitry Andric                       unsigned FieldAlignmentSize);
1385ffd83dbSDimitry Andric 
1395ffd83dbSDimitry Andric   StructInfo() = default;
140*bdd1243dSDimitry Andric   StructInfo(StringRef StructName, bool Union, unsigned AlignmentValue);
1415ffd83dbSDimitry Andric };
1425ffd83dbSDimitry Andric 
1435ffd83dbSDimitry Andric // FIXME: This should probably use a class hierarchy, raw pointers between the
1445ffd83dbSDimitry Andric // objects, and dynamic type resolution instead of a union. On the other hand,
1455ffd83dbSDimitry Andric // ownership then becomes much more complicated; the obvious thing would be to
1465ffd83dbSDimitry Andric // use BumpPtrAllocator, but the lack of a destructor makes that messy.
1475ffd83dbSDimitry Andric 
1485ffd83dbSDimitry Andric struct StructInitializer;
1495ffd83dbSDimitry Andric struct IntFieldInfo {
1505ffd83dbSDimitry Andric   SmallVector<const MCExpr *, 1> Values;
1515ffd83dbSDimitry Andric 
1525ffd83dbSDimitry Andric   IntFieldInfo() = default;
1535ffd83dbSDimitry Andric   IntFieldInfo(const SmallVector<const MCExpr *, 1> &V) { Values = V; }
1545ffd83dbSDimitry Andric   IntFieldInfo(SmallVector<const MCExpr *, 1> &&V) { Values = V; }
1555ffd83dbSDimitry Andric };
1565ffd83dbSDimitry Andric struct RealFieldInfo {
1575ffd83dbSDimitry Andric   SmallVector<APInt, 1> AsIntValues;
1585ffd83dbSDimitry Andric 
1595ffd83dbSDimitry Andric   RealFieldInfo() = default;
1605ffd83dbSDimitry Andric   RealFieldInfo(const SmallVector<APInt, 1> &V) { AsIntValues = V; }
1615ffd83dbSDimitry Andric   RealFieldInfo(SmallVector<APInt, 1> &&V) { AsIntValues = V; }
1625ffd83dbSDimitry Andric };
1635ffd83dbSDimitry Andric struct StructFieldInfo {
1645ffd83dbSDimitry Andric   std::vector<StructInitializer> Initializers;
1655ffd83dbSDimitry Andric   StructInfo Structure;
1665ffd83dbSDimitry Andric 
1675ffd83dbSDimitry Andric   StructFieldInfo() = default;
168*bdd1243dSDimitry Andric   StructFieldInfo(std::vector<StructInitializer> V, StructInfo S);
1695ffd83dbSDimitry Andric };
1705ffd83dbSDimitry Andric 
1715ffd83dbSDimitry Andric class FieldInitializer {
1725ffd83dbSDimitry Andric public:
1735ffd83dbSDimitry Andric   FieldType FT;
1745ffd83dbSDimitry Andric   union {
1755ffd83dbSDimitry Andric     IntFieldInfo IntInfo;
1765ffd83dbSDimitry Andric     RealFieldInfo RealInfo;
1775ffd83dbSDimitry Andric     StructFieldInfo StructInfo;
1785ffd83dbSDimitry Andric   };
1795ffd83dbSDimitry Andric 
180*bdd1243dSDimitry Andric   ~FieldInitializer();
181*bdd1243dSDimitry Andric   FieldInitializer(FieldType FT);
1825ffd83dbSDimitry Andric 
183*bdd1243dSDimitry Andric   FieldInitializer(SmallVector<const MCExpr *, 1> &&Values);
184*bdd1243dSDimitry Andric   FieldInitializer(SmallVector<APInt, 1> &&AsIntValues);
1855ffd83dbSDimitry Andric   FieldInitializer(std::vector<StructInitializer> &&Initializers,
186*bdd1243dSDimitry Andric                    struct StructInfo Structure);
1875ffd83dbSDimitry Andric 
188*bdd1243dSDimitry Andric   FieldInitializer(const FieldInitializer &Initializer);
189*bdd1243dSDimitry Andric   FieldInitializer(FieldInitializer &&Initializer);
1905ffd83dbSDimitry Andric 
191*bdd1243dSDimitry Andric   FieldInitializer &operator=(const FieldInitializer &Initializer);
192*bdd1243dSDimitry Andric   FieldInitializer &operator=(FieldInitializer &&Initializer);
1935ffd83dbSDimitry Andric };
1945ffd83dbSDimitry Andric 
1955ffd83dbSDimitry Andric struct StructInitializer {
1965ffd83dbSDimitry Andric   std::vector<FieldInitializer> FieldInitializers;
1975ffd83dbSDimitry Andric };
1985ffd83dbSDimitry Andric 
1995ffd83dbSDimitry Andric struct FieldInfo {
2005ffd83dbSDimitry Andric   // Offset of the field within the containing STRUCT.
201fe6060f1SDimitry Andric   unsigned Offset = 0;
2025ffd83dbSDimitry Andric 
2035ffd83dbSDimitry Andric   // Total size of the field (= LengthOf * Type).
204e8d8bef9SDimitry Andric   unsigned SizeOf = 0;
2055ffd83dbSDimitry Andric 
2065ffd83dbSDimitry Andric   // Number of elements in the field (1 if scalar, >1 if an array).
207e8d8bef9SDimitry Andric   unsigned LengthOf = 0;
2085ffd83dbSDimitry Andric 
2095ffd83dbSDimitry Andric   // Size of a single entry in this field, in bytes ("type" in MASM standards).
210e8d8bef9SDimitry Andric   unsigned Type = 0;
2115ffd83dbSDimitry Andric 
2125ffd83dbSDimitry Andric   FieldInitializer Contents;
2135ffd83dbSDimitry Andric 
2145ffd83dbSDimitry Andric   FieldInfo(FieldType FT) : Contents(FT) {}
2155ffd83dbSDimitry Andric };
2165ffd83dbSDimitry Andric 
217*bdd1243dSDimitry Andric StructFieldInfo::StructFieldInfo(std::vector<StructInitializer> V,
218*bdd1243dSDimitry Andric                                  StructInfo S) {
219*bdd1243dSDimitry Andric   Initializers = std::move(V);
220*bdd1243dSDimitry Andric   Structure = S;
221*bdd1243dSDimitry Andric }
222*bdd1243dSDimitry Andric 
223*bdd1243dSDimitry Andric StructInfo::StructInfo(StringRef StructName, bool Union,
224*bdd1243dSDimitry Andric                        unsigned AlignmentValue)
225*bdd1243dSDimitry Andric     : Name(StructName), IsUnion(Union), Alignment(AlignmentValue) {}
226*bdd1243dSDimitry Andric 
227e8d8bef9SDimitry Andric FieldInfo &StructInfo::addField(StringRef FieldName, FieldType FT,
228e8d8bef9SDimitry Andric                                 unsigned FieldAlignmentSize) {
2295ffd83dbSDimitry Andric   if (!FieldName.empty())
230e8d8bef9SDimitry Andric     FieldsByName[FieldName.lower()] = Fields.size();
2315ffd83dbSDimitry Andric   Fields.emplace_back(FT);
2325ffd83dbSDimitry Andric   FieldInfo &Field = Fields.back();
233fe6060f1SDimitry Andric   Field.Offset =
234fe6060f1SDimitry Andric       llvm::alignTo(NextOffset, std::min(Alignment, FieldAlignmentSize));
235fe6060f1SDimitry Andric   if (!IsUnion) {
236fe6060f1SDimitry Andric     NextOffset = std::max(NextOffset, Field.Offset);
2375ffd83dbSDimitry Andric   }
238e8d8bef9SDimitry Andric   AlignmentSize = std::max(AlignmentSize, FieldAlignmentSize);
2395ffd83dbSDimitry Andric   return Field;
2405ffd83dbSDimitry Andric }
2415ffd83dbSDimitry Andric 
242*bdd1243dSDimitry Andric FieldInitializer::~FieldInitializer() {
243*bdd1243dSDimitry Andric   switch (FT) {
244*bdd1243dSDimitry Andric   case FT_INTEGRAL:
245*bdd1243dSDimitry Andric     IntInfo.~IntFieldInfo();
246*bdd1243dSDimitry Andric     break;
247*bdd1243dSDimitry Andric   case FT_REAL:
248*bdd1243dSDimitry Andric     RealInfo.~RealFieldInfo();
249*bdd1243dSDimitry Andric     break;
250*bdd1243dSDimitry Andric   case FT_STRUCT:
251*bdd1243dSDimitry Andric     StructInfo.~StructFieldInfo();
252*bdd1243dSDimitry Andric     break;
253*bdd1243dSDimitry Andric   }
254*bdd1243dSDimitry Andric }
255*bdd1243dSDimitry Andric 
256*bdd1243dSDimitry Andric FieldInitializer::FieldInitializer(FieldType FT) : FT(FT) {
257*bdd1243dSDimitry Andric   switch (FT) {
258*bdd1243dSDimitry Andric   case FT_INTEGRAL:
259*bdd1243dSDimitry Andric     new (&IntInfo) IntFieldInfo();
260*bdd1243dSDimitry Andric     break;
261*bdd1243dSDimitry Andric   case FT_REAL:
262*bdd1243dSDimitry Andric     new (&RealInfo) RealFieldInfo();
263*bdd1243dSDimitry Andric     break;
264*bdd1243dSDimitry Andric   case FT_STRUCT:
265*bdd1243dSDimitry Andric     new (&StructInfo) StructFieldInfo();
266*bdd1243dSDimitry Andric     break;
267*bdd1243dSDimitry Andric   }
268*bdd1243dSDimitry Andric }
269*bdd1243dSDimitry Andric 
270*bdd1243dSDimitry Andric FieldInitializer::FieldInitializer(SmallVector<const MCExpr *, 1> &&Values)
271*bdd1243dSDimitry Andric     : FT(FT_INTEGRAL) {
272*bdd1243dSDimitry Andric   new (&IntInfo) IntFieldInfo(Values);
273*bdd1243dSDimitry Andric }
274*bdd1243dSDimitry Andric 
275*bdd1243dSDimitry Andric FieldInitializer::FieldInitializer(SmallVector<APInt, 1> &&AsIntValues)
276*bdd1243dSDimitry Andric     : FT(FT_REAL) {
277*bdd1243dSDimitry Andric   new (&RealInfo) RealFieldInfo(AsIntValues);
278*bdd1243dSDimitry Andric }
279*bdd1243dSDimitry Andric 
280*bdd1243dSDimitry Andric FieldInitializer::FieldInitializer(
281*bdd1243dSDimitry Andric     std::vector<StructInitializer> &&Initializers, struct StructInfo Structure)
282*bdd1243dSDimitry Andric     : FT(FT_STRUCT) {
283*bdd1243dSDimitry Andric   new (&StructInfo) StructFieldInfo(std::move(Initializers), Structure);
284*bdd1243dSDimitry Andric }
285*bdd1243dSDimitry Andric 
286*bdd1243dSDimitry Andric FieldInitializer::FieldInitializer(const FieldInitializer &Initializer)
287*bdd1243dSDimitry Andric     : FT(Initializer.FT) {
288*bdd1243dSDimitry Andric   switch (FT) {
289*bdd1243dSDimitry Andric   case FT_INTEGRAL:
290*bdd1243dSDimitry Andric     new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
291*bdd1243dSDimitry Andric     break;
292*bdd1243dSDimitry Andric   case FT_REAL:
293*bdd1243dSDimitry Andric     new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
294*bdd1243dSDimitry Andric     break;
295*bdd1243dSDimitry Andric   case FT_STRUCT:
296*bdd1243dSDimitry Andric     new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
297*bdd1243dSDimitry Andric     break;
298*bdd1243dSDimitry Andric   }
299*bdd1243dSDimitry Andric }
300*bdd1243dSDimitry Andric 
301*bdd1243dSDimitry Andric FieldInitializer::FieldInitializer(FieldInitializer &&Initializer)
302*bdd1243dSDimitry Andric     : FT(Initializer.FT) {
303*bdd1243dSDimitry Andric   switch (FT) {
304*bdd1243dSDimitry Andric   case FT_INTEGRAL:
305*bdd1243dSDimitry Andric     new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
306*bdd1243dSDimitry Andric     break;
307*bdd1243dSDimitry Andric   case FT_REAL:
308*bdd1243dSDimitry Andric     new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
309*bdd1243dSDimitry Andric     break;
310*bdd1243dSDimitry Andric   case FT_STRUCT:
311*bdd1243dSDimitry Andric     new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
312*bdd1243dSDimitry Andric     break;
313*bdd1243dSDimitry Andric   }
314*bdd1243dSDimitry Andric }
315*bdd1243dSDimitry Andric 
316*bdd1243dSDimitry Andric FieldInitializer &
317*bdd1243dSDimitry Andric FieldInitializer::operator=(const FieldInitializer &Initializer) {
318*bdd1243dSDimitry Andric   if (FT != Initializer.FT) {
319*bdd1243dSDimitry Andric     switch (FT) {
320*bdd1243dSDimitry Andric     case FT_INTEGRAL:
321*bdd1243dSDimitry Andric       IntInfo.~IntFieldInfo();
322*bdd1243dSDimitry Andric       break;
323*bdd1243dSDimitry Andric     case FT_REAL:
324*bdd1243dSDimitry Andric       RealInfo.~RealFieldInfo();
325*bdd1243dSDimitry Andric       break;
326*bdd1243dSDimitry Andric     case FT_STRUCT:
327*bdd1243dSDimitry Andric       StructInfo.~StructFieldInfo();
328*bdd1243dSDimitry Andric       break;
329*bdd1243dSDimitry Andric     }
330*bdd1243dSDimitry Andric   }
331*bdd1243dSDimitry Andric   FT = Initializer.FT;
332*bdd1243dSDimitry Andric   switch (FT) {
333*bdd1243dSDimitry Andric   case FT_INTEGRAL:
334*bdd1243dSDimitry Andric     IntInfo = Initializer.IntInfo;
335*bdd1243dSDimitry Andric     break;
336*bdd1243dSDimitry Andric   case FT_REAL:
337*bdd1243dSDimitry Andric     RealInfo = Initializer.RealInfo;
338*bdd1243dSDimitry Andric     break;
339*bdd1243dSDimitry Andric   case FT_STRUCT:
340*bdd1243dSDimitry Andric     StructInfo = Initializer.StructInfo;
341*bdd1243dSDimitry Andric     break;
342*bdd1243dSDimitry Andric   }
343*bdd1243dSDimitry Andric   return *this;
344*bdd1243dSDimitry Andric }
345*bdd1243dSDimitry Andric 
346*bdd1243dSDimitry Andric FieldInitializer &FieldInitializer::operator=(FieldInitializer &&Initializer) {
347*bdd1243dSDimitry Andric   if (FT != Initializer.FT) {
348*bdd1243dSDimitry Andric     switch (FT) {
349*bdd1243dSDimitry Andric     case FT_INTEGRAL:
350*bdd1243dSDimitry Andric       IntInfo.~IntFieldInfo();
351*bdd1243dSDimitry Andric       break;
352*bdd1243dSDimitry Andric     case FT_REAL:
353*bdd1243dSDimitry Andric       RealInfo.~RealFieldInfo();
354*bdd1243dSDimitry Andric       break;
355*bdd1243dSDimitry Andric     case FT_STRUCT:
356*bdd1243dSDimitry Andric       StructInfo.~StructFieldInfo();
357*bdd1243dSDimitry Andric       break;
358*bdd1243dSDimitry Andric     }
359*bdd1243dSDimitry Andric   }
360*bdd1243dSDimitry Andric   FT = Initializer.FT;
361*bdd1243dSDimitry Andric   switch (FT) {
362*bdd1243dSDimitry Andric   case FT_INTEGRAL:
363*bdd1243dSDimitry Andric     IntInfo = Initializer.IntInfo;
364*bdd1243dSDimitry Andric     break;
365*bdd1243dSDimitry Andric   case FT_REAL:
366*bdd1243dSDimitry Andric     RealInfo = Initializer.RealInfo;
367*bdd1243dSDimitry Andric     break;
368*bdd1243dSDimitry Andric   case FT_STRUCT:
369*bdd1243dSDimitry Andric     StructInfo = Initializer.StructInfo;
370*bdd1243dSDimitry Andric     break;
371*bdd1243dSDimitry Andric   }
372*bdd1243dSDimitry Andric   return *this;
373*bdd1243dSDimitry Andric }
374*bdd1243dSDimitry Andric 
3755ffd83dbSDimitry Andric /// The concrete assembly parser instance.
3765ffd83dbSDimitry Andric // Note that this is a full MCAsmParser, not an MCAsmParserExtension!
3775ffd83dbSDimitry Andric // It's a peer of AsmParser, not of COFFAsmParser, WasmAsmParser, etc.
3785ffd83dbSDimitry Andric class MasmParser : public MCAsmParser {
3795ffd83dbSDimitry Andric private:
3805ffd83dbSDimitry Andric   AsmLexer Lexer;
3815ffd83dbSDimitry Andric   MCContext &Ctx;
3825ffd83dbSDimitry Andric   MCStreamer &Out;
3835ffd83dbSDimitry Andric   const MCAsmInfo &MAI;
3845ffd83dbSDimitry Andric   SourceMgr &SrcMgr;
3855ffd83dbSDimitry Andric   SourceMgr::DiagHandlerTy SavedDiagHandler;
3865ffd83dbSDimitry Andric   void *SavedDiagContext;
3875ffd83dbSDimitry Andric   std::unique_ptr<MCAsmParserExtension> PlatformParser;
3885ffd83dbSDimitry Andric 
3895ffd83dbSDimitry Andric   /// This is the current buffer index we're lexing from as managed by the
3905ffd83dbSDimitry Andric   /// SourceMgr object.
3915ffd83dbSDimitry Andric   unsigned CurBuffer;
392fe6060f1SDimitry Andric 
393fe6060f1SDimitry Andric   /// time of assembly
394fe6060f1SDimitry Andric   struct tm TM;
395fe6060f1SDimitry Andric 
39604eeddc0SDimitry Andric   BitVector EndStatementAtEOFStack;
3975ffd83dbSDimitry Andric 
3985ffd83dbSDimitry Andric   AsmCond TheCondState;
3995ffd83dbSDimitry Andric   std::vector<AsmCond> TheCondStack;
4005ffd83dbSDimitry Andric 
4015ffd83dbSDimitry Andric   /// maps directive names to handler methods in parser
4025ffd83dbSDimitry Andric   /// extensions. Extensions register themselves in this map by calling
4035ffd83dbSDimitry Andric   /// addDirectiveHandler.
4045ffd83dbSDimitry Andric   StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
4055ffd83dbSDimitry Andric 
4065ffd83dbSDimitry Andric   /// maps assembly-time variable names to variables.
4075ffd83dbSDimitry Andric   struct Variable {
408fe6060f1SDimitry Andric     enum RedefinableKind { NOT_REDEFINABLE, WARN_ON_REDEFINITION, REDEFINABLE };
409fe6060f1SDimitry Andric 
4105ffd83dbSDimitry Andric     StringRef Name;
411fe6060f1SDimitry Andric     RedefinableKind Redefinable = REDEFINABLE;
4125ffd83dbSDimitry Andric     bool IsText = false;
4135ffd83dbSDimitry Andric     std::string TextValue;
4145ffd83dbSDimitry Andric   };
4155ffd83dbSDimitry Andric   StringMap<Variable> Variables;
4165ffd83dbSDimitry Andric 
4175ffd83dbSDimitry Andric   /// Stack of active struct definitions.
4185ffd83dbSDimitry Andric   SmallVector<StructInfo, 1> StructInProgress;
4195ffd83dbSDimitry Andric 
4205ffd83dbSDimitry Andric   /// Maps struct tags to struct definitions.
4215ffd83dbSDimitry Andric   StringMap<StructInfo> Structs;
4225ffd83dbSDimitry Andric 
423e8d8bef9SDimitry Andric   /// Maps data location names to types.
424e8d8bef9SDimitry Andric   StringMap<AsmTypeInfo> KnownType;
4255ffd83dbSDimitry Andric 
4265ffd83dbSDimitry Andric   /// Stack of active macro instantiations.
4275ffd83dbSDimitry Andric   std::vector<MacroInstantiation*> ActiveMacros;
4285ffd83dbSDimitry Andric 
4295ffd83dbSDimitry Andric   /// List of bodies of anonymous macros.
4305ffd83dbSDimitry Andric   std::deque<MCAsmMacro> MacroLikeBodies;
4315ffd83dbSDimitry Andric 
4325ffd83dbSDimitry Andric   /// Keeps track of how many .macro's have been instantiated.
4335ffd83dbSDimitry Andric   unsigned NumOfMacroInstantiations;
4345ffd83dbSDimitry Andric 
4355ffd83dbSDimitry Andric   /// The values from the last parsed cpp hash file line comment if any.
4365ffd83dbSDimitry Andric   struct CppHashInfoTy {
4375ffd83dbSDimitry Andric     StringRef Filename;
4385ffd83dbSDimitry Andric     int64_t LineNumber;
4395ffd83dbSDimitry Andric     SMLoc Loc;
4405ffd83dbSDimitry Andric     unsigned Buf;
44104eeddc0SDimitry Andric     CppHashInfoTy() : LineNumber(0), Buf(0) {}
4425ffd83dbSDimitry Andric   };
4435ffd83dbSDimitry Andric   CppHashInfoTy CppHashInfo;
4445ffd83dbSDimitry Andric 
4455ffd83dbSDimitry Andric   /// The filename from the first cpp hash file line comment, if any.
4465ffd83dbSDimitry Andric   StringRef FirstCppHashFilename;
4475ffd83dbSDimitry Andric 
4485ffd83dbSDimitry Andric   /// List of forward directional labels for diagnosis at the end.
4495ffd83dbSDimitry Andric   SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;
4505ffd83dbSDimitry Andric 
4515ffd83dbSDimitry Andric   /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
4525ffd83dbSDimitry Andric   /// Defaults to 1U, meaning Intel.
4535ffd83dbSDimitry Andric   unsigned AssemblerDialect = 1U;
4545ffd83dbSDimitry Andric 
4555ffd83dbSDimitry Andric   /// is Darwin compatibility enabled?
4565ffd83dbSDimitry Andric   bool IsDarwin = false;
4575ffd83dbSDimitry Andric 
4585ffd83dbSDimitry Andric   /// Are we parsing ms-style inline assembly?
4595ffd83dbSDimitry Andric   bool ParsingMSInlineAsm = false;
4605ffd83dbSDimitry Andric 
4615ffd83dbSDimitry Andric   /// Did we already inform the user about inconsistent MD5 usage?
4625ffd83dbSDimitry Andric   bool ReportedInconsistentMD5 = false;
4635ffd83dbSDimitry Andric 
4645ffd83dbSDimitry Andric   // Current <...> expression depth.
4655ffd83dbSDimitry Andric   unsigned AngleBracketDepth = 0U;
4665ffd83dbSDimitry Andric 
467e8d8bef9SDimitry Andric   // Number of locals defined.
468e8d8bef9SDimitry Andric   uint16_t LocalCounter = 0;
469e8d8bef9SDimitry Andric 
4705ffd83dbSDimitry Andric public:
4715ffd83dbSDimitry Andric   MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
472fe6060f1SDimitry Andric              const MCAsmInfo &MAI, struct tm TM, unsigned CB = 0);
4735ffd83dbSDimitry Andric   MasmParser(const MasmParser &) = delete;
4745ffd83dbSDimitry Andric   MasmParser &operator=(const MasmParser &) = delete;
4755ffd83dbSDimitry Andric   ~MasmParser() override;
4765ffd83dbSDimitry Andric 
4775ffd83dbSDimitry Andric   bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
4785ffd83dbSDimitry Andric 
4795ffd83dbSDimitry Andric   void addDirectiveHandler(StringRef Directive,
4805ffd83dbSDimitry Andric                            ExtensionDirectiveHandler Handler) override {
4815ffd83dbSDimitry Andric     ExtensionDirectiveMap[Directive] = Handler;
4825ffd83dbSDimitry Andric     if (DirectiveKindMap.find(Directive) == DirectiveKindMap.end()) {
4835ffd83dbSDimitry Andric       DirectiveKindMap[Directive] = DK_HANDLER_DIRECTIVE;
4845ffd83dbSDimitry Andric     }
4855ffd83dbSDimitry Andric   }
4865ffd83dbSDimitry Andric 
4875ffd83dbSDimitry Andric   void addAliasForDirective(StringRef Directive, StringRef Alias) override {
4885ffd83dbSDimitry Andric     DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
4895ffd83dbSDimitry Andric   }
4905ffd83dbSDimitry Andric 
4915ffd83dbSDimitry Andric   /// @name MCAsmParser Interface
4925ffd83dbSDimitry Andric   /// {
4935ffd83dbSDimitry Andric 
4945ffd83dbSDimitry Andric   SourceMgr &getSourceManager() override { return SrcMgr; }
4955ffd83dbSDimitry Andric   MCAsmLexer &getLexer() override { return Lexer; }
4965ffd83dbSDimitry Andric   MCContext &getContext() override { return Ctx; }
4975ffd83dbSDimitry Andric   MCStreamer &getStreamer() override { return Out; }
4985ffd83dbSDimitry Andric 
4995ffd83dbSDimitry Andric   CodeViewContext &getCVContext() { return Ctx.getCVContext(); }
5005ffd83dbSDimitry Andric 
5015ffd83dbSDimitry Andric   unsigned getAssemblerDialect() override {
5025ffd83dbSDimitry Andric     if (AssemblerDialect == ~0U)
5035ffd83dbSDimitry Andric       return MAI.getAssemblerDialect();
5045ffd83dbSDimitry Andric     else
5055ffd83dbSDimitry Andric       return AssemblerDialect;
5065ffd83dbSDimitry Andric   }
5075ffd83dbSDimitry Andric   void setAssemblerDialect(unsigned i) override {
5085ffd83dbSDimitry Andric     AssemblerDialect = i;
5095ffd83dbSDimitry Andric   }
5105ffd83dbSDimitry Andric 
511*bdd1243dSDimitry Andric   void Note(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt) override;
512*bdd1243dSDimitry Andric   bool Warning(SMLoc L, const Twine &Msg,
513*bdd1243dSDimitry Andric                SMRange Range = std::nullopt) override;
514*bdd1243dSDimitry Andric   bool printError(SMLoc L, const Twine &Msg,
515*bdd1243dSDimitry Andric                   SMRange Range = std::nullopt) override;
5165ffd83dbSDimitry Andric 
517fe6060f1SDimitry Andric   enum ExpandKind { ExpandMacros, DoNotExpandMacros };
518fe6060f1SDimitry Andric   const AsmToken &Lex(ExpandKind ExpandNextToken);
519fe6060f1SDimitry Andric   const AsmToken &Lex() override { return Lex(ExpandMacros); }
5205ffd83dbSDimitry Andric 
5215ffd83dbSDimitry Andric   void setParsingMSInlineAsm(bool V) override {
5225ffd83dbSDimitry Andric     ParsingMSInlineAsm = V;
5235ffd83dbSDimitry Andric     // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and
5245ffd83dbSDimitry Andric     // hex integer literals.
5255ffd83dbSDimitry Andric     Lexer.setLexMasmIntegers(V);
5265ffd83dbSDimitry Andric   }
5275ffd83dbSDimitry Andric   bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
5285ffd83dbSDimitry Andric 
5295ffd83dbSDimitry Andric   bool isParsingMasm() const override { return true; }
5305ffd83dbSDimitry Andric 
531e8d8bef9SDimitry Andric   bool defineMacro(StringRef Name, StringRef Value) override;
532e8d8bef9SDimitry Andric 
533e8d8bef9SDimitry Andric   bool lookUpField(StringRef Name, AsmFieldInfo &Info) const override;
534e8d8bef9SDimitry Andric   bool lookUpField(StringRef Base, StringRef Member,
535e8d8bef9SDimitry Andric                    AsmFieldInfo &Info) const override;
536e8d8bef9SDimitry Andric 
537e8d8bef9SDimitry Andric   bool lookUpType(StringRef Name, AsmTypeInfo &Info) const override;
5385ffd83dbSDimitry Andric 
539fe6060f1SDimitry Andric   bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs,
540fe6060f1SDimitry Andric                         unsigned &NumInputs,
5415ffd83dbSDimitry Andric                         SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5425ffd83dbSDimitry Andric                         SmallVectorImpl<std::string> &Constraints,
5435ffd83dbSDimitry Andric                         SmallVectorImpl<std::string> &Clobbers,
5445ffd83dbSDimitry Andric                         const MCInstrInfo *MII, const MCInstPrinter *IP,
5455ffd83dbSDimitry Andric                         MCAsmParserSemaCallback &SI) override;
5465ffd83dbSDimitry Andric 
5475ffd83dbSDimitry Andric   bool parseExpression(const MCExpr *&Res);
5485ffd83dbSDimitry Andric   bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
549e8d8bef9SDimitry Andric   bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
550e8d8bef9SDimitry Andric                         AsmTypeInfo *TypeInfo) override;
5515ffd83dbSDimitry Andric   bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
5525ffd83dbSDimitry Andric   bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
5535ffd83dbSDimitry Andric                              SMLoc &EndLoc) override;
5545ffd83dbSDimitry Andric   bool parseAbsoluteExpression(int64_t &Res) override;
5555ffd83dbSDimitry Andric 
5565ffd83dbSDimitry Andric   /// Parse a floating point expression using the float \p Semantics
5575ffd83dbSDimitry Andric   /// and set \p Res to the value.
5585ffd83dbSDimitry Andric   bool parseRealValue(const fltSemantics &Semantics, APInt &Res);
5595ffd83dbSDimitry Andric 
5605ffd83dbSDimitry Andric   /// Parse an identifier or string (as a quoted identifier)
5615ffd83dbSDimitry Andric   /// and set \p Res to the identifier contents.
562fe6060f1SDimitry Andric   enum IdentifierPositionKind { StandardPosition, StartOfStatement };
563fe6060f1SDimitry Andric   bool parseIdentifier(StringRef &Res, IdentifierPositionKind Position);
564fe6060f1SDimitry Andric   bool parseIdentifier(StringRef &Res) override {
565fe6060f1SDimitry Andric     return parseIdentifier(Res, StandardPosition);
566fe6060f1SDimitry Andric   }
5675ffd83dbSDimitry Andric   void eatToEndOfStatement() override;
5685ffd83dbSDimitry Andric 
5695ffd83dbSDimitry Andric   bool checkForValidSection() override;
5705ffd83dbSDimitry Andric 
5715ffd83dbSDimitry Andric   /// }
5725ffd83dbSDimitry Andric 
5735ffd83dbSDimitry Andric private:
574fe6060f1SDimitry Andric   bool expandMacros();
575fe6060f1SDimitry Andric   const AsmToken peekTok(bool ShouldSkipSpace = true);
576fe6060f1SDimitry Andric 
5775ffd83dbSDimitry Andric   bool parseStatement(ParseStatementInfo &Info,
5785ffd83dbSDimitry Andric                       MCAsmParserSemaCallback *SI);
5795ffd83dbSDimitry Andric   bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
5805ffd83dbSDimitry Andric   bool parseCppHashLineFilenameComment(SMLoc L);
5815ffd83dbSDimitry Andric 
5825ffd83dbSDimitry Andric   bool expandMacro(raw_svector_ostream &OS, StringRef Body,
5835ffd83dbSDimitry Andric                    ArrayRef<MCAsmMacroParameter> Parameters,
584e8d8bef9SDimitry Andric                    ArrayRef<MCAsmMacroArgument> A,
585e8d8bef9SDimitry Andric                    const std::vector<std::string> &Locals, SMLoc L);
5865ffd83dbSDimitry Andric 
5875ffd83dbSDimitry Andric   /// Are we inside a macro instantiation?
5885ffd83dbSDimitry Andric   bool isInsideMacroInstantiation() {return !ActiveMacros.empty();}
5895ffd83dbSDimitry Andric 
5905ffd83dbSDimitry Andric   /// Handle entry to macro instantiation.
5915ffd83dbSDimitry Andric   ///
5925ffd83dbSDimitry Andric   /// \param M The macro.
5935ffd83dbSDimitry Andric   /// \param NameLoc Instantiation location.
594e8d8bef9SDimitry Andric   bool handleMacroEntry(
595e8d8bef9SDimitry Andric       const MCAsmMacro *M, SMLoc NameLoc,
596e8d8bef9SDimitry Andric       AsmToken::TokenKind ArgumentEndTok = AsmToken::EndOfStatement);
597e8d8bef9SDimitry Andric 
598e8d8bef9SDimitry Andric   /// Handle invocation of macro function.
599e8d8bef9SDimitry Andric   ///
600e8d8bef9SDimitry Andric   /// \param M The macro.
601e8d8bef9SDimitry Andric   /// \param NameLoc Invocation location.
602e8d8bef9SDimitry Andric   bool handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc);
6035ffd83dbSDimitry Andric 
6045ffd83dbSDimitry Andric   /// Handle exit from macro instantiation.
6055ffd83dbSDimitry Andric   void handleMacroExit();
6065ffd83dbSDimitry Andric 
6075ffd83dbSDimitry Andric   /// Extract AsmTokens for a macro argument.
608e8d8bef9SDimitry Andric   bool
609e8d8bef9SDimitry Andric   parseMacroArgument(const MCAsmMacroParameter *MP, MCAsmMacroArgument &MA,
610e8d8bef9SDimitry Andric                      AsmToken::TokenKind EndTok = AsmToken::EndOfStatement);
6115ffd83dbSDimitry Andric 
6125ffd83dbSDimitry Andric   /// Parse all macro arguments for a given macro.
613e8d8bef9SDimitry Andric   bool
614e8d8bef9SDimitry Andric   parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A,
615e8d8bef9SDimitry Andric                       AsmToken::TokenKind EndTok = AsmToken::EndOfStatement);
6165ffd83dbSDimitry Andric 
6175ffd83dbSDimitry Andric   void printMacroInstantiations();
618e8d8bef9SDimitry Andric 
619e8d8bef9SDimitry Andric   bool expandStatement(SMLoc Loc);
620e8d8bef9SDimitry Andric 
6215ffd83dbSDimitry Andric   void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
622*bdd1243dSDimitry Andric                     SMRange Range = std::nullopt) const {
6235ffd83dbSDimitry Andric     ArrayRef<SMRange> Ranges(Range);
6245ffd83dbSDimitry Andric     SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
6255ffd83dbSDimitry Andric   }
6265ffd83dbSDimitry Andric   static void DiagHandler(const SMDiagnostic &Diag, void *Context);
6275ffd83dbSDimitry Andric 
6285ffd83dbSDimitry Andric   bool lookUpField(const StructInfo &Structure, StringRef Member,
629e8d8bef9SDimitry Andric                    AsmFieldInfo &Info) const;
6305ffd83dbSDimitry Andric 
6315ffd83dbSDimitry Andric   /// Should we emit DWARF describing this assembler source?  (Returns false if
6325ffd83dbSDimitry Andric   /// the source has .file directives, which means we don't want to generate
6335ffd83dbSDimitry Andric   /// info describing the assembler source itself.)
6345ffd83dbSDimitry Andric   bool enabledGenDwarfForAssembly();
6355ffd83dbSDimitry Andric 
6365ffd83dbSDimitry Andric   /// Enter the specified file. This returns true on failure.
6375ffd83dbSDimitry Andric   bool enterIncludeFile(const std::string &Filename);
6385ffd83dbSDimitry Andric 
6395ffd83dbSDimitry Andric   /// Reset the current lexer position to that given by \p Loc. The
6405ffd83dbSDimitry Andric   /// current token is not set; clients should ensure Lex() is called
6415ffd83dbSDimitry Andric   /// subsequently.
6425ffd83dbSDimitry Andric   ///
6435ffd83dbSDimitry Andric   /// \param InBuffer If not 0, should be the known buffer id that contains the
6445ffd83dbSDimitry Andric   /// location.
645e8d8bef9SDimitry Andric   void jumpToLoc(SMLoc Loc, unsigned InBuffer = 0,
646e8d8bef9SDimitry Andric                  bool EndStatementAtEOF = true);
6475ffd83dbSDimitry Andric 
648e8d8bef9SDimitry Andric   /// Parse up to a token of kind \p EndTok and return the contents from the
649e8d8bef9SDimitry Andric   /// current token up to (but not including) this token; the current token on
650e8d8bef9SDimitry Andric   /// exit will be either this kind or EOF. Reads through instantiated macro
651e8d8bef9SDimitry Andric   /// functions and text macros.
652e8d8bef9SDimitry Andric   SmallVector<StringRef, 1> parseStringRefsTo(AsmToken::TokenKind EndTok);
653e8d8bef9SDimitry Andric   std::string parseStringTo(AsmToken::TokenKind EndTok);
654e8d8bef9SDimitry Andric 
655e8d8bef9SDimitry Andric   /// Parse up to the end of statement and return the contents from the current
656e8d8bef9SDimitry Andric   /// token until the end of the statement; the current token on exit will be
657e8d8bef9SDimitry Andric   /// either the EndOfStatement or EOF.
6585ffd83dbSDimitry Andric   StringRef parseStringToEndOfStatement() override;
6595ffd83dbSDimitry Andric 
6605ffd83dbSDimitry Andric   bool parseTextItem(std::string &Data);
6615ffd83dbSDimitry Andric 
6625ffd83dbSDimitry Andric   unsigned getBinOpPrecedence(AsmToken::TokenKind K,
6635ffd83dbSDimitry Andric                               MCBinaryExpr::Opcode &Kind);
6645ffd83dbSDimitry Andric 
6655ffd83dbSDimitry Andric   bool parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
6665ffd83dbSDimitry Andric   bool parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
6675ffd83dbSDimitry Andric   bool parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
6685ffd83dbSDimitry Andric 
6695ffd83dbSDimitry Andric   bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc);
6705ffd83dbSDimitry Andric 
6715ffd83dbSDimitry Andric   bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName);
6725ffd83dbSDimitry Andric   bool parseCVFileId(int64_t &FileId, StringRef DirectiveName);
6735ffd83dbSDimitry Andric 
6745ffd83dbSDimitry Andric   // Generic (target and platform independent) directive parsing.
6755ffd83dbSDimitry Andric   enum DirectiveKind {
6765ffd83dbSDimitry Andric     DK_NO_DIRECTIVE, // Placeholder
6775ffd83dbSDimitry Andric     DK_HANDLER_DIRECTIVE,
6785ffd83dbSDimitry Andric     DK_ASSIGN,
6795ffd83dbSDimitry Andric     DK_EQU,
6805ffd83dbSDimitry Andric     DK_TEXTEQU,
6815ffd83dbSDimitry Andric     DK_ASCII,
6825ffd83dbSDimitry Andric     DK_ASCIZ,
6835ffd83dbSDimitry Andric     DK_STRING,
6845ffd83dbSDimitry Andric     DK_BYTE,
6855ffd83dbSDimitry Andric     DK_SBYTE,
6865ffd83dbSDimitry Andric     DK_WORD,
6875ffd83dbSDimitry Andric     DK_SWORD,
6885ffd83dbSDimitry Andric     DK_DWORD,
6895ffd83dbSDimitry Andric     DK_SDWORD,
6905ffd83dbSDimitry Andric     DK_FWORD,
6915ffd83dbSDimitry Andric     DK_QWORD,
6925ffd83dbSDimitry Andric     DK_SQWORD,
6935ffd83dbSDimitry Andric     DK_DB,
6945ffd83dbSDimitry Andric     DK_DD,
695e8d8bef9SDimitry Andric     DK_DF,
6965ffd83dbSDimitry Andric     DK_DQ,
6975ffd83dbSDimitry Andric     DK_DW,
6985ffd83dbSDimitry Andric     DK_REAL4,
6995ffd83dbSDimitry Andric     DK_REAL8,
700e8d8bef9SDimitry Andric     DK_REAL10,
7015ffd83dbSDimitry Andric     DK_ALIGN,
702fe6060f1SDimitry Andric     DK_EVEN,
7035ffd83dbSDimitry Andric     DK_ORG,
7045ffd83dbSDimitry Andric     DK_ENDR,
7055ffd83dbSDimitry Andric     DK_EXTERN,
7065ffd83dbSDimitry Andric     DK_PUBLIC,
7075ffd83dbSDimitry Andric     DK_COMM,
7085ffd83dbSDimitry Andric     DK_COMMENT,
7095ffd83dbSDimitry Andric     DK_INCLUDE,
710e8d8bef9SDimitry Andric     DK_REPEAT,
711e8d8bef9SDimitry Andric     DK_WHILE,
712e8d8bef9SDimitry Andric     DK_FOR,
713e8d8bef9SDimitry Andric     DK_FORC,
7145ffd83dbSDimitry Andric     DK_IF,
7155ffd83dbSDimitry Andric     DK_IFE,
7165ffd83dbSDimitry Andric     DK_IFB,
7175ffd83dbSDimitry Andric     DK_IFNB,
7185ffd83dbSDimitry Andric     DK_IFDEF,
7195ffd83dbSDimitry Andric     DK_IFNDEF,
7205ffd83dbSDimitry Andric     DK_IFDIF,
7215ffd83dbSDimitry Andric     DK_IFDIFI,
7225ffd83dbSDimitry Andric     DK_IFIDN,
7235ffd83dbSDimitry Andric     DK_IFIDNI,
7245ffd83dbSDimitry Andric     DK_ELSEIF,
7255ffd83dbSDimitry Andric     DK_ELSEIFE,
7265ffd83dbSDimitry Andric     DK_ELSEIFB,
7275ffd83dbSDimitry Andric     DK_ELSEIFNB,
7285ffd83dbSDimitry Andric     DK_ELSEIFDEF,
7295ffd83dbSDimitry Andric     DK_ELSEIFNDEF,
7305ffd83dbSDimitry Andric     DK_ELSEIFDIF,
7315ffd83dbSDimitry Andric     DK_ELSEIFDIFI,
7325ffd83dbSDimitry Andric     DK_ELSEIFIDN,
7335ffd83dbSDimitry Andric     DK_ELSEIFIDNI,
7345ffd83dbSDimitry Andric     DK_ELSE,
7355ffd83dbSDimitry Andric     DK_ENDIF,
7365ffd83dbSDimitry Andric     DK_FILE,
7375ffd83dbSDimitry Andric     DK_LINE,
7385ffd83dbSDimitry Andric     DK_LOC,
7395ffd83dbSDimitry Andric     DK_STABS,
7405ffd83dbSDimitry Andric     DK_CV_FILE,
7415ffd83dbSDimitry Andric     DK_CV_FUNC_ID,
7425ffd83dbSDimitry Andric     DK_CV_INLINE_SITE_ID,
7435ffd83dbSDimitry Andric     DK_CV_LOC,
7445ffd83dbSDimitry Andric     DK_CV_LINETABLE,
7455ffd83dbSDimitry Andric     DK_CV_INLINE_LINETABLE,
7465ffd83dbSDimitry Andric     DK_CV_DEF_RANGE,
7475ffd83dbSDimitry Andric     DK_CV_STRINGTABLE,
7485ffd83dbSDimitry Andric     DK_CV_STRING,
7495ffd83dbSDimitry Andric     DK_CV_FILECHECKSUMS,
7505ffd83dbSDimitry Andric     DK_CV_FILECHECKSUM_OFFSET,
7515ffd83dbSDimitry Andric     DK_CV_FPO_DATA,
7525ffd83dbSDimitry Andric     DK_CFI_SECTIONS,
7535ffd83dbSDimitry Andric     DK_CFI_STARTPROC,
7545ffd83dbSDimitry Andric     DK_CFI_ENDPROC,
7555ffd83dbSDimitry Andric     DK_CFI_DEF_CFA,
7565ffd83dbSDimitry Andric     DK_CFI_DEF_CFA_OFFSET,
7575ffd83dbSDimitry Andric     DK_CFI_ADJUST_CFA_OFFSET,
7585ffd83dbSDimitry Andric     DK_CFI_DEF_CFA_REGISTER,
7595ffd83dbSDimitry Andric     DK_CFI_OFFSET,
7605ffd83dbSDimitry Andric     DK_CFI_REL_OFFSET,
7615ffd83dbSDimitry Andric     DK_CFI_PERSONALITY,
7625ffd83dbSDimitry Andric     DK_CFI_LSDA,
7635ffd83dbSDimitry Andric     DK_CFI_REMEMBER_STATE,
7645ffd83dbSDimitry Andric     DK_CFI_RESTORE_STATE,
7655ffd83dbSDimitry Andric     DK_CFI_SAME_VALUE,
7665ffd83dbSDimitry Andric     DK_CFI_RESTORE,
7675ffd83dbSDimitry Andric     DK_CFI_ESCAPE,
7685ffd83dbSDimitry Andric     DK_CFI_RETURN_COLUMN,
7695ffd83dbSDimitry Andric     DK_CFI_SIGNAL_FRAME,
7705ffd83dbSDimitry Andric     DK_CFI_UNDEFINED,
7715ffd83dbSDimitry Andric     DK_CFI_REGISTER,
7725ffd83dbSDimitry Andric     DK_CFI_WINDOW_SAVE,
7735ffd83dbSDimitry Andric     DK_CFI_B_KEY_FRAME,
7745ffd83dbSDimitry Andric     DK_MACRO,
7755ffd83dbSDimitry Andric     DK_EXITM,
7765ffd83dbSDimitry Andric     DK_ENDM,
777e8d8bef9SDimitry Andric     DK_PURGE,
7785ffd83dbSDimitry Andric     DK_ERR,
7795ffd83dbSDimitry Andric     DK_ERRB,
7805ffd83dbSDimitry Andric     DK_ERRNB,
7815ffd83dbSDimitry Andric     DK_ERRDEF,
7825ffd83dbSDimitry Andric     DK_ERRNDEF,
7835ffd83dbSDimitry Andric     DK_ERRDIF,
7845ffd83dbSDimitry Andric     DK_ERRDIFI,
7855ffd83dbSDimitry Andric     DK_ERRIDN,
7865ffd83dbSDimitry Andric     DK_ERRIDNI,
7875ffd83dbSDimitry Andric     DK_ERRE,
7885ffd83dbSDimitry Andric     DK_ERRNZ,
7895ffd83dbSDimitry Andric     DK_ECHO,
7905ffd83dbSDimitry Andric     DK_STRUCT,
7915ffd83dbSDimitry Andric     DK_UNION,
7925ffd83dbSDimitry Andric     DK_ENDS,
793e8d8bef9SDimitry Andric     DK_END,
794e8d8bef9SDimitry Andric     DK_PUSHFRAME,
795e8d8bef9SDimitry Andric     DK_PUSHREG,
796e8d8bef9SDimitry Andric     DK_SAVEREG,
797e8d8bef9SDimitry Andric     DK_SAVEXMM128,
798e8d8bef9SDimitry Andric     DK_SETFRAME,
799e8d8bef9SDimitry Andric     DK_RADIX,
8005ffd83dbSDimitry Andric   };
8015ffd83dbSDimitry Andric 
8025ffd83dbSDimitry Andric   /// Maps directive name --> DirectiveKind enum, for directives parsed by this
8035ffd83dbSDimitry Andric   /// class.
8045ffd83dbSDimitry Andric   StringMap<DirectiveKind> DirectiveKindMap;
8055ffd83dbSDimitry Andric 
806e8d8bef9SDimitry Andric   bool isMacroLikeDirective();
807e8d8bef9SDimitry Andric 
8085ffd83dbSDimitry Andric   // Codeview def_range type parsing.
8095ffd83dbSDimitry Andric   enum CVDefRangeType {
8105ffd83dbSDimitry Andric     CVDR_DEFRANGE = 0, // Placeholder
8115ffd83dbSDimitry Andric     CVDR_DEFRANGE_REGISTER,
8125ffd83dbSDimitry Andric     CVDR_DEFRANGE_FRAMEPOINTER_REL,
8135ffd83dbSDimitry Andric     CVDR_DEFRANGE_SUBFIELD_REGISTER,
8145ffd83dbSDimitry Andric     CVDR_DEFRANGE_REGISTER_REL
8155ffd83dbSDimitry Andric   };
8165ffd83dbSDimitry Andric 
8175ffd83dbSDimitry Andric   /// Maps Codeview def_range types --> CVDefRangeType enum, for Codeview
8185ffd83dbSDimitry Andric   /// def_range types parsed by this class.
8195ffd83dbSDimitry Andric   StringMap<CVDefRangeType> CVDefRangeTypeMap;
8205ffd83dbSDimitry Andric 
821fe6060f1SDimitry Andric   // Generic (target and platform independent) directive parsing.
822fe6060f1SDimitry Andric   enum BuiltinSymbol {
823fe6060f1SDimitry Andric     BI_NO_SYMBOL, // Placeholder
824fe6060f1SDimitry Andric     BI_DATE,
825fe6060f1SDimitry Andric     BI_TIME,
826fe6060f1SDimitry Andric     BI_VERSION,
827fe6060f1SDimitry Andric     BI_FILECUR,
828fe6060f1SDimitry Andric     BI_FILENAME,
829fe6060f1SDimitry Andric     BI_LINE,
830fe6060f1SDimitry Andric     BI_CURSEG,
831fe6060f1SDimitry Andric     BI_CPU,
832fe6060f1SDimitry Andric     BI_INTERFACE,
833fe6060f1SDimitry Andric     BI_CODE,
834fe6060f1SDimitry Andric     BI_DATA,
835fe6060f1SDimitry Andric     BI_FARDATA,
836fe6060f1SDimitry Andric     BI_WORDSIZE,
837fe6060f1SDimitry Andric     BI_CODESIZE,
838fe6060f1SDimitry Andric     BI_DATASIZE,
839fe6060f1SDimitry Andric     BI_MODEL,
840fe6060f1SDimitry Andric     BI_STACK,
841fe6060f1SDimitry Andric   };
842fe6060f1SDimitry Andric 
843fe6060f1SDimitry Andric   /// Maps builtin name --> BuiltinSymbol enum, for builtins handled by this
844fe6060f1SDimitry Andric   /// class.
845fe6060f1SDimitry Andric   StringMap<BuiltinSymbol> BuiltinSymbolMap;
846fe6060f1SDimitry Andric 
847fe6060f1SDimitry Andric   const MCExpr *evaluateBuiltinValue(BuiltinSymbol Symbol, SMLoc StartLoc);
848fe6060f1SDimitry Andric 
849*bdd1243dSDimitry Andric   std::optional<std::string> evaluateBuiltinTextMacro(BuiltinSymbol Symbol,
850fe6060f1SDimitry Andric                                                       SMLoc StartLoc);
851fe6060f1SDimitry Andric 
8525ffd83dbSDimitry Andric   // ".ascii", ".asciz", ".string"
8535ffd83dbSDimitry Andric   bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
8545ffd83dbSDimitry Andric 
8555ffd83dbSDimitry Andric   // "byte", "word", ...
8565ffd83dbSDimitry Andric   bool emitIntValue(const MCExpr *Value, unsigned Size);
8575ffd83dbSDimitry Andric   bool parseScalarInitializer(unsigned Size,
8585ffd83dbSDimitry Andric                               SmallVectorImpl<const MCExpr *> &Values,
8595ffd83dbSDimitry Andric                               unsigned StringPadLength = 0);
8605ffd83dbSDimitry Andric   bool parseScalarInstList(
8615ffd83dbSDimitry Andric       unsigned Size, SmallVectorImpl<const MCExpr *> &Values,
8625ffd83dbSDimitry Andric       const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
863e8d8bef9SDimitry Andric   bool emitIntegralValues(unsigned Size, unsigned *Count = nullptr);
8645ffd83dbSDimitry Andric   bool addIntegralField(StringRef Name, unsigned Size);
8655ffd83dbSDimitry Andric   bool parseDirectiveValue(StringRef IDVal, unsigned Size);
866e8d8bef9SDimitry Andric   bool parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
867e8d8bef9SDimitry Andric                                 StringRef Name, SMLoc NameLoc);
8685ffd83dbSDimitry Andric 
869e8d8bef9SDimitry Andric   // "real4", "real8", "real10"
870e8d8bef9SDimitry Andric   bool emitRealValues(const fltSemantics &Semantics, unsigned *Count = nullptr);
871e8d8bef9SDimitry Andric   bool addRealField(StringRef Name, const fltSemantics &Semantics, size_t Size);
872e8d8bef9SDimitry Andric   bool parseDirectiveRealValue(StringRef IDVal, const fltSemantics &Semantics,
873e8d8bef9SDimitry Andric                                size_t Size);
8745ffd83dbSDimitry Andric   bool parseRealInstList(
8755ffd83dbSDimitry Andric       const fltSemantics &Semantics, SmallVectorImpl<APInt> &Values,
8765ffd83dbSDimitry Andric       const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
877e8d8bef9SDimitry Andric   bool parseDirectiveNamedRealValue(StringRef TypeName,
8785ffd83dbSDimitry Andric                                     const fltSemantics &Semantics,
879e8d8bef9SDimitry Andric                                     unsigned Size, StringRef Name,
880e8d8bef9SDimitry Andric                                     SMLoc NameLoc);
8815ffd83dbSDimitry Andric 
8825ffd83dbSDimitry Andric   bool parseOptionalAngleBracketOpen();
8835ffd83dbSDimitry Andric   bool parseAngleBracketClose(const Twine &Msg = "expected '>'");
8845ffd83dbSDimitry Andric 
8855ffd83dbSDimitry Andric   bool parseFieldInitializer(const FieldInfo &Field,
8865ffd83dbSDimitry Andric                              FieldInitializer &Initializer);
8875ffd83dbSDimitry Andric   bool parseFieldInitializer(const FieldInfo &Field,
8885ffd83dbSDimitry Andric                              const IntFieldInfo &Contents,
8895ffd83dbSDimitry Andric                              FieldInitializer &Initializer);
8905ffd83dbSDimitry Andric   bool parseFieldInitializer(const FieldInfo &Field,
8915ffd83dbSDimitry Andric                              const RealFieldInfo &Contents,
8925ffd83dbSDimitry Andric                              FieldInitializer &Initializer);
8935ffd83dbSDimitry Andric   bool parseFieldInitializer(const FieldInfo &Field,
8945ffd83dbSDimitry Andric                              const StructFieldInfo &Contents,
8955ffd83dbSDimitry Andric                              FieldInitializer &Initializer);
8965ffd83dbSDimitry Andric 
8975ffd83dbSDimitry Andric   bool parseStructInitializer(const StructInfo &Structure,
8985ffd83dbSDimitry Andric                               StructInitializer &Initializer);
8995ffd83dbSDimitry Andric   bool parseStructInstList(
9005ffd83dbSDimitry Andric       const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
9015ffd83dbSDimitry Andric       const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
9025ffd83dbSDimitry Andric 
9035ffd83dbSDimitry Andric   bool emitFieldValue(const FieldInfo &Field);
9045ffd83dbSDimitry Andric   bool emitFieldValue(const FieldInfo &Field, const IntFieldInfo &Contents);
9055ffd83dbSDimitry Andric   bool emitFieldValue(const FieldInfo &Field, const RealFieldInfo &Contents);
9065ffd83dbSDimitry Andric   bool emitFieldValue(const FieldInfo &Field, const StructFieldInfo &Contents);
9075ffd83dbSDimitry Andric 
9085ffd83dbSDimitry Andric   bool emitFieldInitializer(const FieldInfo &Field,
9095ffd83dbSDimitry Andric                             const FieldInitializer &Initializer);
9105ffd83dbSDimitry Andric   bool emitFieldInitializer(const FieldInfo &Field,
9115ffd83dbSDimitry Andric                             const IntFieldInfo &Contents,
9125ffd83dbSDimitry Andric                             const IntFieldInfo &Initializer);
9135ffd83dbSDimitry Andric   bool emitFieldInitializer(const FieldInfo &Field,
9145ffd83dbSDimitry Andric                             const RealFieldInfo &Contents,
9155ffd83dbSDimitry Andric                             const RealFieldInfo &Initializer);
9165ffd83dbSDimitry Andric   bool emitFieldInitializer(const FieldInfo &Field,
9175ffd83dbSDimitry Andric                             const StructFieldInfo &Contents,
9185ffd83dbSDimitry Andric                             const StructFieldInfo &Initializer);
9195ffd83dbSDimitry Andric 
9205ffd83dbSDimitry Andric   bool emitStructInitializer(const StructInfo &Structure,
9215ffd83dbSDimitry Andric                              const StructInitializer &Initializer);
9225ffd83dbSDimitry Andric 
9235ffd83dbSDimitry Andric   // User-defined types (structs, unions):
924e8d8bef9SDimitry Andric   bool emitStructValues(const StructInfo &Structure, unsigned *Count = nullptr);
9255ffd83dbSDimitry Andric   bool addStructField(StringRef Name, const StructInfo &Structure);
9265ffd83dbSDimitry Andric   bool parseDirectiveStructValue(const StructInfo &Structure,
9275ffd83dbSDimitry Andric                                  StringRef Directive, SMLoc DirLoc);
9285ffd83dbSDimitry Andric   bool parseDirectiveNamedStructValue(const StructInfo &Structure,
9295ffd83dbSDimitry Andric                                       StringRef Directive, SMLoc DirLoc,
9305ffd83dbSDimitry Andric                                       StringRef Name);
9315ffd83dbSDimitry Andric 
9325ffd83dbSDimitry Andric   // "=", "equ", "textequ"
9335ffd83dbSDimitry Andric   bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
934fe6060f1SDimitry Andric                             DirectiveKind DirKind, SMLoc NameLoc);
9355ffd83dbSDimitry Andric 
936fe6060f1SDimitry Andric   bool parseDirectiveOrg(); // "org"
937fe6060f1SDimitry Andric 
938fe6060f1SDimitry Andric   bool emitAlignTo(int64_t Alignment);
9395ffd83dbSDimitry Andric   bool parseDirectiveAlign();  // "align"
940fe6060f1SDimitry Andric   bool parseDirectiveEven();   // "even"
9415ffd83dbSDimitry Andric 
9425ffd83dbSDimitry Andric   // ".file", ".line", ".loc", ".stabs"
9435ffd83dbSDimitry Andric   bool parseDirectiveFile(SMLoc DirectiveLoc);
9445ffd83dbSDimitry Andric   bool parseDirectiveLine();
9455ffd83dbSDimitry Andric   bool parseDirectiveLoc();
9465ffd83dbSDimitry Andric   bool parseDirectiveStabs();
9475ffd83dbSDimitry Andric 
9485ffd83dbSDimitry Andric   // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
9495ffd83dbSDimitry Andric   // ".cv_inline_linetable", ".cv_def_range", ".cv_string"
9505ffd83dbSDimitry Andric   bool parseDirectiveCVFile();
9515ffd83dbSDimitry Andric   bool parseDirectiveCVFuncId();
9525ffd83dbSDimitry Andric   bool parseDirectiveCVInlineSiteId();
9535ffd83dbSDimitry Andric   bool parseDirectiveCVLoc();
9545ffd83dbSDimitry Andric   bool parseDirectiveCVLinetable();
9555ffd83dbSDimitry Andric   bool parseDirectiveCVInlineLinetable();
9565ffd83dbSDimitry Andric   bool parseDirectiveCVDefRange();
9575ffd83dbSDimitry Andric   bool parseDirectiveCVString();
9585ffd83dbSDimitry Andric   bool parseDirectiveCVStringTable();
9595ffd83dbSDimitry Andric   bool parseDirectiveCVFileChecksums();
9605ffd83dbSDimitry Andric   bool parseDirectiveCVFileChecksumOffset();
9615ffd83dbSDimitry Andric   bool parseDirectiveCVFPOData();
9625ffd83dbSDimitry Andric 
9635ffd83dbSDimitry Andric   // .cfi directives
9645ffd83dbSDimitry Andric   bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
9655ffd83dbSDimitry Andric   bool parseDirectiveCFIWindowSave();
9665ffd83dbSDimitry Andric   bool parseDirectiveCFISections();
9675ffd83dbSDimitry Andric   bool parseDirectiveCFIStartProc();
9685ffd83dbSDimitry Andric   bool parseDirectiveCFIEndProc();
9695ffd83dbSDimitry Andric   bool parseDirectiveCFIDefCfaOffset();
9705ffd83dbSDimitry Andric   bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
9715ffd83dbSDimitry Andric   bool parseDirectiveCFIAdjustCfaOffset();
9725ffd83dbSDimitry Andric   bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
9735ffd83dbSDimitry Andric   bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);
9745ffd83dbSDimitry Andric   bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
9755ffd83dbSDimitry Andric   bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
9765ffd83dbSDimitry Andric   bool parseDirectiveCFIRememberState();
9775ffd83dbSDimitry Andric   bool parseDirectiveCFIRestoreState();
9785ffd83dbSDimitry Andric   bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
9795ffd83dbSDimitry Andric   bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
9805ffd83dbSDimitry Andric   bool parseDirectiveCFIEscape();
9815ffd83dbSDimitry Andric   bool parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc);
9825ffd83dbSDimitry Andric   bool parseDirectiveCFISignalFrame();
9835ffd83dbSDimitry Andric   bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc);
9845ffd83dbSDimitry Andric 
9855ffd83dbSDimitry Andric   // macro directives
9865ffd83dbSDimitry Andric   bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
987e8d8bef9SDimitry Andric   bool parseDirectiveExitMacro(SMLoc DirectiveLoc, StringRef Directive,
988e8d8bef9SDimitry Andric                                std::string &Value);
9895ffd83dbSDimitry Andric   bool parseDirectiveEndMacro(StringRef Directive);
990e8d8bef9SDimitry Andric   bool parseDirectiveMacro(StringRef Name, SMLoc NameLoc);
9915ffd83dbSDimitry Andric 
9925ffd83dbSDimitry Andric   bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind,
9935ffd83dbSDimitry Andric                             StringRef Name, SMLoc NameLoc);
9945ffd83dbSDimitry Andric   bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind);
9955ffd83dbSDimitry Andric   bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
9965ffd83dbSDimitry Andric   bool parseDirectiveNestedEnds();
9975ffd83dbSDimitry Andric 
99881ad6265SDimitry Andric   bool parseDirectiveExtern();
99981ad6265SDimitry Andric 
10005ffd83dbSDimitry Andric   /// Parse a directive like ".globl" which accepts a single symbol (which
10015ffd83dbSDimitry Andric   /// should be a label or an external).
10025ffd83dbSDimitry Andric   bool parseDirectiveSymbolAttribute(MCSymbolAttr Attr);
10035ffd83dbSDimitry Andric 
10045ffd83dbSDimitry Andric   bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
10055ffd83dbSDimitry Andric 
10065ffd83dbSDimitry Andric   bool parseDirectiveComment(SMLoc DirectiveLoc); // "comment"
10075ffd83dbSDimitry Andric 
10085ffd83dbSDimitry Andric   bool parseDirectiveInclude(); // "include"
10095ffd83dbSDimitry Andric 
10105ffd83dbSDimitry Andric   // "if" or "ife"
10115ffd83dbSDimitry Andric   bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
10125ffd83dbSDimitry Andric   // "ifb" or "ifnb", depending on ExpectBlank.
10135ffd83dbSDimitry Andric   bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
10145ffd83dbSDimitry Andric   // "ifidn", "ifdif", "ifidni", or "ifdifi", depending on ExpectEqual and
10155ffd83dbSDimitry Andric   // CaseInsensitive.
10165ffd83dbSDimitry Andric   bool parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
10175ffd83dbSDimitry Andric                            bool CaseInsensitive);
10185ffd83dbSDimitry Andric   // "ifdef" or "ifndef", depending on expect_defined
10195ffd83dbSDimitry Andric   bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
10205ffd83dbSDimitry Andric   // "elseif" or "elseife"
10215ffd83dbSDimitry Andric   bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
10225ffd83dbSDimitry Andric   // "elseifb" or "elseifnb", depending on ExpectBlank.
10235ffd83dbSDimitry Andric   bool parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank);
10245ffd83dbSDimitry Andric   // ".elseifdef" or ".elseifndef", depending on expect_defined
10255ffd83dbSDimitry Andric   bool parseDirectiveElseIfdef(SMLoc DirectiveLoc, bool expect_defined);
10265ffd83dbSDimitry Andric   // "elseifidn", "elseifdif", "elseifidni", or "elseifdifi", depending on
10275ffd83dbSDimitry Andric   // ExpectEqual and CaseInsensitive.
10285ffd83dbSDimitry Andric   bool parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
10295ffd83dbSDimitry Andric                                bool CaseInsensitive);
10305ffd83dbSDimitry Andric   bool parseDirectiveElse(SMLoc DirectiveLoc);   // "else"
10315ffd83dbSDimitry Andric   bool parseDirectiveEndIf(SMLoc DirectiveLoc);  // "endif"
10325ffd83dbSDimitry Andric   bool parseEscapedString(std::string &Data) override;
10335ffd83dbSDimitry Andric   bool parseAngleBracketString(std::string &Data) override;
10345ffd83dbSDimitry Andric 
10355ffd83dbSDimitry Andric   // Macro-like directives
10365ffd83dbSDimitry Andric   MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
10375ffd83dbSDimitry Andric   void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
10385ffd83dbSDimitry Andric                                 raw_svector_ostream &OS);
1039e8d8bef9SDimitry Andric   void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
1040e8d8bef9SDimitry Andric                                 SMLoc ExitLoc, raw_svector_ostream &OS);
1041e8d8bef9SDimitry Andric   bool parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Directive);
1042e8d8bef9SDimitry Andric   bool parseDirectiveFor(SMLoc DirectiveLoc, StringRef Directive);
1043e8d8bef9SDimitry Andric   bool parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive);
1044e8d8bef9SDimitry Andric   bool parseDirectiveWhile(SMLoc DirectiveLoc);
10455ffd83dbSDimitry Andric 
10465ffd83dbSDimitry Andric   // "_emit" or "__emit"
10475ffd83dbSDimitry Andric   bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
10485ffd83dbSDimitry Andric                             size_t Len);
10495ffd83dbSDimitry Andric 
10505ffd83dbSDimitry Andric   // "align"
10515ffd83dbSDimitry Andric   bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
10525ffd83dbSDimitry Andric 
10535ffd83dbSDimitry Andric   // "end"
10545ffd83dbSDimitry Andric   bool parseDirectiveEnd(SMLoc DirectiveLoc);
10555ffd83dbSDimitry Andric 
10565ffd83dbSDimitry Andric   // ".err"
10575ffd83dbSDimitry Andric   bool parseDirectiveError(SMLoc DirectiveLoc);
10585ffd83dbSDimitry Andric   // ".errb" or ".errnb", depending on ExpectBlank.
10595ffd83dbSDimitry Andric   bool parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank);
10605ffd83dbSDimitry Andric   // ".errdef" or ".errndef", depending on ExpectBlank.
10615ffd83dbSDimitry Andric   bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc, bool ExpectDefined);
10625ffd83dbSDimitry Andric   // ".erridn", ".errdif", ".erridni", or ".errdifi", depending on ExpectEqual
10635ffd83dbSDimitry Andric   // and CaseInsensitive.
10645ffd83dbSDimitry Andric   bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
10655ffd83dbSDimitry Andric                                 bool CaseInsensitive);
10665ffd83dbSDimitry Andric   // ".erre" or ".errnz", depending on ExpectZero.
10675ffd83dbSDimitry Andric   bool parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero);
10685ffd83dbSDimitry Andric 
1069e8d8bef9SDimitry Andric   // ".radix"
1070e8d8bef9SDimitry Andric   bool parseDirectiveRadix(SMLoc DirectiveLoc);
1071e8d8bef9SDimitry Andric 
10725ffd83dbSDimitry Andric   // "echo"
1073fe6060f1SDimitry Andric   bool parseDirectiveEcho(SMLoc DirectiveLoc);
10745ffd83dbSDimitry Andric 
10755ffd83dbSDimitry Andric   void initializeDirectiveKindMap();
10765ffd83dbSDimitry Andric   void initializeCVDefRangeTypeMap();
1077fe6060f1SDimitry Andric   void initializeBuiltinSymbolMap();
10785ffd83dbSDimitry Andric };
10795ffd83dbSDimitry Andric 
10805ffd83dbSDimitry Andric } // end anonymous namespace
10815ffd83dbSDimitry Andric 
10825ffd83dbSDimitry Andric namespace llvm {
10835ffd83dbSDimitry Andric 
1084*bdd1243dSDimitry Andric extern cl::opt<unsigned> AsmMacroMaxNestingDepth;
1085*bdd1243dSDimitry Andric 
10865ffd83dbSDimitry Andric extern MCAsmParserExtension *createCOFFMasmParser();
10875ffd83dbSDimitry Andric 
10885ffd83dbSDimitry Andric } // end namespace llvm
10895ffd83dbSDimitry Andric 
10905ffd83dbSDimitry Andric enum { DEFAULT_ADDRSPACE = 0 };
10915ffd83dbSDimitry Andric 
10925ffd83dbSDimitry Andric MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
1093fe6060f1SDimitry Andric                        const MCAsmInfo &MAI, struct tm TM, unsigned CB)
10945ffd83dbSDimitry Andric     : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
1095fe6060f1SDimitry Andric       CurBuffer(CB ? CB : SM.getMainFileID()), TM(TM) {
10965ffd83dbSDimitry Andric   HadError = false;
10975ffd83dbSDimitry Andric   // Save the old handler.
10985ffd83dbSDimitry Andric   SavedDiagHandler = SrcMgr.getDiagHandler();
10995ffd83dbSDimitry Andric   SavedDiagContext = SrcMgr.getDiagContext();
11005ffd83dbSDimitry Andric   // Set our own handler which calls the saved handler.
11015ffd83dbSDimitry Andric   SrcMgr.setDiagHandler(DiagHandler, this);
11025ffd83dbSDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
1103e8d8bef9SDimitry Andric   EndStatementAtEOFStack.push_back(true);
11045ffd83dbSDimitry Andric 
11055ffd83dbSDimitry Andric   // Initialize the platform / file format parser.
1106fe6060f1SDimitry Andric   switch (Ctx.getObjectFileType()) {
1107fe6060f1SDimitry Andric   case MCContext::IsCOFF:
11085ffd83dbSDimitry Andric     PlatformParser.reset(createCOFFMasmParser());
11095ffd83dbSDimitry Andric     break;
11105ffd83dbSDimitry Andric   default:
11115ffd83dbSDimitry Andric     report_fatal_error("llvm-ml currently supports only COFF output.");
11125ffd83dbSDimitry Andric     break;
11135ffd83dbSDimitry Andric   }
11145ffd83dbSDimitry Andric 
11155ffd83dbSDimitry Andric   initializeDirectiveKindMap();
11165ffd83dbSDimitry Andric   PlatformParser->Initialize(*this);
11175ffd83dbSDimitry Andric   initializeCVDefRangeTypeMap();
1118fe6060f1SDimitry Andric   initializeBuiltinSymbolMap();
11195ffd83dbSDimitry Andric 
11205ffd83dbSDimitry Andric   NumOfMacroInstantiations = 0;
11215ffd83dbSDimitry Andric }
11225ffd83dbSDimitry Andric 
11235ffd83dbSDimitry Andric MasmParser::~MasmParser() {
11245ffd83dbSDimitry Andric   assert((HadError || ActiveMacros.empty()) &&
11255ffd83dbSDimitry Andric          "Unexpected active macro instantiation!");
11265ffd83dbSDimitry Andric 
11275ffd83dbSDimitry Andric   // Restore the saved diagnostics handler and context for use during
11285ffd83dbSDimitry Andric   // finalization.
11295ffd83dbSDimitry Andric   SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
11305ffd83dbSDimitry Andric }
11315ffd83dbSDimitry Andric 
11325ffd83dbSDimitry Andric void MasmParser::printMacroInstantiations() {
11335ffd83dbSDimitry Andric   // Print the active macro instantiation stack.
11345ffd83dbSDimitry Andric   for (std::vector<MacroInstantiation *>::const_reverse_iterator
11355ffd83dbSDimitry Andric            it = ActiveMacros.rbegin(),
11365ffd83dbSDimitry Andric            ie = ActiveMacros.rend();
11375ffd83dbSDimitry Andric        it != ie; ++it)
11385ffd83dbSDimitry Andric     printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note,
11395ffd83dbSDimitry Andric                  "while in macro instantiation");
11405ffd83dbSDimitry Andric }
11415ffd83dbSDimitry Andric 
11425ffd83dbSDimitry Andric void MasmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
11435ffd83dbSDimitry Andric   printPendingErrors();
11445ffd83dbSDimitry Andric   printMessage(L, SourceMgr::DK_Note, Msg, Range);
11455ffd83dbSDimitry Andric   printMacroInstantiations();
11465ffd83dbSDimitry Andric }
11475ffd83dbSDimitry Andric 
11485ffd83dbSDimitry Andric bool MasmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
11495ffd83dbSDimitry Andric   if (getTargetParser().getTargetOptions().MCNoWarn)
11505ffd83dbSDimitry Andric     return false;
11515ffd83dbSDimitry Andric   if (getTargetParser().getTargetOptions().MCFatalWarnings)
11525ffd83dbSDimitry Andric     return Error(L, Msg, Range);
11535ffd83dbSDimitry Andric   printMessage(L, SourceMgr::DK_Warning, Msg, Range);
11545ffd83dbSDimitry Andric   printMacroInstantiations();
11555ffd83dbSDimitry Andric   return false;
11565ffd83dbSDimitry Andric }
11575ffd83dbSDimitry Andric 
11585ffd83dbSDimitry Andric bool MasmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
11595ffd83dbSDimitry Andric   HadError = true;
11605ffd83dbSDimitry Andric   printMessage(L, SourceMgr::DK_Error, Msg, Range);
11615ffd83dbSDimitry Andric   printMacroInstantiations();
11625ffd83dbSDimitry Andric   return true;
11635ffd83dbSDimitry Andric }
11645ffd83dbSDimitry Andric 
11655ffd83dbSDimitry Andric bool MasmParser::enterIncludeFile(const std::string &Filename) {
11665ffd83dbSDimitry Andric   std::string IncludedFile;
11675ffd83dbSDimitry Andric   unsigned NewBuf =
11685ffd83dbSDimitry Andric       SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
11695ffd83dbSDimitry Andric   if (!NewBuf)
11705ffd83dbSDimitry Andric     return true;
11715ffd83dbSDimitry Andric 
11725ffd83dbSDimitry Andric   CurBuffer = NewBuf;
11735ffd83dbSDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
1174e8d8bef9SDimitry Andric   EndStatementAtEOFStack.push_back(true);
11755ffd83dbSDimitry Andric   return false;
11765ffd83dbSDimitry Andric }
11775ffd83dbSDimitry Andric 
1178e8d8bef9SDimitry Andric void MasmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer,
1179e8d8bef9SDimitry Andric                            bool EndStatementAtEOF) {
11805ffd83dbSDimitry Andric   CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
11815ffd83dbSDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
1182e8d8bef9SDimitry Andric                   Loc.getPointer(), EndStatementAtEOF);
11835ffd83dbSDimitry Andric }
11845ffd83dbSDimitry Andric 
1185fe6060f1SDimitry Andric bool MasmParser::expandMacros() {
1186fe6060f1SDimitry Andric   const AsmToken &Tok = getTok();
1187fe6060f1SDimitry Andric   const std::string IDLower = Tok.getIdentifier().lower();
1188fe6060f1SDimitry Andric 
1189fe6060f1SDimitry Andric   const llvm::MCAsmMacro *M = getContext().lookupMacro(IDLower);
1190fe6060f1SDimitry Andric   if (M && M->IsFunction && peekTok().is(AsmToken::LParen)) {
1191fe6060f1SDimitry Andric     // This is a macro function invocation; expand it in place.
1192fe6060f1SDimitry Andric     const SMLoc MacroLoc = Tok.getLoc();
1193fe6060f1SDimitry Andric     const StringRef MacroId = Tok.getIdentifier();
1194fe6060f1SDimitry Andric     Lexer.Lex();
1195fe6060f1SDimitry Andric     if (handleMacroInvocation(M, MacroLoc)) {
1196fe6060f1SDimitry Andric       Lexer.UnLex(AsmToken(AsmToken::Error, MacroId));
1197fe6060f1SDimitry Andric       Lexer.Lex();
1198fe6060f1SDimitry Andric     }
1199fe6060f1SDimitry Andric     return false;
1200fe6060f1SDimitry Andric   }
1201fe6060f1SDimitry Andric 
1202*bdd1243dSDimitry Andric   std::optional<std::string> ExpandedValue;
1203fe6060f1SDimitry Andric   auto BuiltinIt = BuiltinSymbolMap.find(IDLower);
1204fe6060f1SDimitry Andric   if (BuiltinIt != BuiltinSymbolMap.end()) {
1205fe6060f1SDimitry Andric     ExpandedValue =
1206fe6060f1SDimitry Andric         evaluateBuiltinTextMacro(BuiltinIt->getValue(), Tok.getLoc());
1207fe6060f1SDimitry Andric   } else {
1208fe6060f1SDimitry Andric     auto VarIt = Variables.find(IDLower);
1209fe6060f1SDimitry Andric     if (VarIt != Variables.end() && VarIt->getValue().IsText) {
1210fe6060f1SDimitry Andric       ExpandedValue = VarIt->getValue().TextValue;
1211fe6060f1SDimitry Andric     }
1212fe6060f1SDimitry Andric   }
1213fe6060f1SDimitry Andric 
121481ad6265SDimitry Andric   if (!ExpandedValue)
1215fe6060f1SDimitry Andric     return true;
1216fe6060f1SDimitry Andric   std::unique_ptr<MemoryBuffer> Instantiation =
1217fe6060f1SDimitry Andric       MemoryBuffer::getMemBufferCopy(*ExpandedValue, "<instantiation>");
1218fe6060f1SDimitry Andric 
1219fe6060f1SDimitry Andric   // Jump to the macro instantiation and prime the lexer.
1220fe6060f1SDimitry Andric   CurBuffer =
1221fe6060f1SDimitry Andric       SrcMgr.AddNewSourceBuffer(std::move(Instantiation), Tok.getEndLoc());
1222fe6060f1SDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), nullptr,
1223fe6060f1SDimitry Andric                   /*EndStatementAtEOF=*/false);
1224fe6060f1SDimitry Andric   EndStatementAtEOFStack.push_back(false);
1225fe6060f1SDimitry Andric   Lexer.Lex();
1226fe6060f1SDimitry Andric   return false;
1227fe6060f1SDimitry Andric }
1228fe6060f1SDimitry Andric 
1229fe6060f1SDimitry Andric const AsmToken &MasmParser::Lex(ExpandKind ExpandNextToken) {
12305ffd83dbSDimitry Andric   if (Lexer.getTok().is(AsmToken::Error))
12315ffd83dbSDimitry Andric     Error(Lexer.getErrLoc(), Lexer.getErr());
12325ffd83dbSDimitry Andric 
12335ffd83dbSDimitry Andric   // if it's a end of statement with a comment in it
12345ffd83dbSDimitry Andric   if (getTok().is(AsmToken::EndOfStatement)) {
12355ffd83dbSDimitry Andric     // if this is a line comment output it.
12365ffd83dbSDimitry Andric     if (!getTok().getString().empty() && getTok().getString().front() != '\n' &&
12375ffd83dbSDimitry Andric         getTok().getString().front() != '\r' && MAI.preserveAsmComments())
12385ffd83dbSDimitry Andric       Out.addExplicitComment(Twine(getTok().getString()));
12395ffd83dbSDimitry Andric   }
12405ffd83dbSDimitry Andric 
12415ffd83dbSDimitry Andric   const AsmToken *tok = &Lexer.Lex();
1242fe6060f1SDimitry Andric   bool StartOfStatement = Lexer.isAtStartOfStatement();
12435ffd83dbSDimitry Andric 
1244fe6060f1SDimitry Andric   while (ExpandNextToken == ExpandMacros && tok->is(AsmToken::Identifier)) {
1245fe6060f1SDimitry Andric     if (StartOfStatement) {
1246fe6060f1SDimitry Andric       AsmToken NextTok;
1247fe6060f1SDimitry Andric       MutableArrayRef<AsmToken> Buf(NextTok);
1248fe6060f1SDimitry Andric       size_t ReadCount = Lexer.peekTokens(Buf);
1249fe6060f1SDimitry Andric       if (ReadCount && NextTok.is(AsmToken::Identifier) &&
1250fe6060f1SDimitry Andric           (NextTok.getString().equals_insensitive("equ") ||
1251fe6060f1SDimitry Andric            NextTok.getString().equals_insensitive("textequ"))) {
1252fe6060f1SDimitry Andric         // This looks like an EQU or TEXTEQU directive; don't expand the
1253fe6060f1SDimitry Andric         // identifier, allowing for redefinitions.
12545ffd83dbSDimitry Andric         break;
12555ffd83dbSDimitry Andric       }
12565ffd83dbSDimitry Andric     }
1257fe6060f1SDimitry Andric     if (expandMacros())
1258fe6060f1SDimitry Andric       break;
1259fe6060f1SDimitry Andric   }
12605ffd83dbSDimitry Andric 
12615ffd83dbSDimitry Andric   // Parse comments here to be deferred until end of next statement.
12625ffd83dbSDimitry Andric   while (tok->is(AsmToken::Comment)) {
12635ffd83dbSDimitry Andric     if (MAI.preserveAsmComments())
12645ffd83dbSDimitry Andric       Out.addExplicitComment(Twine(tok->getString()));
12655ffd83dbSDimitry Andric     tok = &Lexer.Lex();
12665ffd83dbSDimitry Andric   }
12675ffd83dbSDimitry Andric 
1268e8d8bef9SDimitry Andric   // Recognize and bypass line continuations.
1269e8d8bef9SDimitry Andric   while (tok->is(AsmToken::BackSlash) &&
1270fe6060f1SDimitry Andric          peekTok().is(AsmToken::EndOfStatement)) {
1271e8d8bef9SDimitry Andric     // Eat both the backslash and the end of statement.
1272e8d8bef9SDimitry Andric     Lexer.Lex();
1273e8d8bef9SDimitry Andric     tok = &Lexer.Lex();
1274e8d8bef9SDimitry Andric   }
1275e8d8bef9SDimitry Andric 
12765ffd83dbSDimitry Andric   if (tok->is(AsmToken::Eof)) {
12775ffd83dbSDimitry Andric     // If this is the end of an included file, pop the parent file off the
12785ffd83dbSDimitry Andric     // include stack.
12795ffd83dbSDimitry Andric     SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
12805ffd83dbSDimitry Andric     if (ParentIncludeLoc != SMLoc()) {
1281e8d8bef9SDimitry Andric       EndStatementAtEOFStack.pop_back();
1282e8d8bef9SDimitry Andric       jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
12835ffd83dbSDimitry Andric       return Lex();
12845ffd83dbSDimitry Andric     }
1285e8d8bef9SDimitry Andric     EndStatementAtEOFStack.pop_back();
1286e8d8bef9SDimitry Andric     assert(EndStatementAtEOFStack.empty());
12875ffd83dbSDimitry Andric   }
12885ffd83dbSDimitry Andric 
12895ffd83dbSDimitry Andric   return *tok;
12905ffd83dbSDimitry Andric }
12915ffd83dbSDimitry Andric 
1292fe6060f1SDimitry Andric const AsmToken MasmParser::peekTok(bool ShouldSkipSpace) {
1293fe6060f1SDimitry Andric   AsmToken Tok;
1294fe6060f1SDimitry Andric 
1295fe6060f1SDimitry Andric   MutableArrayRef<AsmToken> Buf(Tok);
1296fe6060f1SDimitry Andric   size_t ReadCount = Lexer.peekTokens(Buf, ShouldSkipSpace);
1297fe6060f1SDimitry Andric 
1298fe6060f1SDimitry Andric   if (ReadCount == 0) {
1299fe6060f1SDimitry Andric     // If this is the end of an included file, pop the parent file off the
1300fe6060f1SDimitry Andric     // include stack.
1301fe6060f1SDimitry Andric     SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
1302fe6060f1SDimitry Andric     if (ParentIncludeLoc != SMLoc()) {
1303fe6060f1SDimitry Andric       EndStatementAtEOFStack.pop_back();
1304fe6060f1SDimitry Andric       jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1305fe6060f1SDimitry Andric       return peekTok(ShouldSkipSpace);
1306fe6060f1SDimitry Andric     }
1307fe6060f1SDimitry Andric     EndStatementAtEOFStack.pop_back();
1308fe6060f1SDimitry Andric     assert(EndStatementAtEOFStack.empty());
1309fe6060f1SDimitry Andric   }
1310fe6060f1SDimitry Andric 
1311fe6060f1SDimitry Andric   assert(ReadCount == 1);
1312fe6060f1SDimitry Andric   return Tok;
1313fe6060f1SDimitry Andric }
1314fe6060f1SDimitry Andric 
13155ffd83dbSDimitry Andric bool MasmParser::enabledGenDwarfForAssembly() {
13165ffd83dbSDimitry Andric   // Check whether the user specified -g.
13175ffd83dbSDimitry Andric   if (!getContext().getGenDwarfForAssembly())
13185ffd83dbSDimitry Andric     return false;
13195ffd83dbSDimitry Andric   // If we haven't encountered any .file directives (which would imply that
13205ffd83dbSDimitry Andric   // the assembler source was produced with debug info already) then emit one
13215ffd83dbSDimitry Andric   // describing the assembler source file itself.
13225ffd83dbSDimitry Andric   if (getContext().getGenDwarfFileNumber() == 0) {
13235ffd83dbSDimitry Andric     // Use the first #line directive for this, if any. It's preprocessed, so
13245ffd83dbSDimitry Andric     // there is no checksum, and of course no source directive.
13255ffd83dbSDimitry Andric     if (!FirstCppHashFilename.empty())
1326*bdd1243dSDimitry Andric       getContext().setMCLineTableRootFile(
1327*bdd1243dSDimitry Andric           /*CUID=*/0, getContext().getCompilationDir(), FirstCppHashFilename,
1328*bdd1243dSDimitry Andric           /*Cksum=*/std::nullopt, /*Source=*/std::nullopt);
13295ffd83dbSDimitry Andric     const MCDwarfFile &RootFile =
13305ffd83dbSDimitry Andric         getContext().getMCDwarfLineTable(/*CUID=*/0).getRootFile();
13315ffd83dbSDimitry Andric     getContext().setGenDwarfFileNumber(getStreamer().emitDwarfFileDirective(
13325ffd83dbSDimitry Andric         /*CUID=*/0, getContext().getCompilationDir(), RootFile.Name,
13335ffd83dbSDimitry Andric         RootFile.Checksum, RootFile.Source));
13345ffd83dbSDimitry Andric   }
13355ffd83dbSDimitry Andric   return true;
13365ffd83dbSDimitry Andric }
13375ffd83dbSDimitry Andric 
13385ffd83dbSDimitry Andric bool MasmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
13395ffd83dbSDimitry Andric   // Create the initial section, if requested.
13405ffd83dbSDimitry Andric   if (!NoInitialTextSection)
1341349cc55cSDimitry Andric     Out.initSections(false, getTargetParser().getSTI());
13425ffd83dbSDimitry Andric 
13435ffd83dbSDimitry Andric   // Prime the lexer.
13445ffd83dbSDimitry Andric   Lex();
13455ffd83dbSDimitry Andric 
13465ffd83dbSDimitry Andric   HadError = false;
13475ffd83dbSDimitry Andric   AsmCond StartingCondState = TheCondState;
13485ffd83dbSDimitry Andric   SmallVector<AsmRewrite, 4> AsmStrRewrites;
13495ffd83dbSDimitry Andric 
13505ffd83dbSDimitry Andric   // If we are generating dwarf for assembly source files save the initial text
13515ffd83dbSDimitry Andric   // section.  (Don't use enabledGenDwarfForAssembly() here, as we aren't
13525ffd83dbSDimitry Andric   // emitting any actual debug info yet and haven't had a chance to parse any
13535ffd83dbSDimitry Andric   // embedded .file directives.)
13545ffd83dbSDimitry Andric   if (getContext().getGenDwarfForAssembly()) {
13555ffd83dbSDimitry Andric     MCSection *Sec = getStreamer().getCurrentSectionOnly();
13565ffd83dbSDimitry Andric     if (!Sec->getBeginSymbol()) {
13575ffd83dbSDimitry Andric       MCSymbol *SectionStartSym = getContext().createTempSymbol();
13585ffd83dbSDimitry Andric       getStreamer().emitLabel(SectionStartSym);
13595ffd83dbSDimitry Andric       Sec->setBeginSymbol(SectionStartSym);
13605ffd83dbSDimitry Andric     }
13615ffd83dbSDimitry Andric     bool InsertResult = getContext().addGenDwarfSection(Sec);
13625ffd83dbSDimitry Andric     assert(InsertResult && ".text section should not have debug info yet");
13635ffd83dbSDimitry Andric     (void)InsertResult;
13645ffd83dbSDimitry Andric   }
13655ffd83dbSDimitry Andric 
1366fe6060f1SDimitry Andric   getTargetParser().onBeginOfFile();
1367fe6060f1SDimitry Andric 
13685ffd83dbSDimitry Andric   // While we have input, parse each statement.
1369e8d8bef9SDimitry Andric   while (Lexer.isNot(AsmToken::Eof) ||
1370e8d8bef9SDimitry Andric          SrcMgr.getParentIncludeLoc(CurBuffer) != SMLoc()) {
1371e8d8bef9SDimitry Andric     // Skip through the EOF at the end of an inclusion.
1372e8d8bef9SDimitry Andric     if (Lexer.is(AsmToken::Eof))
1373e8d8bef9SDimitry Andric       Lex();
1374e8d8bef9SDimitry Andric 
13755ffd83dbSDimitry Andric     ParseStatementInfo Info(&AsmStrRewrites);
13765ffd83dbSDimitry Andric     bool Parsed = parseStatement(Info, nullptr);
13775ffd83dbSDimitry Andric 
13785ffd83dbSDimitry Andric     // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
13795ffd83dbSDimitry Andric     // for printing ErrMsg via Lex() only if no (presumably better) parser error
13805ffd83dbSDimitry Andric     // exists.
13815ffd83dbSDimitry Andric     if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
13825ffd83dbSDimitry Andric       Lex();
13835ffd83dbSDimitry Andric     }
13845ffd83dbSDimitry Andric 
13855ffd83dbSDimitry Andric     // parseStatement returned true so may need to emit an error.
13865ffd83dbSDimitry Andric     printPendingErrors();
13875ffd83dbSDimitry Andric 
13885ffd83dbSDimitry Andric     // Skipping to the next line if needed.
13895ffd83dbSDimitry Andric     if (Parsed && !getLexer().isAtStartOfStatement())
13905ffd83dbSDimitry Andric       eatToEndOfStatement();
13915ffd83dbSDimitry Andric   }
13925ffd83dbSDimitry Andric 
13935ffd83dbSDimitry Andric   getTargetParser().onEndOfFile();
13945ffd83dbSDimitry Andric   printPendingErrors();
13955ffd83dbSDimitry Andric 
13965ffd83dbSDimitry Andric   // All errors should have been emitted.
13975ffd83dbSDimitry Andric   assert(!hasPendingError() && "unexpected error from parseStatement");
13985ffd83dbSDimitry Andric 
13995ffd83dbSDimitry Andric   getTargetParser().flushPendingInstructions(getStreamer());
14005ffd83dbSDimitry Andric 
14015ffd83dbSDimitry Andric   if (TheCondState.TheCond != StartingCondState.TheCond ||
14025ffd83dbSDimitry Andric       TheCondState.Ignore != StartingCondState.Ignore)
14035ffd83dbSDimitry Andric     printError(getTok().getLoc(), "unmatched .ifs or .elses");
14045ffd83dbSDimitry Andric   // Check to see there are no empty DwarfFile slots.
14055ffd83dbSDimitry Andric   const auto &LineTables = getContext().getMCDwarfLineTables();
14065ffd83dbSDimitry Andric   if (!LineTables.empty()) {
14075ffd83dbSDimitry Andric     unsigned Index = 0;
14085ffd83dbSDimitry Andric     for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) {
14095ffd83dbSDimitry Andric       if (File.Name.empty() && Index != 0)
14105ffd83dbSDimitry Andric         printError(getTok().getLoc(), "unassigned file number: " +
14115ffd83dbSDimitry Andric                                           Twine(Index) +
14125ffd83dbSDimitry Andric                                           " for .file directives");
14135ffd83dbSDimitry Andric       ++Index;
14145ffd83dbSDimitry Andric     }
14155ffd83dbSDimitry Andric   }
14165ffd83dbSDimitry Andric 
14175ffd83dbSDimitry Andric   // Check to see that all assembler local symbols were actually defined.
14185ffd83dbSDimitry Andric   // Targets that don't do subsections via symbols may not want this, though,
14195ffd83dbSDimitry Andric   // so conservatively exclude them. Only do this if we're finalizing, though,
14205ffd83dbSDimitry Andric   // as otherwise we won't necessarilly have seen everything yet.
14215ffd83dbSDimitry Andric   if (!NoFinalize) {
14225ffd83dbSDimitry Andric     if (MAI.hasSubsectionsViaSymbols()) {
14235ffd83dbSDimitry Andric       for (const auto &TableEntry : getContext().getSymbols()) {
14245ffd83dbSDimitry Andric         MCSymbol *Sym = TableEntry.getValue();
14255ffd83dbSDimitry Andric         // Variable symbols may not be marked as defined, so check those
14265ffd83dbSDimitry Andric         // explicitly. If we know it's a variable, we have a definition for
14275ffd83dbSDimitry Andric         // the purposes of this check.
14285ffd83dbSDimitry Andric         if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
14295ffd83dbSDimitry Andric           // FIXME: We would really like to refer back to where the symbol was
14305ffd83dbSDimitry Andric           // first referenced for a source location. We need to add something
14315ffd83dbSDimitry Andric           // to track that. Currently, we just point to the end of the file.
14325ffd83dbSDimitry Andric           printError(getTok().getLoc(), "assembler local symbol '" +
14335ffd83dbSDimitry Andric                                             Sym->getName() + "' not defined");
14345ffd83dbSDimitry Andric       }
14355ffd83dbSDimitry Andric     }
14365ffd83dbSDimitry Andric 
14375ffd83dbSDimitry Andric     // Temporary symbols like the ones for directional jumps don't go in the
14385ffd83dbSDimitry Andric     // symbol table. They also need to be diagnosed in all (final) cases.
14395ffd83dbSDimitry Andric     for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
14405ffd83dbSDimitry Andric       if (std::get<2>(LocSym)->isUndefined()) {
14415ffd83dbSDimitry Andric         // Reset the state of any "# line file" directives we've seen to the
14425ffd83dbSDimitry Andric         // context as it was at the diagnostic site.
14435ffd83dbSDimitry Andric         CppHashInfo = std::get<1>(LocSym);
14445ffd83dbSDimitry Andric         printError(std::get<0>(LocSym), "directional label undefined");
14455ffd83dbSDimitry Andric       }
14465ffd83dbSDimitry Andric     }
14475ffd83dbSDimitry Andric   }
14485ffd83dbSDimitry Andric 
14495ffd83dbSDimitry Andric   // Finalize the output stream if there are no errors and if the client wants
14505ffd83dbSDimitry Andric   // us to.
14515ffd83dbSDimitry Andric   if (!HadError && !NoFinalize)
145281ad6265SDimitry Andric     Out.finish(Lexer.getLoc());
14535ffd83dbSDimitry Andric 
14545ffd83dbSDimitry Andric   return HadError || getContext().hadError();
14555ffd83dbSDimitry Andric }
14565ffd83dbSDimitry Andric 
14575ffd83dbSDimitry Andric bool MasmParser::checkForValidSection() {
14585ffd83dbSDimitry Andric   if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) {
1459349cc55cSDimitry Andric     Out.initSections(false, getTargetParser().getSTI());
14605ffd83dbSDimitry Andric     return Error(getTok().getLoc(),
14615ffd83dbSDimitry Andric                  "expected section directive before assembly directive");
14625ffd83dbSDimitry Andric   }
14635ffd83dbSDimitry Andric   return false;
14645ffd83dbSDimitry Andric }
14655ffd83dbSDimitry Andric 
14665ffd83dbSDimitry Andric /// Throw away the rest of the line for testing purposes.
14675ffd83dbSDimitry Andric void MasmParser::eatToEndOfStatement() {
1468e8d8bef9SDimitry Andric   while (Lexer.isNot(AsmToken::EndOfStatement)) {
1469e8d8bef9SDimitry Andric     if (Lexer.is(AsmToken::Eof)) {
1470e8d8bef9SDimitry Andric       SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
1471e8d8bef9SDimitry Andric       if (ParentIncludeLoc == SMLoc()) {
1472e8d8bef9SDimitry Andric         break;
1473e8d8bef9SDimitry Andric       }
1474e8d8bef9SDimitry Andric 
1475e8d8bef9SDimitry Andric       EndStatementAtEOFStack.pop_back();
1476e8d8bef9SDimitry Andric       jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1477e8d8bef9SDimitry Andric     }
1478e8d8bef9SDimitry Andric 
14795ffd83dbSDimitry Andric     Lexer.Lex();
1480e8d8bef9SDimitry Andric   }
14815ffd83dbSDimitry Andric 
14825ffd83dbSDimitry Andric   // Eat EOL.
14835ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::EndOfStatement))
14845ffd83dbSDimitry Andric     Lexer.Lex();
14855ffd83dbSDimitry Andric }
14865ffd83dbSDimitry Andric 
1487e8d8bef9SDimitry Andric SmallVector<StringRef, 1>
1488e8d8bef9SDimitry Andric MasmParser::parseStringRefsTo(AsmToken::TokenKind EndTok) {
1489e8d8bef9SDimitry Andric   SmallVector<StringRef, 1> Refs;
1490e8d8bef9SDimitry Andric   const char *Start = getTok().getLoc().getPointer();
1491e8d8bef9SDimitry Andric   while (Lexer.isNot(EndTok)) {
1492e8d8bef9SDimitry Andric     if (Lexer.is(AsmToken::Eof)) {
1493e8d8bef9SDimitry Andric       SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
1494e8d8bef9SDimitry Andric       if (ParentIncludeLoc == SMLoc()) {
1495e8d8bef9SDimitry Andric         break;
1496e8d8bef9SDimitry Andric       }
1497e8d8bef9SDimitry Andric       Refs.emplace_back(Start, getTok().getLoc().getPointer() - Start);
1498e8d8bef9SDimitry Andric 
1499e8d8bef9SDimitry Andric       EndStatementAtEOFStack.pop_back();
1500e8d8bef9SDimitry Andric       jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1501e8d8bef9SDimitry Andric       Lexer.Lex();
1502e8d8bef9SDimitry Andric       Start = getTok().getLoc().getPointer();
1503e8d8bef9SDimitry Andric     } else {
1504e8d8bef9SDimitry Andric       Lexer.Lex();
1505e8d8bef9SDimitry Andric     }
1506e8d8bef9SDimitry Andric   }
1507e8d8bef9SDimitry Andric   Refs.emplace_back(Start, getTok().getLoc().getPointer() - Start);
1508e8d8bef9SDimitry Andric   return Refs;
1509e8d8bef9SDimitry Andric }
1510e8d8bef9SDimitry Andric 
1511e8d8bef9SDimitry Andric std::string MasmParser::parseStringTo(AsmToken::TokenKind EndTok) {
1512e8d8bef9SDimitry Andric   SmallVector<StringRef, 1> Refs = parseStringRefsTo(EndTok);
1513e8d8bef9SDimitry Andric   std::string Str;
1514e8d8bef9SDimitry Andric   for (StringRef S : Refs) {
1515e8d8bef9SDimitry Andric     Str.append(S.str());
1516e8d8bef9SDimitry Andric   }
1517e8d8bef9SDimitry Andric   return Str;
1518e8d8bef9SDimitry Andric }
1519e8d8bef9SDimitry Andric 
15205ffd83dbSDimitry Andric StringRef MasmParser::parseStringToEndOfStatement() {
15215ffd83dbSDimitry Andric   const char *Start = getTok().getLoc().getPointer();
15225ffd83dbSDimitry Andric 
15235ffd83dbSDimitry Andric   while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
15245ffd83dbSDimitry Andric     Lexer.Lex();
15255ffd83dbSDimitry Andric 
15265ffd83dbSDimitry Andric   const char *End = getTok().getLoc().getPointer();
15275ffd83dbSDimitry Andric   return StringRef(Start, End - Start);
15285ffd83dbSDimitry Andric }
15295ffd83dbSDimitry Andric 
15305ffd83dbSDimitry Andric /// Parse a paren expression and return it.
15315ffd83dbSDimitry Andric /// NOTE: This assumes the leading '(' has already been consumed.
15325ffd83dbSDimitry Andric ///
15335ffd83dbSDimitry Andric /// parenexpr ::= expr)
15345ffd83dbSDimitry Andric ///
15355ffd83dbSDimitry Andric bool MasmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
15365ffd83dbSDimitry Andric   if (parseExpression(Res))
15375ffd83dbSDimitry Andric     return true;
15385ffd83dbSDimitry Andric   EndLoc = Lexer.getTok().getEndLoc();
153904eeddc0SDimitry Andric   return parseRParen();
15405ffd83dbSDimitry Andric }
15415ffd83dbSDimitry Andric 
15425ffd83dbSDimitry Andric /// Parse a bracket expression and return it.
15435ffd83dbSDimitry Andric /// NOTE: This assumes the leading '[' has already been consumed.
15445ffd83dbSDimitry Andric ///
15455ffd83dbSDimitry Andric /// bracketexpr ::= expr]
15465ffd83dbSDimitry Andric ///
15475ffd83dbSDimitry Andric bool MasmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
15485ffd83dbSDimitry Andric   if (parseExpression(Res))
15495ffd83dbSDimitry Andric     return true;
15505ffd83dbSDimitry Andric   EndLoc = getTok().getEndLoc();
15515ffd83dbSDimitry Andric   if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
15525ffd83dbSDimitry Andric     return true;
15535ffd83dbSDimitry Andric   return false;
15545ffd83dbSDimitry Andric }
15555ffd83dbSDimitry Andric 
15565ffd83dbSDimitry Andric /// Parse a primary expression and return it.
15575ffd83dbSDimitry Andric ///  primaryexpr ::= (parenexpr
15585ffd83dbSDimitry Andric ///  primaryexpr ::= symbol
15595ffd83dbSDimitry Andric ///  primaryexpr ::= number
15605ffd83dbSDimitry Andric ///  primaryexpr ::= '.'
1561e8d8bef9SDimitry Andric ///  primaryexpr ::= ~,+,-,'not' primaryexpr
1562e8d8bef9SDimitry Andric ///  primaryexpr ::= string
1563e8d8bef9SDimitry Andric ///          (a string is interpreted as a 64-bit number in big-endian base-256)
1564e8d8bef9SDimitry Andric bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
1565e8d8bef9SDimitry Andric                                   AsmTypeInfo *TypeInfo) {
15665ffd83dbSDimitry Andric   SMLoc FirstTokenLoc = getLexer().getLoc();
15675ffd83dbSDimitry Andric   AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
15685ffd83dbSDimitry Andric   switch (FirstTokenKind) {
15695ffd83dbSDimitry Andric   default:
15705ffd83dbSDimitry Andric     return TokError("unknown token in expression");
15715ffd83dbSDimitry Andric   // If we have an error assume that we've already handled it.
15725ffd83dbSDimitry Andric   case AsmToken::Error:
15735ffd83dbSDimitry Andric     return true;
15745ffd83dbSDimitry Andric   case AsmToken::Exclaim:
15755ffd83dbSDimitry Andric     Lex(); // Eat the operator.
1576e8d8bef9SDimitry Andric     if (parsePrimaryExpr(Res, EndLoc, nullptr))
15775ffd83dbSDimitry Andric       return true;
15785ffd83dbSDimitry Andric     Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
15795ffd83dbSDimitry Andric     return false;
15805ffd83dbSDimitry Andric   case AsmToken::Dollar:
15815ffd83dbSDimitry Andric   case AsmToken::At:
15825ffd83dbSDimitry Andric   case AsmToken::Identifier: {
15835ffd83dbSDimitry Andric     StringRef Identifier;
15845ffd83dbSDimitry Andric     if (parseIdentifier(Identifier)) {
15855ffd83dbSDimitry Andric       // We may have failed but $ may be a valid token.
15865ffd83dbSDimitry Andric       if (getTok().is(AsmToken::Dollar)) {
15875ffd83dbSDimitry Andric         if (Lexer.getMAI().getDollarIsPC()) {
15885ffd83dbSDimitry Andric           Lex();
15895ffd83dbSDimitry Andric           // This is a '$' reference, which references the current PC.  Emit a
15905ffd83dbSDimitry Andric           // temporary label to the streamer and refer to it.
15915ffd83dbSDimitry Andric           MCSymbol *Sym = Ctx.createTempSymbol();
15925ffd83dbSDimitry Andric           Out.emitLabel(Sym);
15935ffd83dbSDimitry Andric           Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
15945ffd83dbSDimitry Andric                                         getContext());
15955ffd83dbSDimitry Andric           EndLoc = FirstTokenLoc;
15965ffd83dbSDimitry Andric           return false;
15975ffd83dbSDimitry Andric         }
15985ffd83dbSDimitry Andric         return Error(FirstTokenLoc, "invalid token in expression");
15995ffd83dbSDimitry Andric       }
16005ffd83dbSDimitry Andric     }
1601e8d8bef9SDimitry Andric     // Parse named bitwise negation.
1602fe6060f1SDimitry Andric     if (Identifier.equals_insensitive("not")) {
1603e8d8bef9SDimitry Andric       if (parsePrimaryExpr(Res, EndLoc, nullptr))
1604e8d8bef9SDimitry Andric         return true;
1605e8d8bef9SDimitry Andric       Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
1606e8d8bef9SDimitry Andric       return false;
1607e8d8bef9SDimitry Andric     }
1608753f127fSDimitry Andric     // Parse directional local label references.
1609753f127fSDimitry Andric     if (Identifier.equals_insensitive("@b") ||
1610753f127fSDimitry Andric         Identifier.equals_insensitive("@f")) {
1611753f127fSDimitry Andric       bool Before = Identifier.equals_insensitive("@b");
1612753f127fSDimitry Andric       MCSymbol *Sym = getContext().getDirectionalLocalSymbol(0, Before);
1613753f127fSDimitry Andric       if (Before && Sym->isUndefined())
1614753f127fSDimitry Andric         return Error(FirstTokenLoc, "Expected @@ label before @B reference");
1615753f127fSDimitry Andric       Res = MCSymbolRefExpr::create(Sym, getContext());
1616753f127fSDimitry Andric       return false;
1617753f127fSDimitry Andric     }
16185ffd83dbSDimitry Andric     // Parse symbol variant.
16195ffd83dbSDimitry Andric     std::pair<StringRef, StringRef> Split;
16205ffd83dbSDimitry Andric     if (!MAI.useParensForSymbolVariant()) {
16215ffd83dbSDimitry Andric       if (FirstTokenKind == AsmToken::String) {
16225ffd83dbSDimitry Andric         if (Lexer.is(AsmToken::At)) {
16235ffd83dbSDimitry Andric           Lex(); // eat @
16245ffd83dbSDimitry Andric           SMLoc AtLoc = getLexer().getLoc();
16255ffd83dbSDimitry Andric           StringRef VName;
16265ffd83dbSDimitry Andric           if (parseIdentifier(VName))
16275ffd83dbSDimitry Andric             return Error(AtLoc, "expected symbol variant after '@'");
16285ffd83dbSDimitry Andric 
16295ffd83dbSDimitry Andric           Split = std::make_pair(Identifier, VName);
16305ffd83dbSDimitry Andric         }
16315ffd83dbSDimitry Andric       } else {
16325ffd83dbSDimitry Andric         Split = Identifier.split('@');
16335ffd83dbSDimitry Andric       }
16345ffd83dbSDimitry Andric     } else if (Lexer.is(AsmToken::LParen)) {
16355ffd83dbSDimitry Andric       Lex(); // eat '('.
16365ffd83dbSDimitry Andric       StringRef VName;
16375ffd83dbSDimitry Andric       parseIdentifier(VName);
16385ffd83dbSDimitry Andric       // eat ')'.
16395ffd83dbSDimitry Andric       if (parseToken(AsmToken::RParen,
16405ffd83dbSDimitry Andric                      "unexpected token in variant, expected ')'"))
16415ffd83dbSDimitry Andric         return true;
16425ffd83dbSDimitry Andric       Split = std::make_pair(Identifier, VName);
16435ffd83dbSDimitry Andric     }
16445ffd83dbSDimitry Andric 
16455ffd83dbSDimitry Andric     EndLoc = SMLoc::getFromPointer(Identifier.end());
16465ffd83dbSDimitry Andric 
16475ffd83dbSDimitry Andric     // This is a symbol reference.
16485ffd83dbSDimitry Andric     StringRef SymbolName = Identifier;
16495ffd83dbSDimitry Andric     if (SymbolName.empty())
16505ffd83dbSDimitry Andric       return Error(getLexer().getLoc(), "expected a symbol reference");
16515ffd83dbSDimitry Andric 
16525ffd83dbSDimitry Andric     MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
16535ffd83dbSDimitry Andric 
16545ffd83dbSDimitry Andric     // Look up the symbol variant if used.
16555ffd83dbSDimitry Andric     if (!Split.second.empty()) {
16565ffd83dbSDimitry Andric       Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
16575ffd83dbSDimitry Andric       if (Variant != MCSymbolRefExpr::VK_Invalid) {
16585ffd83dbSDimitry Andric         SymbolName = Split.first;
16595ffd83dbSDimitry Andric       } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
16605ffd83dbSDimitry Andric         Variant = MCSymbolRefExpr::VK_None;
16615ffd83dbSDimitry Andric       } else {
16625ffd83dbSDimitry Andric         return Error(SMLoc::getFromPointer(Split.second.begin()),
16635ffd83dbSDimitry Andric                      "invalid variant '" + Split.second + "'");
16645ffd83dbSDimitry Andric       }
16655ffd83dbSDimitry Andric     }
16665ffd83dbSDimitry Andric 
16675ffd83dbSDimitry Andric     // Find the field offset if used.
1668e8d8bef9SDimitry Andric     AsmFieldInfo Info;
16695ffd83dbSDimitry Andric     Split = SymbolName.split('.');
1670e8d8bef9SDimitry Andric     if (Split.second.empty()) {
1671e8d8bef9SDimitry Andric     } else {
16725ffd83dbSDimitry Andric       SymbolName = Split.first;
1673e8d8bef9SDimitry Andric       if (lookUpField(SymbolName, Split.second, Info)) {
16745ffd83dbSDimitry Andric         std::pair<StringRef, StringRef> BaseMember = Split.second.split('.');
16755ffd83dbSDimitry Andric         StringRef Base = BaseMember.first, Member = BaseMember.second;
1676e8d8bef9SDimitry Andric         lookUpField(Base, Member, Info);
1677e8d8bef9SDimitry Andric       } else if (Structs.count(SymbolName.lower())) {
1678e8d8bef9SDimitry Andric         // This is actually a reference to a field offset.
1679e8d8bef9SDimitry Andric         Res = MCConstantExpr::create(Info.Offset, getContext());
1680e8d8bef9SDimitry Andric         return false;
16815ffd83dbSDimitry Andric       }
16825ffd83dbSDimitry Andric     }
16835ffd83dbSDimitry Andric 
16845ffd83dbSDimitry Andric     MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
1685fe6060f1SDimitry Andric     if (!Sym) {
1686fe6060f1SDimitry Andric       // If this is a built-in numeric value, treat it as a constant.
1687fe6060f1SDimitry Andric       auto BuiltinIt = BuiltinSymbolMap.find(SymbolName.lower());
1688fe6060f1SDimitry Andric       const BuiltinSymbol Symbol = (BuiltinIt == BuiltinSymbolMap.end())
1689fe6060f1SDimitry Andric                                        ? BI_NO_SYMBOL
1690fe6060f1SDimitry Andric                                        : BuiltinIt->getValue();
1691fe6060f1SDimitry Andric       if (Symbol != BI_NO_SYMBOL) {
1692fe6060f1SDimitry Andric         const MCExpr *Value = evaluateBuiltinValue(Symbol, FirstTokenLoc);
1693fe6060f1SDimitry Andric         if (Value) {
1694fe6060f1SDimitry Andric           Res = Value;
1695fe6060f1SDimitry Andric           return false;
1696fe6060f1SDimitry Andric         }
1697fe6060f1SDimitry Andric       }
1698fe6060f1SDimitry Andric 
1699fe6060f1SDimitry Andric       // Variables use case-insensitive symbol names; if this is a variable, we
1700fe6060f1SDimitry Andric       // find the symbol using its canonical name.
1701fe6060f1SDimitry Andric       auto VarIt = Variables.find(SymbolName.lower());
1702fe6060f1SDimitry Andric       if (VarIt != Variables.end())
1703fe6060f1SDimitry Andric         SymbolName = VarIt->second.Name;
17045ffd83dbSDimitry Andric       Sym = getContext().getOrCreateSymbol(SymbolName);
1705fe6060f1SDimitry Andric     }
17065ffd83dbSDimitry Andric 
17075ffd83dbSDimitry Andric     // If this is an absolute variable reference, substitute it now to preserve
17085ffd83dbSDimitry Andric     // semantics in the face of reassignment.
17095ffd83dbSDimitry Andric     if (Sym->isVariable()) {
1710fe6060f1SDimitry Andric       auto V = Sym->getVariableValue(/*SetUsed=*/false);
17115ffd83dbSDimitry Andric       bool DoInline = isa<MCConstantExpr>(V) && !Variant;
17125ffd83dbSDimitry Andric       if (auto TV = dyn_cast<MCTargetExpr>(V))
17135ffd83dbSDimitry Andric         DoInline = TV->inlineAssignedExpr();
17145ffd83dbSDimitry Andric       if (DoInline) {
17155ffd83dbSDimitry Andric         if (Variant)
17165ffd83dbSDimitry Andric           return Error(EndLoc, "unexpected modifier on variable reference");
1717fe6060f1SDimitry Andric         Res = Sym->getVariableValue(/*SetUsed=*/false);
17185ffd83dbSDimitry Andric         return false;
17195ffd83dbSDimitry Andric       }
17205ffd83dbSDimitry Andric     }
17215ffd83dbSDimitry Andric 
17225ffd83dbSDimitry Andric     // Otherwise create a symbol ref.
17235ffd83dbSDimitry Andric     const MCExpr *SymRef =
17245ffd83dbSDimitry Andric         MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);
1725e8d8bef9SDimitry Andric     if (Info.Offset) {
1726e8d8bef9SDimitry Andric       Res = MCBinaryExpr::create(
1727e8d8bef9SDimitry Andric           MCBinaryExpr::Add, SymRef,
1728e8d8bef9SDimitry Andric           MCConstantExpr::create(Info.Offset, getContext()), getContext());
17295ffd83dbSDimitry Andric     } else {
17305ffd83dbSDimitry Andric       Res = SymRef;
17315ffd83dbSDimitry Andric     }
1732e8d8bef9SDimitry Andric     if (TypeInfo) {
1733e8d8bef9SDimitry Andric       if (Info.Type.Name.empty()) {
1734e8d8bef9SDimitry Andric         auto TypeIt = KnownType.find(Identifier.lower());
1735e8d8bef9SDimitry Andric         if (TypeIt != KnownType.end()) {
1736e8d8bef9SDimitry Andric           Info.Type = TypeIt->second;
1737e8d8bef9SDimitry Andric         }
1738e8d8bef9SDimitry Andric       }
1739e8d8bef9SDimitry Andric 
1740e8d8bef9SDimitry Andric       *TypeInfo = Info.Type;
1741e8d8bef9SDimitry Andric     }
17425ffd83dbSDimitry Andric     return false;
17435ffd83dbSDimitry Andric   }
17445ffd83dbSDimitry Andric   case AsmToken::BigNum:
17455ffd83dbSDimitry Andric     return TokError("literal value out of range for directive");
17465ffd83dbSDimitry Andric   case AsmToken::Integer: {
17475ffd83dbSDimitry Andric     int64_t IntVal = getTok().getIntVal();
17485ffd83dbSDimitry Andric     Res = MCConstantExpr::create(IntVal, getContext());
17495ffd83dbSDimitry Andric     EndLoc = Lexer.getTok().getEndLoc();
17505ffd83dbSDimitry Andric     Lex(); // Eat token.
17515ffd83dbSDimitry Andric     return false;
17525ffd83dbSDimitry Andric   }
1753e8d8bef9SDimitry Andric   case AsmToken::String: {
1754e8d8bef9SDimitry Andric     // MASM strings (used as constants) are interpreted as big-endian base-256.
1755e8d8bef9SDimitry Andric     SMLoc ValueLoc = getTok().getLoc();
1756e8d8bef9SDimitry Andric     std::string Value;
1757e8d8bef9SDimitry Andric     if (parseEscapedString(Value))
1758e8d8bef9SDimitry Andric       return true;
1759e8d8bef9SDimitry Andric     if (Value.size() > 8)
1760e8d8bef9SDimitry Andric       return Error(ValueLoc, "literal value out of range");
1761e8d8bef9SDimitry Andric     uint64_t IntValue = 0;
1762e8d8bef9SDimitry Andric     for (const unsigned char CharVal : Value)
1763e8d8bef9SDimitry Andric       IntValue = (IntValue << 8) | CharVal;
1764e8d8bef9SDimitry Andric     Res = MCConstantExpr::create(IntValue, getContext());
1765e8d8bef9SDimitry Andric     return false;
1766e8d8bef9SDimitry Andric   }
17675ffd83dbSDimitry Andric   case AsmToken::Real: {
17685ffd83dbSDimitry Andric     APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
17695ffd83dbSDimitry Andric     uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
17705ffd83dbSDimitry Andric     Res = MCConstantExpr::create(IntVal, getContext());
17715ffd83dbSDimitry Andric     EndLoc = Lexer.getTok().getEndLoc();
17725ffd83dbSDimitry Andric     Lex(); // Eat token.
17735ffd83dbSDimitry Andric     return false;
17745ffd83dbSDimitry Andric   }
17755ffd83dbSDimitry Andric   case AsmToken::Dot: {
17765ffd83dbSDimitry Andric     // This is a '.' reference, which references the current PC.  Emit a
17775ffd83dbSDimitry Andric     // temporary label to the streamer and refer to it.
17785ffd83dbSDimitry Andric     MCSymbol *Sym = Ctx.createTempSymbol();
17795ffd83dbSDimitry Andric     Out.emitLabel(Sym);
17805ffd83dbSDimitry Andric     Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
17815ffd83dbSDimitry Andric     EndLoc = Lexer.getTok().getEndLoc();
17825ffd83dbSDimitry Andric     Lex(); // Eat identifier.
17835ffd83dbSDimitry Andric     return false;
17845ffd83dbSDimitry Andric   }
17855ffd83dbSDimitry Andric   case AsmToken::LParen:
17865ffd83dbSDimitry Andric     Lex(); // Eat the '('.
17875ffd83dbSDimitry Andric     return parseParenExpr(Res, EndLoc);
17885ffd83dbSDimitry Andric   case AsmToken::LBrac:
17895ffd83dbSDimitry Andric     if (!PlatformParser->HasBracketExpressions())
17905ffd83dbSDimitry Andric       return TokError("brackets expression not supported on this target");
17915ffd83dbSDimitry Andric     Lex(); // Eat the '['.
17925ffd83dbSDimitry Andric     return parseBracketExpr(Res, EndLoc);
17935ffd83dbSDimitry Andric   case AsmToken::Minus:
17945ffd83dbSDimitry Andric     Lex(); // Eat the operator.
1795e8d8bef9SDimitry Andric     if (parsePrimaryExpr(Res, EndLoc, nullptr))
17965ffd83dbSDimitry Andric       return true;
17975ffd83dbSDimitry Andric     Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
17985ffd83dbSDimitry Andric     return false;
17995ffd83dbSDimitry Andric   case AsmToken::Plus:
18005ffd83dbSDimitry Andric     Lex(); // Eat the operator.
1801e8d8bef9SDimitry Andric     if (parsePrimaryExpr(Res, EndLoc, nullptr))
18025ffd83dbSDimitry Andric       return true;
18035ffd83dbSDimitry Andric     Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
18045ffd83dbSDimitry Andric     return false;
18055ffd83dbSDimitry Andric   case AsmToken::Tilde:
18065ffd83dbSDimitry Andric     Lex(); // Eat the operator.
1807e8d8bef9SDimitry Andric     if (parsePrimaryExpr(Res, EndLoc, nullptr))
18085ffd83dbSDimitry Andric       return true;
18095ffd83dbSDimitry Andric     Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
18105ffd83dbSDimitry Andric     return false;
18115ffd83dbSDimitry Andric   // MIPS unary expression operators. The lexer won't generate these tokens if
18125ffd83dbSDimitry Andric   // MCAsmInfo::HasMipsExpressions is false for the target.
18135ffd83dbSDimitry Andric   case AsmToken::PercentCall16:
18145ffd83dbSDimitry Andric   case AsmToken::PercentCall_Hi:
18155ffd83dbSDimitry Andric   case AsmToken::PercentCall_Lo:
18165ffd83dbSDimitry Andric   case AsmToken::PercentDtprel_Hi:
18175ffd83dbSDimitry Andric   case AsmToken::PercentDtprel_Lo:
18185ffd83dbSDimitry Andric   case AsmToken::PercentGot:
18195ffd83dbSDimitry Andric   case AsmToken::PercentGot_Disp:
18205ffd83dbSDimitry Andric   case AsmToken::PercentGot_Hi:
18215ffd83dbSDimitry Andric   case AsmToken::PercentGot_Lo:
18225ffd83dbSDimitry Andric   case AsmToken::PercentGot_Ofst:
18235ffd83dbSDimitry Andric   case AsmToken::PercentGot_Page:
18245ffd83dbSDimitry Andric   case AsmToken::PercentGottprel:
18255ffd83dbSDimitry Andric   case AsmToken::PercentGp_Rel:
18265ffd83dbSDimitry Andric   case AsmToken::PercentHi:
18275ffd83dbSDimitry Andric   case AsmToken::PercentHigher:
18285ffd83dbSDimitry Andric   case AsmToken::PercentHighest:
18295ffd83dbSDimitry Andric   case AsmToken::PercentLo:
18305ffd83dbSDimitry Andric   case AsmToken::PercentNeg:
18315ffd83dbSDimitry Andric   case AsmToken::PercentPcrel_Hi:
18325ffd83dbSDimitry Andric   case AsmToken::PercentPcrel_Lo:
18335ffd83dbSDimitry Andric   case AsmToken::PercentTlsgd:
18345ffd83dbSDimitry Andric   case AsmToken::PercentTlsldm:
18355ffd83dbSDimitry Andric   case AsmToken::PercentTprel_Hi:
18365ffd83dbSDimitry Andric   case AsmToken::PercentTprel_Lo:
18375ffd83dbSDimitry Andric     Lex(); // Eat the operator.
18385ffd83dbSDimitry Andric     if (Lexer.isNot(AsmToken::LParen))
18395ffd83dbSDimitry Andric       return TokError("expected '(' after operator");
18405ffd83dbSDimitry Andric     Lex(); // Eat the operator.
18415ffd83dbSDimitry Andric     if (parseExpression(Res, EndLoc))
18425ffd83dbSDimitry Andric       return true;
184304eeddc0SDimitry Andric     if (parseRParen())
184404eeddc0SDimitry Andric       return true;
18455ffd83dbSDimitry Andric     Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx);
18465ffd83dbSDimitry Andric     return !Res;
18475ffd83dbSDimitry Andric   }
18485ffd83dbSDimitry Andric }
18495ffd83dbSDimitry Andric 
18505ffd83dbSDimitry Andric bool MasmParser::parseExpression(const MCExpr *&Res) {
18515ffd83dbSDimitry Andric   SMLoc EndLoc;
18525ffd83dbSDimitry Andric   return parseExpression(Res, EndLoc);
18535ffd83dbSDimitry Andric }
18545ffd83dbSDimitry Andric 
18555ffd83dbSDimitry Andric /// This function checks if the next token is <string> type or arithmetic.
18565ffd83dbSDimitry Andric /// string that begin with character '<' must end with character '>'.
18575ffd83dbSDimitry Andric /// otherwise it is arithmetics.
18585ffd83dbSDimitry Andric /// If the function returns a 'true' value,
18595ffd83dbSDimitry Andric /// the End argument will be filled with the last location pointed to the '>'
18605ffd83dbSDimitry Andric /// character.
18615ffd83dbSDimitry Andric static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
18625ffd83dbSDimitry Andric   assert((StrLoc.getPointer() != nullptr) &&
18635ffd83dbSDimitry Andric          "Argument to the function cannot be a NULL value");
18645ffd83dbSDimitry Andric   const char *CharPtr = StrLoc.getPointer();
18655ffd83dbSDimitry Andric   while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
18665ffd83dbSDimitry Andric          (*CharPtr != '\0')) {
18675ffd83dbSDimitry Andric     if (*CharPtr == '!')
18685ffd83dbSDimitry Andric       CharPtr++;
18695ffd83dbSDimitry Andric     CharPtr++;
18705ffd83dbSDimitry Andric   }
18715ffd83dbSDimitry Andric   if (*CharPtr == '>') {
18725ffd83dbSDimitry Andric     EndLoc = StrLoc.getFromPointer(CharPtr + 1);
18735ffd83dbSDimitry Andric     return true;
18745ffd83dbSDimitry Andric   }
18755ffd83dbSDimitry Andric   return false;
18765ffd83dbSDimitry Andric }
18775ffd83dbSDimitry Andric 
18785ffd83dbSDimitry Andric /// creating a string without the escape characters '!'.
1879e8d8bef9SDimitry Andric static std::string angleBracketString(StringRef BracketContents) {
18805ffd83dbSDimitry Andric   std::string Res;
1881e8d8bef9SDimitry Andric   for (size_t Pos = 0; Pos < BracketContents.size(); Pos++) {
1882e8d8bef9SDimitry Andric     if (BracketContents[Pos] == '!')
18835ffd83dbSDimitry Andric       Pos++;
1884e8d8bef9SDimitry Andric     Res += BracketContents[Pos];
18855ffd83dbSDimitry Andric   }
18865ffd83dbSDimitry Andric   return Res;
18875ffd83dbSDimitry Andric }
18885ffd83dbSDimitry Andric 
18895ffd83dbSDimitry Andric /// Parse an expression and return it.
18905ffd83dbSDimitry Andric ///
18915ffd83dbSDimitry Andric ///  expr ::= expr &&,|| expr               -> lowest.
18925ffd83dbSDimitry Andric ///  expr ::= expr |,^,&,! expr
18935ffd83dbSDimitry Andric ///  expr ::= expr ==,!=,<>,<,<=,>,>= expr
18945ffd83dbSDimitry Andric ///  expr ::= expr <<,>> expr
18955ffd83dbSDimitry Andric ///  expr ::= expr +,- expr
18965ffd83dbSDimitry Andric ///  expr ::= expr *,/,% expr               -> highest.
18975ffd83dbSDimitry Andric ///  expr ::= primaryexpr
18985ffd83dbSDimitry Andric ///
18995ffd83dbSDimitry Andric bool MasmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
19005ffd83dbSDimitry Andric   // Parse the expression.
19015ffd83dbSDimitry Andric   Res = nullptr;
19025ffd83dbSDimitry Andric   if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
19035ffd83dbSDimitry Andric       parseBinOpRHS(1, Res, EndLoc))
19045ffd83dbSDimitry Andric     return true;
19055ffd83dbSDimitry Andric 
19065ffd83dbSDimitry Andric   // Try to constant fold it up front, if possible. Do not exploit
19075ffd83dbSDimitry Andric   // assembler here.
19085ffd83dbSDimitry Andric   int64_t Value;
19095ffd83dbSDimitry Andric   if (Res->evaluateAsAbsolute(Value))
19105ffd83dbSDimitry Andric     Res = MCConstantExpr::create(Value, getContext());
19115ffd83dbSDimitry Andric 
19125ffd83dbSDimitry Andric   return false;
19135ffd83dbSDimitry Andric }
19145ffd83dbSDimitry Andric 
19155ffd83dbSDimitry Andric bool MasmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
19165ffd83dbSDimitry Andric   Res = nullptr;
19175ffd83dbSDimitry Andric   return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
19185ffd83dbSDimitry Andric }
19195ffd83dbSDimitry Andric 
19205ffd83dbSDimitry Andric bool MasmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
19215ffd83dbSDimitry Andric                                        SMLoc &EndLoc) {
19225ffd83dbSDimitry Andric   if (parseParenExpr(Res, EndLoc))
19235ffd83dbSDimitry Andric     return true;
19245ffd83dbSDimitry Andric 
19255ffd83dbSDimitry Andric   for (; ParenDepth > 0; --ParenDepth) {
19265ffd83dbSDimitry Andric     if (parseBinOpRHS(1, Res, EndLoc))
19275ffd83dbSDimitry Andric       return true;
19285ffd83dbSDimitry Andric 
19295ffd83dbSDimitry Andric     // We don't Lex() the last RParen.
19305ffd83dbSDimitry Andric     // This is the same behavior as parseParenExpression().
19315ffd83dbSDimitry Andric     if (ParenDepth - 1 > 0) {
19325ffd83dbSDimitry Andric       EndLoc = getTok().getEndLoc();
193304eeddc0SDimitry Andric       if (parseRParen())
19345ffd83dbSDimitry Andric         return true;
19355ffd83dbSDimitry Andric     }
19365ffd83dbSDimitry Andric   }
19375ffd83dbSDimitry Andric   return false;
19385ffd83dbSDimitry Andric }
19395ffd83dbSDimitry Andric 
19405ffd83dbSDimitry Andric bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
19415ffd83dbSDimitry Andric   const MCExpr *Expr;
19425ffd83dbSDimitry Andric 
19435ffd83dbSDimitry Andric   SMLoc StartLoc = Lexer.getLoc();
19445ffd83dbSDimitry Andric   if (parseExpression(Expr))
19455ffd83dbSDimitry Andric     return true;
19465ffd83dbSDimitry Andric 
19475ffd83dbSDimitry Andric   if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
19485ffd83dbSDimitry Andric     return Error(StartLoc, "expected absolute expression");
19495ffd83dbSDimitry Andric 
19505ffd83dbSDimitry Andric   return false;
19515ffd83dbSDimitry Andric }
19525ffd83dbSDimitry Andric 
19535ffd83dbSDimitry Andric static unsigned getGNUBinOpPrecedence(AsmToken::TokenKind K,
19545ffd83dbSDimitry Andric                                       MCBinaryExpr::Opcode &Kind,
19555ffd83dbSDimitry Andric                                       bool ShouldUseLogicalShr,
19565ffd83dbSDimitry Andric                                       bool EndExpressionAtGreater) {
19575ffd83dbSDimitry Andric   switch (K) {
19585ffd83dbSDimitry Andric   default:
19595ffd83dbSDimitry Andric     return 0; // not a binop.
19605ffd83dbSDimitry Andric 
19615ffd83dbSDimitry Andric   // Lowest Precedence: &&, ||
19625ffd83dbSDimitry Andric   case AsmToken::AmpAmp:
19635ffd83dbSDimitry Andric     Kind = MCBinaryExpr::LAnd;
19645ffd83dbSDimitry Andric     return 2;
19655ffd83dbSDimitry Andric   case AsmToken::PipePipe:
19665ffd83dbSDimitry Andric     Kind = MCBinaryExpr::LOr;
19675ffd83dbSDimitry Andric     return 1;
19685ffd83dbSDimitry Andric 
19695ffd83dbSDimitry Andric   // Low Precedence: ==, !=, <>, <, <=, >, >=
19705ffd83dbSDimitry Andric   case AsmToken::EqualEqual:
19715ffd83dbSDimitry Andric     Kind = MCBinaryExpr::EQ;
19725ffd83dbSDimitry Andric     return 3;
19735ffd83dbSDimitry Andric   case AsmToken::ExclaimEqual:
19745ffd83dbSDimitry Andric   case AsmToken::LessGreater:
19755ffd83dbSDimitry Andric     Kind = MCBinaryExpr::NE;
19765ffd83dbSDimitry Andric     return 3;
19775ffd83dbSDimitry Andric   case AsmToken::Less:
19785ffd83dbSDimitry Andric     Kind = MCBinaryExpr::LT;
19795ffd83dbSDimitry Andric     return 3;
19805ffd83dbSDimitry Andric   case AsmToken::LessEqual:
19815ffd83dbSDimitry Andric     Kind = MCBinaryExpr::LTE;
19825ffd83dbSDimitry Andric     return 3;
19835ffd83dbSDimitry Andric   case AsmToken::Greater:
19845ffd83dbSDimitry Andric     if (EndExpressionAtGreater)
19855ffd83dbSDimitry Andric       return 0;
19865ffd83dbSDimitry Andric     Kind = MCBinaryExpr::GT;
19875ffd83dbSDimitry Andric     return 3;
19885ffd83dbSDimitry Andric   case AsmToken::GreaterEqual:
19895ffd83dbSDimitry Andric     Kind = MCBinaryExpr::GTE;
19905ffd83dbSDimitry Andric     return 3;
19915ffd83dbSDimitry Andric 
19925ffd83dbSDimitry Andric   // Low Intermediate Precedence: +, -
19935ffd83dbSDimitry Andric   case AsmToken::Plus:
19945ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Add;
19955ffd83dbSDimitry Andric     return 4;
19965ffd83dbSDimitry Andric   case AsmToken::Minus:
19975ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Sub;
19985ffd83dbSDimitry Andric     return 4;
19995ffd83dbSDimitry Andric 
20005ffd83dbSDimitry Andric   // High Intermediate Precedence: |, &, ^
20015ffd83dbSDimitry Andric   case AsmToken::Pipe:
20025ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Or;
20035ffd83dbSDimitry Andric     return 5;
20045ffd83dbSDimitry Andric   case AsmToken::Caret:
20055ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Xor;
20065ffd83dbSDimitry Andric     return 5;
20075ffd83dbSDimitry Andric   case AsmToken::Amp:
20085ffd83dbSDimitry Andric     Kind = MCBinaryExpr::And;
20095ffd83dbSDimitry Andric     return 5;
20105ffd83dbSDimitry Andric 
20115ffd83dbSDimitry Andric   // Highest Precedence: *, /, %, <<, >>
20125ffd83dbSDimitry Andric   case AsmToken::Star:
20135ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Mul;
20145ffd83dbSDimitry Andric     return 6;
20155ffd83dbSDimitry Andric   case AsmToken::Slash:
20165ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Div;
20175ffd83dbSDimitry Andric     return 6;
20185ffd83dbSDimitry Andric   case AsmToken::Percent:
20195ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Mod;
20205ffd83dbSDimitry Andric     return 6;
20215ffd83dbSDimitry Andric   case AsmToken::LessLess:
20225ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Shl;
20235ffd83dbSDimitry Andric     return 6;
20245ffd83dbSDimitry Andric   case AsmToken::GreaterGreater:
20255ffd83dbSDimitry Andric     if (EndExpressionAtGreater)
20265ffd83dbSDimitry Andric       return 0;
20275ffd83dbSDimitry Andric     Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
20285ffd83dbSDimitry Andric     return 6;
20295ffd83dbSDimitry Andric   }
20305ffd83dbSDimitry Andric }
20315ffd83dbSDimitry Andric 
20325ffd83dbSDimitry Andric unsigned MasmParser::getBinOpPrecedence(AsmToken::TokenKind K,
20335ffd83dbSDimitry Andric                                         MCBinaryExpr::Opcode &Kind) {
20345ffd83dbSDimitry Andric   bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
20355ffd83dbSDimitry Andric   return getGNUBinOpPrecedence(K, Kind, ShouldUseLogicalShr,
20365ffd83dbSDimitry Andric                                AngleBracketDepth > 0);
20375ffd83dbSDimitry Andric }
20385ffd83dbSDimitry Andric 
20395ffd83dbSDimitry Andric /// Parse all binary operators with precedence >= 'Precedence'.
20405ffd83dbSDimitry Andric /// Res contains the LHS of the expression on input.
20415ffd83dbSDimitry Andric bool MasmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
20425ffd83dbSDimitry Andric                                SMLoc &EndLoc) {
20435ffd83dbSDimitry Andric   SMLoc StartLoc = Lexer.getLoc();
20445ffd83dbSDimitry Andric   while (true) {
2045e8d8bef9SDimitry Andric     AsmToken::TokenKind TokKind = Lexer.getKind();
2046e8d8bef9SDimitry Andric     if (Lexer.getKind() == AsmToken::Identifier) {
2047e8d8bef9SDimitry Andric       TokKind = StringSwitch<AsmToken::TokenKind>(Lexer.getTok().getString())
2048e8d8bef9SDimitry Andric                     .CaseLower("and", AsmToken::Amp)
2049e8d8bef9SDimitry Andric                     .CaseLower("not", AsmToken::Exclaim)
2050e8d8bef9SDimitry Andric                     .CaseLower("or", AsmToken::Pipe)
2051753f127fSDimitry Andric                     .CaseLower("xor", AsmToken::Caret)
2052753f127fSDimitry Andric                     .CaseLower("shl", AsmToken::LessLess)
2053753f127fSDimitry Andric                     .CaseLower("shr", AsmToken::GreaterGreater)
2054e8d8bef9SDimitry Andric                     .CaseLower("eq", AsmToken::EqualEqual)
2055e8d8bef9SDimitry Andric                     .CaseLower("ne", AsmToken::ExclaimEqual)
2056e8d8bef9SDimitry Andric                     .CaseLower("lt", AsmToken::Less)
2057e8d8bef9SDimitry Andric                     .CaseLower("le", AsmToken::LessEqual)
2058e8d8bef9SDimitry Andric                     .CaseLower("gt", AsmToken::Greater)
2059e8d8bef9SDimitry Andric                     .CaseLower("ge", AsmToken::GreaterEqual)
2060e8d8bef9SDimitry Andric                     .Default(TokKind);
2061e8d8bef9SDimitry Andric     }
20625ffd83dbSDimitry Andric     MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
2063e8d8bef9SDimitry Andric     unsigned TokPrec = getBinOpPrecedence(TokKind, Kind);
20645ffd83dbSDimitry Andric 
20655ffd83dbSDimitry Andric     // If the next token is lower precedence than we are allowed to eat, return
20665ffd83dbSDimitry Andric     // successfully with what we ate already.
20675ffd83dbSDimitry Andric     if (TokPrec < Precedence)
20685ffd83dbSDimitry Andric       return false;
20695ffd83dbSDimitry Andric 
20705ffd83dbSDimitry Andric     Lex();
20715ffd83dbSDimitry Andric 
20725ffd83dbSDimitry Andric     // Eat the next primary expression.
20735ffd83dbSDimitry Andric     const MCExpr *RHS;
20745ffd83dbSDimitry Andric     if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
20755ffd83dbSDimitry Andric       return true;
20765ffd83dbSDimitry Andric 
20775ffd83dbSDimitry Andric     // If BinOp binds less tightly with RHS than the operator after RHS, let
20785ffd83dbSDimitry Andric     // the pending operator take RHS as its LHS.
20795ffd83dbSDimitry Andric     MCBinaryExpr::Opcode Dummy;
20805ffd83dbSDimitry Andric     unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
20815ffd83dbSDimitry Andric     if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
20825ffd83dbSDimitry Andric       return true;
20835ffd83dbSDimitry Andric 
20845ffd83dbSDimitry Andric     // Merge LHS and RHS according to operator.
20855ffd83dbSDimitry Andric     Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);
20865ffd83dbSDimitry Andric   }
20875ffd83dbSDimitry Andric }
20885ffd83dbSDimitry Andric 
20895ffd83dbSDimitry Andric /// ParseStatement:
2090e8d8bef9SDimitry Andric ///   ::= % statement
20915ffd83dbSDimitry Andric ///   ::= EndOfStatement
20925ffd83dbSDimitry Andric ///   ::= Label* Directive ...Operands... EndOfStatement
20935ffd83dbSDimitry Andric ///   ::= Label* Identifier OperandList* EndOfStatement
20945ffd83dbSDimitry Andric bool MasmParser::parseStatement(ParseStatementInfo &Info,
20955ffd83dbSDimitry Andric                                 MCAsmParserSemaCallback *SI) {
20965ffd83dbSDimitry Andric   assert(!hasPendingError() && "parseStatement started with pending error");
20975ffd83dbSDimitry Andric   // Eat initial spaces and comments.
20985ffd83dbSDimitry Andric   while (Lexer.is(AsmToken::Space))
20995ffd83dbSDimitry Andric     Lex();
21005ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::EndOfStatement)) {
21015ffd83dbSDimitry Andric     // If this is a line comment we can drop it safely.
21025ffd83dbSDimitry Andric     if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
21035ffd83dbSDimitry Andric         getTok().getString().front() == '\n')
210481ad6265SDimitry Andric       Out.addBlankLine();
21055ffd83dbSDimitry Andric     Lex();
21065ffd83dbSDimitry Andric     return false;
21075ffd83dbSDimitry Andric   }
2108e8d8bef9SDimitry Andric 
2109e8d8bef9SDimitry Andric   // If preceded by an expansion operator, first expand all text macros and
2110e8d8bef9SDimitry Andric   // macro functions.
2111e8d8bef9SDimitry Andric   if (getTok().is(AsmToken::Percent)) {
2112e8d8bef9SDimitry Andric     SMLoc ExpansionLoc = getTok().getLoc();
2113e8d8bef9SDimitry Andric     if (parseToken(AsmToken::Percent) || expandStatement(ExpansionLoc))
2114e8d8bef9SDimitry Andric       return true;
2115e8d8bef9SDimitry Andric   }
2116e8d8bef9SDimitry Andric 
21175ffd83dbSDimitry Andric   // Statements always start with an identifier, unless we're dealing with a
21185ffd83dbSDimitry Andric   // processor directive (.386, .686, etc.) that lexes as a real.
21195ffd83dbSDimitry Andric   AsmToken ID = getTok();
21205ffd83dbSDimitry Andric   SMLoc IDLoc = ID.getLoc();
21215ffd83dbSDimitry Andric   StringRef IDVal;
21225ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::HashDirective))
21235ffd83dbSDimitry Andric     return parseCppHashLineFilenameComment(IDLoc);
2124753f127fSDimitry Andric   if (Lexer.is(AsmToken::Dot)) {
21255ffd83dbSDimitry Andric     // Treat '.' as a valid identifier in this context.
21265ffd83dbSDimitry Andric     Lex();
21275ffd83dbSDimitry Andric     IDVal = ".";
21285ffd83dbSDimitry Andric   } else if (Lexer.is(AsmToken::LCurly)) {
21295ffd83dbSDimitry Andric     // Treat '{' as a valid identifier in this context.
21305ffd83dbSDimitry Andric     Lex();
21315ffd83dbSDimitry Andric     IDVal = "{";
21325ffd83dbSDimitry Andric 
21335ffd83dbSDimitry Andric   } else if (Lexer.is(AsmToken::RCurly)) {
21345ffd83dbSDimitry Andric     // Treat '}' as a valid identifier in this context.
21355ffd83dbSDimitry Andric     Lex();
21365ffd83dbSDimitry Andric     IDVal = "}";
21375ffd83dbSDimitry Andric   } else if (Lexer.is(AsmToken::Star) &&
21385ffd83dbSDimitry Andric              getTargetParser().starIsStartOfStatement()) {
21395ffd83dbSDimitry Andric     // Accept '*' as a valid start of statement.
21405ffd83dbSDimitry Andric     Lex();
21415ffd83dbSDimitry Andric     IDVal = "*";
21425ffd83dbSDimitry Andric   } else if (Lexer.is(AsmToken::Real)) {
21435ffd83dbSDimitry Andric     // Treat ".<number>" as a valid identifier in this context.
21445ffd83dbSDimitry Andric     IDVal = getTok().getString();
21455ffd83dbSDimitry Andric     Lex(); // always eat a token
21465ffd83dbSDimitry Andric     if (!IDVal.startswith("."))
21475ffd83dbSDimitry Andric       return Error(IDLoc, "unexpected token at start of statement");
2148fe6060f1SDimitry Andric   } else if (parseIdentifier(IDVal, StartOfStatement)) {
21495ffd83dbSDimitry Andric     if (!TheCondState.Ignore) {
21505ffd83dbSDimitry Andric       Lex(); // always eat a token
21515ffd83dbSDimitry Andric       return Error(IDLoc, "unexpected token at start of statement");
21525ffd83dbSDimitry Andric     }
21535ffd83dbSDimitry Andric     IDVal = "";
21545ffd83dbSDimitry Andric   }
21555ffd83dbSDimitry Andric 
21565ffd83dbSDimitry Andric   // Handle conditional assembly here before checking for skipping.  We
21575ffd83dbSDimitry Andric   // have to do this so that .endif isn't skipped in a ".if 0" block for
21585ffd83dbSDimitry Andric   // example.
21595ffd83dbSDimitry Andric   StringMap<DirectiveKind>::const_iterator DirKindIt =
21605ffd83dbSDimitry Andric       DirectiveKindMap.find(IDVal.lower());
21615ffd83dbSDimitry Andric   DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
21625ffd83dbSDimitry Andric                               ? DK_NO_DIRECTIVE
21635ffd83dbSDimitry Andric                               : DirKindIt->getValue();
21645ffd83dbSDimitry Andric   switch (DirKind) {
21655ffd83dbSDimitry Andric   default:
21665ffd83dbSDimitry Andric     break;
21675ffd83dbSDimitry Andric   case DK_IF:
21685ffd83dbSDimitry Andric   case DK_IFE:
21695ffd83dbSDimitry Andric     return parseDirectiveIf(IDLoc, DirKind);
21705ffd83dbSDimitry Andric   case DK_IFB:
21715ffd83dbSDimitry Andric     return parseDirectiveIfb(IDLoc, true);
21725ffd83dbSDimitry Andric   case DK_IFNB:
21735ffd83dbSDimitry Andric     return parseDirectiveIfb(IDLoc, false);
21745ffd83dbSDimitry Andric   case DK_IFDEF:
21755ffd83dbSDimitry Andric     return parseDirectiveIfdef(IDLoc, true);
21765ffd83dbSDimitry Andric   case DK_IFNDEF:
21775ffd83dbSDimitry Andric     return parseDirectiveIfdef(IDLoc, false);
21785ffd83dbSDimitry Andric   case DK_IFDIF:
21795ffd83dbSDimitry Andric     return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false,
21805ffd83dbSDimitry Andric                                /*CaseInsensitive=*/false);
21815ffd83dbSDimitry Andric   case DK_IFDIFI:
21825ffd83dbSDimitry Andric     return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false,
21835ffd83dbSDimitry Andric                                /*CaseInsensitive=*/true);
21845ffd83dbSDimitry Andric   case DK_IFIDN:
21855ffd83dbSDimitry Andric     return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true,
21865ffd83dbSDimitry Andric                                /*CaseInsensitive=*/false);
21875ffd83dbSDimitry Andric   case DK_IFIDNI:
21885ffd83dbSDimitry Andric     return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true,
21895ffd83dbSDimitry Andric                                /*CaseInsensitive=*/true);
21905ffd83dbSDimitry Andric   case DK_ELSEIF:
21915ffd83dbSDimitry Andric   case DK_ELSEIFE:
21925ffd83dbSDimitry Andric     return parseDirectiveElseIf(IDLoc, DirKind);
21935ffd83dbSDimitry Andric   case DK_ELSEIFB:
21945ffd83dbSDimitry Andric     return parseDirectiveElseIfb(IDLoc, true);
21955ffd83dbSDimitry Andric   case DK_ELSEIFNB:
21965ffd83dbSDimitry Andric     return parseDirectiveElseIfb(IDLoc, false);
21975ffd83dbSDimitry Andric   case DK_ELSEIFDEF:
21985ffd83dbSDimitry Andric     return parseDirectiveElseIfdef(IDLoc, true);
21995ffd83dbSDimitry Andric   case DK_ELSEIFNDEF:
22005ffd83dbSDimitry Andric     return parseDirectiveElseIfdef(IDLoc, false);
22015ffd83dbSDimitry Andric   case DK_ELSEIFDIF:
22025ffd83dbSDimitry Andric     return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false,
22035ffd83dbSDimitry Andric                                    /*CaseInsensitive=*/false);
22045ffd83dbSDimitry Andric   case DK_ELSEIFDIFI:
22055ffd83dbSDimitry Andric     return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false,
22065ffd83dbSDimitry Andric                                    /*CaseInsensitive=*/true);
22075ffd83dbSDimitry Andric   case DK_ELSEIFIDN:
22085ffd83dbSDimitry Andric     return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true,
22095ffd83dbSDimitry Andric                                    /*CaseInsensitive=*/false);
22105ffd83dbSDimitry Andric   case DK_ELSEIFIDNI:
22115ffd83dbSDimitry Andric     return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true,
22125ffd83dbSDimitry Andric                                    /*CaseInsensitive=*/true);
22135ffd83dbSDimitry Andric   case DK_ELSE:
22145ffd83dbSDimitry Andric     return parseDirectiveElse(IDLoc);
22155ffd83dbSDimitry Andric   case DK_ENDIF:
22165ffd83dbSDimitry Andric     return parseDirectiveEndIf(IDLoc);
22175ffd83dbSDimitry Andric   }
22185ffd83dbSDimitry Andric 
22195ffd83dbSDimitry Andric   // Ignore the statement if in the middle of inactive conditional
22205ffd83dbSDimitry Andric   // (e.g. ".if 0").
22215ffd83dbSDimitry Andric   if (TheCondState.Ignore) {
22225ffd83dbSDimitry Andric     eatToEndOfStatement();
22235ffd83dbSDimitry Andric     return false;
22245ffd83dbSDimitry Andric   }
22255ffd83dbSDimitry Andric 
22265ffd83dbSDimitry Andric   // FIXME: Recurse on local labels?
22275ffd83dbSDimitry Andric 
2228*bdd1243dSDimitry Andric   // Check for a label.
2229*bdd1243dSDimitry Andric   //   ::= identifier ':'
2230*bdd1243dSDimitry Andric   //   ::= number ':'
2231*bdd1243dSDimitry Andric   if (Lexer.is(AsmToken::Colon) && getTargetParser().isLabel(ID)) {
22325ffd83dbSDimitry Andric     if (checkForValidSection())
22335ffd83dbSDimitry Andric       return true;
22345ffd83dbSDimitry Andric 
22355ffd83dbSDimitry Andric     // identifier ':'   -> Label.
22365ffd83dbSDimitry Andric     Lex();
22375ffd83dbSDimitry Andric 
22385ffd83dbSDimitry Andric     // Diagnose attempt to use '.' as a label.
22395ffd83dbSDimitry Andric     if (IDVal == ".")
22405ffd83dbSDimitry Andric       return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
22415ffd83dbSDimitry Andric 
22425ffd83dbSDimitry Andric     // Diagnose attempt to use a variable as a label.
22435ffd83dbSDimitry Andric     //
22445ffd83dbSDimitry Andric     // FIXME: Diagnostics. Note the location of the definition as a label.
22455ffd83dbSDimitry Andric     // FIXME: This doesn't diagnose assignment to a symbol which has been
22465ffd83dbSDimitry Andric     // implicitly marked as external.
22475ffd83dbSDimitry Andric     MCSymbol *Sym;
22485ffd83dbSDimitry Andric     if (ParsingMSInlineAsm && SI) {
22495ffd83dbSDimitry Andric       StringRef RewrittenLabel =
22505ffd83dbSDimitry Andric           SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
22515ffd83dbSDimitry Andric       assert(!RewrittenLabel.empty() &&
22525ffd83dbSDimitry Andric              "We should have an internal name here.");
22535ffd83dbSDimitry Andric       Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),
22545ffd83dbSDimitry Andric                                      RewrittenLabel);
22555ffd83dbSDimitry Andric       IDVal = RewrittenLabel;
22565ffd83dbSDimitry Andric     }
2257753f127fSDimitry Andric     // Handle directional local labels
2258753f127fSDimitry Andric     if (IDVal == "@@") {
2259753f127fSDimitry Andric       Sym = Ctx.createDirectionalLocalSymbol(0);
2260753f127fSDimitry Andric     } else {
22615ffd83dbSDimitry Andric       Sym = getContext().getOrCreateSymbol(IDVal);
2262753f127fSDimitry Andric     }
2263753f127fSDimitry Andric 
22645ffd83dbSDimitry Andric     // End of Labels should be treated as end of line for lexing
22655ffd83dbSDimitry Andric     // purposes but that information is not available to the Lexer who
22665ffd83dbSDimitry Andric     // does not understand Labels. This may cause us to see a Hash
22675ffd83dbSDimitry Andric     // here instead of a preprocessor line comment.
22685ffd83dbSDimitry Andric     if (getTok().is(AsmToken::Hash)) {
2269e8d8bef9SDimitry Andric       std::string CommentStr = parseStringTo(AsmToken::EndOfStatement);
22705ffd83dbSDimitry Andric       Lexer.Lex();
22715ffd83dbSDimitry Andric       Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
22725ffd83dbSDimitry Andric     }
22735ffd83dbSDimitry Andric 
22745ffd83dbSDimitry Andric     // Consume any end of statement token, if present, to avoid spurious
227581ad6265SDimitry Andric     // addBlankLine calls().
22765ffd83dbSDimitry Andric     if (getTok().is(AsmToken::EndOfStatement)) {
22775ffd83dbSDimitry Andric       Lex();
22785ffd83dbSDimitry Andric     }
22795ffd83dbSDimitry Andric 
2280*bdd1243dSDimitry Andric     getTargetParser().doBeforeLabelEmit(Sym, IDLoc);
22815ffd83dbSDimitry Andric 
22825ffd83dbSDimitry Andric     // Emit the label.
22835ffd83dbSDimitry Andric     if (!getTargetParser().isParsingMSInlineAsm())
22845ffd83dbSDimitry Andric       Out.emitLabel(Sym, IDLoc);
22855ffd83dbSDimitry Andric 
22865ffd83dbSDimitry Andric     // If we are generating dwarf for assembly source files then gather the
22875ffd83dbSDimitry Andric     // info to make a dwarf label entry for this label if needed.
22885ffd83dbSDimitry Andric     if (enabledGenDwarfForAssembly())
22895ffd83dbSDimitry Andric       MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
22905ffd83dbSDimitry Andric                                  IDLoc);
22915ffd83dbSDimitry Andric 
22925ffd83dbSDimitry Andric     getTargetParser().onLabelParsed(Sym);
22935ffd83dbSDimitry Andric 
22945ffd83dbSDimitry Andric     return false;
22955ffd83dbSDimitry Andric   }
22965ffd83dbSDimitry Andric 
22975ffd83dbSDimitry Andric   // If macros are enabled, check to see if this is a macro instantiation.
2298e8d8bef9SDimitry Andric   if (const MCAsmMacro *M = getContext().lookupMacro(IDVal.lower())) {
22995ffd83dbSDimitry Andric     return handleMacroEntry(M, IDLoc);
23005ffd83dbSDimitry Andric   }
23015ffd83dbSDimitry Andric 
23025ffd83dbSDimitry Andric   // Otherwise, we have a normal instruction or directive.
23035ffd83dbSDimitry Andric 
23045ffd83dbSDimitry Andric   if (DirKind != DK_NO_DIRECTIVE) {
23055ffd83dbSDimitry Andric     // There are several entities interested in parsing directives:
23065ffd83dbSDimitry Andric     //
23075ffd83dbSDimitry Andric     // 1. Asm parser extensions. For example, platform-specific parsers
23085ffd83dbSDimitry Andric     //    (like the ELF parser) register themselves as extensions.
23095ffd83dbSDimitry Andric     // 2. The target-specific assembly parser. Some directives are target
23105ffd83dbSDimitry Andric     //    specific or may potentially behave differently on certain targets.
23115ffd83dbSDimitry Andric     // 3. The generic directive parser implemented by this class. These are
23125ffd83dbSDimitry Andric     //    all the directives that behave in a target and platform independent
23135ffd83dbSDimitry Andric     //    manner, or at least have a default behavior that's shared between
23145ffd83dbSDimitry Andric     //    all targets and platforms.
23155ffd83dbSDimitry Andric 
23165ffd83dbSDimitry Andric     getTargetParser().flushPendingInstructions(getStreamer());
23175ffd83dbSDimitry Andric 
23185ffd83dbSDimitry Andric     // Special-case handling of structure-end directives at higher priority,
23195ffd83dbSDimitry Andric     // since ENDS is overloaded as a segment-end directive.
2320fe6060f1SDimitry Andric     if (IDVal.equals_insensitive("ends") && StructInProgress.size() > 1 &&
23215ffd83dbSDimitry Andric         getTok().is(AsmToken::EndOfStatement)) {
23225ffd83dbSDimitry Andric       return parseDirectiveNestedEnds();
23235ffd83dbSDimitry Andric     }
23245ffd83dbSDimitry Andric 
23255ffd83dbSDimitry Andric     // First, check the extension directive map to see if any extension has
23265ffd83dbSDimitry Andric     // registered itself to parse this directive.
23275ffd83dbSDimitry Andric     std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
23285ffd83dbSDimitry Andric         ExtensionDirectiveMap.lookup(IDVal.lower());
23295ffd83dbSDimitry Andric     if (Handler.first)
23305ffd83dbSDimitry Andric       return (*Handler.second)(Handler.first, IDVal, IDLoc);
23315ffd83dbSDimitry Andric 
23325ffd83dbSDimitry Andric     // Next, let the target-specific assembly parser try.
23335ffd83dbSDimitry Andric     SMLoc StartTokLoc = getTok().getLoc();
23345ffd83dbSDimitry Andric     bool TPDirectiveReturn =
23355ffd83dbSDimitry Andric         ID.is(AsmToken::Identifier) && getTargetParser().ParseDirective(ID);
23365ffd83dbSDimitry Andric 
23375ffd83dbSDimitry Andric     if (hasPendingError())
23385ffd83dbSDimitry Andric       return true;
23395ffd83dbSDimitry Andric     // Currently the return value should be true if we are
23405ffd83dbSDimitry Andric     // uninterested but as this is at odds with the standard parsing
23415ffd83dbSDimitry Andric     // convention (return true = error) we have instances of a parsed
23425ffd83dbSDimitry Andric     // directive that fails returning true as an error. Catch these
23435ffd83dbSDimitry Andric     // cases as best as possible errors here.
23445ffd83dbSDimitry Andric     if (TPDirectiveReturn && StartTokLoc != getTok().getLoc())
23455ffd83dbSDimitry Andric       return true;
23465ffd83dbSDimitry Andric     // Return if we did some parsing or believe we succeeded.
23475ffd83dbSDimitry Andric     if (!TPDirectiveReturn || StartTokLoc != getTok().getLoc())
23485ffd83dbSDimitry Andric       return false;
23495ffd83dbSDimitry Andric 
23505ffd83dbSDimitry Andric     // Finally, if no one else is interested in this directive, it must be
23515ffd83dbSDimitry Andric     // generic and familiar to this class.
23525ffd83dbSDimitry Andric     switch (DirKind) {
23535ffd83dbSDimitry Andric     default:
23545ffd83dbSDimitry Andric       break;
23555ffd83dbSDimitry Andric     case DK_ASCII:
23565ffd83dbSDimitry Andric       return parseDirectiveAscii(IDVal, false);
23575ffd83dbSDimitry Andric     case DK_ASCIZ:
23585ffd83dbSDimitry Andric     case DK_STRING:
23595ffd83dbSDimitry Andric       return parseDirectiveAscii(IDVal, true);
23605ffd83dbSDimitry Andric     case DK_BYTE:
23615ffd83dbSDimitry Andric     case DK_SBYTE:
23625ffd83dbSDimitry Andric     case DK_DB:
23635ffd83dbSDimitry Andric       return parseDirectiveValue(IDVal, 1);
23645ffd83dbSDimitry Andric     case DK_WORD:
23655ffd83dbSDimitry Andric     case DK_SWORD:
23665ffd83dbSDimitry Andric     case DK_DW:
23675ffd83dbSDimitry Andric       return parseDirectiveValue(IDVal, 2);
23685ffd83dbSDimitry Andric     case DK_DWORD:
23695ffd83dbSDimitry Andric     case DK_SDWORD:
23705ffd83dbSDimitry Andric     case DK_DD:
23715ffd83dbSDimitry Andric       return parseDirectiveValue(IDVal, 4);
23725ffd83dbSDimitry Andric     case DK_FWORD:
2373e8d8bef9SDimitry Andric     case DK_DF:
23745ffd83dbSDimitry Andric       return parseDirectiveValue(IDVal, 6);
23755ffd83dbSDimitry Andric     case DK_QWORD:
23765ffd83dbSDimitry Andric     case DK_SQWORD:
23775ffd83dbSDimitry Andric     case DK_DQ:
23785ffd83dbSDimitry Andric       return parseDirectiveValue(IDVal, 8);
23795ffd83dbSDimitry Andric     case DK_REAL4:
2380e8d8bef9SDimitry Andric       return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4);
23815ffd83dbSDimitry Andric     case DK_REAL8:
2382e8d8bef9SDimitry Andric       return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8);
2383e8d8bef9SDimitry Andric     case DK_REAL10:
2384e8d8bef9SDimitry Andric       return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10);
23855ffd83dbSDimitry Andric     case DK_STRUCT:
23865ffd83dbSDimitry Andric     case DK_UNION:
23875ffd83dbSDimitry Andric       return parseDirectiveNestedStruct(IDVal, DirKind);
23885ffd83dbSDimitry Andric     case DK_ENDS:
23895ffd83dbSDimitry Andric       return parseDirectiveNestedEnds();
23905ffd83dbSDimitry Andric     case DK_ALIGN:
23915ffd83dbSDimitry Andric       return parseDirectiveAlign();
2392fe6060f1SDimitry Andric     case DK_EVEN:
2393fe6060f1SDimitry Andric       return parseDirectiveEven();
23945ffd83dbSDimitry Andric     case DK_ORG:
23955ffd83dbSDimitry Andric       return parseDirectiveOrg();
23965ffd83dbSDimitry Andric     case DK_EXTERN:
239781ad6265SDimitry Andric       return parseDirectiveExtern();
23985ffd83dbSDimitry Andric     case DK_PUBLIC:
23995ffd83dbSDimitry Andric       return parseDirectiveSymbolAttribute(MCSA_Global);
24005ffd83dbSDimitry Andric     case DK_COMM:
24015ffd83dbSDimitry Andric       return parseDirectiveComm(/*IsLocal=*/false);
24025ffd83dbSDimitry Andric     case DK_COMMENT:
24035ffd83dbSDimitry Andric       return parseDirectiveComment(IDLoc);
24045ffd83dbSDimitry Andric     case DK_INCLUDE:
24055ffd83dbSDimitry Andric       return parseDirectiveInclude();
2406e8d8bef9SDimitry Andric     case DK_REPEAT:
2407e8d8bef9SDimitry Andric       return parseDirectiveRepeat(IDLoc, IDVal);
2408e8d8bef9SDimitry Andric     case DK_WHILE:
2409e8d8bef9SDimitry Andric       return parseDirectiveWhile(IDLoc);
2410e8d8bef9SDimitry Andric     case DK_FOR:
2411e8d8bef9SDimitry Andric       return parseDirectiveFor(IDLoc, IDVal);
2412e8d8bef9SDimitry Andric     case DK_FORC:
2413e8d8bef9SDimitry Andric       return parseDirectiveForc(IDLoc, IDVal);
24145ffd83dbSDimitry Andric     case DK_FILE:
24155ffd83dbSDimitry Andric       return parseDirectiveFile(IDLoc);
24165ffd83dbSDimitry Andric     case DK_LINE:
24175ffd83dbSDimitry Andric       return parseDirectiveLine();
24185ffd83dbSDimitry Andric     case DK_LOC:
24195ffd83dbSDimitry Andric       return parseDirectiveLoc();
24205ffd83dbSDimitry Andric     case DK_STABS:
24215ffd83dbSDimitry Andric       return parseDirectiveStabs();
24225ffd83dbSDimitry Andric     case DK_CV_FILE:
24235ffd83dbSDimitry Andric       return parseDirectiveCVFile();
24245ffd83dbSDimitry Andric     case DK_CV_FUNC_ID:
24255ffd83dbSDimitry Andric       return parseDirectiveCVFuncId();
24265ffd83dbSDimitry Andric     case DK_CV_INLINE_SITE_ID:
24275ffd83dbSDimitry Andric       return parseDirectiveCVInlineSiteId();
24285ffd83dbSDimitry Andric     case DK_CV_LOC:
24295ffd83dbSDimitry Andric       return parseDirectiveCVLoc();
24305ffd83dbSDimitry Andric     case DK_CV_LINETABLE:
24315ffd83dbSDimitry Andric       return parseDirectiveCVLinetable();
24325ffd83dbSDimitry Andric     case DK_CV_INLINE_LINETABLE:
24335ffd83dbSDimitry Andric       return parseDirectiveCVInlineLinetable();
24345ffd83dbSDimitry Andric     case DK_CV_DEF_RANGE:
24355ffd83dbSDimitry Andric       return parseDirectiveCVDefRange();
24365ffd83dbSDimitry Andric     case DK_CV_STRING:
24375ffd83dbSDimitry Andric       return parseDirectiveCVString();
24385ffd83dbSDimitry Andric     case DK_CV_STRINGTABLE:
24395ffd83dbSDimitry Andric       return parseDirectiveCVStringTable();
24405ffd83dbSDimitry Andric     case DK_CV_FILECHECKSUMS:
24415ffd83dbSDimitry Andric       return parseDirectiveCVFileChecksums();
24425ffd83dbSDimitry Andric     case DK_CV_FILECHECKSUM_OFFSET:
24435ffd83dbSDimitry Andric       return parseDirectiveCVFileChecksumOffset();
24445ffd83dbSDimitry Andric     case DK_CV_FPO_DATA:
24455ffd83dbSDimitry Andric       return parseDirectiveCVFPOData();
24465ffd83dbSDimitry Andric     case DK_CFI_SECTIONS:
24475ffd83dbSDimitry Andric       return parseDirectiveCFISections();
24485ffd83dbSDimitry Andric     case DK_CFI_STARTPROC:
24495ffd83dbSDimitry Andric       return parseDirectiveCFIStartProc();
24505ffd83dbSDimitry Andric     case DK_CFI_ENDPROC:
24515ffd83dbSDimitry Andric       return parseDirectiveCFIEndProc();
24525ffd83dbSDimitry Andric     case DK_CFI_DEF_CFA:
24535ffd83dbSDimitry Andric       return parseDirectiveCFIDefCfa(IDLoc);
24545ffd83dbSDimitry Andric     case DK_CFI_DEF_CFA_OFFSET:
24555ffd83dbSDimitry Andric       return parseDirectiveCFIDefCfaOffset();
24565ffd83dbSDimitry Andric     case DK_CFI_ADJUST_CFA_OFFSET:
24575ffd83dbSDimitry Andric       return parseDirectiveCFIAdjustCfaOffset();
24585ffd83dbSDimitry Andric     case DK_CFI_DEF_CFA_REGISTER:
24595ffd83dbSDimitry Andric       return parseDirectiveCFIDefCfaRegister(IDLoc);
24605ffd83dbSDimitry Andric     case DK_CFI_OFFSET:
24615ffd83dbSDimitry Andric       return parseDirectiveCFIOffset(IDLoc);
24625ffd83dbSDimitry Andric     case DK_CFI_REL_OFFSET:
24635ffd83dbSDimitry Andric       return parseDirectiveCFIRelOffset(IDLoc);
24645ffd83dbSDimitry Andric     case DK_CFI_PERSONALITY:
24655ffd83dbSDimitry Andric       return parseDirectiveCFIPersonalityOrLsda(true);
24665ffd83dbSDimitry Andric     case DK_CFI_LSDA:
24675ffd83dbSDimitry Andric       return parseDirectiveCFIPersonalityOrLsda(false);
24685ffd83dbSDimitry Andric     case DK_CFI_REMEMBER_STATE:
24695ffd83dbSDimitry Andric       return parseDirectiveCFIRememberState();
24705ffd83dbSDimitry Andric     case DK_CFI_RESTORE_STATE:
24715ffd83dbSDimitry Andric       return parseDirectiveCFIRestoreState();
24725ffd83dbSDimitry Andric     case DK_CFI_SAME_VALUE:
24735ffd83dbSDimitry Andric       return parseDirectiveCFISameValue(IDLoc);
24745ffd83dbSDimitry Andric     case DK_CFI_RESTORE:
24755ffd83dbSDimitry Andric       return parseDirectiveCFIRestore(IDLoc);
24765ffd83dbSDimitry Andric     case DK_CFI_ESCAPE:
24775ffd83dbSDimitry Andric       return parseDirectiveCFIEscape();
24785ffd83dbSDimitry Andric     case DK_CFI_RETURN_COLUMN:
24795ffd83dbSDimitry Andric       return parseDirectiveCFIReturnColumn(IDLoc);
24805ffd83dbSDimitry Andric     case DK_CFI_SIGNAL_FRAME:
24815ffd83dbSDimitry Andric       return parseDirectiveCFISignalFrame();
24825ffd83dbSDimitry Andric     case DK_CFI_UNDEFINED:
24835ffd83dbSDimitry Andric       return parseDirectiveCFIUndefined(IDLoc);
24845ffd83dbSDimitry Andric     case DK_CFI_REGISTER:
24855ffd83dbSDimitry Andric       return parseDirectiveCFIRegister(IDLoc);
24865ffd83dbSDimitry Andric     case DK_CFI_WINDOW_SAVE:
24875ffd83dbSDimitry Andric       return parseDirectiveCFIWindowSave();
24885ffd83dbSDimitry Andric     case DK_EXITM:
2489e8d8bef9SDimitry Andric       Info.ExitValue = "";
2490e8d8bef9SDimitry Andric       return parseDirectiveExitMacro(IDLoc, IDVal, *Info.ExitValue);
24915ffd83dbSDimitry Andric     case DK_ENDM:
2492e8d8bef9SDimitry Andric       Info.ExitValue = "";
24935ffd83dbSDimitry Andric       return parseDirectiveEndMacro(IDVal);
2494e8d8bef9SDimitry Andric     case DK_PURGE:
24955ffd83dbSDimitry Andric       return parseDirectivePurgeMacro(IDLoc);
24965ffd83dbSDimitry Andric     case DK_END:
24975ffd83dbSDimitry Andric       return parseDirectiveEnd(IDLoc);
24985ffd83dbSDimitry Andric     case DK_ERR:
24995ffd83dbSDimitry Andric       return parseDirectiveError(IDLoc);
25005ffd83dbSDimitry Andric     case DK_ERRB:
25015ffd83dbSDimitry Andric       return parseDirectiveErrorIfb(IDLoc, true);
25025ffd83dbSDimitry Andric     case DK_ERRNB:
25035ffd83dbSDimitry Andric       return parseDirectiveErrorIfb(IDLoc, false);
25045ffd83dbSDimitry Andric     case DK_ERRDEF:
25055ffd83dbSDimitry Andric       return parseDirectiveErrorIfdef(IDLoc, true);
25065ffd83dbSDimitry Andric     case DK_ERRNDEF:
25075ffd83dbSDimitry Andric       return parseDirectiveErrorIfdef(IDLoc, false);
25085ffd83dbSDimitry Andric     case DK_ERRDIF:
25095ffd83dbSDimitry Andric       return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false,
25105ffd83dbSDimitry Andric                                       /*CaseInsensitive=*/false);
25115ffd83dbSDimitry Andric     case DK_ERRDIFI:
25125ffd83dbSDimitry Andric       return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false,
25135ffd83dbSDimitry Andric                                       /*CaseInsensitive=*/true);
25145ffd83dbSDimitry Andric     case DK_ERRIDN:
25155ffd83dbSDimitry Andric       return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true,
25165ffd83dbSDimitry Andric                                       /*CaseInsensitive=*/false);
25175ffd83dbSDimitry Andric     case DK_ERRIDNI:
25185ffd83dbSDimitry Andric       return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true,
25195ffd83dbSDimitry Andric                                       /*CaseInsensitive=*/true);
25205ffd83dbSDimitry Andric     case DK_ERRE:
25215ffd83dbSDimitry Andric       return parseDirectiveErrorIfe(IDLoc, true);
25225ffd83dbSDimitry Andric     case DK_ERRNZ:
25235ffd83dbSDimitry Andric       return parseDirectiveErrorIfe(IDLoc, false);
2524e8d8bef9SDimitry Andric     case DK_RADIX:
2525e8d8bef9SDimitry Andric       return parseDirectiveRadix(IDLoc);
2526fe6060f1SDimitry Andric     case DK_ECHO:
2527fe6060f1SDimitry Andric       return parseDirectiveEcho(IDLoc);
25285ffd83dbSDimitry Andric     }
25295ffd83dbSDimitry Andric 
25305ffd83dbSDimitry Andric     return Error(IDLoc, "unknown directive");
25315ffd83dbSDimitry Andric   }
25325ffd83dbSDimitry Andric 
25335ffd83dbSDimitry Andric   // We also check if this is allocating memory with user-defined type.
25345ffd83dbSDimitry Andric   auto IDIt = Structs.find(IDVal.lower());
25355ffd83dbSDimitry Andric   if (IDIt != Structs.end())
25365ffd83dbSDimitry Andric     return parseDirectiveStructValue(/*Structure=*/IDIt->getValue(), IDVal,
25375ffd83dbSDimitry Andric                                      IDLoc);
25385ffd83dbSDimitry Andric 
25395ffd83dbSDimitry Andric   // Non-conditional Microsoft directives sometimes follow their first argument.
25405ffd83dbSDimitry Andric   const AsmToken nextTok = getTok();
25415ffd83dbSDimitry Andric   const StringRef nextVal = nextTok.getString();
25425ffd83dbSDimitry Andric   const SMLoc nextLoc = nextTok.getLoc();
25435ffd83dbSDimitry Andric 
2544fe6060f1SDimitry Andric   const AsmToken afterNextTok = peekTok();
2545fe6060f1SDimitry Andric 
25465ffd83dbSDimitry Andric   // There are several entities interested in parsing infix directives:
25475ffd83dbSDimitry Andric   //
25485ffd83dbSDimitry Andric   // 1. Asm parser extensions. For example, platform-specific parsers
25495ffd83dbSDimitry Andric   //    (like the ELF parser) register themselves as extensions.
25505ffd83dbSDimitry Andric   // 2. The generic directive parser implemented by this class. These are
25515ffd83dbSDimitry Andric   //    all the directives that behave in a target and platform independent
25525ffd83dbSDimitry Andric   //    manner, or at least have a default behavior that's shared between
25535ffd83dbSDimitry Andric   //    all targets and platforms.
25545ffd83dbSDimitry Andric 
25555ffd83dbSDimitry Andric   getTargetParser().flushPendingInstructions(getStreamer());
25565ffd83dbSDimitry Andric 
25575ffd83dbSDimitry Andric   // Special-case handling of structure-end directives at higher priority, since
25585ffd83dbSDimitry Andric   // ENDS is overloaded as a segment-end directive.
2559fe6060f1SDimitry Andric   if (nextVal.equals_insensitive("ends") && StructInProgress.size() == 1) {
25605ffd83dbSDimitry Andric     Lex();
25615ffd83dbSDimitry Andric     return parseDirectiveEnds(IDVal, IDLoc);
25625ffd83dbSDimitry Andric   }
25635ffd83dbSDimitry Andric 
25645ffd83dbSDimitry Andric   // First, check the extension directive map to see if any extension has
25655ffd83dbSDimitry Andric   // registered itself to parse this directive.
25665ffd83dbSDimitry Andric   std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
25675ffd83dbSDimitry Andric       ExtensionDirectiveMap.lookup(nextVal.lower());
25685ffd83dbSDimitry Andric   if (Handler.first) {
25695ffd83dbSDimitry Andric     Lex();
25705ffd83dbSDimitry Andric     Lexer.UnLex(ID);
25715ffd83dbSDimitry Andric     return (*Handler.second)(Handler.first, nextVal, nextLoc);
25725ffd83dbSDimitry Andric   }
25735ffd83dbSDimitry Andric 
25745ffd83dbSDimitry Andric   // If no one else is interested in this directive, it must be
25755ffd83dbSDimitry Andric   // generic and familiar to this class.
25765ffd83dbSDimitry Andric   DirKindIt = DirectiveKindMap.find(nextVal.lower());
25775ffd83dbSDimitry Andric   DirKind = (DirKindIt == DirectiveKindMap.end())
25785ffd83dbSDimitry Andric                 ? DK_NO_DIRECTIVE
25795ffd83dbSDimitry Andric                 : DirKindIt->getValue();
25805ffd83dbSDimitry Andric   switch (DirKind) {
25815ffd83dbSDimitry Andric   default:
25825ffd83dbSDimitry Andric     break;
25835ffd83dbSDimitry Andric   case DK_ASSIGN:
25845ffd83dbSDimitry Andric   case DK_EQU:
25855ffd83dbSDimitry Andric   case DK_TEXTEQU:
25865ffd83dbSDimitry Andric     Lex();
2587fe6060f1SDimitry Andric     return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
25885ffd83dbSDimitry Andric   case DK_BYTE:
2589fe6060f1SDimitry Andric     if (afterNextTok.is(AsmToken::Identifier) &&
2590fe6060f1SDimitry Andric         afterNextTok.getString().equals_insensitive("ptr")) {
2591fe6060f1SDimitry Andric       // Size directive; part of an instruction.
2592fe6060f1SDimitry Andric       break;
2593fe6060f1SDimitry Andric     }
2594*bdd1243dSDimitry Andric     [[fallthrough]];
2595e8d8bef9SDimitry Andric   case DK_SBYTE:
25965ffd83dbSDimitry Andric   case DK_DB:
25975ffd83dbSDimitry Andric     Lex();
25985ffd83dbSDimitry Andric     return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc);
25995ffd83dbSDimitry Andric   case DK_WORD:
2600fe6060f1SDimitry Andric     if (afterNextTok.is(AsmToken::Identifier) &&
2601fe6060f1SDimitry Andric         afterNextTok.getString().equals_insensitive("ptr")) {
2602fe6060f1SDimitry Andric       // Size directive; part of an instruction.
2603fe6060f1SDimitry Andric       break;
2604fe6060f1SDimitry Andric     }
2605*bdd1243dSDimitry Andric     [[fallthrough]];
2606e8d8bef9SDimitry Andric   case DK_SWORD:
26075ffd83dbSDimitry Andric   case DK_DW:
26085ffd83dbSDimitry Andric     Lex();
26095ffd83dbSDimitry Andric     return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc);
26105ffd83dbSDimitry Andric   case DK_DWORD:
2611fe6060f1SDimitry Andric     if (afterNextTok.is(AsmToken::Identifier) &&
2612fe6060f1SDimitry Andric         afterNextTok.getString().equals_insensitive("ptr")) {
2613fe6060f1SDimitry Andric       // Size directive; part of an instruction.
2614fe6060f1SDimitry Andric       break;
2615fe6060f1SDimitry Andric     }
2616*bdd1243dSDimitry Andric     [[fallthrough]];
2617e8d8bef9SDimitry Andric   case DK_SDWORD:
26185ffd83dbSDimitry Andric   case DK_DD:
26195ffd83dbSDimitry Andric     Lex();
26205ffd83dbSDimitry Andric     return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc);
26215ffd83dbSDimitry Andric   case DK_FWORD:
2622fe6060f1SDimitry Andric     if (afterNextTok.is(AsmToken::Identifier) &&
2623fe6060f1SDimitry Andric         afterNextTok.getString().equals_insensitive("ptr")) {
2624fe6060f1SDimitry Andric       // Size directive; part of an instruction.
2625fe6060f1SDimitry Andric       break;
2626fe6060f1SDimitry Andric     }
2627*bdd1243dSDimitry Andric     [[fallthrough]];
2628e8d8bef9SDimitry Andric   case DK_DF:
26295ffd83dbSDimitry Andric     Lex();
26305ffd83dbSDimitry Andric     return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc);
26315ffd83dbSDimitry Andric   case DK_QWORD:
2632fe6060f1SDimitry Andric     if (afterNextTok.is(AsmToken::Identifier) &&
2633fe6060f1SDimitry Andric         afterNextTok.getString().equals_insensitive("ptr")) {
2634fe6060f1SDimitry Andric       // Size directive; part of an instruction.
2635fe6060f1SDimitry Andric       break;
2636fe6060f1SDimitry Andric     }
2637*bdd1243dSDimitry Andric     [[fallthrough]];
2638e8d8bef9SDimitry Andric   case DK_SQWORD:
26395ffd83dbSDimitry Andric   case DK_DQ:
26405ffd83dbSDimitry Andric     Lex();
26415ffd83dbSDimitry Andric     return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc);
26425ffd83dbSDimitry Andric   case DK_REAL4:
26435ffd83dbSDimitry Andric     Lex();
2644e8d8bef9SDimitry Andric     return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), 4,
2645e8d8bef9SDimitry Andric                                         IDVal, IDLoc);
26465ffd83dbSDimitry Andric   case DK_REAL8:
26475ffd83dbSDimitry Andric     Lex();
2648e8d8bef9SDimitry Andric     return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8,
2649e8d8bef9SDimitry Andric                                         IDVal, IDLoc);
2650e8d8bef9SDimitry Andric   case DK_REAL10:
2651e8d8bef9SDimitry Andric     Lex();
2652e8d8bef9SDimitry Andric     return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(),
2653e8d8bef9SDimitry Andric                                         10, IDVal, IDLoc);
26545ffd83dbSDimitry Andric   case DK_STRUCT:
26555ffd83dbSDimitry Andric   case DK_UNION:
26565ffd83dbSDimitry Andric     Lex();
26575ffd83dbSDimitry Andric     return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc);
26585ffd83dbSDimitry Andric   case DK_ENDS:
26595ffd83dbSDimitry Andric     Lex();
26605ffd83dbSDimitry Andric     return parseDirectiveEnds(IDVal, IDLoc);
2661e8d8bef9SDimitry Andric   case DK_MACRO:
2662e8d8bef9SDimitry Andric     Lex();
2663e8d8bef9SDimitry Andric     return parseDirectiveMacro(IDVal, IDLoc);
26645ffd83dbSDimitry Andric   }
26655ffd83dbSDimitry Andric 
26665ffd83dbSDimitry Andric   // Finally, we check if this is allocating a variable with user-defined type.
26675ffd83dbSDimitry Andric   auto NextIt = Structs.find(nextVal.lower());
26685ffd83dbSDimitry Andric   if (NextIt != Structs.end()) {
26695ffd83dbSDimitry Andric     Lex();
26705ffd83dbSDimitry Andric     return parseDirectiveNamedStructValue(/*Structure=*/NextIt->getValue(),
26715ffd83dbSDimitry Andric                                           nextVal, nextLoc, IDVal);
26725ffd83dbSDimitry Andric   }
26735ffd83dbSDimitry Andric 
26745ffd83dbSDimitry Andric   // __asm _emit or __asm __emit
26755ffd83dbSDimitry Andric   if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
26765ffd83dbSDimitry Andric                              IDVal == "_EMIT" || IDVal == "__EMIT"))
26775ffd83dbSDimitry Andric     return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
26785ffd83dbSDimitry Andric 
26795ffd83dbSDimitry Andric   // __asm align
26805ffd83dbSDimitry Andric   if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
26815ffd83dbSDimitry Andric     return parseDirectiveMSAlign(IDLoc, Info);
26825ffd83dbSDimitry Andric 
26835ffd83dbSDimitry Andric   if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
26845ffd83dbSDimitry Andric     Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
26855ffd83dbSDimitry Andric   if (checkForValidSection())
26865ffd83dbSDimitry Andric     return true;
26875ffd83dbSDimitry Andric 
26885ffd83dbSDimitry Andric   // Canonicalize the opcode to lower case.
26895ffd83dbSDimitry Andric   std::string OpcodeStr = IDVal.lower();
26905ffd83dbSDimitry Andric   ParseInstructionInfo IInfo(Info.AsmRewrites);
26915ffd83dbSDimitry Andric   bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,
26925ffd83dbSDimitry Andric                                                           Info.ParsedOperands);
26935ffd83dbSDimitry Andric   Info.ParseError = ParseHadError;
26945ffd83dbSDimitry Andric 
26955ffd83dbSDimitry Andric   // Dump the parsed representation, if requested.
26965ffd83dbSDimitry Andric   if (getShowParsedOperands()) {
26975ffd83dbSDimitry Andric     SmallString<256> Str;
26985ffd83dbSDimitry Andric     raw_svector_ostream OS(Str);
26995ffd83dbSDimitry Andric     OS << "parsed instruction: [";
27005ffd83dbSDimitry Andric     for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
27015ffd83dbSDimitry Andric       if (i != 0)
27025ffd83dbSDimitry Andric         OS << ", ";
27035ffd83dbSDimitry Andric       Info.ParsedOperands[i]->print(OS);
27045ffd83dbSDimitry Andric     }
27055ffd83dbSDimitry Andric     OS << "]";
27065ffd83dbSDimitry Andric 
27075ffd83dbSDimitry Andric     printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
27085ffd83dbSDimitry Andric   }
27095ffd83dbSDimitry Andric 
27105ffd83dbSDimitry Andric   // Fail even if ParseInstruction erroneously returns false.
27115ffd83dbSDimitry Andric   if (hasPendingError() || ParseHadError)
27125ffd83dbSDimitry Andric     return true;
27135ffd83dbSDimitry Andric 
27145ffd83dbSDimitry Andric   // If we are generating dwarf for the current section then generate a .loc
27155ffd83dbSDimitry Andric   // directive for the instruction.
27165ffd83dbSDimitry Andric   if (!ParseHadError && enabledGenDwarfForAssembly() &&
27175ffd83dbSDimitry Andric       getContext().getGenDwarfSectionSyms().count(
27185ffd83dbSDimitry Andric           getStreamer().getCurrentSectionOnly())) {
27195ffd83dbSDimitry Andric     unsigned Line;
27205ffd83dbSDimitry Andric     if (ActiveMacros.empty())
27215ffd83dbSDimitry Andric       Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
27225ffd83dbSDimitry Andric     else
27235ffd83dbSDimitry Andric       Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
27245ffd83dbSDimitry Andric                                    ActiveMacros.front()->ExitBuffer);
27255ffd83dbSDimitry Andric 
27265ffd83dbSDimitry Andric     // If we previously parsed a cpp hash file line comment then make sure the
27275ffd83dbSDimitry Andric     // current Dwarf File is for the CppHashFilename if not then emit the
27285ffd83dbSDimitry Andric     // Dwarf File table for it and adjust the line number for the .loc.
27295ffd83dbSDimitry Andric     if (!CppHashInfo.Filename.empty()) {
27305ffd83dbSDimitry Andric       unsigned FileNumber = getStreamer().emitDwarfFileDirective(
27315ffd83dbSDimitry Andric           0, StringRef(), CppHashInfo.Filename);
27325ffd83dbSDimitry Andric       getContext().setGenDwarfFileNumber(FileNumber);
27335ffd83dbSDimitry Andric 
27345ffd83dbSDimitry Andric       unsigned CppHashLocLineNo =
27355ffd83dbSDimitry Andric         SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
27365ffd83dbSDimitry Andric       Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
27375ffd83dbSDimitry Andric     }
27385ffd83dbSDimitry Andric 
27395ffd83dbSDimitry Andric     getStreamer().emitDwarfLocDirective(
27405ffd83dbSDimitry Andric         getContext().getGenDwarfFileNumber(), Line, 0,
27415ffd83dbSDimitry Andric         DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0,
27425ffd83dbSDimitry Andric         StringRef());
27435ffd83dbSDimitry Andric   }
27445ffd83dbSDimitry Andric 
27455ffd83dbSDimitry Andric   // If parsing succeeded, match the instruction.
27465ffd83dbSDimitry Andric   if (!ParseHadError) {
27475ffd83dbSDimitry Andric     uint64_t ErrorInfo;
27485ffd83dbSDimitry Andric     if (getTargetParser().MatchAndEmitInstruction(
27495ffd83dbSDimitry Andric             IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
27505ffd83dbSDimitry Andric             getTargetParser().isParsingMSInlineAsm()))
27515ffd83dbSDimitry Andric       return true;
27525ffd83dbSDimitry Andric   }
27535ffd83dbSDimitry Andric   return false;
27545ffd83dbSDimitry Andric }
27555ffd83dbSDimitry Andric 
27565ffd83dbSDimitry Andric // Parse and erase curly braces marking block start/end.
27575ffd83dbSDimitry Andric bool MasmParser::parseCurlyBlockScope(
27585ffd83dbSDimitry Andric     SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
27595ffd83dbSDimitry Andric   // Identify curly brace marking block start/end.
27605ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
27615ffd83dbSDimitry Andric     return false;
27625ffd83dbSDimitry Andric 
27635ffd83dbSDimitry Andric   SMLoc StartLoc = Lexer.getLoc();
27645ffd83dbSDimitry Andric   Lex(); // Eat the brace.
27655ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::EndOfStatement))
27665ffd83dbSDimitry Andric     Lex(); // Eat EndOfStatement following the brace.
27675ffd83dbSDimitry Andric 
27685ffd83dbSDimitry Andric   // Erase the block start/end brace from the output asm string.
27695ffd83dbSDimitry Andric   AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
27705ffd83dbSDimitry Andric                                                   StartLoc.getPointer());
27715ffd83dbSDimitry Andric   return true;
27725ffd83dbSDimitry Andric }
27735ffd83dbSDimitry Andric 
27745ffd83dbSDimitry Andric /// parseCppHashLineFilenameComment as this:
27755ffd83dbSDimitry Andric ///   ::= # number "filename"
27765ffd83dbSDimitry Andric bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
27775ffd83dbSDimitry Andric   Lex(); // Eat the hash token.
27785ffd83dbSDimitry Andric   // Lexer only ever emits HashDirective if it fully formed if it's
27795ffd83dbSDimitry Andric   // done the checking already so this is an internal error.
27805ffd83dbSDimitry Andric   assert(getTok().is(AsmToken::Integer) &&
27815ffd83dbSDimitry Andric          "Lexing Cpp line comment: Expected Integer");
27825ffd83dbSDimitry Andric   int64_t LineNumber = getTok().getIntVal();
27835ffd83dbSDimitry Andric   Lex();
27845ffd83dbSDimitry Andric   assert(getTok().is(AsmToken::String) &&
27855ffd83dbSDimitry Andric          "Lexing Cpp line comment: Expected String");
27865ffd83dbSDimitry Andric   StringRef Filename = getTok().getString();
27875ffd83dbSDimitry Andric   Lex();
27885ffd83dbSDimitry Andric 
27895ffd83dbSDimitry Andric   // Get rid of the enclosing quotes.
27905ffd83dbSDimitry Andric   Filename = Filename.substr(1, Filename.size() - 2);
27915ffd83dbSDimitry Andric 
27925ffd83dbSDimitry Andric   // Save the SMLoc, Filename and LineNumber for later use by diagnostics
27935ffd83dbSDimitry Andric   // and possibly DWARF file info.
27945ffd83dbSDimitry Andric   CppHashInfo.Loc = L;
27955ffd83dbSDimitry Andric   CppHashInfo.Filename = Filename;
27965ffd83dbSDimitry Andric   CppHashInfo.LineNumber = LineNumber;
27975ffd83dbSDimitry Andric   CppHashInfo.Buf = CurBuffer;
27985ffd83dbSDimitry Andric   if (FirstCppHashFilename.empty())
27995ffd83dbSDimitry Andric     FirstCppHashFilename = Filename;
28005ffd83dbSDimitry Andric   return false;
28015ffd83dbSDimitry Andric }
28025ffd83dbSDimitry Andric 
28035ffd83dbSDimitry Andric /// will use the last parsed cpp hash line filename comment
28045ffd83dbSDimitry Andric /// for the Filename and LineNo if any in the diagnostic.
28055ffd83dbSDimitry Andric void MasmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
28065ffd83dbSDimitry Andric   const MasmParser *Parser = static_cast<const MasmParser *>(Context);
28075ffd83dbSDimitry Andric   raw_ostream &OS = errs();
28085ffd83dbSDimitry Andric 
28095ffd83dbSDimitry Andric   const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
28105ffd83dbSDimitry Andric   SMLoc DiagLoc = Diag.getLoc();
28115ffd83dbSDimitry Andric   unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
28125ffd83dbSDimitry Andric   unsigned CppHashBuf =
28135ffd83dbSDimitry Andric       Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
28145ffd83dbSDimitry Andric 
28155ffd83dbSDimitry Andric   // Like SourceMgr::printMessage() we need to print the include stack if any
28165ffd83dbSDimitry Andric   // before printing the message.
28175ffd83dbSDimitry Andric   unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
28185ffd83dbSDimitry Andric   if (!Parser->SavedDiagHandler && DiagCurBuffer &&
28195ffd83dbSDimitry Andric       DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
28205ffd83dbSDimitry Andric     SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
28215ffd83dbSDimitry Andric     DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
28225ffd83dbSDimitry Andric   }
28235ffd83dbSDimitry Andric 
28245ffd83dbSDimitry Andric   // If we have not parsed a cpp hash line filename comment or the source
28255ffd83dbSDimitry Andric   // manager changed or buffer changed (like in a nested include) then just
28265ffd83dbSDimitry Andric   // print the normal diagnostic using its Filename and LineNo.
28275ffd83dbSDimitry Andric   if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
28285ffd83dbSDimitry Andric       DiagBuf != CppHashBuf) {
28295ffd83dbSDimitry Andric     if (Parser->SavedDiagHandler)
28305ffd83dbSDimitry Andric       Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
28315ffd83dbSDimitry Andric     else
28325ffd83dbSDimitry Andric       Diag.print(nullptr, OS);
28335ffd83dbSDimitry Andric     return;
28345ffd83dbSDimitry Andric   }
28355ffd83dbSDimitry Andric 
28365ffd83dbSDimitry Andric   // Use the CppHashFilename and calculate a line number based on the
28375ffd83dbSDimitry Andric   // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
28385ffd83dbSDimitry Andric   // for the diagnostic.
28395ffd83dbSDimitry Andric   const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
28405ffd83dbSDimitry Andric 
28415ffd83dbSDimitry Andric   int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
28425ffd83dbSDimitry Andric   int CppHashLocLineNo =
28435ffd83dbSDimitry Andric       Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
28445ffd83dbSDimitry Andric   int LineNo =
28455ffd83dbSDimitry Andric       Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
28465ffd83dbSDimitry Andric 
28475ffd83dbSDimitry Andric   SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
28485ffd83dbSDimitry Andric                        Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
28495ffd83dbSDimitry Andric                        Diag.getLineContents(), Diag.getRanges());
28505ffd83dbSDimitry Andric 
28515ffd83dbSDimitry Andric   if (Parser->SavedDiagHandler)
28525ffd83dbSDimitry Andric     Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
28535ffd83dbSDimitry Andric   else
28545ffd83dbSDimitry Andric     NewDiag.print(nullptr, OS);
28555ffd83dbSDimitry Andric }
28565ffd83dbSDimitry Andric 
2857e8d8bef9SDimitry Andric // This is similar to the IsIdentifierChar function in AsmLexer.cpp, but does
2858e8d8bef9SDimitry Andric // not accept '.'.
2859e8d8bef9SDimitry Andric static bool isMacroParameterChar(char C) {
2860e8d8bef9SDimitry Andric   return isAlnum(C) || C == '_' || C == '$' || C == '@' || C == '?';
28615ffd83dbSDimitry Andric }
28625ffd83dbSDimitry Andric 
28635ffd83dbSDimitry Andric bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
28645ffd83dbSDimitry Andric                              ArrayRef<MCAsmMacroParameter> Parameters,
28655ffd83dbSDimitry Andric                              ArrayRef<MCAsmMacroArgument> A,
2866e8d8bef9SDimitry Andric                              const std::vector<std::string> &Locals, SMLoc L) {
28675ffd83dbSDimitry Andric   unsigned NParameters = Parameters.size();
2868e8d8bef9SDimitry Andric   if (NParameters != A.size())
28695ffd83dbSDimitry Andric     return Error(L, "Wrong number of arguments");
2870e8d8bef9SDimitry Andric   StringMap<std::string> LocalSymbols;
2871e8d8bef9SDimitry Andric   std::string Name;
2872e8d8bef9SDimitry Andric   Name.reserve(6);
2873e8d8bef9SDimitry Andric   for (StringRef Local : Locals) {
2874e8d8bef9SDimitry Andric     raw_string_ostream LocalName(Name);
2875e8d8bef9SDimitry Andric     LocalName << "??"
2876e8d8bef9SDimitry Andric               << format_hex_no_prefix(LocalCounter++, 4, /*Upper=*/true);
2877e8d8bef9SDimitry Andric     LocalSymbols.insert({Local, LocalName.str()});
2878e8d8bef9SDimitry Andric     Name.clear();
2879e8d8bef9SDimitry Andric   }
28805ffd83dbSDimitry Andric 
2881*bdd1243dSDimitry Andric   std::optional<char> CurrentQuote;
28825ffd83dbSDimitry Andric   while (!Body.empty()) {
28835ffd83dbSDimitry Andric     // Scan for the next substitution.
28845ffd83dbSDimitry Andric     std::size_t End = Body.size(), Pos = 0;
2885e8d8bef9SDimitry Andric     std::size_t IdentifierPos = End;
28865ffd83dbSDimitry Andric     for (; Pos != End; ++Pos) {
2887e8d8bef9SDimitry Andric       // Find the next possible macro parameter, including preceding a '&'
2888e8d8bef9SDimitry Andric       // inside quotes.
2889e8d8bef9SDimitry Andric       if (Body[Pos] == '&')
28905ffd83dbSDimitry Andric         break;
2891e8d8bef9SDimitry Andric       if (isMacroParameterChar(Body[Pos])) {
289281ad6265SDimitry Andric         if (!CurrentQuote)
2893e8d8bef9SDimitry Andric           break;
2894e8d8bef9SDimitry Andric         if (IdentifierPos == End)
2895e8d8bef9SDimitry Andric           IdentifierPos = Pos;
28965ffd83dbSDimitry Andric       } else {
2897e8d8bef9SDimitry Andric         IdentifierPos = End;
28985ffd83dbSDimitry Andric       }
2899e8d8bef9SDimitry Andric 
2900e8d8bef9SDimitry Andric       // Track quotation status
290181ad6265SDimitry Andric       if (!CurrentQuote) {
2902e8d8bef9SDimitry Andric         if (Body[Pos] == '\'' || Body[Pos] == '"')
2903e8d8bef9SDimitry Andric           CurrentQuote = Body[Pos];
2904e8d8bef9SDimitry Andric       } else if (Body[Pos] == CurrentQuote) {
2905e8d8bef9SDimitry Andric         if (Pos + 1 != End && Body[Pos + 1] == CurrentQuote) {
2906e8d8bef9SDimitry Andric           // Escaped quote, and quotes aren't identifier chars; skip
2907e8d8bef9SDimitry Andric           ++Pos;
2908e8d8bef9SDimitry Andric           continue;
2909e8d8bef9SDimitry Andric         } else {
2910e8d8bef9SDimitry Andric           CurrentQuote.reset();
2911e8d8bef9SDimitry Andric         }
2912e8d8bef9SDimitry Andric       }
2913e8d8bef9SDimitry Andric     }
2914e8d8bef9SDimitry Andric     if (IdentifierPos != End) {
2915e8d8bef9SDimitry Andric       // We've recognized an identifier before an apostrophe inside quotes;
2916e8d8bef9SDimitry Andric       // check once to see if we can expand it.
2917e8d8bef9SDimitry Andric       Pos = IdentifierPos;
2918e8d8bef9SDimitry Andric       IdentifierPos = End;
29195ffd83dbSDimitry Andric     }
29205ffd83dbSDimitry Andric 
29215ffd83dbSDimitry Andric     // Add the prefix.
29225ffd83dbSDimitry Andric     OS << Body.slice(0, Pos);
29235ffd83dbSDimitry Andric 
29245ffd83dbSDimitry Andric     // Check if we reached the end.
29255ffd83dbSDimitry Andric     if (Pos == End)
29265ffd83dbSDimitry Andric       break;
29275ffd83dbSDimitry Andric 
2928e8d8bef9SDimitry Andric     unsigned I = Pos;
2929e8d8bef9SDimitry Andric     bool InitialAmpersand = (Body[I] == '&');
2930e8d8bef9SDimitry Andric     if (InitialAmpersand) {
29315ffd83dbSDimitry Andric       ++I;
2932e8d8bef9SDimitry Andric       ++Pos;
2933e8d8bef9SDimitry Andric     }
2934e8d8bef9SDimitry Andric     while (I < End && isMacroParameterChar(Body[I]))
29355ffd83dbSDimitry Andric       ++I;
29365ffd83dbSDimitry Andric 
2937e8d8bef9SDimitry Andric     const char *Begin = Body.data() + Pos;
2938e8d8bef9SDimitry Andric     StringRef Argument(Begin, I - Pos);
2939fe6060f1SDimitry Andric     const std::string ArgumentLower = Argument.lower();
29405ffd83dbSDimitry Andric     unsigned Index = 0;
29415ffd83dbSDimitry Andric 
29425ffd83dbSDimitry Andric     for (; Index < NParameters; ++Index)
2943fe6060f1SDimitry Andric       if (Parameters[Index].Name.equals_insensitive(ArgumentLower))
29445ffd83dbSDimitry Andric         break;
29455ffd83dbSDimitry Andric 
29465ffd83dbSDimitry Andric     if (Index == NParameters) {
2947e8d8bef9SDimitry Andric       if (InitialAmpersand)
2948e8d8bef9SDimitry Andric         OS << '&';
2949fe6060f1SDimitry Andric       auto it = LocalSymbols.find(ArgumentLower);
2950e8d8bef9SDimitry Andric       if (it != LocalSymbols.end())
2951e8d8bef9SDimitry Andric         OS << it->second;
2952e8d8bef9SDimitry Andric       else
2953e8d8bef9SDimitry Andric         OS << Argument;
29545ffd83dbSDimitry Andric       Pos = I;
29555ffd83dbSDimitry Andric     } else {
2956e8d8bef9SDimitry Andric       for (const AsmToken &Token : A[Index]) {
2957e8d8bef9SDimitry Andric         // In MASM, you can write '%expr'.
29585ffd83dbSDimitry Andric         // The prefix '%' evaluates the expression 'expr'
29595ffd83dbSDimitry Andric         // and uses the result as a string (e.g. replace %(1+2) with the
29605ffd83dbSDimitry Andric         // string "3").
29615ffd83dbSDimitry Andric         // Here, we identify the integer token which is the result of the
29625ffd83dbSDimitry Andric         // absolute expression evaluation and replace it with its string
29635ffd83dbSDimitry Andric         // representation.
2964e8d8bef9SDimitry Andric         if (Token.getString().front() == '%' && Token.is(AsmToken::Integer))
29655ffd83dbSDimitry Andric           // Emit an integer value to the buffer.
29665ffd83dbSDimitry Andric           OS << Token.getIntVal();
29675ffd83dbSDimitry Andric         else
2968e8d8bef9SDimitry Andric           OS << Token.getString();
29695ffd83dbSDimitry Andric       }
2970e8d8bef9SDimitry Andric 
2971e8d8bef9SDimitry Andric       Pos += Argument.size();
2972e8d8bef9SDimitry Andric       if (Pos < End && Body[Pos] == '&') {
2973e8d8bef9SDimitry Andric         ++Pos;
29745ffd83dbSDimitry Andric       }
29755ffd83dbSDimitry Andric     }
29765ffd83dbSDimitry Andric     // Update the scan point.
29775ffd83dbSDimitry Andric     Body = Body.substr(Pos);
29785ffd83dbSDimitry Andric   }
29795ffd83dbSDimitry Andric 
29805ffd83dbSDimitry Andric   return false;
29815ffd83dbSDimitry Andric }
29825ffd83dbSDimitry Andric 
29835ffd83dbSDimitry Andric static bool isOperator(AsmToken::TokenKind kind) {
29845ffd83dbSDimitry Andric   switch (kind) {
29855ffd83dbSDimitry Andric   default:
29865ffd83dbSDimitry Andric     return false;
29875ffd83dbSDimitry Andric   case AsmToken::Plus:
29885ffd83dbSDimitry Andric   case AsmToken::Minus:
29895ffd83dbSDimitry Andric   case AsmToken::Tilde:
29905ffd83dbSDimitry Andric   case AsmToken::Slash:
29915ffd83dbSDimitry Andric   case AsmToken::Star:
29925ffd83dbSDimitry Andric   case AsmToken::Dot:
29935ffd83dbSDimitry Andric   case AsmToken::Equal:
29945ffd83dbSDimitry Andric   case AsmToken::EqualEqual:
29955ffd83dbSDimitry Andric   case AsmToken::Pipe:
29965ffd83dbSDimitry Andric   case AsmToken::PipePipe:
29975ffd83dbSDimitry Andric   case AsmToken::Caret:
29985ffd83dbSDimitry Andric   case AsmToken::Amp:
29995ffd83dbSDimitry Andric   case AsmToken::AmpAmp:
30005ffd83dbSDimitry Andric   case AsmToken::Exclaim:
30015ffd83dbSDimitry Andric   case AsmToken::ExclaimEqual:
30025ffd83dbSDimitry Andric   case AsmToken::Less:
30035ffd83dbSDimitry Andric   case AsmToken::LessEqual:
30045ffd83dbSDimitry Andric   case AsmToken::LessLess:
30055ffd83dbSDimitry Andric   case AsmToken::LessGreater:
30065ffd83dbSDimitry Andric   case AsmToken::Greater:
30075ffd83dbSDimitry Andric   case AsmToken::GreaterEqual:
30085ffd83dbSDimitry Andric   case AsmToken::GreaterGreater:
30095ffd83dbSDimitry Andric     return true;
30105ffd83dbSDimitry Andric   }
30115ffd83dbSDimitry Andric }
30125ffd83dbSDimitry Andric 
30135ffd83dbSDimitry Andric namespace {
30145ffd83dbSDimitry Andric 
30155ffd83dbSDimitry Andric class AsmLexerSkipSpaceRAII {
30165ffd83dbSDimitry Andric public:
30175ffd83dbSDimitry Andric   AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
30185ffd83dbSDimitry Andric     Lexer.setSkipSpace(SkipSpace);
30195ffd83dbSDimitry Andric   }
30205ffd83dbSDimitry Andric 
30215ffd83dbSDimitry Andric   ~AsmLexerSkipSpaceRAII() {
30225ffd83dbSDimitry Andric     Lexer.setSkipSpace(true);
30235ffd83dbSDimitry Andric   }
30245ffd83dbSDimitry Andric 
30255ffd83dbSDimitry Andric private:
30265ffd83dbSDimitry Andric   AsmLexer &Lexer;
30275ffd83dbSDimitry Andric };
30285ffd83dbSDimitry Andric 
30295ffd83dbSDimitry Andric } // end anonymous namespace
30305ffd83dbSDimitry Andric 
3031e8d8bef9SDimitry Andric bool MasmParser::parseMacroArgument(const MCAsmMacroParameter *MP,
3032e8d8bef9SDimitry Andric                                     MCAsmMacroArgument &MA,
3033e8d8bef9SDimitry Andric                                     AsmToken::TokenKind EndTok) {
3034e8d8bef9SDimitry Andric   if (MP && MP->Vararg) {
3035e8d8bef9SDimitry Andric     if (Lexer.isNot(EndTok)) {
3036e8d8bef9SDimitry Andric       SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok);
3037e8d8bef9SDimitry Andric       for (StringRef S : Str) {
3038e8d8bef9SDimitry Andric         MA.emplace_back(AsmToken::String, S);
30395ffd83dbSDimitry Andric       }
3040e8d8bef9SDimitry Andric     }
3041e8d8bef9SDimitry Andric     return false;
3042e8d8bef9SDimitry Andric   }
3043e8d8bef9SDimitry Andric 
3044e8d8bef9SDimitry Andric   SMLoc StrLoc = Lexer.getLoc(), EndLoc;
3045e8d8bef9SDimitry Andric   if (Lexer.is(AsmToken::Less) && isAngleBracketString(StrLoc, EndLoc)) {
3046e8d8bef9SDimitry Andric     const char *StrChar = StrLoc.getPointer() + 1;
3047e8d8bef9SDimitry Andric     const char *EndChar = EndLoc.getPointer() - 1;
3048e8d8bef9SDimitry Andric     jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
3049e8d8bef9SDimitry Andric     /// Eat from '<' to '>'.
3050e8d8bef9SDimitry Andric     Lex();
3051e8d8bef9SDimitry Andric     MA.emplace_back(AsmToken::String, StringRef(StrChar, EndChar - StrChar));
30525ffd83dbSDimitry Andric     return false;
30535ffd83dbSDimitry Andric   }
30545ffd83dbSDimitry Andric 
30555ffd83dbSDimitry Andric   unsigned ParenLevel = 0;
30565ffd83dbSDimitry Andric 
30575ffd83dbSDimitry Andric   // Darwin doesn't use spaces to delmit arguments.
30585ffd83dbSDimitry Andric   AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);
30595ffd83dbSDimitry Andric 
30605ffd83dbSDimitry Andric   bool SpaceEaten;
30615ffd83dbSDimitry Andric 
30625ffd83dbSDimitry Andric   while (true) {
30635ffd83dbSDimitry Andric     SpaceEaten = false;
30645ffd83dbSDimitry Andric     if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
3065e8d8bef9SDimitry Andric       return TokError("unexpected token");
30665ffd83dbSDimitry Andric 
30675ffd83dbSDimitry Andric     if (ParenLevel == 0) {
30685ffd83dbSDimitry Andric       if (Lexer.is(AsmToken::Comma))
30695ffd83dbSDimitry Andric         break;
30705ffd83dbSDimitry Andric 
30715ffd83dbSDimitry Andric       if (Lexer.is(AsmToken::Space)) {
30725ffd83dbSDimitry Andric         SpaceEaten = true;
3073e8d8bef9SDimitry Andric         Lex(); // Eat spaces.
30745ffd83dbSDimitry Andric       }
30755ffd83dbSDimitry Andric 
30765ffd83dbSDimitry Andric       // Spaces can delimit parameters, but could also be part an expression.
30775ffd83dbSDimitry Andric       // If the token after a space is an operator, add the token and the next
30785ffd83dbSDimitry Andric       // one into this argument
30795ffd83dbSDimitry Andric       if (!IsDarwin) {
3080e8d8bef9SDimitry Andric         if (isOperator(Lexer.getKind()) && Lexer.isNot(EndTok)) {
30815ffd83dbSDimitry Andric           MA.push_back(getTok());
3082e8d8bef9SDimitry Andric           Lex();
30835ffd83dbSDimitry Andric 
30845ffd83dbSDimitry Andric           // Whitespace after an operator can be ignored.
30855ffd83dbSDimitry Andric           if (Lexer.is(AsmToken::Space))
3086e8d8bef9SDimitry Andric             Lex();
30875ffd83dbSDimitry Andric 
30885ffd83dbSDimitry Andric           continue;
30895ffd83dbSDimitry Andric         }
30905ffd83dbSDimitry Andric       }
30915ffd83dbSDimitry Andric       if (SpaceEaten)
30925ffd83dbSDimitry Andric         break;
30935ffd83dbSDimitry Andric     }
30945ffd83dbSDimitry Andric 
30955ffd83dbSDimitry Andric     // handleMacroEntry relies on not advancing the lexer here
30965ffd83dbSDimitry Andric     // to be able to fill in the remaining default parameter values
3097e8d8bef9SDimitry Andric     if (Lexer.is(EndTok) && (EndTok != AsmToken::RParen || ParenLevel == 0))
30985ffd83dbSDimitry Andric       break;
30995ffd83dbSDimitry Andric 
31005ffd83dbSDimitry Andric     // Adjust the current parentheses level.
31015ffd83dbSDimitry Andric     if (Lexer.is(AsmToken::LParen))
31025ffd83dbSDimitry Andric       ++ParenLevel;
31035ffd83dbSDimitry Andric     else if (Lexer.is(AsmToken::RParen) && ParenLevel)
31045ffd83dbSDimitry Andric       --ParenLevel;
31055ffd83dbSDimitry Andric 
31065ffd83dbSDimitry Andric     // Append the token to the current argument list.
31075ffd83dbSDimitry Andric     MA.push_back(getTok());
3108e8d8bef9SDimitry Andric     Lex();
31095ffd83dbSDimitry Andric   }
31105ffd83dbSDimitry Andric 
31115ffd83dbSDimitry Andric   if (ParenLevel != 0)
3112e8d8bef9SDimitry Andric     return TokError("unbalanced parentheses in argument");
3113e8d8bef9SDimitry Andric 
3114e8d8bef9SDimitry Andric   if (MA.empty() && MP) {
3115e8d8bef9SDimitry Andric     if (MP->Required) {
3116e8d8bef9SDimitry Andric       return TokError("missing value for required parameter '" + MP->Name +
3117e8d8bef9SDimitry Andric                       "'");
3118e8d8bef9SDimitry Andric     } else {
3119e8d8bef9SDimitry Andric       MA = MP->Value;
3120e8d8bef9SDimitry Andric     }
3121e8d8bef9SDimitry Andric   }
31225ffd83dbSDimitry Andric   return false;
31235ffd83dbSDimitry Andric }
31245ffd83dbSDimitry Andric 
31255ffd83dbSDimitry Andric // Parse the macro instantiation arguments.
31265ffd83dbSDimitry Andric bool MasmParser::parseMacroArguments(const MCAsmMacro *M,
3127e8d8bef9SDimitry Andric                                      MCAsmMacroArguments &A,
3128e8d8bef9SDimitry Andric                                      AsmToken::TokenKind EndTok) {
31295ffd83dbSDimitry Andric   const unsigned NParameters = M ? M->Parameters.size() : 0;
31305ffd83dbSDimitry Andric   bool NamedParametersFound = false;
31315ffd83dbSDimitry Andric   SmallVector<SMLoc, 4> FALocs;
31325ffd83dbSDimitry Andric 
31335ffd83dbSDimitry Andric   A.resize(NParameters);
31345ffd83dbSDimitry Andric   FALocs.resize(NParameters);
31355ffd83dbSDimitry Andric 
31365ffd83dbSDimitry Andric   // Parse two kinds of macro invocations:
31375ffd83dbSDimitry Andric   // - macros defined without any parameters accept an arbitrary number of them
31385ffd83dbSDimitry Andric   // - macros defined with parameters accept at most that many of them
31395ffd83dbSDimitry Andric   for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
31405ffd83dbSDimitry Andric        ++Parameter) {
31415ffd83dbSDimitry Andric     SMLoc IDLoc = Lexer.getLoc();
31425ffd83dbSDimitry Andric     MCAsmMacroParameter FA;
31435ffd83dbSDimitry Andric 
3144fe6060f1SDimitry Andric     if (Lexer.is(AsmToken::Identifier) && peekTok().is(AsmToken::Equal)) {
31455ffd83dbSDimitry Andric       if (parseIdentifier(FA.Name))
31465ffd83dbSDimitry Andric         return Error(IDLoc, "invalid argument identifier for formal argument");
31475ffd83dbSDimitry Andric 
31485ffd83dbSDimitry Andric       if (Lexer.isNot(AsmToken::Equal))
31495ffd83dbSDimitry Andric         return TokError("expected '=' after formal parameter identifier");
31505ffd83dbSDimitry Andric 
31515ffd83dbSDimitry Andric       Lex();
31525ffd83dbSDimitry Andric 
31535ffd83dbSDimitry Andric       NamedParametersFound = true;
31545ffd83dbSDimitry Andric     }
31555ffd83dbSDimitry Andric 
31565ffd83dbSDimitry Andric     if (NamedParametersFound && FA.Name.empty())
31575ffd83dbSDimitry Andric       return Error(IDLoc, "cannot mix positional and keyword arguments");
31585ffd83dbSDimitry Andric 
3159e8d8bef9SDimitry Andric     unsigned PI = Parameter;
3160e8d8bef9SDimitry Andric     if (!FA.Name.empty()) {
3161e8d8bef9SDimitry Andric       assert(M && "expected macro to be defined");
3162e8d8bef9SDimitry Andric       unsigned FAI = 0;
3163e8d8bef9SDimitry Andric       for (FAI = 0; FAI < NParameters; ++FAI)
3164e8d8bef9SDimitry Andric         if (M->Parameters[FAI].Name == FA.Name)
3165e8d8bef9SDimitry Andric           break;
3166e8d8bef9SDimitry Andric 
3167e8d8bef9SDimitry Andric       if (FAI >= NParameters) {
3168e8d8bef9SDimitry Andric         return Error(IDLoc, "parameter named '" + FA.Name +
3169e8d8bef9SDimitry Andric                                 "' does not exist for macro '" + M->Name + "'");
3170e8d8bef9SDimitry Andric       }
3171e8d8bef9SDimitry Andric       PI = FAI;
3172e8d8bef9SDimitry Andric     }
3173e8d8bef9SDimitry Andric     const MCAsmMacroParameter *MP = nullptr;
3174e8d8bef9SDimitry Andric     if (M && PI < NParameters)
3175e8d8bef9SDimitry Andric       MP = &M->Parameters[PI];
3176e8d8bef9SDimitry Andric 
31775ffd83dbSDimitry Andric     SMLoc StrLoc = Lexer.getLoc();
31785ffd83dbSDimitry Andric     SMLoc EndLoc;
3179e8d8bef9SDimitry Andric     if (Lexer.is(AsmToken::Percent)) {
31805ffd83dbSDimitry Andric       const MCExpr *AbsoluteExp;
31815ffd83dbSDimitry Andric       int64_t Value;
31825ffd83dbSDimitry Andric       /// Eat '%'.
31835ffd83dbSDimitry Andric       Lex();
31845ffd83dbSDimitry Andric       if (parseExpression(AbsoluteExp, EndLoc))
31855ffd83dbSDimitry Andric         return false;
31865ffd83dbSDimitry Andric       if (!AbsoluteExp->evaluateAsAbsolute(Value,
31875ffd83dbSDimitry Andric                                            getStreamer().getAssemblerPtr()))
31885ffd83dbSDimitry Andric         return Error(StrLoc, "expected absolute expression");
31895ffd83dbSDimitry Andric       const char *StrChar = StrLoc.getPointer();
31905ffd83dbSDimitry Andric       const char *EndChar = EndLoc.getPointer();
31915ffd83dbSDimitry Andric       AsmToken newToken(AsmToken::Integer,
31925ffd83dbSDimitry Andric                         StringRef(StrChar, EndChar - StrChar), Value);
31935ffd83dbSDimitry Andric       FA.Value.push_back(newToken);
3194e8d8bef9SDimitry Andric     } else if (parseMacroArgument(MP, FA.Value, EndTok)) {
3195e8d8bef9SDimitry Andric       if (M)
3196e8d8bef9SDimitry Andric         return addErrorSuffix(" in '" + M->Name + "' macro");
3197e8d8bef9SDimitry Andric       else
31985ffd83dbSDimitry Andric         return true;
31995ffd83dbSDimitry Andric     }
32005ffd83dbSDimitry Andric 
32015ffd83dbSDimitry Andric     if (!FA.Value.empty()) {
32025ffd83dbSDimitry Andric       if (A.size() <= PI)
32035ffd83dbSDimitry Andric         A.resize(PI + 1);
32045ffd83dbSDimitry Andric       A[PI] = FA.Value;
32055ffd83dbSDimitry Andric 
32065ffd83dbSDimitry Andric       if (FALocs.size() <= PI)
32075ffd83dbSDimitry Andric         FALocs.resize(PI + 1);
32085ffd83dbSDimitry Andric 
32095ffd83dbSDimitry Andric       FALocs[PI] = Lexer.getLoc();
32105ffd83dbSDimitry Andric     }
32115ffd83dbSDimitry Andric 
32125ffd83dbSDimitry Andric     // At the end of the statement, fill in remaining arguments that have
32135ffd83dbSDimitry Andric     // default values. If there aren't any, then the next argument is
32145ffd83dbSDimitry Andric     // required but missing
3215e8d8bef9SDimitry Andric     if (Lexer.is(EndTok)) {
32165ffd83dbSDimitry Andric       bool Failure = false;
32175ffd83dbSDimitry Andric       for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
32185ffd83dbSDimitry Andric         if (A[FAI].empty()) {
32195ffd83dbSDimitry Andric           if (M->Parameters[FAI].Required) {
32205ffd83dbSDimitry Andric             Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
32215ffd83dbSDimitry Andric                   "missing value for required parameter "
3222e8d8bef9SDimitry Andric                   "'" +
3223e8d8bef9SDimitry Andric                       M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
32245ffd83dbSDimitry Andric             Failure = true;
32255ffd83dbSDimitry Andric           }
32265ffd83dbSDimitry Andric 
32275ffd83dbSDimitry Andric           if (!M->Parameters[FAI].Value.empty())
32285ffd83dbSDimitry Andric             A[FAI] = M->Parameters[FAI].Value;
32295ffd83dbSDimitry Andric         }
32305ffd83dbSDimitry Andric       }
32315ffd83dbSDimitry Andric       return Failure;
32325ffd83dbSDimitry Andric     }
32335ffd83dbSDimitry Andric 
32345ffd83dbSDimitry Andric     if (Lexer.is(AsmToken::Comma))
32355ffd83dbSDimitry Andric       Lex();
32365ffd83dbSDimitry Andric   }
32375ffd83dbSDimitry Andric 
32385ffd83dbSDimitry Andric   return TokError("too many positional arguments");
32395ffd83dbSDimitry Andric }
32405ffd83dbSDimitry Andric 
3241e8d8bef9SDimitry Andric bool MasmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc,
3242e8d8bef9SDimitry Andric                                   AsmToken::TokenKind ArgumentEndTok) {
32435ffd83dbSDimitry Andric   // Arbitrarily limit macro nesting depth (default matches 'as'). We can
32445ffd83dbSDimitry Andric   // eliminate this, although we should protect against infinite loops.
32455ffd83dbSDimitry Andric   unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;
32465ffd83dbSDimitry Andric   if (ActiveMacros.size() == MaxNestingDepth) {
32475ffd83dbSDimitry Andric     std::ostringstream MaxNestingDepthError;
32485ffd83dbSDimitry Andric     MaxNestingDepthError << "macros cannot be nested more than "
32495ffd83dbSDimitry Andric                          << MaxNestingDepth << " levels deep."
32505ffd83dbSDimitry Andric                          << " Use -asm-macro-max-nesting-depth to increase "
32515ffd83dbSDimitry Andric                             "this limit.";
32525ffd83dbSDimitry Andric     return TokError(MaxNestingDepthError.str());
32535ffd83dbSDimitry Andric   }
32545ffd83dbSDimitry Andric 
32555ffd83dbSDimitry Andric   MCAsmMacroArguments A;
3256e8d8bef9SDimitry Andric   if (parseMacroArguments(M, A, ArgumentEndTok))
32575ffd83dbSDimitry Andric     return true;
32585ffd83dbSDimitry Andric 
32595ffd83dbSDimitry Andric   // Macro instantiation is lexical, unfortunately. We construct a new buffer
32605ffd83dbSDimitry Andric   // to hold the macro body with substitutions.
32615ffd83dbSDimitry Andric   SmallString<256> Buf;
32625ffd83dbSDimitry Andric   StringRef Body = M->Body;
32635ffd83dbSDimitry Andric   raw_svector_ostream OS(Buf);
32645ffd83dbSDimitry Andric 
3265e8d8bef9SDimitry Andric   if (expandMacro(OS, Body, M->Parameters, A, M->Locals, getTok().getLoc()))
32665ffd83dbSDimitry Andric     return true;
32675ffd83dbSDimitry Andric 
3268e8d8bef9SDimitry Andric   // We include the endm in the buffer as our cue to exit the macro
32695ffd83dbSDimitry Andric   // instantiation.
3270e8d8bef9SDimitry Andric   OS << "endm\n";
32715ffd83dbSDimitry Andric 
32725ffd83dbSDimitry Andric   std::unique_ptr<MemoryBuffer> Instantiation =
32735ffd83dbSDimitry Andric       MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
32745ffd83dbSDimitry Andric 
32755ffd83dbSDimitry Andric   // Create the macro instantiation object and add to the current macro
32765ffd83dbSDimitry Andric   // instantiation stack.
32775ffd83dbSDimitry Andric   MacroInstantiation *MI = new MacroInstantiation{
32785ffd83dbSDimitry Andric       NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
32795ffd83dbSDimitry Andric   ActiveMacros.push_back(MI);
32805ffd83dbSDimitry Andric 
32815ffd83dbSDimitry Andric   ++NumOfMacroInstantiations;
32825ffd83dbSDimitry Andric 
32835ffd83dbSDimitry Andric   // Jump to the macro instantiation and prime the lexer.
32845ffd83dbSDimitry Andric   CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
32855ffd83dbSDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
3286e8d8bef9SDimitry Andric   EndStatementAtEOFStack.push_back(true);
32875ffd83dbSDimitry Andric   Lex();
32885ffd83dbSDimitry Andric 
32895ffd83dbSDimitry Andric   return false;
32905ffd83dbSDimitry Andric }
32915ffd83dbSDimitry Andric 
32925ffd83dbSDimitry Andric void MasmParser::handleMacroExit() {
3293e8d8bef9SDimitry Andric   // Jump to the token we should return to, and consume it.
3294e8d8bef9SDimitry Andric   EndStatementAtEOFStack.pop_back();
3295e8d8bef9SDimitry Andric   jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer,
3296e8d8bef9SDimitry Andric             EndStatementAtEOFStack.back());
32975ffd83dbSDimitry Andric   Lex();
32985ffd83dbSDimitry Andric 
32995ffd83dbSDimitry Andric   // Pop the instantiation entry.
33005ffd83dbSDimitry Andric   delete ActiveMacros.back();
33015ffd83dbSDimitry Andric   ActiveMacros.pop_back();
33025ffd83dbSDimitry Andric }
33035ffd83dbSDimitry Andric 
3304e8d8bef9SDimitry Andric bool MasmParser::handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc) {
3305e8d8bef9SDimitry Andric   if (!M->IsFunction)
3306e8d8bef9SDimitry Andric     return Error(NameLoc, "cannot invoke macro procedure as function");
3307e8d8bef9SDimitry Andric 
3308e8d8bef9SDimitry Andric   if (parseToken(AsmToken::LParen, "invoking macro function '" + M->Name +
3309e8d8bef9SDimitry Andric                                        "' requires arguments in parentheses") ||
3310e8d8bef9SDimitry Andric       handleMacroEntry(M, NameLoc, AsmToken::RParen))
3311e8d8bef9SDimitry Andric     return true;
3312e8d8bef9SDimitry Andric 
3313e8d8bef9SDimitry Andric   // Parse all statements in the macro, retrieving the exit value when it ends.
3314e8d8bef9SDimitry Andric   std::string ExitValue;
3315e8d8bef9SDimitry Andric   SmallVector<AsmRewrite, 4> AsmStrRewrites;
3316e8d8bef9SDimitry Andric   while (Lexer.isNot(AsmToken::Eof)) {
3317e8d8bef9SDimitry Andric     ParseStatementInfo Info(&AsmStrRewrites);
3318e8d8bef9SDimitry Andric     bool Parsed = parseStatement(Info, nullptr);
3319e8d8bef9SDimitry Andric 
332081ad6265SDimitry Andric     if (!Parsed && Info.ExitValue) {
3321e8d8bef9SDimitry Andric       ExitValue = std::move(*Info.ExitValue);
3322e8d8bef9SDimitry Andric       break;
3323e8d8bef9SDimitry Andric     }
3324e8d8bef9SDimitry Andric 
3325e8d8bef9SDimitry Andric     // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
3326e8d8bef9SDimitry Andric     // for printing ErrMsg via Lex() only if no (presumably better) parser error
3327e8d8bef9SDimitry Andric     // exists.
3328e8d8bef9SDimitry Andric     if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
3329e8d8bef9SDimitry Andric       Lex();
3330e8d8bef9SDimitry Andric     }
3331e8d8bef9SDimitry Andric 
3332e8d8bef9SDimitry Andric     // parseStatement returned true so may need to emit an error.
3333e8d8bef9SDimitry Andric     printPendingErrors();
3334e8d8bef9SDimitry Andric 
3335e8d8bef9SDimitry Andric     // Skipping to the next line if needed.
3336e8d8bef9SDimitry Andric     if (Parsed && !getLexer().isAtStartOfStatement())
3337e8d8bef9SDimitry Andric       eatToEndOfStatement();
3338e8d8bef9SDimitry Andric   }
3339e8d8bef9SDimitry Andric 
3340e8d8bef9SDimitry Andric   // Consume the right-parenthesis on the other side of the arguments.
334104eeddc0SDimitry Andric   if (parseRParen())
3342e8d8bef9SDimitry Andric     return true;
3343e8d8bef9SDimitry Andric 
3344e8d8bef9SDimitry Andric   // Exit values may require lexing, unfortunately. We construct a new buffer to
3345e8d8bef9SDimitry Andric   // hold the exit value.
3346e8d8bef9SDimitry Andric   std::unique_ptr<MemoryBuffer> MacroValue =
3347e8d8bef9SDimitry Andric       MemoryBuffer::getMemBufferCopy(ExitValue, "<macro-value>");
3348e8d8bef9SDimitry Andric 
3349e8d8bef9SDimitry Andric   // Jump from this location to the instantiated exit value, and prime the
3350e8d8bef9SDimitry Andric   // lexer.
3351e8d8bef9SDimitry Andric   CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(MacroValue), Lexer.getLoc());
3352e8d8bef9SDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), nullptr,
3353e8d8bef9SDimitry Andric                   /*EndStatementAtEOF=*/false);
3354e8d8bef9SDimitry Andric   EndStatementAtEOFStack.push_back(false);
3355e8d8bef9SDimitry Andric   Lex();
3356e8d8bef9SDimitry Andric 
3357e8d8bef9SDimitry Andric   return false;
3358e8d8bef9SDimitry Andric }
3359e8d8bef9SDimitry Andric 
33605ffd83dbSDimitry Andric /// parseIdentifier:
33615ffd83dbSDimitry Andric ///   ::= identifier
33625ffd83dbSDimitry Andric ///   ::= string
3363fe6060f1SDimitry Andric bool MasmParser::parseIdentifier(StringRef &Res,
3364fe6060f1SDimitry Andric                                  IdentifierPositionKind Position) {
33655ffd83dbSDimitry Andric   // The assembler has relaxed rules for accepting identifiers, in particular we
33665ffd83dbSDimitry Andric   // allow things like '.globl $foo' and '.def @feat.00', which would normally
33675ffd83dbSDimitry Andric   // be separate tokens. At this level, we have already lexed so we cannot
33685ffd83dbSDimitry Andric   // (currently) handle this as a context dependent token, instead we detect
33695ffd83dbSDimitry Andric   // adjacent tokens and return the combined identifier.
33705ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
33715ffd83dbSDimitry Andric     SMLoc PrefixLoc = getLexer().getLoc();
33725ffd83dbSDimitry Andric 
33735ffd83dbSDimitry Andric     // Consume the prefix character, and check for a following identifier.
33745ffd83dbSDimitry Andric 
3375fe6060f1SDimitry Andric     AsmToken nextTok = peekTok(false);
33765ffd83dbSDimitry Andric 
3377fe6060f1SDimitry Andric     if (nextTok.isNot(AsmToken::Identifier))
33785ffd83dbSDimitry Andric       return true;
33795ffd83dbSDimitry Andric 
33805ffd83dbSDimitry Andric     // We have a '$' or '@' followed by an identifier, make sure they are adjacent.
3381fe6060f1SDimitry Andric     if (PrefixLoc.getPointer() + 1 != nextTok.getLoc().getPointer())
33825ffd83dbSDimitry Andric       return true;
33835ffd83dbSDimitry Andric 
33845ffd83dbSDimitry Andric     // eat $ or @
33855ffd83dbSDimitry Andric     Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
33865ffd83dbSDimitry Andric     // Construct the joined identifier and consume the token.
33875ffd83dbSDimitry Andric     Res =
33885ffd83dbSDimitry Andric         StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1);
33895ffd83dbSDimitry Andric     Lex(); // Parser Lex to maintain invariants.
33905ffd83dbSDimitry Andric     return false;
33915ffd83dbSDimitry Andric   }
33925ffd83dbSDimitry Andric 
33935ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
33945ffd83dbSDimitry Andric     return true;
33955ffd83dbSDimitry Andric 
33965ffd83dbSDimitry Andric   Res = getTok().getIdentifier();
33975ffd83dbSDimitry Andric 
3398fe6060f1SDimitry Andric   // Consume the identifier token - but if parsing certain directives, avoid
3399fe6060f1SDimitry Andric   // lexical expansion of the next token.
3400fe6060f1SDimitry Andric   ExpandKind ExpandNextToken = ExpandMacros;
3401fe6060f1SDimitry Andric   if (Position == StartOfStatement &&
3402fe6060f1SDimitry Andric       StringSwitch<bool>(Res)
3403fe6060f1SDimitry Andric           .CaseLower("echo", true)
3404fe6060f1SDimitry Andric           .CasesLower("ifdef", "ifndef", "elseifdef", "elseifndef", true)
3405fe6060f1SDimitry Andric           .Default(false)) {
3406fe6060f1SDimitry Andric     ExpandNextToken = DoNotExpandMacros;
3407fe6060f1SDimitry Andric   }
3408fe6060f1SDimitry Andric   Lex(ExpandNextToken);
34095ffd83dbSDimitry Andric 
34105ffd83dbSDimitry Andric   return false;
34115ffd83dbSDimitry Andric }
34125ffd83dbSDimitry Andric 
34135ffd83dbSDimitry Andric /// parseDirectiveEquate:
34145ffd83dbSDimitry Andric ///  ::= name "=" expression
34155ffd83dbSDimitry Andric ///    | name "equ" expression    (not redefinable)
34165ffd83dbSDimitry Andric ///    | name "equ" text-list
3417fe6060f1SDimitry Andric ///    | name "textequ" text-list (redefinability unspecified)
34185ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
3419fe6060f1SDimitry Andric                                       DirectiveKind DirKind, SMLoc NameLoc) {
3420fe6060f1SDimitry Andric   auto BuiltinIt = BuiltinSymbolMap.find(Name.lower());
3421fe6060f1SDimitry Andric   if (BuiltinIt != BuiltinSymbolMap.end())
3422fe6060f1SDimitry Andric     return Error(NameLoc, "cannot redefine a built-in symbol");
3423fe6060f1SDimitry Andric 
3424fe6060f1SDimitry Andric   Variable &Var = Variables[Name.lower()];
34255ffd83dbSDimitry Andric   if (Var.Name.empty()) {
34265ffd83dbSDimitry Andric     Var.Name = Name;
34275ffd83dbSDimitry Andric   }
34285ffd83dbSDimitry Andric 
3429fe6060f1SDimitry Andric   SMLoc StartLoc = Lexer.getLoc();
34305ffd83dbSDimitry Andric   if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) {
34315ffd83dbSDimitry Andric     // "equ" and "textequ" both allow text expressions.
34325ffd83dbSDimitry Andric     std::string Value;
3433fe6060f1SDimitry Andric     std::string TextItem;
3434fe6060f1SDimitry Andric     if (!parseTextItem(TextItem)) {
3435fe6060f1SDimitry Andric       Value += TextItem;
34365ffd83dbSDimitry Andric 
34375ffd83dbSDimitry Andric       // Accept a text-list, not just one text-item.
34385ffd83dbSDimitry Andric       auto parseItem = [&]() -> bool {
3439fe6060f1SDimitry Andric         if (parseTextItem(TextItem))
3440e8d8bef9SDimitry Andric           return TokError("expected text item");
3441fe6060f1SDimitry Andric         Value += TextItem;
34425ffd83dbSDimitry Andric         return false;
34435ffd83dbSDimitry Andric       };
34445ffd83dbSDimitry Andric       if (parseOptionalToken(AsmToken::Comma) && parseMany(parseItem))
34455ffd83dbSDimitry Andric         return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
34465ffd83dbSDimitry Andric 
3447fe6060f1SDimitry Andric       if (!Var.IsText || Var.TextValue != Value) {
3448fe6060f1SDimitry Andric         switch (Var.Redefinable) {
3449fe6060f1SDimitry Andric         case Variable::NOT_REDEFINABLE:
3450fe6060f1SDimitry Andric           return Error(getTok().getLoc(), "invalid variable redefinition");
3451fe6060f1SDimitry Andric         case Variable::WARN_ON_REDEFINITION:
3452fe6060f1SDimitry Andric           if (Warning(NameLoc, "redefining '" + Name +
3453fe6060f1SDimitry Andric                                    "', already defined on the command line")) {
3454fe6060f1SDimitry Andric             return true;
3455fe6060f1SDimitry Andric           }
3456fe6060f1SDimitry Andric           break;
3457fe6060f1SDimitry Andric         default:
3458fe6060f1SDimitry Andric           break;
3459fe6060f1SDimitry Andric         }
3460fe6060f1SDimitry Andric       }
3461fe6060f1SDimitry Andric       Var.IsText = true;
3462fe6060f1SDimitry Andric       Var.TextValue = Value;
3463fe6060f1SDimitry Andric       Var.Redefinable = Variable::REDEFINABLE;
3464fe6060f1SDimitry Andric 
34655ffd83dbSDimitry Andric       return false;
34665ffd83dbSDimitry Andric     }
34675ffd83dbSDimitry Andric   }
34685ffd83dbSDimitry Andric   if (DirKind == DK_TEXTEQU)
34695ffd83dbSDimitry Andric     return TokError("expected <text> in '" + Twine(IDVal) + "' directive");
34705ffd83dbSDimitry Andric 
34715ffd83dbSDimitry Andric   // Parse as expression assignment.
34725ffd83dbSDimitry Andric   const MCExpr *Expr;
3473fe6060f1SDimitry Andric   SMLoc EndLoc;
34745ffd83dbSDimitry Andric   if (parseExpression(Expr, EndLoc))
34755ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3476fe6060f1SDimitry Andric   StringRef ExprAsString = StringRef(
3477fe6060f1SDimitry Andric       StartLoc.getPointer(), EndLoc.getPointer() - StartLoc.getPointer());
3478fe6060f1SDimitry Andric 
3479fe6060f1SDimitry Andric   int64_t Value;
3480fe6060f1SDimitry Andric   if (!Expr->evaluateAsAbsolute(Value, getStreamer().getAssemblerPtr())) {
3481fe6060f1SDimitry Andric     if (DirKind == DK_ASSIGN)
3482fe6060f1SDimitry Andric       return Error(
3483fe6060f1SDimitry Andric           StartLoc,
3484fe6060f1SDimitry Andric           "expected absolute expression; not all symbols have known values",
3485fe6060f1SDimitry Andric           {StartLoc, EndLoc});
3486fe6060f1SDimitry Andric 
3487fe6060f1SDimitry Andric     // Not an absolute expression; define as a text replacement.
3488fe6060f1SDimitry Andric     if (!Var.IsText || Var.TextValue != ExprAsString) {
3489fe6060f1SDimitry Andric       switch (Var.Redefinable) {
3490fe6060f1SDimitry Andric       case Variable::NOT_REDEFINABLE:
3491fe6060f1SDimitry Andric         return Error(getTok().getLoc(), "invalid variable redefinition");
3492fe6060f1SDimitry Andric       case Variable::WARN_ON_REDEFINITION:
3493fe6060f1SDimitry Andric         if (Warning(NameLoc, "redefining '" + Name +
3494fe6060f1SDimitry Andric                                  "', already defined on the command line")) {
3495fe6060f1SDimitry Andric           return true;
3496fe6060f1SDimitry Andric         }
3497fe6060f1SDimitry Andric         break;
3498fe6060f1SDimitry Andric       default:
3499fe6060f1SDimitry Andric         break;
3500fe6060f1SDimitry Andric       }
3501fe6060f1SDimitry Andric     }
3502fe6060f1SDimitry Andric 
3503fe6060f1SDimitry Andric     Var.IsText = true;
3504fe6060f1SDimitry Andric     Var.TextValue = ExprAsString.str();
3505fe6060f1SDimitry Andric     Var.Redefinable = Variable::REDEFINABLE;
3506fe6060f1SDimitry Andric 
3507fe6060f1SDimitry Andric     return false;
3508fe6060f1SDimitry Andric   }
3509fe6060f1SDimitry Andric 
3510e8d8bef9SDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Var.Name);
3511fe6060f1SDimitry Andric 
3512fe6060f1SDimitry Andric   const MCConstantExpr *PrevValue =
3513fe6060f1SDimitry Andric       Sym->isVariable() ? dyn_cast_or_null<MCConstantExpr>(
3514fe6060f1SDimitry Andric                               Sym->getVariableValue(/*SetUsed=*/false))
3515fe6060f1SDimitry Andric                         : nullptr;
3516fe6060f1SDimitry Andric   if (Var.IsText || !PrevValue || PrevValue->getValue() != Value) {
3517fe6060f1SDimitry Andric     switch (Var.Redefinable) {
3518fe6060f1SDimitry Andric     case Variable::NOT_REDEFINABLE:
3519fe6060f1SDimitry Andric       return Error(getTok().getLoc(), "invalid variable redefinition");
3520fe6060f1SDimitry Andric     case Variable::WARN_ON_REDEFINITION:
3521fe6060f1SDimitry Andric       if (Warning(NameLoc, "redefining '" + Name +
3522fe6060f1SDimitry Andric                                "', already defined on the command line")) {
3523fe6060f1SDimitry Andric         return true;
3524fe6060f1SDimitry Andric       }
3525fe6060f1SDimitry Andric       break;
3526fe6060f1SDimitry Andric     default:
3527fe6060f1SDimitry Andric       break;
3528fe6060f1SDimitry Andric     }
3529fe6060f1SDimitry Andric   }
3530fe6060f1SDimitry Andric 
3531fe6060f1SDimitry Andric   Var.IsText = false;
3532fe6060f1SDimitry Andric   Var.TextValue.clear();
3533fe6060f1SDimitry Andric   Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE
3534fe6060f1SDimitry Andric                                            : Variable::NOT_REDEFINABLE;
3535fe6060f1SDimitry Andric 
3536fe6060f1SDimitry Andric   Sym->setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE);
3537e8d8bef9SDimitry Andric   Sym->setVariableValue(Expr);
3538e8d8bef9SDimitry Andric   Sym->setExternal(false);
3539e8d8bef9SDimitry Andric 
35405ffd83dbSDimitry Andric   return false;
35415ffd83dbSDimitry Andric }
35425ffd83dbSDimitry Andric 
35435ffd83dbSDimitry Andric bool MasmParser::parseEscapedString(std::string &Data) {
35445ffd83dbSDimitry Andric   if (check(getTok().isNot(AsmToken::String), "expected string"))
35455ffd83dbSDimitry Andric     return true;
35465ffd83dbSDimitry Andric 
35475ffd83dbSDimitry Andric   Data = "";
3548e8d8bef9SDimitry Andric   char Quote = getTok().getString().front();
35495ffd83dbSDimitry Andric   StringRef Str = getTok().getStringContents();
3550e8d8bef9SDimitry Andric   Data.reserve(Str.size());
3551e8d8bef9SDimitry Andric   for (size_t i = 0, e = Str.size(); i != e; ++i) {
3552e8d8bef9SDimitry Andric     Data.push_back(Str[i]);
3553e8d8bef9SDimitry Andric     if (Str[i] == Quote) {
3554e8d8bef9SDimitry Andric       // MASM treats doubled delimiting quotes as an escaped delimiting quote.
3555e8d8bef9SDimitry Andric       // If we're escaping the string's trailing delimiter, we're definitely
3556e8d8bef9SDimitry Andric       // missing a quotation mark.
3557e8d8bef9SDimitry Andric       if (i + 1 == Str.size())
3558e8d8bef9SDimitry Andric         return Error(getTok().getLoc(), "missing quotation mark in string");
3559e8d8bef9SDimitry Andric       if (Str[i + 1] == Quote)
35605ffd83dbSDimitry Andric         ++i;
35615ffd83dbSDimitry Andric     }
35625ffd83dbSDimitry Andric   }
35635ffd83dbSDimitry Andric 
35645ffd83dbSDimitry Andric   Lex();
35655ffd83dbSDimitry Andric   return false;
35665ffd83dbSDimitry Andric }
35675ffd83dbSDimitry Andric 
35685ffd83dbSDimitry Andric bool MasmParser::parseAngleBracketString(std::string &Data) {
35695ffd83dbSDimitry Andric   SMLoc EndLoc, StartLoc = getTok().getLoc();
35705ffd83dbSDimitry Andric   if (isAngleBracketString(StartLoc, EndLoc)) {
35715ffd83dbSDimitry Andric     const char *StartChar = StartLoc.getPointer() + 1;
35725ffd83dbSDimitry Andric     const char *EndChar = EndLoc.getPointer() - 1;
3573e8d8bef9SDimitry Andric     jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
35745ffd83dbSDimitry Andric     // Eat from '<' to '>'.
35755ffd83dbSDimitry Andric     Lex();
35765ffd83dbSDimitry Andric 
35775ffd83dbSDimitry Andric     Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
35785ffd83dbSDimitry Andric     return false;
35795ffd83dbSDimitry Andric   }
35805ffd83dbSDimitry Andric   return true;
35815ffd83dbSDimitry Andric }
35825ffd83dbSDimitry Andric 
35835ffd83dbSDimitry Andric /// textItem ::= textLiteral | textMacroID | % constExpr
35845ffd83dbSDimitry Andric bool MasmParser::parseTextItem(std::string &Data) {
3585e8d8bef9SDimitry Andric   switch (getTok().getKind()) {
3586e8d8bef9SDimitry Andric   default:
3587e8d8bef9SDimitry Andric     return true;
3588e8d8bef9SDimitry Andric   case AsmToken::Percent: {
3589e8d8bef9SDimitry Andric     int64_t Res;
3590e8d8bef9SDimitry Andric     if (parseToken(AsmToken::Percent) || parseAbsoluteExpression(Res))
3591e8d8bef9SDimitry Andric       return true;
3592e8d8bef9SDimitry Andric     Data = std::to_string(Res);
3593e8d8bef9SDimitry Andric     return false;
3594e8d8bef9SDimitry Andric   }
3595e8d8bef9SDimitry Andric   case AsmToken::Less:
3596e8d8bef9SDimitry Andric   case AsmToken::LessEqual:
3597e8d8bef9SDimitry Andric   case AsmToken::LessLess:
3598e8d8bef9SDimitry Andric   case AsmToken::LessGreater:
35995ffd83dbSDimitry Andric     return parseAngleBracketString(Data);
3600e8d8bef9SDimitry Andric   case AsmToken::Identifier: {
3601fe6060f1SDimitry Andric     // This must be a text macro; we need to expand it accordingly.
3602e8d8bef9SDimitry Andric     StringRef ID;
3603fe6060f1SDimitry Andric     SMLoc StartLoc = getTok().getLoc();
3604e8d8bef9SDimitry Andric     if (parseIdentifier(ID))
3605e8d8bef9SDimitry Andric       return true;
3606e8d8bef9SDimitry Andric     Data = ID.str();
3607e8d8bef9SDimitry Andric 
3608fe6060f1SDimitry Andric     bool Expanded = false;
3609fe6060f1SDimitry Andric     while (true) {
3610fe6060f1SDimitry Andric       // Try to resolve as a built-in text macro
3611fe6060f1SDimitry Andric       auto BuiltinIt = BuiltinSymbolMap.find(ID.lower());
3612fe6060f1SDimitry Andric       if (BuiltinIt != BuiltinSymbolMap.end()) {
3613*bdd1243dSDimitry Andric         std::optional<std::string> BuiltinText =
3614fe6060f1SDimitry Andric             evaluateBuiltinTextMacro(BuiltinIt->getValue(), StartLoc);
361581ad6265SDimitry Andric         if (!BuiltinText) {
3616fe6060f1SDimitry Andric           // Not a text macro; break without substituting
3617fe6060f1SDimitry Andric           break;
3618fe6060f1SDimitry Andric         }
3619fe6060f1SDimitry Andric         Data = std::move(*BuiltinText);
3620fe6060f1SDimitry Andric         ID = StringRef(Data);
3621fe6060f1SDimitry Andric         Expanded = true;
3622fe6060f1SDimitry Andric         continue;
3623fe6060f1SDimitry Andric       }
3624e8d8bef9SDimitry Andric 
3625fe6060f1SDimitry Andric       // Try to resolve as a variable text macro
3626fe6060f1SDimitry Andric       auto VarIt = Variables.find(ID.lower());
3627fe6060f1SDimitry Andric       if (VarIt != Variables.end()) {
3628fe6060f1SDimitry Andric         const Variable &Var = VarIt->getValue();
3629fe6060f1SDimitry Andric         if (!Var.IsText) {
3630fe6060f1SDimitry Andric           // Not a text macro; break without substituting
3631fe6060f1SDimitry Andric           break;
3632fe6060f1SDimitry Andric         }
3633e8d8bef9SDimitry Andric         Data = Var.TextValue;
3634fe6060f1SDimitry Andric         ID = StringRef(Data);
3635fe6060f1SDimitry Andric         Expanded = true;
3636fe6060f1SDimitry Andric         continue;
3637fe6060f1SDimitry Andric       }
3638fe6060f1SDimitry Andric 
3639fe6060f1SDimitry Andric       break;
3640fe6060f1SDimitry Andric     }
3641fe6060f1SDimitry Andric 
3642fe6060f1SDimitry Andric     if (!Expanded) {
3643fe6060f1SDimitry Andric       // Not a text macro; not usable in TextItem context. Since we haven't used
3644fe6060f1SDimitry Andric       // the token, put it back for better error recovery.
3645fe6060f1SDimitry Andric       getLexer().UnLex(AsmToken(AsmToken::Identifier, ID));
3646fe6060f1SDimitry Andric       return true;
3647e8d8bef9SDimitry Andric     }
3648e8d8bef9SDimitry Andric     return false;
3649e8d8bef9SDimitry Andric   }
3650e8d8bef9SDimitry Andric   }
3651e8d8bef9SDimitry Andric   llvm_unreachable("unhandled token kind");
36525ffd83dbSDimitry Andric }
36535ffd83dbSDimitry Andric 
36545ffd83dbSDimitry Andric /// parseDirectiveAscii:
36555ffd83dbSDimitry Andric ///   ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
36565ffd83dbSDimitry Andric bool MasmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
36575ffd83dbSDimitry Andric   auto parseOp = [&]() -> bool {
36585ffd83dbSDimitry Andric     std::string Data;
36595ffd83dbSDimitry Andric     if (checkForValidSection() || parseEscapedString(Data))
36605ffd83dbSDimitry Andric       return true;
36615ffd83dbSDimitry Andric     getStreamer().emitBytes(Data);
36625ffd83dbSDimitry Andric     if (ZeroTerminated)
36635ffd83dbSDimitry Andric       getStreamer().emitBytes(StringRef("\0", 1));
36645ffd83dbSDimitry Andric     return false;
36655ffd83dbSDimitry Andric   };
36665ffd83dbSDimitry Andric 
36675ffd83dbSDimitry Andric   if (parseMany(parseOp))
36685ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
36695ffd83dbSDimitry Andric   return false;
36705ffd83dbSDimitry Andric }
36715ffd83dbSDimitry Andric 
36725ffd83dbSDimitry Andric bool MasmParser::emitIntValue(const MCExpr *Value, unsigned Size) {
36735ffd83dbSDimitry Andric   // Special case constant expressions to match code generator.
36745ffd83dbSDimitry Andric   if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
36755ffd83dbSDimitry Andric     assert(Size <= 8 && "Invalid size");
36765ffd83dbSDimitry Andric     int64_t IntValue = MCE->getValue();
36775ffd83dbSDimitry Andric     if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
36785ffd83dbSDimitry Andric       return Error(MCE->getLoc(), "out of range literal value");
36795ffd83dbSDimitry Andric     getStreamer().emitIntValue(IntValue, Size);
36805ffd83dbSDimitry Andric   } else {
36815ffd83dbSDimitry Andric     const MCSymbolRefExpr *MSE = dyn_cast<MCSymbolRefExpr>(Value);
36825ffd83dbSDimitry Andric     if (MSE && MSE->getSymbol().getName() == "?") {
36835ffd83dbSDimitry Andric       // ? initializer; treat as 0.
36845ffd83dbSDimitry Andric       getStreamer().emitIntValue(0, Size);
36855ffd83dbSDimitry Andric     } else {
36865ffd83dbSDimitry Andric       getStreamer().emitValue(Value, Size, Value->getLoc());
36875ffd83dbSDimitry Andric     }
36885ffd83dbSDimitry Andric   }
36895ffd83dbSDimitry Andric   return false;
36905ffd83dbSDimitry Andric }
36915ffd83dbSDimitry Andric 
36925ffd83dbSDimitry Andric bool MasmParser::parseScalarInitializer(unsigned Size,
36935ffd83dbSDimitry Andric                                         SmallVectorImpl<const MCExpr *> &Values,
36945ffd83dbSDimitry Andric                                         unsigned StringPadLength) {
3695e8d8bef9SDimitry Andric   if (Size == 1 && getTok().is(AsmToken::String)) {
3696e8d8bef9SDimitry Andric     std::string Value;
3697e8d8bef9SDimitry Andric     if (parseEscapedString(Value))
3698e8d8bef9SDimitry Andric       return true;
36995ffd83dbSDimitry Andric     // Treat each character as an initializer.
3700e8d8bef9SDimitry Andric     for (const unsigned char CharVal : Value)
37015ffd83dbSDimitry Andric       Values.push_back(MCConstantExpr::create(CharVal, getContext()));
37025ffd83dbSDimitry Andric 
37035ffd83dbSDimitry Andric     // Pad the string with spaces to the specified length.
37045ffd83dbSDimitry Andric     for (size_t i = Value.size(); i < StringPadLength; ++i)
37055ffd83dbSDimitry Andric       Values.push_back(MCConstantExpr::create(' ', getContext()));
37065ffd83dbSDimitry Andric   } else {
37075ffd83dbSDimitry Andric     const MCExpr *Value;
3708e8d8bef9SDimitry Andric     if (parseExpression(Value))
37095ffd83dbSDimitry Andric       return true;
37105ffd83dbSDimitry Andric     if (getTok().is(AsmToken::Identifier) &&
3711fe6060f1SDimitry Andric         getTok().getString().equals_insensitive("dup")) {
37125ffd83dbSDimitry Andric       Lex(); // Eat 'dup'.
37135ffd83dbSDimitry Andric       const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
37145ffd83dbSDimitry Andric       if (!MCE)
37155ffd83dbSDimitry Andric         return Error(Value->getLoc(),
37165ffd83dbSDimitry Andric                      "cannot repeat value a non-constant number of times");
37175ffd83dbSDimitry Andric       const int64_t Repetitions = MCE->getValue();
37185ffd83dbSDimitry Andric       if (Repetitions < 0)
37195ffd83dbSDimitry Andric         return Error(Value->getLoc(),
37205ffd83dbSDimitry Andric                      "cannot repeat value a negative number of times");
37215ffd83dbSDimitry Andric 
37225ffd83dbSDimitry Andric       SmallVector<const MCExpr *, 1> DuplicatedValues;
37235ffd83dbSDimitry Andric       if (parseToken(AsmToken::LParen,
37245ffd83dbSDimitry Andric                      "parentheses required for 'dup' contents") ||
372504eeddc0SDimitry Andric           parseScalarInstList(Size, DuplicatedValues) || parseRParen())
37265ffd83dbSDimitry Andric         return true;
37275ffd83dbSDimitry Andric 
37285ffd83dbSDimitry Andric       for (int i = 0; i < Repetitions; ++i)
37295ffd83dbSDimitry Andric         Values.append(DuplicatedValues.begin(), DuplicatedValues.end());
37305ffd83dbSDimitry Andric     } else {
37315ffd83dbSDimitry Andric       Values.push_back(Value);
37325ffd83dbSDimitry Andric     }
37335ffd83dbSDimitry Andric   }
37345ffd83dbSDimitry Andric   return false;
37355ffd83dbSDimitry Andric }
37365ffd83dbSDimitry Andric 
37375ffd83dbSDimitry Andric bool MasmParser::parseScalarInstList(unsigned Size,
37385ffd83dbSDimitry Andric                                      SmallVectorImpl<const MCExpr *> &Values,
37395ffd83dbSDimitry Andric                                      const AsmToken::TokenKind EndToken) {
37405ffd83dbSDimitry Andric   while (getTok().isNot(EndToken) &&
37415ffd83dbSDimitry Andric          (EndToken != AsmToken::Greater ||
37425ffd83dbSDimitry Andric           getTok().isNot(AsmToken::GreaterGreater))) {
37435ffd83dbSDimitry Andric     parseScalarInitializer(Size, Values);
37445ffd83dbSDimitry Andric 
37455ffd83dbSDimitry Andric     // If we see a comma, continue, and allow line continuation.
37465ffd83dbSDimitry Andric     if (!parseOptionalToken(AsmToken::Comma))
37475ffd83dbSDimitry Andric       break;
37485ffd83dbSDimitry Andric     parseOptionalToken(AsmToken::EndOfStatement);
37495ffd83dbSDimitry Andric   }
37505ffd83dbSDimitry Andric   return false;
37515ffd83dbSDimitry Andric }
37525ffd83dbSDimitry Andric 
3753e8d8bef9SDimitry Andric bool MasmParser::emitIntegralValues(unsigned Size, unsigned *Count) {
37545ffd83dbSDimitry Andric   SmallVector<const MCExpr *, 1> Values;
37555ffd83dbSDimitry Andric   if (checkForValidSection() || parseScalarInstList(Size, Values))
37565ffd83dbSDimitry Andric     return true;
37575ffd83dbSDimitry Andric 
3758*bdd1243dSDimitry Andric   for (const auto *Value : Values) {
37595ffd83dbSDimitry Andric     emitIntValue(Value, Size);
37605ffd83dbSDimitry Andric   }
3761e8d8bef9SDimitry Andric   if (Count)
3762e8d8bef9SDimitry Andric     *Count = Values.size();
37635ffd83dbSDimitry Andric   return false;
37645ffd83dbSDimitry Andric }
37655ffd83dbSDimitry Andric 
37665ffd83dbSDimitry Andric // Add a field to the current structure.
37675ffd83dbSDimitry Andric bool MasmParser::addIntegralField(StringRef Name, unsigned Size) {
37685ffd83dbSDimitry Andric   StructInfo &Struct = StructInProgress.back();
3769e8d8bef9SDimitry Andric   FieldInfo &Field = Struct.addField(Name, FT_INTEGRAL, Size);
37705ffd83dbSDimitry Andric   IntFieldInfo &IntInfo = Field.Contents.IntInfo;
37715ffd83dbSDimitry Andric 
37725ffd83dbSDimitry Andric   Field.Type = Size;
37735ffd83dbSDimitry Andric 
37745ffd83dbSDimitry Andric   if (parseScalarInstList(Size, IntInfo.Values))
37755ffd83dbSDimitry Andric     return true;
37765ffd83dbSDimitry Andric 
37775ffd83dbSDimitry Andric   Field.SizeOf = Field.Type * IntInfo.Values.size();
37785ffd83dbSDimitry Andric   Field.LengthOf = IntInfo.Values.size();
3779fe6060f1SDimitry Andric   const unsigned FieldEnd = Field.Offset + Field.SizeOf;
3780fe6060f1SDimitry Andric   if (!Struct.IsUnion) {
3781fe6060f1SDimitry Andric     Struct.NextOffset = FieldEnd;
3782fe6060f1SDimitry Andric   }
3783fe6060f1SDimitry Andric   Struct.Size = std::max(Struct.Size, FieldEnd);
37845ffd83dbSDimitry Andric   return false;
37855ffd83dbSDimitry Andric }
37865ffd83dbSDimitry Andric 
37875ffd83dbSDimitry Andric /// parseDirectiveValue
37885ffd83dbSDimitry Andric ///  ::= (byte | word | ... ) [ expression (, expression)* ]
37895ffd83dbSDimitry Andric bool MasmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
37905ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
37915ffd83dbSDimitry Andric     // Initialize data value.
37925ffd83dbSDimitry Andric     if (emitIntegralValues(Size))
37935ffd83dbSDimitry Andric       return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
37945ffd83dbSDimitry Andric   } else if (addIntegralField("", Size)) {
37955ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
37965ffd83dbSDimitry Andric   }
37975ffd83dbSDimitry Andric 
37985ffd83dbSDimitry Andric   return false;
37995ffd83dbSDimitry Andric }
38005ffd83dbSDimitry Andric 
38015ffd83dbSDimitry Andric /// parseDirectiveNamedValue
38025ffd83dbSDimitry Andric ///  ::= name (byte | word | ... ) [ expression (, expression)* ]
3803e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
38045ffd83dbSDimitry Andric                                           StringRef Name, SMLoc NameLoc) {
38055ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
38065ffd83dbSDimitry Andric     // Initialize named data value.
38075ffd83dbSDimitry Andric     MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
38085ffd83dbSDimitry Andric     getStreamer().emitLabel(Sym);
3809e8d8bef9SDimitry Andric     unsigned Count;
3810e8d8bef9SDimitry Andric     if (emitIntegralValues(Size, &Count))
3811e8d8bef9SDimitry Andric       return addErrorSuffix(" in '" + Twine(TypeName) + "' directive");
3812e8d8bef9SDimitry Andric 
3813e8d8bef9SDimitry Andric     AsmTypeInfo Type;
3814e8d8bef9SDimitry Andric     Type.Name = TypeName;
3815e8d8bef9SDimitry Andric     Type.Size = Size * Count;
3816e8d8bef9SDimitry Andric     Type.ElementSize = Size;
3817e8d8bef9SDimitry Andric     Type.Length = Count;
3818e8d8bef9SDimitry Andric     KnownType[Name.lower()] = Type;
38195ffd83dbSDimitry Andric   } else if (addIntegralField(Name, Size)) {
3820e8d8bef9SDimitry Andric     return addErrorSuffix(" in '" + Twine(TypeName) + "' directive");
38215ffd83dbSDimitry Andric   }
38225ffd83dbSDimitry Andric 
38235ffd83dbSDimitry Andric   return false;
38245ffd83dbSDimitry Andric }
38255ffd83dbSDimitry Andric 
38265ffd83dbSDimitry Andric static bool parseHexOcta(MasmParser &Asm, uint64_t &hi, uint64_t &lo) {
38275ffd83dbSDimitry Andric   if (Asm.getTok().isNot(AsmToken::Integer) &&
38285ffd83dbSDimitry Andric       Asm.getTok().isNot(AsmToken::BigNum))
38295ffd83dbSDimitry Andric     return Asm.TokError("unknown token in expression");
38305ffd83dbSDimitry Andric   SMLoc ExprLoc = Asm.getTok().getLoc();
38315ffd83dbSDimitry Andric   APInt IntValue = Asm.getTok().getAPIntVal();
38325ffd83dbSDimitry Andric   Asm.Lex();
38335ffd83dbSDimitry Andric   if (!IntValue.isIntN(128))
38345ffd83dbSDimitry Andric     return Asm.Error(ExprLoc, "out of range literal value");
38355ffd83dbSDimitry Andric   if (!IntValue.isIntN(64)) {
38365ffd83dbSDimitry Andric     hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();
38375ffd83dbSDimitry Andric     lo = IntValue.getLoBits(64).getZExtValue();
38385ffd83dbSDimitry Andric   } else {
38395ffd83dbSDimitry Andric     hi = 0;
38405ffd83dbSDimitry Andric     lo = IntValue.getZExtValue();
38415ffd83dbSDimitry Andric   }
38425ffd83dbSDimitry Andric   return false;
38435ffd83dbSDimitry Andric }
38445ffd83dbSDimitry Andric 
38455ffd83dbSDimitry Andric bool MasmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
38465ffd83dbSDimitry Andric   // We don't truly support arithmetic on floating point expressions, so we
38475ffd83dbSDimitry Andric   // have to manually parse unary prefixes.
38485ffd83dbSDimitry Andric   bool IsNeg = false;
3849e8d8bef9SDimitry Andric   SMLoc SignLoc;
38505ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Minus)) {
3851e8d8bef9SDimitry Andric     SignLoc = getLexer().getLoc();
38525ffd83dbSDimitry Andric     Lexer.Lex();
38535ffd83dbSDimitry Andric     IsNeg = true;
38545ffd83dbSDimitry Andric   } else if (getLexer().is(AsmToken::Plus)) {
3855e8d8bef9SDimitry Andric     SignLoc = getLexer().getLoc();
38565ffd83dbSDimitry Andric     Lexer.Lex();
38575ffd83dbSDimitry Andric   }
38585ffd83dbSDimitry Andric 
38595ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::Error))
38605ffd83dbSDimitry Andric     return TokError(Lexer.getErr());
38615ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
38625ffd83dbSDimitry Andric       Lexer.isNot(AsmToken::Identifier))
38635ffd83dbSDimitry Andric     return TokError("unexpected token in directive");
38645ffd83dbSDimitry Andric 
38655ffd83dbSDimitry Andric   // Convert to an APFloat.
38665ffd83dbSDimitry Andric   APFloat Value(Semantics);
38675ffd83dbSDimitry Andric   StringRef IDVal = getTok().getString();
38685ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Identifier)) {
3869fe6060f1SDimitry Andric     if (IDVal.equals_insensitive("infinity") || IDVal.equals_insensitive("inf"))
38705ffd83dbSDimitry Andric       Value = APFloat::getInf(Semantics);
3871fe6060f1SDimitry Andric     else if (IDVal.equals_insensitive("nan"))
38725ffd83dbSDimitry Andric       Value = APFloat::getNaN(Semantics, false, ~0);
3873fe6060f1SDimitry Andric     else if (IDVal.equals_insensitive("?"))
38745ffd83dbSDimitry Andric       Value = APFloat::getZero(Semantics);
38755ffd83dbSDimitry Andric     else
38765ffd83dbSDimitry Andric       return TokError("invalid floating point literal");
3877e8d8bef9SDimitry Andric   } else if (IDVal.consume_back("r") || IDVal.consume_back("R")) {
3878e8d8bef9SDimitry Andric     // MASM hexadecimal floating-point literal; no APFloat conversion needed.
3879e8d8bef9SDimitry Andric     // To match ML64.exe, ignore the initial sign.
3880e8d8bef9SDimitry Andric     unsigned SizeInBits = Value.getSizeInBits(Semantics);
3881e8d8bef9SDimitry Andric     if (SizeInBits != (IDVal.size() << 2))
3882e8d8bef9SDimitry Andric       return TokError("invalid floating point literal");
3883e8d8bef9SDimitry Andric 
3884e8d8bef9SDimitry Andric     // Consume the numeric token.
3885e8d8bef9SDimitry Andric     Lex();
3886e8d8bef9SDimitry Andric 
3887e8d8bef9SDimitry Andric     Res = APInt(SizeInBits, IDVal, 16);
3888e8d8bef9SDimitry Andric     if (SignLoc.isValid())
3889e8d8bef9SDimitry Andric       return Warning(SignLoc, "MASM-style hex floats ignore explicit sign");
3890e8d8bef9SDimitry Andric     return false;
38915ffd83dbSDimitry Andric   } else if (errorToBool(
38925ffd83dbSDimitry Andric                  Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
38935ffd83dbSDimitry Andric                      .takeError())) {
38945ffd83dbSDimitry Andric     return TokError("invalid floating point literal");
38955ffd83dbSDimitry Andric   }
38965ffd83dbSDimitry Andric   if (IsNeg)
38975ffd83dbSDimitry Andric     Value.changeSign();
38985ffd83dbSDimitry Andric 
38995ffd83dbSDimitry Andric   // Consume the numeric token.
39005ffd83dbSDimitry Andric   Lex();
39015ffd83dbSDimitry Andric 
39025ffd83dbSDimitry Andric   Res = Value.bitcastToAPInt();
39035ffd83dbSDimitry Andric 
39045ffd83dbSDimitry Andric   return false;
39055ffd83dbSDimitry Andric }
39065ffd83dbSDimitry Andric 
39075ffd83dbSDimitry Andric bool MasmParser::parseRealInstList(const fltSemantics &Semantics,
39085ffd83dbSDimitry Andric                                    SmallVectorImpl<APInt> &ValuesAsInt,
39095ffd83dbSDimitry Andric                                    const AsmToken::TokenKind EndToken) {
39105ffd83dbSDimitry Andric   while (getTok().isNot(EndToken) ||
39115ffd83dbSDimitry Andric          (EndToken == AsmToken::Greater &&
39125ffd83dbSDimitry Andric           getTok().isNot(AsmToken::GreaterGreater))) {
3913fe6060f1SDimitry Andric     const AsmToken NextTok = peekTok();
39145ffd83dbSDimitry Andric     if (NextTok.is(AsmToken::Identifier) &&
3915fe6060f1SDimitry Andric         NextTok.getString().equals_insensitive("dup")) {
39165ffd83dbSDimitry Andric       const MCExpr *Value;
39175ffd83dbSDimitry Andric       if (parseExpression(Value) || parseToken(AsmToken::Identifier))
39185ffd83dbSDimitry Andric         return true;
39195ffd83dbSDimitry Andric       const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
39205ffd83dbSDimitry Andric       if (!MCE)
39215ffd83dbSDimitry Andric         return Error(Value->getLoc(),
39225ffd83dbSDimitry Andric                      "cannot repeat value a non-constant number of times");
39235ffd83dbSDimitry Andric       const int64_t Repetitions = MCE->getValue();
39245ffd83dbSDimitry Andric       if (Repetitions < 0)
39255ffd83dbSDimitry Andric         return Error(Value->getLoc(),
39265ffd83dbSDimitry Andric                      "cannot repeat value a negative number of times");
39275ffd83dbSDimitry Andric 
39285ffd83dbSDimitry Andric       SmallVector<APInt, 1> DuplicatedValues;
39295ffd83dbSDimitry Andric       if (parseToken(AsmToken::LParen,
39305ffd83dbSDimitry Andric                      "parentheses required for 'dup' contents") ||
393104eeddc0SDimitry Andric           parseRealInstList(Semantics, DuplicatedValues) || parseRParen())
39325ffd83dbSDimitry Andric         return true;
39335ffd83dbSDimitry Andric 
39345ffd83dbSDimitry Andric       for (int i = 0; i < Repetitions; ++i)
39355ffd83dbSDimitry Andric         ValuesAsInt.append(DuplicatedValues.begin(), DuplicatedValues.end());
39365ffd83dbSDimitry Andric     } else {
39375ffd83dbSDimitry Andric       APInt AsInt;
39385ffd83dbSDimitry Andric       if (parseRealValue(Semantics, AsInt))
39395ffd83dbSDimitry Andric         return true;
39405ffd83dbSDimitry Andric       ValuesAsInt.push_back(AsInt);
39415ffd83dbSDimitry Andric     }
39425ffd83dbSDimitry Andric 
39435ffd83dbSDimitry Andric     // Continue if we see a comma. (Also, allow line continuation.)
39445ffd83dbSDimitry Andric     if (!parseOptionalToken(AsmToken::Comma))
39455ffd83dbSDimitry Andric       break;
39465ffd83dbSDimitry Andric     parseOptionalToken(AsmToken::EndOfStatement);
39475ffd83dbSDimitry Andric   }
39485ffd83dbSDimitry Andric 
39495ffd83dbSDimitry Andric   return false;
39505ffd83dbSDimitry Andric }
39515ffd83dbSDimitry Andric 
39525ffd83dbSDimitry Andric // Initialize real data values.
3953e8d8bef9SDimitry Andric bool MasmParser::emitRealValues(const fltSemantics &Semantics,
3954e8d8bef9SDimitry Andric                                 unsigned *Count) {
3955e8d8bef9SDimitry Andric   if (checkForValidSection())
3956e8d8bef9SDimitry Andric     return true;
3957e8d8bef9SDimitry Andric 
39585ffd83dbSDimitry Andric   SmallVector<APInt, 1> ValuesAsInt;
39595ffd83dbSDimitry Andric   if (parseRealInstList(Semantics, ValuesAsInt))
39605ffd83dbSDimitry Andric     return true;
39615ffd83dbSDimitry Andric 
39625ffd83dbSDimitry Andric   for (const APInt &AsInt : ValuesAsInt) {
3963e8d8bef9SDimitry Andric     getStreamer().emitIntValue(AsInt);
39645ffd83dbSDimitry Andric   }
3965e8d8bef9SDimitry Andric   if (Count)
3966e8d8bef9SDimitry Andric     *Count = ValuesAsInt.size();
39675ffd83dbSDimitry Andric   return false;
39685ffd83dbSDimitry Andric }
39695ffd83dbSDimitry Andric 
39705ffd83dbSDimitry Andric // Add a real field to the current struct.
3971e8d8bef9SDimitry Andric bool MasmParser::addRealField(StringRef Name, const fltSemantics &Semantics,
3972e8d8bef9SDimitry Andric                               size_t Size) {
39735ffd83dbSDimitry Andric   StructInfo &Struct = StructInProgress.back();
3974e8d8bef9SDimitry Andric   FieldInfo &Field = Struct.addField(Name, FT_REAL, Size);
39755ffd83dbSDimitry Andric   RealFieldInfo &RealInfo = Field.Contents.RealInfo;
39765ffd83dbSDimitry Andric 
39775ffd83dbSDimitry Andric   Field.SizeOf = 0;
39785ffd83dbSDimitry Andric 
3979e8d8bef9SDimitry Andric   if (parseRealInstList(Semantics, RealInfo.AsIntValues))
39805ffd83dbSDimitry Andric     return true;
39815ffd83dbSDimitry Andric 
39825ffd83dbSDimitry Andric   Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
39835ffd83dbSDimitry Andric   Field.LengthOf = RealInfo.AsIntValues.size();
39845ffd83dbSDimitry Andric   Field.SizeOf = Field.Type * Field.LengthOf;
3985fe6060f1SDimitry Andric 
3986fe6060f1SDimitry Andric   const unsigned FieldEnd = Field.Offset + Field.SizeOf;
3987fe6060f1SDimitry Andric   if (!Struct.IsUnion) {
3988fe6060f1SDimitry Andric     Struct.NextOffset = FieldEnd;
3989fe6060f1SDimitry Andric   }
3990fe6060f1SDimitry Andric   Struct.Size = std::max(Struct.Size, FieldEnd);
39915ffd83dbSDimitry Andric   return false;
39925ffd83dbSDimitry Andric }
39935ffd83dbSDimitry Andric 
39945ffd83dbSDimitry Andric /// parseDirectiveRealValue
3995e8d8bef9SDimitry Andric ///  ::= (real4 | real8 | real10) [ expression (, expression)* ]
39965ffd83dbSDimitry Andric bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
3997e8d8bef9SDimitry Andric                                          const fltSemantics &Semantics,
3998e8d8bef9SDimitry Andric                                          size_t Size) {
39995ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
40005ffd83dbSDimitry Andric     // Initialize data value.
40015ffd83dbSDimitry Andric     if (emitRealValues(Semantics))
40025ffd83dbSDimitry Andric       return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
4003e8d8bef9SDimitry Andric   } else if (addRealField("", Semantics, Size)) {
40045ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
40055ffd83dbSDimitry Andric   }
40065ffd83dbSDimitry Andric   return false;
40075ffd83dbSDimitry Andric }
40085ffd83dbSDimitry Andric 
40095ffd83dbSDimitry Andric /// parseDirectiveNamedRealValue
4010e8d8bef9SDimitry Andric ///  ::= name (real4 | real8 | real10) [ expression (, expression)* ]
4011e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
40125ffd83dbSDimitry Andric                                               const fltSemantics &Semantics,
4013e8d8bef9SDimitry Andric                                               unsigned Size, StringRef Name,
4014e8d8bef9SDimitry Andric                                               SMLoc NameLoc) {
40155ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
40165ffd83dbSDimitry Andric     // Initialize named data value.
40175ffd83dbSDimitry Andric     MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
40185ffd83dbSDimitry Andric     getStreamer().emitLabel(Sym);
4019e8d8bef9SDimitry Andric     unsigned Count;
4020e8d8bef9SDimitry Andric     if (emitRealValues(Semantics, &Count))
4021e8d8bef9SDimitry Andric       return addErrorSuffix(" in '" + TypeName + "' directive");
4022e8d8bef9SDimitry Andric 
4023e8d8bef9SDimitry Andric     AsmTypeInfo Type;
4024e8d8bef9SDimitry Andric     Type.Name = TypeName;
4025e8d8bef9SDimitry Andric     Type.Size = Size * Count;
4026e8d8bef9SDimitry Andric     Type.ElementSize = Size;
4027e8d8bef9SDimitry Andric     Type.Length = Count;
4028e8d8bef9SDimitry Andric     KnownType[Name.lower()] = Type;
4029e8d8bef9SDimitry Andric   } else if (addRealField(Name, Semantics, Size)) {
4030e8d8bef9SDimitry Andric     return addErrorSuffix(" in '" + TypeName + "' directive");
40315ffd83dbSDimitry Andric   }
40325ffd83dbSDimitry Andric   return false;
40335ffd83dbSDimitry Andric }
40345ffd83dbSDimitry Andric 
40355ffd83dbSDimitry Andric bool MasmParser::parseOptionalAngleBracketOpen() {
40365ffd83dbSDimitry Andric   const AsmToken Tok = getTok();
40375ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::LessLess)) {
40385ffd83dbSDimitry Andric     AngleBracketDepth++;
40395ffd83dbSDimitry Andric     Lexer.UnLex(AsmToken(AsmToken::Less, Tok.getString().substr(1)));
40405ffd83dbSDimitry Andric     return true;
40415ffd83dbSDimitry Andric   } else if (parseOptionalToken(AsmToken::LessGreater)) {
40425ffd83dbSDimitry Andric     AngleBracketDepth++;
40435ffd83dbSDimitry Andric     Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1)));
40445ffd83dbSDimitry Andric     return true;
40455ffd83dbSDimitry Andric   } else if (parseOptionalToken(AsmToken::Less)) {
40465ffd83dbSDimitry Andric     AngleBracketDepth++;
40475ffd83dbSDimitry Andric     return true;
40485ffd83dbSDimitry Andric   }
40495ffd83dbSDimitry Andric 
40505ffd83dbSDimitry Andric   return false;
40515ffd83dbSDimitry Andric }
40525ffd83dbSDimitry Andric 
40535ffd83dbSDimitry Andric bool MasmParser::parseAngleBracketClose(const Twine &Msg) {
40545ffd83dbSDimitry Andric   const AsmToken Tok = getTok();
40555ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::GreaterGreater)) {
40565ffd83dbSDimitry Andric     Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1)));
40575ffd83dbSDimitry Andric   } else if (parseToken(AsmToken::Greater, Msg)) {
40585ffd83dbSDimitry Andric     return true;
40595ffd83dbSDimitry Andric   }
40605ffd83dbSDimitry Andric   AngleBracketDepth--;
40615ffd83dbSDimitry Andric   return false;
40625ffd83dbSDimitry Andric }
40635ffd83dbSDimitry Andric 
40645ffd83dbSDimitry Andric bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
40655ffd83dbSDimitry Andric                                        const IntFieldInfo &Contents,
40665ffd83dbSDimitry Andric                                        FieldInitializer &Initializer) {
40675ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
40685ffd83dbSDimitry Andric 
40695ffd83dbSDimitry Andric   SmallVector<const MCExpr *, 1> Values;
40705ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::LCurly)) {
40715ffd83dbSDimitry Andric     if (Field.LengthOf == 1 && Field.Type > 1)
40725ffd83dbSDimitry Andric       return Error(Loc, "Cannot initialize scalar field with array value");
40735ffd83dbSDimitry Andric     if (parseScalarInstList(Field.Type, Values, AsmToken::RCurly) ||
40745ffd83dbSDimitry Andric         parseToken(AsmToken::RCurly))
40755ffd83dbSDimitry Andric       return true;
40765ffd83dbSDimitry Andric   } else if (parseOptionalAngleBracketOpen()) {
40775ffd83dbSDimitry Andric     if (Field.LengthOf == 1 && Field.Type > 1)
40785ffd83dbSDimitry Andric       return Error(Loc, "Cannot initialize scalar field with array value");
40795ffd83dbSDimitry Andric     if (parseScalarInstList(Field.Type, Values, AsmToken::Greater) ||
40805ffd83dbSDimitry Andric         parseAngleBracketClose())
40815ffd83dbSDimitry Andric       return true;
40825ffd83dbSDimitry Andric   } else if (Field.LengthOf > 1 && Field.Type > 1) {
40835ffd83dbSDimitry Andric     return Error(Loc, "Cannot initialize array field with scalar value");
40845ffd83dbSDimitry Andric   } else if (parseScalarInitializer(Field.Type, Values,
40855ffd83dbSDimitry Andric                                     /*StringPadLength=*/Field.LengthOf)) {
40865ffd83dbSDimitry Andric     return true;
40875ffd83dbSDimitry Andric   }
40885ffd83dbSDimitry Andric 
40895ffd83dbSDimitry Andric   if (Values.size() > Field.LengthOf) {
40905ffd83dbSDimitry Andric     return Error(Loc, "Initializer too long for field; expected at most " +
40915ffd83dbSDimitry Andric                           std::to_string(Field.LengthOf) + " elements, got " +
40925ffd83dbSDimitry Andric                           std::to_string(Values.size()));
40935ffd83dbSDimitry Andric   }
40945ffd83dbSDimitry Andric   // Default-initialize all remaining values.
40955ffd83dbSDimitry Andric   Values.append(Contents.Values.begin() + Values.size(), Contents.Values.end());
40965ffd83dbSDimitry Andric 
40975ffd83dbSDimitry Andric   Initializer = FieldInitializer(std::move(Values));
40985ffd83dbSDimitry Andric   return false;
40995ffd83dbSDimitry Andric }
41005ffd83dbSDimitry Andric 
41015ffd83dbSDimitry Andric bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
41025ffd83dbSDimitry Andric                                        const RealFieldInfo &Contents,
41035ffd83dbSDimitry Andric                                        FieldInitializer &Initializer) {
4104e8d8bef9SDimitry Andric   const fltSemantics *Semantics;
4105e8d8bef9SDimitry Andric   switch (Field.Type) {
4106e8d8bef9SDimitry Andric   case 4:
4107e8d8bef9SDimitry Andric     Semantics = &APFloat::IEEEsingle();
4108e8d8bef9SDimitry Andric     break;
4109e8d8bef9SDimitry Andric   case 8:
4110e8d8bef9SDimitry Andric     Semantics = &APFloat::IEEEdouble();
4111e8d8bef9SDimitry Andric     break;
4112e8d8bef9SDimitry Andric   case 10:
4113e8d8bef9SDimitry Andric     Semantics = &APFloat::x87DoubleExtended();
4114e8d8bef9SDimitry Andric     break;
4115e8d8bef9SDimitry Andric   default:
4116e8d8bef9SDimitry Andric     llvm_unreachable("unknown real field type");
4117e8d8bef9SDimitry Andric   }
41185ffd83dbSDimitry Andric 
41195ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
41205ffd83dbSDimitry Andric 
41215ffd83dbSDimitry Andric   SmallVector<APInt, 1> AsIntValues;
41225ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::LCurly)) {
41235ffd83dbSDimitry Andric     if (Field.LengthOf == 1)
41245ffd83dbSDimitry Andric       return Error(Loc, "Cannot initialize scalar field with array value");
4125e8d8bef9SDimitry Andric     if (parseRealInstList(*Semantics, AsIntValues, AsmToken::RCurly) ||
41265ffd83dbSDimitry Andric         parseToken(AsmToken::RCurly))
41275ffd83dbSDimitry Andric       return true;
41285ffd83dbSDimitry Andric   } else if (parseOptionalAngleBracketOpen()) {
41295ffd83dbSDimitry Andric     if (Field.LengthOf == 1)
41305ffd83dbSDimitry Andric       return Error(Loc, "Cannot initialize scalar field with array value");
4131e8d8bef9SDimitry Andric     if (parseRealInstList(*Semantics, AsIntValues, AsmToken::Greater) ||
41325ffd83dbSDimitry Andric         parseAngleBracketClose())
41335ffd83dbSDimitry Andric       return true;
41345ffd83dbSDimitry Andric   } else if (Field.LengthOf > 1) {
41355ffd83dbSDimitry Andric     return Error(Loc, "Cannot initialize array field with scalar value");
41365ffd83dbSDimitry Andric   } else {
41375ffd83dbSDimitry Andric     AsIntValues.emplace_back();
4138e8d8bef9SDimitry Andric     if (parseRealValue(*Semantics, AsIntValues.back()))
41395ffd83dbSDimitry Andric       return true;
41405ffd83dbSDimitry Andric   }
41415ffd83dbSDimitry Andric 
41425ffd83dbSDimitry Andric   if (AsIntValues.size() > Field.LengthOf) {
41435ffd83dbSDimitry Andric     return Error(Loc, "Initializer too long for field; expected at most " +
41445ffd83dbSDimitry Andric                           std::to_string(Field.LengthOf) + " elements, got " +
41455ffd83dbSDimitry Andric                           std::to_string(AsIntValues.size()));
41465ffd83dbSDimitry Andric   }
41475ffd83dbSDimitry Andric   // Default-initialize all remaining values.
41485ffd83dbSDimitry Andric   AsIntValues.append(Contents.AsIntValues.begin() + AsIntValues.size(),
41495ffd83dbSDimitry Andric                      Contents.AsIntValues.end());
41505ffd83dbSDimitry Andric 
41515ffd83dbSDimitry Andric   Initializer = FieldInitializer(std::move(AsIntValues));
41525ffd83dbSDimitry Andric   return false;
41535ffd83dbSDimitry Andric }
41545ffd83dbSDimitry Andric 
41555ffd83dbSDimitry Andric bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
41565ffd83dbSDimitry Andric                                        const StructFieldInfo &Contents,
41575ffd83dbSDimitry Andric                                        FieldInitializer &Initializer) {
41585ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
41595ffd83dbSDimitry Andric 
41605ffd83dbSDimitry Andric   std::vector<StructInitializer> Initializers;
41615ffd83dbSDimitry Andric   if (Field.LengthOf > 1) {
41625ffd83dbSDimitry Andric     if (parseOptionalToken(AsmToken::LCurly)) {
41635ffd83dbSDimitry Andric       if (parseStructInstList(Contents.Structure, Initializers,
41645ffd83dbSDimitry Andric                               AsmToken::RCurly) ||
41655ffd83dbSDimitry Andric           parseToken(AsmToken::RCurly))
41665ffd83dbSDimitry Andric         return true;
41675ffd83dbSDimitry Andric     } else if (parseOptionalAngleBracketOpen()) {
41685ffd83dbSDimitry Andric       if (parseStructInstList(Contents.Structure, Initializers,
41695ffd83dbSDimitry Andric                               AsmToken::Greater) ||
41705ffd83dbSDimitry Andric           parseAngleBracketClose())
41715ffd83dbSDimitry Andric         return true;
41725ffd83dbSDimitry Andric     } else {
41735ffd83dbSDimitry Andric       return Error(Loc, "Cannot initialize array field with scalar value");
41745ffd83dbSDimitry Andric     }
41755ffd83dbSDimitry Andric   } else {
41765ffd83dbSDimitry Andric     Initializers.emplace_back();
41775ffd83dbSDimitry Andric     if (parseStructInitializer(Contents.Structure, Initializers.back()))
41785ffd83dbSDimitry Andric       return true;
41795ffd83dbSDimitry Andric   }
41805ffd83dbSDimitry Andric 
41815ffd83dbSDimitry Andric   if (Initializers.size() > Field.LengthOf) {
41825ffd83dbSDimitry Andric     return Error(Loc, "Initializer too long for field; expected at most " +
41835ffd83dbSDimitry Andric                           std::to_string(Field.LengthOf) + " elements, got " +
41845ffd83dbSDimitry Andric                           std::to_string(Initializers.size()));
41855ffd83dbSDimitry Andric   }
41865ffd83dbSDimitry Andric   // Default-initialize all remaining values.
41875ffd83dbSDimitry Andric   Initializers.insert(Initializers.end(),
41885ffd83dbSDimitry Andric                       Contents.Initializers.begin() + Initializers.size(),
41895ffd83dbSDimitry Andric                       Contents.Initializers.end());
41905ffd83dbSDimitry Andric 
41915ffd83dbSDimitry Andric   Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
41925ffd83dbSDimitry Andric   return false;
41935ffd83dbSDimitry Andric }
41945ffd83dbSDimitry Andric 
41955ffd83dbSDimitry Andric bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
41965ffd83dbSDimitry Andric                                        FieldInitializer &Initializer) {
41975ffd83dbSDimitry Andric   switch (Field.Contents.FT) {
41985ffd83dbSDimitry Andric   case FT_INTEGRAL:
41995ffd83dbSDimitry Andric     return parseFieldInitializer(Field, Field.Contents.IntInfo, Initializer);
42005ffd83dbSDimitry Andric   case FT_REAL:
42015ffd83dbSDimitry Andric     return parseFieldInitializer(Field, Field.Contents.RealInfo, Initializer);
42025ffd83dbSDimitry Andric   case FT_STRUCT:
42035ffd83dbSDimitry Andric     return parseFieldInitializer(Field, Field.Contents.StructInfo, Initializer);
42045ffd83dbSDimitry Andric   }
42055ffd83dbSDimitry Andric   llvm_unreachable("Unhandled FieldType enum");
42065ffd83dbSDimitry Andric }
42075ffd83dbSDimitry Andric 
42085ffd83dbSDimitry Andric bool MasmParser::parseStructInitializer(const StructInfo &Structure,
42095ffd83dbSDimitry Andric                                         StructInitializer &Initializer) {
42105ffd83dbSDimitry Andric   const AsmToken FirstToken = getTok();
42115ffd83dbSDimitry Andric 
4212*bdd1243dSDimitry Andric   std::optional<AsmToken::TokenKind> EndToken;
42135ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::LCurly)) {
42145ffd83dbSDimitry Andric     EndToken = AsmToken::RCurly;
42155ffd83dbSDimitry Andric   } else if (parseOptionalAngleBracketOpen()) {
42165ffd83dbSDimitry Andric     EndToken = AsmToken::Greater;
42175ffd83dbSDimitry Andric     AngleBracketDepth++;
42185ffd83dbSDimitry Andric   } else if (FirstToken.is(AsmToken::Identifier) &&
42195ffd83dbSDimitry Andric              FirstToken.getString() == "?") {
42205ffd83dbSDimitry Andric     // ? initializer; leave EndToken uninitialized to treat as empty.
42215ffd83dbSDimitry Andric     if (parseToken(AsmToken::Identifier))
42225ffd83dbSDimitry Andric       return true;
42235ffd83dbSDimitry Andric   } else {
42245ffd83dbSDimitry Andric     return Error(FirstToken.getLoc(), "Expected struct initializer");
42255ffd83dbSDimitry Andric   }
42265ffd83dbSDimitry Andric 
42275ffd83dbSDimitry Andric   auto &FieldInitializers = Initializer.FieldInitializers;
42285ffd83dbSDimitry Andric   size_t FieldIndex = 0;
422981ad6265SDimitry Andric   if (EndToken) {
42305ffd83dbSDimitry Andric     // Initialize all fields with given initializers.
4231*bdd1243dSDimitry Andric     while (getTok().isNot(*EndToken) && FieldIndex < Structure.Fields.size()) {
42325ffd83dbSDimitry Andric       const FieldInfo &Field = Structure.Fields[FieldIndex++];
42335ffd83dbSDimitry Andric       if (parseOptionalToken(AsmToken::Comma)) {
42345ffd83dbSDimitry Andric         // Empty initializer; use the default and continue. (Also, allow line
42355ffd83dbSDimitry Andric         // continuation.)
42365ffd83dbSDimitry Andric         FieldInitializers.push_back(Field.Contents);
42375ffd83dbSDimitry Andric         parseOptionalToken(AsmToken::EndOfStatement);
42385ffd83dbSDimitry Andric         continue;
42395ffd83dbSDimitry Andric       }
42405ffd83dbSDimitry Andric       FieldInitializers.emplace_back(Field.Contents.FT);
42415ffd83dbSDimitry Andric       if (parseFieldInitializer(Field, FieldInitializers.back()))
42425ffd83dbSDimitry Andric         return true;
42435ffd83dbSDimitry Andric 
42445ffd83dbSDimitry Andric       // Continue if we see a comma. (Also, allow line continuation.)
42455ffd83dbSDimitry Andric       SMLoc CommaLoc = getTok().getLoc();
42465ffd83dbSDimitry Andric       if (!parseOptionalToken(AsmToken::Comma))
42475ffd83dbSDimitry Andric         break;
42485ffd83dbSDimitry Andric       if (FieldIndex == Structure.Fields.size())
42495ffd83dbSDimitry Andric         return Error(CommaLoc, "'" + Structure.Name +
42505ffd83dbSDimitry Andric                                    "' initializer initializes too many fields");
42515ffd83dbSDimitry Andric       parseOptionalToken(AsmToken::EndOfStatement);
42525ffd83dbSDimitry Andric     }
42535ffd83dbSDimitry Andric   }
42545ffd83dbSDimitry Andric   // Default-initialize all remaining fields.
4255fcaf7f86SDimitry Andric   for (const FieldInfo &Field : llvm::drop_begin(Structure.Fields, FieldIndex))
42565ffd83dbSDimitry Andric     FieldInitializers.push_back(Field.Contents);
42575ffd83dbSDimitry Andric 
425881ad6265SDimitry Andric   if (EndToken) {
4259*bdd1243dSDimitry Andric     if (*EndToken == AsmToken::Greater)
42605ffd83dbSDimitry Andric       return parseAngleBracketClose();
42615ffd83dbSDimitry Andric 
4262*bdd1243dSDimitry Andric     return parseToken(*EndToken);
42635ffd83dbSDimitry Andric   }
42645ffd83dbSDimitry Andric 
42655ffd83dbSDimitry Andric   return false;
42665ffd83dbSDimitry Andric }
42675ffd83dbSDimitry Andric 
42685ffd83dbSDimitry Andric bool MasmParser::parseStructInstList(
42695ffd83dbSDimitry Andric     const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
42705ffd83dbSDimitry Andric     const AsmToken::TokenKind EndToken) {
42715ffd83dbSDimitry Andric   while (getTok().isNot(EndToken) ||
42725ffd83dbSDimitry Andric          (EndToken == AsmToken::Greater &&
42735ffd83dbSDimitry Andric           getTok().isNot(AsmToken::GreaterGreater))) {
4274fe6060f1SDimitry Andric     const AsmToken NextTok = peekTok();
42755ffd83dbSDimitry Andric     if (NextTok.is(AsmToken::Identifier) &&
4276fe6060f1SDimitry Andric         NextTok.getString().equals_insensitive("dup")) {
42775ffd83dbSDimitry Andric       const MCExpr *Value;
42785ffd83dbSDimitry Andric       if (parseExpression(Value) || parseToken(AsmToken::Identifier))
42795ffd83dbSDimitry Andric         return true;
42805ffd83dbSDimitry Andric       const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
42815ffd83dbSDimitry Andric       if (!MCE)
42825ffd83dbSDimitry Andric         return Error(Value->getLoc(),
42835ffd83dbSDimitry Andric                      "cannot repeat value a non-constant number of times");
42845ffd83dbSDimitry Andric       const int64_t Repetitions = MCE->getValue();
42855ffd83dbSDimitry Andric       if (Repetitions < 0)
42865ffd83dbSDimitry Andric         return Error(Value->getLoc(),
42875ffd83dbSDimitry Andric                      "cannot repeat value a negative number of times");
42885ffd83dbSDimitry Andric 
42895ffd83dbSDimitry Andric       std::vector<StructInitializer> DuplicatedValues;
42905ffd83dbSDimitry Andric       if (parseToken(AsmToken::LParen,
42915ffd83dbSDimitry Andric                      "parentheses required for 'dup' contents") ||
429204eeddc0SDimitry Andric           parseStructInstList(Structure, DuplicatedValues) || parseRParen())
42935ffd83dbSDimitry Andric         return true;
42945ffd83dbSDimitry Andric 
42955ffd83dbSDimitry Andric       for (int i = 0; i < Repetitions; ++i)
4296e8d8bef9SDimitry Andric         llvm::append_range(Initializers, DuplicatedValues);
42975ffd83dbSDimitry Andric     } else {
42985ffd83dbSDimitry Andric       Initializers.emplace_back();
42995ffd83dbSDimitry Andric       if (parseStructInitializer(Structure, Initializers.back()))
43005ffd83dbSDimitry Andric         return true;
43015ffd83dbSDimitry Andric     }
43025ffd83dbSDimitry Andric 
43035ffd83dbSDimitry Andric     // Continue if we see a comma. (Also, allow line continuation.)
43045ffd83dbSDimitry Andric     if (!parseOptionalToken(AsmToken::Comma))
43055ffd83dbSDimitry Andric       break;
43065ffd83dbSDimitry Andric     parseOptionalToken(AsmToken::EndOfStatement);
43075ffd83dbSDimitry Andric   }
43085ffd83dbSDimitry Andric 
43095ffd83dbSDimitry Andric   return false;
43105ffd83dbSDimitry Andric }
43115ffd83dbSDimitry Andric 
43125ffd83dbSDimitry Andric bool MasmParser::emitFieldValue(const FieldInfo &Field,
43135ffd83dbSDimitry Andric                                 const IntFieldInfo &Contents) {
43145ffd83dbSDimitry Andric   // Default-initialize all values.
43155ffd83dbSDimitry Andric   for (const MCExpr *Value : Contents.Values) {
43165ffd83dbSDimitry Andric     if (emitIntValue(Value, Field.Type))
43175ffd83dbSDimitry Andric       return true;
43185ffd83dbSDimitry Andric   }
43195ffd83dbSDimitry Andric   return false;
43205ffd83dbSDimitry Andric }
43215ffd83dbSDimitry Andric 
43225ffd83dbSDimitry Andric bool MasmParser::emitFieldValue(const FieldInfo &Field,
43235ffd83dbSDimitry Andric                                 const RealFieldInfo &Contents) {
43245ffd83dbSDimitry Andric   for (const APInt &AsInt : Contents.AsIntValues) {
43255ffd83dbSDimitry Andric     getStreamer().emitIntValue(AsInt.getLimitedValue(),
43265ffd83dbSDimitry Andric                                AsInt.getBitWidth() / 8);
43275ffd83dbSDimitry Andric   }
43285ffd83dbSDimitry Andric   return false;
43295ffd83dbSDimitry Andric }
43305ffd83dbSDimitry Andric 
43315ffd83dbSDimitry Andric bool MasmParser::emitFieldValue(const FieldInfo &Field,
43325ffd83dbSDimitry Andric                                 const StructFieldInfo &Contents) {
43335ffd83dbSDimitry Andric   for (const auto &Initializer : Contents.Initializers) {
43345ffd83dbSDimitry Andric     size_t Index = 0, Offset = 0;
43355ffd83dbSDimitry Andric     for (const auto &SubField : Contents.Structure.Fields) {
43365ffd83dbSDimitry Andric       getStreamer().emitZeros(SubField.Offset - Offset);
43375ffd83dbSDimitry Andric       Offset = SubField.Offset + SubField.SizeOf;
43385ffd83dbSDimitry Andric       emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
43395ffd83dbSDimitry Andric     }
43405ffd83dbSDimitry Andric   }
43415ffd83dbSDimitry Andric   return false;
43425ffd83dbSDimitry Andric }
43435ffd83dbSDimitry Andric 
43445ffd83dbSDimitry Andric bool MasmParser::emitFieldValue(const FieldInfo &Field) {
43455ffd83dbSDimitry Andric   switch (Field.Contents.FT) {
43465ffd83dbSDimitry Andric   case FT_INTEGRAL:
43475ffd83dbSDimitry Andric     return emitFieldValue(Field, Field.Contents.IntInfo);
43485ffd83dbSDimitry Andric   case FT_REAL:
43495ffd83dbSDimitry Andric     return emitFieldValue(Field, Field.Contents.RealInfo);
43505ffd83dbSDimitry Andric   case FT_STRUCT:
43515ffd83dbSDimitry Andric     return emitFieldValue(Field, Field.Contents.StructInfo);
43525ffd83dbSDimitry Andric   }
43535ffd83dbSDimitry Andric   llvm_unreachable("Unhandled FieldType enum");
43545ffd83dbSDimitry Andric }
43555ffd83dbSDimitry Andric 
43565ffd83dbSDimitry Andric bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
43575ffd83dbSDimitry Andric                                       const IntFieldInfo &Contents,
43585ffd83dbSDimitry Andric                                       const IntFieldInfo &Initializer) {
43595ffd83dbSDimitry Andric   for (const auto &Value : Initializer.Values) {
43605ffd83dbSDimitry Andric     if (emitIntValue(Value, Field.Type))
43615ffd83dbSDimitry Andric       return true;
43625ffd83dbSDimitry Andric   }
43635ffd83dbSDimitry Andric   // Default-initialize all remaining values.
4364fcaf7f86SDimitry Andric   for (const auto &Value :
4365fcaf7f86SDimitry Andric            llvm::drop_begin(Contents.Values, Initializer.Values.size())) {
43665ffd83dbSDimitry Andric     if (emitIntValue(Value, Field.Type))
43675ffd83dbSDimitry Andric       return true;
43685ffd83dbSDimitry Andric   }
43695ffd83dbSDimitry Andric   return false;
43705ffd83dbSDimitry Andric }
43715ffd83dbSDimitry Andric 
43725ffd83dbSDimitry Andric bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
43735ffd83dbSDimitry Andric                                       const RealFieldInfo &Contents,
43745ffd83dbSDimitry Andric                                       const RealFieldInfo &Initializer) {
43755ffd83dbSDimitry Andric   for (const auto &AsInt : Initializer.AsIntValues) {
43765ffd83dbSDimitry Andric     getStreamer().emitIntValue(AsInt.getLimitedValue(),
43775ffd83dbSDimitry Andric                                AsInt.getBitWidth() / 8);
43785ffd83dbSDimitry Andric   }
43795ffd83dbSDimitry Andric   // Default-initialize all remaining values.
4380fcaf7f86SDimitry Andric   for (const auto &AsInt :
4381fcaf7f86SDimitry Andric        llvm::drop_begin(Contents.AsIntValues, Initializer.AsIntValues.size())) {
43825ffd83dbSDimitry Andric     getStreamer().emitIntValue(AsInt.getLimitedValue(),
43835ffd83dbSDimitry Andric                                AsInt.getBitWidth() / 8);
43845ffd83dbSDimitry Andric   }
43855ffd83dbSDimitry Andric   return false;
43865ffd83dbSDimitry Andric }
43875ffd83dbSDimitry Andric 
43885ffd83dbSDimitry Andric bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
43895ffd83dbSDimitry Andric                                       const StructFieldInfo &Contents,
43905ffd83dbSDimitry Andric                                       const StructFieldInfo &Initializer) {
43915ffd83dbSDimitry Andric   for (const auto &Init : Initializer.Initializers) {
4392fe6060f1SDimitry Andric     if (emitStructInitializer(Contents.Structure, Init))
4393fe6060f1SDimitry Andric       return true;
43945ffd83dbSDimitry Andric   }
43955ffd83dbSDimitry Andric   // Default-initialize all remaining values.
4396fcaf7f86SDimitry Andric   for (const auto &Init : llvm::drop_begin(Contents.Initializers,
4397fcaf7f86SDimitry Andric                                            Initializer.Initializers.size())) {
4398fe6060f1SDimitry Andric     if (emitStructInitializer(Contents.Structure, Init))
4399fe6060f1SDimitry Andric       return true;
44005ffd83dbSDimitry Andric   }
44015ffd83dbSDimitry Andric   return false;
44025ffd83dbSDimitry Andric }
44035ffd83dbSDimitry Andric 
44045ffd83dbSDimitry Andric bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
44055ffd83dbSDimitry Andric                                       const FieldInitializer &Initializer) {
44065ffd83dbSDimitry Andric   switch (Field.Contents.FT) {
44075ffd83dbSDimitry Andric   case FT_INTEGRAL:
44085ffd83dbSDimitry Andric     return emitFieldInitializer(Field, Field.Contents.IntInfo,
44095ffd83dbSDimitry Andric                                 Initializer.IntInfo);
44105ffd83dbSDimitry Andric   case FT_REAL:
44115ffd83dbSDimitry Andric     return emitFieldInitializer(Field, Field.Contents.RealInfo,
44125ffd83dbSDimitry Andric                                 Initializer.RealInfo);
44135ffd83dbSDimitry Andric   case FT_STRUCT:
44145ffd83dbSDimitry Andric     return emitFieldInitializer(Field, Field.Contents.StructInfo,
44155ffd83dbSDimitry Andric                                 Initializer.StructInfo);
44165ffd83dbSDimitry Andric   }
44175ffd83dbSDimitry Andric   llvm_unreachable("Unhandled FieldType enum");
44185ffd83dbSDimitry Andric }
44195ffd83dbSDimitry Andric 
44205ffd83dbSDimitry Andric bool MasmParser::emitStructInitializer(const StructInfo &Structure,
44215ffd83dbSDimitry Andric                                        const StructInitializer &Initializer) {
4422fe6060f1SDimitry Andric   if (!Structure.Initializable)
4423fe6060f1SDimitry Andric     return Error(getLexer().getLoc(),
4424fe6060f1SDimitry Andric                  "cannot initialize a value of type '" + Structure.Name +
4425fe6060f1SDimitry Andric                      "'; 'org' was used in the type's declaration");
44265ffd83dbSDimitry Andric   size_t Index = 0, Offset = 0;
44275ffd83dbSDimitry Andric   for (const auto &Init : Initializer.FieldInitializers) {
44285ffd83dbSDimitry Andric     const auto &Field = Structure.Fields[Index++];
44295ffd83dbSDimitry Andric     getStreamer().emitZeros(Field.Offset - Offset);
44305ffd83dbSDimitry Andric     Offset = Field.Offset + Field.SizeOf;
44315ffd83dbSDimitry Andric     if (emitFieldInitializer(Field, Init))
44325ffd83dbSDimitry Andric       return true;
44335ffd83dbSDimitry Andric   }
44345ffd83dbSDimitry Andric   // Default-initialize all remaining fields.
4435fcaf7f86SDimitry Andric   for (const auto &Field : llvm::drop_begin(
4436fcaf7f86SDimitry Andric            Structure.Fields, Initializer.FieldInitializers.size())) {
44375ffd83dbSDimitry Andric     getStreamer().emitZeros(Field.Offset - Offset);
44385ffd83dbSDimitry Andric     Offset = Field.Offset + Field.SizeOf;
44395ffd83dbSDimitry Andric     if (emitFieldValue(Field))
44405ffd83dbSDimitry Andric       return true;
44415ffd83dbSDimitry Andric   }
44425ffd83dbSDimitry Andric   // Add final padding.
44435ffd83dbSDimitry Andric   if (Offset != Structure.Size)
44445ffd83dbSDimitry Andric     getStreamer().emitZeros(Structure.Size - Offset);
44455ffd83dbSDimitry Andric   return false;
44465ffd83dbSDimitry Andric }
44475ffd83dbSDimitry Andric 
44485ffd83dbSDimitry Andric // Set data values from initializers.
4449e8d8bef9SDimitry Andric bool MasmParser::emitStructValues(const StructInfo &Structure,
4450e8d8bef9SDimitry Andric                                   unsigned *Count) {
44515ffd83dbSDimitry Andric   std::vector<StructInitializer> Initializers;
44525ffd83dbSDimitry Andric   if (parseStructInstList(Structure, Initializers))
44535ffd83dbSDimitry Andric     return true;
44545ffd83dbSDimitry Andric 
44555ffd83dbSDimitry Andric   for (const auto &Initializer : Initializers) {
44565ffd83dbSDimitry Andric     if (emitStructInitializer(Structure, Initializer))
44575ffd83dbSDimitry Andric       return true;
44585ffd83dbSDimitry Andric   }
44595ffd83dbSDimitry Andric 
4460e8d8bef9SDimitry Andric   if (Count)
4461e8d8bef9SDimitry Andric     *Count = Initializers.size();
44625ffd83dbSDimitry Andric   return false;
44635ffd83dbSDimitry Andric }
44645ffd83dbSDimitry Andric 
44655ffd83dbSDimitry Andric // Declare a field in the current struct.
44665ffd83dbSDimitry Andric bool MasmParser::addStructField(StringRef Name, const StructInfo &Structure) {
44675ffd83dbSDimitry Andric   StructInfo &OwningStruct = StructInProgress.back();
4468e8d8bef9SDimitry Andric   FieldInfo &Field =
4469e8d8bef9SDimitry Andric       OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
44705ffd83dbSDimitry Andric   StructFieldInfo &StructInfo = Field.Contents.StructInfo;
44715ffd83dbSDimitry Andric 
44725ffd83dbSDimitry Andric   StructInfo.Structure = Structure;
44735ffd83dbSDimitry Andric   Field.Type = Structure.Size;
44745ffd83dbSDimitry Andric 
44755ffd83dbSDimitry Andric   if (parseStructInstList(Structure, StructInfo.Initializers))
44765ffd83dbSDimitry Andric     return true;
44775ffd83dbSDimitry Andric 
44785ffd83dbSDimitry Andric   Field.LengthOf = StructInfo.Initializers.size();
44795ffd83dbSDimitry Andric   Field.SizeOf = Field.Type * Field.LengthOf;
4480fe6060f1SDimitry Andric 
4481fe6060f1SDimitry Andric   const unsigned FieldEnd = Field.Offset + Field.SizeOf;
4482fe6060f1SDimitry Andric   if (!OwningStruct.IsUnion) {
4483fe6060f1SDimitry Andric     OwningStruct.NextOffset = FieldEnd;
4484fe6060f1SDimitry Andric   }
4485fe6060f1SDimitry Andric   OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd);
44865ffd83dbSDimitry Andric 
44875ffd83dbSDimitry Andric   return false;
44885ffd83dbSDimitry Andric }
44895ffd83dbSDimitry Andric 
44905ffd83dbSDimitry Andric /// parseDirectiveStructValue
44915ffd83dbSDimitry Andric ///  ::= struct-id (<struct-initializer> | {struct-initializer})
44925ffd83dbSDimitry Andric ///                [, (<struct-initializer> | {struct-initializer})]*
44935ffd83dbSDimitry Andric bool MasmParser::parseDirectiveStructValue(const StructInfo &Structure,
44945ffd83dbSDimitry Andric                                            StringRef Directive, SMLoc DirLoc) {
44955ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
44965ffd83dbSDimitry Andric     if (emitStructValues(Structure))
44975ffd83dbSDimitry Andric       return true;
44985ffd83dbSDimitry Andric   } else if (addStructField("", Structure)) {
44995ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
45005ffd83dbSDimitry Andric   }
45015ffd83dbSDimitry Andric 
45025ffd83dbSDimitry Andric   return false;
45035ffd83dbSDimitry Andric }
45045ffd83dbSDimitry Andric 
45055ffd83dbSDimitry Andric /// parseDirectiveNamedValue
45065ffd83dbSDimitry Andric ///  ::= name (byte | word | ... ) [ expression (, expression)* ]
45075ffd83dbSDimitry Andric bool MasmParser::parseDirectiveNamedStructValue(const StructInfo &Structure,
45085ffd83dbSDimitry Andric                                                 StringRef Directive,
45095ffd83dbSDimitry Andric                                                 SMLoc DirLoc, StringRef Name) {
45105ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
45115ffd83dbSDimitry Andric     // Initialize named data value.
45125ffd83dbSDimitry Andric     MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
45135ffd83dbSDimitry Andric     getStreamer().emitLabel(Sym);
4514e8d8bef9SDimitry Andric     unsigned Count;
4515e8d8bef9SDimitry Andric     if (emitStructValues(Structure, &Count))
45165ffd83dbSDimitry Andric       return true;
4517e8d8bef9SDimitry Andric     AsmTypeInfo Type;
4518e8d8bef9SDimitry Andric     Type.Name = Structure.Name;
4519e8d8bef9SDimitry Andric     Type.Size = Structure.Size * Count;
4520e8d8bef9SDimitry Andric     Type.ElementSize = Structure.Size;
4521e8d8bef9SDimitry Andric     Type.Length = Count;
4522e8d8bef9SDimitry Andric     KnownType[Name.lower()] = Type;
45235ffd83dbSDimitry Andric   } else if (addStructField(Name, Structure)) {
45245ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
45255ffd83dbSDimitry Andric   }
45265ffd83dbSDimitry Andric 
45275ffd83dbSDimitry Andric   return false;
45285ffd83dbSDimitry Andric }
45295ffd83dbSDimitry Andric 
45305ffd83dbSDimitry Andric /// parseDirectiveStruct
45315ffd83dbSDimitry Andric ///  ::= <name> (STRUC | STRUCT | UNION) [fieldAlign] [, NONUNIQUE]
45325ffd83dbSDimitry Andric ///      (dataDir | generalDir | offsetDir | nestedStruct)+
45335ffd83dbSDimitry Andric ///      <name> ENDS
45345ffd83dbSDimitry Andric ////// dataDir = data declaration
45355ffd83dbSDimitry Andric ////// offsetDir = EVEN, ORG, ALIGN
45365ffd83dbSDimitry Andric bool MasmParser::parseDirectiveStruct(StringRef Directive,
45375ffd83dbSDimitry Andric                                       DirectiveKind DirKind, StringRef Name,
45385ffd83dbSDimitry Andric                                       SMLoc NameLoc) {
45395ffd83dbSDimitry Andric   // We ignore NONUNIQUE; we do not support OPTION M510 or OPTION OLDSTRUCTS
45405ffd83dbSDimitry Andric   // anyway, so all field accesses must be qualified.
45415ffd83dbSDimitry Andric   AsmToken NextTok = getTok();
45425ffd83dbSDimitry Andric   int64_t AlignmentValue = 1;
45435ffd83dbSDimitry Andric   if (NextTok.isNot(AsmToken::Comma) &&
45445ffd83dbSDimitry Andric       NextTok.isNot(AsmToken::EndOfStatement) &&
45455ffd83dbSDimitry Andric       parseAbsoluteExpression(AlignmentValue)) {
45465ffd83dbSDimitry Andric     return addErrorSuffix(" in alignment value for '" + Twine(Directive) +
45475ffd83dbSDimitry Andric                           "' directive");
45485ffd83dbSDimitry Andric   }
45495ffd83dbSDimitry Andric   if (!isPowerOf2_64(AlignmentValue)) {
45505ffd83dbSDimitry Andric     return Error(NextTok.getLoc(), "alignment must be a power of two; was " +
45515ffd83dbSDimitry Andric                                        std::to_string(AlignmentValue));
45525ffd83dbSDimitry Andric   }
45535ffd83dbSDimitry Andric 
45545ffd83dbSDimitry Andric   StringRef Qualifier;
45555ffd83dbSDimitry Andric   SMLoc QualifierLoc;
45565ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::Comma)) {
45575ffd83dbSDimitry Andric     QualifierLoc = getTok().getLoc();
45585ffd83dbSDimitry Andric     if (parseIdentifier(Qualifier))
45595ffd83dbSDimitry Andric       return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
4560fe6060f1SDimitry Andric     if (!Qualifier.equals_insensitive("nonunique"))
45615ffd83dbSDimitry Andric       return Error(QualifierLoc, "Unrecognized qualifier for '" +
45625ffd83dbSDimitry Andric                                      Twine(Directive) +
45635ffd83dbSDimitry Andric                                      "' directive; expected none or NONUNIQUE");
45645ffd83dbSDimitry Andric   }
45655ffd83dbSDimitry Andric 
45665ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement))
45675ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
45685ffd83dbSDimitry Andric 
45695ffd83dbSDimitry Andric   StructInProgress.emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
45705ffd83dbSDimitry Andric   return false;
45715ffd83dbSDimitry Andric }
45725ffd83dbSDimitry Andric 
45735ffd83dbSDimitry Andric /// parseDirectiveNestedStruct
45745ffd83dbSDimitry Andric ///  ::= (STRUC | STRUCT | UNION) [name]
45755ffd83dbSDimitry Andric ///      (dataDir | generalDir | offsetDir | nestedStruct)+
45765ffd83dbSDimitry Andric ///      ENDS
45775ffd83dbSDimitry Andric bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
45785ffd83dbSDimitry Andric                                             DirectiveKind DirKind) {
45795ffd83dbSDimitry Andric   if (StructInProgress.empty())
45805ffd83dbSDimitry Andric     return TokError("missing name in top-level '" + Twine(Directive) +
45815ffd83dbSDimitry Andric                     "' directive");
45825ffd83dbSDimitry Andric 
45835ffd83dbSDimitry Andric   StringRef Name;
45845ffd83dbSDimitry Andric   if (getTok().is(AsmToken::Identifier)) {
45855ffd83dbSDimitry Andric     Name = getTok().getIdentifier();
45865ffd83dbSDimitry Andric     parseToken(AsmToken::Identifier);
45875ffd83dbSDimitry Andric   }
45885ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement))
45895ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
45905ffd83dbSDimitry Andric 
4591e8d8bef9SDimitry Andric   // Reserve space to ensure Alignment doesn't get invalidated when
4592e8d8bef9SDimitry Andric   // StructInProgress grows.
4593e8d8bef9SDimitry Andric   StructInProgress.reserve(StructInProgress.size() + 1);
45945ffd83dbSDimitry Andric   StructInProgress.emplace_back(Name, DirKind == DK_UNION,
45955ffd83dbSDimitry Andric                                 StructInProgress.back().Alignment);
45965ffd83dbSDimitry Andric   return false;
45975ffd83dbSDimitry Andric }
45985ffd83dbSDimitry Andric 
45995ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
46005ffd83dbSDimitry Andric   if (StructInProgress.empty())
46015ffd83dbSDimitry Andric     return Error(NameLoc, "ENDS directive without matching STRUC/STRUCT/UNION");
46025ffd83dbSDimitry Andric   if (StructInProgress.size() > 1)
46035ffd83dbSDimitry Andric     return Error(NameLoc, "unexpected name in nested ENDS directive");
4604fe6060f1SDimitry Andric   if (StructInProgress.back().Name.compare_insensitive(Name))
46055ffd83dbSDimitry Andric     return Error(NameLoc, "mismatched name in ENDS directive; expected '" +
46065ffd83dbSDimitry Andric                               StructInProgress.back().Name + "'");
46075ffd83dbSDimitry Andric   StructInfo Structure = StructInProgress.pop_back_val();
4608e8d8bef9SDimitry Andric   // Pad to make the structure's size divisible by the smaller of its alignment
4609e8d8bef9SDimitry Andric   // and the size of its largest field.
4610e8d8bef9SDimitry Andric   Structure.Size = llvm::alignTo(
4611e8d8bef9SDimitry Andric       Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
46125ffd83dbSDimitry Andric   Structs[Name.lower()] = Structure;
46135ffd83dbSDimitry Andric 
46145ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement))
46155ffd83dbSDimitry Andric     return addErrorSuffix(" in ENDS directive");
46165ffd83dbSDimitry Andric 
46175ffd83dbSDimitry Andric   return false;
46185ffd83dbSDimitry Andric }
46195ffd83dbSDimitry Andric 
46205ffd83dbSDimitry Andric bool MasmParser::parseDirectiveNestedEnds() {
46215ffd83dbSDimitry Andric   if (StructInProgress.empty())
46225ffd83dbSDimitry Andric     return TokError("ENDS directive without matching STRUC/STRUCT/UNION");
46235ffd83dbSDimitry Andric   if (StructInProgress.size() == 1)
46245ffd83dbSDimitry Andric     return TokError("missing name in top-level ENDS directive");
46255ffd83dbSDimitry Andric 
46265ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement))
46275ffd83dbSDimitry Andric     return addErrorSuffix(" in nested ENDS directive");
46285ffd83dbSDimitry Andric 
46295ffd83dbSDimitry Andric   StructInfo Structure = StructInProgress.pop_back_val();
46305ffd83dbSDimitry Andric   // Pad to make the structure's size divisible by its alignment.
46315ffd83dbSDimitry Andric   Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment);
46325ffd83dbSDimitry Andric 
46335ffd83dbSDimitry Andric   StructInfo &ParentStruct = StructInProgress.back();
46345ffd83dbSDimitry Andric   if (Structure.Name.empty()) {
4635fe6060f1SDimitry Andric     // Anonymous substructures' fields are addressed as if they belong to the
4636fe6060f1SDimitry Andric     // parent structure - so we transfer them to the parent here.
46375ffd83dbSDimitry Andric     const size_t OldFields = ParentStruct.Fields.size();
46385ffd83dbSDimitry Andric     ParentStruct.Fields.insert(
46395ffd83dbSDimitry Andric         ParentStruct.Fields.end(),
46405ffd83dbSDimitry Andric         std::make_move_iterator(Structure.Fields.begin()),
46415ffd83dbSDimitry Andric         std::make_move_iterator(Structure.Fields.end()));
46425ffd83dbSDimitry Andric     for (const auto &FieldByName : Structure.FieldsByName) {
46435ffd83dbSDimitry Andric       ParentStruct.FieldsByName[FieldByName.getKey()] =
46445ffd83dbSDimitry Andric           FieldByName.getValue() + OldFields;
46455ffd83dbSDimitry Andric     }
4646fe6060f1SDimitry Andric 
4647fe6060f1SDimitry Andric     unsigned FirstFieldOffset = 0;
4648fe6060f1SDimitry Andric     if (!Structure.Fields.empty() && !ParentStruct.IsUnion) {
4649fe6060f1SDimitry Andric       FirstFieldOffset = llvm::alignTo(
4650fe6060f1SDimitry Andric           ParentStruct.NextOffset,
4651fe6060f1SDimitry Andric           std::min(ParentStruct.Alignment, Structure.AlignmentSize));
46525ffd83dbSDimitry Andric     }
46535ffd83dbSDimitry Andric 
4654fe6060f1SDimitry Andric     if (ParentStruct.IsUnion) {
46555ffd83dbSDimitry Andric       ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
4656fe6060f1SDimitry Andric     } else {
4657fcaf7f86SDimitry Andric       for (auto &Field : llvm::drop_begin(ParentStruct.Fields, OldFields))
4658fcaf7f86SDimitry Andric         Field.Offset += FirstFieldOffset;
4659fe6060f1SDimitry Andric 
4660fe6060f1SDimitry Andric       const unsigned StructureEnd = FirstFieldOffset + Structure.Size;
4661fe6060f1SDimitry Andric       if (!ParentStruct.IsUnion) {
4662fe6060f1SDimitry Andric         ParentStruct.NextOffset = StructureEnd;
4663fe6060f1SDimitry Andric       }
4664fe6060f1SDimitry Andric       ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4665fe6060f1SDimitry Andric     }
46665ffd83dbSDimitry Andric   } else {
4667e8d8bef9SDimitry Andric     FieldInfo &Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
4668e8d8bef9SDimitry Andric                                              Structure.AlignmentSize);
46695ffd83dbSDimitry Andric     StructFieldInfo &StructInfo = Field.Contents.StructInfo;
46705ffd83dbSDimitry Andric     Field.Type = Structure.Size;
46715ffd83dbSDimitry Andric     Field.LengthOf = 1;
46725ffd83dbSDimitry Andric     Field.SizeOf = Structure.Size;
46735ffd83dbSDimitry Andric 
4674fe6060f1SDimitry Andric     const unsigned StructureEnd = Field.Offset + Field.SizeOf;
4675fe6060f1SDimitry Andric     if (!ParentStruct.IsUnion) {
4676fe6060f1SDimitry Andric       ParentStruct.NextOffset = StructureEnd;
4677fe6060f1SDimitry Andric     }
4678fe6060f1SDimitry Andric     ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
46795ffd83dbSDimitry Andric 
46805ffd83dbSDimitry Andric     StructInfo.Structure = Structure;
46815ffd83dbSDimitry Andric     StructInfo.Initializers.emplace_back();
46825ffd83dbSDimitry Andric     auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
46835ffd83dbSDimitry Andric     for (const auto &SubField : Structure.Fields) {
46845ffd83dbSDimitry Andric       FieldInitializers.push_back(SubField.Contents);
46855ffd83dbSDimitry Andric     }
46865ffd83dbSDimitry Andric   }
46875ffd83dbSDimitry Andric 
46885ffd83dbSDimitry Andric   return false;
46895ffd83dbSDimitry Andric }
46905ffd83dbSDimitry Andric 
46915ffd83dbSDimitry Andric /// parseDirectiveOrg
4692fe6060f1SDimitry Andric ///  ::= org expression
46935ffd83dbSDimitry Andric bool MasmParser::parseDirectiveOrg() {
46945ffd83dbSDimitry Andric   const MCExpr *Offset;
46955ffd83dbSDimitry Andric   SMLoc OffsetLoc = Lexer.getLoc();
46965ffd83dbSDimitry Andric   if (checkForValidSection() || parseExpression(Offset))
46975ffd83dbSDimitry Andric     return true;
46985ffd83dbSDimitry Andric   if (parseToken(AsmToken::EndOfStatement))
4699fe6060f1SDimitry Andric     return addErrorSuffix(" in 'org' directive");
47005ffd83dbSDimitry Andric 
4701fe6060f1SDimitry Andric   if (StructInProgress.empty()) {
4702fe6060f1SDimitry Andric     // Not in a struct; change the offset for the next instruction or data
4703fe6060f1SDimitry Andric     if (checkForValidSection())
4704fe6060f1SDimitry Andric       return addErrorSuffix(" in 'org' directive");
4705fe6060f1SDimitry Andric 
4706fe6060f1SDimitry Andric     getStreamer().emitValueToOffset(Offset, 0, OffsetLoc);
4707fe6060f1SDimitry Andric   } else {
4708fe6060f1SDimitry Andric     // Offset the next field of this struct
4709fe6060f1SDimitry Andric     StructInfo &Structure = StructInProgress.back();
4710fe6060f1SDimitry Andric     int64_t OffsetRes;
4711fe6060f1SDimitry Andric     if (!Offset->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr()))
4712fe6060f1SDimitry Andric       return Error(OffsetLoc,
4713fe6060f1SDimitry Andric                    "expected absolute expression in 'org' directive");
4714fe6060f1SDimitry Andric     if (OffsetRes < 0)
4715fe6060f1SDimitry Andric       return Error(
4716fe6060f1SDimitry Andric           OffsetLoc,
4717fe6060f1SDimitry Andric           "expected non-negative value in struct's 'org' directive; was " +
4718fe6060f1SDimitry Andric               std::to_string(OffsetRes));
4719fe6060f1SDimitry Andric     Structure.NextOffset = static_cast<unsigned>(OffsetRes);
4720fe6060f1SDimitry Andric 
4721fe6060f1SDimitry Andric     // ORG-affected structures cannot be initialized
4722fe6060f1SDimitry Andric     Structure.Initializable = false;
4723fe6060f1SDimitry Andric   }
4724fe6060f1SDimitry Andric 
47255ffd83dbSDimitry Andric   return false;
47265ffd83dbSDimitry Andric }
47275ffd83dbSDimitry Andric 
4728fe6060f1SDimitry Andric bool MasmParser::emitAlignTo(int64_t Alignment) {
4729fe6060f1SDimitry Andric   if (StructInProgress.empty()) {
4730fe6060f1SDimitry Andric     // Not in a struct; align the next instruction or data
47315ffd83dbSDimitry Andric     if (checkForValidSection())
4732fe6060f1SDimitry Andric       return true;
47335ffd83dbSDimitry Andric 
47345ffd83dbSDimitry Andric     // Check whether we should use optimal code alignment for this align
47355ffd83dbSDimitry Andric     // directive.
47365ffd83dbSDimitry Andric     const MCSection *Section = getStreamer().getCurrentSectionOnly();
47375ffd83dbSDimitry Andric     assert(Section && "must have section to emit alignment");
473881ad6265SDimitry Andric     if (Section->useCodeAlign()) {
4739*bdd1243dSDimitry Andric       getStreamer().emitCodeAlignment(Align(Alignment),
4740*bdd1243dSDimitry Andric                                       &getTargetParser().getSTI(),
4741349cc55cSDimitry Andric                                       /*MaxBytesToEmit=*/0);
47425ffd83dbSDimitry Andric     } else {
47435ffd83dbSDimitry Andric       // FIXME: Target specific behavior about how the "extra" bytes are filled.
4744*bdd1243dSDimitry Andric       getStreamer().emitValueToAlignment(Align(Alignment), /*Value=*/0,
4745fe6060f1SDimitry Andric                                          /*ValueSize=*/1,
47465ffd83dbSDimitry Andric                                          /*MaxBytesToEmit=*/0);
47475ffd83dbSDimitry Andric     }
4748fe6060f1SDimitry Andric   } else {
4749fe6060f1SDimitry Andric     // Align the next field of this struct
4750fe6060f1SDimitry Andric     StructInfo &Structure = StructInProgress.back();
4751fe6060f1SDimitry Andric     Structure.NextOffset = llvm::alignTo(Structure.NextOffset, Alignment);
4752fe6060f1SDimitry Andric   }
4753fe6060f1SDimitry Andric 
4754fe6060f1SDimitry Andric   return false;
4755fe6060f1SDimitry Andric }
4756fe6060f1SDimitry Andric 
4757fe6060f1SDimitry Andric /// parseDirectiveAlign
4758fe6060f1SDimitry Andric ///  ::= align expression
4759fe6060f1SDimitry Andric bool MasmParser::parseDirectiveAlign() {
4760fe6060f1SDimitry Andric   SMLoc AlignmentLoc = getLexer().getLoc();
4761fe6060f1SDimitry Andric   int64_t Alignment;
4762fe6060f1SDimitry Andric 
4763fe6060f1SDimitry Andric   // Ignore empty 'align' directives.
4764fe6060f1SDimitry Andric   if (getTok().is(AsmToken::EndOfStatement)) {
4765fe6060f1SDimitry Andric     return Warning(AlignmentLoc,
4766fe6060f1SDimitry Andric                    "align directive with no operand is ignored") &&
4767fe6060f1SDimitry Andric            parseToken(AsmToken::EndOfStatement);
4768fe6060f1SDimitry Andric   }
4769fe6060f1SDimitry Andric   if (parseAbsoluteExpression(Alignment) ||
4770fe6060f1SDimitry Andric       parseToken(AsmToken::EndOfStatement))
4771fe6060f1SDimitry Andric     return addErrorSuffix(" in align directive");
4772fe6060f1SDimitry Andric 
4773fe6060f1SDimitry Andric   // Always emit an alignment here even if we throw an error.
4774fe6060f1SDimitry Andric   bool ReturnVal = false;
4775fe6060f1SDimitry Andric 
4776fe6060f1SDimitry Andric   // Reject alignments that aren't either a power of two or zero, for ML.exe
4777fe6060f1SDimitry Andric   // compatibility. Alignment of zero is silently rounded up to one.
4778fe6060f1SDimitry Andric   if (Alignment == 0)
4779fe6060f1SDimitry Andric     Alignment = 1;
4780fe6060f1SDimitry Andric   if (!isPowerOf2_64(Alignment))
4781fe6060f1SDimitry Andric     ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2; was " +
4782fe6060f1SDimitry Andric                                          std::to_string(Alignment));
4783fe6060f1SDimitry Andric 
4784fe6060f1SDimitry Andric   if (emitAlignTo(Alignment))
4785fe6060f1SDimitry Andric     ReturnVal |= addErrorSuffix(" in align directive");
47865ffd83dbSDimitry Andric 
47875ffd83dbSDimitry Andric   return ReturnVal;
47885ffd83dbSDimitry Andric }
47895ffd83dbSDimitry Andric 
4790fe6060f1SDimitry Andric /// parseDirectiveEven
4791fe6060f1SDimitry Andric ///  ::= even
4792fe6060f1SDimitry Andric bool MasmParser::parseDirectiveEven() {
4793fe6060f1SDimitry Andric   if (parseToken(AsmToken::EndOfStatement) || emitAlignTo(2))
4794fe6060f1SDimitry Andric     return addErrorSuffix(" in even directive");
4795fe6060f1SDimitry Andric 
4796fe6060f1SDimitry Andric   return false;
4797fe6060f1SDimitry Andric }
4798fe6060f1SDimitry Andric 
47995ffd83dbSDimitry Andric /// parseDirectiveFile
48005ffd83dbSDimitry Andric /// ::= .file filename
48015ffd83dbSDimitry Andric /// ::= .file number [directory] filename [md5 checksum] [source source-text]
48025ffd83dbSDimitry Andric bool MasmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
48035ffd83dbSDimitry Andric   // FIXME: I'm not sure what this is.
48045ffd83dbSDimitry Andric   int64_t FileNumber = -1;
48055ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
48065ffd83dbSDimitry Andric     FileNumber = getTok().getIntVal();
48075ffd83dbSDimitry Andric     Lex();
48085ffd83dbSDimitry Andric 
48095ffd83dbSDimitry Andric     if (FileNumber < 0)
48105ffd83dbSDimitry Andric       return TokError("negative file number");
48115ffd83dbSDimitry Andric   }
48125ffd83dbSDimitry Andric 
48135ffd83dbSDimitry Andric   std::string Path;
48145ffd83dbSDimitry Andric 
48155ffd83dbSDimitry Andric   // Usually the directory and filename together, otherwise just the directory.
48165ffd83dbSDimitry Andric   // Allow the strings to have escaped octal character sequence.
48175ffd83dbSDimitry Andric   if (check(getTok().isNot(AsmToken::String),
48185ffd83dbSDimitry Andric             "unexpected token in '.file' directive") ||
48195ffd83dbSDimitry Andric       parseEscapedString(Path))
48205ffd83dbSDimitry Andric     return true;
48215ffd83dbSDimitry Andric 
48225ffd83dbSDimitry Andric   StringRef Directory;
48235ffd83dbSDimitry Andric   StringRef Filename;
48245ffd83dbSDimitry Andric   std::string FilenameData;
48255ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::String)) {
48265ffd83dbSDimitry Andric     if (check(FileNumber == -1,
48275ffd83dbSDimitry Andric               "explicit path specified, but no file number") ||
48285ffd83dbSDimitry Andric         parseEscapedString(FilenameData))
48295ffd83dbSDimitry Andric       return true;
48305ffd83dbSDimitry Andric     Filename = FilenameData;
48315ffd83dbSDimitry Andric     Directory = Path;
48325ffd83dbSDimitry Andric   } else {
48335ffd83dbSDimitry Andric     Filename = Path;
48345ffd83dbSDimitry Andric   }
48355ffd83dbSDimitry Andric 
48365ffd83dbSDimitry Andric   uint64_t MD5Hi, MD5Lo;
48375ffd83dbSDimitry Andric   bool HasMD5 = false;
48385ffd83dbSDimitry Andric 
4839*bdd1243dSDimitry Andric   std::optional<StringRef> Source;
48405ffd83dbSDimitry Andric   bool HasSource = false;
48415ffd83dbSDimitry Andric   std::string SourceString;
48425ffd83dbSDimitry Andric 
48435ffd83dbSDimitry Andric   while (!parseOptionalToken(AsmToken::EndOfStatement)) {
48445ffd83dbSDimitry Andric     StringRef Keyword;
48455ffd83dbSDimitry Andric     if (check(getTok().isNot(AsmToken::Identifier),
48465ffd83dbSDimitry Andric               "unexpected token in '.file' directive") ||
48475ffd83dbSDimitry Andric         parseIdentifier(Keyword))
48485ffd83dbSDimitry Andric       return true;
48495ffd83dbSDimitry Andric     if (Keyword == "md5") {
48505ffd83dbSDimitry Andric       HasMD5 = true;
48515ffd83dbSDimitry Andric       if (check(FileNumber == -1,
48525ffd83dbSDimitry Andric                 "MD5 checksum specified, but no file number") ||
48535ffd83dbSDimitry Andric           parseHexOcta(*this, MD5Hi, MD5Lo))
48545ffd83dbSDimitry Andric         return true;
48555ffd83dbSDimitry Andric     } else if (Keyword == "source") {
48565ffd83dbSDimitry Andric       HasSource = true;
48575ffd83dbSDimitry Andric       if (check(FileNumber == -1,
48585ffd83dbSDimitry Andric                 "source specified, but no file number") ||
48595ffd83dbSDimitry Andric           check(getTok().isNot(AsmToken::String),
48605ffd83dbSDimitry Andric                 "unexpected token in '.file' directive") ||
48615ffd83dbSDimitry Andric           parseEscapedString(SourceString))
48625ffd83dbSDimitry Andric         return true;
48635ffd83dbSDimitry Andric     } else {
48645ffd83dbSDimitry Andric       return TokError("unexpected token in '.file' directive");
48655ffd83dbSDimitry Andric     }
48665ffd83dbSDimitry Andric   }
48675ffd83dbSDimitry Andric 
48685ffd83dbSDimitry Andric   if (FileNumber == -1) {
48695ffd83dbSDimitry Andric     // Ignore the directive if there is no number and the target doesn't support
48705ffd83dbSDimitry Andric     // numberless .file directives. This allows some portability of assembler
48715ffd83dbSDimitry Andric     // between different object file formats.
48725ffd83dbSDimitry Andric     if (getContext().getAsmInfo()->hasSingleParameterDotFile())
48735ffd83dbSDimitry Andric       getStreamer().emitFileDirective(Filename);
48745ffd83dbSDimitry Andric   } else {
48755ffd83dbSDimitry Andric     // In case there is a -g option as well as debug info from directive .file,
48765ffd83dbSDimitry Andric     // we turn off the -g option, directly use the existing debug info instead.
48775ffd83dbSDimitry Andric     // Throw away any implicit file table for the assembler source.
48785ffd83dbSDimitry Andric     if (Ctx.getGenDwarfForAssembly()) {
48795ffd83dbSDimitry Andric       Ctx.getMCDwarfLineTable(0).resetFileTable();
48805ffd83dbSDimitry Andric       Ctx.setGenDwarfForAssembly(false);
48815ffd83dbSDimitry Andric     }
48825ffd83dbSDimitry Andric 
4883*bdd1243dSDimitry Andric     std::optional<MD5::MD5Result> CKMem;
48845ffd83dbSDimitry Andric     if (HasMD5) {
48855ffd83dbSDimitry Andric       MD5::MD5Result Sum;
48865ffd83dbSDimitry Andric       for (unsigned i = 0; i != 8; ++i) {
488781ad6265SDimitry Andric         Sum[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
488881ad6265SDimitry Andric         Sum[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
48895ffd83dbSDimitry Andric       }
48905ffd83dbSDimitry Andric       CKMem = Sum;
48915ffd83dbSDimitry Andric     }
48925ffd83dbSDimitry Andric     if (HasSource) {
48935ffd83dbSDimitry Andric       char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
48945ffd83dbSDimitry Andric       memcpy(SourceBuf, SourceString.data(), SourceString.size());
48955ffd83dbSDimitry Andric       Source = StringRef(SourceBuf, SourceString.size());
48965ffd83dbSDimitry Andric     }
48975ffd83dbSDimitry Andric     if (FileNumber == 0) {
48985ffd83dbSDimitry Andric       if (Ctx.getDwarfVersion() < 5)
48995ffd83dbSDimitry Andric         return Warning(DirectiveLoc, "file 0 not supported prior to DWARF-5");
49005ffd83dbSDimitry Andric       getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
49015ffd83dbSDimitry Andric     } else {
49025ffd83dbSDimitry Andric       Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
49035ffd83dbSDimitry Andric           FileNumber, Directory, Filename, CKMem, Source);
49045ffd83dbSDimitry Andric       if (!FileNumOrErr)
49055ffd83dbSDimitry Andric         return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
49065ffd83dbSDimitry Andric     }
49075ffd83dbSDimitry Andric     // Alert the user if there are some .file directives with MD5 and some not.
49085ffd83dbSDimitry Andric     // But only do that once.
49095ffd83dbSDimitry Andric     if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
49105ffd83dbSDimitry Andric       ReportedInconsistentMD5 = true;
49115ffd83dbSDimitry Andric       return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
49125ffd83dbSDimitry Andric     }
49135ffd83dbSDimitry Andric   }
49145ffd83dbSDimitry Andric 
49155ffd83dbSDimitry Andric   return false;
49165ffd83dbSDimitry Andric }
49175ffd83dbSDimitry Andric 
49185ffd83dbSDimitry Andric /// parseDirectiveLine
49195ffd83dbSDimitry Andric /// ::= .line [number]
49205ffd83dbSDimitry Andric bool MasmParser::parseDirectiveLine() {
49215ffd83dbSDimitry Andric   int64_t LineNumber;
49225ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
49235ffd83dbSDimitry Andric     if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
49245ffd83dbSDimitry Andric       return true;
49255ffd83dbSDimitry Andric     (void)LineNumber;
49265ffd83dbSDimitry Andric     // FIXME: Do something with the .line.
49275ffd83dbSDimitry Andric   }
492881ad6265SDimitry Andric   if (parseEOL())
49295ffd83dbSDimitry Andric     return true;
49305ffd83dbSDimitry Andric 
49315ffd83dbSDimitry Andric   return false;
49325ffd83dbSDimitry Andric }
49335ffd83dbSDimitry Andric 
49345ffd83dbSDimitry Andric /// parseDirectiveLoc
49355ffd83dbSDimitry Andric /// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
49365ffd83dbSDimitry Andric ///                                [epilogue_begin] [is_stmt VALUE] [isa VALUE]
49375ffd83dbSDimitry Andric /// The first number is a file number, must have been previously assigned with
49385ffd83dbSDimitry Andric /// a .file directive, the second number is the line number and optionally the
49395ffd83dbSDimitry Andric /// third number is a column position (zero if not specified).  The remaining
49405ffd83dbSDimitry Andric /// optional items are .loc sub-directives.
49415ffd83dbSDimitry Andric bool MasmParser::parseDirectiveLoc() {
49425ffd83dbSDimitry Andric   int64_t FileNumber = 0, LineNumber = 0;
49435ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
49445ffd83dbSDimitry Andric   if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
49455ffd83dbSDimitry Andric       check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
49465ffd83dbSDimitry Andric             "file number less than one in '.loc' directive") ||
49475ffd83dbSDimitry Andric       check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
49485ffd83dbSDimitry Andric             "unassigned file number in '.loc' directive"))
49495ffd83dbSDimitry Andric     return true;
49505ffd83dbSDimitry Andric 
49515ffd83dbSDimitry Andric   // optional
49525ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
49535ffd83dbSDimitry Andric     LineNumber = getTok().getIntVal();
49545ffd83dbSDimitry Andric     if (LineNumber < 0)
49555ffd83dbSDimitry Andric       return TokError("line number less than zero in '.loc' directive");
49565ffd83dbSDimitry Andric     Lex();
49575ffd83dbSDimitry Andric   }
49585ffd83dbSDimitry Andric 
49595ffd83dbSDimitry Andric   int64_t ColumnPos = 0;
49605ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
49615ffd83dbSDimitry Andric     ColumnPos = getTok().getIntVal();
49625ffd83dbSDimitry Andric     if (ColumnPos < 0)
49635ffd83dbSDimitry Andric       return TokError("column position less than zero in '.loc' directive");
49645ffd83dbSDimitry Andric     Lex();
49655ffd83dbSDimitry Andric   }
49665ffd83dbSDimitry Andric 
49675ffd83dbSDimitry Andric   auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();
49685ffd83dbSDimitry Andric   unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;
49695ffd83dbSDimitry Andric   unsigned Isa = 0;
49705ffd83dbSDimitry Andric   int64_t Discriminator = 0;
49715ffd83dbSDimitry Andric 
49725ffd83dbSDimitry Andric   auto parseLocOp = [&]() -> bool {
49735ffd83dbSDimitry Andric     StringRef Name;
49745ffd83dbSDimitry Andric     SMLoc Loc = getTok().getLoc();
49755ffd83dbSDimitry Andric     if (parseIdentifier(Name))
49765ffd83dbSDimitry Andric       return TokError("unexpected token in '.loc' directive");
49775ffd83dbSDimitry Andric 
49785ffd83dbSDimitry Andric     if (Name == "basic_block")
49795ffd83dbSDimitry Andric       Flags |= DWARF2_FLAG_BASIC_BLOCK;
49805ffd83dbSDimitry Andric     else if (Name == "prologue_end")
49815ffd83dbSDimitry Andric       Flags |= DWARF2_FLAG_PROLOGUE_END;
49825ffd83dbSDimitry Andric     else if (Name == "epilogue_begin")
49835ffd83dbSDimitry Andric       Flags |= DWARF2_FLAG_EPILOGUE_BEGIN;
49845ffd83dbSDimitry Andric     else if (Name == "is_stmt") {
49855ffd83dbSDimitry Andric       Loc = getTok().getLoc();
49865ffd83dbSDimitry Andric       const MCExpr *Value;
49875ffd83dbSDimitry Andric       if (parseExpression(Value))
49885ffd83dbSDimitry Andric         return true;
49895ffd83dbSDimitry Andric       // The expression must be the constant 0 or 1.
49905ffd83dbSDimitry Andric       if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
49915ffd83dbSDimitry Andric         int Value = MCE->getValue();
49925ffd83dbSDimitry Andric         if (Value == 0)
49935ffd83dbSDimitry Andric           Flags &= ~DWARF2_FLAG_IS_STMT;
49945ffd83dbSDimitry Andric         else if (Value == 1)
49955ffd83dbSDimitry Andric           Flags |= DWARF2_FLAG_IS_STMT;
49965ffd83dbSDimitry Andric         else
49975ffd83dbSDimitry Andric           return Error(Loc, "is_stmt value not 0 or 1");
49985ffd83dbSDimitry Andric       } else {
49995ffd83dbSDimitry Andric         return Error(Loc, "is_stmt value not the constant value of 0 or 1");
50005ffd83dbSDimitry Andric       }
50015ffd83dbSDimitry Andric     } else if (Name == "isa") {
50025ffd83dbSDimitry Andric       Loc = getTok().getLoc();
50035ffd83dbSDimitry Andric       const MCExpr *Value;
50045ffd83dbSDimitry Andric       if (parseExpression(Value))
50055ffd83dbSDimitry Andric         return true;
50065ffd83dbSDimitry Andric       // The expression must be a constant greater or equal to 0.
50075ffd83dbSDimitry Andric       if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
50085ffd83dbSDimitry Andric         int Value = MCE->getValue();
50095ffd83dbSDimitry Andric         if (Value < 0)
50105ffd83dbSDimitry Andric           return Error(Loc, "isa number less than zero");
50115ffd83dbSDimitry Andric         Isa = Value;
50125ffd83dbSDimitry Andric       } else {
50135ffd83dbSDimitry Andric         return Error(Loc, "isa number not a constant value");
50145ffd83dbSDimitry Andric       }
50155ffd83dbSDimitry Andric     } else if (Name == "discriminator") {
50165ffd83dbSDimitry Andric       if (parseAbsoluteExpression(Discriminator))
50175ffd83dbSDimitry Andric         return true;
50185ffd83dbSDimitry Andric     } else {
50195ffd83dbSDimitry Andric       return Error(Loc, "unknown sub-directive in '.loc' directive");
50205ffd83dbSDimitry Andric     }
50215ffd83dbSDimitry Andric     return false;
50225ffd83dbSDimitry Andric   };
50235ffd83dbSDimitry Andric 
50245ffd83dbSDimitry Andric   if (parseMany(parseLocOp, false /*hasComma*/))
50255ffd83dbSDimitry Andric     return true;
50265ffd83dbSDimitry Andric 
50275ffd83dbSDimitry Andric   getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
50285ffd83dbSDimitry Andric                                       Isa, Discriminator, StringRef());
50295ffd83dbSDimitry Andric 
50305ffd83dbSDimitry Andric   return false;
50315ffd83dbSDimitry Andric }
50325ffd83dbSDimitry Andric 
50335ffd83dbSDimitry Andric /// parseDirectiveStabs
50345ffd83dbSDimitry Andric /// ::= .stabs string, number, number, number
50355ffd83dbSDimitry Andric bool MasmParser::parseDirectiveStabs() {
50365ffd83dbSDimitry Andric   return TokError("unsupported directive '.stabs'");
50375ffd83dbSDimitry Andric }
50385ffd83dbSDimitry Andric 
50395ffd83dbSDimitry Andric /// parseDirectiveCVFile
50405ffd83dbSDimitry Andric /// ::= .cv_file number filename [checksum] [checksumkind]
50415ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFile() {
50425ffd83dbSDimitry Andric   SMLoc FileNumberLoc = getTok().getLoc();
50435ffd83dbSDimitry Andric   int64_t FileNumber;
50445ffd83dbSDimitry Andric   std::string Filename;
50455ffd83dbSDimitry Andric   std::string Checksum;
50465ffd83dbSDimitry Andric   int64_t ChecksumKind = 0;
50475ffd83dbSDimitry Andric 
50485ffd83dbSDimitry Andric   if (parseIntToken(FileNumber,
50495ffd83dbSDimitry Andric                     "expected file number in '.cv_file' directive") ||
50505ffd83dbSDimitry Andric       check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
50515ffd83dbSDimitry Andric       check(getTok().isNot(AsmToken::String),
50525ffd83dbSDimitry Andric             "unexpected token in '.cv_file' directive") ||
50535ffd83dbSDimitry Andric       parseEscapedString(Filename))
50545ffd83dbSDimitry Andric     return true;
50555ffd83dbSDimitry Andric   if (!parseOptionalToken(AsmToken::EndOfStatement)) {
50565ffd83dbSDimitry Andric     if (check(getTok().isNot(AsmToken::String),
50575ffd83dbSDimitry Andric               "unexpected token in '.cv_file' directive") ||
50585ffd83dbSDimitry Andric         parseEscapedString(Checksum) ||
50595ffd83dbSDimitry Andric         parseIntToken(ChecksumKind,
50605ffd83dbSDimitry Andric                       "expected checksum kind in '.cv_file' directive") ||
506181ad6265SDimitry Andric         parseEOL())
50625ffd83dbSDimitry Andric       return true;
50635ffd83dbSDimitry Andric   }
50645ffd83dbSDimitry Andric 
50655ffd83dbSDimitry Andric   Checksum = fromHex(Checksum);
50665ffd83dbSDimitry Andric   void *CKMem = Ctx.allocate(Checksum.size(), 1);
50675ffd83dbSDimitry Andric   memcpy(CKMem, Checksum.data(), Checksum.size());
50685ffd83dbSDimitry Andric   ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
50695ffd83dbSDimitry Andric                                     Checksum.size());
50705ffd83dbSDimitry Andric 
507181ad6265SDimitry Andric   if (!getStreamer().emitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
50725ffd83dbSDimitry Andric                                          static_cast<uint8_t>(ChecksumKind)))
50735ffd83dbSDimitry Andric     return Error(FileNumberLoc, "file number already allocated");
50745ffd83dbSDimitry Andric 
50755ffd83dbSDimitry Andric   return false;
50765ffd83dbSDimitry Andric }
50775ffd83dbSDimitry Andric 
50785ffd83dbSDimitry Andric bool MasmParser::parseCVFunctionId(int64_t &FunctionId,
50795ffd83dbSDimitry Andric                                    StringRef DirectiveName) {
50805ffd83dbSDimitry Andric   SMLoc Loc;
50815ffd83dbSDimitry Andric   return parseTokenLoc(Loc) ||
50825ffd83dbSDimitry Andric          parseIntToken(FunctionId, "expected function id in '" + DirectiveName +
50835ffd83dbSDimitry Andric                                        "' directive") ||
50845ffd83dbSDimitry Andric          check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,
50855ffd83dbSDimitry Andric                "expected function id within range [0, UINT_MAX)");
50865ffd83dbSDimitry Andric }
50875ffd83dbSDimitry Andric 
50885ffd83dbSDimitry Andric bool MasmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
50895ffd83dbSDimitry Andric   SMLoc Loc;
50905ffd83dbSDimitry Andric   return parseTokenLoc(Loc) ||
50915ffd83dbSDimitry Andric          parseIntToken(FileNumber, "expected integer in '" + DirectiveName +
50925ffd83dbSDimitry Andric                                        "' directive") ||
50935ffd83dbSDimitry Andric          check(FileNumber < 1, Loc, "file number less than one in '" +
50945ffd83dbSDimitry Andric                                         DirectiveName + "' directive") ||
50955ffd83dbSDimitry Andric          check(!getCVContext().isValidFileNumber(FileNumber), Loc,
50965ffd83dbSDimitry Andric                "unassigned file number in '" + DirectiveName + "' directive");
50975ffd83dbSDimitry Andric }
50985ffd83dbSDimitry Andric 
50995ffd83dbSDimitry Andric /// parseDirectiveCVFuncId
51005ffd83dbSDimitry Andric /// ::= .cv_func_id FunctionId
51015ffd83dbSDimitry Andric ///
51025ffd83dbSDimitry Andric /// Introduces a function ID that can be used with .cv_loc.
51035ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFuncId() {
51045ffd83dbSDimitry Andric   SMLoc FunctionIdLoc = getTok().getLoc();
51055ffd83dbSDimitry Andric   int64_t FunctionId;
51065ffd83dbSDimitry Andric 
510781ad6265SDimitry Andric   if (parseCVFunctionId(FunctionId, ".cv_func_id") || parseEOL())
51085ffd83dbSDimitry Andric     return true;
51095ffd83dbSDimitry Andric 
511081ad6265SDimitry Andric   if (!getStreamer().emitCVFuncIdDirective(FunctionId))
51115ffd83dbSDimitry Andric     return Error(FunctionIdLoc, "function id already allocated");
51125ffd83dbSDimitry Andric 
51135ffd83dbSDimitry Andric   return false;
51145ffd83dbSDimitry Andric }
51155ffd83dbSDimitry Andric 
51165ffd83dbSDimitry Andric /// parseDirectiveCVInlineSiteId
51175ffd83dbSDimitry Andric /// ::= .cv_inline_site_id FunctionId
51185ffd83dbSDimitry Andric ///         "within" IAFunc
51195ffd83dbSDimitry Andric ///         "inlined_at" IAFile IALine [IACol]
51205ffd83dbSDimitry Andric ///
51215ffd83dbSDimitry Andric /// Introduces a function ID that can be used with .cv_loc. Includes "inlined
51225ffd83dbSDimitry Andric /// at" source location information for use in the line table of the caller,
51235ffd83dbSDimitry Andric /// whether the caller is a real function or another inlined call site.
51245ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVInlineSiteId() {
51255ffd83dbSDimitry Andric   SMLoc FunctionIdLoc = getTok().getLoc();
51265ffd83dbSDimitry Andric   int64_t FunctionId;
51275ffd83dbSDimitry Andric   int64_t IAFunc;
51285ffd83dbSDimitry Andric   int64_t IAFile;
51295ffd83dbSDimitry Andric   int64_t IALine;
51305ffd83dbSDimitry Andric   int64_t IACol = 0;
51315ffd83dbSDimitry Andric 
51325ffd83dbSDimitry Andric   // FunctionId
51335ffd83dbSDimitry Andric   if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))
51345ffd83dbSDimitry Andric     return true;
51355ffd83dbSDimitry Andric 
51365ffd83dbSDimitry Andric   // "within"
51375ffd83dbSDimitry Andric   if (check((getLexer().isNot(AsmToken::Identifier) ||
51385ffd83dbSDimitry Andric              getTok().getIdentifier() != "within"),
51395ffd83dbSDimitry Andric             "expected 'within' identifier in '.cv_inline_site_id' directive"))
51405ffd83dbSDimitry Andric     return true;
51415ffd83dbSDimitry Andric   Lex();
51425ffd83dbSDimitry Andric 
51435ffd83dbSDimitry Andric   // IAFunc
51445ffd83dbSDimitry Andric   if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))
51455ffd83dbSDimitry Andric     return true;
51465ffd83dbSDimitry Andric 
51475ffd83dbSDimitry Andric   // "inlined_at"
51485ffd83dbSDimitry Andric   if (check((getLexer().isNot(AsmToken::Identifier) ||
51495ffd83dbSDimitry Andric              getTok().getIdentifier() != "inlined_at"),
51505ffd83dbSDimitry Andric             "expected 'inlined_at' identifier in '.cv_inline_site_id' "
51515ffd83dbSDimitry Andric             "directive") )
51525ffd83dbSDimitry Andric     return true;
51535ffd83dbSDimitry Andric   Lex();
51545ffd83dbSDimitry Andric 
51555ffd83dbSDimitry Andric   // IAFile IALine
51565ffd83dbSDimitry Andric   if (parseCVFileId(IAFile, ".cv_inline_site_id") ||
51575ffd83dbSDimitry Andric       parseIntToken(IALine, "expected line number after 'inlined_at'"))
51585ffd83dbSDimitry Andric     return true;
51595ffd83dbSDimitry Andric 
51605ffd83dbSDimitry Andric   // [IACol]
51615ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
51625ffd83dbSDimitry Andric     IACol = getTok().getIntVal();
51635ffd83dbSDimitry Andric     Lex();
51645ffd83dbSDimitry Andric   }
51655ffd83dbSDimitry Andric 
516681ad6265SDimitry Andric   if (parseEOL())
51675ffd83dbSDimitry Andric     return true;
51685ffd83dbSDimitry Andric 
516981ad6265SDimitry Andric   if (!getStreamer().emitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
51705ffd83dbSDimitry Andric                                                  IALine, IACol, FunctionIdLoc))
51715ffd83dbSDimitry Andric     return Error(FunctionIdLoc, "function id already allocated");
51725ffd83dbSDimitry Andric 
51735ffd83dbSDimitry Andric   return false;
51745ffd83dbSDimitry Andric }
51755ffd83dbSDimitry Andric 
51765ffd83dbSDimitry Andric /// parseDirectiveCVLoc
51775ffd83dbSDimitry Andric /// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
51785ffd83dbSDimitry Andric ///                                [is_stmt VALUE]
51795ffd83dbSDimitry Andric /// The first number is a file number, must have been previously assigned with
51805ffd83dbSDimitry Andric /// a .file directive, the second number is the line number and optionally the
51815ffd83dbSDimitry Andric /// third number is a column position (zero if not specified).  The remaining
51825ffd83dbSDimitry Andric /// optional items are .loc sub-directives.
51835ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVLoc() {
51845ffd83dbSDimitry Andric   SMLoc DirectiveLoc = getTok().getLoc();
51855ffd83dbSDimitry Andric   int64_t FunctionId, FileNumber;
51865ffd83dbSDimitry Andric   if (parseCVFunctionId(FunctionId, ".cv_loc") ||
51875ffd83dbSDimitry Andric       parseCVFileId(FileNumber, ".cv_loc"))
51885ffd83dbSDimitry Andric     return true;
51895ffd83dbSDimitry Andric 
51905ffd83dbSDimitry Andric   int64_t LineNumber = 0;
51915ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
51925ffd83dbSDimitry Andric     LineNumber = getTok().getIntVal();
51935ffd83dbSDimitry Andric     if (LineNumber < 0)
51945ffd83dbSDimitry Andric       return TokError("line number less than zero in '.cv_loc' directive");
51955ffd83dbSDimitry Andric     Lex();
51965ffd83dbSDimitry Andric   }
51975ffd83dbSDimitry Andric 
51985ffd83dbSDimitry Andric   int64_t ColumnPos = 0;
51995ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
52005ffd83dbSDimitry Andric     ColumnPos = getTok().getIntVal();
52015ffd83dbSDimitry Andric     if (ColumnPos < 0)
52025ffd83dbSDimitry Andric       return TokError("column position less than zero in '.cv_loc' directive");
52035ffd83dbSDimitry Andric     Lex();
52045ffd83dbSDimitry Andric   }
52055ffd83dbSDimitry Andric 
52065ffd83dbSDimitry Andric   bool PrologueEnd = false;
52075ffd83dbSDimitry Andric   uint64_t IsStmt = 0;
52085ffd83dbSDimitry Andric 
52095ffd83dbSDimitry Andric   auto parseOp = [&]() -> bool {
52105ffd83dbSDimitry Andric     StringRef Name;
52115ffd83dbSDimitry Andric     SMLoc Loc = getTok().getLoc();
52125ffd83dbSDimitry Andric     if (parseIdentifier(Name))
52135ffd83dbSDimitry Andric       return TokError("unexpected token in '.cv_loc' directive");
52145ffd83dbSDimitry Andric     if (Name == "prologue_end")
52155ffd83dbSDimitry Andric       PrologueEnd = true;
52165ffd83dbSDimitry Andric     else if (Name == "is_stmt") {
52175ffd83dbSDimitry Andric       Loc = getTok().getLoc();
52185ffd83dbSDimitry Andric       const MCExpr *Value;
52195ffd83dbSDimitry Andric       if (parseExpression(Value))
52205ffd83dbSDimitry Andric         return true;
52215ffd83dbSDimitry Andric       // The expression must be the constant 0 or 1.
52225ffd83dbSDimitry Andric       IsStmt = ~0ULL;
52235ffd83dbSDimitry Andric       if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
52245ffd83dbSDimitry Andric         IsStmt = MCE->getValue();
52255ffd83dbSDimitry Andric 
52265ffd83dbSDimitry Andric       if (IsStmt > 1)
52275ffd83dbSDimitry Andric         return Error(Loc, "is_stmt value not 0 or 1");
52285ffd83dbSDimitry Andric     } else {
52295ffd83dbSDimitry Andric       return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
52305ffd83dbSDimitry Andric     }
52315ffd83dbSDimitry Andric     return false;
52325ffd83dbSDimitry Andric   };
52335ffd83dbSDimitry Andric 
52345ffd83dbSDimitry Andric   if (parseMany(parseOp, false /*hasComma*/))
52355ffd83dbSDimitry Andric     return true;
52365ffd83dbSDimitry Andric 
52375ffd83dbSDimitry Andric   getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,
52385ffd83dbSDimitry Andric                                    ColumnPos, PrologueEnd, IsStmt, StringRef(),
52395ffd83dbSDimitry Andric                                    DirectiveLoc);
52405ffd83dbSDimitry Andric   return false;
52415ffd83dbSDimitry Andric }
52425ffd83dbSDimitry Andric 
52435ffd83dbSDimitry Andric /// parseDirectiveCVLinetable
52445ffd83dbSDimitry Andric /// ::= .cv_linetable FunctionId, FnStart, FnEnd
52455ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVLinetable() {
52465ffd83dbSDimitry Andric   int64_t FunctionId;
52475ffd83dbSDimitry Andric   StringRef FnStartName, FnEndName;
52485ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
52495ffd83dbSDimitry Andric   if (parseCVFunctionId(FunctionId, ".cv_linetable") ||
52505ffd83dbSDimitry Andric       parseToken(AsmToken::Comma,
52515ffd83dbSDimitry Andric                  "unexpected token in '.cv_linetable' directive") ||
52525ffd83dbSDimitry Andric       parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
52535ffd83dbSDimitry Andric                                   "expected identifier in directive") ||
52545ffd83dbSDimitry Andric       parseToken(AsmToken::Comma,
52555ffd83dbSDimitry Andric                  "unexpected token in '.cv_linetable' directive") ||
52565ffd83dbSDimitry Andric       parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
52575ffd83dbSDimitry Andric                                   "expected identifier in directive"))
52585ffd83dbSDimitry Andric     return true;
52595ffd83dbSDimitry Andric 
52605ffd83dbSDimitry Andric   MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
52615ffd83dbSDimitry Andric   MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
52625ffd83dbSDimitry Andric 
52635ffd83dbSDimitry Andric   getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
52645ffd83dbSDimitry Andric   return false;
52655ffd83dbSDimitry Andric }
52665ffd83dbSDimitry Andric 
52675ffd83dbSDimitry Andric /// parseDirectiveCVInlineLinetable
52685ffd83dbSDimitry Andric /// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
52695ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVInlineLinetable() {
52705ffd83dbSDimitry Andric   int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
52715ffd83dbSDimitry Andric   StringRef FnStartName, FnEndName;
52725ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
52735ffd83dbSDimitry Andric   if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||
52745ffd83dbSDimitry Andric       parseTokenLoc(Loc) ||
52755ffd83dbSDimitry Andric       parseIntToken(
52765ffd83dbSDimitry Andric           SourceFileId,
52775ffd83dbSDimitry Andric           "expected SourceField in '.cv_inline_linetable' directive") ||
52785ffd83dbSDimitry Andric       check(SourceFileId <= 0, Loc,
52795ffd83dbSDimitry Andric             "File id less than zero in '.cv_inline_linetable' directive") ||
52805ffd83dbSDimitry Andric       parseTokenLoc(Loc) ||
52815ffd83dbSDimitry Andric       parseIntToken(
52825ffd83dbSDimitry Andric           SourceLineNum,
52835ffd83dbSDimitry Andric           "expected SourceLineNum in '.cv_inline_linetable' directive") ||
52845ffd83dbSDimitry Andric       check(SourceLineNum < 0, Loc,
52855ffd83dbSDimitry Andric             "Line number less than zero in '.cv_inline_linetable' directive") ||
52865ffd83dbSDimitry Andric       parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
52875ffd83dbSDimitry Andric                                   "expected identifier in directive") ||
52885ffd83dbSDimitry Andric       parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
52895ffd83dbSDimitry Andric                                   "expected identifier in directive"))
52905ffd83dbSDimitry Andric     return true;
52915ffd83dbSDimitry Andric 
529281ad6265SDimitry Andric   if (parseEOL())
52935ffd83dbSDimitry Andric     return true;
52945ffd83dbSDimitry Andric 
52955ffd83dbSDimitry Andric   MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
52965ffd83dbSDimitry Andric   MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
52975ffd83dbSDimitry Andric   getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
52985ffd83dbSDimitry Andric                                                SourceLineNum, FnStartSym,
52995ffd83dbSDimitry Andric                                                FnEndSym);
53005ffd83dbSDimitry Andric   return false;
53015ffd83dbSDimitry Andric }
53025ffd83dbSDimitry Andric 
53035ffd83dbSDimitry Andric void MasmParser::initializeCVDefRangeTypeMap() {
53045ffd83dbSDimitry Andric   CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
53055ffd83dbSDimitry Andric   CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
53065ffd83dbSDimitry Andric   CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
53075ffd83dbSDimitry Andric   CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
53085ffd83dbSDimitry Andric }
53095ffd83dbSDimitry Andric 
53105ffd83dbSDimitry Andric /// parseDirectiveCVDefRange
53115ffd83dbSDimitry Andric /// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
53125ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVDefRange() {
53135ffd83dbSDimitry Andric   SMLoc Loc;
53145ffd83dbSDimitry Andric   std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
53155ffd83dbSDimitry Andric   while (getLexer().is(AsmToken::Identifier)) {
53165ffd83dbSDimitry Andric     Loc = getLexer().getLoc();
53175ffd83dbSDimitry Andric     StringRef GapStartName;
53185ffd83dbSDimitry Andric     if (parseIdentifier(GapStartName))
53195ffd83dbSDimitry Andric       return Error(Loc, "expected identifier in directive");
53205ffd83dbSDimitry Andric     MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
53215ffd83dbSDimitry Andric 
53225ffd83dbSDimitry Andric     Loc = getLexer().getLoc();
53235ffd83dbSDimitry Andric     StringRef GapEndName;
53245ffd83dbSDimitry Andric     if (parseIdentifier(GapEndName))
53255ffd83dbSDimitry Andric       return Error(Loc, "expected identifier in directive");
53265ffd83dbSDimitry Andric     MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
53275ffd83dbSDimitry Andric 
53285ffd83dbSDimitry Andric     Ranges.push_back({GapStartSym, GapEndSym});
53295ffd83dbSDimitry Andric   }
53305ffd83dbSDimitry Andric 
53315ffd83dbSDimitry Andric   StringRef CVDefRangeTypeStr;
53325ffd83dbSDimitry Andric   if (parseToken(
53335ffd83dbSDimitry Andric           AsmToken::Comma,
53345ffd83dbSDimitry Andric           "expected comma before def_range type in .cv_def_range directive") ||
53355ffd83dbSDimitry Andric       parseIdentifier(CVDefRangeTypeStr))
53365ffd83dbSDimitry Andric     return Error(Loc, "expected def_range type in directive");
53375ffd83dbSDimitry Andric 
53385ffd83dbSDimitry Andric   StringMap<CVDefRangeType>::const_iterator CVTypeIt =
53395ffd83dbSDimitry Andric       CVDefRangeTypeMap.find(CVDefRangeTypeStr);
53405ffd83dbSDimitry Andric   CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
53415ffd83dbSDimitry Andric                                 ? CVDR_DEFRANGE
53425ffd83dbSDimitry Andric                                 : CVTypeIt->getValue();
53435ffd83dbSDimitry Andric   switch (CVDRType) {
53445ffd83dbSDimitry Andric   case CVDR_DEFRANGE_REGISTER: {
53455ffd83dbSDimitry Andric     int64_t DRRegister;
53465ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma, "expected comma before register number in "
53475ffd83dbSDimitry Andric                                     ".cv_def_range directive") ||
53485ffd83dbSDimitry Andric         parseAbsoluteExpression(DRRegister))
53495ffd83dbSDimitry Andric       return Error(Loc, "expected register number");
53505ffd83dbSDimitry Andric 
53515ffd83dbSDimitry Andric     codeview::DefRangeRegisterHeader DRHdr;
53525ffd83dbSDimitry Andric     DRHdr.Register = DRRegister;
53535ffd83dbSDimitry Andric     DRHdr.MayHaveNoName = 0;
53545ffd83dbSDimitry Andric     getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
53555ffd83dbSDimitry Andric     break;
53565ffd83dbSDimitry Andric   }
53575ffd83dbSDimitry Andric   case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
53585ffd83dbSDimitry Andric     int64_t DROffset;
53595ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma,
53605ffd83dbSDimitry Andric                    "expected comma before offset in .cv_def_range directive") ||
53615ffd83dbSDimitry Andric         parseAbsoluteExpression(DROffset))
53625ffd83dbSDimitry Andric       return Error(Loc, "expected offset value");
53635ffd83dbSDimitry Andric 
53645ffd83dbSDimitry Andric     codeview::DefRangeFramePointerRelHeader DRHdr;
53655ffd83dbSDimitry Andric     DRHdr.Offset = DROffset;
53665ffd83dbSDimitry Andric     getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
53675ffd83dbSDimitry Andric     break;
53685ffd83dbSDimitry Andric   }
53695ffd83dbSDimitry Andric   case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
53705ffd83dbSDimitry Andric     int64_t DRRegister;
53715ffd83dbSDimitry Andric     int64_t DROffsetInParent;
53725ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma, "expected comma before register number in "
53735ffd83dbSDimitry Andric                                     ".cv_def_range directive") ||
53745ffd83dbSDimitry Andric         parseAbsoluteExpression(DRRegister))
53755ffd83dbSDimitry Andric       return Error(Loc, "expected register number");
53765ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma,
53775ffd83dbSDimitry Andric                    "expected comma before offset in .cv_def_range directive") ||
53785ffd83dbSDimitry Andric         parseAbsoluteExpression(DROffsetInParent))
53795ffd83dbSDimitry Andric       return Error(Loc, "expected offset value");
53805ffd83dbSDimitry Andric 
53815ffd83dbSDimitry Andric     codeview::DefRangeSubfieldRegisterHeader DRHdr;
53825ffd83dbSDimitry Andric     DRHdr.Register = DRRegister;
53835ffd83dbSDimitry Andric     DRHdr.MayHaveNoName = 0;
53845ffd83dbSDimitry Andric     DRHdr.OffsetInParent = DROffsetInParent;
53855ffd83dbSDimitry Andric     getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
53865ffd83dbSDimitry Andric     break;
53875ffd83dbSDimitry Andric   }
53885ffd83dbSDimitry Andric   case CVDR_DEFRANGE_REGISTER_REL: {
53895ffd83dbSDimitry Andric     int64_t DRRegister;
53905ffd83dbSDimitry Andric     int64_t DRFlags;
53915ffd83dbSDimitry Andric     int64_t DRBasePointerOffset;
53925ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma, "expected comma before register number in "
53935ffd83dbSDimitry Andric                                     ".cv_def_range directive") ||
53945ffd83dbSDimitry Andric         parseAbsoluteExpression(DRRegister))
53955ffd83dbSDimitry Andric       return Error(Loc, "expected register value");
53965ffd83dbSDimitry Andric     if (parseToken(
53975ffd83dbSDimitry Andric             AsmToken::Comma,
53985ffd83dbSDimitry Andric             "expected comma before flag value in .cv_def_range directive") ||
53995ffd83dbSDimitry Andric         parseAbsoluteExpression(DRFlags))
54005ffd83dbSDimitry Andric       return Error(Loc, "expected flag value");
54015ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
54025ffd83dbSDimitry Andric                                     "in .cv_def_range directive") ||
54035ffd83dbSDimitry Andric         parseAbsoluteExpression(DRBasePointerOffset))
54045ffd83dbSDimitry Andric       return Error(Loc, "expected base pointer offset value");
54055ffd83dbSDimitry Andric 
54065ffd83dbSDimitry Andric     codeview::DefRangeRegisterRelHeader DRHdr;
54075ffd83dbSDimitry Andric     DRHdr.Register = DRRegister;
54085ffd83dbSDimitry Andric     DRHdr.Flags = DRFlags;
54095ffd83dbSDimitry Andric     DRHdr.BasePointerOffset = DRBasePointerOffset;
54105ffd83dbSDimitry Andric     getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
54115ffd83dbSDimitry Andric     break;
54125ffd83dbSDimitry Andric   }
54135ffd83dbSDimitry Andric   default:
54145ffd83dbSDimitry Andric     return Error(Loc, "unexpected def_range type in .cv_def_range directive");
54155ffd83dbSDimitry Andric   }
54165ffd83dbSDimitry Andric   return true;
54175ffd83dbSDimitry Andric }
54185ffd83dbSDimitry Andric 
54195ffd83dbSDimitry Andric /// parseDirectiveCVString
54205ffd83dbSDimitry Andric /// ::= .cv_stringtable "string"
54215ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVString() {
54225ffd83dbSDimitry Andric   std::string Data;
54235ffd83dbSDimitry Andric   if (checkForValidSection() || parseEscapedString(Data))
54245ffd83dbSDimitry Andric     return addErrorSuffix(" in '.cv_string' directive");
54255ffd83dbSDimitry Andric 
54265ffd83dbSDimitry Andric   // Put the string in the table and emit the offset.
54275ffd83dbSDimitry Andric   std::pair<StringRef, unsigned> Insertion =
54285ffd83dbSDimitry Andric       getCVContext().addToStringTable(Data);
54295ffd83dbSDimitry Andric   getStreamer().emitIntValue(Insertion.second, 4);
54305ffd83dbSDimitry Andric   return false;
54315ffd83dbSDimitry Andric }
54325ffd83dbSDimitry Andric 
54335ffd83dbSDimitry Andric /// parseDirectiveCVStringTable
54345ffd83dbSDimitry Andric /// ::= .cv_stringtable
54355ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVStringTable() {
54365ffd83dbSDimitry Andric   getStreamer().emitCVStringTableDirective();
54375ffd83dbSDimitry Andric   return false;
54385ffd83dbSDimitry Andric }
54395ffd83dbSDimitry Andric 
54405ffd83dbSDimitry Andric /// parseDirectiveCVFileChecksums
54415ffd83dbSDimitry Andric /// ::= .cv_filechecksums
54425ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFileChecksums() {
54435ffd83dbSDimitry Andric   getStreamer().emitCVFileChecksumsDirective();
54445ffd83dbSDimitry Andric   return false;
54455ffd83dbSDimitry Andric }
54465ffd83dbSDimitry Andric 
54475ffd83dbSDimitry Andric /// parseDirectiveCVFileChecksumOffset
54485ffd83dbSDimitry Andric /// ::= .cv_filechecksumoffset fileno
54495ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFileChecksumOffset() {
54505ffd83dbSDimitry Andric   int64_t FileNo;
54515ffd83dbSDimitry Andric   if (parseIntToken(FileNo, "expected identifier in directive"))
54525ffd83dbSDimitry Andric     return true;
545381ad6265SDimitry Andric   if (parseEOL())
54545ffd83dbSDimitry Andric     return true;
54555ffd83dbSDimitry Andric   getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
54565ffd83dbSDimitry Andric   return false;
54575ffd83dbSDimitry Andric }
54585ffd83dbSDimitry Andric 
54595ffd83dbSDimitry Andric /// parseDirectiveCVFPOData
54605ffd83dbSDimitry Andric /// ::= .cv_fpo_data procsym
54615ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFPOData() {
54625ffd83dbSDimitry Andric   SMLoc DirLoc = getLexer().getLoc();
54635ffd83dbSDimitry Andric   StringRef ProcName;
54645ffd83dbSDimitry Andric   if (parseIdentifier(ProcName))
54655ffd83dbSDimitry Andric     return TokError("expected symbol name");
54665ffd83dbSDimitry Andric   if (parseEOL("unexpected tokens"))
54675ffd83dbSDimitry Andric     return addErrorSuffix(" in '.cv_fpo_data' directive");
54685ffd83dbSDimitry Andric   MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
546981ad6265SDimitry Andric   getStreamer().emitCVFPOData(ProcSym, DirLoc);
54705ffd83dbSDimitry Andric   return false;
54715ffd83dbSDimitry Andric }
54725ffd83dbSDimitry Andric 
54735ffd83dbSDimitry Andric /// parseDirectiveCFISections
54745ffd83dbSDimitry Andric /// ::= .cfi_sections section [, section]
54755ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFISections() {
54765ffd83dbSDimitry Andric   StringRef Name;
54775ffd83dbSDimitry Andric   bool EH = false;
54785ffd83dbSDimitry Andric   bool Debug = false;
54795ffd83dbSDimitry Andric 
54805ffd83dbSDimitry Andric   if (parseIdentifier(Name))
54815ffd83dbSDimitry Andric     return TokError("Expected an identifier");
54825ffd83dbSDimitry Andric 
54835ffd83dbSDimitry Andric   if (Name == ".eh_frame")
54845ffd83dbSDimitry Andric     EH = true;
54855ffd83dbSDimitry Andric   else if (Name == ".debug_frame")
54865ffd83dbSDimitry Andric     Debug = true;
54875ffd83dbSDimitry Andric 
54885ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Comma)) {
54895ffd83dbSDimitry Andric     Lex();
54905ffd83dbSDimitry Andric 
54915ffd83dbSDimitry Andric     if (parseIdentifier(Name))
54925ffd83dbSDimitry Andric       return TokError("Expected an identifier");
54935ffd83dbSDimitry Andric 
54945ffd83dbSDimitry Andric     if (Name == ".eh_frame")
54955ffd83dbSDimitry Andric       EH = true;
54965ffd83dbSDimitry Andric     else if (Name == ".debug_frame")
54975ffd83dbSDimitry Andric       Debug = true;
54985ffd83dbSDimitry Andric   }
54995ffd83dbSDimitry Andric 
55005ffd83dbSDimitry Andric   getStreamer().emitCFISections(EH, Debug);
55015ffd83dbSDimitry Andric   return false;
55025ffd83dbSDimitry Andric }
55035ffd83dbSDimitry Andric 
55045ffd83dbSDimitry Andric /// parseDirectiveCFIStartProc
55055ffd83dbSDimitry Andric /// ::= .cfi_startproc [simple]
55065ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIStartProc() {
55075ffd83dbSDimitry Andric   StringRef Simple;
55085ffd83dbSDimitry Andric   if (!parseOptionalToken(AsmToken::EndOfStatement)) {
55095ffd83dbSDimitry Andric     if (check(parseIdentifier(Simple) || Simple != "simple",
55105ffd83dbSDimitry Andric               "unexpected token") ||
55115ffd83dbSDimitry Andric         parseToken(AsmToken::EndOfStatement))
55125ffd83dbSDimitry Andric       return addErrorSuffix(" in '.cfi_startproc' directive");
55135ffd83dbSDimitry Andric   }
55145ffd83dbSDimitry Andric 
55155ffd83dbSDimitry Andric   // TODO(kristina): Deal with a corner case of incorrect diagnostic context
55165ffd83dbSDimitry Andric   // being produced if this directive is emitted as part of preprocessor macro
55175ffd83dbSDimitry Andric   // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
55185ffd83dbSDimitry Andric   // Tools like llvm-mc on the other hand are not affected by it, and report
55195ffd83dbSDimitry Andric   // correct context information.
55205ffd83dbSDimitry Andric   getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
55215ffd83dbSDimitry Andric   return false;
55225ffd83dbSDimitry Andric }
55235ffd83dbSDimitry Andric 
55245ffd83dbSDimitry Andric /// parseDirectiveCFIEndProc
55255ffd83dbSDimitry Andric /// ::= .cfi_endproc
55265ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIEndProc() {
55275ffd83dbSDimitry Andric   getStreamer().emitCFIEndProc();
55285ffd83dbSDimitry Andric   return false;
55295ffd83dbSDimitry Andric }
55305ffd83dbSDimitry Andric 
55315ffd83dbSDimitry Andric /// parse register name or number.
55325ffd83dbSDimitry Andric bool MasmParser::parseRegisterOrRegisterNumber(int64_t &Register,
55335ffd83dbSDimitry Andric                                                SMLoc DirectiveLoc) {
5534*bdd1243dSDimitry Andric   MCRegister RegNo;
55355ffd83dbSDimitry Andric 
55365ffd83dbSDimitry Andric   if (getLexer().isNot(AsmToken::Integer)) {
5537*bdd1243dSDimitry Andric     if (getTargetParser().parseRegister(RegNo, DirectiveLoc, DirectiveLoc))
55385ffd83dbSDimitry Andric       return true;
55395ffd83dbSDimitry Andric     Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
55405ffd83dbSDimitry Andric   } else
55415ffd83dbSDimitry Andric     return parseAbsoluteExpression(Register);
55425ffd83dbSDimitry Andric 
55435ffd83dbSDimitry Andric   return false;
55445ffd83dbSDimitry Andric }
55455ffd83dbSDimitry Andric 
55465ffd83dbSDimitry Andric /// parseDirectiveCFIDefCfa
55475ffd83dbSDimitry Andric /// ::= .cfi_def_cfa register,  offset
55485ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
55495ffd83dbSDimitry Andric   int64_t Register = 0, Offset = 0;
55505ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
55515ffd83dbSDimitry Andric       parseToken(AsmToken::Comma, "unexpected token in directive") ||
55525ffd83dbSDimitry Andric       parseAbsoluteExpression(Offset))
55535ffd83dbSDimitry Andric     return true;
55545ffd83dbSDimitry Andric 
55555ffd83dbSDimitry Andric   getStreamer().emitCFIDefCfa(Register, Offset);
55565ffd83dbSDimitry Andric   return false;
55575ffd83dbSDimitry Andric }
55585ffd83dbSDimitry Andric 
55595ffd83dbSDimitry Andric /// parseDirectiveCFIDefCfaOffset
55605ffd83dbSDimitry Andric /// ::= .cfi_def_cfa_offset offset
55615ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIDefCfaOffset() {
55625ffd83dbSDimitry Andric   int64_t Offset = 0;
55635ffd83dbSDimitry Andric   if (parseAbsoluteExpression(Offset))
55645ffd83dbSDimitry Andric     return true;
55655ffd83dbSDimitry Andric 
55665ffd83dbSDimitry Andric   getStreamer().emitCFIDefCfaOffset(Offset);
55675ffd83dbSDimitry Andric   return false;
55685ffd83dbSDimitry Andric }
55695ffd83dbSDimitry Andric 
55705ffd83dbSDimitry Andric /// parseDirectiveCFIRegister
55715ffd83dbSDimitry Andric /// ::= .cfi_register register, register
55725ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
55735ffd83dbSDimitry Andric   int64_t Register1 = 0, Register2 = 0;
55745ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) ||
55755ffd83dbSDimitry Andric       parseToken(AsmToken::Comma, "unexpected token in directive") ||
55765ffd83dbSDimitry Andric       parseRegisterOrRegisterNumber(Register2, DirectiveLoc))
55775ffd83dbSDimitry Andric     return true;
55785ffd83dbSDimitry Andric 
55795ffd83dbSDimitry Andric   getStreamer().emitCFIRegister(Register1, Register2);
55805ffd83dbSDimitry Andric   return false;
55815ffd83dbSDimitry Andric }
55825ffd83dbSDimitry Andric 
55835ffd83dbSDimitry Andric /// parseDirectiveCFIWindowSave
55845ffd83dbSDimitry Andric /// ::= .cfi_window_save
55855ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIWindowSave() {
55865ffd83dbSDimitry Andric   getStreamer().emitCFIWindowSave();
55875ffd83dbSDimitry Andric   return false;
55885ffd83dbSDimitry Andric }
55895ffd83dbSDimitry Andric 
55905ffd83dbSDimitry Andric /// parseDirectiveCFIAdjustCfaOffset
55915ffd83dbSDimitry Andric /// ::= .cfi_adjust_cfa_offset adjustment
55925ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIAdjustCfaOffset() {
55935ffd83dbSDimitry Andric   int64_t Adjustment = 0;
55945ffd83dbSDimitry Andric   if (parseAbsoluteExpression(Adjustment))
55955ffd83dbSDimitry Andric     return true;
55965ffd83dbSDimitry Andric 
55975ffd83dbSDimitry Andric   getStreamer().emitCFIAdjustCfaOffset(Adjustment);
55985ffd83dbSDimitry Andric   return false;
55995ffd83dbSDimitry Andric }
56005ffd83dbSDimitry Andric 
56015ffd83dbSDimitry Andric /// parseDirectiveCFIDefCfaRegister
56025ffd83dbSDimitry Andric /// ::= .cfi_def_cfa_register register
56035ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
56045ffd83dbSDimitry Andric   int64_t Register = 0;
56055ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
56065ffd83dbSDimitry Andric     return true;
56075ffd83dbSDimitry Andric 
56085ffd83dbSDimitry Andric   getStreamer().emitCFIDefCfaRegister(Register);
56095ffd83dbSDimitry Andric   return false;
56105ffd83dbSDimitry Andric }
56115ffd83dbSDimitry Andric 
56125ffd83dbSDimitry Andric /// parseDirectiveCFIOffset
56135ffd83dbSDimitry Andric /// ::= .cfi_offset register, offset
56145ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
56155ffd83dbSDimitry Andric   int64_t Register = 0;
56165ffd83dbSDimitry Andric   int64_t Offset = 0;
56175ffd83dbSDimitry Andric 
56185ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
56195ffd83dbSDimitry Andric       parseToken(AsmToken::Comma, "unexpected token in directive") ||
56205ffd83dbSDimitry Andric       parseAbsoluteExpression(Offset))
56215ffd83dbSDimitry Andric     return true;
56225ffd83dbSDimitry Andric 
56235ffd83dbSDimitry Andric   getStreamer().emitCFIOffset(Register, Offset);
56245ffd83dbSDimitry Andric   return false;
56255ffd83dbSDimitry Andric }
56265ffd83dbSDimitry Andric 
56275ffd83dbSDimitry Andric /// parseDirectiveCFIRelOffset
56285ffd83dbSDimitry Andric /// ::= .cfi_rel_offset register, offset
56295ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
56305ffd83dbSDimitry Andric   int64_t Register = 0, Offset = 0;
56315ffd83dbSDimitry Andric 
56325ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
56335ffd83dbSDimitry Andric       parseToken(AsmToken::Comma, "unexpected token in directive") ||
56345ffd83dbSDimitry Andric       parseAbsoluteExpression(Offset))
56355ffd83dbSDimitry Andric     return true;
56365ffd83dbSDimitry Andric 
56375ffd83dbSDimitry Andric   getStreamer().emitCFIRelOffset(Register, Offset);
56385ffd83dbSDimitry Andric   return false;
56395ffd83dbSDimitry Andric }
56405ffd83dbSDimitry Andric 
56415ffd83dbSDimitry Andric static bool isValidEncoding(int64_t Encoding) {
56425ffd83dbSDimitry Andric   if (Encoding & ~0xff)
56435ffd83dbSDimitry Andric     return false;
56445ffd83dbSDimitry Andric 
56455ffd83dbSDimitry Andric   if (Encoding == dwarf::DW_EH_PE_omit)
56465ffd83dbSDimitry Andric     return true;
56475ffd83dbSDimitry Andric 
56485ffd83dbSDimitry Andric   const unsigned Format = Encoding & 0xf;
56495ffd83dbSDimitry Andric   if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
56505ffd83dbSDimitry Andric       Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
56515ffd83dbSDimitry Andric       Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
56525ffd83dbSDimitry Andric       Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
56535ffd83dbSDimitry Andric     return false;
56545ffd83dbSDimitry Andric 
56555ffd83dbSDimitry Andric   const unsigned Application = Encoding & 0x70;
56565ffd83dbSDimitry Andric   if (Application != dwarf::DW_EH_PE_absptr &&
56575ffd83dbSDimitry Andric       Application != dwarf::DW_EH_PE_pcrel)
56585ffd83dbSDimitry Andric     return false;
56595ffd83dbSDimitry Andric 
56605ffd83dbSDimitry Andric   return true;
56615ffd83dbSDimitry Andric }
56625ffd83dbSDimitry Andric 
56635ffd83dbSDimitry Andric /// parseDirectiveCFIPersonalityOrLsda
56645ffd83dbSDimitry Andric /// IsPersonality true for cfi_personality, false for cfi_lsda
56655ffd83dbSDimitry Andric /// ::= .cfi_personality encoding, [symbol_name]
56665ffd83dbSDimitry Andric /// ::= .cfi_lsda encoding, [symbol_name]
56675ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
56685ffd83dbSDimitry Andric   int64_t Encoding = 0;
56695ffd83dbSDimitry Andric   if (parseAbsoluteExpression(Encoding))
56705ffd83dbSDimitry Andric     return true;
56715ffd83dbSDimitry Andric   if (Encoding == dwarf::DW_EH_PE_omit)
56725ffd83dbSDimitry Andric     return false;
56735ffd83dbSDimitry Andric 
56745ffd83dbSDimitry Andric   StringRef Name;
56755ffd83dbSDimitry Andric   if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
56765ffd83dbSDimitry Andric       parseToken(AsmToken::Comma, "unexpected token in directive") ||
56775ffd83dbSDimitry Andric       check(parseIdentifier(Name), "expected identifier in directive"))
56785ffd83dbSDimitry Andric     return true;
56795ffd83dbSDimitry Andric 
56805ffd83dbSDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
56815ffd83dbSDimitry Andric 
56825ffd83dbSDimitry Andric   if (IsPersonality)
56835ffd83dbSDimitry Andric     getStreamer().emitCFIPersonality(Sym, Encoding);
56845ffd83dbSDimitry Andric   else
56855ffd83dbSDimitry Andric     getStreamer().emitCFILsda(Sym, Encoding);
56865ffd83dbSDimitry Andric   return false;
56875ffd83dbSDimitry Andric }
56885ffd83dbSDimitry Andric 
56895ffd83dbSDimitry Andric /// parseDirectiveCFIRememberState
56905ffd83dbSDimitry Andric /// ::= .cfi_remember_state
56915ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIRememberState() {
56925ffd83dbSDimitry Andric   getStreamer().emitCFIRememberState();
56935ffd83dbSDimitry Andric   return false;
56945ffd83dbSDimitry Andric }
56955ffd83dbSDimitry Andric 
56965ffd83dbSDimitry Andric /// parseDirectiveCFIRestoreState
56975ffd83dbSDimitry Andric /// ::= .cfi_remember_state
56985ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIRestoreState() {
56995ffd83dbSDimitry Andric   getStreamer().emitCFIRestoreState();
57005ffd83dbSDimitry Andric   return false;
57015ffd83dbSDimitry Andric }
57025ffd83dbSDimitry Andric 
57035ffd83dbSDimitry Andric /// parseDirectiveCFISameValue
57045ffd83dbSDimitry Andric /// ::= .cfi_same_value register
57055ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
57065ffd83dbSDimitry Andric   int64_t Register = 0;
57075ffd83dbSDimitry Andric 
57085ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
57095ffd83dbSDimitry Andric     return true;
57105ffd83dbSDimitry Andric 
57115ffd83dbSDimitry Andric   getStreamer().emitCFISameValue(Register);
57125ffd83dbSDimitry Andric   return false;
57135ffd83dbSDimitry Andric }
57145ffd83dbSDimitry Andric 
57155ffd83dbSDimitry Andric /// parseDirectiveCFIRestore
57165ffd83dbSDimitry Andric /// ::= .cfi_restore register
57175ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
57185ffd83dbSDimitry Andric   int64_t Register = 0;
57195ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
57205ffd83dbSDimitry Andric     return true;
57215ffd83dbSDimitry Andric 
57225ffd83dbSDimitry Andric   getStreamer().emitCFIRestore(Register);
57235ffd83dbSDimitry Andric   return false;
57245ffd83dbSDimitry Andric }
57255ffd83dbSDimitry Andric 
57265ffd83dbSDimitry Andric /// parseDirectiveCFIEscape
57275ffd83dbSDimitry Andric /// ::= .cfi_escape expression[,...]
57285ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIEscape() {
57295ffd83dbSDimitry Andric   std::string Values;
57305ffd83dbSDimitry Andric   int64_t CurrValue;
57315ffd83dbSDimitry Andric   if (parseAbsoluteExpression(CurrValue))
57325ffd83dbSDimitry Andric     return true;
57335ffd83dbSDimitry Andric 
57345ffd83dbSDimitry Andric   Values.push_back((uint8_t)CurrValue);
57355ffd83dbSDimitry Andric 
57365ffd83dbSDimitry Andric   while (getLexer().is(AsmToken::Comma)) {
57375ffd83dbSDimitry Andric     Lex();
57385ffd83dbSDimitry Andric 
57395ffd83dbSDimitry Andric     if (parseAbsoluteExpression(CurrValue))
57405ffd83dbSDimitry Andric       return true;
57415ffd83dbSDimitry Andric 
57425ffd83dbSDimitry Andric     Values.push_back((uint8_t)CurrValue);
57435ffd83dbSDimitry Andric   }
57445ffd83dbSDimitry Andric 
57455ffd83dbSDimitry Andric   getStreamer().emitCFIEscape(Values);
57465ffd83dbSDimitry Andric   return false;
57475ffd83dbSDimitry Andric }
57485ffd83dbSDimitry Andric 
57495ffd83dbSDimitry Andric /// parseDirectiveCFIReturnColumn
57505ffd83dbSDimitry Andric /// ::= .cfi_return_column register
57515ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
57525ffd83dbSDimitry Andric   int64_t Register = 0;
57535ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
57545ffd83dbSDimitry Andric     return true;
57555ffd83dbSDimitry Andric   getStreamer().emitCFIReturnColumn(Register);
57565ffd83dbSDimitry Andric   return false;
57575ffd83dbSDimitry Andric }
57585ffd83dbSDimitry Andric 
57595ffd83dbSDimitry Andric /// parseDirectiveCFISignalFrame
57605ffd83dbSDimitry Andric /// ::= .cfi_signal_frame
57615ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFISignalFrame() {
576281ad6265SDimitry Andric   if (parseEOL())
57635ffd83dbSDimitry Andric     return true;
57645ffd83dbSDimitry Andric 
57655ffd83dbSDimitry Andric   getStreamer().emitCFISignalFrame();
57665ffd83dbSDimitry Andric   return false;
57675ffd83dbSDimitry Andric }
57685ffd83dbSDimitry Andric 
57695ffd83dbSDimitry Andric /// parseDirectiveCFIUndefined
57705ffd83dbSDimitry Andric /// ::= .cfi_undefined register
57715ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
57725ffd83dbSDimitry Andric   int64_t Register = 0;
57735ffd83dbSDimitry Andric 
57745ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
57755ffd83dbSDimitry Andric     return true;
57765ffd83dbSDimitry Andric 
57775ffd83dbSDimitry Andric   getStreamer().emitCFIUndefined(Register);
57785ffd83dbSDimitry Andric   return false;
57795ffd83dbSDimitry Andric }
57805ffd83dbSDimitry Andric 
57815ffd83dbSDimitry Andric /// parseDirectiveMacro
5782e8d8bef9SDimitry Andric /// ::= name macro [parameters]
5783e8d8bef9SDimitry Andric ///     ["LOCAL" identifiers]
5784e8d8bef9SDimitry Andric ///   parameters ::= parameter [, parameter]*
5785e8d8bef9SDimitry Andric ///   parameter ::= name ":" qualifier
5786e8d8bef9SDimitry Andric ///   qualifier ::= "req" | "vararg" | "=" macro_argument
5787e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
57885ffd83dbSDimitry Andric   MCAsmMacroParameters Parameters;
57895ffd83dbSDimitry Andric   while (getLexer().isNot(AsmToken::EndOfStatement)) {
57905ffd83dbSDimitry Andric     if (!Parameters.empty() && Parameters.back().Vararg)
57915ffd83dbSDimitry Andric       return Error(Lexer.getLoc(),
57925ffd83dbSDimitry Andric                    "Vararg parameter '" + Parameters.back().Name +
5793e8d8bef9SDimitry Andric                        "' should be last in the list of parameters");
57945ffd83dbSDimitry Andric 
57955ffd83dbSDimitry Andric     MCAsmMacroParameter Parameter;
57965ffd83dbSDimitry Andric     if (parseIdentifier(Parameter.Name))
5797e8d8bef9SDimitry Andric       return TokError("expected identifier in 'macro' directive");
57985ffd83dbSDimitry Andric 
57995ffd83dbSDimitry Andric     // Emit an error if two (or more) named parameters share the same name.
58005ffd83dbSDimitry Andric     for (const MCAsmMacroParameter& CurrParam : Parameters)
5801fe6060f1SDimitry Andric       if (CurrParam.Name.equals_insensitive(Parameter.Name))
58025ffd83dbSDimitry Andric         return TokError("macro '" + Name + "' has multiple parameters"
58035ffd83dbSDimitry Andric                         " named '" + Parameter.Name + "'");
58045ffd83dbSDimitry Andric 
58055ffd83dbSDimitry Andric     if (Lexer.is(AsmToken::Colon)) {
58065ffd83dbSDimitry Andric       Lex();  // consume ':'
58075ffd83dbSDimitry Andric 
5808e8d8bef9SDimitry Andric       if (parseOptionalToken(AsmToken::Equal)) {
5809e8d8bef9SDimitry Andric         // Default value
5810e8d8bef9SDimitry Andric         SMLoc ParamLoc;
5811e8d8bef9SDimitry Andric 
5812e8d8bef9SDimitry Andric         ParamLoc = Lexer.getLoc();
5813e8d8bef9SDimitry Andric         if (parseMacroArgument(nullptr, Parameter.Value))
5814e8d8bef9SDimitry Andric           return true;
5815e8d8bef9SDimitry Andric       } else {
58165ffd83dbSDimitry Andric         SMLoc QualLoc;
58175ffd83dbSDimitry Andric         StringRef Qualifier;
58185ffd83dbSDimitry Andric 
58195ffd83dbSDimitry Andric         QualLoc = Lexer.getLoc();
58205ffd83dbSDimitry Andric         if (parseIdentifier(Qualifier))
58215ffd83dbSDimitry Andric           return Error(QualLoc, "missing parameter qualifier for "
5822e8d8bef9SDimitry Andric                                 "'" +
5823e8d8bef9SDimitry Andric                                     Parameter.Name + "' in macro '" + Name +
5824e8d8bef9SDimitry Andric                                     "'");
58255ffd83dbSDimitry Andric 
5826fe6060f1SDimitry Andric         if (Qualifier.equals_insensitive("req"))
58275ffd83dbSDimitry Andric           Parameter.Required = true;
5828fe6060f1SDimitry Andric         else if (Qualifier.equals_insensitive("vararg"))
58295ffd83dbSDimitry Andric           Parameter.Vararg = true;
58305ffd83dbSDimitry Andric         else
5831e8d8bef9SDimitry Andric           return Error(QualLoc,
5832e8d8bef9SDimitry Andric                        Qualifier + " is not a valid parameter qualifier for '" +
5833e8d8bef9SDimitry Andric                            Parameter.Name + "' in macro '" + Name + "'");
58345ffd83dbSDimitry Andric       }
58355ffd83dbSDimitry Andric     }
58365ffd83dbSDimitry Andric 
58375ffd83dbSDimitry Andric     Parameters.push_back(std::move(Parameter));
58385ffd83dbSDimitry Andric 
58395ffd83dbSDimitry Andric     if (getLexer().is(AsmToken::Comma))
58405ffd83dbSDimitry Andric       Lex();
58415ffd83dbSDimitry Andric   }
58425ffd83dbSDimitry Andric 
58435ffd83dbSDimitry Andric   // Eat just the end of statement.
58445ffd83dbSDimitry Andric   Lexer.Lex();
58455ffd83dbSDimitry Andric 
5846e8d8bef9SDimitry Andric   std::vector<std::string> Locals;
5847e8d8bef9SDimitry Andric   if (getTok().is(AsmToken::Identifier) &&
5848fe6060f1SDimitry Andric       getTok().getIdentifier().equals_insensitive("local")) {
5849e8d8bef9SDimitry Andric     Lex(); // Eat the LOCAL directive.
5850e8d8bef9SDimitry Andric 
5851e8d8bef9SDimitry Andric     StringRef ID;
5852e8d8bef9SDimitry Andric     while (true) {
5853e8d8bef9SDimitry Andric       if (parseIdentifier(ID))
5854e8d8bef9SDimitry Andric         return true;
5855e8d8bef9SDimitry Andric       Locals.push_back(ID.lower());
5856e8d8bef9SDimitry Andric 
5857e8d8bef9SDimitry Andric       // If we see a comma, continue (and allow line continuation).
5858e8d8bef9SDimitry Andric       if (!parseOptionalToken(AsmToken::Comma))
5859e8d8bef9SDimitry Andric         break;
5860e8d8bef9SDimitry Andric       parseOptionalToken(AsmToken::EndOfStatement);
5861e8d8bef9SDimitry Andric     }
5862e8d8bef9SDimitry Andric   }
5863e8d8bef9SDimitry Andric 
58645ffd83dbSDimitry Andric   // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors.
58655ffd83dbSDimitry Andric   AsmToken EndToken, StartToken = getTok();
58665ffd83dbSDimitry Andric   unsigned MacroDepth = 0;
5867e8d8bef9SDimitry Andric   bool IsMacroFunction = false;
58685ffd83dbSDimitry Andric   // Lex the macro definition.
58695ffd83dbSDimitry Andric   while (true) {
58705ffd83dbSDimitry Andric     // Ignore Lexing errors in macros.
58715ffd83dbSDimitry Andric     while (Lexer.is(AsmToken::Error)) {
58725ffd83dbSDimitry Andric       Lexer.Lex();
58735ffd83dbSDimitry Andric     }
58745ffd83dbSDimitry Andric 
58755ffd83dbSDimitry Andric     // Check whether we have reached the end of the file.
58765ffd83dbSDimitry Andric     if (getLexer().is(AsmToken::Eof))
5877e8d8bef9SDimitry Andric       return Error(NameLoc, "no matching 'endm' in definition");
58785ffd83dbSDimitry Andric 
5879e8d8bef9SDimitry Andric     // Otherwise, check whether we have reached the 'endm'... and determine if
5880e8d8bef9SDimitry Andric     // this is a macro function.
58815ffd83dbSDimitry Andric     if (getLexer().is(AsmToken::Identifier)) {
5882fe6060f1SDimitry Andric       if (getTok().getIdentifier().equals_insensitive("endm")) {
58835ffd83dbSDimitry Andric         if (MacroDepth == 0) { // Outermost macro.
58845ffd83dbSDimitry Andric           EndToken = getTok();
58855ffd83dbSDimitry Andric           Lexer.Lex();
58865ffd83dbSDimitry Andric           if (getLexer().isNot(AsmToken::EndOfStatement))
58875ffd83dbSDimitry Andric             return TokError("unexpected token in '" + EndToken.getIdentifier() +
58885ffd83dbSDimitry Andric                             "' directive");
58895ffd83dbSDimitry Andric           break;
58905ffd83dbSDimitry Andric         } else {
58915ffd83dbSDimitry Andric           // Otherwise we just found the end of an inner macro.
58925ffd83dbSDimitry Andric           --MacroDepth;
58935ffd83dbSDimitry Andric         }
5894fe6060f1SDimitry Andric       } else if (getTok().getIdentifier().equals_insensitive("exitm")) {
5895fe6060f1SDimitry Andric         if (MacroDepth == 0 && peekTok().isNot(AsmToken::EndOfStatement)) {
5896e8d8bef9SDimitry Andric           IsMacroFunction = true;
5897e8d8bef9SDimitry Andric         }
5898e8d8bef9SDimitry Andric       } else if (isMacroLikeDirective()) {
5899e8d8bef9SDimitry Andric         // We allow nested macros. Those aren't instantiated until the
5900e8d8bef9SDimitry Andric         // outermost macro is expanded so just ignore them for now.
59015ffd83dbSDimitry Andric         ++MacroDepth;
59025ffd83dbSDimitry Andric       }
59035ffd83dbSDimitry Andric     }
59045ffd83dbSDimitry Andric 
59055ffd83dbSDimitry Andric     // Otherwise, scan til the end of the statement.
59065ffd83dbSDimitry Andric     eatToEndOfStatement();
59075ffd83dbSDimitry Andric   }
59085ffd83dbSDimitry Andric 
5909e8d8bef9SDimitry Andric   if (getContext().lookupMacro(Name.lower())) {
5910e8d8bef9SDimitry Andric     return Error(NameLoc, "macro '" + Name + "' is already defined");
59115ffd83dbSDimitry Andric   }
59125ffd83dbSDimitry Andric 
59135ffd83dbSDimitry Andric   const char *BodyStart = StartToken.getLoc().getPointer();
59145ffd83dbSDimitry Andric   const char *BodyEnd = EndToken.getLoc().getPointer();
59155ffd83dbSDimitry Andric   StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5916e8d8bef9SDimitry Andric   MCAsmMacro Macro(Name, Body, std::move(Parameters), std::move(Locals),
5917e8d8bef9SDimitry Andric                    IsMacroFunction);
59185ffd83dbSDimitry Andric   DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
59195ffd83dbSDimitry Andric                   Macro.dump());
5920fe6060f1SDimitry Andric   getContext().defineMacro(Name.lower(), std::move(Macro));
59215ffd83dbSDimitry Andric   return false;
59225ffd83dbSDimitry Andric }
59235ffd83dbSDimitry Andric 
59245ffd83dbSDimitry Andric /// parseDirectiveExitMacro
5925e8d8bef9SDimitry Andric /// ::= "exitm" [textitem]
5926e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
5927e8d8bef9SDimitry Andric                                          StringRef Directive,
5928e8d8bef9SDimitry Andric                                          std::string &Value) {
5929e8d8bef9SDimitry Andric   SMLoc EndLoc = getTok().getLoc();
5930e8d8bef9SDimitry Andric   if (getTok().isNot(AsmToken::EndOfStatement) && parseTextItem(Value))
5931e8d8bef9SDimitry Andric     return Error(EndLoc,
5932e8d8bef9SDimitry Andric                  "unable to parse text item in '" + Directive + "' directive");
5933e8d8bef9SDimitry Andric   eatToEndOfStatement();
59345ffd83dbSDimitry Andric 
59355ffd83dbSDimitry Andric   if (!isInsideMacroInstantiation())
59365ffd83dbSDimitry Andric     return TokError("unexpected '" + Directive + "' in file, "
59375ffd83dbSDimitry Andric                                                  "no current macro definition");
59385ffd83dbSDimitry Andric 
59395ffd83dbSDimitry Andric   // Exit all conditionals that are active in the current macro.
59405ffd83dbSDimitry Andric   while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
59415ffd83dbSDimitry Andric     TheCondState = TheCondStack.back();
59425ffd83dbSDimitry Andric     TheCondStack.pop_back();
59435ffd83dbSDimitry Andric   }
59445ffd83dbSDimitry Andric 
59455ffd83dbSDimitry Andric   handleMacroExit();
59465ffd83dbSDimitry Andric   return false;
59475ffd83dbSDimitry Andric }
59485ffd83dbSDimitry Andric 
59495ffd83dbSDimitry Andric /// parseDirectiveEndMacro
5950e8d8bef9SDimitry Andric /// ::= endm
59515ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
59525ffd83dbSDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
59535ffd83dbSDimitry Andric     return TokError("unexpected token in '" + Directive + "' directive");
59545ffd83dbSDimitry Andric 
59555ffd83dbSDimitry Andric   // If we are inside a macro instantiation, terminate the current
59565ffd83dbSDimitry Andric   // instantiation.
59575ffd83dbSDimitry Andric   if (isInsideMacroInstantiation()) {
59585ffd83dbSDimitry Andric     handleMacroExit();
59595ffd83dbSDimitry Andric     return false;
59605ffd83dbSDimitry Andric   }
59615ffd83dbSDimitry Andric 
59625ffd83dbSDimitry Andric   // Otherwise, this .endmacro is a stray entry in the file; well formed
59635ffd83dbSDimitry Andric   // .endmacro directives are handled during the macro definition parsing.
59645ffd83dbSDimitry Andric   return TokError("unexpected '" + Directive + "' in file, "
59655ffd83dbSDimitry Andric                                                "no current macro definition");
59665ffd83dbSDimitry Andric }
59675ffd83dbSDimitry Andric 
59685ffd83dbSDimitry Andric /// parseDirectivePurgeMacro
5969e8d8bef9SDimitry Andric /// ::= purge identifier ( , identifier )*
59705ffd83dbSDimitry Andric bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
59715ffd83dbSDimitry Andric   StringRef Name;
5972e8d8bef9SDimitry Andric   while (true) {
5973e8d8bef9SDimitry Andric     SMLoc NameLoc;
5974e8d8bef9SDimitry Andric     if (parseTokenLoc(NameLoc) ||
5975e8d8bef9SDimitry Andric         check(parseIdentifier(Name), NameLoc,
5976e8d8bef9SDimitry Andric               "expected identifier in 'purge' directive"))
59775ffd83dbSDimitry Andric       return true;
59785ffd83dbSDimitry Andric 
59795ffd83dbSDimitry Andric     DEBUG_WITH_TYPE("asm-macros", dbgs()
59805ffd83dbSDimitry Andric                                       << "Un-defining macro: " << Name << "\n");
5981e8d8bef9SDimitry Andric     if (!getContext().lookupMacro(Name.lower()))
5982e8d8bef9SDimitry Andric       return Error(NameLoc, "macro '" + Name + "' is not defined");
5983e8d8bef9SDimitry Andric     getContext().undefineMacro(Name.lower());
5984e8d8bef9SDimitry Andric 
5985e8d8bef9SDimitry Andric     if (!parseOptionalToken(AsmToken::Comma))
5986e8d8bef9SDimitry Andric       break;
5987e8d8bef9SDimitry Andric     parseOptionalToken(AsmToken::EndOfStatement);
5988e8d8bef9SDimitry Andric   }
5989e8d8bef9SDimitry Andric 
59905ffd83dbSDimitry Andric   return false;
59915ffd83dbSDimitry Andric }
59925ffd83dbSDimitry Andric 
599381ad6265SDimitry Andric bool MasmParser::parseDirectiveExtern() {
599481ad6265SDimitry Andric   // .extern is the default - but we still need to take any provided type info.
599581ad6265SDimitry Andric   auto parseOp = [&]() -> bool {
599681ad6265SDimitry Andric     StringRef Name;
599781ad6265SDimitry Andric     SMLoc NameLoc = getTok().getLoc();
599881ad6265SDimitry Andric     if (parseIdentifier(Name))
599981ad6265SDimitry Andric       return Error(NameLoc, "expected name");
600081ad6265SDimitry Andric     if (parseToken(AsmToken::Colon))
600181ad6265SDimitry Andric       return true;
600281ad6265SDimitry Andric 
600381ad6265SDimitry Andric     StringRef TypeName;
600481ad6265SDimitry Andric     SMLoc TypeLoc = getTok().getLoc();
600581ad6265SDimitry Andric     if (parseIdentifier(TypeName))
600681ad6265SDimitry Andric       return Error(TypeLoc, "expected type");
600781ad6265SDimitry Andric     if (!TypeName.equals_insensitive("proc")) {
600881ad6265SDimitry Andric       AsmTypeInfo Type;
600981ad6265SDimitry Andric       if (lookUpType(TypeName, Type))
601081ad6265SDimitry Andric         return Error(TypeLoc, "unrecognized type");
601181ad6265SDimitry Andric       KnownType[Name.lower()] = Type;
601281ad6265SDimitry Andric     }
601381ad6265SDimitry Andric 
601481ad6265SDimitry Andric     MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
601581ad6265SDimitry Andric     Sym->setExternal(true);
601681ad6265SDimitry Andric     getStreamer().emitSymbolAttribute(Sym, MCSA_Extern);
601781ad6265SDimitry Andric 
601881ad6265SDimitry Andric     return false;
601981ad6265SDimitry Andric   };
602081ad6265SDimitry Andric 
602181ad6265SDimitry Andric   if (parseMany(parseOp))
602281ad6265SDimitry Andric     return addErrorSuffix(" in directive 'extern'");
602381ad6265SDimitry Andric   return false;
602481ad6265SDimitry Andric }
602581ad6265SDimitry 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 
609481ad6265SDimitry Andric   if (parseEOL())
60955ffd83dbSDimitry Andric     return true;
60965ffd83dbSDimitry Andric 
60975ffd83dbSDimitry Andric   // NOTE: a size of zero for a .comm should create a undefined symbol
60985ffd83dbSDimitry Andric   // but a size of .lcomm creates a bss symbol of size zero.
60995ffd83dbSDimitry Andric   if (Size < 0)
61005ffd83dbSDimitry Andric     return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
61015ffd83dbSDimitry Andric                           "be less than zero");
61025ffd83dbSDimitry Andric 
61035ffd83dbSDimitry Andric   // NOTE: The alignment in the directive is a power of 2 value, the assembler
61045ffd83dbSDimitry Andric   // may internally end up wanting an alignment in bytes.
61055ffd83dbSDimitry Andric   // FIXME: Diagnose overflow.
61065ffd83dbSDimitry Andric   if (Pow2Alignment < 0)
61075ffd83dbSDimitry Andric     return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
61085ffd83dbSDimitry Andric                                    "alignment, can't be less than zero");
61095ffd83dbSDimitry Andric 
61105ffd83dbSDimitry Andric   Sym->redefineIfPossible();
61115ffd83dbSDimitry Andric   if (!Sym->isUndefined())
61125ffd83dbSDimitry Andric     return Error(IDLoc, "invalid symbol redefinition");
61135ffd83dbSDimitry Andric 
61145ffd83dbSDimitry Andric   // Create the Symbol as a common or local common with Size and Pow2Alignment.
61155ffd83dbSDimitry Andric   if (IsLocal) {
6116*bdd1243dSDimitry Andric     getStreamer().emitLocalCommonSymbol(Sym, Size,
6117*bdd1243dSDimitry Andric                                         Align(1ULL << Pow2Alignment));
61185ffd83dbSDimitry Andric     return false;
61195ffd83dbSDimitry Andric   }
61205ffd83dbSDimitry Andric 
6121*bdd1243dSDimitry Andric   getStreamer().emitCommonSymbol(Sym, Size, Align(1ULL << 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));
614181ad6265SDimitry Andric   return parseEOL();
61425ffd83dbSDimitry Andric }
61435ffd83dbSDimitry Andric 
61445ffd83dbSDimitry Andric /// parseDirectiveInclude
61455ffd83dbSDimitry Andric ///  ::= include <filename>
61465ffd83dbSDimitry Andric ///    | include filename
61475ffd83dbSDimitry Andric bool MasmParser::parseDirectiveInclude() {
61485ffd83dbSDimitry Andric   // Allow the strings to have escaped octal character sequence.
61495ffd83dbSDimitry Andric   std::string Filename;
61505ffd83dbSDimitry Andric   SMLoc IncludeLoc = getTok().getLoc();
61515ffd83dbSDimitry Andric 
6152fe6060f1SDimitry Andric   if (parseAngleBracketString(Filename))
6153e8d8bef9SDimitry Andric     Filename = parseStringTo(AsmToken::EndOfStatement);
6154fe6060f1SDimitry Andric   if (check(Filename.empty(), "missing filename in 'include' directive") ||
61555ffd83dbSDimitry Andric       check(getTok().isNot(AsmToken::EndOfStatement),
61565ffd83dbSDimitry Andric             "unexpected token in 'include' directive") ||
61575ffd83dbSDimitry Andric       // Attempt to switch the lexer to the included file before consuming the
61585ffd83dbSDimitry Andric       // end of statement to avoid losing it when we switch.
61595ffd83dbSDimitry Andric       check(enterIncludeFile(Filename), IncludeLoc,
61605ffd83dbSDimitry Andric             "Could not find include file '" + Filename + "'"))
61615ffd83dbSDimitry Andric     return true;
61625ffd83dbSDimitry Andric 
61635ffd83dbSDimitry Andric   return false;
61645ffd83dbSDimitry Andric }
61655ffd83dbSDimitry Andric 
61665ffd83dbSDimitry Andric /// parseDirectiveIf
61675ffd83dbSDimitry Andric /// ::= .if{,eq,ge,gt,le,lt,ne} expression
61685ffd83dbSDimitry Andric bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
61695ffd83dbSDimitry Andric   TheCondStack.push_back(TheCondState);
61705ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::IfCond;
61715ffd83dbSDimitry Andric   if (TheCondState.Ignore) {
61725ffd83dbSDimitry Andric     eatToEndOfStatement();
61735ffd83dbSDimitry Andric   } else {
61745ffd83dbSDimitry Andric     int64_t ExprValue;
617581ad6265SDimitry Andric     if (parseAbsoluteExpression(ExprValue) || parseEOL())
61765ffd83dbSDimitry Andric       return true;
61775ffd83dbSDimitry Andric 
61785ffd83dbSDimitry Andric     switch (DirKind) {
61795ffd83dbSDimitry Andric     default:
61805ffd83dbSDimitry Andric       llvm_unreachable("unsupported directive");
61815ffd83dbSDimitry Andric     case DK_IF:
61825ffd83dbSDimitry Andric       break;
61835ffd83dbSDimitry Andric     case DK_IFE:
61845ffd83dbSDimitry Andric       ExprValue = ExprValue == 0;
61855ffd83dbSDimitry Andric       break;
61865ffd83dbSDimitry Andric     }
61875ffd83dbSDimitry Andric 
61885ffd83dbSDimitry Andric     TheCondState.CondMet = ExprValue;
61895ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
61905ffd83dbSDimitry Andric   }
61915ffd83dbSDimitry Andric 
61925ffd83dbSDimitry Andric   return false;
61935ffd83dbSDimitry Andric }
61945ffd83dbSDimitry Andric 
61955ffd83dbSDimitry Andric /// parseDirectiveIfb
6196e8d8bef9SDimitry Andric /// ::= .ifb textitem
61975ffd83dbSDimitry Andric bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
61985ffd83dbSDimitry Andric   TheCondStack.push_back(TheCondState);
61995ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::IfCond;
62005ffd83dbSDimitry Andric 
62015ffd83dbSDimitry Andric   if (TheCondState.Ignore) {
62025ffd83dbSDimitry Andric     eatToEndOfStatement();
62035ffd83dbSDimitry Andric   } else {
62045ffd83dbSDimitry Andric     std::string Str;
62055ffd83dbSDimitry Andric     if (parseTextItem(Str))
6206e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'ifb' directive");
62075ffd83dbSDimitry Andric 
620881ad6265SDimitry Andric     if (parseEOL())
62095ffd83dbSDimitry Andric       return true;
62105ffd83dbSDimitry Andric 
62115ffd83dbSDimitry Andric     TheCondState.CondMet = ExpectBlank == Str.empty();
62125ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
62135ffd83dbSDimitry Andric   }
62145ffd83dbSDimitry Andric 
62155ffd83dbSDimitry Andric   return false;
62165ffd83dbSDimitry Andric }
62175ffd83dbSDimitry Andric 
62185ffd83dbSDimitry Andric /// parseDirectiveIfidn
6219e8d8bef9SDimitry Andric ///   ::= ifidn textitem, textitem
6220e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
6221e8d8bef9SDimitry Andric                                      bool CaseInsensitive) {
62225ffd83dbSDimitry Andric   std::string String1, String2;
62235ffd83dbSDimitry Andric 
62245ffd83dbSDimitry Andric   if (parseTextItem(String1)) {
62255ffd83dbSDimitry Andric     if (ExpectEqual)
6226e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'ifidn' directive");
6227e8d8bef9SDimitry Andric     return TokError("expected text item parameter for 'ifdif' directive");
62285ffd83dbSDimitry Andric   }
62295ffd83dbSDimitry Andric 
62305ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::Comma)) {
62315ffd83dbSDimitry Andric     if (ExpectEqual)
62325ffd83dbSDimitry Andric       return TokError(
62335ffd83dbSDimitry Andric           "expected comma after first string for 'ifidn' directive");
62345ffd83dbSDimitry Andric     return TokError("expected comma after first string for 'ifdif' directive");
62355ffd83dbSDimitry Andric   }
62365ffd83dbSDimitry Andric   Lex();
62375ffd83dbSDimitry Andric 
62385ffd83dbSDimitry Andric   if (parseTextItem(String2)) {
62395ffd83dbSDimitry Andric     if (ExpectEqual)
6240e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'ifidn' directive");
6241e8d8bef9SDimitry Andric     return TokError("expected text item parameter for 'ifdif' directive");
62425ffd83dbSDimitry Andric   }
62435ffd83dbSDimitry Andric 
62445ffd83dbSDimitry Andric   TheCondStack.push_back(TheCondState);
62455ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::IfCond;
62465ffd83dbSDimitry Andric   if (CaseInsensitive)
62475ffd83dbSDimitry Andric     TheCondState.CondMet =
6248fe6060f1SDimitry Andric         ExpectEqual == (StringRef(String1).equals_insensitive(String2));
62495ffd83dbSDimitry Andric   else
62505ffd83dbSDimitry Andric     TheCondState.CondMet = ExpectEqual == (String1 == String2);
62515ffd83dbSDimitry Andric   TheCondState.Ignore = !TheCondState.CondMet;
62525ffd83dbSDimitry Andric 
62535ffd83dbSDimitry Andric   return false;
62545ffd83dbSDimitry Andric }
62555ffd83dbSDimitry Andric 
62565ffd83dbSDimitry Andric /// parseDirectiveIfdef
62575ffd83dbSDimitry Andric /// ::= ifdef symbol
62585ffd83dbSDimitry Andric ///   | ifdef variable
62595ffd83dbSDimitry Andric bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
62605ffd83dbSDimitry Andric   TheCondStack.push_back(TheCondState);
62615ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::IfCond;
62625ffd83dbSDimitry Andric 
62635ffd83dbSDimitry Andric   if (TheCondState.Ignore) {
62645ffd83dbSDimitry Andric     eatToEndOfStatement();
62655ffd83dbSDimitry Andric   } else {
62665ffd83dbSDimitry Andric     bool is_defined = false;
6267*bdd1243dSDimitry Andric     MCRegister Reg;
62685ffd83dbSDimitry Andric     SMLoc StartLoc, EndLoc;
6269*bdd1243dSDimitry Andric     is_defined = (getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc) ==
6270*bdd1243dSDimitry Andric                   MatchOperand_Success);
62715ffd83dbSDimitry Andric     if (!is_defined) {
62725ffd83dbSDimitry Andric       StringRef Name;
62735ffd83dbSDimitry Andric       if (check(parseIdentifier(Name), "expected identifier after 'ifdef'") ||
627481ad6265SDimitry Andric           parseEOL())
62755ffd83dbSDimitry Andric         return true;
62765ffd83dbSDimitry Andric 
6277fe6060f1SDimitry Andric       if (BuiltinSymbolMap.find(Name.lower()) != BuiltinSymbolMap.end()) {
6278fe6060f1SDimitry Andric         is_defined = true;
6279fe6060f1SDimitry Andric       } else if (Variables.find(Name.lower()) != Variables.end()) {
62805ffd83dbSDimitry Andric         is_defined = true;
62815ffd83dbSDimitry Andric       } else {
6282fe6060f1SDimitry Andric         MCSymbol *Sym = getContext().lookupSymbol(Name.lower());
62835ffd83dbSDimitry Andric         is_defined = (Sym && !Sym->isUndefined(false));
62845ffd83dbSDimitry Andric       }
62855ffd83dbSDimitry Andric     }
62865ffd83dbSDimitry Andric 
62875ffd83dbSDimitry Andric     TheCondState.CondMet = (is_defined == expect_defined);
62885ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
62895ffd83dbSDimitry Andric   }
62905ffd83dbSDimitry Andric 
62915ffd83dbSDimitry Andric   return false;
62925ffd83dbSDimitry Andric }
62935ffd83dbSDimitry Andric 
62945ffd83dbSDimitry Andric /// parseDirectiveElseIf
62955ffd83dbSDimitry Andric /// ::= elseif expression
62965ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
62975ffd83dbSDimitry Andric                                       DirectiveKind DirKind) {
62985ffd83dbSDimitry Andric   if (TheCondState.TheCond != AsmCond::IfCond &&
62995ffd83dbSDimitry Andric       TheCondState.TheCond != AsmCond::ElseIfCond)
63005ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
63015ffd83dbSDimitry Andric                                " .if or  an .elseif");
63025ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::ElseIfCond;
63035ffd83dbSDimitry Andric 
63045ffd83dbSDimitry Andric   bool LastIgnoreState = false;
63055ffd83dbSDimitry Andric   if (!TheCondStack.empty())
63065ffd83dbSDimitry Andric     LastIgnoreState = TheCondStack.back().Ignore;
63075ffd83dbSDimitry Andric   if (LastIgnoreState || TheCondState.CondMet) {
63085ffd83dbSDimitry Andric     TheCondState.Ignore = true;
63095ffd83dbSDimitry Andric     eatToEndOfStatement();
63105ffd83dbSDimitry Andric   } else {
63115ffd83dbSDimitry Andric     int64_t ExprValue;
63125ffd83dbSDimitry Andric     if (parseAbsoluteExpression(ExprValue))
63135ffd83dbSDimitry Andric       return true;
63145ffd83dbSDimitry Andric 
631581ad6265SDimitry Andric     if (parseEOL())
63165ffd83dbSDimitry Andric       return true;
63175ffd83dbSDimitry Andric 
63185ffd83dbSDimitry Andric     switch (DirKind) {
63195ffd83dbSDimitry Andric     default:
63205ffd83dbSDimitry Andric       llvm_unreachable("unsupported directive");
63215ffd83dbSDimitry Andric     case DK_ELSEIF:
63225ffd83dbSDimitry Andric       break;
63235ffd83dbSDimitry Andric     case DK_ELSEIFE:
63245ffd83dbSDimitry Andric       ExprValue = ExprValue == 0;
63255ffd83dbSDimitry Andric       break;
63265ffd83dbSDimitry Andric     }
63275ffd83dbSDimitry Andric 
63285ffd83dbSDimitry Andric     TheCondState.CondMet = ExprValue;
63295ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
63305ffd83dbSDimitry Andric   }
63315ffd83dbSDimitry Andric 
63325ffd83dbSDimitry Andric   return false;
63335ffd83dbSDimitry Andric }
63345ffd83dbSDimitry Andric 
63355ffd83dbSDimitry Andric /// parseDirectiveElseIfb
6336e8d8bef9SDimitry Andric /// ::= elseifb textitem
63375ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
63385ffd83dbSDimitry Andric   if (TheCondState.TheCond != AsmCond::IfCond &&
63395ffd83dbSDimitry Andric       TheCondState.TheCond != AsmCond::ElseIfCond)
63405ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
63415ffd83dbSDimitry Andric                                " if or an elseif");
63425ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::ElseIfCond;
63435ffd83dbSDimitry Andric 
63445ffd83dbSDimitry Andric   bool LastIgnoreState = false;
63455ffd83dbSDimitry Andric   if (!TheCondStack.empty())
63465ffd83dbSDimitry Andric     LastIgnoreState = TheCondStack.back().Ignore;
63475ffd83dbSDimitry Andric   if (LastIgnoreState || TheCondState.CondMet) {
63485ffd83dbSDimitry Andric     TheCondState.Ignore = true;
63495ffd83dbSDimitry Andric     eatToEndOfStatement();
63505ffd83dbSDimitry Andric   } else {
63515ffd83dbSDimitry Andric     std::string Str;
6352e8d8bef9SDimitry Andric     if (parseTextItem(Str)) {
6353e8d8bef9SDimitry Andric       if (ExpectBlank)
6354e8d8bef9SDimitry Andric         return TokError("expected text item parameter for 'elseifb' directive");
6355e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'elseifnb' directive");
6356e8d8bef9SDimitry Andric     }
63575ffd83dbSDimitry Andric 
635881ad6265SDimitry Andric     if (parseEOL())
63595ffd83dbSDimitry Andric       return true;
63605ffd83dbSDimitry Andric 
63615ffd83dbSDimitry Andric     TheCondState.CondMet = ExpectBlank == Str.empty();
63625ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
63635ffd83dbSDimitry Andric   }
63645ffd83dbSDimitry Andric 
63655ffd83dbSDimitry Andric   return false;
63665ffd83dbSDimitry Andric }
63675ffd83dbSDimitry Andric 
63685ffd83dbSDimitry Andric /// parseDirectiveElseIfdef
63695ffd83dbSDimitry Andric /// ::= elseifdef symbol
63705ffd83dbSDimitry Andric ///   | elseifdef variable
63715ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
63725ffd83dbSDimitry Andric                                          bool expect_defined) {
63735ffd83dbSDimitry Andric   if (TheCondState.TheCond != AsmCond::IfCond &&
63745ffd83dbSDimitry Andric       TheCondState.TheCond != AsmCond::ElseIfCond)
63755ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
63765ffd83dbSDimitry Andric                                " if or an elseif");
63775ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::ElseIfCond;
63785ffd83dbSDimitry Andric 
63795ffd83dbSDimitry Andric   bool LastIgnoreState = false;
63805ffd83dbSDimitry Andric   if (!TheCondStack.empty())
63815ffd83dbSDimitry Andric     LastIgnoreState = TheCondStack.back().Ignore;
63825ffd83dbSDimitry Andric   if (LastIgnoreState || TheCondState.CondMet) {
63835ffd83dbSDimitry Andric     TheCondState.Ignore = true;
63845ffd83dbSDimitry Andric     eatToEndOfStatement();
63855ffd83dbSDimitry Andric   } else {
63865ffd83dbSDimitry Andric     bool is_defined = false;
6387*bdd1243dSDimitry Andric     MCRegister Reg;
63885ffd83dbSDimitry Andric     SMLoc StartLoc, EndLoc;
6389*bdd1243dSDimitry Andric     is_defined = (getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc) ==
63905ffd83dbSDimitry Andric                   MatchOperand_Success);
63915ffd83dbSDimitry Andric     if (!is_defined) {
63925ffd83dbSDimitry Andric       StringRef Name;
63935ffd83dbSDimitry Andric       if (check(parseIdentifier(Name),
63945ffd83dbSDimitry Andric                 "expected identifier after 'elseifdef'") ||
639581ad6265SDimitry Andric           parseEOL())
63965ffd83dbSDimitry Andric         return true;
63975ffd83dbSDimitry Andric 
6398fe6060f1SDimitry Andric       if (BuiltinSymbolMap.find(Name.lower()) != BuiltinSymbolMap.end()) {
6399fe6060f1SDimitry Andric         is_defined = true;
6400fe6060f1SDimitry Andric       } else if (Variables.find(Name.lower()) != Variables.end()) {
64015ffd83dbSDimitry Andric         is_defined = true;
64025ffd83dbSDimitry Andric       } else {
64035ffd83dbSDimitry Andric         MCSymbol *Sym = getContext().lookupSymbol(Name);
64045ffd83dbSDimitry Andric         is_defined = (Sym && !Sym->isUndefined(false));
64055ffd83dbSDimitry Andric       }
64065ffd83dbSDimitry Andric     }
64075ffd83dbSDimitry Andric 
64085ffd83dbSDimitry Andric     TheCondState.CondMet = (is_defined == expect_defined);
64095ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
64105ffd83dbSDimitry Andric   }
64115ffd83dbSDimitry Andric 
64125ffd83dbSDimitry Andric   return false;
64135ffd83dbSDimitry Andric }
64145ffd83dbSDimitry Andric 
64155ffd83dbSDimitry Andric /// parseDirectiveElseIfidn
6416e8d8bef9SDimitry Andric /// ::= elseifidn textitem, textitem
64175ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
64185ffd83dbSDimitry Andric                                          bool CaseInsensitive) {
64195ffd83dbSDimitry Andric   if (TheCondState.TheCond != AsmCond::IfCond &&
64205ffd83dbSDimitry Andric       TheCondState.TheCond != AsmCond::ElseIfCond)
64215ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
64225ffd83dbSDimitry Andric                                " if or an elseif");
64235ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::ElseIfCond;
64245ffd83dbSDimitry Andric 
64255ffd83dbSDimitry Andric   bool LastIgnoreState = false;
64265ffd83dbSDimitry Andric   if (!TheCondStack.empty())
64275ffd83dbSDimitry Andric     LastIgnoreState = TheCondStack.back().Ignore;
64285ffd83dbSDimitry Andric   if (LastIgnoreState || TheCondState.CondMet) {
64295ffd83dbSDimitry Andric     TheCondState.Ignore = true;
64305ffd83dbSDimitry Andric     eatToEndOfStatement();
64315ffd83dbSDimitry Andric   } else {
64325ffd83dbSDimitry Andric     std::string String1, String2;
64335ffd83dbSDimitry Andric 
64345ffd83dbSDimitry Andric     if (parseTextItem(String1)) {
64355ffd83dbSDimitry Andric       if (ExpectEqual)
6436e8d8bef9SDimitry Andric         return TokError(
6437e8d8bef9SDimitry Andric             "expected text item parameter for 'elseifidn' directive");
6438e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'elseifdif' directive");
64395ffd83dbSDimitry Andric     }
64405ffd83dbSDimitry Andric 
64415ffd83dbSDimitry Andric     if (Lexer.isNot(AsmToken::Comma)) {
64425ffd83dbSDimitry Andric       if (ExpectEqual)
64435ffd83dbSDimitry Andric         return TokError(
64445ffd83dbSDimitry Andric             "expected comma after first string for 'elseifidn' directive");
64455ffd83dbSDimitry Andric       return TokError(
64465ffd83dbSDimitry Andric           "expected comma after first string for 'elseifdif' directive");
64475ffd83dbSDimitry Andric     }
64485ffd83dbSDimitry Andric     Lex();
64495ffd83dbSDimitry Andric 
64505ffd83dbSDimitry Andric     if (parseTextItem(String2)) {
64515ffd83dbSDimitry Andric       if (ExpectEqual)
6452e8d8bef9SDimitry Andric         return TokError(
6453e8d8bef9SDimitry Andric             "expected text item parameter for 'elseifidn' directive");
6454e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'elseifdif' directive");
64555ffd83dbSDimitry Andric     }
64565ffd83dbSDimitry Andric 
64575ffd83dbSDimitry Andric     if (CaseInsensitive)
64585ffd83dbSDimitry Andric       TheCondState.CondMet =
6459fe6060f1SDimitry Andric           ExpectEqual == (StringRef(String1).equals_insensitive(String2));
64605ffd83dbSDimitry Andric     else
64615ffd83dbSDimitry Andric       TheCondState.CondMet = ExpectEqual == (String1 == String2);
64625ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
64635ffd83dbSDimitry Andric   }
64645ffd83dbSDimitry Andric 
64655ffd83dbSDimitry Andric   return false;
64665ffd83dbSDimitry Andric }
64675ffd83dbSDimitry Andric 
64685ffd83dbSDimitry Andric /// parseDirectiveElse
64695ffd83dbSDimitry Andric /// ::= else
64705ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
647181ad6265SDimitry Andric   if (parseEOL())
64725ffd83dbSDimitry Andric     return true;
64735ffd83dbSDimitry Andric 
64745ffd83dbSDimitry Andric   if (TheCondState.TheCond != AsmCond::IfCond &&
64755ffd83dbSDimitry Andric       TheCondState.TheCond != AsmCond::ElseIfCond)
64765ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered an else that doesn't follow an if"
64775ffd83dbSDimitry Andric                                " or an elseif");
64785ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::ElseCond;
64795ffd83dbSDimitry Andric   bool LastIgnoreState = false;
64805ffd83dbSDimitry Andric   if (!TheCondStack.empty())
64815ffd83dbSDimitry Andric     LastIgnoreState = TheCondStack.back().Ignore;
64825ffd83dbSDimitry Andric   if (LastIgnoreState || TheCondState.CondMet)
64835ffd83dbSDimitry Andric     TheCondState.Ignore = true;
64845ffd83dbSDimitry Andric   else
64855ffd83dbSDimitry Andric     TheCondState.Ignore = false;
64865ffd83dbSDimitry Andric 
64875ffd83dbSDimitry Andric   return false;
64885ffd83dbSDimitry Andric }
64895ffd83dbSDimitry Andric 
64905ffd83dbSDimitry Andric /// parseDirectiveEnd
64915ffd83dbSDimitry Andric /// ::= end
64925ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
649381ad6265SDimitry Andric   if (parseEOL())
64945ffd83dbSDimitry Andric     return true;
64955ffd83dbSDimitry Andric 
64965ffd83dbSDimitry Andric   while (Lexer.isNot(AsmToken::Eof))
64975ffd83dbSDimitry Andric     Lexer.Lex();
64985ffd83dbSDimitry Andric 
64995ffd83dbSDimitry Andric   return false;
65005ffd83dbSDimitry Andric }
65015ffd83dbSDimitry Andric 
65025ffd83dbSDimitry Andric /// parseDirectiveError
65035ffd83dbSDimitry Andric ///   ::= .err [message]
65045ffd83dbSDimitry Andric bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
65055ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
65065ffd83dbSDimitry Andric     if (TheCondStack.back().Ignore) {
65075ffd83dbSDimitry Andric       eatToEndOfStatement();
65085ffd83dbSDimitry Andric       return false;
65095ffd83dbSDimitry Andric     }
65105ffd83dbSDimitry Andric   }
65115ffd83dbSDimitry Andric 
6512e8d8bef9SDimitry Andric   std::string Message = ".err directive invoked in source file";
65135ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::EndOfStatement))
6514e8d8bef9SDimitry Andric     Message = parseStringTo(AsmToken::EndOfStatement);
65155ffd83dbSDimitry Andric   Lex();
65165ffd83dbSDimitry Andric 
65175ffd83dbSDimitry Andric   return Error(DirectiveLoc, Message);
65185ffd83dbSDimitry Andric }
65195ffd83dbSDimitry Andric 
65205ffd83dbSDimitry Andric /// parseDirectiveErrorIfb
65215ffd83dbSDimitry Andric ///   ::= .errb textitem[, message]
65225ffd83dbSDimitry Andric bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
65235ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
65245ffd83dbSDimitry Andric     if (TheCondStack.back().Ignore) {
65255ffd83dbSDimitry Andric       eatToEndOfStatement();
65265ffd83dbSDimitry Andric       return false;
65275ffd83dbSDimitry Andric     }
65285ffd83dbSDimitry Andric   }
65295ffd83dbSDimitry Andric 
65305ffd83dbSDimitry Andric   std::string Text;
65315ffd83dbSDimitry Andric   if (parseTextItem(Text))
65325ffd83dbSDimitry Andric     return Error(getTok().getLoc(), "missing text item in '.errb' directive");
65335ffd83dbSDimitry Andric 
6534e8d8bef9SDimitry Andric   std::string Message = ".errb directive invoked in source file";
65355ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::EndOfStatement)) {
65365ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma))
65375ffd83dbSDimitry Andric       return addErrorSuffix(" in '.errb' directive");
6538e8d8bef9SDimitry Andric     Message = parseStringTo(AsmToken::EndOfStatement);
65395ffd83dbSDimitry Andric   }
65405ffd83dbSDimitry Andric   Lex();
65415ffd83dbSDimitry Andric 
65425ffd83dbSDimitry Andric   if (Text.empty() == ExpectBlank)
65435ffd83dbSDimitry Andric     return Error(DirectiveLoc, Message);
65445ffd83dbSDimitry Andric   return false;
65455ffd83dbSDimitry Andric }
65465ffd83dbSDimitry Andric 
65475ffd83dbSDimitry Andric /// parseDirectiveErrorIfdef
65485ffd83dbSDimitry Andric ///   ::= .errdef name[, message]
65495ffd83dbSDimitry Andric bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
65505ffd83dbSDimitry Andric                                           bool ExpectDefined) {
65515ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
65525ffd83dbSDimitry Andric     if (TheCondStack.back().Ignore) {
65535ffd83dbSDimitry Andric       eatToEndOfStatement();
65545ffd83dbSDimitry Andric       return false;
65555ffd83dbSDimitry Andric     }
65565ffd83dbSDimitry Andric   }
65575ffd83dbSDimitry Andric 
65585ffd83dbSDimitry Andric   bool IsDefined = false;
6559*bdd1243dSDimitry Andric   MCRegister Reg;
65605ffd83dbSDimitry Andric   SMLoc StartLoc, EndLoc;
6561*bdd1243dSDimitry Andric   IsDefined = (getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc) ==
65625ffd83dbSDimitry Andric                MatchOperand_Success);
65635ffd83dbSDimitry Andric   if (!IsDefined) {
65645ffd83dbSDimitry Andric     StringRef Name;
65655ffd83dbSDimitry Andric     if (check(parseIdentifier(Name), "expected identifier after '.errdef'"))
65665ffd83dbSDimitry Andric       return true;
65675ffd83dbSDimitry Andric 
6568fe6060f1SDimitry Andric     if (BuiltinSymbolMap.find(Name.lower()) != BuiltinSymbolMap.end()) {
6569fe6060f1SDimitry Andric       IsDefined = true;
6570fe6060f1SDimitry Andric     } else if (Variables.find(Name.lower()) != Variables.end()) {
65715ffd83dbSDimitry Andric       IsDefined = true;
65725ffd83dbSDimitry Andric     } else {
65735ffd83dbSDimitry Andric       MCSymbol *Sym = getContext().lookupSymbol(Name);
65745ffd83dbSDimitry Andric       IsDefined = (Sym && !Sym->isUndefined(false));
65755ffd83dbSDimitry Andric     }
65765ffd83dbSDimitry Andric   }
65775ffd83dbSDimitry Andric 
6578e8d8bef9SDimitry Andric   std::string Message = ".errdef directive invoked in source file";
65795ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::EndOfStatement)) {
65805ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma))
65815ffd83dbSDimitry Andric       return addErrorSuffix(" in '.errdef' directive");
6582e8d8bef9SDimitry Andric     Message = parseStringTo(AsmToken::EndOfStatement);
65835ffd83dbSDimitry Andric   }
65845ffd83dbSDimitry Andric   Lex();
65855ffd83dbSDimitry Andric 
65865ffd83dbSDimitry Andric   if (IsDefined == ExpectDefined)
65875ffd83dbSDimitry Andric     return Error(DirectiveLoc, Message);
65885ffd83dbSDimitry Andric   return false;
65895ffd83dbSDimitry Andric }
65905ffd83dbSDimitry Andric 
65915ffd83dbSDimitry Andric /// parseDirectiveErrorIfidn
6592e8d8bef9SDimitry Andric ///   ::= .erridn textitem, textitem[, message]
65935ffd83dbSDimitry Andric bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
65945ffd83dbSDimitry Andric                                           bool CaseInsensitive) {
65955ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
65965ffd83dbSDimitry Andric     if (TheCondStack.back().Ignore) {
65975ffd83dbSDimitry Andric       eatToEndOfStatement();
65985ffd83dbSDimitry Andric       return false;
65995ffd83dbSDimitry Andric     }
66005ffd83dbSDimitry Andric   }
66015ffd83dbSDimitry Andric 
66025ffd83dbSDimitry Andric   std::string String1, String2;
66035ffd83dbSDimitry Andric 
66045ffd83dbSDimitry Andric   if (parseTextItem(String1)) {
66055ffd83dbSDimitry Andric     if (ExpectEqual)
66065ffd83dbSDimitry Andric       return TokError("expected string parameter for '.erridn' directive");
66075ffd83dbSDimitry Andric     return TokError("expected string parameter for '.errdif' directive");
66085ffd83dbSDimitry Andric   }
66095ffd83dbSDimitry Andric 
66105ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::Comma)) {
66115ffd83dbSDimitry Andric     if (ExpectEqual)
66125ffd83dbSDimitry Andric       return TokError(
66135ffd83dbSDimitry Andric           "expected comma after first string for '.erridn' directive");
66145ffd83dbSDimitry Andric     return TokError(
66155ffd83dbSDimitry Andric         "expected comma after first string for '.errdif' directive");
66165ffd83dbSDimitry Andric   }
66175ffd83dbSDimitry Andric   Lex();
66185ffd83dbSDimitry Andric 
66195ffd83dbSDimitry Andric   if (parseTextItem(String2)) {
66205ffd83dbSDimitry Andric     if (ExpectEqual)
66215ffd83dbSDimitry Andric       return TokError("expected string parameter for '.erridn' directive");
66225ffd83dbSDimitry Andric     return TokError("expected string parameter for '.errdif' directive");
66235ffd83dbSDimitry Andric   }
66245ffd83dbSDimitry Andric 
6625e8d8bef9SDimitry Andric   std::string Message;
66265ffd83dbSDimitry Andric   if (ExpectEqual)
66275ffd83dbSDimitry Andric     Message = ".erridn directive invoked in source file";
66285ffd83dbSDimitry Andric   else
66295ffd83dbSDimitry Andric     Message = ".errdif directive invoked in source file";
66305ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::EndOfStatement)) {
66315ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma))
66325ffd83dbSDimitry Andric       return addErrorSuffix(" in '.erridn' directive");
6633e8d8bef9SDimitry Andric     Message = parseStringTo(AsmToken::EndOfStatement);
66345ffd83dbSDimitry Andric   }
66355ffd83dbSDimitry Andric   Lex();
66365ffd83dbSDimitry Andric 
66375ffd83dbSDimitry Andric   if (CaseInsensitive)
66385ffd83dbSDimitry Andric     TheCondState.CondMet =
6639fe6060f1SDimitry Andric         ExpectEqual == (StringRef(String1).equals_insensitive(String2));
66405ffd83dbSDimitry Andric   else
66415ffd83dbSDimitry Andric     TheCondState.CondMet = ExpectEqual == (String1 == String2);
66425ffd83dbSDimitry Andric   TheCondState.Ignore = !TheCondState.CondMet;
66435ffd83dbSDimitry Andric 
66445ffd83dbSDimitry Andric   if ((CaseInsensitive &&
6645fe6060f1SDimitry Andric        ExpectEqual == StringRef(String1).equals_insensitive(String2)) ||
66465ffd83dbSDimitry Andric       (ExpectEqual == (String1 == String2)))
66475ffd83dbSDimitry Andric     return Error(DirectiveLoc, Message);
66485ffd83dbSDimitry Andric   return false;
66495ffd83dbSDimitry Andric }
66505ffd83dbSDimitry Andric 
66515ffd83dbSDimitry Andric /// parseDirectiveErrorIfe
66525ffd83dbSDimitry Andric ///   ::= .erre expression[, message]
66535ffd83dbSDimitry Andric bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero) {
66545ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
66555ffd83dbSDimitry Andric     if (TheCondStack.back().Ignore) {
66565ffd83dbSDimitry Andric       eatToEndOfStatement();
66575ffd83dbSDimitry Andric       return false;
66585ffd83dbSDimitry Andric     }
66595ffd83dbSDimitry Andric   }
66605ffd83dbSDimitry Andric 
66615ffd83dbSDimitry Andric   int64_t ExprValue;
66625ffd83dbSDimitry Andric   if (parseAbsoluteExpression(ExprValue))
66635ffd83dbSDimitry Andric     return addErrorSuffix(" in '.erre' directive");
66645ffd83dbSDimitry Andric 
6665e8d8bef9SDimitry Andric   std::string Message = ".erre directive invoked in source file";
66665ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::EndOfStatement)) {
66675ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma))
66685ffd83dbSDimitry Andric       return addErrorSuffix(" in '.erre' directive");
6669e8d8bef9SDimitry Andric     Message = parseStringTo(AsmToken::EndOfStatement);
66705ffd83dbSDimitry Andric   }
66715ffd83dbSDimitry Andric   Lex();
66725ffd83dbSDimitry Andric 
66735ffd83dbSDimitry Andric   if ((ExprValue == 0) == ExpectZero)
66745ffd83dbSDimitry Andric     return Error(DirectiveLoc, Message);
66755ffd83dbSDimitry Andric   return false;
66765ffd83dbSDimitry Andric }
66775ffd83dbSDimitry Andric 
66785ffd83dbSDimitry Andric /// parseDirectiveEndIf
66795ffd83dbSDimitry Andric /// ::= .endif
66805ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
668181ad6265SDimitry Andric   if (parseEOL())
66825ffd83dbSDimitry Andric     return true;
66835ffd83dbSDimitry Andric 
66845ffd83dbSDimitry Andric   if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
66855ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
66865ffd83dbSDimitry Andric                                "an .if or .else");
66875ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
66885ffd83dbSDimitry Andric     TheCondState = TheCondStack.back();
66895ffd83dbSDimitry Andric     TheCondStack.pop_back();
66905ffd83dbSDimitry Andric   }
66915ffd83dbSDimitry Andric 
66925ffd83dbSDimitry Andric   return false;
66935ffd83dbSDimitry Andric }
66945ffd83dbSDimitry Andric 
66955ffd83dbSDimitry Andric void MasmParser::initializeDirectiveKindMap() {
66965ffd83dbSDimitry Andric   DirectiveKindMap["="] = DK_ASSIGN;
66975ffd83dbSDimitry Andric   DirectiveKindMap["equ"] = DK_EQU;
66985ffd83dbSDimitry Andric   DirectiveKindMap["textequ"] = DK_TEXTEQU;
66995ffd83dbSDimitry Andric   // DirectiveKindMap[".ascii"] = DK_ASCII;
67005ffd83dbSDimitry Andric   // DirectiveKindMap[".asciz"] = DK_ASCIZ;
67015ffd83dbSDimitry Andric   // DirectiveKindMap[".string"] = DK_STRING;
67025ffd83dbSDimitry Andric   DirectiveKindMap["byte"] = DK_BYTE;
67035ffd83dbSDimitry Andric   DirectiveKindMap["sbyte"] = DK_SBYTE;
67045ffd83dbSDimitry Andric   DirectiveKindMap["word"] = DK_WORD;
67055ffd83dbSDimitry Andric   DirectiveKindMap["sword"] = DK_SWORD;
67065ffd83dbSDimitry Andric   DirectiveKindMap["dword"] = DK_DWORD;
67075ffd83dbSDimitry Andric   DirectiveKindMap["sdword"] = DK_SDWORD;
67085ffd83dbSDimitry Andric   DirectiveKindMap["fword"] = DK_FWORD;
67095ffd83dbSDimitry Andric   DirectiveKindMap["qword"] = DK_QWORD;
67105ffd83dbSDimitry Andric   DirectiveKindMap["sqword"] = DK_SQWORD;
67115ffd83dbSDimitry Andric   DirectiveKindMap["real4"] = DK_REAL4;
67125ffd83dbSDimitry Andric   DirectiveKindMap["real8"] = DK_REAL8;
6713e8d8bef9SDimitry Andric   DirectiveKindMap["real10"] = DK_REAL10;
67145ffd83dbSDimitry Andric   DirectiveKindMap["align"] = DK_ALIGN;
6715fe6060f1SDimitry Andric   DirectiveKindMap["even"] = DK_EVEN;
6716fe6060f1SDimitry Andric   DirectiveKindMap["org"] = DK_ORG;
67175ffd83dbSDimitry Andric   DirectiveKindMap["extern"] = DK_EXTERN;
6718*bdd1243dSDimitry Andric   DirectiveKindMap["extrn"] = DK_EXTERN;
67195ffd83dbSDimitry Andric   DirectiveKindMap["public"] = DK_PUBLIC;
67205ffd83dbSDimitry Andric   // DirectiveKindMap[".comm"] = DK_COMM;
67215ffd83dbSDimitry Andric   DirectiveKindMap["comment"] = DK_COMMENT;
67225ffd83dbSDimitry Andric   DirectiveKindMap["include"] = DK_INCLUDE;
6723e8d8bef9SDimitry Andric   DirectiveKindMap["repeat"] = DK_REPEAT;
6724e8d8bef9SDimitry Andric   DirectiveKindMap["rept"] = DK_REPEAT;
6725e8d8bef9SDimitry Andric   DirectiveKindMap["while"] = DK_WHILE;
6726e8d8bef9SDimitry Andric   DirectiveKindMap["for"] = DK_FOR;
6727e8d8bef9SDimitry Andric   DirectiveKindMap["irp"] = DK_FOR;
6728e8d8bef9SDimitry Andric   DirectiveKindMap["forc"] = DK_FORC;
6729e8d8bef9SDimitry Andric   DirectiveKindMap["irpc"] = DK_FORC;
67305ffd83dbSDimitry Andric   DirectiveKindMap["if"] = DK_IF;
67315ffd83dbSDimitry Andric   DirectiveKindMap["ife"] = DK_IFE;
67325ffd83dbSDimitry Andric   DirectiveKindMap["ifb"] = DK_IFB;
67335ffd83dbSDimitry Andric   DirectiveKindMap["ifnb"] = DK_IFNB;
67345ffd83dbSDimitry Andric   DirectiveKindMap["ifdef"] = DK_IFDEF;
67355ffd83dbSDimitry Andric   DirectiveKindMap["ifndef"] = DK_IFNDEF;
67365ffd83dbSDimitry Andric   DirectiveKindMap["ifdif"] = DK_IFDIF;
67375ffd83dbSDimitry Andric   DirectiveKindMap["ifdifi"] = DK_IFDIFI;
67385ffd83dbSDimitry Andric   DirectiveKindMap["ifidn"] = DK_IFIDN;
67395ffd83dbSDimitry Andric   DirectiveKindMap["ifidni"] = DK_IFIDNI;
67405ffd83dbSDimitry Andric   DirectiveKindMap["elseif"] = DK_ELSEIF;
67415ffd83dbSDimitry Andric   DirectiveKindMap["elseifdef"] = DK_ELSEIFDEF;
67425ffd83dbSDimitry Andric   DirectiveKindMap["elseifndef"] = DK_ELSEIFNDEF;
67435ffd83dbSDimitry Andric   DirectiveKindMap["elseifdif"] = DK_ELSEIFDIF;
67445ffd83dbSDimitry Andric   DirectiveKindMap["elseifidn"] = DK_ELSEIFIDN;
67455ffd83dbSDimitry Andric   DirectiveKindMap["else"] = DK_ELSE;
67465ffd83dbSDimitry Andric   DirectiveKindMap["end"] = DK_END;
67475ffd83dbSDimitry Andric   DirectiveKindMap["endif"] = DK_ENDIF;
67485ffd83dbSDimitry Andric   // DirectiveKindMap[".file"] = DK_FILE;
67495ffd83dbSDimitry Andric   // DirectiveKindMap[".line"] = DK_LINE;
67505ffd83dbSDimitry Andric   // DirectiveKindMap[".loc"] = DK_LOC;
67515ffd83dbSDimitry Andric   // DirectiveKindMap[".stabs"] = DK_STABS;
67525ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_file"] = DK_CV_FILE;
67535ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
67545ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
67555ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
67565ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
67575ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
67585ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
67595ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_string"] = DK_CV_STRING;
67605ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
67615ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
67625ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
67635ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
67645ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
67655ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
67665ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
67675ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
67685ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
67695ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
67705ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
67715ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
67725ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
67735ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
67745ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
67755ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
67765ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
67775ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
67785ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
67795ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
67805ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
67815ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
67825ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
67835ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
67845ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
67855ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
6786e8d8bef9SDimitry Andric   DirectiveKindMap["macro"] = DK_MACRO;
6787e8d8bef9SDimitry Andric   DirectiveKindMap["exitm"] = DK_EXITM;
6788e8d8bef9SDimitry Andric   DirectiveKindMap["endm"] = DK_ENDM;
6789e8d8bef9SDimitry Andric   DirectiveKindMap["purge"] = DK_PURGE;
67905ffd83dbSDimitry Andric   DirectiveKindMap[".err"] = DK_ERR;
67915ffd83dbSDimitry Andric   DirectiveKindMap[".errb"] = DK_ERRB;
67925ffd83dbSDimitry Andric   DirectiveKindMap[".errnb"] = DK_ERRNB;
67935ffd83dbSDimitry Andric   DirectiveKindMap[".errdef"] = DK_ERRDEF;
67945ffd83dbSDimitry Andric   DirectiveKindMap[".errndef"] = DK_ERRNDEF;
67955ffd83dbSDimitry Andric   DirectiveKindMap[".errdif"] = DK_ERRDIF;
67965ffd83dbSDimitry Andric   DirectiveKindMap[".errdifi"] = DK_ERRDIFI;
67975ffd83dbSDimitry Andric   DirectiveKindMap[".erridn"] = DK_ERRIDN;
67985ffd83dbSDimitry Andric   DirectiveKindMap[".erridni"] = DK_ERRIDNI;
67995ffd83dbSDimitry Andric   DirectiveKindMap[".erre"] = DK_ERRE;
68005ffd83dbSDimitry Andric   DirectiveKindMap[".errnz"] = DK_ERRNZ;
6801e8d8bef9SDimitry Andric   DirectiveKindMap[".pushframe"] = DK_PUSHFRAME;
6802e8d8bef9SDimitry Andric   DirectiveKindMap[".pushreg"] = DK_PUSHREG;
6803e8d8bef9SDimitry Andric   DirectiveKindMap[".savereg"] = DK_SAVEREG;
6804e8d8bef9SDimitry Andric   DirectiveKindMap[".savexmm128"] = DK_SAVEXMM128;
6805e8d8bef9SDimitry Andric   DirectiveKindMap[".setframe"] = DK_SETFRAME;
6806e8d8bef9SDimitry Andric   DirectiveKindMap[".radix"] = DK_RADIX;
68075ffd83dbSDimitry Andric   DirectiveKindMap["db"] = DK_DB;
68085ffd83dbSDimitry Andric   DirectiveKindMap["dd"] = DK_DD;
6809e8d8bef9SDimitry Andric   DirectiveKindMap["df"] = DK_DF;
68105ffd83dbSDimitry Andric   DirectiveKindMap["dq"] = DK_DQ;
68115ffd83dbSDimitry Andric   DirectiveKindMap["dw"] = DK_DW;
68125ffd83dbSDimitry Andric   DirectiveKindMap["echo"] = DK_ECHO;
68135ffd83dbSDimitry Andric   DirectiveKindMap["struc"] = DK_STRUCT;
68145ffd83dbSDimitry Andric   DirectiveKindMap["struct"] = DK_STRUCT;
68155ffd83dbSDimitry Andric   DirectiveKindMap["union"] = DK_UNION;
68165ffd83dbSDimitry Andric   DirectiveKindMap["ends"] = DK_ENDS;
68175ffd83dbSDimitry Andric }
68185ffd83dbSDimitry Andric 
6819e8d8bef9SDimitry Andric bool MasmParser::isMacroLikeDirective() {
6820e8d8bef9SDimitry Andric   if (getLexer().is(AsmToken::Identifier)) {
6821e8d8bef9SDimitry Andric     bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier())
6822e8d8bef9SDimitry Andric                            .CasesLower("repeat", "rept", true)
6823e8d8bef9SDimitry Andric                            .CaseLower("while", true)
6824e8d8bef9SDimitry Andric                            .CasesLower("for", "irp", true)
6825e8d8bef9SDimitry Andric                            .CasesLower("forc", "irpc", true)
6826e8d8bef9SDimitry Andric                            .Default(false);
6827e8d8bef9SDimitry Andric     if (IsMacroLike)
6828e8d8bef9SDimitry Andric       return true;
6829e8d8bef9SDimitry Andric   }
6830fe6060f1SDimitry Andric   if (peekTok().is(AsmToken::Identifier) &&
6831fe6060f1SDimitry Andric       peekTok().getIdentifier().equals_insensitive("macro"))
6832e8d8bef9SDimitry Andric     return true;
6833e8d8bef9SDimitry Andric 
6834e8d8bef9SDimitry Andric   return false;
6835e8d8bef9SDimitry Andric }
6836e8d8bef9SDimitry Andric 
68375ffd83dbSDimitry Andric MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
68385ffd83dbSDimitry Andric   AsmToken EndToken, StartToken = getTok();
68395ffd83dbSDimitry Andric 
68405ffd83dbSDimitry Andric   unsigned NestLevel = 0;
68415ffd83dbSDimitry Andric   while (true) {
68425ffd83dbSDimitry Andric     // Check whether we have reached the end of the file.
68435ffd83dbSDimitry Andric     if (getLexer().is(AsmToken::Eof)) {
6844e8d8bef9SDimitry Andric       printError(DirectiveLoc, "no matching 'endm' in definition");
68455ffd83dbSDimitry Andric       return nullptr;
68465ffd83dbSDimitry Andric     }
68475ffd83dbSDimitry Andric 
6848e8d8bef9SDimitry Andric     if (isMacroLikeDirective())
68495ffd83dbSDimitry Andric       ++NestLevel;
68505ffd83dbSDimitry Andric 
6851e8d8bef9SDimitry Andric     // Otherwise, check whether we have reached the endm.
6852e8d8bef9SDimitry Andric     if (Lexer.is(AsmToken::Identifier) &&
6853fe6060f1SDimitry Andric         getTok().getIdentifier().equals_insensitive("endm")) {
68545ffd83dbSDimitry Andric       if (NestLevel == 0) {
68555ffd83dbSDimitry Andric         EndToken = getTok();
68565ffd83dbSDimitry Andric         Lex();
68575ffd83dbSDimitry Andric         if (Lexer.isNot(AsmToken::EndOfStatement)) {
6858e8d8bef9SDimitry Andric           printError(getTok().getLoc(), "unexpected token in 'endm' directive");
68595ffd83dbSDimitry Andric           return nullptr;
68605ffd83dbSDimitry Andric         }
68615ffd83dbSDimitry Andric         break;
68625ffd83dbSDimitry Andric       }
68635ffd83dbSDimitry Andric       --NestLevel;
68645ffd83dbSDimitry Andric     }
68655ffd83dbSDimitry Andric 
68665ffd83dbSDimitry Andric     // Otherwise, scan till the end of the statement.
68675ffd83dbSDimitry Andric     eatToEndOfStatement();
68685ffd83dbSDimitry Andric   }
68695ffd83dbSDimitry Andric 
68705ffd83dbSDimitry Andric   const char *BodyStart = StartToken.getLoc().getPointer();
68715ffd83dbSDimitry Andric   const char *BodyEnd = EndToken.getLoc().getPointer();
68725ffd83dbSDimitry Andric   StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
68735ffd83dbSDimitry Andric 
68745ffd83dbSDimitry Andric   // We Are Anonymous.
68755ffd83dbSDimitry Andric   MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
68765ffd83dbSDimitry Andric   return &MacroLikeBodies.back();
68775ffd83dbSDimitry Andric }
68785ffd83dbSDimitry Andric 
6879e8d8bef9SDimitry Andric bool MasmParser::expandStatement(SMLoc Loc) {
6880e8d8bef9SDimitry Andric   std::string Body = parseStringTo(AsmToken::EndOfStatement);
6881e8d8bef9SDimitry Andric   SMLoc EndLoc = getTok().getLoc();
6882e8d8bef9SDimitry Andric 
6883e8d8bef9SDimitry Andric   MCAsmMacroParameters Parameters;
6884e8d8bef9SDimitry Andric   MCAsmMacroArguments Arguments;
6885fe6060f1SDimitry Andric 
6886fe6060f1SDimitry Andric   StringMap<std::string> BuiltinValues;
6887fe6060f1SDimitry Andric   for (const auto &S : BuiltinSymbolMap) {
6888fe6060f1SDimitry Andric     const BuiltinSymbol &Sym = S.getValue();
6889*bdd1243dSDimitry Andric     if (std::optional<std::string> Text = evaluateBuiltinTextMacro(Sym, Loc)) {
6890fe6060f1SDimitry Andric       BuiltinValues[S.getKey().lower()] = std::move(*Text);
6891fe6060f1SDimitry Andric     }
6892fe6060f1SDimitry Andric   }
6893fe6060f1SDimitry Andric   for (const auto &B : BuiltinValues) {
6894fe6060f1SDimitry Andric     MCAsmMacroParameter P;
6895fe6060f1SDimitry Andric     MCAsmMacroArgument A;
6896fe6060f1SDimitry Andric     P.Name = B.getKey();
6897fe6060f1SDimitry Andric     P.Required = true;
6898fe6060f1SDimitry Andric     A.push_back(AsmToken(AsmToken::String, B.getValue()));
6899fe6060f1SDimitry Andric 
6900fe6060f1SDimitry Andric     Parameters.push_back(std::move(P));
6901fe6060f1SDimitry Andric     Arguments.push_back(std::move(A));
6902fe6060f1SDimitry Andric   }
6903fe6060f1SDimitry Andric 
6904e8d8bef9SDimitry Andric   for (const auto &V : Variables) {
6905e8d8bef9SDimitry Andric     const Variable &Var = V.getValue();
6906e8d8bef9SDimitry Andric     if (Var.IsText) {
6907fe6060f1SDimitry Andric       MCAsmMacroParameter P;
6908fe6060f1SDimitry Andric       MCAsmMacroArgument A;
6909e8d8bef9SDimitry Andric       P.Name = Var.Name;
6910e8d8bef9SDimitry Andric       P.Required = true;
6911e8d8bef9SDimitry Andric       A.push_back(AsmToken(AsmToken::String, Var.TextValue));
6912fe6060f1SDimitry Andric 
6913fe6060f1SDimitry Andric       Parameters.push_back(std::move(P));
6914fe6060f1SDimitry Andric       Arguments.push_back(std::move(A));
6915e8d8bef9SDimitry Andric     }
6916e8d8bef9SDimitry Andric   }
6917e8d8bef9SDimitry Andric   MacroLikeBodies.emplace_back(StringRef(), Body, Parameters);
6918e8d8bef9SDimitry Andric   MCAsmMacro M = MacroLikeBodies.back();
6919e8d8bef9SDimitry Andric 
6920e8d8bef9SDimitry Andric   // Expand the statement in a new buffer.
6921e8d8bef9SDimitry Andric   SmallString<80> Buf;
6922e8d8bef9SDimitry Andric   raw_svector_ostream OS(Buf);
6923e8d8bef9SDimitry Andric   if (expandMacro(OS, M.Body, M.Parameters, Arguments, M.Locals, EndLoc))
6924e8d8bef9SDimitry Andric     return true;
6925e8d8bef9SDimitry Andric   std::unique_ptr<MemoryBuffer> Expansion =
6926e8d8bef9SDimitry Andric       MemoryBuffer::getMemBufferCopy(OS.str(), "<expansion>");
6927e8d8bef9SDimitry Andric 
6928e8d8bef9SDimitry Andric   // Jump to the expanded statement and prime the lexer.
6929e8d8bef9SDimitry Andric   CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Expansion), EndLoc);
6930e8d8bef9SDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
6931e8d8bef9SDimitry Andric   EndStatementAtEOFStack.push_back(false);
6932e8d8bef9SDimitry Andric   Lex();
6933e8d8bef9SDimitry Andric   return false;
6934e8d8bef9SDimitry Andric }
6935e8d8bef9SDimitry Andric 
69365ffd83dbSDimitry Andric void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
69375ffd83dbSDimitry Andric                                           raw_svector_ostream &OS) {
6938e8d8bef9SDimitry Andric   instantiateMacroLikeBody(M, DirectiveLoc, /*ExitLoc=*/getTok().getLoc(), OS);
6939e8d8bef9SDimitry Andric }
6940e8d8bef9SDimitry Andric void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
6941e8d8bef9SDimitry Andric                                           SMLoc ExitLoc,
6942e8d8bef9SDimitry Andric                                           raw_svector_ostream &OS) {
6943e8d8bef9SDimitry Andric   OS << "endm\n";
69445ffd83dbSDimitry Andric 
69455ffd83dbSDimitry Andric   std::unique_ptr<MemoryBuffer> Instantiation =
69465ffd83dbSDimitry Andric       MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
69475ffd83dbSDimitry Andric 
69485ffd83dbSDimitry Andric   // Create the macro instantiation object and add to the current macro
69495ffd83dbSDimitry Andric   // instantiation stack.
6950e8d8bef9SDimitry Andric   MacroInstantiation *MI = new MacroInstantiation{DirectiveLoc, CurBuffer,
6951e8d8bef9SDimitry Andric                                                   ExitLoc, TheCondStack.size()};
69525ffd83dbSDimitry Andric   ActiveMacros.push_back(MI);
69535ffd83dbSDimitry Andric 
69545ffd83dbSDimitry Andric   // Jump to the macro instantiation and prime the lexer.
69555ffd83dbSDimitry Andric   CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
69565ffd83dbSDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
6957e8d8bef9SDimitry Andric   EndStatementAtEOFStack.push_back(true);
69585ffd83dbSDimitry Andric   Lex();
69595ffd83dbSDimitry Andric }
69605ffd83dbSDimitry Andric 
6961e8d8bef9SDimitry Andric /// parseDirectiveRepeat
6962e8d8bef9SDimitry Andric ///   ::= ("repeat" | "rept") count
6963e8d8bef9SDimitry Andric ///       body
6964e8d8bef9SDimitry Andric ///     endm
6965e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) {
69665ffd83dbSDimitry Andric   const MCExpr *CountExpr;
69675ffd83dbSDimitry Andric   SMLoc CountLoc = getTok().getLoc();
69685ffd83dbSDimitry Andric   if (parseExpression(CountExpr))
69695ffd83dbSDimitry Andric     return true;
69705ffd83dbSDimitry Andric 
69715ffd83dbSDimitry Andric   int64_t Count;
69725ffd83dbSDimitry Andric   if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
69735ffd83dbSDimitry Andric     return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
69745ffd83dbSDimitry Andric   }
69755ffd83dbSDimitry Andric 
697681ad6265SDimitry Andric   if (check(Count < 0, CountLoc, "Count is negative") || parseEOL())
69775ffd83dbSDimitry Andric     return true;
69785ffd83dbSDimitry Andric 
6979e8d8bef9SDimitry Andric   // Lex the repeat definition.
69805ffd83dbSDimitry Andric   MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
69815ffd83dbSDimitry Andric   if (!M)
69825ffd83dbSDimitry Andric     return true;
69835ffd83dbSDimitry Andric 
69845ffd83dbSDimitry Andric   // Macro instantiation is lexical, unfortunately. We construct a new buffer
69855ffd83dbSDimitry Andric   // to hold the macro body with substitutions.
69865ffd83dbSDimitry Andric   SmallString<256> Buf;
69875ffd83dbSDimitry Andric   raw_svector_ostream OS(Buf);
69885ffd83dbSDimitry Andric   while (Count--) {
6989*bdd1243dSDimitry Andric     if (expandMacro(OS, M->Body, std::nullopt, std::nullopt, M->Locals,
6990*bdd1243dSDimitry Andric                     getTok().getLoc()))
69915ffd83dbSDimitry Andric       return true;
69925ffd83dbSDimitry Andric   }
69935ffd83dbSDimitry Andric   instantiateMacroLikeBody(M, DirectiveLoc, OS);
69945ffd83dbSDimitry Andric 
69955ffd83dbSDimitry Andric   return false;
69965ffd83dbSDimitry Andric }
69975ffd83dbSDimitry Andric 
6998e8d8bef9SDimitry Andric /// parseDirectiveWhile
6999e8d8bef9SDimitry Andric /// ::= "while" expression
7000e8d8bef9SDimitry Andric ///       body
7001e8d8bef9SDimitry Andric ///     endm
7002e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) {
7003e8d8bef9SDimitry Andric   const MCExpr *CondExpr;
7004e8d8bef9SDimitry Andric   SMLoc CondLoc = getTok().getLoc();
7005e8d8bef9SDimitry Andric   if (parseExpression(CondExpr))
7006e8d8bef9SDimitry Andric     return true;
7007e8d8bef9SDimitry Andric 
7008e8d8bef9SDimitry Andric   // Lex the repeat definition.
7009e8d8bef9SDimitry Andric   MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
7010e8d8bef9SDimitry Andric   if (!M)
7011e8d8bef9SDimitry Andric     return true;
7012e8d8bef9SDimitry Andric 
7013e8d8bef9SDimitry Andric   // Macro instantiation is lexical, unfortunately. We construct a new buffer
7014e8d8bef9SDimitry Andric   // to hold the macro body with substitutions.
7015e8d8bef9SDimitry Andric   SmallString<256> Buf;
7016e8d8bef9SDimitry Andric   raw_svector_ostream OS(Buf);
7017e8d8bef9SDimitry Andric   int64_t Condition;
7018e8d8bef9SDimitry Andric   if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr()))
7019e8d8bef9SDimitry Andric     return Error(CondLoc, "expected absolute expression in 'while' directive");
7020e8d8bef9SDimitry Andric   if (Condition) {
7021e8d8bef9SDimitry Andric     // Instantiate the macro, then resume at this directive to recheck the
7022e8d8bef9SDimitry Andric     // condition.
7023*bdd1243dSDimitry Andric     if (expandMacro(OS, M->Body, std::nullopt, std::nullopt, M->Locals,
7024*bdd1243dSDimitry Andric                     getTok().getLoc()))
7025e8d8bef9SDimitry Andric       return true;
7026e8d8bef9SDimitry Andric     instantiateMacroLikeBody(M, DirectiveLoc, /*ExitLoc=*/DirectiveLoc, OS);
7027e8d8bef9SDimitry Andric   }
7028e8d8bef9SDimitry Andric 
7029e8d8bef9SDimitry Andric   return false;
7030e8d8bef9SDimitry Andric }
7031e8d8bef9SDimitry Andric 
7032e8d8bef9SDimitry Andric /// parseDirectiveFor
7033e8d8bef9SDimitry Andric /// ::= ("for" | "irp") symbol [":" qualifier], <values>
7034e8d8bef9SDimitry Andric ///       body
7035e8d8bef9SDimitry Andric ///     endm
7036e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
70375ffd83dbSDimitry Andric   MCAsmMacroParameter Parameter;
70385ffd83dbSDimitry Andric   MCAsmMacroArguments A;
70395ffd83dbSDimitry Andric   if (check(parseIdentifier(Parameter.Name),
7040e8d8bef9SDimitry Andric             "expected identifier in '" + Dir + "' directive"))
7041e8d8bef9SDimitry Andric     return true;
7042e8d8bef9SDimitry Andric 
7043e8d8bef9SDimitry Andric   // Parse optional qualifier (default value, or "req")
7044e8d8bef9SDimitry Andric   if (parseOptionalToken(AsmToken::Colon)) {
7045e8d8bef9SDimitry Andric     if (parseOptionalToken(AsmToken::Equal)) {
7046e8d8bef9SDimitry Andric       // Default value
7047e8d8bef9SDimitry Andric       SMLoc ParamLoc;
7048e8d8bef9SDimitry Andric 
7049e8d8bef9SDimitry Andric       ParamLoc = Lexer.getLoc();
7050e8d8bef9SDimitry Andric       if (parseMacroArgument(nullptr, Parameter.Value))
7051e8d8bef9SDimitry Andric         return true;
7052e8d8bef9SDimitry Andric     } else {
7053e8d8bef9SDimitry Andric       SMLoc QualLoc;
7054e8d8bef9SDimitry Andric       StringRef Qualifier;
7055e8d8bef9SDimitry Andric 
7056e8d8bef9SDimitry Andric       QualLoc = Lexer.getLoc();
7057e8d8bef9SDimitry Andric       if (parseIdentifier(Qualifier))
7058e8d8bef9SDimitry Andric         return Error(QualLoc, "missing parameter qualifier for "
7059e8d8bef9SDimitry Andric                               "'" +
7060e8d8bef9SDimitry Andric                                   Parameter.Name + "' in '" + Dir +
7061e8d8bef9SDimitry Andric                                   "' directive");
7062e8d8bef9SDimitry Andric 
7063fe6060f1SDimitry Andric       if (Qualifier.equals_insensitive("req"))
7064e8d8bef9SDimitry Andric         Parameter.Required = true;
7065e8d8bef9SDimitry Andric       else
7066e8d8bef9SDimitry Andric         return Error(QualLoc,
7067e8d8bef9SDimitry Andric                      Qualifier + " is not a valid parameter qualifier for '" +
7068e8d8bef9SDimitry Andric                          Parameter.Name + "' in '" + Dir + "' directive");
7069e8d8bef9SDimitry Andric     }
7070e8d8bef9SDimitry Andric   }
7071e8d8bef9SDimitry Andric 
7072e8d8bef9SDimitry Andric   if (parseToken(AsmToken::Comma,
7073e8d8bef9SDimitry Andric                  "expected comma in '" + Dir + "' directive") ||
7074e8d8bef9SDimitry Andric       parseToken(AsmToken::Less,
7075e8d8bef9SDimitry Andric                  "values in '" + Dir +
7076e8d8bef9SDimitry Andric                      "' directive must be enclosed in angle brackets"))
7077e8d8bef9SDimitry Andric     return true;
7078e8d8bef9SDimitry Andric 
7079e8d8bef9SDimitry Andric   while (true) {
7080e8d8bef9SDimitry Andric     A.emplace_back();
7081e8d8bef9SDimitry Andric     if (parseMacroArgument(&Parameter, A.back(), /*EndTok=*/AsmToken::Greater))
7082e8d8bef9SDimitry Andric       return addErrorSuffix(" in arguments for '" + Dir + "' directive");
7083e8d8bef9SDimitry Andric 
7084e8d8bef9SDimitry Andric     // If we see a comma, continue, and allow line continuation.
7085e8d8bef9SDimitry Andric     if (!parseOptionalToken(AsmToken::Comma))
7086e8d8bef9SDimitry Andric       break;
7087e8d8bef9SDimitry Andric     parseOptionalToken(AsmToken::EndOfStatement);
7088e8d8bef9SDimitry Andric   }
7089e8d8bef9SDimitry Andric 
7090e8d8bef9SDimitry Andric   if (parseToken(AsmToken::Greater,
7091e8d8bef9SDimitry Andric                  "values in '" + Dir +
7092e8d8bef9SDimitry Andric                      "' directive must be enclosed in angle brackets") ||
709381ad6265SDimitry Andric       parseEOL())
70945ffd83dbSDimitry Andric     return true;
70955ffd83dbSDimitry Andric 
7096e8d8bef9SDimitry Andric   // Lex the for definition.
70975ffd83dbSDimitry Andric   MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
70985ffd83dbSDimitry Andric   if (!M)
70995ffd83dbSDimitry Andric     return true;
71005ffd83dbSDimitry Andric 
71015ffd83dbSDimitry Andric   // Macro instantiation is lexical, unfortunately. We construct a new buffer
71025ffd83dbSDimitry Andric   // to hold the macro body with substitutions.
71035ffd83dbSDimitry Andric   SmallString<256> Buf;
71045ffd83dbSDimitry Andric   raw_svector_ostream OS(Buf);
71055ffd83dbSDimitry Andric 
71065ffd83dbSDimitry Andric   for (const MCAsmMacroArgument &Arg : A) {
7107e8d8bef9SDimitry Andric     if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc()))
71085ffd83dbSDimitry Andric       return true;
71095ffd83dbSDimitry Andric   }
71105ffd83dbSDimitry Andric 
71115ffd83dbSDimitry Andric   instantiateMacroLikeBody(M, DirectiveLoc, OS);
71125ffd83dbSDimitry Andric 
71135ffd83dbSDimitry Andric   return false;
71145ffd83dbSDimitry Andric }
71155ffd83dbSDimitry Andric 
7116e8d8bef9SDimitry Andric /// parseDirectiveForc
7117e8d8bef9SDimitry Andric /// ::= ("forc" | "irpc") symbol, <string>
7118e8d8bef9SDimitry Andric ///       body
7119e8d8bef9SDimitry Andric ///     endm
7120e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
71215ffd83dbSDimitry Andric   MCAsmMacroParameter Parameter;
71225ffd83dbSDimitry Andric 
7123e8d8bef9SDimitry Andric   std::string Argument;
71245ffd83dbSDimitry Andric   if (check(parseIdentifier(Parameter.Name),
7125e8d8bef9SDimitry Andric             "expected identifier in '" + Directive + "' directive") ||
7126e8d8bef9SDimitry Andric       parseToken(AsmToken::Comma,
7127e8d8bef9SDimitry Andric                  "expected comma in '" + Directive + "' directive"))
71285ffd83dbSDimitry Andric     return true;
7129e8d8bef9SDimitry Andric   if (parseAngleBracketString(Argument)) {
7130e8d8bef9SDimitry Andric     // Match ml64.exe; treat all characters to end of statement as a string,
7131e8d8bef9SDimitry Andric     // ignoring comment markers, then discard anything following a space (using
7132e8d8bef9SDimitry Andric     // the C locale).
7133e8d8bef9SDimitry Andric     Argument = parseStringTo(AsmToken::EndOfStatement);
7134e8d8bef9SDimitry Andric     if (getTok().is(AsmToken::EndOfStatement))
7135e8d8bef9SDimitry Andric       Argument += getTok().getString();
7136e8d8bef9SDimitry Andric     size_t End = 0;
7137e8d8bef9SDimitry Andric     for (; End < Argument.size(); ++End) {
7138e8d8bef9SDimitry Andric       if (isSpace(Argument[End]))
7139e8d8bef9SDimitry Andric         break;
7140e8d8bef9SDimitry Andric     }
7141e8d8bef9SDimitry Andric     Argument.resize(End);
7142e8d8bef9SDimitry Andric   }
714381ad6265SDimitry Andric   if (parseEOL())
71445ffd83dbSDimitry Andric     return true;
71455ffd83dbSDimitry Andric 
71465ffd83dbSDimitry Andric   // Lex the irpc definition.
71475ffd83dbSDimitry Andric   MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
71485ffd83dbSDimitry Andric   if (!M)
71495ffd83dbSDimitry Andric     return true;
71505ffd83dbSDimitry Andric 
71515ffd83dbSDimitry Andric   // Macro instantiation is lexical, unfortunately. We construct a new buffer
71525ffd83dbSDimitry Andric   // to hold the macro body with substitutions.
71535ffd83dbSDimitry Andric   SmallString<256> Buf;
71545ffd83dbSDimitry Andric   raw_svector_ostream OS(Buf);
71555ffd83dbSDimitry Andric 
7156e8d8bef9SDimitry Andric   StringRef Values(Argument);
71575ffd83dbSDimitry Andric   for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
71585ffd83dbSDimitry Andric     MCAsmMacroArgument Arg;
71595ffd83dbSDimitry Andric     Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1));
71605ffd83dbSDimitry Andric 
7161e8d8bef9SDimitry Andric     if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc()))
71625ffd83dbSDimitry Andric       return true;
71635ffd83dbSDimitry Andric   }
71645ffd83dbSDimitry Andric 
71655ffd83dbSDimitry Andric   instantiateMacroLikeBody(M, DirectiveLoc, OS);
71665ffd83dbSDimitry Andric 
71675ffd83dbSDimitry Andric   return false;
71685ffd83dbSDimitry Andric }
71695ffd83dbSDimitry Andric 
71705ffd83dbSDimitry Andric bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
71715ffd83dbSDimitry Andric                                       size_t Len) {
71725ffd83dbSDimitry Andric   const MCExpr *Value;
71735ffd83dbSDimitry Andric   SMLoc ExprLoc = getLexer().getLoc();
71745ffd83dbSDimitry Andric   if (parseExpression(Value))
71755ffd83dbSDimitry Andric     return true;
71765ffd83dbSDimitry Andric   const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
71775ffd83dbSDimitry Andric   if (!MCE)
71785ffd83dbSDimitry Andric     return Error(ExprLoc, "unexpected expression in _emit");
71795ffd83dbSDimitry Andric   uint64_t IntValue = MCE->getValue();
71805ffd83dbSDimitry Andric   if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
71815ffd83dbSDimitry Andric     return Error(ExprLoc, "literal value out of range for directive");
71825ffd83dbSDimitry Andric 
71835ffd83dbSDimitry Andric   Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
71845ffd83dbSDimitry Andric   return false;
71855ffd83dbSDimitry Andric }
71865ffd83dbSDimitry Andric 
71875ffd83dbSDimitry Andric bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
71885ffd83dbSDimitry Andric   const MCExpr *Value;
71895ffd83dbSDimitry Andric   SMLoc ExprLoc = getLexer().getLoc();
71905ffd83dbSDimitry Andric   if (parseExpression(Value))
71915ffd83dbSDimitry Andric     return true;
71925ffd83dbSDimitry Andric   const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
71935ffd83dbSDimitry Andric   if (!MCE)
71945ffd83dbSDimitry Andric     return Error(ExprLoc, "unexpected expression in align");
71955ffd83dbSDimitry Andric   uint64_t IntValue = MCE->getValue();
71965ffd83dbSDimitry Andric   if (!isPowerOf2_64(IntValue))
71975ffd83dbSDimitry Andric     return Error(ExprLoc, "literal value not a power of two greater then zero");
71985ffd83dbSDimitry Andric 
71995ffd83dbSDimitry Andric   Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
72005ffd83dbSDimitry Andric   return false;
72015ffd83dbSDimitry Andric }
72025ffd83dbSDimitry Andric 
7203e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
7204e8d8bef9SDimitry Andric   const SMLoc Loc = getLexer().getLoc();
7205e8d8bef9SDimitry Andric   std::string RadixStringRaw = parseStringTo(AsmToken::EndOfStatement);
7206e8d8bef9SDimitry Andric   StringRef RadixString = StringRef(RadixStringRaw).trim();
7207e8d8bef9SDimitry Andric   unsigned Radix;
7208e8d8bef9SDimitry Andric   if (RadixString.getAsInteger(10, Radix)) {
7209e8d8bef9SDimitry Andric     return Error(Loc,
7210e8d8bef9SDimitry Andric                  "radix must be a decimal number in the range 2 to 16; was " +
7211e8d8bef9SDimitry Andric                      RadixString);
7212e8d8bef9SDimitry Andric   }
7213e8d8bef9SDimitry Andric   if (Radix < 2 || Radix > 16)
7214e8d8bef9SDimitry Andric     return Error(Loc, "radix must be in the range 2 to 16; was " +
7215e8d8bef9SDimitry Andric                           std::to_string(Radix));
7216e8d8bef9SDimitry Andric   getLexer().setMasmDefaultRadix(Radix);
7217e8d8bef9SDimitry Andric   return false;
7218e8d8bef9SDimitry Andric }
7219e8d8bef9SDimitry Andric 
7220e8d8bef9SDimitry Andric /// parseDirectiveEcho
7221e8d8bef9SDimitry Andric ///   ::= "echo" message
7222fe6060f1SDimitry Andric bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) {
7223e8d8bef9SDimitry Andric   std::string Message = parseStringTo(AsmToken::EndOfStatement);
7224e8d8bef9SDimitry Andric   llvm::outs() << Message;
7225e8d8bef9SDimitry Andric   if (!StringRef(Message).endswith("\n"))
7226e8d8bef9SDimitry Andric     llvm::outs() << '\n';
72275ffd83dbSDimitry Andric   return false;
72285ffd83dbSDimitry Andric }
72295ffd83dbSDimitry Andric 
72305ffd83dbSDimitry Andric // We are comparing pointers, but the pointers are relative to a single string.
72315ffd83dbSDimitry Andric // Thus, this should always be deterministic.
72325ffd83dbSDimitry Andric static int rewritesSort(const AsmRewrite *AsmRewriteA,
72335ffd83dbSDimitry Andric                         const AsmRewrite *AsmRewriteB) {
72345ffd83dbSDimitry Andric   if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
72355ffd83dbSDimitry Andric     return -1;
72365ffd83dbSDimitry Andric   if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
72375ffd83dbSDimitry Andric     return 1;
72385ffd83dbSDimitry Andric 
72395ffd83dbSDimitry Andric   // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
72405ffd83dbSDimitry Andric   // rewrite to the same location.  Make sure the SizeDirective rewrite is
72415ffd83dbSDimitry Andric   // performed first, then the Imm/ImmPrefix and finally the Input/Output.  This
72425ffd83dbSDimitry Andric   // ensures the sort algorithm is stable.
72435ffd83dbSDimitry Andric   if (AsmRewritePrecedence[AsmRewriteA->Kind] >
72445ffd83dbSDimitry Andric       AsmRewritePrecedence[AsmRewriteB->Kind])
72455ffd83dbSDimitry Andric     return -1;
72465ffd83dbSDimitry Andric 
72475ffd83dbSDimitry Andric   if (AsmRewritePrecedence[AsmRewriteA->Kind] <
72485ffd83dbSDimitry Andric       AsmRewritePrecedence[AsmRewriteB->Kind])
72495ffd83dbSDimitry Andric     return 1;
72505ffd83dbSDimitry Andric   llvm_unreachable("Unstable rewrite sort.");
72515ffd83dbSDimitry Andric }
72525ffd83dbSDimitry Andric 
7253e8d8bef9SDimitry Andric bool MasmParser::defineMacro(StringRef Name, StringRef Value) {
7254e8d8bef9SDimitry Andric   Variable &Var = Variables[Name.lower()];
7255e8d8bef9SDimitry Andric   if (Var.Name.empty()) {
7256e8d8bef9SDimitry Andric     Var.Name = Name;
7257fe6060f1SDimitry Andric   } else if (Var.Redefinable == Variable::NOT_REDEFINABLE) {
7258fe6060f1SDimitry Andric     return Error(SMLoc(), "invalid variable redefinition");
7259fe6060f1SDimitry Andric   } else if (Var.Redefinable == Variable::WARN_ON_REDEFINITION &&
7260fe6060f1SDimitry Andric              Warning(SMLoc(), "redefining '" + Name +
7261fe6060f1SDimitry Andric                                   "', already defined on the command line")) {
7262fe6060f1SDimitry Andric     return true;
7263e8d8bef9SDimitry Andric   }
7264fe6060f1SDimitry Andric   Var.Redefinable = Variable::WARN_ON_REDEFINITION;
7265e8d8bef9SDimitry Andric   Var.IsText = true;
7266e8d8bef9SDimitry Andric   Var.TextValue = Value.str();
7267e8d8bef9SDimitry Andric   return false;
72685ffd83dbSDimitry Andric }
72695ffd83dbSDimitry Andric 
7270e8d8bef9SDimitry Andric bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info) const {
7271e8d8bef9SDimitry Andric   const std::pair<StringRef, StringRef> BaseMember = Name.split('.');
7272e8d8bef9SDimitry Andric   const StringRef Base = BaseMember.first, Member = BaseMember.second;
7273e8d8bef9SDimitry Andric   return lookUpField(Base, Member, Info);
7274e8d8bef9SDimitry Andric }
7275e8d8bef9SDimitry Andric 
7276e8d8bef9SDimitry Andric bool MasmParser::lookUpField(StringRef Base, StringRef Member,
7277e8d8bef9SDimitry Andric                              AsmFieldInfo &Info) const {
72785ffd83dbSDimitry Andric   if (Base.empty())
72795ffd83dbSDimitry Andric     return true;
72805ffd83dbSDimitry Andric 
7281e8d8bef9SDimitry Andric   AsmFieldInfo BaseInfo;
7282e8d8bef9SDimitry Andric   if (Base.contains('.') && !lookUpField(Base, BaseInfo))
7283e8d8bef9SDimitry Andric     Base = BaseInfo.Type.Name;
72845ffd83dbSDimitry Andric 
72855ffd83dbSDimitry Andric   auto StructIt = Structs.find(Base.lower());
7286e8d8bef9SDimitry Andric   auto TypeIt = KnownType.find(Base.lower());
7287e8d8bef9SDimitry Andric   if (TypeIt != KnownType.end()) {
7288e8d8bef9SDimitry Andric     StructIt = Structs.find(TypeIt->second.Name.lower());
7289e8d8bef9SDimitry Andric   }
72905ffd83dbSDimitry Andric   if (StructIt != Structs.end())
7291e8d8bef9SDimitry Andric     return lookUpField(StructIt->second, Member, Info);
72925ffd83dbSDimitry Andric 
72935ffd83dbSDimitry Andric   return true;
72945ffd83dbSDimitry Andric }
72955ffd83dbSDimitry Andric 
72965ffd83dbSDimitry Andric bool MasmParser::lookUpField(const StructInfo &Structure, StringRef Member,
7297e8d8bef9SDimitry Andric                              AsmFieldInfo &Info) const {
72985ffd83dbSDimitry Andric   if (Member.empty()) {
7299e8d8bef9SDimitry Andric     Info.Type.Name = Structure.Name;
7300e8d8bef9SDimitry Andric     Info.Type.Size = Structure.Size;
7301e8d8bef9SDimitry Andric     Info.Type.ElementSize = Structure.Size;
7302e8d8bef9SDimitry Andric     Info.Type.Length = 1;
73035ffd83dbSDimitry Andric     return false;
73045ffd83dbSDimitry Andric   }
73055ffd83dbSDimitry Andric 
73065ffd83dbSDimitry Andric   std::pair<StringRef, StringRef> Split = Member.split('.');
73075ffd83dbSDimitry Andric   const StringRef FieldName = Split.first, FieldMember = Split.second;
73085ffd83dbSDimitry Andric 
73095ffd83dbSDimitry Andric   auto StructIt = Structs.find(FieldName.lower());
73105ffd83dbSDimitry Andric   if (StructIt != Structs.end())
7311e8d8bef9SDimitry Andric     return lookUpField(StructIt->second, FieldMember, Info);
73125ffd83dbSDimitry Andric 
73135ffd83dbSDimitry Andric   auto FieldIt = Structure.FieldsByName.find(FieldName.lower());
73145ffd83dbSDimitry Andric   if (FieldIt == Structure.FieldsByName.end())
73155ffd83dbSDimitry Andric     return true;
73165ffd83dbSDimitry Andric 
73175ffd83dbSDimitry Andric   const FieldInfo &Field = Structure.Fields[FieldIt->second];
73185ffd83dbSDimitry Andric   if (FieldMember.empty()) {
7319e8d8bef9SDimitry Andric     Info.Offset += Field.Offset;
7320e8d8bef9SDimitry Andric     Info.Type.Size = Field.SizeOf;
7321e8d8bef9SDimitry Andric     Info.Type.ElementSize = Field.Type;
7322e8d8bef9SDimitry Andric     Info.Type.Length = Field.LengthOf;
73235ffd83dbSDimitry Andric     if (Field.Contents.FT == FT_STRUCT)
7324e8d8bef9SDimitry Andric       Info.Type.Name = Field.Contents.StructInfo.Structure.Name;
7325e8d8bef9SDimitry Andric     else
7326e8d8bef9SDimitry Andric       Info.Type.Name = "";
73275ffd83dbSDimitry Andric     return false;
73285ffd83dbSDimitry Andric   }
73295ffd83dbSDimitry Andric 
73305ffd83dbSDimitry Andric   if (Field.Contents.FT != FT_STRUCT)
73315ffd83dbSDimitry Andric     return true;
73325ffd83dbSDimitry Andric   const StructFieldInfo &StructInfo = Field.Contents.StructInfo;
73335ffd83dbSDimitry Andric 
7334e8d8bef9SDimitry Andric   if (lookUpField(StructInfo.Structure, FieldMember, Info))
73355ffd83dbSDimitry Andric     return true;
73365ffd83dbSDimitry Andric 
7337e8d8bef9SDimitry Andric   Info.Offset += Field.Offset;
73385ffd83dbSDimitry Andric   return false;
73395ffd83dbSDimitry Andric }
73405ffd83dbSDimitry Andric 
7341e8d8bef9SDimitry Andric bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info) const {
7342e8d8bef9SDimitry Andric   unsigned Size = StringSwitch<unsigned>(Name)
7343e8d8bef9SDimitry Andric                       .CasesLower("byte", "db", "sbyte", 1)
7344e8d8bef9SDimitry Andric                       .CasesLower("word", "dw", "sword", 2)
7345e8d8bef9SDimitry Andric                       .CasesLower("dword", "dd", "sdword", 4)
7346e8d8bef9SDimitry Andric                       .CasesLower("fword", "df", 6)
7347e8d8bef9SDimitry Andric                       .CasesLower("qword", "dq", "sqword", 8)
7348e8d8bef9SDimitry Andric                       .CaseLower("real4", 4)
7349e8d8bef9SDimitry Andric                       .CaseLower("real8", 8)
7350e8d8bef9SDimitry Andric                       .CaseLower("real10", 10)
7351e8d8bef9SDimitry Andric                       .Default(0);
7352e8d8bef9SDimitry Andric   if (Size) {
7353e8d8bef9SDimitry Andric     Info.Name = Name;
7354e8d8bef9SDimitry Andric     Info.ElementSize = Size;
7355e8d8bef9SDimitry Andric     Info.Length = 1;
7356e8d8bef9SDimitry Andric     Info.Size = Size;
7357e8d8bef9SDimitry Andric     return false;
7358e8d8bef9SDimitry Andric   }
7359e8d8bef9SDimitry Andric 
7360e8d8bef9SDimitry Andric   auto StructIt = Structs.find(Name.lower());
7361e8d8bef9SDimitry Andric   if (StructIt != Structs.end()) {
7362e8d8bef9SDimitry Andric     const StructInfo &Structure = StructIt->second;
7363e8d8bef9SDimitry Andric     Info.Name = Name;
7364e8d8bef9SDimitry Andric     Info.ElementSize = Structure.Size;
7365e8d8bef9SDimitry Andric     Info.Length = 1;
7366e8d8bef9SDimitry Andric     Info.Size = Structure.Size;
7367e8d8bef9SDimitry Andric     return false;
7368e8d8bef9SDimitry Andric   }
7369e8d8bef9SDimitry Andric 
7370e8d8bef9SDimitry Andric   return true;
7371e8d8bef9SDimitry Andric }
7372e8d8bef9SDimitry Andric 
73735ffd83dbSDimitry Andric bool MasmParser::parseMSInlineAsm(
7374fe6060f1SDimitry Andric     std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs,
7375fe6060f1SDimitry Andric     SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
73765ffd83dbSDimitry Andric     SmallVectorImpl<std::string> &Constraints,
73775ffd83dbSDimitry Andric     SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
73785ffd83dbSDimitry Andric     const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
73795ffd83dbSDimitry Andric   SmallVector<void *, 4> InputDecls;
73805ffd83dbSDimitry Andric   SmallVector<void *, 4> OutputDecls;
73815ffd83dbSDimitry Andric   SmallVector<bool, 4> InputDeclsAddressOf;
73825ffd83dbSDimitry Andric   SmallVector<bool, 4> OutputDeclsAddressOf;
73835ffd83dbSDimitry Andric   SmallVector<std::string, 4> InputConstraints;
73845ffd83dbSDimitry Andric   SmallVector<std::string, 4> OutputConstraints;
73855ffd83dbSDimitry Andric   SmallVector<unsigned, 4> ClobberRegs;
73865ffd83dbSDimitry Andric 
73875ffd83dbSDimitry Andric   SmallVector<AsmRewrite, 4> AsmStrRewrites;
73885ffd83dbSDimitry Andric 
73895ffd83dbSDimitry Andric   // Prime the lexer.
73905ffd83dbSDimitry Andric   Lex();
73915ffd83dbSDimitry Andric 
73925ffd83dbSDimitry Andric   // While we have input, parse each statement.
73935ffd83dbSDimitry Andric   unsigned InputIdx = 0;
73945ffd83dbSDimitry Andric   unsigned OutputIdx = 0;
73955ffd83dbSDimitry Andric   while (getLexer().isNot(AsmToken::Eof)) {
73965ffd83dbSDimitry Andric     // Parse curly braces marking block start/end.
73975ffd83dbSDimitry Andric     if (parseCurlyBlockScope(AsmStrRewrites))
73985ffd83dbSDimitry Andric       continue;
73995ffd83dbSDimitry Andric 
74005ffd83dbSDimitry Andric     ParseStatementInfo Info(&AsmStrRewrites);
74015ffd83dbSDimitry Andric     bool StatementErr = parseStatement(Info, &SI);
74025ffd83dbSDimitry Andric 
74035ffd83dbSDimitry Andric     if (StatementErr || Info.ParseError) {
74045ffd83dbSDimitry Andric       // Emit pending errors if any exist.
74055ffd83dbSDimitry Andric       printPendingErrors();
74065ffd83dbSDimitry Andric       return true;
74075ffd83dbSDimitry Andric     }
74085ffd83dbSDimitry Andric 
74095ffd83dbSDimitry Andric     // No pending error should exist here.
74105ffd83dbSDimitry Andric     assert(!hasPendingError() && "unexpected error from parseStatement");
74115ffd83dbSDimitry Andric 
74125ffd83dbSDimitry Andric     if (Info.Opcode == ~0U)
74135ffd83dbSDimitry Andric       continue;
74145ffd83dbSDimitry Andric 
74155ffd83dbSDimitry Andric     const MCInstrDesc &Desc = MII->get(Info.Opcode);
74165ffd83dbSDimitry Andric 
74175ffd83dbSDimitry Andric     // Build the list of clobbers, outputs and inputs.
74185ffd83dbSDimitry Andric     for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
74195ffd83dbSDimitry Andric       MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
74205ffd83dbSDimitry Andric 
74215ffd83dbSDimitry Andric       // Register operand.
74225ffd83dbSDimitry Andric       if (Operand.isReg() && !Operand.needAddressOf() &&
74235ffd83dbSDimitry Andric           !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {
74245ffd83dbSDimitry Andric         unsigned NumDefs = Desc.getNumDefs();
74255ffd83dbSDimitry Andric         // Clobber.
74265ffd83dbSDimitry Andric         if (NumDefs && Operand.getMCOperandNum() < NumDefs)
74275ffd83dbSDimitry Andric           ClobberRegs.push_back(Operand.getReg());
74285ffd83dbSDimitry Andric         continue;
74295ffd83dbSDimitry Andric       }
74305ffd83dbSDimitry Andric 
74315ffd83dbSDimitry Andric       // Expr/Input or Output.
74325ffd83dbSDimitry Andric       StringRef SymName = Operand.getSymName();
74335ffd83dbSDimitry Andric       if (SymName.empty())
74345ffd83dbSDimitry Andric         continue;
74355ffd83dbSDimitry Andric 
74365ffd83dbSDimitry Andric       void *OpDecl = Operand.getOpDecl();
74375ffd83dbSDimitry Andric       if (!OpDecl)
74385ffd83dbSDimitry Andric         continue;
74395ffd83dbSDimitry Andric 
74405ffd83dbSDimitry Andric       StringRef Constraint = Operand.getConstraint();
74415ffd83dbSDimitry Andric       if (Operand.isImm()) {
74425ffd83dbSDimitry Andric         // Offset as immediate.
74435ffd83dbSDimitry Andric         if (Operand.isOffsetOfLocal())
74445ffd83dbSDimitry Andric           Constraint = "r";
74455ffd83dbSDimitry Andric         else
74465ffd83dbSDimitry Andric           Constraint = "i";
74475ffd83dbSDimitry Andric       }
74485ffd83dbSDimitry Andric 
74495ffd83dbSDimitry Andric       bool isOutput = (i == 1) && Desc.mayStore();
74505ffd83dbSDimitry Andric       SMLoc Start = SMLoc::getFromPointer(SymName.data());
74515ffd83dbSDimitry Andric       if (isOutput) {
74525ffd83dbSDimitry Andric         ++InputIdx;
74535ffd83dbSDimitry Andric         OutputDecls.push_back(OpDecl);
74545ffd83dbSDimitry Andric         OutputDeclsAddressOf.push_back(Operand.needAddressOf());
74555ffd83dbSDimitry Andric         OutputConstraints.push_back(("=" + Constraint).str());
74565ffd83dbSDimitry Andric         AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size());
74575ffd83dbSDimitry Andric       } else {
74585ffd83dbSDimitry Andric         InputDecls.push_back(OpDecl);
74595ffd83dbSDimitry Andric         InputDeclsAddressOf.push_back(Operand.needAddressOf());
74605ffd83dbSDimitry Andric         InputConstraints.push_back(Constraint.str());
7461*bdd1243dSDimitry Andric         if (Desc.operands()[i - 1].isBranchTarget())
74625ffd83dbSDimitry Andric           AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size());
74635ffd83dbSDimitry Andric         else
74645ffd83dbSDimitry Andric           AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
74655ffd83dbSDimitry Andric       }
74665ffd83dbSDimitry Andric     }
74675ffd83dbSDimitry Andric 
74685ffd83dbSDimitry Andric     // Consider implicit defs to be clobbers.  Think of cpuid and push.
7469*bdd1243dSDimitry Andric     llvm::append_range(ClobberRegs, Desc.implicit_defs());
74705ffd83dbSDimitry Andric   }
74715ffd83dbSDimitry Andric 
74725ffd83dbSDimitry Andric   // Set the number of Outputs and Inputs.
74735ffd83dbSDimitry Andric   NumOutputs = OutputDecls.size();
74745ffd83dbSDimitry Andric   NumInputs = InputDecls.size();
74755ffd83dbSDimitry Andric 
74765ffd83dbSDimitry Andric   // Set the unique clobbers.
74775ffd83dbSDimitry Andric   array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
74785ffd83dbSDimitry Andric   ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()),
74795ffd83dbSDimitry Andric                     ClobberRegs.end());
74805ffd83dbSDimitry Andric   Clobbers.assign(ClobberRegs.size(), std::string());
74815ffd83dbSDimitry Andric   for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
74825ffd83dbSDimitry Andric     raw_string_ostream OS(Clobbers[I]);
74835ffd83dbSDimitry Andric     IP->printRegName(OS, ClobberRegs[I]);
74845ffd83dbSDimitry Andric   }
74855ffd83dbSDimitry Andric 
74865ffd83dbSDimitry Andric   // Merge the various outputs and inputs.  Output are expected first.
74875ffd83dbSDimitry Andric   if (NumOutputs || NumInputs) {
74885ffd83dbSDimitry Andric     unsigned NumExprs = NumOutputs + NumInputs;
74895ffd83dbSDimitry Andric     OpDecls.resize(NumExprs);
74905ffd83dbSDimitry Andric     Constraints.resize(NumExprs);
74915ffd83dbSDimitry Andric     for (unsigned i = 0; i < NumOutputs; ++i) {
74925ffd83dbSDimitry Andric       OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
74935ffd83dbSDimitry Andric       Constraints[i] = OutputConstraints[i];
74945ffd83dbSDimitry Andric     }
74955ffd83dbSDimitry Andric     for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
74965ffd83dbSDimitry Andric       OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
74975ffd83dbSDimitry Andric       Constraints[j] = InputConstraints[i];
74985ffd83dbSDimitry Andric     }
74995ffd83dbSDimitry Andric   }
75005ffd83dbSDimitry Andric 
75015ffd83dbSDimitry Andric   // Build the IR assembly string.
75025ffd83dbSDimitry Andric   std::string AsmStringIR;
75035ffd83dbSDimitry Andric   raw_string_ostream OS(AsmStringIR);
75045ffd83dbSDimitry Andric   StringRef ASMString =
75055ffd83dbSDimitry Andric       SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer();
75065ffd83dbSDimitry Andric   const char *AsmStart = ASMString.begin();
75075ffd83dbSDimitry Andric   const char *AsmEnd = ASMString.end();
75085ffd83dbSDimitry Andric   array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
75095ffd83dbSDimitry Andric   for (auto it = AsmStrRewrites.begin(); it != AsmStrRewrites.end(); ++it) {
75105ffd83dbSDimitry Andric     const AsmRewrite &AR = *it;
75115ffd83dbSDimitry Andric     // Check if this has already been covered by another rewrite...
75125ffd83dbSDimitry Andric     if (AR.Done)
75135ffd83dbSDimitry Andric       continue;
75145ffd83dbSDimitry Andric     AsmRewriteKind Kind = AR.Kind;
75155ffd83dbSDimitry Andric 
75165ffd83dbSDimitry Andric     const char *Loc = AR.Loc.getPointer();
75175ffd83dbSDimitry Andric     assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
75185ffd83dbSDimitry Andric 
75195ffd83dbSDimitry Andric     // Emit everything up to the immediate/expression.
75205ffd83dbSDimitry Andric     if (unsigned Len = Loc - AsmStart)
75215ffd83dbSDimitry Andric       OS << StringRef(AsmStart, Len);
75225ffd83dbSDimitry Andric 
75235ffd83dbSDimitry Andric     // Skip the original expression.
75245ffd83dbSDimitry Andric     if (Kind == AOK_Skip) {
75255ffd83dbSDimitry Andric       AsmStart = Loc + AR.Len;
75265ffd83dbSDimitry Andric       continue;
75275ffd83dbSDimitry Andric     }
75285ffd83dbSDimitry Andric 
75295ffd83dbSDimitry Andric     unsigned AdditionalSkip = 0;
75305ffd83dbSDimitry Andric     // Rewrite expressions in $N notation.
75315ffd83dbSDimitry Andric     switch (Kind) {
75325ffd83dbSDimitry Andric     default:
75335ffd83dbSDimitry Andric       break;
75345ffd83dbSDimitry Andric     case AOK_IntelExpr:
75355ffd83dbSDimitry Andric       assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
75365ffd83dbSDimitry Andric       if (AR.IntelExp.NeedBracs)
75375ffd83dbSDimitry Andric         OS << "[";
75385ffd83dbSDimitry Andric       if (AR.IntelExp.hasBaseReg())
75395ffd83dbSDimitry Andric         OS << AR.IntelExp.BaseReg;
75405ffd83dbSDimitry Andric       if (AR.IntelExp.hasIndexReg())
75415ffd83dbSDimitry Andric         OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
75425ffd83dbSDimitry Andric            << AR.IntelExp.IndexReg;
75435ffd83dbSDimitry Andric       if (AR.IntelExp.Scale > 1)
75445ffd83dbSDimitry Andric         OS << " * $$" << AR.IntelExp.Scale;
75455ffd83dbSDimitry Andric       if (AR.IntelExp.hasOffset()) {
75465ffd83dbSDimitry Andric         if (AR.IntelExp.hasRegs())
75475ffd83dbSDimitry Andric           OS << " + ";
75485ffd83dbSDimitry Andric         // Fuse this rewrite with a rewrite of the offset name, if present.
75495ffd83dbSDimitry Andric         StringRef OffsetName = AR.IntelExp.OffsetName;
75505ffd83dbSDimitry Andric         SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());
75515ffd83dbSDimitry Andric         size_t OffsetLen = OffsetName.size();
75525ffd83dbSDimitry Andric         auto rewrite_it = std::find_if(
75535ffd83dbSDimitry Andric             it, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
75545ffd83dbSDimitry Andric               return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
75555ffd83dbSDimitry Andric                      (FusingAR.Kind == AOK_Input ||
75565ffd83dbSDimitry Andric                       FusingAR.Kind == AOK_CallInput);
75575ffd83dbSDimitry Andric             });
75585ffd83dbSDimitry Andric         if (rewrite_it == AsmStrRewrites.end()) {
75595ffd83dbSDimitry Andric           OS << "offset " << OffsetName;
75605ffd83dbSDimitry Andric         } else if (rewrite_it->Kind == AOK_CallInput) {
75615ffd83dbSDimitry Andric           OS << "${" << InputIdx++ << ":P}";
75625ffd83dbSDimitry Andric           rewrite_it->Done = true;
75635ffd83dbSDimitry Andric         } else {
75645ffd83dbSDimitry Andric           OS << '$' << InputIdx++;
75655ffd83dbSDimitry Andric           rewrite_it->Done = true;
75665ffd83dbSDimitry Andric         }
75675ffd83dbSDimitry Andric       }
75685ffd83dbSDimitry Andric       if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
75695ffd83dbSDimitry Andric         OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
75705ffd83dbSDimitry Andric       if (AR.IntelExp.NeedBracs)
75715ffd83dbSDimitry Andric         OS << "]";
75725ffd83dbSDimitry Andric       break;
75735ffd83dbSDimitry Andric     case AOK_Label:
75745ffd83dbSDimitry Andric       OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
75755ffd83dbSDimitry Andric       break;
75765ffd83dbSDimitry Andric     case AOK_Input:
75775ffd83dbSDimitry Andric       OS << '$' << InputIdx++;
75785ffd83dbSDimitry Andric       break;
75795ffd83dbSDimitry Andric     case AOK_CallInput:
75805ffd83dbSDimitry Andric       OS << "${" << InputIdx++ << ":P}";
75815ffd83dbSDimitry Andric       break;
75825ffd83dbSDimitry Andric     case AOK_Output:
75835ffd83dbSDimitry Andric       OS << '$' << OutputIdx++;
75845ffd83dbSDimitry Andric       break;
75855ffd83dbSDimitry Andric     case AOK_SizeDirective:
75865ffd83dbSDimitry Andric       switch (AR.Val) {
75875ffd83dbSDimitry Andric       default: break;
75885ffd83dbSDimitry Andric       case 8:  OS << "byte ptr "; break;
75895ffd83dbSDimitry Andric       case 16: OS << "word ptr "; break;
75905ffd83dbSDimitry Andric       case 32: OS << "dword ptr "; break;
75915ffd83dbSDimitry Andric       case 64: OS << "qword ptr "; break;
75925ffd83dbSDimitry Andric       case 80: OS << "xword ptr "; break;
75935ffd83dbSDimitry Andric       case 128: OS << "xmmword ptr "; break;
75945ffd83dbSDimitry Andric       case 256: OS << "ymmword ptr "; break;
75955ffd83dbSDimitry Andric       }
75965ffd83dbSDimitry Andric       break;
75975ffd83dbSDimitry Andric     case AOK_Emit:
75985ffd83dbSDimitry Andric       OS << ".byte";
75995ffd83dbSDimitry Andric       break;
76005ffd83dbSDimitry Andric     case AOK_Align: {
76015ffd83dbSDimitry Andric       // MS alignment directives are measured in bytes. If the native assembler
76025ffd83dbSDimitry Andric       // measures alignment in bytes, we can pass it straight through.
76035ffd83dbSDimitry Andric       OS << ".align";
76045ffd83dbSDimitry Andric       if (getContext().getAsmInfo()->getAlignmentIsInBytes())
76055ffd83dbSDimitry Andric         break;
76065ffd83dbSDimitry Andric 
76075ffd83dbSDimitry Andric       // Alignment is in log2 form, so print that instead and skip the original
76085ffd83dbSDimitry Andric       // immediate.
76095ffd83dbSDimitry Andric       unsigned Val = AR.Val;
76105ffd83dbSDimitry Andric       OS << ' ' << Val;
76115ffd83dbSDimitry Andric       assert(Val < 10 && "Expected alignment less then 2^10.");
76125ffd83dbSDimitry Andric       AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
76135ffd83dbSDimitry Andric       break;
76145ffd83dbSDimitry Andric     }
76155ffd83dbSDimitry Andric     case AOK_EVEN:
76165ffd83dbSDimitry Andric       OS << ".even";
76175ffd83dbSDimitry Andric       break;
76185ffd83dbSDimitry Andric     case AOK_EndOfStatement:
76195ffd83dbSDimitry Andric       OS << "\n\t";
76205ffd83dbSDimitry Andric       break;
76215ffd83dbSDimitry Andric     }
76225ffd83dbSDimitry Andric 
76235ffd83dbSDimitry Andric     // Skip the original expression.
76245ffd83dbSDimitry Andric     AsmStart = Loc + AR.Len + AdditionalSkip;
76255ffd83dbSDimitry Andric   }
76265ffd83dbSDimitry Andric 
76275ffd83dbSDimitry Andric   // Emit the remainder of the asm string.
76285ffd83dbSDimitry Andric   if (AsmStart != AsmEnd)
76295ffd83dbSDimitry Andric     OS << StringRef(AsmStart, AsmEnd - AsmStart);
76305ffd83dbSDimitry Andric 
76315ffd83dbSDimitry Andric   AsmString = OS.str();
76325ffd83dbSDimitry Andric   return false;
76335ffd83dbSDimitry Andric }
76345ffd83dbSDimitry Andric 
7635fe6060f1SDimitry Andric void MasmParser::initializeBuiltinSymbolMap() {
7636fe6060f1SDimitry Andric   // Numeric built-ins (supported in all versions)
7637fe6060f1SDimitry Andric   BuiltinSymbolMap["@version"] = BI_VERSION;
7638fe6060f1SDimitry Andric   BuiltinSymbolMap["@line"] = BI_LINE;
7639fe6060f1SDimitry Andric 
7640fe6060f1SDimitry Andric   // Text built-ins (supported in all versions)
7641fe6060f1SDimitry Andric   BuiltinSymbolMap["@date"] = BI_DATE;
7642fe6060f1SDimitry Andric   BuiltinSymbolMap["@time"] = BI_TIME;
7643fe6060f1SDimitry Andric   BuiltinSymbolMap["@filecur"] = BI_FILECUR;
7644fe6060f1SDimitry Andric   BuiltinSymbolMap["@filename"] = BI_FILENAME;
7645fe6060f1SDimitry Andric   BuiltinSymbolMap["@curseg"] = BI_CURSEG;
7646fe6060f1SDimitry Andric 
7647fe6060f1SDimitry Andric   // Some built-ins exist only for MASM32 (32-bit x86)
7648fe6060f1SDimitry Andric   if (getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
7649fe6060f1SDimitry Andric       Triple::x86) {
7650fe6060f1SDimitry Andric     // Numeric built-ins
7651fe6060f1SDimitry Andric     // BuiltinSymbolMap["@cpu"] = BI_CPU;
7652fe6060f1SDimitry Andric     // BuiltinSymbolMap["@interface"] = BI_INTERFACE;
7653fe6060f1SDimitry Andric     // BuiltinSymbolMap["@wordsize"] = BI_WORDSIZE;
7654fe6060f1SDimitry Andric     // BuiltinSymbolMap["@codesize"] = BI_CODESIZE;
7655fe6060f1SDimitry Andric     // BuiltinSymbolMap["@datasize"] = BI_DATASIZE;
7656fe6060f1SDimitry Andric     // BuiltinSymbolMap["@model"] = BI_MODEL;
7657fe6060f1SDimitry Andric 
7658fe6060f1SDimitry Andric     // Text built-ins
7659fe6060f1SDimitry Andric     // BuiltinSymbolMap["@code"] = BI_CODE;
7660fe6060f1SDimitry Andric     // BuiltinSymbolMap["@data"] = BI_DATA;
7661fe6060f1SDimitry Andric     // BuiltinSymbolMap["@fardata?"] = BI_FARDATA;
7662fe6060f1SDimitry Andric     // BuiltinSymbolMap["@stack"] = BI_STACK;
7663fe6060f1SDimitry Andric   }
7664fe6060f1SDimitry Andric }
7665fe6060f1SDimitry Andric 
7666fe6060f1SDimitry Andric const MCExpr *MasmParser::evaluateBuiltinValue(BuiltinSymbol Symbol,
7667fe6060f1SDimitry Andric                                                SMLoc StartLoc) {
7668fe6060f1SDimitry Andric   switch (Symbol) {
7669fe6060f1SDimitry Andric   default:
7670fe6060f1SDimitry Andric     return nullptr;
7671fe6060f1SDimitry Andric   case BI_VERSION:
7672fe6060f1SDimitry Andric     // Match a recent version of ML.EXE.
7673fe6060f1SDimitry Andric     return MCConstantExpr::create(1427, getContext());
7674fe6060f1SDimitry Andric   case BI_LINE: {
7675fe6060f1SDimitry Andric     int64_t Line;
7676fe6060f1SDimitry Andric     if (ActiveMacros.empty())
7677fe6060f1SDimitry Andric       Line = SrcMgr.FindLineNumber(StartLoc, CurBuffer);
7678fe6060f1SDimitry Andric     else
7679fe6060f1SDimitry Andric       Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
7680fe6060f1SDimitry Andric                                    ActiveMacros.front()->ExitBuffer);
7681fe6060f1SDimitry Andric     return MCConstantExpr::create(Line, getContext());
7682fe6060f1SDimitry Andric   }
7683fe6060f1SDimitry Andric   }
7684fe6060f1SDimitry Andric   llvm_unreachable("unhandled built-in symbol");
7685fe6060f1SDimitry Andric }
7686fe6060f1SDimitry Andric 
7687*bdd1243dSDimitry Andric std::optional<std::string>
7688fe6060f1SDimitry Andric MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
7689fe6060f1SDimitry Andric   switch (Symbol) {
7690fe6060f1SDimitry Andric   default:
7691fe6060f1SDimitry Andric     return {};
7692fe6060f1SDimitry Andric   case BI_DATE: {
7693fe6060f1SDimitry Andric     // Current local date, formatted MM/DD/YY
7694fe6060f1SDimitry Andric     char TmpBuffer[sizeof("mm/dd/yy")];
7695fe6060f1SDimitry Andric     const size_t Len = strftime(TmpBuffer, sizeof(TmpBuffer), "%D", &TM);
7696fe6060f1SDimitry Andric     return std::string(TmpBuffer, Len);
7697fe6060f1SDimitry Andric   }
7698fe6060f1SDimitry Andric   case BI_TIME: {
7699fe6060f1SDimitry Andric     // Current local time, formatted HH:MM:SS (24-hour clock)
7700fe6060f1SDimitry Andric     char TmpBuffer[sizeof("hh:mm:ss")];
7701fe6060f1SDimitry Andric     const size_t Len = strftime(TmpBuffer, sizeof(TmpBuffer), "%T", &TM);
7702fe6060f1SDimitry Andric     return std::string(TmpBuffer, Len);
7703fe6060f1SDimitry Andric   }
7704fe6060f1SDimitry Andric   case BI_FILECUR:
7705fe6060f1SDimitry Andric     return SrcMgr
7706fe6060f1SDimitry Andric         .getMemoryBuffer(
7707fe6060f1SDimitry Andric             ActiveMacros.empty() ? CurBuffer : ActiveMacros.front()->ExitBuffer)
7708fe6060f1SDimitry Andric         ->getBufferIdentifier()
7709fe6060f1SDimitry Andric         .str();
7710fe6060f1SDimitry Andric   case BI_FILENAME:
7711fe6060f1SDimitry Andric     return sys::path::stem(SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())
7712fe6060f1SDimitry Andric                                ->getBufferIdentifier())
7713fe6060f1SDimitry Andric         .upper();
7714fe6060f1SDimitry Andric   case BI_CURSEG:
7715fe6060f1SDimitry Andric     return getStreamer().getCurrentSectionOnly()->getName().str();
7716fe6060f1SDimitry Andric   }
7717fe6060f1SDimitry Andric   llvm_unreachable("unhandled built-in symbol");
7718fe6060f1SDimitry Andric }
7719fe6060f1SDimitry Andric 
77205ffd83dbSDimitry Andric /// Create an MCAsmParser instance.
77215ffd83dbSDimitry Andric MCAsmParser *llvm::createMCMasmParser(SourceMgr &SM, MCContext &C,
77225ffd83dbSDimitry Andric                                       MCStreamer &Out, const MCAsmInfo &MAI,
7723fe6060f1SDimitry Andric                                       struct tm TM, unsigned CB) {
7724fe6060f1SDimitry Andric   return new MasmParser(SM, C, Out, MAI, TM, CB);
77255ffd83dbSDimitry Andric }
7726