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; 1145ffd83dbSDimitry Andric ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites) 1155ffd83dbSDimitry Andric : AsmRewrites(rewrites) {} 1165ffd83dbSDimitry Andric }; 1175ffd83dbSDimitry Andric 1185ffd83dbSDimitry Andric enum FieldType { 1195ffd83dbSDimitry Andric FT_INTEGRAL, // Initializer: integer expression, stored as an MCExpr. 1205ffd83dbSDimitry Andric FT_REAL, // Initializer: real number, stored as an APInt. 1215ffd83dbSDimitry Andric FT_STRUCT // Initializer: struct initializer, stored recursively. 1225ffd83dbSDimitry Andric }; 1235ffd83dbSDimitry Andric 1245ffd83dbSDimitry Andric struct FieldInfo; 1255ffd83dbSDimitry Andric struct StructInfo { 1265ffd83dbSDimitry Andric StringRef Name; 1275ffd83dbSDimitry Andric bool IsUnion = false; 128fe6060f1SDimitry Andric bool Initializable = true; 129e8d8bef9SDimitry Andric unsigned Alignment = 0; 130e8d8bef9SDimitry Andric unsigned AlignmentSize = 0; 131fe6060f1SDimitry Andric unsigned NextOffset = 0; 132fe6060f1SDimitry Andric unsigned Size = 0; 1335ffd83dbSDimitry Andric std::vector<FieldInfo> Fields; 1345ffd83dbSDimitry Andric StringMap<size_t> FieldsByName; 1355ffd83dbSDimitry Andric 136e8d8bef9SDimitry Andric FieldInfo &addField(StringRef FieldName, FieldType FT, 137e8d8bef9SDimitry Andric unsigned FieldAlignmentSize); 1385ffd83dbSDimitry Andric 1395ffd83dbSDimitry Andric StructInfo() = default; 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; 1535ffd83dbSDimitry Andric IntFieldInfo(const SmallVector<const MCExpr *, 1> &V) { Values = V; } 154*06c3fb27SDimitry 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; 1605ffd83dbSDimitry Andric RealFieldInfo(const SmallVector<APInt, 1> &V) { AsIntValues = V; } 161*06c3fb27SDimitry 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 2145ffd83dbSDimitry Andric FieldInfo(FieldType FT) : Contents(FT) {} 2155ffd83dbSDimitry Andric }; 2165ffd83dbSDimitry Andric 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 223bdd1243dSDimitry Andric StructInfo::StructInfo(StringRef StructName, bool Union, 224bdd1243dSDimitry Andric unsigned AlignmentValue) 225bdd1243dSDimitry Andric : Name(StructName), IsUnion(Union), Alignment(AlignmentValue) {} 226bdd1243dSDimitry Andric 227e8d8bef9SDimitry Andric FieldInfo &StructInfo::addField(StringRef FieldName, FieldType FT, 228e8d8bef9SDimitry Andric unsigned FieldAlignmentSize) { 2295ffd83dbSDimitry Andric if (!FieldName.empty()) 230e8d8bef9SDimitry Andric FieldsByName[FieldName.lower()] = Fields.size(); 2315ffd83dbSDimitry Andric Fields.emplace_back(FT); 2325ffd83dbSDimitry Andric FieldInfo &Field = Fields.back(); 233fe6060f1SDimitry Andric Field.Offset = 234fe6060f1SDimitry Andric llvm::alignTo(NextOffset, std::min(Alignment, FieldAlignmentSize)); 235fe6060f1SDimitry Andric if (!IsUnion) { 236fe6060f1SDimitry Andric NextOffset = std::max(NextOffset, Field.Offset); 2375ffd83dbSDimitry Andric } 238e8d8bef9SDimitry Andric AlignmentSize = std::max(AlignmentSize, FieldAlignmentSize); 2395ffd83dbSDimitry Andric return Field; 2405ffd83dbSDimitry Andric } 2415ffd83dbSDimitry Andric 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 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 270bdd1243dSDimitry Andric FieldInitializer::FieldInitializer(SmallVector<const MCExpr *, 1> &&Values) 271bdd1243dSDimitry Andric : FT(FT_INTEGRAL) { 272*06c3fb27SDimitry Andric new (&IntInfo) IntFieldInfo(std::move(Values)); 273bdd1243dSDimitry Andric } 274bdd1243dSDimitry Andric 275bdd1243dSDimitry Andric FieldInitializer::FieldInitializer(SmallVector<APInt, 1> &&AsIntValues) 276bdd1243dSDimitry Andric : FT(FT_REAL) { 277*06c3fb27SDimitry Andric new (&RealInfo) RealFieldInfo(std::move(AsIntValues)); 278bdd1243dSDimitry Andric } 279bdd1243dSDimitry Andric 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 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 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 & 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 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; 44104eeddc0SDimitry Andric CppHashInfoTy() : LineNumber(0), Buf(0) {} 4425ffd83dbSDimitry Andric }; 4435ffd83dbSDimitry Andric CppHashInfoTy CppHashInfo; 4445ffd83dbSDimitry Andric 4455ffd83dbSDimitry Andric /// The filename from the first cpp hash file line comment, if any. 4465ffd83dbSDimitry Andric StringRef FirstCppHashFilename; 4475ffd83dbSDimitry Andric 4485ffd83dbSDimitry Andric /// List of forward directional labels for diagnosis at the end. 4495ffd83dbSDimitry Andric SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels; 4505ffd83dbSDimitry Andric 4515ffd83dbSDimitry Andric /// AssemblerDialect. ~OU means unset value and use value provided by MAI. 4525ffd83dbSDimitry Andric /// Defaults to 1U, meaning Intel. 4535ffd83dbSDimitry Andric unsigned AssemblerDialect = 1U; 4545ffd83dbSDimitry Andric 4555ffd83dbSDimitry Andric /// is Darwin compatibility enabled? 4565ffd83dbSDimitry Andric bool IsDarwin = false; 4575ffd83dbSDimitry Andric 4585ffd83dbSDimitry Andric /// Are we parsing ms-style inline assembly? 4595ffd83dbSDimitry Andric bool ParsingMSInlineAsm = false; 4605ffd83dbSDimitry Andric 4615ffd83dbSDimitry Andric /// Did we already inform the user about inconsistent MD5 usage? 4625ffd83dbSDimitry Andric bool ReportedInconsistentMD5 = false; 4635ffd83dbSDimitry Andric 4645ffd83dbSDimitry Andric // Current <...> expression depth. 4655ffd83dbSDimitry Andric unsigned AngleBracketDepth = 0U; 4665ffd83dbSDimitry Andric 467e8d8bef9SDimitry Andric // Number of locals defined. 468e8d8bef9SDimitry Andric uint16_t LocalCounter = 0; 469e8d8bef9SDimitry Andric 4705ffd83dbSDimitry Andric public: 4715ffd83dbSDimitry Andric MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, 472fe6060f1SDimitry Andric const MCAsmInfo &MAI, struct tm TM, unsigned CB = 0); 4735ffd83dbSDimitry Andric MasmParser(const MasmParser &) = delete; 4745ffd83dbSDimitry Andric MasmParser &operator=(const MasmParser &) = delete; 4755ffd83dbSDimitry Andric ~MasmParser() override; 4765ffd83dbSDimitry Andric 4775ffd83dbSDimitry Andric bool Run(bool NoInitialTextSection, bool NoFinalize = false) override; 4785ffd83dbSDimitry Andric 4795ffd83dbSDimitry Andric void addDirectiveHandler(StringRef Directive, 4805ffd83dbSDimitry Andric ExtensionDirectiveHandler Handler) override { 4815ffd83dbSDimitry Andric ExtensionDirectiveMap[Directive] = Handler; 482*06c3fb27SDimitry Andric if (!DirectiveKindMap.contains(Directive)) { 4835ffd83dbSDimitry Andric DirectiveKindMap[Directive] = DK_HANDLER_DIRECTIVE; 4845ffd83dbSDimitry Andric } 4855ffd83dbSDimitry Andric } 4865ffd83dbSDimitry Andric 4875ffd83dbSDimitry Andric void addAliasForDirective(StringRef Directive, StringRef Alias) override { 4885ffd83dbSDimitry Andric DirectiveKindMap[Directive] = DirectiveKindMap[Alias]; 4895ffd83dbSDimitry Andric } 4905ffd83dbSDimitry Andric 4915ffd83dbSDimitry Andric /// @name MCAsmParser Interface 4925ffd83dbSDimitry Andric /// { 4935ffd83dbSDimitry Andric 4945ffd83dbSDimitry Andric SourceMgr &getSourceManager() override { return SrcMgr; } 4955ffd83dbSDimitry Andric MCAsmLexer &getLexer() override { return Lexer; } 4965ffd83dbSDimitry Andric MCContext &getContext() override { return Ctx; } 4975ffd83dbSDimitry Andric MCStreamer &getStreamer() override { return Out; } 4985ffd83dbSDimitry Andric 4995ffd83dbSDimitry Andric CodeViewContext &getCVContext() { return Ctx.getCVContext(); } 5005ffd83dbSDimitry Andric 5015ffd83dbSDimitry Andric unsigned getAssemblerDialect() override { 5025ffd83dbSDimitry Andric if (AssemblerDialect == ~0U) 5035ffd83dbSDimitry Andric return MAI.getAssemblerDialect(); 5045ffd83dbSDimitry Andric else 5055ffd83dbSDimitry Andric return AssemblerDialect; 5065ffd83dbSDimitry Andric } 5075ffd83dbSDimitry Andric void setAssemblerDialect(unsigned i) override { 5085ffd83dbSDimitry Andric AssemblerDialect = i; 5095ffd83dbSDimitry Andric } 5105ffd83dbSDimitry Andric 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); 519fe6060f1SDimitry Andric const AsmToken &Lex() override { return Lex(ExpandMacros); } 5205ffd83dbSDimitry Andric 5215ffd83dbSDimitry Andric void setParsingMSInlineAsm(bool V) override { 5225ffd83dbSDimitry Andric ParsingMSInlineAsm = V; 5235ffd83dbSDimitry Andric // When parsing MS inline asm, we must lex 0b1101 and 0ABCH as binary and 5245ffd83dbSDimitry Andric // hex integer literals. 5255ffd83dbSDimitry Andric Lexer.setLexMasmIntegers(V); 5265ffd83dbSDimitry Andric } 5275ffd83dbSDimitry Andric bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; } 5285ffd83dbSDimitry Andric 5295ffd83dbSDimitry Andric bool isParsingMasm() const override { return true; } 5305ffd83dbSDimitry Andric 531e8d8bef9SDimitry Andric bool defineMacro(StringRef Name, StringRef Value) override; 532e8d8bef9SDimitry Andric 533e8d8bef9SDimitry Andric bool lookUpField(StringRef Name, AsmFieldInfo &Info) const override; 534e8d8bef9SDimitry Andric bool lookUpField(StringRef Base, StringRef Member, 535e8d8bef9SDimitry Andric AsmFieldInfo &Info) const override; 536e8d8bef9SDimitry Andric 537e8d8bef9SDimitry Andric bool lookUpType(StringRef Name, AsmTypeInfo &Info) const override; 5385ffd83dbSDimitry Andric 539fe6060f1SDimitry Andric bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs, 540fe6060f1SDimitry Andric unsigned &NumInputs, 5415ffd83dbSDimitry Andric SmallVectorImpl<std::pair<void *, bool>> &OpDecls, 5425ffd83dbSDimitry Andric SmallVectorImpl<std::string> &Constraints, 5435ffd83dbSDimitry Andric SmallVectorImpl<std::string> &Clobbers, 5445ffd83dbSDimitry Andric const MCInstrInfo *MII, const MCInstPrinter *IP, 5455ffd83dbSDimitry Andric MCAsmParserSemaCallback &SI) override; 5465ffd83dbSDimitry Andric 5475ffd83dbSDimitry Andric bool parseExpression(const MCExpr *&Res); 5485ffd83dbSDimitry Andric bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override; 549e8d8bef9SDimitry Andric bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc, 550e8d8bef9SDimitry Andric AsmTypeInfo *TypeInfo) override; 5515ffd83dbSDimitry Andric bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override; 5525ffd83dbSDimitry Andric bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res, 5535ffd83dbSDimitry Andric SMLoc &EndLoc) override; 5545ffd83dbSDimitry Andric bool parseAbsoluteExpression(int64_t &Res) override; 5555ffd83dbSDimitry Andric 5565ffd83dbSDimitry Andric /// Parse a floating point expression using the float \p Semantics 5575ffd83dbSDimitry Andric /// and set \p Res to the value. 5585ffd83dbSDimitry Andric bool parseRealValue(const fltSemantics &Semantics, APInt &Res); 5595ffd83dbSDimitry Andric 5605ffd83dbSDimitry Andric /// Parse an identifier or string (as a quoted identifier) 5615ffd83dbSDimitry Andric /// and set \p Res to the identifier contents. 562fe6060f1SDimitry Andric enum IdentifierPositionKind { StandardPosition, StartOfStatement }; 563fe6060f1SDimitry Andric bool parseIdentifier(StringRef &Res, IdentifierPositionKind Position); 564fe6060f1SDimitry Andric bool parseIdentifier(StringRef &Res) override { 565fe6060f1SDimitry Andric return parseIdentifier(Res, StandardPosition); 566fe6060f1SDimitry Andric } 5675ffd83dbSDimitry Andric void eatToEndOfStatement() override; 5685ffd83dbSDimitry Andric 5695ffd83dbSDimitry Andric bool checkForValidSection() override; 5705ffd83dbSDimitry Andric 5715ffd83dbSDimitry Andric /// } 5725ffd83dbSDimitry Andric 5735ffd83dbSDimitry Andric private: 574fe6060f1SDimitry Andric bool expandMacros(); 575fe6060f1SDimitry Andric const AsmToken peekTok(bool ShouldSkipSpace = true); 576fe6060f1SDimitry Andric 5775ffd83dbSDimitry Andric bool parseStatement(ParseStatementInfo &Info, 5785ffd83dbSDimitry Andric MCAsmParserSemaCallback *SI); 5795ffd83dbSDimitry Andric bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites); 5805ffd83dbSDimitry Andric bool parseCppHashLineFilenameComment(SMLoc L); 5815ffd83dbSDimitry Andric 5825ffd83dbSDimitry Andric bool expandMacro(raw_svector_ostream &OS, StringRef Body, 5835ffd83dbSDimitry Andric ArrayRef<MCAsmMacroParameter> Parameters, 584e8d8bef9SDimitry Andric ArrayRef<MCAsmMacroArgument> A, 585e8d8bef9SDimitry Andric const std::vector<std::string> &Locals, SMLoc L); 5865ffd83dbSDimitry Andric 5875ffd83dbSDimitry Andric /// Are we inside a macro instantiation? 5885ffd83dbSDimitry Andric bool isInsideMacroInstantiation() {return !ActiveMacros.empty();} 5895ffd83dbSDimitry Andric 5905ffd83dbSDimitry Andric /// Handle entry to macro instantiation. 5915ffd83dbSDimitry Andric /// 5925ffd83dbSDimitry Andric /// \param M The macro. 5935ffd83dbSDimitry Andric /// \param NameLoc Instantiation location. 594e8d8bef9SDimitry Andric bool handleMacroEntry( 595e8d8bef9SDimitry Andric const MCAsmMacro *M, SMLoc NameLoc, 596e8d8bef9SDimitry Andric AsmToken::TokenKind ArgumentEndTok = AsmToken::EndOfStatement); 597e8d8bef9SDimitry Andric 598e8d8bef9SDimitry Andric /// Handle invocation of macro function. 599e8d8bef9SDimitry Andric /// 600e8d8bef9SDimitry Andric /// \param M The macro. 601e8d8bef9SDimitry Andric /// \param NameLoc Invocation location. 602e8d8bef9SDimitry Andric bool handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc); 6035ffd83dbSDimitry Andric 6045ffd83dbSDimitry Andric /// Handle exit from macro instantiation. 6055ffd83dbSDimitry Andric void handleMacroExit(); 6065ffd83dbSDimitry Andric 6075ffd83dbSDimitry Andric /// Extract AsmTokens for a macro argument. 608e8d8bef9SDimitry Andric bool 609e8d8bef9SDimitry Andric parseMacroArgument(const MCAsmMacroParameter *MP, MCAsmMacroArgument &MA, 610e8d8bef9SDimitry Andric AsmToken::TokenKind EndTok = AsmToken::EndOfStatement); 6115ffd83dbSDimitry Andric 6125ffd83dbSDimitry Andric /// Parse all macro arguments for a given macro. 613e8d8bef9SDimitry Andric bool 614e8d8bef9SDimitry Andric parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A, 615e8d8bef9SDimitry Andric AsmToken::TokenKind EndTok = AsmToken::EndOfStatement); 6165ffd83dbSDimitry Andric 6175ffd83dbSDimitry Andric void printMacroInstantiations(); 618e8d8bef9SDimitry Andric 619e8d8bef9SDimitry Andric bool expandStatement(SMLoc Loc); 620e8d8bef9SDimitry Andric 6215ffd83dbSDimitry Andric void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg, 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); 965*06c3fb27SDimitry Andric bool parseDirectiveCFIWindowSave(SMLoc DirectiveLoc); 9665ffd83dbSDimitry Andric bool parseDirectiveCFISections(); 9675ffd83dbSDimitry Andric bool parseDirectiveCFIStartProc(); 9685ffd83dbSDimitry Andric bool parseDirectiveCFIEndProc(); 969*06c3fb27SDimitry Andric bool parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc); 9705ffd83dbSDimitry Andric bool parseDirectiveCFIDefCfa(SMLoc DirectiveLoc); 971*06c3fb27SDimitry 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); 976*06c3fb27SDimitry Andric bool parseDirectiveCFIRememberState(SMLoc DirectiveLoc); 977*06c3fb27SDimitry Andric bool parseDirectiveCFIRestoreState(SMLoc DirectiveLoc); 9785ffd83dbSDimitry Andric bool parseDirectiveCFISameValue(SMLoc DirectiveLoc); 9795ffd83dbSDimitry Andric bool parseDirectiveCFIRestore(SMLoc DirectiveLoc); 980*06c3fb27SDimitry 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 10925ffd83dbSDimitry Andric MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, 1093fe6060f1SDimitry Andric const MCAsmInfo &MAI, struct tm TM, unsigned CB) 10945ffd83dbSDimitry Andric : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM), 1095fe6060f1SDimitry Andric CurBuffer(CB ? CB : SM.getMainFileID()), TM(TM) { 10965ffd83dbSDimitry Andric HadError = false; 10975ffd83dbSDimitry Andric // Save the old handler. 10985ffd83dbSDimitry Andric SavedDiagHandler = SrcMgr.getDiagHandler(); 10995ffd83dbSDimitry Andric SavedDiagContext = SrcMgr.getDiagContext(); 11005ffd83dbSDimitry Andric // Set our own handler which calls the saved handler. 11015ffd83dbSDimitry Andric SrcMgr.setDiagHandler(DiagHandler, this); 11025ffd83dbSDimitry Andric Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); 1103e8d8bef9SDimitry Andric EndStatementAtEOFStack.push_back(true); 11045ffd83dbSDimitry Andric 11055ffd83dbSDimitry Andric // Initialize the platform / file format parser. 1106fe6060f1SDimitry Andric switch (Ctx.getObjectFileType()) { 1107fe6060f1SDimitry Andric case MCContext::IsCOFF: 11085ffd83dbSDimitry Andric PlatformParser.reset(createCOFFMasmParser()); 11095ffd83dbSDimitry Andric break; 11105ffd83dbSDimitry Andric default: 11115ffd83dbSDimitry Andric report_fatal_error("llvm-ml currently supports only COFF output."); 11125ffd83dbSDimitry Andric break; 11135ffd83dbSDimitry Andric } 11145ffd83dbSDimitry Andric 11155ffd83dbSDimitry Andric initializeDirectiveKindMap(); 11165ffd83dbSDimitry Andric PlatformParser->Initialize(*this); 11175ffd83dbSDimitry Andric initializeCVDefRangeTypeMap(); 1118fe6060f1SDimitry Andric initializeBuiltinSymbolMap(); 11195ffd83dbSDimitry Andric 11205ffd83dbSDimitry Andric NumOfMacroInstantiations = 0; 11215ffd83dbSDimitry Andric } 11225ffd83dbSDimitry Andric 11235ffd83dbSDimitry Andric MasmParser::~MasmParser() { 11245ffd83dbSDimitry Andric assert((HadError || ActiveMacros.empty()) && 11255ffd83dbSDimitry Andric "Unexpected active macro instantiation!"); 11265ffd83dbSDimitry Andric 11275ffd83dbSDimitry Andric // Restore the saved diagnostics handler and context for use during 11285ffd83dbSDimitry Andric // finalization. 11295ffd83dbSDimitry Andric SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext); 11305ffd83dbSDimitry Andric } 11315ffd83dbSDimitry Andric 11325ffd83dbSDimitry Andric void MasmParser::printMacroInstantiations() { 11335ffd83dbSDimitry Andric // Print the active macro instantiation stack. 11345ffd83dbSDimitry Andric for (std::vector<MacroInstantiation *>::const_reverse_iterator 11355ffd83dbSDimitry Andric it = ActiveMacros.rbegin(), 11365ffd83dbSDimitry Andric ie = ActiveMacros.rend(); 11375ffd83dbSDimitry Andric it != ie; ++it) 11385ffd83dbSDimitry Andric printMessage((*it)->InstantiationLoc, SourceMgr::DK_Note, 11395ffd83dbSDimitry Andric "while in macro instantiation"); 11405ffd83dbSDimitry Andric } 11415ffd83dbSDimitry Andric 11425ffd83dbSDimitry Andric void MasmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) { 11435ffd83dbSDimitry Andric printPendingErrors(); 11445ffd83dbSDimitry Andric printMessage(L, SourceMgr::DK_Note, Msg, Range); 11455ffd83dbSDimitry Andric printMacroInstantiations(); 11465ffd83dbSDimitry Andric } 11475ffd83dbSDimitry Andric 11485ffd83dbSDimitry Andric bool MasmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) { 11495ffd83dbSDimitry Andric if (getTargetParser().getTargetOptions().MCNoWarn) 11505ffd83dbSDimitry Andric return false; 11515ffd83dbSDimitry Andric if (getTargetParser().getTargetOptions().MCFatalWarnings) 11525ffd83dbSDimitry Andric return Error(L, Msg, Range); 11535ffd83dbSDimitry Andric printMessage(L, SourceMgr::DK_Warning, Msg, Range); 11545ffd83dbSDimitry Andric printMacroInstantiations(); 11555ffd83dbSDimitry Andric return false; 11565ffd83dbSDimitry Andric } 11575ffd83dbSDimitry Andric 11585ffd83dbSDimitry Andric bool MasmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) { 11595ffd83dbSDimitry Andric HadError = true; 11605ffd83dbSDimitry Andric printMessage(L, SourceMgr::DK_Error, Msg, Range); 11615ffd83dbSDimitry Andric printMacroInstantiations(); 11625ffd83dbSDimitry Andric return true; 11635ffd83dbSDimitry Andric } 11645ffd83dbSDimitry Andric 11655ffd83dbSDimitry Andric bool MasmParser::enterIncludeFile(const std::string &Filename) { 11665ffd83dbSDimitry Andric std::string IncludedFile; 11675ffd83dbSDimitry Andric unsigned NewBuf = 11685ffd83dbSDimitry Andric SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); 11695ffd83dbSDimitry Andric if (!NewBuf) 11705ffd83dbSDimitry Andric return true; 11715ffd83dbSDimitry Andric 11725ffd83dbSDimitry Andric CurBuffer = NewBuf; 11735ffd83dbSDimitry Andric Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); 1174e8d8bef9SDimitry Andric EndStatementAtEOFStack.push_back(true); 11755ffd83dbSDimitry Andric return false; 11765ffd83dbSDimitry Andric } 11775ffd83dbSDimitry Andric 1178e8d8bef9SDimitry Andric void MasmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer, 1179e8d8bef9SDimitry Andric bool EndStatementAtEOF) { 11805ffd83dbSDimitry Andric CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc); 11815ffd83dbSDimitry Andric Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), 1182e8d8bef9SDimitry Andric Loc.getPointer(), EndStatementAtEOF); 11835ffd83dbSDimitry Andric } 11845ffd83dbSDimitry Andric 1185fe6060f1SDimitry Andric bool MasmParser::expandMacros() { 1186fe6060f1SDimitry Andric const AsmToken &Tok = getTok(); 1187fe6060f1SDimitry Andric const std::string IDLower = Tok.getIdentifier().lower(); 1188fe6060f1SDimitry Andric 1189fe6060f1SDimitry Andric const llvm::MCAsmMacro *M = getContext().lookupMacro(IDLower); 1190fe6060f1SDimitry Andric if (M && M->IsFunction && peekTok().is(AsmToken::LParen)) { 1191fe6060f1SDimitry Andric // This is a macro function invocation; expand it in place. 1192fe6060f1SDimitry Andric const SMLoc MacroLoc = Tok.getLoc(); 1193fe6060f1SDimitry Andric const StringRef MacroId = Tok.getIdentifier(); 1194fe6060f1SDimitry Andric Lexer.Lex(); 1195fe6060f1SDimitry Andric if (handleMacroInvocation(M, MacroLoc)) { 1196fe6060f1SDimitry Andric Lexer.UnLex(AsmToken(AsmToken::Error, MacroId)); 1197fe6060f1SDimitry Andric Lexer.Lex(); 1198fe6060f1SDimitry Andric } 1199fe6060f1SDimitry Andric return false; 1200fe6060f1SDimitry Andric } 1201fe6060f1SDimitry Andric 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 1229fe6060f1SDimitry Andric const AsmToken &MasmParser::Lex(ExpandKind ExpandNextToken) { 12305ffd83dbSDimitry Andric if (Lexer.getTok().is(AsmToken::Error)) 12315ffd83dbSDimitry Andric Error(Lexer.getErrLoc(), Lexer.getErr()); 12325ffd83dbSDimitry Andric 12335ffd83dbSDimitry Andric // if it's a end of statement with a comment in it 12345ffd83dbSDimitry Andric if (getTok().is(AsmToken::EndOfStatement)) { 12355ffd83dbSDimitry Andric // if this is a line comment output it. 12365ffd83dbSDimitry Andric if (!getTok().getString().empty() && getTok().getString().front() != '\n' && 12375ffd83dbSDimitry Andric getTok().getString().front() != '\r' && MAI.preserveAsmComments()) 12385ffd83dbSDimitry Andric Out.addExplicitComment(Twine(getTok().getString())); 12395ffd83dbSDimitry Andric } 12405ffd83dbSDimitry Andric 12415ffd83dbSDimitry Andric const AsmToken *tok = &Lexer.Lex(); 1242fe6060f1SDimitry Andric bool StartOfStatement = Lexer.isAtStartOfStatement(); 12435ffd83dbSDimitry Andric 1244fe6060f1SDimitry Andric while (ExpandNextToken == ExpandMacros && tok->is(AsmToken::Identifier)) { 1245fe6060f1SDimitry Andric if (StartOfStatement) { 1246fe6060f1SDimitry Andric AsmToken NextTok; 1247fe6060f1SDimitry Andric MutableArrayRef<AsmToken> Buf(NextTok); 1248fe6060f1SDimitry Andric size_t ReadCount = Lexer.peekTokens(Buf); 1249fe6060f1SDimitry Andric if (ReadCount && NextTok.is(AsmToken::Identifier) && 1250fe6060f1SDimitry Andric (NextTok.getString().equals_insensitive("equ") || 1251fe6060f1SDimitry Andric NextTok.getString().equals_insensitive("textequ"))) { 1252fe6060f1SDimitry Andric // This looks like an EQU or TEXTEQU directive; don't expand the 1253fe6060f1SDimitry Andric // identifier, allowing for redefinitions. 12545ffd83dbSDimitry Andric break; 12555ffd83dbSDimitry Andric } 12565ffd83dbSDimitry Andric } 1257fe6060f1SDimitry Andric if (expandMacros()) 1258fe6060f1SDimitry Andric break; 1259fe6060f1SDimitry Andric } 12605ffd83dbSDimitry Andric 12615ffd83dbSDimitry Andric // Parse comments here to be deferred until end of next statement. 12625ffd83dbSDimitry Andric while (tok->is(AsmToken::Comment)) { 12635ffd83dbSDimitry Andric if (MAI.preserveAsmComments()) 12645ffd83dbSDimitry Andric Out.addExplicitComment(Twine(tok->getString())); 12655ffd83dbSDimitry Andric tok = &Lexer.Lex(); 12665ffd83dbSDimitry Andric } 12675ffd83dbSDimitry Andric 1268e8d8bef9SDimitry Andric // Recognize and bypass line continuations. 1269e8d8bef9SDimitry Andric while (tok->is(AsmToken::BackSlash) && 1270fe6060f1SDimitry Andric peekTok().is(AsmToken::EndOfStatement)) { 1271e8d8bef9SDimitry Andric // Eat both the backslash and the end of statement. 1272e8d8bef9SDimitry Andric Lexer.Lex(); 1273e8d8bef9SDimitry Andric tok = &Lexer.Lex(); 1274e8d8bef9SDimitry Andric } 1275e8d8bef9SDimitry Andric 12765ffd83dbSDimitry Andric if (tok->is(AsmToken::Eof)) { 12775ffd83dbSDimitry Andric // If this is the end of an included file, pop the parent file off the 12785ffd83dbSDimitry Andric // include stack. 12795ffd83dbSDimitry Andric SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); 12805ffd83dbSDimitry Andric if (ParentIncludeLoc != SMLoc()) { 1281e8d8bef9SDimitry Andric EndStatementAtEOFStack.pop_back(); 1282e8d8bef9SDimitry Andric jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back()); 12835ffd83dbSDimitry Andric return Lex(); 12845ffd83dbSDimitry Andric } 1285e8d8bef9SDimitry Andric EndStatementAtEOFStack.pop_back(); 1286e8d8bef9SDimitry Andric assert(EndStatementAtEOFStack.empty()); 12875ffd83dbSDimitry Andric } 12885ffd83dbSDimitry Andric 12895ffd83dbSDimitry Andric return *tok; 12905ffd83dbSDimitry Andric } 12915ffd83dbSDimitry Andric 1292fe6060f1SDimitry Andric const AsmToken MasmParser::peekTok(bool ShouldSkipSpace) { 1293fe6060f1SDimitry Andric AsmToken Tok; 1294fe6060f1SDimitry Andric 1295fe6060f1SDimitry Andric MutableArrayRef<AsmToken> Buf(Tok); 1296fe6060f1SDimitry Andric size_t ReadCount = Lexer.peekTokens(Buf, ShouldSkipSpace); 1297fe6060f1SDimitry Andric 1298fe6060f1SDimitry Andric if (ReadCount == 0) { 1299fe6060f1SDimitry Andric // If this is the end of an included file, pop the parent file off the 1300fe6060f1SDimitry Andric // include stack. 1301fe6060f1SDimitry Andric SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); 1302fe6060f1SDimitry Andric if (ParentIncludeLoc != SMLoc()) { 1303fe6060f1SDimitry Andric EndStatementAtEOFStack.pop_back(); 1304fe6060f1SDimitry Andric jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back()); 1305fe6060f1SDimitry Andric return peekTok(ShouldSkipSpace); 1306fe6060f1SDimitry Andric } 1307fe6060f1SDimitry Andric EndStatementAtEOFStack.pop_back(); 1308fe6060f1SDimitry Andric assert(EndStatementAtEOFStack.empty()); 1309fe6060f1SDimitry Andric } 1310fe6060f1SDimitry Andric 1311fe6060f1SDimitry Andric assert(ReadCount == 1); 1312fe6060f1SDimitry Andric return Tok; 1313fe6060f1SDimitry Andric } 1314fe6060f1SDimitry Andric 13155ffd83dbSDimitry Andric bool MasmParser::enabledGenDwarfForAssembly() { 13165ffd83dbSDimitry Andric // Check whether the user specified -g. 13175ffd83dbSDimitry Andric if (!getContext().getGenDwarfForAssembly()) 13185ffd83dbSDimitry Andric return false; 13195ffd83dbSDimitry Andric // If we haven't encountered any .file directives (which would imply that 13205ffd83dbSDimitry Andric // the assembler source was produced with debug info already) then emit one 13215ffd83dbSDimitry Andric // describing the assembler source file itself. 13225ffd83dbSDimitry Andric if (getContext().getGenDwarfFileNumber() == 0) { 13235ffd83dbSDimitry Andric // Use the first #line directive for this, if any. It's preprocessed, so 13245ffd83dbSDimitry Andric // there is no checksum, and of course no source directive. 13255ffd83dbSDimitry Andric if (!FirstCppHashFilename.empty()) 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 13385ffd83dbSDimitry Andric bool MasmParser::Run(bool NoInitialTextSection, bool NoFinalize) { 13395ffd83dbSDimitry Andric // Create the initial section, if requested. 13405ffd83dbSDimitry Andric if (!NoInitialTextSection) 1341349cc55cSDimitry Andric Out.initSections(false, getTargetParser().getSTI()); 13425ffd83dbSDimitry Andric 13435ffd83dbSDimitry Andric // Prime the lexer. 13445ffd83dbSDimitry Andric Lex(); 13455ffd83dbSDimitry Andric 13465ffd83dbSDimitry Andric HadError = false; 13475ffd83dbSDimitry Andric AsmCond StartingCondState = TheCondState; 13485ffd83dbSDimitry Andric SmallVector<AsmRewrite, 4> AsmStrRewrites; 13495ffd83dbSDimitry Andric 13505ffd83dbSDimitry Andric // If we are generating dwarf for assembly source files save the initial text 13515ffd83dbSDimitry Andric // section. (Don't use enabledGenDwarfForAssembly() here, as we aren't 13525ffd83dbSDimitry Andric // emitting any actual debug info yet and haven't had a chance to parse any 13535ffd83dbSDimitry Andric // embedded .file directives.) 13545ffd83dbSDimitry Andric if (getContext().getGenDwarfForAssembly()) { 13555ffd83dbSDimitry Andric MCSection *Sec = getStreamer().getCurrentSectionOnly(); 13565ffd83dbSDimitry Andric if (!Sec->getBeginSymbol()) { 13575ffd83dbSDimitry Andric MCSymbol *SectionStartSym = getContext().createTempSymbol(); 13585ffd83dbSDimitry Andric getStreamer().emitLabel(SectionStartSym); 13595ffd83dbSDimitry Andric Sec->setBeginSymbol(SectionStartSym); 13605ffd83dbSDimitry Andric } 13615ffd83dbSDimitry Andric bool InsertResult = getContext().addGenDwarfSection(Sec); 13625ffd83dbSDimitry Andric assert(InsertResult && ".text section should not have debug info yet"); 13635ffd83dbSDimitry Andric (void)InsertResult; 13645ffd83dbSDimitry Andric } 13655ffd83dbSDimitry Andric 1366fe6060f1SDimitry Andric getTargetParser().onBeginOfFile(); 1367fe6060f1SDimitry Andric 13685ffd83dbSDimitry Andric // While we have input, parse each statement. 1369e8d8bef9SDimitry Andric while (Lexer.isNot(AsmToken::Eof) || 1370e8d8bef9SDimitry Andric SrcMgr.getParentIncludeLoc(CurBuffer) != SMLoc()) { 1371e8d8bef9SDimitry Andric // Skip through the EOF at the end of an inclusion. 1372e8d8bef9SDimitry Andric if (Lexer.is(AsmToken::Eof)) 1373e8d8bef9SDimitry Andric Lex(); 1374e8d8bef9SDimitry Andric 13755ffd83dbSDimitry Andric ParseStatementInfo Info(&AsmStrRewrites); 13765ffd83dbSDimitry Andric bool Parsed = parseStatement(Info, nullptr); 13775ffd83dbSDimitry Andric 13785ffd83dbSDimitry Andric // If we have a Lexer Error we are on an Error Token. Load in Lexer Error 13795ffd83dbSDimitry Andric // for printing ErrMsg via Lex() only if no (presumably better) parser error 13805ffd83dbSDimitry Andric // exists. 13815ffd83dbSDimitry Andric if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) { 13825ffd83dbSDimitry Andric Lex(); 13835ffd83dbSDimitry Andric } 13845ffd83dbSDimitry Andric 13855ffd83dbSDimitry Andric // parseStatement returned true so may need to emit an error. 13865ffd83dbSDimitry Andric printPendingErrors(); 13875ffd83dbSDimitry Andric 13885ffd83dbSDimitry Andric // Skipping to the next line if needed. 13895ffd83dbSDimitry Andric if (Parsed && !getLexer().isAtStartOfStatement()) 13905ffd83dbSDimitry Andric eatToEndOfStatement(); 13915ffd83dbSDimitry Andric } 13925ffd83dbSDimitry Andric 13935ffd83dbSDimitry Andric getTargetParser().onEndOfFile(); 13945ffd83dbSDimitry Andric printPendingErrors(); 13955ffd83dbSDimitry Andric 13965ffd83dbSDimitry Andric // All errors should have been emitted. 13975ffd83dbSDimitry Andric assert(!hasPendingError() && "unexpected error from parseStatement"); 13985ffd83dbSDimitry Andric 13995ffd83dbSDimitry Andric getTargetParser().flushPendingInstructions(getStreamer()); 14005ffd83dbSDimitry Andric 14015ffd83dbSDimitry Andric if (TheCondState.TheCond != StartingCondState.TheCond || 14025ffd83dbSDimitry Andric TheCondState.Ignore != StartingCondState.Ignore) 14035ffd83dbSDimitry Andric printError(getTok().getLoc(), "unmatched .ifs or .elses"); 14045ffd83dbSDimitry Andric // Check to see there are no empty DwarfFile slots. 14055ffd83dbSDimitry Andric const auto &LineTables = getContext().getMCDwarfLineTables(); 14065ffd83dbSDimitry Andric if (!LineTables.empty()) { 14075ffd83dbSDimitry Andric unsigned Index = 0; 14085ffd83dbSDimitry Andric for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) { 14095ffd83dbSDimitry Andric if (File.Name.empty() && Index != 0) 14105ffd83dbSDimitry Andric printError(getTok().getLoc(), "unassigned file number: " + 14115ffd83dbSDimitry Andric Twine(Index) + 14125ffd83dbSDimitry Andric " for .file directives"); 14135ffd83dbSDimitry Andric ++Index; 14145ffd83dbSDimitry Andric } 14155ffd83dbSDimitry Andric } 14165ffd83dbSDimitry Andric 14175ffd83dbSDimitry Andric // Check to see that all assembler local symbols were actually defined. 14185ffd83dbSDimitry Andric // Targets that don't do subsections via symbols may not want this, though, 14195ffd83dbSDimitry Andric // so conservatively exclude them. Only do this if we're finalizing, though, 14205ffd83dbSDimitry Andric // as otherwise we won't necessarilly have seen everything yet. 14215ffd83dbSDimitry Andric if (!NoFinalize) { 14225ffd83dbSDimitry Andric if (MAI.hasSubsectionsViaSymbols()) { 14235ffd83dbSDimitry Andric for (const auto &TableEntry : getContext().getSymbols()) { 14245ffd83dbSDimitry Andric MCSymbol *Sym = TableEntry.getValue(); 14255ffd83dbSDimitry Andric // Variable symbols may not be marked as defined, so check those 14265ffd83dbSDimitry Andric // explicitly. If we know it's a variable, we have a definition for 14275ffd83dbSDimitry Andric // the purposes of this check. 14285ffd83dbSDimitry Andric if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined()) 14295ffd83dbSDimitry Andric // FIXME: We would really like to refer back to where the symbol was 14305ffd83dbSDimitry Andric // first referenced for a source location. We need to add something 14315ffd83dbSDimitry Andric // to track that. Currently, we just point to the end of the file. 14325ffd83dbSDimitry Andric printError(getTok().getLoc(), "assembler local symbol '" + 14335ffd83dbSDimitry Andric Sym->getName() + "' not defined"); 14345ffd83dbSDimitry Andric } 14355ffd83dbSDimitry Andric } 14365ffd83dbSDimitry Andric 14375ffd83dbSDimitry Andric // Temporary symbols like the ones for directional jumps don't go in the 14385ffd83dbSDimitry Andric // symbol table. They also need to be diagnosed in all (final) cases. 14395ffd83dbSDimitry Andric for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) { 14405ffd83dbSDimitry Andric if (std::get<2>(LocSym)->isUndefined()) { 14415ffd83dbSDimitry Andric // Reset the state of any "# line file" directives we've seen to the 14425ffd83dbSDimitry Andric // context as it was at the diagnostic site. 14435ffd83dbSDimitry Andric CppHashInfo = std::get<1>(LocSym); 14445ffd83dbSDimitry Andric printError(std::get<0>(LocSym), "directional label undefined"); 14455ffd83dbSDimitry Andric } 14465ffd83dbSDimitry Andric } 14475ffd83dbSDimitry Andric } 14485ffd83dbSDimitry Andric 14495ffd83dbSDimitry Andric // Finalize the output stream if there are no errors and if the client wants 14505ffd83dbSDimitry Andric // us to. 14515ffd83dbSDimitry Andric if (!HadError && !NoFinalize) 145281ad6265SDimitry Andric Out.finish(Lexer.getLoc()); 14535ffd83dbSDimitry Andric 14545ffd83dbSDimitry Andric return HadError || getContext().hadError(); 14555ffd83dbSDimitry Andric } 14565ffd83dbSDimitry Andric 14575ffd83dbSDimitry Andric bool MasmParser::checkForValidSection() { 14585ffd83dbSDimitry Andric if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) { 1459349cc55cSDimitry Andric Out.initSections(false, getTargetParser().getSTI()); 14605ffd83dbSDimitry Andric return Error(getTok().getLoc(), 14615ffd83dbSDimitry Andric "expected section directive before assembly directive"); 14625ffd83dbSDimitry Andric } 14635ffd83dbSDimitry Andric return false; 14645ffd83dbSDimitry Andric } 14655ffd83dbSDimitry Andric 14665ffd83dbSDimitry Andric /// Throw away the rest of the line for testing purposes. 14675ffd83dbSDimitry Andric void MasmParser::eatToEndOfStatement() { 1468e8d8bef9SDimitry Andric while (Lexer.isNot(AsmToken::EndOfStatement)) { 1469e8d8bef9SDimitry Andric if (Lexer.is(AsmToken::Eof)) { 1470e8d8bef9SDimitry Andric SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); 1471e8d8bef9SDimitry Andric if (ParentIncludeLoc == SMLoc()) { 1472e8d8bef9SDimitry Andric break; 1473e8d8bef9SDimitry Andric } 1474e8d8bef9SDimitry Andric 1475e8d8bef9SDimitry Andric EndStatementAtEOFStack.pop_back(); 1476e8d8bef9SDimitry Andric jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back()); 1477e8d8bef9SDimitry Andric } 1478e8d8bef9SDimitry Andric 14795ffd83dbSDimitry Andric Lexer.Lex(); 1480e8d8bef9SDimitry Andric } 14815ffd83dbSDimitry Andric 14825ffd83dbSDimitry Andric // Eat EOL. 14835ffd83dbSDimitry Andric if (Lexer.is(AsmToken::EndOfStatement)) 14845ffd83dbSDimitry Andric Lexer.Lex(); 14855ffd83dbSDimitry Andric } 14865ffd83dbSDimitry Andric 1487e8d8bef9SDimitry Andric SmallVector<StringRef, 1> 1488e8d8bef9SDimitry Andric MasmParser::parseStringRefsTo(AsmToken::TokenKind EndTok) { 1489e8d8bef9SDimitry Andric SmallVector<StringRef, 1> Refs; 1490e8d8bef9SDimitry Andric const char *Start = getTok().getLoc().getPointer(); 1491e8d8bef9SDimitry Andric while (Lexer.isNot(EndTok)) { 1492e8d8bef9SDimitry Andric if (Lexer.is(AsmToken::Eof)) { 1493e8d8bef9SDimitry Andric SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); 1494e8d8bef9SDimitry Andric if (ParentIncludeLoc == SMLoc()) { 1495e8d8bef9SDimitry Andric break; 1496e8d8bef9SDimitry Andric } 1497e8d8bef9SDimitry Andric Refs.emplace_back(Start, getTok().getLoc().getPointer() - Start); 1498e8d8bef9SDimitry Andric 1499e8d8bef9SDimitry Andric EndStatementAtEOFStack.pop_back(); 1500e8d8bef9SDimitry Andric jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back()); 1501e8d8bef9SDimitry Andric Lexer.Lex(); 1502e8d8bef9SDimitry Andric Start = getTok().getLoc().getPointer(); 1503e8d8bef9SDimitry Andric } else { 1504e8d8bef9SDimitry Andric Lexer.Lex(); 1505e8d8bef9SDimitry Andric } 1506e8d8bef9SDimitry Andric } 1507e8d8bef9SDimitry Andric Refs.emplace_back(Start, getTok().getLoc().getPointer() - Start); 1508e8d8bef9SDimitry Andric return Refs; 1509e8d8bef9SDimitry Andric } 1510e8d8bef9SDimitry Andric 1511e8d8bef9SDimitry Andric std::string MasmParser::parseStringTo(AsmToken::TokenKind EndTok) { 1512e8d8bef9SDimitry Andric SmallVector<StringRef, 1> Refs = parseStringRefsTo(EndTok); 1513e8d8bef9SDimitry Andric std::string Str; 1514e8d8bef9SDimitry Andric for (StringRef S : Refs) { 1515e8d8bef9SDimitry Andric Str.append(S.str()); 1516e8d8bef9SDimitry Andric } 1517e8d8bef9SDimitry Andric return Str; 1518e8d8bef9SDimitry Andric } 1519e8d8bef9SDimitry Andric 15205ffd83dbSDimitry Andric StringRef MasmParser::parseStringToEndOfStatement() { 15215ffd83dbSDimitry Andric const char *Start = getTok().getLoc().getPointer(); 15225ffd83dbSDimitry Andric 15235ffd83dbSDimitry Andric while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof)) 15245ffd83dbSDimitry Andric Lexer.Lex(); 15255ffd83dbSDimitry Andric 15265ffd83dbSDimitry Andric const char *End = getTok().getLoc().getPointer(); 15275ffd83dbSDimitry Andric return StringRef(Start, End - Start); 15285ffd83dbSDimitry Andric } 15295ffd83dbSDimitry Andric 15305ffd83dbSDimitry Andric /// Parse a paren expression and return it. 15315ffd83dbSDimitry Andric /// NOTE: This assumes the leading '(' has already been consumed. 15325ffd83dbSDimitry Andric /// 15335ffd83dbSDimitry Andric /// parenexpr ::= expr) 15345ffd83dbSDimitry Andric /// 15355ffd83dbSDimitry Andric bool MasmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) { 15365ffd83dbSDimitry Andric if (parseExpression(Res)) 15375ffd83dbSDimitry Andric return true; 15385ffd83dbSDimitry Andric EndLoc = Lexer.getTok().getEndLoc(); 153904eeddc0SDimitry Andric return parseRParen(); 15405ffd83dbSDimitry Andric } 15415ffd83dbSDimitry Andric 15425ffd83dbSDimitry Andric /// Parse a bracket expression and return it. 15435ffd83dbSDimitry Andric /// NOTE: This assumes the leading '[' has already been consumed. 15445ffd83dbSDimitry Andric /// 15455ffd83dbSDimitry Andric /// bracketexpr ::= expr] 15465ffd83dbSDimitry Andric /// 15475ffd83dbSDimitry Andric bool MasmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) { 15485ffd83dbSDimitry Andric if (parseExpression(Res)) 15495ffd83dbSDimitry Andric return true; 15505ffd83dbSDimitry Andric EndLoc = getTok().getEndLoc(); 15515ffd83dbSDimitry Andric if (parseToken(AsmToken::RBrac, "expected ']' in brackets expression")) 15525ffd83dbSDimitry Andric return true; 15535ffd83dbSDimitry Andric return false; 15545ffd83dbSDimitry Andric } 15555ffd83dbSDimitry Andric 15565ffd83dbSDimitry Andric /// Parse a primary expression and return it. 15575ffd83dbSDimitry Andric /// primaryexpr ::= (parenexpr 15585ffd83dbSDimitry Andric /// primaryexpr ::= symbol 15595ffd83dbSDimitry Andric /// primaryexpr ::= number 15605ffd83dbSDimitry Andric /// primaryexpr ::= '.' 1561e8d8bef9SDimitry Andric /// primaryexpr ::= ~,+,-,'not' primaryexpr 1562e8d8bef9SDimitry Andric /// primaryexpr ::= string 1563e8d8bef9SDimitry Andric /// (a string is interpreted as a 64-bit number in big-endian base-256) 1564e8d8bef9SDimitry Andric bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc, 1565e8d8bef9SDimitry Andric AsmTypeInfo *TypeInfo) { 15665ffd83dbSDimitry Andric SMLoc FirstTokenLoc = getLexer().getLoc(); 15675ffd83dbSDimitry Andric AsmToken::TokenKind FirstTokenKind = Lexer.getKind(); 15685ffd83dbSDimitry Andric switch (FirstTokenKind) { 15695ffd83dbSDimitry Andric default: 15705ffd83dbSDimitry Andric return TokError("unknown token in expression"); 15715ffd83dbSDimitry Andric // If we have an error assume that we've already handled it. 15725ffd83dbSDimitry Andric case AsmToken::Error: 15735ffd83dbSDimitry Andric return true; 15745ffd83dbSDimitry Andric case AsmToken::Exclaim: 15755ffd83dbSDimitry Andric Lex(); // Eat the operator. 1576e8d8bef9SDimitry Andric if (parsePrimaryExpr(Res, EndLoc, nullptr)) 15775ffd83dbSDimitry Andric return true; 15785ffd83dbSDimitry Andric Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc); 15795ffd83dbSDimitry Andric return false; 15805ffd83dbSDimitry Andric case AsmToken::Dollar: 15815ffd83dbSDimitry Andric case AsmToken::At: 15825ffd83dbSDimitry Andric case AsmToken::Identifier: { 15835ffd83dbSDimitry Andric StringRef Identifier; 15845ffd83dbSDimitry Andric if (parseIdentifier(Identifier)) { 15855ffd83dbSDimitry Andric // We may have failed but $ may be a valid token. 15865ffd83dbSDimitry Andric if (getTok().is(AsmToken::Dollar)) { 15875ffd83dbSDimitry Andric if (Lexer.getMAI().getDollarIsPC()) { 15885ffd83dbSDimitry Andric Lex(); 15895ffd83dbSDimitry Andric // This is a '$' reference, which references the current PC. Emit a 15905ffd83dbSDimitry Andric // temporary label to the streamer and refer to it. 15915ffd83dbSDimitry Andric MCSymbol *Sym = Ctx.createTempSymbol(); 15925ffd83dbSDimitry Andric Out.emitLabel(Sym); 15935ffd83dbSDimitry Andric Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, 15945ffd83dbSDimitry Andric getContext()); 15955ffd83dbSDimitry Andric EndLoc = FirstTokenLoc; 15965ffd83dbSDimitry Andric return false; 15975ffd83dbSDimitry Andric } 15985ffd83dbSDimitry Andric return Error(FirstTokenLoc, "invalid token in expression"); 15995ffd83dbSDimitry Andric } 16005ffd83dbSDimitry Andric } 1601e8d8bef9SDimitry Andric // Parse named bitwise negation. 1602fe6060f1SDimitry Andric if (Identifier.equals_insensitive("not")) { 1603e8d8bef9SDimitry Andric if (parsePrimaryExpr(Res, EndLoc, nullptr)) 1604e8d8bef9SDimitry Andric return true; 1605e8d8bef9SDimitry Andric Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc); 1606e8d8bef9SDimitry Andric return false; 1607e8d8bef9SDimitry Andric } 1608753f127fSDimitry Andric // Parse directional local label references. 1609753f127fSDimitry Andric if (Identifier.equals_insensitive("@b") || 1610753f127fSDimitry Andric Identifier.equals_insensitive("@f")) { 1611753f127fSDimitry Andric bool Before = Identifier.equals_insensitive("@b"); 1612753f127fSDimitry Andric MCSymbol *Sym = getContext().getDirectionalLocalSymbol(0, Before); 1613753f127fSDimitry Andric if (Before && Sym->isUndefined()) 1614753f127fSDimitry Andric return Error(FirstTokenLoc, "Expected @@ label before @B reference"); 1615753f127fSDimitry Andric Res = MCSymbolRefExpr::create(Sym, getContext()); 1616753f127fSDimitry Andric return false; 1617753f127fSDimitry Andric } 16185ffd83dbSDimitry Andric // Parse symbol variant. 16195ffd83dbSDimitry Andric std::pair<StringRef, StringRef> Split; 16205ffd83dbSDimitry Andric if (!MAI.useParensForSymbolVariant()) { 16215ffd83dbSDimitry Andric Split = Identifier.split('@'); 16225ffd83dbSDimitry Andric } else if (Lexer.is(AsmToken::LParen)) { 16235ffd83dbSDimitry Andric Lex(); // eat '('. 16245ffd83dbSDimitry Andric StringRef VName; 16255ffd83dbSDimitry Andric parseIdentifier(VName); 16265ffd83dbSDimitry Andric // eat ')'. 16275ffd83dbSDimitry Andric if (parseToken(AsmToken::RParen, 16285ffd83dbSDimitry Andric "unexpected token in variant, expected ')'")) 16295ffd83dbSDimitry Andric return true; 16305ffd83dbSDimitry Andric Split = std::make_pair(Identifier, VName); 16315ffd83dbSDimitry Andric } 16325ffd83dbSDimitry Andric 16335ffd83dbSDimitry Andric EndLoc = SMLoc::getFromPointer(Identifier.end()); 16345ffd83dbSDimitry Andric 16355ffd83dbSDimitry Andric // This is a symbol reference. 16365ffd83dbSDimitry Andric StringRef SymbolName = Identifier; 16375ffd83dbSDimitry Andric if (SymbolName.empty()) 16385ffd83dbSDimitry Andric return Error(getLexer().getLoc(), "expected a symbol reference"); 16395ffd83dbSDimitry Andric 16405ffd83dbSDimitry Andric MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; 16415ffd83dbSDimitry Andric 16425ffd83dbSDimitry Andric // Look up the symbol variant if used. 16435ffd83dbSDimitry Andric if (!Split.second.empty()) { 16445ffd83dbSDimitry Andric Variant = MCSymbolRefExpr::getVariantKindForName(Split.second); 16455ffd83dbSDimitry Andric if (Variant != MCSymbolRefExpr::VK_Invalid) { 16465ffd83dbSDimitry Andric SymbolName = Split.first; 16475ffd83dbSDimitry Andric } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) { 16485ffd83dbSDimitry Andric Variant = MCSymbolRefExpr::VK_None; 16495ffd83dbSDimitry Andric } else { 16505ffd83dbSDimitry Andric return Error(SMLoc::getFromPointer(Split.second.begin()), 16515ffd83dbSDimitry Andric "invalid variant '" + Split.second + "'"); 16525ffd83dbSDimitry Andric } 16535ffd83dbSDimitry Andric } 16545ffd83dbSDimitry Andric 16555ffd83dbSDimitry Andric // Find the field offset if used. 1656e8d8bef9SDimitry Andric AsmFieldInfo Info; 16575ffd83dbSDimitry Andric Split = SymbolName.split('.'); 1658e8d8bef9SDimitry Andric if (Split.second.empty()) { 1659e8d8bef9SDimitry Andric } else { 16605ffd83dbSDimitry Andric SymbolName = Split.first; 1661e8d8bef9SDimitry Andric if (lookUpField(SymbolName, Split.second, Info)) { 16625ffd83dbSDimitry Andric std::pair<StringRef, StringRef> BaseMember = Split.second.split('.'); 16635ffd83dbSDimitry Andric StringRef Base = BaseMember.first, Member = BaseMember.second; 1664e8d8bef9SDimitry Andric lookUpField(Base, Member, Info); 1665e8d8bef9SDimitry Andric } else if (Structs.count(SymbolName.lower())) { 1666e8d8bef9SDimitry Andric // This is actually a reference to a field offset. 1667e8d8bef9SDimitry Andric Res = MCConstantExpr::create(Info.Offset, getContext()); 1668e8d8bef9SDimitry Andric return false; 16695ffd83dbSDimitry Andric } 16705ffd83dbSDimitry Andric } 16715ffd83dbSDimitry Andric 16725ffd83dbSDimitry Andric MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName); 1673fe6060f1SDimitry Andric if (!Sym) { 1674fe6060f1SDimitry Andric // If this is a built-in numeric value, treat it as a constant. 1675fe6060f1SDimitry Andric auto BuiltinIt = BuiltinSymbolMap.find(SymbolName.lower()); 1676fe6060f1SDimitry Andric const BuiltinSymbol Symbol = (BuiltinIt == BuiltinSymbolMap.end()) 1677fe6060f1SDimitry Andric ? BI_NO_SYMBOL 1678fe6060f1SDimitry Andric : BuiltinIt->getValue(); 1679fe6060f1SDimitry Andric if (Symbol != BI_NO_SYMBOL) { 1680fe6060f1SDimitry Andric const MCExpr *Value = evaluateBuiltinValue(Symbol, FirstTokenLoc); 1681fe6060f1SDimitry Andric if (Value) { 1682fe6060f1SDimitry Andric Res = Value; 1683fe6060f1SDimitry Andric return false; 1684fe6060f1SDimitry Andric } 1685fe6060f1SDimitry Andric } 1686fe6060f1SDimitry Andric 1687fe6060f1SDimitry Andric // Variables use case-insensitive symbol names; if this is a variable, we 1688fe6060f1SDimitry Andric // find the symbol using its canonical name. 1689fe6060f1SDimitry Andric auto VarIt = Variables.find(SymbolName.lower()); 1690fe6060f1SDimitry Andric if (VarIt != Variables.end()) 1691fe6060f1SDimitry Andric SymbolName = VarIt->second.Name; 16925ffd83dbSDimitry Andric Sym = getContext().getOrCreateSymbol(SymbolName); 1693fe6060f1SDimitry Andric } 16945ffd83dbSDimitry Andric 16955ffd83dbSDimitry Andric // If this is an absolute variable reference, substitute it now to preserve 16965ffd83dbSDimitry Andric // semantics in the face of reassignment. 16975ffd83dbSDimitry Andric if (Sym->isVariable()) { 1698fe6060f1SDimitry Andric auto V = Sym->getVariableValue(/*SetUsed=*/false); 16995ffd83dbSDimitry Andric bool DoInline = isa<MCConstantExpr>(V) && !Variant; 17005ffd83dbSDimitry Andric if (auto TV = dyn_cast<MCTargetExpr>(V)) 17015ffd83dbSDimitry Andric DoInline = TV->inlineAssignedExpr(); 17025ffd83dbSDimitry Andric if (DoInline) { 17035ffd83dbSDimitry Andric if (Variant) 17045ffd83dbSDimitry Andric return Error(EndLoc, "unexpected modifier on variable reference"); 1705fe6060f1SDimitry Andric Res = Sym->getVariableValue(/*SetUsed=*/false); 17065ffd83dbSDimitry Andric return false; 17075ffd83dbSDimitry Andric } 17085ffd83dbSDimitry Andric } 17095ffd83dbSDimitry Andric 17105ffd83dbSDimitry Andric // Otherwise create a symbol ref. 17115ffd83dbSDimitry Andric const MCExpr *SymRef = 17125ffd83dbSDimitry Andric MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc); 1713e8d8bef9SDimitry Andric if (Info.Offset) { 1714e8d8bef9SDimitry Andric Res = MCBinaryExpr::create( 1715e8d8bef9SDimitry Andric MCBinaryExpr::Add, SymRef, 1716e8d8bef9SDimitry Andric MCConstantExpr::create(Info.Offset, getContext()), getContext()); 17175ffd83dbSDimitry Andric } else { 17185ffd83dbSDimitry Andric Res = SymRef; 17195ffd83dbSDimitry Andric } 1720e8d8bef9SDimitry Andric if (TypeInfo) { 1721e8d8bef9SDimitry Andric if (Info.Type.Name.empty()) { 1722e8d8bef9SDimitry Andric auto TypeIt = KnownType.find(Identifier.lower()); 1723e8d8bef9SDimitry Andric if (TypeIt != KnownType.end()) { 1724e8d8bef9SDimitry Andric Info.Type = TypeIt->second; 1725e8d8bef9SDimitry Andric } 1726e8d8bef9SDimitry Andric } 1727e8d8bef9SDimitry Andric 1728e8d8bef9SDimitry Andric *TypeInfo = Info.Type; 1729e8d8bef9SDimitry Andric } 17305ffd83dbSDimitry Andric return false; 17315ffd83dbSDimitry Andric } 17325ffd83dbSDimitry Andric case AsmToken::BigNum: 17335ffd83dbSDimitry Andric return TokError("literal value out of range for directive"); 17345ffd83dbSDimitry Andric case AsmToken::Integer: { 17355ffd83dbSDimitry Andric int64_t IntVal = getTok().getIntVal(); 17365ffd83dbSDimitry Andric Res = MCConstantExpr::create(IntVal, getContext()); 17375ffd83dbSDimitry Andric EndLoc = Lexer.getTok().getEndLoc(); 17385ffd83dbSDimitry Andric Lex(); // Eat token. 17395ffd83dbSDimitry Andric return false; 17405ffd83dbSDimitry Andric } 1741e8d8bef9SDimitry Andric case AsmToken::String: { 1742e8d8bef9SDimitry Andric // MASM strings (used as constants) are interpreted as big-endian base-256. 1743e8d8bef9SDimitry Andric SMLoc ValueLoc = getTok().getLoc(); 1744e8d8bef9SDimitry Andric std::string Value; 1745e8d8bef9SDimitry Andric if (parseEscapedString(Value)) 1746e8d8bef9SDimitry Andric return true; 1747e8d8bef9SDimitry Andric if (Value.size() > 8) 1748e8d8bef9SDimitry Andric return Error(ValueLoc, "literal value out of range"); 1749e8d8bef9SDimitry Andric uint64_t IntValue = 0; 1750e8d8bef9SDimitry Andric for (const unsigned char CharVal : Value) 1751e8d8bef9SDimitry Andric IntValue = (IntValue << 8) | CharVal; 1752e8d8bef9SDimitry Andric Res = MCConstantExpr::create(IntValue, getContext()); 1753e8d8bef9SDimitry Andric return false; 1754e8d8bef9SDimitry Andric } 17555ffd83dbSDimitry Andric case AsmToken::Real: { 17565ffd83dbSDimitry Andric APFloat RealVal(APFloat::IEEEdouble(), getTok().getString()); 17575ffd83dbSDimitry Andric uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue(); 17585ffd83dbSDimitry Andric Res = MCConstantExpr::create(IntVal, getContext()); 17595ffd83dbSDimitry Andric EndLoc = Lexer.getTok().getEndLoc(); 17605ffd83dbSDimitry Andric Lex(); // Eat token. 17615ffd83dbSDimitry Andric return false; 17625ffd83dbSDimitry Andric } 17635ffd83dbSDimitry Andric case AsmToken::Dot: { 17645ffd83dbSDimitry Andric // This is a '.' reference, which references the current PC. Emit a 17655ffd83dbSDimitry Andric // temporary label to the streamer and refer to it. 17665ffd83dbSDimitry Andric MCSymbol *Sym = Ctx.createTempSymbol(); 17675ffd83dbSDimitry Andric Out.emitLabel(Sym); 17685ffd83dbSDimitry Andric Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 17695ffd83dbSDimitry Andric EndLoc = Lexer.getTok().getEndLoc(); 17705ffd83dbSDimitry Andric Lex(); // Eat identifier. 17715ffd83dbSDimitry Andric return false; 17725ffd83dbSDimitry Andric } 17735ffd83dbSDimitry Andric case AsmToken::LParen: 17745ffd83dbSDimitry Andric Lex(); // Eat the '('. 17755ffd83dbSDimitry Andric return parseParenExpr(Res, EndLoc); 17765ffd83dbSDimitry Andric case AsmToken::LBrac: 17775ffd83dbSDimitry Andric if (!PlatformParser->HasBracketExpressions()) 17785ffd83dbSDimitry Andric return TokError("brackets expression not supported on this target"); 17795ffd83dbSDimitry Andric Lex(); // Eat the '['. 17805ffd83dbSDimitry Andric return parseBracketExpr(Res, EndLoc); 17815ffd83dbSDimitry Andric case AsmToken::Minus: 17825ffd83dbSDimitry Andric Lex(); // Eat the operator. 1783e8d8bef9SDimitry Andric if (parsePrimaryExpr(Res, EndLoc, nullptr)) 17845ffd83dbSDimitry Andric return true; 17855ffd83dbSDimitry Andric Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc); 17865ffd83dbSDimitry Andric return false; 17875ffd83dbSDimitry Andric case AsmToken::Plus: 17885ffd83dbSDimitry Andric Lex(); // Eat the operator. 1789e8d8bef9SDimitry Andric if (parsePrimaryExpr(Res, EndLoc, nullptr)) 17905ffd83dbSDimitry Andric return true; 17915ffd83dbSDimitry Andric Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc); 17925ffd83dbSDimitry Andric return false; 17935ffd83dbSDimitry Andric case AsmToken::Tilde: 17945ffd83dbSDimitry Andric Lex(); // Eat the operator. 1795e8d8bef9SDimitry Andric if (parsePrimaryExpr(Res, EndLoc, nullptr)) 17965ffd83dbSDimitry Andric return true; 17975ffd83dbSDimitry Andric Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc); 17985ffd83dbSDimitry Andric return false; 17995ffd83dbSDimitry Andric // MIPS unary expression operators. The lexer won't generate these tokens if 18005ffd83dbSDimitry Andric // MCAsmInfo::HasMipsExpressions is false for the target. 18015ffd83dbSDimitry Andric case AsmToken::PercentCall16: 18025ffd83dbSDimitry Andric case AsmToken::PercentCall_Hi: 18035ffd83dbSDimitry Andric case AsmToken::PercentCall_Lo: 18045ffd83dbSDimitry Andric case AsmToken::PercentDtprel_Hi: 18055ffd83dbSDimitry Andric case AsmToken::PercentDtprel_Lo: 18065ffd83dbSDimitry Andric case AsmToken::PercentGot: 18075ffd83dbSDimitry Andric case AsmToken::PercentGot_Disp: 18085ffd83dbSDimitry Andric case AsmToken::PercentGot_Hi: 18095ffd83dbSDimitry Andric case AsmToken::PercentGot_Lo: 18105ffd83dbSDimitry Andric case AsmToken::PercentGot_Ofst: 18115ffd83dbSDimitry Andric case AsmToken::PercentGot_Page: 18125ffd83dbSDimitry Andric case AsmToken::PercentGottprel: 18135ffd83dbSDimitry Andric case AsmToken::PercentGp_Rel: 18145ffd83dbSDimitry Andric case AsmToken::PercentHi: 18155ffd83dbSDimitry Andric case AsmToken::PercentHigher: 18165ffd83dbSDimitry Andric case AsmToken::PercentHighest: 18175ffd83dbSDimitry Andric case AsmToken::PercentLo: 18185ffd83dbSDimitry Andric case AsmToken::PercentNeg: 18195ffd83dbSDimitry Andric case AsmToken::PercentPcrel_Hi: 18205ffd83dbSDimitry Andric case AsmToken::PercentPcrel_Lo: 18215ffd83dbSDimitry Andric case AsmToken::PercentTlsgd: 18225ffd83dbSDimitry Andric case AsmToken::PercentTlsldm: 18235ffd83dbSDimitry Andric case AsmToken::PercentTprel_Hi: 18245ffd83dbSDimitry Andric case AsmToken::PercentTprel_Lo: 18255ffd83dbSDimitry Andric Lex(); // Eat the operator. 18265ffd83dbSDimitry Andric if (Lexer.isNot(AsmToken::LParen)) 18275ffd83dbSDimitry Andric return TokError("expected '(' after operator"); 18285ffd83dbSDimitry Andric Lex(); // Eat the operator. 18295ffd83dbSDimitry Andric if (parseExpression(Res, EndLoc)) 18305ffd83dbSDimitry Andric return true; 183104eeddc0SDimitry Andric if (parseRParen()) 183204eeddc0SDimitry Andric return true; 18335ffd83dbSDimitry Andric Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx); 18345ffd83dbSDimitry Andric return !Res; 18355ffd83dbSDimitry Andric } 18365ffd83dbSDimitry Andric } 18375ffd83dbSDimitry Andric 18385ffd83dbSDimitry Andric bool MasmParser::parseExpression(const MCExpr *&Res) { 18395ffd83dbSDimitry Andric SMLoc EndLoc; 18405ffd83dbSDimitry Andric return parseExpression(Res, EndLoc); 18415ffd83dbSDimitry Andric } 18425ffd83dbSDimitry Andric 18435ffd83dbSDimitry Andric /// This function checks if the next token is <string> type or arithmetic. 18445ffd83dbSDimitry Andric /// string that begin with character '<' must end with character '>'. 18455ffd83dbSDimitry Andric /// otherwise it is arithmetics. 18465ffd83dbSDimitry Andric /// If the function returns a 'true' value, 18475ffd83dbSDimitry Andric /// the End argument will be filled with the last location pointed to the '>' 18485ffd83dbSDimitry Andric /// character. 18495ffd83dbSDimitry Andric static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) { 18505ffd83dbSDimitry Andric assert((StrLoc.getPointer() != nullptr) && 18515ffd83dbSDimitry Andric "Argument to the function cannot be a NULL value"); 18525ffd83dbSDimitry Andric const char *CharPtr = StrLoc.getPointer(); 18535ffd83dbSDimitry Andric while ((*CharPtr != '>') && (*CharPtr != '\n') && (*CharPtr != '\r') && 18545ffd83dbSDimitry Andric (*CharPtr != '\0')) { 18555ffd83dbSDimitry Andric if (*CharPtr == '!') 18565ffd83dbSDimitry Andric CharPtr++; 18575ffd83dbSDimitry Andric CharPtr++; 18585ffd83dbSDimitry Andric } 18595ffd83dbSDimitry Andric if (*CharPtr == '>') { 18605ffd83dbSDimitry Andric EndLoc = StrLoc.getFromPointer(CharPtr + 1); 18615ffd83dbSDimitry Andric return true; 18625ffd83dbSDimitry Andric } 18635ffd83dbSDimitry Andric return false; 18645ffd83dbSDimitry Andric } 18655ffd83dbSDimitry Andric 18665ffd83dbSDimitry Andric /// creating a string without the escape characters '!'. 1867e8d8bef9SDimitry Andric static std::string angleBracketString(StringRef BracketContents) { 18685ffd83dbSDimitry Andric std::string Res; 1869e8d8bef9SDimitry Andric for (size_t Pos = 0; Pos < BracketContents.size(); Pos++) { 1870e8d8bef9SDimitry Andric if (BracketContents[Pos] == '!') 18715ffd83dbSDimitry Andric Pos++; 1872e8d8bef9SDimitry Andric Res += BracketContents[Pos]; 18735ffd83dbSDimitry Andric } 18745ffd83dbSDimitry Andric return Res; 18755ffd83dbSDimitry Andric } 18765ffd83dbSDimitry Andric 18775ffd83dbSDimitry Andric /// Parse an expression and return it. 18785ffd83dbSDimitry Andric /// 18795ffd83dbSDimitry Andric /// expr ::= expr &&,|| expr -> lowest. 18805ffd83dbSDimitry Andric /// expr ::= expr |,^,&,! expr 18815ffd83dbSDimitry Andric /// expr ::= expr ==,!=,<>,<,<=,>,>= expr 18825ffd83dbSDimitry Andric /// expr ::= expr <<,>> expr 18835ffd83dbSDimitry Andric /// expr ::= expr +,- expr 18845ffd83dbSDimitry Andric /// expr ::= expr *,/,% expr -> highest. 18855ffd83dbSDimitry Andric /// expr ::= primaryexpr 18865ffd83dbSDimitry Andric /// 18875ffd83dbSDimitry Andric bool MasmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) { 18885ffd83dbSDimitry Andric // Parse the expression. 18895ffd83dbSDimitry Andric Res = nullptr; 18905ffd83dbSDimitry Andric if (getTargetParser().parsePrimaryExpr(Res, EndLoc) || 18915ffd83dbSDimitry Andric parseBinOpRHS(1, Res, EndLoc)) 18925ffd83dbSDimitry Andric return true; 18935ffd83dbSDimitry Andric 18945ffd83dbSDimitry Andric // Try to constant fold it up front, if possible. Do not exploit 18955ffd83dbSDimitry Andric // assembler here. 18965ffd83dbSDimitry Andric int64_t Value; 18975ffd83dbSDimitry Andric if (Res->evaluateAsAbsolute(Value)) 18985ffd83dbSDimitry Andric Res = MCConstantExpr::create(Value, getContext()); 18995ffd83dbSDimitry Andric 19005ffd83dbSDimitry Andric return false; 19015ffd83dbSDimitry Andric } 19025ffd83dbSDimitry Andric 19035ffd83dbSDimitry Andric bool MasmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) { 19045ffd83dbSDimitry Andric Res = nullptr; 19055ffd83dbSDimitry Andric return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc); 19065ffd83dbSDimitry Andric } 19075ffd83dbSDimitry Andric 19085ffd83dbSDimitry Andric bool MasmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res, 19095ffd83dbSDimitry Andric SMLoc &EndLoc) { 19105ffd83dbSDimitry Andric if (parseParenExpr(Res, EndLoc)) 19115ffd83dbSDimitry Andric return true; 19125ffd83dbSDimitry Andric 19135ffd83dbSDimitry Andric for (; ParenDepth > 0; --ParenDepth) { 19145ffd83dbSDimitry Andric if (parseBinOpRHS(1, Res, EndLoc)) 19155ffd83dbSDimitry Andric return true; 19165ffd83dbSDimitry Andric 19175ffd83dbSDimitry Andric // We don't Lex() the last RParen. 19185ffd83dbSDimitry Andric // This is the same behavior as parseParenExpression(). 19195ffd83dbSDimitry Andric if (ParenDepth - 1 > 0) { 19205ffd83dbSDimitry Andric EndLoc = getTok().getEndLoc(); 192104eeddc0SDimitry Andric if (parseRParen()) 19225ffd83dbSDimitry Andric return true; 19235ffd83dbSDimitry Andric } 19245ffd83dbSDimitry Andric } 19255ffd83dbSDimitry Andric return false; 19265ffd83dbSDimitry Andric } 19275ffd83dbSDimitry Andric 19285ffd83dbSDimitry Andric bool MasmParser::parseAbsoluteExpression(int64_t &Res) { 19295ffd83dbSDimitry Andric const MCExpr *Expr; 19305ffd83dbSDimitry Andric 19315ffd83dbSDimitry Andric SMLoc StartLoc = Lexer.getLoc(); 19325ffd83dbSDimitry Andric if (parseExpression(Expr)) 19335ffd83dbSDimitry Andric return true; 19345ffd83dbSDimitry Andric 19355ffd83dbSDimitry Andric if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr())) 19365ffd83dbSDimitry Andric return Error(StartLoc, "expected absolute expression"); 19375ffd83dbSDimitry Andric 19385ffd83dbSDimitry Andric return false; 19395ffd83dbSDimitry Andric } 19405ffd83dbSDimitry Andric 19415ffd83dbSDimitry Andric static unsigned getGNUBinOpPrecedence(AsmToken::TokenKind K, 19425ffd83dbSDimitry Andric MCBinaryExpr::Opcode &Kind, 19435ffd83dbSDimitry Andric bool ShouldUseLogicalShr, 19445ffd83dbSDimitry Andric bool EndExpressionAtGreater) { 19455ffd83dbSDimitry Andric switch (K) { 19465ffd83dbSDimitry Andric default: 19475ffd83dbSDimitry Andric return 0; // not a binop. 19485ffd83dbSDimitry Andric 19495ffd83dbSDimitry Andric // Lowest Precedence: &&, || 19505ffd83dbSDimitry Andric case AsmToken::AmpAmp: 19515ffd83dbSDimitry Andric Kind = MCBinaryExpr::LAnd; 19525ffd83dbSDimitry Andric return 2; 19535ffd83dbSDimitry Andric case AsmToken::PipePipe: 19545ffd83dbSDimitry Andric Kind = MCBinaryExpr::LOr; 19555ffd83dbSDimitry Andric return 1; 19565ffd83dbSDimitry Andric 19575ffd83dbSDimitry Andric // Low Precedence: ==, !=, <>, <, <=, >, >= 19585ffd83dbSDimitry Andric case AsmToken::EqualEqual: 19595ffd83dbSDimitry Andric Kind = MCBinaryExpr::EQ; 19605ffd83dbSDimitry Andric return 3; 19615ffd83dbSDimitry Andric case AsmToken::ExclaimEqual: 19625ffd83dbSDimitry Andric case AsmToken::LessGreater: 19635ffd83dbSDimitry Andric Kind = MCBinaryExpr::NE; 19645ffd83dbSDimitry Andric return 3; 19655ffd83dbSDimitry Andric case AsmToken::Less: 19665ffd83dbSDimitry Andric Kind = MCBinaryExpr::LT; 19675ffd83dbSDimitry Andric return 3; 19685ffd83dbSDimitry Andric case AsmToken::LessEqual: 19695ffd83dbSDimitry Andric Kind = MCBinaryExpr::LTE; 19705ffd83dbSDimitry Andric return 3; 19715ffd83dbSDimitry Andric case AsmToken::Greater: 19725ffd83dbSDimitry Andric if (EndExpressionAtGreater) 19735ffd83dbSDimitry Andric return 0; 19745ffd83dbSDimitry Andric Kind = MCBinaryExpr::GT; 19755ffd83dbSDimitry Andric return 3; 19765ffd83dbSDimitry Andric case AsmToken::GreaterEqual: 19775ffd83dbSDimitry Andric Kind = MCBinaryExpr::GTE; 19785ffd83dbSDimitry Andric return 3; 19795ffd83dbSDimitry Andric 19805ffd83dbSDimitry Andric // Low Intermediate Precedence: +, - 19815ffd83dbSDimitry Andric case AsmToken::Plus: 19825ffd83dbSDimitry Andric Kind = MCBinaryExpr::Add; 19835ffd83dbSDimitry Andric return 4; 19845ffd83dbSDimitry Andric case AsmToken::Minus: 19855ffd83dbSDimitry Andric Kind = MCBinaryExpr::Sub; 19865ffd83dbSDimitry Andric return 4; 19875ffd83dbSDimitry Andric 19885ffd83dbSDimitry Andric // High Intermediate Precedence: |, &, ^ 19895ffd83dbSDimitry Andric case AsmToken::Pipe: 19905ffd83dbSDimitry Andric Kind = MCBinaryExpr::Or; 19915ffd83dbSDimitry Andric return 5; 19925ffd83dbSDimitry Andric case AsmToken::Caret: 19935ffd83dbSDimitry Andric Kind = MCBinaryExpr::Xor; 19945ffd83dbSDimitry Andric return 5; 19955ffd83dbSDimitry Andric case AsmToken::Amp: 19965ffd83dbSDimitry Andric Kind = MCBinaryExpr::And; 19975ffd83dbSDimitry Andric return 5; 19985ffd83dbSDimitry Andric 19995ffd83dbSDimitry Andric // Highest Precedence: *, /, %, <<, >> 20005ffd83dbSDimitry Andric case AsmToken::Star: 20015ffd83dbSDimitry Andric Kind = MCBinaryExpr::Mul; 20025ffd83dbSDimitry Andric return 6; 20035ffd83dbSDimitry Andric case AsmToken::Slash: 20045ffd83dbSDimitry Andric Kind = MCBinaryExpr::Div; 20055ffd83dbSDimitry Andric return 6; 20065ffd83dbSDimitry Andric case AsmToken::Percent: 20075ffd83dbSDimitry Andric Kind = MCBinaryExpr::Mod; 20085ffd83dbSDimitry Andric return 6; 20095ffd83dbSDimitry Andric case AsmToken::LessLess: 20105ffd83dbSDimitry Andric Kind = MCBinaryExpr::Shl; 20115ffd83dbSDimitry Andric return 6; 20125ffd83dbSDimitry Andric case AsmToken::GreaterGreater: 20135ffd83dbSDimitry Andric if (EndExpressionAtGreater) 20145ffd83dbSDimitry Andric return 0; 20155ffd83dbSDimitry Andric Kind = ShouldUseLogicalShr ? MCBinaryExpr::LShr : MCBinaryExpr::AShr; 20165ffd83dbSDimitry Andric return 6; 20175ffd83dbSDimitry Andric } 20185ffd83dbSDimitry Andric } 20195ffd83dbSDimitry Andric 20205ffd83dbSDimitry Andric unsigned MasmParser::getBinOpPrecedence(AsmToken::TokenKind K, 20215ffd83dbSDimitry Andric MCBinaryExpr::Opcode &Kind) { 20225ffd83dbSDimitry Andric bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr(); 20235ffd83dbSDimitry Andric return getGNUBinOpPrecedence(K, Kind, ShouldUseLogicalShr, 20245ffd83dbSDimitry Andric AngleBracketDepth > 0); 20255ffd83dbSDimitry Andric } 20265ffd83dbSDimitry Andric 20275ffd83dbSDimitry Andric /// Parse all binary operators with precedence >= 'Precedence'. 20285ffd83dbSDimitry Andric /// Res contains the LHS of the expression on input. 20295ffd83dbSDimitry Andric bool MasmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, 20305ffd83dbSDimitry Andric SMLoc &EndLoc) { 20315ffd83dbSDimitry Andric SMLoc StartLoc = Lexer.getLoc(); 20325ffd83dbSDimitry Andric while (true) { 2033e8d8bef9SDimitry Andric AsmToken::TokenKind TokKind = Lexer.getKind(); 2034e8d8bef9SDimitry Andric if (Lexer.getKind() == AsmToken::Identifier) { 2035e8d8bef9SDimitry Andric TokKind = StringSwitch<AsmToken::TokenKind>(Lexer.getTok().getString()) 2036e8d8bef9SDimitry Andric .CaseLower("and", AsmToken::Amp) 2037e8d8bef9SDimitry Andric .CaseLower("not", AsmToken::Exclaim) 2038e8d8bef9SDimitry Andric .CaseLower("or", AsmToken::Pipe) 2039753f127fSDimitry Andric .CaseLower("xor", AsmToken::Caret) 2040753f127fSDimitry Andric .CaseLower("shl", AsmToken::LessLess) 2041753f127fSDimitry Andric .CaseLower("shr", AsmToken::GreaterGreater) 2042e8d8bef9SDimitry Andric .CaseLower("eq", AsmToken::EqualEqual) 2043e8d8bef9SDimitry Andric .CaseLower("ne", AsmToken::ExclaimEqual) 2044e8d8bef9SDimitry Andric .CaseLower("lt", AsmToken::Less) 2045e8d8bef9SDimitry Andric .CaseLower("le", AsmToken::LessEqual) 2046e8d8bef9SDimitry Andric .CaseLower("gt", AsmToken::Greater) 2047e8d8bef9SDimitry Andric .CaseLower("ge", AsmToken::GreaterEqual) 2048e8d8bef9SDimitry Andric .Default(TokKind); 2049e8d8bef9SDimitry Andric } 20505ffd83dbSDimitry Andric MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add; 2051e8d8bef9SDimitry Andric unsigned TokPrec = getBinOpPrecedence(TokKind, Kind); 20525ffd83dbSDimitry Andric 20535ffd83dbSDimitry Andric // If the next token is lower precedence than we are allowed to eat, return 20545ffd83dbSDimitry Andric // successfully with what we ate already. 20555ffd83dbSDimitry Andric if (TokPrec < Precedence) 20565ffd83dbSDimitry Andric return false; 20575ffd83dbSDimitry Andric 20585ffd83dbSDimitry Andric Lex(); 20595ffd83dbSDimitry Andric 20605ffd83dbSDimitry Andric // Eat the next primary expression. 20615ffd83dbSDimitry Andric const MCExpr *RHS; 20625ffd83dbSDimitry Andric if (getTargetParser().parsePrimaryExpr(RHS, EndLoc)) 20635ffd83dbSDimitry Andric return true; 20645ffd83dbSDimitry Andric 20655ffd83dbSDimitry Andric // If BinOp binds less tightly with RHS than the operator after RHS, let 20665ffd83dbSDimitry Andric // the pending operator take RHS as its LHS. 20675ffd83dbSDimitry Andric MCBinaryExpr::Opcode Dummy; 20685ffd83dbSDimitry Andric unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy); 20695ffd83dbSDimitry Andric if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1, RHS, EndLoc)) 20705ffd83dbSDimitry Andric return true; 20715ffd83dbSDimitry Andric 20725ffd83dbSDimitry Andric // Merge LHS and RHS according to operator. 20735ffd83dbSDimitry Andric Res = MCBinaryExpr::create(Kind, Res, RHS, getContext(), StartLoc); 20745ffd83dbSDimitry Andric } 20755ffd83dbSDimitry Andric } 20765ffd83dbSDimitry Andric 20775ffd83dbSDimitry Andric /// ParseStatement: 2078e8d8bef9SDimitry Andric /// ::= % statement 20795ffd83dbSDimitry Andric /// ::= EndOfStatement 20805ffd83dbSDimitry Andric /// ::= Label* Directive ...Operands... EndOfStatement 20815ffd83dbSDimitry Andric /// ::= Label* Identifier OperandList* EndOfStatement 20825ffd83dbSDimitry Andric bool MasmParser::parseStatement(ParseStatementInfo &Info, 20835ffd83dbSDimitry Andric MCAsmParserSemaCallback *SI) { 20845ffd83dbSDimitry Andric assert(!hasPendingError() && "parseStatement started with pending error"); 20855ffd83dbSDimitry Andric // Eat initial spaces and comments. 20865ffd83dbSDimitry Andric while (Lexer.is(AsmToken::Space)) 20875ffd83dbSDimitry Andric Lex(); 20885ffd83dbSDimitry Andric if (Lexer.is(AsmToken::EndOfStatement)) { 20895ffd83dbSDimitry Andric // If this is a line comment we can drop it safely. 20905ffd83dbSDimitry Andric if (getTok().getString().empty() || getTok().getString().front() == '\r' || 20915ffd83dbSDimitry Andric getTok().getString().front() == '\n') 209281ad6265SDimitry Andric Out.addBlankLine(); 20935ffd83dbSDimitry Andric Lex(); 20945ffd83dbSDimitry Andric return false; 20955ffd83dbSDimitry Andric } 2096e8d8bef9SDimitry Andric 2097e8d8bef9SDimitry Andric // If preceded by an expansion operator, first expand all text macros and 2098e8d8bef9SDimitry Andric // macro functions. 2099e8d8bef9SDimitry Andric if (getTok().is(AsmToken::Percent)) { 2100e8d8bef9SDimitry Andric SMLoc ExpansionLoc = getTok().getLoc(); 2101e8d8bef9SDimitry Andric if (parseToken(AsmToken::Percent) || expandStatement(ExpansionLoc)) 2102e8d8bef9SDimitry Andric return true; 2103e8d8bef9SDimitry Andric } 2104e8d8bef9SDimitry Andric 21055ffd83dbSDimitry Andric // Statements always start with an identifier, unless we're dealing with a 21065ffd83dbSDimitry Andric // processor directive (.386, .686, etc.) that lexes as a real. 21075ffd83dbSDimitry Andric AsmToken ID = getTok(); 21085ffd83dbSDimitry Andric SMLoc IDLoc = ID.getLoc(); 21095ffd83dbSDimitry Andric StringRef IDVal; 21105ffd83dbSDimitry Andric if (Lexer.is(AsmToken::HashDirective)) 21115ffd83dbSDimitry Andric return parseCppHashLineFilenameComment(IDLoc); 2112753f127fSDimitry Andric if (Lexer.is(AsmToken::Dot)) { 21135ffd83dbSDimitry Andric // Treat '.' as a valid identifier in this context. 21145ffd83dbSDimitry Andric Lex(); 21155ffd83dbSDimitry Andric IDVal = "."; 21165ffd83dbSDimitry Andric } else if (Lexer.is(AsmToken::Real)) { 21175ffd83dbSDimitry Andric // Treat ".<number>" as a valid identifier in this context. 21185ffd83dbSDimitry Andric IDVal = getTok().getString(); 21195ffd83dbSDimitry Andric Lex(); // always eat a token 21205ffd83dbSDimitry Andric if (!IDVal.startswith(".")) 21215ffd83dbSDimitry Andric return Error(IDLoc, "unexpected token at start of statement"); 2122fe6060f1SDimitry Andric } else if (parseIdentifier(IDVal, StartOfStatement)) { 21235ffd83dbSDimitry Andric if (!TheCondState.Ignore) { 21245ffd83dbSDimitry Andric Lex(); // always eat a token 21255ffd83dbSDimitry Andric return Error(IDLoc, "unexpected token at start of statement"); 21265ffd83dbSDimitry Andric } 21275ffd83dbSDimitry Andric IDVal = ""; 21285ffd83dbSDimitry Andric } 21295ffd83dbSDimitry Andric 21305ffd83dbSDimitry Andric // Handle conditional assembly here before checking for skipping. We 21315ffd83dbSDimitry Andric // have to do this so that .endif isn't skipped in a ".if 0" block for 21325ffd83dbSDimitry Andric // example. 21335ffd83dbSDimitry Andric StringMap<DirectiveKind>::const_iterator DirKindIt = 21345ffd83dbSDimitry Andric DirectiveKindMap.find(IDVal.lower()); 21355ffd83dbSDimitry Andric DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end()) 21365ffd83dbSDimitry Andric ? DK_NO_DIRECTIVE 21375ffd83dbSDimitry Andric : DirKindIt->getValue(); 21385ffd83dbSDimitry Andric switch (DirKind) { 21395ffd83dbSDimitry Andric default: 21405ffd83dbSDimitry Andric break; 21415ffd83dbSDimitry Andric case DK_IF: 21425ffd83dbSDimitry Andric case DK_IFE: 21435ffd83dbSDimitry Andric return parseDirectiveIf(IDLoc, DirKind); 21445ffd83dbSDimitry Andric case DK_IFB: 21455ffd83dbSDimitry Andric return parseDirectiveIfb(IDLoc, true); 21465ffd83dbSDimitry Andric case DK_IFNB: 21475ffd83dbSDimitry Andric return parseDirectiveIfb(IDLoc, false); 21485ffd83dbSDimitry Andric case DK_IFDEF: 21495ffd83dbSDimitry Andric return parseDirectiveIfdef(IDLoc, true); 21505ffd83dbSDimitry Andric case DK_IFNDEF: 21515ffd83dbSDimitry Andric return parseDirectiveIfdef(IDLoc, false); 21525ffd83dbSDimitry Andric case DK_IFDIF: 21535ffd83dbSDimitry Andric return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false, 21545ffd83dbSDimitry Andric /*CaseInsensitive=*/false); 21555ffd83dbSDimitry Andric case DK_IFDIFI: 21565ffd83dbSDimitry Andric return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false, 21575ffd83dbSDimitry Andric /*CaseInsensitive=*/true); 21585ffd83dbSDimitry Andric case DK_IFIDN: 21595ffd83dbSDimitry Andric return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true, 21605ffd83dbSDimitry Andric /*CaseInsensitive=*/false); 21615ffd83dbSDimitry Andric case DK_IFIDNI: 21625ffd83dbSDimitry Andric return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true, 21635ffd83dbSDimitry Andric /*CaseInsensitive=*/true); 21645ffd83dbSDimitry Andric case DK_ELSEIF: 21655ffd83dbSDimitry Andric case DK_ELSEIFE: 21665ffd83dbSDimitry Andric return parseDirectiveElseIf(IDLoc, DirKind); 21675ffd83dbSDimitry Andric case DK_ELSEIFB: 21685ffd83dbSDimitry Andric return parseDirectiveElseIfb(IDLoc, true); 21695ffd83dbSDimitry Andric case DK_ELSEIFNB: 21705ffd83dbSDimitry Andric return parseDirectiveElseIfb(IDLoc, false); 21715ffd83dbSDimitry Andric case DK_ELSEIFDEF: 21725ffd83dbSDimitry Andric return parseDirectiveElseIfdef(IDLoc, true); 21735ffd83dbSDimitry Andric case DK_ELSEIFNDEF: 21745ffd83dbSDimitry Andric return parseDirectiveElseIfdef(IDLoc, false); 21755ffd83dbSDimitry Andric case DK_ELSEIFDIF: 21765ffd83dbSDimitry Andric return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false, 21775ffd83dbSDimitry Andric /*CaseInsensitive=*/false); 21785ffd83dbSDimitry Andric case DK_ELSEIFDIFI: 21795ffd83dbSDimitry Andric return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false, 21805ffd83dbSDimitry Andric /*CaseInsensitive=*/true); 21815ffd83dbSDimitry Andric case DK_ELSEIFIDN: 21825ffd83dbSDimitry Andric return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true, 21835ffd83dbSDimitry Andric /*CaseInsensitive=*/false); 21845ffd83dbSDimitry Andric case DK_ELSEIFIDNI: 21855ffd83dbSDimitry Andric return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true, 21865ffd83dbSDimitry Andric /*CaseInsensitive=*/true); 21875ffd83dbSDimitry Andric case DK_ELSE: 21885ffd83dbSDimitry Andric return parseDirectiveElse(IDLoc); 21895ffd83dbSDimitry Andric case DK_ENDIF: 21905ffd83dbSDimitry Andric return parseDirectiveEndIf(IDLoc); 21915ffd83dbSDimitry Andric } 21925ffd83dbSDimitry Andric 21935ffd83dbSDimitry Andric // Ignore the statement if in the middle of inactive conditional 21945ffd83dbSDimitry Andric // (e.g. ".if 0"). 21955ffd83dbSDimitry Andric if (TheCondState.Ignore) { 21965ffd83dbSDimitry Andric eatToEndOfStatement(); 21975ffd83dbSDimitry Andric return false; 21985ffd83dbSDimitry Andric } 21995ffd83dbSDimitry Andric 22005ffd83dbSDimitry Andric // FIXME: Recurse on local labels? 22015ffd83dbSDimitry Andric 2202bdd1243dSDimitry Andric // Check for a label. 2203bdd1243dSDimitry Andric // ::= identifier ':' 2204bdd1243dSDimitry Andric // ::= number ':' 2205bdd1243dSDimitry Andric if (Lexer.is(AsmToken::Colon) && getTargetParser().isLabel(ID)) { 22065ffd83dbSDimitry Andric if (checkForValidSection()) 22075ffd83dbSDimitry Andric return true; 22085ffd83dbSDimitry Andric 22095ffd83dbSDimitry Andric // identifier ':' -> Label. 22105ffd83dbSDimitry Andric Lex(); 22115ffd83dbSDimitry Andric 22125ffd83dbSDimitry Andric // Diagnose attempt to use '.' as a label. 22135ffd83dbSDimitry Andric if (IDVal == ".") 22145ffd83dbSDimitry Andric return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label"); 22155ffd83dbSDimitry Andric 22165ffd83dbSDimitry Andric // Diagnose attempt to use a variable as a label. 22175ffd83dbSDimitry Andric // 22185ffd83dbSDimitry Andric // FIXME: Diagnostics. Note the location of the definition as a label. 22195ffd83dbSDimitry Andric // FIXME: This doesn't diagnose assignment to a symbol which has been 22205ffd83dbSDimitry Andric // implicitly marked as external. 22215ffd83dbSDimitry Andric MCSymbol *Sym; 22225ffd83dbSDimitry Andric if (ParsingMSInlineAsm && SI) { 22235ffd83dbSDimitry Andric StringRef RewrittenLabel = 22245ffd83dbSDimitry Andric SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true); 22255ffd83dbSDimitry Andric assert(!RewrittenLabel.empty() && 22265ffd83dbSDimitry Andric "We should have an internal name here."); 22275ffd83dbSDimitry Andric Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(), 22285ffd83dbSDimitry Andric RewrittenLabel); 22295ffd83dbSDimitry Andric IDVal = RewrittenLabel; 22305ffd83dbSDimitry Andric } 2231753f127fSDimitry Andric // Handle directional local labels 2232753f127fSDimitry Andric if (IDVal == "@@") { 2233753f127fSDimitry Andric Sym = Ctx.createDirectionalLocalSymbol(0); 2234753f127fSDimitry Andric } else { 22355ffd83dbSDimitry Andric Sym = getContext().getOrCreateSymbol(IDVal); 2236753f127fSDimitry Andric } 2237753f127fSDimitry Andric 22385ffd83dbSDimitry Andric // End of Labels should be treated as end of line for lexing 22395ffd83dbSDimitry Andric // purposes but that information is not available to the Lexer who 22405ffd83dbSDimitry Andric // does not understand Labels. This may cause us to see a Hash 22415ffd83dbSDimitry Andric // here instead of a preprocessor line comment. 22425ffd83dbSDimitry Andric if (getTok().is(AsmToken::Hash)) { 2243e8d8bef9SDimitry Andric std::string CommentStr = parseStringTo(AsmToken::EndOfStatement); 22445ffd83dbSDimitry Andric Lexer.Lex(); 22455ffd83dbSDimitry Andric Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr)); 22465ffd83dbSDimitry Andric } 22475ffd83dbSDimitry Andric 22485ffd83dbSDimitry Andric // Consume any end of statement token, if present, to avoid spurious 224981ad6265SDimitry Andric // addBlankLine calls(). 22505ffd83dbSDimitry Andric if (getTok().is(AsmToken::EndOfStatement)) { 22515ffd83dbSDimitry Andric Lex(); 22525ffd83dbSDimitry Andric } 22535ffd83dbSDimitry Andric 2254bdd1243dSDimitry Andric getTargetParser().doBeforeLabelEmit(Sym, IDLoc); 22555ffd83dbSDimitry Andric 22565ffd83dbSDimitry Andric // Emit the label. 22575ffd83dbSDimitry Andric if (!getTargetParser().isParsingMSInlineAsm()) 22585ffd83dbSDimitry Andric Out.emitLabel(Sym, IDLoc); 22595ffd83dbSDimitry Andric 22605ffd83dbSDimitry Andric // If we are generating dwarf for assembly source files then gather the 22615ffd83dbSDimitry Andric // info to make a dwarf label entry for this label if needed. 22625ffd83dbSDimitry Andric if (enabledGenDwarfForAssembly()) 22635ffd83dbSDimitry Andric MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(), 22645ffd83dbSDimitry Andric IDLoc); 22655ffd83dbSDimitry Andric 22665ffd83dbSDimitry Andric getTargetParser().onLabelParsed(Sym); 22675ffd83dbSDimitry Andric 22685ffd83dbSDimitry Andric return false; 22695ffd83dbSDimitry Andric } 22705ffd83dbSDimitry Andric 22715ffd83dbSDimitry Andric // If macros are enabled, check to see if this is a macro instantiation. 2272e8d8bef9SDimitry Andric if (const MCAsmMacro *M = getContext().lookupMacro(IDVal.lower())) { 22735ffd83dbSDimitry Andric return handleMacroEntry(M, IDLoc); 22745ffd83dbSDimitry Andric } 22755ffd83dbSDimitry Andric 22765ffd83dbSDimitry Andric // Otherwise, we have a normal instruction or directive. 22775ffd83dbSDimitry Andric 22785ffd83dbSDimitry Andric if (DirKind != DK_NO_DIRECTIVE) { 22795ffd83dbSDimitry Andric // There are several entities interested in parsing directives: 22805ffd83dbSDimitry Andric // 22815ffd83dbSDimitry Andric // 1. Asm parser extensions. For example, platform-specific parsers 22825ffd83dbSDimitry Andric // (like the ELF parser) register themselves as extensions. 22835ffd83dbSDimitry Andric // 2. The target-specific assembly parser. Some directives are target 22845ffd83dbSDimitry Andric // specific or may potentially behave differently on certain targets. 22855ffd83dbSDimitry Andric // 3. The generic directive parser implemented by this class. These are 22865ffd83dbSDimitry Andric // all the directives that behave in a target and platform independent 22875ffd83dbSDimitry Andric // manner, or at least have a default behavior that's shared between 22885ffd83dbSDimitry Andric // all targets and platforms. 22895ffd83dbSDimitry Andric 22905ffd83dbSDimitry Andric getTargetParser().flushPendingInstructions(getStreamer()); 22915ffd83dbSDimitry Andric 22925ffd83dbSDimitry Andric // Special-case handling of structure-end directives at higher priority, 22935ffd83dbSDimitry Andric // since ENDS is overloaded as a segment-end directive. 2294fe6060f1SDimitry Andric if (IDVal.equals_insensitive("ends") && StructInProgress.size() > 1 && 22955ffd83dbSDimitry Andric getTok().is(AsmToken::EndOfStatement)) { 22965ffd83dbSDimitry Andric return parseDirectiveNestedEnds(); 22975ffd83dbSDimitry Andric } 22985ffd83dbSDimitry Andric 22995ffd83dbSDimitry Andric // First, check the extension directive map to see if any extension has 23005ffd83dbSDimitry Andric // registered itself to parse this directive. 23015ffd83dbSDimitry Andric std::pair<MCAsmParserExtension *, DirectiveHandler> Handler = 23025ffd83dbSDimitry Andric ExtensionDirectiveMap.lookup(IDVal.lower()); 23035ffd83dbSDimitry Andric if (Handler.first) 23045ffd83dbSDimitry Andric return (*Handler.second)(Handler.first, IDVal, IDLoc); 23055ffd83dbSDimitry Andric 23065ffd83dbSDimitry Andric // Next, let the target-specific assembly parser try. 2307*06c3fb27SDimitry Andric if (ID.isNot(AsmToken::Identifier)) 2308*06c3fb27SDimitry Andric return false; 23095ffd83dbSDimitry Andric 2310*06c3fb27SDimitry Andric ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(ID); 2311*06c3fb27SDimitry Andric assert(TPDirectiveReturn.isFailure() == hasPendingError() && 2312*06c3fb27SDimitry Andric "Should only return Failure iff there was an error"); 2313*06c3fb27SDimitry Andric if (TPDirectiveReturn.isFailure()) 23145ffd83dbSDimitry Andric return true; 2315*06c3fb27SDimitry Andric if (TPDirectiveReturn.isSuccess()) 23165ffd83dbSDimitry Andric return false; 23175ffd83dbSDimitry Andric 23185ffd83dbSDimitry Andric // Finally, if no one else is interested in this directive, it must be 23195ffd83dbSDimitry Andric // generic and familiar to this class. 23205ffd83dbSDimitry Andric switch (DirKind) { 23215ffd83dbSDimitry Andric default: 23225ffd83dbSDimitry Andric break; 23235ffd83dbSDimitry Andric case DK_ASCII: 23245ffd83dbSDimitry Andric return parseDirectiveAscii(IDVal, false); 23255ffd83dbSDimitry Andric case DK_ASCIZ: 23265ffd83dbSDimitry Andric case DK_STRING: 23275ffd83dbSDimitry Andric return parseDirectiveAscii(IDVal, true); 23285ffd83dbSDimitry Andric case DK_BYTE: 23295ffd83dbSDimitry Andric case DK_SBYTE: 23305ffd83dbSDimitry Andric case DK_DB: 23315ffd83dbSDimitry Andric return parseDirectiveValue(IDVal, 1); 23325ffd83dbSDimitry Andric case DK_WORD: 23335ffd83dbSDimitry Andric case DK_SWORD: 23345ffd83dbSDimitry Andric case DK_DW: 23355ffd83dbSDimitry Andric return parseDirectiveValue(IDVal, 2); 23365ffd83dbSDimitry Andric case DK_DWORD: 23375ffd83dbSDimitry Andric case DK_SDWORD: 23385ffd83dbSDimitry Andric case DK_DD: 23395ffd83dbSDimitry Andric return parseDirectiveValue(IDVal, 4); 23405ffd83dbSDimitry Andric case DK_FWORD: 2341e8d8bef9SDimitry Andric case DK_DF: 23425ffd83dbSDimitry Andric return parseDirectiveValue(IDVal, 6); 23435ffd83dbSDimitry Andric case DK_QWORD: 23445ffd83dbSDimitry Andric case DK_SQWORD: 23455ffd83dbSDimitry Andric case DK_DQ: 23465ffd83dbSDimitry Andric return parseDirectiveValue(IDVal, 8); 23475ffd83dbSDimitry Andric case DK_REAL4: 2348e8d8bef9SDimitry Andric return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4); 23495ffd83dbSDimitry Andric case DK_REAL8: 2350e8d8bef9SDimitry Andric return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8); 2351e8d8bef9SDimitry Andric case DK_REAL10: 2352e8d8bef9SDimitry Andric return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10); 23535ffd83dbSDimitry Andric case DK_STRUCT: 23545ffd83dbSDimitry Andric case DK_UNION: 23555ffd83dbSDimitry Andric return parseDirectiveNestedStruct(IDVal, DirKind); 23565ffd83dbSDimitry Andric case DK_ENDS: 23575ffd83dbSDimitry Andric return parseDirectiveNestedEnds(); 23585ffd83dbSDimitry Andric case DK_ALIGN: 23595ffd83dbSDimitry Andric return parseDirectiveAlign(); 2360fe6060f1SDimitry Andric case DK_EVEN: 2361fe6060f1SDimitry Andric return parseDirectiveEven(); 23625ffd83dbSDimitry Andric case DK_ORG: 23635ffd83dbSDimitry Andric return parseDirectiveOrg(); 23645ffd83dbSDimitry Andric case DK_EXTERN: 236581ad6265SDimitry Andric return parseDirectiveExtern(); 23665ffd83dbSDimitry Andric case DK_PUBLIC: 23675ffd83dbSDimitry Andric return parseDirectiveSymbolAttribute(MCSA_Global); 23685ffd83dbSDimitry Andric case DK_COMM: 23695ffd83dbSDimitry Andric return parseDirectiveComm(/*IsLocal=*/false); 23705ffd83dbSDimitry Andric case DK_COMMENT: 23715ffd83dbSDimitry Andric return parseDirectiveComment(IDLoc); 23725ffd83dbSDimitry Andric case DK_INCLUDE: 23735ffd83dbSDimitry Andric return parseDirectiveInclude(); 2374e8d8bef9SDimitry Andric case DK_REPEAT: 2375e8d8bef9SDimitry Andric return parseDirectiveRepeat(IDLoc, IDVal); 2376e8d8bef9SDimitry Andric case DK_WHILE: 2377e8d8bef9SDimitry Andric return parseDirectiveWhile(IDLoc); 2378e8d8bef9SDimitry Andric case DK_FOR: 2379e8d8bef9SDimitry Andric return parseDirectiveFor(IDLoc, IDVal); 2380e8d8bef9SDimitry Andric case DK_FORC: 2381e8d8bef9SDimitry Andric return parseDirectiveForc(IDLoc, IDVal); 23825ffd83dbSDimitry Andric case DK_FILE: 23835ffd83dbSDimitry Andric return parseDirectiveFile(IDLoc); 23845ffd83dbSDimitry Andric case DK_LINE: 23855ffd83dbSDimitry Andric return parseDirectiveLine(); 23865ffd83dbSDimitry Andric case DK_LOC: 23875ffd83dbSDimitry Andric return parseDirectiveLoc(); 23885ffd83dbSDimitry Andric case DK_STABS: 23895ffd83dbSDimitry Andric return parseDirectiveStabs(); 23905ffd83dbSDimitry Andric case DK_CV_FILE: 23915ffd83dbSDimitry Andric return parseDirectiveCVFile(); 23925ffd83dbSDimitry Andric case DK_CV_FUNC_ID: 23935ffd83dbSDimitry Andric return parseDirectiveCVFuncId(); 23945ffd83dbSDimitry Andric case DK_CV_INLINE_SITE_ID: 23955ffd83dbSDimitry Andric return parseDirectiveCVInlineSiteId(); 23965ffd83dbSDimitry Andric case DK_CV_LOC: 23975ffd83dbSDimitry Andric return parseDirectiveCVLoc(); 23985ffd83dbSDimitry Andric case DK_CV_LINETABLE: 23995ffd83dbSDimitry Andric return parseDirectiveCVLinetable(); 24005ffd83dbSDimitry Andric case DK_CV_INLINE_LINETABLE: 24015ffd83dbSDimitry Andric return parseDirectiveCVInlineLinetable(); 24025ffd83dbSDimitry Andric case DK_CV_DEF_RANGE: 24035ffd83dbSDimitry Andric return parseDirectiveCVDefRange(); 24045ffd83dbSDimitry Andric case DK_CV_STRING: 24055ffd83dbSDimitry Andric return parseDirectiveCVString(); 24065ffd83dbSDimitry Andric case DK_CV_STRINGTABLE: 24075ffd83dbSDimitry Andric return parseDirectiveCVStringTable(); 24085ffd83dbSDimitry Andric case DK_CV_FILECHECKSUMS: 24095ffd83dbSDimitry Andric return parseDirectiveCVFileChecksums(); 24105ffd83dbSDimitry Andric case DK_CV_FILECHECKSUM_OFFSET: 24115ffd83dbSDimitry Andric return parseDirectiveCVFileChecksumOffset(); 24125ffd83dbSDimitry Andric case DK_CV_FPO_DATA: 24135ffd83dbSDimitry Andric return parseDirectiveCVFPOData(); 24145ffd83dbSDimitry Andric case DK_CFI_SECTIONS: 24155ffd83dbSDimitry Andric return parseDirectiveCFISections(); 24165ffd83dbSDimitry Andric case DK_CFI_STARTPROC: 24175ffd83dbSDimitry Andric return parseDirectiveCFIStartProc(); 24185ffd83dbSDimitry Andric case DK_CFI_ENDPROC: 24195ffd83dbSDimitry Andric return parseDirectiveCFIEndProc(); 24205ffd83dbSDimitry Andric case DK_CFI_DEF_CFA: 24215ffd83dbSDimitry Andric return parseDirectiveCFIDefCfa(IDLoc); 24225ffd83dbSDimitry Andric case DK_CFI_DEF_CFA_OFFSET: 2423*06c3fb27SDimitry Andric return parseDirectiveCFIDefCfaOffset(IDLoc); 24245ffd83dbSDimitry Andric case DK_CFI_ADJUST_CFA_OFFSET: 2425*06c3fb27SDimitry Andric return parseDirectiveCFIAdjustCfaOffset(IDLoc); 24265ffd83dbSDimitry Andric case DK_CFI_DEF_CFA_REGISTER: 24275ffd83dbSDimitry Andric return parseDirectiveCFIDefCfaRegister(IDLoc); 24285ffd83dbSDimitry Andric case DK_CFI_OFFSET: 24295ffd83dbSDimitry Andric return parseDirectiveCFIOffset(IDLoc); 24305ffd83dbSDimitry Andric case DK_CFI_REL_OFFSET: 24315ffd83dbSDimitry Andric return parseDirectiveCFIRelOffset(IDLoc); 24325ffd83dbSDimitry Andric case DK_CFI_PERSONALITY: 24335ffd83dbSDimitry Andric return parseDirectiveCFIPersonalityOrLsda(true); 24345ffd83dbSDimitry Andric case DK_CFI_LSDA: 24355ffd83dbSDimitry Andric return parseDirectiveCFIPersonalityOrLsda(false); 24365ffd83dbSDimitry Andric case DK_CFI_REMEMBER_STATE: 2437*06c3fb27SDimitry Andric return parseDirectiveCFIRememberState(IDLoc); 24385ffd83dbSDimitry Andric case DK_CFI_RESTORE_STATE: 2439*06c3fb27SDimitry Andric return parseDirectiveCFIRestoreState(IDLoc); 24405ffd83dbSDimitry Andric case DK_CFI_SAME_VALUE: 24415ffd83dbSDimitry Andric return parseDirectiveCFISameValue(IDLoc); 24425ffd83dbSDimitry Andric case DK_CFI_RESTORE: 24435ffd83dbSDimitry Andric return parseDirectiveCFIRestore(IDLoc); 24445ffd83dbSDimitry Andric case DK_CFI_ESCAPE: 2445*06c3fb27SDimitry Andric return parseDirectiveCFIEscape(IDLoc); 24465ffd83dbSDimitry Andric case DK_CFI_RETURN_COLUMN: 24475ffd83dbSDimitry Andric return parseDirectiveCFIReturnColumn(IDLoc); 24485ffd83dbSDimitry Andric case DK_CFI_SIGNAL_FRAME: 24495ffd83dbSDimitry Andric return parseDirectiveCFISignalFrame(); 24505ffd83dbSDimitry Andric case DK_CFI_UNDEFINED: 24515ffd83dbSDimitry Andric return parseDirectiveCFIUndefined(IDLoc); 24525ffd83dbSDimitry Andric case DK_CFI_REGISTER: 24535ffd83dbSDimitry Andric return parseDirectiveCFIRegister(IDLoc); 24545ffd83dbSDimitry Andric case DK_CFI_WINDOW_SAVE: 2455*06c3fb27SDimitry Andric return parseDirectiveCFIWindowSave(IDLoc); 24565ffd83dbSDimitry Andric case DK_EXITM: 2457e8d8bef9SDimitry Andric Info.ExitValue = ""; 2458e8d8bef9SDimitry Andric return parseDirectiveExitMacro(IDLoc, IDVal, *Info.ExitValue); 24595ffd83dbSDimitry Andric case DK_ENDM: 2460e8d8bef9SDimitry Andric Info.ExitValue = ""; 24615ffd83dbSDimitry Andric return parseDirectiveEndMacro(IDVal); 2462e8d8bef9SDimitry Andric case DK_PURGE: 24635ffd83dbSDimitry Andric return parseDirectivePurgeMacro(IDLoc); 24645ffd83dbSDimitry Andric case DK_END: 24655ffd83dbSDimitry Andric return parseDirectiveEnd(IDLoc); 24665ffd83dbSDimitry Andric case DK_ERR: 24675ffd83dbSDimitry Andric return parseDirectiveError(IDLoc); 24685ffd83dbSDimitry Andric case DK_ERRB: 24695ffd83dbSDimitry Andric return parseDirectiveErrorIfb(IDLoc, true); 24705ffd83dbSDimitry Andric case DK_ERRNB: 24715ffd83dbSDimitry Andric return parseDirectiveErrorIfb(IDLoc, false); 24725ffd83dbSDimitry Andric case DK_ERRDEF: 24735ffd83dbSDimitry Andric return parseDirectiveErrorIfdef(IDLoc, true); 24745ffd83dbSDimitry Andric case DK_ERRNDEF: 24755ffd83dbSDimitry Andric return parseDirectiveErrorIfdef(IDLoc, false); 24765ffd83dbSDimitry Andric case DK_ERRDIF: 24775ffd83dbSDimitry Andric return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false, 24785ffd83dbSDimitry Andric /*CaseInsensitive=*/false); 24795ffd83dbSDimitry Andric case DK_ERRDIFI: 24805ffd83dbSDimitry Andric return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false, 24815ffd83dbSDimitry Andric /*CaseInsensitive=*/true); 24825ffd83dbSDimitry Andric case DK_ERRIDN: 24835ffd83dbSDimitry Andric return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true, 24845ffd83dbSDimitry Andric /*CaseInsensitive=*/false); 24855ffd83dbSDimitry Andric case DK_ERRIDNI: 24865ffd83dbSDimitry Andric return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true, 24875ffd83dbSDimitry Andric /*CaseInsensitive=*/true); 24885ffd83dbSDimitry Andric case DK_ERRE: 24895ffd83dbSDimitry Andric return parseDirectiveErrorIfe(IDLoc, true); 24905ffd83dbSDimitry Andric case DK_ERRNZ: 24915ffd83dbSDimitry Andric return parseDirectiveErrorIfe(IDLoc, false); 2492e8d8bef9SDimitry Andric case DK_RADIX: 2493e8d8bef9SDimitry Andric return parseDirectiveRadix(IDLoc); 2494fe6060f1SDimitry Andric case DK_ECHO: 2495fe6060f1SDimitry Andric return parseDirectiveEcho(IDLoc); 24965ffd83dbSDimitry Andric } 24975ffd83dbSDimitry Andric 24985ffd83dbSDimitry Andric return Error(IDLoc, "unknown directive"); 24995ffd83dbSDimitry Andric } 25005ffd83dbSDimitry Andric 25015ffd83dbSDimitry Andric // We also check if this is allocating memory with user-defined type. 25025ffd83dbSDimitry Andric auto IDIt = Structs.find(IDVal.lower()); 25035ffd83dbSDimitry Andric if (IDIt != Structs.end()) 25045ffd83dbSDimitry Andric return parseDirectiveStructValue(/*Structure=*/IDIt->getValue(), IDVal, 25055ffd83dbSDimitry Andric IDLoc); 25065ffd83dbSDimitry Andric 25075ffd83dbSDimitry Andric // Non-conditional Microsoft directives sometimes follow their first argument. 25085ffd83dbSDimitry Andric const AsmToken nextTok = getTok(); 25095ffd83dbSDimitry Andric const StringRef nextVal = nextTok.getString(); 25105ffd83dbSDimitry Andric const SMLoc nextLoc = nextTok.getLoc(); 25115ffd83dbSDimitry Andric 2512fe6060f1SDimitry Andric const AsmToken afterNextTok = peekTok(); 2513fe6060f1SDimitry Andric 25145ffd83dbSDimitry Andric // There are several entities interested in parsing infix directives: 25155ffd83dbSDimitry Andric // 25165ffd83dbSDimitry Andric // 1. Asm parser extensions. For example, platform-specific parsers 25175ffd83dbSDimitry Andric // (like the ELF parser) register themselves as extensions. 25185ffd83dbSDimitry Andric // 2. The generic directive parser implemented by this class. These are 25195ffd83dbSDimitry Andric // all the directives that behave in a target and platform independent 25205ffd83dbSDimitry Andric // manner, or at least have a default behavior that's shared between 25215ffd83dbSDimitry Andric // all targets and platforms. 25225ffd83dbSDimitry Andric 25235ffd83dbSDimitry Andric getTargetParser().flushPendingInstructions(getStreamer()); 25245ffd83dbSDimitry Andric 25255ffd83dbSDimitry Andric // Special-case handling of structure-end directives at higher priority, since 25265ffd83dbSDimitry Andric // ENDS is overloaded as a segment-end directive. 2527fe6060f1SDimitry Andric if (nextVal.equals_insensitive("ends") && StructInProgress.size() == 1) { 25285ffd83dbSDimitry Andric Lex(); 25295ffd83dbSDimitry Andric return parseDirectiveEnds(IDVal, IDLoc); 25305ffd83dbSDimitry Andric } 25315ffd83dbSDimitry Andric 25325ffd83dbSDimitry Andric // First, check the extension directive map to see if any extension has 25335ffd83dbSDimitry Andric // registered itself to parse this directive. 25345ffd83dbSDimitry Andric std::pair<MCAsmParserExtension *, DirectiveHandler> Handler = 25355ffd83dbSDimitry Andric ExtensionDirectiveMap.lookup(nextVal.lower()); 25365ffd83dbSDimitry Andric if (Handler.first) { 25375ffd83dbSDimitry Andric Lex(); 25385ffd83dbSDimitry Andric Lexer.UnLex(ID); 25395ffd83dbSDimitry Andric return (*Handler.second)(Handler.first, nextVal, nextLoc); 25405ffd83dbSDimitry Andric } 25415ffd83dbSDimitry Andric 25425ffd83dbSDimitry Andric // If no one else is interested in this directive, it must be 25435ffd83dbSDimitry Andric // generic and familiar to this class. 25445ffd83dbSDimitry Andric DirKindIt = DirectiveKindMap.find(nextVal.lower()); 25455ffd83dbSDimitry Andric DirKind = (DirKindIt == DirectiveKindMap.end()) 25465ffd83dbSDimitry Andric ? DK_NO_DIRECTIVE 25475ffd83dbSDimitry Andric : DirKindIt->getValue(); 25485ffd83dbSDimitry Andric switch (DirKind) { 25495ffd83dbSDimitry Andric default: 25505ffd83dbSDimitry Andric break; 25515ffd83dbSDimitry Andric case DK_ASSIGN: 25525ffd83dbSDimitry Andric case DK_EQU: 25535ffd83dbSDimitry Andric case DK_TEXTEQU: 25545ffd83dbSDimitry Andric Lex(); 2555fe6060f1SDimitry Andric return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc); 25565ffd83dbSDimitry Andric case DK_BYTE: 2557fe6060f1SDimitry Andric if (afterNextTok.is(AsmToken::Identifier) && 2558fe6060f1SDimitry Andric afterNextTok.getString().equals_insensitive("ptr")) { 2559fe6060f1SDimitry Andric // Size directive; part of an instruction. 2560fe6060f1SDimitry Andric break; 2561fe6060f1SDimitry Andric } 2562bdd1243dSDimitry Andric [[fallthrough]]; 2563e8d8bef9SDimitry Andric case DK_SBYTE: 25645ffd83dbSDimitry Andric case DK_DB: 25655ffd83dbSDimitry Andric Lex(); 25665ffd83dbSDimitry Andric return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc); 25675ffd83dbSDimitry Andric case DK_WORD: 2568fe6060f1SDimitry Andric if (afterNextTok.is(AsmToken::Identifier) && 2569fe6060f1SDimitry Andric afterNextTok.getString().equals_insensitive("ptr")) { 2570fe6060f1SDimitry Andric // Size directive; part of an instruction. 2571fe6060f1SDimitry Andric break; 2572fe6060f1SDimitry Andric } 2573bdd1243dSDimitry Andric [[fallthrough]]; 2574e8d8bef9SDimitry Andric case DK_SWORD: 25755ffd83dbSDimitry Andric case DK_DW: 25765ffd83dbSDimitry Andric Lex(); 25775ffd83dbSDimitry Andric return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc); 25785ffd83dbSDimitry Andric case DK_DWORD: 2579fe6060f1SDimitry Andric if (afterNextTok.is(AsmToken::Identifier) && 2580fe6060f1SDimitry Andric afterNextTok.getString().equals_insensitive("ptr")) { 2581fe6060f1SDimitry Andric // Size directive; part of an instruction. 2582fe6060f1SDimitry Andric break; 2583fe6060f1SDimitry Andric } 2584bdd1243dSDimitry Andric [[fallthrough]]; 2585e8d8bef9SDimitry Andric case DK_SDWORD: 25865ffd83dbSDimitry Andric case DK_DD: 25875ffd83dbSDimitry Andric Lex(); 25885ffd83dbSDimitry Andric return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc); 25895ffd83dbSDimitry Andric case DK_FWORD: 2590fe6060f1SDimitry Andric if (afterNextTok.is(AsmToken::Identifier) && 2591fe6060f1SDimitry Andric afterNextTok.getString().equals_insensitive("ptr")) { 2592fe6060f1SDimitry Andric // Size directive; part of an instruction. 2593fe6060f1SDimitry Andric break; 2594fe6060f1SDimitry Andric } 2595bdd1243dSDimitry Andric [[fallthrough]]; 2596e8d8bef9SDimitry Andric case DK_DF: 25975ffd83dbSDimitry Andric Lex(); 25985ffd83dbSDimitry Andric return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc); 25995ffd83dbSDimitry Andric case DK_QWORD: 2600fe6060f1SDimitry Andric if (afterNextTok.is(AsmToken::Identifier) && 2601fe6060f1SDimitry Andric afterNextTok.getString().equals_insensitive("ptr")) { 2602fe6060f1SDimitry Andric // Size directive; part of an instruction. 2603fe6060f1SDimitry Andric break; 2604fe6060f1SDimitry Andric } 2605bdd1243dSDimitry Andric [[fallthrough]]; 2606e8d8bef9SDimitry Andric case DK_SQWORD: 26075ffd83dbSDimitry Andric case DK_DQ: 26085ffd83dbSDimitry Andric Lex(); 26095ffd83dbSDimitry Andric return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc); 26105ffd83dbSDimitry Andric case DK_REAL4: 26115ffd83dbSDimitry Andric Lex(); 2612e8d8bef9SDimitry Andric return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), 4, 2613e8d8bef9SDimitry Andric IDVal, IDLoc); 26145ffd83dbSDimitry Andric case DK_REAL8: 26155ffd83dbSDimitry Andric Lex(); 2616e8d8bef9SDimitry Andric return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8, 2617e8d8bef9SDimitry Andric IDVal, IDLoc); 2618e8d8bef9SDimitry Andric case DK_REAL10: 2619e8d8bef9SDimitry Andric Lex(); 2620e8d8bef9SDimitry Andric return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(), 2621e8d8bef9SDimitry Andric 10, IDVal, IDLoc); 26225ffd83dbSDimitry Andric case DK_STRUCT: 26235ffd83dbSDimitry Andric case DK_UNION: 26245ffd83dbSDimitry Andric Lex(); 26255ffd83dbSDimitry Andric return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc); 26265ffd83dbSDimitry Andric case DK_ENDS: 26275ffd83dbSDimitry Andric Lex(); 26285ffd83dbSDimitry Andric return parseDirectiveEnds(IDVal, IDLoc); 2629e8d8bef9SDimitry Andric case DK_MACRO: 2630e8d8bef9SDimitry Andric Lex(); 2631e8d8bef9SDimitry Andric return parseDirectiveMacro(IDVal, IDLoc); 26325ffd83dbSDimitry Andric } 26335ffd83dbSDimitry Andric 26345ffd83dbSDimitry Andric // Finally, we check if this is allocating a variable with user-defined type. 26355ffd83dbSDimitry Andric auto NextIt = Structs.find(nextVal.lower()); 26365ffd83dbSDimitry Andric if (NextIt != Structs.end()) { 26375ffd83dbSDimitry Andric Lex(); 26385ffd83dbSDimitry Andric return parseDirectiveNamedStructValue(/*Structure=*/NextIt->getValue(), 26395ffd83dbSDimitry Andric nextVal, nextLoc, IDVal); 26405ffd83dbSDimitry Andric } 26415ffd83dbSDimitry Andric 26425ffd83dbSDimitry Andric // __asm _emit or __asm __emit 26435ffd83dbSDimitry Andric if (ParsingMSInlineAsm && (IDVal == "_emit" || IDVal == "__emit" || 26445ffd83dbSDimitry Andric IDVal == "_EMIT" || IDVal == "__EMIT")) 26455ffd83dbSDimitry Andric return parseDirectiveMSEmit(IDLoc, Info, IDVal.size()); 26465ffd83dbSDimitry Andric 26475ffd83dbSDimitry Andric // __asm align 26485ffd83dbSDimitry Andric if (ParsingMSInlineAsm && (IDVal == "align" || IDVal == "ALIGN")) 26495ffd83dbSDimitry Andric return parseDirectiveMSAlign(IDLoc, Info); 26505ffd83dbSDimitry Andric 26515ffd83dbSDimitry Andric if (ParsingMSInlineAsm && (IDVal == "even" || IDVal == "EVEN")) 26525ffd83dbSDimitry Andric Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4); 26535ffd83dbSDimitry Andric if (checkForValidSection()) 26545ffd83dbSDimitry Andric return true; 26555ffd83dbSDimitry Andric 26565ffd83dbSDimitry Andric // Canonicalize the opcode to lower case. 26575ffd83dbSDimitry Andric std::string OpcodeStr = IDVal.lower(); 26585ffd83dbSDimitry Andric ParseInstructionInfo IInfo(Info.AsmRewrites); 26595ffd83dbSDimitry Andric bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID, 26605ffd83dbSDimitry Andric Info.ParsedOperands); 26615ffd83dbSDimitry Andric Info.ParseError = ParseHadError; 26625ffd83dbSDimitry Andric 26635ffd83dbSDimitry Andric // Dump the parsed representation, if requested. 26645ffd83dbSDimitry Andric if (getShowParsedOperands()) { 26655ffd83dbSDimitry Andric SmallString<256> Str; 26665ffd83dbSDimitry Andric raw_svector_ostream OS(Str); 26675ffd83dbSDimitry Andric OS << "parsed instruction: ["; 26685ffd83dbSDimitry Andric for (unsigned i = 0; i != Info.ParsedOperands.size(); ++i) { 26695ffd83dbSDimitry Andric if (i != 0) 26705ffd83dbSDimitry Andric OS << ", "; 26715ffd83dbSDimitry Andric Info.ParsedOperands[i]->print(OS); 26725ffd83dbSDimitry Andric } 26735ffd83dbSDimitry Andric OS << "]"; 26745ffd83dbSDimitry Andric 26755ffd83dbSDimitry Andric printMessage(IDLoc, SourceMgr::DK_Note, OS.str()); 26765ffd83dbSDimitry Andric } 26775ffd83dbSDimitry Andric 26785ffd83dbSDimitry Andric // Fail even if ParseInstruction erroneously returns false. 26795ffd83dbSDimitry Andric if (hasPendingError() || ParseHadError) 26805ffd83dbSDimitry Andric return true; 26815ffd83dbSDimitry Andric 26825ffd83dbSDimitry Andric // If we are generating dwarf for the current section then generate a .loc 26835ffd83dbSDimitry Andric // directive for the instruction. 26845ffd83dbSDimitry Andric if (!ParseHadError && enabledGenDwarfForAssembly() && 26855ffd83dbSDimitry Andric getContext().getGenDwarfSectionSyms().count( 26865ffd83dbSDimitry Andric getStreamer().getCurrentSectionOnly())) { 26875ffd83dbSDimitry Andric unsigned Line; 26885ffd83dbSDimitry Andric if (ActiveMacros.empty()) 26895ffd83dbSDimitry Andric Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer); 26905ffd83dbSDimitry Andric else 26915ffd83dbSDimitry Andric Line = SrcMgr.FindLineNumber(ActiveMacros.front()->InstantiationLoc, 26925ffd83dbSDimitry Andric ActiveMacros.front()->ExitBuffer); 26935ffd83dbSDimitry Andric 26945ffd83dbSDimitry Andric // If we previously parsed a cpp hash file line comment then make sure the 26955ffd83dbSDimitry Andric // current Dwarf File is for the CppHashFilename if not then emit the 26965ffd83dbSDimitry Andric // Dwarf File table for it and adjust the line number for the .loc. 26975ffd83dbSDimitry Andric if (!CppHashInfo.Filename.empty()) { 26985ffd83dbSDimitry Andric unsigned FileNumber = getStreamer().emitDwarfFileDirective( 26995ffd83dbSDimitry Andric 0, StringRef(), CppHashInfo.Filename); 27005ffd83dbSDimitry Andric getContext().setGenDwarfFileNumber(FileNumber); 27015ffd83dbSDimitry Andric 27025ffd83dbSDimitry Andric unsigned CppHashLocLineNo = 27035ffd83dbSDimitry Andric SrcMgr.FindLineNumber(CppHashInfo.Loc, CppHashInfo.Buf); 27045ffd83dbSDimitry Andric Line = CppHashInfo.LineNumber - 1 + (Line - CppHashLocLineNo); 27055ffd83dbSDimitry Andric } 27065ffd83dbSDimitry Andric 27075ffd83dbSDimitry Andric getStreamer().emitDwarfLocDirective( 27085ffd83dbSDimitry Andric getContext().getGenDwarfFileNumber(), Line, 0, 27095ffd83dbSDimitry Andric DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0, 27105ffd83dbSDimitry Andric StringRef()); 27115ffd83dbSDimitry Andric } 27125ffd83dbSDimitry Andric 27135ffd83dbSDimitry Andric // If parsing succeeded, match the instruction. 27145ffd83dbSDimitry Andric if (!ParseHadError) { 27155ffd83dbSDimitry Andric uint64_t ErrorInfo; 27165ffd83dbSDimitry Andric if (getTargetParser().MatchAndEmitInstruction( 27175ffd83dbSDimitry Andric IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo, 27185ffd83dbSDimitry Andric getTargetParser().isParsingMSInlineAsm())) 27195ffd83dbSDimitry Andric return true; 27205ffd83dbSDimitry Andric } 27215ffd83dbSDimitry Andric return false; 27225ffd83dbSDimitry Andric } 27235ffd83dbSDimitry Andric 27245ffd83dbSDimitry Andric // Parse and erase curly braces marking block start/end. 27255ffd83dbSDimitry Andric bool MasmParser::parseCurlyBlockScope( 27265ffd83dbSDimitry Andric SmallVectorImpl<AsmRewrite> &AsmStrRewrites) { 27275ffd83dbSDimitry Andric // Identify curly brace marking block start/end. 27285ffd83dbSDimitry Andric if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly)) 27295ffd83dbSDimitry Andric return false; 27305ffd83dbSDimitry Andric 27315ffd83dbSDimitry Andric SMLoc StartLoc = Lexer.getLoc(); 27325ffd83dbSDimitry Andric Lex(); // Eat the brace. 27335ffd83dbSDimitry Andric if (Lexer.is(AsmToken::EndOfStatement)) 27345ffd83dbSDimitry Andric Lex(); // Eat EndOfStatement following the brace. 27355ffd83dbSDimitry Andric 27365ffd83dbSDimitry Andric // Erase the block start/end brace from the output asm string. 27375ffd83dbSDimitry Andric AsmStrRewrites.emplace_back(AOK_Skip, StartLoc, Lexer.getLoc().getPointer() - 27385ffd83dbSDimitry Andric StartLoc.getPointer()); 27395ffd83dbSDimitry Andric return true; 27405ffd83dbSDimitry Andric } 27415ffd83dbSDimitry Andric 27425ffd83dbSDimitry Andric /// parseCppHashLineFilenameComment as this: 27435ffd83dbSDimitry Andric /// ::= # number "filename" 27445ffd83dbSDimitry Andric bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) { 27455ffd83dbSDimitry Andric Lex(); // Eat the hash token. 27465ffd83dbSDimitry Andric // Lexer only ever emits HashDirective if it fully formed if it's 27475ffd83dbSDimitry Andric // done the checking already so this is an internal error. 27485ffd83dbSDimitry Andric assert(getTok().is(AsmToken::Integer) && 27495ffd83dbSDimitry Andric "Lexing Cpp line comment: Expected Integer"); 27505ffd83dbSDimitry Andric int64_t LineNumber = getTok().getIntVal(); 27515ffd83dbSDimitry Andric Lex(); 27525ffd83dbSDimitry Andric assert(getTok().is(AsmToken::String) && 27535ffd83dbSDimitry Andric "Lexing Cpp line comment: Expected String"); 27545ffd83dbSDimitry Andric StringRef Filename = getTok().getString(); 27555ffd83dbSDimitry Andric Lex(); 27565ffd83dbSDimitry Andric 27575ffd83dbSDimitry Andric // Get rid of the enclosing quotes. 27585ffd83dbSDimitry Andric Filename = Filename.substr(1, Filename.size() - 2); 27595ffd83dbSDimitry Andric 27605ffd83dbSDimitry Andric // Save the SMLoc, Filename and LineNumber for later use by diagnostics 27615ffd83dbSDimitry Andric // and possibly DWARF file info. 27625ffd83dbSDimitry Andric CppHashInfo.Loc = L; 27635ffd83dbSDimitry Andric CppHashInfo.Filename = Filename; 27645ffd83dbSDimitry Andric CppHashInfo.LineNumber = LineNumber; 27655ffd83dbSDimitry Andric CppHashInfo.Buf = CurBuffer; 27665ffd83dbSDimitry Andric if (FirstCppHashFilename.empty()) 27675ffd83dbSDimitry Andric FirstCppHashFilename = Filename; 27685ffd83dbSDimitry Andric return false; 27695ffd83dbSDimitry Andric } 27705ffd83dbSDimitry Andric 27715ffd83dbSDimitry Andric /// will use the last parsed cpp hash line filename comment 27725ffd83dbSDimitry Andric /// for the Filename and LineNo if any in the diagnostic. 27735ffd83dbSDimitry Andric void MasmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { 27745ffd83dbSDimitry Andric const MasmParser *Parser = static_cast<const MasmParser *>(Context); 27755ffd83dbSDimitry Andric raw_ostream &OS = errs(); 27765ffd83dbSDimitry Andric 27775ffd83dbSDimitry Andric const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr(); 27785ffd83dbSDimitry Andric SMLoc DiagLoc = Diag.getLoc(); 27795ffd83dbSDimitry Andric unsigned DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); 27805ffd83dbSDimitry Andric unsigned CppHashBuf = 27815ffd83dbSDimitry Andric Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc); 27825ffd83dbSDimitry Andric 27835ffd83dbSDimitry Andric // Like SourceMgr::printMessage() we need to print the include stack if any 27845ffd83dbSDimitry Andric // before printing the message. 27855ffd83dbSDimitry Andric unsigned DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); 27865ffd83dbSDimitry Andric if (!Parser->SavedDiagHandler && DiagCurBuffer && 27875ffd83dbSDimitry Andric DiagCurBuffer != DiagSrcMgr.getMainFileID()) { 27885ffd83dbSDimitry Andric SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer); 27895ffd83dbSDimitry Andric DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS); 27905ffd83dbSDimitry Andric } 27915ffd83dbSDimitry Andric 27925ffd83dbSDimitry Andric // If we have not parsed a cpp hash line filename comment or the source 27935ffd83dbSDimitry Andric // manager changed or buffer changed (like in a nested include) then just 27945ffd83dbSDimitry Andric // print the normal diagnostic using its Filename and LineNo. 27955ffd83dbSDimitry Andric if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr || 27965ffd83dbSDimitry Andric DiagBuf != CppHashBuf) { 27975ffd83dbSDimitry Andric if (Parser->SavedDiagHandler) 27985ffd83dbSDimitry Andric Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext); 27995ffd83dbSDimitry Andric else 28005ffd83dbSDimitry Andric Diag.print(nullptr, OS); 28015ffd83dbSDimitry Andric return; 28025ffd83dbSDimitry Andric } 28035ffd83dbSDimitry Andric 28045ffd83dbSDimitry Andric // Use the CppHashFilename and calculate a line number based on the 28055ffd83dbSDimitry Andric // CppHashInfo.Loc and CppHashInfo.LineNumber relative to this Diag's SMLoc 28065ffd83dbSDimitry Andric // for the diagnostic. 28075ffd83dbSDimitry Andric const std::string &Filename = std::string(Parser->CppHashInfo.Filename); 28085ffd83dbSDimitry Andric 28095ffd83dbSDimitry Andric int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf); 28105ffd83dbSDimitry Andric int CppHashLocLineNo = 28115ffd83dbSDimitry Andric Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf); 28125ffd83dbSDimitry Andric int LineNo = 28135ffd83dbSDimitry Andric Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo); 28145ffd83dbSDimitry Andric 28155ffd83dbSDimitry Andric SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), Filename, LineNo, 28165ffd83dbSDimitry Andric Diag.getColumnNo(), Diag.getKind(), Diag.getMessage(), 28175ffd83dbSDimitry Andric Diag.getLineContents(), Diag.getRanges()); 28185ffd83dbSDimitry Andric 28195ffd83dbSDimitry Andric if (Parser->SavedDiagHandler) 28205ffd83dbSDimitry Andric Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext); 28215ffd83dbSDimitry Andric else 28225ffd83dbSDimitry Andric NewDiag.print(nullptr, OS); 28235ffd83dbSDimitry Andric } 28245ffd83dbSDimitry Andric 2825e8d8bef9SDimitry Andric // This is similar to the IsIdentifierChar function in AsmLexer.cpp, but does 2826e8d8bef9SDimitry Andric // not accept '.'. 2827e8d8bef9SDimitry Andric static bool isMacroParameterChar(char C) { 2828e8d8bef9SDimitry Andric return isAlnum(C) || C == '_' || C == '$' || C == '@' || C == '?'; 28295ffd83dbSDimitry Andric } 28305ffd83dbSDimitry Andric 28315ffd83dbSDimitry Andric bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, 28325ffd83dbSDimitry Andric ArrayRef<MCAsmMacroParameter> Parameters, 28335ffd83dbSDimitry Andric ArrayRef<MCAsmMacroArgument> A, 2834e8d8bef9SDimitry Andric const std::vector<std::string> &Locals, SMLoc L) { 28355ffd83dbSDimitry Andric unsigned NParameters = Parameters.size(); 2836e8d8bef9SDimitry Andric if (NParameters != A.size()) 28375ffd83dbSDimitry Andric return Error(L, "Wrong number of arguments"); 2838e8d8bef9SDimitry Andric StringMap<std::string> LocalSymbols; 2839e8d8bef9SDimitry Andric std::string Name; 2840e8d8bef9SDimitry Andric Name.reserve(6); 2841e8d8bef9SDimitry Andric for (StringRef Local : Locals) { 2842e8d8bef9SDimitry Andric raw_string_ostream LocalName(Name); 2843e8d8bef9SDimitry Andric LocalName << "??" 2844e8d8bef9SDimitry Andric << format_hex_no_prefix(LocalCounter++, 4, /*Upper=*/true); 2845e8d8bef9SDimitry Andric LocalSymbols.insert({Local, LocalName.str()}); 2846e8d8bef9SDimitry Andric Name.clear(); 2847e8d8bef9SDimitry Andric } 28485ffd83dbSDimitry Andric 2849bdd1243dSDimitry Andric std::optional<char> CurrentQuote; 28505ffd83dbSDimitry Andric while (!Body.empty()) { 28515ffd83dbSDimitry Andric // Scan for the next substitution. 28525ffd83dbSDimitry Andric std::size_t End = Body.size(), Pos = 0; 2853e8d8bef9SDimitry Andric std::size_t IdentifierPos = End; 28545ffd83dbSDimitry Andric for (; Pos != End; ++Pos) { 2855e8d8bef9SDimitry Andric // Find the next possible macro parameter, including preceding a '&' 2856e8d8bef9SDimitry Andric // inside quotes. 2857e8d8bef9SDimitry Andric if (Body[Pos] == '&') 28585ffd83dbSDimitry Andric break; 2859e8d8bef9SDimitry Andric if (isMacroParameterChar(Body[Pos])) { 286081ad6265SDimitry Andric if (!CurrentQuote) 2861e8d8bef9SDimitry Andric break; 2862e8d8bef9SDimitry Andric if (IdentifierPos == End) 2863e8d8bef9SDimitry Andric IdentifierPos = Pos; 28645ffd83dbSDimitry Andric } else { 2865e8d8bef9SDimitry Andric IdentifierPos = End; 28665ffd83dbSDimitry Andric } 2867e8d8bef9SDimitry Andric 2868e8d8bef9SDimitry Andric // Track quotation status 286981ad6265SDimitry Andric if (!CurrentQuote) { 2870e8d8bef9SDimitry Andric if (Body[Pos] == '\'' || Body[Pos] == '"') 2871e8d8bef9SDimitry Andric CurrentQuote = Body[Pos]; 2872e8d8bef9SDimitry Andric } else if (Body[Pos] == CurrentQuote) { 2873e8d8bef9SDimitry Andric if (Pos + 1 != End && Body[Pos + 1] == CurrentQuote) { 2874e8d8bef9SDimitry Andric // Escaped quote, and quotes aren't identifier chars; skip 2875e8d8bef9SDimitry Andric ++Pos; 2876e8d8bef9SDimitry Andric continue; 2877e8d8bef9SDimitry Andric } else { 2878e8d8bef9SDimitry Andric CurrentQuote.reset(); 2879e8d8bef9SDimitry Andric } 2880e8d8bef9SDimitry Andric } 2881e8d8bef9SDimitry Andric } 2882e8d8bef9SDimitry Andric if (IdentifierPos != End) { 2883e8d8bef9SDimitry Andric // We've recognized an identifier before an apostrophe inside quotes; 2884e8d8bef9SDimitry Andric // check once to see if we can expand it. 2885e8d8bef9SDimitry Andric Pos = IdentifierPos; 2886e8d8bef9SDimitry Andric IdentifierPos = End; 28875ffd83dbSDimitry Andric } 28885ffd83dbSDimitry Andric 28895ffd83dbSDimitry Andric // Add the prefix. 28905ffd83dbSDimitry Andric OS << Body.slice(0, Pos); 28915ffd83dbSDimitry Andric 28925ffd83dbSDimitry Andric // Check if we reached the end. 28935ffd83dbSDimitry Andric if (Pos == End) 28945ffd83dbSDimitry Andric break; 28955ffd83dbSDimitry Andric 2896e8d8bef9SDimitry Andric unsigned I = Pos; 2897e8d8bef9SDimitry Andric bool InitialAmpersand = (Body[I] == '&'); 2898e8d8bef9SDimitry Andric if (InitialAmpersand) { 28995ffd83dbSDimitry Andric ++I; 2900e8d8bef9SDimitry Andric ++Pos; 2901e8d8bef9SDimitry Andric } 2902e8d8bef9SDimitry Andric while (I < End && isMacroParameterChar(Body[I])) 29035ffd83dbSDimitry Andric ++I; 29045ffd83dbSDimitry Andric 2905e8d8bef9SDimitry Andric const char *Begin = Body.data() + Pos; 2906e8d8bef9SDimitry Andric StringRef Argument(Begin, I - Pos); 2907fe6060f1SDimitry Andric const std::string ArgumentLower = Argument.lower(); 29085ffd83dbSDimitry Andric unsigned Index = 0; 29095ffd83dbSDimitry Andric 29105ffd83dbSDimitry Andric for (; Index < NParameters; ++Index) 2911fe6060f1SDimitry Andric if (Parameters[Index].Name.equals_insensitive(ArgumentLower)) 29125ffd83dbSDimitry Andric break; 29135ffd83dbSDimitry Andric 29145ffd83dbSDimitry Andric if (Index == NParameters) { 2915e8d8bef9SDimitry Andric if (InitialAmpersand) 2916e8d8bef9SDimitry Andric OS << '&'; 2917fe6060f1SDimitry Andric auto it = LocalSymbols.find(ArgumentLower); 2918e8d8bef9SDimitry Andric if (it != LocalSymbols.end()) 2919e8d8bef9SDimitry Andric OS << it->second; 2920e8d8bef9SDimitry Andric else 2921e8d8bef9SDimitry Andric OS << Argument; 29225ffd83dbSDimitry Andric Pos = I; 29235ffd83dbSDimitry Andric } else { 2924e8d8bef9SDimitry Andric for (const AsmToken &Token : A[Index]) { 2925e8d8bef9SDimitry Andric // In MASM, you can write '%expr'. 29265ffd83dbSDimitry Andric // The prefix '%' evaluates the expression 'expr' 29275ffd83dbSDimitry Andric // and uses the result as a string (e.g. replace %(1+2) with the 29285ffd83dbSDimitry Andric // string "3"). 29295ffd83dbSDimitry Andric // Here, we identify the integer token which is the result of the 29305ffd83dbSDimitry Andric // absolute expression evaluation and replace it with its string 29315ffd83dbSDimitry Andric // representation. 2932e8d8bef9SDimitry Andric if (Token.getString().front() == '%' && Token.is(AsmToken::Integer)) 29335ffd83dbSDimitry Andric // Emit an integer value to the buffer. 29345ffd83dbSDimitry Andric OS << Token.getIntVal(); 29355ffd83dbSDimitry Andric else 2936e8d8bef9SDimitry Andric OS << Token.getString(); 29375ffd83dbSDimitry Andric } 2938e8d8bef9SDimitry Andric 2939e8d8bef9SDimitry Andric Pos += Argument.size(); 2940e8d8bef9SDimitry Andric if (Pos < End && Body[Pos] == '&') { 2941e8d8bef9SDimitry Andric ++Pos; 29425ffd83dbSDimitry Andric } 29435ffd83dbSDimitry Andric } 29445ffd83dbSDimitry Andric // Update the scan point. 29455ffd83dbSDimitry Andric Body = Body.substr(Pos); 29465ffd83dbSDimitry Andric } 29475ffd83dbSDimitry Andric 29485ffd83dbSDimitry Andric return false; 29495ffd83dbSDimitry Andric } 29505ffd83dbSDimitry Andric 29515ffd83dbSDimitry Andric static bool isOperator(AsmToken::TokenKind kind) { 29525ffd83dbSDimitry Andric switch (kind) { 29535ffd83dbSDimitry Andric default: 29545ffd83dbSDimitry Andric return false; 29555ffd83dbSDimitry Andric case AsmToken::Plus: 29565ffd83dbSDimitry Andric case AsmToken::Minus: 29575ffd83dbSDimitry Andric case AsmToken::Tilde: 29585ffd83dbSDimitry Andric case AsmToken::Slash: 29595ffd83dbSDimitry Andric case AsmToken::Star: 29605ffd83dbSDimitry Andric case AsmToken::Dot: 29615ffd83dbSDimitry Andric case AsmToken::Equal: 29625ffd83dbSDimitry Andric case AsmToken::EqualEqual: 29635ffd83dbSDimitry Andric case AsmToken::Pipe: 29645ffd83dbSDimitry Andric case AsmToken::PipePipe: 29655ffd83dbSDimitry Andric case AsmToken::Caret: 29665ffd83dbSDimitry Andric case AsmToken::Amp: 29675ffd83dbSDimitry Andric case AsmToken::AmpAmp: 29685ffd83dbSDimitry Andric case AsmToken::Exclaim: 29695ffd83dbSDimitry Andric case AsmToken::ExclaimEqual: 29705ffd83dbSDimitry Andric case AsmToken::Less: 29715ffd83dbSDimitry Andric case AsmToken::LessEqual: 29725ffd83dbSDimitry Andric case AsmToken::LessLess: 29735ffd83dbSDimitry Andric case AsmToken::LessGreater: 29745ffd83dbSDimitry Andric case AsmToken::Greater: 29755ffd83dbSDimitry Andric case AsmToken::GreaterEqual: 29765ffd83dbSDimitry Andric case AsmToken::GreaterGreater: 29775ffd83dbSDimitry Andric return true; 29785ffd83dbSDimitry Andric } 29795ffd83dbSDimitry Andric } 29805ffd83dbSDimitry Andric 29815ffd83dbSDimitry Andric namespace { 29825ffd83dbSDimitry Andric 29835ffd83dbSDimitry Andric class AsmLexerSkipSpaceRAII { 29845ffd83dbSDimitry Andric public: 29855ffd83dbSDimitry Andric AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) { 29865ffd83dbSDimitry Andric Lexer.setSkipSpace(SkipSpace); 29875ffd83dbSDimitry Andric } 29885ffd83dbSDimitry Andric 29895ffd83dbSDimitry Andric ~AsmLexerSkipSpaceRAII() { 29905ffd83dbSDimitry Andric Lexer.setSkipSpace(true); 29915ffd83dbSDimitry Andric } 29925ffd83dbSDimitry Andric 29935ffd83dbSDimitry Andric private: 29945ffd83dbSDimitry Andric AsmLexer &Lexer; 29955ffd83dbSDimitry Andric }; 29965ffd83dbSDimitry Andric 29975ffd83dbSDimitry Andric } // end anonymous namespace 29985ffd83dbSDimitry Andric 2999e8d8bef9SDimitry Andric bool MasmParser::parseMacroArgument(const MCAsmMacroParameter *MP, 3000e8d8bef9SDimitry Andric MCAsmMacroArgument &MA, 3001e8d8bef9SDimitry Andric AsmToken::TokenKind EndTok) { 3002e8d8bef9SDimitry Andric if (MP && MP->Vararg) { 3003e8d8bef9SDimitry Andric if (Lexer.isNot(EndTok)) { 3004e8d8bef9SDimitry Andric SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok); 3005e8d8bef9SDimitry Andric for (StringRef S : Str) { 3006e8d8bef9SDimitry Andric MA.emplace_back(AsmToken::String, S); 30075ffd83dbSDimitry Andric } 3008e8d8bef9SDimitry Andric } 3009e8d8bef9SDimitry Andric return false; 3010e8d8bef9SDimitry Andric } 3011e8d8bef9SDimitry Andric 3012e8d8bef9SDimitry Andric SMLoc StrLoc = Lexer.getLoc(), EndLoc; 3013e8d8bef9SDimitry Andric if (Lexer.is(AsmToken::Less) && isAngleBracketString(StrLoc, EndLoc)) { 3014e8d8bef9SDimitry Andric const char *StrChar = StrLoc.getPointer() + 1; 3015e8d8bef9SDimitry Andric const char *EndChar = EndLoc.getPointer() - 1; 3016e8d8bef9SDimitry Andric jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back()); 3017e8d8bef9SDimitry Andric /// Eat from '<' to '>'. 3018e8d8bef9SDimitry Andric Lex(); 3019e8d8bef9SDimitry Andric MA.emplace_back(AsmToken::String, StringRef(StrChar, EndChar - StrChar)); 30205ffd83dbSDimitry Andric return false; 30215ffd83dbSDimitry Andric } 30225ffd83dbSDimitry Andric 30235ffd83dbSDimitry Andric unsigned ParenLevel = 0; 30245ffd83dbSDimitry Andric 30255ffd83dbSDimitry Andric // Darwin doesn't use spaces to delmit arguments. 30265ffd83dbSDimitry Andric AsmLexerSkipSpaceRAII ScopedSkipSpace(Lexer, IsDarwin); 30275ffd83dbSDimitry Andric 30285ffd83dbSDimitry Andric bool SpaceEaten; 30295ffd83dbSDimitry Andric 30305ffd83dbSDimitry Andric while (true) { 30315ffd83dbSDimitry Andric SpaceEaten = false; 30325ffd83dbSDimitry Andric if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal)) 3033e8d8bef9SDimitry Andric return TokError("unexpected token"); 30345ffd83dbSDimitry Andric 30355ffd83dbSDimitry Andric if (ParenLevel == 0) { 30365ffd83dbSDimitry Andric if (Lexer.is(AsmToken::Comma)) 30375ffd83dbSDimitry Andric break; 30385ffd83dbSDimitry Andric 30395ffd83dbSDimitry Andric if (Lexer.is(AsmToken::Space)) { 30405ffd83dbSDimitry Andric SpaceEaten = true; 3041e8d8bef9SDimitry Andric Lex(); // Eat spaces. 30425ffd83dbSDimitry Andric } 30435ffd83dbSDimitry Andric 30445ffd83dbSDimitry Andric // Spaces can delimit parameters, but could also be part an expression. 30455ffd83dbSDimitry Andric // If the token after a space is an operator, add the token and the next 30465ffd83dbSDimitry Andric // one into this argument 30475ffd83dbSDimitry Andric if (!IsDarwin) { 3048e8d8bef9SDimitry Andric if (isOperator(Lexer.getKind()) && Lexer.isNot(EndTok)) { 30495ffd83dbSDimitry Andric MA.push_back(getTok()); 3050e8d8bef9SDimitry Andric Lex(); 30515ffd83dbSDimitry Andric 30525ffd83dbSDimitry Andric // Whitespace after an operator can be ignored. 30535ffd83dbSDimitry Andric if (Lexer.is(AsmToken::Space)) 3054e8d8bef9SDimitry Andric Lex(); 30555ffd83dbSDimitry Andric 30565ffd83dbSDimitry Andric continue; 30575ffd83dbSDimitry Andric } 30585ffd83dbSDimitry Andric } 30595ffd83dbSDimitry Andric if (SpaceEaten) 30605ffd83dbSDimitry Andric break; 30615ffd83dbSDimitry Andric } 30625ffd83dbSDimitry Andric 30635ffd83dbSDimitry Andric // handleMacroEntry relies on not advancing the lexer here 30645ffd83dbSDimitry Andric // to be able to fill in the remaining default parameter values 3065e8d8bef9SDimitry Andric if (Lexer.is(EndTok) && (EndTok != AsmToken::RParen || ParenLevel == 0)) 30665ffd83dbSDimitry Andric break; 30675ffd83dbSDimitry Andric 30685ffd83dbSDimitry Andric // Adjust the current parentheses level. 30695ffd83dbSDimitry Andric if (Lexer.is(AsmToken::LParen)) 30705ffd83dbSDimitry Andric ++ParenLevel; 30715ffd83dbSDimitry Andric else if (Lexer.is(AsmToken::RParen) && ParenLevel) 30725ffd83dbSDimitry Andric --ParenLevel; 30735ffd83dbSDimitry Andric 30745ffd83dbSDimitry Andric // Append the token to the current argument list. 30755ffd83dbSDimitry Andric MA.push_back(getTok()); 3076e8d8bef9SDimitry Andric Lex(); 30775ffd83dbSDimitry Andric } 30785ffd83dbSDimitry Andric 30795ffd83dbSDimitry Andric if (ParenLevel != 0) 3080e8d8bef9SDimitry Andric return TokError("unbalanced parentheses in argument"); 3081e8d8bef9SDimitry Andric 3082e8d8bef9SDimitry Andric if (MA.empty() && MP) { 3083e8d8bef9SDimitry Andric if (MP->Required) { 3084e8d8bef9SDimitry Andric return TokError("missing value for required parameter '" + MP->Name + 3085e8d8bef9SDimitry Andric "'"); 3086e8d8bef9SDimitry Andric } else { 3087e8d8bef9SDimitry Andric MA = MP->Value; 3088e8d8bef9SDimitry Andric } 3089e8d8bef9SDimitry Andric } 30905ffd83dbSDimitry Andric return false; 30915ffd83dbSDimitry Andric } 30925ffd83dbSDimitry Andric 30935ffd83dbSDimitry Andric // Parse the macro instantiation arguments. 30945ffd83dbSDimitry Andric bool MasmParser::parseMacroArguments(const MCAsmMacro *M, 3095e8d8bef9SDimitry Andric MCAsmMacroArguments &A, 3096e8d8bef9SDimitry Andric AsmToken::TokenKind EndTok) { 30975ffd83dbSDimitry Andric const unsigned NParameters = M ? M->Parameters.size() : 0; 30985ffd83dbSDimitry Andric bool NamedParametersFound = false; 30995ffd83dbSDimitry Andric SmallVector<SMLoc, 4> FALocs; 31005ffd83dbSDimitry Andric 31015ffd83dbSDimitry Andric A.resize(NParameters); 31025ffd83dbSDimitry Andric FALocs.resize(NParameters); 31035ffd83dbSDimitry Andric 31045ffd83dbSDimitry Andric // Parse two kinds of macro invocations: 31055ffd83dbSDimitry Andric // - macros defined without any parameters accept an arbitrary number of them 31065ffd83dbSDimitry Andric // - macros defined with parameters accept at most that many of them 31075ffd83dbSDimitry Andric for (unsigned Parameter = 0; !NParameters || Parameter < NParameters; 31085ffd83dbSDimitry Andric ++Parameter) { 31095ffd83dbSDimitry Andric SMLoc IDLoc = Lexer.getLoc(); 31105ffd83dbSDimitry Andric MCAsmMacroParameter FA; 31115ffd83dbSDimitry Andric 3112fe6060f1SDimitry Andric if (Lexer.is(AsmToken::Identifier) && peekTok().is(AsmToken::Equal)) { 31135ffd83dbSDimitry Andric if (parseIdentifier(FA.Name)) 31145ffd83dbSDimitry Andric return Error(IDLoc, "invalid argument identifier for formal argument"); 31155ffd83dbSDimitry Andric 31165ffd83dbSDimitry Andric if (Lexer.isNot(AsmToken::Equal)) 31175ffd83dbSDimitry Andric return TokError("expected '=' after formal parameter identifier"); 31185ffd83dbSDimitry Andric 31195ffd83dbSDimitry Andric Lex(); 31205ffd83dbSDimitry Andric 31215ffd83dbSDimitry Andric NamedParametersFound = true; 31225ffd83dbSDimitry Andric } 31235ffd83dbSDimitry Andric 31245ffd83dbSDimitry Andric if (NamedParametersFound && FA.Name.empty()) 31255ffd83dbSDimitry Andric return Error(IDLoc, "cannot mix positional and keyword arguments"); 31265ffd83dbSDimitry Andric 3127e8d8bef9SDimitry Andric unsigned PI = Parameter; 3128e8d8bef9SDimitry Andric if (!FA.Name.empty()) { 3129e8d8bef9SDimitry Andric assert(M && "expected macro to be defined"); 3130e8d8bef9SDimitry Andric unsigned FAI = 0; 3131e8d8bef9SDimitry Andric for (FAI = 0; FAI < NParameters; ++FAI) 3132e8d8bef9SDimitry Andric if (M->Parameters[FAI].Name == FA.Name) 3133e8d8bef9SDimitry Andric break; 3134e8d8bef9SDimitry Andric 3135e8d8bef9SDimitry Andric if (FAI >= NParameters) { 3136e8d8bef9SDimitry Andric return Error(IDLoc, "parameter named '" + FA.Name + 3137e8d8bef9SDimitry Andric "' does not exist for macro '" + M->Name + "'"); 3138e8d8bef9SDimitry Andric } 3139e8d8bef9SDimitry Andric PI = FAI; 3140e8d8bef9SDimitry Andric } 3141e8d8bef9SDimitry Andric const MCAsmMacroParameter *MP = nullptr; 3142e8d8bef9SDimitry Andric if (M && PI < NParameters) 3143e8d8bef9SDimitry Andric MP = &M->Parameters[PI]; 3144e8d8bef9SDimitry Andric 31455ffd83dbSDimitry Andric SMLoc StrLoc = Lexer.getLoc(); 31465ffd83dbSDimitry Andric SMLoc EndLoc; 3147e8d8bef9SDimitry Andric if (Lexer.is(AsmToken::Percent)) { 31485ffd83dbSDimitry Andric const MCExpr *AbsoluteExp; 31495ffd83dbSDimitry Andric int64_t Value; 31505ffd83dbSDimitry Andric /// Eat '%'. 31515ffd83dbSDimitry Andric Lex(); 31525ffd83dbSDimitry Andric if (parseExpression(AbsoluteExp, EndLoc)) 31535ffd83dbSDimitry Andric return false; 31545ffd83dbSDimitry Andric if (!AbsoluteExp->evaluateAsAbsolute(Value, 31555ffd83dbSDimitry Andric getStreamer().getAssemblerPtr())) 31565ffd83dbSDimitry Andric return Error(StrLoc, "expected absolute expression"); 31575ffd83dbSDimitry Andric const char *StrChar = StrLoc.getPointer(); 31585ffd83dbSDimitry Andric const char *EndChar = EndLoc.getPointer(); 31595ffd83dbSDimitry Andric AsmToken newToken(AsmToken::Integer, 31605ffd83dbSDimitry Andric StringRef(StrChar, EndChar - StrChar), Value); 31615ffd83dbSDimitry Andric FA.Value.push_back(newToken); 3162e8d8bef9SDimitry Andric } else if (parseMacroArgument(MP, FA.Value, EndTok)) { 3163e8d8bef9SDimitry Andric if (M) 3164e8d8bef9SDimitry Andric return addErrorSuffix(" in '" + M->Name + "' macro"); 3165e8d8bef9SDimitry Andric else 31665ffd83dbSDimitry Andric return true; 31675ffd83dbSDimitry Andric } 31685ffd83dbSDimitry Andric 31695ffd83dbSDimitry Andric if (!FA.Value.empty()) { 31705ffd83dbSDimitry Andric if (A.size() <= PI) 31715ffd83dbSDimitry Andric A.resize(PI + 1); 31725ffd83dbSDimitry Andric A[PI] = FA.Value; 31735ffd83dbSDimitry Andric 31745ffd83dbSDimitry Andric if (FALocs.size() <= PI) 31755ffd83dbSDimitry Andric FALocs.resize(PI + 1); 31765ffd83dbSDimitry Andric 31775ffd83dbSDimitry Andric FALocs[PI] = Lexer.getLoc(); 31785ffd83dbSDimitry Andric } 31795ffd83dbSDimitry Andric 31805ffd83dbSDimitry Andric // At the end of the statement, fill in remaining arguments that have 31815ffd83dbSDimitry Andric // default values. If there aren't any, then the next argument is 31825ffd83dbSDimitry Andric // required but missing 3183e8d8bef9SDimitry Andric if (Lexer.is(EndTok)) { 31845ffd83dbSDimitry Andric bool Failure = false; 31855ffd83dbSDimitry Andric for (unsigned FAI = 0; FAI < NParameters; ++FAI) { 31865ffd83dbSDimitry Andric if (A[FAI].empty()) { 31875ffd83dbSDimitry Andric if (M->Parameters[FAI].Required) { 31885ffd83dbSDimitry Andric Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(), 31895ffd83dbSDimitry Andric "missing value for required parameter " 3190e8d8bef9SDimitry Andric "'" + 3191e8d8bef9SDimitry Andric M->Parameters[FAI].Name + "' in macro '" + M->Name + "'"); 31925ffd83dbSDimitry Andric Failure = true; 31935ffd83dbSDimitry Andric } 31945ffd83dbSDimitry Andric 31955ffd83dbSDimitry Andric if (!M->Parameters[FAI].Value.empty()) 31965ffd83dbSDimitry Andric A[FAI] = M->Parameters[FAI].Value; 31975ffd83dbSDimitry Andric } 31985ffd83dbSDimitry Andric } 31995ffd83dbSDimitry Andric return Failure; 32005ffd83dbSDimitry Andric } 32015ffd83dbSDimitry Andric 32025ffd83dbSDimitry Andric if (Lexer.is(AsmToken::Comma)) 32035ffd83dbSDimitry Andric Lex(); 32045ffd83dbSDimitry Andric } 32055ffd83dbSDimitry Andric 32065ffd83dbSDimitry Andric return TokError("too many positional arguments"); 32075ffd83dbSDimitry Andric } 32085ffd83dbSDimitry Andric 3209e8d8bef9SDimitry Andric bool MasmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc, 3210e8d8bef9SDimitry Andric AsmToken::TokenKind ArgumentEndTok) { 32115ffd83dbSDimitry Andric // Arbitrarily limit macro nesting depth (default matches 'as'). We can 32125ffd83dbSDimitry Andric // eliminate this, although we should protect against infinite loops. 32135ffd83dbSDimitry Andric unsigned MaxNestingDepth = AsmMacroMaxNestingDepth; 32145ffd83dbSDimitry Andric if (ActiveMacros.size() == MaxNestingDepth) { 32155ffd83dbSDimitry Andric std::ostringstream MaxNestingDepthError; 32165ffd83dbSDimitry Andric MaxNestingDepthError << "macros cannot be nested more than " 32175ffd83dbSDimitry Andric << MaxNestingDepth << " levels deep." 32185ffd83dbSDimitry Andric << " Use -asm-macro-max-nesting-depth to increase " 32195ffd83dbSDimitry Andric "this limit."; 32205ffd83dbSDimitry Andric return TokError(MaxNestingDepthError.str()); 32215ffd83dbSDimitry Andric } 32225ffd83dbSDimitry Andric 32235ffd83dbSDimitry Andric MCAsmMacroArguments A; 3224e8d8bef9SDimitry Andric if (parseMacroArguments(M, A, ArgumentEndTok)) 32255ffd83dbSDimitry Andric return true; 32265ffd83dbSDimitry Andric 32275ffd83dbSDimitry Andric // Macro instantiation is lexical, unfortunately. We construct a new buffer 32285ffd83dbSDimitry Andric // to hold the macro body with substitutions. 32295ffd83dbSDimitry Andric SmallString<256> Buf; 32305ffd83dbSDimitry Andric StringRef Body = M->Body; 32315ffd83dbSDimitry Andric raw_svector_ostream OS(Buf); 32325ffd83dbSDimitry Andric 3233e8d8bef9SDimitry Andric if (expandMacro(OS, Body, M->Parameters, A, M->Locals, getTok().getLoc())) 32345ffd83dbSDimitry Andric return true; 32355ffd83dbSDimitry Andric 3236e8d8bef9SDimitry Andric // We include the endm in the buffer as our cue to exit the macro 32375ffd83dbSDimitry Andric // instantiation. 3238e8d8bef9SDimitry Andric OS << "endm\n"; 32395ffd83dbSDimitry Andric 32405ffd83dbSDimitry Andric std::unique_ptr<MemoryBuffer> Instantiation = 32415ffd83dbSDimitry Andric MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>"); 32425ffd83dbSDimitry Andric 32435ffd83dbSDimitry Andric // Create the macro instantiation object and add to the current macro 32445ffd83dbSDimitry Andric // instantiation stack. 32455ffd83dbSDimitry Andric MacroInstantiation *MI = new MacroInstantiation{ 32465ffd83dbSDimitry Andric NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()}; 32475ffd83dbSDimitry Andric ActiveMacros.push_back(MI); 32485ffd83dbSDimitry Andric 32495ffd83dbSDimitry Andric ++NumOfMacroInstantiations; 32505ffd83dbSDimitry Andric 32515ffd83dbSDimitry Andric // Jump to the macro instantiation and prime the lexer. 32525ffd83dbSDimitry Andric CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc()); 32535ffd83dbSDimitry Andric Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); 3254e8d8bef9SDimitry Andric EndStatementAtEOFStack.push_back(true); 32555ffd83dbSDimitry Andric Lex(); 32565ffd83dbSDimitry Andric 32575ffd83dbSDimitry Andric return false; 32585ffd83dbSDimitry Andric } 32595ffd83dbSDimitry Andric 32605ffd83dbSDimitry Andric void MasmParser::handleMacroExit() { 3261e8d8bef9SDimitry Andric // Jump to the token we should return to, and consume it. 3262e8d8bef9SDimitry Andric EndStatementAtEOFStack.pop_back(); 3263e8d8bef9SDimitry Andric jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer, 3264e8d8bef9SDimitry Andric EndStatementAtEOFStack.back()); 32655ffd83dbSDimitry Andric Lex(); 32665ffd83dbSDimitry Andric 32675ffd83dbSDimitry Andric // Pop the instantiation entry. 32685ffd83dbSDimitry Andric delete ActiveMacros.back(); 32695ffd83dbSDimitry Andric ActiveMacros.pop_back(); 32705ffd83dbSDimitry Andric } 32715ffd83dbSDimitry Andric 3272e8d8bef9SDimitry Andric bool MasmParser::handleMacroInvocation(const MCAsmMacro *M, SMLoc NameLoc) { 3273e8d8bef9SDimitry Andric if (!M->IsFunction) 3274e8d8bef9SDimitry Andric return Error(NameLoc, "cannot invoke macro procedure as function"); 3275e8d8bef9SDimitry Andric 3276e8d8bef9SDimitry Andric if (parseToken(AsmToken::LParen, "invoking macro function '" + M->Name + 3277e8d8bef9SDimitry Andric "' requires arguments in parentheses") || 3278e8d8bef9SDimitry Andric handleMacroEntry(M, NameLoc, AsmToken::RParen)) 3279e8d8bef9SDimitry Andric return true; 3280e8d8bef9SDimitry Andric 3281e8d8bef9SDimitry Andric // Parse all statements in the macro, retrieving the exit value when it ends. 3282e8d8bef9SDimitry Andric std::string ExitValue; 3283e8d8bef9SDimitry Andric SmallVector<AsmRewrite, 4> AsmStrRewrites; 3284e8d8bef9SDimitry Andric while (Lexer.isNot(AsmToken::Eof)) { 3285e8d8bef9SDimitry Andric ParseStatementInfo Info(&AsmStrRewrites); 3286e8d8bef9SDimitry Andric bool Parsed = parseStatement(Info, nullptr); 3287e8d8bef9SDimitry Andric 328881ad6265SDimitry Andric if (!Parsed && Info.ExitValue) { 3289e8d8bef9SDimitry Andric ExitValue = std::move(*Info.ExitValue); 3290e8d8bef9SDimitry Andric break; 3291e8d8bef9SDimitry Andric } 3292e8d8bef9SDimitry Andric 3293e8d8bef9SDimitry Andric // If we have a Lexer Error we are on an Error Token. Load in Lexer Error 3294e8d8bef9SDimitry Andric // for printing ErrMsg via Lex() only if no (presumably better) parser error 3295e8d8bef9SDimitry Andric // exists. 3296e8d8bef9SDimitry Andric if (Parsed && !hasPendingError() && Lexer.getTok().is(AsmToken::Error)) { 3297e8d8bef9SDimitry Andric Lex(); 3298e8d8bef9SDimitry Andric } 3299e8d8bef9SDimitry Andric 3300e8d8bef9SDimitry Andric // parseStatement returned true so may need to emit an error. 3301e8d8bef9SDimitry Andric printPendingErrors(); 3302e8d8bef9SDimitry Andric 3303e8d8bef9SDimitry Andric // Skipping to the next line if needed. 3304e8d8bef9SDimitry Andric if (Parsed && !getLexer().isAtStartOfStatement()) 3305e8d8bef9SDimitry Andric eatToEndOfStatement(); 3306e8d8bef9SDimitry Andric } 3307e8d8bef9SDimitry Andric 3308e8d8bef9SDimitry Andric // Consume the right-parenthesis on the other side of the arguments. 330904eeddc0SDimitry Andric if (parseRParen()) 3310e8d8bef9SDimitry Andric return true; 3311e8d8bef9SDimitry Andric 3312e8d8bef9SDimitry Andric // Exit values may require lexing, unfortunately. We construct a new buffer to 3313e8d8bef9SDimitry Andric // hold the exit value. 3314e8d8bef9SDimitry Andric std::unique_ptr<MemoryBuffer> MacroValue = 3315e8d8bef9SDimitry Andric MemoryBuffer::getMemBufferCopy(ExitValue, "<macro-value>"); 3316e8d8bef9SDimitry Andric 3317e8d8bef9SDimitry Andric // Jump from this location to the instantiated exit value, and prime the 3318e8d8bef9SDimitry Andric // lexer. 3319e8d8bef9SDimitry Andric CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(MacroValue), Lexer.getLoc()); 3320e8d8bef9SDimitry Andric Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), nullptr, 3321e8d8bef9SDimitry Andric /*EndStatementAtEOF=*/false); 3322e8d8bef9SDimitry Andric EndStatementAtEOFStack.push_back(false); 3323e8d8bef9SDimitry Andric Lex(); 3324e8d8bef9SDimitry Andric 3325e8d8bef9SDimitry Andric return false; 3326e8d8bef9SDimitry Andric } 3327e8d8bef9SDimitry Andric 33285ffd83dbSDimitry Andric /// parseIdentifier: 33295ffd83dbSDimitry Andric /// ::= identifier 33305ffd83dbSDimitry Andric /// ::= string 3331fe6060f1SDimitry Andric bool MasmParser::parseIdentifier(StringRef &Res, 3332fe6060f1SDimitry Andric IdentifierPositionKind Position) { 33335ffd83dbSDimitry Andric // The assembler has relaxed rules for accepting identifiers, in particular we 33345ffd83dbSDimitry Andric // allow things like '.globl $foo' and '.def @feat.00', which would normally 33355ffd83dbSDimitry Andric // be separate tokens. At this level, we have already lexed so we cannot 33365ffd83dbSDimitry Andric // (currently) handle this as a context dependent token, instead we detect 33375ffd83dbSDimitry Andric // adjacent tokens and return the combined identifier. 33385ffd83dbSDimitry Andric if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) { 33395ffd83dbSDimitry Andric SMLoc PrefixLoc = getLexer().getLoc(); 33405ffd83dbSDimitry Andric 33415ffd83dbSDimitry Andric // Consume the prefix character, and check for a following identifier. 33425ffd83dbSDimitry Andric 3343fe6060f1SDimitry Andric AsmToken nextTok = peekTok(false); 33445ffd83dbSDimitry Andric 3345fe6060f1SDimitry Andric if (nextTok.isNot(AsmToken::Identifier)) 33465ffd83dbSDimitry Andric return true; 33475ffd83dbSDimitry Andric 33485ffd83dbSDimitry Andric // We have a '$' or '@' followed by an identifier, make sure they are adjacent. 3349fe6060f1SDimitry Andric if (PrefixLoc.getPointer() + 1 != nextTok.getLoc().getPointer()) 33505ffd83dbSDimitry Andric return true; 33515ffd83dbSDimitry Andric 33525ffd83dbSDimitry Andric // eat $ or @ 33535ffd83dbSDimitry Andric Lexer.Lex(); // Lexer's Lex guarantees consecutive token. 33545ffd83dbSDimitry Andric // Construct the joined identifier and consume the token. 33555ffd83dbSDimitry Andric Res = 33565ffd83dbSDimitry Andric StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1); 33575ffd83dbSDimitry Andric Lex(); // Parser Lex to maintain invariants. 33585ffd83dbSDimitry Andric return false; 33595ffd83dbSDimitry Andric } 33605ffd83dbSDimitry Andric 33615ffd83dbSDimitry Andric if (Lexer.isNot(AsmToken::Identifier) && Lexer.isNot(AsmToken::String)) 33625ffd83dbSDimitry Andric return true; 33635ffd83dbSDimitry Andric 33645ffd83dbSDimitry Andric Res = getTok().getIdentifier(); 33655ffd83dbSDimitry Andric 3366fe6060f1SDimitry Andric // Consume the identifier token - but if parsing certain directives, avoid 3367fe6060f1SDimitry Andric // lexical expansion of the next token. 3368fe6060f1SDimitry Andric ExpandKind ExpandNextToken = ExpandMacros; 3369fe6060f1SDimitry Andric if (Position == StartOfStatement && 3370fe6060f1SDimitry Andric StringSwitch<bool>(Res) 3371fe6060f1SDimitry Andric .CaseLower("echo", true) 3372fe6060f1SDimitry Andric .CasesLower("ifdef", "ifndef", "elseifdef", "elseifndef", true) 3373fe6060f1SDimitry Andric .Default(false)) { 3374fe6060f1SDimitry Andric ExpandNextToken = DoNotExpandMacros; 3375fe6060f1SDimitry Andric } 3376fe6060f1SDimitry Andric Lex(ExpandNextToken); 33775ffd83dbSDimitry Andric 33785ffd83dbSDimitry Andric return false; 33795ffd83dbSDimitry Andric } 33805ffd83dbSDimitry Andric 33815ffd83dbSDimitry Andric /// parseDirectiveEquate: 33825ffd83dbSDimitry Andric /// ::= name "=" expression 33835ffd83dbSDimitry Andric /// | name "equ" expression (not redefinable) 33845ffd83dbSDimitry Andric /// | name "equ" text-list 3385fe6060f1SDimitry Andric /// | name "textequ" text-list (redefinability unspecified) 33865ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name, 3387fe6060f1SDimitry Andric DirectiveKind DirKind, SMLoc NameLoc) { 3388fe6060f1SDimitry Andric auto BuiltinIt = BuiltinSymbolMap.find(Name.lower()); 3389fe6060f1SDimitry Andric if (BuiltinIt != BuiltinSymbolMap.end()) 3390fe6060f1SDimitry Andric return Error(NameLoc, "cannot redefine a built-in symbol"); 3391fe6060f1SDimitry Andric 3392fe6060f1SDimitry Andric Variable &Var = Variables[Name.lower()]; 33935ffd83dbSDimitry Andric if (Var.Name.empty()) { 33945ffd83dbSDimitry Andric Var.Name = Name; 33955ffd83dbSDimitry Andric } 33965ffd83dbSDimitry Andric 3397fe6060f1SDimitry Andric SMLoc StartLoc = Lexer.getLoc(); 33985ffd83dbSDimitry Andric if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) { 33995ffd83dbSDimitry Andric // "equ" and "textequ" both allow text expressions. 34005ffd83dbSDimitry Andric std::string Value; 3401fe6060f1SDimitry Andric std::string TextItem; 3402fe6060f1SDimitry Andric if (!parseTextItem(TextItem)) { 3403fe6060f1SDimitry Andric Value += TextItem; 34045ffd83dbSDimitry Andric 34055ffd83dbSDimitry Andric // Accept a text-list, not just one text-item. 34065ffd83dbSDimitry Andric auto parseItem = [&]() -> bool { 3407fe6060f1SDimitry Andric if (parseTextItem(TextItem)) 3408e8d8bef9SDimitry Andric return TokError("expected text item"); 3409fe6060f1SDimitry Andric Value += TextItem; 34105ffd83dbSDimitry Andric return false; 34115ffd83dbSDimitry Andric }; 34125ffd83dbSDimitry Andric if (parseOptionalToken(AsmToken::Comma) && parseMany(parseItem)) 34135ffd83dbSDimitry Andric return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); 34145ffd83dbSDimitry Andric 3415fe6060f1SDimitry Andric if (!Var.IsText || Var.TextValue != Value) { 3416fe6060f1SDimitry Andric switch (Var.Redefinable) { 3417fe6060f1SDimitry Andric case Variable::NOT_REDEFINABLE: 3418fe6060f1SDimitry Andric return Error(getTok().getLoc(), "invalid variable redefinition"); 3419fe6060f1SDimitry Andric case Variable::WARN_ON_REDEFINITION: 3420fe6060f1SDimitry Andric if (Warning(NameLoc, "redefining '" + Name + 3421fe6060f1SDimitry Andric "', already defined on the command line")) { 3422fe6060f1SDimitry Andric return true; 3423fe6060f1SDimitry Andric } 3424fe6060f1SDimitry Andric break; 3425fe6060f1SDimitry Andric default: 3426fe6060f1SDimitry Andric break; 3427fe6060f1SDimitry Andric } 3428fe6060f1SDimitry Andric } 3429fe6060f1SDimitry Andric Var.IsText = true; 3430fe6060f1SDimitry Andric Var.TextValue = Value; 3431fe6060f1SDimitry Andric Var.Redefinable = Variable::REDEFINABLE; 3432fe6060f1SDimitry Andric 34335ffd83dbSDimitry Andric return false; 34345ffd83dbSDimitry Andric } 34355ffd83dbSDimitry Andric } 34365ffd83dbSDimitry Andric if (DirKind == DK_TEXTEQU) 34375ffd83dbSDimitry Andric return TokError("expected <text> in '" + Twine(IDVal) + "' directive"); 34385ffd83dbSDimitry Andric 34395ffd83dbSDimitry Andric // Parse as expression assignment. 34405ffd83dbSDimitry Andric const MCExpr *Expr; 3441fe6060f1SDimitry Andric SMLoc EndLoc; 34425ffd83dbSDimitry Andric if (parseExpression(Expr, EndLoc)) 34435ffd83dbSDimitry Andric return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); 3444fe6060f1SDimitry Andric StringRef ExprAsString = StringRef( 3445fe6060f1SDimitry Andric StartLoc.getPointer(), EndLoc.getPointer() - StartLoc.getPointer()); 3446fe6060f1SDimitry Andric 3447fe6060f1SDimitry Andric int64_t Value; 3448fe6060f1SDimitry Andric if (!Expr->evaluateAsAbsolute(Value, getStreamer().getAssemblerPtr())) { 3449fe6060f1SDimitry Andric if (DirKind == DK_ASSIGN) 3450fe6060f1SDimitry Andric return Error( 3451fe6060f1SDimitry Andric StartLoc, 3452fe6060f1SDimitry Andric "expected absolute expression; not all symbols have known values", 3453fe6060f1SDimitry Andric {StartLoc, EndLoc}); 3454fe6060f1SDimitry Andric 3455fe6060f1SDimitry Andric // Not an absolute expression; define as a text replacement. 3456fe6060f1SDimitry Andric if (!Var.IsText || Var.TextValue != ExprAsString) { 3457fe6060f1SDimitry Andric switch (Var.Redefinable) { 3458fe6060f1SDimitry Andric case Variable::NOT_REDEFINABLE: 3459fe6060f1SDimitry Andric return Error(getTok().getLoc(), "invalid variable redefinition"); 3460fe6060f1SDimitry Andric case Variable::WARN_ON_REDEFINITION: 3461fe6060f1SDimitry Andric if (Warning(NameLoc, "redefining '" + Name + 3462fe6060f1SDimitry Andric "', already defined on the command line")) { 3463fe6060f1SDimitry Andric return true; 3464fe6060f1SDimitry Andric } 3465fe6060f1SDimitry Andric break; 3466fe6060f1SDimitry Andric default: 3467fe6060f1SDimitry Andric break; 3468fe6060f1SDimitry Andric } 3469fe6060f1SDimitry Andric } 3470fe6060f1SDimitry Andric 3471fe6060f1SDimitry Andric Var.IsText = true; 3472fe6060f1SDimitry Andric Var.TextValue = ExprAsString.str(); 3473fe6060f1SDimitry Andric Var.Redefinable = Variable::REDEFINABLE; 3474fe6060f1SDimitry Andric 3475fe6060f1SDimitry Andric return false; 3476fe6060f1SDimitry Andric } 3477fe6060f1SDimitry Andric 3478e8d8bef9SDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Var.Name); 3479fe6060f1SDimitry Andric 3480fe6060f1SDimitry Andric const MCConstantExpr *PrevValue = 3481fe6060f1SDimitry Andric Sym->isVariable() ? dyn_cast_or_null<MCConstantExpr>( 3482fe6060f1SDimitry Andric Sym->getVariableValue(/*SetUsed=*/false)) 3483fe6060f1SDimitry Andric : nullptr; 3484fe6060f1SDimitry Andric if (Var.IsText || !PrevValue || PrevValue->getValue() != Value) { 3485fe6060f1SDimitry Andric switch (Var.Redefinable) { 3486fe6060f1SDimitry Andric case Variable::NOT_REDEFINABLE: 3487fe6060f1SDimitry Andric return Error(getTok().getLoc(), "invalid variable redefinition"); 3488fe6060f1SDimitry Andric case Variable::WARN_ON_REDEFINITION: 3489fe6060f1SDimitry Andric if (Warning(NameLoc, "redefining '" + Name + 3490fe6060f1SDimitry Andric "', already defined on the command line")) { 3491fe6060f1SDimitry Andric return true; 3492fe6060f1SDimitry Andric } 3493fe6060f1SDimitry Andric break; 3494fe6060f1SDimitry Andric default: 3495fe6060f1SDimitry Andric break; 3496fe6060f1SDimitry Andric } 3497fe6060f1SDimitry Andric } 3498fe6060f1SDimitry Andric 3499fe6060f1SDimitry Andric Var.IsText = false; 3500fe6060f1SDimitry Andric Var.TextValue.clear(); 3501fe6060f1SDimitry Andric Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE 3502fe6060f1SDimitry Andric : Variable::NOT_REDEFINABLE; 3503fe6060f1SDimitry Andric 3504fe6060f1SDimitry Andric Sym->setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE); 3505e8d8bef9SDimitry Andric Sym->setVariableValue(Expr); 3506e8d8bef9SDimitry Andric Sym->setExternal(false); 3507e8d8bef9SDimitry Andric 35085ffd83dbSDimitry Andric return false; 35095ffd83dbSDimitry Andric } 35105ffd83dbSDimitry Andric 35115ffd83dbSDimitry Andric bool MasmParser::parseEscapedString(std::string &Data) { 35125ffd83dbSDimitry Andric if (check(getTok().isNot(AsmToken::String), "expected string")) 35135ffd83dbSDimitry Andric return true; 35145ffd83dbSDimitry Andric 35155ffd83dbSDimitry Andric Data = ""; 3516e8d8bef9SDimitry Andric char Quote = getTok().getString().front(); 35175ffd83dbSDimitry Andric StringRef Str = getTok().getStringContents(); 3518e8d8bef9SDimitry Andric Data.reserve(Str.size()); 3519e8d8bef9SDimitry Andric for (size_t i = 0, e = Str.size(); i != e; ++i) { 3520e8d8bef9SDimitry Andric Data.push_back(Str[i]); 3521e8d8bef9SDimitry Andric if (Str[i] == Quote) { 3522e8d8bef9SDimitry Andric // MASM treats doubled delimiting quotes as an escaped delimiting quote. 3523e8d8bef9SDimitry Andric // If we're escaping the string's trailing delimiter, we're definitely 3524e8d8bef9SDimitry Andric // missing a quotation mark. 3525e8d8bef9SDimitry Andric if (i + 1 == Str.size()) 3526e8d8bef9SDimitry Andric return Error(getTok().getLoc(), "missing quotation mark in string"); 3527e8d8bef9SDimitry Andric if (Str[i + 1] == Quote) 35285ffd83dbSDimitry Andric ++i; 35295ffd83dbSDimitry Andric } 35305ffd83dbSDimitry Andric } 35315ffd83dbSDimitry Andric 35325ffd83dbSDimitry Andric Lex(); 35335ffd83dbSDimitry Andric return false; 35345ffd83dbSDimitry Andric } 35355ffd83dbSDimitry Andric 35365ffd83dbSDimitry Andric bool MasmParser::parseAngleBracketString(std::string &Data) { 35375ffd83dbSDimitry Andric SMLoc EndLoc, StartLoc = getTok().getLoc(); 35385ffd83dbSDimitry Andric if (isAngleBracketString(StartLoc, EndLoc)) { 35395ffd83dbSDimitry Andric const char *StartChar = StartLoc.getPointer() + 1; 35405ffd83dbSDimitry Andric const char *EndChar = EndLoc.getPointer() - 1; 3541e8d8bef9SDimitry Andric jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back()); 35425ffd83dbSDimitry Andric // Eat from '<' to '>'. 35435ffd83dbSDimitry Andric Lex(); 35445ffd83dbSDimitry Andric 35455ffd83dbSDimitry Andric Data = angleBracketString(StringRef(StartChar, EndChar - StartChar)); 35465ffd83dbSDimitry Andric return false; 35475ffd83dbSDimitry Andric } 35485ffd83dbSDimitry Andric return true; 35495ffd83dbSDimitry Andric } 35505ffd83dbSDimitry Andric 35515ffd83dbSDimitry Andric /// textItem ::= textLiteral | textMacroID | % constExpr 35525ffd83dbSDimitry Andric bool MasmParser::parseTextItem(std::string &Data) { 3553e8d8bef9SDimitry Andric switch (getTok().getKind()) { 3554e8d8bef9SDimitry Andric default: 3555e8d8bef9SDimitry Andric return true; 3556e8d8bef9SDimitry Andric case AsmToken::Percent: { 3557e8d8bef9SDimitry Andric int64_t Res; 3558e8d8bef9SDimitry Andric if (parseToken(AsmToken::Percent) || parseAbsoluteExpression(Res)) 3559e8d8bef9SDimitry Andric return true; 3560e8d8bef9SDimitry Andric Data = std::to_string(Res); 3561e8d8bef9SDimitry Andric return false; 3562e8d8bef9SDimitry Andric } 3563e8d8bef9SDimitry Andric case AsmToken::Less: 3564e8d8bef9SDimitry Andric case AsmToken::LessEqual: 3565e8d8bef9SDimitry Andric case AsmToken::LessLess: 3566e8d8bef9SDimitry Andric case AsmToken::LessGreater: 35675ffd83dbSDimitry Andric return parseAngleBracketString(Data); 3568e8d8bef9SDimitry Andric case AsmToken::Identifier: { 3569fe6060f1SDimitry Andric // This must be a text macro; we need to expand it accordingly. 3570e8d8bef9SDimitry Andric StringRef ID; 3571fe6060f1SDimitry Andric SMLoc StartLoc = getTok().getLoc(); 3572e8d8bef9SDimitry Andric if (parseIdentifier(ID)) 3573e8d8bef9SDimitry Andric return true; 3574e8d8bef9SDimitry Andric Data = ID.str(); 3575e8d8bef9SDimitry Andric 3576fe6060f1SDimitry Andric bool Expanded = false; 3577fe6060f1SDimitry Andric while (true) { 3578fe6060f1SDimitry Andric // Try to resolve as a built-in text macro 3579fe6060f1SDimitry Andric auto BuiltinIt = BuiltinSymbolMap.find(ID.lower()); 3580fe6060f1SDimitry Andric if (BuiltinIt != BuiltinSymbolMap.end()) { 3581bdd1243dSDimitry Andric std::optional<std::string> BuiltinText = 3582fe6060f1SDimitry Andric evaluateBuiltinTextMacro(BuiltinIt->getValue(), StartLoc); 358381ad6265SDimitry Andric if (!BuiltinText) { 3584fe6060f1SDimitry Andric // Not a text macro; break without substituting 3585fe6060f1SDimitry Andric break; 3586fe6060f1SDimitry Andric } 3587fe6060f1SDimitry Andric Data = std::move(*BuiltinText); 3588fe6060f1SDimitry Andric ID = StringRef(Data); 3589fe6060f1SDimitry Andric Expanded = true; 3590fe6060f1SDimitry Andric continue; 3591fe6060f1SDimitry Andric } 3592e8d8bef9SDimitry Andric 3593fe6060f1SDimitry Andric // Try to resolve as a variable text macro 3594fe6060f1SDimitry Andric auto VarIt = Variables.find(ID.lower()); 3595fe6060f1SDimitry Andric if (VarIt != Variables.end()) { 3596fe6060f1SDimitry Andric const Variable &Var = VarIt->getValue(); 3597fe6060f1SDimitry Andric if (!Var.IsText) { 3598fe6060f1SDimitry Andric // Not a text macro; break without substituting 3599fe6060f1SDimitry Andric break; 3600fe6060f1SDimitry Andric } 3601e8d8bef9SDimitry Andric Data = Var.TextValue; 3602fe6060f1SDimitry Andric ID = StringRef(Data); 3603fe6060f1SDimitry Andric Expanded = true; 3604fe6060f1SDimitry Andric continue; 3605fe6060f1SDimitry Andric } 3606fe6060f1SDimitry Andric 3607fe6060f1SDimitry Andric break; 3608fe6060f1SDimitry Andric } 3609fe6060f1SDimitry Andric 3610fe6060f1SDimitry Andric if (!Expanded) { 3611fe6060f1SDimitry Andric // Not a text macro; not usable in TextItem context. Since we haven't used 3612fe6060f1SDimitry Andric // the token, put it back for better error recovery. 3613fe6060f1SDimitry Andric getLexer().UnLex(AsmToken(AsmToken::Identifier, ID)); 3614fe6060f1SDimitry Andric return true; 3615e8d8bef9SDimitry Andric } 3616e8d8bef9SDimitry Andric return false; 3617e8d8bef9SDimitry Andric } 3618e8d8bef9SDimitry Andric } 3619e8d8bef9SDimitry Andric llvm_unreachable("unhandled token kind"); 36205ffd83dbSDimitry Andric } 36215ffd83dbSDimitry Andric 36225ffd83dbSDimitry Andric /// parseDirectiveAscii: 36235ffd83dbSDimitry Andric /// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ] 36245ffd83dbSDimitry Andric bool MasmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) { 36255ffd83dbSDimitry Andric auto parseOp = [&]() -> bool { 36265ffd83dbSDimitry Andric std::string Data; 36275ffd83dbSDimitry Andric if (checkForValidSection() || parseEscapedString(Data)) 36285ffd83dbSDimitry Andric return true; 36295ffd83dbSDimitry Andric getStreamer().emitBytes(Data); 36305ffd83dbSDimitry Andric if (ZeroTerminated) 36315ffd83dbSDimitry Andric getStreamer().emitBytes(StringRef("\0", 1)); 36325ffd83dbSDimitry Andric return false; 36335ffd83dbSDimitry Andric }; 36345ffd83dbSDimitry Andric 36355ffd83dbSDimitry Andric if (parseMany(parseOp)) 36365ffd83dbSDimitry Andric return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); 36375ffd83dbSDimitry Andric return false; 36385ffd83dbSDimitry Andric } 36395ffd83dbSDimitry Andric 36405ffd83dbSDimitry Andric bool MasmParser::emitIntValue(const MCExpr *Value, unsigned Size) { 36415ffd83dbSDimitry Andric // Special case constant expressions to match code generator. 36425ffd83dbSDimitry Andric if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { 36435ffd83dbSDimitry Andric assert(Size <= 8 && "Invalid size"); 36445ffd83dbSDimitry Andric int64_t IntValue = MCE->getValue(); 36455ffd83dbSDimitry Andric if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue)) 36465ffd83dbSDimitry Andric return Error(MCE->getLoc(), "out of range literal value"); 36475ffd83dbSDimitry Andric getStreamer().emitIntValue(IntValue, Size); 36485ffd83dbSDimitry Andric } else { 36495ffd83dbSDimitry Andric const MCSymbolRefExpr *MSE = dyn_cast<MCSymbolRefExpr>(Value); 36505ffd83dbSDimitry Andric if (MSE && MSE->getSymbol().getName() == "?") { 36515ffd83dbSDimitry Andric // ? initializer; treat as 0. 36525ffd83dbSDimitry Andric getStreamer().emitIntValue(0, Size); 36535ffd83dbSDimitry Andric } else { 36545ffd83dbSDimitry Andric getStreamer().emitValue(Value, Size, Value->getLoc()); 36555ffd83dbSDimitry Andric } 36565ffd83dbSDimitry Andric } 36575ffd83dbSDimitry Andric return false; 36585ffd83dbSDimitry Andric } 36595ffd83dbSDimitry Andric 36605ffd83dbSDimitry Andric bool MasmParser::parseScalarInitializer(unsigned Size, 36615ffd83dbSDimitry Andric SmallVectorImpl<const MCExpr *> &Values, 36625ffd83dbSDimitry Andric unsigned StringPadLength) { 3663e8d8bef9SDimitry Andric if (Size == 1 && getTok().is(AsmToken::String)) { 3664e8d8bef9SDimitry Andric std::string Value; 3665e8d8bef9SDimitry Andric if (parseEscapedString(Value)) 3666e8d8bef9SDimitry Andric return true; 36675ffd83dbSDimitry Andric // Treat each character as an initializer. 3668e8d8bef9SDimitry Andric for (const unsigned char CharVal : Value) 36695ffd83dbSDimitry Andric Values.push_back(MCConstantExpr::create(CharVal, getContext())); 36705ffd83dbSDimitry Andric 36715ffd83dbSDimitry Andric // Pad the string with spaces to the specified length. 36725ffd83dbSDimitry Andric for (size_t i = Value.size(); i < StringPadLength; ++i) 36735ffd83dbSDimitry Andric Values.push_back(MCConstantExpr::create(' ', getContext())); 36745ffd83dbSDimitry Andric } else { 36755ffd83dbSDimitry Andric const MCExpr *Value; 3676e8d8bef9SDimitry Andric if (parseExpression(Value)) 36775ffd83dbSDimitry Andric return true; 36785ffd83dbSDimitry Andric if (getTok().is(AsmToken::Identifier) && 3679fe6060f1SDimitry Andric getTok().getString().equals_insensitive("dup")) { 36805ffd83dbSDimitry Andric Lex(); // Eat 'dup'. 36815ffd83dbSDimitry Andric const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); 36825ffd83dbSDimitry Andric if (!MCE) 36835ffd83dbSDimitry Andric return Error(Value->getLoc(), 36845ffd83dbSDimitry Andric "cannot repeat value a non-constant number of times"); 36855ffd83dbSDimitry Andric const int64_t Repetitions = MCE->getValue(); 36865ffd83dbSDimitry Andric if (Repetitions < 0) 36875ffd83dbSDimitry Andric return Error(Value->getLoc(), 36885ffd83dbSDimitry Andric "cannot repeat value a negative number of times"); 36895ffd83dbSDimitry Andric 36905ffd83dbSDimitry Andric SmallVector<const MCExpr *, 1> DuplicatedValues; 36915ffd83dbSDimitry Andric if (parseToken(AsmToken::LParen, 36925ffd83dbSDimitry Andric "parentheses required for 'dup' contents") || 369304eeddc0SDimitry Andric parseScalarInstList(Size, DuplicatedValues) || parseRParen()) 36945ffd83dbSDimitry Andric return true; 36955ffd83dbSDimitry Andric 36965ffd83dbSDimitry Andric for (int i = 0; i < Repetitions; ++i) 36975ffd83dbSDimitry Andric Values.append(DuplicatedValues.begin(), DuplicatedValues.end()); 36985ffd83dbSDimitry Andric } else { 36995ffd83dbSDimitry Andric Values.push_back(Value); 37005ffd83dbSDimitry Andric } 37015ffd83dbSDimitry Andric } 37025ffd83dbSDimitry Andric return false; 37035ffd83dbSDimitry Andric } 37045ffd83dbSDimitry Andric 37055ffd83dbSDimitry Andric bool MasmParser::parseScalarInstList(unsigned Size, 37065ffd83dbSDimitry Andric SmallVectorImpl<const MCExpr *> &Values, 37075ffd83dbSDimitry Andric const AsmToken::TokenKind EndToken) { 37085ffd83dbSDimitry Andric while (getTok().isNot(EndToken) && 37095ffd83dbSDimitry Andric (EndToken != AsmToken::Greater || 37105ffd83dbSDimitry Andric getTok().isNot(AsmToken::GreaterGreater))) { 37115ffd83dbSDimitry Andric parseScalarInitializer(Size, Values); 37125ffd83dbSDimitry Andric 37135ffd83dbSDimitry Andric // If we see a comma, continue, and allow line continuation. 37145ffd83dbSDimitry Andric if (!parseOptionalToken(AsmToken::Comma)) 37155ffd83dbSDimitry Andric break; 37165ffd83dbSDimitry Andric parseOptionalToken(AsmToken::EndOfStatement); 37175ffd83dbSDimitry Andric } 37185ffd83dbSDimitry Andric return false; 37195ffd83dbSDimitry Andric } 37205ffd83dbSDimitry Andric 3721e8d8bef9SDimitry Andric bool MasmParser::emitIntegralValues(unsigned Size, unsigned *Count) { 37225ffd83dbSDimitry Andric SmallVector<const MCExpr *, 1> Values; 37235ffd83dbSDimitry Andric if (checkForValidSection() || parseScalarInstList(Size, Values)) 37245ffd83dbSDimitry Andric return true; 37255ffd83dbSDimitry Andric 3726bdd1243dSDimitry Andric for (const auto *Value : Values) { 37275ffd83dbSDimitry Andric emitIntValue(Value, Size); 37285ffd83dbSDimitry Andric } 3729e8d8bef9SDimitry Andric if (Count) 3730e8d8bef9SDimitry Andric *Count = Values.size(); 37315ffd83dbSDimitry Andric return false; 37325ffd83dbSDimitry Andric } 37335ffd83dbSDimitry Andric 37345ffd83dbSDimitry Andric // Add a field to the current structure. 37355ffd83dbSDimitry Andric bool MasmParser::addIntegralField(StringRef Name, unsigned Size) { 37365ffd83dbSDimitry Andric StructInfo &Struct = StructInProgress.back(); 3737e8d8bef9SDimitry Andric FieldInfo &Field = Struct.addField(Name, FT_INTEGRAL, Size); 37385ffd83dbSDimitry Andric IntFieldInfo &IntInfo = Field.Contents.IntInfo; 37395ffd83dbSDimitry Andric 37405ffd83dbSDimitry Andric Field.Type = Size; 37415ffd83dbSDimitry Andric 37425ffd83dbSDimitry Andric if (parseScalarInstList(Size, IntInfo.Values)) 37435ffd83dbSDimitry Andric return true; 37445ffd83dbSDimitry Andric 37455ffd83dbSDimitry Andric Field.SizeOf = Field.Type * IntInfo.Values.size(); 37465ffd83dbSDimitry Andric Field.LengthOf = IntInfo.Values.size(); 3747fe6060f1SDimitry Andric const unsigned FieldEnd = Field.Offset + Field.SizeOf; 3748fe6060f1SDimitry Andric if (!Struct.IsUnion) { 3749fe6060f1SDimitry Andric Struct.NextOffset = FieldEnd; 3750fe6060f1SDimitry Andric } 3751fe6060f1SDimitry Andric Struct.Size = std::max(Struct.Size, FieldEnd); 37525ffd83dbSDimitry Andric return false; 37535ffd83dbSDimitry Andric } 37545ffd83dbSDimitry Andric 37555ffd83dbSDimitry Andric /// parseDirectiveValue 37565ffd83dbSDimitry Andric /// ::= (byte | word | ... ) [ expression (, expression)* ] 37575ffd83dbSDimitry Andric bool MasmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) { 37585ffd83dbSDimitry Andric if (StructInProgress.empty()) { 37595ffd83dbSDimitry Andric // Initialize data value. 37605ffd83dbSDimitry Andric if (emitIntegralValues(Size)) 37615ffd83dbSDimitry Andric return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); 37625ffd83dbSDimitry Andric } else if (addIntegralField("", Size)) { 37635ffd83dbSDimitry Andric return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); 37645ffd83dbSDimitry Andric } 37655ffd83dbSDimitry Andric 37665ffd83dbSDimitry Andric return false; 37675ffd83dbSDimitry Andric } 37685ffd83dbSDimitry Andric 37695ffd83dbSDimitry Andric /// parseDirectiveNamedValue 37705ffd83dbSDimitry Andric /// ::= name (byte | word | ... ) [ expression (, expression)* ] 3771e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveNamedValue(StringRef TypeName, unsigned Size, 37725ffd83dbSDimitry Andric StringRef Name, SMLoc NameLoc) { 37735ffd83dbSDimitry Andric if (StructInProgress.empty()) { 37745ffd83dbSDimitry Andric // Initialize named data value. 37755ffd83dbSDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 37765ffd83dbSDimitry Andric getStreamer().emitLabel(Sym); 3777e8d8bef9SDimitry Andric unsigned Count; 3778e8d8bef9SDimitry Andric if (emitIntegralValues(Size, &Count)) 3779e8d8bef9SDimitry Andric return addErrorSuffix(" in '" + Twine(TypeName) + "' directive"); 3780e8d8bef9SDimitry Andric 3781e8d8bef9SDimitry Andric AsmTypeInfo Type; 3782e8d8bef9SDimitry Andric Type.Name = TypeName; 3783e8d8bef9SDimitry Andric Type.Size = Size * Count; 3784e8d8bef9SDimitry Andric Type.ElementSize = Size; 3785e8d8bef9SDimitry Andric Type.Length = Count; 3786e8d8bef9SDimitry Andric KnownType[Name.lower()] = Type; 37875ffd83dbSDimitry Andric } else if (addIntegralField(Name, Size)) { 3788e8d8bef9SDimitry Andric return addErrorSuffix(" in '" + Twine(TypeName) + "' directive"); 37895ffd83dbSDimitry Andric } 37905ffd83dbSDimitry Andric 37915ffd83dbSDimitry Andric return false; 37925ffd83dbSDimitry Andric } 37935ffd83dbSDimitry Andric 37945ffd83dbSDimitry Andric static bool parseHexOcta(MasmParser &Asm, uint64_t &hi, uint64_t &lo) { 37955ffd83dbSDimitry Andric if (Asm.getTok().isNot(AsmToken::Integer) && 37965ffd83dbSDimitry Andric Asm.getTok().isNot(AsmToken::BigNum)) 37975ffd83dbSDimitry Andric return Asm.TokError("unknown token in expression"); 37985ffd83dbSDimitry Andric SMLoc ExprLoc = Asm.getTok().getLoc(); 37995ffd83dbSDimitry Andric APInt IntValue = Asm.getTok().getAPIntVal(); 38005ffd83dbSDimitry Andric Asm.Lex(); 38015ffd83dbSDimitry Andric if (!IntValue.isIntN(128)) 38025ffd83dbSDimitry Andric return Asm.Error(ExprLoc, "out of range literal value"); 38035ffd83dbSDimitry Andric if (!IntValue.isIntN(64)) { 38045ffd83dbSDimitry Andric hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue(); 38055ffd83dbSDimitry Andric lo = IntValue.getLoBits(64).getZExtValue(); 38065ffd83dbSDimitry Andric } else { 38075ffd83dbSDimitry Andric hi = 0; 38085ffd83dbSDimitry Andric lo = IntValue.getZExtValue(); 38095ffd83dbSDimitry Andric } 38105ffd83dbSDimitry Andric return false; 38115ffd83dbSDimitry Andric } 38125ffd83dbSDimitry Andric 38135ffd83dbSDimitry Andric bool MasmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) { 38145ffd83dbSDimitry Andric // We don't truly support arithmetic on floating point expressions, so we 38155ffd83dbSDimitry Andric // have to manually parse unary prefixes. 38165ffd83dbSDimitry Andric bool IsNeg = false; 3817e8d8bef9SDimitry Andric SMLoc SignLoc; 38185ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Minus)) { 3819e8d8bef9SDimitry Andric SignLoc = getLexer().getLoc(); 38205ffd83dbSDimitry Andric Lexer.Lex(); 38215ffd83dbSDimitry Andric IsNeg = true; 38225ffd83dbSDimitry Andric } else if (getLexer().is(AsmToken::Plus)) { 3823e8d8bef9SDimitry Andric SignLoc = getLexer().getLoc(); 38245ffd83dbSDimitry Andric Lexer.Lex(); 38255ffd83dbSDimitry Andric } 38265ffd83dbSDimitry Andric 38275ffd83dbSDimitry Andric if (Lexer.is(AsmToken::Error)) 38285ffd83dbSDimitry Andric return TokError(Lexer.getErr()); 38295ffd83dbSDimitry Andric if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) && 38305ffd83dbSDimitry Andric Lexer.isNot(AsmToken::Identifier)) 38315ffd83dbSDimitry Andric return TokError("unexpected token in directive"); 38325ffd83dbSDimitry Andric 38335ffd83dbSDimitry Andric // Convert to an APFloat. 38345ffd83dbSDimitry Andric APFloat Value(Semantics); 38355ffd83dbSDimitry Andric StringRef IDVal = getTok().getString(); 38365ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Identifier)) { 3837fe6060f1SDimitry Andric if (IDVal.equals_insensitive("infinity") || IDVal.equals_insensitive("inf")) 38385ffd83dbSDimitry Andric Value = APFloat::getInf(Semantics); 3839fe6060f1SDimitry Andric else if (IDVal.equals_insensitive("nan")) 38405ffd83dbSDimitry Andric Value = APFloat::getNaN(Semantics, false, ~0); 3841fe6060f1SDimitry Andric else if (IDVal.equals_insensitive("?")) 38425ffd83dbSDimitry Andric Value = APFloat::getZero(Semantics); 38435ffd83dbSDimitry Andric else 38445ffd83dbSDimitry Andric return TokError("invalid floating point literal"); 3845e8d8bef9SDimitry Andric } else if (IDVal.consume_back("r") || IDVal.consume_back("R")) { 3846e8d8bef9SDimitry Andric // MASM hexadecimal floating-point literal; no APFloat conversion needed. 3847e8d8bef9SDimitry Andric // To match ML64.exe, ignore the initial sign. 3848e8d8bef9SDimitry Andric unsigned SizeInBits = Value.getSizeInBits(Semantics); 3849e8d8bef9SDimitry Andric if (SizeInBits != (IDVal.size() << 2)) 3850e8d8bef9SDimitry Andric return TokError("invalid floating point literal"); 3851e8d8bef9SDimitry Andric 3852e8d8bef9SDimitry Andric // Consume the numeric token. 3853e8d8bef9SDimitry Andric Lex(); 3854e8d8bef9SDimitry Andric 3855e8d8bef9SDimitry Andric Res = APInt(SizeInBits, IDVal, 16); 3856e8d8bef9SDimitry Andric if (SignLoc.isValid()) 3857e8d8bef9SDimitry Andric return Warning(SignLoc, "MASM-style hex floats ignore explicit sign"); 3858e8d8bef9SDimitry Andric return false; 38595ffd83dbSDimitry Andric } else if (errorToBool( 38605ffd83dbSDimitry Andric Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) 38615ffd83dbSDimitry Andric .takeError())) { 38625ffd83dbSDimitry Andric return TokError("invalid floating point literal"); 38635ffd83dbSDimitry Andric } 38645ffd83dbSDimitry Andric if (IsNeg) 38655ffd83dbSDimitry Andric Value.changeSign(); 38665ffd83dbSDimitry Andric 38675ffd83dbSDimitry Andric // Consume the numeric token. 38685ffd83dbSDimitry Andric Lex(); 38695ffd83dbSDimitry Andric 38705ffd83dbSDimitry Andric Res = Value.bitcastToAPInt(); 38715ffd83dbSDimitry Andric 38725ffd83dbSDimitry Andric return false; 38735ffd83dbSDimitry Andric } 38745ffd83dbSDimitry Andric 38755ffd83dbSDimitry Andric bool MasmParser::parseRealInstList(const fltSemantics &Semantics, 38765ffd83dbSDimitry Andric SmallVectorImpl<APInt> &ValuesAsInt, 38775ffd83dbSDimitry Andric const AsmToken::TokenKind EndToken) { 38785ffd83dbSDimitry Andric while (getTok().isNot(EndToken) || 38795ffd83dbSDimitry Andric (EndToken == AsmToken::Greater && 38805ffd83dbSDimitry Andric getTok().isNot(AsmToken::GreaterGreater))) { 3881fe6060f1SDimitry Andric const AsmToken NextTok = peekTok(); 38825ffd83dbSDimitry Andric if (NextTok.is(AsmToken::Identifier) && 3883fe6060f1SDimitry Andric NextTok.getString().equals_insensitive("dup")) { 38845ffd83dbSDimitry Andric const MCExpr *Value; 38855ffd83dbSDimitry Andric if (parseExpression(Value) || parseToken(AsmToken::Identifier)) 38865ffd83dbSDimitry Andric return true; 38875ffd83dbSDimitry Andric const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); 38885ffd83dbSDimitry Andric if (!MCE) 38895ffd83dbSDimitry Andric return Error(Value->getLoc(), 38905ffd83dbSDimitry Andric "cannot repeat value a non-constant number of times"); 38915ffd83dbSDimitry Andric const int64_t Repetitions = MCE->getValue(); 38925ffd83dbSDimitry Andric if (Repetitions < 0) 38935ffd83dbSDimitry Andric return Error(Value->getLoc(), 38945ffd83dbSDimitry Andric "cannot repeat value a negative number of times"); 38955ffd83dbSDimitry Andric 38965ffd83dbSDimitry Andric SmallVector<APInt, 1> DuplicatedValues; 38975ffd83dbSDimitry Andric if (parseToken(AsmToken::LParen, 38985ffd83dbSDimitry Andric "parentheses required for 'dup' contents") || 389904eeddc0SDimitry Andric parseRealInstList(Semantics, DuplicatedValues) || parseRParen()) 39005ffd83dbSDimitry Andric return true; 39015ffd83dbSDimitry Andric 39025ffd83dbSDimitry Andric for (int i = 0; i < Repetitions; ++i) 39035ffd83dbSDimitry Andric ValuesAsInt.append(DuplicatedValues.begin(), DuplicatedValues.end()); 39045ffd83dbSDimitry Andric } else { 39055ffd83dbSDimitry Andric APInt AsInt; 39065ffd83dbSDimitry Andric if (parseRealValue(Semantics, AsInt)) 39075ffd83dbSDimitry Andric return true; 39085ffd83dbSDimitry Andric ValuesAsInt.push_back(AsInt); 39095ffd83dbSDimitry Andric } 39105ffd83dbSDimitry Andric 39115ffd83dbSDimitry Andric // Continue if we see a comma. (Also, allow line continuation.) 39125ffd83dbSDimitry Andric if (!parseOptionalToken(AsmToken::Comma)) 39135ffd83dbSDimitry Andric break; 39145ffd83dbSDimitry Andric parseOptionalToken(AsmToken::EndOfStatement); 39155ffd83dbSDimitry Andric } 39165ffd83dbSDimitry Andric 39175ffd83dbSDimitry Andric return false; 39185ffd83dbSDimitry Andric } 39195ffd83dbSDimitry Andric 39205ffd83dbSDimitry Andric // Initialize real data values. 3921e8d8bef9SDimitry Andric bool MasmParser::emitRealValues(const fltSemantics &Semantics, 3922e8d8bef9SDimitry Andric unsigned *Count) { 3923e8d8bef9SDimitry Andric if (checkForValidSection()) 3924e8d8bef9SDimitry Andric return true; 3925e8d8bef9SDimitry Andric 39265ffd83dbSDimitry Andric SmallVector<APInt, 1> ValuesAsInt; 39275ffd83dbSDimitry Andric if (parseRealInstList(Semantics, ValuesAsInt)) 39285ffd83dbSDimitry Andric return true; 39295ffd83dbSDimitry Andric 39305ffd83dbSDimitry Andric for (const APInt &AsInt : ValuesAsInt) { 3931e8d8bef9SDimitry Andric getStreamer().emitIntValue(AsInt); 39325ffd83dbSDimitry Andric } 3933e8d8bef9SDimitry Andric if (Count) 3934e8d8bef9SDimitry Andric *Count = ValuesAsInt.size(); 39355ffd83dbSDimitry Andric return false; 39365ffd83dbSDimitry Andric } 39375ffd83dbSDimitry Andric 39385ffd83dbSDimitry Andric // Add a real field to the current struct. 3939e8d8bef9SDimitry Andric bool MasmParser::addRealField(StringRef Name, const fltSemantics &Semantics, 3940e8d8bef9SDimitry Andric size_t Size) { 39415ffd83dbSDimitry Andric StructInfo &Struct = StructInProgress.back(); 3942e8d8bef9SDimitry Andric FieldInfo &Field = Struct.addField(Name, FT_REAL, Size); 39435ffd83dbSDimitry Andric RealFieldInfo &RealInfo = Field.Contents.RealInfo; 39445ffd83dbSDimitry Andric 39455ffd83dbSDimitry Andric Field.SizeOf = 0; 39465ffd83dbSDimitry Andric 3947e8d8bef9SDimitry Andric if (parseRealInstList(Semantics, RealInfo.AsIntValues)) 39485ffd83dbSDimitry Andric return true; 39495ffd83dbSDimitry Andric 39505ffd83dbSDimitry Andric Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8; 39515ffd83dbSDimitry Andric Field.LengthOf = RealInfo.AsIntValues.size(); 39525ffd83dbSDimitry Andric Field.SizeOf = Field.Type * Field.LengthOf; 3953fe6060f1SDimitry Andric 3954fe6060f1SDimitry Andric const unsigned FieldEnd = Field.Offset + Field.SizeOf; 3955fe6060f1SDimitry Andric if (!Struct.IsUnion) { 3956fe6060f1SDimitry Andric Struct.NextOffset = FieldEnd; 3957fe6060f1SDimitry Andric } 3958fe6060f1SDimitry Andric Struct.Size = std::max(Struct.Size, FieldEnd); 39595ffd83dbSDimitry Andric return false; 39605ffd83dbSDimitry Andric } 39615ffd83dbSDimitry Andric 39625ffd83dbSDimitry Andric /// parseDirectiveRealValue 3963e8d8bef9SDimitry Andric /// ::= (real4 | real8 | real10) [ expression (, expression)* ] 39645ffd83dbSDimitry Andric bool MasmParser::parseDirectiveRealValue(StringRef IDVal, 3965e8d8bef9SDimitry Andric const fltSemantics &Semantics, 3966e8d8bef9SDimitry Andric size_t Size) { 39675ffd83dbSDimitry Andric if (StructInProgress.empty()) { 39685ffd83dbSDimitry Andric // Initialize data value. 39695ffd83dbSDimitry Andric if (emitRealValues(Semantics)) 39705ffd83dbSDimitry Andric return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); 3971e8d8bef9SDimitry Andric } else if (addRealField("", Semantics, Size)) { 39725ffd83dbSDimitry Andric return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); 39735ffd83dbSDimitry Andric } 39745ffd83dbSDimitry Andric return false; 39755ffd83dbSDimitry Andric } 39765ffd83dbSDimitry Andric 39775ffd83dbSDimitry Andric /// parseDirectiveNamedRealValue 3978e8d8bef9SDimitry Andric /// ::= name (real4 | real8 | real10) [ expression (, expression)* ] 3979e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName, 39805ffd83dbSDimitry Andric const fltSemantics &Semantics, 3981e8d8bef9SDimitry Andric unsigned Size, StringRef Name, 3982e8d8bef9SDimitry Andric SMLoc NameLoc) { 39835ffd83dbSDimitry Andric if (StructInProgress.empty()) { 39845ffd83dbSDimitry Andric // Initialize named data value. 39855ffd83dbSDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 39865ffd83dbSDimitry Andric getStreamer().emitLabel(Sym); 3987e8d8bef9SDimitry Andric unsigned Count; 3988e8d8bef9SDimitry Andric if (emitRealValues(Semantics, &Count)) 3989e8d8bef9SDimitry Andric return addErrorSuffix(" in '" + TypeName + "' directive"); 3990e8d8bef9SDimitry Andric 3991e8d8bef9SDimitry Andric AsmTypeInfo Type; 3992e8d8bef9SDimitry Andric Type.Name = TypeName; 3993e8d8bef9SDimitry Andric Type.Size = Size * Count; 3994e8d8bef9SDimitry Andric Type.ElementSize = Size; 3995e8d8bef9SDimitry Andric Type.Length = Count; 3996e8d8bef9SDimitry Andric KnownType[Name.lower()] = Type; 3997e8d8bef9SDimitry Andric } else if (addRealField(Name, Semantics, Size)) { 3998e8d8bef9SDimitry Andric return addErrorSuffix(" in '" + TypeName + "' directive"); 39995ffd83dbSDimitry Andric } 40005ffd83dbSDimitry Andric return false; 40015ffd83dbSDimitry Andric } 40025ffd83dbSDimitry Andric 40035ffd83dbSDimitry Andric bool MasmParser::parseOptionalAngleBracketOpen() { 40045ffd83dbSDimitry Andric const AsmToken Tok = getTok(); 40055ffd83dbSDimitry Andric if (parseOptionalToken(AsmToken::LessLess)) { 40065ffd83dbSDimitry Andric AngleBracketDepth++; 40075ffd83dbSDimitry Andric Lexer.UnLex(AsmToken(AsmToken::Less, Tok.getString().substr(1))); 40085ffd83dbSDimitry Andric return true; 40095ffd83dbSDimitry Andric } else if (parseOptionalToken(AsmToken::LessGreater)) { 40105ffd83dbSDimitry Andric AngleBracketDepth++; 40115ffd83dbSDimitry Andric Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1))); 40125ffd83dbSDimitry Andric return true; 40135ffd83dbSDimitry Andric } else if (parseOptionalToken(AsmToken::Less)) { 40145ffd83dbSDimitry Andric AngleBracketDepth++; 40155ffd83dbSDimitry Andric return true; 40165ffd83dbSDimitry Andric } 40175ffd83dbSDimitry Andric 40185ffd83dbSDimitry Andric return false; 40195ffd83dbSDimitry Andric } 40205ffd83dbSDimitry Andric 40215ffd83dbSDimitry Andric bool MasmParser::parseAngleBracketClose(const Twine &Msg) { 40225ffd83dbSDimitry Andric const AsmToken Tok = getTok(); 40235ffd83dbSDimitry Andric if (parseOptionalToken(AsmToken::GreaterGreater)) { 40245ffd83dbSDimitry Andric Lexer.UnLex(AsmToken(AsmToken::Greater, Tok.getString().substr(1))); 40255ffd83dbSDimitry Andric } else if (parseToken(AsmToken::Greater, Msg)) { 40265ffd83dbSDimitry Andric return true; 40275ffd83dbSDimitry Andric } 40285ffd83dbSDimitry Andric AngleBracketDepth--; 40295ffd83dbSDimitry Andric return false; 40305ffd83dbSDimitry Andric } 40315ffd83dbSDimitry Andric 40325ffd83dbSDimitry Andric bool MasmParser::parseFieldInitializer(const FieldInfo &Field, 40335ffd83dbSDimitry Andric const IntFieldInfo &Contents, 40345ffd83dbSDimitry Andric FieldInitializer &Initializer) { 40355ffd83dbSDimitry Andric SMLoc Loc = getTok().getLoc(); 40365ffd83dbSDimitry Andric 40375ffd83dbSDimitry Andric SmallVector<const MCExpr *, 1> Values; 40385ffd83dbSDimitry Andric if (parseOptionalToken(AsmToken::LCurly)) { 40395ffd83dbSDimitry Andric if (Field.LengthOf == 1 && Field.Type > 1) 40405ffd83dbSDimitry Andric return Error(Loc, "Cannot initialize scalar field with array value"); 40415ffd83dbSDimitry Andric if (parseScalarInstList(Field.Type, Values, AsmToken::RCurly) || 40425ffd83dbSDimitry Andric parseToken(AsmToken::RCurly)) 40435ffd83dbSDimitry Andric return true; 40445ffd83dbSDimitry Andric } else if (parseOptionalAngleBracketOpen()) { 40455ffd83dbSDimitry Andric if (Field.LengthOf == 1 && Field.Type > 1) 40465ffd83dbSDimitry Andric return Error(Loc, "Cannot initialize scalar field with array value"); 40475ffd83dbSDimitry Andric if (parseScalarInstList(Field.Type, Values, AsmToken::Greater) || 40485ffd83dbSDimitry Andric parseAngleBracketClose()) 40495ffd83dbSDimitry Andric return true; 40505ffd83dbSDimitry Andric } else if (Field.LengthOf > 1 && Field.Type > 1) { 40515ffd83dbSDimitry Andric return Error(Loc, "Cannot initialize array field with scalar value"); 40525ffd83dbSDimitry Andric } else if (parseScalarInitializer(Field.Type, Values, 40535ffd83dbSDimitry Andric /*StringPadLength=*/Field.LengthOf)) { 40545ffd83dbSDimitry Andric return true; 40555ffd83dbSDimitry Andric } 40565ffd83dbSDimitry Andric 40575ffd83dbSDimitry Andric if (Values.size() > Field.LengthOf) { 40585ffd83dbSDimitry Andric return Error(Loc, "Initializer too long for field; expected at most " + 40595ffd83dbSDimitry Andric std::to_string(Field.LengthOf) + " elements, got " + 40605ffd83dbSDimitry Andric std::to_string(Values.size())); 40615ffd83dbSDimitry Andric } 40625ffd83dbSDimitry Andric // Default-initialize all remaining values. 40635ffd83dbSDimitry Andric Values.append(Contents.Values.begin() + Values.size(), Contents.Values.end()); 40645ffd83dbSDimitry Andric 40655ffd83dbSDimitry Andric Initializer = FieldInitializer(std::move(Values)); 40665ffd83dbSDimitry Andric return false; 40675ffd83dbSDimitry Andric } 40685ffd83dbSDimitry Andric 40695ffd83dbSDimitry Andric bool MasmParser::parseFieldInitializer(const FieldInfo &Field, 40705ffd83dbSDimitry Andric const RealFieldInfo &Contents, 40715ffd83dbSDimitry Andric FieldInitializer &Initializer) { 4072e8d8bef9SDimitry Andric const fltSemantics *Semantics; 4073e8d8bef9SDimitry Andric switch (Field.Type) { 4074e8d8bef9SDimitry Andric case 4: 4075e8d8bef9SDimitry Andric Semantics = &APFloat::IEEEsingle(); 4076e8d8bef9SDimitry Andric break; 4077e8d8bef9SDimitry Andric case 8: 4078e8d8bef9SDimitry Andric Semantics = &APFloat::IEEEdouble(); 4079e8d8bef9SDimitry Andric break; 4080e8d8bef9SDimitry Andric case 10: 4081e8d8bef9SDimitry Andric Semantics = &APFloat::x87DoubleExtended(); 4082e8d8bef9SDimitry Andric break; 4083e8d8bef9SDimitry Andric default: 4084e8d8bef9SDimitry Andric llvm_unreachable("unknown real field type"); 4085e8d8bef9SDimitry Andric } 40865ffd83dbSDimitry Andric 40875ffd83dbSDimitry Andric SMLoc Loc = getTok().getLoc(); 40885ffd83dbSDimitry Andric 40895ffd83dbSDimitry Andric SmallVector<APInt, 1> AsIntValues; 40905ffd83dbSDimitry Andric if (parseOptionalToken(AsmToken::LCurly)) { 40915ffd83dbSDimitry Andric if (Field.LengthOf == 1) 40925ffd83dbSDimitry Andric return Error(Loc, "Cannot initialize scalar field with array value"); 4093e8d8bef9SDimitry Andric if (parseRealInstList(*Semantics, AsIntValues, AsmToken::RCurly) || 40945ffd83dbSDimitry Andric parseToken(AsmToken::RCurly)) 40955ffd83dbSDimitry Andric return true; 40965ffd83dbSDimitry Andric } else if (parseOptionalAngleBracketOpen()) { 40975ffd83dbSDimitry Andric if (Field.LengthOf == 1) 40985ffd83dbSDimitry Andric return Error(Loc, "Cannot initialize scalar field with array value"); 4099e8d8bef9SDimitry Andric if (parseRealInstList(*Semantics, AsIntValues, AsmToken::Greater) || 41005ffd83dbSDimitry Andric parseAngleBracketClose()) 41015ffd83dbSDimitry Andric return true; 41025ffd83dbSDimitry Andric } else if (Field.LengthOf > 1) { 41035ffd83dbSDimitry Andric return Error(Loc, "Cannot initialize array field with scalar value"); 41045ffd83dbSDimitry Andric } else { 41055ffd83dbSDimitry Andric AsIntValues.emplace_back(); 4106e8d8bef9SDimitry Andric if (parseRealValue(*Semantics, AsIntValues.back())) 41075ffd83dbSDimitry Andric return true; 41085ffd83dbSDimitry Andric } 41095ffd83dbSDimitry Andric 41105ffd83dbSDimitry Andric if (AsIntValues.size() > Field.LengthOf) { 41115ffd83dbSDimitry Andric return Error(Loc, "Initializer too long for field; expected at most " + 41125ffd83dbSDimitry Andric std::to_string(Field.LengthOf) + " elements, got " + 41135ffd83dbSDimitry Andric std::to_string(AsIntValues.size())); 41145ffd83dbSDimitry Andric } 41155ffd83dbSDimitry Andric // Default-initialize all remaining values. 41165ffd83dbSDimitry Andric AsIntValues.append(Contents.AsIntValues.begin() + AsIntValues.size(), 41175ffd83dbSDimitry Andric Contents.AsIntValues.end()); 41185ffd83dbSDimitry Andric 41195ffd83dbSDimitry Andric Initializer = FieldInitializer(std::move(AsIntValues)); 41205ffd83dbSDimitry Andric return false; 41215ffd83dbSDimitry Andric } 41225ffd83dbSDimitry Andric 41235ffd83dbSDimitry Andric bool MasmParser::parseFieldInitializer(const FieldInfo &Field, 41245ffd83dbSDimitry Andric const StructFieldInfo &Contents, 41255ffd83dbSDimitry Andric FieldInitializer &Initializer) { 41265ffd83dbSDimitry Andric SMLoc Loc = getTok().getLoc(); 41275ffd83dbSDimitry Andric 41285ffd83dbSDimitry Andric std::vector<StructInitializer> Initializers; 41295ffd83dbSDimitry Andric if (Field.LengthOf > 1) { 41305ffd83dbSDimitry Andric if (parseOptionalToken(AsmToken::LCurly)) { 41315ffd83dbSDimitry Andric if (parseStructInstList(Contents.Structure, Initializers, 41325ffd83dbSDimitry Andric AsmToken::RCurly) || 41335ffd83dbSDimitry Andric parseToken(AsmToken::RCurly)) 41345ffd83dbSDimitry Andric return true; 41355ffd83dbSDimitry Andric } else if (parseOptionalAngleBracketOpen()) { 41365ffd83dbSDimitry Andric if (parseStructInstList(Contents.Structure, Initializers, 41375ffd83dbSDimitry Andric AsmToken::Greater) || 41385ffd83dbSDimitry Andric parseAngleBracketClose()) 41395ffd83dbSDimitry Andric return true; 41405ffd83dbSDimitry Andric } else { 41415ffd83dbSDimitry Andric return Error(Loc, "Cannot initialize array field with scalar value"); 41425ffd83dbSDimitry Andric } 41435ffd83dbSDimitry Andric } else { 41445ffd83dbSDimitry Andric Initializers.emplace_back(); 41455ffd83dbSDimitry Andric if (parseStructInitializer(Contents.Structure, Initializers.back())) 41465ffd83dbSDimitry Andric return true; 41475ffd83dbSDimitry Andric } 41485ffd83dbSDimitry Andric 41495ffd83dbSDimitry Andric if (Initializers.size() > Field.LengthOf) { 41505ffd83dbSDimitry Andric return Error(Loc, "Initializer too long for field; expected at most " + 41515ffd83dbSDimitry Andric std::to_string(Field.LengthOf) + " elements, got " + 41525ffd83dbSDimitry Andric std::to_string(Initializers.size())); 41535ffd83dbSDimitry Andric } 41545ffd83dbSDimitry Andric // Default-initialize all remaining values. 41555ffd83dbSDimitry Andric Initializers.insert(Initializers.end(), 41565ffd83dbSDimitry Andric Contents.Initializers.begin() + Initializers.size(), 41575ffd83dbSDimitry Andric Contents.Initializers.end()); 41585ffd83dbSDimitry Andric 41595ffd83dbSDimitry Andric Initializer = FieldInitializer(std::move(Initializers), Contents.Structure); 41605ffd83dbSDimitry Andric return false; 41615ffd83dbSDimitry Andric } 41625ffd83dbSDimitry Andric 41635ffd83dbSDimitry Andric bool MasmParser::parseFieldInitializer(const FieldInfo &Field, 41645ffd83dbSDimitry Andric FieldInitializer &Initializer) { 41655ffd83dbSDimitry Andric switch (Field.Contents.FT) { 41665ffd83dbSDimitry Andric case FT_INTEGRAL: 41675ffd83dbSDimitry Andric return parseFieldInitializer(Field, Field.Contents.IntInfo, Initializer); 41685ffd83dbSDimitry Andric case FT_REAL: 41695ffd83dbSDimitry Andric return parseFieldInitializer(Field, Field.Contents.RealInfo, Initializer); 41705ffd83dbSDimitry Andric case FT_STRUCT: 41715ffd83dbSDimitry Andric return parseFieldInitializer(Field, Field.Contents.StructInfo, Initializer); 41725ffd83dbSDimitry Andric } 41735ffd83dbSDimitry Andric llvm_unreachable("Unhandled FieldType enum"); 41745ffd83dbSDimitry Andric } 41755ffd83dbSDimitry Andric 41765ffd83dbSDimitry Andric bool MasmParser::parseStructInitializer(const StructInfo &Structure, 41775ffd83dbSDimitry Andric StructInitializer &Initializer) { 41785ffd83dbSDimitry Andric const AsmToken FirstToken = getTok(); 41795ffd83dbSDimitry Andric 4180bdd1243dSDimitry Andric std::optional<AsmToken::TokenKind> EndToken; 41815ffd83dbSDimitry Andric if (parseOptionalToken(AsmToken::LCurly)) { 41825ffd83dbSDimitry Andric EndToken = AsmToken::RCurly; 41835ffd83dbSDimitry Andric } else if (parseOptionalAngleBracketOpen()) { 41845ffd83dbSDimitry Andric EndToken = AsmToken::Greater; 41855ffd83dbSDimitry Andric AngleBracketDepth++; 41865ffd83dbSDimitry Andric } else if (FirstToken.is(AsmToken::Identifier) && 41875ffd83dbSDimitry Andric FirstToken.getString() == "?") { 41885ffd83dbSDimitry Andric // ? initializer; leave EndToken uninitialized to treat as empty. 41895ffd83dbSDimitry Andric if (parseToken(AsmToken::Identifier)) 41905ffd83dbSDimitry Andric return true; 41915ffd83dbSDimitry Andric } else { 41925ffd83dbSDimitry Andric return Error(FirstToken.getLoc(), "Expected struct initializer"); 41935ffd83dbSDimitry Andric } 41945ffd83dbSDimitry Andric 41955ffd83dbSDimitry Andric auto &FieldInitializers = Initializer.FieldInitializers; 41965ffd83dbSDimitry Andric size_t FieldIndex = 0; 419781ad6265SDimitry Andric if (EndToken) { 41985ffd83dbSDimitry Andric // Initialize all fields with given initializers. 4199bdd1243dSDimitry Andric while (getTok().isNot(*EndToken) && FieldIndex < Structure.Fields.size()) { 42005ffd83dbSDimitry Andric const FieldInfo &Field = Structure.Fields[FieldIndex++]; 42015ffd83dbSDimitry Andric if (parseOptionalToken(AsmToken::Comma)) { 42025ffd83dbSDimitry Andric // Empty initializer; use the default and continue. (Also, allow line 42035ffd83dbSDimitry Andric // continuation.) 42045ffd83dbSDimitry Andric FieldInitializers.push_back(Field.Contents); 42055ffd83dbSDimitry Andric parseOptionalToken(AsmToken::EndOfStatement); 42065ffd83dbSDimitry Andric continue; 42075ffd83dbSDimitry Andric } 42085ffd83dbSDimitry Andric FieldInitializers.emplace_back(Field.Contents.FT); 42095ffd83dbSDimitry Andric if (parseFieldInitializer(Field, FieldInitializers.back())) 42105ffd83dbSDimitry Andric return true; 42115ffd83dbSDimitry Andric 42125ffd83dbSDimitry Andric // Continue if we see a comma. (Also, allow line continuation.) 42135ffd83dbSDimitry Andric SMLoc CommaLoc = getTok().getLoc(); 42145ffd83dbSDimitry Andric if (!parseOptionalToken(AsmToken::Comma)) 42155ffd83dbSDimitry Andric break; 42165ffd83dbSDimitry Andric if (FieldIndex == Structure.Fields.size()) 42175ffd83dbSDimitry Andric return Error(CommaLoc, "'" + Structure.Name + 42185ffd83dbSDimitry Andric "' initializer initializes too many fields"); 42195ffd83dbSDimitry Andric parseOptionalToken(AsmToken::EndOfStatement); 42205ffd83dbSDimitry Andric } 42215ffd83dbSDimitry Andric } 42225ffd83dbSDimitry Andric // Default-initialize all remaining fields. 4223fcaf7f86SDimitry Andric for (const FieldInfo &Field : llvm::drop_begin(Structure.Fields, FieldIndex)) 42245ffd83dbSDimitry Andric FieldInitializers.push_back(Field.Contents); 42255ffd83dbSDimitry Andric 422681ad6265SDimitry Andric if (EndToken) { 4227bdd1243dSDimitry Andric if (*EndToken == AsmToken::Greater) 42285ffd83dbSDimitry Andric return parseAngleBracketClose(); 42295ffd83dbSDimitry Andric 4230bdd1243dSDimitry Andric return parseToken(*EndToken); 42315ffd83dbSDimitry Andric } 42325ffd83dbSDimitry Andric 42335ffd83dbSDimitry Andric return false; 42345ffd83dbSDimitry Andric } 42355ffd83dbSDimitry Andric 42365ffd83dbSDimitry Andric bool MasmParser::parseStructInstList( 42375ffd83dbSDimitry Andric const StructInfo &Structure, std::vector<StructInitializer> &Initializers, 42385ffd83dbSDimitry Andric const AsmToken::TokenKind EndToken) { 42395ffd83dbSDimitry Andric while (getTok().isNot(EndToken) || 42405ffd83dbSDimitry Andric (EndToken == AsmToken::Greater && 42415ffd83dbSDimitry Andric getTok().isNot(AsmToken::GreaterGreater))) { 4242fe6060f1SDimitry Andric const AsmToken NextTok = peekTok(); 42435ffd83dbSDimitry Andric if (NextTok.is(AsmToken::Identifier) && 4244fe6060f1SDimitry Andric NextTok.getString().equals_insensitive("dup")) { 42455ffd83dbSDimitry Andric const MCExpr *Value; 42465ffd83dbSDimitry Andric if (parseExpression(Value) || parseToken(AsmToken::Identifier)) 42475ffd83dbSDimitry Andric return true; 42485ffd83dbSDimitry Andric const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); 42495ffd83dbSDimitry Andric if (!MCE) 42505ffd83dbSDimitry Andric return Error(Value->getLoc(), 42515ffd83dbSDimitry Andric "cannot repeat value a non-constant number of times"); 42525ffd83dbSDimitry Andric const int64_t Repetitions = MCE->getValue(); 42535ffd83dbSDimitry Andric if (Repetitions < 0) 42545ffd83dbSDimitry Andric return Error(Value->getLoc(), 42555ffd83dbSDimitry Andric "cannot repeat value a negative number of times"); 42565ffd83dbSDimitry Andric 42575ffd83dbSDimitry Andric std::vector<StructInitializer> DuplicatedValues; 42585ffd83dbSDimitry Andric if (parseToken(AsmToken::LParen, 42595ffd83dbSDimitry Andric "parentheses required for 'dup' contents") || 426004eeddc0SDimitry Andric parseStructInstList(Structure, DuplicatedValues) || parseRParen()) 42615ffd83dbSDimitry Andric return true; 42625ffd83dbSDimitry Andric 42635ffd83dbSDimitry Andric for (int i = 0; i < Repetitions; ++i) 4264e8d8bef9SDimitry Andric llvm::append_range(Initializers, DuplicatedValues); 42655ffd83dbSDimitry Andric } else { 42665ffd83dbSDimitry Andric Initializers.emplace_back(); 42675ffd83dbSDimitry Andric if (parseStructInitializer(Structure, Initializers.back())) 42685ffd83dbSDimitry Andric return true; 42695ffd83dbSDimitry Andric } 42705ffd83dbSDimitry Andric 42715ffd83dbSDimitry Andric // Continue if we see a comma. (Also, allow line continuation.) 42725ffd83dbSDimitry Andric if (!parseOptionalToken(AsmToken::Comma)) 42735ffd83dbSDimitry Andric break; 42745ffd83dbSDimitry Andric parseOptionalToken(AsmToken::EndOfStatement); 42755ffd83dbSDimitry Andric } 42765ffd83dbSDimitry Andric 42775ffd83dbSDimitry Andric return false; 42785ffd83dbSDimitry Andric } 42795ffd83dbSDimitry Andric 42805ffd83dbSDimitry Andric bool MasmParser::emitFieldValue(const FieldInfo &Field, 42815ffd83dbSDimitry Andric const IntFieldInfo &Contents) { 42825ffd83dbSDimitry Andric // Default-initialize all values. 42835ffd83dbSDimitry Andric for (const MCExpr *Value : Contents.Values) { 42845ffd83dbSDimitry Andric if (emitIntValue(Value, Field.Type)) 42855ffd83dbSDimitry Andric return true; 42865ffd83dbSDimitry Andric } 42875ffd83dbSDimitry Andric return false; 42885ffd83dbSDimitry Andric } 42895ffd83dbSDimitry Andric 42905ffd83dbSDimitry Andric bool MasmParser::emitFieldValue(const FieldInfo &Field, 42915ffd83dbSDimitry Andric const RealFieldInfo &Contents) { 42925ffd83dbSDimitry Andric for (const APInt &AsInt : Contents.AsIntValues) { 42935ffd83dbSDimitry Andric getStreamer().emitIntValue(AsInt.getLimitedValue(), 42945ffd83dbSDimitry Andric AsInt.getBitWidth() / 8); 42955ffd83dbSDimitry Andric } 42965ffd83dbSDimitry Andric return false; 42975ffd83dbSDimitry Andric } 42985ffd83dbSDimitry Andric 42995ffd83dbSDimitry Andric bool MasmParser::emitFieldValue(const FieldInfo &Field, 43005ffd83dbSDimitry Andric const StructFieldInfo &Contents) { 43015ffd83dbSDimitry Andric for (const auto &Initializer : Contents.Initializers) { 43025ffd83dbSDimitry Andric size_t Index = 0, Offset = 0; 43035ffd83dbSDimitry Andric for (const auto &SubField : Contents.Structure.Fields) { 43045ffd83dbSDimitry Andric getStreamer().emitZeros(SubField.Offset - Offset); 43055ffd83dbSDimitry Andric Offset = SubField.Offset + SubField.SizeOf; 43065ffd83dbSDimitry Andric emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]); 43075ffd83dbSDimitry Andric } 43085ffd83dbSDimitry Andric } 43095ffd83dbSDimitry Andric return false; 43105ffd83dbSDimitry Andric } 43115ffd83dbSDimitry Andric 43125ffd83dbSDimitry Andric bool MasmParser::emitFieldValue(const FieldInfo &Field) { 43135ffd83dbSDimitry Andric switch (Field.Contents.FT) { 43145ffd83dbSDimitry Andric case FT_INTEGRAL: 43155ffd83dbSDimitry Andric return emitFieldValue(Field, Field.Contents.IntInfo); 43165ffd83dbSDimitry Andric case FT_REAL: 43175ffd83dbSDimitry Andric return emitFieldValue(Field, Field.Contents.RealInfo); 43185ffd83dbSDimitry Andric case FT_STRUCT: 43195ffd83dbSDimitry Andric return emitFieldValue(Field, Field.Contents.StructInfo); 43205ffd83dbSDimitry Andric } 43215ffd83dbSDimitry Andric llvm_unreachable("Unhandled FieldType enum"); 43225ffd83dbSDimitry Andric } 43235ffd83dbSDimitry Andric 43245ffd83dbSDimitry Andric bool MasmParser::emitFieldInitializer(const FieldInfo &Field, 43255ffd83dbSDimitry Andric const IntFieldInfo &Contents, 43265ffd83dbSDimitry Andric const IntFieldInfo &Initializer) { 43275ffd83dbSDimitry Andric for (const auto &Value : Initializer.Values) { 43285ffd83dbSDimitry Andric if (emitIntValue(Value, Field.Type)) 43295ffd83dbSDimitry Andric return true; 43305ffd83dbSDimitry Andric } 43315ffd83dbSDimitry Andric // Default-initialize all remaining values. 4332fcaf7f86SDimitry Andric for (const auto &Value : 4333fcaf7f86SDimitry Andric llvm::drop_begin(Contents.Values, Initializer.Values.size())) { 43345ffd83dbSDimitry Andric if (emitIntValue(Value, Field.Type)) 43355ffd83dbSDimitry Andric return true; 43365ffd83dbSDimitry Andric } 43375ffd83dbSDimitry Andric return false; 43385ffd83dbSDimitry Andric } 43395ffd83dbSDimitry Andric 43405ffd83dbSDimitry Andric bool MasmParser::emitFieldInitializer(const FieldInfo &Field, 43415ffd83dbSDimitry Andric const RealFieldInfo &Contents, 43425ffd83dbSDimitry Andric const RealFieldInfo &Initializer) { 43435ffd83dbSDimitry Andric for (const auto &AsInt : Initializer.AsIntValues) { 43445ffd83dbSDimitry Andric getStreamer().emitIntValue(AsInt.getLimitedValue(), 43455ffd83dbSDimitry Andric AsInt.getBitWidth() / 8); 43465ffd83dbSDimitry Andric } 43475ffd83dbSDimitry Andric // Default-initialize all remaining values. 4348fcaf7f86SDimitry Andric for (const auto &AsInt : 4349fcaf7f86SDimitry Andric llvm::drop_begin(Contents.AsIntValues, Initializer.AsIntValues.size())) { 43505ffd83dbSDimitry Andric getStreamer().emitIntValue(AsInt.getLimitedValue(), 43515ffd83dbSDimitry Andric AsInt.getBitWidth() / 8); 43525ffd83dbSDimitry Andric } 43535ffd83dbSDimitry Andric return false; 43545ffd83dbSDimitry Andric } 43555ffd83dbSDimitry Andric 43565ffd83dbSDimitry Andric bool MasmParser::emitFieldInitializer(const FieldInfo &Field, 43575ffd83dbSDimitry Andric const StructFieldInfo &Contents, 43585ffd83dbSDimitry Andric const StructFieldInfo &Initializer) { 43595ffd83dbSDimitry Andric for (const auto &Init : Initializer.Initializers) { 4360fe6060f1SDimitry Andric if (emitStructInitializer(Contents.Structure, Init)) 4361fe6060f1SDimitry Andric return true; 43625ffd83dbSDimitry Andric } 43635ffd83dbSDimitry Andric // Default-initialize all remaining values. 4364fcaf7f86SDimitry Andric for (const auto &Init : llvm::drop_begin(Contents.Initializers, 4365fcaf7f86SDimitry Andric Initializer.Initializers.size())) { 4366fe6060f1SDimitry Andric if (emitStructInitializer(Contents.Structure, Init)) 4367fe6060f1SDimitry Andric return true; 43685ffd83dbSDimitry Andric } 43695ffd83dbSDimitry Andric return false; 43705ffd83dbSDimitry Andric } 43715ffd83dbSDimitry Andric 43725ffd83dbSDimitry Andric bool MasmParser::emitFieldInitializer(const FieldInfo &Field, 43735ffd83dbSDimitry Andric const FieldInitializer &Initializer) { 43745ffd83dbSDimitry Andric switch (Field.Contents.FT) { 43755ffd83dbSDimitry Andric case FT_INTEGRAL: 43765ffd83dbSDimitry Andric return emitFieldInitializer(Field, Field.Contents.IntInfo, 43775ffd83dbSDimitry Andric Initializer.IntInfo); 43785ffd83dbSDimitry Andric case FT_REAL: 43795ffd83dbSDimitry Andric return emitFieldInitializer(Field, Field.Contents.RealInfo, 43805ffd83dbSDimitry Andric Initializer.RealInfo); 43815ffd83dbSDimitry Andric case FT_STRUCT: 43825ffd83dbSDimitry Andric return emitFieldInitializer(Field, Field.Contents.StructInfo, 43835ffd83dbSDimitry Andric Initializer.StructInfo); 43845ffd83dbSDimitry Andric } 43855ffd83dbSDimitry Andric llvm_unreachable("Unhandled FieldType enum"); 43865ffd83dbSDimitry Andric } 43875ffd83dbSDimitry Andric 43885ffd83dbSDimitry Andric bool MasmParser::emitStructInitializer(const StructInfo &Structure, 43895ffd83dbSDimitry Andric const StructInitializer &Initializer) { 4390fe6060f1SDimitry Andric if (!Structure.Initializable) 4391fe6060f1SDimitry Andric return Error(getLexer().getLoc(), 4392fe6060f1SDimitry Andric "cannot initialize a value of type '" + Structure.Name + 4393fe6060f1SDimitry Andric "'; 'org' was used in the type's declaration"); 43945ffd83dbSDimitry Andric size_t Index = 0, Offset = 0; 43955ffd83dbSDimitry Andric for (const auto &Init : Initializer.FieldInitializers) { 43965ffd83dbSDimitry Andric const auto &Field = Structure.Fields[Index++]; 43975ffd83dbSDimitry Andric getStreamer().emitZeros(Field.Offset - Offset); 43985ffd83dbSDimitry Andric Offset = Field.Offset + Field.SizeOf; 43995ffd83dbSDimitry Andric if (emitFieldInitializer(Field, Init)) 44005ffd83dbSDimitry Andric return true; 44015ffd83dbSDimitry Andric } 44025ffd83dbSDimitry Andric // Default-initialize all remaining fields. 4403fcaf7f86SDimitry Andric for (const auto &Field : llvm::drop_begin( 4404fcaf7f86SDimitry Andric Structure.Fields, Initializer.FieldInitializers.size())) { 44055ffd83dbSDimitry Andric getStreamer().emitZeros(Field.Offset - Offset); 44065ffd83dbSDimitry Andric Offset = Field.Offset + Field.SizeOf; 44075ffd83dbSDimitry Andric if (emitFieldValue(Field)) 44085ffd83dbSDimitry Andric return true; 44095ffd83dbSDimitry Andric } 44105ffd83dbSDimitry Andric // Add final padding. 44115ffd83dbSDimitry Andric if (Offset != Structure.Size) 44125ffd83dbSDimitry Andric getStreamer().emitZeros(Structure.Size - Offset); 44135ffd83dbSDimitry Andric return false; 44145ffd83dbSDimitry Andric } 44155ffd83dbSDimitry Andric 44165ffd83dbSDimitry Andric // Set data values from initializers. 4417e8d8bef9SDimitry Andric bool MasmParser::emitStructValues(const StructInfo &Structure, 4418e8d8bef9SDimitry Andric unsigned *Count) { 44195ffd83dbSDimitry Andric std::vector<StructInitializer> Initializers; 44205ffd83dbSDimitry Andric if (parseStructInstList(Structure, Initializers)) 44215ffd83dbSDimitry Andric return true; 44225ffd83dbSDimitry Andric 44235ffd83dbSDimitry Andric for (const auto &Initializer : Initializers) { 44245ffd83dbSDimitry Andric if (emitStructInitializer(Structure, Initializer)) 44255ffd83dbSDimitry Andric return true; 44265ffd83dbSDimitry Andric } 44275ffd83dbSDimitry Andric 4428e8d8bef9SDimitry Andric if (Count) 4429e8d8bef9SDimitry Andric *Count = Initializers.size(); 44305ffd83dbSDimitry Andric return false; 44315ffd83dbSDimitry Andric } 44325ffd83dbSDimitry Andric 44335ffd83dbSDimitry Andric // Declare a field in the current struct. 44345ffd83dbSDimitry Andric bool MasmParser::addStructField(StringRef Name, const StructInfo &Structure) { 44355ffd83dbSDimitry Andric StructInfo &OwningStruct = StructInProgress.back(); 4436e8d8bef9SDimitry Andric FieldInfo &Field = 4437e8d8bef9SDimitry Andric OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize); 44385ffd83dbSDimitry Andric StructFieldInfo &StructInfo = Field.Contents.StructInfo; 44395ffd83dbSDimitry Andric 44405ffd83dbSDimitry Andric StructInfo.Structure = Structure; 44415ffd83dbSDimitry Andric Field.Type = Structure.Size; 44425ffd83dbSDimitry Andric 44435ffd83dbSDimitry Andric if (parseStructInstList(Structure, StructInfo.Initializers)) 44445ffd83dbSDimitry Andric return true; 44455ffd83dbSDimitry Andric 44465ffd83dbSDimitry Andric Field.LengthOf = StructInfo.Initializers.size(); 44475ffd83dbSDimitry Andric Field.SizeOf = Field.Type * Field.LengthOf; 4448fe6060f1SDimitry Andric 4449fe6060f1SDimitry Andric const unsigned FieldEnd = Field.Offset + Field.SizeOf; 4450fe6060f1SDimitry Andric if (!OwningStruct.IsUnion) { 4451fe6060f1SDimitry Andric OwningStruct.NextOffset = FieldEnd; 4452fe6060f1SDimitry Andric } 4453fe6060f1SDimitry Andric OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd); 44545ffd83dbSDimitry Andric 44555ffd83dbSDimitry Andric return false; 44565ffd83dbSDimitry Andric } 44575ffd83dbSDimitry Andric 44585ffd83dbSDimitry Andric /// parseDirectiveStructValue 44595ffd83dbSDimitry Andric /// ::= struct-id (<struct-initializer> | {struct-initializer}) 44605ffd83dbSDimitry Andric /// [, (<struct-initializer> | {struct-initializer})]* 44615ffd83dbSDimitry Andric bool MasmParser::parseDirectiveStructValue(const StructInfo &Structure, 44625ffd83dbSDimitry Andric StringRef Directive, SMLoc DirLoc) { 44635ffd83dbSDimitry Andric if (StructInProgress.empty()) { 44645ffd83dbSDimitry Andric if (emitStructValues(Structure)) 44655ffd83dbSDimitry Andric return true; 44665ffd83dbSDimitry Andric } else if (addStructField("", Structure)) { 44675ffd83dbSDimitry Andric return addErrorSuffix(" in '" + Twine(Directive) + "' directive"); 44685ffd83dbSDimitry Andric } 44695ffd83dbSDimitry Andric 44705ffd83dbSDimitry Andric return false; 44715ffd83dbSDimitry Andric } 44725ffd83dbSDimitry Andric 44735ffd83dbSDimitry Andric /// parseDirectiveNamedValue 44745ffd83dbSDimitry Andric /// ::= name (byte | word | ... ) [ expression (, expression)* ] 44755ffd83dbSDimitry Andric bool MasmParser::parseDirectiveNamedStructValue(const StructInfo &Structure, 44765ffd83dbSDimitry Andric StringRef Directive, 44775ffd83dbSDimitry Andric SMLoc DirLoc, StringRef Name) { 44785ffd83dbSDimitry Andric if (StructInProgress.empty()) { 44795ffd83dbSDimitry Andric // Initialize named data value. 44805ffd83dbSDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 44815ffd83dbSDimitry Andric getStreamer().emitLabel(Sym); 4482e8d8bef9SDimitry Andric unsigned Count; 4483e8d8bef9SDimitry Andric if (emitStructValues(Structure, &Count)) 44845ffd83dbSDimitry Andric return true; 4485e8d8bef9SDimitry Andric AsmTypeInfo Type; 4486e8d8bef9SDimitry Andric Type.Name = Structure.Name; 4487e8d8bef9SDimitry Andric Type.Size = Structure.Size * Count; 4488e8d8bef9SDimitry Andric Type.ElementSize = Structure.Size; 4489e8d8bef9SDimitry Andric Type.Length = Count; 4490e8d8bef9SDimitry Andric KnownType[Name.lower()] = Type; 44915ffd83dbSDimitry Andric } else if (addStructField(Name, Structure)) { 44925ffd83dbSDimitry Andric return addErrorSuffix(" in '" + Twine(Directive) + "' directive"); 44935ffd83dbSDimitry Andric } 44945ffd83dbSDimitry Andric 44955ffd83dbSDimitry Andric return false; 44965ffd83dbSDimitry Andric } 44975ffd83dbSDimitry Andric 44985ffd83dbSDimitry Andric /// parseDirectiveStruct 44995ffd83dbSDimitry Andric /// ::= <name> (STRUC | STRUCT | UNION) [fieldAlign] [, NONUNIQUE] 45005ffd83dbSDimitry Andric /// (dataDir | generalDir | offsetDir | nestedStruct)+ 45015ffd83dbSDimitry Andric /// <name> ENDS 45025ffd83dbSDimitry Andric ////// dataDir = data declaration 45035ffd83dbSDimitry Andric ////// offsetDir = EVEN, ORG, ALIGN 45045ffd83dbSDimitry Andric bool MasmParser::parseDirectiveStruct(StringRef Directive, 45055ffd83dbSDimitry Andric DirectiveKind DirKind, StringRef Name, 45065ffd83dbSDimitry Andric SMLoc NameLoc) { 45075ffd83dbSDimitry Andric // We ignore NONUNIQUE; we do not support OPTION M510 or OPTION OLDSTRUCTS 45085ffd83dbSDimitry Andric // anyway, so all field accesses must be qualified. 45095ffd83dbSDimitry Andric AsmToken NextTok = getTok(); 45105ffd83dbSDimitry Andric int64_t AlignmentValue = 1; 45115ffd83dbSDimitry Andric if (NextTok.isNot(AsmToken::Comma) && 45125ffd83dbSDimitry Andric NextTok.isNot(AsmToken::EndOfStatement) && 45135ffd83dbSDimitry Andric parseAbsoluteExpression(AlignmentValue)) { 45145ffd83dbSDimitry Andric return addErrorSuffix(" in alignment value for '" + Twine(Directive) + 45155ffd83dbSDimitry Andric "' directive"); 45165ffd83dbSDimitry Andric } 45175ffd83dbSDimitry Andric if (!isPowerOf2_64(AlignmentValue)) { 45185ffd83dbSDimitry Andric return Error(NextTok.getLoc(), "alignment must be a power of two; was " + 45195ffd83dbSDimitry Andric std::to_string(AlignmentValue)); 45205ffd83dbSDimitry Andric } 45215ffd83dbSDimitry Andric 45225ffd83dbSDimitry Andric StringRef Qualifier; 45235ffd83dbSDimitry Andric SMLoc QualifierLoc; 45245ffd83dbSDimitry Andric if (parseOptionalToken(AsmToken::Comma)) { 45255ffd83dbSDimitry Andric QualifierLoc = getTok().getLoc(); 45265ffd83dbSDimitry Andric if (parseIdentifier(Qualifier)) 45275ffd83dbSDimitry Andric return addErrorSuffix(" in '" + Twine(Directive) + "' directive"); 4528fe6060f1SDimitry Andric if (!Qualifier.equals_insensitive("nonunique")) 45295ffd83dbSDimitry Andric return Error(QualifierLoc, "Unrecognized qualifier for '" + 45305ffd83dbSDimitry Andric Twine(Directive) + 45315ffd83dbSDimitry Andric "' directive; expected none or NONUNIQUE"); 45325ffd83dbSDimitry Andric } 45335ffd83dbSDimitry Andric 4534*06c3fb27SDimitry Andric if (parseEOL()) 45355ffd83dbSDimitry Andric return addErrorSuffix(" in '" + Twine(Directive) + "' directive"); 45365ffd83dbSDimitry Andric 45375ffd83dbSDimitry Andric StructInProgress.emplace_back(Name, DirKind == DK_UNION, AlignmentValue); 45385ffd83dbSDimitry Andric return false; 45395ffd83dbSDimitry Andric } 45405ffd83dbSDimitry Andric 45415ffd83dbSDimitry Andric /// parseDirectiveNestedStruct 45425ffd83dbSDimitry Andric /// ::= (STRUC | STRUCT | UNION) [name] 45435ffd83dbSDimitry Andric /// (dataDir | generalDir | offsetDir | nestedStruct)+ 45445ffd83dbSDimitry Andric /// ENDS 45455ffd83dbSDimitry Andric bool MasmParser::parseDirectiveNestedStruct(StringRef Directive, 45465ffd83dbSDimitry Andric DirectiveKind DirKind) { 45475ffd83dbSDimitry Andric if (StructInProgress.empty()) 45485ffd83dbSDimitry Andric return TokError("missing name in top-level '" + Twine(Directive) + 45495ffd83dbSDimitry Andric "' directive"); 45505ffd83dbSDimitry Andric 45515ffd83dbSDimitry Andric StringRef Name; 45525ffd83dbSDimitry Andric if (getTok().is(AsmToken::Identifier)) { 45535ffd83dbSDimitry Andric Name = getTok().getIdentifier(); 45545ffd83dbSDimitry Andric parseToken(AsmToken::Identifier); 45555ffd83dbSDimitry Andric } 4556*06c3fb27SDimitry Andric if (parseEOL()) 45575ffd83dbSDimitry Andric return addErrorSuffix(" in '" + Twine(Directive) + "' directive"); 45585ffd83dbSDimitry Andric 4559e8d8bef9SDimitry Andric // Reserve space to ensure Alignment doesn't get invalidated when 4560e8d8bef9SDimitry Andric // StructInProgress grows. 4561e8d8bef9SDimitry Andric StructInProgress.reserve(StructInProgress.size() + 1); 45625ffd83dbSDimitry Andric StructInProgress.emplace_back(Name, DirKind == DK_UNION, 45635ffd83dbSDimitry Andric StructInProgress.back().Alignment); 45645ffd83dbSDimitry Andric return false; 45655ffd83dbSDimitry Andric } 45665ffd83dbSDimitry Andric 45675ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) { 45685ffd83dbSDimitry Andric if (StructInProgress.empty()) 45695ffd83dbSDimitry Andric return Error(NameLoc, "ENDS directive without matching STRUC/STRUCT/UNION"); 45705ffd83dbSDimitry Andric if (StructInProgress.size() > 1) 45715ffd83dbSDimitry Andric return Error(NameLoc, "unexpected name in nested ENDS directive"); 4572fe6060f1SDimitry Andric if (StructInProgress.back().Name.compare_insensitive(Name)) 45735ffd83dbSDimitry Andric return Error(NameLoc, "mismatched name in ENDS directive; expected '" + 45745ffd83dbSDimitry Andric StructInProgress.back().Name + "'"); 45755ffd83dbSDimitry Andric StructInfo Structure = StructInProgress.pop_back_val(); 4576e8d8bef9SDimitry Andric // Pad to make the structure's size divisible by the smaller of its alignment 4577e8d8bef9SDimitry Andric // and the size of its largest field. 4578e8d8bef9SDimitry Andric Structure.Size = llvm::alignTo( 4579e8d8bef9SDimitry Andric Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize)); 45805ffd83dbSDimitry Andric Structs[Name.lower()] = Structure; 45815ffd83dbSDimitry Andric 4582*06c3fb27SDimitry Andric if (parseEOL()) 45835ffd83dbSDimitry Andric return addErrorSuffix(" in ENDS directive"); 45845ffd83dbSDimitry Andric 45855ffd83dbSDimitry Andric return false; 45865ffd83dbSDimitry Andric } 45875ffd83dbSDimitry Andric 45885ffd83dbSDimitry Andric bool MasmParser::parseDirectiveNestedEnds() { 45895ffd83dbSDimitry Andric if (StructInProgress.empty()) 45905ffd83dbSDimitry Andric return TokError("ENDS directive without matching STRUC/STRUCT/UNION"); 45915ffd83dbSDimitry Andric if (StructInProgress.size() == 1) 45925ffd83dbSDimitry Andric return TokError("missing name in top-level ENDS directive"); 45935ffd83dbSDimitry Andric 4594*06c3fb27SDimitry Andric if (parseEOL()) 45955ffd83dbSDimitry Andric return addErrorSuffix(" in nested ENDS directive"); 45965ffd83dbSDimitry Andric 45975ffd83dbSDimitry Andric StructInfo Structure = StructInProgress.pop_back_val(); 45985ffd83dbSDimitry Andric // Pad to make the structure's size divisible by its alignment. 45995ffd83dbSDimitry Andric Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment); 46005ffd83dbSDimitry Andric 46015ffd83dbSDimitry Andric StructInfo &ParentStruct = StructInProgress.back(); 46025ffd83dbSDimitry Andric if (Structure.Name.empty()) { 4603fe6060f1SDimitry Andric // Anonymous substructures' fields are addressed as if they belong to the 4604fe6060f1SDimitry Andric // parent structure - so we transfer them to the parent here. 46055ffd83dbSDimitry Andric const size_t OldFields = ParentStruct.Fields.size(); 46065ffd83dbSDimitry Andric ParentStruct.Fields.insert( 46075ffd83dbSDimitry Andric ParentStruct.Fields.end(), 46085ffd83dbSDimitry Andric std::make_move_iterator(Structure.Fields.begin()), 46095ffd83dbSDimitry Andric std::make_move_iterator(Structure.Fields.end())); 46105ffd83dbSDimitry Andric for (const auto &FieldByName : Structure.FieldsByName) { 46115ffd83dbSDimitry Andric ParentStruct.FieldsByName[FieldByName.getKey()] = 46125ffd83dbSDimitry Andric FieldByName.getValue() + OldFields; 46135ffd83dbSDimitry Andric } 4614fe6060f1SDimitry Andric 4615fe6060f1SDimitry Andric unsigned FirstFieldOffset = 0; 4616fe6060f1SDimitry Andric if (!Structure.Fields.empty() && !ParentStruct.IsUnion) { 4617fe6060f1SDimitry Andric FirstFieldOffset = llvm::alignTo( 4618fe6060f1SDimitry Andric ParentStruct.NextOffset, 4619fe6060f1SDimitry Andric std::min(ParentStruct.Alignment, Structure.AlignmentSize)); 46205ffd83dbSDimitry Andric } 46215ffd83dbSDimitry Andric 4622fe6060f1SDimitry Andric if (ParentStruct.IsUnion) { 46235ffd83dbSDimitry Andric ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size); 4624fe6060f1SDimitry Andric } else { 4625fcaf7f86SDimitry Andric for (auto &Field : llvm::drop_begin(ParentStruct.Fields, OldFields)) 4626fcaf7f86SDimitry Andric Field.Offset += FirstFieldOffset; 4627fe6060f1SDimitry Andric 4628fe6060f1SDimitry Andric const unsigned StructureEnd = FirstFieldOffset + Structure.Size; 4629fe6060f1SDimitry Andric if (!ParentStruct.IsUnion) { 4630fe6060f1SDimitry Andric ParentStruct.NextOffset = StructureEnd; 4631fe6060f1SDimitry Andric } 4632fe6060f1SDimitry Andric ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd); 4633fe6060f1SDimitry Andric } 46345ffd83dbSDimitry Andric } else { 4635e8d8bef9SDimitry Andric FieldInfo &Field = ParentStruct.addField(Structure.Name, FT_STRUCT, 4636e8d8bef9SDimitry Andric Structure.AlignmentSize); 46375ffd83dbSDimitry Andric StructFieldInfo &StructInfo = Field.Contents.StructInfo; 46385ffd83dbSDimitry Andric Field.Type = Structure.Size; 46395ffd83dbSDimitry Andric Field.LengthOf = 1; 46405ffd83dbSDimitry Andric Field.SizeOf = Structure.Size; 46415ffd83dbSDimitry Andric 4642fe6060f1SDimitry Andric const unsigned StructureEnd = Field.Offset + Field.SizeOf; 4643fe6060f1SDimitry Andric if (!ParentStruct.IsUnion) { 4644fe6060f1SDimitry Andric ParentStruct.NextOffset = StructureEnd; 4645fe6060f1SDimitry Andric } 4646fe6060f1SDimitry Andric ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd); 46475ffd83dbSDimitry Andric 46485ffd83dbSDimitry Andric StructInfo.Structure = Structure; 46495ffd83dbSDimitry Andric StructInfo.Initializers.emplace_back(); 46505ffd83dbSDimitry Andric auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers; 46515ffd83dbSDimitry Andric for (const auto &SubField : Structure.Fields) { 46525ffd83dbSDimitry Andric FieldInitializers.push_back(SubField.Contents); 46535ffd83dbSDimitry Andric } 46545ffd83dbSDimitry Andric } 46555ffd83dbSDimitry Andric 46565ffd83dbSDimitry Andric return false; 46575ffd83dbSDimitry Andric } 46585ffd83dbSDimitry Andric 46595ffd83dbSDimitry Andric /// parseDirectiveOrg 4660fe6060f1SDimitry Andric /// ::= org expression 46615ffd83dbSDimitry Andric bool MasmParser::parseDirectiveOrg() { 46625ffd83dbSDimitry Andric const MCExpr *Offset; 46635ffd83dbSDimitry Andric SMLoc OffsetLoc = Lexer.getLoc(); 46645ffd83dbSDimitry Andric if (checkForValidSection() || parseExpression(Offset)) 46655ffd83dbSDimitry Andric return true; 4666*06c3fb27SDimitry Andric if (parseEOL()) 4667fe6060f1SDimitry Andric return addErrorSuffix(" in 'org' directive"); 46685ffd83dbSDimitry Andric 4669fe6060f1SDimitry Andric if (StructInProgress.empty()) { 4670fe6060f1SDimitry Andric // Not in a struct; change the offset for the next instruction or data 4671fe6060f1SDimitry Andric if (checkForValidSection()) 4672fe6060f1SDimitry Andric return addErrorSuffix(" in 'org' directive"); 4673fe6060f1SDimitry Andric 4674fe6060f1SDimitry Andric getStreamer().emitValueToOffset(Offset, 0, OffsetLoc); 4675fe6060f1SDimitry Andric } else { 4676fe6060f1SDimitry Andric // Offset the next field of this struct 4677fe6060f1SDimitry Andric StructInfo &Structure = StructInProgress.back(); 4678fe6060f1SDimitry Andric int64_t OffsetRes; 4679fe6060f1SDimitry Andric if (!Offset->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr())) 4680fe6060f1SDimitry Andric return Error(OffsetLoc, 4681fe6060f1SDimitry Andric "expected absolute expression in 'org' directive"); 4682fe6060f1SDimitry Andric if (OffsetRes < 0) 4683fe6060f1SDimitry Andric return Error( 4684fe6060f1SDimitry Andric OffsetLoc, 4685fe6060f1SDimitry Andric "expected non-negative value in struct's 'org' directive; was " + 4686fe6060f1SDimitry Andric std::to_string(OffsetRes)); 4687fe6060f1SDimitry Andric Structure.NextOffset = static_cast<unsigned>(OffsetRes); 4688fe6060f1SDimitry Andric 4689fe6060f1SDimitry Andric // ORG-affected structures cannot be initialized 4690fe6060f1SDimitry Andric Structure.Initializable = false; 4691fe6060f1SDimitry Andric } 4692fe6060f1SDimitry Andric 46935ffd83dbSDimitry Andric return false; 46945ffd83dbSDimitry Andric } 46955ffd83dbSDimitry Andric 4696fe6060f1SDimitry Andric bool MasmParser::emitAlignTo(int64_t Alignment) { 4697fe6060f1SDimitry Andric if (StructInProgress.empty()) { 4698fe6060f1SDimitry Andric // Not in a struct; align the next instruction or data 46995ffd83dbSDimitry Andric if (checkForValidSection()) 4700fe6060f1SDimitry Andric return true; 47015ffd83dbSDimitry Andric 47025ffd83dbSDimitry Andric // Check whether we should use optimal code alignment for this align 47035ffd83dbSDimitry Andric // directive. 47045ffd83dbSDimitry Andric const MCSection *Section = getStreamer().getCurrentSectionOnly(); 47055ffd83dbSDimitry Andric assert(Section && "must have section to emit alignment"); 470681ad6265SDimitry Andric if (Section->useCodeAlign()) { 4707bdd1243dSDimitry Andric getStreamer().emitCodeAlignment(Align(Alignment), 4708bdd1243dSDimitry Andric &getTargetParser().getSTI(), 4709349cc55cSDimitry Andric /*MaxBytesToEmit=*/0); 47105ffd83dbSDimitry Andric } else { 47115ffd83dbSDimitry Andric // FIXME: Target specific behavior about how the "extra" bytes are filled. 4712bdd1243dSDimitry Andric getStreamer().emitValueToAlignment(Align(Alignment), /*Value=*/0, 4713fe6060f1SDimitry Andric /*ValueSize=*/1, 47145ffd83dbSDimitry Andric /*MaxBytesToEmit=*/0); 47155ffd83dbSDimitry Andric } 4716fe6060f1SDimitry Andric } else { 4717fe6060f1SDimitry Andric // Align the next field of this struct 4718fe6060f1SDimitry Andric StructInfo &Structure = StructInProgress.back(); 4719fe6060f1SDimitry Andric Structure.NextOffset = llvm::alignTo(Structure.NextOffset, Alignment); 4720fe6060f1SDimitry Andric } 4721fe6060f1SDimitry Andric 4722fe6060f1SDimitry Andric return false; 4723fe6060f1SDimitry Andric } 4724fe6060f1SDimitry Andric 4725fe6060f1SDimitry Andric /// parseDirectiveAlign 4726fe6060f1SDimitry Andric /// ::= align expression 4727fe6060f1SDimitry Andric bool MasmParser::parseDirectiveAlign() { 4728fe6060f1SDimitry Andric SMLoc AlignmentLoc = getLexer().getLoc(); 4729fe6060f1SDimitry Andric int64_t Alignment; 4730fe6060f1SDimitry Andric 4731fe6060f1SDimitry Andric // Ignore empty 'align' directives. 4732fe6060f1SDimitry Andric if (getTok().is(AsmToken::EndOfStatement)) { 4733fe6060f1SDimitry Andric return Warning(AlignmentLoc, 4734fe6060f1SDimitry Andric "align directive with no operand is ignored") && 4735*06c3fb27SDimitry Andric parseEOL(); 4736fe6060f1SDimitry Andric } 4737*06c3fb27SDimitry Andric if (parseAbsoluteExpression(Alignment) || parseEOL()) 4738fe6060f1SDimitry Andric return addErrorSuffix(" in align directive"); 4739fe6060f1SDimitry Andric 4740fe6060f1SDimitry Andric // Always emit an alignment here even if we throw an error. 4741fe6060f1SDimitry Andric bool ReturnVal = false; 4742fe6060f1SDimitry Andric 4743fe6060f1SDimitry Andric // Reject alignments that aren't either a power of two or zero, for ML.exe 4744fe6060f1SDimitry Andric // compatibility. Alignment of zero is silently rounded up to one. 4745fe6060f1SDimitry Andric if (Alignment == 0) 4746fe6060f1SDimitry Andric Alignment = 1; 4747fe6060f1SDimitry Andric if (!isPowerOf2_64(Alignment)) 4748fe6060f1SDimitry Andric ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2; was " + 4749fe6060f1SDimitry Andric std::to_string(Alignment)); 4750fe6060f1SDimitry Andric 4751fe6060f1SDimitry Andric if (emitAlignTo(Alignment)) 4752fe6060f1SDimitry Andric ReturnVal |= addErrorSuffix(" in align directive"); 47535ffd83dbSDimitry Andric 47545ffd83dbSDimitry Andric return ReturnVal; 47555ffd83dbSDimitry Andric } 47565ffd83dbSDimitry Andric 4757fe6060f1SDimitry Andric /// parseDirectiveEven 4758fe6060f1SDimitry Andric /// ::= even 4759fe6060f1SDimitry Andric bool MasmParser::parseDirectiveEven() { 4760*06c3fb27SDimitry Andric if (parseEOL() || emitAlignTo(2)) 4761fe6060f1SDimitry Andric return addErrorSuffix(" in even directive"); 4762fe6060f1SDimitry Andric 4763fe6060f1SDimitry Andric return false; 4764fe6060f1SDimitry Andric } 4765fe6060f1SDimitry Andric 47665ffd83dbSDimitry Andric /// parseDirectiveFile 47675ffd83dbSDimitry Andric /// ::= .file filename 47685ffd83dbSDimitry Andric /// ::= .file number [directory] filename [md5 checksum] [source source-text] 47695ffd83dbSDimitry Andric bool MasmParser::parseDirectiveFile(SMLoc DirectiveLoc) { 47705ffd83dbSDimitry Andric // FIXME: I'm not sure what this is. 47715ffd83dbSDimitry Andric int64_t FileNumber = -1; 47725ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Integer)) { 47735ffd83dbSDimitry Andric FileNumber = getTok().getIntVal(); 47745ffd83dbSDimitry Andric Lex(); 47755ffd83dbSDimitry Andric 47765ffd83dbSDimitry Andric if (FileNumber < 0) 47775ffd83dbSDimitry Andric return TokError("negative file number"); 47785ffd83dbSDimitry Andric } 47795ffd83dbSDimitry Andric 47805ffd83dbSDimitry Andric std::string Path; 47815ffd83dbSDimitry Andric 47825ffd83dbSDimitry Andric // Usually the directory and filename together, otherwise just the directory. 47835ffd83dbSDimitry Andric // Allow the strings to have escaped octal character sequence. 47845ffd83dbSDimitry Andric if (check(getTok().isNot(AsmToken::String), 47855ffd83dbSDimitry Andric "unexpected token in '.file' directive") || 47865ffd83dbSDimitry Andric parseEscapedString(Path)) 47875ffd83dbSDimitry Andric return true; 47885ffd83dbSDimitry Andric 47895ffd83dbSDimitry Andric StringRef Directory; 47905ffd83dbSDimitry Andric StringRef Filename; 47915ffd83dbSDimitry Andric std::string FilenameData; 47925ffd83dbSDimitry Andric if (getLexer().is(AsmToken::String)) { 47935ffd83dbSDimitry Andric if (check(FileNumber == -1, 47945ffd83dbSDimitry Andric "explicit path specified, but no file number") || 47955ffd83dbSDimitry Andric parseEscapedString(FilenameData)) 47965ffd83dbSDimitry Andric return true; 47975ffd83dbSDimitry Andric Filename = FilenameData; 47985ffd83dbSDimitry Andric Directory = Path; 47995ffd83dbSDimitry Andric } else { 48005ffd83dbSDimitry Andric Filename = Path; 48015ffd83dbSDimitry Andric } 48025ffd83dbSDimitry Andric 48035ffd83dbSDimitry Andric uint64_t MD5Hi, MD5Lo; 48045ffd83dbSDimitry Andric bool HasMD5 = false; 48055ffd83dbSDimitry Andric 4806bdd1243dSDimitry Andric std::optional<StringRef> Source; 48075ffd83dbSDimitry Andric bool HasSource = false; 48085ffd83dbSDimitry Andric std::string SourceString; 48095ffd83dbSDimitry Andric 48105ffd83dbSDimitry Andric while (!parseOptionalToken(AsmToken::EndOfStatement)) { 48115ffd83dbSDimitry Andric StringRef Keyword; 48125ffd83dbSDimitry Andric if (check(getTok().isNot(AsmToken::Identifier), 48135ffd83dbSDimitry Andric "unexpected token in '.file' directive") || 48145ffd83dbSDimitry Andric parseIdentifier(Keyword)) 48155ffd83dbSDimitry Andric return true; 48165ffd83dbSDimitry Andric if (Keyword == "md5") { 48175ffd83dbSDimitry Andric HasMD5 = true; 48185ffd83dbSDimitry Andric if (check(FileNumber == -1, 48195ffd83dbSDimitry Andric "MD5 checksum specified, but no file number") || 48205ffd83dbSDimitry Andric parseHexOcta(*this, MD5Hi, MD5Lo)) 48215ffd83dbSDimitry Andric return true; 48225ffd83dbSDimitry Andric } else if (Keyword == "source") { 48235ffd83dbSDimitry Andric HasSource = true; 48245ffd83dbSDimitry Andric if (check(FileNumber == -1, 48255ffd83dbSDimitry Andric "source specified, but no file number") || 48265ffd83dbSDimitry Andric check(getTok().isNot(AsmToken::String), 48275ffd83dbSDimitry Andric "unexpected token in '.file' directive") || 48285ffd83dbSDimitry Andric parseEscapedString(SourceString)) 48295ffd83dbSDimitry Andric return true; 48305ffd83dbSDimitry Andric } else { 48315ffd83dbSDimitry Andric return TokError("unexpected token in '.file' directive"); 48325ffd83dbSDimitry Andric } 48335ffd83dbSDimitry Andric } 48345ffd83dbSDimitry Andric 48355ffd83dbSDimitry Andric if (FileNumber == -1) { 48365ffd83dbSDimitry Andric // Ignore the directive if there is no number and the target doesn't support 48375ffd83dbSDimitry Andric // numberless .file directives. This allows some portability of assembler 48385ffd83dbSDimitry Andric // between different object file formats. 48395ffd83dbSDimitry Andric if (getContext().getAsmInfo()->hasSingleParameterDotFile()) 48405ffd83dbSDimitry Andric getStreamer().emitFileDirective(Filename); 48415ffd83dbSDimitry Andric } else { 48425ffd83dbSDimitry Andric // In case there is a -g option as well as debug info from directive .file, 48435ffd83dbSDimitry Andric // we turn off the -g option, directly use the existing debug info instead. 48445ffd83dbSDimitry Andric // Throw away any implicit file table for the assembler source. 48455ffd83dbSDimitry Andric if (Ctx.getGenDwarfForAssembly()) { 48465ffd83dbSDimitry Andric Ctx.getMCDwarfLineTable(0).resetFileTable(); 48475ffd83dbSDimitry Andric Ctx.setGenDwarfForAssembly(false); 48485ffd83dbSDimitry Andric } 48495ffd83dbSDimitry Andric 4850bdd1243dSDimitry Andric std::optional<MD5::MD5Result> CKMem; 48515ffd83dbSDimitry Andric if (HasMD5) { 48525ffd83dbSDimitry Andric MD5::MD5Result Sum; 48535ffd83dbSDimitry Andric for (unsigned i = 0; i != 8; ++i) { 485481ad6265SDimitry Andric Sum[i] = uint8_t(MD5Hi >> ((7 - i) * 8)); 485581ad6265SDimitry Andric Sum[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8)); 48565ffd83dbSDimitry Andric } 48575ffd83dbSDimitry Andric CKMem = Sum; 48585ffd83dbSDimitry Andric } 48595ffd83dbSDimitry Andric if (HasSource) { 48605ffd83dbSDimitry Andric char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size())); 48615ffd83dbSDimitry Andric memcpy(SourceBuf, SourceString.data(), SourceString.size()); 48625ffd83dbSDimitry Andric Source = StringRef(SourceBuf, SourceString.size()); 48635ffd83dbSDimitry Andric } 48645ffd83dbSDimitry Andric if (FileNumber == 0) { 48655ffd83dbSDimitry Andric if (Ctx.getDwarfVersion() < 5) 48665ffd83dbSDimitry Andric return Warning(DirectiveLoc, "file 0 not supported prior to DWARF-5"); 48675ffd83dbSDimitry Andric getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source); 48685ffd83dbSDimitry Andric } else { 48695ffd83dbSDimitry Andric Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective( 48705ffd83dbSDimitry Andric FileNumber, Directory, Filename, CKMem, Source); 48715ffd83dbSDimitry Andric if (!FileNumOrErr) 48725ffd83dbSDimitry Andric return Error(DirectiveLoc, toString(FileNumOrErr.takeError())); 48735ffd83dbSDimitry Andric } 48745ffd83dbSDimitry Andric // Alert the user if there are some .file directives with MD5 and some not. 48755ffd83dbSDimitry Andric // But only do that once. 48765ffd83dbSDimitry Andric if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) { 48775ffd83dbSDimitry Andric ReportedInconsistentMD5 = true; 48785ffd83dbSDimitry Andric return Warning(DirectiveLoc, "inconsistent use of MD5 checksums"); 48795ffd83dbSDimitry Andric } 48805ffd83dbSDimitry Andric } 48815ffd83dbSDimitry Andric 48825ffd83dbSDimitry Andric return false; 48835ffd83dbSDimitry Andric } 48845ffd83dbSDimitry Andric 48855ffd83dbSDimitry Andric /// parseDirectiveLine 48865ffd83dbSDimitry Andric /// ::= .line [number] 48875ffd83dbSDimitry Andric bool MasmParser::parseDirectiveLine() { 48885ffd83dbSDimitry Andric int64_t LineNumber; 48895ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Integer)) { 48905ffd83dbSDimitry Andric if (parseIntToken(LineNumber, "unexpected token in '.line' directive")) 48915ffd83dbSDimitry Andric return true; 48925ffd83dbSDimitry Andric (void)LineNumber; 48935ffd83dbSDimitry Andric // FIXME: Do something with the .line. 48945ffd83dbSDimitry Andric } 489581ad6265SDimitry Andric if (parseEOL()) 48965ffd83dbSDimitry Andric return true; 48975ffd83dbSDimitry Andric 48985ffd83dbSDimitry Andric return false; 48995ffd83dbSDimitry Andric } 49005ffd83dbSDimitry Andric 49015ffd83dbSDimitry Andric /// parseDirectiveLoc 49025ffd83dbSDimitry Andric /// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end] 49035ffd83dbSDimitry Andric /// [epilogue_begin] [is_stmt VALUE] [isa VALUE] 49045ffd83dbSDimitry Andric /// The first number is a file number, must have been previously assigned with 49055ffd83dbSDimitry Andric /// a .file directive, the second number is the line number and optionally the 49065ffd83dbSDimitry Andric /// third number is a column position (zero if not specified). The remaining 49075ffd83dbSDimitry Andric /// optional items are .loc sub-directives. 49085ffd83dbSDimitry Andric bool MasmParser::parseDirectiveLoc() { 49095ffd83dbSDimitry Andric int64_t FileNumber = 0, LineNumber = 0; 49105ffd83dbSDimitry Andric SMLoc Loc = getTok().getLoc(); 49115ffd83dbSDimitry Andric if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") || 49125ffd83dbSDimitry Andric check(FileNumber < 1 && Ctx.getDwarfVersion() < 5, Loc, 49135ffd83dbSDimitry Andric "file number less than one in '.loc' directive") || 49145ffd83dbSDimitry Andric check(!getContext().isValidDwarfFileNumber(FileNumber), Loc, 49155ffd83dbSDimitry Andric "unassigned file number in '.loc' directive")) 49165ffd83dbSDimitry Andric return true; 49175ffd83dbSDimitry Andric 49185ffd83dbSDimitry Andric // optional 49195ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Integer)) { 49205ffd83dbSDimitry Andric LineNumber = getTok().getIntVal(); 49215ffd83dbSDimitry Andric if (LineNumber < 0) 49225ffd83dbSDimitry Andric return TokError("line number less than zero in '.loc' directive"); 49235ffd83dbSDimitry Andric Lex(); 49245ffd83dbSDimitry Andric } 49255ffd83dbSDimitry Andric 49265ffd83dbSDimitry Andric int64_t ColumnPos = 0; 49275ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Integer)) { 49285ffd83dbSDimitry Andric ColumnPos = getTok().getIntVal(); 49295ffd83dbSDimitry Andric if (ColumnPos < 0) 49305ffd83dbSDimitry Andric return TokError("column position less than zero in '.loc' directive"); 49315ffd83dbSDimitry Andric Lex(); 49325ffd83dbSDimitry Andric } 49335ffd83dbSDimitry Andric 49345ffd83dbSDimitry Andric auto PrevFlags = getContext().getCurrentDwarfLoc().getFlags(); 49355ffd83dbSDimitry Andric unsigned Flags = PrevFlags & DWARF2_FLAG_IS_STMT; 49365ffd83dbSDimitry Andric unsigned Isa = 0; 49375ffd83dbSDimitry Andric int64_t Discriminator = 0; 49385ffd83dbSDimitry Andric 49395ffd83dbSDimitry Andric auto parseLocOp = [&]() -> bool { 49405ffd83dbSDimitry Andric StringRef Name; 49415ffd83dbSDimitry Andric SMLoc Loc = getTok().getLoc(); 49425ffd83dbSDimitry Andric if (parseIdentifier(Name)) 49435ffd83dbSDimitry Andric return TokError("unexpected token in '.loc' directive"); 49445ffd83dbSDimitry Andric 49455ffd83dbSDimitry Andric if (Name == "basic_block") 49465ffd83dbSDimitry Andric Flags |= DWARF2_FLAG_BASIC_BLOCK; 49475ffd83dbSDimitry Andric else if (Name == "prologue_end") 49485ffd83dbSDimitry Andric Flags |= DWARF2_FLAG_PROLOGUE_END; 49495ffd83dbSDimitry Andric else if (Name == "epilogue_begin") 49505ffd83dbSDimitry Andric Flags |= DWARF2_FLAG_EPILOGUE_BEGIN; 49515ffd83dbSDimitry Andric else if (Name == "is_stmt") { 49525ffd83dbSDimitry Andric Loc = getTok().getLoc(); 49535ffd83dbSDimitry Andric const MCExpr *Value; 49545ffd83dbSDimitry Andric if (parseExpression(Value)) 49555ffd83dbSDimitry Andric return true; 49565ffd83dbSDimitry Andric // The expression must be the constant 0 or 1. 49575ffd83dbSDimitry Andric if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { 49585ffd83dbSDimitry Andric int Value = MCE->getValue(); 49595ffd83dbSDimitry Andric if (Value == 0) 49605ffd83dbSDimitry Andric Flags &= ~DWARF2_FLAG_IS_STMT; 49615ffd83dbSDimitry Andric else if (Value == 1) 49625ffd83dbSDimitry Andric Flags |= DWARF2_FLAG_IS_STMT; 49635ffd83dbSDimitry Andric else 49645ffd83dbSDimitry Andric return Error(Loc, "is_stmt value not 0 or 1"); 49655ffd83dbSDimitry Andric } else { 49665ffd83dbSDimitry Andric return Error(Loc, "is_stmt value not the constant value of 0 or 1"); 49675ffd83dbSDimitry Andric } 49685ffd83dbSDimitry Andric } else if (Name == "isa") { 49695ffd83dbSDimitry Andric Loc = getTok().getLoc(); 49705ffd83dbSDimitry Andric const MCExpr *Value; 49715ffd83dbSDimitry Andric if (parseExpression(Value)) 49725ffd83dbSDimitry Andric return true; 49735ffd83dbSDimitry Andric // The expression must be a constant greater or equal to 0. 49745ffd83dbSDimitry Andric if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { 49755ffd83dbSDimitry Andric int Value = MCE->getValue(); 49765ffd83dbSDimitry Andric if (Value < 0) 49775ffd83dbSDimitry Andric return Error(Loc, "isa number less than zero"); 49785ffd83dbSDimitry Andric Isa = Value; 49795ffd83dbSDimitry Andric } else { 49805ffd83dbSDimitry Andric return Error(Loc, "isa number not a constant value"); 49815ffd83dbSDimitry Andric } 49825ffd83dbSDimitry Andric } else if (Name == "discriminator") { 49835ffd83dbSDimitry Andric if (parseAbsoluteExpression(Discriminator)) 49845ffd83dbSDimitry Andric return true; 49855ffd83dbSDimitry Andric } else { 49865ffd83dbSDimitry Andric return Error(Loc, "unknown sub-directive in '.loc' directive"); 49875ffd83dbSDimitry Andric } 49885ffd83dbSDimitry Andric return false; 49895ffd83dbSDimitry Andric }; 49905ffd83dbSDimitry Andric 49915ffd83dbSDimitry Andric if (parseMany(parseLocOp, false /*hasComma*/)) 49925ffd83dbSDimitry Andric return true; 49935ffd83dbSDimitry Andric 49945ffd83dbSDimitry Andric getStreamer().emitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags, 49955ffd83dbSDimitry Andric Isa, Discriminator, StringRef()); 49965ffd83dbSDimitry Andric 49975ffd83dbSDimitry Andric return false; 49985ffd83dbSDimitry Andric } 49995ffd83dbSDimitry Andric 50005ffd83dbSDimitry Andric /// parseDirectiveStabs 50015ffd83dbSDimitry Andric /// ::= .stabs string, number, number, number 50025ffd83dbSDimitry Andric bool MasmParser::parseDirectiveStabs() { 50035ffd83dbSDimitry Andric return TokError("unsupported directive '.stabs'"); 50045ffd83dbSDimitry Andric } 50055ffd83dbSDimitry Andric 50065ffd83dbSDimitry Andric /// parseDirectiveCVFile 50075ffd83dbSDimitry Andric /// ::= .cv_file number filename [checksum] [checksumkind] 50085ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFile() { 50095ffd83dbSDimitry Andric SMLoc FileNumberLoc = getTok().getLoc(); 50105ffd83dbSDimitry Andric int64_t FileNumber; 50115ffd83dbSDimitry Andric std::string Filename; 50125ffd83dbSDimitry Andric std::string Checksum; 50135ffd83dbSDimitry Andric int64_t ChecksumKind = 0; 50145ffd83dbSDimitry Andric 50155ffd83dbSDimitry Andric if (parseIntToken(FileNumber, 50165ffd83dbSDimitry Andric "expected file number in '.cv_file' directive") || 50175ffd83dbSDimitry Andric check(FileNumber < 1, FileNumberLoc, "file number less than one") || 50185ffd83dbSDimitry Andric check(getTok().isNot(AsmToken::String), 50195ffd83dbSDimitry Andric "unexpected token in '.cv_file' directive") || 50205ffd83dbSDimitry Andric parseEscapedString(Filename)) 50215ffd83dbSDimitry Andric return true; 50225ffd83dbSDimitry Andric if (!parseOptionalToken(AsmToken::EndOfStatement)) { 50235ffd83dbSDimitry Andric if (check(getTok().isNot(AsmToken::String), 50245ffd83dbSDimitry Andric "unexpected token in '.cv_file' directive") || 50255ffd83dbSDimitry Andric parseEscapedString(Checksum) || 50265ffd83dbSDimitry Andric parseIntToken(ChecksumKind, 50275ffd83dbSDimitry Andric "expected checksum kind in '.cv_file' directive") || 502881ad6265SDimitry Andric parseEOL()) 50295ffd83dbSDimitry Andric return true; 50305ffd83dbSDimitry Andric } 50315ffd83dbSDimitry Andric 50325ffd83dbSDimitry Andric Checksum = fromHex(Checksum); 50335ffd83dbSDimitry Andric void *CKMem = Ctx.allocate(Checksum.size(), 1); 50345ffd83dbSDimitry Andric memcpy(CKMem, Checksum.data(), Checksum.size()); 50355ffd83dbSDimitry Andric ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem), 50365ffd83dbSDimitry Andric Checksum.size()); 50375ffd83dbSDimitry Andric 503881ad6265SDimitry Andric if (!getStreamer().emitCVFileDirective(FileNumber, Filename, ChecksumAsBytes, 50395ffd83dbSDimitry Andric static_cast<uint8_t>(ChecksumKind))) 50405ffd83dbSDimitry Andric return Error(FileNumberLoc, "file number already allocated"); 50415ffd83dbSDimitry Andric 50425ffd83dbSDimitry Andric return false; 50435ffd83dbSDimitry Andric } 50445ffd83dbSDimitry Andric 50455ffd83dbSDimitry Andric bool MasmParser::parseCVFunctionId(int64_t &FunctionId, 50465ffd83dbSDimitry Andric StringRef DirectiveName) { 50475ffd83dbSDimitry Andric SMLoc Loc; 50485ffd83dbSDimitry Andric return parseTokenLoc(Loc) || 50495ffd83dbSDimitry Andric parseIntToken(FunctionId, "expected function id in '" + DirectiveName + 50505ffd83dbSDimitry Andric "' directive") || 50515ffd83dbSDimitry Andric check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc, 50525ffd83dbSDimitry Andric "expected function id within range [0, UINT_MAX)"); 50535ffd83dbSDimitry Andric } 50545ffd83dbSDimitry Andric 50555ffd83dbSDimitry Andric bool MasmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) { 50565ffd83dbSDimitry Andric SMLoc Loc; 50575ffd83dbSDimitry Andric return parseTokenLoc(Loc) || 50585ffd83dbSDimitry Andric parseIntToken(FileNumber, "expected integer in '" + DirectiveName + 50595ffd83dbSDimitry Andric "' directive") || 50605ffd83dbSDimitry Andric check(FileNumber < 1, Loc, "file number less than one in '" + 50615ffd83dbSDimitry Andric DirectiveName + "' directive") || 50625ffd83dbSDimitry Andric check(!getCVContext().isValidFileNumber(FileNumber), Loc, 50635ffd83dbSDimitry Andric "unassigned file number in '" + DirectiveName + "' directive"); 50645ffd83dbSDimitry Andric } 50655ffd83dbSDimitry Andric 50665ffd83dbSDimitry Andric /// parseDirectiveCVFuncId 50675ffd83dbSDimitry Andric /// ::= .cv_func_id FunctionId 50685ffd83dbSDimitry Andric /// 50695ffd83dbSDimitry Andric /// Introduces a function ID that can be used with .cv_loc. 50705ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFuncId() { 50715ffd83dbSDimitry Andric SMLoc FunctionIdLoc = getTok().getLoc(); 50725ffd83dbSDimitry Andric int64_t FunctionId; 50735ffd83dbSDimitry Andric 507481ad6265SDimitry Andric if (parseCVFunctionId(FunctionId, ".cv_func_id") || parseEOL()) 50755ffd83dbSDimitry Andric return true; 50765ffd83dbSDimitry Andric 507781ad6265SDimitry Andric if (!getStreamer().emitCVFuncIdDirective(FunctionId)) 50785ffd83dbSDimitry Andric return Error(FunctionIdLoc, "function id already allocated"); 50795ffd83dbSDimitry Andric 50805ffd83dbSDimitry Andric return false; 50815ffd83dbSDimitry Andric } 50825ffd83dbSDimitry Andric 50835ffd83dbSDimitry Andric /// parseDirectiveCVInlineSiteId 50845ffd83dbSDimitry Andric /// ::= .cv_inline_site_id FunctionId 50855ffd83dbSDimitry Andric /// "within" IAFunc 50865ffd83dbSDimitry Andric /// "inlined_at" IAFile IALine [IACol] 50875ffd83dbSDimitry Andric /// 50885ffd83dbSDimitry Andric /// Introduces a function ID that can be used with .cv_loc. Includes "inlined 50895ffd83dbSDimitry Andric /// at" source location information for use in the line table of the caller, 50905ffd83dbSDimitry Andric /// whether the caller is a real function or another inlined call site. 50915ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVInlineSiteId() { 50925ffd83dbSDimitry Andric SMLoc FunctionIdLoc = getTok().getLoc(); 50935ffd83dbSDimitry Andric int64_t FunctionId; 50945ffd83dbSDimitry Andric int64_t IAFunc; 50955ffd83dbSDimitry Andric int64_t IAFile; 50965ffd83dbSDimitry Andric int64_t IALine; 50975ffd83dbSDimitry Andric int64_t IACol = 0; 50985ffd83dbSDimitry Andric 50995ffd83dbSDimitry Andric // FunctionId 51005ffd83dbSDimitry Andric if (parseCVFunctionId(FunctionId, ".cv_inline_site_id")) 51015ffd83dbSDimitry Andric return true; 51025ffd83dbSDimitry Andric 51035ffd83dbSDimitry Andric // "within" 51045ffd83dbSDimitry Andric if (check((getLexer().isNot(AsmToken::Identifier) || 51055ffd83dbSDimitry Andric getTok().getIdentifier() != "within"), 51065ffd83dbSDimitry Andric "expected 'within' identifier in '.cv_inline_site_id' directive")) 51075ffd83dbSDimitry Andric return true; 51085ffd83dbSDimitry Andric Lex(); 51095ffd83dbSDimitry Andric 51105ffd83dbSDimitry Andric // IAFunc 51115ffd83dbSDimitry Andric if (parseCVFunctionId(IAFunc, ".cv_inline_site_id")) 51125ffd83dbSDimitry Andric return true; 51135ffd83dbSDimitry Andric 51145ffd83dbSDimitry Andric // "inlined_at" 51155ffd83dbSDimitry Andric if (check((getLexer().isNot(AsmToken::Identifier) || 51165ffd83dbSDimitry Andric getTok().getIdentifier() != "inlined_at"), 51175ffd83dbSDimitry Andric "expected 'inlined_at' identifier in '.cv_inline_site_id' " 51185ffd83dbSDimitry Andric "directive") ) 51195ffd83dbSDimitry Andric return true; 51205ffd83dbSDimitry Andric Lex(); 51215ffd83dbSDimitry Andric 51225ffd83dbSDimitry Andric // IAFile IALine 51235ffd83dbSDimitry Andric if (parseCVFileId(IAFile, ".cv_inline_site_id") || 51245ffd83dbSDimitry Andric parseIntToken(IALine, "expected line number after 'inlined_at'")) 51255ffd83dbSDimitry Andric return true; 51265ffd83dbSDimitry Andric 51275ffd83dbSDimitry Andric // [IACol] 51285ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Integer)) { 51295ffd83dbSDimitry Andric IACol = getTok().getIntVal(); 51305ffd83dbSDimitry Andric Lex(); 51315ffd83dbSDimitry Andric } 51325ffd83dbSDimitry Andric 513381ad6265SDimitry Andric if (parseEOL()) 51345ffd83dbSDimitry Andric return true; 51355ffd83dbSDimitry Andric 513681ad6265SDimitry Andric if (!getStreamer().emitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile, 51375ffd83dbSDimitry Andric IALine, IACol, FunctionIdLoc)) 51385ffd83dbSDimitry Andric return Error(FunctionIdLoc, "function id already allocated"); 51395ffd83dbSDimitry Andric 51405ffd83dbSDimitry Andric return false; 51415ffd83dbSDimitry Andric } 51425ffd83dbSDimitry Andric 51435ffd83dbSDimitry Andric /// parseDirectiveCVLoc 51445ffd83dbSDimitry Andric /// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end] 51455ffd83dbSDimitry Andric /// [is_stmt VALUE] 51465ffd83dbSDimitry Andric /// The first number is a file number, must have been previously assigned with 51475ffd83dbSDimitry Andric /// a .file directive, the second number is the line number and optionally the 51485ffd83dbSDimitry Andric /// third number is a column position (zero if not specified). The remaining 51495ffd83dbSDimitry Andric /// optional items are .loc sub-directives. 51505ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVLoc() { 51515ffd83dbSDimitry Andric SMLoc DirectiveLoc = getTok().getLoc(); 51525ffd83dbSDimitry Andric int64_t FunctionId, FileNumber; 51535ffd83dbSDimitry Andric if (parseCVFunctionId(FunctionId, ".cv_loc") || 51545ffd83dbSDimitry Andric parseCVFileId(FileNumber, ".cv_loc")) 51555ffd83dbSDimitry Andric return true; 51565ffd83dbSDimitry Andric 51575ffd83dbSDimitry Andric int64_t LineNumber = 0; 51585ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Integer)) { 51595ffd83dbSDimitry Andric LineNumber = getTok().getIntVal(); 51605ffd83dbSDimitry Andric if (LineNumber < 0) 51615ffd83dbSDimitry Andric return TokError("line number less than zero in '.cv_loc' directive"); 51625ffd83dbSDimitry Andric Lex(); 51635ffd83dbSDimitry Andric } 51645ffd83dbSDimitry Andric 51655ffd83dbSDimitry Andric int64_t ColumnPos = 0; 51665ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Integer)) { 51675ffd83dbSDimitry Andric ColumnPos = getTok().getIntVal(); 51685ffd83dbSDimitry Andric if (ColumnPos < 0) 51695ffd83dbSDimitry Andric return TokError("column position less than zero in '.cv_loc' directive"); 51705ffd83dbSDimitry Andric Lex(); 51715ffd83dbSDimitry Andric } 51725ffd83dbSDimitry Andric 51735ffd83dbSDimitry Andric bool PrologueEnd = false; 51745ffd83dbSDimitry Andric uint64_t IsStmt = 0; 51755ffd83dbSDimitry Andric 51765ffd83dbSDimitry Andric auto parseOp = [&]() -> bool { 51775ffd83dbSDimitry Andric StringRef Name; 51785ffd83dbSDimitry Andric SMLoc Loc = getTok().getLoc(); 51795ffd83dbSDimitry Andric if (parseIdentifier(Name)) 51805ffd83dbSDimitry Andric return TokError("unexpected token in '.cv_loc' directive"); 51815ffd83dbSDimitry Andric if (Name == "prologue_end") 51825ffd83dbSDimitry Andric PrologueEnd = true; 51835ffd83dbSDimitry Andric else if (Name == "is_stmt") { 51845ffd83dbSDimitry Andric Loc = getTok().getLoc(); 51855ffd83dbSDimitry Andric const MCExpr *Value; 51865ffd83dbSDimitry Andric if (parseExpression(Value)) 51875ffd83dbSDimitry Andric return true; 51885ffd83dbSDimitry Andric // The expression must be the constant 0 or 1. 51895ffd83dbSDimitry Andric IsStmt = ~0ULL; 51905ffd83dbSDimitry Andric if (const auto *MCE = dyn_cast<MCConstantExpr>(Value)) 51915ffd83dbSDimitry Andric IsStmt = MCE->getValue(); 51925ffd83dbSDimitry Andric 51935ffd83dbSDimitry Andric if (IsStmt > 1) 51945ffd83dbSDimitry Andric return Error(Loc, "is_stmt value not 0 or 1"); 51955ffd83dbSDimitry Andric } else { 51965ffd83dbSDimitry Andric return Error(Loc, "unknown sub-directive in '.cv_loc' directive"); 51975ffd83dbSDimitry Andric } 51985ffd83dbSDimitry Andric return false; 51995ffd83dbSDimitry Andric }; 52005ffd83dbSDimitry Andric 52015ffd83dbSDimitry Andric if (parseMany(parseOp, false /*hasComma*/)) 52025ffd83dbSDimitry Andric return true; 52035ffd83dbSDimitry Andric 52045ffd83dbSDimitry Andric getStreamer().emitCVLocDirective(FunctionId, FileNumber, LineNumber, 52055ffd83dbSDimitry Andric ColumnPos, PrologueEnd, IsStmt, StringRef(), 52065ffd83dbSDimitry Andric DirectiveLoc); 52075ffd83dbSDimitry Andric return false; 52085ffd83dbSDimitry Andric } 52095ffd83dbSDimitry Andric 52105ffd83dbSDimitry Andric /// parseDirectiveCVLinetable 52115ffd83dbSDimitry Andric /// ::= .cv_linetable FunctionId, FnStart, FnEnd 52125ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVLinetable() { 52135ffd83dbSDimitry Andric int64_t FunctionId; 52145ffd83dbSDimitry Andric StringRef FnStartName, FnEndName; 52155ffd83dbSDimitry Andric SMLoc Loc = getTok().getLoc(); 52165ffd83dbSDimitry Andric if (parseCVFunctionId(FunctionId, ".cv_linetable") || 52175ffd83dbSDimitry Andric parseToken(AsmToken::Comma, 52185ffd83dbSDimitry Andric "unexpected token in '.cv_linetable' directive") || 52195ffd83dbSDimitry Andric parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc, 52205ffd83dbSDimitry Andric "expected identifier in directive") || 52215ffd83dbSDimitry Andric parseToken(AsmToken::Comma, 52225ffd83dbSDimitry Andric "unexpected token in '.cv_linetable' directive") || 52235ffd83dbSDimitry Andric parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc, 52245ffd83dbSDimitry Andric "expected identifier in directive")) 52255ffd83dbSDimitry Andric return true; 52265ffd83dbSDimitry Andric 52275ffd83dbSDimitry Andric MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName); 52285ffd83dbSDimitry Andric MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName); 52295ffd83dbSDimitry Andric 52305ffd83dbSDimitry Andric getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym); 52315ffd83dbSDimitry Andric return false; 52325ffd83dbSDimitry Andric } 52335ffd83dbSDimitry Andric 52345ffd83dbSDimitry Andric /// parseDirectiveCVInlineLinetable 52355ffd83dbSDimitry Andric /// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd 52365ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVInlineLinetable() { 52375ffd83dbSDimitry Andric int64_t PrimaryFunctionId, SourceFileId, SourceLineNum; 52385ffd83dbSDimitry Andric StringRef FnStartName, FnEndName; 52395ffd83dbSDimitry Andric SMLoc Loc = getTok().getLoc(); 52405ffd83dbSDimitry Andric if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") || 52415ffd83dbSDimitry Andric parseTokenLoc(Loc) || 52425ffd83dbSDimitry Andric parseIntToken( 52435ffd83dbSDimitry Andric SourceFileId, 52445ffd83dbSDimitry Andric "expected SourceField in '.cv_inline_linetable' directive") || 52455ffd83dbSDimitry Andric check(SourceFileId <= 0, Loc, 52465ffd83dbSDimitry Andric "File id less than zero in '.cv_inline_linetable' directive") || 52475ffd83dbSDimitry Andric parseTokenLoc(Loc) || 52485ffd83dbSDimitry Andric parseIntToken( 52495ffd83dbSDimitry Andric SourceLineNum, 52505ffd83dbSDimitry Andric "expected SourceLineNum in '.cv_inline_linetable' directive") || 52515ffd83dbSDimitry Andric check(SourceLineNum < 0, Loc, 52525ffd83dbSDimitry Andric "Line number less than zero in '.cv_inline_linetable' directive") || 52535ffd83dbSDimitry Andric parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc, 52545ffd83dbSDimitry Andric "expected identifier in directive") || 52555ffd83dbSDimitry Andric parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc, 52565ffd83dbSDimitry Andric "expected identifier in directive")) 52575ffd83dbSDimitry Andric return true; 52585ffd83dbSDimitry Andric 525981ad6265SDimitry Andric if (parseEOL()) 52605ffd83dbSDimitry Andric return true; 52615ffd83dbSDimitry Andric 52625ffd83dbSDimitry Andric MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName); 52635ffd83dbSDimitry Andric MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName); 52645ffd83dbSDimitry Andric getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId, 52655ffd83dbSDimitry Andric SourceLineNum, FnStartSym, 52665ffd83dbSDimitry Andric FnEndSym); 52675ffd83dbSDimitry Andric return false; 52685ffd83dbSDimitry Andric } 52695ffd83dbSDimitry Andric 52705ffd83dbSDimitry Andric void MasmParser::initializeCVDefRangeTypeMap() { 52715ffd83dbSDimitry Andric CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER; 52725ffd83dbSDimitry Andric CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL; 52735ffd83dbSDimitry Andric CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER; 52745ffd83dbSDimitry Andric CVDefRangeTypeMap["reg_rel"] = CVDR_DEFRANGE_REGISTER_REL; 52755ffd83dbSDimitry Andric } 52765ffd83dbSDimitry Andric 52775ffd83dbSDimitry Andric /// parseDirectiveCVDefRange 52785ffd83dbSDimitry Andric /// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes* 52795ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVDefRange() { 52805ffd83dbSDimitry Andric SMLoc Loc; 52815ffd83dbSDimitry Andric std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges; 52825ffd83dbSDimitry Andric while (getLexer().is(AsmToken::Identifier)) { 52835ffd83dbSDimitry Andric Loc = getLexer().getLoc(); 52845ffd83dbSDimitry Andric StringRef GapStartName; 52855ffd83dbSDimitry Andric if (parseIdentifier(GapStartName)) 52865ffd83dbSDimitry Andric return Error(Loc, "expected identifier in directive"); 52875ffd83dbSDimitry Andric MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName); 52885ffd83dbSDimitry Andric 52895ffd83dbSDimitry Andric Loc = getLexer().getLoc(); 52905ffd83dbSDimitry Andric StringRef GapEndName; 52915ffd83dbSDimitry Andric if (parseIdentifier(GapEndName)) 52925ffd83dbSDimitry Andric return Error(Loc, "expected identifier in directive"); 52935ffd83dbSDimitry Andric MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName); 52945ffd83dbSDimitry Andric 52955ffd83dbSDimitry Andric Ranges.push_back({GapStartSym, GapEndSym}); 52965ffd83dbSDimitry Andric } 52975ffd83dbSDimitry Andric 52985ffd83dbSDimitry Andric StringRef CVDefRangeTypeStr; 52995ffd83dbSDimitry Andric if (parseToken( 53005ffd83dbSDimitry Andric AsmToken::Comma, 53015ffd83dbSDimitry Andric "expected comma before def_range type in .cv_def_range directive") || 53025ffd83dbSDimitry Andric parseIdentifier(CVDefRangeTypeStr)) 53035ffd83dbSDimitry Andric return Error(Loc, "expected def_range type in directive"); 53045ffd83dbSDimitry Andric 53055ffd83dbSDimitry Andric StringMap<CVDefRangeType>::const_iterator CVTypeIt = 53065ffd83dbSDimitry Andric CVDefRangeTypeMap.find(CVDefRangeTypeStr); 53075ffd83dbSDimitry Andric CVDefRangeType CVDRType = (CVTypeIt == CVDefRangeTypeMap.end()) 53085ffd83dbSDimitry Andric ? CVDR_DEFRANGE 53095ffd83dbSDimitry Andric : CVTypeIt->getValue(); 53105ffd83dbSDimitry Andric switch (CVDRType) { 53115ffd83dbSDimitry Andric case CVDR_DEFRANGE_REGISTER: { 53125ffd83dbSDimitry Andric int64_t DRRegister; 53135ffd83dbSDimitry Andric if (parseToken(AsmToken::Comma, "expected comma before register number in " 53145ffd83dbSDimitry Andric ".cv_def_range directive") || 53155ffd83dbSDimitry Andric parseAbsoluteExpression(DRRegister)) 53165ffd83dbSDimitry Andric return Error(Loc, "expected register number"); 53175ffd83dbSDimitry Andric 53185ffd83dbSDimitry Andric codeview::DefRangeRegisterHeader DRHdr; 53195ffd83dbSDimitry Andric DRHdr.Register = DRRegister; 53205ffd83dbSDimitry Andric DRHdr.MayHaveNoName = 0; 53215ffd83dbSDimitry Andric getStreamer().emitCVDefRangeDirective(Ranges, DRHdr); 53225ffd83dbSDimitry Andric break; 53235ffd83dbSDimitry Andric } 53245ffd83dbSDimitry Andric case CVDR_DEFRANGE_FRAMEPOINTER_REL: { 53255ffd83dbSDimitry Andric int64_t DROffset; 53265ffd83dbSDimitry Andric if (parseToken(AsmToken::Comma, 53275ffd83dbSDimitry Andric "expected comma before offset in .cv_def_range directive") || 53285ffd83dbSDimitry Andric parseAbsoluteExpression(DROffset)) 53295ffd83dbSDimitry Andric return Error(Loc, "expected offset value"); 53305ffd83dbSDimitry Andric 53315ffd83dbSDimitry Andric codeview::DefRangeFramePointerRelHeader DRHdr; 53325ffd83dbSDimitry Andric DRHdr.Offset = DROffset; 53335ffd83dbSDimitry Andric getStreamer().emitCVDefRangeDirective(Ranges, DRHdr); 53345ffd83dbSDimitry Andric break; 53355ffd83dbSDimitry Andric } 53365ffd83dbSDimitry Andric case CVDR_DEFRANGE_SUBFIELD_REGISTER: { 53375ffd83dbSDimitry Andric int64_t DRRegister; 53385ffd83dbSDimitry Andric int64_t DROffsetInParent; 53395ffd83dbSDimitry Andric if (parseToken(AsmToken::Comma, "expected comma before register number in " 53405ffd83dbSDimitry Andric ".cv_def_range directive") || 53415ffd83dbSDimitry Andric parseAbsoluteExpression(DRRegister)) 53425ffd83dbSDimitry Andric return Error(Loc, "expected register number"); 53435ffd83dbSDimitry Andric if (parseToken(AsmToken::Comma, 53445ffd83dbSDimitry Andric "expected comma before offset in .cv_def_range directive") || 53455ffd83dbSDimitry Andric parseAbsoluteExpression(DROffsetInParent)) 53465ffd83dbSDimitry Andric return Error(Loc, "expected offset value"); 53475ffd83dbSDimitry Andric 53485ffd83dbSDimitry Andric codeview::DefRangeSubfieldRegisterHeader DRHdr; 53495ffd83dbSDimitry Andric DRHdr.Register = DRRegister; 53505ffd83dbSDimitry Andric DRHdr.MayHaveNoName = 0; 53515ffd83dbSDimitry Andric DRHdr.OffsetInParent = DROffsetInParent; 53525ffd83dbSDimitry Andric getStreamer().emitCVDefRangeDirective(Ranges, DRHdr); 53535ffd83dbSDimitry Andric break; 53545ffd83dbSDimitry Andric } 53555ffd83dbSDimitry Andric case CVDR_DEFRANGE_REGISTER_REL: { 53565ffd83dbSDimitry Andric int64_t DRRegister; 53575ffd83dbSDimitry Andric int64_t DRFlags; 53585ffd83dbSDimitry Andric int64_t DRBasePointerOffset; 53595ffd83dbSDimitry Andric if (parseToken(AsmToken::Comma, "expected comma before register number in " 53605ffd83dbSDimitry Andric ".cv_def_range directive") || 53615ffd83dbSDimitry Andric parseAbsoluteExpression(DRRegister)) 53625ffd83dbSDimitry Andric return Error(Loc, "expected register value"); 53635ffd83dbSDimitry Andric if (parseToken( 53645ffd83dbSDimitry Andric AsmToken::Comma, 53655ffd83dbSDimitry Andric "expected comma before flag value in .cv_def_range directive") || 53665ffd83dbSDimitry Andric parseAbsoluteExpression(DRFlags)) 53675ffd83dbSDimitry Andric return Error(Loc, "expected flag value"); 53685ffd83dbSDimitry Andric if (parseToken(AsmToken::Comma, "expected comma before base pointer offset " 53695ffd83dbSDimitry Andric "in .cv_def_range directive") || 53705ffd83dbSDimitry Andric parseAbsoluteExpression(DRBasePointerOffset)) 53715ffd83dbSDimitry Andric return Error(Loc, "expected base pointer offset value"); 53725ffd83dbSDimitry Andric 53735ffd83dbSDimitry Andric codeview::DefRangeRegisterRelHeader DRHdr; 53745ffd83dbSDimitry Andric DRHdr.Register = DRRegister; 53755ffd83dbSDimitry Andric DRHdr.Flags = DRFlags; 53765ffd83dbSDimitry Andric DRHdr.BasePointerOffset = DRBasePointerOffset; 53775ffd83dbSDimitry Andric getStreamer().emitCVDefRangeDirective(Ranges, DRHdr); 53785ffd83dbSDimitry Andric break; 53795ffd83dbSDimitry Andric } 53805ffd83dbSDimitry Andric default: 53815ffd83dbSDimitry Andric return Error(Loc, "unexpected def_range type in .cv_def_range directive"); 53825ffd83dbSDimitry Andric } 53835ffd83dbSDimitry Andric return true; 53845ffd83dbSDimitry Andric } 53855ffd83dbSDimitry Andric 53865ffd83dbSDimitry Andric /// parseDirectiveCVString 53875ffd83dbSDimitry Andric /// ::= .cv_stringtable "string" 53885ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVString() { 53895ffd83dbSDimitry Andric std::string Data; 53905ffd83dbSDimitry Andric if (checkForValidSection() || parseEscapedString(Data)) 53915ffd83dbSDimitry Andric return addErrorSuffix(" in '.cv_string' directive"); 53925ffd83dbSDimitry Andric 53935ffd83dbSDimitry Andric // Put the string in the table and emit the offset. 53945ffd83dbSDimitry Andric std::pair<StringRef, unsigned> Insertion = 53955ffd83dbSDimitry Andric getCVContext().addToStringTable(Data); 53965ffd83dbSDimitry Andric getStreamer().emitIntValue(Insertion.second, 4); 53975ffd83dbSDimitry Andric return false; 53985ffd83dbSDimitry Andric } 53995ffd83dbSDimitry Andric 54005ffd83dbSDimitry Andric /// parseDirectiveCVStringTable 54015ffd83dbSDimitry Andric /// ::= .cv_stringtable 54025ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVStringTable() { 54035ffd83dbSDimitry Andric getStreamer().emitCVStringTableDirective(); 54045ffd83dbSDimitry Andric return false; 54055ffd83dbSDimitry Andric } 54065ffd83dbSDimitry Andric 54075ffd83dbSDimitry Andric /// parseDirectiveCVFileChecksums 54085ffd83dbSDimitry Andric /// ::= .cv_filechecksums 54095ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFileChecksums() { 54105ffd83dbSDimitry Andric getStreamer().emitCVFileChecksumsDirective(); 54115ffd83dbSDimitry Andric return false; 54125ffd83dbSDimitry Andric } 54135ffd83dbSDimitry Andric 54145ffd83dbSDimitry Andric /// parseDirectiveCVFileChecksumOffset 54155ffd83dbSDimitry Andric /// ::= .cv_filechecksumoffset fileno 54165ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFileChecksumOffset() { 54175ffd83dbSDimitry Andric int64_t FileNo; 54185ffd83dbSDimitry Andric if (parseIntToken(FileNo, "expected identifier in directive")) 54195ffd83dbSDimitry Andric return true; 542081ad6265SDimitry Andric if (parseEOL()) 54215ffd83dbSDimitry Andric return true; 54225ffd83dbSDimitry Andric getStreamer().emitCVFileChecksumOffsetDirective(FileNo); 54235ffd83dbSDimitry Andric return false; 54245ffd83dbSDimitry Andric } 54255ffd83dbSDimitry Andric 54265ffd83dbSDimitry Andric /// parseDirectiveCVFPOData 54275ffd83dbSDimitry Andric /// ::= .cv_fpo_data procsym 54285ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCVFPOData() { 54295ffd83dbSDimitry Andric SMLoc DirLoc = getLexer().getLoc(); 54305ffd83dbSDimitry Andric StringRef ProcName; 54315ffd83dbSDimitry Andric if (parseIdentifier(ProcName)) 54325ffd83dbSDimitry Andric return TokError("expected symbol name"); 54335ffd83dbSDimitry Andric if (parseEOL("unexpected tokens")) 54345ffd83dbSDimitry Andric return addErrorSuffix(" in '.cv_fpo_data' directive"); 54355ffd83dbSDimitry Andric MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName); 543681ad6265SDimitry Andric getStreamer().emitCVFPOData(ProcSym, DirLoc); 54375ffd83dbSDimitry Andric return false; 54385ffd83dbSDimitry Andric } 54395ffd83dbSDimitry Andric 54405ffd83dbSDimitry Andric /// parseDirectiveCFISections 54415ffd83dbSDimitry Andric /// ::= .cfi_sections section [, section] 54425ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFISections() { 54435ffd83dbSDimitry Andric StringRef Name; 54445ffd83dbSDimitry Andric bool EH = false; 54455ffd83dbSDimitry Andric bool Debug = false; 54465ffd83dbSDimitry Andric 54475ffd83dbSDimitry Andric if (parseIdentifier(Name)) 54485ffd83dbSDimitry Andric return TokError("Expected an identifier"); 54495ffd83dbSDimitry Andric 54505ffd83dbSDimitry Andric if (Name == ".eh_frame") 54515ffd83dbSDimitry Andric EH = true; 54525ffd83dbSDimitry Andric else if (Name == ".debug_frame") 54535ffd83dbSDimitry Andric Debug = true; 54545ffd83dbSDimitry Andric 54555ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Comma)) { 54565ffd83dbSDimitry Andric Lex(); 54575ffd83dbSDimitry Andric 54585ffd83dbSDimitry Andric if (parseIdentifier(Name)) 54595ffd83dbSDimitry Andric return TokError("Expected an identifier"); 54605ffd83dbSDimitry Andric 54615ffd83dbSDimitry Andric if (Name == ".eh_frame") 54625ffd83dbSDimitry Andric EH = true; 54635ffd83dbSDimitry Andric else if (Name == ".debug_frame") 54645ffd83dbSDimitry Andric Debug = true; 54655ffd83dbSDimitry Andric } 54665ffd83dbSDimitry Andric 54675ffd83dbSDimitry Andric getStreamer().emitCFISections(EH, Debug); 54685ffd83dbSDimitry Andric return false; 54695ffd83dbSDimitry Andric } 54705ffd83dbSDimitry Andric 54715ffd83dbSDimitry Andric /// parseDirectiveCFIStartProc 54725ffd83dbSDimitry Andric /// ::= .cfi_startproc [simple] 54735ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIStartProc() { 54745ffd83dbSDimitry Andric StringRef Simple; 54755ffd83dbSDimitry Andric if (!parseOptionalToken(AsmToken::EndOfStatement)) { 54765ffd83dbSDimitry Andric if (check(parseIdentifier(Simple) || Simple != "simple", 54775ffd83dbSDimitry Andric "unexpected token") || 5478*06c3fb27SDimitry Andric parseEOL()) 54795ffd83dbSDimitry Andric return addErrorSuffix(" in '.cfi_startproc' directive"); 54805ffd83dbSDimitry Andric } 54815ffd83dbSDimitry Andric 54825ffd83dbSDimitry Andric // TODO(kristina): Deal with a corner case of incorrect diagnostic context 54835ffd83dbSDimitry Andric // being produced if this directive is emitted as part of preprocessor macro 54845ffd83dbSDimitry Andric // expansion which can *ONLY* happen if Clang's cc1as is the API consumer. 54855ffd83dbSDimitry Andric // Tools like llvm-mc on the other hand are not affected by it, and report 54865ffd83dbSDimitry Andric // correct context information. 54875ffd83dbSDimitry Andric getStreamer().emitCFIStartProc(!Simple.empty(), Lexer.getLoc()); 54885ffd83dbSDimitry Andric return false; 54895ffd83dbSDimitry Andric } 54905ffd83dbSDimitry Andric 54915ffd83dbSDimitry Andric /// parseDirectiveCFIEndProc 54925ffd83dbSDimitry Andric /// ::= .cfi_endproc 54935ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIEndProc() { 54945ffd83dbSDimitry Andric getStreamer().emitCFIEndProc(); 54955ffd83dbSDimitry Andric return false; 54965ffd83dbSDimitry Andric } 54975ffd83dbSDimitry Andric 54985ffd83dbSDimitry Andric /// parse register name or number. 54995ffd83dbSDimitry Andric bool MasmParser::parseRegisterOrRegisterNumber(int64_t &Register, 55005ffd83dbSDimitry Andric SMLoc DirectiveLoc) { 5501bdd1243dSDimitry Andric MCRegister RegNo; 55025ffd83dbSDimitry Andric 55035ffd83dbSDimitry Andric if (getLexer().isNot(AsmToken::Integer)) { 5504bdd1243dSDimitry Andric if (getTargetParser().parseRegister(RegNo, DirectiveLoc, DirectiveLoc)) 55055ffd83dbSDimitry Andric return true; 55065ffd83dbSDimitry Andric Register = getContext().getRegisterInfo()->getDwarfRegNum(RegNo, true); 55075ffd83dbSDimitry Andric } else 55085ffd83dbSDimitry Andric return parseAbsoluteExpression(Register); 55095ffd83dbSDimitry Andric 55105ffd83dbSDimitry Andric return false; 55115ffd83dbSDimitry Andric } 55125ffd83dbSDimitry Andric 55135ffd83dbSDimitry Andric /// parseDirectiveCFIDefCfa 55145ffd83dbSDimitry Andric /// ::= .cfi_def_cfa register, offset 55155ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) { 55165ffd83dbSDimitry Andric int64_t Register = 0, Offset = 0; 55175ffd83dbSDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || 55185ffd83dbSDimitry Andric parseToken(AsmToken::Comma, "unexpected token in directive") || 55195ffd83dbSDimitry Andric parseAbsoluteExpression(Offset)) 55205ffd83dbSDimitry Andric return true; 55215ffd83dbSDimitry Andric 55225ffd83dbSDimitry Andric getStreamer().emitCFIDefCfa(Register, Offset); 55235ffd83dbSDimitry Andric return false; 55245ffd83dbSDimitry Andric } 55255ffd83dbSDimitry Andric 55265ffd83dbSDimitry Andric /// parseDirectiveCFIDefCfaOffset 55275ffd83dbSDimitry Andric /// ::= .cfi_def_cfa_offset offset 5528*06c3fb27SDimitry Andric bool MasmParser::parseDirectiveCFIDefCfaOffset(SMLoc DirectiveLoc) { 55295ffd83dbSDimitry Andric int64_t Offset = 0; 55305ffd83dbSDimitry Andric if (parseAbsoluteExpression(Offset)) 55315ffd83dbSDimitry Andric return true; 55325ffd83dbSDimitry Andric 5533*06c3fb27SDimitry Andric getStreamer().emitCFIDefCfaOffset(Offset, DirectiveLoc); 55345ffd83dbSDimitry Andric return false; 55355ffd83dbSDimitry Andric } 55365ffd83dbSDimitry Andric 55375ffd83dbSDimitry Andric /// parseDirectiveCFIRegister 55385ffd83dbSDimitry Andric /// ::= .cfi_register register, register 55395ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) { 55405ffd83dbSDimitry Andric int64_t Register1 = 0, Register2 = 0; 55415ffd83dbSDimitry Andric if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) || 55425ffd83dbSDimitry Andric parseToken(AsmToken::Comma, "unexpected token in directive") || 55435ffd83dbSDimitry Andric parseRegisterOrRegisterNumber(Register2, DirectiveLoc)) 55445ffd83dbSDimitry Andric return true; 55455ffd83dbSDimitry Andric 5546*06c3fb27SDimitry Andric getStreamer().emitCFIRegister(Register1, Register2, DirectiveLoc); 55475ffd83dbSDimitry Andric return false; 55485ffd83dbSDimitry Andric } 55495ffd83dbSDimitry Andric 55505ffd83dbSDimitry Andric /// parseDirectiveCFIWindowSave 55515ffd83dbSDimitry Andric /// ::= .cfi_window_save 5552*06c3fb27SDimitry Andric bool MasmParser::parseDirectiveCFIWindowSave(SMLoc DirectiveLoc) { 5553*06c3fb27SDimitry Andric getStreamer().emitCFIWindowSave(DirectiveLoc); 55545ffd83dbSDimitry Andric return false; 55555ffd83dbSDimitry Andric } 55565ffd83dbSDimitry Andric 55575ffd83dbSDimitry Andric /// parseDirectiveCFIAdjustCfaOffset 55585ffd83dbSDimitry Andric /// ::= .cfi_adjust_cfa_offset adjustment 5559*06c3fb27SDimitry Andric bool MasmParser::parseDirectiveCFIAdjustCfaOffset(SMLoc DirectiveLoc) { 55605ffd83dbSDimitry Andric int64_t Adjustment = 0; 55615ffd83dbSDimitry Andric if (parseAbsoluteExpression(Adjustment)) 55625ffd83dbSDimitry Andric return true; 55635ffd83dbSDimitry Andric 5564*06c3fb27SDimitry Andric getStreamer().emitCFIAdjustCfaOffset(Adjustment, DirectiveLoc); 55655ffd83dbSDimitry Andric return false; 55665ffd83dbSDimitry Andric } 55675ffd83dbSDimitry Andric 55685ffd83dbSDimitry Andric /// parseDirectiveCFIDefCfaRegister 55695ffd83dbSDimitry Andric /// ::= .cfi_def_cfa_register register 55705ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) { 55715ffd83dbSDimitry Andric int64_t Register = 0; 55725ffd83dbSDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) 55735ffd83dbSDimitry Andric return true; 55745ffd83dbSDimitry Andric 55755ffd83dbSDimitry Andric getStreamer().emitCFIDefCfaRegister(Register); 55765ffd83dbSDimitry Andric return false; 55775ffd83dbSDimitry Andric } 55785ffd83dbSDimitry Andric 55795ffd83dbSDimitry Andric /// parseDirectiveCFIOffset 55805ffd83dbSDimitry Andric /// ::= .cfi_offset register, offset 55815ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) { 55825ffd83dbSDimitry Andric int64_t Register = 0; 55835ffd83dbSDimitry Andric int64_t Offset = 0; 55845ffd83dbSDimitry Andric 55855ffd83dbSDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || 55865ffd83dbSDimitry Andric parseToken(AsmToken::Comma, "unexpected token in directive") || 55875ffd83dbSDimitry Andric parseAbsoluteExpression(Offset)) 55885ffd83dbSDimitry Andric return true; 55895ffd83dbSDimitry Andric 55905ffd83dbSDimitry Andric getStreamer().emitCFIOffset(Register, Offset); 55915ffd83dbSDimitry Andric return false; 55925ffd83dbSDimitry Andric } 55935ffd83dbSDimitry Andric 55945ffd83dbSDimitry Andric /// parseDirectiveCFIRelOffset 55955ffd83dbSDimitry Andric /// ::= .cfi_rel_offset register, offset 55965ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) { 55975ffd83dbSDimitry Andric int64_t Register = 0, Offset = 0; 55985ffd83dbSDimitry Andric 55995ffd83dbSDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) || 56005ffd83dbSDimitry Andric parseToken(AsmToken::Comma, "unexpected token in directive") || 56015ffd83dbSDimitry Andric parseAbsoluteExpression(Offset)) 56025ffd83dbSDimitry Andric return true; 56035ffd83dbSDimitry Andric 5604*06c3fb27SDimitry Andric getStreamer().emitCFIRelOffset(Register, Offset, DirectiveLoc); 56055ffd83dbSDimitry Andric return false; 56065ffd83dbSDimitry Andric } 56075ffd83dbSDimitry Andric 56085ffd83dbSDimitry Andric static bool isValidEncoding(int64_t Encoding) { 56095ffd83dbSDimitry Andric if (Encoding & ~0xff) 56105ffd83dbSDimitry Andric return false; 56115ffd83dbSDimitry Andric 56125ffd83dbSDimitry Andric if (Encoding == dwarf::DW_EH_PE_omit) 56135ffd83dbSDimitry Andric return true; 56145ffd83dbSDimitry Andric 56155ffd83dbSDimitry Andric const unsigned Format = Encoding & 0xf; 56165ffd83dbSDimitry Andric if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 && 56175ffd83dbSDimitry Andric Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 && 56185ffd83dbSDimitry Andric Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 && 56195ffd83dbSDimitry Andric Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed) 56205ffd83dbSDimitry Andric return false; 56215ffd83dbSDimitry Andric 56225ffd83dbSDimitry Andric const unsigned Application = Encoding & 0x70; 56235ffd83dbSDimitry Andric if (Application != dwarf::DW_EH_PE_absptr && 56245ffd83dbSDimitry Andric Application != dwarf::DW_EH_PE_pcrel) 56255ffd83dbSDimitry Andric return false; 56265ffd83dbSDimitry Andric 56275ffd83dbSDimitry Andric return true; 56285ffd83dbSDimitry Andric } 56295ffd83dbSDimitry Andric 56305ffd83dbSDimitry Andric /// parseDirectiveCFIPersonalityOrLsda 56315ffd83dbSDimitry Andric /// IsPersonality true for cfi_personality, false for cfi_lsda 56325ffd83dbSDimitry Andric /// ::= .cfi_personality encoding, [symbol_name] 56335ffd83dbSDimitry Andric /// ::= .cfi_lsda encoding, [symbol_name] 56345ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) { 56355ffd83dbSDimitry Andric int64_t Encoding = 0; 56365ffd83dbSDimitry Andric if (parseAbsoluteExpression(Encoding)) 56375ffd83dbSDimitry Andric return true; 56385ffd83dbSDimitry Andric if (Encoding == dwarf::DW_EH_PE_omit) 56395ffd83dbSDimitry Andric return false; 56405ffd83dbSDimitry Andric 56415ffd83dbSDimitry Andric StringRef Name; 56425ffd83dbSDimitry Andric if (check(!isValidEncoding(Encoding), "unsupported encoding.") || 56435ffd83dbSDimitry Andric parseToken(AsmToken::Comma, "unexpected token in directive") || 56445ffd83dbSDimitry Andric check(parseIdentifier(Name), "expected identifier in directive")) 56455ffd83dbSDimitry Andric return true; 56465ffd83dbSDimitry Andric 56475ffd83dbSDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 56485ffd83dbSDimitry Andric 56495ffd83dbSDimitry Andric if (IsPersonality) 56505ffd83dbSDimitry Andric getStreamer().emitCFIPersonality(Sym, Encoding); 56515ffd83dbSDimitry Andric else 56525ffd83dbSDimitry Andric getStreamer().emitCFILsda(Sym, Encoding); 56535ffd83dbSDimitry Andric return false; 56545ffd83dbSDimitry Andric } 56555ffd83dbSDimitry Andric 56565ffd83dbSDimitry Andric /// parseDirectiveCFIRememberState 56575ffd83dbSDimitry Andric /// ::= .cfi_remember_state 5658*06c3fb27SDimitry Andric bool MasmParser::parseDirectiveCFIRememberState(SMLoc DirectiveLoc) { 5659*06c3fb27SDimitry Andric getStreamer().emitCFIRememberState(DirectiveLoc); 56605ffd83dbSDimitry Andric return false; 56615ffd83dbSDimitry Andric } 56625ffd83dbSDimitry Andric 56635ffd83dbSDimitry Andric /// parseDirectiveCFIRestoreState 56645ffd83dbSDimitry Andric /// ::= .cfi_remember_state 5665*06c3fb27SDimitry Andric bool MasmParser::parseDirectiveCFIRestoreState(SMLoc DirectiveLoc) { 5666*06c3fb27SDimitry Andric getStreamer().emitCFIRestoreState(DirectiveLoc); 56675ffd83dbSDimitry Andric return false; 56685ffd83dbSDimitry Andric } 56695ffd83dbSDimitry Andric 56705ffd83dbSDimitry Andric /// parseDirectiveCFISameValue 56715ffd83dbSDimitry Andric /// ::= .cfi_same_value register 56725ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) { 56735ffd83dbSDimitry Andric int64_t Register = 0; 56745ffd83dbSDimitry Andric 56755ffd83dbSDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) 56765ffd83dbSDimitry Andric return true; 56775ffd83dbSDimitry Andric 5678*06c3fb27SDimitry Andric getStreamer().emitCFISameValue(Register, DirectiveLoc); 56795ffd83dbSDimitry Andric return false; 56805ffd83dbSDimitry Andric } 56815ffd83dbSDimitry Andric 56825ffd83dbSDimitry Andric /// parseDirectiveCFIRestore 56835ffd83dbSDimitry Andric /// ::= .cfi_restore register 56845ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) { 56855ffd83dbSDimitry Andric int64_t Register = 0; 56865ffd83dbSDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) 56875ffd83dbSDimitry Andric return true; 56885ffd83dbSDimitry Andric 56895ffd83dbSDimitry Andric getStreamer().emitCFIRestore(Register); 56905ffd83dbSDimitry Andric return false; 56915ffd83dbSDimitry Andric } 56925ffd83dbSDimitry Andric 56935ffd83dbSDimitry Andric /// parseDirectiveCFIEscape 56945ffd83dbSDimitry Andric /// ::= .cfi_escape expression[,...] 5695*06c3fb27SDimitry Andric bool MasmParser::parseDirectiveCFIEscape(SMLoc DirectiveLoc) { 56965ffd83dbSDimitry Andric std::string Values; 56975ffd83dbSDimitry Andric int64_t CurrValue; 56985ffd83dbSDimitry Andric if (parseAbsoluteExpression(CurrValue)) 56995ffd83dbSDimitry Andric return true; 57005ffd83dbSDimitry Andric 57015ffd83dbSDimitry Andric Values.push_back((uint8_t)CurrValue); 57025ffd83dbSDimitry Andric 57035ffd83dbSDimitry Andric while (getLexer().is(AsmToken::Comma)) { 57045ffd83dbSDimitry Andric Lex(); 57055ffd83dbSDimitry Andric 57065ffd83dbSDimitry Andric if (parseAbsoluteExpression(CurrValue)) 57075ffd83dbSDimitry Andric return true; 57085ffd83dbSDimitry Andric 57095ffd83dbSDimitry Andric Values.push_back((uint8_t)CurrValue); 57105ffd83dbSDimitry Andric } 57115ffd83dbSDimitry Andric 5712*06c3fb27SDimitry Andric getStreamer().emitCFIEscape(Values, DirectiveLoc); 57135ffd83dbSDimitry Andric return false; 57145ffd83dbSDimitry Andric } 57155ffd83dbSDimitry Andric 57165ffd83dbSDimitry Andric /// parseDirectiveCFIReturnColumn 57175ffd83dbSDimitry Andric /// ::= .cfi_return_column register 57185ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) { 57195ffd83dbSDimitry Andric int64_t Register = 0; 57205ffd83dbSDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) 57215ffd83dbSDimitry Andric return true; 57225ffd83dbSDimitry Andric getStreamer().emitCFIReturnColumn(Register); 57235ffd83dbSDimitry Andric return false; 57245ffd83dbSDimitry Andric } 57255ffd83dbSDimitry Andric 57265ffd83dbSDimitry Andric /// parseDirectiveCFISignalFrame 57275ffd83dbSDimitry Andric /// ::= .cfi_signal_frame 57285ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFISignalFrame() { 572981ad6265SDimitry Andric if (parseEOL()) 57305ffd83dbSDimitry Andric return true; 57315ffd83dbSDimitry Andric 57325ffd83dbSDimitry Andric getStreamer().emitCFISignalFrame(); 57335ffd83dbSDimitry Andric return false; 57345ffd83dbSDimitry Andric } 57355ffd83dbSDimitry Andric 57365ffd83dbSDimitry Andric /// parseDirectiveCFIUndefined 57375ffd83dbSDimitry Andric /// ::= .cfi_undefined register 57385ffd83dbSDimitry Andric bool MasmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) { 57395ffd83dbSDimitry Andric int64_t Register = 0; 57405ffd83dbSDimitry Andric 57415ffd83dbSDimitry Andric if (parseRegisterOrRegisterNumber(Register, DirectiveLoc)) 57425ffd83dbSDimitry Andric return true; 57435ffd83dbSDimitry Andric 57445ffd83dbSDimitry Andric getStreamer().emitCFIUndefined(Register); 57455ffd83dbSDimitry Andric return false; 57465ffd83dbSDimitry Andric } 57475ffd83dbSDimitry Andric 57485ffd83dbSDimitry Andric /// parseDirectiveMacro 5749e8d8bef9SDimitry Andric /// ::= name macro [parameters] 5750e8d8bef9SDimitry Andric /// ["LOCAL" identifiers] 5751e8d8bef9SDimitry Andric /// parameters ::= parameter [, parameter]* 5752e8d8bef9SDimitry Andric /// parameter ::= name ":" qualifier 5753e8d8bef9SDimitry Andric /// qualifier ::= "req" | "vararg" | "=" macro_argument 5754e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) { 57555ffd83dbSDimitry Andric MCAsmMacroParameters Parameters; 57565ffd83dbSDimitry Andric while (getLexer().isNot(AsmToken::EndOfStatement)) { 57575ffd83dbSDimitry Andric if (!Parameters.empty() && Parameters.back().Vararg) 57585ffd83dbSDimitry Andric return Error(Lexer.getLoc(), 57595ffd83dbSDimitry Andric "Vararg parameter '" + Parameters.back().Name + 5760e8d8bef9SDimitry Andric "' should be last in the list of parameters"); 57615ffd83dbSDimitry Andric 57625ffd83dbSDimitry Andric MCAsmMacroParameter Parameter; 57635ffd83dbSDimitry Andric if (parseIdentifier(Parameter.Name)) 5764e8d8bef9SDimitry Andric return TokError("expected identifier in 'macro' directive"); 57655ffd83dbSDimitry Andric 57665ffd83dbSDimitry Andric // Emit an error if two (or more) named parameters share the same name. 57675ffd83dbSDimitry Andric for (const MCAsmMacroParameter& CurrParam : Parameters) 5768fe6060f1SDimitry Andric if (CurrParam.Name.equals_insensitive(Parameter.Name)) 57695ffd83dbSDimitry Andric return TokError("macro '" + Name + "' has multiple parameters" 57705ffd83dbSDimitry Andric " named '" + Parameter.Name + "'"); 57715ffd83dbSDimitry Andric 57725ffd83dbSDimitry Andric if (Lexer.is(AsmToken::Colon)) { 57735ffd83dbSDimitry Andric Lex(); // consume ':' 57745ffd83dbSDimitry Andric 5775e8d8bef9SDimitry Andric if (parseOptionalToken(AsmToken::Equal)) { 5776e8d8bef9SDimitry Andric // Default value 5777e8d8bef9SDimitry Andric SMLoc ParamLoc; 5778e8d8bef9SDimitry Andric 5779e8d8bef9SDimitry Andric ParamLoc = Lexer.getLoc(); 5780e8d8bef9SDimitry Andric if (parseMacroArgument(nullptr, Parameter.Value)) 5781e8d8bef9SDimitry Andric return true; 5782e8d8bef9SDimitry Andric } else { 57835ffd83dbSDimitry Andric SMLoc QualLoc; 57845ffd83dbSDimitry Andric StringRef Qualifier; 57855ffd83dbSDimitry Andric 57865ffd83dbSDimitry Andric QualLoc = Lexer.getLoc(); 57875ffd83dbSDimitry Andric if (parseIdentifier(Qualifier)) 57885ffd83dbSDimitry Andric return Error(QualLoc, "missing parameter qualifier for " 5789e8d8bef9SDimitry Andric "'" + 5790e8d8bef9SDimitry Andric Parameter.Name + "' in macro '" + Name + 5791e8d8bef9SDimitry Andric "'"); 57925ffd83dbSDimitry Andric 5793fe6060f1SDimitry Andric if (Qualifier.equals_insensitive("req")) 57945ffd83dbSDimitry Andric Parameter.Required = true; 5795fe6060f1SDimitry Andric else if (Qualifier.equals_insensitive("vararg")) 57965ffd83dbSDimitry Andric Parameter.Vararg = true; 57975ffd83dbSDimitry Andric else 5798e8d8bef9SDimitry Andric return Error(QualLoc, 5799e8d8bef9SDimitry Andric Qualifier + " is not a valid parameter qualifier for '" + 5800e8d8bef9SDimitry Andric Parameter.Name + "' in macro '" + Name + "'"); 58015ffd83dbSDimitry Andric } 58025ffd83dbSDimitry Andric } 58035ffd83dbSDimitry Andric 58045ffd83dbSDimitry Andric Parameters.push_back(std::move(Parameter)); 58055ffd83dbSDimitry Andric 58065ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Comma)) 58075ffd83dbSDimitry Andric Lex(); 58085ffd83dbSDimitry Andric } 58095ffd83dbSDimitry Andric 58105ffd83dbSDimitry Andric // Eat just the end of statement. 58115ffd83dbSDimitry Andric Lexer.Lex(); 58125ffd83dbSDimitry Andric 5813e8d8bef9SDimitry Andric std::vector<std::string> Locals; 5814e8d8bef9SDimitry Andric if (getTok().is(AsmToken::Identifier) && 5815fe6060f1SDimitry Andric getTok().getIdentifier().equals_insensitive("local")) { 5816e8d8bef9SDimitry Andric Lex(); // Eat the LOCAL directive. 5817e8d8bef9SDimitry Andric 5818e8d8bef9SDimitry Andric StringRef ID; 5819e8d8bef9SDimitry Andric while (true) { 5820e8d8bef9SDimitry Andric if (parseIdentifier(ID)) 5821e8d8bef9SDimitry Andric return true; 5822e8d8bef9SDimitry Andric Locals.push_back(ID.lower()); 5823e8d8bef9SDimitry Andric 5824e8d8bef9SDimitry Andric // If we see a comma, continue (and allow line continuation). 5825e8d8bef9SDimitry Andric if (!parseOptionalToken(AsmToken::Comma)) 5826e8d8bef9SDimitry Andric break; 5827e8d8bef9SDimitry Andric parseOptionalToken(AsmToken::EndOfStatement); 5828e8d8bef9SDimitry Andric } 5829e8d8bef9SDimitry Andric } 5830e8d8bef9SDimitry Andric 58315ffd83dbSDimitry Andric // Consuming deferred text, so use Lexer.Lex to ignore Lexing Errors. 58325ffd83dbSDimitry Andric AsmToken EndToken, StartToken = getTok(); 58335ffd83dbSDimitry Andric unsigned MacroDepth = 0; 5834e8d8bef9SDimitry Andric bool IsMacroFunction = false; 58355ffd83dbSDimitry Andric // Lex the macro definition. 58365ffd83dbSDimitry Andric while (true) { 58375ffd83dbSDimitry Andric // Ignore Lexing errors in macros. 58385ffd83dbSDimitry Andric while (Lexer.is(AsmToken::Error)) { 58395ffd83dbSDimitry Andric Lexer.Lex(); 58405ffd83dbSDimitry Andric } 58415ffd83dbSDimitry Andric 58425ffd83dbSDimitry Andric // Check whether we have reached the end of the file. 58435ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Eof)) 5844e8d8bef9SDimitry Andric return Error(NameLoc, "no matching 'endm' in definition"); 58455ffd83dbSDimitry Andric 5846e8d8bef9SDimitry Andric // Otherwise, check whether we have reached the 'endm'... and determine if 5847e8d8bef9SDimitry Andric // this is a macro function. 58485ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Identifier)) { 5849fe6060f1SDimitry Andric if (getTok().getIdentifier().equals_insensitive("endm")) { 58505ffd83dbSDimitry Andric if (MacroDepth == 0) { // Outermost macro. 58515ffd83dbSDimitry Andric EndToken = getTok(); 58525ffd83dbSDimitry Andric Lexer.Lex(); 58535ffd83dbSDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 58545ffd83dbSDimitry Andric return TokError("unexpected token in '" + EndToken.getIdentifier() + 58555ffd83dbSDimitry Andric "' directive"); 58565ffd83dbSDimitry Andric break; 58575ffd83dbSDimitry Andric } else { 58585ffd83dbSDimitry Andric // Otherwise we just found the end of an inner macro. 58595ffd83dbSDimitry Andric --MacroDepth; 58605ffd83dbSDimitry Andric } 5861fe6060f1SDimitry Andric } else if (getTok().getIdentifier().equals_insensitive("exitm")) { 5862fe6060f1SDimitry Andric if (MacroDepth == 0 && peekTok().isNot(AsmToken::EndOfStatement)) { 5863e8d8bef9SDimitry Andric IsMacroFunction = true; 5864e8d8bef9SDimitry Andric } 5865e8d8bef9SDimitry Andric } else if (isMacroLikeDirective()) { 5866e8d8bef9SDimitry Andric // We allow nested macros. Those aren't instantiated until the 5867e8d8bef9SDimitry Andric // outermost macro is expanded so just ignore them for now. 58685ffd83dbSDimitry Andric ++MacroDepth; 58695ffd83dbSDimitry Andric } 58705ffd83dbSDimitry Andric } 58715ffd83dbSDimitry Andric 58725ffd83dbSDimitry Andric // Otherwise, scan til the end of the statement. 58735ffd83dbSDimitry Andric eatToEndOfStatement(); 58745ffd83dbSDimitry Andric } 58755ffd83dbSDimitry Andric 5876e8d8bef9SDimitry Andric if (getContext().lookupMacro(Name.lower())) { 5877e8d8bef9SDimitry Andric return Error(NameLoc, "macro '" + Name + "' is already defined"); 58785ffd83dbSDimitry Andric } 58795ffd83dbSDimitry Andric 58805ffd83dbSDimitry Andric const char *BodyStart = StartToken.getLoc().getPointer(); 58815ffd83dbSDimitry Andric const char *BodyEnd = EndToken.getLoc().getPointer(); 58825ffd83dbSDimitry Andric StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); 5883e8d8bef9SDimitry Andric MCAsmMacro Macro(Name, Body, std::move(Parameters), std::move(Locals), 5884e8d8bef9SDimitry Andric IsMacroFunction); 58855ffd83dbSDimitry Andric DEBUG_WITH_TYPE("asm-macros", dbgs() << "Defining new macro:\n"; 58865ffd83dbSDimitry Andric Macro.dump()); 5887fe6060f1SDimitry Andric getContext().defineMacro(Name.lower(), std::move(Macro)); 58885ffd83dbSDimitry Andric return false; 58895ffd83dbSDimitry Andric } 58905ffd83dbSDimitry Andric 58915ffd83dbSDimitry Andric /// parseDirectiveExitMacro 5892e8d8bef9SDimitry Andric /// ::= "exitm" [textitem] 5893e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc, 5894e8d8bef9SDimitry Andric StringRef Directive, 5895e8d8bef9SDimitry Andric std::string &Value) { 5896e8d8bef9SDimitry Andric SMLoc EndLoc = getTok().getLoc(); 5897e8d8bef9SDimitry Andric if (getTok().isNot(AsmToken::EndOfStatement) && parseTextItem(Value)) 5898e8d8bef9SDimitry Andric return Error(EndLoc, 5899e8d8bef9SDimitry Andric "unable to parse text item in '" + Directive + "' directive"); 5900e8d8bef9SDimitry Andric eatToEndOfStatement(); 59015ffd83dbSDimitry Andric 59025ffd83dbSDimitry Andric if (!isInsideMacroInstantiation()) 59035ffd83dbSDimitry Andric return TokError("unexpected '" + Directive + "' in file, " 59045ffd83dbSDimitry Andric "no current macro definition"); 59055ffd83dbSDimitry Andric 59065ffd83dbSDimitry Andric // Exit all conditionals that are active in the current macro. 59075ffd83dbSDimitry Andric while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) { 59085ffd83dbSDimitry Andric TheCondState = TheCondStack.back(); 59095ffd83dbSDimitry Andric TheCondStack.pop_back(); 59105ffd83dbSDimitry Andric } 59115ffd83dbSDimitry Andric 59125ffd83dbSDimitry Andric handleMacroExit(); 59135ffd83dbSDimitry Andric return false; 59145ffd83dbSDimitry Andric } 59155ffd83dbSDimitry Andric 59165ffd83dbSDimitry Andric /// parseDirectiveEndMacro 5917e8d8bef9SDimitry Andric /// ::= endm 59185ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEndMacro(StringRef Directive) { 59195ffd83dbSDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 59205ffd83dbSDimitry Andric return TokError("unexpected token in '" + Directive + "' directive"); 59215ffd83dbSDimitry Andric 59225ffd83dbSDimitry Andric // If we are inside a macro instantiation, terminate the current 59235ffd83dbSDimitry Andric // instantiation. 59245ffd83dbSDimitry Andric if (isInsideMacroInstantiation()) { 59255ffd83dbSDimitry Andric handleMacroExit(); 59265ffd83dbSDimitry Andric return false; 59275ffd83dbSDimitry Andric } 59285ffd83dbSDimitry Andric 59295ffd83dbSDimitry Andric // Otherwise, this .endmacro is a stray entry in the file; well formed 59305ffd83dbSDimitry Andric // .endmacro directives are handled during the macro definition parsing. 59315ffd83dbSDimitry Andric return TokError("unexpected '" + Directive + "' in file, " 59325ffd83dbSDimitry Andric "no current macro definition"); 59335ffd83dbSDimitry Andric } 59345ffd83dbSDimitry Andric 59355ffd83dbSDimitry Andric /// parseDirectivePurgeMacro 5936e8d8bef9SDimitry Andric /// ::= purge identifier ( , identifier )* 59375ffd83dbSDimitry Andric bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) { 59385ffd83dbSDimitry Andric StringRef Name; 5939e8d8bef9SDimitry Andric while (true) { 5940e8d8bef9SDimitry Andric SMLoc NameLoc; 5941e8d8bef9SDimitry Andric if (parseTokenLoc(NameLoc) || 5942e8d8bef9SDimitry Andric check(parseIdentifier(Name), NameLoc, 5943e8d8bef9SDimitry Andric "expected identifier in 'purge' directive")) 59445ffd83dbSDimitry Andric return true; 59455ffd83dbSDimitry Andric 59465ffd83dbSDimitry Andric DEBUG_WITH_TYPE("asm-macros", dbgs() 59475ffd83dbSDimitry Andric << "Un-defining macro: " << Name << "\n"); 5948e8d8bef9SDimitry Andric if (!getContext().lookupMacro(Name.lower())) 5949e8d8bef9SDimitry Andric return Error(NameLoc, "macro '" + Name + "' is not defined"); 5950e8d8bef9SDimitry Andric getContext().undefineMacro(Name.lower()); 5951e8d8bef9SDimitry Andric 5952e8d8bef9SDimitry Andric if (!parseOptionalToken(AsmToken::Comma)) 5953e8d8bef9SDimitry Andric break; 5954e8d8bef9SDimitry Andric parseOptionalToken(AsmToken::EndOfStatement); 5955e8d8bef9SDimitry Andric } 5956e8d8bef9SDimitry Andric 59575ffd83dbSDimitry Andric return false; 59585ffd83dbSDimitry Andric } 59595ffd83dbSDimitry Andric 596081ad6265SDimitry Andric bool MasmParser::parseDirectiveExtern() { 596181ad6265SDimitry Andric // .extern is the default - but we still need to take any provided type info. 596281ad6265SDimitry Andric auto parseOp = [&]() -> bool { 596381ad6265SDimitry Andric StringRef Name; 596481ad6265SDimitry Andric SMLoc NameLoc = getTok().getLoc(); 596581ad6265SDimitry Andric if (parseIdentifier(Name)) 596681ad6265SDimitry Andric return Error(NameLoc, "expected name"); 596781ad6265SDimitry Andric if (parseToken(AsmToken::Colon)) 596881ad6265SDimitry Andric return true; 596981ad6265SDimitry Andric 597081ad6265SDimitry Andric StringRef TypeName; 597181ad6265SDimitry Andric SMLoc TypeLoc = getTok().getLoc(); 597281ad6265SDimitry Andric if (parseIdentifier(TypeName)) 597381ad6265SDimitry Andric return Error(TypeLoc, "expected type"); 597481ad6265SDimitry Andric if (!TypeName.equals_insensitive("proc")) { 597581ad6265SDimitry Andric AsmTypeInfo Type; 597681ad6265SDimitry Andric if (lookUpType(TypeName, Type)) 597781ad6265SDimitry Andric return Error(TypeLoc, "unrecognized type"); 597881ad6265SDimitry Andric KnownType[Name.lower()] = Type; 597981ad6265SDimitry Andric } 598081ad6265SDimitry Andric 598181ad6265SDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 598281ad6265SDimitry Andric Sym->setExternal(true); 598381ad6265SDimitry Andric getStreamer().emitSymbolAttribute(Sym, MCSA_Extern); 598481ad6265SDimitry Andric 598581ad6265SDimitry Andric return false; 598681ad6265SDimitry Andric }; 598781ad6265SDimitry Andric 598881ad6265SDimitry Andric if (parseMany(parseOp)) 598981ad6265SDimitry Andric return addErrorSuffix(" in directive 'extern'"); 599081ad6265SDimitry Andric return false; 599181ad6265SDimitry Andric } 599281ad6265SDimitry Andric 59935ffd83dbSDimitry Andric /// parseDirectiveSymbolAttribute 59945ffd83dbSDimitry Andric /// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ] 59955ffd83dbSDimitry Andric bool MasmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) { 59965ffd83dbSDimitry Andric auto parseOp = [&]() -> bool { 59975ffd83dbSDimitry Andric StringRef Name; 59985ffd83dbSDimitry Andric SMLoc Loc = getTok().getLoc(); 59995ffd83dbSDimitry Andric if (parseIdentifier(Name)) 60005ffd83dbSDimitry Andric return Error(Loc, "expected identifier"); 60015ffd83dbSDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 60025ffd83dbSDimitry Andric 60035ffd83dbSDimitry Andric // Assembler local symbols don't make any sense here. Complain loudly. 60045ffd83dbSDimitry Andric if (Sym->isTemporary()) 60055ffd83dbSDimitry Andric return Error(Loc, "non-local symbol required"); 60065ffd83dbSDimitry Andric 60075ffd83dbSDimitry Andric if (!getStreamer().emitSymbolAttribute(Sym, Attr)) 60085ffd83dbSDimitry Andric return Error(Loc, "unable to emit symbol attribute"); 60095ffd83dbSDimitry Andric return false; 60105ffd83dbSDimitry Andric }; 60115ffd83dbSDimitry Andric 60125ffd83dbSDimitry Andric if (parseMany(parseOp)) 60135ffd83dbSDimitry Andric return addErrorSuffix(" in directive"); 60145ffd83dbSDimitry Andric return false; 60155ffd83dbSDimitry Andric } 60165ffd83dbSDimitry Andric 60175ffd83dbSDimitry Andric /// parseDirectiveComm 60185ffd83dbSDimitry Andric /// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ] 60195ffd83dbSDimitry Andric bool MasmParser::parseDirectiveComm(bool IsLocal) { 60205ffd83dbSDimitry Andric if (checkForValidSection()) 60215ffd83dbSDimitry Andric return true; 60225ffd83dbSDimitry Andric 60235ffd83dbSDimitry Andric SMLoc IDLoc = getLexer().getLoc(); 60245ffd83dbSDimitry Andric StringRef Name; 60255ffd83dbSDimitry Andric if (parseIdentifier(Name)) 60265ffd83dbSDimitry Andric return TokError("expected identifier in directive"); 60275ffd83dbSDimitry Andric 60285ffd83dbSDimitry Andric // Handle the identifier as the key symbol. 60295ffd83dbSDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 60305ffd83dbSDimitry Andric 60315ffd83dbSDimitry Andric if (getLexer().isNot(AsmToken::Comma)) 60325ffd83dbSDimitry Andric return TokError("unexpected token in directive"); 60335ffd83dbSDimitry Andric Lex(); 60345ffd83dbSDimitry Andric 60355ffd83dbSDimitry Andric int64_t Size; 60365ffd83dbSDimitry Andric SMLoc SizeLoc = getLexer().getLoc(); 60375ffd83dbSDimitry Andric if (parseAbsoluteExpression(Size)) 60385ffd83dbSDimitry Andric return true; 60395ffd83dbSDimitry Andric 60405ffd83dbSDimitry Andric int64_t Pow2Alignment = 0; 60415ffd83dbSDimitry Andric SMLoc Pow2AlignmentLoc; 60425ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Comma)) { 60435ffd83dbSDimitry Andric Lex(); 60445ffd83dbSDimitry Andric Pow2AlignmentLoc = getLexer().getLoc(); 60455ffd83dbSDimitry Andric if (parseAbsoluteExpression(Pow2Alignment)) 60465ffd83dbSDimitry Andric return true; 60475ffd83dbSDimitry Andric 60485ffd83dbSDimitry Andric LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType(); 60495ffd83dbSDimitry Andric if (IsLocal && LCOMM == LCOMM::NoAlignment) 60505ffd83dbSDimitry Andric return Error(Pow2AlignmentLoc, "alignment not supported on this target"); 60515ffd83dbSDimitry Andric 60525ffd83dbSDimitry Andric // If this target takes alignments in bytes (not log) validate and convert. 60535ffd83dbSDimitry Andric if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) || 60545ffd83dbSDimitry Andric (IsLocal && LCOMM == LCOMM::ByteAlignment)) { 60555ffd83dbSDimitry Andric if (!isPowerOf2_64(Pow2Alignment)) 60565ffd83dbSDimitry Andric return Error(Pow2AlignmentLoc, "alignment must be a power of 2"); 60575ffd83dbSDimitry Andric Pow2Alignment = Log2_64(Pow2Alignment); 60585ffd83dbSDimitry Andric } 60595ffd83dbSDimitry Andric } 60605ffd83dbSDimitry Andric 606181ad6265SDimitry Andric if (parseEOL()) 60625ffd83dbSDimitry Andric return true; 60635ffd83dbSDimitry Andric 60645ffd83dbSDimitry Andric // NOTE: a size of zero for a .comm should create a undefined symbol 60655ffd83dbSDimitry Andric // but a size of .lcomm creates a bss symbol of size zero. 60665ffd83dbSDimitry Andric if (Size < 0) 60675ffd83dbSDimitry Andric return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't " 60685ffd83dbSDimitry Andric "be less than zero"); 60695ffd83dbSDimitry Andric 60705ffd83dbSDimitry Andric // NOTE: The alignment in the directive is a power of 2 value, the assembler 60715ffd83dbSDimitry Andric // may internally end up wanting an alignment in bytes. 60725ffd83dbSDimitry Andric // FIXME: Diagnose overflow. 60735ffd83dbSDimitry Andric if (Pow2Alignment < 0) 60745ffd83dbSDimitry Andric return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive " 60755ffd83dbSDimitry Andric "alignment, can't be less than zero"); 60765ffd83dbSDimitry Andric 60775ffd83dbSDimitry Andric Sym->redefineIfPossible(); 60785ffd83dbSDimitry Andric if (!Sym->isUndefined()) 60795ffd83dbSDimitry Andric return Error(IDLoc, "invalid symbol redefinition"); 60805ffd83dbSDimitry Andric 60815ffd83dbSDimitry Andric // Create the Symbol as a common or local common with Size and Pow2Alignment. 60825ffd83dbSDimitry Andric if (IsLocal) { 6083bdd1243dSDimitry Andric getStreamer().emitLocalCommonSymbol(Sym, Size, 6084bdd1243dSDimitry Andric Align(1ULL << Pow2Alignment)); 60855ffd83dbSDimitry Andric return false; 60865ffd83dbSDimitry Andric } 60875ffd83dbSDimitry Andric 6088bdd1243dSDimitry Andric getStreamer().emitCommonSymbol(Sym, Size, Align(1ULL << Pow2Alignment)); 60895ffd83dbSDimitry Andric return false; 60905ffd83dbSDimitry Andric } 60915ffd83dbSDimitry Andric 60925ffd83dbSDimitry Andric /// parseDirectiveComment 60935ffd83dbSDimitry Andric /// ::= comment delimiter [[text]] 60945ffd83dbSDimitry Andric /// [[text]] 60955ffd83dbSDimitry Andric /// [[text]] delimiter [[text]] 60965ffd83dbSDimitry Andric bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) { 6097e8d8bef9SDimitry Andric std::string FirstLine = parseStringTo(AsmToken::EndOfStatement); 60985ffd83dbSDimitry Andric size_t DelimiterEnd = FirstLine.find_first_of("\b\t\v\f\r\x1A "); 6099*06c3fb27SDimitry Andric assert(DelimiterEnd != std::string::npos); 6100e8d8bef9SDimitry Andric StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd); 61015ffd83dbSDimitry Andric if (Delimiter.empty()) 61025ffd83dbSDimitry Andric return Error(DirectiveLoc, "no delimiter in 'comment' directive"); 61035ffd83dbSDimitry Andric do { 61045ffd83dbSDimitry Andric if (getTok().is(AsmToken::Eof)) 61055ffd83dbSDimitry Andric return Error(DirectiveLoc, "unmatched delimiter in 'comment' directive"); 61065ffd83dbSDimitry Andric Lex(); // eat end of statement 6107e8d8bef9SDimitry Andric } while ( 6108e8d8bef9SDimitry Andric !StringRef(parseStringTo(AsmToken::EndOfStatement)).contains(Delimiter)); 610981ad6265SDimitry Andric return parseEOL(); 61105ffd83dbSDimitry Andric } 61115ffd83dbSDimitry Andric 61125ffd83dbSDimitry Andric /// parseDirectiveInclude 61135ffd83dbSDimitry Andric /// ::= include <filename> 61145ffd83dbSDimitry Andric /// | include filename 61155ffd83dbSDimitry Andric bool MasmParser::parseDirectiveInclude() { 61165ffd83dbSDimitry Andric // Allow the strings to have escaped octal character sequence. 61175ffd83dbSDimitry Andric std::string Filename; 61185ffd83dbSDimitry Andric SMLoc IncludeLoc = getTok().getLoc(); 61195ffd83dbSDimitry Andric 6120fe6060f1SDimitry Andric if (parseAngleBracketString(Filename)) 6121e8d8bef9SDimitry Andric Filename = parseStringTo(AsmToken::EndOfStatement); 6122fe6060f1SDimitry Andric if (check(Filename.empty(), "missing filename in 'include' directive") || 61235ffd83dbSDimitry Andric check(getTok().isNot(AsmToken::EndOfStatement), 61245ffd83dbSDimitry Andric "unexpected token in 'include' directive") || 61255ffd83dbSDimitry Andric // Attempt to switch the lexer to the included file before consuming the 61265ffd83dbSDimitry Andric // end of statement to avoid losing it when we switch. 61275ffd83dbSDimitry Andric check(enterIncludeFile(Filename), IncludeLoc, 61285ffd83dbSDimitry Andric "Could not find include file '" + Filename + "'")) 61295ffd83dbSDimitry Andric return true; 61305ffd83dbSDimitry Andric 61315ffd83dbSDimitry Andric return false; 61325ffd83dbSDimitry Andric } 61335ffd83dbSDimitry Andric 61345ffd83dbSDimitry Andric /// parseDirectiveIf 61355ffd83dbSDimitry Andric /// ::= .if{,eq,ge,gt,le,lt,ne} expression 61365ffd83dbSDimitry Andric bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) { 61375ffd83dbSDimitry Andric TheCondStack.push_back(TheCondState); 61385ffd83dbSDimitry Andric TheCondState.TheCond = AsmCond::IfCond; 61395ffd83dbSDimitry Andric if (TheCondState.Ignore) { 61405ffd83dbSDimitry Andric eatToEndOfStatement(); 61415ffd83dbSDimitry Andric } else { 61425ffd83dbSDimitry Andric int64_t ExprValue; 614381ad6265SDimitry Andric if (parseAbsoluteExpression(ExprValue) || parseEOL()) 61445ffd83dbSDimitry Andric return true; 61455ffd83dbSDimitry Andric 61465ffd83dbSDimitry Andric switch (DirKind) { 61475ffd83dbSDimitry Andric default: 61485ffd83dbSDimitry Andric llvm_unreachable("unsupported directive"); 61495ffd83dbSDimitry Andric case DK_IF: 61505ffd83dbSDimitry Andric break; 61515ffd83dbSDimitry Andric case DK_IFE: 61525ffd83dbSDimitry Andric ExprValue = ExprValue == 0; 61535ffd83dbSDimitry Andric break; 61545ffd83dbSDimitry Andric } 61555ffd83dbSDimitry Andric 61565ffd83dbSDimitry Andric TheCondState.CondMet = ExprValue; 61575ffd83dbSDimitry Andric TheCondState.Ignore = !TheCondState.CondMet; 61585ffd83dbSDimitry Andric } 61595ffd83dbSDimitry Andric 61605ffd83dbSDimitry Andric return false; 61615ffd83dbSDimitry Andric } 61625ffd83dbSDimitry Andric 61635ffd83dbSDimitry Andric /// parseDirectiveIfb 6164e8d8bef9SDimitry Andric /// ::= .ifb textitem 61655ffd83dbSDimitry Andric bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { 61665ffd83dbSDimitry Andric TheCondStack.push_back(TheCondState); 61675ffd83dbSDimitry Andric TheCondState.TheCond = AsmCond::IfCond; 61685ffd83dbSDimitry Andric 61695ffd83dbSDimitry Andric if (TheCondState.Ignore) { 61705ffd83dbSDimitry Andric eatToEndOfStatement(); 61715ffd83dbSDimitry Andric } else { 61725ffd83dbSDimitry Andric std::string Str; 61735ffd83dbSDimitry Andric if (parseTextItem(Str)) 6174e8d8bef9SDimitry Andric return TokError("expected text item parameter for 'ifb' directive"); 61755ffd83dbSDimitry Andric 617681ad6265SDimitry Andric if (parseEOL()) 61775ffd83dbSDimitry Andric return true; 61785ffd83dbSDimitry Andric 61795ffd83dbSDimitry Andric TheCondState.CondMet = ExpectBlank == Str.empty(); 61805ffd83dbSDimitry Andric TheCondState.Ignore = !TheCondState.CondMet; 61815ffd83dbSDimitry Andric } 61825ffd83dbSDimitry Andric 61835ffd83dbSDimitry Andric return false; 61845ffd83dbSDimitry Andric } 61855ffd83dbSDimitry Andric 61865ffd83dbSDimitry Andric /// parseDirectiveIfidn 6187e8d8bef9SDimitry Andric /// ::= ifidn textitem, textitem 6188e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual, 6189e8d8bef9SDimitry Andric bool CaseInsensitive) { 61905ffd83dbSDimitry Andric std::string String1, String2; 61915ffd83dbSDimitry Andric 61925ffd83dbSDimitry Andric if (parseTextItem(String1)) { 61935ffd83dbSDimitry Andric if (ExpectEqual) 6194e8d8bef9SDimitry Andric return TokError("expected text item parameter for 'ifidn' directive"); 6195e8d8bef9SDimitry Andric return TokError("expected text item parameter for 'ifdif' directive"); 61965ffd83dbSDimitry Andric } 61975ffd83dbSDimitry Andric 61985ffd83dbSDimitry Andric if (Lexer.isNot(AsmToken::Comma)) { 61995ffd83dbSDimitry Andric if (ExpectEqual) 62005ffd83dbSDimitry Andric return TokError( 62015ffd83dbSDimitry Andric "expected comma after first string for 'ifidn' directive"); 62025ffd83dbSDimitry Andric return TokError("expected comma after first string for 'ifdif' directive"); 62035ffd83dbSDimitry Andric } 62045ffd83dbSDimitry Andric Lex(); 62055ffd83dbSDimitry Andric 62065ffd83dbSDimitry Andric if (parseTextItem(String2)) { 62075ffd83dbSDimitry Andric if (ExpectEqual) 6208e8d8bef9SDimitry Andric return TokError("expected text item parameter for 'ifidn' directive"); 6209e8d8bef9SDimitry Andric return TokError("expected text item parameter for 'ifdif' directive"); 62105ffd83dbSDimitry Andric } 62115ffd83dbSDimitry Andric 62125ffd83dbSDimitry Andric TheCondStack.push_back(TheCondState); 62135ffd83dbSDimitry Andric TheCondState.TheCond = AsmCond::IfCond; 62145ffd83dbSDimitry Andric if (CaseInsensitive) 62155ffd83dbSDimitry Andric TheCondState.CondMet = 6216fe6060f1SDimitry Andric ExpectEqual == (StringRef(String1).equals_insensitive(String2)); 62175ffd83dbSDimitry Andric else 62185ffd83dbSDimitry Andric TheCondState.CondMet = ExpectEqual == (String1 == String2); 62195ffd83dbSDimitry Andric TheCondState.Ignore = !TheCondState.CondMet; 62205ffd83dbSDimitry Andric 62215ffd83dbSDimitry Andric return false; 62225ffd83dbSDimitry Andric } 62235ffd83dbSDimitry Andric 62245ffd83dbSDimitry Andric /// parseDirectiveIfdef 62255ffd83dbSDimitry Andric /// ::= ifdef symbol 62265ffd83dbSDimitry Andric /// | ifdef variable 62275ffd83dbSDimitry Andric bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { 62285ffd83dbSDimitry Andric TheCondStack.push_back(TheCondState); 62295ffd83dbSDimitry Andric TheCondState.TheCond = AsmCond::IfCond; 62305ffd83dbSDimitry Andric 62315ffd83dbSDimitry Andric if (TheCondState.Ignore) { 62325ffd83dbSDimitry Andric eatToEndOfStatement(); 62335ffd83dbSDimitry Andric } else { 62345ffd83dbSDimitry Andric bool is_defined = false; 6235bdd1243dSDimitry Andric MCRegister Reg; 62365ffd83dbSDimitry Andric SMLoc StartLoc, EndLoc; 6237bdd1243dSDimitry Andric is_defined = (getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc) == 6238bdd1243dSDimitry Andric MatchOperand_Success); 62395ffd83dbSDimitry Andric if (!is_defined) { 62405ffd83dbSDimitry Andric StringRef Name; 62415ffd83dbSDimitry Andric if (check(parseIdentifier(Name), "expected identifier after 'ifdef'") || 624281ad6265SDimitry Andric parseEOL()) 62435ffd83dbSDimitry Andric return true; 62445ffd83dbSDimitry Andric 6245*06c3fb27SDimitry Andric if (BuiltinSymbolMap.contains(Name.lower())) { 6246fe6060f1SDimitry Andric is_defined = true; 6247*06c3fb27SDimitry Andric } else if (Variables.contains(Name.lower())) { 62485ffd83dbSDimitry Andric is_defined = true; 62495ffd83dbSDimitry Andric } else { 6250fe6060f1SDimitry Andric MCSymbol *Sym = getContext().lookupSymbol(Name.lower()); 62515ffd83dbSDimitry Andric is_defined = (Sym && !Sym->isUndefined(false)); 62525ffd83dbSDimitry Andric } 62535ffd83dbSDimitry Andric } 62545ffd83dbSDimitry Andric 62555ffd83dbSDimitry Andric TheCondState.CondMet = (is_defined == expect_defined); 62565ffd83dbSDimitry Andric TheCondState.Ignore = !TheCondState.CondMet; 62575ffd83dbSDimitry Andric } 62585ffd83dbSDimitry Andric 62595ffd83dbSDimitry Andric return false; 62605ffd83dbSDimitry Andric } 62615ffd83dbSDimitry Andric 62625ffd83dbSDimitry Andric /// parseDirectiveElseIf 62635ffd83dbSDimitry Andric /// ::= elseif expression 62645ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc, 62655ffd83dbSDimitry Andric DirectiveKind DirKind) { 62665ffd83dbSDimitry Andric if (TheCondState.TheCond != AsmCond::IfCond && 62675ffd83dbSDimitry Andric TheCondState.TheCond != AsmCond::ElseIfCond) 62685ffd83dbSDimitry Andric return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an" 62695ffd83dbSDimitry Andric " .if or an .elseif"); 62705ffd83dbSDimitry Andric TheCondState.TheCond = AsmCond::ElseIfCond; 62715ffd83dbSDimitry Andric 62725ffd83dbSDimitry Andric bool LastIgnoreState = false; 62735ffd83dbSDimitry Andric if (!TheCondStack.empty()) 62745ffd83dbSDimitry Andric LastIgnoreState = TheCondStack.back().Ignore; 62755ffd83dbSDimitry Andric if (LastIgnoreState || TheCondState.CondMet) { 62765ffd83dbSDimitry Andric TheCondState.Ignore = true; 62775ffd83dbSDimitry Andric eatToEndOfStatement(); 62785ffd83dbSDimitry Andric } else { 62795ffd83dbSDimitry Andric int64_t ExprValue; 62805ffd83dbSDimitry Andric if (parseAbsoluteExpression(ExprValue)) 62815ffd83dbSDimitry Andric return true; 62825ffd83dbSDimitry Andric 628381ad6265SDimitry Andric if (parseEOL()) 62845ffd83dbSDimitry Andric return true; 62855ffd83dbSDimitry Andric 62865ffd83dbSDimitry Andric switch (DirKind) { 62875ffd83dbSDimitry Andric default: 62885ffd83dbSDimitry Andric llvm_unreachable("unsupported directive"); 62895ffd83dbSDimitry Andric case DK_ELSEIF: 62905ffd83dbSDimitry Andric break; 62915ffd83dbSDimitry Andric case DK_ELSEIFE: 62925ffd83dbSDimitry Andric ExprValue = ExprValue == 0; 62935ffd83dbSDimitry Andric break; 62945ffd83dbSDimitry Andric } 62955ffd83dbSDimitry Andric 62965ffd83dbSDimitry Andric TheCondState.CondMet = ExprValue; 62975ffd83dbSDimitry Andric TheCondState.Ignore = !TheCondState.CondMet; 62985ffd83dbSDimitry Andric } 62995ffd83dbSDimitry Andric 63005ffd83dbSDimitry Andric return false; 63015ffd83dbSDimitry Andric } 63025ffd83dbSDimitry Andric 63035ffd83dbSDimitry Andric /// parseDirectiveElseIfb 6304e8d8bef9SDimitry Andric /// ::= elseifb textitem 63055ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank) { 63065ffd83dbSDimitry Andric if (TheCondState.TheCond != AsmCond::IfCond && 63075ffd83dbSDimitry Andric TheCondState.TheCond != AsmCond::ElseIfCond) 63085ffd83dbSDimitry Andric return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an" 63095ffd83dbSDimitry Andric " if or an elseif"); 63105ffd83dbSDimitry Andric TheCondState.TheCond = AsmCond::ElseIfCond; 63115ffd83dbSDimitry Andric 63125ffd83dbSDimitry Andric bool LastIgnoreState = false; 63135ffd83dbSDimitry Andric if (!TheCondStack.empty()) 63145ffd83dbSDimitry Andric LastIgnoreState = TheCondStack.back().Ignore; 63155ffd83dbSDimitry Andric if (LastIgnoreState || TheCondState.CondMet) { 63165ffd83dbSDimitry Andric TheCondState.Ignore = true; 63175ffd83dbSDimitry Andric eatToEndOfStatement(); 63185ffd83dbSDimitry Andric } else { 63195ffd83dbSDimitry Andric std::string Str; 6320e8d8bef9SDimitry Andric if (parseTextItem(Str)) { 6321e8d8bef9SDimitry Andric if (ExpectBlank) 6322e8d8bef9SDimitry Andric return TokError("expected text item parameter for 'elseifb' directive"); 6323e8d8bef9SDimitry Andric return TokError("expected text item parameter for 'elseifnb' directive"); 6324e8d8bef9SDimitry Andric } 63255ffd83dbSDimitry Andric 632681ad6265SDimitry Andric if (parseEOL()) 63275ffd83dbSDimitry Andric return true; 63285ffd83dbSDimitry Andric 63295ffd83dbSDimitry Andric TheCondState.CondMet = ExpectBlank == Str.empty(); 63305ffd83dbSDimitry Andric TheCondState.Ignore = !TheCondState.CondMet; 63315ffd83dbSDimitry Andric } 63325ffd83dbSDimitry Andric 63335ffd83dbSDimitry Andric return false; 63345ffd83dbSDimitry Andric } 63355ffd83dbSDimitry Andric 63365ffd83dbSDimitry Andric /// parseDirectiveElseIfdef 63375ffd83dbSDimitry Andric /// ::= elseifdef symbol 63385ffd83dbSDimitry Andric /// | elseifdef variable 63395ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc, 63405ffd83dbSDimitry Andric bool expect_defined) { 63415ffd83dbSDimitry Andric if (TheCondState.TheCond != AsmCond::IfCond && 63425ffd83dbSDimitry Andric TheCondState.TheCond != AsmCond::ElseIfCond) 63435ffd83dbSDimitry Andric return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an" 63445ffd83dbSDimitry Andric " if or an elseif"); 63455ffd83dbSDimitry Andric TheCondState.TheCond = AsmCond::ElseIfCond; 63465ffd83dbSDimitry Andric 63475ffd83dbSDimitry Andric bool LastIgnoreState = false; 63485ffd83dbSDimitry Andric if (!TheCondStack.empty()) 63495ffd83dbSDimitry Andric LastIgnoreState = TheCondStack.back().Ignore; 63505ffd83dbSDimitry Andric if (LastIgnoreState || TheCondState.CondMet) { 63515ffd83dbSDimitry Andric TheCondState.Ignore = true; 63525ffd83dbSDimitry Andric eatToEndOfStatement(); 63535ffd83dbSDimitry Andric } else { 63545ffd83dbSDimitry Andric bool is_defined = false; 6355bdd1243dSDimitry Andric MCRegister Reg; 63565ffd83dbSDimitry Andric SMLoc StartLoc, EndLoc; 6357bdd1243dSDimitry Andric is_defined = (getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc) == 63585ffd83dbSDimitry Andric MatchOperand_Success); 63595ffd83dbSDimitry Andric if (!is_defined) { 63605ffd83dbSDimitry Andric StringRef Name; 63615ffd83dbSDimitry Andric if (check(parseIdentifier(Name), 63625ffd83dbSDimitry Andric "expected identifier after 'elseifdef'") || 636381ad6265SDimitry Andric parseEOL()) 63645ffd83dbSDimitry Andric return true; 63655ffd83dbSDimitry Andric 6366*06c3fb27SDimitry Andric if (BuiltinSymbolMap.contains(Name.lower())) { 6367fe6060f1SDimitry Andric is_defined = true; 6368*06c3fb27SDimitry Andric } else if (Variables.contains(Name.lower())) { 63695ffd83dbSDimitry Andric is_defined = true; 63705ffd83dbSDimitry Andric } else { 63715ffd83dbSDimitry Andric MCSymbol *Sym = getContext().lookupSymbol(Name); 63725ffd83dbSDimitry Andric is_defined = (Sym && !Sym->isUndefined(false)); 63735ffd83dbSDimitry Andric } 63745ffd83dbSDimitry Andric } 63755ffd83dbSDimitry Andric 63765ffd83dbSDimitry Andric TheCondState.CondMet = (is_defined == expect_defined); 63775ffd83dbSDimitry Andric TheCondState.Ignore = !TheCondState.CondMet; 63785ffd83dbSDimitry Andric } 63795ffd83dbSDimitry Andric 63805ffd83dbSDimitry Andric return false; 63815ffd83dbSDimitry Andric } 63825ffd83dbSDimitry Andric 63835ffd83dbSDimitry Andric /// parseDirectiveElseIfidn 6384e8d8bef9SDimitry Andric /// ::= elseifidn textitem, textitem 63855ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual, 63865ffd83dbSDimitry Andric bool CaseInsensitive) { 63875ffd83dbSDimitry Andric if (TheCondState.TheCond != AsmCond::IfCond && 63885ffd83dbSDimitry Andric TheCondState.TheCond != AsmCond::ElseIfCond) 63895ffd83dbSDimitry Andric return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an" 63905ffd83dbSDimitry Andric " if or an elseif"); 63915ffd83dbSDimitry Andric TheCondState.TheCond = AsmCond::ElseIfCond; 63925ffd83dbSDimitry Andric 63935ffd83dbSDimitry Andric bool LastIgnoreState = false; 63945ffd83dbSDimitry Andric if (!TheCondStack.empty()) 63955ffd83dbSDimitry Andric LastIgnoreState = TheCondStack.back().Ignore; 63965ffd83dbSDimitry Andric if (LastIgnoreState || TheCondState.CondMet) { 63975ffd83dbSDimitry Andric TheCondState.Ignore = true; 63985ffd83dbSDimitry Andric eatToEndOfStatement(); 63995ffd83dbSDimitry Andric } else { 64005ffd83dbSDimitry Andric std::string String1, String2; 64015ffd83dbSDimitry Andric 64025ffd83dbSDimitry Andric if (parseTextItem(String1)) { 64035ffd83dbSDimitry Andric if (ExpectEqual) 6404e8d8bef9SDimitry Andric return TokError( 6405e8d8bef9SDimitry Andric "expected text item parameter for 'elseifidn' directive"); 6406e8d8bef9SDimitry Andric return TokError("expected text item parameter for 'elseifdif' directive"); 64075ffd83dbSDimitry Andric } 64085ffd83dbSDimitry Andric 64095ffd83dbSDimitry Andric if (Lexer.isNot(AsmToken::Comma)) { 64105ffd83dbSDimitry Andric if (ExpectEqual) 64115ffd83dbSDimitry Andric return TokError( 64125ffd83dbSDimitry Andric "expected comma after first string for 'elseifidn' directive"); 64135ffd83dbSDimitry Andric return TokError( 64145ffd83dbSDimitry Andric "expected comma after first string for 'elseifdif' directive"); 64155ffd83dbSDimitry Andric } 64165ffd83dbSDimitry Andric Lex(); 64175ffd83dbSDimitry Andric 64185ffd83dbSDimitry Andric if (parseTextItem(String2)) { 64195ffd83dbSDimitry Andric if (ExpectEqual) 6420e8d8bef9SDimitry Andric return TokError( 6421e8d8bef9SDimitry Andric "expected text item parameter for 'elseifidn' directive"); 6422e8d8bef9SDimitry Andric return TokError("expected text item parameter for 'elseifdif' directive"); 64235ffd83dbSDimitry Andric } 64245ffd83dbSDimitry Andric 64255ffd83dbSDimitry Andric if (CaseInsensitive) 64265ffd83dbSDimitry Andric TheCondState.CondMet = 6427fe6060f1SDimitry Andric ExpectEqual == (StringRef(String1).equals_insensitive(String2)); 64285ffd83dbSDimitry Andric else 64295ffd83dbSDimitry Andric TheCondState.CondMet = ExpectEqual == (String1 == String2); 64305ffd83dbSDimitry Andric TheCondState.Ignore = !TheCondState.CondMet; 64315ffd83dbSDimitry Andric } 64325ffd83dbSDimitry Andric 64335ffd83dbSDimitry Andric return false; 64345ffd83dbSDimitry Andric } 64355ffd83dbSDimitry Andric 64365ffd83dbSDimitry Andric /// parseDirectiveElse 64375ffd83dbSDimitry Andric /// ::= else 64385ffd83dbSDimitry Andric bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) { 643981ad6265SDimitry Andric if (parseEOL()) 64405ffd83dbSDimitry Andric return true; 64415ffd83dbSDimitry Andric 64425ffd83dbSDimitry Andric if (TheCondState.TheCond != AsmCond::IfCond && 64435ffd83dbSDimitry Andric TheCondState.TheCond != AsmCond::ElseIfCond) 64445ffd83dbSDimitry Andric return Error(DirectiveLoc, "Encountered an else that doesn't follow an if" 64455ffd83dbSDimitry Andric " or an elseif"); 64465ffd83dbSDimitry Andric TheCondState.TheCond = AsmCond::ElseCond; 64475ffd83dbSDimitry Andric bool LastIgnoreState = false; 64485ffd83dbSDimitry Andric if (!TheCondStack.empty()) 64495ffd83dbSDimitry Andric LastIgnoreState = TheCondStack.back().Ignore; 64505ffd83dbSDimitry Andric if (LastIgnoreState || TheCondState.CondMet) 64515ffd83dbSDimitry Andric TheCondState.Ignore = true; 64525ffd83dbSDimitry Andric else 64535ffd83dbSDimitry Andric TheCondState.Ignore = false; 64545ffd83dbSDimitry Andric 64555ffd83dbSDimitry Andric return false; 64565ffd83dbSDimitry Andric } 64575ffd83dbSDimitry Andric 64585ffd83dbSDimitry Andric /// parseDirectiveEnd 64595ffd83dbSDimitry Andric /// ::= end 64605ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) { 646181ad6265SDimitry Andric if (parseEOL()) 64625ffd83dbSDimitry Andric return true; 64635ffd83dbSDimitry Andric 64645ffd83dbSDimitry Andric while (Lexer.isNot(AsmToken::Eof)) 64655ffd83dbSDimitry Andric Lexer.Lex(); 64665ffd83dbSDimitry Andric 64675ffd83dbSDimitry Andric return false; 64685ffd83dbSDimitry Andric } 64695ffd83dbSDimitry Andric 64705ffd83dbSDimitry Andric /// parseDirectiveError 64715ffd83dbSDimitry Andric /// ::= .err [message] 64725ffd83dbSDimitry Andric bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) { 64735ffd83dbSDimitry Andric if (!TheCondStack.empty()) { 64745ffd83dbSDimitry Andric if (TheCondStack.back().Ignore) { 64755ffd83dbSDimitry Andric eatToEndOfStatement(); 64765ffd83dbSDimitry Andric return false; 64775ffd83dbSDimitry Andric } 64785ffd83dbSDimitry Andric } 64795ffd83dbSDimitry Andric 6480e8d8bef9SDimitry Andric std::string Message = ".err directive invoked in source file"; 64815ffd83dbSDimitry Andric if (Lexer.isNot(AsmToken::EndOfStatement)) 6482e8d8bef9SDimitry Andric Message = parseStringTo(AsmToken::EndOfStatement); 64835ffd83dbSDimitry Andric Lex(); 64845ffd83dbSDimitry Andric 64855ffd83dbSDimitry Andric return Error(DirectiveLoc, Message); 64865ffd83dbSDimitry Andric } 64875ffd83dbSDimitry Andric 64885ffd83dbSDimitry Andric /// parseDirectiveErrorIfb 64895ffd83dbSDimitry Andric /// ::= .errb textitem[, message] 64905ffd83dbSDimitry Andric bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank) { 64915ffd83dbSDimitry Andric if (!TheCondStack.empty()) { 64925ffd83dbSDimitry Andric if (TheCondStack.back().Ignore) { 64935ffd83dbSDimitry Andric eatToEndOfStatement(); 64945ffd83dbSDimitry Andric return false; 64955ffd83dbSDimitry Andric } 64965ffd83dbSDimitry Andric } 64975ffd83dbSDimitry Andric 64985ffd83dbSDimitry Andric std::string Text; 64995ffd83dbSDimitry Andric if (parseTextItem(Text)) 65005ffd83dbSDimitry Andric return Error(getTok().getLoc(), "missing text item in '.errb' directive"); 65015ffd83dbSDimitry Andric 6502e8d8bef9SDimitry Andric std::string Message = ".errb directive invoked in source file"; 65035ffd83dbSDimitry Andric if (Lexer.isNot(AsmToken::EndOfStatement)) { 65045ffd83dbSDimitry Andric if (parseToken(AsmToken::Comma)) 65055ffd83dbSDimitry Andric return addErrorSuffix(" in '.errb' directive"); 6506e8d8bef9SDimitry Andric Message = parseStringTo(AsmToken::EndOfStatement); 65075ffd83dbSDimitry Andric } 65085ffd83dbSDimitry Andric Lex(); 65095ffd83dbSDimitry Andric 65105ffd83dbSDimitry Andric if (Text.empty() == ExpectBlank) 65115ffd83dbSDimitry Andric return Error(DirectiveLoc, Message); 65125ffd83dbSDimitry Andric return false; 65135ffd83dbSDimitry Andric } 65145ffd83dbSDimitry Andric 65155ffd83dbSDimitry Andric /// parseDirectiveErrorIfdef 65165ffd83dbSDimitry Andric /// ::= .errdef name[, message] 65175ffd83dbSDimitry Andric bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc, 65185ffd83dbSDimitry Andric bool ExpectDefined) { 65195ffd83dbSDimitry Andric if (!TheCondStack.empty()) { 65205ffd83dbSDimitry Andric if (TheCondStack.back().Ignore) { 65215ffd83dbSDimitry Andric eatToEndOfStatement(); 65225ffd83dbSDimitry Andric return false; 65235ffd83dbSDimitry Andric } 65245ffd83dbSDimitry Andric } 65255ffd83dbSDimitry Andric 65265ffd83dbSDimitry Andric bool IsDefined = false; 6527bdd1243dSDimitry Andric MCRegister Reg; 65285ffd83dbSDimitry Andric SMLoc StartLoc, EndLoc; 6529bdd1243dSDimitry Andric IsDefined = (getTargetParser().tryParseRegister(Reg, StartLoc, EndLoc) == 65305ffd83dbSDimitry Andric MatchOperand_Success); 65315ffd83dbSDimitry Andric if (!IsDefined) { 65325ffd83dbSDimitry Andric StringRef Name; 65335ffd83dbSDimitry Andric if (check(parseIdentifier(Name), "expected identifier after '.errdef'")) 65345ffd83dbSDimitry Andric return true; 65355ffd83dbSDimitry Andric 6536*06c3fb27SDimitry Andric if (BuiltinSymbolMap.contains(Name.lower())) { 6537fe6060f1SDimitry Andric IsDefined = true; 6538*06c3fb27SDimitry Andric } else if (Variables.contains(Name.lower())) { 65395ffd83dbSDimitry Andric IsDefined = true; 65405ffd83dbSDimitry Andric } else { 65415ffd83dbSDimitry Andric MCSymbol *Sym = getContext().lookupSymbol(Name); 65425ffd83dbSDimitry Andric IsDefined = (Sym && !Sym->isUndefined(false)); 65435ffd83dbSDimitry Andric } 65445ffd83dbSDimitry Andric } 65455ffd83dbSDimitry Andric 6546e8d8bef9SDimitry Andric std::string Message = ".errdef directive invoked in source file"; 65475ffd83dbSDimitry Andric if (Lexer.isNot(AsmToken::EndOfStatement)) { 65485ffd83dbSDimitry Andric if (parseToken(AsmToken::Comma)) 65495ffd83dbSDimitry Andric return addErrorSuffix(" in '.errdef' directive"); 6550e8d8bef9SDimitry Andric Message = parseStringTo(AsmToken::EndOfStatement); 65515ffd83dbSDimitry Andric } 65525ffd83dbSDimitry Andric Lex(); 65535ffd83dbSDimitry Andric 65545ffd83dbSDimitry Andric if (IsDefined == ExpectDefined) 65555ffd83dbSDimitry Andric return Error(DirectiveLoc, Message); 65565ffd83dbSDimitry Andric return false; 65575ffd83dbSDimitry Andric } 65585ffd83dbSDimitry Andric 65595ffd83dbSDimitry Andric /// parseDirectiveErrorIfidn 6560e8d8bef9SDimitry Andric /// ::= .erridn textitem, textitem[, message] 65615ffd83dbSDimitry Andric bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual, 65625ffd83dbSDimitry Andric bool CaseInsensitive) { 65635ffd83dbSDimitry Andric if (!TheCondStack.empty()) { 65645ffd83dbSDimitry Andric if (TheCondStack.back().Ignore) { 65655ffd83dbSDimitry Andric eatToEndOfStatement(); 65665ffd83dbSDimitry Andric return false; 65675ffd83dbSDimitry Andric } 65685ffd83dbSDimitry Andric } 65695ffd83dbSDimitry Andric 65705ffd83dbSDimitry Andric std::string String1, String2; 65715ffd83dbSDimitry Andric 65725ffd83dbSDimitry Andric if (parseTextItem(String1)) { 65735ffd83dbSDimitry Andric if (ExpectEqual) 65745ffd83dbSDimitry Andric return TokError("expected string parameter for '.erridn' directive"); 65755ffd83dbSDimitry Andric return TokError("expected string parameter for '.errdif' directive"); 65765ffd83dbSDimitry Andric } 65775ffd83dbSDimitry Andric 65785ffd83dbSDimitry Andric if (Lexer.isNot(AsmToken::Comma)) { 65795ffd83dbSDimitry Andric if (ExpectEqual) 65805ffd83dbSDimitry Andric return TokError( 65815ffd83dbSDimitry Andric "expected comma after first string for '.erridn' directive"); 65825ffd83dbSDimitry Andric return TokError( 65835ffd83dbSDimitry Andric "expected comma after first string for '.errdif' directive"); 65845ffd83dbSDimitry Andric } 65855ffd83dbSDimitry Andric Lex(); 65865ffd83dbSDimitry Andric 65875ffd83dbSDimitry Andric if (parseTextItem(String2)) { 65885ffd83dbSDimitry Andric if (ExpectEqual) 65895ffd83dbSDimitry Andric return TokError("expected string parameter for '.erridn' directive"); 65905ffd83dbSDimitry Andric return TokError("expected string parameter for '.errdif' directive"); 65915ffd83dbSDimitry Andric } 65925ffd83dbSDimitry Andric 6593e8d8bef9SDimitry Andric std::string Message; 65945ffd83dbSDimitry Andric if (ExpectEqual) 65955ffd83dbSDimitry Andric Message = ".erridn directive invoked in source file"; 65965ffd83dbSDimitry Andric else 65975ffd83dbSDimitry Andric Message = ".errdif directive invoked in source file"; 65985ffd83dbSDimitry Andric if (Lexer.isNot(AsmToken::EndOfStatement)) { 65995ffd83dbSDimitry Andric if (parseToken(AsmToken::Comma)) 66005ffd83dbSDimitry Andric return addErrorSuffix(" in '.erridn' directive"); 6601e8d8bef9SDimitry Andric Message = parseStringTo(AsmToken::EndOfStatement); 66025ffd83dbSDimitry Andric } 66035ffd83dbSDimitry Andric Lex(); 66045ffd83dbSDimitry Andric 66055ffd83dbSDimitry Andric if (CaseInsensitive) 66065ffd83dbSDimitry Andric TheCondState.CondMet = 6607fe6060f1SDimitry Andric ExpectEqual == (StringRef(String1).equals_insensitive(String2)); 66085ffd83dbSDimitry Andric else 66095ffd83dbSDimitry Andric TheCondState.CondMet = ExpectEqual == (String1 == String2); 66105ffd83dbSDimitry Andric TheCondState.Ignore = !TheCondState.CondMet; 66115ffd83dbSDimitry Andric 66125ffd83dbSDimitry Andric if ((CaseInsensitive && 6613fe6060f1SDimitry Andric ExpectEqual == StringRef(String1).equals_insensitive(String2)) || 66145ffd83dbSDimitry Andric (ExpectEqual == (String1 == String2))) 66155ffd83dbSDimitry Andric return Error(DirectiveLoc, Message); 66165ffd83dbSDimitry Andric return false; 66175ffd83dbSDimitry Andric } 66185ffd83dbSDimitry Andric 66195ffd83dbSDimitry Andric /// parseDirectiveErrorIfe 66205ffd83dbSDimitry Andric /// ::= .erre expression[, message] 66215ffd83dbSDimitry Andric bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero) { 66225ffd83dbSDimitry Andric if (!TheCondStack.empty()) { 66235ffd83dbSDimitry Andric if (TheCondStack.back().Ignore) { 66245ffd83dbSDimitry Andric eatToEndOfStatement(); 66255ffd83dbSDimitry Andric return false; 66265ffd83dbSDimitry Andric } 66275ffd83dbSDimitry Andric } 66285ffd83dbSDimitry Andric 66295ffd83dbSDimitry Andric int64_t ExprValue; 66305ffd83dbSDimitry Andric if (parseAbsoluteExpression(ExprValue)) 66315ffd83dbSDimitry Andric return addErrorSuffix(" in '.erre' directive"); 66325ffd83dbSDimitry Andric 6633e8d8bef9SDimitry Andric std::string Message = ".erre directive invoked in source file"; 66345ffd83dbSDimitry Andric if (Lexer.isNot(AsmToken::EndOfStatement)) { 66355ffd83dbSDimitry Andric if (parseToken(AsmToken::Comma)) 66365ffd83dbSDimitry Andric return addErrorSuffix(" in '.erre' directive"); 6637e8d8bef9SDimitry Andric Message = parseStringTo(AsmToken::EndOfStatement); 66385ffd83dbSDimitry Andric } 66395ffd83dbSDimitry Andric Lex(); 66405ffd83dbSDimitry Andric 66415ffd83dbSDimitry Andric if ((ExprValue == 0) == ExpectZero) 66425ffd83dbSDimitry Andric return Error(DirectiveLoc, Message); 66435ffd83dbSDimitry Andric return false; 66445ffd83dbSDimitry Andric } 66455ffd83dbSDimitry Andric 66465ffd83dbSDimitry Andric /// parseDirectiveEndIf 66475ffd83dbSDimitry Andric /// ::= .endif 66485ffd83dbSDimitry Andric bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) { 664981ad6265SDimitry Andric if (parseEOL()) 66505ffd83dbSDimitry Andric return true; 66515ffd83dbSDimitry Andric 66525ffd83dbSDimitry Andric if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty()) 66535ffd83dbSDimitry Andric return Error(DirectiveLoc, "Encountered a .endif that doesn't follow " 66545ffd83dbSDimitry Andric "an .if or .else"); 66555ffd83dbSDimitry Andric if (!TheCondStack.empty()) { 66565ffd83dbSDimitry Andric TheCondState = TheCondStack.back(); 66575ffd83dbSDimitry Andric TheCondStack.pop_back(); 66585ffd83dbSDimitry Andric } 66595ffd83dbSDimitry Andric 66605ffd83dbSDimitry Andric return false; 66615ffd83dbSDimitry Andric } 66625ffd83dbSDimitry Andric 66635ffd83dbSDimitry Andric void MasmParser::initializeDirectiveKindMap() { 66645ffd83dbSDimitry Andric DirectiveKindMap["="] = DK_ASSIGN; 66655ffd83dbSDimitry Andric DirectiveKindMap["equ"] = DK_EQU; 66665ffd83dbSDimitry Andric DirectiveKindMap["textequ"] = DK_TEXTEQU; 66675ffd83dbSDimitry Andric // DirectiveKindMap[".ascii"] = DK_ASCII; 66685ffd83dbSDimitry Andric // DirectiveKindMap[".asciz"] = DK_ASCIZ; 66695ffd83dbSDimitry Andric // DirectiveKindMap[".string"] = DK_STRING; 66705ffd83dbSDimitry Andric DirectiveKindMap["byte"] = DK_BYTE; 66715ffd83dbSDimitry Andric DirectiveKindMap["sbyte"] = DK_SBYTE; 66725ffd83dbSDimitry Andric DirectiveKindMap["word"] = DK_WORD; 66735ffd83dbSDimitry Andric DirectiveKindMap["sword"] = DK_SWORD; 66745ffd83dbSDimitry Andric DirectiveKindMap["dword"] = DK_DWORD; 66755ffd83dbSDimitry Andric DirectiveKindMap["sdword"] = DK_SDWORD; 66765ffd83dbSDimitry Andric DirectiveKindMap["fword"] = DK_FWORD; 66775ffd83dbSDimitry Andric DirectiveKindMap["qword"] = DK_QWORD; 66785ffd83dbSDimitry Andric DirectiveKindMap["sqword"] = DK_SQWORD; 66795ffd83dbSDimitry Andric DirectiveKindMap["real4"] = DK_REAL4; 66805ffd83dbSDimitry Andric DirectiveKindMap["real8"] = DK_REAL8; 6681e8d8bef9SDimitry Andric DirectiveKindMap["real10"] = DK_REAL10; 66825ffd83dbSDimitry Andric DirectiveKindMap["align"] = DK_ALIGN; 6683fe6060f1SDimitry Andric DirectiveKindMap["even"] = DK_EVEN; 6684fe6060f1SDimitry Andric DirectiveKindMap["org"] = DK_ORG; 66855ffd83dbSDimitry Andric DirectiveKindMap["extern"] = DK_EXTERN; 6686bdd1243dSDimitry Andric DirectiveKindMap["extrn"] = DK_EXTERN; 66875ffd83dbSDimitry Andric DirectiveKindMap["public"] = DK_PUBLIC; 66885ffd83dbSDimitry Andric // DirectiveKindMap[".comm"] = DK_COMM; 66895ffd83dbSDimitry Andric DirectiveKindMap["comment"] = DK_COMMENT; 66905ffd83dbSDimitry Andric DirectiveKindMap["include"] = DK_INCLUDE; 6691e8d8bef9SDimitry Andric DirectiveKindMap["repeat"] = DK_REPEAT; 6692e8d8bef9SDimitry Andric DirectiveKindMap["rept"] = DK_REPEAT; 6693e8d8bef9SDimitry Andric DirectiveKindMap["while"] = DK_WHILE; 6694e8d8bef9SDimitry Andric DirectiveKindMap["for"] = DK_FOR; 6695e8d8bef9SDimitry Andric DirectiveKindMap["irp"] = DK_FOR; 6696e8d8bef9SDimitry Andric DirectiveKindMap["forc"] = DK_FORC; 6697e8d8bef9SDimitry Andric DirectiveKindMap["irpc"] = DK_FORC; 66985ffd83dbSDimitry Andric DirectiveKindMap["if"] = DK_IF; 66995ffd83dbSDimitry Andric DirectiveKindMap["ife"] = DK_IFE; 67005ffd83dbSDimitry Andric DirectiveKindMap["ifb"] = DK_IFB; 67015ffd83dbSDimitry Andric DirectiveKindMap["ifnb"] = DK_IFNB; 67025ffd83dbSDimitry Andric DirectiveKindMap["ifdef"] = DK_IFDEF; 67035ffd83dbSDimitry Andric DirectiveKindMap["ifndef"] = DK_IFNDEF; 67045ffd83dbSDimitry Andric DirectiveKindMap["ifdif"] = DK_IFDIF; 67055ffd83dbSDimitry Andric DirectiveKindMap["ifdifi"] = DK_IFDIFI; 67065ffd83dbSDimitry Andric DirectiveKindMap["ifidn"] = DK_IFIDN; 67075ffd83dbSDimitry Andric DirectiveKindMap["ifidni"] = DK_IFIDNI; 67085ffd83dbSDimitry Andric DirectiveKindMap["elseif"] = DK_ELSEIF; 67095ffd83dbSDimitry Andric DirectiveKindMap["elseifdef"] = DK_ELSEIFDEF; 67105ffd83dbSDimitry Andric DirectiveKindMap["elseifndef"] = DK_ELSEIFNDEF; 67115ffd83dbSDimitry Andric DirectiveKindMap["elseifdif"] = DK_ELSEIFDIF; 67125ffd83dbSDimitry Andric DirectiveKindMap["elseifidn"] = DK_ELSEIFIDN; 67135ffd83dbSDimitry Andric DirectiveKindMap["else"] = DK_ELSE; 67145ffd83dbSDimitry Andric DirectiveKindMap["end"] = DK_END; 67155ffd83dbSDimitry Andric DirectiveKindMap["endif"] = DK_ENDIF; 67165ffd83dbSDimitry Andric // DirectiveKindMap[".file"] = DK_FILE; 67175ffd83dbSDimitry Andric // DirectiveKindMap[".line"] = DK_LINE; 67185ffd83dbSDimitry Andric // DirectiveKindMap[".loc"] = DK_LOC; 67195ffd83dbSDimitry Andric // DirectiveKindMap[".stabs"] = DK_STABS; 67205ffd83dbSDimitry Andric // DirectiveKindMap[".cv_file"] = DK_CV_FILE; 67215ffd83dbSDimitry Andric // DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID; 67225ffd83dbSDimitry Andric // DirectiveKindMap[".cv_loc"] = DK_CV_LOC; 67235ffd83dbSDimitry Andric // DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE; 67245ffd83dbSDimitry Andric // DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE; 67255ffd83dbSDimitry Andric // DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID; 67265ffd83dbSDimitry Andric // DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE; 67275ffd83dbSDimitry Andric // DirectiveKindMap[".cv_string"] = DK_CV_STRING; 67285ffd83dbSDimitry Andric // DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE; 67295ffd83dbSDimitry Andric // DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS; 67305ffd83dbSDimitry Andric // DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET; 67315ffd83dbSDimitry Andric // DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA; 67325ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS; 67335ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC; 67345ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC; 67355ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA; 67365ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET; 67375ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET; 67385ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER; 67395ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET; 67405ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET; 67415ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY; 67425ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA; 67435ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE; 67445ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE; 67455ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE; 67465ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE; 67475ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE; 67485ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN; 67495ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME; 67505ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED; 67515ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER; 67525ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE; 67535ffd83dbSDimitry Andric // DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME; 6754e8d8bef9SDimitry Andric DirectiveKindMap["macro"] = DK_MACRO; 6755e8d8bef9SDimitry Andric DirectiveKindMap["exitm"] = DK_EXITM; 6756e8d8bef9SDimitry Andric DirectiveKindMap["endm"] = DK_ENDM; 6757e8d8bef9SDimitry Andric DirectiveKindMap["purge"] = DK_PURGE; 67585ffd83dbSDimitry Andric DirectiveKindMap[".err"] = DK_ERR; 67595ffd83dbSDimitry Andric DirectiveKindMap[".errb"] = DK_ERRB; 67605ffd83dbSDimitry Andric DirectiveKindMap[".errnb"] = DK_ERRNB; 67615ffd83dbSDimitry Andric DirectiveKindMap[".errdef"] = DK_ERRDEF; 67625ffd83dbSDimitry Andric DirectiveKindMap[".errndef"] = DK_ERRNDEF; 67635ffd83dbSDimitry Andric DirectiveKindMap[".errdif"] = DK_ERRDIF; 67645ffd83dbSDimitry Andric DirectiveKindMap[".errdifi"] = DK_ERRDIFI; 67655ffd83dbSDimitry Andric DirectiveKindMap[".erridn"] = DK_ERRIDN; 67665ffd83dbSDimitry Andric DirectiveKindMap[".erridni"] = DK_ERRIDNI; 67675ffd83dbSDimitry Andric DirectiveKindMap[".erre"] = DK_ERRE; 67685ffd83dbSDimitry Andric DirectiveKindMap[".errnz"] = DK_ERRNZ; 6769e8d8bef9SDimitry Andric DirectiveKindMap[".pushframe"] = DK_PUSHFRAME; 6770e8d8bef9SDimitry Andric DirectiveKindMap[".pushreg"] = DK_PUSHREG; 6771e8d8bef9SDimitry Andric DirectiveKindMap[".savereg"] = DK_SAVEREG; 6772e8d8bef9SDimitry Andric DirectiveKindMap[".savexmm128"] = DK_SAVEXMM128; 6773e8d8bef9SDimitry Andric DirectiveKindMap[".setframe"] = DK_SETFRAME; 6774e8d8bef9SDimitry Andric DirectiveKindMap[".radix"] = DK_RADIX; 67755ffd83dbSDimitry Andric DirectiveKindMap["db"] = DK_DB; 67765ffd83dbSDimitry Andric DirectiveKindMap["dd"] = DK_DD; 6777e8d8bef9SDimitry Andric DirectiveKindMap["df"] = DK_DF; 67785ffd83dbSDimitry Andric DirectiveKindMap["dq"] = DK_DQ; 67795ffd83dbSDimitry Andric DirectiveKindMap["dw"] = DK_DW; 67805ffd83dbSDimitry Andric DirectiveKindMap["echo"] = DK_ECHO; 67815ffd83dbSDimitry Andric DirectiveKindMap["struc"] = DK_STRUCT; 67825ffd83dbSDimitry Andric DirectiveKindMap["struct"] = DK_STRUCT; 67835ffd83dbSDimitry Andric DirectiveKindMap["union"] = DK_UNION; 67845ffd83dbSDimitry Andric DirectiveKindMap["ends"] = DK_ENDS; 67855ffd83dbSDimitry Andric } 67865ffd83dbSDimitry Andric 6787e8d8bef9SDimitry Andric bool MasmParser::isMacroLikeDirective() { 6788e8d8bef9SDimitry Andric if (getLexer().is(AsmToken::Identifier)) { 6789e8d8bef9SDimitry Andric bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier()) 6790e8d8bef9SDimitry Andric .CasesLower("repeat", "rept", true) 6791e8d8bef9SDimitry Andric .CaseLower("while", true) 6792e8d8bef9SDimitry Andric .CasesLower("for", "irp", true) 6793e8d8bef9SDimitry Andric .CasesLower("forc", "irpc", true) 6794e8d8bef9SDimitry Andric .Default(false); 6795e8d8bef9SDimitry Andric if (IsMacroLike) 6796e8d8bef9SDimitry Andric return true; 6797e8d8bef9SDimitry Andric } 6798fe6060f1SDimitry Andric if (peekTok().is(AsmToken::Identifier) && 6799fe6060f1SDimitry Andric peekTok().getIdentifier().equals_insensitive("macro")) 6800e8d8bef9SDimitry Andric return true; 6801e8d8bef9SDimitry Andric 6802e8d8bef9SDimitry Andric return false; 6803e8d8bef9SDimitry Andric } 6804e8d8bef9SDimitry Andric 68055ffd83dbSDimitry Andric MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { 68065ffd83dbSDimitry Andric AsmToken EndToken, StartToken = getTok(); 68075ffd83dbSDimitry Andric 68085ffd83dbSDimitry Andric unsigned NestLevel = 0; 68095ffd83dbSDimitry Andric while (true) { 68105ffd83dbSDimitry Andric // Check whether we have reached the end of the file. 68115ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Eof)) { 6812e8d8bef9SDimitry Andric printError(DirectiveLoc, "no matching 'endm' in definition"); 68135ffd83dbSDimitry Andric return nullptr; 68145ffd83dbSDimitry Andric } 68155ffd83dbSDimitry Andric 6816e8d8bef9SDimitry Andric if (isMacroLikeDirective()) 68175ffd83dbSDimitry Andric ++NestLevel; 68185ffd83dbSDimitry Andric 6819e8d8bef9SDimitry Andric // Otherwise, check whether we have reached the endm. 6820e8d8bef9SDimitry Andric if (Lexer.is(AsmToken::Identifier) && 6821fe6060f1SDimitry Andric getTok().getIdentifier().equals_insensitive("endm")) { 68225ffd83dbSDimitry Andric if (NestLevel == 0) { 68235ffd83dbSDimitry Andric EndToken = getTok(); 68245ffd83dbSDimitry Andric Lex(); 68255ffd83dbSDimitry Andric if (Lexer.isNot(AsmToken::EndOfStatement)) { 6826e8d8bef9SDimitry Andric printError(getTok().getLoc(), "unexpected token in 'endm' directive"); 68275ffd83dbSDimitry Andric return nullptr; 68285ffd83dbSDimitry Andric } 68295ffd83dbSDimitry Andric break; 68305ffd83dbSDimitry Andric } 68315ffd83dbSDimitry Andric --NestLevel; 68325ffd83dbSDimitry Andric } 68335ffd83dbSDimitry Andric 68345ffd83dbSDimitry Andric // Otherwise, scan till the end of the statement. 68355ffd83dbSDimitry Andric eatToEndOfStatement(); 68365ffd83dbSDimitry Andric } 68375ffd83dbSDimitry Andric 68385ffd83dbSDimitry Andric const char *BodyStart = StartToken.getLoc().getPointer(); 68395ffd83dbSDimitry Andric const char *BodyEnd = EndToken.getLoc().getPointer(); 68405ffd83dbSDimitry Andric StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); 68415ffd83dbSDimitry Andric 68425ffd83dbSDimitry Andric // We Are Anonymous. 68435ffd83dbSDimitry Andric MacroLikeBodies.emplace_back(StringRef(), Body, MCAsmMacroParameters()); 68445ffd83dbSDimitry Andric return &MacroLikeBodies.back(); 68455ffd83dbSDimitry Andric } 68465ffd83dbSDimitry Andric 6847e8d8bef9SDimitry Andric bool MasmParser::expandStatement(SMLoc Loc) { 6848e8d8bef9SDimitry Andric std::string Body = parseStringTo(AsmToken::EndOfStatement); 6849e8d8bef9SDimitry Andric SMLoc EndLoc = getTok().getLoc(); 6850e8d8bef9SDimitry Andric 6851e8d8bef9SDimitry Andric MCAsmMacroParameters Parameters; 6852e8d8bef9SDimitry Andric MCAsmMacroArguments Arguments; 6853fe6060f1SDimitry Andric 6854fe6060f1SDimitry Andric StringMap<std::string> BuiltinValues; 6855fe6060f1SDimitry Andric for (const auto &S : BuiltinSymbolMap) { 6856fe6060f1SDimitry Andric const BuiltinSymbol &Sym = S.getValue(); 6857bdd1243dSDimitry Andric if (std::optional<std::string> Text = evaluateBuiltinTextMacro(Sym, Loc)) { 6858fe6060f1SDimitry Andric BuiltinValues[S.getKey().lower()] = std::move(*Text); 6859fe6060f1SDimitry Andric } 6860fe6060f1SDimitry Andric } 6861fe6060f1SDimitry Andric for (const auto &B : BuiltinValues) { 6862fe6060f1SDimitry Andric MCAsmMacroParameter P; 6863fe6060f1SDimitry Andric MCAsmMacroArgument A; 6864fe6060f1SDimitry Andric P.Name = B.getKey(); 6865fe6060f1SDimitry Andric P.Required = true; 6866fe6060f1SDimitry Andric A.push_back(AsmToken(AsmToken::String, B.getValue())); 6867fe6060f1SDimitry Andric 6868fe6060f1SDimitry Andric Parameters.push_back(std::move(P)); 6869fe6060f1SDimitry Andric Arguments.push_back(std::move(A)); 6870fe6060f1SDimitry Andric } 6871fe6060f1SDimitry Andric 6872e8d8bef9SDimitry Andric for (const auto &V : Variables) { 6873e8d8bef9SDimitry Andric const Variable &Var = V.getValue(); 6874e8d8bef9SDimitry Andric if (Var.IsText) { 6875fe6060f1SDimitry Andric MCAsmMacroParameter P; 6876fe6060f1SDimitry Andric MCAsmMacroArgument A; 6877e8d8bef9SDimitry Andric P.Name = Var.Name; 6878e8d8bef9SDimitry Andric P.Required = true; 6879e8d8bef9SDimitry Andric A.push_back(AsmToken(AsmToken::String, Var.TextValue)); 6880fe6060f1SDimitry Andric 6881fe6060f1SDimitry Andric Parameters.push_back(std::move(P)); 6882fe6060f1SDimitry Andric Arguments.push_back(std::move(A)); 6883e8d8bef9SDimitry Andric } 6884e8d8bef9SDimitry Andric } 6885e8d8bef9SDimitry Andric MacroLikeBodies.emplace_back(StringRef(), Body, Parameters); 6886e8d8bef9SDimitry Andric MCAsmMacro M = MacroLikeBodies.back(); 6887e8d8bef9SDimitry Andric 6888e8d8bef9SDimitry Andric // Expand the statement in a new buffer. 6889e8d8bef9SDimitry Andric SmallString<80> Buf; 6890e8d8bef9SDimitry Andric raw_svector_ostream OS(Buf); 6891e8d8bef9SDimitry Andric if (expandMacro(OS, M.Body, M.Parameters, Arguments, M.Locals, EndLoc)) 6892e8d8bef9SDimitry Andric return true; 6893e8d8bef9SDimitry Andric std::unique_ptr<MemoryBuffer> Expansion = 6894e8d8bef9SDimitry Andric MemoryBuffer::getMemBufferCopy(OS.str(), "<expansion>"); 6895e8d8bef9SDimitry Andric 6896e8d8bef9SDimitry Andric // Jump to the expanded statement and prime the lexer. 6897e8d8bef9SDimitry Andric CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Expansion), EndLoc); 6898e8d8bef9SDimitry Andric Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); 6899e8d8bef9SDimitry Andric EndStatementAtEOFStack.push_back(false); 6900e8d8bef9SDimitry Andric Lex(); 6901e8d8bef9SDimitry Andric return false; 6902e8d8bef9SDimitry Andric } 6903e8d8bef9SDimitry Andric 69045ffd83dbSDimitry Andric void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, 69055ffd83dbSDimitry Andric raw_svector_ostream &OS) { 6906e8d8bef9SDimitry Andric instantiateMacroLikeBody(M, DirectiveLoc, /*ExitLoc=*/getTok().getLoc(), OS); 6907e8d8bef9SDimitry Andric } 6908e8d8bef9SDimitry Andric void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, 6909e8d8bef9SDimitry Andric SMLoc ExitLoc, 6910e8d8bef9SDimitry Andric raw_svector_ostream &OS) { 6911e8d8bef9SDimitry Andric OS << "endm\n"; 69125ffd83dbSDimitry Andric 69135ffd83dbSDimitry Andric std::unique_ptr<MemoryBuffer> Instantiation = 69145ffd83dbSDimitry Andric MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>"); 69155ffd83dbSDimitry Andric 69165ffd83dbSDimitry Andric // Create the macro instantiation object and add to the current macro 69175ffd83dbSDimitry Andric // instantiation stack. 6918e8d8bef9SDimitry Andric MacroInstantiation *MI = new MacroInstantiation{DirectiveLoc, CurBuffer, 6919e8d8bef9SDimitry Andric ExitLoc, TheCondStack.size()}; 69205ffd83dbSDimitry Andric ActiveMacros.push_back(MI); 69215ffd83dbSDimitry Andric 69225ffd83dbSDimitry Andric // Jump to the macro instantiation and prime the lexer. 69235ffd83dbSDimitry Andric CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc()); 69245ffd83dbSDimitry Andric Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); 6925e8d8bef9SDimitry Andric EndStatementAtEOFStack.push_back(true); 69265ffd83dbSDimitry Andric Lex(); 69275ffd83dbSDimitry Andric } 69285ffd83dbSDimitry Andric 6929e8d8bef9SDimitry Andric /// parseDirectiveRepeat 6930e8d8bef9SDimitry Andric /// ::= ("repeat" | "rept") count 6931e8d8bef9SDimitry Andric /// body 6932e8d8bef9SDimitry Andric /// endm 6933e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) { 69345ffd83dbSDimitry Andric const MCExpr *CountExpr; 69355ffd83dbSDimitry Andric SMLoc CountLoc = getTok().getLoc(); 69365ffd83dbSDimitry Andric if (parseExpression(CountExpr)) 69375ffd83dbSDimitry Andric return true; 69385ffd83dbSDimitry Andric 69395ffd83dbSDimitry Andric int64_t Count; 69405ffd83dbSDimitry Andric if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) { 69415ffd83dbSDimitry Andric return Error(CountLoc, "unexpected token in '" + Dir + "' directive"); 69425ffd83dbSDimitry Andric } 69435ffd83dbSDimitry Andric 694481ad6265SDimitry Andric if (check(Count < 0, CountLoc, "Count is negative") || parseEOL()) 69455ffd83dbSDimitry Andric return true; 69465ffd83dbSDimitry Andric 6947e8d8bef9SDimitry Andric // Lex the repeat definition. 69485ffd83dbSDimitry Andric MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); 69495ffd83dbSDimitry Andric if (!M) 69505ffd83dbSDimitry Andric return true; 69515ffd83dbSDimitry Andric 69525ffd83dbSDimitry Andric // Macro instantiation is lexical, unfortunately. We construct a new buffer 69535ffd83dbSDimitry Andric // to hold the macro body with substitutions. 69545ffd83dbSDimitry Andric SmallString<256> Buf; 69555ffd83dbSDimitry Andric raw_svector_ostream OS(Buf); 69565ffd83dbSDimitry Andric while (Count--) { 6957bdd1243dSDimitry Andric if (expandMacro(OS, M->Body, std::nullopt, std::nullopt, M->Locals, 6958bdd1243dSDimitry Andric getTok().getLoc())) 69595ffd83dbSDimitry Andric return true; 69605ffd83dbSDimitry Andric } 69615ffd83dbSDimitry Andric instantiateMacroLikeBody(M, DirectiveLoc, OS); 69625ffd83dbSDimitry Andric 69635ffd83dbSDimitry Andric return false; 69645ffd83dbSDimitry Andric } 69655ffd83dbSDimitry Andric 6966e8d8bef9SDimitry Andric /// parseDirectiveWhile 6967e8d8bef9SDimitry Andric /// ::= "while" expression 6968e8d8bef9SDimitry Andric /// body 6969e8d8bef9SDimitry Andric /// endm 6970e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) { 6971e8d8bef9SDimitry Andric const MCExpr *CondExpr; 6972e8d8bef9SDimitry Andric SMLoc CondLoc = getTok().getLoc(); 6973e8d8bef9SDimitry Andric if (parseExpression(CondExpr)) 6974e8d8bef9SDimitry Andric return true; 6975e8d8bef9SDimitry Andric 6976e8d8bef9SDimitry Andric // Lex the repeat definition. 6977e8d8bef9SDimitry Andric MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); 6978e8d8bef9SDimitry Andric if (!M) 6979e8d8bef9SDimitry Andric return true; 6980e8d8bef9SDimitry Andric 6981e8d8bef9SDimitry Andric // Macro instantiation is lexical, unfortunately. We construct a new buffer 6982e8d8bef9SDimitry Andric // to hold the macro body with substitutions. 6983e8d8bef9SDimitry Andric SmallString<256> Buf; 6984e8d8bef9SDimitry Andric raw_svector_ostream OS(Buf); 6985e8d8bef9SDimitry Andric int64_t Condition; 6986e8d8bef9SDimitry Andric if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr())) 6987e8d8bef9SDimitry Andric return Error(CondLoc, "expected absolute expression in 'while' directive"); 6988e8d8bef9SDimitry Andric if (Condition) { 6989e8d8bef9SDimitry Andric // Instantiate the macro, then resume at this directive to recheck the 6990e8d8bef9SDimitry Andric // condition. 6991bdd1243dSDimitry Andric if (expandMacro(OS, M->Body, std::nullopt, std::nullopt, M->Locals, 6992bdd1243dSDimitry Andric getTok().getLoc())) 6993e8d8bef9SDimitry Andric return true; 6994e8d8bef9SDimitry Andric instantiateMacroLikeBody(M, DirectiveLoc, /*ExitLoc=*/DirectiveLoc, OS); 6995e8d8bef9SDimitry Andric } 6996e8d8bef9SDimitry Andric 6997e8d8bef9SDimitry Andric return false; 6998e8d8bef9SDimitry Andric } 6999e8d8bef9SDimitry Andric 7000e8d8bef9SDimitry Andric /// parseDirectiveFor 7001e8d8bef9SDimitry Andric /// ::= ("for" | "irp") symbol [":" qualifier], <values> 7002e8d8bef9SDimitry Andric /// body 7003e8d8bef9SDimitry Andric /// endm 7004e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) { 70055ffd83dbSDimitry Andric MCAsmMacroParameter Parameter; 70065ffd83dbSDimitry Andric MCAsmMacroArguments A; 70075ffd83dbSDimitry Andric if (check(parseIdentifier(Parameter.Name), 7008e8d8bef9SDimitry Andric "expected identifier in '" + Dir + "' directive")) 7009e8d8bef9SDimitry Andric return true; 7010e8d8bef9SDimitry Andric 7011e8d8bef9SDimitry Andric // Parse optional qualifier (default value, or "req") 7012e8d8bef9SDimitry Andric if (parseOptionalToken(AsmToken::Colon)) { 7013e8d8bef9SDimitry Andric if (parseOptionalToken(AsmToken::Equal)) { 7014e8d8bef9SDimitry Andric // Default value 7015e8d8bef9SDimitry Andric SMLoc ParamLoc; 7016e8d8bef9SDimitry Andric 7017e8d8bef9SDimitry Andric ParamLoc = Lexer.getLoc(); 7018e8d8bef9SDimitry Andric if (parseMacroArgument(nullptr, Parameter.Value)) 7019e8d8bef9SDimitry Andric return true; 7020e8d8bef9SDimitry Andric } else { 7021e8d8bef9SDimitry Andric SMLoc QualLoc; 7022e8d8bef9SDimitry Andric StringRef Qualifier; 7023e8d8bef9SDimitry Andric 7024e8d8bef9SDimitry Andric QualLoc = Lexer.getLoc(); 7025e8d8bef9SDimitry Andric if (parseIdentifier(Qualifier)) 7026e8d8bef9SDimitry Andric return Error(QualLoc, "missing parameter qualifier for " 7027e8d8bef9SDimitry Andric "'" + 7028e8d8bef9SDimitry Andric Parameter.Name + "' in '" + Dir + 7029e8d8bef9SDimitry Andric "' directive"); 7030e8d8bef9SDimitry Andric 7031fe6060f1SDimitry Andric if (Qualifier.equals_insensitive("req")) 7032e8d8bef9SDimitry Andric Parameter.Required = true; 7033e8d8bef9SDimitry Andric else 7034e8d8bef9SDimitry Andric return Error(QualLoc, 7035e8d8bef9SDimitry Andric Qualifier + " is not a valid parameter qualifier for '" + 7036e8d8bef9SDimitry Andric Parameter.Name + "' in '" + Dir + "' directive"); 7037e8d8bef9SDimitry Andric } 7038e8d8bef9SDimitry Andric } 7039e8d8bef9SDimitry Andric 7040e8d8bef9SDimitry Andric if (parseToken(AsmToken::Comma, 7041e8d8bef9SDimitry Andric "expected comma in '" + Dir + "' directive") || 7042e8d8bef9SDimitry Andric parseToken(AsmToken::Less, 7043e8d8bef9SDimitry Andric "values in '" + Dir + 7044e8d8bef9SDimitry Andric "' directive must be enclosed in angle brackets")) 7045e8d8bef9SDimitry Andric return true; 7046e8d8bef9SDimitry Andric 7047e8d8bef9SDimitry Andric while (true) { 7048e8d8bef9SDimitry Andric A.emplace_back(); 7049e8d8bef9SDimitry Andric if (parseMacroArgument(&Parameter, A.back(), /*EndTok=*/AsmToken::Greater)) 7050e8d8bef9SDimitry Andric return addErrorSuffix(" in arguments for '" + Dir + "' directive"); 7051e8d8bef9SDimitry Andric 7052e8d8bef9SDimitry Andric // If we see a comma, continue, and allow line continuation. 7053e8d8bef9SDimitry Andric if (!parseOptionalToken(AsmToken::Comma)) 7054e8d8bef9SDimitry Andric break; 7055e8d8bef9SDimitry Andric parseOptionalToken(AsmToken::EndOfStatement); 7056e8d8bef9SDimitry Andric } 7057e8d8bef9SDimitry Andric 7058e8d8bef9SDimitry Andric if (parseToken(AsmToken::Greater, 7059e8d8bef9SDimitry Andric "values in '" + Dir + 7060e8d8bef9SDimitry Andric "' directive must be enclosed in angle brackets") || 706181ad6265SDimitry Andric parseEOL()) 70625ffd83dbSDimitry Andric return true; 70635ffd83dbSDimitry Andric 7064e8d8bef9SDimitry Andric // Lex the for definition. 70655ffd83dbSDimitry Andric MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); 70665ffd83dbSDimitry Andric if (!M) 70675ffd83dbSDimitry Andric return true; 70685ffd83dbSDimitry Andric 70695ffd83dbSDimitry Andric // Macro instantiation is lexical, unfortunately. We construct a new buffer 70705ffd83dbSDimitry Andric // to hold the macro body with substitutions. 70715ffd83dbSDimitry Andric SmallString<256> Buf; 70725ffd83dbSDimitry Andric raw_svector_ostream OS(Buf); 70735ffd83dbSDimitry Andric 70745ffd83dbSDimitry Andric for (const MCAsmMacroArgument &Arg : A) { 7075e8d8bef9SDimitry Andric if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc())) 70765ffd83dbSDimitry Andric return true; 70775ffd83dbSDimitry Andric } 70785ffd83dbSDimitry Andric 70795ffd83dbSDimitry Andric instantiateMacroLikeBody(M, DirectiveLoc, OS); 70805ffd83dbSDimitry Andric 70815ffd83dbSDimitry Andric return false; 70825ffd83dbSDimitry Andric } 70835ffd83dbSDimitry Andric 7084e8d8bef9SDimitry Andric /// parseDirectiveForc 7085e8d8bef9SDimitry Andric /// ::= ("forc" | "irpc") symbol, <string> 7086e8d8bef9SDimitry Andric /// body 7087e8d8bef9SDimitry Andric /// endm 7088e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) { 70895ffd83dbSDimitry Andric MCAsmMacroParameter Parameter; 70905ffd83dbSDimitry Andric 7091e8d8bef9SDimitry Andric std::string Argument; 70925ffd83dbSDimitry Andric if (check(parseIdentifier(Parameter.Name), 7093e8d8bef9SDimitry Andric "expected identifier in '" + Directive + "' directive") || 7094e8d8bef9SDimitry Andric parseToken(AsmToken::Comma, 7095e8d8bef9SDimitry Andric "expected comma in '" + Directive + "' directive")) 70965ffd83dbSDimitry Andric return true; 7097e8d8bef9SDimitry Andric if (parseAngleBracketString(Argument)) { 7098e8d8bef9SDimitry Andric // Match ml64.exe; treat all characters to end of statement as a string, 7099e8d8bef9SDimitry Andric // ignoring comment markers, then discard anything following a space (using 7100e8d8bef9SDimitry Andric // the C locale). 7101e8d8bef9SDimitry Andric Argument = parseStringTo(AsmToken::EndOfStatement); 7102e8d8bef9SDimitry Andric if (getTok().is(AsmToken::EndOfStatement)) 7103e8d8bef9SDimitry Andric Argument += getTok().getString(); 7104e8d8bef9SDimitry Andric size_t End = 0; 7105e8d8bef9SDimitry Andric for (; End < Argument.size(); ++End) { 7106e8d8bef9SDimitry Andric if (isSpace(Argument[End])) 7107e8d8bef9SDimitry Andric break; 7108e8d8bef9SDimitry Andric } 7109e8d8bef9SDimitry Andric Argument.resize(End); 7110e8d8bef9SDimitry Andric } 711181ad6265SDimitry Andric if (parseEOL()) 71125ffd83dbSDimitry Andric return true; 71135ffd83dbSDimitry Andric 71145ffd83dbSDimitry Andric // Lex the irpc definition. 71155ffd83dbSDimitry Andric MCAsmMacro *M = parseMacroLikeBody(DirectiveLoc); 71165ffd83dbSDimitry Andric if (!M) 71175ffd83dbSDimitry Andric return true; 71185ffd83dbSDimitry Andric 71195ffd83dbSDimitry Andric // Macro instantiation is lexical, unfortunately. We construct a new buffer 71205ffd83dbSDimitry Andric // to hold the macro body with substitutions. 71215ffd83dbSDimitry Andric SmallString<256> Buf; 71225ffd83dbSDimitry Andric raw_svector_ostream OS(Buf); 71235ffd83dbSDimitry Andric 7124e8d8bef9SDimitry Andric StringRef Values(Argument); 71255ffd83dbSDimitry Andric for (std::size_t I = 0, End = Values.size(); I != End; ++I) { 71265ffd83dbSDimitry Andric MCAsmMacroArgument Arg; 71275ffd83dbSDimitry Andric Arg.emplace_back(AsmToken::Identifier, Values.slice(I, I + 1)); 71285ffd83dbSDimitry Andric 7129e8d8bef9SDimitry Andric if (expandMacro(OS, M->Body, Parameter, Arg, M->Locals, getTok().getLoc())) 71305ffd83dbSDimitry Andric return true; 71315ffd83dbSDimitry Andric } 71325ffd83dbSDimitry Andric 71335ffd83dbSDimitry Andric instantiateMacroLikeBody(M, DirectiveLoc, OS); 71345ffd83dbSDimitry Andric 71355ffd83dbSDimitry Andric return false; 71365ffd83dbSDimitry Andric } 71375ffd83dbSDimitry Andric 71385ffd83dbSDimitry Andric bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info, 71395ffd83dbSDimitry Andric size_t Len) { 71405ffd83dbSDimitry Andric const MCExpr *Value; 71415ffd83dbSDimitry Andric SMLoc ExprLoc = getLexer().getLoc(); 71425ffd83dbSDimitry Andric if (parseExpression(Value)) 71435ffd83dbSDimitry Andric return true; 71445ffd83dbSDimitry Andric const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); 71455ffd83dbSDimitry Andric if (!MCE) 71465ffd83dbSDimitry Andric return Error(ExprLoc, "unexpected expression in _emit"); 71475ffd83dbSDimitry Andric uint64_t IntValue = MCE->getValue(); 71485ffd83dbSDimitry Andric if (!isUInt<8>(IntValue) && !isInt<8>(IntValue)) 71495ffd83dbSDimitry Andric return Error(ExprLoc, "literal value out of range for directive"); 71505ffd83dbSDimitry Andric 71515ffd83dbSDimitry Andric Info.AsmRewrites->emplace_back(AOK_Emit, IDLoc, Len); 71525ffd83dbSDimitry Andric return false; 71535ffd83dbSDimitry Andric } 71545ffd83dbSDimitry Andric 71555ffd83dbSDimitry Andric bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) { 71565ffd83dbSDimitry Andric const MCExpr *Value; 71575ffd83dbSDimitry Andric SMLoc ExprLoc = getLexer().getLoc(); 71585ffd83dbSDimitry Andric if (parseExpression(Value)) 71595ffd83dbSDimitry Andric return true; 71605ffd83dbSDimitry Andric const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value); 71615ffd83dbSDimitry Andric if (!MCE) 71625ffd83dbSDimitry Andric return Error(ExprLoc, "unexpected expression in align"); 71635ffd83dbSDimitry Andric uint64_t IntValue = MCE->getValue(); 71645ffd83dbSDimitry Andric if (!isPowerOf2_64(IntValue)) 71655ffd83dbSDimitry Andric return Error(ExprLoc, "literal value not a power of two greater then zero"); 71665ffd83dbSDimitry Andric 71675ffd83dbSDimitry Andric Info.AsmRewrites->emplace_back(AOK_Align, IDLoc, 5, Log2_64(IntValue)); 71685ffd83dbSDimitry Andric return false; 71695ffd83dbSDimitry Andric } 71705ffd83dbSDimitry Andric 7171e8d8bef9SDimitry Andric bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) { 7172e8d8bef9SDimitry Andric const SMLoc Loc = getLexer().getLoc(); 7173e8d8bef9SDimitry Andric std::string RadixStringRaw = parseStringTo(AsmToken::EndOfStatement); 7174e8d8bef9SDimitry Andric StringRef RadixString = StringRef(RadixStringRaw).trim(); 7175e8d8bef9SDimitry Andric unsigned Radix; 7176e8d8bef9SDimitry Andric if (RadixString.getAsInteger(10, Radix)) { 7177e8d8bef9SDimitry Andric return Error(Loc, 7178e8d8bef9SDimitry Andric "radix must be a decimal number in the range 2 to 16; was " + 7179e8d8bef9SDimitry Andric RadixString); 7180e8d8bef9SDimitry Andric } 7181e8d8bef9SDimitry Andric if (Radix < 2 || Radix > 16) 7182e8d8bef9SDimitry Andric return Error(Loc, "radix must be in the range 2 to 16; was " + 7183e8d8bef9SDimitry Andric std::to_string(Radix)); 7184e8d8bef9SDimitry Andric getLexer().setMasmDefaultRadix(Radix); 7185e8d8bef9SDimitry Andric return false; 7186e8d8bef9SDimitry Andric } 7187e8d8bef9SDimitry Andric 7188e8d8bef9SDimitry Andric /// parseDirectiveEcho 7189e8d8bef9SDimitry Andric /// ::= "echo" message 7190fe6060f1SDimitry Andric bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) { 7191e8d8bef9SDimitry Andric std::string Message = parseStringTo(AsmToken::EndOfStatement); 7192e8d8bef9SDimitry Andric llvm::outs() << Message; 7193e8d8bef9SDimitry Andric if (!StringRef(Message).endswith("\n")) 7194e8d8bef9SDimitry Andric llvm::outs() << '\n'; 71955ffd83dbSDimitry Andric return false; 71965ffd83dbSDimitry Andric } 71975ffd83dbSDimitry Andric 71985ffd83dbSDimitry Andric // We are comparing pointers, but the pointers are relative to a single string. 71995ffd83dbSDimitry Andric // Thus, this should always be deterministic. 72005ffd83dbSDimitry Andric static int rewritesSort(const AsmRewrite *AsmRewriteA, 72015ffd83dbSDimitry Andric const AsmRewrite *AsmRewriteB) { 72025ffd83dbSDimitry Andric if (AsmRewriteA->Loc.getPointer() < AsmRewriteB->Loc.getPointer()) 72035ffd83dbSDimitry Andric return -1; 72045ffd83dbSDimitry Andric if (AsmRewriteB->Loc.getPointer() < AsmRewriteA->Loc.getPointer()) 72055ffd83dbSDimitry Andric return 1; 72065ffd83dbSDimitry Andric 72075ffd83dbSDimitry Andric // It's possible to have a SizeDirective, Imm/ImmPrefix and an Input/Output 72085ffd83dbSDimitry Andric // rewrite to the same location. Make sure the SizeDirective rewrite is 72095ffd83dbSDimitry Andric // performed first, then the Imm/ImmPrefix and finally the Input/Output. This 72105ffd83dbSDimitry Andric // ensures the sort algorithm is stable. 72115ffd83dbSDimitry Andric if (AsmRewritePrecedence[AsmRewriteA->Kind] > 72125ffd83dbSDimitry Andric AsmRewritePrecedence[AsmRewriteB->Kind]) 72135ffd83dbSDimitry Andric return -1; 72145ffd83dbSDimitry Andric 72155ffd83dbSDimitry Andric if (AsmRewritePrecedence[AsmRewriteA->Kind] < 72165ffd83dbSDimitry Andric AsmRewritePrecedence[AsmRewriteB->Kind]) 72175ffd83dbSDimitry Andric return 1; 72185ffd83dbSDimitry Andric llvm_unreachable("Unstable rewrite sort."); 72195ffd83dbSDimitry Andric } 72205ffd83dbSDimitry Andric 7221e8d8bef9SDimitry Andric bool MasmParser::defineMacro(StringRef Name, StringRef Value) { 7222e8d8bef9SDimitry Andric Variable &Var = Variables[Name.lower()]; 7223e8d8bef9SDimitry Andric if (Var.Name.empty()) { 7224e8d8bef9SDimitry Andric Var.Name = Name; 7225fe6060f1SDimitry Andric } else if (Var.Redefinable == Variable::NOT_REDEFINABLE) { 7226fe6060f1SDimitry Andric return Error(SMLoc(), "invalid variable redefinition"); 7227fe6060f1SDimitry Andric } else if (Var.Redefinable == Variable::WARN_ON_REDEFINITION && 7228fe6060f1SDimitry Andric Warning(SMLoc(), "redefining '" + Name + 7229fe6060f1SDimitry Andric "', already defined on the command line")) { 7230fe6060f1SDimitry Andric return true; 7231e8d8bef9SDimitry Andric } 7232fe6060f1SDimitry Andric Var.Redefinable = Variable::WARN_ON_REDEFINITION; 7233e8d8bef9SDimitry Andric Var.IsText = true; 7234e8d8bef9SDimitry Andric Var.TextValue = Value.str(); 7235e8d8bef9SDimitry Andric return false; 72365ffd83dbSDimitry Andric } 72375ffd83dbSDimitry Andric 7238e8d8bef9SDimitry Andric bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info) const { 7239e8d8bef9SDimitry Andric const std::pair<StringRef, StringRef> BaseMember = Name.split('.'); 7240e8d8bef9SDimitry Andric const StringRef Base = BaseMember.first, Member = BaseMember.second; 7241e8d8bef9SDimitry Andric return lookUpField(Base, Member, Info); 7242e8d8bef9SDimitry Andric } 7243e8d8bef9SDimitry Andric 7244e8d8bef9SDimitry Andric bool MasmParser::lookUpField(StringRef Base, StringRef Member, 7245e8d8bef9SDimitry Andric AsmFieldInfo &Info) const { 72465ffd83dbSDimitry Andric if (Base.empty()) 72475ffd83dbSDimitry Andric return true; 72485ffd83dbSDimitry Andric 7249e8d8bef9SDimitry Andric AsmFieldInfo BaseInfo; 7250e8d8bef9SDimitry Andric if (Base.contains('.') && !lookUpField(Base, BaseInfo)) 7251e8d8bef9SDimitry Andric Base = BaseInfo.Type.Name; 72525ffd83dbSDimitry Andric 72535ffd83dbSDimitry Andric auto StructIt = Structs.find(Base.lower()); 7254e8d8bef9SDimitry Andric auto TypeIt = KnownType.find(Base.lower()); 7255e8d8bef9SDimitry Andric if (TypeIt != KnownType.end()) { 7256e8d8bef9SDimitry Andric StructIt = Structs.find(TypeIt->second.Name.lower()); 7257e8d8bef9SDimitry Andric } 72585ffd83dbSDimitry Andric if (StructIt != Structs.end()) 7259e8d8bef9SDimitry Andric return lookUpField(StructIt->second, Member, Info); 72605ffd83dbSDimitry Andric 72615ffd83dbSDimitry Andric return true; 72625ffd83dbSDimitry Andric } 72635ffd83dbSDimitry Andric 72645ffd83dbSDimitry Andric bool MasmParser::lookUpField(const StructInfo &Structure, StringRef Member, 7265e8d8bef9SDimitry Andric AsmFieldInfo &Info) const { 72665ffd83dbSDimitry Andric if (Member.empty()) { 7267e8d8bef9SDimitry Andric Info.Type.Name = Structure.Name; 7268e8d8bef9SDimitry Andric Info.Type.Size = Structure.Size; 7269e8d8bef9SDimitry Andric Info.Type.ElementSize = Structure.Size; 7270e8d8bef9SDimitry Andric Info.Type.Length = 1; 72715ffd83dbSDimitry Andric return false; 72725ffd83dbSDimitry Andric } 72735ffd83dbSDimitry Andric 72745ffd83dbSDimitry Andric std::pair<StringRef, StringRef> Split = Member.split('.'); 72755ffd83dbSDimitry Andric const StringRef FieldName = Split.first, FieldMember = Split.second; 72765ffd83dbSDimitry Andric 72775ffd83dbSDimitry Andric auto StructIt = Structs.find(FieldName.lower()); 72785ffd83dbSDimitry Andric if (StructIt != Structs.end()) 7279e8d8bef9SDimitry Andric return lookUpField(StructIt->second, FieldMember, Info); 72805ffd83dbSDimitry Andric 72815ffd83dbSDimitry Andric auto FieldIt = Structure.FieldsByName.find(FieldName.lower()); 72825ffd83dbSDimitry Andric if (FieldIt == Structure.FieldsByName.end()) 72835ffd83dbSDimitry Andric return true; 72845ffd83dbSDimitry Andric 72855ffd83dbSDimitry Andric const FieldInfo &Field = Structure.Fields[FieldIt->second]; 72865ffd83dbSDimitry Andric if (FieldMember.empty()) { 7287e8d8bef9SDimitry Andric Info.Offset += Field.Offset; 7288e8d8bef9SDimitry Andric Info.Type.Size = Field.SizeOf; 7289e8d8bef9SDimitry Andric Info.Type.ElementSize = Field.Type; 7290e8d8bef9SDimitry Andric Info.Type.Length = Field.LengthOf; 72915ffd83dbSDimitry Andric if (Field.Contents.FT == FT_STRUCT) 7292e8d8bef9SDimitry Andric Info.Type.Name = Field.Contents.StructInfo.Structure.Name; 7293e8d8bef9SDimitry Andric else 7294e8d8bef9SDimitry Andric Info.Type.Name = ""; 72955ffd83dbSDimitry Andric return false; 72965ffd83dbSDimitry Andric } 72975ffd83dbSDimitry Andric 72985ffd83dbSDimitry Andric if (Field.Contents.FT != FT_STRUCT) 72995ffd83dbSDimitry Andric return true; 73005ffd83dbSDimitry Andric const StructFieldInfo &StructInfo = Field.Contents.StructInfo; 73015ffd83dbSDimitry Andric 7302e8d8bef9SDimitry Andric if (lookUpField(StructInfo.Structure, FieldMember, Info)) 73035ffd83dbSDimitry Andric return true; 73045ffd83dbSDimitry Andric 7305e8d8bef9SDimitry Andric Info.Offset += Field.Offset; 73065ffd83dbSDimitry Andric return false; 73075ffd83dbSDimitry Andric } 73085ffd83dbSDimitry Andric 7309e8d8bef9SDimitry Andric bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info) const { 7310e8d8bef9SDimitry Andric unsigned Size = StringSwitch<unsigned>(Name) 7311e8d8bef9SDimitry Andric .CasesLower("byte", "db", "sbyte", 1) 7312e8d8bef9SDimitry Andric .CasesLower("word", "dw", "sword", 2) 7313e8d8bef9SDimitry Andric .CasesLower("dword", "dd", "sdword", 4) 7314e8d8bef9SDimitry Andric .CasesLower("fword", "df", 6) 7315e8d8bef9SDimitry Andric .CasesLower("qword", "dq", "sqword", 8) 7316e8d8bef9SDimitry Andric .CaseLower("real4", 4) 7317e8d8bef9SDimitry Andric .CaseLower("real8", 8) 7318e8d8bef9SDimitry Andric .CaseLower("real10", 10) 7319e8d8bef9SDimitry Andric .Default(0); 7320e8d8bef9SDimitry Andric if (Size) { 7321e8d8bef9SDimitry Andric Info.Name = Name; 7322e8d8bef9SDimitry Andric Info.ElementSize = Size; 7323e8d8bef9SDimitry Andric Info.Length = 1; 7324e8d8bef9SDimitry Andric Info.Size = Size; 7325e8d8bef9SDimitry Andric return false; 7326e8d8bef9SDimitry Andric } 7327e8d8bef9SDimitry Andric 7328e8d8bef9SDimitry Andric auto StructIt = Structs.find(Name.lower()); 7329e8d8bef9SDimitry Andric if (StructIt != Structs.end()) { 7330e8d8bef9SDimitry Andric const StructInfo &Structure = StructIt->second; 7331e8d8bef9SDimitry Andric Info.Name = Name; 7332e8d8bef9SDimitry Andric Info.ElementSize = Structure.Size; 7333e8d8bef9SDimitry Andric Info.Length = 1; 7334e8d8bef9SDimitry Andric Info.Size = Structure.Size; 7335e8d8bef9SDimitry Andric return false; 7336e8d8bef9SDimitry Andric } 7337e8d8bef9SDimitry Andric 7338e8d8bef9SDimitry Andric return true; 7339e8d8bef9SDimitry Andric } 7340e8d8bef9SDimitry Andric 73415ffd83dbSDimitry Andric bool MasmParser::parseMSInlineAsm( 7342fe6060f1SDimitry Andric std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, 7343fe6060f1SDimitry Andric SmallVectorImpl<std::pair<void *, bool>> &OpDecls, 73445ffd83dbSDimitry Andric SmallVectorImpl<std::string> &Constraints, 73455ffd83dbSDimitry Andric SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII, 73465ffd83dbSDimitry Andric const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) { 73475ffd83dbSDimitry Andric SmallVector<void *, 4> InputDecls; 73485ffd83dbSDimitry Andric SmallVector<void *, 4> OutputDecls; 73495ffd83dbSDimitry Andric SmallVector<bool, 4> InputDeclsAddressOf; 73505ffd83dbSDimitry Andric SmallVector<bool, 4> OutputDeclsAddressOf; 73515ffd83dbSDimitry Andric SmallVector<std::string, 4> InputConstraints; 73525ffd83dbSDimitry Andric SmallVector<std::string, 4> OutputConstraints; 73535ffd83dbSDimitry Andric SmallVector<unsigned, 4> ClobberRegs; 73545ffd83dbSDimitry Andric 73555ffd83dbSDimitry Andric SmallVector<AsmRewrite, 4> AsmStrRewrites; 73565ffd83dbSDimitry Andric 73575ffd83dbSDimitry Andric // Prime the lexer. 73585ffd83dbSDimitry Andric Lex(); 73595ffd83dbSDimitry Andric 73605ffd83dbSDimitry Andric // While we have input, parse each statement. 73615ffd83dbSDimitry Andric unsigned InputIdx = 0; 73625ffd83dbSDimitry Andric unsigned OutputIdx = 0; 73635ffd83dbSDimitry Andric while (getLexer().isNot(AsmToken::Eof)) { 73645ffd83dbSDimitry Andric // Parse curly braces marking block start/end. 73655ffd83dbSDimitry Andric if (parseCurlyBlockScope(AsmStrRewrites)) 73665ffd83dbSDimitry Andric continue; 73675ffd83dbSDimitry Andric 73685ffd83dbSDimitry Andric ParseStatementInfo Info(&AsmStrRewrites); 73695ffd83dbSDimitry Andric bool StatementErr = parseStatement(Info, &SI); 73705ffd83dbSDimitry Andric 73715ffd83dbSDimitry Andric if (StatementErr || Info.ParseError) { 73725ffd83dbSDimitry Andric // Emit pending errors if any exist. 73735ffd83dbSDimitry Andric printPendingErrors(); 73745ffd83dbSDimitry Andric return true; 73755ffd83dbSDimitry Andric } 73765ffd83dbSDimitry Andric 73775ffd83dbSDimitry Andric // No pending error should exist here. 73785ffd83dbSDimitry Andric assert(!hasPendingError() && "unexpected error from parseStatement"); 73795ffd83dbSDimitry Andric 73805ffd83dbSDimitry Andric if (Info.Opcode == ~0U) 73815ffd83dbSDimitry Andric continue; 73825ffd83dbSDimitry Andric 73835ffd83dbSDimitry Andric const MCInstrDesc &Desc = MII->get(Info.Opcode); 73845ffd83dbSDimitry Andric 73855ffd83dbSDimitry Andric // Build the list of clobbers, outputs and inputs. 73865ffd83dbSDimitry Andric for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) { 73875ffd83dbSDimitry Andric MCParsedAsmOperand &Operand = *Info.ParsedOperands[i]; 73885ffd83dbSDimitry Andric 73895ffd83dbSDimitry Andric // Register operand. 73905ffd83dbSDimitry Andric if (Operand.isReg() && !Operand.needAddressOf() && 73915ffd83dbSDimitry Andric !getTargetParser().OmitRegisterFromClobberLists(Operand.getReg())) { 73925ffd83dbSDimitry Andric unsigned NumDefs = Desc.getNumDefs(); 73935ffd83dbSDimitry Andric // Clobber. 73945ffd83dbSDimitry Andric if (NumDefs && Operand.getMCOperandNum() < NumDefs) 73955ffd83dbSDimitry Andric ClobberRegs.push_back(Operand.getReg()); 73965ffd83dbSDimitry Andric continue; 73975ffd83dbSDimitry Andric } 73985ffd83dbSDimitry Andric 73995ffd83dbSDimitry Andric // Expr/Input or Output. 74005ffd83dbSDimitry Andric StringRef SymName = Operand.getSymName(); 74015ffd83dbSDimitry Andric if (SymName.empty()) 74025ffd83dbSDimitry Andric continue; 74035ffd83dbSDimitry Andric 74045ffd83dbSDimitry Andric void *OpDecl = Operand.getOpDecl(); 74055ffd83dbSDimitry Andric if (!OpDecl) 74065ffd83dbSDimitry Andric continue; 74075ffd83dbSDimitry Andric 74085ffd83dbSDimitry Andric StringRef Constraint = Operand.getConstraint(); 74095ffd83dbSDimitry Andric if (Operand.isImm()) { 74105ffd83dbSDimitry Andric // Offset as immediate. 74115ffd83dbSDimitry Andric if (Operand.isOffsetOfLocal()) 74125ffd83dbSDimitry Andric Constraint = "r"; 74135ffd83dbSDimitry Andric else 74145ffd83dbSDimitry Andric Constraint = "i"; 74155ffd83dbSDimitry Andric } 74165ffd83dbSDimitry Andric 74175ffd83dbSDimitry Andric bool isOutput = (i == 1) && Desc.mayStore(); 74185ffd83dbSDimitry Andric SMLoc Start = SMLoc::getFromPointer(SymName.data()); 74195ffd83dbSDimitry Andric if (isOutput) { 74205ffd83dbSDimitry Andric ++InputIdx; 74215ffd83dbSDimitry Andric OutputDecls.push_back(OpDecl); 74225ffd83dbSDimitry Andric OutputDeclsAddressOf.push_back(Operand.needAddressOf()); 74235ffd83dbSDimitry Andric OutputConstraints.push_back(("=" + Constraint).str()); 74245ffd83dbSDimitry Andric AsmStrRewrites.emplace_back(AOK_Output, Start, SymName.size()); 74255ffd83dbSDimitry Andric } else { 74265ffd83dbSDimitry Andric InputDecls.push_back(OpDecl); 74275ffd83dbSDimitry Andric InputDeclsAddressOf.push_back(Operand.needAddressOf()); 74285ffd83dbSDimitry Andric InputConstraints.push_back(Constraint.str()); 7429bdd1243dSDimitry Andric if (Desc.operands()[i - 1].isBranchTarget()) 74305ffd83dbSDimitry Andric AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size()); 74315ffd83dbSDimitry Andric else 74325ffd83dbSDimitry Andric AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size()); 74335ffd83dbSDimitry Andric } 74345ffd83dbSDimitry Andric } 74355ffd83dbSDimitry Andric 74365ffd83dbSDimitry Andric // Consider implicit defs to be clobbers. Think of cpuid and push. 7437bdd1243dSDimitry Andric llvm::append_range(ClobberRegs, Desc.implicit_defs()); 74385ffd83dbSDimitry Andric } 74395ffd83dbSDimitry Andric 74405ffd83dbSDimitry Andric // Set the number of Outputs and Inputs. 74415ffd83dbSDimitry Andric NumOutputs = OutputDecls.size(); 74425ffd83dbSDimitry Andric NumInputs = InputDecls.size(); 74435ffd83dbSDimitry Andric 74445ffd83dbSDimitry Andric // Set the unique clobbers. 74455ffd83dbSDimitry Andric array_pod_sort(ClobberRegs.begin(), ClobberRegs.end()); 74465ffd83dbSDimitry Andric ClobberRegs.erase(std::unique(ClobberRegs.begin(), ClobberRegs.end()), 74475ffd83dbSDimitry Andric 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); 74775ffd83dbSDimitry Andric for (auto it = AsmStrRewrites.begin(); it != AsmStrRewrites.end(); ++it) { 74785ffd83dbSDimitry Andric const AsmRewrite &AR = *it; 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( 75215ffd83dbSDimitry Andric it, 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 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 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> 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. 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