xref: /freebsd/contrib/llvm-project/llvm/lib/MC/MCParser/MasmParser.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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>
68bdd1243dSDimitry 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.
109bdd1243dSDimitry Andric   std::optional<std::string> ExitValue;
110e8d8bef9SDimitry Andric 
1115ffd83dbSDimitry Andric   SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
1125ffd83dbSDimitry Andric 
1135ffd83dbSDimitry Andric   ParseStatementInfo() = delete;
ParseStatementInfo__anon60b61cd60111::ParseStatementInfo1145ffd83dbSDimitry 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;
140bdd1243dSDimitry 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;
IntFieldInfo__anon60b61cd60111::IntFieldInfo1535ffd83dbSDimitry Andric   IntFieldInfo(const SmallVector<const MCExpr *, 1> &V) { Values = V; }
IntFieldInfo__anon60b61cd60111::IntFieldInfo15406c3fb27SDimitry Andric   IntFieldInfo(SmallVector<const MCExpr *, 1> &&V) { Values = std::move(V); }
1555ffd83dbSDimitry Andric };
1565ffd83dbSDimitry Andric struct RealFieldInfo {
1575ffd83dbSDimitry Andric   SmallVector<APInt, 1> AsIntValues;
1585ffd83dbSDimitry Andric 
1595ffd83dbSDimitry Andric   RealFieldInfo() = default;
RealFieldInfo__anon60b61cd60111::RealFieldInfo1605ffd83dbSDimitry Andric   RealFieldInfo(const SmallVector<APInt, 1> &V) { AsIntValues = V; }
RealFieldInfo__anon60b61cd60111::RealFieldInfo16106c3fb27SDimitry Andric   RealFieldInfo(SmallVector<APInt, 1> &&V) { AsIntValues = std::move(V); }
1625ffd83dbSDimitry Andric };
1635ffd83dbSDimitry Andric struct StructFieldInfo {
1645ffd83dbSDimitry Andric   std::vector<StructInitializer> Initializers;
1655ffd83dbSDimitry Andric   StructInfo Structure;
1665ffd83dbSDimitry Andric 
1675ffd83dbSDimitry Andric   StructFieldInfo() = default;
168bdd1243dSDimitry 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 
180bdd1243dSDimitry Andric   ~FieldInitializer();
181bdd1243dSDimitry Andric   FieldInitializer(FieldType FT);
1825ffd83dbSDimitry Andric 
183bdd1243dSDimitry Andric   FieldInitializer(SmallVector<const MCExpr *, 1> &&Values);
184bdd1243dSDimitry Andric   FieldInitializer(SmallVector<APInt, 1> &&AsIntValues);
1855ffd83dbSDimitry Andric   FieldInitializer(std::vector<StructInitializer> &&Initializers,
186bdd1243dSDimitry Andric                    struct StructInfo Structure);
1875ffd83dbSDimitry Andric 
188bdd1243dSDimitry Andric   FieldInitializer(const FieldInitializer &Initializer);
189bdd1243dSDimitry Andric   FieldInitializer(FieldInitializer &&Initializer);
1905ffd83dbSDimitry Andric 
191bdd1243dSDimitry Andric   FieldInitializer &operator=(const FieldInitializer &Initializer);
192bdd1243dSDimitry 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 
FieldInfo__anon60b61cd60111::FieldInfo2145ffd83dbSDimitry Andric   FieldInfo(FieldType FT) : Contents(FT) {}
2155ffd83dbSDimitry Andric };
2165ffd83dbSDimitry Andric 
StructFieldInfo(std::vector<StructInitializer> V,StructInfo S)217bdd1243dSDimitry Andric StructFieldInfo::StructFieldInfo(std::vector<StructInitializer> V,
218bdd1243dSDimitry Andric                                  StructInfo S) {
219bdd1243dSDimitry Andric   Initializers = std::move(V);
220bdd1243dSDimitry Andric   Structure = S;
221bdd1243dSDimitry Andric }
222bdd1243dSDimitry Andric 
StructInfo(StringRef StructName,bool Union,unsigned AlignmentValue)223bdd1243dSDimitry Andric StructInfo::StructInfo(StringRef StructName, bool Union,
224bdd1243dSDimitry Andric                        unsigned AlignmentValue)
225bdd1243dSDimitry Andric     : Name(StructName), IsUnion(Union), Alignment(AlignmentValue) {}
226bdd1243dSDimitry Andric 
addField(StringRef FieldName,FieldType FT,unsigned FieldAlignmentSize)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 
~FieldInitializer()242bdd1243dSDimitry Andric FieldInitializer::~FieldInitializer() {
243bdd1243dSDimitry Andric   switch (FT) {
244bdd1243dSDimitry Andric   case FT_INTEGRAL:
245bdd1243dSDimitry Andric     IntInfo.~IntFieldInfo();
246bdd1243dSDimitry Andric     break;
247bdd1243dSDimitry Andric   case FT_REAL:
248bdd1243dSDimitry Andric     RealInfo.~RealFieldInfo();
249bdd1243dSDimitry Andric     break;
250bdd1243dSDimitry Andric   case FT_STRUCT:
251bdd1243dSDimitry Andric     StructInfo.~StructFieldInfo();
252bdd1243dSDimitry Andric     break;
253bdd1243dSDimitry Andric   }
254bdd1243dSDimitry Andric }
255bdd1243dSDimitry Andric 
FieldInitializer(FieldType FT)256bdd1243dSDimitry Andric FieldInitializer::FieldInitializer(FieldType FT) : FT(FT) {
257bdd1243dSDimitry Andric   switch (FT) {
258bdd1243dSDimitry Andric   case FT_INTEGRAL:
259bdd1243dSDimitry Andric     new (&IntInfo) IntFieldInfo();
260bdd1243dSDimitry Andric     break;
261bdd1243dSDimitry Andric   case FT_REAL:
262bdd1243dSDimitry Andric     new (&RealInfo) RealFieldInfo();
263bdd1243dSDimitry Andric     break;
264bdd1243dSDimitry Andric   case FT_STRUCT:
265bdd1243dSDimitry Andric     new (&StructInfo) StructFieldInfo();
266bdd1243dSDimitry Andric     break;
267bdd1243dSDimitry Andric   }
268bdd1243dSDimitry Andric }
269bdd1243dSDimitry Andric 
FieldInitializer(SmallVector<const MCExpr *,1> && Values)270bdd1243dSDimitry Andric FieldInitializer::FieldInitializer(SmallVector<const MCExpr *, 1> &&Values)
271bdd1243dSDimitry Andric     : FT(FT_INTEGRAL) {
27206c3fb27SDimitry Andric   new (&IntInfo) IntFieldInfo(std::move(Values));
273bdd1243dSDimitry Andric }
274bdd1243dSDimitry Andric 
FieldInitializer(SmallVector<APInt,1> && AsIntValues)275bdd1243dSDimitry Andric FieldInitializer::FieldInitializer(SmallVector<APInt, 1> &&AsIntValues)
276bdd1243dSDimitry Andric     : FT(FT_REAL) {
27706c3fb27SDimitry Andric   new (&RealInfo) RealFieldInfo(std::move(AsIntValues));
278bdd1243dSDimitry Andric }
279bdd1243dSDimitry Andric 
FieldInitializer(std::vector<StructInitializer> && Initializers,struct StructInfo Structure)280bdd1243dSDimitry Andric FieldInitializer::FieldInitializer(
281bdd1243dSDimitry Andric     std::vector<StructInitializer> &&Initializers, struct StructInfo Structure)
282bdd1243dSDimitry Andric     : FT(FT_STRUCT) {
283bdd1243dSDimitry Andric   new (&StructInfo) StructFieldInfo(std::move(Initializers), Structure);
284bdd1243dSDimitry Andric }
285bdd1243dSDimitry Andric 
FieldInitializer(const FieldInitializer & Initializer)286bdd1243dSDimitry Andric FieldInitializer::FieldInitializer(const FieldInitializer &Initializer)
287bdd1243dSDimitry Andric     : FT(Initializer.FT) {
288bdd1243dSDimitry Andric   switch (FT) {
289bdd1243dSDimitry Andric   case FT_INTEGRAL:
290bdd1243dSDimitry Andric     new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
291bdd1243dSDimitry Andric     break;
292bdd1243dSDimitry Andric   case FT_REAL:
293bdd1243dSDimitry Andric     new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
294bdd1243dSDimitry Andric     break;
295bdd1243dSDimitry Andric   case FT_STRUCT:
296bdd1243dSDimitry Andric     new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
297bdd1243dSDimitry Andric     break;
298bdd1243dSDimitry Andric   }
299bdd1243dSDimitry Andric }
300bdd1243dSDimitry Andric 
FieldInitializer(FieldInitializer && Initializer)301bdd1243dSDimitry Andric FieldInitializer::FieldInitializer(FieldInitializer &&Initializer)
302bdd1243dSDimitry Andric     : FT(Initializer.FT) {
303bdd1243dSDimitry Andric   switch (FT) {
304bdd1243dSDimitry Andric   case FT_INTEGRAL:
305bdd1243dSDimitry Andric     new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
306bdd1243dSDimitry Andric     break;
307bdd1243dSDimitry Andric   case FT_REAL:
308bdd1243dSDimitry Andric     new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
309bdd1243dSDimitry Andric     break;
310bdd1243dSDimitry Andric   case FT_STRUCT:
311bdd1243dSDimitry Andric     new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
312bdd1243dSDimitry Andric     break;
313bdd1243dSDimitry Andric   }
314bdd1243dSDimitry Andric }
315bdd1243dSDimitry Andric 
316bdd1243dSDimitry Andric FieldInitializer &
operator =(const FieldInitializer & Initializer)317bdd1243dSDimitry Andric FieldInitializer::operator=(const FieldInitializer &Initializer) {
318bdd1243dSDimitry Andric   if (FT != Initializer.FT) {
319bdd1243dSDimitry Andric     switch (FT) {
320bdd1243dSDimitry Andric     case FT_INTEGRAL:
321bdd1243dSDimitry Andric       IntInfo.~IntFieldInfo();
322bdd1243dSDimitry Andric       break;
323bdd1243dSDimitry Andric     case FT_REAL:
324bdd1243dSDimitry Andric       RealInfo.~RealFieldInfo();
325bdd1243dSDimitry Andric       break;
326bdd1243dSDimitry Andric     case FT_STRUCT:
327bdd1243dSDimitry Andric       StructInfo.~StructFieldInfo();
328bdd1243dSDimitry Andric       break;
329bdd1243dSDimitry Andric     }
330bdd1243dSDimitry Andric   }
331bdd1243dSDimitry Andric   FT = Initializer.FT;
332bdd1243dSDimitry Andric   switch (FT) {
333bdd1243dSDimitry Andric   case FT_INTEGRAL:
334bdd1243dSDimitry Andric     IntInfo = Initializer.IntInfo;
335bdd1243dSDimitry Andric     break;
336bdd1243dSDimitry Andric   case FT_REAL:
337bdd1243dSDimitry Andric     RealInfo = Initializer.RealInfo;
338bdd1243dSDimitry Andric     break;
339bdd1243dSDimitry Andric   case FT_STRUCT:
340bdd1243dSDimitry Andric     StructInfo = Initializer.StructInfo;
341bdd1243dSDimitry Andric     break;
342bdd1243dSDimitry Andric   }
343bdd1243dSDimitry Andric   return *this;
344bdd1243dSDimitry Andric }
345bdd1243dSDimitry Andric 
operator =(FieldInitializer && Initializer)346bdd1243dSDimitry Andric FieldInitializer &FieldInitializer::operator=(FieldInitializer &&Initializer) {
347bdd1243dSDimitry Andric   if (FT != Initializer.FT) {
348bdd1243dSDimitry Andric     switch (FT) {
349bdd1243dSDimitry Andric     case FT_INTEGRAL:
350bdd1243dSDimitry Andric       IntInfo.~IntFieldInfo();
351bdd1243dSDimitry Andric       break;
352bdd1243dSDimitry Andric     case FT_REAL:
353bdd1243dSDimitry Andric       RealInfo.~RealFieldInfo();
354bdd1243dSDimitry Andric       break;
355bdd1243dSDimitry Andric     case FT_STRUCT:
356bdd1243dSDimitry Andric       StructInfo.~StructFieldInfo();
357bdd1243dSDimitry Andric       break;
358bdd1243dSDimitry Andric     }
359bdd1243dSDimitry Andric   }
360bdd1243dSDimitry Andric   FT = Initializer.FT;
361bdd1243dSDimitry Andric   switch (FT) {
362bdd1243dSDimitry Andric   case FT_INTEGRAL:
363bdd1243dSDimitry Andric     IntInfo = Initializer.IntInfo;
364bdd1243dSDimitry Andric     break;
365bdd1243dSDimitry Andric   case FT_REAL:
366bdd1243dSDimitry Andric     RealInfo = Initializer.RealInfo;
367bdd1243dSDimitry Andric     break;
368bdd1243dSDimitry Andric   case FT_STRUCT:
369bdd1243dSDimitry Andric     StructInfo = Initializer.StructInfo;
370bdd1243dSDimitry Andric     break;
371bdd1243dSDimitry Andric   }
372bdd1243dSDimitry Andric   return *this;
373bdd1243dSDimitry Andric }
374bdd1243dSDimitry 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;
CppHashInfoTy__anon60b61cd60111::MasmParser::CppHashInfoTy44104eeddc0SDimitry 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 
addDirectiveHandler(StringRef Directive,ExtensionDirectiveHandler Handler)4795ffd83dbSDimitry Andric   void addDirectiveHandler(StringRef Directive,
4805ffd83dbSDimitry Andric                            ExtensionDirectiveHandler Handler) override {
4815ffd83dbSDimitry Andric     ExtensionDirectiveMap[Directive] = Handler;
48206c3fb27SDimitry Andric     if (!DirectiveKindMap.contains(Directive)) {
4835ffd83dbSDimitry Andric       DirectiveKindMap[Directive] = DK_HANDLER_DIRECTIVE;
4845ffd83dbSDimitry Andric     }
4855ffd83dbSDimitry Andric   }
4865ffd83dbSDimitry Andric 
addAliasForDirective(StringRef Directive,StringRef Alias)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 
getSourceManager()4945ffd83dbSDimitry Andric   SourceMgr &getSourceManager() override { return SrcMgr; }
getLexer()4955ffd83dbSDimitry Andric   MCAsmLexer &getLexer() override { return Lexer; }
getContext()4965ffd83dbSDimitry Andric   MCContext &getContext() override { return Ctx; }
getStreamer()4975ffd83dbSDimitry Andric   MCStreamer &getStreamer() override { return Out; }
4985ffd83dbSDimitry Andric 
getCVContext()4995ffd83dbSDimitry Andric   CodeViewContext &getCVContext() { return Ctx.getCVContext(); }
5005ffd83dbSDimitry Andric 
getAssemblerDialect()5015ffd83dbSDimitry Andric   unsigned getAssemblerDialect() override {
5025ffd83dbSDimitry Andric     if (AssemblerDialect == ~0U)
5035ffd83dbSDimitry Andric       return MAI.getAssemblerDialect();
5045ffd83dbSDimitry Andric     else
5055ffd83dbSDimitry Andric       return AssemblerDialect;
5065ffd83dbSDimitry Andric   }
setAssemblerDialect(unsigned i)5075ffd83dbSDimitry Andric   void setAssemblerDialect(unsigned i) override {
5085ffd83dbSDimitry Andric     AssemblerDialect = i;
5095ffd83dbSDimitry Andric   }
5105ffd83dbSDimitry Andric 
511bdd1243dSDimitry Andric   void Note(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt) override;
512bdd1243dSDimitry Andric   bool Warning(SMLoc L, const Twine &Msg,
513bdd1243dSDimitry Andric                SMRange Range = std::nullopt) override;
514bdd1243dSDimitry Andric   bool printError(SMLoc L, const Twine &Msg,
515bdd1243dSDimitry Andric                   SMRange Range = std::nullopt) override;
5165ffd83dbSDimitry Andric 
517fe6060f1SDimitry Andric   enum ExpandKind { ExpandMacros, DoNotExpandMacros };
518fe6060f1SDimitry Andric   const AsmToken &Lex(ExpandKind ExpandNextToken);
Lex()519fe6060f1SDimitry Andric   const AsmToken &Lex() override { return Lex(ExpandMacros); }
5205ffd83dbSDimitry Andric 
setParsingMSInlineAsm(bool V)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   }
isParsingMSInlineAsm()5275ffd83dbSDimitry Andric   bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
5285ffd83dbSDimitry Andric 
isParsingMasm() const5295ffd83dbSDimitry 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);
parseIdentifier(StringRef & Res)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?
isInsideMacroInstantiation()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 
printMessage(SMLoc Loc,SourceMgr::DiagKind Kind,const Twine & Msg,SMRange Range=std::nullopt) const6215ffd83dbSDimitry Andric   void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
622bdd1243dSDimitry 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 
849bdd1243dSDimitry 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);
96506c3fb27SDimitry Andric   bool parseDirectiveCFIWindowSave(SMLoc DirectiveLoc);
9665ffd83dbSDimitry Andric   bool parseDirectiveCFISections();
9675ffd83dbSDimitry Andric   bool parseDirectiveCFIStartProc();
9685ffd83dbSDimitry Andric   bool parseDirectiveCFIEndProc();
96906c3fb27SDimitry Andric   bool parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc);
9705ffd83dbSDimitry Andric   bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc);
97106c3fb27SDimitry Andric   bool parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc);
9725ffd83dbSDimitry Andric   bool parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc);
9735ffd83dbSDimitry Andric   bool parseDirectiveCFIOffset(SMLoc DirectiveLoc);
9745ffd83dbSDimitry Andric   bool parseDirectiveCFIRelOffset(SMLoc DirectiveLoc);
9755ffd83dbSDimitry Andric   bool parseDirectiveCFIPersonalityOrLsda(bool IsPersonality);
97606c3fb27SDimitry Andric   bool parseDirectiveCFIRememberState(SMLoc DirectiveLoc);
97706c3fb27SDimitry Andric   bool parseDirectiveCFIRestoreState(SMLoc DirectiveLoc);
9785ffd83dbSDimitry Andric   bool parseDirectiveCFISameValue(SMLoc DirectiveLoc);
9795ffd83dbSDimitry Andric   bool parseDirectiveCFIRestore(SMLoc DirectiveLoc);
98006c3fb27SDimitry Andric   bool parseDirectiveCFIEscape(SMLoc DirectiveLoc);
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 
1084bdd1243dSDimitry Andric extern cl::opt<unsigned> AsmMacroMaxNestingDepth;
1085bdd1243dSDimitry Andric 
10865ffd83dbSDimitry Andric extern MCAsmParserExtension *createCOFFMasmParser();
10875ffd83dbSDimitry Andric 
10885ffd83dbSDimitry Andric } // end namespace llvm
10895ffd83dbSDimitry Andric 
10905ffd83dbSDimitry Andric enum { DEFAULT_ADDRSPACE = 0 };
10915ffd83dbSDimitry Andric 
MasmParser(SourceMgr & SM,MCContext & Ctx,MCStreamer & Out,const MCAsmInfo & MAI,struct tm TM,unsigned CB)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 
~MasmParser()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 
printMacroInstantiations()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 
Note(SMLoc L,const Twine & Msg,SMRange Range)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 
Warning(SMLoc L,const Twine & Msg,SMRange Range)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 
printError(SMLoc L,const Twine & Msg,SMRange Range)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 
enterIncludeFile(const std::string & Filename)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 
jumpToLoc(SMLoc Loc,unsigned InBuffer,bool EndStatementAtEOF)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 
expandMacros()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 
1202bdd1243dSDimitry 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 
Lex(ExpandKind ExpandNextToken)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 
peekTok(bool ShouldSkipSpace)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 
enabledGenDwarfForAssembly()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())
1326bdd1243dSDimitry Andric       getContext().setMCLineTableRootFile(
1327bdd1243dSDimitry Andric           /*CUID=*/0, getContext().getCompilationDir(), FirstCppHashFilename,
1328bdd1243dSDimitry 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 
Run(bool NoInitialTextSection,bool NoFinalize)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()) {
1424*0fca6ea1SDimitry Andric         MCSymbol *Sym = TableEntry.getValue().Symbol;
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.
1428*0fca6ea1SDimitry Andric         if (Sym && Sym->isTemporary() && !Sym->isVariable() &&
1429*0fca6ea1SDimitry Andric             !Sym->isDefined())
14305ffd83dbSDimitry Andric           // FIXME: We would really like to refer back to where the symbol was
14315ffd83dbSDimitry Andric           // first referenced for a source location. We need to add something
14325ffd83dbSDimitry Andric           // to track that. Currently, we just point to the end of the file.
14335ffd83dbSDimitry Andric           printError(getTok().getLoc(), "assembler local symbol '" +
14345ffd83dbSDimitry Andric                                             Sym->getName() + "' not defined");
14355ffd83dbSDimitry Andric       }
14365ffd83dbSDimitry Andric     }
14375ffd83dbSDimitry Andric 
14385ffd83dbSDimitry Andric     // Temporary symbols like the ones for directional jumps don't go in the
14395ffd83dbSDimitry Andric     // symbol table. They also need to be diagnosed in all (final) cases.
14405ffd83dbSDimitry Andric     for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
14415ffd83dbSDimitry Andric       if (std::get<2>(LocSym)->isUndefined()) {
14425ffd83dbSDimitry Andric         // Reset the state of any "# line file" directives we've seen to the
14435ffd83dbSDimitry Andric         // context as it was at the diagnostic site.
14445ffd83dbSDimitry Andric         CppHashInfo = std::get<1>(LocSym);
14455ffd83dbSDimitry Andric         printError(std::get<0>(LocSym), "directional label undefined");
14465ffd83dbSDimitry Andric       }
14475ffd83dbSDimitry Andric     }
14485ffd83dbSDimitry Andric   }
14495ffd83dbSDimitry Andric 
14505ffd83dbSDimitry Andric   // Finalize the output stream if there are no errors and if the client wants
14515ffd83dbSDimitry Andric   // us to.
14525ffd83dbSDimitry Andric   if (!HadError && !NoFinalize)
145381ad6265SDimitry Andric     Out.finish(Lexer.getLoc());
14545ffd83dbSDimitry Andric 
14555ffd83dbSDimitry Andric   return HadError || getContext().hadError();
14565ffd83dbSDimitry Andric }
14575ffd83dbSDimitry Andric 
checkForValidSection()14585ffd83dbSDimitry Andric bool MasmParser::checkForValidSection() {
14595ffd83dbSDimitry Andric   if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) {
1460349cc55cSDimitry Andric     Out.initSections(false, getTargetParser().getSTI());
14615ffd83dbSDimitry Andric     return Error(getTok().getLoc(),
14625ffd83dbSDimitry Andric                  "expected section directive before assembly directive");
14635ffd83dbSDimitry Andric   }
14645ffd83dbSDimitry Andric   return false;
14655ffd83dbSDimitry Andric }
14665ffd83dbSDimitry Andric 
14675ffd83dbSDimitry Andric /// Throw away the rest of the line for testing purposes.
eatToEndOfStatement()14685ffd83dbSDimitry Andric void MasmParser::eatToEndOfStatement() {
1469e8d8bef9SDimitry Andric   while (Lexer.isNot(AsmToken::EndOfStatement)) {
1470e8d8bef9SDimitry Andric     if (Lexer.is(AsmToken::Eof)) {
1471e8d8bef9SDimitry Andric       SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
1472e8d8bef9SDimitry Andric       if (ParentIncludeLoc == SMLoc()) {
1473e8d8bef9SDimitry Andric         break;
1474e8d8bef9SDimitry Andric       }
1475e8d8bef9SDimitry Andric 
1476e8d8bef9SDimitry Andric       EndStatementAtEOFStack.pop_back();
1477e8d8bef9SDimitry Andric       jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1478e8d8bef9SDimitry Andric     }
1479e8d8bef9SDimitry Andric 
14805ffd83dbSDimitry Andric     Lexer.Lex();
1481e8d8bef9SDimitry Andric   }
14825ffd83dbSDimitry Andric 
14835ffd83dbSDimitry Andric   // Eat EOL.
14845ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::EndOfStatement))
14855ffd83dbSDimitry Andric     Lexer.Lex();
14865ffd83dbSDimitry Andric }
14875ffd83dbSDimitry Andric 
1488e8d8bef9SDimitry Andric SmallVector<StringRef, 1>
parseStringRefsTo(AsmToken::TokenKind EndTok)1489e8d8bef9SDimitry Andric MasmParser::parseStringRefsTo(AsmToken::TokenKind EndTok) {
1490e8d8bef9SDimitry Andric   SmallVector<StringRef, 1> Refs;
1491e8d8bef9SDimitry Andric   const char *Start = getTok().getLoc().getPointer();
1492e8d8bef9SDimitry Andric   while (Lexer.isNot(EndTok)) {
1493e8d8bef9SDimitry Andric     if (Lexer.is(AsmToken::Eof)) {
1494e8d8bef9SDimitry Andric       SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
1495e8d8bef9SDimitry Andric       if (ParentIncludeLoc == SMLoc()) {
1496e8d8bef9SDimitry Andric         break;
1497e8d8bef9SDimitry Andric       }
1498e8d8bef9SDimitry Andric       Refs.emplace_back(Start, getTok().getLoc().getPointer() - Start);
1499e8d8bef9SDimitry Andric 
1500e8d8bef9SDimitry Andric       EndStatementAtEOFStack.pop_back();
1501e8d8bef9SDimitry Andric       jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1502e8d8bef9SDimitry Andric       Lexer.Lex();
1503e8d8bef9SDimitry Andric       Start = getTok().getLoc().getPointer();
1504e8d8bef9SDimitry Andric     } else {
1505e8d8bef9SDimitry Andric       Lexer.Lex();
1506e8d8bef9SDimitry Andric     }
1507e8d8bef9SDimitry Andric   }
1508e8d8bef9SDimitry Andric   Refs.emplace_back(Start, getTok().getLoc().getPointer() - Start);
1509e8d8bef9SDimitry Andric   return Refs;
1510e8d8bef9SDimitry Andric }
1511e8d8bef9SDimitry Andric 
parseStringTo(AsmToken::TokenKind EndTok)1512e8d8bef9SDimitry Andric std::string MasmParser::parseStringTo(AsmToken::TokenKind EndTok) {
1513e8d8bef9SDimitry Andric   SmallVector<StringRef, 1> Refs = parseStringRefsTo(EndTok);
1514e8d8bef9SDimitry Andric   std::string Str;
1515e8d8bef9SDimitry Andric   for (StringRef S : Refs) {
1516e8d8bef9SDimitry Andric     Str.append(S.str());
1517e8d8bef9SDimitry Andric   }
1518e8d8bef9SDimitry Andric   return Str;
1519e8d8bef9SDimitry Andric }
1520e8d8bef9SDimitry Andric 
parseStringToEndOfStatement()15215ffd83dbSDimitry Andric StringRef MasmParser::parseStringToEndOfStatement() {
15225ffd83dbSDimitry Andric   const char *Start = getTok().getLoc().getPointer();
15235ffd83dbSDimitry Andric 
15245ffd83dbSDimitry Andric   while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
15255ffd83dbSDimitry Andric     Lexer.Lex();
15265ffd83dbSDimitry Andric 
15275ffd83dbSDimitry Andric   const char *End = getTok().getLoc().getPointer();
15285ffd83dbSDimitry Andric   return StringRef(Start, End - Start);
15295ffd83dbSDimitry Andric }
15305ffd83dbSDimitry Andric 
15315ffd83dbSDimitry Andric /// Parse a paren expression and return it.
15325ffd83dbSDimitry Andric /// NOTE: This assumes the leading '(' has already been consumed.
15335ffd83dbSDimitry Andric ///
15345ffd83dbSDimitry Andric /// parenexpr ::= expr)
15355ffd83dbSDimitry Andric ///
parseParenExpr(const MCExpr * & Res,SMLoc & EndLoc)15365ffd83dbSDimitry Andric bool MasmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
15375ffd83dbSDimitry Andric   if (parseExpression(Res))
15385ffd83dbSDimitry Andric     return true;
15395ffd83dbSDimitry Andric   EndLoc = Lexer.getTok().getEndLoc();
154004eeddc0SDimitry Andric   return parseRParen();
15415ffd83dbSDimitry Andric }
15425ffd83dbSDimitry Andric 
15435ffd83dbSDimitry Andric /// Parse a bracket expression and return it.
15445ffd83dbSDimitry Andric /// NOTE: This assumes the leading '[' has already been consumed.
15455ffd83dbSDimitry Andric ///
15465ffd83dbSDimitry Andric /// bracketexpr ::= expr]
15475ffd83dbSDimitry Andric ///
parseBracketExpr(const MCExpr * & Res,SMLoc & EndLoc)15485ffd83dbSDimitry Andric bool MasmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
15495ffd83dbSDimitry Andric   if (parseExpression(Res))
15505ffd83dbSDimitry Andric     return true;
15515ffd83dbSDimitry Andric   EndLoc = getTok().getEndLoc();
15525ffd83dbSDimitry Andric   if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression"))
15535ffd83dbSDimitry Andric     return true;
15545ffd83dbSDimitry Andric   return false;
15555ffd83dbSDimitry Andric }
15565ffd83dbSDimitry Andric 
15575ffd83dbSDimitry Andric /// Parse a primary expression and return it.
15585ffd83dbSDimitry Andric ///  primaryexpr ::= (parenexpr
15595ffd83dbSDimitry Andric ///  primaryexpr ::= symbol
15605ffd83dbSDimitry Andric ///  primaryexpr ::= number
15615ffd83dbSDimitry Andric ///  primaryexpr ::= '.'
1562e8d8bef9SDimitry Andric ///  primaryexpr ::= ~,+,-,'not' primaryexpr
1563e8d8bef9SDimitry Andric ///  primaryexpr ::= string
1564e8d8bef9SDimitry Andric ///          (a string is interpreted as a 64-bit number in big-endian base-256)
parsePrimaryExpr(const MCExpr * & Res,SMLoc & EndLoc,AsmTypeInfo * TypeInfo)1565e8d8bef9SDimitry Andric bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
1566e8d8bef9SDimitry Andric                                   AsmTypeInfo *TypeInfo) {
15675ffd83dbSDimitry Andric   SMLoc FirstTokenLoc = getLexer().getLoc();
15685ffd83dbSDimitry Andric   AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
15695ffd83dbSDimitry Andric   switch (FirstTokenKind) {
15705ffd83dbSDimitry Andric   default:
15715ffd83dbSDimitry Andric     return TokError("unknown token in expression");
15725ffd83dbSDimitry Andric   // If we have an error assume that we've already handled it.
15735ffd83dbSDimitry Andric   case AsmToken::Error:
15745ffd83dbSDimitry Andric     return true;
15755ffd83dbSDimitry Andric   case AsmToken::Exclaim:
15765ffd83dbSDimitry Andric     Lex(); // Eat the operator.
1577e8d8bef9SDimitry Andric     if (parsePrimaryExpr(Res, EndLoc, nullptr))
15785ffd83dbSDimitry Andric       return true;
15795ffd83dbSDimitry Andric     Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
15805ffd83dbSDimitry Andric     return false;
15815ffd83dbSDimitry Andric   case AsmToken::Dollar:
15825ffd83dbSDimitry Andric   case AsmToken::At:
15835ffd83dbSDimitry Andric   case AsmToken::Identifier: {
15845ffd83dbSDimitry Andric     StringRef Identifier;
15855ffd83dbSDimitry Andric     if (parseIdentifier(Identifier)) {
15865ffd83dbSDimitry Andric       // We may have failed but $ may be a valid token.
15875ffd83dbSDimitry Andric       if (getTok().is(AsmToken::Dollar)) {
15885ffd83dbSDimitry Andric         if (Lexer.getMAI().getDollarIsPC()) {
15895ffd83dbSDimitry Andric           Lex();
15905ffd83dbSDimitry Andric           // This is a '$' reference, which references the current PC.  Emit a
15915ffd83dbSDimitry Andric           // temporary label to the streamer and refer to it.
15925ffd83dbSDimitry Andric           MCSymbol *Sym = Ctx.createTempSymbol();
15935ffd83dbSDimitry Andric           Out.emitLabel(Sym);
15945ffd83dbSDimitry Andric           Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
15955ffd83dbSDimitry Andric                                         getContext());
15965ffd83dbSDimitry Andric           EndLoc = FirstTokenLoc;
15975ffd83dbSDimitry Andric           return false;
15985ffd83dbSDimitry Andric         }
15995ffd83dbSDimitry Andric         return Error(FirstTokenLoc, "invalid token in expression");
16005ffd83dbSDimitry Andric       }
16015ffd83dbSDimitry Andric     }
1602e8d8bef9SDimitry Andric     // Parse named bitwise negation.
1603fe6060f1SDimitry Andric     if (Identifier.equals_insensitive("not")) {
1604e8d8bef9SDimitry Andric       if (parsePrimaryExpr(Res, EndLoc, nullptr))
1605e8d8bef9SDimitry Andric         return true;
1606e8d8bef9SDimitry Andric       Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
1607e8d8bef9SDimitry Andric       return false;
1608e8d8bef9SDimitry Andric     }
1609753f127fSDimitry Andric     // Parse directional local label references.
1610753f127fSDimitry Andric     if (Identifier.equals_insensitive("@b") ||
1611753f127fSDimitry Andric         Identifier.equals_insensitive("@f")) {
1612753f127fSDimitry Andric       bool Before = Identifier.equals_insensitive("@b");
1613753f127fSDimitry Andric       MCSymbol *Sym = getContext().getDirectionalLocalSymbol(0, Before);
1614753f127fSDimitry Andric       if (Before && Sym->isUndefined())
1615753f127fSDimitry Andric         return Error(FirstTokenLoc, "Expected @@ label before @B reference");
1616753f127fSDimitry Andric       Res = MCSymbolRefExpr::create(Sym, getContext());
1617753f127fSDimitry Andric       return false;
1618753f127fSDimitry Andric     }
16195ffd83dbSDimitry Andric     // Parse symbol variant.
16205ffd83dbSDimitry Andric     std::pair<StringRef, StringRef> Split;
16215ffd83dbSDimitry Andric     if (!MAI.useParensForSymbolVariant()) {
16225ffd83dbSDimitry Andric       Split = Identifier.split('@');
16235ffd83dbSDimitry Andric     } else if (Lexer.is(AsmToken::LParen)) {
16245ffd83dbSDimitry Andric       Lex(); // eat '('.
16255ffd83dbSDimitry Andric       StringRef VName;
16265ffd83dbSDimitry Andric       parseIdentifier(VName);
16275ffd83dbSDimitry Andric       // eat ')'.
16285ffd83dbSDimitry Andric       if (parseToken(AsmToken::RParen,
16295ffd83dbSDimitry Andric                      "unexpected token in variant, expected ')'"))
16305ffd83dbSDimitry Andric         return true;
16315ffd83dbSDimitry Andric       Split = std::make_pair(Identifier, VName);
16325ffd83dbSDimitry Andric     }
16335ffd83dbSDimitry Andric 
16345ffd83dbSDimitry Andric     EndLoc = SMLoc::getFromPointer(Identifier.end());
16355ffd83dbSDimitry Andric 
16365ffd83dbSDimitry Andric     // This is a symbol reference.
16375ffd83dbSDimitry Andric     StringRef SymbolName = Identifier;
16385ffd83dbSDimitry Andric     if (SymbolName.empty())
16395ffd83dbSDimitry Andric       return Error(getLexer().getLoc(), "expected a symbol reference");
16405ffd83dbSDimitry Andric 
16415ffd83dbSDimitry Andric     MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
16425ffd83dbSDimitry Andric 
16435ffd83dbSDimitry Andric     // Look up the symbol variant if used.
16445ffd83dbSDimitry Andric     if (!Split.second.empty()) {
16455ffd83dbSDimitry Andric       Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
16465ffd83dbSDimitry Andric       if (Variant != MCSymbolRefExpr::VK_Invalid) {
16475ffd83dbSDimitry Andric         SymbolName = Split.first;
16485ffd83dbSDimitry Andric       } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) {
16495ffd83dbSDimitry Andric         Variant = MCSymbolRefExpr::VK_None;
16505ffd83dbSDimitry Andric       } else {
16515ffd83dbSDimitry Andric         return Error(SMLoc::getFromPointer(Split.second.begin()),
16525ffd83dbSDimitry Andric                      "invalid variant '" + Split.second + "'");
16535ffd83dbSDimitry Andric       }
16545ffd83dbSDimitry Andric     }
16555ffd83dbSDimitry Andric 
16565ffd83dbSDimitry Andric     // Find the field offset if used.
1657e8d8bef9SDimitry Andric     AsmFieldInfo Info;
16585ffd83dbSDimitry Andric     Split = SymbolName.split('.');
1659e8d8bef9SDimitry Andric     if (Split.second.empty()) {
1660e8d8bef9SDimitry Andric     } else {
16615ffd83dbSDimitry Andric       SymbolName = Split.first;
1662e8d8bef9SDimitry Andric       if (lookUpField(SymbolName, Split.second, Info)) {
16635ffd83dbSDimitry Andric         std::pair<StringRef, StringRef> BaseMember = Split.second.split('.');
16645ffd83dbSDimitry Andric         StringRef Base = BaseMember.first, Member = BaseMember.second;
1665e8d8bef9SDimitry Andric         lookUpField(Base, Member, Info);
1666e8d8bef9SDimitry Andric       } else if (Structs.count(SymbolName.lower())) {
1667e8d8bef9SDimitry Andric         // This is actually a reference to a field offset.
1668e8d8bef9SDimitry Andric         Res = MCConstantExpr::create(Info.Offset, getContext());
1669e8d8bef9SDimitry Andric         return false;
16705ffd83dbSDimitry Andric       }
16715ffd83dbSDimitry Andric     }
16725ffd83dbSDimitry Andric 
16735ffd83dbSDimitry Andric     MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
1674fe6060f1SDimitry Andric     if (!Sym) {
1675fe6060f1SDimitry Andric       // If this is a built-in numeric value, treat it as a constant.
1676fe6060f1SDimitry Andric       auto BuiltinIt = BuiltinSymbolMap.find(SymbolName.lower());
1677fe6060f1SDimitry Andric       const BuiltinSymbol Symbol = (BuiltinIt == BuiltinSymbolMap.end())
1678fe6060f1SDimitry Andric                                        ? BI_NO_SYMBOL
1679fe6060f1SDimitry Andric                                        : BuiltinIt->getValue();
1680fe6060f1SDimitry Andric       if (Symbol != BI_NO_SYMBOL) {
1681fe6060f1SDimitry Andric         const MCExpr *Value = evaluateBuiltinValue(Symbol, FirstTokenLoc);
1682fe6060f1SDimitry Andric         if (Value) {
1683fe6060f1SDimitry Andric           Res = Value;
1684fe6060f1SDimitry Andric           return false;
1685fe6060f1SDimitry Andric         }
1686fe6060f1SDimitry Andric       }
1687fe6060f1SDimitry Andric 
1688fe6060f1SDimitry Andric       // Variables use case-insensitive symbol names; if this is a variable, we
1689fe6060f1SDimitry Andric       // find the symbol using its canonical name.
1690fe6060f1SDimitry Andric       auto VarIt = Variables.find(SymbolName.lower());
1691fe6060f1SDimitry Andric       if (VarIt != Variables.end())
1692fe6060f1SDimitry Andric         SymbolName = VarIt->second.Name;
16935ffd83dbSDimitry Andric       Sym = getContext().getOrCreateSymbol(SymbolName);
1694fe6060f1SDimitry Andric     }
16955ffd83dbSDimitry Andric 
16965ffd83dbSDimitry Andric     // If this is an absolute variable reference, substitute it now to preserve
16975ffd83dbSDimitry Andric     // semantics in the face of reassignment.
16985ffd83dbSDimitry Andric     if (Sym->isVariable()) {
1699fe6060f1SDimitry Andric       auto V = Sym->getVariableValue(/*SetUsed=*/false);
17005ffd83dbSDimitry Andric       bool DoInline = isa<MCConstantExpr>(V) && !Variant;
17015ffd83dbSDimitry Andric       if (auto TV = dyn_cast<MCTargetExpr>(V))
17025ffd83dbSDimitry Andric         DoInline = TV->inlineAssignedExpr();
17035ffd83dbSDimitry Andric       if (DoInline) {
17045ffd83dbSDimitry Andric         if (Variant)
17055ffd83dbSDimitry Andric           return Error(EndLoc, "unexpected modifier on variable reference");
1706fe6060f1SDimitry Andric         Res = Sym->getVariableValue(/*SetUsed=*/false);
17075ffd83dbSDimitry Andric         return false;
17085ffd83dbSDimitry Andric       }
17095ffd83dbSDimitry Andric     }
17105ffd83dbSDimitry Andric 
17115ffd83dbSDimitry Andric     // Otherwise create a symbol ref.
17125ffd83dbSDimitry Andric     const MCExpr *SymRef =
17135ffd83dbSDimitry Andric         MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);
1714e8d8bef9SDimitry Andric     if (Info.Offset) {
1715e8d8bef9SDimitry Andric       Res = MCBinaryExpr::create(
1716e8d8bef9SDimitry Andric           MCBinaryExpr::Add, SymRef,
1717e8d8bef9SDimitry Andric           MCConstantExpr::create(Info.Offset, getContext()), getContext());
17185ffd83dbSDimitry Andric     } else {
17195ffd83dbSDimitry Andric       Res = SymRef;
17205ffd83dbSDimitry Andric     }
1721e8d8bef9SDimitry Andric     if (TypeInfo) {
1722e8d8bef9SDimitry Andric       if (Info.Type.Name.empty()) {
1723e8d8bef9SDimitry Andric         auto TypeIt = KnownType.find(Identifier.lower());
1724e8d8bef9SDimitry Andric         if (TypeIt != KnownType.end()) {
1725e8d8bef9SDimitry Andric           Info.Type = TypeIt->second;
1726e8d8bef9SDimitry Andric         }
1727e8d8bef9SDimitry Andric       }
1728e8d8bef9SDimitry Andric 
1729e8d8bef9SDimitry Andric       *TypeInfo = Info.Type;
1730e8d8bef9SDimitry Andric     }
17315ffd83dbSDimitry Andric     return false;
17325ffd83dbSDimitry Andric   }
17335ffd83dbSDimitry Andric   case AsmToken::BigNum:
17345ffd83dbSDimitry Andric     return TokError("literal value out of range for directive");
17355ffd83dbSDimitry Andric   case AsmToken::Integer: {
17365ffd83dbSDimitry Andric     int64_t IntVal = getTok().getIntVal();
17375ffd83dbSDimitry Andric     Res = MCConstantExpr::create(IntVal, getContext());
17385ffd83dbSDimitry Andric     EndLoc = Lexer.getTok().getEndLoc();
17395ffd83dbSDimitry Andric     Lex(); // Eat token.
17405ffd83dbSDimitry Andric     return false;
17415ffd83dbSDimitry Andric   }
1742e8d8bef9SDimitry Andric   case AsmToken::String: {
1743e8d8bef9SDimitry Andric     // MASM strings (used as constants) are interpreted as big-endian base-256.
1744e8d8bef9SDimitry Andric     SMLoc ValueLoc = getTok().getLoc();
1745e8d8bef9SDimitry Andric     std::string Value;
1746e8d8bef9SDimitry Andric     if (parseEscapedString(Value))
1747e8d8bef9SDimitry Andric       return true;
1748e8d8bef9SDimitry Andric     if (Value.size() > 8)
1749e8d8bef9SDimitry Andric       return Error(ValueLoc, "literal value out of range");
1750e8d8bef9SDimitry Andric     uint64_t IntValue = 0;
1751e8d8bef9SDimitry Andric     for (const unsigned char CharVal : Value)
1752e8d8bef9SDimitry Andric       IntValue = (IntValue << 8) | CharVal;
1753e8d8bef9SDimitry Andric     Res = MCConstantExpr::create(IntValue, getContext());
1754e8d8bef9SDimitry Andric     return false;
1755e8d8bef9SDimitry Andric   }
17565ffd83dbSDimitry Andric   case AsmToken::Real: {
17575ffd83dbSDimitry Andric     APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
17585ffd83dbSDimitry Andric     uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
17595ffd83dbSDimitry Andric     Res = MCConstantExpr::create(IntVal, getContext());
17605ffd83dbSDimitry Andric     EndLoc = Lexer.getTok().getEndLoc();
17615ffd83dbSDimitry Andric     Lex(); // Eat token.
17625ffd83dbSDimitry Andric     return false;
17635ffd83dbSDimitry Andric   }
17645ffd83dbSDimitry Andric   case AsmToken::Dot: {
17655ffd83dbSDimitry Andric     // This is a '.' reference, which references the current PC.  Emit a
17665ffd83dbSDimitry Andric     // temporary label to the streamer and refer to it.
17675ffd83dbSDimitry Andric     MCSymbol *Sym = Ctx.createTempSymbol();
17685ffd83dbSDimitry Andric     Out.emitLabel(Sym);
17695ffd83dbSDimitry Andric     Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
17705ffd83dbSDimitry Andric     EndLoc = Lexer.getTok().getEndLoc();
17715ffd83dbSDimitry Andric     Lex(); // Eat identifier.
17725ffd83dbSDimitry Andric     return false;
17735ffd83dbSDimitry Andric   }
17745ffd83dbSDimitry Andric   case AsmToken::LParen:
17755ffd83dbSDimitry Andric     Lex(); // Eat the '('.
17765ffd83dbSDimitry Andric     return parseParenExpr(Res, EndLoc);
17775ffd83dbSDimitry Andric   case AsmToken::LBrac:
17785ffd83dbSDimitry Andric     if (!PlatformParser->HasBracketExpressions())
17795ffd83dbSDimitry Andric       return TokError("brackets expression not supported on this target");
17805ffd83dbSDimitry Andric     Lex(); // Eat the '['.
17815ffd83dbSDimitry Andric     return parseBracketExpr(Res, EndLoc);
17825ffd83dbSDimitry Andric   case AsmToken::Minus:
17835ffd83dbSDimitry Andric     Lex(); // Eat the operator.
1784e8d8bef9SDimitry Andric     if (parsePrimaryExpr(Res, EndLoc, nullptr))
17855ffd83dbSDimitry Andric       return true;
17865ffd83dbSDimitry Andric     Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
17875ffd83dbSDimitry Andric     return false;
17885ffd83dbSDimitry Andric   case AsmToken::Plus:
17895ffd83dbSDimitry Andric     Lex(); // Eat the operator.
1790e8d8bef9SDimitry Andric     if (parsePrimaryExpr(Res, EndLoc, nullptr))
17915ffd83dbSDimitry Andric       return true;
17925ffd83dbSDimitry Andric     Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
17935ffd83dbSDimitry Andric     return false;
17945ffd83dbSDimitry Andric   case AsmToken::Tilde:
17955ffd83dbSDimitry Andric     Lex(); // Eat the operator.
1796e8d8bef9SDimitry Andric     if (parsePrimaryExpr(Res, EndLoc, nullptr))
17975ffd83dbSDimitry Andric       return true;
17985ffd83dbSDimitry Andric     Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
17995ffd83dbSDimitry Andric     return false;
18005ffd83dbSDimitry Andric   // MIPS unary expression operators. The lexer won't generate these tokens if
18015ffd83dbSDimitry Andric   // MCAsmInfo::HasMipsExpressions is false for the target.
18025ffd83dbSDimitry Andric   case AsmToken::PercentCall16:
18035ffd83dbSDimitry Andric   case AsmToken::PercentCall_Hi:
18045ffd83dbSDimitry Andric   case AsmToken::PercentCall_Lo:
18055ffd83dbSDimitry Andric   case AsmToken::PercentDtprel_Hi:
18065ffd83dbSDimitry Andric   case AsmToken::PercentDtprel_Lo:
18075ffd83dbSDimitry Andric   case AsmToken::PercentGot:
18085ffd83dbSDimitry Andric   case AsmToken::PercentGot_Disp:
18095ffd83dbSDimitry Andric   case AsmToken::PercentGot_Hi:
18105ffd83dbSDimitry Andric   case AsmToken::PercentGot_Lo:
18115ffd83dbSDimitry Andric   case AsmToken::PercentGot_Ofst:
18125ffd83dbSDimitry Andric   case AsmToken::PercentGot_Page:
18135ffd83dbSDimitry Andric   case AsmToken::PercentGottprel:
18145ffd83dbSDimitry Andric   case AsmToken::PercentGp_Rel:
18155ffd83dbSDimitry Andric   case AsmToken::PercentHi:
18165ffd83dbSDimitry Andric   case AsmToken::PercentHigher:
18175ffd83dbSDimitry Andric   case AsmToken::PercentHighest:
18185ffd83dbSDimitry Andric   case AsmToken::PercentLo:
18195ffd83dbSDimitry Andric   case AsmToken::PercentNeg:
18205ffd83dbSDimitry Andric   case AsmToken::PercentPcrel_Hi:
18215ffd83dbSDimitry Andric   case AsmToken::PercentPcrel_Lo:
18225ffd83dbSDimitry Andric   case AsmToken::PercentTlsgd:
18235ffd83dbSDimitry Andric   case AsmToken::PercentTlsldm:
18245ffd83dbSDimitry Andric   case AsmToken::PercentTprel_Hi:
18255ffd83dbSDimitry Andric   case AsmToken::PercentTprel_Lo:
18265ffd83dbSDimitry Andric     Lex(); // Eat the operator.
18275ffd83dbSDimitry Andric     if (Lexer.isNot(AsmToken::LParen))
18285ffd83dbSDimitry Andric       return TokError("expected '(' after operator");
18295ffd83dbSDimitry Andric     Lex(); // Eat the operator.
18305ffd83dbSDimitry Andric     if (parseExpression(Res, EndLoc))
18315ffd83dbSDimitry Andric       return true;
183204eeddc0SDimitry Andric     if (parseRParen())
183304eeddc0SDimitry Andric       return true;
18345ffd83dbSDimitry Andric     Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx);
18355ffd83dbSDimitry Andric     return !Res;
18365ffd83dbSDimitry Andric   }
18375ffd83dbSDimitry Andric }
18385ffd83dbSDimitry Andric 
parseExpression(const MCExpr * & Res)18395ffd83dbSDimitry Andric bool MasmParser::parseExpression(const MCExpr *&Res) {
18405ffd83dbSDimitry Andric   SMLoc EndLoc;
18415ffd83dbSDimitry Andric   return parseExpression(Res, EndLoc);
18425ffd83dbSDimitry Andric }
18435ffd83dbSDimitry Andric 
18445ffd83dbSDimitry Andric /// This function checks if the next token is <string> type or arithmetic.
18455ffd83dbSDimitry Andric /// string that begin with character '<' must end with character '>'.
18465ffd83dbSDimitry Andric /// otherwise it is arithmetics.
18475ffd83dbSDimitry Andric /// If the function returns a 'true' value,
18485ffd83dbSDimitry Andric /// the End argument will be filled with the last location pointed to the '>'
18495ffd83dbSDimitry Andric /// character.
isAngleBracketString(SMLoc & StrLoc,SMLoc & EndLoc)18505ffd83dbSDimitry Andric static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
18515ffd83dbSDimitry Andric   assert((StrLoc.getPointer() != nullptr) &&
18525ffd83dbSDimitry Andric          "Argument to the function cannot be a NULL value");
18535ffd83dbSDimitry Andric   const char *CharPtr = StrLoc.getPointer();
18545ffd83dbSDimitry Andric   while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') &&
18555ffd83dbSDimitry Andric          (*CharPtr != '\0')) {
18565ffd83dbSDimitry Andric     if (*CharPtr == '!')
18575ffd83dbSDimitry Andric       CharPtr++;
18585ffd83dbSDimitry Andric     CharPtr++;
18595ffd83dbSDimitry Andric   }
18605ffd83dbSDimitry Andric   if (*CharPtr == '>') {
18615ffd83dbSDimitry Andric     EndLoc = StrLoc.getFromPointer(CharPtr + 1);
18625ffd83dbSDimitry Andric     return true;
18635ffd83dbSDimitry Andric   }
18645ffd83dbSDimitry Andric   return false;
18655ffd83dbSDimitry Andric }
18665ffd83dbSDimitry Andric 
18675ffd83dbSDimitry Andric /// creating a string without the escape characters '!'.
angleBracketString(StringRef BracketContents)1868e8d8bef9SDimitry Andric static std::string angleBracketString(StringRef BracketContents) {
18695ffd83dbSDimitry Andric   std::string Res;
1870e8d8bef9SDimitry Andric   for (size_t Pos = 0; Pos < BracketContents.size(); Pos++) {
1871e8d8bef9SDimitry Andric     if (BracketContents[Pos] == '!')
18725ffd83dbSDimitry Andric       Pos++;
1873e8d8bef9SDimitry Andric     Res += BracketContents[Pos];
18745ffd83dbSDimitry Andric   }
18755ffd83dbSDimitry Andric   return Res;
18765ffd83dbSDimitry Andric }
18775ffd83dbSDimitry Andric 
18785ffd83dbSDimitry Andric /// Parse an expression and return it.
18795ffd83dbSDimitry Andric ///
18805ffd83dbSDimitry Andric ///  expr ::= expr &&,|| expr               -> lowest.
18815ffd83dbSDimitry Andric ///  expr ::= expr |,^,&,! expr
18825ffd83dbSDimitry Andric ///  expr ::= expr ==,!=,<>,<,<=,>,>= expr
18835ffd83dbSDimitry Andric ///  expr ::= expr <<,>> expr
18845ffd83dbSDimitry Andric ///  expr ::= expr +,- expr
18855ffd83dbSDimitry Andric ///  expr ::= expr *,/,% expr               -> highest.
18865ffd83dbSDimitry Andric ///  expr ::= primaryexpr
18875ffd83dbSDimitry Andric ///
parseExpression(const MCExpr * & Res,SMLoc & EndLoc)18885ffd83dbSDimitry Andric bool MasmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
18895ffd83dbSDimitry Andric   // Parse the expression.
18905ffd83dbSDimitry Andric   Res = nullptr;
18915ffd83dbSDimitry Andric   if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
18925ffd83dbSDimitry Andric       parseBinOpRHS(1, Res, EndLoc))
18935ffd83dbSDimitry Andric     return true;
18945ffd83dbSDimitry Andric 
18955ffd83dbSDimitry Andric   // Try to constant fold it up front, if possible. Do not exploit
18965ffd83dbSDimitry Andric   // assembler here.
18975ffd83dbSDimitry Andric   int64_t Value;
18985ffd83dbSDimitry Andric   if (Res->evaluateAsAbsolute(Value))
18995ffd83dbSDimitry Andric     Res = MCConstantExpr::create(Value, getContext());
19005ffd83dbSDimitry Andric 
19015ffd83dbSDimitry Andric   return false;
19025ffd83dbSDimitry Andric }
19035ffd83dbSDimitry Andric 
parseParenExpression(const MCExpr * & Res,SMLoc & EndLoc)19045ffd83dbSDimitry Andric bool MasmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
19055ffd83dbSDimitry Andric   Res = nullptr;
19065ffd83dbSDimitry Andric   return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
19075ffd83dbSDimitry Andric }
19085ffd83dbSDimitry Andric 
parseParenExprOfDepth(unsigned ParenDepth,const MCExpr * & Res,SMLoc & EndLoc)19095ffd83dbSDimitry Andric bool MasmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
19105ffd83dbSDimitry Andric                                        SMLoc &EndLoc) {
19115ffd83dbSDimitry Andric   if (parseParenExpr(Res, EndLoc))
19125ffd83dbSDimitry Andric     return true;
19135ffd83dbSDimitry Andric 
19145ffd83dbSDimitry Andric   for (; ParenDepth > 0; --ParenDepth) {
19155ffd83dbSDimitry Andric     if (parseBinOpRHS(1, Res, EndLoc))
19165ffd83dbSDimitry Andric       return true;
19175ffd83dbSDimitry Andric 
19185ffd83dbSDimitry Andric     // We don't Lex() the last RParen.
19195ffd83dbSDimitry Andric     // This is the same behavior as parseParenExpression().
19205ffd83dbSDimitry Andric     if (ParenDepth - 1 > 0) {
19215ffd83dbSDimitry Andric       EndLoc = getTok().getEndLoc();
192204eeddc0SDimitry Andric       if (parseRParen())
19235ffd83dbSDimitry Andric         return true;
19245ffd83dbSDimitry Andric     }
19255ffd83dbSDimitry Andric   }
19265ffd83dbSDimitry Andric   return false;
19275ffd83dbSDimitry Andric }
19285ffd83dbSDimitry Andric 
parseAbsoluteExpression(int64_t & Res)19295ffd83dbSDimitry Andric bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
19305ffd83dbSDimitry Andric   const MCExpr *Expr;
19315ffd83dbSDimitry Andric 
19325ffd83dbSDimitry Andric   SMLoc StartLoc = Lexer.getLoc();
19335ffd83dbSDimitry Andric   if (parseExpression(Expr))
19345ffd83dbSDimitry Andric     return true;
19355ffd83dbSDimitry Andric 
19365ffd83dbSDimitry Andric   if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
19375ffd83dbSDimitry Andric     return Error(StartLoc, "expected absolute expression");
19385ffd83dbSDimitry Andric 
19395ffd83dbSDimitry Andric   return false;
19405ffd83dbSDimitry Andric }
19415ffd83dbSDimitry Andric 
getGNUBinOpPrecedence(AsmToken::TokenKind K,MCBinaryExpr::Opcode & Kind,bool ShouldUseLogicalShr,bool EndExpressionAtGreater)19425ffd83dbSDimitry Andric static unsigned getGNUBinOpPrecedence(AsmToken::TokenKind K,
19435ffd83dbSDimitry Andric                                       MCBinaryExpr::Opcode &Kind,
19445ffd83dbSDimitry Andric                                       bool ShouldUseLogicalShr,
19455ffd83dbSDimitry Andric                                       bool EndExpressionAtGreater) {
19465ffd83dbSDimitry Andric   switch (K) {
19475ffd83dbSDimitry Andric   default:
19485ffd83dbSDimitry Andric     return 0; // not a binop.
19495ffd83dbSDimitry Andric 
19505ffd83dbSDimitry Andric   // Lowest Precedence: &&, ||
19515ffd83dbSDimitry Andric   case AsmToken::AmpAmp:
19525ffd83dbSDimitry Andric     Kind = MCBinaryExpr::LAnd;
19535ffd83dbSDimitry Andric     return 2;
19545ffd83dbSDimitry Andric   case AsmToken::PipePipe:
19555ffd83dbSDimitry Andric     Kind = MCBinaryExpr::LOr;
19565ffd83dbSDimitry Andric     return 1;
19575ffd83dbSDimitry Andric 
19585ffd83dbSDimitry Andric   // Low Precedence: ==, !=, <>, <, <=, >, >=
19595ffd83dbSDimitry Andric   case AsmToken::EqualEqual:
19605ffd83dbSDimitry Andric     Kind = MCBinaryExpr::EQ;
19615ffd83dbSDimitry Andric     return 3;
19625ffd83dbSDimitry Andric   case AsmToken::ExclaimEqual:
19635ffd83dbSDimitry Andric   case AsmToken::LessGreater:
19645ffd83dbSDimitry Andric     Kind = MCBinaryExpr::NE;
19655ffd83dbSDimitry Andric     return 3;
19665ffd83dbSDimitry Andric   case AsmToken::Less:
19675ffd83dbSDimitry Andric     Kind = MCBinaryExpr::LT;
19685ffd83dbSDimitry Andric     return 3;
19695ffd83dbSDimitry Andric   case AsmToken::LessEqual:
19705ffd83dbSDimitry Andric     Kind = MCBinaryExpr::LTE;
19715ffd83dbSDimitry Andric     return 3;
19725ffd83dbSDimitry Andric   case AsmToken::Greater:
19735ffd83dbSDimitry Andric     if (EndExpressionAtGreater)
19745ffd83dbSDimitry Andric       return 0;
19755ffd83dbSDimitry Andric     Kind = MCBinaryExpr::GT;
19765ffd83dbSDimitry Andric     return 3;
19775ffd83dbSDimitry Andric   case AsmToken::GreaterEqual:
19785ffd83dbSDimitry Andric     Kind = MCBinaryExpr::GTE;
19795ffd83dbSDimitry Andric     return 3;
19805ffd83dbSDimitry Andric 
19815ffd83dbSDimitry Andric   // Low Intermediate Precedence: +, -
19825ffd83dbSDimitry Andric   case AsmToken::Plus:
19835ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Add;
19845ffd83dbSDimitry Andric     return 4;
19855ffd83dbSDimitry Andric   case AsmToken::Minus:
19865ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Sub;
19875ffd83dbSDimitry Andric     return 4;
19885ffd83dbSDimitry Andric 
19895ffd83dbSDimitry Andric   // High Intermediate Precedence: |, &, ^
19905ffd83dbSDimitry Andric   case AsmToken::Pipe:
19915ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Or;
19925ffd83dbSDimitry Andric     return 5;
19935ffd83dbSDimitry Andric   case AsmToken::Caret:
19945ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Xor;
19955ffd83dbSDimitry Andric     return 5;
19965ffd83dbSDimitry Andric   case AsmToken::Amp:
19975ffd83dbSDimitry Andric     Kind = MCBinaryExpr::And;
19985ffd83dbSDimitry Andric     return 5;
19995ffd83dbSDimitry Andric 
20005ffd83dbSDimitry Andric   // Highest Precedence: *, /, %, <<, >>
20015ffd83dbSDimitry Andric   case AsmToken::Star:
20025ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Mul;
20035ffd83dbSDimitry Andric     return 6;
20045ffd83dbSDimitry Andric   case AsmToken::Slash:
20055ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Div;
20065ffd83dbSDimitry Andric     return 6;
20075ffd83dbSDimitry Andric   case AsmToken::Percent:
20085ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Mod;
20095ffd83dbSDimitry Andric     return 6;
20105ffd83dbSDimitry Andric   case AsmToken::LessLess:
20115ffd83dbSDimitry Andric     Kind = MCBinaryExpr::Shl;
20125ffd83dbSDimitry Andric     return 6;
20135ffd83dbSDimitry Andric   case AsmToken::GreaterGreater:
20145ffd83dbSDimitry Andric     if (EndExpressionAtGreater)
20155ffd83dbSDimitry Andric       return 0;
20165ffd83dbSDimitry Andric     Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr;
20175ffd83dbSDimitry Andric     return 6;
20185ffd83dbSDimitry Andric   }
20195ffd83dbSDimitry Andric }
20205ffd83dbSDimitry Andric 
getBinOpPrecedence(AsmToken::TokenKind K,MCBinaryExpr::Opcode & Kind)20215ffd83dbSDimitry Andric unsigned MasmParser::getBinOpPrecedence(AsmToken::TokenKind K,
20225ffd83dbSDimitry Andric                                         MCBinaryExpr::Opcode &Kind) {
20235ffd83dbSDimitry Andric   bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
20245ffd83dbSDimitry Andric   return getGNUBinOpPrecedence(K, Kind, ShouldUseLogicalShr,
20255ffd83dbSDimitry Andric                                AngleBracketDepth > 0);
20265ffd83dbSDimitry Andric }
20275ffd83dbSDimitry Andric 
20285ffd83dbSDimitry Andric /// Parse all binary operators with precedence >= 'Precedence'.
20295ffd83dbSDimitry Andric /// Res contains the LHS of the expression on input.
parseBinOpRHS(unsigned Precedence,const MCExpr * & Res,SMLoc & EndLoc)20305ffd83dbSDimitry Andric bool MasmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
20315ffd83dbSDimitry Andric                                SMLoc &EndLoc) {
20325ffd83dbSDimitry Andric   SMLoc StartLoc = Lexer.getLoc();
20335ffd83dbSDimitry Andric   while (true) {
2034e8d8bef9SDimitry Andric     AsmToken::TokenKind TokKind = Lexer.getKind();
2035e8d8bef9SDimitry Andric     if (Lexer.getKind() == AsmToken::Identifier) {
2036e8d8bef9SDimitry Andric       TokKind = StringSwitch<AsmToken::TokenKind>(Lexer.getTok().getString())
2037e8d8bef9SDimitry Andric                     .CaseLower("and", AsmToken::Amp)
2038e8d8bef9SDimitry Andric                     .CaseLower("not", AsmToken::Exclaim)
2039e8d8bef9SDimitry Andric                     .CaseLower("or", AsmToken::Pipe)
2040753f127fSDimitry Andric                     .CaseLower("xor", AsmToken::Caret)
2041753f127fSDimitry Andric                     .CaseLower("shl", AsmToken::LessLess)
2042753f127fSDimitry Andric                     .CaseLower("shr", AsmToken::GreaterGreater)
2043e8d8bef9SDimitry Andric                     .CaseLower("eq", AsmToken::EqualEqual)
2044e8d8bef9SDimitry Andric                     .CaseLower("ne", AsmToken::ExclaimEqual)
2045e8d8bef9SDimitry Andric                     .CaseLower("lt", AsmToken::Less)
2046e8d8bef9SDimitry Andric                     .CaseLower("le", AsmToken::LessEqual)
2047e8d8bef9SDimitry Andric                     .CaseLower("gt", AsmToken::Greater)
2048e8d8bef9SDimitry Andric                     .CaseLower("ge", AsmToken::GreaterEqual)
2049e8d8bef9SDimitry Andric                     .Default(TokKind);
2050e8d8bef9SDimitry Andric     }
20515ffd83dbSDimitry Andric     MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
2052e8d8bef9SDimitry Andric     unsigned TokPrec = getBinOpPrecedence(TokKind, Kind);
20535ffd83dbSDimitry Andric 
20545ffd83dbSDimitry Andric     // If the next token is lower precedence than we are allowed to eat, return
20555ffd83dbSDimitry Andric     // successfully with what we ate already.
20565ffd83dbSDimitry Andric     if (TokPrec < Precedence)
20575ffd83dbSDimitry Andric       return false;
20585ffd83dbSDimitry Andric 
20595ffd83dbSDimitry Andric     Lex();
20605ffd83dbSDimitry Andric 
20615ffd83dbSDimitry Andric     // Eat the next primary expression.
20625ffd83dbSDimitry Andric     const MCExpr *RHS;
20635ffd83dbSDimitry Andric     if (getTargetParser().parsePrimaryExpr(RHS, EndLoc))
20645ffd83dbSDimitry Andric       return true;
20655ffd83dbSDimitry Andric 
20665ffd83dbSDimitry Andric     // If BinOp binds less tightly with RHS than the operator after RHS, let
20675ffd83dbSDimitry Andric     // the pending operator take RHS as its LHS.
20685ffd83dbSDimitry Andric     MCBinaryExpr::Opcode Dummy;
20695ffd83dbSDimitry Andric     unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
20705ffd83dbSDimitry Andric     if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc))
20715ffd83dbSDimitry Andric       return true;
20725ffd83dbSDimitry Andric 
20735ffd83dbSDimitry Andric     // Merge LHS and RHS according to operator.
20745ffd83dbSDimitry Andric     Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc);
20755ffd83dbSDimitry Andric   }
20765ffd83dbSDimitry Andric }
20775ffd83dbSDimitry Andric 
20785ffd83dbSDimitry Andric /// ParseStatement:
2079e8d8bef9SDimitry Andric ///   ::= % statement
20805ffd83dbSDimitry Andric ///   ::= EndOfStatement
20815ffd83dbSDimitry Andric ///   ::= Label* Directive ...Operands... EndOfStatement
20825ffd83dbSDimitry Andric ///   ::= Label* Identifier OperandList* EndOfStatement
parseStatement(ParseStatementInfo & Info,MCAsmParserSemaCallback * SI)20835ffd83dbSDimitry Andric bool MasmParser::parseStatement(ParseStatementInfo &Info,
20845ffd83dbSDimitry Andric                                 MCAsmParserSemaCallback *SI) {
20855ffd83dbSDimitry Andric   assert(!hasPendingError() && "parseStatement started with pending error");
20865ffd83dbSDimitry Andric   // Eat initial spaces and comments.
20875ffd83dbSDimitry Andric   while (Lexer.is(AsmToken::Space))
20885ffd83dbSDimitry Andric     Lex();
20895ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::EndOfStatement)) {
20905ffd83dbSDimitry Andric     // If this is a line comment we can drop it safely.
20915ffd83dbSDimitry Andric     if (getTok().getString().empty() || getTok().getString().front() == '\r' ||
20925ffd83dbSDimitry Andric         getTok().getString().front() == '\n')
209381ad6265SDimitry Andric       Out.addBlankLine();
20945ffd83dbSDimitry Andric     Lex();
20955ffd83dbSDimitry Andric     return false;
20965ffd83dbSDimitry Andric   }
2097e8d8bef9SDimitry Andric 
2098e8d8bef9SDimitry Andric   // If preceded by an expansion operator, first expand all text macros and
2099e8d8bef9SDimitry Andric   // macro functions.
2100e8d8bef9SDimitry Andric   if (getTok().is(AsmToken::Percent)) {
2101e8d8bef9SDimitry Andric     SMLoc ExpansionLoc = getTok().getLoc();
2102e8d8bef9SDimitry Andric     if (parseToken(AsmToken::Percent) || expandStatement(ExpansionLoc))
2103e8d8bef9SDimitry Andric       return true;
2104e8d8bef9SDimitry Andric   }
2105e8d8bef9SDimitry Andric 
21065ffd83dbSDimitry Andric   // Statements always start with an identifier, unless we're dealing with a
21075ffd83dbSDimitry Andric   // processor directive (.386, .686, etc.) that lexes as a real.
21085ffd83dbSDimitry Andric   AsmToken ID = getTok();
21095ffd83dbSDimitry Andric   SMLoc IDLoc = ID.getLoc();
21105ffd83dbSDimitry Andric   StringRef IDVal;
21115ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::HashDirective))
21125ffd83dbSDimitry Andric     return parseCppHashLineFilenameComment(IDLoc);
2113753f127fSDimitry Andric   if (Lexer.is(AsmToken::Dot)) {
21145ffd83dbSDimitry Andric     // Treat '.' as a valid identifier in this context.
21155ffd83dbSDimitry Andric     Lex();
21165ffd83dbSDimitry Andric     IDVal = ".";
21175ffd83dbSDimitry Andric   } else if (Lexer.is(AsmToken::Real)) {
21185ffd83dbSDimitry Andric     // Treat ".<number>" as a valid identifier in this context.
21195ffd83dbSDimitry Andric     IDVal = getTok().getString();
21205ffd83dbSDimitry Andric     Lex(); // always eat a token
21215f757f3fSDimitry Andric     if (!IDVal.starts_with("."))
21225ffd83dbSDimitry Andric       return Error(IDLoc, "unexpected token at start of statement");
2123fe6060f1SDimitry Andric   } else if (parseIdentifier(IDVal, StartOfStatement)) {
21245ffd83dbSDimitry Andric     if (!TheCondState.Ignore) {
21255ffd83dbSDimitry Andric       Lex(); // always eat a token
21265ffd83dbSDimitry Andric       return Error(IDLoc, "unexpected token at start of statement");
21275ffd83dbSDimitry Andric     }
21285ffd83dbSDimitry Andric     IDVal = "";
21295ffd83dbSDimitry Andric   }
21305ffd83dbSDimitry Andric 
21315ffd83dbSDimitry Andric   // Handle conditional assembly here before checking for skipping.  We
21325ffd83dbSDimitry Andric   // have to do this so that .endif isn't skipped in a ".if 0" block for
21335ffd83dbSDimitry Andric   // example.
21345ffd83dbSDimitry Andric   StringMap<DirectiveKind>::const_iterator DirKindIt =
21355ffd83dbSDimitry Andric       DirectiveKindMap.find(IDVal.lower());
21365ffd83dbSDimitry Andric   DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
21375ffd83dbSDimitry Andric                               ? DK_NO_DIRECTIVE
21385ffd83dbSDimitry Andric                               : DirKindIt->getValue();
21395ffd83dbSDimitry Andric   switch (DirKind) {
21405ffd83dbSDimitry Andric   default:
21415ffd83dbSDimitry Andric     break;
21425ffd83dbSDimitry Andric   case DK_IF:
21435ffd83dbSDimitry Andric   case DK_IFE:
21445ffd83dbSDimitry Andric     return parseDirectiveIf(IDLoc, DirKind);
21455ffd83dbSDimitry Andric   case DK_IFB:
21465ffd83dbSDimitry Andric     return parseDirectiveIfb(IDLoc, true);
21475ffd83dbSDimitry Andric   case DK_IFNB:
21485ffd83dbSDimitry Andric     return parseDirectiveIfb(IDLoc, false);
21495ffd83dbSDimitry Andric   case DK_IFDEF:
21505ffd83dbSDimitry Andric     return parseDirectiveIfdef(IDLoc, true);
21515ffd83dbSDimitry Andric   case DK_IFNDEF:
21525ffd83dbSDimitry Andric     return parseDirectiveIfdef(IDLoc, false);
21535ffd83dbSDimitry Andric   case DK_IFDIF:
21545ffd83dbSDimitry Andric     return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false,
21555ffd83dbSDimitry Andric                                /*CaseInsensitive=*/false);
21565ffd83dbSDimitry Andric   case DK_IFDIFI:
21575ffd83dbSDimitry Andric     return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false,
21585ffd83dbSDimitry Andric                                /*CaseInsensitive=*/true);
21595ffd83dbSDimitry Andric   case DK_IFIDN:
21605ffd83dbSDimitry Andric     return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true,
21615ffd83dbSDimitry Andric                                /*CaseInsensitive=*/false);
21625ffd83dbSDimitry Andric   case DK_IFIDNI:
21635ffd83dbSDimitry Andric     return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true,
21645ffd83dbSDimitry Andric                                /*CaseInsensitive=*/true);
21655ffd83dbSDimitry Andric   case DK_ELSEIF:
21665ffd83dbSDimitry Andric   case DK_ELSEIFE:
21675ffd83dbSDimitry Andric     return parseDirectiveElseIf(IDLoc, DirKind);
21685ffd83dbSDimitry Andric   case DK_ELSEIFB:
21695ffd83dbSDimitry Andric     return parseDirectiveElseIfb(IDLoc, true);
21705ffd83dbSDimitry Andric   case DK_ELSEIFNB:
21715ffd83dbSDimitry Andric     return parseDirectiveElseIfb(IDLoc, false);
21725ffd83dbSDimitry Andric   case DK_ELSEIFDEF:
21735ffd83dbSDimitry Andric     return parseDirectiveElseIfdef(IDLoc, true);
21745ffd83dbSDimitry Andric   case DK_ELSEIFNDEF:
21755ffd83dbSDimitry Andric     return parseDirectiveElseIfdef(IDLoc, false);
21765ffd83dbSDimitry Andric   case DK_ELSEIFDIF:
21775ffd83dbSDimitry Andric     return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false,
21785ffd83dbSDimitry Andric                                    /*CaseInsensitive=*/false);
21795ffd83dbSDimitry Andric   case DK_ELSEIFDIFI:
21805ffd83dbSDimitry Andric     return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false,
21815ffd83dbSDimitry Andric                                    /*CaseInsensitive=*/true);
21825ffd83dbSDimitry Andric   case DK_ELSEIFIDN:
21835ffd83dbSDimitry Andric     return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true,
21845ffd83dbSDimitry Andric                                    /*CaseInsensitive=*/false);
21855ffd83dbSDimitry Andric   case DK_ELSEIFIDNI:
21865ffd83dbSDimitry Andric     return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true,
21875ffd83dbSDimitry Andric                                    /*CaseInsensitive=*/true);
21885ffd83dbSDimitry Andric   case DK_ELSE:
21895ffd83dbSDimitry Andric     return parseDirectiveElse(IDLoc);
21905ffd83dbSDimitry Andric   case DK_ENDIF:
21915ffd83dbSDimitry Andric     return parseDirectiveEndIf(IDLoc);
21925ffd83dbSDimitry Andric   }
21935ffd83dbSDimitry Andric 
21945ffd83dbSDimitry Andric   // Ignore the statement if in the middle of inactive conditional
21955ffd83dbSDimitry Andric   // (e.g. ".if 0").
21965ffd83dbSDimitry Andric   if (TheCondState.Ignore) {
21975ffd83dbSDimitry Andric     eatToEndOfStatement();
21985ffd83dbSDimitry Andric     return false;
21995ffd83dbSDimitry Andric   }
22005ffd83dbSDimitry Andric 
22015ffd83dbSDimitry Andric   // FIXME: Recurse on local labels?
22025ffd83dbSDimitry Andric 
2203bdd1243dSDimitry Andric   // Check for a label.
2204bdd1243dSDimitry Andric   //   ::= identifier ':'
2205bdd1243dSDimitry Andric   //   ::= number ':'
2206bdd1243dSDimitry Andric   if (Lexer.is(AsmToken::Colon) && getTargetParser().isLabel(ID)) {
22075ffd83dbSDimitry Andric     if (checkForValidSection())
22085ffd83dbSDimitry Andric       return true;
22095ffd83dbSDimitry Andric 
22105ffd83dbSDimitry Andric     // identifier ':'   -> Label.
22115ffd83dbSDimitry Andric     Lex();
22125ffd83dbSDimitry Andric 
22135ffd83dbSDimitry Andric     // Diagnose attempt to use '.' as a label.
22145ffd83dbSDimitry Andric     if (IDVal == ".")
22155ffd83dbSDimitry Andric       return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
22165ffd83dbSDimitry Andric 
22175ffd83dbSDimitry Andric     // Diagnose attempt to use a variable as a label.
22185ffd83dbSDimitry Andric     //
22195ffd83dbSDimitry Andric     // FIXME: Diagnostics. Note the location of the definition as a label.
22205ffd83dbSDimitry Andric     // FIXME: This doesn't diagnose assignment to a symbol which has been
22215ffd83dbSDimitry Andric     // implicitly marked as external.
22225ffd83dbSDimitry Andric     MCSymbol *Sym;
22235ffd83dbSDimitry Andric     if (ParsingMSInlineAsm && SI) {
22245ffd83dbSDimitry Andric       StringRef RewrittenLabel =
22255ffd83dbSDimitry Andric           SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true);
22265ffd83dbSDimitry Andric       assert(!RewrittenLabel.empty() &&
22275ffd83dbSDimitry Andric              "We should have an internal name here.");
22285ffd83dbSDimitry Andric       Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(),
22295ffd83dbSDimitry Andric                                      RewrittenLabel);
22305ffd83dbSDimitry Andric       IDVal = RewrittenLabel;
22315ffd83dbSDimitry Andric     }
2232753f127fSDimitry Andric     // Handle directional local labels
2233753f127fSDimitry Andric     if (IDVal == "@@") {
2234753f127fSDimitry Andric       Sym = Ctx.createDirectionalLocalSymbol(0);
2235753f127fSDimitry Andric     } else {
22365ffd83dbSDimitry Andric       Sym = getContext().getOrCreateSymbol(IDVal);
2237753f127fSDimitry Andric     }
2238753f127fSDimitry Andric 
22395ffd83dbSDimitry Andric     // End of Labels should be treated as end of line for lexing
22405ffd83dbSDimitry Andric     // purposes but that information is not available to the Lexer who
22415ffd83dbSDimitry Andric     // does not understand Labels. This may cause us to see a Hash
22425ffd83dbSDimitry Andric     // here instead of a preprocessor line comment.
22435ffd83dbSDimitry Andric     if (getTok().is(AsmToken::Hash)) {
2244e8d8bef9SDimitry Andric       std::string CommentStr = parseStringTo(AsmToken::EndOfStatement);
22455ffd83dbSDimitry Andric       Lexer.Lex();
22465ffd83dbSDimitry Andric       Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr));
22475ffd83dbSDimitry Andric     }
22485ffd83dbSDimitry Andric 
22495ffd83dbSDimitry Andric     // Consume any end of statement token, if present, to avoid spurious
225081ad6265SDimitry Andric     // addBlankLine calls().
22515ffd83dbSDimitry Andric     if (getTok().is(AsmToken::EndOfStatement)) {
22525ffd83dbSDimitry Andric       Lex();
22535ffd83dbSDimitry Andric     }
22545ffd83dbSDimitry Andric 
2255bdd1243dSDimitry Andric     getTargetParser().doBeforeLabelEmit(Sym, IDLoc);
22565ffd83dbSDimitry Andric 
22575ffd83dbSDimitry Andric     // Emit the label.
22585ffd83dbSDimitry Andric     if (!getTargetParser().isParsingMSInlineAsm())
22595ffd83dbSDimitry Andric       Out.emitLabel(Sym, IDLoc);
22605ffd83dbSDimitry Andric 
22615ffd83dbSDimitry Andric     // If we are generating dwarf for assembly source files then gather the
22625ffd83dbSDimitry Andric     // info to make a dwarf label entry for this label if needed.
22635ffd83dbSDimitry Andric     if (enabledGenDwarfForAssembly())
22645ffd83dbSDimitry Andric       MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
22655ffd83dbSDimitry Andric                                  IDLoc);
22665ffd83dbSDimitry Andric 
22675ffd83dbSDimitry Andric     getTargetParser().onLabelParsed(Sym);
22685ffd83dbSDimitry Andric 
22695ffd83dbSDimitry Andric     return false;
22705ffd83dbSDimitry Andric   }
22715ffd83dbSDimitry Andric 
22725ffd83dbSDimitry Andric   // If macros are enabled, check to see if this is a macro instantiation.
2273e8d8bef9SDimitry Andric   if (const MCAsmMacro *M = getContext().lookupMacro(IDVal.lower())) {
22745ffd83dbSDimitry Andric     return handleMacroEntry(M, IDLoc);
22755ffd83dbSDimitry Andric   }
22765ffd83dbSDimitry Andric 
22775ffd83dbSDimitry Andric   // Otherwise, we have a normal instruction or directive.
22785ffd83dbSDimitry Andric 
22795ffd83dbSDimitry Andric   if (DirKind != DK_NO_DIRECTIVE) {
22805ffd83dbSDimitry Andric     // There are several entities interested in parsing directives:
22815ffd83dbSDimitry Andric     //
22825ffd83dbSDimitry Andric     // 1. Asm parser extensions. For example, platform-specific parsers
22835ffd83dbSDimitry Andric     //    (like the ELF parser) register themselves as extensions.
22845ffd83dbSDimitry Andric     // 2. The target-specific assembly parser. Some directives are target
22855ffd83dbSDimitry Andric     //    specific or may potentially behave differently on certain targets.
22865ffd83dbSDimitry Andric     // 3. The generic directive parser implemented by this class. These are
22875ffd83dbSDimitry Andric     //    all the directives that behave in a target and platform independent
22885ffd83dbSDimitry Andric     //    manner, or at least have a default behavior that's shared between
22895ffd83dbSDimitry Andric     //    all targets and platforms.
22905ffd83dbSDimitry Andric 
22915ffd83dbSDimitry Andric     getTargetParser().flushPendingInstructions(getStreamer());
22925ffd83dbSDimitry Andric 
22935ffd83dbSDimitry Andric     // Special-case handling of structure-end directives at higher priority,
22945ffd83dbSDimitry Andric     // since ENDS is overloaded as a segment-end directive.
2295fe6060f1SDimitry Andric     if (IDVal.equals_insensitive("ends") && StructInProgress.size() > 1 &&
22965ffd83dbSDimitry Andric         getTok().is(AsmToken::EndOfStatement)) {
22975ffd83dbSDimitry Andric       return parseDirectiveNestedEnds();
22985ffd83dbSDimitry Andric     }
22995ffd83dbSDimitry Andric 
23005ffd83dbSDimitry Andric     // First, check the extension directive map to see if any extension has
23015ffd83dbSDimitry Andric     // registered itself to parse this directive.
23025ffd83dbSDimitry Andric     std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
23035ffd83dbSDimitry Andric         ExtensionDirectiveMap.lookup(IDVal.lower());
23045ffd83dbSDimitry Andric     if (Handler.first)
23055ffd83dbSDimitry Andric       return (*Handler.second)(Handler.first, IDVal, IDLoc);
23065ffd83dbSDimitry Andric 
23075ffd83dbSDimitry Andric     // Next, let the target-specific assembly parser try.
230806c3fb27SDimitry Andric     if (ID.isNot(AsmToken::Identifier))
230906c3fb27SDimitry Andric       return false;
23105ffd83dbSDimitry Andric 
231106c3fb27SDimitry Andric     ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(ID);
231206c3fb27SDimitry Andric     assert(TPDirectiveReturn.isFailure() == hasPendingError() &&
231306c3fb27SDimitry Andric            "Should only return Failure iff there was an error");
231406c3fb27SDimitry Andric     if (TPDirectiveReturn.isFailure())
23155ffd83dbSDimitry Andric       return true;
231606c3fb27SDimitry Andric     if (TPDirectiveReturn.isSuccess())
23175ffd83dbSDimitry Andric       return false;
23185ffd83dbSDimitry Andric 
23195ffd83dbSDimitry Andric     // Finally, if no one else is interested in this directive, it must be
23205ffd83dbSDimitry Andric     // generic and familiar to this class.
23215ffd83dbSDimitry Andric     switch (DirKind) {
23225ffd83dbSDimitry Andric     default:
23235ffd83dbSDimitry Andric       break;
23245ffd83dbSDimitry Andric     case DK_ASCII:
23255ffd83dbSDimitry Andric       return parseDirectiveAscii(IDVal, false);
23265ffd83dbSDimitry Andric     case DK_ASCIZ:
23275ffd83dbSDimitry Andric     case DK_STRING:
23285ffd83dbSDimitry Andric       return parseDirectiveAscii(IDVal, true);
23295ffd83dbSDimitry Andric     case DK_BYTE:
23305ffd83dbSDimitry Andric     case DK_SBYTE:
23315ffd83dbSDimitry Andric     case DK_DB:
23325ffd83dbSDimitry Andric       return parseDirectiveValue(IDVal, 1);
23335ffd83dbSDimitry Andric     case DK_WORD:
23345ffd83dbSDimitry Andric     case DK_SWORD:
23355ffd83dbSDimitry Andric     case DK_DW:
23365ffd83dbSDimitry Andric       return parseDirectiveValue(IDVal, 2);
23375ffd83dbSDimitry Andric     case DK_DWORD:
23385ffd83dbSDimitry Andric     case DK_SDWORD:
23395ffd83dbSDimitry Andric     case DK_DD:
23405ffd83dbSDimitry Andric       return parseDirectiveValue(IDVal, 4);
23415ffd83dbSDimitry Andric     case DK_FWORD:
2342e8d8bef9SDimitry Andric     case DK_DF:
23435ffd83dbSDimitry Andric       return parseDirectiveValue(IDVal, 6);
23445ffd83dbSDimitry Andric     case DK_QWORD:
23455ffd83dbSDimitry Andric     case DK_SQWORD:
23465ffd83dbSDimitry Andric     case DK_DQ:
23475ffd83dbSDimitry Andric       return parseDirectiveValue(IDVal, 8);
23485ffd83dbSDimitry Andric     case DK_REAL4:
2349e8d8bef9SDimitry Andric       return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4);
23505ffd83dbSDimitry Andric     case DK_REAL8:
2351e8d8bef9SDimitry Andric       return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8);
2352e8d8bef9SDimitry Andric     case DK_REAL10:
2353e8d8bef9SDimitry Andric       return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10);
23545ffd83dbSDimitry Andric     case DK_STRUCT:
23555ffd83dbSDimitry Andric     case DK_UNION:
23565ffd83dbSDimitry Andric       return parseDirectiveNestedStruct(IDVal, DirKind);
23575ffd83dbSDimitry Andric     case DK_ENDS:
23585ffd83dbSDimitry Andric       return parseDirectiveNestedEnds();
23595ffd83dbSDimitry Andric     case DK_ALIGN:
23605ffd83dbSDimitry Andric       return parseDirectiveAlign();
2361fe6060f1SDimitry Andric     case DK_EVEN:
2362fe6060f1SDimitry Andric       return parseDirectiveEven();
23635ffd83dbSDimitry Andric     case DK_ORG:
23645ffd83dbSDimitry Andric       return parseDirectiveOrg();
23655ffd83dbSDimitry Andric     case DK_EXTERN:
236681ad6265SDimitry Andric       return parseDirectiveExtern();
23675ffd83dbSDimitry Andric     case DK_PUBLIC:
23685ffd83dbSDimitry Andric       return parseDirectiveSymbolAttribute(MCSA_Global);
23695ffd83dbSDimitry Andric     case DK_COMM:
23705ffd83dbSDimitry Andric       return parseDirectiveComm(/*IsLocal=*/false);
23715ffd83dbSDimitry Andric     case DK_COMMENT:
23725ffd83dbSDimitry Andric       return parseDirectiveComment(IDLoc);
23735ffd83dbSDimitry Andric     case DK_INCLUDE:
23745ffd83dbSDimitry Andric       return parseDirectiveInclude();
2375e8d8bef9SDimitry Andric     case DK_REPEAT:
2376e8d8bef9SDimitry Andric       return parseDirectiveRepeat(IDLoc, IDVal);
2377e8d8bef9SDimitry Andric     case DK_WHILE:
2378e8d8bef9SDimitry Andric       return parseDirectiveWhile(IDLoc);
2379e8d8bef9SDimitry Andric     case DK_FOR:
2380e8d8bef9SDimitry Andric       return parseDirectiveFor(IDLoc, IDVal);
2381e8d8bef9SDimitry Andric     case DK_FORC:
2382e8d8bef9SDimitry Andric       return parseDirectiveForc(IDLoc, IDVal);
23835ffd83dbSDimitry Andric     case DK_FILE:
23845ffd83dbSDimitry Andric       return parseDirectiveFile(IDLoc);
23855ffd83dbSDimitry Andric     case DK_LINE:
23865ffd83dbSDimitry Andric       return parseDirectiveLine();
23875ffd83dbSDimitry Andric     case DK_LOC:
23885ffd83dbSDimitry Andric       return parseDirectiveLoc();
23895ffd83dbSDimitry Andric     case DK_STABS:
23905ffd83dbSDimitry Andric       return parseDirectiveStabs();
23915ffd83dbSDimitry Andric     case DK_CV_FILE:
23925ffd83dbSDimitry Andric       return parseDirectiveCVFile();
23935ffd83dbSDimitry Andric     case DK_CV_FUNC_ID:
23945ffd83dbSDimitry Andric       return parseDirectiveCVFuncId();
23955ffd83dbSDimitry Andric     case DK_CV_INLINE_SITE_ID:
23965ffd83dbSDimitry Andric       return parseDirectiveCVInlineSiteId();
23975ffd83dbSDimitry Andric     case DK_CV_LOC:
23985ffd83dbSDimitry Andric       return parseDirectiveCVLoc();
23995ffd83dbSDimitry Andric     case DK_CV_LINETABLE:
24005ffd83dbSDimitry Andric       return parseDirectiveCVLinetable();
24015ffd83dbSDimitry Andric     case DK_CV_INLINE_LINETABLE:
24025ffd83dbSDimitry Andric       return parseDirectiveCVInlineLinetable();
24035ffd83dbSDimitry Andric     case DK_CV_DEF_RANGE:
24045ffd83dbSDimitry Andric       return parseDirectiveCVDefRange();
24055ffd83dbSDimitry Andric     case DK_CV_STRING:
24065ffd83dbSDimitry Andric       return parseDirectiveCVString();
24075ffd83dbSDimitry Andric     case DK_CV_STRINGTABLE:
24085ffd83dbSDimitry Andric       return parseDirectiveCVStringTable();
24095ffd83dbSDimitry Andric     case DK_CV_FILECHECKSUMS:
24105ffd83dbSDimitry Andric       return parseDirectiveCVFileChecksums();
24115ffd83dbSDimitry Andric     case DK_CV_FILECHECKSUM_OFFSET:
24125ffd83dbSDimitry Andric       return parseDirectiveCVFileChecksumOffset();
24135ffd83dbSDimitry Andric     case DK_CV_FPO_DATA:
24145ffd83dbSDimitry Andric       return parseDirectiveCVFPOData();
24155ffd83dbSDimitry Andric     case DK_CFI_SECTIONS:
24165ffd83dbSDimitry Andric       return parseDirectiveCFISections();
24175ffd83dbSDimitry Andric     case DK_CFI_STARTPROC:
24185ffd83dbSDimitry Andric       return parseDirectiveCFIStartProc();
24195ffd83dbSDimitry Andric     case DK_CFI_ENDPROC:
24205ffd83dbSDimitry Andric       return parseDirectiveCFIEndProc();
24215ffd83dbSDimitry Andric     case DK_CFI_DEF_CFA:
24225ffd83dbSDimitry Andric       return parseDirectiveCFIDefCfa(IDLoc);
24235ffd83dbSDimitry Andric     case DK_CFI_DEF_CFA_OFFSET:
242406c3fb27SDimitry Andric       return parseDirectiveCFIDefCfaOffset(IDLoc);
24255ffd83dbSDimitry Andric     case DK_CFI_ADJUST_CFA_OFFSET:
242606c3fb27SDimitry Andric       return parseDirectiveCFIAdjustCfaOffset(IDLoc);
24275ffd83dbSDimitry Andric     case DK_CFI_DEF_CFA_REGISTER:
24285ffd83dbSDimitry Andric       return parseDirectiveCFIDefCfaRegister(IDLoc);
24295ffd83dbSDimitry Andric     case DK_CFI_OFFSET:
24305ffd83dbSDimitry Andric       return parseDirectiveCFIOffset(IDLoc);
24315ffd83dbSDimitry Andric     case DK_CFI_REL_OFFSET:
24325ffd83dbSDimitry Andric       return parseDirectiveCFIRelOffset(IDLoc);
24335ffd83dbSDimitry Andric     case DK_CFI_PERSONALITY:
24345ffd83dbSDimitry Andric       return parseDirectiveCFIPersonalityOrLsda(true);
24355ffd83dbSDimitry Andric     case DK_CFI_LSDA:
24365ffd83dbSDimitry Andric       return parseDirectiveCFIPersonalityOrLsda(false);
24375ffd83dbSDimitry Andric     case DK_CFI_REMEMBER_STATE:
243806c3fb27SDimitry Andric       return parseDirectiveCFIRememberState(IDLoc);
24395ffd83dbSDimitry Andric     case DK_CFI_RESTORE_STATE:
244006c3fb27SDimitry Andric       return parseDirectiveCFIRestoreState(IDLoc);
24415ffd83dbSDimitry Andric     case DK_CFI_SAME_VALUE:
24425ffd83dbSDimitry Andric       return parseDirectiveCFISameValue(IDLoc);
24435ffd83dbSDimitry Andric     case DK_CFI_RESTORE:
24445ffd83dbSDimitry Andric       return parseDirectiveCFIRestore(IDLoc);
24455ffd83dbSDimitry Andric     case DK_CFI_ESCAPE:
244606c3fb27SDimitry Andric       return parseDirectiveCFIEscape(IDLoc);
24475ffd83dbSDimitry Andric     case DK_CFI_RETURN_COLUMN:
24485ffd83dbSDimitry Andric       return parseDirectiveCFIReturnColumn(IDLoc);
24495ffd83dbSDimitry Andric     case DK_CFI_SIGNAL_FRAME:
24505ffd83dbSDimitry Andric       return parseDirectiveCFISignalFrame();
24515ffd83dbSDimitry Andric     case DK_CFI_UNDEFINED:
24525ffd83dbSDimitry Andric       return parseDirectiveCFIUndefined(IDLoc);
24535ffd83dbSDimitry Andric     case DK_CFI_REGISTER:
24545ffd83dbSDimitry Andric       return parseDirectiveCFIRegister(IDLoc);
24555ffd83dbSDimitry Andric     case DK_CFI_WINDOW_SAVE:
245606c3fb27SDimitry Andric       return parseDirectiveCFIWindowSave(IDLoc);
24575ffd83dbSDimitry Andric     case DK_EXITM:
2458e8d8bef9SDimitry Andric       Info.ExitValue = "";
2459e8d8bef9SDimitry Andric       return parseDirectiveExitMacro(IDLoc, IDVal, *Info.ExitValue);
24605ffd83dbSDimitry Andric     case DK_ENDM:
2461e8d8bef9SDimitry Andric       Info.ExitValue = "";
24625ffd83dbSDimitry Andric       return parseDirectiveEndMacro(IDVal);
2463e8d8bef9SDimitry Andric     case DK_PURGE:
24645ffd83dbSDimitry Andric       return parseDirectivePurgeMacro(IDLoc);
24655ffd83dbSDimitry Andric     case DK_END:
24665ffd83dbSDimitry Andric       return parseDirectiveEnd(IDLoc);
24675ffd83dbSDimitry Andric     case DK_ERR:
24685ffd83dbSDimitry Andric       return parseDirectiveError(IDLoc);
24695ffd83dbSDimitry Andric     case DK_ERRB:
24705ffd83dbSDimitry Andric       return parseDirectiveErrorIfb(IDLoc, true);
24715ffd83dbSDimitry Andric     case DK_ERRNB:
24725ffd83dbSDimitry Andric       return parseDirectiveErrorIfb(IDLoc, false);
24735ffd83dbSDimitry Andric     case DK_ERRDEF:
24745ffd83dbSDimitry Andric       return parseDirectiveErrorIfdef(IDLoc, true);
24755ffd83dbSDimitry Andric     case DK_ERRNDEF:
24765ffd83dbSDimitry Andric       return parseDirectiveErrorIfdef(IDLoc, false);
24775ffd83dbSDimitry Andric     case DK_ERRDIF:
24785ffd83dbSDimitry Andric       return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false,
24795ffd83dbSDimitry Andric                                       /*CaseInsensitive=*/false);
24805ffd83dbSDimitry Andric     case DK_ERRDIFI:
24815ffd83dbSDimitry Andric       return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false,
24825ffd83dbSDimitry Andric                                       /*CaseInsensitive=*/true);
24835ffd83dbSDimitry Andric     case DK_ERRIDN:
24845ffd83dbSDimitry Andric       return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true,
24855ffd83dbSDimitry Andric                                       /*CaseInsensitive=*/false);
24865ffd83dbSDimitry Andric     case DK_ERRIDNI:
24875ffd83dbSDimitry Andric       return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true,
24885ffd83dbSDimitry Andric                                       /*CaseInsensitive=*/true);
24895ffd83dbSDimitry Andric     case DK_ERRE:
24905ffd83dbSDimitry Andric       return parseDirectiveErrorIfe(IDLoc, true);
24915ffd83dbSDimitry Andric     case DK_ERRNZ:
24925ffd83dbSDimitry Andric       return parseDirectiveErrorIfe(IDLoc, false);
2493e8d8bef9SDimitry Andric     case DK_RADIX:
2494e8d8bef9SDimitry Andric       return parseDirectiveRadix(IDLoc);
2495fe6060f1SDimitry Andric     case DK_ECHO:
2496fe6060f1SDimitry Andric       return parseDirectiveEcho(IDLoc);
24975ffd83dbSDimitry Andric     }
24985ffd83dbSDimitry Andric 
24995ffd83dbSDimitry Andric     return Error(IDLoc, "unknown directive");
25005ffd83dbSDimitry Andric   }
25015ffd83dbSDimitry Andric 
25025ffd83dbSDimitry Andric   // We also check if this is allocating memory with user-defined type.
25035ffd83dbSDimitry Andric   auto IDIt = Structs.find(IDVal.lower());
25045ffd83dbSDimitry Andric   if (IDIt != Structs.end())
25055ffd83dbSDimitry Andric     return parseDirectiveStructValue(/*Structure=*/IDIt->getValue(), IDVal,
25065ffd83dbSDimitry Andric                                      IDLoc);
25075ffd83dbSDimitry Andric 
25085ffd83dbSDimitry Andric   // Non-conditional Microsoft directives sometimes follow their first argument.
25095ffd83dbSDimitry Andric   const AsmToken nextTok = getTok();
25105ffd83dbSDimitry Andric   const StringRef nextVal = nextTok.getString();
25115ffd83dbSDimitry Andric   const SMLoc nextLoc = nextTok.getLoc();
25125ffd83dbSDimitry Andric 
2513fe6060f1SDimitry Andric   const AsmToken afterNextTok = peekTok();
2514fe6060f1SDimitry Andric 
25155ffd83dbSDimitry Andric   // There are several entities interested in parsing infix directives:
25165ffd83dbSDimitry Andric   //
25175ffd83dbSDimitry Andric   // 1. Asm parser extensions. For example, platform-specific parsers
25185ffd83dbSDimitry Andric   //    (like the ELF parser) register themselves as extensions.
25195ffd83dbSDimitry Andric   // 2. The generic directive parser implemented by this class. These are
25205ffd83dbSDimitry Andric   //    all the directives that behave in a target and platform independent
25215ffd83dbSDimitry Andric   //    manner, or at least have a default behavior that's shared between
25225ffd83dbSDimitry Andric   //    all targets and platforms.
25235ffd83dbSDimitry Andric 
25245ffd83dbSDimitry Andric   getTargetParser().flushPendingInstructions(getStreamer());
25255ffd83dbSDimitry Andric 
25265ffd83dbSDimitry Andric   // Special-case handling of structure-end directives at higher priority, since
25275ffd83dbSDimitry Andric   // ENDS is overloaded as a segment-end directive.
2528fe6060f1SDimitry Andric   if (nextVal.equals_insensitive("ends") && StructInProgress.size() == 1) {
25295ffd83dbSDimitry Andric     Lex();
25305ffd83dbSDimitry Andric     return parseDirectiveEnds(IDVal, IDLoc);
25315ffd83dbSDimitry Andric   }
25325ffd83dbSDimitry Andric 
25335ffd83dbSDimitry Andric   // First, check the extension directive map to see if any extension has
25345ffd83dbSDimitry Andric   // registered itself to parse this directive.
25355ffd83dbSDimitry Andric   std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
25365ffd83dbSDimitry Andric       ExtensionDirectiveMap.lookup(nextVal.lower());
25375ffd83dbSDimitry Andric   if (Handler.first) {
25385ffd83dbSDimitry Andric     Lex();
25395ffd83dbSDimitry Andric     Lexer.UnLex(ID);
25405ffd83dbSDimitry Andric     return (*Handler.second)(Handler.first, nextVal, nextLoc);
25415ffd83dbSDimitry Andric   }
25425ffd83dbSDimitry Andric 
25435ffd83dbSDimitry Andric   // If no one else is interested in this directive, it must be
25445ffd83dbSDimitry Andric   // generic and familiar to this class.
25455ffd83dbSDimitry Andric   DirKindIt = DirectiveKindMap.find(nextVal.lower());
25465ffd83dbSDimitry Andric   DirKind = (DirKindIt == DirectiveKindMap.end())
25475ffd83dbSDimitry Andric                 ? DK_NO_DIRECTIVE
25485ffd83dbSDimitry Andric                 : DirKindIt->getValue();
25495ffd83dbSDimitry Andric   switch (DirKind) {
25505ffd83dbSDimitry Andric   default:
25515ffd83dbSDimitry Andric     break;
25525ffd83dbSDimitry Andric   case DK_ASSIGN:
25535ffd83dbSDimitry Andric   case DK_EQU:
25545ffd83dbSDimitry Andric   case DK_TEXTEQU:
25555ffd83dbSDimitry Andric     Lex();
2556fe6060f1SDimitry Andric     return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
25575ffd83dbSDimitry Andric   case DK_BYTE:
2558fe6060f1SDimitry Andric     if (afterNextTok.is(AsmToken::Identifier) &&
2559fe6060f1SDimitry Andric         afterNextTok.getString().equals_insensitive("ptr")) {
2560fe6060f1SDimitry Andric       // Size directive; part of an instruction.
2561fe6060f1SDimitry Andric       break;
2562fe6060f1SDimitry Andric     }
2563bdd1243dSDimitry Andric     [[fallthrough]];
2564e8d8bef9SDimitry Andric   case DK_SBYTE:
25655ffd83dbSDimitry Andric   case DK_DB:
25665ffd83dbSDimitry Andric     Lex();
25675ffd83dbSDimitry Andric     return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc);
25685ffd83dbSDimitry Andric   case DK_WORD:
2569fe6060f1SDimitry Andric     if (afterNextTok.is(AsmToken::Identifier) &&
2570fe6060f1SDimitry Andric         afterNextTok.getString().equals_insensitive("ptr")) {
2571fe6060f1SDimitry Andric       // Size directive; part of an instruction.
2572fe6060f1SDimitry Andric       break;
2573fe6060f1SDimitry Andric     }
2574bdd1243dSDimitry Andric     [[fallthrough]];
2575e8d8bef9SDimitry Andric   case DK_SWORD:
25765ffd83dbSDimitry Andric   case DK_DW:
25775ffd83dbSDimitry Andric     Lex();
25785ffd83dbSDimitry Andric     return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc);
25795ffd83dbSDimitry Andric   case DK_DWORD:
2580fe6060f1SDimitry Andric     if (afterNextTok.is(AsmToken::Identifier) &&
2581fe6060f1SDimitry Andric         afterNextTok.getString().equals_insensitive("ptr")) {
2582fe6060f1SDimitry Andric       // Size directive; part of an instruction.
2583fe6060f1SDimitry Andric       break;
2584fe6060f1SDimitry Andric     }
2585bdd1243dSDimitry Andric     [[fallthrough]];
2586e8d8bef9SDimitry Andric   case DK_SDWORD:
25875ffd83dbSDimitry Andric   case DK_DD:
25885ffd83dbSDimitry Andric     Lex();
25895ffd83dbSDimitry Andric     return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc);
25905ffd83dbSDimitry Andric   case DK_FWORD:
2591fe6060f1SDimitry Andric     if (afterNextTok.is(AsmToken::Identifier) &&
2592fe6060f1SDimitry Andric         afterNextTok.getString().equals_insensitive("ptr")) {
2593fe6060f1SDimitry Andric       // Size directive; part of an instruction.
2594fe6060f1SDimitry Andric       break;
2595fe6060f1SDimitry Andric     }
2596bdd1243dSDimitry Andric     [[fallthrough]];
2597e8d8bef9SDimitry Andric   case DK_DF:
25985ffd83dbSDimitry Andric     Lex();
25995ffd83dbSDimitry Andric     return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc);
26005ffd83dbSDimitry Andric   case DK_QWORD:
2601fe6060f1SDimitry Andric     if (afterNextTok.is(AsmToken::Identifier) &&
2602fe6060f1SDimitry Andric         afterNextTok.getString().equals_insensitive("ptr")) {
2603fe6060f1SDimitry Andric       // Size directive; part of an instruction.
2604fe6060f1SDimitry Andric       break;
2605fe6060f1SDimitry Andric     }
2606bdd1243dSDimitry Andric     [[fallthrough]];
2607e8d8bef9SDimitry Andric   case DK_SQWORD:
26085ffd83dbSDimitry Andric   case DK_DQ:
26095ffd83dbSDimitry Andric     Lex();
26105ffd83dbSDimitry Andric     return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc);
26115ffd83dbSDimitry Andric   case DK_REAL4:
26125ffd83dbSDimitry Andric     Lex();
2613e8d8bef9SDimitry Andric     return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), 4,
2614e8d8bef9SDimitry Andric                                         IDVal, IDLoc);
26155ffd83dbSDimitry Andric   case DK_REAL8:
26165ffd83dbSDimitry Andric     Lex();
2617e8d8bef9SDimitry Andric     return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8,
2618e8d8bef9SDimitry Andric                                         IDVal, IDLoc);
2619e8d8bef9SDimitry Andric   case DK_REAL10:
2620e8d8bef9SDimitry Andric     Lex();
2621e8d8bef9SDimitry Andric     return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(),
2622e8d8bef9SDimitry Andric                                         10, IDVal, IDLoc);
26235ffd83dbSDimitry Andric   case DK_STRUCT:
26245ffd83dbSDimitry Andric   case DK_UNION:
26255ffd83dbSDimitry Andric     Lex();
26265ffd83dbSDimitry Andric     return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc);
26275ffd83dbSDimitry Andric   case DK_ENDS:
26285ffd83dbSDimitry Andric     Lex();
26295ffd83dbSDimitry Andric     return parseDirectiveEnds(IDVal, IDLoc);
2630e8d8bef9SDimitry Andric   case DK_MACRO:
2631e8d8bef9SDimitry Andric     Lex();
2632e8d8bef9SDimitry Andric     return parseDirectiveMacro(IDVal, IDLoc);
26335ffd83dbSDimitry Andric   }
26345ffd83dbSDimitry Andric 
26355ffd83dbSDimitry Andric   // Finally, we check if this is allocating a variable with user-defined type.
26365ffd83dbSDimitry Andric   auto NextIt = Structs.find(nextVal.lower());
26375ffd83dbSDimitry Andric   if (NextIt != Structs.end()) {
26385ffd83dbSDimitry Andric     Lex();
26395ffd83dbSDimitry Andric     return parseDirectiveNamedStructValue(/*Structure=*/NextIt->getValue(),
26405ffd83dbSDimitry Andric                                           nextVal, nextLoc, IDVal);
26415ffd83dbSDimitry Andric   }
26425ffd83dbSDimitry Andric 
26435ffd83dbSDimitry Andric   // __asm _emit or __asm __emit
26445ffd83dbSDimitry Andric   if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
26455ffd83dbSDimitry Andric                              IDVal == "_EMIT" || IDVal == "__EMIT"))
26465ffd83dbSDimitry Andric     return parseDirectiveMSEmit(IDLoc, Info, IDVal.size());
26475ffd83dbSDimitry Andric 
26485ffd83dbSDimitry Andric   // __asm align
26495ffd83dbSDimitry Andric   if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
26505ffd83dbSDimitry Andric     return parseDirectiveMSAlign(IDLoc, Info);
26515ffd83dbSDimitry Andric 
26525ffd83dbSDimitry Andric   if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN"))
26535ffd83dbSDimitry Andric     Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4);
26545ffd83dbSDimitry Andric   if (checkForValidSection())
26555ffd83dbSDimitry Andric     return true;
26565ffd83dbSDimitry Andric 
26575ffd83dbSDimitry Andric   // Canonicalize the opcode to lower case.
26585ffd83dbSDimitry Andric   std::string OpcodeStr = IDVal.lower();
26595ffd83dbSDimitry Andric   ParseInstructionInfo IInfo(Info.AsmRewrites);
26605ffd83dbSDimitry Andric   bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID,
26615ffd83dbSDimitry Andric                                                           Info.ParsedOperands);
26625ffd83dbSDimitry Andric   Info.ParseError = ParseHadError;
26635ffd83dbSDimitry Andric 
26645ffd83dbSDimitry Andric   // Dump the parsed representation, if requested.
26655ffd83dbSDimitry Andric   if (getShowParsedOperands()) {
26665ffd83dbSDimitry Andric     SmallString<256> Str;
26675ffd83dbSDimitry Andric     raw_svector_ostream OS(Str);
26685ffd83dbSDimitry Andric     OS << "parsed instruction: [";
26695ffd83dbSDimitry Andric     for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) {
26705ffd83dbSDimitry Andric       if (i != 0)
26715ffd83dbSDimitry Andric         OS << ", ";
26725ffd83dbSDimitry Andric       Info.ParsedOperands[i]->print(OS);
26735ffd83dbSDimitry Andric     }
26745ffd83dbSDimitry Andric     OS << "]";
26755ffd83dbSDimitry Andric 
26765ffd83dbSDimitry Andric     printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
26775ffd83dbSDimitry Andric   }
26785ffd83dbSDimitry Andric 
26795ffd83dbSDimitry Andric   // Fail even if ParseInstruction erroneously returns false.
26805ffd83dbSDimitry Andric   if (hasPendingError() || ParseHadError)
26815ffd83dbSDimitry Andric     return true;
26825ffd83dbSDimitry Andric 
26835ffd83dbSDimitry Andric   // If we are generating dwarf for the current section then generate a .loc
26845ffd83dbSDimitry Andric   // directive for the instruction.
26855ffd83dbSDimitry Andric   if (!ParseHadError && enabledGenDwarfForAssembly() &&
26865ffd83dbSDimitry Andric       getContext().getGenDwarfSectionSyms().count(
26875ffd83dbSDimitry Andric           getStreamer().getCurrentSectionOnly())) {
26885ffd83dbSDimitry Andric     unsigned Line;
26895ffd83dbSDimitry Andric     if (ActiveMacros.empty())
26905ffd83dbSDimitry Andric       Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
26915ffd83dbSDimitry Andric     else
26925ffd83dbSDimitry Andric       Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
26935ffd83dbSDimitry Andric                                    ActiveMacros.front()->ExitBuffer);
26945ffd83dbSDimitry Andric 
26955ffd83dbSDimitry Andric     // If we previously parsed a cpp hash file line comment then make sure the
26965ffd83dbSDimitry Andric     // current Dwarf File is for the CppHashFilename if not then emit the
26975ffd83dbSDimitry Andric     // Dwarf File table for it and adjust the line number for the .loc.
26985ffd83dbSDimitry Andric     if (!CppHashInfo.Filename.empty()) {
26995ffd83dbSDimitry Andric       unsigned FileNumber = getStreamer().emitDwarfFileDirective(
27005ffd83dbSDimitry Andric           0, StringRef(), CppHashInfo.Filename);
27015ffd83dbSDimitry Andric       getContext().setGenDwarfFileNumber(FileNumber);
27025ffd83dbSDimitry Andric 
27035ffd83dbSDimitry Andric       unsigned CppHashLocLineNo =
27045ffd83dbSDimitry Andric         SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf);
27055ffd83dbSDimitry Andric       Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo);
27065ffd83dbSDimitry Andric     }
27075ffd83dbSDimitry Andric 
27085ffd83dbSDimitry Andric     getStreamer().emitDwarfLocDirective(
27095ffd83dbSDimitry Andric         getContext().getGenDwarfFileNumber(), Line, 0,
27105ffd83dbSDimitry Andric         DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0,
27115ffd83dbSDimitry Andric         StringRef());
27125ffd83dbSDimitry Andric   }
27135ffd83dbSDimitry Andric 
27145ffd83dbSDimitry Andric   // If parsing succeeded, match the instruction.
27155ffd83dbSDimitry Andric   if (!ParseHadError) {
27165ffd83dbSDimitry Andric     uint64_t ErrorInfo;
27175ffd83dbSDimitry Andric     if (getTargetParser().MatchAndEmitInstruction(
27185ffd83dbSDimitry Andric             IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo,
27195ffd83dbSDimitry Andric             getTargetParser().isParsingMSInlineAsm()))
27205ffd83dbSDimitry Andric       return true;
27215ffd83dbSDimitry Andric   }
27225ffd83dbSDimitry Andric   return false;
27235ffd83dbSDimitry Andric }
27245ffd83dbSDimitry Andric 
27255ffd83dbSDimitry Andric // Parse and erase curly braces marking block start/end.
parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> & AsmStrRewrites)27265ffd83dbSDimitry Andric bool MasmParser::parseCurlyBlockScope(
27275ffd83dbSDimitry Andric     SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
27285ffd83dbSDimitry Andric   // Identify curly brace marking block start/end.
27295ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
27305ffd83dbSDimitry Andric     return false;
27315ffd83dbSDimitry Andric 
27325ffd83dbSDimitry Andric   SMLoc StartLoc = Lexer.getLoc();
27335ffd83dbSDimitry Andric   Lex(); // Eat the brace.
27345ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::EndOfStatement))
27355ffd83dbSDimitry Andric     Lex(); // Eat EndOfStatement following the brace.
27365ffd83dbSDimitry Andric 
27375ffd83dbSDimitry Andric   // Erase the block start/end brace from the output asm string.
27385ffd83dbSDimitry Andric   AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() -
27395ffd83dbSDimitry Andric                                                   StartLoc.getPointer());
27405ffd83dbSDimitry Andric   return true;
27415ffd83dbSDimitry Andric }
27425ffd83dbSDimitry Andric 
27435ffd83dbSDimitry Andric /// parseCppHashLineFilenameComment as this:
27445ffd83dbSDimitry Andric ///   ::= # number "filename"
parseCppHashLineFilenameComment(SMLoc L)27455ffd83dbSDimitry Andric bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
27465ffd83dbSDimitry Andric   Lex(); // Eat the hash token.
27475ffd83dbSDimitry Andric   // Lexer only ever emits HashDirective if it fully formed if it's
27485ffd83dbSDimitry Andric   // done the checking already so this is an internal error.
27495ffd83dbSDimitry Andric   assert(getTok().is(AsmToken::Integer) &&
27505ffd83dbSDimitry Andric          "Lexing Cpp line comment: Expected Integer");
27515ffd83dbSDimitry Andric   int64_t LineNumber = getTok().getIntVal();
27525ffd83dbSDimitry Andric   Lex();
27535ffd83dbSDimitry Andric   assert(getTok().is(AsmToken::String) &&
27545ffd83dbSDimitry Andric          "Lexing Cpp line comment: Expected String");
27555ffd83dbSDimitry Andric   StringRef Filename = getTok().getString();
27565ffd83dbSDimitry Andric   Lex();
27575ffd83dbSDimitry Andric 
27585ffd83dbSDimitry Andric   // Get rid of the enclosing quotes.
27595ffd83dbSDimitry Andric   Filename = Filename.substr(1, Filename.size() - 2);
27605ffd83dbSDimitry Andric 
27615ffd83dbSDimitry Andric   // Save the SMLoc, Filename and LineNumber for later use by diagnostics
27625ffd83dbSDimitry Andric   // and possibly DWARF file info.
27635ffd83dbSDimitry Andric   CppHashInfo.Loc = L;
27645ffd83dbSDimitry Andric   CppHashInfo.Filename = Filename;
27655ffd83dbSDimitry Andric   CppHashInfo.LineNumber = LineNumber;
27665ffd83dbSDimitry Andric   CppHashInfo.Buf = CurBuffer;
27675ffd83dbSDimitry Andric   if (FirstCppHashFilename.empty())
27685ffd83dbSDimitry Andric     FirstCppHashFilename = Filename;
27695ffd83dbSDimitry Andric   return false;
27705ffd83dbSDimitry Andric }
27715ffd83dbSDimitry Andric 
27725ffd83dbSDimitry Andric /// will use the last parsed cpp hash line filename comment
27735ffd83dbSDimitry Andric /// for the Filename and LineNo if any in the diagnostic.
DiagHandler(const SMDiagnostic & Diag,void * Context)27745ffd83dbSDimitry Andric void MasmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
27755ffd83dbSDimitry Andric   const MasmParser *Parser = static_cast<const MasmParser *>(Context);
27765ffd83dbSDimitry Andric   raw_ostream &OS = errs();
27775ffd83dbSDimitry Andric 
27785ffd83dbSDimitry Andric   const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
27795ffd83dbSDimitry Andric   SMLoc DiagLoc = Diag.getLoc();
27805ffd83dbSDimitry Andric   unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
27815ffd83dbSDimitry Andric   unsigned CppHashBuf =
27825ffd83dbSDimitry Andric       Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
27835ffd83dbSDimitry Andric 
27845ffd83dbSDimitry Andric   // Like SourceMgr::printMessage() we need to print the include stack if any
27855ffd83dbSDimitry Andric   // before printing the message.
27865ffd83dbSDimitry Andric   unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
27875ffd83dbSDimitry Andric   if (!Parser->SavedDiagHandler && DiagCurBuffer &&
27885ffd83dbSDimitry Andric       DiagCurBuffer != DiagSrcMgr.getMainFileID()) {
27895ffd83dbSDimitry Andric     SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
27905ffd83dbSDimitry Andric     DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
27915ffd83dbSDimitry Andric   }
27925ffd83dbSDimitry Andric 
27935ffd83dbSDimitry Andric   // If we have not parsed a cpp hash line filename comment or the source
27945ffd83dbSDimitry Andric   // manager changed or buffer changed (like in a nested include) then just
27955ffd83dbSDimitry Andric   // print the normal diagnostic using its Filename and LineNo.
27965ffd83dbSDimitry Andric   if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
27975ffd83dbSDimitry Andric       DiagBuf != CppHashBuf) {
27985ffd83dbSDimitry Andric     if (Parser->SavedDiagHandler)
27995ffd83dbSDimitry Andric       Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
28005ffd83dbSDimitry Andric     else
28015ffd83dbSDimitry Andric       Diag.print(nullptr, OS);
28025ffd83dbSDimitry Andric     return;
28035ffd83dbSDimitry Andric   }
28045ffd83dbSDimitry Andric 
28055ffd83dbSDimitry Andric   // Use the CppHashFilename and calculate a line number based on the
28065ffd83dbSDimitry Andric   // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc
28075ffd83dbSDimitry Andric   // for the diagnostic.
28085ffd83dbSDimitry Andric   const std::string &Filename = std::string(Parser->CppHashInfo.Filename);
28095ffd83dbSDimitry Andric 
28105ffd83dbSDimitry Andric   int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
28115ffd83dbSDimitry Andric   int CppHashLocLineNo =
28125ffd83dbSDimitry Andric       Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
28135ffd83dbSDimitry Andric   int LineNo =
28145ffd83dbSDimitry Andric       Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
28155ffd83dbSDimitry Andric 
28165ffd83dbSDimitry Andric   SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo,
28175ffd83dbSDimitry Andric                        Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(),
28185ffd83dbSDimitry Andric                        Diag.getLineContents(), Diag.getRanges());
28195ffd83dbSDimitry Andric 
28205ffd83dbSDimitry Andric   if (Parser->SavedDiagHandler)
28215ffd83dbSDimitry Andric     Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
28225ffd83dbSDimitry Andric   else
28235ffd83dbSDimitry Andric     NewDiag.print(nullptr, OS);
28245ffd83dbSDimitry Andric }
28255ffd83dbSDimitry Andric 
2826e8d8bef9SDimitry Andric // This is similar to the IsIdentifierChar function in AsmLexer.cpp, but does
2827e8d8bef9SDimitry Andric // not accept '.'.
isMacroParameterChar(char C)2828e8d8bef9SDimitry Andric static bool isMacroParameterChar(char C) {
2829e8d8bef9SDimitry Andric   return isAlnum(C) || C == '_' || C == '$' || C == '@' || C == '?';
28305ffd83dbSDimitry Andric }
28315ffd83dbSDimitry Andric 
expandMacro(raw_svector_ostream & OS,StringRef Body,ArrayRef<MCAsmMacroParameter> Parameters,ArrayRef<MCAsmMacroArgument> A,const std::vector<std::string> & Locals,SMLoc L)28325ffd83dbSDimitry Andric bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
28335ffd83dbSDimitry Andric                              ArrayRef<MCAsmMacroParameter> Parameters,
28345ffd83dbSDimitry Andric                              ArrayRef<MCAsmMacroArgument> A,
2835e8d8bef9SDimitry Andric                              const std::vector<std::string> &Locals, SMLoc L) {
28365ffd83dbSDimitry Andric   unsigned NParameters = Parameters.size();
2837e8d8bef9SDimitry Andric   if (NParameters != A.size())
28385ffd83dbSDimitry Andric     return Error(L, "Wrong number of arguments");
2839e8d8bef9SDimitry Andric   StringMap<std::string> LocalSymbols;
2840e8d8bef9SDimitry Andric   std::string Name;
2841e8d8bef9SDimitry Andric   Name.reserve(6);
2842e8d8bef9SDimitry Andric   for (StringRef Local : Locals) {
2843e8d8bef9SDimitry Andric     raw_string_ostream LocalName(Name);
2844e8d8bef9SDimitry Andric     LocalName << "??"
2845e8d8bef9SDimitry Andric               << format_hex_no_prefix(LocalCounter++, 4, /*Upper=*/true);
2846*0fca6ea1SDimitry Andric     LocalSymbols.insert({Local, Name});
2847e8d8bef9SDimitry Andric     Name.clear();
2848e8d8bef9SDimitry Andric   }
28495ffd83dbSDimitry Andric 
2850bdd1243dSDimitry Andric   std::optional<char> CurrentQuote;
28515ffd83dbSDimitry Andric   while (!Body.empty()) {
28525ffd83dbSDimitry Andric     // Scan for the next substitution.
28535ffd83dbSDimitry Andric     std::size_t End = Body.size(), Pos = 0;
2854e8d8bef9SDimitry Andric     std::size_t IdentifierPos = End;
28555ffd83dbSDimitry Andric     for (; Pos != End; ++Pos) {
2856e8d8bef9SDimitry Andric       // Find the next possible macro parameter, including preceding a '&'
2857e8d8bef9SDimitry Andric       // inside quotes.
2858e8d8bef9SDimitry Andric       if (Body[Pos] == '&')
28595ffd83dbSDimitry Andric         break;
2860e8d8bef9SDimitry Andric       if (isMacroParameterChar(Body[Pos])) {
286181ad6265SDimitry Andric         if (!CurrentQuote)
2862e8d8bef9SDimitry Andric           break;
2863e8d8bef9SDimitry Andric         if (IdentifierPos == End)
2864e8d8bef9SDimitry Andric           IdentifierPos = Pos;
28655ffd83dbSDimitry Andric       } else {
2866e8d8bef9SDimitry Andric         IdentifierPos = End;
28675ffd83dbSDimitry Andric       }
2868e8d8bef9SDimitry Andric 
2869e8d8bef9SDimitry Andric       // Track quotation status
287081ad6265SDimitry Andric       if (!CurrentQuote) {
2871e8d8bef9SDimitry Andric         if (Body[Pos] == '\'' || Body[Pos] == '"')
2872e8d8bef9SDimitry Andric           CurrentQuote = Body[Pos];
2873e8d8bef9SDimitry Andric       } else if (Body[Pos] == CurrentQuote) {
2874e8d8bef9SDimitry Andric         if (Pos + 1 != End && Body[Pos + 1] == CurrentQuote) {
2875e8d8bef9SDimitry Andric           // Escaped quote, and quotes aren't identifier chars; skip
2876e8d8bef9SDimitry Andric           ++Pos;
2877e8d8bef9SDimitry Andric           continue;
2878e8d8bef9SDimitry Andric         } else {
2879e8d8bef9SDimitry Andric           CurrentQuote.reset();
2880e8d8bef9SDimitry Andric         }
2881e8d8bef9SDimitry Andric       }
2882e8d8bef9SDimitry Andric     }
2883e8d8bef9SDimitry Andric     if (IdentifierPos != End) {
2884e8d8bef9SDimitry Andric       // We've recognized an identifier before an apostrophe inside quotes;
2885e8d8bef9SDimitry Andric       // check once to see if we can expand it.
2886e8d8bef9SDimitry Andric       Pos = IdentifierPos;
2887e8d8bef9SDimitry Andric       IdentifierPos = End;
28885ffd83dbSDimitry Andric     }
28895ffd83dbSDimitry Andric 
28905ffd83dbSDimitry Andric     // Add the prefix.
28915ffd83dbSDimitry Andric     OS << Body.slice(0, Pos);
28925ffd83dbSDimitry Andric 
28935ffd83dbSDimitry Andric     // Check if we reached the end.
28945ffd83dbSDimitry Andric     if (Pos == End)
28955ffd83dbSDimitry Andric       break;
28965ffd83dbSDimitry Andric 
2897e8d8bef9SDimitry Andric     unsigned I = Pos;
2898e8d8bef9SDimitry Andric     bool InitialAmpersand = (Body[I] == '&');
2899e8d8bef9SDimitry Andric     if (InitialAmpersand) {
29005ffd83dbSDimitry Andric       ++I;
2901e8d8bef9SDimitry Andric       ++Pos;
2902e8d8bef9SDimitry Andric     }
2903e8d8bef9SDimitry Andric     while (I < End && isMacroParameterChar(Body[I]))
29045ffd83dbSDimitry Andric       ++I;
29055ffd83dbSDimitry Andric 
2906e8d8bef9SDimitry Andric     const char *Begin = Body.data() + Pos;
2907e8d8bef9SDimitry Andric     StringRef Argument(Begin, I - Pos);
2908fe6060f1SDimitry Andric     const std::string ArgumentLower = Argument.lower();
29095ffd83dbSDimitry Andric     unsigned Index = 0;
29105ffd83dbSDimitry Andric 
29115ffd83dbSDimitry Andric     for (; Index < NParameters; ++Index)
2912fe6060f1SDimitry Andric       if (Parameters[Index].Name.equals_insensitive(ArgumentLower))
29135ffd83dbSDimitry Andric         break;
29145ffd83dbSDimitry Andric 
29155ffd83dbSDimitry Andric     if (Index == NParameters) {
2916e8d8bef9SDimitry Andric       if (InitialAmpersand)
2917e8d8bef9SDimitry Andric         OS << '&';
2918fe6060f1SDimitry Andric       auto it = LocalSymbols.find(ArgumentLower);
2919e8d8bef9SDimitry Andric       if (it != LocalSymbols.end())
2920e8d8bef9SDimitry Andric         OS << it->second;
2921e8d8bef9SDimitry Andric       else
2922e8d8bef9SDimitry Andric         OS << Argument;
29235ffd83dbSDimitry Andric       Pos = I;
29245ffd83dbSDimitry Andric     } else {
2925e8d8bef9SDimitry Andric       for (const AsmToken &Token : A[Index]) {
2926e8d8bef9SDimitry Andric         // In MASM, you can write '%expr'.
29275ffd83dbSDimitry Andric         // The prefix '%' evaluates the expression 'expr'
29285ffd83dbSDimitry Andric         // and uses the result as a string (e.g. replace %(1+2) with the
29295ffd83dbSDimitry Andric         // string "3").
29305ffd83dbSDimitry Andric         // Here, we identify the integer token which is the result of the
29315ffd83dbSDimitry Andric         // absolute expression evaluation and replace it with its string
29325ffd83dbSDimitry Andric         // representation.
2933e8d8bef9SDimitry Andric         if (Token.getString().front() == '%' && Token.is(AsmToken::Integer))
29345ffd83dbSDimitry Andric           // Emit an integer value to the buffer.
29355ffd83dbSDimitry Andric           OS << Token.getIntVal();
29365ffd83dbSDimitry Andric         else
2937e8d8bef9SDimitry Andric           OS << Token.getString();
29385ffd83dbSDimitry Andric       }
2939e8d8bef9SDimitry Andric 
2940e8d8bef9SDimitry Andric       Pos += Argument.size();
2941e8d8bef9SDimitry Andric       if (Pos < End && Body[Pos] == '&') {
2942e8d8bef9SDimitry Andric         ++Pos;
29435ffd83dbSDimitry Andric       }
29445ffd83dbSDimitry Andric     }
29455ffd83dbSDimitry Andric     // Update the scan point.
29465ffd83dbSDimitry Andric     Body = Body.substr(Pos);
29475ffd83dbSDimitry Andric   }
29485ffd83dbSDimitry Andric 
29495ffd83dbSDimitry Andric   return false;
29505ffd83dbSDimitry Andric }
29515ffd83dbSDimitry Andric 
isOperator(AsmToken::TokenKind kind)29525ffd83dbSDimitry Andric static bool isOperator(AsmToken::TokenKind kind) {
29535ffd83dbSDimitry Andric   switch (kind) {
29545ffd83dbSDimitry Andric   default:
29555ffd83dbSDimitry Andric     return false;
29565ffd83dbSDimitry Andric   case AsmToken::Plus:
29575ffd83dbSDimitry Andric   case AsmToken::Minus:
29585ffd83dbSDimitry Andric   case AsmToken::Tilde:
29595ffd83dbSDimitry Andric   case AsmToken::Slash:
29605ffd83dbSDimitry Andric   case AsmToken::Star:
29615ffd83dbSDimitry Andric   case AsmToken::Dot:
29625ffd83dbSDimitry Andric   case AsmToken::Equal:
29635ffd83dbSDimitry Andric   case AsmToken::EqualEqual:
29645ffd83dbSDimitry Andric   case AsmToken::Pipe:
29655ffd83dbSDimitry Andric   case AsmToken::PipePipe:
29665ffd83dbSDimitry Andric   case AsmToken::Caret:
29675ffd83dbSDimitry Andric   case AsmToken::Amp:
29685ffd83dbSDimitry Andric   case AsmToken::AmpAmp:
29695ffd83dbSDimitry Andric   case AsmToken::Exclaim:
29705ffd83dbSDimitry Andric   case AsmToken::ExclaimEqual:
29715ffd83dbSDimitry Andric   case AsmToken::Less:
29725ffd83dbSDimitry Andric   case AsmToken::LessEqual:
29735ffd83dbSDimitry Andric   case AsmToken::LessLess:
29745ffd83dbSDimitry Andric   case AsmToken::LessGreater:
29755ffd83dbSDimitry Andric   case AsmToken::Greater:
29765ffd83dbSDimitry Andric   case AsmToken::GreaterEqual:
29775ffd83dbSDimitry Andric   case AsmToken::GreaterGreater:
29785ffd83dbSDimitry Andric     return true;
29795ffd83dbSDimitry Andric   }
29805ffd83dbSDimitry Andric }
29815ffd83dbSDimitry Andric 
29825ffd83dbSDimitry Andric namespace {
29835ffd83dbSDimitry Andric 
29845ffd83dbSDimitry Andric class AsmLexerSkipSpaceRAII {
29855ffd83dbSDimitry Andric public:
AsmLexerSkipSpaceRAII(AsmLexer & Lexer,bool SkipSpace)29865ffd83dbSDimitry Andric   AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) {
29875ffd83dbSDimitry Andric     Lexer.setSkipSpace(SkipSpace);
29885ffd83dbSDimitry Andric   }
29895ffd83dbSDimitry Andric 
~AsmLexerSkipSpaceRAII()29905ffd83dbSDimitry Andric   ~AsmLexerSkipSpaceRAII() {
29915ffd83dbSDimitry Andric     Lexer.setSkipSpace(true);
29925ffd83dbSDimitry Andric   }
29935ffd83dbSDimitry Andric 
29945ffd83dbSDimitry Andric private:
29955ffd83dbSDimitry Andric   AsmLexer &Lexer;
29965ffd83dbSDimitry Andric };
29975ffd83dbSDimitry Andric 
29985ffd83dbSDimitry Andric } // end anonymous namespace
29995ffd83dbSDimitry Andric 
parseMacroArgument(const MCAsmMacroParameter * MP,MCAsmMacroArgument & MA,AsmToken::TokenKind EndTok)3000e8d8bef9SDimitry Andric bool MasmParser::parseMacroArgument(const MCAsmMacroParameter *MP,
3001e8d8bef9SDimitry Andric                                     MCAsmMacroArgument &MA,
3002e8d8bef9SDimitry Andric                                     AsmToken::TokenKind EndTok) {
3003e8d8bef9SDimitry Andric   if (MP && MP->Vararg) {
3004e8d8bef9SDimitry Andric     if (Lexer.isNot(EndTok)) {
3005e8d8bef9SDimitry Andric       SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok);
3006e8d8bef9SDimitry Andric       for (StringRef S : Str) {
3007e8d8bef9SDimitry Andric         MA.emplace_back(AsmToken::String, S);
30085ffd83dbSDimitry Andric       }
3009e8d8bef9SDimitry Andric     }
3010e8d8bef9SDimitry Andric     return false;
3011e8d8bef9SDimitry Andric   }
3012e8d8bef9SDimitry Andric 
3013e8d8bef9SDimitry Andric   SMLoc StrLoc = Lexer.getLoc(), EndLoc;
3014e8d8bef9SDimitry Andric   if (Lexer.is(AsmToken::Less) && isAngleBracketString(StrLoc, EndLoc)) {
3015e8d8bef9SDimitry Andric     const char *StrChar = StrLoc.getPointer() + 1;
3016e8d8bef9SDimitry Andric     const char *EndChar = EndLoc.getPointer() - 1;
3017e8d8bef9SDimitry Andric     jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
3018e8d8bef9SDimitry Andric     /// Eat from '<' to '>'.
3019e8d8bef9SDimitry Andric     Lex();
3020e8d8bef9SDimitry Andric     MA.emplace_back(AsmToken::String, StringRef(StrChar, EndChar - StrChar));
30215ffd83dbSDimitry Andric     return false;
30225ffd83dbSDimitry Andric   }
30235ffd83dbSDimitry Andric 
30245ffd83dbSDimitry Andric   unsigned ParenLevel = 0;
30255ffd83dbSDimitry Andric 
30265ffd83dbSDimitry Andric   // Darwin doesn't use spaces to delmit arguments.
30275ffd83dbSDimitry Andric   AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin);
30285ffd83dbSDimitry Andric 
30295ffd83dbSDimitry Andric   bool SpaceEaten;
30305ffd83dbSDimitry Andric 
30315ffd83dbSDimitry Andric   while (true) {
30325ffd83dbSDimitry Andric     SpaceEaten = false;
30335ffd83dbSDimitry Andric     if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal))
3034e8d8bef9SDimitry Andric       return TokError("unexpected token");
30355ffd83dbSDimitry Andric 
30365ffd83dbSDimitry Andric     if (ParenLevel == 0) {
30375ffd83dbSDimitry Andric       if (Lexer.is(AsmToken::Comma))
30385ffd83dbSDimitry Andric         break;
30395ffd83dbSDimitry Andric 
30405ffd83dbSDimitry Andric       if (Lexer.is(AsmToken::Space)) {
30415ffd83dbSDimitry Andric         SpaceEaten = true;
3042e8d8bef9SDimitry Andric         Lex(); // Eat spaces.
30435ffd83dbSDimitry Andric       }
30445ffd83dbSDimitry Andric 
30455ffd83dbSDimitry Andric       // Spaces can delimit parameters, but could also be part an expression.
30465ffd83dbSDimitry Andric       // If the token after a space is an operator, add the token and the next
30475ffd83dbSDimitry Andric       // one into this argument
30485ffd83dbSDimitry Andric       if (!IsDarwin) {
3049e8d8bef9SDimitry Andric         if (isOperator(Lexer.getKind()) && Lexer.isNot(EndTok)) {
30505ffd83dbSDimitry Andric           MA.push_back(getTok());
3051e8d8bef9SDimitry Andric           Lex();
30525ffd83dbSDimitry Andric 
30535ffd83dbSDimitry Andric           // Whitespace after an operator can be ignored.
30545ffd83dbSDimitry Andric           if (Lexer.is(AsmToken::Space))
3055e8d8bef9SDimitry Andric             Lex();
30565ffd83dbSDimitry Andric 
30575ffd83dbSDimitry Andric           continue;
30585ffd83dbSDimitry Andric         }
30595ffd83dbSDimitry Andric       }
30605ffd83dbSDimitry Andric       if (SpaceEaten)
30615ffd83dbSDimitry Andric         break;
30625ffd83dbSDimitry Andric     }
30635ffd83dbSDimitry Andric 
30645ffd83dbSDimitry Andric     // handleMacroEntry relies on not advancing the lexer here
30655ffd83dbSDimitry Andric     // to be able to fill in the remaining default parameter values
3066e8d8bef9SDimitry Andric     if (Lexer.is(EndTok) && (EndTok != AsmToken::RParen || ParenLevel == 0))
30675ffd83dbSDimitry Andric       break;
30685ffd83dbSDimitry Andric 
30695ffd83dbSDimitry Andric     // Adjust the current parentheses level.
30705ffd83dbSDimitry Andric     if (Lexer.is(AsmToken::LParen))
30715ffd83dbSDimitry Andric       ++ParenLevel;
30725ffd83dbSDimitry Andric     else if (Lexer.is(AsmToken::RParen) && ParenLevel)
30735ffd83dbSDimitry Andric       --ParenLevel;
30745ffd83dbSDimitry Andric 
30755ffd83dbSDimitry Andric     // Append the token to the current argument list.
30765ffd83dbSDimitry Andric     MA.push_back(getTok());
3077e8d8bef9SDimitry Andric     Lex();
30785ffd83dbSDimitry Andric   }
30795ffd83dbSDimitry Andric 
30805ffd83dbSDimitry Andric   if (ParenLevel != 0)
3081e8d8bef9SDimitry Andric     return TokError("unbalanced parentheses in argument");
3082e8d8bef9SDimitry Andric 
3083e8d8bef9SDimitry Andric   if (MA.empty() && MP) {
3084e8d8bef9SDimitry Andric     if (MP->Required) {
3085e8d8bef9SDimitry Andric       return TokError("missing value for required parameter '" + MP->Name +
3086e8d8bef9SDimitry Andric                       "'");
3087e8d8bef9SDimitry Andric     } else {
3088e8d8bef9SDimitry Andric       MA = MP->Value;
3089e8d8bef9SDimitry Andric     }
3090e8d8bef9SDimitry Andric   }
30915ffd83dbSDimitry Andric   return false;
30925ffd83dbSDimitry Andric }
30935ffd83dbSDimitry Andric 
30945ffd83dbSDimitry Andric // Parse the macro instantiation arguments.
parseMacroArguments(const MCAsmMacro * M,MCAsmMacroArguments & A,AsmToken::TokenKind EndTok)30955ffd83dbSDimitry Andric bool MasmParser::parseMacroArguments(const MCAsmMacro *M,
3096e8d8bef9SDimitry Andric                                      MCAsmMacroArguments &A,
3097e8d8bef9SDimitry Andric                                      AsmToken::TokenKind EndTok) {
30985ffd83dbSDimitry Andric   const unsigned NParameters = M ? M->Parameters.size() : 0;
30995ffd83dbSDimitry Andric   bool NamedParametersFound = false;
31005ffd83dbSDimitry Andric   SmallVector<SMLoc, 4> FALocs;
31015ffd83dbSDimitry Andric 
31025ffd83dbSDimitry Andric   A.resize(NParameters);
31035ffd83dbSDimitry Andric   FALocs.resize(NParameters);
31045ffd83dbSDimitry Andric 
31055ffd83dbSDimitry Andric   // Parse two kinds of macro invocations:
31065ffd83dbSDimitry Andric   // - macros defined without any parameters accept an arbitrary number of them
31075ffd83dbSDimitry Andric   // - macros defined with parameters accept at most that many of them
31085ffd83dbSDimitry Andric   for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
31095ffd83dbSDimitry Andric        ++Parameter) {
31105ffd83dbSDimitry Andric     SMLoc IDLoc = Lexer.getLoc();
31115ffd83dbSDimitry Andric     MCAsmMacroParameter FA;
31125ffd83dbSDimitry Andric 
3113fe6060f1SDimitry Andric     if (Lexer.is(AsmToken::Identifier) && peekTok().is(AsmToken::Equal)) {
31145ffd83dbSDimitry Andric       if (parseIdentifier(FA.Name))
31155ffd83dbSDimitry Andric         return Error(IDLoc, "invalid argument identifier for formal argument");
31165ffd83dbSDimitry Andric 
31175ffd83dbSDimitry Andric       if (Lexer.isNot(AsmToken::Equal))
31185ffd83dbSDimitry Andric         return TokError("expected '=' after formal parameter identifier");
31195ffd83dbSDimitry Andric 
31205ffd83dbSDimitry Andric       Lex();
31215ffd83dbSDimitry Andric 
31225ffd83dbSDimitry Andric       NamedParametersFound = true;
31235ffd83dbSDimitry Andric     }
31245ffd83dbSDimitry Andric 
31255ffd83dbSDimitry Andric     if (NamedParametersFound && FA.Name.empty())
31265ffd83dbSDimitry Andric       return Error(IDLoc, "cannot mix positional and keyword arguments");
31275ffd83dbSDimitry Andric 
3128e8d8bef9SDimitry Andric     unsigned PI = Parameter;
3129e8d8bef9SDimitry Andric     if (!FA.Name.empty()) {
3130e8d8bef9SDimitry Andric       assert(M && "expected macro to be defined");
3131e8d8bef9SDimitry Andric       unsigned FAI = 0;
3132e8d8bef9SDimitry Andric       for (FAI = 0; FAI < NParameters; ++FAI)
3133e8d8bef9SDimitry Andric         if (M->Parameters[FAI].Name == FA.Name)
3134e8d8bef9SDimitry Andric           break;
3135e8d8bef9SDimitry Andric 
3136e8d8bef9SDimitry Andric       if (FAI >= NParameters) {
3137e8d8bef9SDimitry Andric         return Error(IDLoc, "parameter named '" + FA.Name +
3138e8d8bef9SDimitry Andric                                 "' does not exist for macro '" + M->Name + "'");
3139e8d8bef9SDimitry Andric       }
3140e8d8bef9SDimitry Andric       PI = FAI;
3141e8d8bef9SDimitry Andric     }
3142e8d8bef9SDimitry Andric     const MCAsmMacroParameter *MP = nullptr;
3143e8d8bef9SDimitry Andric     if (M && PI < NParameters)
3144e8d8bef9SDimitry Andric       MP = &M->Parameters[PI];
3145e8d8bef9SDimitry Andric 
31465ffd83dbSDimitry Andric     SMLoc StrLoc = Lexer.getLoc();
31475ffd83dbSDimitry Andric     SMLoc EndLoc;
3148e8d8bef9SDimitry Andric     if (Lexer.is(AsmToken::Percent)) {
31495ffd83dbSDimitry Andric       const MCExpr *AbsoluteExp;
31505ffd83dbSDimitry Andric       int64_t Value;
31515ffd83dbSDimitry Andric       /// Eat '%'.
31525ffd83dbSDimitry Andric       Lex();
31535ffd83dbSDimitry Andric       if (parseExpression(AbsoluteExp, EndLoc))
31545ffd83dbSDimitry Andric         return false;
31555ffd83dbSDimitry Andric       if (!AbsoluteExp->evaluateAsAbsolute(Value,
31565ffd83dbSDimitry Andric                                            getStreamer().getAssemblerPtr()))
31575ffd83dbSDimitry Andric         return Error(StrLoc, "expected absolute expression");
31585ffd83dbSDimitry Andric       const char *StrChar = StrLoc.getPointer();
31595ffd83dbSDimitry Andric       const char *EndChar = EndLoc.getPointer();
31605ffd83dbSDimitry Andric       AsmToken newToken(AsmToken::Integer,
31615ffd83dbSDimitry Andric                         StringRef(StrChar, EndChar - StrChar), Value);
31625ffd83dbSDimitry Andric       FA.Value.push_back(newToken);
3163e8d8bef9SDimitry Andric     } else if (parseMacroArgument(MP, FA.Value, EndTok)) {
3164e8d8bef9SDimitry Andric       if (M)
3165e8d8bef9SDimitry Andric         return addErrorSuffix(" in '" + M->Name + "' macro");
3166e8d8bef9SDimitry Andric       else
31675ffd83dbSDimitry Andric         return true;
31685ffd83dbSDimitry Andric     }
31695ffd83dbSDimitry Andric 
31705ffd83dbSDimitry Andric     if (!FA.Value.empty()) {
31715ffd83dbSDimitry Andric       if (A.size() <= PI)
31725ffd83dbSDimitry Andric         A.resize(PI + 1);
31735ffd83dbSDimitry Andric       A[PI] = FA.Value;
31745ffd83dbSDimitry Andric 
31755ffd83dbSDimitry Andric       if (FALocs.size() <= PI)
31765ffd83dbSDimitry Andric         FALocs.resize(PI + 1);
31775ffd83dbSDimitry Andric 
31785ffd83dbSDimitry Andric       FALocs[PI] = Lexer.getLoc();
31795ffd83dbSDimitry Andric     }
31805ffd83dbSDimitry Andric 
31815ffd83dbSDimitry Andric     // At the end of the statement, fill in remaining arguments that have
31825ffd83dbSDimitry Andric     // default values. If there aren't any, then the next argument is
31835ffd83dbSDimitry Andric     // required but missing
3184e8d8bef9SDimitry Andric     if (Lexer.is(EndTok)) {
31855ffd83dbSDimitry Andric       bool Failure = false;
31865ffd83dbSDimitry Andric       for (unsigned FAI = 0; FAI < NParameters; ++FAI) {
31875ffd83dbSDimitry Andric         if (A[FAI].empty()) {
31885ffd83dbSDimitry Andric           if (M->Parameters[FAI].Required) {
31895ffd83dbSDimitry Andric             Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(),
31905ffd83dbSDimitry Andric                   "missing value for required parameter "
3191e8d8bef9SDimitry Andric                   "'" +
3192e8d8bef9SDimitry Andric                       M->Parameters[FAI].Name + "' in macro '" + M->Name + "'");
31935ffd83dbSDimitry Andric             Failure = true;
31945ffd83dbSDimitry Andric           }
31955ffd83dbSDimitry Andric 
31965ffd83dbSDimitry Andric           if (!M->Parameters[FAI].Value.empty())
31975ffd83dbSDimitry Andric             A[FAI] = M->Parameters[FAI].Value;
31985ffd83dbSDimitry Andric         }
31995ffd83dbSDimitry Andric       }
32005ffd83dbSDimitry Andric       return Failure;
32015ffd83dbSDimitry Andric     }
32025ffd83dbSDimitry Andric 
32035ffd83dbSDimitry Andric     if (Lexer.is(AsmToken::Comma))
32045ffd83dbSDimitry Andric       Lex();
32055ffd83dbSDimitry Andric   }
32065ffd83dbSDimitry Andric 
32075ffd83dbSDimitry Andric   return TokError("too many positional arguments");
32085ffd83dbSDimitry Andric }
32095ffd83dbSDimitry Andric 
handleMacroEntry(const MCAsmMacro * M,SMLoc NameLoc,AsmToken::TokenKind ArgumentEndTok)3210e8d8bef9SDimitry Andric bool MasmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc,
3211e8d8bef9SDimitry Andric                                   AsmToken::TokenKind ArgumentEndTok) {
32125ffd83dbSDimitry Andric   // Arbitrarily limit macro nesting depth (default matches 'as'). We can
32135ffd83dbSDimitry Andric   // eliminate this, although we should protect against infinite loops.
32145ffd83dbSDimitry Andric   unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;
32155ffd83dbSDimitry Andric   if (ActiveMacros.size() == MaxNestingDepth) {
32165ffd83dbSDimitry Andric     std::ostringstream MaxNestingDepthError;
32175ffd83dbSDimitry Andric     MaxNestingDepthError << "macros cannot be nested more than "
32185ffd83dbSDimitry Andric                          << MaxNestingDepth << " levels deep."
32195ffd83dbSDimitry Andric                          << " Use -asm-macro-max-nesting-depth to increase "
32205ffd83dbSDimitry Andric                             "this limit.";
32215ffd83dbSDimitry Andric     return TokError(MaxNestingDepthError.str());
32225ffd83dbSDimitry Andric   }
32235ffd83dbSDimitry Andric 
32245ffd83dbSDimitry Andric   MCAsmMacroArguments A;
3225e8d8bef9SDimitry Andric   if (parseMacroArguments(M, A, ArgumentEndTok))
32265ffd83dbSDimitry Andric     return true;
32275ffd83dbSDimitry Andric 
32285ffd83dbSDimitry Andric   // Macro instantiation is lexical, unfortunately. We construct a new buffer
32295ffd83dbSDimitry Andric   // to hold the macro body with substitutions.
32305ffd83dbSDimitry Andric   SmallString<256> Buf;
32315ffd83dbSDimitry Andric   StringRef Body = M->Body;
32325ffd83dbSDimitry Andric   raw_svector_ostream OS(Buf);
32335ffd83dbSDimitry Andric 
3234e8d8bef9SDimitry Andric   if (expandMacro(OS, Body, M->Parameters, A, M->Locals, getTok().getLoc()))
32355ffd83dbSDimitry Andric     return true;
32365ffd83dbSDimitry Andric 
3237e8d8bef9SDimitry Andric   // We include the endm in the buffer as our cue to exit the macro
32385ffd83dbSDimitry Andric   // instantiation.
3239e8d8bef9SDimitry Andric   OS << "endm\n";
32405ffd83dbSDimitry Andric 
32415ffd83dbSDimitry Andric   std::unique_ptr<MemoryBuffer> Instantiation =
32425ffd83dbSDimitry Andric       MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
32435ffd83dbSDimitry Andric 
32445ffd83dbSDimitry Andric   // Create the macro instantiation object and add to the current macro
32455ffd83dbSDimitry Andric   // instantiation stack.
32465ffd83dbSDimitry Andric   MacroInstantiation *MI = new MacroInstantiation{
32475ffd83dbSDimitry Andric       NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
32485ffd83dbSDimitry Andric   ActiveMacros.push_back(MI);
32495ffd83dbSDimitry Andric 
32505ffd83dbSDimitry Andric   ++NumOfMacroInstantiations;
32515ffd83dbSDimitry Andric 
32525ffd83dbSDimitry Andric   // Jump to the macro instantiation and prime the lexer.
32535ffd83dbSDimitry Andric   CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
32545ffd83dbSDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
3255e8d8bef9SDimitry Andric   EndStatementAtEOFStack.push_back(true);
32565ffd83dbSDimitry Andric   Lex();
32575ffd83dbSDimitry Andric 
32585ffd83dbSDimitry Andric   return false;
32595ffd83dbSDimitry Andric }
32605ffd83dbSDimitry Andric 
handleMacroExit()32615ffd83dbSDimitry Andric void MasmParser::handleMacroExit() {
3262e8d8bef9SDimitry Andric   // Jump to the token we should return to, and consume it.
3263e8d8bef9SDimitry Andric   EndStatementAtEOFStack.pop_back();
3264e8d8bef9SDimitry Andric   jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer,
3265e8d8bef9SDimitry Andric             EndStatementAtEOFStack.back());
32665ffd83dbSDimitry Andric   Lex();
32675ffd83dbSDimitry Andric 
32685ffd83dbSDimitry Andric   // Pop the instantiation entry.
32695ffd83dbSDimitry Andric   delete ActiveMacros.back();
32705ffd83dbSDimitry Andric   ActiveMacros.pop_back();
32715ffd83dbSDimitry Andric }
32725ffd83dbSDimitry Andric 
handleMacroInvocation(const MCAsmMacro * M,SMLoc NameLoc)3273e8d8bef9SDimitry Andric bool MasmParser::handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc) {
3274e8d8bef9SDimitry Andric   if (!M->IsFunction)
3275e8d8bef9SDimitry Andric     return Error(NameLoc, "cannot invoke macro procedure as function");
3276e8d8bef9SDimitry Andric 
3277e8d8bef9SDimitry Andric   if (parseToken(AsmToken::LParen, "invoking macro function '" + M->Name +
3278e8d8bef9SDimitry Andric                                        "' requires arguments in parentheses") ||
3279e8d8bef9SDimitry Andric       handleMacroEntry(M, NameLoc, AsmToken::RParen))
3280e8d8bef9SDimitry Andric     return true;
3281e8d8bef9SDimitry Andric 
3282e8d8bef9SDimitry Andric   // Parse all statements in the macro, retrieving the exit value when it ends.
3283e8d8bef9SDimitry Andric   std::string ExitValue;
3284e8d8bef9SDimitry Andric   SmallVector<AsmRewrite, 4> AsmStrRewrites;
3285e8d8bef9SDimitry Andric   while (Lexer.isNot(AsmToken::Eof)) {
3286e8d8bef9SDimitry Andric     ParseStatementInfo Info(&AsmStrRewrites);
3287e8d8bef9SDimitry Andric     bool Parsed = parseStatement(Info, nullptr);
3288e8d8bef9SDimitry Andric 
328981ad6265SDimitry Andric     if (!Parsed && Info.ExitValue) {
3290e8d8bef9SDimitry Andric       ExitValue = std::move(*Info.ExitValue);
3291e8d8bef9SDimitry Andric       break;
3292e8d8bef9SDimitry Andric     }
3293e8d8bef9SDimitry Andric 
3294e8d8bef9SDimitry Andric     // If we have a Lexer Error we are on an Error Token. Load in Lexer Error
3295e8d8bef9SDimitry Andric     // for printing ErrMsg via Lex() only if no (presumably better) parser error
3296e8d8bef9SDimitry Andric     // exists.
3297e8d8bef9SDimitry Andric     if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) {
3298e8d8bef9SDimitry Andric       Lex();
3299e8d8bef9SDimitry Andric     }
3300e8d8bef9SDimitry Andric 
3301e8d8bef9SDimitry Andric     // parseStatement returned true so may need to emit an error.
3302e8d8bef9SDimitry Andric     printPendingErrors();
3303e8d8bef9SDimitry Andric 
3304e8d8bef9SDimitry Andric     // Skipping to the next line if needed.
3305e8d8bef9SDimitry Andric     if (Parsed && !getLexer().isAtStartOfStatement())
3306e8d8bef9SDimitry Andric       eatToEndOfStatement();
3307e8d8bef9SDimitry Andric   }
3308e8d8bef9SDimitry Andric 
3309e8d8bef9SDimitry Andric   // Consume the right-parenthesis on the other side of the arguments.
331004eeddc0SDimitry Andric   if (parseRParen())
3311e8d8bef9SDimitry Andric     return true;
3312e8d8bef9SDimitry Andric 
3313e8d8bef9SDimitry Andric   // Exit values may require lexing, unfortunately. We construct a new buffer to
3314e8d8bef9SDimitry Andric   // hold the exit value.
3315e8d8bef9SDimitry Andric   std::unique_ptr<MemoryBuffer> MacroValue =
3316e8d8bef9SDimitry Andric       MemoryBuffer::getMemBufferCopy(ExitValue, "<macro-value>");
3317e8d8bef9SDimitry Andric 
3318e8d8bef9SDimitry Andric   // Jump from this location to the instantiated exit value, and prime the
3319e8d8bef9SDimitry Andric   // lexer.
3320e8d8bef9SDimitry Andric   CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(MacroValue), Lexer.getLoc());
3321e8d8bef9SDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), nullptr,
3322e8d8bef9SDimitry Andric                   /*EndStatementAtEOF=*/false);
3323e8d8bef9SDimitry Andric   EndStatementAtEOFStack.push_back(false);
3324e8d8bef9SDimitry Andric   Lex();
3325e8d8bef9SDimitry Andric 
3326e8d8bef9SDimitry Andric   return false;
3327e8d8bef9SDimitry Andric }
3328e8d8bef9SDimitry Andric 
33295ffd83dbSDimitry Andric /// parseIdentifier:
33305ffd83dbSDimitry Andric ///   ::= identifier
33315ffd83dbSDimitry Andric ///   ::= string
parseIdentifier(StringRef & Res,IdentifierPositionKind Position)3332fe6060f1SDimitry Andric bool MasmParser::parseIdentifier(StringRef &Res,
3333fe6060f1SDimitry Andric                                  IdentifierPositionKind Position) {
33345ffd83dbSDimitry Andric   // The assembler has relaxed rules for accepting identifiers, in particular we
33355ffd83dbSDimitry Andric   // allow things like '.globl $foo' and '.def @feat.00', which would normally
33365ffd83dbSDimitry Andric   // be separate tokens. At this level, we have already lexed so we cannot
33375ffd83dbSDimitry Andric   // (currently) handle this as a context dependent token, instead we detect
33385ffd83dbSDimitry Andric   // adjacent tokens and return the combined identifier.
33395ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
33405ffd83dbSDimitry Andric     SMLoc PrefixLoc = getLexer().getLoc();
33415ffd83dbSDimitry Andric 
33425ffd83dbSDimitry Andric     // Consume the prefix character, and check for a following identifier.
33435ffd83dbSDimitry Andric 
3344fe6060f1SDimitry Andric     AsmToken nextTok = peekTok(false);
33455ffd83dbSDimitry Andric 
3346fe6060f1SDimitry Andric     if (nextTok.isNot(AsmToken::Identifier))
33475ffd83dbSDimitry Andric       return true;
33485ffd83dbSDimitry Andric 
33495ffd83dbSDimitry Andric     // We have a '$' or '@' followed by an identifier, make sure they are adjacent.
3350fe6060f1SDimitry Andric     if (PrefixLoc.getPointer() + 1 != nextTok.getLoc().getPointer())
33515ffd83dbSDimitry Andric       return true;
33525ffd83dbSDimitry Andric 
33535ffd83dbSDimitry Andric     // eat $ or @
33545ffd83dbSDimitry Andric     Lexer.Lex(); // Lexer's Lex guarantees consecutive token.
33555ffd83dbSDimitry Andric     // Construct the joined identifier and consume the token.
33565ffd83dbSDimitry Andric     Res =
33575ffd83dbSDimitry Andric         StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1);
33585ffd83dbSDimitry Andric     Lex(); // Parser Lex to maintain invariants.
33595ffd83dbSDimitry Andric     return false;
33605ffd83dbSDimitry Andric   }
33615ffd83dbSDimitry Andric 
33625ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String))
33635ffd83dbSDimitry Andric     return true;
33645ffd83dbSDimitry Andric 
33655ffd83dbSDimitry Andric   Res = getTok().getIdentifier();
33665ffd83dbSDimitry Andric 
3367fe6060f1SDimitry Andric   // Consume the identifier token - but if parsing certain directives, avoid
3368fe6060f1SDimitry Andric   // lexical expansion of the next token.
3369fe6060f1SDimitry Andric   ExpandKind ExpandNextToken = ExpandMacros;
3370fe6060f1SDimitry Andric   if (Position == StartOfStatement &&
3371fe6060f1SDimitry Andric       StringSwitch<bool>(Res)
3372fe6060f1SDimitry Andric           .CaseLower("echo", true)
3373fe6060f1SDimitry Andric           .CasesLower("ifdef", "ifndef", "elseifdef", "elseifndef", true)
3374fe6060f1SDimitry Andric           .Default(false)) {
3375fe6060f1SDimitry Andric     ExpandNextToken = DoNotExpandMacros;
3376fe6060f1SDimitry Andric   }
3377fe6060f1SDimitry Andric   Lex(ExpandNextToken);
33785ffd83dbSDimitry Andric 
33795ffd83dbSDimitry Andric   return false;
33805ffd83dbSDimitry Andric }
33815ffd83dbSDimitry Andric 
33825ffd83dbSDimitry Andric /// parseDirectiveEquate:
33835ffd83dbSDimitry Andric ///  ::= name "=" expression
33845ffd83dbSDimitry Andric ///    | name "equ" expression    (not redefinable)
33855ffd83dbSDimitry Andric ///    | name "equ" text-list
3386fe6060f1SDimitry Andric ///    | name "textequ" text-list (redefinability unspecified)
parseDirectiveEquate(StringRef IDVal,StringRef Name,DirectiveKind DirKind,SMLoc NameLoc)33875ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
3388fe6060f1SDimitry Andric                                       DirectiveKind DirKind, SMLoc NameLoc) {
3389fe6060f1SDimitry Andric   auto BuiltinIt = BuiltinSymbolMap.find(Name.lower());
3390fe6060f1SDimitry Andric   if (BuiltinIt != BuiltinSymbolMap.end())
3391fe6060f1SDimitry Andric     return Error(NameLoc, "cannot redefine a built-in symbol");
3392fe6060f1SDimitry Andric 
3393fe6060f1SDimitry Andric   Variable &Var = Variables[Name.lower()];
33945ffd83dbSDimitry Andric   if (Var.Name.empty()) {
33955ffd83dbSDimitry Andric     Var.Name = Name;
33965ffd83dbSDimitry Andric   }
33975ffd83dbSDimitry Andric 
3398fe6060f1SDimitry Andric   SMLoc StartLoc = Lexer.getLoc();
33995ffd83dbSDimitry Andric   if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) {
34005ffd83dbSDimitry Andric     // "equ" and "textequ" both allow text expressions.
34015ffd83dbSDimitry Andric     std::string Value;
3402fe6060f1SDimitry Andric     std::string TextItem;
3403fe6060f1SDimitry Andric     if (!parseTextItem(TextItem)) {
3404fe6060f1SDimitry Andric       Value += TextItem;
34055ffd83dbSDimitry Andric 
34065ffd83dbSDimitry Andric       // Accept a text-list, not just one text-item.
34075ffd83dbSDimitry Andric       auto parseItem = [&]() -> bool {
3408fe6060f1SDimitry Andric         if (parseTextItem(TextItem))
3409e8d8bef9SDimitry Andric           return TokError("expected text item");
3410fe6060f1SDimitry Andric         Value += TextItem;
34115ffd83dbSDimitry Andric         return false;
34125ffd83dbSDimitry Andric       };
34135ffd83dbSDimitry Andric       if (parseOptionalToken(AsmToken::Comma) && parseMany(parseItem))
34145ffd83dbSDimitry Andric         return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
34155ffd83dbSDimitry Andric 
3416fe6060f1SDimitry Andric       if (!Var.IsText || Var.TextValue != Value) {
3417fe6060f1SDimitry Andric         switch (Var.Redefinable) {
3418fe6060f1SDimitry Andric         case Variable::NOT_REDEFINABLE:
3419fe6060f1SDimitry Andric           return Error(getTok().getLoc(), "invalid variable redefinition");
3420fe6060f1SDimitry Andric         case Variable::WARN_ON_REDEFINITION:
3421fe6060f1SDimitry Andric           if (Warning(NameLoc, "redefining '" + Name +
3422fe6060f1SDimitry Andric                                    "', already defined on the command line")) {
3423fe6060f1SDimitry Andric             return true;
3424fe6060f1SDimitry Andric           }
3425fe6060f1SDimitry Andric           break;
3426fe6060f1SDimitry Andric         default:
3427fe6060f1SDimitry Andric           break;
3428fe6060f1SDimitry Andric         }
3429fe6060f1SDimitry Andric       }
3430fe6060f1SDimitry Andric       Var.IsText = true;
3431fe6060f1SDimitry Andric       Var.TextValue = Value;
3432fe6060f1SDimitry Andric       Var.Redefinable = Variable::REDEFINABLE;
3433fe6060f1SDimitry Andric 
34345ffd83dbSDimitry Andric       return false;
34355ffd83dbSDimitry Andric     }
34365ffd83dbSDimitry Andric   }
34375ffd83dbSDimitry Andric   if (DirKind == DK_TEXTEQU)
34385ffd83dbSDimitry Andric     return TokError("expected <text> in '" + Twine(IDVal) + "' directive");
34395ffd83dbSDimitry Andric 
34405ffd83dbSDimitry Andric   // Parse as expression assignment.
34415ffd83dbSDimitry Andric   const MCExpr *Expr;
3442fe6060f1SDimitry Andric   SMLoc EndLoc;
34435ffd83dbSDimitry Andric   if (parseExpression(Expr, EndLoc))
34445ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3445fe6060f1SDimitry Andric   StringRef ExprAsString = StringRef(
3446fe6060f1SDimitry Andric       StartLoc.getPointer(), EndLoc.getPointer() - StartLoc.getPointer());
3447fe6060f1SDimitry Andric 
3448fe6060f1SDimitry Andric   int64_t Value;
3449fe6060f1SDimitry Andric   if (!Expr->evaluateAsAbsolute(Value, getStreamer().getAssemblerPtr())) {
3450fe6060f1SDimitry Andric     if (DirKind == DK_ASSIGN)
3451fe6060f1SDimitry Andric       return Error(
3452fe6060f1SDimitry Andric           StartLoc,
3453fe6060f1SDimitry Andric           "expected absolute expression; not all symbols have known values",
3454fe6060f1SDimitry Andric           {StartLoc, EndLoc});
3455fe6060f1SDimitry Andric 
3456fe6060f1SDimitry Andric     // Not an absolute expression; define as a text replacement.
3457fe6060f1SDimitry Andric     if (!Var.IsText || Var.TextValue != ExprAsString) {
3458fe6060f1SDimitry Andric       switch (Var.Redefinable) {
3459fe6060f1SDimitry Andric       case Variable::NOT_REDEFINABLE:
3460fe6060f1SDimitry Andric         return Error(getTok().getLoc(), "invalid variable redefinition");
3461fe6060f1SDimitry Andric       case Variable::WARN_ON_REDEFINITION:
3462fe6060f1SDimitry Andric         if (Warning(NameLoc, "redefining '" + Name +
3463fe6060f1SDimitry Andric                                  "', already defined on the command line")) {
3464fe6060f1SDimitry Andric           return true;
3465fe6060f1SDimitry Andric         }
3466fe6060f1SDimitry Andric         break;
3467fe6060f1SDimitry Andric       default:
3468fe6060f1SDimitry Andric         break;
3469fe6060f1SDimitry Andric       }
3470fe6060f1SDimitry Andric     }
3471fe6060f1SDimitry Andric 
3472fe6060f1SDimitry Andric     Var.IsText = true;
3473fe6060f1SDimitry Andric     Var.TextValue = ExprAsString.str();
3474fe6060f1SDimitry Andric     Var.Redefinable = Variable::REDEFINABLE;
3475fe6060f1SDimitry Andric 
3476fe6060f1SDimitry Andric     return false;
3477fe6060f1SDimitry Andric   }
3478fe6060f1SDimitry Andric 
3479e8d8bef9SDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Var.Name);
3480fe6060f1SDimitry Andric 
3481fe6060f1SDimitry Andric   const MCConstantExpr *PrevValue =
3482fe6060f1SDimitry Andric       Sym->isVariable() ? dyn_cast_or_null<MCConstantExpr>(
3483fe6060f1SDimitry Andric                               Sym->getVariableValue(/*SetUsed=*/false))
3484fe6060f1SDimitry Andric                         : nullptr;
3485fe6060f1SDimitry Andric   if (Var.IsText || !PrevValue || PrevValue->getValue() != Value) {
3486fe6060f1SDimitry Andric     switch (Var.Redefinable) {
3487fe6060f1SDimitry Andric     case Variable::NOT_REDEFINABLE:
3488fe6060f1SDimitry Andric       return Error(getTok().getLoc(), "invalid variable redefinition");
3489fe6060f1SDimitry Andric     case Variable::WARN_ON_REDEFINITION:
3490fe6060f1SDimitry Andric       if (Warning(NameLoc, "redefining '" + Name +
3491fe6060f1SDimitry Andric                                "', already defined on the command line")) {
3492fe6060f1SDimitry Andric         return true;
3493fe6060f1SDimitry Andric       }
3494fe6060f1SDimitry Andric       break;
3495fe6060f1SDimitry Andric     default:
3496fe6060f1SDimitry Andric       break;
3497fe6060f1SDimitry Andric     }
3498fe6060f1SDimitry Andric   }
3499fe6060f1SDimitry Andric 
3500fe6060f1SDimitry Andric   Var.IsText = false;
3501fe6060f1SDimitry Andric   Var.TextValue.clear();
3502fe6060f1SDimitry Andric   Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE
3503fe6060f1SDimitry Andric                                            : Variable::NOT_REDEFINABLE;
3504fe6060f1SDimitry Andric 
3505fe6060f1SDimitry Andric   Sym->setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE);
3506e8d8bef9SDimitry Andric   Sym->setVariableValue(Expr);
3507e8d8bef9SDimitry Andric   Sym->setExternal(false);
3508e8d8bef9SDimitry Andric 
35095ffd83dbSDimitry Andric   return false;
35105ffd83dbSDimitry Andric }
35115ffd83dbSDimitry Andric 
parseEscapedString(std::string & Data)35125ffd83dbSDimitry Andric bool MasmParser::parseEscapedString(std::string &Data) {
35135ffd83dbSDimitry Andric   if (check(getTok().isNot(AsmToken::String), "expected string"))
35145ffd83dbSDimitry Andric     return true;
35155ffd83dbSDimitry Andric 
35165ffd83dbSDimitry Andric   Data = "";
3517e8d8bef9SDimitry Andric   char Quote = getTok().getString().front();
35185ffd83dbSDimitry Andric   StringRef Str = getTok().getStringContents();
3519e8d8bef9SDimitry Andric   Data.reserve(Str.size());
3520e8d8bef9SDimitry Andric   for (size_t i = 0, e = Str.size(); i != e; ++i) {
3521e8d8bef9SDimitry Andric     Data.push_back(Str[i]);
3522e8d8bef9SDimitry Andric     if (Str[i] == Quote) {
3523e8d8bef9SDimitry Andric       // MASM treats doubled delimiting quotes as an escaped delimiting quote.
3524e8d8bef9SDimitry Andric       // If we're escaping the string's trailing delimiter, we're definitely
3525e8d8bef9SDimitry Andric       // missing a quotation mark.
3526e8d8bef9SDimitry Andric       if (i + 1 == Str.size())
3527e8d8bef9SDimitry Andric         return Error(getTok().getLoc(), "missing quotation mark in string");
3528e8d8bef9SDimitry Andric       if (Str[i + 1] == Quote)
35295ffd83dbSDimitry Andric         ++i;
35305ffd83dbSDimitry Andric     }
35315ffd83dbSDimitry Andric   }
35325ffd83dbSDimitry Andric 
35335ffd83dbSDimitry Andric   Lex();
35345ffd83dbSDimitry Andric   return false;
35355ffd83dbSDimitry Andric }
35365ffd83dbSDimitry Andric 
parseAngleBracketString(std::string & Data)35375ffd83dbSDimitry Andric bool MasmParser::parseAngleBracketString(std::string &Data) {
35385ffd83dbSDimitry Andric   SMLoc EndLoc, StartLoc = getTok().getLoc();
35395ffd83dbSDimitry Andric   if (isAngleBracketString(StartLoc, EndLoc)) {
35405ffd83dbSDimitry Andric     const char *StartChar = StartLoc.getPointer() + 1;
35415ffd83dbSDimitry Andric     const char *EndChar = EndLoc.getPointer() - 1;
3542e8d8bef9SDimitry Andric     jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
35435ffd83dbSDimitry Andric     // Eat from '<' to '>'.
35445ffd83dbSDimitry Andric     Lex();
35455ffd83dbSDimitry Andric 
35465ffd83dbSDimitry Andric     Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
35475ffd83dbSDimitry Andric     return false;
35485ffd83dbSDimitry Andric   }
35495ffd83dbSDimitry Andric   return true;
35505ffd83dbSDimitry Andric }
35515ffd83dbSDimitry Andric 
35525ffd83dbSDimitry Andric /// textItem ::= textLiteral | textMacroID | % constExpr
parseTextItem(std::string & Data)35535ffd83dbSDimitry Andric bool MasmParser::parseTextItem(std::string &Data) {
3554e8d8bef9SDimitry Andric   switch (getTok().getKind()) {
3555e8d8bef9SDimitry Andric   default:
3556e8d8bef9SDimitry Andric     return true;
3557e8d8bef9SDimitry Andric   case AsmToken::Percent: {
3558e8d8bef9SDimitry Andric     int64_t Res;
3559e8d8bef9SDimitry Andric     if (parseToken(AsmToken::Percent) || parseAbsoluteExpression(Res))
3560e8d8bef9SDimitry Andric       return true;
3561e8d8bef9SDimitry Andric     Data = std::to_string(Res);
3562e8d8bef9SDimitry Andric     return false;
3563e8d8bef9SDimitry Andric   }
3564e8d8bef9SDimitry Andric   case AsmToken::Less:
3565e8d8bef9SDimitry Andric   case AsmToken::LessEqual:
3566e8d8bef9SDimitry Andric   case AsmToken::LessLess:
3567e8d8bef9SDimitry Andric   case AsmToken::LessGreater:
35685ffd83dbSDimitry Andric     return parseAngleBracketString(Data);
3569e8d8bef9SDimitry Andric   case AsmToken::Identifier: {
3570fe6060f1SDimitry Andric     // This must be a text macro; we need to expand it accordingly.
3571e8d8bef9SDimitry Andric     StringRef ID;
3572fe6060f1SDimitry Andric     SMLoc StartLoc = getTok().getLoc();
3573e8d8bef9SDimitry Andric     if (parseIdentifier(ID))
3574e8d8bef9SDimitry Andric       return true;
3575e8d8bef9SDimitry Andric     Data = ID.str();
3576e8d8bef9SDimitry Andric 
3577fe6060f1SDimitry Andric     bool Expanded = false;
3578fe6060f1SDimitry Andric     while (true) {
3579fe6060f1SDimitry Andric       // Try to resolve as a built-in text macro
3580fe6060f1SDimitry Andric       auto BuiltinIt = BuiltinSymbolMap.find(ID.lower());
3581fe6060f1SDimitry Andric       if (BuiltinIt != BuiltinSymbolMap.end()) {
3582bdd1243dSDimitry Andric         std::optional<std::string> BuiltinText =
3583fe6060f1SDimitry Andric             evaluateBuiltinTextMacro(BuiltinIt->getValue(), StartLoc);
358481ad6265SDimitry Andric         if (!BuiltinText) {
3585fe6060f1SDimitry Andric           // Not a text macro; break without substituting
3586fe6060f1SDimitry Andric           break;
3587fe6060f1SDimitry Andric         }
3588fe6060f1SDimitry Andric         Data = std::move(*BuiltinText);
3589fe6060f1SDimitry Andric         ID = StringRef(Data);
3590fe6060f1SDimitry Andric         Expanded = true;
3591fe6060f1SDimitry Andric         continue;
3592fe6060f1SDimitry Andric       }
3593e8d8bef9SDimitry Andric 
3594fe6060f1SDimitry Andric       // Try to resolve as a variable text macro
3595fe6060f1SDimitry Andric       auto VarIt = Variables.find(ID.lower());
3596fe6060f1SDimitry Andric       if (VarIt != Variables.end()) {
3597fe6060f1SDimitry Andric         const Variable &Var = VarIt->getValue();
3598fe6060f1SDimitry Andric         if (!Var.IsText) {
3599fe6060f1SDimitry Andric           // Not a text macro; break without substituting
3600fe6060f1SDimitry Andric           break;
3601fe6060f1SDimitry Andric         }
3602e8d8bef9SDimitry Andric         Data = Var.TextValue;
3603fe6060f1SDimitry Andric         ID = StringRef(Data);
3604fe6060f1SDimitry Andric         Expanded = true;
3605fe6060f1SDimitry Andric         continue;
3606fe6060f1SDimitry Andric       }
3607fe6060f1SDimitry Andric 
3608fe6060f1SDimitry Andric       break;
3609fe6060f1SDimitry Andric     }
3610fe6060f1SDimitry Andric 
3611fe6060f1SDimitry Andric     if (!Expanded) {
3612fe6060f1SDimitry Andric       // Not a text macro; not usable in TextItem context. Since we haven't used
3613fe6060f1SDimitry Andric       // the token, put it back for better error recovery.
3614fe6060f1SDimitry Andric       getLexer().UnLex(AsmToken(AsmToken::Identifier, ID));
3615fe6060f1SDimitry Andric       return true;
3616e8d8bef9SDimitry Andric     }
3617e8d8bef9SDimitry Andric     return false;
3618e8d8bef9SDimitry Andric   }
3619e8d8bef9SDimitry Andric   }
3620e8d8bef9SDimitry Andric   llvm_unreachable("unhandled token kind");
36215ffd83dbSDimitry Andric }
36225ffd83dbSDimitry Andric 
36235ffd83dbSDimitry Andric /// parseDirectiveAscii:
36245ffd83dbSDimitry Andric ///   ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
parseDirectiveAscii(StringRef IDVal,bool ZeroTerminated)36255ffd83dbSDimitry Andric bool MasmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
36265ffd83dbSDimitry Andric   auto parseOp = [&]() -> bool {
36275ffd83dbSDimitry Andric     std::string Data;
36285ffd83dbSDimitry Andric     if (checkForValidSection() || parseEscapedString(Data))
36295ffd83dbSDimitry Andric       return true;
36305ffd83dbSDimitry Andric     getStreamer().emitBytes(Data);
36315ffd83dbSDimitry Andric     if (ZeroTerminated)
36325ffd83dbSDimitry Andric       getStreamer().emitBytes(StringRef("\0", 1));
36335ffd83dbSDimitry Andric     return false;
36345ffd83dbSDimitry Andric   };
36355ffd83dbSDimitry Andric 
36365ffd83dbSDimitry Andric   if (parseMany(parseOp))
36375ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
36385ffd83dbSDimitry Andric   return false;
36395ffd83dbSDimitry Andric }
36405ffd83dbSDimitry Andric 
emitIntValue(const MCExpr * Value,unsigned Size)36415ffd83dbSDimitry Andric bool MasmParser::emitIntValue(const MCExpr *Value, unsigned Size) {
36425ffd83dbSDimitry Andric   // Special case constant expressions to match code generator.
36435ffd83dbSDimitry Andric   if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
36445ffd83dbSDimitry Andric     assert(Size <= 8 && "Invalid size");
36455ffd83dbSDimitry Andric     int64_t IntValue = MCE->getValue();
36465ffd83dbSDimitry Andric     if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
36475ffd83dbSDimitry Andric       return Error(MCE->getLoc(), "out of range literal value");
36485ffd83dbSDimitry Andric     getStreamer().emitIntValue(IntValue, Size);
36495ffd83dbSDimitry Andric   } else {
36505ffd83dbSDimitry Andric     const MCSymbolRefExpr *MSE = dyn_cast<MCSymbolRefExpr>(Value);
36515ffd83dbSDimitry Andric     if (MSE && MSE->getSymbol().getName() == "?") {
36525ffd83dbSDimitry Andric       // ? initializer; treat as 0.
36535ffd83dbSDimitry Andric       getStreamer().emitIntValue(0, Size);
36545ffd83dbSDimitry Andric     } else {
36555ffd83dbSDimitry Andric       getStreamer().emitValue(Value, Size, Value->getLoc());
36565ffd83dbSDimitry Andric     }
36575ffd83dbSDimitry Andric   }
36585ffd83dbSDimitry Andric   return false;
36595ffd83dbSDimitry Andric }
36605ffd83dbSDimitry Andric 
parseScalarInitializer(unsigned Size,SmallVectorImpl<const MCExpr * > & Values,unsigned StringPadLength)36615ffd83dbSDimitry Andric bool MasmParser::parseScalarInitializer(unsigned Size,
36625ffd83dbSDimitry Andric                                         SmallVectorImpl<const MCExpr *> &Values,
36635ffd83dbSDimitry Andric                                         unsigned StringPadLength) {
3664e8d8bef9SDimitry Andric   if (Size == 1 && getTok().is(AsmToken::String)) {
3665e8d8bef9SDimitry Andric     std::string Value;
3666e8d8bef9SDimitry Andric     if (parseEscapedString(Value))
3667e8d8bef9SDimitry Andric       return true;
36685ffd83dbSDimitry Andric     // Treat each character as an initializer.
3669e8d8bef9SDimitry Andric     for (const unsigned char CharVal : Value)
36705ffd83dbSDimitry Andric       Values.push_back(MCConstantExpr::create(CharVal, getContext()));
36715ffd83dbSDimitry Andric 
36725ffd83dbSDimitry Andric     // Pad the string with spaces to the specified length.
36735ffd83dbSDimitry Andric     for (size_t i = Value.size(); i < StringPadLength; ++i)
36745ffd83dbSDimitry Andric       Values.push_back(MCConstantExpr::create(' ', getContext()));
36755ffd83dbSDimitry Andric   } else {
36765ffd83dbSDimitry Andric     const MCExpr *Value;
3677e8d8bef9SDimitry Andric     if (parseExpression(Value))
36785ffd83dbSDimitry Andric       return true;
36795ffd83dbSDimitry Andric     if (getTok().is(AsmToken::Identifier) &&
3680fe6060f1SDimitry Andric         getTok().getString().equals_insensitive("dup")) {
36815ffd83dbSDimitry Andric       Lex(); // Eat 'dup'.
36825ffd83dbSDimitry Andric       const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
36835ffd83dbSDimitry Andric       if (!MCE)
36845ffd83dbSDimitry Andric         return Error(Value->getLoc(),
36855ffd83dbSDimitry Andric                      "cannot repeat value a non-constant number of times");
36865ffd83dbSDimitry Andric       const int64_t Repetitions = MCE->getValue();
36875ffd83dbSDimitry Andric       if (Repetitions < 0)
36885ffd83dbSDimitry Andric         return Error(Value->getLoc(),
36895ffd83dbSDimitry Andric                      "cannot repeat value a negative number of times");
36905ffd83dbSDimitry Andric 
36915ffd83dbSDimitry Andric       SmallVector<const MCExpr *, 1> DuplicatedValues;
36925ffd83dbSDimitry Andric       if (parseToken(AsmToken::LParen,
36935ffd83dbSDimitry Andric                      "parentheses required for 'dup' contents") ||
369404eeddc0SDimitry Andric           parseScalarInstList(Size, DuplicatedValues) || parseRParen())
36955ffd83dbSDimitry Andric         return true;
36965ffd83dbSDimitry Andric 
36975ffd83dbSDimitry Andric       for (int i = 0; i < Repetitions; ++i)
36985ffd83dbSDimitry Andric         Values.append(DuplicatedValues.begin(), DuplicatedValues.end());
36995ffd83dbSDimitry Andric     } else {
37005ffd83dbSDimitry Andric       Values.push_back(Value);
37015ffd83dbSDimitry Andric     }
37025ffd83dbSDimitry Andric   }
37035ffd83dbSDimitry Andric   return false;
37045ffd83dbSDimitry Andric }
37055ffd83dbSDimitry Andric 
parseScalarInstList(unsigned Size,SmallVectorImpl<const MCExpr * > & Values,const AsmToken::TokenKind EndToken)37065ffd83dbSDimitry Andric bool MasmParser::parseScalarInstList(unsigned Size,
37075ffd83dbSDimitry Andric                                      SmallVectorImpl<const MCExpr *> &Values,
37085ffd83dbSDimitry Andric                                      const AsmToken::TokenKind EndToken) {
37095ffd83dbSDimitry Andric   while (getTok().isNot(EndToken) &&
37105ffd83dbSDimitry Andric          (EndToken != AsmToken::Greater ||
37115ffd83dbSDimitry Andric           getTok().isNot(AsmToken::GreaterGreater))) {
37125ffd83dbSDimitry Andric     parseScalarInitializer(Size, Values);
37135ffd83dbSDimitry Andric 
37145ffd83dbSDimitry Andric     // If we see a comma, continue, and allow line continuation.
37155ffd83dbSDimitry Andric     if (!parseOptionalToken(AsmToken::Comma))
37165ffd83dbSDimitry Andric       break;
37175ffd83dbSDimitry Andric     parseOptionalToken(AsmToken::EndOfStatement);
37185ffd83dbSDimitry Andric   }
37195ffd83dbSDimitry Andric   return false;
37205ffd83dbSDimitry Andric }
37215ffd83dbSDimitry Andric 
emitIntegralValues(unsigned Size,unsigned * Count)3722e8d8bef9SDimitry Andric bool MasmParser::emitIntegralValues(unsigned Size, unsigned *Count) {
37235ffd83dbSDimitry Andric   SmallVector<const MCExpr *, 1> Values;
37245ffd83dbSDimitry Andric   if (checkForValidSection() || parseScalarInstList(Size, Values))
37255ffd83dbSDimitry Andric     return true;
37265ffd83dbSDimitry Andric 
3727bdd1243dSDimitry Andric   for (const auto *Value : Values) {
37285ffd83dbSDimitry Andric     emitIntValue(Value, Size);
37295ffd83dbSDimitry Andric   }
3730e8d8bef9SDimitry Andric   if (Count)
3731e8d8bef9SDimitry Andric     *Count = Values.size();
37325ffd83dbSDimitry Andric   return false;
37335ffd83dbSDimitry Andric }
37345ffd83dbSDimitry Andric 
37355ffd83dbSDimitry Andric // Add a field to the current structure.
addIntegralField(StringRef Name,unsigned Size)37365ffd83dbSDimitry Andric bool MasmParser::addIntegralField(StringRef Name, unsigned Size) {
37375ffd83dbSDimitry Andric   StructInfo &Struct = StructInProgress.back();
3738e8d8bef9SDimitry Andric   FieldInfo &Field = Struct.addField(Name, FT_INTEGRAL, Size);
37395ffd83dbSDimitry Andric   IntFieldInfo &IntInfo = Field.Contents.IntInfo;
37405ffd83dbSDimitry Andric 
37415ffd83dbSDimitry Andric   Field.Type = Size;
37425ffd83dbSDimitry Andric 
37435ffd83dbSDimitry Andric   if (parseScalarInstList(Size, IntInfo.Values))
37445ffd83dbSDimitry Andric     return true;
37455ffd83dbSDimitry Andric 
37465ffd83dbSDimitry Andric   Field.SizeOf = Field.Type * IntInfo.Values.size();
37475ffd83dbSDimitry Andric   Field.LengthOf = IntInfo.Values.size();
3748fe6060f1SDimitry Andric   const unsigned FieldEnd = Field.Offset + Field.SizeOf;
3749fe6060f1SDimitry Andric   if (!Struct.IsUnion) {
3750fe6060f1SDimitry Andric     Struct.NextOffset = FieldEnd;
3751fe6060f1SDimitry Andric   }
3752fe6060f1SDimitry Andric   Struct.Size = std::max(Struct.Size, FieldEnd);
37535ffd83dbSDimitry Andric   return false;
37545ffd83dbSDimitry Andric }
37555ffd83dbSDimitry Andric 
37565ffd83dbSDimitry Andric /// parseDirectiveValue
37575ffd83dbSDimitry Andric ///  ::= (byte | word | ... ) [ expression (, expression)* ]
parseDirectiveValue(StringRef IDVal,unsigned Size)37585ffd83dbSDimitry Andric bool MasmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
37595ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
37605ffd83dbSDimitry Andric     // Initialize data value.
37615ffd83dbSDimitry Andric     if (emitIntegralValues(Size))
37625ffd83dbSDimitry Andric       return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
37635ffd83dbSDimitry Andric   } else if (addIntegralField("", Size)) {
37645ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
37655ffd83dbSDimitry Andric   }
37665ffd83dbSDimitry Andric 
37675ffd83dbSDimitry Andric   return false;
37685ffd83dbSDimitry Andric }
37695ffd83dbSDimitry Andric 
37705ffd83dbSDimitry Andric /// parseDirectiveNamedValue
37715ffd83dbSDimitry Andric ///  ::= name (byte | word | ... ) [ expression (, expression)* ]
parseDirectiveNamedValue(StringRef TypeName,unsigned Size,StringRef Name,SMLoc NameLoc)3772e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
37735ffd83dbSDimitry Andric                                           StringRef Name, SMLoc NameLoc) {
37745ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
37755ffd83dbSDimitry Andric     // Initialize named data value.
37765ffd83dbSDimitry Andric     MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
37775ffd83dbSDimitry Andric     getStreamer().emitLabel(Sym);
3778e8d8bef9SDimitry Andric     unsigned Count;
3779e8d8bef9SDimitry Andric     if (emitIntegralValues(Size, &Count))
3780e8d8bef9SDimitry Andric       return addErrorSuffix(" in '" + Twine(TypeName) + "' directive");
3781e8d8bef9SDimitry Andric 
3782e8d8bef9SDimitry Andric     AsmTypeInfo Type;
3783e8d8bef9SDimitry Andric     Type.Name = TypeName;
3784e8d8bef9SDimitry Andric     Type.Size = Size * Count;
3785e8d8bef9SDimitry Andric     Type.ElementSize = Size;
3786e8d8bef9SDimitry Andric     Type.Length = Count;
3787e8d8bef9SDimitry Andric     KnownType[Name.lower()] = Type;
37885ffd83dbSDimitry Andric   } else if (addIntegralField(Name, Size)) {
3789e8d8bef9SDimitry Andric     return addErrorSuffix(" in '" + Twine(TypeName) + "' directive");
37905ffd83dbSDimitry Andric   }
37915ffd83dbSDimitry Andric 
37925ffd83dbSDimitry Andric   return false;
37935ffd83dbSDimitry Andric }
37945ffd83dbSDimitry Andric 
parseHexOcta(MasmParser & Asm,uint64_t & hi,uint64_t & lo)37955ffd83dbSDimitry Andric static bool parseHexOcta(MasmParser &Asm, uint64_t &hi, uint64_t &lo) {
37965ffd83dbSDimitry Andric   if (Asm.getTok().isNot(AsmToken::Integer) &&
37975ffd83dbSDimitry Andric       Asm.getTok().isNot(AsmToken::BigNum))
37985ffd83dbSDimitry Andric     return Asm.TokError("unknown token in expression");
37995ffd83dbSDimitry Andric   SMLoc ExprLoc = Asm.getTok().getLoc();
38005ffd83dbSDimitry Andric   APInt IntValue = Asm.getTok().getAPIntVal();
38015ffd83dbSDimitry Andric   Asm.Lex();
38025ffd83dbSDimitry Andric   if (!IntValue.isIntN(128))
38035ffd83dbSDimitry Andric     return Asm.Error(ExprLoc, "out of range literal value");
38045ffd83dbSDimitry Andric   if (!IntValue.isIntN(64)) {
38055ffd83dbSDimitry Andric     hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue();
38065ffd83dbSDimitry Andric     lo = IntValue.getLoBits(64).getZExtValue();
38075ffd83dbSDimitry Andric   } else {
38085ffd83dbSDimitry Andric     hi = 0;
38095ffd83dbSDimitry Andric     lo = IntValue.getZExtValue();
38105ffd83dbSDimitry Andric   }
38115ffd83dbSDimitry Andric   return false;
38125ffd83dbSDimitry Andric }
38135ffd83dbSDimitry Andric 
parseRealValue(const fltSemantics & Semantics,APInt & Res)38145ffd83dbSDimitry Andric bool MasmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
38155ffd83dbSDimitry Andric   // We don't truly support arithmetic on floating point expressions, so we
38165ffd83dbSDimitry Andric   // have to manually parse unary prefixes.
38175ffd83dbSDimitry Andric   bool IsNeg = false;
3818e8d8bef9SDimitry Andric   SMLoc SignLoc;
38195ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Minus)) {
3820e8d8bef9SDimitry Andric     SignLoc = getLexer().getLoc();
38215ffd83dbSDimitry Andric     Lexer.Lex();
38225ffd83dbSDimitry Andric     IsNeg = true;
38235ffd83dbSDimitry Andric   } else if (getLexer().is(AsmToken::Plus)) {
3824e8d8bef9SDimitry Andric     SignLoc = getLexer().getLoc();
38255ffd83dbSDimitry Andric     Lexer.Lex();
38265ffd83dbSDimitry Andric   }
38275ffd83dbSDimitry Andric 
38285ffd83dbSDimitry Andric   if (Lexer.is(AsmToken::Error))
38295ffd83dbSDimitry Andric     return TokError(Lexer.getErr());
38305ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) &&
38315ffd83dbSDimitry Andric       Lexer.isNot(AsmToken::Identifier))
38325ffd83dbSDimitry Andric     return TokError("unexpected token in directive");
38335ffd83dbSDimitry Andric 
38345ffd83dbSDimitry Andric   // Convert to an APFloat.
38355ffd83dbSDimitry Andric   APFloat Value(Semantics);
38365ffd83dbSDimitry Andric   StringRef IDVal = getTok().getString();
38375ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Identifier)) {
3838fe6060f1SDimitry Andric     if (IDVal.equals_insensitive("infinity") || IDVal.equals_insensitive("inf"))
38395ffd83dbSDimitry Andric       Value = APFloat::getInf(Semantics);
3840fe6060f1SDimitry Andric     else if (IDVal.equals_insensitive("nan"))
38415ffd83dbSDimitry Andric       Value = APFloat::getNaN(Semantics, false, ~0);
3842fe6060f1SDimitry Andric     else if (IDVal.equals_insensitive("?"))
38435ffd83dbSDimitry Andric       Value = APFloat::getZero(Semantics);
38445ffd83dbSDimitry Andric     else
38455ffd83dbSDimitry Andric       return TokError("invalid floating point literal");
3846e8d8bef9SDimitry Andric   } else if (IDVal.consume_back("r") || IDVal.consume_back("R")) {
3847e8d8bef9SDimitry Andric     // MASM hexadecimal floating-point literal; no APFloat conversion needed.
3848e8d8bef9SDimitry Andric     // To match ML64.exe, ignore the initial sign.
3849e8d8bef9SDimitry Andric     unsigned SizeInBits = Value.getSizeInBits(Semantics);
3850e8d8bef9SDimitry Andric     if (SizeInBits != (IDVal.size() << 2))
3851e8d8bef9SDimitry Andric       return TokError("invalid floating point literal");
3852e8d8bef9SDimitry Andric 
3853e8d8bef9SDimitry Andric     // Consume the numeric token.
3854e8d8bef9SDimitry Andric     Lex();
3855e8d8bef9SDimitry Andric 
3856e8d8bef9SDimitry Andric     Res = APInt(SizeInBits, IDVal, 16);
3857e8d8bef9SDimitry Andric     if (SignLoc.isValid())
3858e8d8bef9SDimitry Andric       return Warning(SignLoc, "MASM-style hex floats ignore explicit sign");
3859e8d8bef9SDimitry Andric     return false;
38605ffd83dbSDimitry Andric   } else if (errorToBool(
38615ffd83dbSDimitry Andric                  Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
38625ffd83dbSDimitry Andric                      .takeError())) {
38635ffd83dbSDimitry Andric     return TokError("invalid floating point literal");
38645ffd83dbSDimitry Andric   }
38655ffd83dbSDimitry Andric   if (IsNeg)
38665ffd83dbSDimitry Andric     Value.changeSign();
38675ffd83dbSDimitry Andric 
38685ffd83dbSDimitry Andric   // Consume the numeric token.
38695ffd83dbSDimitry Andric   Lex();
38705ffd83dbSDimitry Andric 
38715ffd83dbSDimitry Andric   Res = Value.bitcastToAPInt();
38725ffd83dbSDimitry Andric 
38735ffd83dbSDimitry Andric   return false;
38745ffd83dbSDimitry Andric }
38755ffd83dbSDimitry Andric 
parseRealInstList(const fltSemantics & Semantics,SmallVectorImpl<APInt> & ValuesAsInt,const AsmToken::TokenKind EndToken)38765ffd83dbSDimitry Andric bool MasmParser::parseRealInstList(const fltSemantics &Semantics,
38775ffd83dbSDimitry Andric                                    SmallVectorImpl<APInt> &ValuesAsInt,
38785ffd83dbSDimitry Andric                                    const AsmToken::TokenKind EndToken) {
38795ffd83dbSDimitry Andric   while (getTok().isNot(EndToken) ||
38805ffd83dbSDimitry Andric          (EndToken == AsmToken::Greater &&
38815ffd83dbSDimitry Andric           getTok().isNot(AsmToken::GreaterGreater))) {
3882fe6060f1SDimitry Andric     const AsmToken NextTok = peekTok();
38835ffd83dbSDimitry Andric     if (NextTok.is(AsmToken::Identifier) &&
3884fe6060f1SDimitry Andric         NextTok.getString().equals_insensitive("dup")) {
38855ffd83dbSDimitry Andric       const MCExpr *Value;
38865ffd83dbSDimitry Andric       if (parseExpression(Value) || parseToken(AsmToken::Identifier))
38875ffd83dbSDimitry Andric         return true;
38885ffd83dbSDimitry Andric       const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
38895ffd83dbSDimitry Andric       if (!MCE)
38905ffd83dbSDimitry Andric         return Error(Value->getLoc(),
38915ffd83dbSDimitry Andric                      "cannot repeat value a non-constant number of times");
38925ffd83dbSDimitry Andric       const int64_t Repetitions = MCE->getValue();
38935ffd83dbSDimitry Andric       if (Repetitions < 0)
38945ffd83dbSDimitry Andric         return Error(Value->getLoc(),
38955ffd83dbSDimitry Andric                      "cannot repeat value a negative number of times");
38965ffd83dbSDimitry Andric 
38975ffd83dbSDimitry Andric       SmallVector<APInt, 1> DuplicatedValues;
38985ffd83dbSDimitry Andric       if (parseToken(AsmToken::LParen,
38995ffd83dbSDimitry Andric                      "parentheses required for 'dup' contents") ||
390004eeddc0SDimitry Andric           parseRealInstList(Semantics, DuplicatedValues) || parseRParen())
39015ffd83dbSDimitry Andric         return true;
39025ffd83dbSDimitry Andric 
39035ffd83dbSDimitry Andric       for (int i = 0; i < Repetitions; ++i)
39045ffd83dbSDimitry Andric         ValuesAsInt.append(DuplicatedValues.begin(), DuplicatedValues.end());
39055ffd83dbSDimitry Andric     } else {
39065ffd83dbSDimitry Andric       APInt AsInt;
39075ffd83dbSDimitry Andric       if (parseRealValue(Semantics, AsInt))
39085ffd83dbSDimitry Andric         return true;
39095ffd83dbSDimitry Andric       ValuesAsInt.push_back(AsInt);
39105ffd83dbSDimitry Andric     }
39115ffd83dbSDimitry Andric 
39125ffd83dbSDimitry Andric     // Continue if we see a comma. (Also, allow line continuation.)
39135ffd83dbSDimitry Andric     if (!parseOptionalToken(AsmToken::Comma))
39145ffd83dbSDimitry Andric       break;
39155ffd83dbSDimitry Andric     parseOptionalToken(AsmToken::EndOfStatement);
39165ffd83dbSDimitry Andric   }
39175ffd83dbSDimitry Andric 
39185ffd83dbSDimitry Andric   return false;
39195ffd83dbSDimitry Andric }
39205ffd83dbSDimitry Andric 
39215ffd83dbSDimitry Andric // Initialize real data values.
emitRealValues(const fltSemantics & Semantics,unsigned * Count)3922e8d8bef9SDimitry Andric bool MasmParser::emitRealValues(const fltSemantics &Semantics,
3923e8d8bef9SDimitry Andric                                 unsigned *Count) {
3924e8d8bef9SDimitry Andric   if (checkForValidSection())
3925e8d8bef9SDimitry Andric     return true;
3926e8d8bef9SDimitry Andric 
39275ffd83dbSDimitry Andric   SmallVector<APInt, 1> ValuesAsInt;
39285ffd83dbSDimitry Andric   if (parseRealInstList(Semantics, ValuesAsInt))
39295ffd83dbSDimitry Andric     return true;
39305ffd83dbSDimitry Andric 
39315ffd83dbSDimitry Andric   for (const APInt &AsInt : ValuesAsInt) {
3932e8d8bef9SDimitry Andric     getStreamer().emitIntValue(AsInt);
39335ffd83dbSDimitry Andric   }
3934e8d8bef9SDimitry Andric   if (Count)
3935e8d8bef9SDimitry Andric     *Count = ValuesAsInt.size();
39365ffd83dbSDimitry Andric   return false;
39375ffd83dbSDimitry Andric }
39385ffd83dbSDimitry Andric 
39395ffd83dbSDimitry Andric // Add a real field to the current struct.
addRealField(StringRef Name,const fltSemantics & Semantics,size_t Size)3940e8d8bef9SDimitry Andric bool MasmParser::addRealField(StringRef Name, const fltSemantics &Semantics,
3941e8d8bef9SDimitry Andric                               size_t Size) {
39425ffd83dbSDimitry Andric   StructInfo &Struct = StructInProgress.back();
3943e8d8bef9SDimitry Andric   FieldInfo &Field = Struct.addField(Name, FT_REAL, Size);
39445ffd83dbSDimitry Andric   RealFieldInfo &RealInfo = Field.Contents.RealInfo;
39455ffd83dbSDimitry Andric 
39465ffd83dbSDimitry Andric   Field.SizeOf = 0;
39475ffd83dbSDimitry Andric 
3948e8d8bef9SDimitry Andric   if (parseRealInstList(Semantics, RealInfo.AsIntValues))
39495ffd83dbSDimitry Andric     return true;
39505ffd83dbSDimitry Andric 
39515ffd83dbSDimitry Andric   Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
39525ffd83dbSDimitry Andric   Field.LengthOf = RealInfo.AsIntValues.size();
39535ffd83dbSDimitry Andric   Field.SizeOf = Field.Type * Field.LengthOf;
3954fe6060f1SDimitry Andric 
3955fe6060f1SDimitry Andric   const unsigned FieldEnd = Field.Offset + Field.SizeOf;
3956fe6060f1SDimitry Andric   if (!Struct.IsUnion) {
3957fe6060f1SDimitry Andric     Struct.NextOffset = FieldEnd;
3958fe6060f1SDimitry Andric   }
3959fe6060f1SDimitry Andric   Struct.Size = std::max(Struct.Size, FieldEnd);
39605ffd83dbSDimitry Andric   return false;
39615ffd83dbSDimitry Andric }
39625ffd83dbSDimitry Andric 
39635ffd83dbSDimitry Andric /// parseDirectiveRealValue
3964e8d8bef9SDimitry Andric ///  ::= (real4 | real8 | real10) [ expression (, expression)* ]
parseDirectiveRealValue(StringRef IDVal,const fltSemantics & Semantics,size_t Size)39655ffd83dbSDimitry Andric bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
3966e8d8bef9SDimitry Andric                                          const fltSemantics &Semantics,
3967e8d8bef9SDimitry Andric                                          size_t Size) {
39685ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
39695ffd83dbSDimitry Andric     // Initialize data value.
39705ffd83dbSDimitry Andric     if (emitRealValues(Semantics))
39715ffd83dbSDimitry Andric       return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
3972e8d8bef9SDimitry Andric   } else if (addRealField("", Semantics, Size)) {
39735ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
39745ffd83dbSDimitry Andric   }
39755ffd83dbSDimitry Andric   return false;
39765ffd83dbSDimitry Andric }
39775ffd83dbSDimitry Andric 
39785ffd83dbSDimitry Andric /// parseDirectiveNamedRealValue
3979e8d8bef9SDimitry Andric ///  ::= name (real4 | real8 | real10) [ expression (, expression)* ]
parseDirectiveNamedRealValue(StringRef TypeName,const fltSemantics & Semantics,unsigned Size,StringRef Name,SMLoc NameLoc)3980e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
39815ffd83dbSDimitry Andric                                               const fltSemantics &Semantics,
3982e8d8bef9SDimitry Andric                                               unsigned Size, StringRef Name,
3983e8d8bef9SDimitry Andric                                               SMLoc NameLoc) {
39845ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
39855ffd83dbSDimitry Andric     // Initialize named data value.
39865ffd83dbSDimitry Andric     MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
39875ffd83dbSDimitry Andric     getStreamer().emitLabel(Sym);
3988e8d8bef9SDimitry Andric     unsigned Count;
3989e8d8bef9SDimitry Andric     if (emitRealValues(Semantics, &Count))
3990e8d8bef9SDimitry Andric       return addErrorSuffix(" in '" + TypeName + "' directive");
3991e8d8bef9SDimitry Andric 
3992e8d8bef9SDimitry Andric     AsmTypeInfo Type;
3993e8d8bef9SDimitry Andric     Type.Name = TypeName;
3994e8d8bef9SDimitry Andric     Type.Size = Size * Count;
3995e8d8bef9SDimitry Andric     Type.ElementSize = Size;
3996e8d8bef9SDimitry Andric     Type.Length = Count;
3997e8d8bef9SDimitry Andric     KnownType[Name.lower()] = Type;
3998e8d8bef9SDimitry Andric   } else if (addRealField(Name, Semantics, Size)) {
3999e8d8bef9SDimitry Andric     return addErrorSuffix(" in '" + TypeName + "' directive");
40005ffd83dbSDimitry Andric   }
40015ffd83dbSDimitry Andric   return false;
40025ffd83dbSDimitry Andric }
40035ffd83dbSDimitry Andric 
parseOptionalAngleBracketOpen()40045ffd83dbSDimitry Andric bool MasmParser::parseOptionalAngleBracketOpen() {
40055ffd83dbSDimitry Andric   const AsmToken Tok = getTok();
40065ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::LessLess)) {
40075ffd83dbSDimitry Andric     AngleBracketDepth++;
40085ffd83dbSDimitry Andric     Lexer.UnLex(AsmToken(AsmToken::Less, Tok.getString().substr(1)));
40095ffd83dbSDimitry Andric     return true;
40105ffd83dbSDimitry Andric   } else if (parseOptionalToken(AsmToken::LessGreater)) {
40115ffd83dbSDimitry Andric     AngleBracketDepth++;
40125ffd83dbSDimitry Andric     Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1)));
40135ffd83dbSDimitry Andric     return true;
40145ffd83dbSDimitry Andric   } else if (parseOptionalToken(AsmToken::Less)) {
40155ffd83dbSDimitry Andric     AngleBracketDepth++;
40165ffd83dbSDimitry Andric     return true;
40175ffd83dbSDimitry Andric   }
40185ffd83dbSDimitry Andric 
40195ffd83dbSDimitry Andric   return false;
40205ffd83dbSDimitry Andric }
40215ffd83dbSDimitry Andric 
parseAngleBracketClose(const Twine & Msg)40225ffd83dbSDimitry Andric bool MasmParser::parseAngleBracketClose(const Twine &Msg) {
40235ffd83dbSDimitry Andric   const AsmToken Tok = getTok();
40245ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::GreaterGreater)) {
40255ffd83dbSDimitry Andric     Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1)));
40265ffd83dbSDimitry Andric   } else if (parseToken(AsmToken::Greater, Msg)) {
40275ffd83dbSDimitry Andric     return true;
40285ffd83dbSDimitry Andric   }
40295ffd83dbSDimitry Andric   AngleBracketDepth--;
40305ffd83dbSDimitry Andric   return false;
40315ffd83dbSDimitry Andric }
40325ffd83dbSDimitry Andric 
parseFieldInitializer(const FieldInfo & Field,const IntFieldInfo & Contents,FieldInitializer & Initializer)40335ffd83dbSDimitry Andric bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
40345ffd83dbSDimitry Andric                                        const IntFieldInfo &Contents,
40355ffd83dbSDimitry Andric                                        FieldInitializer &Initializer) {
40365ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
40375ffd83dbSDimitry Andric 
40385ffd83dbSDimitry Andric   SmallVector<const MCExpr *, 1> Values;
40395ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::LCurly)) {
40405ffd83dbSDimitry Andric     if (Field.LengthOf == 1 && Field.Type > 1)
40415ffd83dbSDimitry Andric       return Error(Loc, "Cannot initialize scalar field with array value");
40425ffd83dbSDimitry Andric     if (parseScalarInstList(Field.Type, Values, AsmToken::RCurly) ||
40435ffd83dbSDimitry Andric         parseToken(AsmToken::RCurly))
40445ffd83dbSDimitry Andric       return true;
40455ffd83dbSDimitry Andric   } else if (parseOptionalAngleBracketOpen()) {
40465ffd83dbSDimitry Andric     if (Field.LengthOf == 1 && Field.Type > 1)
40475ffd83dbSDimitry Andric       return Error(Loc, "Cannot initialize scalar field with array value");
40485ffd83dbSDimitry Andric     if (parseScalarInstList(Field.Type, Values, AsmToken::Greater) ||
40495ffd83dbSDimitry Andric         parseAngleBracketClose())
40505ffd83dbSDimitry Andric       return true;
40515ffd83dbSDimitry Andric   } else if (Field.LengthOf > 1 && Field.Type > 1) {
40525ffd83dbSDimitry Andric     return Error(Loc, "Cannot initialize array field with scalar value");
40535ffd83dbSDimitry Andric   } else if (parseScalarInitializer(Field.Type, Values,
40545ffd83dbSDimitry Andric                                     /*StringPadLength=*/Field.LengthOf)) {
40555ffd83dbSDimitry Andric     return true;
40565ffd83dbSDimitry Andric   }
40575ffd83dbSDimitry Andric 
40585ffd83dbSDimitry Andric   if (Values.size() > Field.LengthOf) {
40595ffd83dbSDimitry Andric     return Error(Loc, "Initializer too long for field; expected at most " +
40605ffd83dbSDimitry Andric                           std::to_string(Field.LengthOf) + " elements, got " +
40615ffd83dbSDimitry Andric                           std::to_string(Values.size()));
40625ffd83dbSDimitry Andric   }
40635ffd83dbSDimitry Andric   // Default-initialize all remaining values.
40645ffd83dbSDimitry Andric   Values.append(Contents.Values.begin() + Values.size(), Contents.Values.end());
40655ffd83dbSDimitry Andric 
40665ffd83dbSDimitry Andric   Initializer = FieldInitializer(std::move(Values));
40675ffd83dbSDimitry Andric   return false;
40685ffd83dbSDimitry Andric }
40695ffd83dbSDimitry Andric 
parseFieldInitializer(const FieldInfo & Field,const RealFieldInfo & Contents,FieldInitializer & Initializer)40705ffd83dbSDimitry Andric bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
40715ffd83dbSDimitry Andric                                        const RealFieldInfo &Contents,
40725ffd83dbSDimitry Andric                                        FieldInitializer &Initializer) {
4073e8d8bef9SDimitry Andric   const fltSemantics *Semantics;
4074e8d8bef9SDimitry Andric   switch (Field.Type) {
4075e8d8bef9SDimitry Andric   case 4:
4076e8d8bef9SDimitry Andric     Semantics = &APFloat::IEEEsingle();
4077e8d8bef9SDimitry Andric     break;
4078e8d8bef9SDimitry Andric   case 8:
4079e8d8bef9SDimitry Andric     Semantics = &APFloat::IEEEdouble();
4080e8d8bef9SDimitry Andric     break;
4081e8d8bef9SDimitry Andric   case 10:
4082e8d8bef9SDimitry Andric     Semantics = &APFloat::x87DoubleExtended();
4083e8d8bef9SDimitry Andric     break;
4084e8d8bef9SDimitry Andric   default:
4085e8d8bef9SDimitry Andric     llvm_unreachable("unknown real field type");
4086e8d8bef9SDimitry Andric   }
40875ffd83dbSDimitry Andric 
40885ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
40895ffd83dbSDimitry Andric 
40905ffd83dbSDimitry Andric   SmallVector<APInt, 1> AsIntValues;
40915ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::LCurly)) {
40925ffd83dbSDimitry Andric     if (Field.LengthOf == 1)
40935ffd83dbSDimitry Andric       return Error(Loc, "Cannot initialize scalar field with array value");
4094e8d8bef9SDimitry Andric     if (parseRealInstList(*Semantics, AsIntValues, AsmToken::RCurly) ||
40955ffd83dbSDimitry Andric         parseToken(AsmToken::RCurly))
40965ffd83dbSDimitry Andric       return true;
40975ffd83dbSDimitry Andric   } else if (parseOptionalAngleBracketOpen()) {
40985ffd83dbSDimitry Andric     if (Field.LengthOf == 1)
40995ffd83dbSDimitry Andric       return Error(Loc, "Cannot initialize scalar field with array value");
4100e8d8bef9SDimitry Andric     if (parseRealInstList(*Semantics, AsIntValues, AsmToken::Greater) ||
41015ffd83dbSDimitry Andric         parseAngleBracketClose())
41025ffd83dbSDimitry Andric       return true;
41035ffd83dbSDimitry Andric   } else if (Field.LengthOf > 1) {
41045ffd83dbSDimitry Andric     return Error(Loc, "Cannot initialize array field with scalar value");
41055ffd83dbSDimitry Andric   } else {
41065ffd83dbSDimitry Andric     AsIntValues.emplace_back();
4107e8d8bef9SDimitry Andric     if (parseRealValue(*Semantics, AsIntValues.back()))
41085ffd83dbSDimitry Andric       return true;
41095ffd83dbSDimitry Andric   }
41105ffd83dbSDimitry Andric 
41115ffd83dbSDimitry Andric   if (AsIntValues.size() > Field.LengthOf) {
41125ffd83dbSDimitry Andric     return Error(Loc, "Initializer too long for field; expected at most " +
41135ffd83dbSDimitry Andric                           std::to_string(Field.LengthOf) + " elements, got " +
41145ffd83dbSDimitry Andric                           std::to_string(AsIntValues.size()));
41155ffd83dbSDimitry Andric   }
41165ffd83dbSDimitry Andric   // Default-initialize all remaining values.
41175ffd83dbSDimitry Andric   AsIntValues.append(Contents.AsIntValues.begin() + AsIntValues.size(),
41185ffd83dbSDimitry Andric                      Contents.AsIntValues.end());
41195ffd83dbSDimitry Andric 
41205ffd83dbSDimitry Andric   Initializer = FieldInitializer(std::move(AsIntValues));
41215ffd83dbSDimitry Andric   return false;
41225ffd83dbSDimitry Andric }
41235ffd83dbSDimitry Andric 
parseFieldInitializer(const FieldInfo & Field,const StructFieldInfo & Contents,FieldInitializer & Initializer)41245ffd83dbSDimitry Andric bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
41255ffd83dbSDimitry Andric                                        const StructFieldInfo &Contents,
41265ffd83dbSDimitry Andric                                        FieldInitializer &Initializer) {
41275ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
41285ffd83dbSDimitry Andric 
41295ffd83dbSDimitry Andric   std::vector<StructInitializer> Initializers;
41305ffd83dbSDimitry Andric   if (Field.LengthOf > 1) {
41315ffd83dbSDimitry Andric     if (parseOptionalToken(AsmToken::LCurly)) {
41325ffd83dbSDimitry Andric       if (parseStructInstList(Contents.Structure, Initializers,
41335ffd83dbSDimitry Andric                               AsmToken::RCurly) ||
41345ffd83dbSDimitry Andric           parseToken(AsmToken::RCurly))
41355ffd83dbSDimitry Andric         return true;
41365ffd83dbSDimitry Andric     } else if (parseOptionalAngleBracketOpen()) {
41375ffd83dbSDimitry Andric       if (parseStructInstList(Contents.Structure, Initializers,
41385ffd83dbSDimitry Andric                               AsmToken::Greater) ||
41395ffd83dbSDimitry Andric           parseAngleBracketClose())
41405ffd83dbSDimitry Andric         return true;
41415ffd83dbSDimitry Andric     } else {
41425ffd83dbSDimitry Andric       return Error(Loc, "Cannot initialize array field with scalar value");
41435ffd83dbSDimitry Andric     }
41445ffd83dbSDimitry Andric   } else {
41455ffd83dbSDimitry Andric     Initializers.emplace_back();
41465ffd83dbSDimitry Andric     if (parseStructInitializer(Contents.Structure, Initializers.back()))
41475ffd83dbSDimitry Andric       return true;
41485ffd83dbSDimitry Andric   }
41495ffd83dbSDimitry Andric 
41505ffd83dbSDimitry Andric   if (Initializers.size() > Field.LengthOf) {
41515ffd83dbSDimitry Andric     return Error(Loc, "Initializer too long for field; expected at most " +
41525ffd83dbSDimitry Andric                           std::to_string(Field.LengthOf) + " elements, got " +
41535ffd83dbSDimitry Andric                           std::to_string(Initializers.size()));
41545ffd83dbSDimitry Andric   }
41555ffd83dbSDimitry Andric   // Default-initialize all remaining values.
41565ffd83dbSDimitry Andric   Initializers.insert(Initializers.end(),
41575ffd83dbSDimitry Andric                       Contents.Initializers.begin() + Initializers.size(),
41585ffd83dbSDimitry Andric                       Contents.Initializers.end());
41595ffd83dbSDimitry Andric 
41605ffd83dbSDimitry Andric   Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
41615ffd83dbSDimitry Andric   return false;
41625ffd83dbSDimitry Andric }
41635ffd83dbSDimitry Andric 
parseFieldInitializer(const FieldInfo & Field,FieldInitializer & Initializer)41645ffd83dbSDimitry Andric bool MasmParser::parseFieldInitializer(const FieldInfo &Field,
41655ffd83dbSDimitry Andric                                        FieldInitializer &Initializer) {
41665ffd83dbSDimitry Andric   switch (Field.Contents.FT) {
41675ffd83dbSDimitry Andric   case FT_INTEGRAL:
41685ffd83dbSDimitry Andric     return parseFieldInitializer(Field, Field.Contents.IntInfo, Initializer);
41695ffd83dbSDimitry Andric   case FT_REAL:
41705ffd83dbSDimitry Andric     return parseFieldInitializer(Field, Field.Contents.RealInfo, Initializer);
41715ffd83dbSDimitry Andric   case FT_STRUCT:
41725ffd83dbSDimitry Andric     return parseFieldInitializer(Field, Field.Contents.StructInfo, Initializer);
41735ffd83dbSDimitry Andric   }
41745ffd83dbSDimitry Andric   llvm_unreachable("Unhandled FieldType enum");
41755ffd83dbSDimitry Andric }
41765ffd83dbSDimitry Andric 
parseStructInitializer(const StructInfo & Structure,StructInitializer & Initializer)41775ffd83dbSDimitry Andric bool MasmParser::parseStructInitializer(const StructInfo &Structure,
41785ffd83dbSDimitry Andric                                         StructInitializer &Initializer) {
41795ffd83dbSDimitry Andric   const AsmToken FirstToken = getTok();
41805ffd83dbSDimitry Andric 
4181bdd1243dSDimitry Andric   std::optional<AsmToken::TokenKind> EndToken;
41825ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::LCurly)) {
41835ffd83dbSDimitry Andric     EndToken = AsmToken::RCurly;
41845ffd83dbSDimitry Andric   } else if (parseOptionalAngleBracketOpen()) {
41855ffd83dbSDimitry Andric     EndToken = AsmToken::Greater;
41865ffd83dbSDimitry Andric     AngleBracketDepth++;
41875ffd83dbSDimitry Andric   } else if (FirstToken.is(AsmToken::Identifier) &&
41885ffd83dbSDimitry Andric              FirstToken.getString() == "?") {
41895ffd83dbSDimitry Andric     // ? initializer; leave EndToken uninitialized to treat as empty.
41905ffd83dbSDimitry Andric     if (parseToken(AsmToken::Identifier))
41915ffd83dbSDimitry Andric       return true;
41925ffd83dbSDimitry Andric   } else {
41935ffd83dbSDimitry Andric     return Error(FirstToken.getLoc(), "Expected struct initializer");
41945ffd83dbSDimitry Andric   }
41955ffd83dbSDimitry Andric 
41965ffd83dbSDimitry Andric   auto &FieldInitializers = Initializer.FieldInitializers;
41975ffd83dbSDimitry Andric   size_t FieldIndex = 0;
419881ad6265SDimitry Andric   if (EndToken) {
41995ffd83dbSDimitry Andric     // Initialize all fields with given initializers.
4200bdd1243dSDimitry Andric     while (getTok().isNot(*EndToken) && FieldIndex < Structure.Fields.size()) {
42015ffd83dbSDimitry Andric       const FieldInfo &Field = Structure.Fields[FieldIndex++];
42025ffd83dbSDimitry Andric       if (parseOptionalToken(AsmToken::Comma)) {
42035ffd83dbSDimitry Andric         // Empty initializer; use the default and continue. (Also, allow line
42045ffd83dbSDimitry Andric         // continuation.)
42055ffd83dbSDimitry Andric         FieldInitializers.push_back(Field.Contents);
42065ffd83dbSDimitry Andric         parseOptionalToken(AsmToken::EndOfStatement);
42075ffd83dbSDimitry Andric         continue;
42085ffd83dbSDimitry Andric       }
42095ffd83dbSDimitry Andric       FieldInitializers.emplace_back(Field.Contents.FT);
42105ffd83dbSDimitry Andric       if (parseFieldInitializer(Field, FieldInitializers.back()))
42115ffd83dbSDimitry Andric         return true;
42125ffd83dbSDimitry Andric 
42135ffd83dbSDimitry Andric       // Continue if we see a comma. (Also, allow line continuation.)
42145ffd83dbSDimitry Andric       SMLoc CommaLoc = getTok().getLoc();
42155ffd83dbSDimitry Andric       if (!parseOptionalToken(AsmToken::Comma))
42165ffd83dbSDimitry Andric         break;
42175ffd83dbSDimitry Andric       if (FieldIndex == Structure.Fields.size())
42185ffd83dbSDimitry Andric         return Error(CommaLoc, "'" + Structure.Name +
42195ffd83dbSDimitry Andric                                    "' initializer initializes too many fields");
42205ffd83dbSDimitry Andric       parseOptionalToken(AsmToken::EndOfStatement);
42215ffd83dbSDimitry Andric     }
42225ffd83dbSDimitry Andric   }
42235ffd83dbSDimitry Andric   // Default-initialize all remaining fields.
4224fcaf7f86SDimitry Andric   for (const FieldInfo &Field : llvm::drop_begin(Structure.Fields, FieldIndex))
42255ffd83dbSDimitry Andric     FieldInitializers.push_back(Field.Contents);
42265ffd83dbSDimitry Andric 
422781ad6265SDimitry Andric   if (EndToken) {
4228bdd1243dSDimitry Andric     if (*EndToken == AsmToken::Greater)
42295ffd83dbSDimitry Andric       return parseAngleBracketClose();
42305ffd83dbSDimitry Andric 
4231bdd1243dSDimitry Andric     return parseToken(*EndToken);
42325ffd83dbSDimitry Andric   }
42335ffd83dbSDimitry Andric 
42345ffd83dbSDimitry Andric   return false;
42355ffd83dbSDimitry Andric }
42365ffd83dbSDimitry Andric 
parseStructInstList(const StructInfo & Structure,std::vector<StructInitializer> & Initializers,const AsmToken::TokenKind EndToken)42375ffd83dbSDimitry Andric bool MasmParser::parseStructInstList(
42385ffd83dbSDimitry Andric     const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
42395ffd83dbSDimitry Andric     const AsmToken::TokenKind EndToken) {
42405ffd83dbSDimitry Andric   while (getTok().isNot(EndToken) ||
42415ffd83dbSDimitry Andric          (EndToken == AsmToken::Greater &&
42425ffd83dbSDimitry Andric           getTok().isNot(AsmToken::GreaterGreater))) {
4243fe6060f1SDimitry Andric     const AsmToken NextTok = peekTok();
42445ffd83dbSDimitry Andric     if (NextTok.is(AsmToken::Identifier) &&
4245fe6060f1SDimitry Andric         NextTok.getString().equals_insensitive("dup")) {
42465ffd83dbSDimitry Andric       const MCExpr *Value;
42475ffd83dbSDimitry Andric       if (parseExpression(Value) || parseToken(AsmToken::Identifier))
42485ffd83dbSDimitry Andric         return true;
42495ffd83dbSDimitry Andric       const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
42505ffd83dbSDimitry Andric       if (!MCE)
42515ffd83dbSDimitry Andric         return Error(Value->getLoc(),
42525ffd83dbSDimitry Andric                      "cannot repeat value a non-constant number of times");
42535ffd83dbSDimitry Andric       const int64_t Repetitions = MCE->getValue();
42545ffd83dbSDimitry Andric       if (Repetitions < 0)
42555ffd83dbSDimitry Andric         return Error(Value->getLoc(),
42565ffd83dbSDimitry Andric                      "cannot repeat value a negative number of times");
42575ffd83dbSDimitry Andric 
42585ffd83dbSDimitry Andric       std::vector<StructInitializer> DuplicatedValues;
42595ffd83dbSDimitry Andric       if (parseToken(AsmToken::LParen,
42605ffd83dbSDimitry Andric                      "parentheses required for 'dup' contents") ||
426104eeddc0SDimitry Andric           parseStructInstList(Structure, DuplicatedValues) || parseRParen())
42625ffd83dbSDimitry Andric         return true;
42635ffd83dbSDimitry Andric 
42645ffd83dbSDimitry Andric       for (int i = 0; i < Repetitions; ++i)
4265e8d8bef9SDimitry Andric         llvm::append_range(Initializers, DuplicatedValues);
42665ffd83dbSDimitry Andric     } else {
42675ffd83dbSDimitry Andric       Initializers.emplace_back();
42685ffd83dbSDimitry Andric       if (parseStructInitializer(Structure, Initializers.back()))
42695ffd83dbSDimitry Andric         return true;
42705ffd83dbSDimitry Andric     }
42715ffd83dbSDimitry Andric 
42725ffd83dbSDimitry Andric     // Continue if we see a comma. (Also, allow line continuation.)
42735ffd83dbSDimitry Andric     if (!parseOptionalToken(AsmToken::Comma))
42745ffd83dbSDimitry Andric       break;
42755ffd83dbSDimitry Andric     parseOptionalToken(AsmToken::EndOfStatement);
42765ffd83dbSDimitry Andric   }
42775ffd83dbSDimitry Andric 
42785ffd83dbSDimitry Andric   return false;
42795ffd83dbSDimitry Andric }
42805ffd83dbSDimitry Andric 
emitFieldValue(const FieldInfo & Field,const IntFieldInfo & Contents)42815ffd83dbSDimitry Andric bool MasmParser::emitFieldValue(const FieldInfo &Field,
42825ffd83dbSDimitry Andric                                 const IntFieldInfo &Contents) {
42835ffd83dbSDimitry Andric   // Default-initialize all values.
42845ffd83dbSDimitry Andric   for (const MCExpr *Value : Contents.Values) {
42855ffd83dbSDimitry Andric     if (emitIntValue(Value, Field.Type))
42865ffd83dbSDimitry Andric       return true;
42875ffd83dbSDimitry Andric   }
42885ffd83dbSDimitry Andric   return false;
42895ffd83dbSDimitry Andric }
42905ffd83dbSDimitry Andric 
emitFieldValue(const FieldInfo & Field,const RealFieldInfo & Contents)42915ffd83dbSDimitry Andric bool MasmParser::emitFieldValue(const FieldInfo &Field,
42925ffd83dbSDimitry Andric                                 const RealFieldInfo &Contents) {
42935ffd83dbSDimitry Andric   for (const APInt &AsInt : Contents.AsIntValues) {
42945ffd83dbSDimitry Andric     getStreamer().emitIntValue(AsInt.getLimitedValue(),
42955ffd83dbSDimitry Andric                                AsInt.getBitWidth() / 8);
42965ffd83dbSDimitry Andric   }
42975ffd83dbSDimitry Andric   return false;
42985ffd83dbSDimitry Andric }
42995ffd83dbSDimitry Andric 
emitFieldValue(const FieldInfo & Field,const StructFieldInfo & Contents)43005ffd83dbSDimitry Andric bool MasmParser::emitFieldValue(const FieldInfo &Field,
43015ffd83dbSDimitry Andric                                 const StructFieldInfo &Contents) {
43025ffd83dbSDimitry Andric   for (const auto &Initializer : Contents.Initializers) {
43035ffd83dbSDimitry Andric     size_t Index = 0, Offset = 0;
43045ffd83dbSDimitry Andric     for (const auto &SubField : Contents.Structure.Fields) {
43055ffd83dbSDimitry Andric       getStreamer().emitZeros(SubField.Offset - Offset);
43065ffd83dbSDimitry Andric       Offset = SubField.Offset + SubField.SizeOf;
43075ffd83dbSDimitry Andric       emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
43085ffd83dbSDimitry Andric     }
43095ffd83dbSDimitry Andric   }
43105ffd83dbSDimitry Andric   return false;
43115ffd83dbSDimitry Andric }
43125ffd83dbSDimitry Andric 
emitFieldValue(const FieldInfo & Field)43135ffd83dbSDimitry Andric bool MasmParser::emitFieldValue(const FieldInfo &Field) {
43145ffd83dbSDimitry Andric   switch (Field.Contents.FT) {
43155ffd83dbSDimitry Andric   case FT_INTEGRAL:
43165ffd83dbSDimitry Andric     return emitFieldValue(Field, Field.Contents.IntInfo);
43175ffd83dbSDimitry Andric   case FT_REAL:
43185ffd83dbSDimitry Andric     return emitFieldValue(Field, Field.Contents.RealInfo);
43195ffd83dbSDimitry Andric   case FT_STRUCT:
43205ffd83dbSDimitry Andric     return emitFieldValue(Field, Field.Contents.StructInfo);
43215ffd83dbSDimitry Andric   }
43225ffd83dbSDimitry Andric   llvm_unreachable("Unhandled FieldType enum");
43235ffd83dbSDimitry Andric }
43245ffd83dbSDimitry Andric 
emitFieldInitializer(const FieldInfo & Field,const IntFieldInfo & Contents,const IntFieldInfo & Initializer)43255ffd83dbSDimitry Andric bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
43265ffd83dbSDimitry Andric                                       const IntFieldInfo &Contents,
43275ffd83dbSDimitry Andric                                       const IntFieldInfo &Initializer) {
43285ffd83dbSDimitry Andric   for (const auto &Value : Initializer.Values) {
43295ffd83dbSDimitry Andric     if (emitIntValue(Value, Field.Type))
43305ffd83dbSDimitry Andric       return true;
43315ffd83dbSDimitry Andric   }
43325ffd83dbSDimitry Andric   // Default-initialize all remaining values.
4333fcaf7f86SDimitry Andric   for (const auto &Value :
4334fcaf7f86SDimitry Andric            llvm::drop_begin(Contents.Values, Initializer.Values.size())) {
43355ffd83dbSDimitry Andric     if (emitIntValue(Value, Field.Type))
43365ffd83dbSDimitry Andric       return true;
43375ffd83dbSDimitry Andric   }
43385ffd83dbSDimitry Andric   return false;
43395ffd83dbSDimitry Andric }
43405ffd83dbSDimitry Andric 
emitFieldInitializer(const FieldInfo & Field,const RealFieldInfo & Contents,const RealFieldInfo & Initializer)43415ffd83dbSDimitry Andric bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
43425ffd83dbSDimitry Andric                                       const RealFieldInfo &Contents,
43435ffd83dbSDimitry Andric                                       const RealFieldInfo &Initializer) {
43445ffd83dbSDimitry Andric   for (const auto &AsInt : Initializer.AsIntValues) {
43455ffd83dbSDimitry Andric     getStreamer().emitIntValue(AsInt.getLimitedValue(),
43465ffd83dbSDimitry Andric                                AsInt.getBitWidth() / 8);
43475ffd83dbSDimitry Andric   }
43485ffd83dbSDimitry Andric   // Default-initialize all remaining values.
4349fcaf7f86SDimitry Andric   for (const auto &AsInt :
4350fcaf7f86SDimitry Andric        llvm::drop_begin(Contents.AsIntValues, Initializer.AsIntValues.size())) {
43515ffd83dbSDimitry Andric     getStreamer().emitIntValue(AsInt.getLimitedValue(),
43525ffd83dbSDimitry Andric                                AsInt.getBitWidth() / 8);
43535ffd83dbSDimitry Andric   }
43545ffd83dbSDimitry Andric   return false;
43555ffd83dbSDimitry Andric }
43565ffd83dbSDimitry Andric 
emitFieldInitializer(const FieldInfo & Field,const StructFieldInfo & Contents,const StructFieldInfo & Initializer)43575ffd83dbSDimitry Andric bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
43585ffd83dbSDimitry Andric                                       const StructFieldInfo &Contents,
43595ffd83dbSDimitry Andric                                       const StructFieldInfo &Initializer) {
43605ffd83dbSDimitry Andric   for (const auto &Init : Initializer.Initializers) {
4361fe6060f1SDimitry Andric     if (emitStructInitializer(Contents.Structure, Init))
4362fe6060f1SDimitry Andric       return true;
43635ffd83dbSDimitry Andric   }
43645ffd83dbSDimitry Andric   // Default-initialize all remaining values.
4365fcaf7f86SDimitry Andric   for (const auto &Init : llvm::drop_begin(Contents.Initializers,
4366fcaf7f86SDimitry Andric                                            Initializer.Initializers.size())) {
4367fe6060f1SDimitry Andric     if (emitStructInitializer(Contents.Structure, Init))
4368fe6060f1SDimitry Andric       return true;
43695ffd83dbSDimitry Andric   }
43705ffd83dbSDimitry Andric   return false;
43715ffd83dbSDimitry Andric }
43725ffd83dbSDimitry Andric 
emitFieldInitializer(const FieldInfo & Field,const FieldInitializer & Initializer)43735ffd83dbSDimitry Andric bool MasmParser::emitFieldInitializer(const FieldInfo &Field,
43745ffd83dbSDimitry Andric                                       const FieldInitializer &Initializer) {
43755ffd83dbSDimitry Andric   switch (Field.Contents.FT) {
43765ffd83dbSDimitry Andric   case FT_INTEGRAL:
43775ffd83dbSDimitry Andric     return emitFieldInitializer(Field, Field.Contents.IntInfo,
43785ffd83dbSDimitry Andric                                 Initializer.IntInfo);
43795ffd83dbSDimitry Andric   case FT_REAL:
43805ffd83dbSDimitry Andric     return emitFieldInitializer(Field, Field.Contents.RealInfo,
43815ffd83dbSDimitry Andric                                 Initializer.RealInfo);
43825ffd83dbSDimitry Andric   case FT_STRUCT:
43835ffd83dbSDimitry Andric     return emitFieldInitializer(Field, Field.Contents.StructInfo,
43845ffd83dbSDimitry Andric                                 Initializer.StructInfo);
43855ffd83dbSDimitry Andric   }
43865ffd83dbSDimitry Andric   llvm_unreachable("Unhandled FieldType enum");
43875ffd83dbSDimitry Andric }
43885ffd83dbSDimitry Andric 
emitStructInitializer(const StructInfo & Structure,const StructInitializer & Initializer)43895ffd83dbSDimitry Andric bool MasmParser::emitStructInitializer(const StructInfo &Structure,
43905ffd83dbSDimitry Andric                                        const StructInitializer &Initializer) {
4391fe6060f1SDimitry Andric   if (!Structure.Initializable)
4392fe6060f1SDimitry Andric     return Error(getLexer().getLoc(),
4393fe6060f1SDimitry Andric                  "cannot initialize a value of type '" + Structure.Name +
4394fe6060f1SDimitry Andric                      "'; 'org' was used in the type's declaration");
43955ffd83dbSDimitry Andric   size_t Index = 0, Offset = 0;
43965ffd83dbSDimitry Andric   for (const auto &Init : Initializer.FieldInitializers) {
43975ffd83dbSDimitry Andric     const auto &Field = Structure.Fields[Index++];
43985ffd83dbSDimitry Andric     getStreamer().emitZeros(Field.Offset - Offset);
43995ffd83dbSDimitry Andric     Offset = Field.Offset + Field.SizeOf;
44005ffd83dbSDimitry Andric     if (emitFieldInitializer(Field, Init))
44015ffd83dbSDimitry Andric       return true;
44025ffd83dbSDimitry Andric   }
44035ffd83dbSDimitry Andric   // Default-initialize all remaining fields.
4404fcaf7f86SDimitry Andric   for (const auto &Field : llvm::drop_begin(
4405fcaf7f86SDimitry Andric            Structure.Fields, Initializer.FieldInitializers.size())) {
44065ffd83dbSDimitry Andric     getStreamer().emitZeros(Field.Offset - Offset);
44075ffd83dbSDimitry Andric     Offset = Field.Offset + Field.SizeOf;
44085ffd83dbSDimitry Andric     if (emitFieldValue(Field))
44095ffd83dbSDimitry Andric       return true;
44105ffd83dbSDimitry Andric   }
44115ffd83dbSDimitry Andric   // Add final padding.
44125ffd83dbSDimitry Andric   if (Offset != Structure.Size)
44135ffd83dbSDimitry Andric     getStreamer().emitZeros(Structure.Size - Offset);
44145ffd83dbSDimitry Andric   return false;
44155ffd83dbSDimitry Andric }
44165ffd83dbSDimitry Andric 
44175ffd83dbSDimitry Andric // Set data values from initializers.
emitStructValues(const StructInfo & Structure,unsigned * Count)4418e8d8bef9SDimitry Andric bool MasmParser::emitStructValues(const StructInfo &Structure,
4419e8d8bef9SDimitry Andric                                   unsigned *Count) {
44205ffd83dbSDimitry Andric   std::vector<StructInitializer> Initializers;
44215ffd83dbSDimitry Andric   if (parseStructInstList(Structure, Initializers))
44225ffd83dbSDimitry Andric     return true;
44235ffd83dbSDimitry Andric 
44245ffd83dbSDimitry Andric   for (const auto &Initializer : Initializers) {
44255ffd83dbSDimitry Andric     if (emitStructInitializer(Structure, Initializer))
44265ffd83dbSDimitry Andric       return true;
44275ffd83dbSDimitry Andric   }
44285ffd83dbSDimitry Andric 
4429e8d8bef9SDimitry Andric   if (Count)
4430e8d8bef9SDimitry Andric     *Count = Initializers.size();
44315ffd83dbSDimitry Andric   return false;
44325ffd83dbSDimitry Andric }
44335ffd83dbSDimitry Andric 
44345ffd83dbSDimitry Andric // Declare a field in the current struct.
addStructField(StringRef Name,const StructInfo & Structure)44355ffd83dbSDimitry Andric bool MasmParser::addStructField(StringRef Name, const StructInfo &Structure) {
44365ffd83dbSDimitry Andric   StructInfo &OwningStruct = StructInProgress.back();
4437e8d8bef9SDimitry Andric   FieldInfo &Field =
4438e8d8bef9SDimitry Andric       OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
44395ffd83dbSDimitry Andric   StructFieldInfo &StructInfo = Field.Contents.StructInfo;
44405ffd83dbSDimitry Andric 
44415ffd83dbSDimitry Andric   StructInfo.Structure = Structure;
44425ffd83dbSDimitry Andric   Field.Type = Structure.Size;
44435ffd83dbSDimitry Andric 
44445ffd83dbSDimitry Andric   if (parseStructInstList(Structure, StructInfo.Initializers))
44455ffd83dbSDimitry Andric     return true;
44465ffd83dbSDimitry Andric 
44475ffd83dbSDimitry Andric   Field.LengthOf = StructInfo.Initializers.size();
44485ffd83dbSDimitry Andric   Field.SizeOf = Field.Type * Field.LengthOf;
4449fe6060f1SDimitry Andric 
4450fe6060f1SDimitry Andric   const unsigned FieldEnd = Field.Offset + Field.SizeOf;
4451fe6060f1SDimitry Andric   if (!OwningStruct.IsUnion) {
4452fe6060f1SDimitry Andric     OwningStruct.NextOffset = FieldEnd;
4453fe6060f1SDimitry Andric   }
4454fe6060f1SDimitry Andric   OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd);
44555ffd83dbSDimitry Andric 
44565ffd83dbSDimitry Andric   return false;
44575ffd83dbSDimitry Andric }
44585ffd83dbSDimitry Andric 
44595ffd83dbSDimitry Andric /// parseDirectiveStructValue
44605ffd83dbSDimitry Andric ///  ::= struct-id (<struct-initializer> | {struct-initializer})
44615ffd83dbSDimitry Andric ///                [, (<struct-initializer> | {struct-initializer})]*
parseDirectiveStructValue(const StructInfo & Structure,StringRef Directive,SMLoc DirLoc)44625ffd83dbSDimitry Andric bool MasmParser::parseDirectiveStructValue(const StructInfo &Structure,
44635ffd83dbSDimitry Andric                                            StringRef Directive, SMLoc DirLoc) {
44645ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
44655ffd83dbSDimitry Andric     if (emitStructValues(Structure))
44665ffd83dbSDimitry Andric       return true;
44675ffd83dbSDimitry Andric   } else if (addStructField("", Structure)) {
44685ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
44695ffd83dbSDimitry Andric   }
44705ffd83dbSDimitry Andric 
44715ffd83dbSDimitry Andric   return false;
44725ffd83dbSDimitry Andric }
44735ffd83dbSDimitry Andric 
44745ffd83dbSDimitry Andric /// parseDirectiveNamedValue
44755ffd83dbSDimitry Andric ///  ::= name (byte | word | ... ) [ expression (, expression)* ]
parseDirectiveNamedStructValue(const StructInfo & Structure,StringRef Directive,SMLoc DirLoc,StringRef Name)44765ffd83dbSDimitry Andric bool MasmParser::parseDirectiveNamedStructValue(const StructInfo &Structure,
44775ffd83dbSDimitry Andric                                                 StringRef Directive,
44785ffd83dbSDimitry Andric                                                 SMLoc DirLoc, StringRef Name) {
44795ffd83dbSDimitry Andric   if (StructInProgress.empty()) {
44805ffd83dbSDimitry Andric     // Initialize named data value.
44815ffd83dbSDimitry Andric     MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
44825ffd83dbSDimitry Andric     getStreamer().emitLabel(Sym);
4483e8d8bef9SDimitry Andric     unsigned Count;
4484e8d8bef9SDimitry Andric     if (emitStructValues(Structure, &Count))
44855ffd83dbSDimitry Andric       return true;
4486e8d8bef9SDimitry Andric     AsmTypeInfo Type;
4487e8d8bef9SDimitry Andric     Type.Name = Structure.Name;
4488e8d8bef9SDimitry Andric     Type.Size = Structure.Size * Count;
4489e8d8bef9SDimitry Andric     Type.ElementSize = Structure.Size;
4490e8d8bef9SDimitry Andric     Type.Length = Count;
4491e8d8bef9SDimitry Andric     KnownType[Name.lower()] = Type;
44925ffd83dbSDimitry Andric   } else if (addStructField(Name, Structure)) {
44935ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
44945ffd83dbSDimitry Andric   }
44955ffd83dbSDimitry Andric 
44965ffd83dbSDimitry Andric   return false;
44975ffd83dbSDimitry Andric }
44985ffd83dbSDimitry Andric 
44995ffd83dbSDimitry Andric /// parseDirectiveStruct
45005ffd83dbSDimitry Andric ///  ::= <name> (STRUC | STRUCT | UNION) [fieldAlign] [, NONUNIQUE]
45015ffd83dbSDimitry Andric ///      (dataDir | generalDir | offsetDir | nestedStruct)+
45025ffd83dbSDimitry Andric ///      <name> ENDS
45035ffd83dbSDimitry Andric ////// dataDir = data declaration
45045ffd83dbSDimitry Andric ////// offsetDir = EVEN, ORG, ALIGN
parseDirectiveStruct(StringRef Directive,DirectiveKind DirKind,StringRef Name,SMLoc NameLoc)45055ffd83dbSDimitry Andric bool MasmParser::parseDirectiveStruct(StringRef Directive,
45065ffd83dbSDimitry Andric                                       DirectiveKind DirKind, StringRef Name,
45075ffd83dbSDimitry Andric                                       SMLoc NameLoc) {
45085ffd83dbSDimitry Andric   // We ignore NONUNIQUE; we do not support OPTION M510 or OPTION OLDSTRUCTS
45095ffd83dbSDimitry Andric   // anyway, so all field accesses must be qualified.
45105ffd83dbSDimitry Andric   AsmToken NextTok = getTok();
45115ffd83dbSDimitry Andric   int64_t AlignmentValue = 1;
45125ffd83dbSDimitry Andric   if (NextTok.isNot(AsmToken::Comma) &&
45135ffd83dbSDimitry Andric       NextTok.isNot(AsmToken::EndOfStatement) &&
45145ffd83dbSDimitry Andric       parseAbsoluteExpression(AlignmentValue)) {
45155ffd83dbSDimitry Andric     return addErrorSuffix(" in alignment value for '" + Twine(Directive) +
45165ffd83dbSDimitry Andric                           "' directive");
45175ffd83dbSDimitry Andric   }
45185ffd83dbSDimitry Andric   if (!isPowerOf2_64(AlignmentValue)) {
45195ffd83dbSDimitry Andric     return Error(NextTok.getLoc(), "alignment must be a power of two; was " +
45205ffd83dbSDimitry Andric                                        std::to_string(AlignmentValue));
45215ffd83dbSDimitry Andric   }
45225ffd83dbSDimitry Andric 
45235ffd83dbSDimitry Andric   StringRef Qualifier;
45245ffd83dbSDimitry Andric   SMLoc QualifierLoc;
45255ffd83dbSDimitry Andric   if (parseOptionalToken(AsmToken::Comma)) {
45265ffd83dbSDimitry Andric     QualifierLoc = getTok().getLoc();
45275ffd83dbSDimitry Andric     if (parseIdentifier(Qualifier))
45285ffd83dbSDimitry Andric       return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
4529fe6060f1SDimitry Andric     if (!Qualifier.equals_insensitive("nonunique"))
45305ffd83dbSDimitry Andric       return Error(QualifierLoc, "Unrecognized qualifier for '" +
45315ffd83dbSDimitry Andric                                      Twine(Directive) +
45325ffd83dbSDimitry Andric                                      "' directive; expected none or NONUNIQUE");
45335ffd83dbSDimitry Andric   }
45345ffd83dbSDimitry Andric 
453506c3fb27SDimitry Andric   if (parseEOL())
45365ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
45375ffd83dbSDimitry Andric 
45385ffd83dbSDimitry Andric   StructInProgress.emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
45395ffd83dbSDimitry Andric   return false;
45405ffd83dbSDimitry Andric }
45415ffd83dbSDimitry Andric 
45425ffd83dbSDimitry Andric /// parseDirectiveNestedStruct
45435ffd83dbSDimitry Andric ///  ::= (STRUC | STRUCT | UNION) [name]
45445ffd83dbSDimitry Andric ///      (dataDir | generalDir | offsetDir | nestedStruct)+
45455ffd83dbSDimitry Andric ///      ENDS
parseDirectiveNestedStruct(StringRef Directive,DirectiveKind DirKind)45465ffd83dbSDimitry Andric bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
45475ffd83dbSDimitry Andric                                             DirectiveKind DirKind) {
45485ffd83dbSDimitry Andric   if (StructInProgress.empty())
45495ffd83dbSDimitry Andric     return TokError("missing name in top-level '" + Twine(Directive) +
45505ffd83dbSDimitry Andric                     "' directive");
45515ffd83dbSDimitry Andric 
45525ffd83dbSDimitry Andric   StringRef Name;
45535ffd83dbSDimitry Andric   if (getTok().is(AsmToken::Identifier)) {
45545ffd83dbSDimitry Andric     Name = getTok().getIdentifier();
45555ffd83dbSDimitry Andric     parseToken(AsmToken::Identifier);
45565ffd83dbSDimitry Andric   }
455706c3fb27SDimitry Andric   if (parseEOL())
45585ffd83dbSDimitry Andric     return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
45595ffd83dbSDimitry Andric 
4560e8d8bef9SDimitry Andric   // Reserve space to ensure Alignment doesn't get invalidated when
4561e8d8bef9SDimitry Andric   // StructInProgress grows.
4562e8d8bef9SDimitry Andric   StructInProgress.reserve(StructInProgress.size() + 1);
45635ffd83dbSDimitry Andric   StructInProgress.emplace_back(Name, DirKind == DK_UNION,
45645ffd83dbSDimitry Andric                                 StructInProgress.back().Alignment);
45655ffd83dbSDimitry Andric   return false;
45665ffd83dbSDimitry Andric }
45675ffd83dbSDimitry Andric 
parseDirectiveEnds(StringRef Name,SMLoc NameLoc)45685ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
45695ffd83dbSDimitry Andric   if (StructInProgress.empty())
45705ffd83dbSDimitry Andric     return Error(NameLoc, "ENDS directive without matching STRUC/STRUCT/UNION");
45715ffd83dbSDimitry Andric   if (StructInProgress.size() > 1)
45725ffd83dbSDimitry Andric     return Error(NameLoc, "unexpected name in nested ENDS directive");
4573fe6060f1SDimitry Andric   if (StructInProgress.back().Name.compare_insensitive(Name))
45745ffd83dbSDimitry Andric     return Error(NameLoc, "mismatched name in ENDS directive; expected '" +
45755ffd83dbSDimitry Andric                               StructInProgress.back().Name + "'");
45765ffd83dbSDimitry Andric   StructInfo Structure = StructInProgress.pop_back_val();
4577e8d8bef9SDimitry Andric   // Pad to make the structure's size divisible by the smaller of its alignment
4578e8d8bef9SDimitry Andric   // and the size of its largest field.
4579e8d8bef9SDimitry Andric   Structure.Size = llvm::alignTo(
4580e8d8bef9SDimitry Andric       Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
45815ffd83dbSDimitry Andric   Structs[Name.lower()] = Structure;
45825ffd83dbSDimitry Andric 
458306c3fb27SDimitry Andric   if (parseEOL())
45845ffd83dbSDimitry Andric     return addErrorSuffix(" in ENDS directive");
45855ffd83dbSDimitry Andric 
45865ffd83dbSDimitry Andric   return false;
45875ffd83dbSDimitry Andric }
45885ffd83dbSDimitry Andric 
parseDirectiveNestedEnds()45895ffd83dbSDimitry Andric bool MasmParser::parseDirectiveNestedEnds() {
45905ffd83dbSDimitry Andric   if (StructInProgress.empty())
45915ffd83dbSDimitry Andric     return TokError("ENDS directive without matching STRUC/STRUCT/UNION");
45925ffd83dbSDimitry Andric   if (StructInProgress.size() == 1)
45935ffd83dbSDimitry Andric     return TokError("missing name in top-level ENDS directive");
45945ffd83dbSDimitry Andric 
459506c3fb27SDimitry Andric   if (parseEOL())
45965ffd83dbSDimitry Andric     return addErrorSuffix(" in nested ENDS directive");
45975ffd83dbSDimitry Andric 
45985ffd83dbSDimitry Andric   StructInfo Structure = StructInProgress.pop_back_val();
45995ffd83dbSDimitry Andric   // Pad to make the structure's size divisible by its alignment.
46005ffd83dbSDimitry Andric   Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment);
46015ffd83dbSDimitry Andric 
46025ffd83dbSDimitry Andric   StructInfo &ParentStruct = StructInProgress.back();
46035ffd83dbSDimitry Andric   if (Structure.Name.empty()) {
4604fe6060f1SDimitry Andric     // Anonymous substructures' fields are addressed as if they belong to the
4605fe6060f1SDimitry Andric     // parent structure - so we transfer them to the parent here.
46065ffd83dbSDimitry Andric     const size_t OldFields = ParentStruct.Fields.size();
46075ffd83dbSDimitry Andric     ParentStruct.Fields.insert(
46085ffd83dbSDimitry Andric         ParentStruct.Fields.end(),
46095ffd83dbSDimitry Andric         std::make_move_iterator(Structure.Fields.begin()),
46105ffd83dbSDimitry Andric         std::make_move_iterator(Structure.Fields.end()));
46115ffd83dbSDimitry Andric     for (const auto &FieldByName : Structure.FieldsByName) {
46125ffd83dbSDimitry Andric       ParentStruct.FieldsByName[FieldByName.getKey()] =
46135ffd83dbSDimitry Andric           FieldByName.getValue() + OldFields;
46145ffd83dbSDimitry Andric     }
4615fe6060f1SDimitry Andric 
4616fe6060f1SDimitry Andric     unsigned FirstFieldOffset = 0;
4617fe6060f1SDimitry Andric     if (!Structure.Fields.empty() && !ParentStruct.IsUnion) {
4618fe6060f1SDimitry Andric       FirstFieldOffset = llvm::alignTo(
4619fe6060f1SDimitry Andric           ParentStruct.NextOffset,
4620fe6060f1SDimitry Andric           std::min(ParentStruct.Alignment, Structure.AlignmentSize));
46215ffd83dbSDimitry Andric     }
46225ffd83dbSDimitry Andric 
4623fe6060f1SDimitry Andric     if (ParentStruct.IsUnion) {
46245ffd83dbSDimitry Andric       ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
4625fe6060f1SDimitry Andric     } else {
4626fcaf7f86SDimitry Andric       for (auto &Field : llvm::drop_begin(ParentStruct.Fields, OldFields))
4627fcaf7f86SDimitry Andric         Field.Offset += FirstFieldOffset;
4628fe6060f1SDimitry Andric 
4629fe6060f1SDimitry Andric       const unsigned StructureEnd = FirstFieldOffset + Structure.Size;
4630fe6060f1SDimitry Andric       if (!ParentStruct.IsUnion) {
4631fe6060f1SDimitry Andric         ParentStruct.NextOffset = StructureEnd;
4632fe6060f1SDimitry Andric       }
4633fe6060f1SDimitry Andric       ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4634fe6060f1SDimitry Andric     }
46355ffd83dbSDimitry Andric   } else {
4636e8d8bef9SDimitry Andric     FieldInfo &Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
4637e8d8bef9SDimitry Andric                                              Structure.AlignmentSize);
46385ffd83dbSDimitry Andric     StructFieldInfo &StructInfo = Field.Contents.StructInfo;
46395ffd83dbSDimitry Andric     Field.Type = Structure.Size;
46405ffd83dbSDimitry Andric     Field.LengthOf = 1;
46415ffd83dbSDimitry Andric     Field.SizeOf = Structure.Size;
46425ffd83dbSDimitry Andric 
4643fe6060f1SDimitry Andric     const unsigned StructureEnd = Field.Offset + Field.SizeOf;
4644fe6060f1SDimitry Andric     if (!ParentStruct.IsUnion) {
4645fe6060f1SDimitry Andric       ParentStruct.NextOffset = StructureEnd;
4646fe6060f1SDimitry Andric     }
4647fe6060f1SDimitry Andric     ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
46485ffd83dbSDimitry Andric 
46495ffd83dbSDimitry Andric     StructInfo.Structure = Structure;
46505ffd83dbSDimitry Andric     StructInfo.Initializers.emplace_back();
46515ffd83dbSDimitry Andric     auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
46525ffd83dbSDimitry Andric     for (const auto &SubField : Structure.Fields) {
46535ffd83dbSDimitry Andric       FieldInitializers.push_back(SubField.Contents);
46545ffd83dbSDimitry Andric     }
46555ffd83dbSDimitry Andric   }
46565ffd83dbSDimitry Andric 
46575ffd83dbSDimitry Andric   return false;
46585ffd83dbSDimitry Andric }
46595ffd83dbSDimitry Andric 
46605ffd83dbSDimitry Andric /// parseDirectiveOrg
4661fe6060f1SDimitry Andric ///  ::= org expression
parseDirectiveOrg()46625ffd83dbSDimitry Andric bool MasmParser::parseDirectiveOrg() {
46635ffd83dbSDimitry Andric   const MCExpr *Offset;
46645ffd83dbSDimitry Andric   SMLoc OffsetLoc = Lexer.getLoc();
46655ffd83dbSDimitry Andric   if (checkForValidSection() || parseExpression(Offset))
46665ffd83dbSDimitry Andric     return true;
466706c3fb27SDimitry Andric   if (parseEOL())
4668fe6060f1SDimitry Andric     return addErrorSuffix(" in 'org' directive");
46695ffd83dbSDimitry Andric 
4670fe6060f1SDimitry Andric   if (StructInProgress.empty()) {
4671fe6060f1SDimitry Andric     // Not in a struct; change the offset for the next instruction or data
4672fe6060f1SDimitry Andric     if (checkForValidSection())
4673fe6060f1SDimitry Andric       return addErrorSuffix(" in 'org' directive");
4674fe6060f1SDimitry Andric 
4675fe6060f1SDimitry Andric     getStreamer().emitValueToOffset(Offset, 0, OffsetLoc);
4676fe6060f1SDimitry Andric   } else {
4677fe6060f1SDimitry Andric     // Offset the next field of this struct
4678fe6060f1SDimitry Andric     StructInfo &Structure = StructInProgress.back();
4679fe6060f1SDimitry Andric     int64_t OffsetRes;
4680fe6060f1SDimitry Andric     if (!Offset->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr()))
4681fe6060f1SDimitry Andric       return Error(OffsetLoc,
4682fe6060f1SDimitry Andric                    "expected absolute expression in 'org' directive");
4683fe6060f1SDimitry Andric     if (OffsetRes < 0)
4684fe6060f1SDimitry Andric       return Error(
4685fe6060f1SDimitry Andric           OffsetLoc,
4686fe6060f1SDimitry Andric           "expected non-negative value in struct's 'org' directive; was " +
4687fe6060f1SDimitry Andric               std::to_string(OffsetRes));
4688fe6060f1SDimitry Andric     Structure.NextOffset = static_cast<unsigned>(OffsetRes);
4689fe6060f1SDimitry Andric 
4690fe6060f1SDimitry Andric     // ORG-affected structures cannot be initialized
4691fe6060f1SDimitry Andric     Structure.Initializable = false;
4692fe6060f1SDimitry Andric   }
4693fe6060f1SDimitry Andric 
46945ffd83dbSDimitry Andric   return false;
46955ffd83dbSDimitry Andric }
46965ffd83dbSDimitry Andric 
emitAlignTo(int64_t Alignment)4697fe6060f1SDimitry Andric bool MasmParser::emitAlignTo(int64_t Alignment) {
4698fe6060f1SDimitry Andric   if (StructInProgress.empty()) {
4699fe6060f1SDimitry Andric     // Not in a struct; align the next instruction or data
47005ffd83dbSDimitry Andric     if (checkForValidSection())
4701fe6060f1SDimitry Andric       return true;
47025ffd83dbSDimitry Andric 
47035ffd83dbSDimitry Andric     // Check whether we should use optimal code alignment for this align
47045ffd83dbSDimitry Andric     // directive.
47055ffd83dbSDimitry Andric     const MCSection *Section = getStreamer().getCurrentSectionOnly();
47065ffd83dbSDimitry Andric     assert(Section && "must have section to emit alignment");
470781ad6265SDimitry Andric     if (Section->useCodeAlign()) {
4708bdd1243dSDimitry Andric       getStreamer().emitCodeAlignment(Align(Alignment),
4709bdd1243dSDimitry Andric                                       &getTargetParser().getSTI(),
4710349cc55cSDimitry Andric                                       /*MaxBytesToEmit=*/0);
47115ffd83dbSDimitry Andric     } else {
47125ffd83dbSDimitry Andric       // FIXME: Target specific behavior about how the "extra" bytes are filled.
4713bdd1243dSDimitry Andric       getStreamer().emitValueToAlignment(Align(Alignment), /*Value=*/0,
4714fe6060f1SDimitry Andric                                          /*ValueSize=*/1,
47155ffd83dbSDimitry Andric                                          /*MaxBytesToEmit=*/0);
47165ffd83dbSDimitry Andric     }
4717fe6060f1SDimitry Andric   } else {
4718fe6060f1SDimitry Andric     // Align the next field of this struct
4719fe6060f1SDimitry Andric     StructInfo &Structure = StructInProgress.back();
4720fe6060f1SDimitry Andric     Structure.NextOffset = llvm::alignTo(Structure.NextOffset, Alignment);
4721fe6060f1SDimitry Andric   }
4722fe6060f1SDimitry Andric 
4723fe6060f1SDimitry Andric   return false;
4724fe6060f1SDimitry Andric }
4725fe6060f1SDimitry Andric 
4726fe6060f1SDimitry Andric /// parseDirectiveAlign
4727fe6060f1SDimitry Andric ///  ::= align expression
parseDirectiveAlign()4728fe6060f1SDimitry Andric bool MasmParser::parseDirectiveAlign() {
4729fe6060f1SDimitry Andric   SMLoc AlignmentLoc = getLexer().getLoc();
4730fe6060f1SDimitry Andric   int64_t Alignment;
4731fe6060f1SDimitry Andric 
4732fe6060f1SDimitry Andric   // Ignore empty 'align' directives.
4733fe6060f1SDimitry Andric   if (getTok().is(AsmToken::EndOfStatement)) {
4734fe6060f1SDimitry Andric     return Warning(AlignmentLoc,
4735fe6060f1SDimitry Andric                    "align directive with no operand is ignored") &&
473606c3fb27SDimitry Andric            parseEOL();
4737fe6060f1SDimitry Andric   }
473806c3fb27SDimitry Andric   if (parseAbsoluteExpression(Alignment) || parseEOL())
4739fe6060f1SDimitry Andric     return addErrorSuffix(" in align directive");
4740fe6060f1SDimitry Andric 
4741fe6060f1SDimitry Andric   // Always emit an alignment here even if we throw an error.
4742fe6060f1SDimitry Andric   bool ReturnVal = false;
4743fe6060f1SDimitry Andric 
4744fe6060f1SDimitry Andric   // Reject alignments that aren't either a power of two or zero, for ML.exe
4745fe6060f1SDimitry Andric   // compatibility. Alignment of zero is silently rounded up to one.
4746fe6060f1SDimitry Andric   if (Alignment == 0)
4747fe6060f1SDimitry Andric     Alignment = 1;
4748fe6060f1SDimitry Andric   if (!isPowerOf2_64(Alignment))
4749fe6060f1SDimitry Andric     ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2; was " +
4750fe6060f1SDimitry Andric                                          std::to_string(Alignment));
4751fe6060f1SDimitry Andric 
4752fe6060f1SDimitry Andric   if (emitAlignTo(Alignment))
4753fe6060f1SDimitry Andric     ReturnVal |= addErrorSuffix(" in align directive");
47545ffd83dbSDimitry Andric 
47555ffd83dbSDimitry Andric   return ReturnVal;
47565ffd83dbSDimitry Andric }
47575ffd83dbSDimitry Andric 
4758fe6060f1SDimitry Andric /// parseDirectiveEven
4759fe6060f1SDimitry Andric ///  ::= even
parseDirectiveEven()4760fe6060f1SDimitry Andric bool MasmParser::parseDirectiveEven() {
476106c3fb27SDimitry Andric   if (parseEOL() || emitAlignTo(2))
4762fe6060f1SDimitry Andric     return addErrorSuffix(" in even directive");
4763fe6060f1SDimitry Andric 
4764fe6060f1SDimitry Andric   return false;
4765fe6060f1SDimitry Andric }
4766fe6060f1SDimitry Andric 
47675ffd83dbSDimitry Andric /// parseDirectiveFile
47685ffd83dbSDimitry Andric /// ::= .file filename
47695ffd83dbSDimitry Andric /// ::= .file number [directory] filename [md5 checksum] [source source-text]
parseDirectiveFile(SMLoc DirectiveLoc)47705ffd83dbSDimitry Andric bool MasmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
47715ffd83dbSDimitry Andric   // FIXME: I'm not sure what this is.
47725ffd83dbSDimitry Andric   int64_t FileNumber = -1;
47735ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
47745ffd83dbSDimitry Andric     FileNumber = getTok().getIntVal();
47755ffd83dbSDimitry Andric     Lex();
47765ffd83dbSDimitry Andric 
47775ffd83dbSDimitry Andric     if (FileNumber < 0)
47785ffd83dbSDimitry Andric       return TokError("negative file number");
47795ffd83dbSDimitry Andric   }
47805ffd83dbSDimitry Andric 
47815ffd83dbSDimitry Andric   std::string Path;
47825ffd83dbSDimitry Andric 
47835ffd83dbSDimitry Andric   // Usually the directory and filename together, otherwise just the directory.
47845ffd83dbSDimitry Andric   // Allow the strings to have escaped octal character sequence.
47855ffd83dbSDimitry Andric   if (check(getTok().isNot(AsmToken::String),
47865ffd83dbSDimitry Andric             "unexpected token in '.file' directive") ||
47875ffd83dbSDimitry Andric       parseEscapedString(Path))
47885ffd83dbSDimitry Andric     return true;
47895ffd83dbSDimitry Andric 
47905ffd83dbSDimitry Andric   StringRef Directory;
47915ffd83dbSDimitry Andric   StringRef Filename;
47925ffd83dbSDimitry Andric   std::string FilenameData;
47935ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::String)) {
47945ffd83dbSDimitry Andric     if (check(FileNumber == -1,
47955ffd83dbSDimitry Andric               "explicit path specified, but no file number") ||
47965ffd83dbSDimitry Andric         parseEscapedString(FilenameData))
47975ffd83dbSDimitry Andric       return true;
47985ffd83dbSDimitry Andric     Filename = FilenameData;
47995ffd83dbSDimitry Andric     Directory = Path;
48005ffd83dbSDimitry Andric   } else {
48015ffd83dbSDimitry Andric     Filename = Path;
48025ffd83dbSDimitry Andric   }
48035ffd83dbSDimitry Andric 
48045ffd83dbSDimitry Andric   uint64_t MD5Hi, MD5Lo;
48055ffd83dbSDimitry Andric   bool HasMD5 = false;
48065ffd83dbSDimitry Andric 
4807bdd1243dSDimitry Andric   std::optional<StringRef> Source;
48085ffd83dbSDimitry Andric   bool HasSource = false;
48095ffd83dbSDimitry Andric   std::string SourceString;
48105ffd83dbSDimitry Andric 
48115ffd83dbSDimitry Andric   while (!parseOptionalToken(AsmToken::EndOfStatement)) {
48125ffd83dbSDimitry Andric     StringRef Keyword;
48135ffd83dbSDimitry Andric     if (check(getTok().isNot(AsmToken::Identifier),
48145ffd83dbSDimitry Andric               "unexpected token in '.file' directive") ||
48155ffd83dbSDimitry Andric         parseIdentifier(Keyword))
48165ffd83dbSDimitry Andric       return true;
48175ffd83dbSDimitry Andric     if (Keyword == "md5") {
48185ffd83dbSDimitry Andric       HasMD5 = true;
48195ffd83dbSDimitry Andric       if (check(FileNumber == -1,
48205ffd83dbSDimitry Andric                 "MD5 checksum specified, but no file number") ||
48215ffd83dbSDimitry Andric           parseHexOcta(*this, MD5Hi, MD5Lo))
48225ffd83dbSDimitry Andric         return true;
48235ffd83dbSDimitry Andric     } else if (Keyword == "source") {
48245ffd83dbSDimitry Andric       HasSource = true;
48255ffd83dbSDimitry Andric       if (check(FileNumber == -1,
48265ffd83dbSDimitry Andric                 "source specified, but no file number") ||
48275ffd83dbSDimitry Andric           check(getTok().isNot(AsmToken::String),
48285ffd83dbSDimitry Andric                 "unexpected token in '.file' directive") ||
48295ffd83dbSDimitry Andric           parseEscapedString(SourceString))
48305ffd83dbSDimitry Andric         return true;
48315ffd83dbSDimitry Andric     } else {
48325ffd83dbSDimitry Andric       return TokError("unexpected token in '.file' directive");
48335ffd83dbSDimitry Andric     }
48345ffd83dbSDimitry Andric   }
48355ffd83dbSDimitry Andric 
48365ffd83dbSDimitry Andric   if (FileNumber == -1) {
48375ffd83dbSDimitry Andric     // Ignore the directive if there is no number and the target doesn't support
48385ffd83dbSDimitry Andric     // numberless .file directives. This allows some portability of assembler
48395ffd83dbSDimitry Andric     // between different object file formats.
48405ffd83dbSDimitry Andric     if (getContext().getAsmInfo()->hasSingleParameterDotFile())
48415ffd83dbSDimitry Andric       getStreamer().emitFileDirective(Filename);
48425ffd83dbSDimitry Andric   } else {
48435ffd83dbSDimitry Andric     // In case there is a -g option as well as debug info from directive .file,
48445ffd83dbSDimitry Andric     // we turn off the -g option, directly use the existing debug info instead.
48455ffd83dbSDimitry Andric     // Throw away any implicit file table for the assembler source.
48465ffd83dbSDimitry Andric     if (Ctx.getGenDwarfForAssembly()) {
48475ffd83dbSDimitry Andric       Ctx.getMCDwarfLineTable(0).resetFileTable();
48485ffd83dbSDimitry Andric       Ctx.setGenDwarfForAssembly(false);
48495ffd83dbSDimitry Andric     }
48505ffd83dbSDimitry Andric 
4851bdd1243dSDimitry Andric     std::optional<MD5::MD5Result> CKMem;
48525ffd83dbSDimitry Andric     if (HasMD5) {
48535ffd83dbSDimitry Andric       MD5::MD5Result Sum;
48545ffd83dbSDimitry Andric       for (unsigned i = 0; i != 8; ++i) {
485581ad6265SDimitry Andric         Sum[i] = uint8_t(MD5Hi >> ((7 - i) * 8));
485681ad6265SDimitry Andric         Sum[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8));
48575ffd83dbSDimitry Andric       }
48585ffd83dbSDimitry Andric       CKMem = Sum;
48595ffd83dbSDimitry Andric     }
48605ffd83dbSDimitry Andric     if (HasSource) {
48615ffd83dbSDimitry Andric       char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
48625ffd83dbSDimitry Andric       memcpy(SourceBuf, SourceString.data(), SourceString.size());
48635ffd83dbSDimitry Andric       Source = StringRef(SourceBuf, SourceString.size());
48645ffd83dbSDimitry Andric     }
48655ffd83dbSDimitry Andric     if (FileNumber == 0) {
48665ffd83dbSDimitry Andric       if (Ctx.getDwarfVersion() < 5)
48675ffd83dbSDimitry Andric         return Warning(DirectiveLoc, "file 0 not supported prior to DWARF-5");
48685ffd83dbSDimitry Andric       getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source);
48695ffd83dbSDimitry Andric     } else {
48705ffd83dbSDimitry Andric       Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
48715ffd83dbSDimitry Andric           FileNumber, Directory, Filename, CKMem, Source);
48725ffd83dbSDimitry Andric       if (!FileNumOrErr)
48735ffd83dbSDimitry Andric         return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
48745ffd83dbSDimitry Andric     }
48755ffd83dbSDimitry Andric     // Alert the user if there are some .file directives with MD5 and some not.
48765ffd83dbSDimitry Andric     // But only do that once.
48775ffd83dbSDimitry Andric     if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
48785ffd83dbSDimitry Andric       ReportedInconsistentMD5 = true;
48795ffd83dbSDimitry Andric       return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
48805ffd83dbSDimitry Andric     }
48815ffd83dbSDimitry Andric   }
48825ffd83dbSDimitry Andric 
48835ffd83dbSDimitry Andric   return false;
48845ffd83dbSDimitry Andric }
48855ffd83dbSDimitry Andric 
48865ffd83dbSDimitry Andric /// parseDirectiveLine
48875ffd83dbSDimitry Andric /// ::= .line [number]
parseDirectiveLine()48885ffd83dbSDimitry Andric bool MasmParser::parseDirectiveLine() {
48895ffd83dbSDimitry Andric   int64_t LineNumber;
48905ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
48915ffd83dbSDimitry Andric     if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
48925ffd83dbSDimitry Andric       return true;
48935ffd83dbSDimitry Andric     (void)LineNumber;
48945ffd83dbSDimitry Andric     // FIXME: Do something with the .line.
48955ffd83dbSDimitry Andric   }
489681ad6265SDimitry Andric   if (parseEOL())
48975ffd83dbSDimitry Andric     return true;
48985ffd83dbSDimitry Andric 
48995ffd83dbSDimitry Andric   return false;
49005ffd83dbSDimitry Andric }
49015ffd83dbSDimitry Andric 
49025ffd83dbSDimitry Andric /// parseDirectiveLoc
49035ffd83dbSDimitry Andric /// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
49045ffd83dbSDimitry Andric ///                                [epilogue_begin] [is_stmt VALUE] [isa VALUE]
49055ffd83dbSDimitry Andric /// The first number is a file number, must have been previously assigned with
49065ffd83dbSDimitry Andric /// a .file directive, the second number is the line number and optionally the
49075ffd83dbSDimitry Andric /// third number is a column position (zero if not specified).  The remaining
49085ffd83dbSDimitry Andric /// optional items are .loc sub-directives.
parseDirectiveLoc()49095ffd83dbSDimitry Andric bool MasmParser::parseDirectiveLoc() {
49105ffd83dbSDimitry Andric   int64_t FileNumber = 0, LineNumber = 0;
49115ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
49125ffd83dbSDimitry Andric   if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
49135ffd83dbSDimitry Andric       check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc,
49145ffd83dbSDimitry Andric             "file number less than one in '.loc' directive") ||
49155ffd83dbSDimitry Andric       check(!getContext().isValidDwarfFileNumber(FileNumber), Loc,
49165ffd83dbSDimitry Andric             "unassigned file number in '.loc' directive"))
49175ffd83dbSDimitry Andric     return true;
49185ffd83dbSDimitry Andric 
49195ffd83dbSDimitry Andric   // optional
49205ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
49215ffd83dbSDimitry Andric     LineNumber = getTok().getIntVal();
49225ffd83dbSDimitry Andric     if (LineNumber < 0)
49235ffd83dbSDimitry Andric       return TokError("line number less than zero in '.loc' directive");
49245ffd83dbSDimitry Andric     Lex();
49255ffd83dbSDimitry Andric   }
49265ffd83dbSDimitry Andric 
49275ffd83dbSDimitry Andric   int64_t ColumnPos = 0;
49285ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
49295ffd83dbSDimitry Andric     ColumnPos = getTok().getIntVal();
49305ffd83dbSDimitry Andric     if (ColumnPos < 0)
49315ffd83dbSDimitry Andric       return TokError("column position less than zero in '.loc' directive");
49325ffd83dbSDimitry Andric     Lex();
49335ffd83dbSDimitry Andric   }
49345ffd83dbSDimitry Andric 
49355ffd83dbSDimitry Andric   auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags();
49365ffd83dbSDimitry Andric   unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT;
49375ffd83dbSDimitry Andric   unsigned Isa = 0;
49385ffd83dbSDimitry Andric   int64_t Discriminator = 0;
49395ffd83dbSDimitry Andric 
49405ffd83dbSDimitry Andric   auto parseLocOp = [&]() -> bool {
49415ffd83dbSDimitry Andric     StringRef Name;
49425ffd83dbSDimitry Andric     SMLoc Loc = getTok().getLoc();
49435ffd83dbSDimitry Andric     if (parseIdentifier(Name))
49445ffd83dbSDimitry Andric       return TokError("unexpected token in '.loc' directive");
49455ffd83dbSDimitry Andric 
49465ffd83dbSDimitry Andric     if (Name == "basic_block")
49475ffd83dbSDimitry Andric       Flags |= DWARF2_FLAG_BASIC_BLOCK;
49485ffd83dbSDimitry Andric     else if (Name == "prologue_end")
49495ffd83dbSDimitry Andric       Flags |= DWARF2_FLAG_PROLOGUE_END;
49505ffd83dbSDimitry Andric     else if (Name == "epilogue_begin")
49515ffd83dbSDimitry Andric       Flags |= DWARF2_FLAG_EPILOGUE_BEGIN;
49525ffd83dbSDimitry Andric     else if (Name == "is_stmt") {
49535ffd83dbSDimitry Andric       Loc = getTok().getLoc();
49545ffd83dbSDimitry Andric       const MCExpr *Value;
49555ffd83dbSDimitry Andric       if (parseExpression(Value))
49565ffd83dbSDimitry Andric         return true;
49575ffd83dbSDimitry Andric       // The expression must be the constant 0 or 1.
49585ffd83dbSDimitry Andric       if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
49595ffd83dbSDimitry Andric         int Value = MCE->getValue();
49605ffd83dbSDimitry Andric         if (Value == 0)
49615ffd83dbSDimitry Andric           Flags &= ~DWARF2_FLAG_IS_STMT;
49625ffd83dbSDimitry Andric         else if (Value == 1)
49635ffd83dbSDimitry Andric           Flags |= DWARF2_FLAG_IS_STMT;
49645ffd83dbSDimitry Andric         else
49655ffd83dbSDimitry Andric           return Error(Loc, "is_stmt value not 0 or 1");
49665ffd83dbSDimitry Andric       } else {
49675ffd83dbSDimitry Andric         return Error(Loc, "is_stmt value not the constant value of 0 or 1");
49685ffd83dbSDimitry Andric       }
49695ffd83dbSDimitry Andric     } else if (Name == "isa") {
49705ffd83dbSDimitry Andric       Loc = getTok().getLoc();
49715ffd83dbSDimitry Andric       const MCExpr *Value;
49725ffd83dbSDimitry Andric       if (parseExpression(Value))
49735ffd83dbSDimitry Andric         return true;
49745ffd83dbSDimitry Andric       // The expression must be a constant greater or equal to 0.
49755ffd83dbSDimitry Andric       if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
49765ffd83dbSDimitry Andric         int Value = MCE->getValue();
49775ffd83dbSDimitry Andric         if (Value < 0)
49785ffd83dbSDimitry Andric           return Error(Loc, "isa number less than zero");
49795ffd83dbSDimitry Andric         Isa = Value;
49805ffd83dbSDimitry Andric       } else {
49815ffd83dbSDimitry Andric         return Error(Loc, "isa number not a constant value");
49825ffd83dbSDimitry Andric       }
49835ffd83dbSDimitry Andric     } else if (Name == "discriminator") {
49845ffd83dbSDimitry Andric       if (parseAbsoluteExpression(Discriminator))
49855ffd83dbSDimitry Andric         return true;
49865ffd83dbSDimitry Andric     } else {
49875ffd83dbSDimitry Andric       return Error(Loc, "unknown sub-directive in '.loc' directive");
49885ffd83dbSDimitry Andric     }
49895ffd83dbSDimitry Andric     return false;
49905ffd83dbSDimitry Andric   };
49915ffd83dbSDimitry Andric 
49925ffd83dbSDimitry Andric   if (parseMany(parseLocOp, false /*hasComma*/))
49935ffd83dbSDimitry Andric     return true;
49945ffd83dbSDimitry Andric 
49955ffd83dbSDimitry Andric   getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
49965ffd83dbSDimitry Andric                                       Isa, Discriminator, StringRef());
49975ffd83dbSDimitry Andric 
49985ffd83dbSDimitry Andric   return false;
49995ffd83dbSDimitry Andric }
50005ffd83dbSDimitry Andric 
50015ffd83dbSDimitry Andric /// parseDirectiveStabs
50025ffd83dbSDimitry Andric /// ::= .stabs string, number, number, number
parseDirectiveStabs()50035ffd83dbSDimitry Andric bool MasmParser::parseDirectiveStabs() {
50045ffd83dbSDimitry Andric   return TokError("unsupported directive '.stabs'");
50055ffd83dbSDimitry Andric }
50065ffd83dbSDimitry Andric 
50075ffd83dbSDimitry Andric /// parseDirectiveCVFile
50085ffd83dbSDimitry Andric /// ::= .cv_file number filename [checksum] [checksumkind]
parseDirectiveCVFile()50095ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFile() {
50105ffd83dbSDimitry Andric   SMLoc FileNumberLoc = getTok().getLoc();
50115ffd83dbSDimitry Andric   int64_t FileNumber;
50125ffd83dbSDimitry Andric   std::string Filename;
50135ffd83dbSDimitry Andric   std::string Checksum;
50145ffd83dbSDimitry Andric   int64_t ChecksumKind = 0;
50155ffd83dbSDimitry Andric 
50165ffd83dbSDimitry Andric   if (parseIntToken(FileNumber,
50175ffd83dbSDimitry Andric                     "expected file number in '.cv_file' directive") ||
50185ffd83dbSDimitry Andric       check(FileNumber < 1, FileNumberLoc, "file number less than one") ||
50195ffd83dbSDimitry Andric       check(getTok().isNot(AsmToken::String),
50205ffd83dbSDimitry Andric             "unexpected token in '.cv_file' directive") ||
50215ffd83dbSDimitry Andric       parseEscapedString(Filename))
50225ffd83dbSDimitry Andric     return true;
50235ffd83dbSDimitry Andric   if (!parseOptionalToken(AsmToken::EndOfStatement)) {
50245ffd83dbSDimitry Andric     if (check(getTok().isNot(AsmToken::String),
50255ffd83dbSDimitry Andric               "unexpected token in '.cv_file' directive") ||
50265ffd83dbSDimitry Andric         parseEscapedString(Checksum) ||
50275ffd83dbSDimitry Andric         parseIntToken(ChecksumKind,
50285ffd83dbSDimitry Andric                       "expected checksum kind in '.cv_file' directive") ||
502981ad6265SDimitry Andric         parseEOL())
50305ffd83dbSDimitry Andric       return true;
50315ffd83dbSDimitry Andric   }
50325ffd83dbSDimitry Andric 
50335ffd83dbSDimitry Andric   Checksum = fromHex(Checksum);
50345ffd83dbSDimitry Andric   void *CKMem = Ctx.allocate(Checksum.size(), 1);
50355ffd83dbSDimitry Andric   memcpy(CKMem, Checksum.data(), Checksum.size());
50365ffd83dbSDimitry Andric   ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
50375ffd83dbSDimitry Andric                                     Checksum.size());
50385ffd83dbSDimitry Andric 
503981ad6265SDimitry Andric   if (!getStreamer().emitCVFileDirective(FileNumber, Filename, ChecksumAsBytes,
50405ffd83dbSDimitry Andric                                          static_cast<uint8_t>(ChecksumKind)))
50415ffd83dbSDimitry Andric     return Error(FileNumberLoc, "file number already allocated");
50425ffd83dbSDimitry Andric 
50435ffd83dbSDimitry Andric   return false;
50445ffd83dbSDimitry Andric }
50455ffd83dbSDimitry Andric 
parseCVFunctionId(int64_t & FunctionId,StringRef DirectiveName)50465ffd83dbSDimitry Andric bool MasmParser::parseCVFunctionId(int64_t &FunctionId,
50475ffd83dbSDimitry Andric                                    StringRef DirectiveName) {
50485ffd83dbSDimitry Andric   SMLoc Loc;
50495ffd83dbSDimitry Andric   return parseTokenLoc(Loc) ||
50505ffd83dbSDimitry Andric          parseIntToken(FunctionId, "expected function id in '" + DirectiveName +
50515ffd83dbSDimitry Andric                                        "' directive") ||
50525ffd83dbSDimitry Andric          check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,
50535ffd83dbSDimitry Andric                "expected function id within range [0, UINT_MAX)");
50545ffd83dbSDimitry Andric }
50555ffd83dbSDimitry Andric 
parseCVFileId(int64_t & FileNumber,StringRef DirectiveName)50565ffd83dbSDimitry Andric bool MasmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
50575ffd83dbSDimitry Andric   SMLoc Loc;
50585ffd83dbSDimitry Andric   return parseTokenLoc(Loc) ||
50595ffd83dbSDimitry Andric          parseIntToken(FileNumber, "expected integer in '" + DirectiveName +
50605ffd83dbSDimitry Andric                                        "' directive") ||
50615ffd83dbSDimitry Andric          check(FileNumber < 1, Loc, "file number less than one in '" +
50625ffd83dbSDimitry Andric                                         DirectiveName + "' directive") ||
50635ffd83dbSDimitry Andric          check(!getCVContext().isValidFileNumber(FileNumber), Loc,
50645ffd83dbSDimitry Andric                "unassigned file number in '" + DirectiveName + "' directive");
50655ffd83dbSDimitry Andric }
50665ffd83dbSDimitry Andric 
50675ffd83dbSDimitry Andric /// parseDirectiveCVFuncId
50685ffd83dbSDimitry Andric /// ::= .cv_func_id FunctionId
50695ffd83dbSDimitry Andric ///
50705ffd83dbSDimitry Andric /// Introduces a function ID that can be used with .cv_loc.
parseDirectiveCVFuncId()50715ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFuncId() {
50725ffd83dbSDimitry Andric   SMLoc FunctionIdLoc = getTok().getLoc();
50735ffd83dbSDimitry Andric   int64_t FunctionId;
50745ffd83dbSDimitry Andric 
507581ad6265SDimitry Andric   if (parseCVFunctionId(FunctionId, ".cv_func_id") || parseEOL())
50765ffd83dbSDimitry Andric     return true;
50775ffd83dbSDimitry Andric 
507881ad6265SDimitry Andric   if (!getStreamer().emitCVFuncIdDirective(FunctionId))
50795ffd83dbSDimitry Andric     return Error(FunctionIdLoc, "function id already allocated");
50805ffd83dbSDimitry Andric 
50815ffd83dbSDimitry Andric   return false;
50825ffd83dbSDimitry Andric }
50835ffd83dbSDimitry Andric 
50845ffd83dbSDimitry Andric /// parseDirectiveCVInlineSiteId
50855ffd83dbSDimitry Andric /// ::= .cv_inline_site_id FunctionId
50865ffd83dbSDimitry Andric ///         "within" IAFunc
50875ffd83dbSDimitry Andric ///         "inlined_at" IAFile IALine [IACol]
50885ffd83dbSDimitry Andric ///
50895ffd83dbSDimitry Andric /// Introduces a function ID that can be used with .cv_loc. Includes "inlined
50905ffd83dbSDimitry Andric /// at" source location information for use in the line table of the caller,
50915ffd83dbSDimitry Andric /// whether the caller is a real function or another inlined call site.
parseDirectiveCVInlineSiteId()50925ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVInlineSiteId() {
50935ffd83dbSDimitry Andric   SMLoc FunctionIdLoc = getTok().getLoc();
50945ffd83dbSDimitry Andric   int64_t FunctionId;
50955ffd83dbSDimitry Andric   int64_t IAFunc;
50965ffd83dbSDimitry Andric   int64_t IAFile;
50975ffd83dbSDimitry Andric   int64_t IALine;
50985ffd83dbSDimitry Andric   int64_t IACol = 0;
50995ffd83dbSDimitry Andric 
51005ffd83dbSDimitry Andric   // FunctionId
51015ffd83dbSDimitry Andric   if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))
51025ffd83dbSDimitry Andric     return true;
51035ffd83dbSDimitry Andric 
51045ffd83dbSDimitry Andric   // "within"
51055ffd83dbSDimitry Andric   if (check((getLexer().isNot(AsmToken::Identifier) ||
51065ffd83dbSDimitry Andric              getTok().getIdentifier() != "within"),
51075ffd83dbSDimitry Andric             "expected 'within' identifier in '.cv_inline_site_id' directive"))
51085ffd83dbSDimitry Andric     return true;
51095ffd83dbSDimitry Andric   Lex();
51105ffd83dbSDimitry Andric 
51115ffd83dbSDimitry Andric   // IAFunc
51125ffd83dbSDimitry Andric   if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))
51135ffd83dbSDimitry Andric     return true;
51145ffd83dbSDimitry Andric 
51155ffd83dbSDimitry Andric   // "inlined_at"
51165ffd83dbSDimitry Andric   if (check((getLexer().isNot(AsmToken::Identifier) ||
51175ffd83dbSDimitry Andric              getTok().getIdentifier() != "inlined_at"),
51185ffd83dbSDimitry Andric             "expected 'inlined_at' identifier in '.cv_inline_site_id' "
51195ffd83dbSDimitry Andric             "directive") )
51205ffd83dbSDimitry Andric     return true;
51215ffd83dbSDimitry Andric   Lex();
51225ffd83dbSDimitry Andric 
51235ffd83dbSDimitry Andric   // IAFile IALine
51245ffd83dbSDimitry Andric   if (parseCVFileId(IAFile, ".cv_inline_site_id") ||
51255ffd83dbSDimitry Andric       parseIntToken(IALine, "expected line number after 'inlined_at'"))
51265ffd83dbSDimitry Andric     return true;
51275ffd83dbSDimitry Andric 
51285ffd83dbSDimitry Andric   // [IACol]
51295ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
51305ffd83dbSDimitry Andric     IACol = getTok().getIntVal();
51315ffd83dbSDimitry Andric     Lex();
51325ffd83dbSDimitry Andric   }
51335ffd83dbSDimitry Andric 
513481ad6265SDimitry Andric   if (parseEOL())
51355ffd83dbSDimitry Andric     return true;
51365ffd83dbSDimitry Andric 
513781ad6265SDimitry Andric   if (!getStreamer().emitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
51385ffd83dbSDimitry Andric                                                  IALine, IACol, FunctionIdLoc))
51395ffd83dbSDimitry Andric     return Error(FunctionIdLoc, "function id already allocated");
51405ffd83dbSDimitry Andric 
51415ffd83dbSDimitry Andric   return false;
51425ffd83dbSDimitry Andric }
51435ffd83dbSDimitry Andric 
51445ffd83dbSDimitry Andric /// parseDirectiveCVLoc
51455ffd83dbSDimitry Andric /// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
51465ffd83dbSDimitry Andric ///                                [is_stmt VALUE]
51475ffd83dbSDimitry Andric /// The first number is a file number, must have been previously assigned with
51485ffd83dbSDimitry Andric /// a .file directive, the second number is the line number and optionally the
51495ffd83dbSDimitry Andric /// third number is a column position (zero if not specified).  The remaining
51505ffd83dbSDimitry Andric /// optional items are .loc sub-directives.
parseDirectiveCVLoc()51515ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVLoc() {
51525ffd83dbSDimitry Andric   SMLoc DirectiveLoc = getTok().getLoc();
51535ffd83dbSDimitry Andric   int64_t FunctionId, FileNumber;
51545ffd83dbSDimitry Andric   if (parseCVFunctionId(FunctionId, ".cv_loc") ||
51555ffd83dbSDimitry Andric       parseCVFileId(FileNumber, ".cv_loc"))
51565ffd83dbSDimitry Andric     return true;
51575ffd83dbSDimitry Andric 
51585ffd83dbSDimitry Andric   int64_t LineNumber = 0;
51595ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
51605ffd83dbSDimitry Andric     LineNumber = getTok().getIntVal();
51615ffd83dbSDimitry Andric     if (LineNumber < 0)
51625ffd83dbSDimitry Andric       return TokError("line number less than zero in '.cv_loc' directive");
51635ffd83dbSDimitry Andric     Lex();
51645ffd83dbSDimitry Andric   }
51655ffd83dbSDimitry Andric 
51665ffd83dbSDimitry Andric   int64_t ColumnPos = 0;
51675ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Integer)) {
51685ffd83dbSDimitry Andric     ColumnPos = getTok().getIntVal();
51695ffd83dbSDimitry Andric     if (ColumnPos < 0)
51705ffd83dbSDimitry Andric       return TokError("column position less than zero in '.cv_loc' directive");
51715ffd83dbSDimitry Andric     Lex();
51725ffd83dbSDimitry Andric   }
51735ffd83dbSDimitry Andric 
51745ffd83dbSDimitry Andric   bool PrologueEnd = false;
51755ffd83dbSDimitry Andric   uint64_t IsStmt = 0;
51765ffd83dbSDimitry Andric 
51775ffd83dbSDimitry Andric   auto parseOp = [&]() -> bool {
51785ffd83dbSDimitry Andric     StringRef Name;
51795ffd83dbSDimitry Andric     SMLoc Loc = getTok().getLoc();
51805ffd83dbSDimitry Andric     if (parseIdentifier(Name))
51815ffd83dbSDimitry Andric       return TokError("unexpected token in '.cv_loc' directive");
51825ffd83dbSDimitry Andric     if (Name == "prologue_end")
51835ffd83dbSDimitry Andric       PrologueEnd = true;
51845ffd83dbSDimitry Andric     else if (Name == "is_stmt") {
51855ffd83dbSDimitry Andric       Loc = getTok().getLoc();
51865ffd83dbSDimitry Andric       const MCExpr *Value;
51875ffd83dbSDimitry Andric       if (parseExpression(Value))
51885ffd83dbSDimitry Andric         return true;
51895ffd83dbSDimitry Andric       // The expression must be the constant 0 or 1.
51905ffd83dbSDimitry Andric       IsStmt = ~0ULL;
51915ffd83dbSDimitry Andric       if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
51925ffd83dbSDimitry Andric         IsStmt = MCE->getValue();
51935ffd83dbSDimitry Andric 
51945ffd83dbSDimitry Andric       if (IsStmt > 1)
51955ffd83dbSDimitry Andric         return Error(Loc, "is_stmt value not 0 or 1");
51965ffd83dbSDimitry Andric     } else {
51975ffd83dbSDimitry Andric       return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
51985ffd83dbSDimitry Andric     }
51995ffd83dbSDimitry Andric     return false;
52005ffd83dbSDimitry Andric   };
52015ffd83dbSDimitry Andric 
52025ffd83dbSDimitry Andric   if (parseMany(parseOp, false /*hasComma*/))
52035ffd83dbSDimitry Andric     return true;
52045ffd83dbSDimitry Andric 
52055ffd83dbSDimitry Andric   getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber,
52065ffd83dbSDimitry Andric                                    ColumnPos, PrologueEnd, IsStmt, StringRef(),
52075ffd83dbSDimitry Andric                                    DirectiveLoc);
52085ffd83dbSDimitry Andric   return false;
52095ffd83dbSDimitry Andric }
52105ffd83dbSDimitry Andric 
52115ffd83dbSDimitry Andric /// parseDirectiveCVLinetable
52125ffd83dbSDimitry Andric /// ::= .cv_linetable FunctionId, FnStart, FnEnd
parseDirectiveCVLinetable()52135ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVLinetable() {
52145ffd83dbSDimitry Andric   int64_t FunctionId;
52155ffd83dbSDimitry Andric   StringRef FnStartName, FnEndName;
52165ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
52175ffd83dbSDimitry Andric   if (parseCVFunctionId(FunctionId, ".cv_linetable") ||
52185ffd83dbSDimitry Andric       parseToken(AsmToken::Comma,
52195ffd83dbSDimitry Andric                  "unexpected token in '.cv_linetable' directive") ||
52205ffd83dbSDimitry Andric       parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
52215ffd83dbSDimitry Andric                                   "expected identifier in directive") ||
52225ffd83dbSDimitry Andric       parseToken(AsmToken::Comma,
52235ffd83dbSDimitry Andric                  "unexpected token in '.cv_linetable' directive") ||
52245ffd83dbSDimitry Andric       parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
52255ffd83dbSDimitry Andric                                   "expected identifier in directive"))
52265ffd83dbSDimitry Andric     return true;
52275ffd83dbSDimitry Andric 
52285ffd83dbSDimitry Andric   MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
52295ffd83dbSDimitry Andric   MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
52305ffd83dbSDimitry Andric 
52315ffd83dbSDimitry Andric   getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
52325ffd83dbSDimitry Andric   return false;
52335ffd83dbSDimitry Andric }
52345ffd83dbSDimitry Andric 
52355ffd83dbSDimitry Andric /// parseDirectiveCVInlineLinetable
52365ffd83dbSDimitry Andric /// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
parseDirectiveCVInlineLinetable()52375ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVInlineLinetable() {
52385ffd83dbSDimitry Andric   int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
52395ffd83dbSDimitry Andric   StringRef FnStartName, FnEndName;
52405ffd83dbSDimitry Andric   SMLoc Loc = getTok().getLoc();
52415ffd83dbSDimitry Andric   if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||
52425ffd83dbSDimitry Andric       parseTokenLoc(Loc) ||
52435ffd83dbSDimitry Andric       parseIntToken(
52445ffd83dbSDimitry Andric           SourceFileId,
52455ffd83dbSDimitry Andric           "expected SourceField in '.cv_inline_linetable' directive") ||
52465ffd83dbSDimitry Andric       check(SourceFileId <= 0, Loc,
52475ffd83dbSDimitry Andric             "File id less than zero in '.cv_inline_linetable' directive") ||
52485ffd83dbSDimitry Andric       parseTokenLoc(Loc) ||
52495ffd83dbSDimitry Andric       parseIntToken(
52505ffd83dbSDimitry Andric           SourceLineNum,
52515ffd83dbSDimitry Andric           "expected SourceLineNum in '.cv_inline_linetable' directive") ||
52525ffd83dbSDimitry Andric       check(SourceLineNum < 0, Loc,
52535ffd83dbSDimitry Andric             "Line number less than zero in '.cv_inline_linetable' directive") ||
52545ffd83dbSDimitry Andric       parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
52555ffd83dbSDimitry Andric                                   "expected identifier in directive") ||
52565ffd83dbSDimitry Andric       parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc,
52575ffd83dbSDimitry Andric                                   "expected identifier in directive"))
52585ffd83dbSDimitry Andric     return true;
52595ffd83dbSDimitry Andric 
526081ad6265SDimitry Andric   if (parseEOL())
52615ffd83dbSDimitry Andric     return true;
52625ffd83dbSDimitry Andric 
52635ffd83dbSDimitry Andric   MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
52645ffd83dbSDimitry Andric   MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
52655ffd83dbSDimitry Andric   getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
52665ffd83dbSDimitry Andric                                                SourceLineNum, FnStartSym,
52675ffd83dbSDimitry Andric                                                FnEndSym);
52685ffd83dbSDimitry Andric   return false;
52695ffd83dbSDimitry Andric }
52705ffd83dbSDimitry Andric 
initializeCVDefRangeTypeMap()52715ffd83dbSDimitry Andric void MasmParser::initializeCVDefRangeTypeMap() {
52725ffd83dbSDimitry Andric   CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
52735ffd83dbSDimitry Andric   CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
52745ffd83dbSDimitry Andric   CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
52755ffd83dbSDimitry Andric   CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL;
52765ffd83dbSDimitry Andric }
52775ffd83dbSDimitry Andric 
52785ffd83dbSDimitry Andric /// parseDirectiveCVDefRange
52795ffd83dbSDimitry Andric /// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
parseDirectiveCVDefRange()52805ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVDefRange() {
52815ffd83dbSDimitry Andric   SMLoc Loc;
52825ffd83dbSDimitry Andric   std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
52835ffd83dbSDimitry Andric   while (getLexer().is(AsmToken::Identifier)) {
52845ffd83dbSDimitry Andric     Loc = getLexer().getLoc();
52855ffd83dbSDimitry Andric     StringRef GapStartName;
52865ffd83dbSDimitry Andric     if (parseIdentifier(GapStartName))
52875ffd83dbSDimitry Andric       return Error(Loc, "expected identifier in directive");
52885ffd83dbSDimitry Andric     MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
52895ffd83dbSDimitry Andric 
52905ffd83dbSDimitry Andric     Loc = getLexer().getLoc();
52915ffd83dbSDimitry Andric     StringRef GapEndName;
52925ffd83dbSDimitry Andric     if (parseIdentifier(GapEndName))
52935ffd83dbSDimitry Andric       return Error(Loc, "expected identifier in directive");
52945ffd83dbSDimitry Andric     MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
52955ffd83dbSDimitry Andric 
52965ffd83dbSDimitry Andric     Ranges.push_back({GapStartSym, GapEndSym});
52975ffd83dbSDimitry Andric   }
52985ffd83dbSDimitry Andric 
52995ffd83dbSDimitry Andric   StringRef CVDefRangeTypeStr;
53005ffd83dbSDimitry Andric   if (parseToken(
53015ffd83dbSDimitry Andric           AsmToken::Comma,
53025ffd83dbSDimitry Andric           "expected comma before def_range type in .cv_def_range directive") ||
53035ffd83dbSDimitry Andric       parseIdentifier(CVDefRangeTypeStr))
53045ffd83dbSDimitry Andric     return Error(Loc, "expected def_range type in directive");
53055ffd83dbSDimitry Andric 
53065ffd83dbSDimitry Andric   StringMap<CVDefRangeType>::const_iterator CVTypeIt =
53075ffd83dbSDimitry Andric       CVDefRangeTypeMap.find(CVDefRangeTypeStr);
53085ffd83dbSDimitry Andric   CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end())
53095ffd83dbSDimitry Andric                                 ? CVDR_DEFRANGE
53105ffd83dbSDimitry Andric                                 : CVTypeIt->getValue();
53115ffd83dbSDimitry Andric   switch (CVDRType) {
53125ffd83dbSDimitry Andric   case CVDR_DEFRANGE_REGISTER: {
53135ffd83dbSDimitry Andric     int64_t DRRegister;
53145ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma, "expected comma before register number in "
53155ffd83dbSDimitry Andric                                     ".cv_def_range directive") ||
53165ffd83dbSDimitry Andric         parseAbsoluteExpression(DRRegister))
53175ffd83dbSDimitry Andric       return Error(Loc, "expected register number");
53185ffd83dbSDimitry Andric 
53195ffd83dbSDimitry Andric     codeview::DefRangeRegisterHeader DRHdr;
53205ffd83dbSDimitry Andric     DRHdr.Register = DRRegister;
53215ffd83dbSDimitry Andric     DRHdr.MayHaveNoName = 0;
53225ffd83dbSDimitry Andric     getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
53235ffd83dbSDimitry Andric     break;
53245ffd83dbSDimitry Andric   }
53255ffd83dbSDimitry Andric   case CVDR_DEFRANGE_FRAMEPOINTER_REL: {
53265ffd83dbSDimitry Andric     int64_t DROffset;
53275ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma,
53285ffd83dbSDimitry Andric                    "expected comma before offset in .cv_def_range directive") ||
53295ffd83dbSDimitry Andric         parseAbsoluteExpression(DROffset))
53305ffd83dbSDimitry Andric       return Error(Loc, "expected offset value");
53315ffd83dbSDimitry Andric 
53325ffd83dbSDimitry Andric     codeview::DefRangeFramePointerRelHeader DRHdr;
53335ffd83dbSDimitry Andric     DRHdr.Offset = DROffset;
53345ffd83dbSDimitry Andric     getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
53355ffd83dbSDimitry Andric     break;
53365ffd83dbSDimitry Andric   }
53375ffd83dbSDimitry Andric   case CVDR_DEFRANGE_SUBFIELD_REGISTER: {
53385ffd83dbSDimitry Andric     int64_t DRRegister;
53395ffd83dbSDimitry Andric     int64_t DROffsetInParent;
53405ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma, "expected comma before register number in "
53415ffd83dbSDimitry Andric                                     ".cv_def_range directive") ||
53425ffd83dbSDimitry Andric         parseAbsoluteExpression(DRRegister))
53435ffd83dbSDimitry Andric       return Error(Loc, "expected register number");
53445ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma,
53455ffd83dbSDimitry Andric                    "expected comma before offset in .cv_def_range directive") ||
53465ffd83dbSDimitry Andric         parseAbsoluteExpression(DROffsetInParent))
53475ffd83dbSDimitry Andric       return Error(Loc, "expected offset value");
53485ffd83dbSDimitry Andric 
53495ffd83dbSDimitry Andric     codeview::DefRangeSubfieldRegisterHeader DRHdr;
53505ffd83dbSDimitry Andric     DRHdr.Register = DRRegister;
53515ffd83dbSDimitry Andric     DRHdr.MayHaveNoName = 0;
53525ffd83dbSDimitry Andric     DRHdr.OffsetInParent = DROffsetInParent;
53535ffd83dbSDimitry Andric     getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
53545ffd83dbSDimitry Andric     break;
53555ffd83dbSDimitry Andric   }
53565ffd83dbSDimitry Andric   case CVDR_DEFRANGE_REGISTER_REL: {
53575ffd83dbSDimitry Andric     int64_t DRRegister;
53585ffd83dbSDimitry Andric     int64_t DRFlags;
53595ffd83dbSDimitry Andric     int64_t DRBasePointerOffset;
53605ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma, "expected comma before register number in "
53615ffd83dbSDimitry Andric                                     ".cv_def_range directive") ||
53625ffd83dbSDimitry Andric         parseAbsoluteExpression(DRRegister))
53635ffd83dbSDimitry Andric       return Error(Loc, "expected register value");
53645ffd83dbSDimitry Andric     if (parseToken(
53655ffd83dbSDimitry Andric             AsmToken::Comma,
53665ffd83dbSDimitry Andric             "expected comma before flag value in .cv_def_range directive") ||
53675ffd83dbSDimitry Andric         parseAbsoluteExpression(DRFlags))
53685ffd83dbSDimitry Andric       return Error(Loc, "expected flag value");
53695ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma, "expected comma before base pointer offset "
53705ffd83dbSDimitry Andric                                     "in .cv_def_range directive") ||
53715ffd83dbSDimitry Andric         parseAbsoluteExpression(DRBasePointerOffset))
53725ffd83dbSDimitry Andric       return Error(Loc, "expected base pointer offset value");
53735ffd83dbSDimitry Andric 
53745ffd83dbSDimitry Andric     codeview::DefRangeRegisterRelHeader DRHdr;
53755ffd83dbSDimitry Andric     DRHdr.Register = DRRegister;
53765ffd83dbSDimitry Andric     DRHdr.Flags = DRFlags;
53775ffd83dbSDimitry Andric     DRHdr.BasePointerOffset = DRBasePointerOffset;
53785ffd83dbSDimitry Andric     getStreamer().emitCVDefRangeDirective(Ranges, DRHdr);
53795ffd83dbSDimitry Andric     break;
53805ffd83dbSDimitry Andric   }
53815ffd83dbSDimitry Andric   default:
53825ffd83dbSDimitry Andric     return Error(Loc, "unexpected def_range type in .cv_def_range directive");
53835ffd83dbSDimitry Andric   }
53845ffd83dbSDimitry Andric   return true;
53855ffd83dbSDimitry Andric }
53865ffd83dbSDimitry Andric 
53875ffd83dbSDimitry Andric /// parseDirectiveCVString
53885ffd83dbSDimitry Andric /// ::= .cv_stringtable "string"
parseDirectiveCVString()53895ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVString() {
53905ffd83dbSDimitry Andric   std::string Data;
53915ffd83dbSDimitry Andric   if (checkForValidSection() || parseEscapedString(Data))
53925ffd83dbSDimitry Andric     return addErrorSuffix(" in '.cv_string' directive");
53935ffd83dbSDimitry Andric 
53945ffd83dbSDimitry Andric   // Put the string in the table and emit the offset.
53955ffd83dbSDimitry Andric   std::pair<StringRef, unsigned> Insertion =
53965ffd83dbSDimitry Andric       getCVContext().addToStringTable(Data);
53975ffd83dbSDimitry Andric   getStreamer().emitIntValue(Insertion.second, 4);
53985ffd83dbSDimitry Andric   return false;
53995ffd83dbSDimitry Andric }
54005ffd83dbSDimitry Andric 
54015ffd83dbSDimitry Andric /// parseDirectiveCVStringTable
54025ffd83dbSDimitry Andric /// ::= .cv_stringtable
parseDirectiveCVStringTable()54035ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVStringTable() {
54045ffd83dbSDimitry Andric   getStreamer().emitCVStringTableDirective();
54055ffd83dbSDimitry Andric   return false;
54065ffd83dbSDimitry Andric }
54075ffd83dbSDimitry Andric 
54085ffd83dbSDimitry Andric /// parseDirectiveCVFileChecksums
54095ffd83dbSDimitry Andric /// ::= .cv_filechecksums
parseDirectiveCVFileChecksums()54105ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFileChecksums() {
54115ffd83dbSDimitry Andric   getStreamer().emitCVFileChecksumsDirective();
54125ffd83dbSDimitry Andric   return false;
54135ffd83dbSDimitry Andric }
54145ffd83dbSDimitry Andric 
54155ffd83dbSDimitry Andric /// parseDirectiveCVFileChecksumOffset
54165ffd83dbSDimitry Andric /// ::= .cv_filechecksumoffset fileno
parseDirectiveCVFileChecksumOffset()54175ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFileChecksumOffset() {
54185ffd83dbSDimitry Andric   int64_t FileNo;
54195ffd83dbSDimitry Andric   if (parseIntToken(FileNo, "expected identifier in directive"))
54205ffd83dbSDimitry Andric     return true;
542181ad6265SDimitry Andric   if (parseEOL())
54225ffd83dbSDimitry Andric     return true;
54235ffd83dbSDimitry Andric   getStreamer().emitCVFileChecksumOffsetDirective(FileNo);
54245ffd83dbSDimitry Andric   return false;
54255ffd83dbSDimitry Andric }
54265ffd83dbSDimitry Andric 
54275ffd83dbSDimitry Andric /// parseDirectiveCVFPOData
54285ffd83dbSDimitry Andric /// ::= .cv_fpo_data procsym
parseDirectiveCVFPOData()54295ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFPOData() {
54305ffd83dbSDimitry Andric   SMLoc DirLoc = getLexer().getLoc();
54315ffd83dbSDimitry Andric   StringRef ProcName;
54325ffd83dbSDimitry Andric   if (parseIdentifier(ProcName))
54335ffd83dbSDimitry Andric     return TokError("expected symbol name");
54345ffd83dbSDimitry Andric   if (parseEOL("unexpected tokens"))
54355ffd83dbSDimitry Andric     return addErrorSuffix(" in '.cv_fpo_data' directive");
54365ffd83dbSDimitry Andric   MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
543781ad6265SDimitry Andric   getStreamer().emitCVFPOData(ProcSym, DirLoc);
54385ffd83dbSDimitry Andric   return false;
54395ffd83dbSDimitry Andric }
54405ffd83dbSDimitry Andric 
54415ffd83dbSDimitry Andric /// parseDirectiveCFISections
54425ffd83dbSDimitry Andric /// ::= .cfi_sections section [, section]
parseDirectiveCFISections()54435ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFISections() {
54445ffd83dbSDimitry Andric   StringRef Name;
54455ffd83dbSDimitry Andric   bool EH = false;
54465ffd83dbSDimitry Andric   bool Debug = false;
54475ffd83dbSDimitry Andric 
54485ffd83dbSDimitry Andric   if (parseIdentifier(Name))
54495ffd83dbSDimitry Andric     return TokError("Expected an identifier");
54505ffd83dbSDimitry Andric 
54515ffd83dbSDimitry Andric   if (Name == ".eh_frame")
54525ffd83dbSDimitry Andric     EH = true;
54535ffd83dbSDimitry Andric   else if (Name == ".debug_frame")
54545ffd83dbSDimitry Andric     Debug = true;
54555ffd83dbSDimitry Andric 
54565ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Comma)) {
54575ffd83dbSDimitry Andric     Lex();
54585ffd83dbSDimitry Andric 
54595ffd83dbSDimitry Andric     if (parseIdentifier(Name))
54605ffd83dbSDimitry Andric       return TokError("Expected an identifier");
54615ffd83dbSDimitry Andric 
54625ffd83dbSDimitry Andric     if (Name == ".eh_frame")
54635ffd83dbSDimitry Andric       EH = true;
54645ffd83dbSDimitry Andric     else if (Name == ".debug_frame")
54655ffd83dbSDimitry Andric       Debug = true;
54665ffd83dbSDimitry Andric   }
54675ffd83dbSDimitry Andric 
54685ffd83dbSDimitry Andric   getStreamer().emitCFISections(EH, Debug);
54695ffd83dbSDimitry Andric   return false;
54705ffd83dbSDimitry Andric }
54715ffd83dbSDimitry Andric 
54725ffd83dbSDimitry Andric /// parseDirectiveCFIStartProc
54735ffd83dbSDimitry Andric /// ::= .cfi_startproc [simple]
parseDirectiveCFIStartProc()54745ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIStartProc() {
54755ffd83dbSDimitry Andric   StringRef Simple;
54765ffd83dbSDimitry Andric   if (!parseOptionalToken(AsmToken::EndOfStatement)) {
54775ffd83dbSDimitry Andric     if (check(parseIdentifier(Simple) || Simple != "simple",
54785ffd83dbSDimitry Andric               "unexpected token") ||
547906c3fb27SDimitry Andric         parseEOL())
54805ffd83dbSDimitry Andric       return addErrorSuffix(" in '.cfi_startproc' directive");
54815ffd83dbSDimitry Andric   }
54825ffd83dbSDimitry Andric 
54835ffd83dbSDimitry Andric   // TODO(kristina): Deal with a corner case of incorrect diagnostic context
54845ffd83dbSDimitry Andric   // being produced if this directive is emitted as part of preprocessor macro
54855ffd83dbSDimitry Andric   // expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
54865ffd83dbSDimitry Andric   // Tools like llvm-mc on the other hand are not affected by it, and report
54875ffd83dbSDimitry Andric   // correct context information.
54885ffd83dbSDimitry Andric   getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc());
54895ffd83dbSDimitry Andric   return false;
54905ffd83dbSDimitry Andric }
54915ffd83dbSDimitry Andric 
54925ffd83dbSDimitry Andric /// parseDirectiveCFIEndProc
54935ffd83dbSDimitry Andric /// ::= .cfi_endproc
parseDirectiveCFIEndProc()54945ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIEndProc() {
54955ffd83dbSDimitry Andric   getStreamer().emitCFIEndProc();
54965ffd83dbSDimitry Andric   return false;
54975ffd83dbSDimitry Andric }
54985ffd83dbSDimitry Andric 
54995ffd83dbSDimitry Andric /// parse register name or number.
parseRegisterOrRegisterNumber(int64_t & Register,SMLoc DirectiveLoc)55005ffd83dbSDimitry Andric bool MasmParser::parseRegisterOrRegisterNumber(int64_t &Register,
55015ffd83dbSDimitry Andric                                                SMLoc DirectiveLoc) {
5502bdd1243dSDimitry Andric   MCRegister RegNo;
55035ffd83dbSDimitry Andric 
55045ffd83dbSDimitry Andric   if (getLexer().isNot(AsmToken::Integer)) {
5505bdd1243dSDimitry Andric     if (getTargetParser().parseRegister(RegNo, DirectiveLoc, DirectiveLoc))
55065ffd83dbSDimitry Andric       return true;
55075ffd83dbSDimitry Andric     Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true);
55085ffd83dbSDimitry Andric   } else
55095ffd83dbSDimitry Andric     return parseAbsoluteExpression(Register);
55105ffd83dbSDimitry Andric 
55115ffd83dbSDimitry Andric   return false;
55125ffd83dbSDimitry Andric }
55135ffd83dbSDimitry Andric 
55145ffd83dbSDimitry Andric /// parseDirectiveCFIDefCfa
55155ffd83dbSDimitry Andric /// ::= .cfi_def_cfa register,  offset
parseDirectiveCFIDefCfa(SMLoc DirectiveLoc)55165ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
55175ffd83dbSDimitry Andric   int64_t Register = 0, Offset = 0;
55185ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
55195ffd83dbSDimitry Andric       parseToken(AsmToken::Comma, "unexpected token in directive") ||
55205ffd83dbSDimitry Andric       parseAbsoluteExpression(Offset))
55215ffd83dbSDimitry Andric     return true;
55225ffd83dbSDimitry Andric 
55235ffd83dbSDimitry Andric   getStreamer().emitCFIDefCfa(Register, Offset);
55245ffd83dbSDimitry Andric   return false;
55255ffd83dbSDimitry Andric }
55265ffd83dbSDimitry Andric 
55275ffd83dbSDimitry Andric /// parseDirectiveCFIDefCfaOffset
55285ffd83dbSDimitry Andric /// ::= .cfi_def_cfa_offset offset
parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc)552906c3fb27SDimitry Andric bool MasmParser::parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc) {
55305ffd83dbSDimitry Andric   int64_t Offset = 0;
55315ffd83dbSDimitry Andric   if (parseAbsoluteExpression(Offset))
55325ffd83dbSDimitry Andric     return true;
55335ffd83dbSDimitry Andric 
553406c3fb27SDimitry Andric   getStreamer().emitCFIDefCfaOffset(Offset, DirectiveLoc);
55355ffd83dbSDimitry Andric   return false;
55365ffd83dbSDimitry Andric }
55375ffd83dbSDimitry Andric 
55385ffd83dbSDimitry Andric /// parseDirectiveCFIRegister
55395ffd83dbSDimitry Andric /// ::= .cfi_register register, register
parseDirectiveCFIRegister(SMLoc DirectiveLoc)55405ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
55415ffd83dbSDimitry Andric   int64_t Register1 = 0, Register2 = 0;
55425ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) ||
55435ffd83dbSDimitry Andric       parseToken(AsmToken::Comma, "unexpected token in directive") ||
55445ffd83dbSDimitry Andric       parseRegisterOrRegisterNumber(Register2, DirectiveLoc))
55455ffd83dbSDimitry Andric     return true;
55465ffd83dbSDimitry Andric 
554706c3fb27SDimitry Andric   getStreamer().emitCFIRegister(Register1, Register2, DirectiveLoc);
55485ffd83dbSDimitry Andric   return false;
55495ffd83dbSDimitry Andric }
55505ffd83dbSDimitry Andric 
55515ffd83dbSDimitry Andric /// parseDirectiveCFIWindowSave
55525ffd83dbSDimitry Andric /// ::= .cfi_window_save
parseDirectiveCFIWindowSave(SMLoc DirectiveLoc)555306c3fb27SDimitry Andric bool MasmParser::parseDirectiveCFIWindowSave(SMLoc DirectiveLoc) {
555406c3fb27SDimitry Andric   getStreamer().emitCFIWindowSave(DirectiveLoc);
55555ffd83dbSDimitry Andric   return false;
55565ffd83dbSDimitry Andric }
55575ffd83dbSDimitry Andric 
55585ffd83dbSDimitry Andric /// parseDirectiveCFIAdjustCfaOffset
55595ffd83dbSDimitry Andric /// ::= .cfi_adjust_cfa_offset adjustment
parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc)556006c3fb27SDimitry Andric bool MasmParser::parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc) {
55615ffd83dbSDimitry Andric   int64_t Adjustment = 0;
55625ffd83dbSDimitry Andric   if (parseAbsoluteExpression(Adjustment))
55635ffd83dbSDimitry Andric     return true;
55645ffd83dbSDimitry Andric 
556506c3fb27SDimitry Andric   getStreamer().emitCFIAdjustCfaOffset(Adjustment, DirectiveLoc);
55665ffd83dbSDimitry Andric   return false;
55675ffd83dbSDimitry Andric }
55685ffd83dbSDimitry Andric 
55695ffd83dbSDimitry Andric /// parseDirectiveCFIDefCfaRegister
55705ffd83dbSDimitry Andric /// ::= .cfi_def_cfa_register register
parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc)55715ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
55725ffd83dbSDimitry Andric   int64_t Register = 0;
55735ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
55745ffd83dbSDimitry Andric     return true;
55755ffd83dbSDimitry Andric 
55765ffd83dbSDimitry Andric   getStreamer().emitCFIDefCfaRegister(Register);
55775ffd83dbSDimitry Andric   return false;
55785ffd83dbSDimitry Andric }
55795ffd83dbSDimitry Andric 
55805ffd83dbSDimitry Andric /// parseDirectiveCFIOffset
55815ffd83dbSDimitry Andric /// ::= .cfi_offset register, offset
parseDirectiveCFIOffset(SMLoc DirectiveLoc)55825ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
55835ffd83dbSDimitry Andric   int64_t Register = 0;
55845ffd83dbSDimitry Andric   int64_t Offset = 0;
55855ffd83dbSDimitry Andric 
55865ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
55875ffd83dbSDimitry Andric       parseToken(AsmToken::Comma, "unexpected token in directive") ||
55885ffd83dbSDimitry Andric       parseAbsoluteExpression(Offset))
55895ffd83dbSDimitry Andric     return true;
55905ffd83dbSDimitry Andric 
55915ffd83dbSDimitry Andric   getStreamer().emitCFIOffset(Register, Offset);
55925ffd83dbSDimitry Andric   return false;
55935ffd83dbSDimitry Andric }
55945ffd83dbSDimitry Andric 
55955ffd83dbSDimitry Andric /// parseDirectiveCFIRelOffset
55965ffd83dbSDimitry Andric /// ::= .cfi_rel_offset register, offset
parseDirectiveCFIRelOffset(SMLoc DirectiveLoc)55975ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
55985ffd83dbSDimitry Andric   int64_t Register = 0, Offset = 0;
55995ffd83dbSDimitry Andric 
56005ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
56015ffd83dbSDimitry Andric       parseToken(AsmToken::Comma, "unexpected token in directive") ||
56025ffd83dbSDimitry Andric       parseAbsoluteExpression(Offset))
56035ffd83dbSDimitry Andric     return true;
56045ffd83dbSDimitry Andric 
560506c3fb27SDimitry Andric   getStreamer().emitCFIRelOffset(Register, Offset, DirectiveLoc);
56065ffd83dbSDimitry Andric   return false;
56075ffd83dbSDimitry Andric }
56085ffd83dbSDimitry Andric 
isValidEncoding(int64_t Encoding)56095ffd83dbSDimitry Andric static bool isValidEncoding(int64_t Encoding) {
56105ffd83dbSDimitry Andric   if (Encoding & ~0xff)
56115ffd83dbSDimitry Andric     return false;
56125ffd83dbSDimitry Andric 
56135ffd83dbSDimitry Andric   if (Encoding == dwarf::DW_EH_PE_omit)
56145ffd83dbSDimitry Andric     return true;
56155ffd83dbSDimitry Andric 
56165ffd83dbSDimitry Andric   const unsigned Format = Encoding & 0xf;
56175ffd83dbSDimitry Andric   if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
56185ffd83dbSDimitry Andric       Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
56195ffd83dbSDimitry Andric       Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
56205ffd83dbSDimitry Andric       Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
56215ffd83dbSDimitry Andric     return false;
56225ffd83dbSDimitry Andric 
56235ffd83dbSDimitry Andric   const unsigned Application = Encoding & 0x70;
56245ffd83dbSDimitry Andric   if (Application != dwarf::DW_EH_PE_absptr &&
56255ffd83dbSDimitry Andric       Application != dwarf::DW_EH_PE_pcrel)
56265ffd83dbSDimitry Andric     return false;
56275ffd83dbSDimitry Andric 
56285ffd83dbSDimitry Andric   return true;
56295ffd83dbSDimitry Andric }
56305ffd83dbSDimitry Andric 
56315ffd83dbSDimitry Andric /// parseDirectiveCFIPersonalityOrLsda
56325ffd83dbSDimitry Andric /// IsPersonality true for cfi_personality, false for cfi_lsda
56335ffd83dbSDimitry Andric /// ::= .cfi_personality encoding, [symbol_name]
56345ffd83dbSDimitry Andric /// ::= .cfi_lsda encoding, [symbol_name]
parseDirectiveCFIPersonalityOrLsda(bool IsPersonality)56355ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
56365ffd83dbSDimitry Andric   int64_t Encoding = 0;
56375ffd83dbSDimitry Andric   if (parseAbsoluteExpression(Encoding))
56385ffd83dbSDimitry Andric     return true;
56395ffd83dbSDimitry Andric   if (Encoding == dwarf::DW_EH_PE_omit)
56405ffd83dbSDimitry Andric     return false;
56415ffd83dbSDimitry Andric 
56425ffd83dbSDimitry Andric   StringRef Name;
56435ffd83dbSDimitry Andric   if (check(!isValidEncoding(Encoding), "unsupported encoding.") ||
56445ffd83dbSDimitry Andric       parseToken(AsmToken::Comma, "unexpected token in directive") ||
56455ffd83dbSDimitry Andric       check(parseIdentifier(Name), "expected identifier in directive"))
56465ffd83dbSDimitry Andric     return true;
56475ffd83dbSDimitry Andric 
56485ffd83dbSDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
56495ffd83dbSDimitry Andric 
56505ffd83dbSDimitry Andric   if (IsPersonality)
56515ffd83dbSDimitry Andric     getStreamer().emitCFIPersonality(Sym, Encoding);
56525ffd83dbSDimitry Andric   else
56535ffd83dbSDimitry Andric     getStreamer().emitCFILsda(Sym, Encoding);
56545ffd83dbSDimitry Andric   return false;
56555ffd83dbSDimitry Andric }
56565ffd83dbSDimitry Andric 
56575ffd83dbSDimitry Andric /// parseDirectiveCFIRememberState
56585ffd83dbSDimitry Andric /// ::= .cfi_remember_state
parseDirectiveCFIRememberState(SMLoc DirectiveLoc)565906c3fb27SDimitry Andric bool MasmParser::parseDirectiveCFIRememberState(SMLoc DirectiveLoc) {
566006c3fb27SDimitry Andric   getStreamer().emitCFIRememberState(DirectiveLoc);
56615ffd83dbSDimitry Andric   return false;
56625ffd83dbSDimitry Andric }
56635ffd83dbSDimitry Andric 
56645ffd83dbSDimitry Andric /// parseDirectiveCFIRestoreState
56655ffd83dbSDimitry Andric /// ::= .cfi_remember_state
parseDirectiveCFIRestoreState(SMLoc DirectiveLoc)566606c3fb27SDimitry Andric bool MasmParser::parseDirectiveCFIRestoreState(SMLoc DirectiveLoc) {
566706c3fb27SDimitry Andric   getStreamer().emitCFIRestoreState(DirectiveLoc);
56685ffd83dbSDimitry Andric   return false;
56695ffd83dbSDimitry Andric }
56705ffd83dbSDimitry Andric 
56715ffd83dbSDimitry Andric /// parseDirectiveCFISameValue
56725ffd83dbSDimitry Andric /// ::= .cfi_same_value register
parseDirectiveCFISameValue(SMLoc DirectiveLoc)56735ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
56745ffd83dbSDimitry Andric   int64_t Register = 0;
56755ffd83dbSDimitry Andric 
56765ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
56775ffd83dbSDimitry Andric     return true;
56785ffd83dbSDimitry Andric 
567906c3fb27SDimitry Andric   getStreamer().emitCFISameValue(Register, DirectiveLoc);
56805ffd83dbSDimitry Andric   return false;
56815ffd83dbSDimitry Andric }
56825ffd83dbSDimitry Andric 
56835ffd83dbSDimitry Andric /// parseDirectiveCFIRestore
56845ffd83dbSDimitry Andric /// ::= .cfi_restore register
parseDirectiveCFIRestore(SMLoc DirectiveLoc)56855ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
56865ffd83dbSDimitry Andric   int64_t Register = 0;
56875ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
56885ffd83dbSDimitry Andric     return true;
56895ffd83dbSDimitry Andric 
56905ffd83dbSDimitry Andric   getStreamer().emitCFIRestore(Register);
56915ffd83dbSDimitry Andric   return false;
56925ffd83dbSDimitry Andric }
56935ffd83dbSDimitry Andric 
56945ffd83dbSDimitry Andric /// parseDirectiveCFIEscape
56955ffd83dbSDimitry Andric /// ::= .cfi_escape expression[,...]
parseDirectiveCFIEscape(SMLoc DirectiveLoc)569606c3fb27SDimitry Andric bool MasmParser::parseDirectiveCFIEscape(SMLoc DirectiveLoc) {
56975ffd83dbSDimitry Andric   std::string Values;
56985ffd83dbSDimitry Andric   int64_t CurrValue;
56995ffd83dbSDimitry Andric   if (parseAbsoluteExpression(CurrValue))
57005ffd83dbSDimitry Andric     return true;
57015ffd83dbSDimitry Andric 
57025ffd83dbSDimitry Andric   Values.push_back((uint8_t)CurrValue);
57035ffd83dbSDimitry Andric 
57045ffd83dbSDimitry Andric   while (getLexer().is(AsmToken::Comma)) {
57055ffd83dbSDimitry Andric     Lex();
57065ffd83dbSDimitry Andric 
57075ffd83dbSDimitry Andric     if (parseAbsoluteExpression(CurrValue))
57085ffd83dbSDimitry Andric       return true;
57095ffd83dbSDimitry Andric 
57105ffd83dbSDimitry Andric     Values.push_back((uint8_t)CurrValue);
57115ffd83dbSDimitry Andric   }
57125ffd83dbSDimitry Andric 
571306c3fb27SDimitry Andric   getStreamer().emitCFIEscape(Values, DirectiveLoc);
57145ffd83dbSDimitry Andric   return false;
57155ffd83dbSDimitry Andric }
57165ffd83dbSDimitry Andric 
57175ffd83dbSDimitry Andric /// parseDirectiveCFIReturnColumn
57185ffd83dbSDimitry Andric /// ::= .cfi_return_column register
parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc)57195ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
57205ffd83dbSDimitry Andric   int64_t Register = 0;
57215ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
57225ffd83dbSDimitry Andric     return true;
57235ffd83dbSDimitry Andric   getStreamer().emitCFIReturnColumn(Register);
57245ffd83dbSDimitry Andric   return false;
57255ffd83dbSDimitry Andric }
57265ffd83dbSDimitry Andric 
57275ffd83dbSDimitry Andric /// parseDirectiveCFISignalFrame
57285ffd83dbSDimitry Andric /// ::= .cfi_signal_frame
parseDirectiveCFISignalFrame()57295ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFISignalFrame() {
573081ad6265SDimitry Andric   if (parseEOL())
57315ffd83dbSDimitry Andric     return true;
57325ffd83dbSDimitry Andric 
57335ffd83dbSDimitry Andric   getStreamer().emitCFISignalFrame();
57345ffd83dbSDimitry Andric   return false;
57355ffd83dbSDimitry Andric }
57365ffd83dbSDimitry Andric 
57375ffd83dbSDimitry Andric /// parseDirectiveCFIUndefined
57385ffd83dbSDimitry Andric /// ::= .cfi_undefined register
parseDirectiveCFIUndefined(SMLoc DirectiveLoc)57395ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
57405ffd83dbSDimitry Andric   int64_t Register = 0;
57415ffd83dbSDimitry Andric 
57425ffd83dbSDimitry Andric   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
57435ffd83dbSDimitry Andric     return true;
57445ffd83dbSDimitry Andric 
57455ffd83dbSDimitry Andric   getStreamer().emitCFIUndefined(Register);
57465ffd83dbSDimitry Andric   return false;
57475ffd83dbSDimitry Andric }
57485ffd83dbSDimitry Andric 
57495ffd83dbSDimitry Andric /// parseDirectiveMacro
5750e8d8bef9SDimitry Andric /// ::= name macro [parameters]
5751e8d8bef9SDimitry Andric ///     ["LOCAL" identifiers]
5752e8d8bef9SDimitry Andric ///   parameters ::= parameter [, parameter]*
5753e8d8bef9SDimitry Andric ///   parameter ::= name ":" qualifier
5754e8d8bef9SDimitry Andric ///   qualifier ::= "req" | "vararg" | "=" macro_argument
parseDirectiveMacro(StringRef Name,SMLoc NameLoc)5755e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
57565ffd83dbSDimitry Andric   MCAsmMacroParameters Parameters;
57575ffd83dbSDimitry Andric   while (getLexer().isNot(AsmToken::EndOfStatement)) {
57585ffd83dbSDimitry Andric     if (!Parameters.empty() && Parameters.back().Vararg)
57595ffd83dbSDimitry Andric       return Error(Lexer.getLoc(),
57605ffd83dbSDimitry Andric                    "Vararg parameter '" + Parameters.back().Name +
5761e8d8bef9SDimitry Andric                        "' should be last in the list of parameters");
57625ffd83dbSDimitry Andric 
57635ffd83dbSDimitry Andric     MCAsmMacroParameter Parameter;
57645ffd83dbSDimitry Andric     if (parseIdentifier(Parameter.Name))
5765e8d8bef9SDimitry Andric       return TokError("expected identifier in 'macro' directive");
57665ffd83dbSDimitry Andric 
57675ffd83dbSDimitry Andric     // Emit an error if two (or more) named parameters share the same name.
57685ffd83dbSDimitry Andric     for (const MCAsmMacroParameter& CurrParam : Parameters)
5769fe6060f1SDimitry Andric       if (CurrParam.Name.equals_insensitive(Parameter.Name))
57705ffd83dbSDimitry Andric         return TokError("macro '" + Name + "' has multiple parameters"
57715ffd83dbSDimitry Andric                         " named '" + Parameter.Name + "'");
57725ffd83dbSDimitry Andric 
57735ffd83dbSDimitry Andric     if (Lexer.is(AsmToken::Colon)) {
57745ffd83dbSDimitry Andric       Lex();  // consume ':'
57755ffd83dbSDimitry Andric 
5776e8d8bef9SDimitry Andric       if (parseOptionalToken(AsmToken::Equal)) {
5777e8d8bef9SDimitry Andric         // Default value
5778e8d8bef9SDimitry Andric         SMLoc ParamLoc;
5779e8d8bef9SDimitry Andric 
5780e8d8bef9SDimitry Andric         ParamLoc = Lexer.getLoc();
5781e8d8bef9SDimitry Andric         if (parseMacroArgument(nullptr, Parameter.Value))
5782e8d8bef9SDimitry Andric           return true;
5783e8d8bef9SDimitry Andric       } else {
57845ffd83dbSDimitry Andric         SMLoc QualLoc;
57855ffd83dbSDimitry Andric         StringRef Qualifier;
57865ffd83dbSDimitry Andric 
57875ffd83dbSDimitry Andric         QualLoc = Lexer.getLoc();
57885ffd83dbSDimitry Andric         if (parseIdentifier(Qualifier))
57895ffd83dbSDimitry Andric           return Error(QualLoc, "missing parameter qualifier for "
5790e8d8bef9SDimitry Andric                                 "'" +
5791e8d8bef9SDimitry Andric                                     Parameter.Name + "' in macro '" + Name +
5792e8d8bef9SDimitry Andric                                     "'");
57935ffd83dbSDimitry Andric 
5794fe6060f1SDimitry Andric         if (Qualifier.equals_insensitive("req"))
57955ffd83dbSDimitry Andric           Parameter.Required = true;
5796fe6060f1SDimitry Andric         else if (Qualifier.equals_insensitive("vararg"))
57975ffd83dbSDimitry Andric           Parameter.Vararg = true;
57985ffd83dbSDimitry Andric         else
5799e8d8bef9SDimitry Andric           return Error(QualLoc,
5800e8d8bef9SDimitry Andric                        Qualifier + " is not a valid parameter qualifier for '" +
5801e8d8bef9SDimitry Andric                            Parameter.Name + "' in macro '" + Name + "'");
58025ffd83dbSDimitry Andric       }
58035ffd83dbSDimitry Andric     }
58045ffd83dbSDimitry Andric 
58055ffd83dbSDimitry Andric     Parameters.push_back(std::move(Parameter));
58065ffd83dbSDimitry Andric 
58075ffd83dbSDimitry Andric     if (getLexer().is(AsmToken::Comma))
58085ffd83dbSDimitry Andric       Lex();
58095ffd83dbSDimitry Andric   }
58105ffd83dbSDimitry Andric 
58115ffd83dbSDimitry Andric   // Eat just the end of statement.
58125ffd83dbSDimitry Andric   Lexer.Lex();
58135ffd83dbSDimitry Andric 
5814e8d8bef9SDimitry Andric   std::vector<std::string> Locals;
5815e8d8bef9SDimitry Andric   if (getTok().is(AsmToken::Identifier) &&
5816fe6060f1SDimitry Andric       getTok().getIdentifier().equals_insensitive("local")) {
5817e8d8bef9SDimitry Andric     Lex(); // Eat the LOCAL directive.
5818e8d8bef9SDimitry Andric 
5819e8d8bef9SDimitry Andric     StringRef ID;
5820e8d8bef9SDimitry Andric     while (true) {
5821e8d8bef9SDimitry Andric       if (parseIdentifier(ID))
5822e8d8bef9SDimitry Andric         return true;
5823e8d8bef9SDimitry Andric       Locals.push_back(ID.lower());
5824e8d8bef9SDimitry Andric 
5825e8d8bef9SDimitry Andric       // If we see a comma, continue (and allow line continuation).
5826e8d8bef9SDimitry Andric       if (!parseOptionalToken(AsmToken::Comma))
5827e8d8bef9SDimitry Andric         break;
5828e8d8bef9SDimitry Andric       parseOptionalToken(AsmToken::EndOfStatement);
5829e8d8bef9SDimitry Andric     }
5830e8d8bef9SDimitry Andric   }
5831e8d8bef9SDimitry Andric 
58325ffd83dbSDimitry Andric   // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors.
58335ffd83dbSDimitry Andric   AsmToken EndToken, StartToken = getTok();
58345ffd83dbSDimitry Andric   unsigned MacroDepth = 0;
5835e8d8bef9SDimitry Andric   bool IsMacroFunction = false;
58365ffd83dbSDimitry Andric   // Lex the macro definition.
58375ffd83dbSDimitry Andric   while (true) {
58385ffd83dbSDimitry Andric     // Ignore Lexing errors in macros.
58395ffd83dbSDimitry Andric     while (Lexer.is(AsmToken::Error)) {
58405ffd83dbSDimitry Andric       Lexer.Lex();
58415ffd83dbSDimitry Andric     }
58425ffd83dbSDimitry Andric 
58435ffd83dbSDimitry Andric     // Check whether we have reached the end of the file.
58445ffd83dbSDimitry Andric     if (getLexer().is(AsmToken::Eof))
5845e8d8bef9SDimitry Andric       return Error(NameLoc, "no matching 'endm' in definition");
58465ffd83dbSDimitry Andric 
5847e8d8bef9SDimitry Andric     // Otherwise, check whether we have reached the 'endm'... and determine if
5848e8d8bef9SDimitry Andric     // this is a macro function.
58495ffd83dbSDimitry Andric     if (getLexer().is(AsmToken::Identifier)) {
5850fe6060f1SDimitry Andric       if (getTok().getIdentifier().equals_insensitive("endm")) {
58515ffd83dbSDimitry Andric         if (MacroDepth == 0) { // Outermost macro.
58525ffd83dbSDimitry Andric           EndToken = getTok();
58535ffd83dbSDimitry Andric           Lexer.Lex();
58545ffd83dbSDimitry Andric           if (getLexer().isNot(AsmToken::EndOfStatement))
58555ffd83dbSDimitry Andric             return TokError("unexpected token in '" + EndToken.getIdentifier() +
58565ffd83dbSDimitry Andric                             "' directive");
58575ffd83dbSDimitry Andric           break;
58585ffd83dbSDimitry Andric         } else {
58595ffd83dbSDimitry Andric           // Otherwise we just found the end of an inner macro.
58605ffd83dbSDimitry Andric           --MacroDepth;
58615ffd83dbSDimitry Andric         }
5862fe6060f1SDimitry Andric       } else if (getTok().getIdentifier().equals_insensitive("exitm")) {
5863fe6060f1SDimitry Andric         if (MacroDepth == 0 && peekTok().isNot(AsmToken::EndOfStatement)) {
5864e8d8bef9SDimitry Andric           IsMacroFunction = true;
5865e8d8bef9SDimitry Andric         }
5866e8d8bef9SDimitry Andric       } else if (isMacroLikeDirective()) {
5867e8d8bef9SDimitry Andric         // We allow nested macros. Those aren't instantiated until the
5868e8d8bef9SDimitry Andric         // outermost macro is expanded so just ignore them for now.
58695ffd83dbSDimitry Andric         ++MacroDepth;
58705ffd83dbSDimitry Andric       }
58715ffd83dbSDimitry Andric     }
58725ffd83dbSDimitry Andric 
58735ffd83dbSDimitry Andric     // Otherwise, scan til the end of the statement.
58745ffd83dbSDimitry Andric     eatToEndOfStatement();
58755ffd83dbSDimitry Andric   }
58765ffd83dbSDimitry Andric 
5877e8d8bef9SDimitry Andric   if (getContext().lookupMacro(Name.lower())) {
5878e8d8bef9SDimitry Andric     return Error(NameLoc, "macro '" + Name + "' is already defined");
58795ffd83dbSDimitry Andric   }
58805ffd83dbSDimitry Andric 
58815ffd83dbSDimitry Andric   const char *BodyStart = StartToken.getLoc().getPointer();
58825ffd83dbSDimitry Andric   const char *BodyEnd = EndToken.getLoc().getPointer();
58835ffd83dbSDimitry Andric   StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5884e8d8bef9SDimitry Andric   MCAsmMacro Macro(Name, Body, std::move(Parameters), std::move(Locals),
5885e8d8bef9SDimitry Andric                    IsMacroFunction);
58865ffd83dbSDimitry Andric   DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n";
58875ffd83dbSDimitry Andric                   Macro.dump());
5888fe6060f1SDimitry Andric   getContext().defineMacro(Name.lower(), std::move(Macro));
58895ffd83dbSDimitry Andric   return false;
58905ffd83dbSDimitry Andric }
58915ffd83dbSDimitry Andric 
58925ffd83dbSDimitry Andric /// parseDirectiveExitMacro
5893e8d8bef9SDimitry Andric /// ::= "exitm" [textitem]
parseDirectiveExitMacro(SMLoc DirectiveLoc,StringRef Directive,std::string & Value)5894e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
5895e8d8bef9SDimitry Andric                                          StringRef Directive,
5896e8d8bef9SDimitry Andric                                          std::string &Value) {
5897e8d8bef9SDimitry Andric   SMLoc EndLoc = getTok().getLoc();
5898e8d8bef9SDimitry Andric   if (getTok().isNot(AsmToken::EndOfStatement) && parseTextItem(Value))
5899e8d8bef9SDimitry Andric     return Error(EndLoc,
5900e8d8bef9SDimitry Andric                  "unable to parse text item in '" + Directive + "' directive");
5901e8d8bef9SDimitry Andric   eatToEndOfStatement();
59025ffd83dbSDimitry Andric 
59035ffd83dbSDimitry Andric   if (!isInsideMacroInstantiation())
59045ffd83dbSDimitry Andric     return TokError("unexpected '" + Directive + "' in file, "
59055ffd83dbSDimitry Andric                                                  "no current macro definition");
59065ffd83dbSDimitry Andric 
59075ffd83dbSDimitry Andric   // Exit all conditionals that are active in the current macro.
59085ffd83dbSDimitry Andric   while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
59095ffd83dbSDimitry Andric     TheCondState = TheCondStack.back();
59105ffd83dbSDimitry Andric     TheCondStack.pop_back();
59115ffd83dbSDimitry Andric   }
59125ffd83dbSDimitry Andric 
59135ffd83dbSDimitry Andric   handleMacroExit();
59145ffd83dbSDimitry Andric   return false;
59155ffd83dbSDimitry Andric }
59165ffd83dbSDimitry Andric 
59175ffd83dbSDimitry Andric /// parseDirectiveEndMacro
5918e8d8bef9SDimitry Andric /// ::= endm
parseDirectiveEndMacro(StringRef Directive)59195ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
59205ffd83dbSDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
59215ffd83dbSDimitry Andric     return TokError("unexpected token in '" + Directive + "' directive");
59225ffd83dbSDimitry Andric 
59235ffd83dbSDimitry Andric   // If we are inside a macro instantiation, terminate the current
59245ffd83dbSDimitry Andric   // instantiation.
59255ffd83dbSDimitry Andric   if (isInsideMacroInstantiation()) {
59265ffd83dbSDimitry Andric     handleMacroExit();
59275ffd83dbSDimitry Andric     return false;
59285ffd83dbSDimitry Andric   }
59295ffd83dbSDimitry Andric 
59305ffd83dbSDimitry Andric   // Otherwise, this .endmacro is a stray entry in the file; well formed
59315ffd83dbSDimitry Andric   // .endmacro directives are handled during the macro definition parsing.
59325ffd83dbSDimitry Andric   return TokError("unexpected '" + Directive + "' in file, "
59335ffd83dbSDimitry Andric                                                "no current macro definition");
59345ffd83dbSDimitry Andric }
59355ffd83dbSDimitry Andric 
59365ffd83dbSDimitry Andric /// parseDirectivePurgeMacro
5937e8d8bef9SDimitry Andric /// ::= purge identifier ( , identifier )*
parseDirectivePurgeMacro(SMLoc DirectiveLoc)59385ffd83dbSDimitry Andric bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
59395ffd83dbSDimitry Andric   StringRef Name;
5940e8d8bef9SDimitry Andric   while (true) {
5941e8d8bef9SDimitry Andric     SMLoc NameLoc;
5942e8d8bef9SDimitry Andric     if (parseTokenLoc(NameLoc) ||
5943e8d8bef9SDimitry Andric         check(parseIdentifier(Name), NameLoc,
5944e8d8bef9SDimitry Andric               "expected identifier in 'purge' directive"))
59455ffd83dbSDimitry Andric       return true;
59465ffd83dbSDimitry Andric 
59475ffd83dbSDimitry Andric     DEBUG_WITH_TYPE("asm-macros", dbgs()
59485ffd83dbSDimitry Andric                                       << "Un-defining macro: " << Name << "\n");
5949e8d8bef9SDimitry Andric     if (!getContext().lookupMacro(Name.lower()))
5950e8d8bef9SDimitry Andric       return Error(NameLoc, "macro '" + Name + "' is not defined");
5951e8d8bef9SDimitry Andric     getContext().undefineMacro(Name.lower());
5952e8d8bef9SDimitry Andric 
5953e8d8bef9SDimitry Andric     if (!parseOptionalToken(AsmToken::Comma))
5954e8d8bef9SDimitry Andric       break;
5955e8d8bef9SDimitry Andric     parseOptionalToken(AsmToken::EndOfStatement);
5956e8d8bef9SDimitry Andric   }
5957e8d8bef9SDimitry Andric 
59585ffd83dbSDimitry Andric   return false;
59595ffd83dbSDimitry Andric }
59605ffd83dbSDimitry Andric 
parseDirectiveExtern()596181ad6265SDimitry Andric bool MasmParser::parseDirectiveExtern() {
596281ad6265SDimitry Andric   // .extern is the default - but we still need to take any provided type info.
596381ad6265SDimitry Andric   auto parseOp = [&]() -> bool {
596481ad6265SDimitry Andric     StringRef Name;
596581ad6265SDimitry Andric     SMLoc NameLoc = getTok().getLoc();
596681ad6265SDimitry Andric     if (parseIdentifier(Name))
596781ad6265SDimitry Andric       return Error(NameLoc, "expected name");
596881ad6265SDimitry Andric     if (parseToken(AsmToken::Colon))
596981ad6265SDimitry Andric       return true;
597081ad6265SDimitry Andric 
597181ad6265SDimitry Andric     StringRef TypeName;
597281ad6265SDimitry Andric     SMLoc TypeLoc = getTok().getLoc();
597381ad6265SDimitry Andric     if (parseIdentifier(TypeName))
597481ad6265SDimitry Andric       return Error(TypeLoc, "expected type");
597581ad6265SDimitry Andric     if (!TypeName.equals_insensitive("proc")) {
597681ad6265SDimitry Andric       AsmTypeInfo Type;
597781ad6265SDimitry Andric       if (lookUpType(TypeName, Type))
597881ad6265SDimitry Andric         return Error(TypeLoc, "unrecognized type");
597981ad6265SDimitry Andric       KnownType[Name.lower()] = Type;
598081ad6265SDimitry Andric     }
598181ad6265SDimitry Andric 
598281ad6265SDimitry Andric     MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
598381ad6265SDimitry Andric     Sym->setExternal(true);
598481ad6265SDimitry Andric     getStreamer().emitSymbolAttribute(Sym, MCSA_Extern);
598581ad6265SDimitry Andric 
598681ad6265SDimitry Andric     return false;
598781ad6265SDimitry Andric   };
598881ad6265SDimitry Andric 
598981ad6265SDimitry Andric   if (parseMany(parseOp))
599081ad6265SDimitry Andric     return addErrorSuffix(" in directive 'extern'");
599181ad6265SDimitry Andric   return false;
599281ad6265SDimitry Andric }
599381ad6265SDimitry Andric 
59945ffd83dbSDimitry Andric /// parseDirectiveSymbolAttribute
59955ffd83dbSDimitry Andric ///  ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
parseDirectiveSymbolAttribute(MCSymbolAttr Attr)59965ffd83dbSDimitry Andric bool MasmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
59975ffd83dbSDimitry Andric   auto parseOp = [&]() -> bool {
59985ffd83dbSDimitry Andric     StringRef Name;
59995ffd83dbSDimitry Andric     SMLoc Loc = getTok().getLoc();
60005ffd83dbSDimitry Andric     if (parseIdentifier(Name))
60015ffd83dbSDimitry Andric       return Error(Loc, "expected identifier");
60025ffd83dbSDimitry Andric     MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
60035ffd83dbSDimitry Andric 
60045ffd83dbSDimitry Andric     // Assembler local symbols don't make any sense here. Complain loudly.
60055ffd83dbSDimitry Andric     if (Sym->isTemporary())
60065ffd83dbSDimitry Andric       return Error(Loc, "non-local symbol required");
60075ffd83dbSDimitry Andric 
60085ffd83dbSDimitry Andric     if (!getStreamer().emitSymbolAttribute(Sym, Attr))
60095ffd83dbSDimitry Andric       return Error(Loc, "unable to emit symbol attribute");
60105ffd83dbSDimitry Andric     return false;
60115ffd83dbSDimitry Andric   };
60125ffd83dbSDimitry Andric 
60135ffd83dbSDimitry Andric   if (parseMany(parseOp))
60145ffd83dbSDimitry Andric     return addErrorSuffix(" in directive");
60155ffd83dbSDimitry Andric   return false;
60165ffd83dbSDimitry Andric }
60175ffd83dbSDimitry Andric 
60185ffd83dbSDimitry Andric /// parseDirectiveComm
60195ffd83dbSDimitry Andric ///  ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
parseDirectiveComm(bool IsLocal)60205ffd83dbSDimitry Andric bool MasmParser::parseDirectiveComm(bool IsLocal) {
60215ffd83dbSDimitry Andric   if (checkForValidSection())
60225ffd83dbSDimitry Andric     return true;
60235ffd83dbSDimitry Andric 
60245ffd83dbSDimitry Andric   SMLoc IDLoc = getLexer().getLoc();
60255ffd83dbSDimitry Andric   StringRef Name;
60265ffd83dbSDimitry Andric   if (parseIdentifier(Name))
60275ffd83dbSDimitry Andric     return TokError("expected identifier in directive");
60285ffd83dbSDimitry Andric 
60295ffd83dbSDimitry Andric   // Handle the identifier as the key symbol.
60305ffd83dbSDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
60315ffd83dbSDimitry Andric 
60325ffd83dbSDimitry Andric   if (getLexer().isNot(AsmToken::Comma))
60335ffd83dbSDimitry Andric     return TokError("unexpected token in directive");
60345ffd83dbSDimitry Andric   Lex();
60355ffd83dbSDimitry Andric 
60365ffd83dbSDimitry Andric   int64_t Size;
60375ffd83dbSDimitry Andric   SMLoc SizeLoc = getLexer().getLoc();
60385ffd83dbSDimitry Andric   if (parseAbsoluteExpression(Size))
60395ffd83dbSDimitry Andric     return true;
60405ffd83dbSDimitry Andric 
60415ffd83dbSDimitry Andric   int64_t Pow2Alignment = 0;
60425ffd83dbSDimitry Andric   SMLoc Pow2AlignmentLoc;
60435ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Comma)) {
60445ffd83dbSDimitry Andric     Lex();
60455ffd83dbSDimitry Andric     Pow2AlignmentLoc = getLexer().getLoc();
60465ffd83dbSDimitry Andric     if (parseAbsoluteExpression(Pow2Alignment))
60475ffd83dbSDimitry Andric       return true;
60485ffd83dbSDimitry Andric 
60495ffd83dbSDimitry Andric     LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
60505ffd83dbSDimitry Andric     if (IsLocal && LCOMM == LCOMM::NoAlignment)
60515ffd83dbSDimitry Andric       return Error(Pow2AlignmentLoc, "alignment not supported on this target");
60525ffd83dbSDimitry Andric 
60535ffd83dbSDimitry Andric     // If this target takes alignments in bytes (not log) validate and convert.
60545ffd83dbSDimitry Andric     if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
60555ffd83dbSDimitry Andric         (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
60565ffd83dbSDimitry Andric       if (!isPowerOf2_64(Pow2Alignment))
60575ffd83dbSDimitry Andric         return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
60585ffd83dbSDimitry Andric       Pow2Alignment = Log2_64(Pow2Alignment);
60595ffd83dbSDimitry Andric     }
60605ffd83dbSDimitry Andric   }
60615ffd83dbSDimitry Andric 
606281ad6265SDimitry Andric   if (parseEOL())
60635ffd83dbSDimitry Andric     return true;
60645ffd83dbSDimitry Andric 
60655ffd83dbSDimitry Andric   // NOTE: a size of zero for a .comm should create a undefined symbol
60665ffd83dbSDimitry Andric   // but a size of .lcomm creates a bss symbol of size zero.
60675ffd83dbSDimitry Andric   if (Size < 0)
60685ffd83dbSDimitry Andric     return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
60695ffd83dbSDimitry Andric                           "be less than zero");
60705ffd83dbSDimitry Andric 
60715ffd83dbSDimitry Andric   // NOTE: The alignment in the directive is a power of 2 value, the assembler
60725ffd83dbSDimitry Andric   // may internally end up wanting an alignment in bytes.
60735ffd83dbSDimitry Andric   // FIXME: Diagnose overflow.
60745ffd83dbSDimitry Andric   if (Pow2Alignment < 0)
60755ffd83dbSDimitry Andric     return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
60765ffd83dbSDimitry Andric                                    "alignment, can't be less than zero");
60775ffd83dbSDimitry Andric 
60785ffd83dbSDimitry Andric   Sym->redefineIfPossible();
60795ffd83dbSDimitry Andric   if (!Sym->isUndefined())
60805ffd83dbSDimitry Andric     return Error(IDLoc, "invalid symbol redefinition");
60815ffd83dbSDimitry Andric 
60825ffd83dbSDimitry Andric   // Create the Symbol as a common or local common with Size and Pow2Alignment.
60835ffd83dbSDimitry Andric   if (IsLocal) {
6084bdd1243dSDimitry Andric     getStreamer().emitLocalCommonSymbol(Sym, Size,
6085bdd1243dSDimitry Andric                                         Align(1ULL << Pow2Alignment));
60865ffd83dbSDimitry Andric     return false;
60875ffd83dbSDimitry Andric   }
60885ffd83dbSDimitry Andric 
6089bdd1243dSDimitry Andric   getStreamer().emitCommonSymbol(Sym, Size, Align(1ULL << Pow2Alignment));
60905ffd83dbSDimitry Andric   return false;
60915ffd83dbSDimitry Andric }
60925ffd83dbSDimitry Andric 
60935ffd83dbSDimitry Andric /// parseDirectiveComment
60945ffd83dbSDimitry Andric ///  ::= comment delimiter [[text]]
60955ffd83dbSDimitry Andric ///              [[text]]
60965ffd83dbSDimitry Andric ///              [[text]] delimiter [[text]]
parseDirectiveComment(SMLoc DirectiveLoc)60975ffd83dbSDimitry Andric bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
6098e8d8bef9SDimitry Andric   std::string FirstLine = parseStringTo(AsmToken::EndOfStatement);
60995ffd83dbSDimitry Andric   size_t DelimiterEnd = FirstLine.find_first_of("\b\t\v\f\r\x1A ");
610006c3fb27SDimitry Andric   assert(DelimiterEnd != std::string::npos);
6101e8d8bef9SDimitry Andric   StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd);
61025ffd83dbSDimitry Andric   if (Delimiter.empty())
61035ffd83dbSDimitry Andric     return Error(DirectiveLoc, "no delimiter in 'comment' directive");
61045ffd83dbSDimitry Andric   do {
61055ffd83dbSDimitry Andric     if (getTok().is(AsmToken::Eof))
61065ffd83dbSDimitry Andric       return Error(DirectiveLoc, "unmatched delimiter in 'comment' directive");
61075ffd83dbSDimitry Andric     Lex();  // eat end of statement
6108e8d8bef9SDimitry Andric   } while (
6109e8d8bef9SDimitry Andric       !StringRef(parseStringTo(AsmToken::EndOfStatement)).contains(Delimiter));
611081ad6265SDimitry Andric   return parseEOL();
61115ffd83dbSDimitry Andric }
61125ffd83dbSDimitry Andric 
61135ffd83dbSDimitry Andric /// parseDirectiveInclude
61145ffd83dbSDimitry Andric ///  ::= include <filename>
61155ffd83dbSDimitry Andric ///    | include filename
parseDirectiveInclude()61165ffd83dbSDimitry Andric bool MasmParser::parseDirectiveInclude() {
61175ffd83dbSDimitry Andric   // Allow the strings to have escaped octal character sequence.
61185ffd83dbSDimitry Andric   std::string Filename;
61195ffd83dbSDimitry Andric   SMLoc IncludeLoc = getTok().getLoc();
61205ffd83dbSDimitry Andric 
6121fe6060f1SDimitry Andric   if (parseAngleBracketString(Filename))
6122e8d8bef9SDimitry Andric     Filename = parseStringTo(AsmToken::EndOfStatement);
6123fe6060f1SDimitry Andric   if (check(Filename.empty(), "missing filename in 'include' directive") ||
61245ffd83dbSDimitry Andric       check(getTok().isNot(AsmToken::EndOfStatement),
61255ffd83dbSDimitry Andric             "unexpected token in 'include' directive") ||
61265ffd83dbSDimitry Andric       // Attempt to switch the lexer to the included file before consuming the
61275ffd83dbSDimitry Andric       // end of statement to avoid losing it when we switch.
61285ffd83dbSDimitry Andric       check(enterIncludeFile(Filename), IncludeLoc,
61295ffd83dbSDimitry Andric             "Could not find include file '" + Filename + "'"))
61305ffd83dbSDimitry Andric     return true;
61315ffd83dbSDimitry Andric 
61325ffd83dbSDimitry Andric   return false;
61335ffd83dbSDimitry Andric }
61345ffd83dbSDimitry Andric 
61355ffd83dbSDimitry Andric /// parseDirectiveIf
61365ffd83dbSDimitry Andric /// ::= .if{,eq,ge,gt,le,lt,ne} expression
parseDirectiveIf(SMLoc DirectiveLoc,DirectiveKind DirKind)61375ffd83dbSDimitry Andric bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
61385ffd83dbSDimitry Andric   TheCondStack.push_back(TheCondState);
61395ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::IfCond;
61405ffd83dbSDimitry Andric   if (TheCondState.Ignore) {
61415ffd83dbSDimitry Andric     eatToEndOfStatement();
61425ffd83dbSDimitry Andric   } else {
61435ffd83dbSDimitry Andric     int64_t ExprValue;
614481ad6265SDimitry Andric     if (parseAbsoluteExpression(ExprValue) || parseEOL())
61455ffd83dbSDimitry Andric       return true;
61465ffd83dbSDimitry Andric 
61475ffd83dbSDimitry Andric     switch (DirKind) {
61485ffd83dbSDimitry Andric     default:
61495ffd83dbSDimitry Andric       llvm_unreachable("unsupported directive");
61505ffd83dbSDimitry Andric     case DK_IF:
61515ffd83dbSDimitry Andric       break;
61525ffd83dbSDimitry Andric     case DK_IFE:
61535ffd83dbSDimitry Andric       ExprValue = ExprValue == 0;
61545ffd83dbSDimitry Andric       break;
61555ffd83dbSDimitry Andric     }
61565ffd83dbSDimitry Andric 
61575ffd83dbSDimitry Andric     TheCondState.CondMet = ExprValue;
61585ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
61595ffd83dbSDimitry Andric   }
61605ffd83dbSDimitry Andric 
61615ffd83dbSDimitry Andric   return false;
61625ffd83dbSDimitry Andric }
61635ffd83dbSDimitry Andric 
61645ffd83dbSDimitry Andric /// parseDirectiveIfb
6165e8d8bef9SDimitry Andric /// ::= .ifb textitem
parseDirectiveIfb(SMLoc DirectiveLoc,bool ExpectBlank)61665ffd83dbSDimitry Andric bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
61675ffd83dbSDimitry Andric   TheCondStack.push_back(TheCondState);
61685ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::IfCond;
61695ffd83dbSDimitry Andric 
61705ffd83dbSDimitry Andric   if (TheCondState.Ignore) {
61715ffd83dbSDimitry Andric     eatToEndOfStatement();
61725ffd83dbSDimitry Andric   } else {
61735ffd83dbSDimitry Andric     std::string Str;
61745ffd83dbSDimitry Andric     if (parseTextItem(Str))
6175e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'ifb' directive");
61765ffd83dbSDimitry Andric 
617781ad6265SDimitry Andric     if (parseEOL())
61785ffd83dbSDimitry Andric       return true;
61795ffd83dbSDimitry Andric 
61805ffd83dbSDimitry Andric     TheCondState.CondMet = ExpectBlank == Str.empty();
61815ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
61825ffd83dbSDimitry Andric   }
61835ffd83dbSDimitry Andric 
61845ffd83dbSDimitry Andric   return false;
61855ffd83dbSDimitry Andric }
61865ffd83dbSDimitry Andric 
61875ffd83dbSDimitry Andric /// parseDirectiveIfidn
6188e8d8bef9SDimitry Andric ///   ::= ifidn textitem, textitem
parseDirectiveIfidn(SMLoc DirectiveLoc,bool ExpectEqual,bool CaseInsensitive)6189e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
6190e8d8bef9SDimitry Andric                                      bool CaseInsensitive) {
61915ffd83dbSDimitry Andric   std::string String1, String2;
61925ffd83dbSDimitry Andric 
61935ffd83dbSDimitry Andric   if (parseTextItem(String1)) {
61945ffd83dbSDimitry Andric     if (ExpectEqual)
6195e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'ifidn' directive");
6196e8d8bef9SDimitry Andric     return TokError("expected text item parameter for 'ifdif' directive");
61975ffd83dbSDimitry Andric   }
61985ffd83dbSDimitry Andric 
61995ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::Comma)) {
62005ffd83dbSDimitry Andric     if (ExpectEqual)
62015ffd83dbSDimitry Andric       return TokError(
62025ffd83dbSDimitry Andric           "expected comma after first string for 'ifidn' directive");
62035ffd83dbSDimitry Andric     return TokError("expected comma after first string for 'ifdif' directive");
62045ffd83dbSDimitry Andric   }
62055ffd83dbSDimitry Andric   Lex();
62065ffd83dbSDimitry Andric 
62075ffd83dbSDimitry Andric   if (parseTextItem(String2)) {
62085ffd83dbSDimitry Andric     if (ExpectEqual)
6209e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'ifidn' directive");
6210e8d8bef9SDimitry Andric     return TokError("expected text item parameter for 'ifdif' directive");
62115ffd83dbSDimitry Andric   }
62125ffd83dbSDimitry Andric 
62135ffd83dbSDimitry Andric   TheCondStack.push_back(TheCondState);
62145ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::IfCond;
62155ffd83dbSDimitry Andric   if (CaseInsensitive)
62165ffd83dbSDimitry Andric     TheCondState.CondMet =
6217fe6060f1SDimitry Andric         ExpectEqual == (StringRef(String1).equals_insensitive(String2));
62185ffd83dbSDimitry Andric   else
62195ffd83dbSDimitry Andric     TheCondState.CondMet = ExpectEqual == (String1 == String2);
62205ffd83dbSDimitry Andric   TheCondState.Ignore = !TheCondState.CondMet;
62215ffd83dbSDimitry Andric 
62225ffd83dbSDimitry Andric   return false;
62235ffd83dbSDimitry Andric }
62245ffd83dbSDimitry Andric 
62255ffd83dbSDimitry Andric /// parseDirectiveIfdef
62265ffd83dbSDimitry Andric /// ::= ifdef symbol
62275ffd83dbSDimitry Andric ///   | ifdef variable
parseDirectiveIfdef(SMLoc DirectiveLoc,bool expect_defined)62285ffd83dbSDimitry Andric bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
62295ffd83dbSDimitry Andric   TheCondStack.push_back(TheCondState);
62305ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::IfCond;
62315ffd83dbSDimitry Andric 
62325ffd83dbSDimitry Andric   if (TheCondState.Ignore) {
62335ffd83dbSDimitry Andric     eatToEndOfStatement();
62345ffd83dbSDimitry Andric   } else {
62355ffd83dbSDimitry Andric     bool is_defined = false;
6236bdd1243dSDimitry Andric     MCRegister Reg;
62375ffd83dbSDimitry Andric     SMLoc StartLoc, EndLoc;
62385f757f3fSDimitry Andric     is_defined =
62395f757f3fSDimitry Andric         getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
62405ffd83dbSDimitry Andric     if (!is_defined) {
62415ffd83dbSDimitry Andric       StringRef Name;
62425ffd83dbSDimitry Andric       if (check(parseIdentifier(Name), "expected identifier after 'ifdef'") ||
624381ad6265SDimitry Andric           parseEOL())
62445ffd83dbSDimitry Andric         return true;
62455ffd83dbSDimitry Andric 
624606c3fb27SDimitry Andric       if (BuiltinSymbolMap.contains(Name.lower())) {
6247fe6060f1SDimitry Andric         is_defined = true;
624806c3fb27SDimitry Andric       } else if (Variables.contains(Name.lower())) {
62495ffd83dbSDimitry Andric         is_defined = true;
62505ffd83dbSDimitry Andric       } else {
6251fe6060f1SDimitry Andric         MCSymbol *Sym = getContext().lookupSymbol(Name.lower());
62525ffd83dbSDimitry Andric         is_defined = (Sym && !Sym->isUndefined(false));
62535ffd83dbSDimitry Andric       }
62545ffd83dbSDimitry Andric     }
62555ffd83dbSDimitry Andric 
62565ffd83dbSDimitry Andric     TheCondState.CondMet = (is_defined == expect_defined);
62575ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
62585ffd83dbSDimitry Andric   }
62595ffd83dbSDimitry Andric 
62605ffd83dbSDimitry Andric   return false;
62615ffd83dbSDimitry Andric }
62625ffd83dbSDimitry Andric 
62635ffd83dbSDimitry Andric /// parseDirectiveElseIf
62645ffd83dbSDimitry Andric /// ::= elseif expression
parseDirectiveElseIf(SMLoc DirectiveLoc,DirectiveKind DirKind)62655ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
62665ffd83dbSDimitry Andric                                       DirectiveKind DirKind) {
62675ffd83dbSDimitry Andric   if (TheCondState.TheCond != AsmCond::IfCond &&
62685ffd83dbSDimitry Andric       TheCondState.TheCond != AsmCond::ElseIfCond)
62695ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
62705ffd83dbSDimitry Andric                                " .if or  an .elseif");
62715ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::ElseIfCond;
62725ffd83dbSDimitry Andric 
62735ffd83dbSDimitry Andric   bool LastIgnoreState = false;
62745ffd83dbSDimitry Andric   if (!TheCondStack.empty())
62755ffd83dbSDimitry Andric     LastIgnoreState = TheCondStack.back().Ignore;
62765ffd83dbSDimitry Andric   if (LastIgnoreState || TheCondState.CondMet) {
62775ffd83dbSDimitry Andric     TheCondState.Ignore = true;
62785ffd83dbSDimitry Andric     eatToEndOfStatement();
62795ffd83dbSDimitry Andric   } else {
62805ffd83dbSDimitry Andric     int64_t ExprValue;
62815ffd83dbSDimitry Andric     if (parseAbsoluteExpression(ExprValue))
62825ffd83dbSDimitry Andric       return true;
62835ffd83dbSDimitry Andric 
628481ad6265SDimitry Andric     if (parseEOL())
62855ffd83dbSDimitry Andric       return true;
62865ffd83dbSDimitry Andric 
62875ffd83dbSDimitry Andric     switch (DirKind) {
62885ffd83dbSDimitry Andric     default:
62895ffd83dbSDimitry Andric       llvm_unreachable("unsupported directive");
62905ffd83dbSDimitry Andric     case DK_ELSEIF:
62915ffd83dbSDimitry Andric       break;
62925ffd83dbSDimitry Andric     case DK_ELSEIFE:
62935ffd83dbSDimitry Andric       ExprValue = ExprValue == 0;
62945ffd83dbSDimitry Andric       break;
62955ffd83dbSDimitry Andric     }
62965ffd83dbSDimitry Andric 
62975ffd83dbSDimitry Andric     TheCondState.CondMet = ExprValue;
62985ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
62995ffd83dbSDimitry Andric   }
63005ffd83dbSDimitry Andric 
63015ffd83dbSDimitry Andric   return false;
63025ffd83dbSDimitry Andric }
63035ffd83dbSDimitry Andric 
63045ffd83dbSDimitry Andric /// parseDirectiveElseIfb
6305e8d8bef9SDimitry Andric /// ::= elseifb textitem
parseDirectiveElseIfb(SMLoc DirectiveLoc,bool ExpectBlank)63065ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
63075ffd83dbSDimitry Andric   if (TheCondState.TheCond != AsmCond::IfCond &&
63085ffd83dbSDimitry Andric       TheCondState.TheCond != AsmCond::ElseIfCond)
63095ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
63105ffd83dbSDimitry Andric                                " if or an elseif");
63115ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::ElseIfCond;
63125ffd83dbSDimitry Andric 
63135ffd83dbSDimitry Andric   bool LastIgnoreState = false;
63145ffd83dbSDimitry Andric   if (!TheCondStack.empty())
63155ffd83dbSDimitry Andric     LastIgnoreState = TheCondStack.back().Ignore;
63165ffd83dbSDimitry Andric   if (LastIgnoreState || TheCondState.CondMet) {
63175ffd83dbSDimitry Andric     TheCondState.Ignore = true;
63185ffd83dbSDimitry Andric     eatToEndOfStatement();
63195ffd83dbSDimitry Andric   } else {
63205ffd83dbSDimitry Andric     std::string Str;
6321e8d8bef9SDimitry Andric     if (parseTextItem(Str)) {
6322e8d8bef9SDimitry Andric       if (ExpectBlank)
6323e8d8bef9SDimitry Andric         return TokError("expected text item parameter for 'elseifb' directive");
6324e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'elseifnb' directive");
6325e8d8bef9SDimitry Andric     }
63265ffd83dbSDimitry Andric 
632781ad6265SDimitry Andric     if (parseEOL())
63285ffd83dbSDimitry Andric       return true;
63295ffd83dbSDimitry Andric 
63305ffd83dbSDimitry Andric     TheCondState.CondMet = ExpectBlank == Str.empty();
63315ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
63325ffd83dbSDimitry Andric   }
63335ffd83dbSDimitry Andric 
63345ffd83dbSDimitry Andric   return false;
63355ffd83dbSDimitry Andric }
63365ffd83dbSDimitry Andric 
63375ffd83dbSDimitry Andric /// parseDirectiveElseIfdef
63385ffd83dbSDimitry Andric /// ::= elseifdef symbol
63395ffd83dbSDimitry Andric ///   | elseifdef variable
parseDirectiveElseIfdef(SMLoc DirectiveLoc,bool expect_defined)63405ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
63415ffd83dbSDimitry Andric                                          bool expect_defined) {
63425ffd83dbSDimitry Andric   if (TheCondState.TheCond != AsmCond::IfCond &&
63435ffd83dbSDimitry Andric       TheCondState.TheCond != AsmCond::ElseIfCond)
63445ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
63455ffd83dbSDimitry Andric                                " if or an elseif");
63465ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::ElseIfCond;
63475ffd83dbSDimitry Andric 
63485ffd83dbSDimitry Andric   bool LastIgnoreState = false;
63495ffd83dbSDimitry Andric   if (!TheCondStack.empty())
63505ffd83dbSDimitry Andric     LastIgnoreState = TheCondStack.back().Ignore;
63515ffd83dbSDimitry Andric   if (LastIgnoreState || TheCondState.CondMet) {
63525ffd83dbSDimitry Andric     TheCondState.Ignore = true;
63535ffd83dbSDimitry Andric     eatToEndOfStatement();
63545ffd83dbSDimitry Andric   } else {
63555ffd83dbSDimitry Andric     bool is_defined = false;
6356bdd1243dSDimitry Andric     MCRegister Reg;
63575ffd83dbSDimitry Andric     SMLoc StartLoc, EndLoc;
63585f757f3fSDimitry Andric     is_defined =
63595f757f3fSDimitry Andric         getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
63605ffd83dbSDimitry Andric     if (!is_defined) {
63615ffd83dbSDimitry Andric       StringRef Name;
63625ffd83dbSDimitry Andric       if (check(parseIdentifier(Name),
63635ffd83dbSDimitry Andric                 "expected identifier after 'elseifdef'") ||
636481ad6265SDimitry Andric           parseEOL())
63655ffd83dbSDimitry Andric         return true;
63665ffd83dbSDimitry Andric 
636706c3fb27SDimitry Andric       if (BuiltinSymbolMap.contains(Name.lower())) {
6368fe6060f1SDimitry Andric         is_defined = true;
636906c3fb27SDimitry Andric       } else if (Variables.contains(Name.lower())) {
63705ffd83dbSDimitry Andric         is_defined = true;
63715ffd83dbSDimitry Andric       } else {
63725ffd83dbSDimitry Andric         MCSymbol *Sym = getContext().lookupSymbol(Name);
63735ffd83dbSDimitry Andric         is_defined = (Sym && !Sym->isUndefined(false));
63745ffd83dbSDimitry Andric       }
63755ffd83dbSDimitry Andric     }
63765ffd83dbSDimitry Andric 
63775ffd83dbSDimitry Andric     TheCondState.CondMet = (is_defined == expect_defined);
63785ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
63795ffd83dbSDimitry Andric   }
63805ffd83dbSDimitry Andric 
63815ffd83dbSDimitry Andric   return false;
63825ffd83dbSDimitry Andric }
63835ffd83dbSDimitry Andric 
63845ffd83dbSDimitry Andric /// parseDirectiveElseIfidn
6385e8d8bef9SDimitry Andric /// ::= elseifidn textitem, textitem
parseDirectiveElseIfidn(SMLoc DirectiveLoc,bool ExpectEqual,bool CaseInsensitive)63865ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
63875ffd83dbSDimitry Andric                                          bool CaseInsensitive) {
63885ffd83dbSDimitry Andric   if (TheCondState.TheCond != AsmCond::IfCond &&
63895ffd83dbSDimitry Andric       TheCondState.TheCond != AsmCond::ElseIfCond)
63905ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
63915ffd83dbSDimitry Andric                                " if or an elseif");
63925ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::ElseIfCond;
63935ffd83dbSDimitry Andric 
63945ffd83dbSDimitry Andric   bool LastIgnoreState = false;
63955ffd83dbSDimitry Andric   if (!TheCondStack.empty())
63965ffd83dbSDimitry Andric     LastIgnoreState = TheCondStack.back().Ignore;
63975ffd83dbSDimitry Andric   if (LastIgnoreState || TheCondState.CondMet) {
63985ffd83dbSDimitry Andric     TheCondState.Ignore = true;
63995ffd83dbSDimitry Andric     eatToEndOfStatement();
64005ffd83dbSDimitry Andric   } else {
64015ffd83dbSDimitry Andric     std::string String1, String2;
64025ffd83dbSDimitry Andric 
64035ffd83dbSDimitry Andric     if (parseTextItem(String1)) {
64045ffd83dbSDimitry Andric       if (ExpectEqual)
6405e8d8bef9SDimitry Andric         return TokError(
6406e8d8bef9SDimitry Andric             "expected text item parameter for 'elseifidn' directive");
6407e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'elseifdif' directive");
64085ffd83dbSDimitry Andric     }
64095ffd83dbSDimitry Andric 
64105ffd83dbSDimitry Andric     if (Lexer.isNot(AsmToken::Comma)) {
64115ffd83dbSDimitry Andric       if (ExpectEqual)
64125ffd83dbSDimitry Andric         return TokError(
64135ffd83dbSDimitry Andric             "expected comma after first string for 'elseifidn' directive");
64145ffd83dbSDimitry Andric       return TokError(
64155ffd83dbSDimitry Andric           "expected comma after first string for 'elseifdif' directive");
64165ffd83dbSDimitry Andric     }
64175ffd83dbSDimitry Andric     Lex();
64185ffd83dbSDimitry Andric 
64195ffd83dbSDimitry Andric     if (parseTextItem(String2)) {
64205ffd83dbSDimitry Andric       if (ExpectEqual)
6421e8d8bef9SDimitry Andric         return TokError(
6422e8d8bef9SDimitry Andric             "expected text item parameter for 'elseifidn' directive");
6423e8d8bef9SDimitry Andric       return TokError("expected text item parameter for 'elseifdif' directive");
64245ffd83dbSDimitry Andric     }
64255ffd83dbSDimitry Andric 
64265ffd83dbSDimitry Andric     if (CaseInsensitive)
64275ffd83dbSDimitry Andric       TheCondState.CondMet =
6428fe6060f1SDimitry Andric           ExpectEqual == (StringRef(String1).equals_insensitive(String2));
64295ffd83dbSDimitry Andric     else
64305ffd83dbSDimitry Andric       TheCondState.CondMet = ExpectEqual == (String1 == String2);
64315ffd83dbSDimitry Andric     TheCondState.Ignore = !TheCondState.CondMet;
64325ffd83dbSDimitry Andric   }
64335ffd83dbSDimitry Andric 
64345ffd83dbSDimitry Andric   return false;
64355ffd83dbSDimitry Andric }
64365ffd83dbSDimitry Andric 
64375ffd83dbSDimitry Andric /// parseDirectiveElse
64385ffd83dbSDimitry Andric /// ::= else
parseDirectiveElse(SMLoc DirectiveLoc)64395ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
644081ad6265SDimitry Andric   if (parseEOL())
64415ffd83dbSDimitry Andric     return true;
64425ffd83dbSDimitry Andric 
64435ffd83dbSDimitry Andric   if (TheCondState.TheCond != AsmCond::IfCond &&
64445ffd83dbSDimitry Andric       TheCondState.TheCond != AsmCond::ElseIfCond)
64455ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered an else that doesn't follow an if"
64465ffd83dbSDimitry Andric                                " or an elseif");
64475ffd83dbSDimitry Andric   TheCondState.TheCond = AsmCond::ElseCond;
64485ffd83dbSDimitry Andric   bool LastIgnoreState = false;
64495ffd83dbSDimitry Andric   if (!TheCondStack.empty())
64505ffd83dbSDimitry Andric     LastIgnoreState = TheCondStack.back().Ignore;
64515ffd83dbSDimitry Andric   if (LastIgnoreState || TheCondState.CondMet)
64525ffd83dbSDimitry Andric     TheCondState.Ignore = true;
64535ffd83dbSDimitry Andric   else
64545ffd83dbSDimitry Andric     TheCondState.Ignore = false;
64555ffd83dbSDimitry Andric 
64565ffd83dbSDimitry Andric   return false;
64575ffd83dbSDimitry Andric }
64585ffd83dbSDimitry Andric 
64595ffd83dbSDimitry Andric /// parseDirectiveEnd
64605ffd83dbSDimitry Andric /// ::= end
parseDirectiveEnd(SMLoc DirectiveLoc)64615ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
646281ad6265SDimitry Andric   if (parseEOL())
64635ffd83dbSDimitry Andric     return true;
64645ffd83dbSDimitry Andric 
64655ffd83dbSDimitry Andric   while (Lexer.isNot(AsmToken::Eof))
64665ffd83dbSDimitry Andric     Lexer.Lex();
64675ffd83dbSDimitry Andric 
64685ffd83dbSDimitry Andric   return false;
64695ffd83dbSDimitry Andric }
64705ffd83dbSDimitry Andric 
64715ffd83dbSDimitry Andric /// parseDirectiveError
64725ffd83dbSDimitry Andric ///   ::= .err [message]
parseDirectiveError(SMLoc DirectiveLoc)64735ffd83dbSDimitry Andric bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
64745ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
64755ffd83dbSDimitry Andric     if (TheCondStack.back().Ignore) {
64765ffd83dbSDimitry Andric       eatToEndOfStatement();
64775ffd83dbSDimitry Andric       return false;
64785ffd83dbSDimitry Andric     }
64795ffd83dbSDimitry Andric   }
64805ffd83dbSDimitry Andric 
6481e8d8bef9SDimitry Andric   std::string Message = ".err directive invoked in source file";
64825ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::EndOfStatement))
6483e8d8bef9SDimitry Andric     Message = parseStringTo(AsmToken::EndOfStatement);
64845ffd83dbSDimitry Andric   Lex();
64855ffd83dbSDimitry Andric 
64865ffd83dbSDimitry Andric   return Error(DirectiveLoc, Message);
64875ffd83dbSDimitry Andric }
64885ffd83dbSDimitry Andric 
64895ffd83dbSDimitry Andric /// parseDirectiveErrorIfb
64905ffd83dbSDimitry Andric ///   ::= .errb textitem[, message]
parseDirectiveErrorIfb(SMLoc DirectiveLoc,bool ExpectBlank)64915ffd83dbSDimitry Andric bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
64925ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
64935ffd83dbSDimitry Andric     if (TheCondStack.back().Ignore) {
64945ffd83dbSDimitry Andric       eatToEndOfStatement();
64955ffd83dbSDimitry Andric       return false;
64965ffd83dbSDimitry Andric     }
64975ffd83dbSDimitry Andric   }
64985ffd83dbSDimitry Andric 
64995ffd83dbSDimitry Andric   std::string Text;
65005ffd83dbSDimitry Andric   if (parseTextItem(Text))
65015ffd83dbSDimitry Andric     return Error(getTok().getLoc(), "missing text item in '.errb' directive");
65025ffd83dbSDimitry Andric 
6503e8d8bef9SDimitry Andric   std::string Message = ".errb directive invoked in source file";
65045ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::EndOfStatement)) {
65055ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma))
65065ffd83dbSDimitry Andric       return addErrorSuffix(" in '.errb' directive");
6507e8d8bef9SDimitry Andric     Message = parseStringTo(AsmToken::EndOfStatement);
65085ffd83dbSDimitry Andric   }
65095ffd83dbSDimitry Andric   Lex();
65105ffd83dbSDimitry Andric 
65115ffd83dbSDimitry Andric   if (Text.empty() == ExpectBlank)
65125ffd83dbSDimitry Andric     return Error(DirectiveLoc, Message);
65135ffd83dbSDimitry Andric   return false;
65145ffd83dbSDimitry Andric }
65155ffd83dbSDimitry Andric 
65165ffd83dbSDimitry Andric /// parseDirectiveErrorIfdef
65175ffd83dbSDimitry Andric ///   ::= .errdef name[, message]
parseDirectiveErrorIfdef(SMLoc DirectiveLoc,bool ExpectDefined)65185ffd83dbSDimitry Andric bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
65195ffd83dbSDimitry Andric                                           bool ExpectDefined) {
65205ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
65215ffd83dbSDimitry Andric     if (TheCondStack.back().Ignore) {
65225ffd83dbSDimitry Andric       eatToEndOfStatement();
65235ffd83dbSDimitry Andric       return false;
65245ffd83dbSDimitry Andric     }
65255ffd83dbSDimitry Andric   }
65265ffd83dbSDimitry Andric 
65275ffd83dbSDimitry Andric   bool IsDefined = false;
6528bdd1243dSDimitry Andric   MCRegister Reg;
65295ffd83dbSDimitry Andric   SMLoc StartLoc, EndLoc;
65305f757f3fSDimitry Andric   IsDefined =
65315f757f3fSDimitry Andric       getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
65325ffd83dbSDimitry Andric   if (!IsDefined) {
65335ffd83dbSDimitry Andric     StringRef Name;
65345ffd83dbSDimitry Andric     if (check(parseIdentifier(Name), "expected identifier after '.errdef'"))
65355ffd83dbSDimitry Andric       return true;
65365ffd83dbSDimitry Andric 
653706c3fb27SDimitry Andric     if (BuiltinSymbolMap.contains(Name.lower())) {
6538fe6060f1SDimitry Andric       IsDefined = true;
653906c3fb27SDimitry Andric     } else if (Variables.contains(Name.lower())) {
65405ffd83dbSDimitry Andric       IsDefined = true;
65415ffd83dbSDimitry Andric     } else {
65425ffd83dbSDimitry Andric       MCSymbol *Sym = getContext().lookupSymbol(Name);
65435ffd83dbSDimitry Andric       IsDefined = (Sym && !Sym->isUndefined(false));
65445ffd83dbSDimitry Andric     }
65455ffd83dbSDimitry Andric   }
65465ffd83dbSDimitry Andric 
6547e8d8bef9SDimitry Andric   std::string Message = ".errdef directive invoked in source file";
65485ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::EndOfStatement)) {
65495ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma))
65505ffd83dbSDimitry Andric       return addErrorSuffix(" in '.errdef' directive");
6551e8d8bef9SDimitry Andric     Message = parseStringTo(AsmToken::EndOfStatement);
65525ffd83dbSDimitry Andric   }
65535ffd83dbSDimitry Andric   Lex();
65545ffd83dbSDimitry Andric 
65555ffd83dbSDimitry Andric   if (IsDefined == ExpectDefined)
65565ffd83dbSDimitry Andric     return Error(DirectiveLoc, Message);
65575ffd83dbSDimitry Andric   return false;
65585ffd83dbSDimitry Andric }
65595ffd83dbSDimitry Andric 
65605ffd83dbSDimitry Andric /// parseDirectiveErrorIfidn
6561e8d8bef9SDimitry Andric ///   ::= .erridn textitem, textitem[, message]
parseDirectiveErrorIfidn(SMLoc DirectiveLoc,bool ExpectEqual,bool CaseInsensitive)65625ffd83dbSDimitry Andric bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
65635ffd83dbSDimitry Andric                                           bool CaseInsensitive) {
65645ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
65655ffd83dbSDimitry Andric     if (TheCondStack.back().Ignore) {
65665ffd83dbSDimitry Andric       eatToEndOfStatement();
65675ffd83dbSDimitry Andric       return false;
65685ffd83dbSDimitry Andric     }
65695ffd83dbSDimitry Andric   }
65705ffd83dbSDimitry Andric 
65715ffd83dbSDimitry Andric   std::string String1, String2;
65725ffd83dbSDimitry Andric 
65735ffd83dbSDimitry Andric   if (parseTextItem(String1)) {
65745ffd83dbSDimitry Andric     if (ExpectEqual)
65755ffd83dbSDimitry Andric       return TokError("expected string parameter for '.erridn' directive");
65765ffd83dbSDimitry Andric     return TokError("expected string parameter for '.errdif' directive");
65775ffd83dbSDimitry Andric   }
65785ffd83dbSDimitry Andric 
65795ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::Comma)) {
65805ffd83dbSDimitry Andric     if (ExpectEqual)
65815ffd83dbSDimitry Andric       return TokError(
65825ffd83dbSDimitry Andric           "expected comma after first string for '.erridn' directive");
65835ffd83dbSDimitry Andric     return TokError(
65845ffd83dbSDimitry Andric         "expected comma after first string for '.errdif' directive");
65855ffd83dbSDimitry Andric   }
65865ffd83dbSDimitry Andric   Lex();
65875ffd83dbSDimitry Andric 
65885ffd83dbSDimitry Andric   if (parseTextItem(String2)) {
65895ffd83dbSDimitry Andric     if (ExpectEqual)
65905ffd83dbSDimitry Andric       return TokError("expected string parameter for '.erridn' directive");
65915ffd83dbSDimitry Andric     return TokError("expected string parameter for '.errdif' directive");
65925ffd83dbSDimitry Andric   }
65935ffd83dbSDimitry Andric 
6594e8d8bef9SDimitry Andric   std::string Message;
65955ffd83dbSDimitry Andric   if (ExpectEqual)
65965ffd83dbSDimitry Andric     Message = ".erridn directive invoked in source file";
65975ffd83dbSDimitry Andric   else
65985ffd83dbSDimitry Andric     Message = ".errdif directive invoked in source file";
65995ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::EndOfStatement)) {
66005ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma))
66015ffd83dbSDimitry Andric       return addErrorSuffix(" in '.erridn' directive");
6602e8d8bef9SDimitry Andric     Message = parseStringTo(AsmToken::EndOfStatement);
66035ffd83dbSDimitry Andric   }
66045ffd83dbSDimitry Andric   Lex();
66055ffd83dbSDimitry Andric 
66065ffd83dbSDimitry Andric   if (CaseInsensitive)
66075ffd83dbSDimitry Andric     TheCondState.CondMet =
6608fe6060f1SDimitry Andric         ExpectEqual == (StringRef(String1).equals_insensitive(String2));
66095ffd83dbSDimitry Andric   else
66105ffd83dbSDimitry Andric     TheCondState.CondMet = ExpectEqual == (String1 == String2);
66115ffd83dbSDimitry Andric   TheCondState.Ignore = !TheCondState.CondMet;
66125ffd83dbSDimitry Andric 
66135ffd83dbSDimitry Andric   if ((CaseInsensitive &&
6614fe6060f1SDimitry Andric        ExpectEqual == StringRef(String1).equals_insensitive(String2)) ||
66155ffd83dbSDimitry Andric       (ExpectEqual == (String1 == String2)))
66165ffd83dbSDimitry Andric     return Error(DirectiveLoc, Message);
66175ffd83dbSDimitry Andric   return false;
66185ffd83dbSDimitry Andric }
66195ffd83dbSDimitry Andric 
66205ffd83dbSDimitry Andric /// parseDirectiveErrorIfe
66215ffd83dbSDimitry Andric ///   ::= .erre expression[, message]
parseDirectiveErrorIfe(SMLoc DirectiveLoc,bool ExpectZero)66225ffd83dbSDimitry Andric bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero) {
66235ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
66245ffd83dbSDimitry Andric     if (TheCondStack.back().Ignore) {
66255ffd83dbSDimitry Andric       eatToEndOfStatement();
66265ffd83dbSDimitry Andric       return false;
66275ffd83dbSDimitry Andric     }
66285ffd83dbSDimitry Andric   }
66295ffd83dbSDimitry Andric 
66305ffd83dbSDimitry Andric   int64_t ExprValue;
66315ffd83dbSDimitry Andric   if (parseAbsoluteExpression(ExprValue))
66325ffd83dbSDimitry Andric     return addErrorSuffix(" in '.erre' directive");
66335ffd83dbSDimitry Andric 
6634e8d8bef9SDimitry Andric   std::string Message = ".erre directive invoked in source file";
66355ffd83dbSDimitry Andric   if (Lexer.isNot(AsmToken::EndOfStatement)) {
66365ffd83dbSDimitry Andric     if (parseToken(AsmToken::Comma))
66375ffd83dbSDimitry Andric       return addErrorSuffix(" in '.erre' directive");
6638e8d8bef9SDimitry Andric     Message = parseStringTo(AsmToken::EndOfStatement);
66395ffd83dbSDimitry Andric   }
66405ffd83dbSDimitry Andric   Lex();
66415ffd83dbSDimitry Andric 
66425ffd83dbSDimitry Andric   if ((ExprValue == 0) == ExpectZero)
66435ffd83dbSDimitry Andric     return Error(DirectiveLoc, Message);
66445ffd83dbSDimitry Andric   return false;
66455ffd83dbSDimitry Andric }
66465ffd83dbSDimitry Andric 
66475ffd83dbSDimitry Andric /// parseDirectiveEndIf
66485ffd83dbSDimitry Andric /// ::= .endif
parseDirectiveEndIf(SMLoc DirectiveLoc)66495ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
665081ad6265SDimitry Andric   if (parseEOL())
66515ffd83dbSDimitry Andric     return true;
66525ffd83dbSDimitry Andric 
66535ffd83dbSDimitry Andric   if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty())
66545ffd83dbSDimitry Andric     return Error(DirectiveLoc, "Encountered a .endif that doesn't follow "
66555ffd83dbSDimitry Andric                                "an .if or .else");
66565ffd83dbSDimitry Andric   if (!TheCondStack.empty()) {
66575ffd83dbSDimitry Andric     TheCondState = TheCondStack.back();
66585ffd83dbSDimitry Andric     TheCondStack.pop_back();
66595ffd83dbSDimitry Andric   }
66605ffd83dbSDimitry Andric 
66615ffd83dbSDimitry Andric   return false;
66625ffd83dbSDimitry Andric }
66635ffd83dbSDimitry Andric 
initializeDirectiveKindMap()66645ffd83dbSDimitry Andric void MasmParser::initializeDirectiveKindMap() {
66655ffd83dbSDimitry Andric   DirectiveKindMap["="] = DK_ASSIGN;
66665ffd83dbSDimitry Andric   DirectiveKindMap["equ"] = DK_EQU;
66675ffd83dbSDimitry Andric   DirectiveKindMap["textequ"] = DK_TEXTEQU;
66685ffd83dbSDimitry Andric   // DirectiveKindMap[".ascii"] = DK_ASCII;
66695ffd83dbSDimitry Andric   // DirectiveKindMap[".asciz"] = DK_ASCIZ;
66705ffd83dbSDimitry Andric   // DirectiveKindMap[".string"] = DK_STRING;
66715ffd83dbSDimitry Andric   DirectiveKindMap["byte"] = DK_BYTE;
66725ffd83dbSDimitry Andric   DirectiveKindMap["sbyte"] = DK_SBYTE;
66735ffd83dbSDimitry Andric   DirectiveKindMap["word"] = DK_WORD;
66745ffd83dbSDimitry Andric   DirectiveKindMap["sword"] = DK_SWORD;
66755ffd83dbSDimitry Andric   DirectiveKindMap["dword"] = DK_DWORD;
66765ffd83dbSDimitry Andric   DirectiveKindMap["sdword"] = DK_SDWORD;
66775ffd83dbSDimitry Andric   DirectiveKindMap["fword"] = DK_FWORD;
66785ffd83dbSDimitry Andric   DirectiveKindMap["qword"] = DK_QWORD;
66795ffd83dbSDimitry Andric   DirectiveKindMap["sqword"] = DK_SQWORD;
66805ffd83dbSDimitry Andric   DirectiveKindMap["real4"] = DK_REAL4;
66815ffd83dbSDimitry Andric   DirectiveKindMap["real8"] = DK_REAL8;
6682e8d8bef9SDimitry Andric   DirectiveKindMap["real10"] = DK_REAL10;
66835ffd83dbSDimitry Andric   DirectiveKindMap["align"] = DK_ALIGN;
6684fe6060f1SDimitry Andric   DirectiveKindMap["even"] = DK_EVEN;
6685fe6060f1SDimitry Andric   DirectiveKindMap["org"] = DK_ORG;
66865ffd83dbSDimitry Andric   DirectiveKindMap["extern"] = DK_EXTERN;
6687bdd1243dSDimitry Andric   DirectiveKindMap["extrn"] = DK_EXTERN;
66885ffd83dbSDimitry Andric   DirectiveKindMap["public"] = DK_PUBLIC;
66895ffd83dbSDimitry Andric   // DirectiveKindMap[".comm"] = DK_COMM;
66905ffd83dbSDimitry Andric   DirectiveKindMap["comment"] = DK_COMMENT;
66915ffd83dbSDimitry Andric   DirectiveKindMap["include"] = DK_INCLUDE;
6692e8d8bef9SDimitry Andric   DirectiveKindMap["repeat"] = DK_REPEAT;
6693e8d8bef9SDimitry Andric   DirectiveKindMap["rept"] = DK_REPEAT;
6694e8d8bef9SDimitry Andric   DirectiveKindMap["while"] = DK_WHILE;
6695e8d8bef9SDimitry Andric   DirectiveKindMap["for"] = DK_FOR;
6696e8d8bef9SDimitry Andric   DirectiveKindMap["irp"] = DK_FOR;
6697e8d8bef9SDimitry Andric   DirectiveKindMap["forc"] = DK_FORC;
6698e8d8bef9SDimitry Andric   DirectiveKindMap["irpc"] = DK_FORC;
66995ffd83dbSDimitry Andric   DirectiveKindMap["if"] = DK_IF;
67005ffd83dbSDimitry Andric   DirectiveKindMap["ife"] = DK_IFE;
67015ffd83dbSDimitry Andric   DirectiveKindMap["ifb"] = DK_IFB;
67025ffd83dbSDimitry Andric   DirectiveKindMap["ifnb"] = DK_IFNB;
67035ffd83dbSDimitry Andric   DirectiveKindMap["ifdef"] = DK_IFDEF;
67045ffd83dbSDimitry Andric   DirectiveKindMap["ifndef"] = DK_IFNDEF;
67055ffd83dbSDimitry Andric   DirectiveKindMap["ifdif"] = DK_IFDIF;
67065ffd83dbSDimitry Andric   DirectiveKindMap["ifdifi"] = DK_IFDIFI;
67075ffd83dbSDimitry Andric   DirectiveKindMap["ifidn"] = DK_IFIDN;
67085ffd83dbSDimitry Andric   DirectiveKindMap["ifidni"] = DK_IFIDNI;
67095ffd83dbSDimitry Andric   DirectiveKindMap["elseif"] = DK_ELSEIF;
67105ffd83dbSDimitry Andric   DirectiveKindMap["elseifdef"] = DK_ELSEIFDEF;
67115ffd83dbSDimitry Andric   DirectiveKindMap["elseifndef"] = DK_ELSEIFNDEF;
67125ffd83dbSDimitry Andric   DirectiveKindMap["elseifdif"] = DK_ELSEIFDIF;
67135ffd83dbSDimitry Andric   DirectiveKindMap["elseifidn"] = DK_ELSEIFIDN;
67145ffd83dbSDimitry Andric   DirectiveKindMap["else"] = DK_ELSE;
67155ffd83dbSDimitry Andric   DirectiveKindMap["end"] = DK_END;
67165ffd83dbSDimitry Andric   DirectiveKindMap["endif"] = DK_ENDIF;
67175ffd83dbSDimitry Andric   // DirectiveKindMap[".file"] = DK_FILE;
67185ffd83dbSDimitry Andric   // DirectiveKindMap[".line"] = DK_LINE;
67195ffd83dbSDimitry Andric   // DirectiveKindMap[".loc"] = DK_LOC;
67205ffd83dbSDimitry Andric   // DirectiveKindMap[".stabs"] = DK_STABS;
67215ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_file"] = DK_CV_FILE;
67225ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
67235ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
67245ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
67255ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
67265ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
67275ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
67285ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_string"] = DK_CV_STRING;
67295ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
67305ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
67315ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
67325ffd83dbSDimitry Andric   // DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
67335ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
67345ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
67355ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
67365ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
67375ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
67385ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
67395ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
67405ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
67415ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
67425ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
67435ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
67445ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
67455ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
67465ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
67475ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
67485ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
67495ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
67505ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
67515ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
67525ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
67535ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
67545ffd83dbSDimitry Andric   // DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
6755e8d8bef9SDimitry Andric   DirectiveKindMap["macro"] = DK_MACRO;
6756e8d8bef9SDimitry Andric   DirectiveKindMap["exitm"] = DK_EXITM;
6757e8d8bef9SDimitry Andric   DirectiveKindMap["endm"] = DK_ENDM;
6758e8d8bef9SDimitry Andric   DirectiveKindMap["purge"] = DK_PURGE;
67595ffd83dbSDimitry Andric   DirectiveKindMap[".err"] = DK_ERR;
67605ffd83dbSDimitry Andric   DirectiveKindMap[".errb"] = DK_ERRB;
67615ffd83dbSDimitry Andric   DirectiveKindMap[".errnb"] = DK_ERRNB;
67625ffd83dbSDimitry Andric   DirectiveKindMap[".errdef"] = DK_ERRDEF;
67635ffd83dbSDimitry Andric   DirectiveKindMap[".errndef"] = DK_ERRNDEF;
67645ffd83dbSDimitry Andric   DirectiveKindMap[".errdif"] = DK_ERRDIF;
67655ffd83dbSDimitry Andric   DirectiveKindMap[".errdifi"] = DK_ERRDIFI;
67665ffd83dbSDimitry Andric   DirectiveKindMap[".erridn"] = DK_ERRIDN;
67675ffd83dbSDimitry Andric   DirectiveKindMap[".erridni"] = DK_ERRIDNI;
67685ffd83dbSDimitry Andric   DirectiveKindMap[".erre"] = DK_ERRE;
67695ffd83dbSDimitry Andric   DirectiveKindMap[".errnz"] = DK_ERRNZ;
6770e8d8bef9SDimitry Andric   DirectiveKindMap[".pushframe"] = DK_PUSHFRAME;
6771e8d8bef9SDimitry Andric   DirectiveKindMap[".pushreg"] = DK_PUSHREG;
6772e8d8bef9SDimitry Andric   DirectiveKindMap[".savereg"] = DK_SAVEREG;
6773e8d8bef9SDimitry Andric   DirectiveKindMap[".savexmm128"] = DK_SAVEXMM128;
6774e8d8bef9SDimitry Andric   DirectiveKindMap[".setframe"] = DK_SETFRAME;
6775e8d8bef9SDimitry Andric   DirectiveKindMap[".radix"] = DK_RADIX;
67765ffd83dbSDimitry Andric   DirectiveKindMap["db"] = DK_DB;
67775ffd83dbSDimitry Andric   DirectiveKindMap["dd"] = DK_DD;
6778e8d8bef9SDimitry Andric   DirectiveKindMap["df"] = DK_DF;
67795ffd83dbSDimitry Andric   DirectiveKindMap["dq"] = DK_DQ;
67805ffd83dbSDimitry Andric   DirectiveKindMap["dw"] = DK_DW;
67815ffd83dbSDimitry Andric   DirectiveKindMap["echo"] = DK_ECHO;
67825ffd83dbSDimitry Andric   DirectiveKindMap["struc"] = DK_STRUCT;
67835ffd83dbSDimitry Andric   DirectiveKindMap["struct"] = DK_STRUCT;
67845ffd83dbSDimitry Andric   DirectiveKindMap["union"] = DK_UNION;
67855ffd83dbSDimitry Andric   DirectiveKindMap["ends"] = DK_ENDS;
67865ffd83dbSDimitry Andric }
67875ffd83dbSDimitry Andric 
isMacroLikeDirective()6788e8d8bef9SDimitry Andric bool MasmParser::isMacroLikeDirective() {
6789e8d8bef9SDimitry Andric   if (getLexer().is(AsmToken::Identifier)) {
6790e8d8bef9SDimitry Andric     bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier())
6791e8d8bef9SDimitry Andric                            .CasesLower("repeat", "rept", true)
6792e8d8bef9SDimitry Andric                            .CaseLower("while", true)
6793e8d8bef9SDimitry Andric                            .CasesLower("for", "irp", true)
6794e8d8bef9SDimitry Andric                            .CasesLower("forc", "irpc", true)
6795e8d8bef9SDimitry Andric                            .Default(false);
6796e8d8bef9SDimitry Andric     if (IsMacroLike)
6797e8d8bef9SDimitry Andric       return true;
6798e8d8bef9SDimitry Andric   }
6799fe6060f1SDimitry Andric   if (peekTok().is(AsmToken::Identifier) &&
6800fe6060f1SDimitry Andric       peekTok().getIdentifier().equals_insensitive("macro"))
6801e8d8bef9SDimitry Andric     return true;
6802e8d8bef9SDimitry Andric 
6803e8d8bef9SDimitry Andric   return false;
6804e8d8bef9SDimitry Andric }
6805e8d8bef9SDimitry Andric 
parseMacroLikeBody(SMLoc DirectiveLoc)68065ffd83dbSDimitry Andric MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
68075ffd83dbSDimitry Andric   AsmToken EndToken, StartToken = getTok();
68085ffd83dbSDimitry Andric 
68095ffd83dbSDimitry Andric   unsigned NestLevel = 0;
68105ffd83dbSDimitry Andric   while (true) {
68115ffd83dbSDimitry Andric     // Check whether we have reached the end of the file.
68125ffd83dbSDimitry Andric     if (getLexer().is(AsmToken::Eof)) {
6813e8d8bef9SDimitry Andric       printError(DirectiveLoc, "no matching 'endm' in definition");
68145ffd83dbSDimitry Andric       return nullptr;
68155ffd83dbSDimitry Andric     }
68165ffd83dbSDimitry Andric 
6817e8d8bef9SDimitry Andric     if (isMacroLikeDirective())
68185ffd83dbSDimitry Andric       ++NestLevel;
68195ffd83dbSDimitry Andric 
6820e8d8bef9SDimitry Andric     // Otherwise, check whether we have reached the endm.
6821e8d8bef9SDimitry Andric     if (Lexer.is(AsmToken::Identifier) &&
6822fe6060f1SDimitry Andric         getTok().getIdentifier().equals_insensitive("endm")) {
68235ffd83dbSDimitry Andric       if (NestLevel == 0) {
68245ffd83dbSDimitry Andric         EndToken = getTok();
68255ffd83dbSDimitry Andric         Lex();
68265ffd83dbSDimitry Andric         if (Lexer.isNot(AsmToken::EndOfStatement)) {
6827e8d8bef9SDimitry Andric           printError(getTok().getLoc(), "unexpected token in 'endm' directive");
68285ffd83dbSDimitry Andric           return nullptr;
68295ffd83dbSDimitry Andric         }
68305ffd83dbSDimitry Andric         break;
68315ffd83dbSDimitry Andric       }
68325ffd83dbSDimitry Andric       --NestLevel;
68335ffd83dbSDimitry Andric     }
68345ffd83dbSDimitry Andric 
68355ffd83dbSDimitry Andric     // Otherwise, scan till the end of the statement.
68365ffd83dbSDimitry Andric     eatToEndOfStatement();
68375ffd83dbSDimitry Andric   }
68385ffd83dbSDimitry Andric 
68395ffd83dbSDimitry Andric   const char *BodyStart = StartToken.getLoc().getPointer();
68405ffd83dbSDimitry Andric   const char *BodyEnd = EndToken.getLoc().getPointer();
68415ffd83dbSDimitry Andric   StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
68425ffd83dbSDimitry Andric 
68435ffd83dbSDimitry Andric   // We Are Anonymous.
68445ffd83dbSDimitry Andric   MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters());
68455ffd83dbSDimitry Andric   return &MacroLikeBodies.back();
68465ffd83dbSDimitry Andric }
68475ffd83dbSDimitry Andric 
expandStatement(SMLoc Loc)6848e8d8bef9SDimitry Andric bool MasmParser::expandStatement(SMLoc Loc) {
6849e8d8bef9SDimitry Andric   std::string Body = parseStringTo(AsmToken::EndOfStatement);
6850e8d8bef9SDimitry Andric   SMLoc EndLoc = getTok().getLoc();
6851e8d8bef9SDimitry Andric 
6852e8d8bef9SDimitry Andric   MCAsmMacroParameters Parameters;
6853e8d8bef9SDimitry Andric   MCAsmMacroArguments Arguments;
6854fe6060f1SDimitry Andric 
6855fe6060f1SDimitry Andric   StringMap<std::string> BuiltinValues;
6856fe6060f1SDimitry Andric   for (const auto &S : BuiltinSymbolMap) {
6857fe6060f1SDimitry Andric     const BuiltinSymbol &Sym = S.getValue();
6858bdd1243dSDimitry Andric     if (std::optional<std::string> Text = evaluateBuiltinTextMacro(Sym, Loc)) {
6859fe6060f1SDimitry Andric       BuiltinValues[S.getKey().lower()] = std::move(*Text);
6860fe6060f1SDimitry Andric     }
6861fe6060f1SDimitry Andric   }
6862fe6060f1SDimitry Andric   for (const auto &B : BuiltinValues) {
6863fe6060f1SDimitry Andric     MCAsmMacroParameter P;
6864fe6060f1SDimitry Andric     MCAsmMacroArgument A;
6865fe6060f1SDimitry Andric     P.Name = B.getKey();
6866fe6060f1SDimitry Andric     P.Required = true;
6867fe6060f1SDimitry Andric     A.push_back(AsmToken(AsmToken::String, B.getValue()));
6868fe6060f1SDimitry Andric 
6869fe6060f1SDimitry Andric     Parameters.push_back(std::move(P));
6870fe6060f1SDimitry Andric     Arguments.push_back(std::move(A));
6871fe6060f1SDimitry Andric   }
6872fe6060f1SDimitry Andric 
6873e8d8bef9SDimitry Andric   for (const auto &V : Variables) {
6874e8d8bef9SDimitry Andric     const Variable &Var = V.getValue();
6875e8d8bef9SDimitry Andric     if (Var.IsText) {
6876fe6060f1SDimitry Andric       MCAsmMacroParameter P;
6877fe6060f1SDimitry Andric       MCAsmMacroArgument A;
6878e8d8bef9SDimitry Andric       P.Name = Var.Name;
6879e8d8bef9SDimitry Andric       P.Required = true;
6880e8d8bef9SDimitry Andric       A.push_back(AsmToken(AsmToken::String, Var.TextValue));
6881fe6060f1SDimitry Andric 
6882fe6060f1SDimitry Andric       Parameters.push_back(std::move(P));
6883fe6060f1SDimitry Andric       Arguments.push_back(std::move(A));
6884e8d8bef9SDimitry Andric     }
6885e8d8bef9SDimitry Andric   }
6886e8d8bef9SDimitry Andric   MacroLikeBodies.emplace_back(StringRef(), Body, Parameters);
6887e8d8bef9SDimitry Andric   MCAsmMacro M = MacroLikeBodies.back();
6888e8d8bef9SDimitry Andric 
6889e8d8bef9SDimitry Andric   // Expand the statement in a new buffer.
6890e8d8bef9SDimitry Andric   SmallString<80> Buf;
6891e8d8bef9SDimitry Andric   raw_svector_ostream OS(Buf);
6892e8d8bef9SDimitry Andric   if (expandMacro(OS, M.Body, M.Parameters, Arguments, M.Locals, EndLoc))
6893e8d8bef9SDimitry Andric     return true;
6894e8d8bef9SDimitry Andric   std::unique_ptr<MemoryBuffer> Expansion =
6895e8d8bef9SDimitry Andric       MemoryBuffer::getMemBufferCopy(OS.str(), "<expansion>");
6896e8d8bef9SDimitry Andric 
6897e8d8bef9SDimitry Andric   // Jump to the expanded statement and prime the lexer.
6898e8d8bef9SDimitry Andric   CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Expansion), EndLoc);
6899e8d8bef9SDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
6900e8d8bef9SDimitry Andric   EndStatementAtEOFStack.push_back(false);
6901e8d8bef9SDimitry Andric   Lex();
6902e8d8bef9SDimitry Andric   return false;
6903e8d8bef9SDimitry Andric }
6904e8d8bef9SDimitry Andric 
instantiateMacroLikeBody(MCAsmMacro * M,SMLoc DirectiveLoc,raw_svector_ostream & OS)69055ffd83dbSDimitry Andric void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
69065ffd83dbSDimitry Andric                                           raw_svector_ostream &OS) {
6907e8d8bef9SDimitry Andric   instantiateMacroLikeBody(M, DirectiveLoc, /*ExitLoc=*/getTok().getLoc(), OS);
6908e8d8bef9SDimitry Andric }
instantiateMacroLikeBody(MCAsmMacro * M,SMLoc DirectiveLoc,SMLoc ExitLoc,raw_svector_ostream & OS)6909e8d8bef9SDimitry Andric void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
6910e8d8bef9SDimitry Andric                                           SMLoc ExitLoc,
6911e8d8bef9SDimitry Andric                                           raw_svector_ostream &OS) {
6912e8d8bef9SDimitry Andric   OS << "endm\n";
69135ffd83dbSDimitry Andric 
69145ffd83dbSDimitry Andric   std::unique_ptr<MemoryBuffer> Instantiation =
69155ffd83dbSDimitry Andric       MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
69165ffd83dbSDimitry Andric 
69175ffd83dbSDimitry Andric   // Create the macro instantiation object and add to the current macro
69185ffd83dbSDimitry Andric   // instantiation stack.
6919e8d8bef9SDimitry Andric   MacroInstantiation *MI = new MacroInstantiation{DirectiveLoc, CurBuffer,
6920e8d8bef9SDimitry Andric                                                   ExitLoc, TheCondStack.size()};
69215ffd83dbSDimitry Andric   ActiveMacros.push_back(MI);
69225ffd83dbSDimitry Andric 
69235ffd83dbSDimitry Andric   // Jump to the macro instantiation and prime the lexer.
69245ffd83dbSDimitry Andric   CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc());
69255ffd83dbSDimitry Andric   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
6926e8d8bef9SDimitry Andric   EndStatementAtEOFStack.push_back(true);
69275ffd83dbSDimitry Andric   Lex();
69285ffd83dbSDimitry Andric }
69295ffd83dbSDimitry Andric 
6930e8d8bef9SDimitry Andric /// parseDirectiveRepeat
6931e8d8bef9SDimitry Andric ///   ::= ("repeat" | "rept") count
6932e8d8bef9SDimitry Andric ///       body
6933e8d8bef9SDimitry Andric ///     endm
parseDirectiveRepeat(SMLoc DirectiveLoc,StringRef Dir)6934e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) {
69355ffd83dbSDimitry Andric   const MCExpr *CountExpr;
69365ffd83dbSDimitry Andric   SMLoc CountLoc = getTok().getLoc();
69375ffd83dbSDimitry Andric   if (parseExpression(CountExpr))
69385ffd83dbSDimitry Andric     return true;
69395ffd83dbSDimitry Andric 
69405ffd83dbSDimitry Andric   int64_t Count;
69415ffd83dbSDimitry Andric   if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
69425ffd83dbSDimitry Andric     return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
69435ffd83dbSDimitry Andric   }
69445ffd83dbSDimitry Andric 
694581ad6265SDimitry Andric   if (check(Count < 0, CountLoc, "Count is negative") || parseEOL())
69465ffd83dbSDimitry Andric     return true;
69475ffd83dbSDimitry Andric 
6948e8d8bef9SDimitry Andric   // Lex the repeat definition.
69495ffd83dbSDimitry Andric   MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
69505ffd83dbSDimitry Andric   if (!M)
69515ffd83dbSDimitry Andric     return true;
69525ffd83dbSDimitry Andric 
69535ffd83dbSDimitry Andric   // Macro instantiation is lexical, unfortunately. We construct a new buffer
69545ffd83dbSDimitry Andric   // to hold the macro body with substitutions.
69555ffd83dbSDimitry Andric   SmallString<256> Buf;
69565ffd83dbSDimitry Andric   raw_svector_ostream OS(Buf);
69575ffd83dbSDimitry Andric   while (Count--) {
6958bdd1243dSDimitry Andric     if (expandMacro(OS, M->Body, std::nullopt, std::nullopt, M->Locals,
6959bdd1243dSDimitry Andric                     getTok().getLoc()))
69605ffd83dbSDimitry Andric       return true;
69615ffd83dbSDimitry Andric   }
69625ffd83dbSDimitry Andric   instantiateMacroLikeBody(M, DirectiveLoc, OS);
69635ffd83dbSDimitry Andric 
69645ffd83dbSDimitry Andric   return false;
69655ffd83dbSDimitry Andric }
69665ffd83dbSDimitry Andric 
6967e8d8bef9SDimitry Andric /// parseDirectiveWhile
6968e8d8bef9SDimitry Andric /// ::= "while" expression
6969e8d8bef9SDimitry Andric ///       body
6970e8d8bef9SDimitry Andric ///     endm
parseDirectiveWhile(SMLoc DirectiveLoc)6971e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) {
6972e8d8bef9SDimitry Andric   const MCExpr *CondExpr;
6973e8d8bef9SDimitry Andric   SMLoc CondLoc = getTok().getLoc();
6974e8d8bef9SDimitry Andric   if (parseExpression(CondExpr))
6975e8d8bef9SDimitry Andric     return true;
6976e8d8bef9SDimitry Andric 
6977e8d8bef9SDimitry Andric   // Lex the repeat definition.
6978e8d8bef9SDimitry Andric   MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
6979e8d8bef9SDimitry Andric   if (!M)
6980e8d8bef9SDimitry Andric     return true;
6981e8d8bef9SDimitry Andric 
6982e8d8bef9SDimitry Andric   // Macro instantiation is lexical, unfortunately. We construct a new buffer
6983e8d8bef9SDimitry Andric   // to hold the macro body with substitutions.
6984e8d8bef9SDimitry Andric   SmallString<256> Buf;
6985e8d8bef9SDimitry Andric   raw_svector_ostream OS(Buf);
6986e8d8bef9SDimitry Andric   int64_t Condition;
6987e8d8bef9SDimitry Andric   if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr()))
6988e8d8bef9SDimitry Andric     return Error(CondLoc, "expected absolute expression in 'while' directive");
6989e8d8bef9SDimitry Andric   if (Condition) {
6990e8d8bef9SDimitry Andric     // Instantiate the macro, then resume at this directive to recheck the
6991e8d8bef9SDimitry Andric     // condition.
6992bdd1243dSDimitry Andric     if (expandMacro(OS, M->Body, std::nullopt, std::nullopt, M->Locals,
6993bdd1243dSDimitry Andric                     getTok().getLoc()))
6994e8d8bef9SDimitry Andric       return true;
6995e8d8bef9SDimitry Andric     instantiateMacroLikeBody(M, DirectiveLoc, /*ExitLoc=*/DirectiveLoc, OS);
6996e8d8bef9SDimitry Andric   }
6997e8d8bef9SDimitry Andric 
6998e8d8bef9SDimitry Andric   return false;
6999e8d8bef9SDimitry Andric }
7000e8d8bef9SDimitry Andric 
7001e8d8bef9SDimitry Andric /// parseDirectiveFor
7002e8d8bef9SDimitry Andric /// ::= ("for" | "irp") symbol [":" qualifier], <values>
7003e8d8bef9SDimitry Andric ///       body
7004e8d8bef9SDimitry Andric ///     endm
parseDirectiveFor(SMLoc DirectiveLoc,StringRef Dir)7005e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
70065ffd83dbSDimitry Andric   MCAsmMacroParameter Parameter;
70075ffd83dbSDimitry Andric   MCAsmMacroArguments A;
70085ffd83dbSDimitry Andric   if (check(parseIdentifier(Parameter.Name),
7009e8d8bef9SDimitry Andric             "expected identifier in '" + Dir + "' directive"))
7010e8d8bef9SDimitry Andric     return true;
7011e8d8bef9SDimitry Andric 
7012e8d8bef9SDimitry Andric   // Parse optional qualifier (default value, or "req")
7013e8d8bef9SDimitry Andric   if (parseOptionalToken(AsmToken::Colon)) {
7014e8d8bef9SDimitry Andric     if (parseOptionalToken(AsmToken::Equal)) {
7015e8d8bef9SDimitry Andric       // Default value
7016e8d8bef9SDimitry Andric       SMLoc ParamLoc;
7017e8d8bef9SDimitry Andric 
7018e8d8bef9SDimitry Andric       ParamLoc = Lexer.getLoc();
7019e8d8bef9SDimitry Andric       if (parseMacroArgument(nullptr, Parameter.Value))
7020e8d8bef9SDimitry Andric         return true;
7021e8d8bef9SDimitry Andric     } else {
7022e8d8bef9SDimitry Andric       SMLoc QualLoc;
7023e8d8bef9SDimitry Andric       StringRef Qualifier;
7024e8d8bef9SDimitry Andric 
7025e8d8bef9SDimitry Andric       QualLoc = Lexer.getLoc();
7026e8d8bef9SDimitry Andric       if (parseIdentifier(Qualifier))
7027e8d8bef9SDimitry Andric         return Error(QualLoc, "missing parameter qualifier for "
7028e8d8bef9SDimitry Andric                               "'" +
7029e8d8bef9SDimitry Andric                                   Parameter.Name + "' in '" + Dir +
7030e8d8bef9SDimitry Andric                                   "' directive");
7031e8d8bef9SDimitry Andric 
7032fe6060f1SDimitry Andric       if (Qualifier.equals_insensitive("req"))
7033e8d8bef9SDimitry Andric         Parameter.Required = true;
7034e8d8bef9SDimitry Andric       else
7035e8d8bef9SDimitry Andric         return Error(QualLoc,
7036e8d8bef9SDimitry Andric                      Qualifier + " is not a valid parameter qualifier for '" +
7037e8d8bef9SDimitry Andric                          Parameter.Name + "' in '" + Dir + "' directive");
7038e8d8bef9SDimitry Andric     }
7039e8d8bef9SDimitry Andric   }
7040e8d8bef9SDimitry Andric 
7041e8d8bef9SDimitry Andric   if (parseToken(AsmToken::Comma,
7042e8d8bef9SDimitry Andric                  "expected comma in '" + Dir + "' directive") ||
7043e8d8bef9SDimitry Andric       parseToken(AsmToken::Less,
7044e8d8bef9SDimitry Andric                  "values in '" + Dir +
7045e8d8bef9SDimitry Andric                      "' directive must be enclosed in angle brackets"))
7046e8d8bef9SDimitry Andric     return true;
7047e8d8bef9SDimitry Andric 
7048e8d8bef9SDimitry Andric   while (true) {
7049e8d8bef9SDimitry Andric     A.emplace_back();
7050e8d8bef9SDimitry Andric     if (parseMacroArgument(&Parameter, A.back(), /*EndTok=*/AsmToken::Greater))
7051e8d8bef9SDimitry Andric       return addErrorSuffix(" in arguments for '" + Dir + "' directive");
7052e8d8bef9SDimitry Andric 
7053e8d8bef9SDimitry Andric     // If we see a comma, continue, and allow line continuation.
7054e8d8bef9SDimitry Andric     if (!parseOptionalToken(AsmToken::Comma))
7055e8d8bef9SDimitry Andric       break;
7056e8d8bef9SDimitry Andric     parseOptionalToken(AsmToken::EndOfStatement);
7057e8d8bef9SDimitry Andric   }
7058e8d8bef9SDimitry Andric 
7059e8d8bef9SDimitry Andric   if (parseToken(AsmToken::Greater,
7060e8d8bef9SDimitry Andric                  "values in '" + Dir +
7061e8d8bef9SDimitry Andric                      "' directive must be enclosed in angle brackets") ||
706281ad6265SDimitry Andric       parseEOL())
70635ffd83dbSDimitry Andric     return true;
70645ffd83dbSDimitry Andric 
7065e8d8bef9SDimitry Andric   // Lex the for definition.
70665ffd83dbSDimitry Andric   MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
70675ffd83dbSDimitry Andric   if (!M)
70685ffd83dbSDimitry Andric     return true;
70695ffd83dbSDimitry Andric 
70705ffd83dbSDimitry Andric   // Macro instantiation is lexical, unfortunately. We construct a new buffer
70715ffd83dbSDimitry Andric   // to hold the macro body with substitutions.
70725ffd83dbSDimitry Andric   SmallString<256> Buf;
70735ffd83dbSDimitry Andric   raw_svector_ostream OS(Buf);
70745ffd83dbSDimitry Andric 
70755ffd83dbSDimitry Andric   for (const MCAsmMacroArgument &Arg : A) {
7076e8d8bef9SDimitry Andric     if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc()))
70775ffd83dbSDimitry Andric       return true;
70785ffd83dbSDimitry Andric   }
70795ffd83dbSDimitry Andric 
70805ffd83dbSDimitry Andric   instantiateMacroLikeBody(M, DirectiveLoc, OS);
70815ffd83dbSDimitry Andric 
70825ffd83dbSDimitry Andric   return false;
70835ffd83dbSDimitry Andric }
70845ffd83dbSDimitry Andric 
7085e8d8bef9SDimitry Andric /// parseDirectiveForc
7086e8d8bef9SDimitry Andric /// ::= ("forc" | "irpc") symbol, <string>
7087e8d8bef9SDimitry Andric ///       body
7088e8d8bef9SDimitry Andric ///     endm
parseDirectiveForc(SMLoc DirectiveLoc,StringRef Directive)7089e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
70905ffd83dbSDimitry Andric   MCAsmMacroParameter Parameter;
70915ffd83dbSDimitry Andric 
7092e8d8bef9SDimitry Andric   std::string Argument;
70935ffd83dbSDimitry Andric   if (check(parseIdentifier(Parameter.Name),
7094e8d8bef9SDimitry Andric             "expected identifier in '" + Directive + "' directive") ||
7095e8d8bef9SDimitry Andric       parseToken(AsmToken::Comma,
7096e8d8bef9SDimitry Andric                  "expected comma in '" + Directive + "' directive"))
70975ffd83dbSDimitry Andric     return true;
7098e8d8bef9SDimitry Andric   if (parseAngleBracketString(Argument)) {
7099e8d8bef9SDimitry Andric     // Match ml64.exe; treat all characters to end of statement as a string,
7100e8d8bef9SDimitry Andric     // ignoring comment markers, then discard anything following a space (using
7101e8d8bef9SDimitry Andric     // the C locale).
7102e8d8bef9SDimitry Andric     Argument = parseStringTo(AsmToken::EndOfStatement);
7103e8d8bef9SDimitry Andric     if (getTok().is(AsmToken::EndOfStatement))
7104e8d8bef9SDimitry Andric       Argument += getTok().getString();
7105e8d8bef9SDimitry Andric     size_t End = 0;
7106e8d8bef9SDimitry Andric     for (; End < Argument.size(); ++End) {
7107e8d8bef9SDimitry Andric       if (isSpace(Argument[End]))
7108e8d8bef9SDimitry Andric         break;
7109e8d8bef9SDimitry Andric     }
7110e8d8bef9SDimitry Andric     Argument.resize(End);
7111e8d8bef9SDimitry Andric   }
711281ad6265SDimitry Andric   if (parseEOL())
71135ffd83dbSDimitry Andric     return true;
71145ffd83dbSDimitry Andric 
71155ffd83dbSDimitry Andric   // Lex the irpc definition.
71165ffd83dbSDimitry Andric   MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc);
71175ffd83dbSDimitry Andric   if (!M)
71185ffd83dbSDimitry Andric     return true;
71195ffd83dbSDimitry Andric 
71205ffd83dbSDimitry Andric   // Macro instantiation is lexical, unfortunately. We construct a new buffer
71215ffd83dbSDimitry Andric   // to hold the macro body with substitutions.
71225ffd83dbSDimitry Andric   SmallString<256> Buf;
71235ffd83dbSDimitry Andric   raw_svector_ostream OS(Buf);
71245ffd83dbSDimitry Andric 
7125e8d8bef9SDimitry Andric   StringRef Values(Argument);
71265ffd83dbSDimitry Andric   for (std::size_t I = 0, End = Values.size(); I != End; ++I) {
71275ffd83dbSDimitry Andric     MCAsmMacroArgument Arg;
71285ffd83dbSDimitry Andric     Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1));
71295ffd83dbSDimitry Andric 
7130e8d8bef9SDimitry Andric     if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc()))
71315ffd83dbSDimitry Andric       return true;
71325ffd83dbSDimitry Andric   }
71335ffd83dbSDimitry Andric 
71345ffd83dbSDimitry Andric   instantiateMacroLikeBody(M, DirectiveLoc, OS);
71355ffd83dbSDimitry Andric 
71365ffd83dbSDimitry Andric   return false;
71375ffd83dbSDimitry Andric }
71385ffd83dbSDimitry Andric 
parseDirectiveMSEmit(SMLoc IDLoc,ParseStatementInfo & Info,size_t Len)71395ffd83dbSDimitry Andric bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
71405ffd83dbSDimitry Andric                                       size_t Len) {
71415ffd83dbSDimitry Andric   const MCExpr *Value;
71425ffd83dbSDimitry Andric   SMLoc ExprLoc = getLexer().getLoc();
71435ffd83dbSDimitry Andric   if (parseExpression(Value))
71445ffd83dbSDimitry Andric     return true;
71455ffd83dbSDimitry Andric   const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
71465ffd83dbSDimitry Andric   if (!MCE)
71475ffd83dbSDimitry Andric     return Error(ExprLoc, "unexpected expression in _emit");
71485ffd83dbSDimitry Andric   uint64_t IntValue = MCE->getValue();
71495ffd83dbSDimitry Andric   if (!isUInt<8>(IntValue) && !isInt<8>(IntValue))
71505ffd83dbSDimitry Andric     return Error(ExprLoc, "literal value out of range for directive");
71515ffd83dbSDimitry Andric 
71525ffd83dbSDimitry Andric   Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len);
71535ffd83dbSDimitry Andric   return false;
71545ffd83dbSDimitry Andric }
71555ffd83dbSDimitry Andric 
parseDirectiveMSAlign(SMLoc IDLoc,ParseStatementInfo & Info)71565ffd83dbSDimitry Andric bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
71575ffd83dbSDimitry Andric   const MCExpr *Value;
71585ffd83dbSDimitry Andric   SMLoc ExprLoc = getLexer().getLoc();
71595ffd83dbSDimitry Andric   if (parseExpression(Value))
71605ffd83dbSDimitry Andric     return true;
71615ffd83dbSDimitry Andric   const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
71625ffd83dbSDimitry Andric   if (!MCE)
71635ffd83dbSDimitry Andric     return Error(ExprLoc, "unexpected expression in align");
71645ffd83dbSDimitry Andric   uint64_t IntValue = MCE->getValue();
71655ffd83dbSDimitry Andric   if (!isPowerOf2_64(IntValue))
71665ffd83dbSDimitry Andric     return Error(ExprLoc, "literal value not a power of two greater then zero");
71675ffd83dbSDimitry Andric 
71685ffd83dbSDimitry Andric   Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue));
71695ffd83dbSDimitry Andric   return false;
71705ffd83dbSDimitry Andric }
71715ffd83dbSDimitry Andric 
parseDirectiveRadix(SMLoc DirectiveLoc)7172e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
7173e8d8bef9SDimitry Andric   const SMLoc Loc = getLexer().getLoc();
7174e8d8bef9SDimitry Andric   std::string RadixStringRaw = parseStringTo(AsmToken::EndOfStatement);
7175e8d8bef9SDimitry Andric   StringRef RadixString = StringRef(RadixStringRaw).trim();
7176e8d8bef9SDimitry Andric   unsigned Radix;
7177e8d8bef9SDimitry Andric   if (RadixString.getAsInteger(10, Radix)) {
7178e8d8bef9SDimitry Andric     return Error(Loc,
7179e8d8bef9SDimitry Andric                  "radix must be a decimal number in the range 2 to 16; was " +
7180e8d8bef9SDimitry Andric                      RadixString);
7181e8d8bef9SDimitry Andric   }
7182e8d8bef9SDimitry Andric   if (Radix < 2 || Radix > 16)
7183e8d8bef9SDimitry Andric     return Error(Loc, "radix must be in the range 2 to 16; was " +
7184e8d8bef9SDimitry Andric                           std::to_string(Radix));
7185e8d8bef9SDimitry Andric   getLexer().setMasmDefaultRadix(Radix);
7186e8d8bef9SDimitry Andric   return false;
7187e8d8bef9SDimitry Andric }
7188e8d8bef9SDimitry Andric 
7189e8d8bef9SDimitry Andric /// parseDirectiveEcho
7190e8d8bef9SDimitry Andric ///   ::= "echo" message
parseDirectiveEcho(SMLoc DirectiveLoc)7191fe6060f1SDimitry Andric bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) {
7192e8d8bef9SDimitry Andric   std::string Message = parseStringTo(AsmToken::EndOfStatement);
7193e8d8bef9SDimitry Andric   llvm::outs() << Message;
71945f757f3fSDimitry Andric   if (!StringRef(Message).ends_with("\n"))
7195e8d8bef9SDimitry Andric     llvm::outs() << '\n';
71965ffd83dbSDimitry Andric   return false;
71975ffd83dbSDimitry Andric }
71985ffd83dbSDimitry Andric 
71995ffd83dbSDimitry Andric // We are comparing pointers, but the pointers are relative to a single string.
72005ffd83dbSDimitry Andric // Thus, this should always be deterministic.
rewritesSort(const AsmRewrite * AsmRewriteA,const AsmRewrite * AsmRewriteB)72015ffd83dbSDimitry Andric static int rewritesSort(const AsmRewrite *AsmRewriteA,
72025ffd83dbSDimitry Andric                         const AsmRewrite *AsmRewriteB) {
72035ffd83dbSDimitry Andric   if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer())
72045ffd83dbSDimitry Andric     return -1;
72055ffd83dbSDimitry Andric   if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer())
72065ffd83dbSDimitry Andric     return 1;
72075ffd83dbSDimitry Andric 
72085ffd83dbSDimitry Andric   // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output
72095ffd83dbSDimitry Andric   // rewrite to the same location.  Make sure the SizeDirective rewrite is
72105ffd83dbSDimitry Andric   // performed first, then the Imm/ImmPrefix and finally the Input/Output.  This
72115ffd83dbSDimitry Andric   // ensures the sort algorithm is stable.
72125ffd83dbSDimitry Andric   if (AsmRewritePrecedence[AsmRewriteA->Kind] >
72135ffd83dbSDimitry Andric       AsmRewritePrecedence[AsmRewriteB->Kind])
72145ffd83dbSDimitry Andric     return -1;
72155ffd83dbSDimitry Andric 
72165ffd83dbSDimitry Andric   if (AsmRewritePrecedence[AsmRewriteA->Kind] <
72175ffd83dbSDimitry Andric       AsmRewritePrecedence[AsmRewriteB->Kind])
72185ffd83dbSDimitry Andric     return 1;
72195ffd83dbSDimitry Andric   llvm_unreachable("Unstable rewrite sort.");
72205ffd83dbSDimitry Andric }
72215ffd83dbSDimitry Andric 
defineMacro(StringRef Name,StringRef Value)7222e8d8bef9SDimitry Andric bool MasmParser::defineMacro(StringRef Name, StringRef Value) {
7223e8d8bef9SDimitry Andric   Variable &Var = Variables[Name.lower()];
7224e8d8bef9SDimitry Andric   if (Var.Name.empty()) {
7225e8d8bef9SDimitry Andric     Var.Name = Name;
7226fe6060f1SDimitry Andric   } else if (Var.Redefinable == Variable::NOT_REDEFINABLE) {
7227fe6060f1SDimitry Andric     return Error(SMLoc(), "invalid variable redefinition");
7228fe6060f1SDimitry Andric   } else if (Var.Redefinable == Variable::WARN_ON_REDEFINITION &&
7229fe6060f1SDimitry Andric              Warning(SMLoc(), "redefining '" + Name +
7230fe6060f1SDimitry Andric                                   "', already defined on the command line")) {
7231fe6060f1SDimitry Andric     return true;
7232e8d8bef9SDimitry Andric   }
7233fe6060f1SDimitry Andric   Var.Redefinable = Variable::WARN_ON_REDEFINITION;
7234e8d8bef9SDimitry Andric   Var.IsText = true;
7235e8d8bef9SDimitry Andric   Var.TextValue = Value.str();
7236e8d8bef9SDimitry Andric   return false;
72375ffd83dbSDimitry Andric }
72385ffd83dbSDimitry Andric 
lookUpField(StringRef Name,AsmFieldInfo & Info) const7239e8d8bef9SDimitry Andric bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info) const {
7240e8d8bef9SDimitry Andric   const std::pair<StringRef, StringRef> BaseMember = Name.split('.');
7241e8d8bef9SDimitry Andric   const StringRef Base = BaseMember.first, Member = BaseMember.second;
7242e8d8bef9SDimitry Andric   return lookUpField(Base, Member, Info);
7243e8d8bef9SDimitry Andric }
7244e8d8bef9SDimitry Andric 
lookUpField(StringRef Base,StringRef Member,AsmFieldInfo & Info) const7245e8d8bef9SDimitry Andric bool MasmParser::lookUpField(StringRef Base, StringRef Member,
7246e8d8bef9SDimitry Andric                              AsmFieldInfo &Info) const {
72475ffd83dbSDimitry Andric   if (Base.empty())
72485ffd83dbSDimitry Andric     return true;
72495ffd83dbSDimitry Andric 
7250e8d8bef9SDimitry Andric   AsmFieldInfo BaseInfo;
7251e8d8bef9SDimitry Andric   if (Base.contains('.') && !lookUpField(Base, BaseInfo))
7252e8d8bef9SDimitry Andric     Base = BaseInfo.Type.Name;
72535ffd83dbSDimitry Andric 
72545ffd83dbSDimitry Andric   auto StructIt = Structs.find(Base.lower());
7255e8d8bef9SDimitry Andric   auto TypeIt = KnownType.find(Base.lower());
7256e8d8bef9SDimitry Andric   if (TypeIt != KnownType.end()) {
7257e8d8bef9SDimitry Andric     StructIt = Structs.find(TypeIt->second.Name.lower());
7258e8d8bef9SDimitry Andric   }
72595ffd83dbSDimitry Andric   if (StructIt != Structs.end())
7260e8d8bef9SDimitry Andric     return lookUpField(StructIt->second, Member, Info);
72615ffd83dbSDimitry Andric 
72625ffd83dbSDimitry Andric   return true;
72635ffd83dbSDimitry Andric }
72645ffd83dbSDimitry Andric 
lookUpField(const StructInfo & Structure,StringRef Member,AsmFieldInfo & Info) const72655ffd83dbSDimitry Andric bool MasmParser::lookUpField(const StructInfo &Structure, StringRef Member,
7266e8d8bef9SDimitry Andric                              AsmFieldInfo &Info) const {
72675ffd83dbSDimitry Andric   if (Member.empty()) {
7268e8d8bef9SDimitry Andric     Info.Type.Name = Structure.Name;
7269e8d8bef9SDimitry Andric     Info.Type.Size = Structure.Size;
7270e8d8bef9SDimitry Andric     Info.Type.ElementSize = Structure.Size;
7271e8d8bef9SDimitry Andric     Info.Type.Length = 1;
72725ffd83dbSDimitry Andric     return false;
72735ffd83dbSDimitry Andric   }
72745ffd83dbSDimitry Andric 
72755ffd83dbSDimitry Andric   std::pair<StringRef, StringRef> Split = Member.split('.');
72765ffd83dbSDimitry Andric   const StringRef FieldName = Split.first, FieldMember = Split.second;
72775ffd83dbSDimitry Andric 
72785ffd83dbSDimitry Andric   auto StructIt = Structs.find(FieldName.lower());
72795ffd83dbSDimitry Andric   if (StructIt != Structs.end())
7280e8d8bef9SDimitry Andric     return lookUpField(StructIt->second, FieldMember, Info);
72815ffd83dbSDimitry Andric 
72825ffd83dbSDimitry Andric   auto FieldIt = Structure.FieldsByName.find(FieldName.lower());
72835ffd83dbSDimitry Andric   if (FieldIt == Structure.FieldsByName.end())
72845ffd83dbSDimitry Andric     return true;
72855ffd83dbSDimitry Andric 
72865ffd83dbSDimitry Andric   const FieldInfo &Field = Structure.Fields[FieldIt->second];
72875ffd83dbSDimitry Andric   if (FieldMember.empty()) {
7288e8d8bef9SDimitry Andric     Info.Offset += Field.Offset;
7289e8d8bef9SDimitry Andric     Info.Type.Size = Field.SizeOf;
7290e8d8bef9SDimitry Andric     Info.Type.ElementSize = Field.Type;
7291e8d8bef9SDimitry Andric     Info.Type.Length = Field.LengthOf;
72925ffd83dbSDimitry Andric     if (Field.Contents.FT == FT_STRUCT)
7293e8d8bef9SDimitry Andric       Info.Type.Name = Field.Contents.StructInfo.Structure.Name;
7294e8d8bef9SDimitry Andric     else
7295e8d8bef9SDimitry Andric       Info.Type.Name = "";
72965ffd83dbSDimitry Andric     return false;
72975ffd83dbSDimitry Andric   }
72985ffd83dbSDimitry Andric 
72995ffd83dbSDimitry Andric   if (Field.Contents.FT != FT_STRUCT)
73005ffd83dbSDimitry Andric     return true;
73015ffd83dbSDimitry Andric   const StructFieldInfo &StructInfo = Field.Contents.StructInfo;
73025ffd83dbSDimitry Andric 
7303e8d8bef9SDimitry Andric   if (lookUpField(StructInfo.Structure, FieldMember, Info))
73045ffd83dbSDimitry Andric     return true;
73055ffd83dbSDimitry Andric 
7306e8d8bef9SDimitry Andric   Info.Offset += Field.Offset;
73075ffd83dbSDimitry Andric   return false;
73085ffd83dbSDimitry Andric }
73095ffd83dbSDimitry Andric 
lookUpType(StringRef Name,AsmTypeInfo & Info) const7310e8d8bef9SDimitry Andric bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info) const {
7311e8d8bef9SDimitry Andric   unsigned Size = StringSwitch<unsigned>(Name)
7312e8d8bef9SDimitry Andric                       .CasesLower("byte", "db", "sbyte", 1)
7313e8d8bef9SDimitry Andric                       .CasesLower("word", "dw", "sword", 2)
7314e8d8bef9SDimitry Andric                       .CasesLower("dword", "dd", "sdword", 4)
7315e8d8bef9SDimitry Andric                       .CasesLower("fword", "df", 6)
7316e8d8bef9SDimitry Andric                       .CasesLower("qword", "dq", "sqword", 8)
7317e8d8bef9SDimitry Andric                       .CaseLower("real4", 4)
7318e8d8bef9SDimitry Andric                       .CaseLower("real8", 8)
7319e8d8bef9SDimitry Andric                       .CaseLower("real10", 10)
7320e8d8bef9SDimitry Andric                       .Default(0);
7321e8d8bef9SDimitry Andric   if (Size) {
7322e8d8bef9SDimitry Andric     Info.Name = Name;
7323e8d8bef9SDimitry Andric     Info.ElementSize = Size;
7324e8d8bef9SDimitry Andric     Info.Length = 1;
7325e8d8bef9SDimitry Andric     Info.Size = Size;
7326e8d8bef9SDimitry Andric     return false;
7327e8d8bef9SDimitry Andric   }
7328e8d8bef9SDimitry Andric 
7329e8d8bef9SDimitry Andric   auto StructIt = Structs.find(Name.lower());
7330e8d8bef9SDimitry Andric   if (StructIt != Structs.end()) {
7331e8d8bef9SDimitry Andric     const StructInfo &Structure = StructIt->second;
7332e8d8bef9SDimitry Andric     Info.Name = Name;
7333e8d8bef9SDimitry Andric     Info.ElementSize = Structure.Size;
7334e8d8bef9SDimitry Andric     Info.Length = 1;
7335e8d8bef9SDimitry Andric     Info.Size = Structure.Size;
7336e8d8bef9SDimitry Andric     return false;
7337e8d8bef9SDimitry Andric   }
7338e8d8bef9SDimitry Andric 
7339e8d8bef9SDimitry Andric   return true;
7340e8d8bef9SDimitry Andric }
7341e8d8bef9SDimitry Andric 
parseMSInlineAsm(std::string & AsmString,unsigned & NumOutputs,unsigned & NumInputs,SmallVectorImpl<std::pair<void *,bool>> & OpDecls,SmallVectorImpl<std::string> & Constraints,SmallVectorImpl<std::string> & Clobbers,const MCInstrInfo * MII,const MCInstPrinter * IP,MCAsmParserSemaCallback & SI)73425ffd83dbSDimitry Andric bool MasmParser::parseMSInlineAsm(
7343fe6060f1SDimitry Andric     std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs,
7344fe6060f1SDimitry Andric     SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
73455ffd83dbSDimitry Andric     SmallVectorImpl<std::string> &Constraints,
73465ffd83dbSDimitry Andric     SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
73475ffd83dbSDimitry Andric     const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
73485ffd83dbSDimitry Andric   SmallVector<void *, 4> InputDecls;
73495ffd83dbSDimitry Andric   SmallVector<void *, 4> OutputDecls;
73505ffd83dbSDimitry Andric   SmallVector<bool, 4> InputDeclsAddressOf;
73515ffd83dbSDimitry Andric   SmallVector<bool, 4> OutputDeclsAddressOf;
73525ffd83dbSDimitry Andric   SmallVector<std::string, 4> InputConstraints;
73535ffd83dbSDimitry Andric   SmallVector<std::string, 4> OutputConstraints;
73545ffd83dbSDimitry Andric   SmallVector<unsigned, 4> ClobberRegs;
73555ffd83dbSDimitry Andric 
73565ffd83dbSDimitry Andric   SmallVector<AsmRewrite, 4> AsmStrRewrites;
73575ffd83dbSDimitry Andric 
73585ffd83dbSDimitry Andric   // Prime the lexer.
73595ffd83dbSDimitry Andric   Lex();
73605ffd83dbSDimitry Andric 
73615ffd83dbSDimitry Andric   // While we have input, parse each statement.
73625ffd83dbSDimitry Andric   unsigned InputIdx = 0;
73635ffd83dbSDimitry Andric   unsigned OutputIdx = 0;
73645ffd83dbSDimitry Andric   while (getLexer().isNot(AsmToken::Eof)) {
73655ffd83dbSDimitry Andric     // Parse curly braces marking block start/end.
73665ffd83dbSDimitry Andric     if (parseCurlyBlockScope(AsmStrRewrites))
73675ffd83dbSDimitry Andric       continue;
73685ffd83dbSDimitry Andric 
73695ffd83dbSDimitry Andric     ParseStatementInfo Info(&AsmStrRewrites);
73705ffd83dbSDimitry Andric     bool StatementErr = parseStatement(Info, &SI);
73715ffd83dbSDimitry Andric 
73725ffd83dbSDimitry Andric     if (StatementErr || Info.ParseError) {
73735ffd83dbSDimitry Andric       // Emit pending errors if any exist.
73745ffd83dbSDimitry Andric       printPendingErrors();
73755ffd83dbSDimitry Andric       return true;
73765ffd83dbSDimitry Andric     }
73775ffd83dbSDimitry Andric 
73785ffd83dbSDimitry Andric     // No pending error should exist here.
73795ffd83dbSDimitry Andric     assert(!hasPendingError() && "unexpected error from parseStatement");
73805ffd83dbSDimitry Andric 
73815ffd83dbSDimitry Andric     if (Info.Opcode == ~0U)
73825ffd83dbSDimitry Andric       continue;
73835ffd83dbSDimitry Andric 
73845ffd83dbSDimitry Andric     const MCInstrDesc &Desc = MII->get(Info.Opcode);
73855ffd83dbSDimitry Andric 
73865ffd83dbSDimitry Andric     // Build the list of clobbers, outputs and inputs.
73875ffd83dbSDimitry Andric     for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
73885ffd83dbSDimitry Andric       MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
73895ffd83dbSDimitry Andric 
73905ffd83dbSDimitry Andric       // Register operand.
73915ffd83dbSDimitry Andric       if (Operand.isReg() && !Operand.needAddressOf() &&
73925ffd83dbSDimitry Andric           !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) {
73935ffd83dbSDimitry Andric         unsigned NumDefs = Desc.getNumDefs();
73945ffd83dbSDimitry Andric         // Clobber.
73955ffd83dbSDimitry Andric         if (NumDefs && Operand.getMCOperandNum() < NumDefs)
73965ffd83dbSDimitry Andric           ClobberRegs.push_back(Operand.getReg());
73975ffd83dbSDimitry Andric         continue;
73985ffd83dbSDimitry Andric       }
73995ffd83dbSDimitry Andric 
74005ffd83dbSDimitry Andric       // Expr/Input or Output.
74015ffd83dbSDimitry Andric       StringRef SymName = Operand.getSymName();
74025ffd83dbSDimitry Andric       if (SymName.empty())
74035ffd83dbSDimitry Andric         continue;
74045ffd83dbSDimitry Andric 
74055ffd83dbSDimitry Andric       void *OpDecl = Operand.getOpDecl();
74065ffd83dbSDimitry Andric       if (!OpDecl)
74075ffd83dbSDimitry Andric         continue;
74085ffd83dbSDimitry Andric 
74095ffd83dbSDimitry Andric       StringRef Constraint = Operand.getConstraint();
74105ffd83dbSDimitry Andric       if (Operand.isImm()) {
74115ffd83dbSDimitry Andric         // Offset as immediate.
74125ffd83dbSDimitry Andric         if (Operand.isOffsetOfLocal())
74135ffd83dbSDimitry Andric           Constraint = "r";
74145ffd83dbSDimitry Andric         else
74155ffd83dbSDimitry Andric           Constraint = "i";
74165ffd83dbSDimitry Andric       }
74175ffd83dbSDimitry Andric 
74185ffd83dbSDimitry Andric       bool isOutput = (i == 1) && Desc.mayStore();
74195ffd83dbSDimitry Andric       SMLoc Start = SMLoc::getFromPointer(SymName.data());
74205ffd83dbSDimitry Andric       if (isOutput) {
74215ffd83dbSDimitry Andric         ++InputIdx;
74225ffd83dbSDimitry Andric         OutputDecls.push_back(OpDecl);
74235ffd83dbSDimitry Andric         OutputDeclsAddressOf.push_back(Operand.needAddressOf());
74245ffd83dbSDimitry Andric         OutputConstraints.push_back(("=" + Constraint).str());
74255ffd83dbSDimitry Andric         AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size());
74265ffd83dbSDimitry Andric       } else {
74275ffd83dbSDimitry Andric         InputDecls.push_back(OpDecl);
74285ffd83dbSDimitry Andric         InputDeclsAddressOf.push_back(Operand.needAddressOf());
74295ffd83dbSDimitry Andric         InputConstraints.push_back(Constraint.str());
7430bdd1243dSDimitry Andric         if (Desc.operands()[i - 1].isBranchTarget())
74315ffd83dbSDimitry Andric           AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size());
74325ffd83dbSDimitry Andric         else
74335ffd83dbSDimitry Andric           AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
74345ffd83dbSDimitry Andric       }
74355ffd83dbSDimitry Andric     }
74365ffd83dbSDimitry Andric 
74375ffd83dbSDimitry Andric     // Consider implicit defs to be clobbers.  Think of cpuid and push.
7438bdd1243dSDimitry Andric     llvm::append_range(ClobberRegs, Desc.implicit_defs());
74395ffd83dbSDimitry Andric   }
74405ffd83dbSDimitry Andric 
74415ffd83dbSDimitry Andric   // Set the number of Outputs and Inputs.
74425ffd83dbSDimitry Andric   NumOutputs = OutputDecls.size();
74435ffd83dbSDimitry Andric   NumInputs = InputDecls.size();
74445ffd83dbSDimitry Andric 
74455ffd83dbSDimitry Andric   // Set the unique clobbers.
74465ffd83dbSDimitry Andric   array_pod_sort(ClobberRegs.begin(), ClobberRegs.end());
7447*0fca6ea1SDimitry Andric   ClobberRegs.erase(llvm::unique(ClobberRegs), ClobberRegs.end());
74485ffd83dbSDimitry Andric   Clobbers.assign(ClobberRegs.size(), std::string());
74495ffd83dbSDimitry Andric   for (unsigned I = 0, E = ClobberRegs.size(); I != E; ++I) {
74505ffd83dbSDimitry Andric     raw_string_ostream OS(Clobbers[I]);
74515ffd83dbSDimitry Andric     IP->printRegName(OS, ClobberRegs[I]);
74525ffd83dbSDimitry Andric   }
74535ffd83dbSDimitry Andric 
74545ffd83dbSDimitry Andric   // Merge the various outputs and inputs.  Output are expected first.
74555ffd83dbSDimitry Andric   if (NumOutputs || NumInputs) {
74565ffd83dbSDimitry Andric     unsigned NumExprs = NumOutputs + NumInputs;
74575ffd83dbSDimitry Andric     OpDecls.resize(NumExprs);
74585ffd83dbSDimitry Andric     Constraints.resize(NumExprs);
74595ffd83dbSDimitry Andric     for (unsigned i = 0; i < NumOutputs; ++i) {
74605ffd83dbSDimitry Andric       OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
74615ffd83dbSDimitry Andric       Constraints[i] = OutputConstraints[i];
74625ffd83dbSDimitry Andric     }
74635ffd83dbSDimitry Andric     for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
74645ffd83dbSDimitry Andric       OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
74655ffd83dbSDimitry Andric       Constraints[j] = InputConstraints[i];
74665ffd83dbSDimitry Andric     }
74675ffd83dbSDimitry Andric   }
74685ffd83dbSDimitry Andric 
74695ffd83dbSDimitry Andric   // Build the IR assembly string.
74705ffd83dbSDimitry Andric   std::string AsmStringIR;
74715ffd83dbSDimitry Andric   raw_string_ostream OS(AsmStringIR);
74725ffd83dbSDimitry Andric   StringRef ASMString =
74735ffd83dbSDimitry Andric       SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer();
74745ffd83dbSDimitry Andric   const char *AsmStart = ASMString.begin();
74755ffd83dbSDimitry Andric   const char *AsmEnd = ASMString.end();
74765ffd83dbSDimitry Andric   array_pod_sort(AsmStrRewrites.begin(), AsmStrRewrites.end(), rewritesSort);
7477*0fca6ea1SDimitry Andric   for (auto I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) {
7478*0fca6ea1SDimitry Andric     const AsmRewrite &AR = *I;
74795ffd83dbSDimitry Andric     // Check if this has already been covered by another rewrite...
74805ffd83dbSDimitry Andric     if (AR.Done)
74815ffd83dbSDimitry Andric       continue;
74825ffd83dbSDimitry Andric     AsmRewriteKind Kind = AR.Kind;
74835ffd83dbSDimitry Andric 
74845ffd83dbSDimitry Andric     const char *Loc = AR.Loc.getPointer();
74855ffd83dbSDimitry Andric     assert(Loc >= AsmStart && "Expected Loc to be at or after Start!");
74865ffd83dbSDimitry Andric 
74875ffd83dbSDimitry Andric     // Emit everything up to the immediate/expression.
74885ffd83dbSDimitry Andric     if (unsigned Len = Loc - AsmStart)
74895ffd83dbSDimitry Andric       OS << StringRef(AsmStart, Len);
74905ffd83dbSDimitry Andric 
74915ffd83dbSDimitry Andric     // Skip the original expression.
74925ffd83dbSDimitry Andric     if (Kind == AOK_Skip) {
74935ffd83dbSDimitry Andric       AsmStart = Loc + AR.Len;
74945ffd83dbSDimitry Andric       continue;
74955ffd83dbSDimitry Andric     }
74965ffd83dbSDimitry Andric 
74975ffd83dbSDimitry Andric     unsigned AdditionalSkip = 0;
74985ffd83dbSDimitry Andric     // Rewrite expressions in $N notation.
74995ffd83dbSDimitry Andric     switch (Kind) {
75005ffd83dbSDimitry Andric     default:
75015ffd83dbSDimitry Andric       break;
75025ffd83dbSDimitry Andric     case AOK_IntelExpr:
75035ffd83dbSDimitry Andric       assert(AR.IntelExp.isValid() && "cannot write invalid intel expression");
75045ffd83dbSDimitry Andric       if (AR.IntelExp.NeedBracs)
75055ffd83dbSDimitry Andric         OS << "[";
75065ffd83dbSDimitry Andric       if (AR.IntelExp.hasBaseReg())
75075ffd83dbSDimitry Andric         OS << AR.IntelExp.BaseReg;
75085ffd83dbSDimitry Andric       if (AR.IntelExp.hasIndexReg())
75095ffd83dbSDimitry Andric         OS << (AR.IntelExp.hasBaseReg() ? " + " : "")
75105ffd83dbSDimitry Andric            << AR.IntelExp.IndexReg;
75115ffd83dbSDimitry Andric       if (AR.IntelExp.Scale > 1)
75125ffd83dbSDimitry Andric         OS << " * $$" << AR.IntelExp.Scale;
75135ffd83dbSDimitry Andric       if (AR.IntelExp.hasOffset()) {
75145ffd83dbSDimitry Andric         if (AR.IntelExp.hasRegs())
75155ffd83dbSDimitry Andric           OS << " + ";
75165ffd83dbSDimitry Andric         // Fuse this rewrite with a rewrite of the offset name, if present.
75175ffd83dbSDimitry Andric         StringRef OffsetName = AR.IntelExp.OffsetName;
75185ffd83dbSDimitry Andric         SMLoc OffsetLoc = SMLoc::getFromPointer(AR.IntelExp.OffsetName.data());
75195ffd83dbSDimitry Andric         size_t OffsetLen = OffsetName.size();
75205ffd83dbSDimitry Andric         auto rewrite_it = std::find_if(
7521*0fca6ea1SDimitry Andric             I, AsmStrRewrites.end(), [&](const AsmRewrite &FusingAR) {
75225ffd83dbSDimitry Andric               return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
75235ffd83dbSDimitry Andric                      (FusingAR.Kind == AOK_Input ||
75245ffd83dbSDimitry Andric                       FusingAR.Kind == AOK_CallInput);
75255ffd83dbSDimitry Andric             });
75265ffd83dbSDimitry Andric         if (rewrite_it == AsmStrRewrites.end()) {
75275ffd83dbSDimitry Andric           OS << "offset " << OffsetName;
75285ffd83dbSDimitry Andric         } else if (rewrite_it->Kind == AOK_CallInput) {
75295ffd83dbSDimitry Andric           OS << "${" << InputIdx++ << ":P}";
75305ffd83dbSDimitry Andric           rewrite_it->Done = true;
75315ffd83dbSDimitry Andric         } else {
75325ffd83dbSDimitry Andric           OS << '$' << InputIdx++;
75335ffd83dbSDimitry Andric           rewrite_it->Done = true;
75345ffd83dbSDimitry Andric         }
75355ffd83dbSDimitry Andric       }
75365ffd83dbSDimitry Andric       if (AR.IntelExp.Imm || AR.IntelExp.emitImm())
75375ffd83dbSDimitry Andric         OS << (AR.IntelExp.emitImm() ? "$$" : " + $$") << AR.IntelExp.Imm;
75385ffd83dbSDimitry Andric       if (AR.IntelExp.NeedBracs)
75395ffd83dbSDimitry Andric         OS << "]";
75405ffd83dbSDimitry Andric       break;
75415ffd83dbSDimitry Andric     case AOK_Label:
75425ffd83dbSDimitry Andric       OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label;
75435ffd83dbSDimitry Andric       break;
75445ffd83dbSDimitry Andric     case AOK_Input:
75455ffd83dbSDimitry Andric       OS << '$' << InputIdx++;
75465ffd83dbSDimitry Andric       break;
75475ffd83dbSDimitry Andric     case AOK_CallInput:
75485ffd83dbSDimitry Andric       OS << "${" << InputIdx++ << ":P}";
75495ffd83dbSDimitry Andric       break;
75505ffd83dbSDimitry Andric     case AOK_Output:
75515ffd83dbSDimitry Andric       OS << '$' << OutputIdx++;
75525ffd83dbSDimitry Andric       break;
75535ffd83dbSDimitry Andric     case AOK_SizeDirective:
75545ffd83dbSDimitry Andric       switch (AR.Val) {
75555ffd83dbSDimitry Andric       default: break;
75565ffd83dbSDimitry Andric       case 8:  OS << "byte ptr "; break;
75575ffd83dbSDimitry Andric       case 16: OS << "word ptr "; break;
75585ffd83dbSDimitry Andric       case 32: OS << "dword ptr "; break;
75595ffd83dbSDimitry Andric       case 64: OS << "qword ptr "; break;
75605ffd83dbSDimitry Andric       case 80: OS << "xword ptr "; break;
75615ffd83dbSDimitry Andric       case 128: OS << "xmmword ptr "; break;
75625ffd83dbSDimitry Andric       case 256: OS << "ymmword ptr "; break;
75635ffd83dbSDimitry Andric       }
75645ffd83dbSDimitry Andric       break;
75655ffd83dbSDimitry Andric     case AOK_Emit:
75665ffd83dbSDimitry Andric       OS << ".byte";
75675ffd83dbSDimitry Andric       break;
75685ffd83dbSDimitry Andric     case AOK_Align: {
75695ffd83dbSDimitry Andric       // MS alignment directives are measured in bytes. If the native assembler
75705ffd83dbSDimitry Andric       // measures alignment in bytes, we can pass it straight through.
75715ffd83dbSDimitry Andric       OS << ".align";
75725ffd83dbSDimitry Andric       if (getContext().getAsmInfo()->getAlignmentIsInBytes())
75735ffd83dbSDimitry Andric         break;
75745ffd83dbSDimitry Andric 
75755ffd83dbSDimitry Andric       // Alignment is in log2 form, so print that instead and skip the original
75765ffd83dbSDimitry Andric       // immediate.
75775ffd83dbSDimitry Andric       unsigned Val = AR.Val;
75785ffd83dbSDimitry Andric       OS << ' ' << Val;
75795ffd83dbSDimitry Andric       assert(Val < 10 && "Expected alignment less then 2^10.");
75805ffd83dbSDimitry Andric       AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
75815ffd83dbSDimitry Andric       break;
75825ffd83dbSDimitry Andric     }
75835ffd83dbSDimitry Andric     case AOK_EVEN:
75845ffd83dbSDimitry Andric       OS << ".even";
75855ffd83dbSDimitry Andric       break;
75865ffd83dbSDimitry Andric     case AOK_EndOfStatement:
75875ffd83dbSDimitry Andric       OS << "\n\t";
75885ffd83dbSDimitry Andric       break;
75895ffd83dbSDimitry Andric     }
75905ffd83dbSDimitry Andric 
75915ffd83dbSDimitry Andric     // Skip the original expression.
75925ffd83dbSDimitry Andric     AsmStart = Loc + AR.Len + AdditionalSkip;
75935ffd83dbSDimitry Andric   }
75945ffd83dbSDimitry Andric 
75955ffd83dbSDimitry Andric   // Emit the remainder of the asm string.
75965ffd83dbSDimitry Andric   if (AsmStart != AsmEnd)
75975ffd83dbSDimitry Andric     OS << StringRef(AsmStart, AsmEnd - AsmStart);
75985ffd83dbSDimitry Andric 
75995ffd83dbSDimitry Andric   AsmString = OS.str();
76005ffd83dbSDimitry Andric   return false;
76015ffd83dbSDimitry Andric }
76025ffd83dbSDimitry Andric 
initializeBuiltinSymbolMap()7603fe6060f1SDimitry Andric void MasmParser::initializeBuiltinSymbolMap() {
7604fe6060f1SDimitry Andric   // Numeric built-ins (supported in all versions)
7605fe6060f1SDimitry Andric   BuiltinSymbolMap["@version"] = BI_VERSION;
7606fe6060f1SDimitry Andric   BuiltinSymbolMap["@line"] = BI_LINE;
7607fe6060f1SDimitry Andric 
7608fe6060f1SDimitry Andric   // Text built-ins (supported in all versions)
7609fe6060f1SDimitry Andric   BuiltinSymbolMap["@date"] = BI_DATE;
7610fe6060f1SDimitry Andric   BuiltinSymbolMap["@time"] = BI_TIME;
7611fe6060f1SDimitry Andric   BuiltinSymbolMap["@filecur"] = BI_FILECUR;
7612fe6060f1SDimitry Andric   BuiltinSymbolMap["@filename"] = BI_FILENAME;
7613fe6060f1SDimitry Andric   BuiltinSymbolMap["@curseg"] = BI_CURSEG;
7614fe6060f1SDimitry Andric 
7615fe6060f1SDimitry Andric   // Some built-ins exist only for MASM32 (32-bit x86)
7616fe6060f1SDimitry Andric   if (getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
7617fe6060f1SDimitry Andric       Triple::x86) {
7618fe6060f1SDimitry Andric     // Numeric built-ins
7619fe6060f1SDimitry Andric     // BuiltinSymbolMap["@cpu"] = BI_CPU;
7620fe6060f1SDimitry Andric     // BuiltinSymbolMap["@interface"] = BI_INTERFACE;
7621fe6060f1SDimitry Andric     // BuiltinSymbolMap["@wordsize"] = BI_WORDSIZE;
7622fe6060f1SDimitry Andric     // BuiltinSymbolMap["@codesize"] = BI_CODESIZE;
7623fe6060f1SDimitry Andric     // BuiltinSymbolMap["@datasize"] = BI_DATASIZE;
7624fe6060f1SDimitry Andric     // BuiltinSymbolMap["@model"] = BI_MODEL;
7625fe6060f1SDimitry Andric 
7626fe6060f1SDimitry Andric     // Text built-ins
7627fe6060f1SDimitry Andric     // BuiltinSymbolMap["@code"] = BI_CODE;
7628fe6060f1SDimitry Andric     // BuiltinSymbolMap["@data"] = BI_DATA;
7629fe6060f1SDimitry Andric     // BuiltinSymbolMap["@fardata?"] = BI_FARDATA;
7630fe6060f1SDimitry Andric     // BuiltinSymbolMap["@stack"] = BI_STACK;
7631fe6060f1SDimitry Andric   }
7632fe6060f1SDimitry Andric }
7633fe6060f1SDimitry Andric 
evaluateBuiltinValue(BuiltinSymbol Symbol,SMLoc StartLoc)7634fe6060f1SDimitry Andric const MCExpr *MasmParser::evaluateBuiltinValue(BuiltinSymbol Symbol,
7635fe6060f1SDimitry Andric                                                SMLoc StartLoc) {
7636fe6060f1SDimitry Andric   switch (Symbol) {
7637fe6060f1SDimitry Andric   default:
7638fe6060f1SDimitry Andric     return nullptr;
7639fe6060f1SDimitry Andric   case BI_VERSION:
7640fe6060f1SDimitry Andric     // Match a recent version of ML.EXE.
7641fe6060f1SDimitry Andric     return MCConstantExpr::create(1427, getContext());
7642fe6060f1SDimitry Andric   case BI_LINE: {
7643fe6060f1SDimitry Andric     int64_t Line;
7644fe6060f1SDimitry Andric     if (ActiveMacros.empty())
7645fe6060f1SDimitry Andric       Line = SrcMgr.FindLineNumber(StartLoc, CurBuffer);
7646fe6060f1SDimitry Andric     else
7647fe6060f1SDimitry Andric       Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc,
7648fe6060f1SDimitry Andric                                    ActiveMacros.front()->ExitBuffer);
7649fe6060f1SDimitry Andric     return MCConstantExpr::create(Line, getContext());
7650fe6060f1SDimitry Andric   }
7651fe6060f1SDimitry Andric   }
7652fe6060f1SDimitry Andric   llvm_unreachable("unhandled built-in symbol");
7653fe6060f1SDimitry Andric }
7654fe6060f1SDimitry Andric 
7655bdd1243dSDimitry Andric std::optional<std::string>
evaluateBuiltinTextMacro(BuiltinSymbol Symbol,SMLoc StartLoc)7656fe6060f1SDimitry Andric MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
7657fe6060f1SDimitry Andric   switch (Symbol) {
7658fe6060f1SDimitry Andric   default:
7659fe6060f1SDimitry Andric     return {};
7660fe6060f1SDimitry Andric   case BI_DATE: {
7661fe6060f1SDimitry Andric     // Current local date, formatted MM/DD/YY
7662fe6060f1SDimitry Andric     char TmpBuffer[sizeof("mm/dd/yy")];
7663fe6060f1SDimitry Andric     const size_t Len = strftime(TmpBuffer, sizeof(TmpBuffer), "%D", &TM);
7664fe6060f1SDimitry Andric     return std::string(TmpBuffer, Len);
7665fe6060f1SDimitry Andric   }
7666fe6060f1SDimitry Andric   case BI_TIME: {
7667fe6060f1SDimitry Andric     // Current local time, formatted HH:MM:SS (24-hour clock)
7668fe6060f1SDimitry Andric     char TmpBuffer[sizeof("hh:mm:ss")];
7669fe6060f1SDimitry Andric     const size_t Len = strftime(TmpBuffer, sizeof(TmpBuffer), "%T", &TM);
7670fe6060f1SDimitry Andric     return std::string(TmpBuffer, Len);
7671fe6060f1SDimitry Andric   }
7672fe6060f1SDimitry Andric   case BI_FILECUR:
7673fe6060f1SDimitry Andric     return SrcMgr
7674fe6060f1SDimitry Andric         .getMemoryBuffer(
7675fe6060f1SDimitry Andric             ActiveMacros.empty() ? CurBuffer : ActiveMacros.front()->ExitBuffer)
7676fe6060f1SDimitry Andric         ->getBufferIdentifier()
7677fe6060f1SDimitry Andric         .str();
7678fe6060f1SDimitry Andric   case BI_FILENAME:
7679fe6060f1SDimitry Andric     return sys::path::stem(SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())
7680fe6060f1SDimitry Andric                                ->getBufferIdentifier())
7681fe6060f1SDimitry Andric         .upper();
7682fe6060f1SDimitry Andric   case BI_CURSEG:
7683fe6060f1SDimitry Andric     return getStreamer().getCurrentSectionOnly()->getName().str();
7684fe6060f1SDimitry Andric   }
7685fe6060f1SDimitry Andric   llvm_unreachable("unhandled built-in symbol");
7686fe6060f1SDimitry Andric }
7687fe6060f1SDimitry Andric 
76885ffd83dbSDimitry Andric /// Create an MCAsmParser instance.
createMCMasmParser(SourceMgr & SM,MCContext & C,MCStreamer & Out,const MCAsmInfo & MAI,struct tm TM,unsigned CB)76895ffd83dbSDimitry Andric MCAsmParser *llvm::createMCMasmParser(SourceMgr &SM, MCContext &C,
76905ffd83dbSDimitry Andric                                       MCStreamer &Out, const MCAsmInfo &MAI,
7691fe6060f1SDimitry Andric                                       struct tm TM, unsigned CB) {
7692fe6060f1SDimitry Andric   return new MasmParser(SM, C, Out, MAI, TM, CB);
76935ffd83dbSDimitry Andric }
7694