74typedef std::vector<AsmToken> MCAsmMacroArgument;
75typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
78struct MacroInstantiation {
80 SMLoc InstantiationLoc;
89 size_t CondStackDepth;
92struct ParseStatementInfo {
97 unsigned Opcode = ~0
U;
100 bool ParseError =
false;
103 std::optional<std::string> ExitValue;
105 SmallVectorImpl<AsmRewrite> *AsmRewrites =
nullptr;
107 ParseStatementInfo() =
delete;
108 ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
109 : AsmRewrites(rewrites) {}
121 bool IsUnion =
false;
122 bool Initializable =
true;
123 unsigned Alignment = 0;
124 unsigned AlignmentSize = 0;
125 unsigned NextOffset = 0;
127 std::vector<FieldInfo> Fields;
128 StringMap<size_t> FieldsByName;
130 FieldInfo &addField(StringRef FieldName, FieldType FT,
131 unsigned FieldAlignmentSize);
133 StructInfo() =
default;
134 StructInfo(StringRef
StructName,
bool Union,
unsigned AlignmentValue);
142struct StructInitializer;
146 IntFieldInfo() =
default;
150struct RealFieldInfo {
153 RealFieldInfo() =
default;
157struct StructFieldInfo {
158 std::vector<StructInitializer> Initializers;
159 StructInfo Structure;
161 StructFieldInfo() =
default;
162 StructFieldInfo(std::vector<StructInitializer> V, StructInfo S);
165class FieldInitializer {
169 IntFieldInfo IntInfo;
170 RealFieldInfo RealInfo;
171 StructFieldInfo StructInfo;
175 FieldInitializer(FieldType FT);
179 FieldInitializer(std::vector<StructInitializer> &&Initializers,
180 struct StructInfo Structure);
182 FieldInitializer(
const FieldInitializer &Initializer);
183 FieldInitializer(FieldInitializer &&Initializer);
185 FieldInitializer &operator=(
const FieldInitializer &Initializer);
186 FieldInitializer &operator=(FieldInitializer &&Initializer);
189struct StructInitializer {
190 std::vector<FieldInitializer> FieldInitializers;
201 unsigned LengthOf = 0;
206 FieldInitializer Contents;
208 FieldInfo(FieldType FT) : Contents(FT) {}
211StructFieldInfo::StructFieldInfo(std::vector<StructInitializer> V,
213 Initializers = std::move(V);
214 Structure = std::move(S);
217StructInfo::StructInfo(StringRef
StructName,
bool Union,
218 unsigned AlignmentValue)
221FieldInfo &StructInfo::addField(
StringRef FieldName, FieldType FT,
222 unsigned FieldAlignmentSize) {
223 if (!FieldName.
empty())
224 FieldsByName[FieldName.
lower()] = Fields.size();
225 Fields.emplace_back(FT);
226 FieldInfo &
Field = Fields.back();
228 llvm::alignTo(NextOffset, std::min(Alignment, FieldAlignmentSize));
232 AlignmentSize = std::max(AlignmentSize, FieldAlignmentSize);
236FieldInitializer::~FieldInitializer() {
239 IntInfo.~IntFieldInfo();
242 RealInfo.~RealFieldInfo();
245 StructInfo.~StructFieldInfo();
250FieldInitializer::FieldInitializer(FieldType FT) : FT(FT) {
253 new (&IntInfo) IntFieldInfo();
256 new (&RealInfo) RealFieldInfo();
259 new (&StructInfo) StructFieldInfo();
266 new (&IntInfo) IntFieldInfo(std::move(
Values));
271 new (&RealInfo) RealFieldInfo(std::move(AsIntValues));
274FieldInitializer::FieldInitializer(
275 std::vector<StructInitializer> &&Initializers,
struct StructInfo Structure)
277 new (&StructInfo) StructFieldInfo(std::move(Initializers), Structure);
280FieldInitializer::FieldInitializer(
const FieldInitializer &Initializer)
281 : FT(Initializer.FT) {
284 new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
287 new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
290 new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
295FieldInitializer::FieldInitializer(FieldInitializer &&Initializer)
296 : FT(Initializer.FT) {
299 new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
302 new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
305 new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
311FieldInitializer::operator=(
const FieldInitializer &Initializer) {
312 if (FT != Initializer.FT) {
315 IntInfo.~IntFieldInfo();
318 RealInfo.~RealFieldInfo();
321 StructInfo.~StructFieldInfo();
328 IntInfo = Initializer.IntInfo;
331 RealInfo = Initializer.RealInfo;
334 StructInfo = Initializer.StructInfo;
340FieldInitializer &FieldInitializer::operator=(FieldInitializer &&Initializer) {
341 if (FT != Initializer.FT) {
344 IntInfo.~IntFieldInfo();
347 RealInfo.~RealFieldInfo();
350 StructInfo.~StructFieldInfo();
357 IntInfo = Initializer.IntInfo;
360 RealInfo = Initializer.RealInfo;
363 StructInfo = Initializer.StructInfo;
372class MasmParser :
public MCAsmParser {
375 void *SavedDiagContext;
376 std::unique_ptr<MCAsmParserExtension> PlatformParser;
385 BitVector EndStatementAtEOFStack;
387 AsmCond TheCondState;
388 std::vector<AsmCond> TheCondStack;
393 StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
397 enum RedefinableKind { NOT_REDEFINABLE, WARN_ON_REDEFINITION, REDEFINABLE };
400 RedefinableKind Redefinable = REDEFINABLE;
402 std::string TextValue;
404 StringMap<Variable> Variables;
410 StringMap<StructInfo> Structs;
413 StringMap<AsmTypeInfo> KnownType;
416 std::vector<MacroInstantiation*> ActiveMacros;
419 std::deque<MCAsmMacro> MacroLikeBodies;
422 unsigned NumOfMacroInstantiations;
425 struct CppHashInfoTy {
430 CppHashInfoTy() : LineNumber(0), Buf(0) {}
432 CppHashInfoTy CppHashInfo;
435 StringRef FirstCppHashFilename;
442 unsigned AssemblerDialect = 1U;
445 bool ParsingMSInlineAsm =
false;
448 unsigned AngleBracketDepth = 0
U;
451 uint16_t LocalCounter = 0;
454 MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
455 const MCAsmInfo &MAI,
struct tm TM,
unsigned CB = 0);
456 MasmParser(
const MasmParser &) =
delete;
457 MasmParser &operator=(
const MasmParser &) =
delete;
458 ~MasmParser()
override;
460 bool Run(
bool NoInitialTextSection,
bool NoFinalize =
false)
override;
462 void addDirectiveHandler(StringRef Directive,
463 ExtensionDirectiveHandler Handler)
override {
464 ExtensionDirectiveMap[Directive] = std::move(Handler);
465 DirectiveKindMap.try_emplace(Directive, DK_HANDLER_DIRECTIVE);
468 void addAliasForDirective(StringRef Directive, StringRef Alias)
override {
469 DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
475 unsigned getAssemblerDialect()
override {
476 if (AssemblerDialect == ~0U)
477 return MAI.getAssemblerDialect();
479 return AssemblerDialect;
481 void setAssemblerDialect(
unsigned i)
override {
482 AssemblerDialect = i;
485 void Note(SMLoc L,
const Twine &
Msg, SMRange
Range = {})
override;
487 bool printError(SMLoc L,
const Twine &
Msg, SMRange
Range = {})
override;
489 enum ExpandKind { ExpandMacros, DoNotExpandMacros };
490 const AsmToken &Lex(ExpandKind ExpandNextToken);
491 const AsmToken &Lex()
override {
return Lex(ExpandMacros); }
493 void setParsingMSInlineAsm(
bool V)
override {
494 ParsingMSInlineAsm =
V;
497 Lexer.setLexMasmIntegers(V);
499 bool isParsingMSInlineAsm()
override {
return ParsingMSInlineAsm; }
501 bool isParsingMasm()
const override {
return true; }
503 bool defineMacro(StringRef Name, StringRef
Value)
override;
505 bool lookUpField(StringRef Name, AsmFieldInfo &Info)
const override;
506 bool lookUpField(StringRef
Base, StringRef Member,
507 AsmFieldInfo &Info)
const override;
509 bool lookUpType(StringRef Name, AsmTypeInfo &Info)
const override;
511 bool parseMSInlineAsm(std::string &AsmString,
unsigned &NumOutputs,
513 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
514 SmallVectorImpl<std::string> &Constraints,
515 SmallVectorImpl<std::string> &Clobbers,
516 const MCInstrInfo *MII, MCInstPrinter *IP,
517 MCAsmParserSemaCallback &SI)
override;
519 bool parseExpression(
const MCExpr *&Res);
520 bool parseExpression(
const MCExpr *&Res, SMLoc &EndLoc)
override;
521 bool parsePrimaryExpr(
const MCExpr *&Res, SMLoc &EndLoc,
522 AsmTypeInfo *TypeInfo)
override;
523 bool parseParenExpression(
const MCExpr *&Res, SMLoc &EndLoc)
override;
524 bool parseAbsoluteExpression(int64_t &Res)
override;
528 bool parseRealValue(
const fltSemantics &Semantics, APInt &Res);
532 enum IdentifierPositionKind { StandardPosition, StartOfStatement };
533 bool parseIdentifier(StringRef &Res, IdentifierPositionKind Position);
534 bool parseIdentifier(StringRef &Res)
override {
535 return parseIdentifier(Res, StandardPosition);
537 void eatToEndOfStatement()
override;
539 bool checkForValidSection()
override;
545 const AsmToken peekTok(
bool ShouldSkipSpace =
true);
547 bool parseStatement(ParseStatementInfo &Info,
548 MCAsmParserSemaCallback *SI);
549 bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
550 bool parseCppHashLineFilenameComment(SMLoc L);
552 bool expandMacro(raw_svector_ostream &OS, StringRef Body,
555 const std::vector<std::string> &Locals, SMLoc L);
558 bool isInsideMacroInstantiation() {
return !ActiveMacros.empty();}
564 bool handleMacroEntry(
565 const MCAsmMacro *M, SMLoc NameLoc,
572 bool handleMacroInvocation(
const MCAsmMacro *M, SMLoc NameLoc);
575 void handleMacroExit();
579 parseMacroArgument(
const MCAsmMacroParameter *MP, MCAsmMacroArgument &MA,
584 parseMacroArguments(
const MCAsmMacro *M, MCAsmMacroArguments &
A,
587 void printMacroInstantiations();
589 bool expandStatement(SMLoc Loc);
592 SMRange
Range = {})
const {
598 bool lookUpField(
const StructInfo &Structure, StringRef Member,
599 AsmFieldInfo &Info)
const;
602 bool enterIncludeFile(
const std::string &
Filename);
610 void jumpToLoc(SMLoc Loc,
unsigned InBuffer = 0,
611 bool EndStatementAtEOF =
true);
623 StringRef parseStringToEndOfStatement()
override;
625 bool parseTextItem(std::string &
Data);
626 bool parseTextList(std::string &Result, StringRef IDVal);
627 bool setTextVariable(Variable &Var, StringRef Name, StringRef
Value,
628 SMLoc NameLoc, Variable::RedefinableKind Redefinable);
633 bool parseBinOpRHS(
unsigned Precedence,
const MCExpr *&Res, SMLoc &EndLoc);
634 bool parseParenExpr(
const MCExpr *&Res, SMLoc &EndLoc);
635 bool parseBracketExpr(
const MCExpr *&Res, SMLoc &EndLoc);
640 DK_HANDLER_DIRECTIVE,
731 StringMap<DirectiveKind> DirectiveKindMap;
733 bool isMacroLikeDirective();
760 StringMap<BuiltinSymbol> BuiltinSymbolMap;
762 const MCExpr *evaluateBuiltinValue(BuiltinSymbol Symbol, SMLoc StartLoc);
764 std::optional<std::string> evaluateBuiltinTextMacro(BuiltinSymbol Symbol,
768 enum BuiltinFunction {
775 StringMap<BuiltinFunction> BuiltinFunctionMap;
777 bool evaluateBuiltinMacroFunction(BuiltinFunction
Function, StringRef Name,
781 bool parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated);
784 bool emitIntValue(
const MCExpr *
Value,
unsigned Size);
785 bool parseScalarInitializer(
unsigned Size,
786 SmallVectorImpl<const MCExpr *> &
Values,
787 unsigned StringPadLength = 0);
788 bool parseScalarInstList(
789 unsigned Size, SmallVectorImpl<const MCExpr *> &
Values,
791 bool emitIntegralValues(
unsigned Size,
unsigned *
Count =
nullptr);
792 bool addIntegralField(StringRef Name,
unsigned Size);
793 bool parseDirectiveValue(StringRef IDVal,
unsigned Size);
794 bool parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
795 StringRef Name, SMLoc NameLoc);
798 bool emitRealValues(
const fltSemantics &Semantics,
unsigned *
Count =
nullptr);
799 bool addRealField(StringRef Name,
const fltSemantics &Semantics,
size_t Size);
800 bool parseDirectiveRealValue(StringRef IDVal,
const fltSemantics &Semantics,
802 bool parseRealInstList(
803 const fltSemantics &Semantics, SmallVectorImpl<APInt> &
Values,
805 bool parseDirectiveNamedRealValue(StringRef TypeName,
806 const fltSemantics &Semantics,
807 unsigned Size, StringRef Name,
810 bool parseOptionalAngleBracketOpen();
811 bool parseAngleBracketClose(
const Twine &
Msg =
"expected '>'");
813 bool parseFieldInitializer(
const FieldInfo &
Field,
814 FieldInitializer &Initializer);
815 bool parseFieldInitializer(
const FieldInfo &
Field,
816 const IntFieldInfo &Contents,
817 FieldInitializer &Initializer);
818 bool parseFieldInitializer(
const FieldInfo &
Field,
819 const RealFieldInfo &Contents,
820 FieldInitializer &Initializer);
821 bool parseFieldInitializer(
const FieldInfo &
Field,
822 const StructFieldInfo &Contents,
823 FieldInitializer &Initializer);
825 bool parseStructInitializer(
const StructInfo &Structure,
826 StructInitializer &Initializer);
827 bool parseStructInstList(
828 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
831 bool emitFieldValue(
const FieldInfo &
Field);
832 bool emitFieldValue(
const FieldInfo &
Field,
const IntFieldInfo &Contents);
833 bool emitFieldValue(
const FieldInfo &
Field,
const RealFieldInfo &Contents);
834 bool emitFieldValue(
const FieldInfo &
Field,
const StructFieldInfo &Contents);
836 bool emitFieldInitializer(
const FieldInfo &
Field,
837 const FieldInitializer &Initializer);
838 bool emitFieldInitializer(
const FieldInfo &
Field,
839 const IntFieldInfo &Contents,
840 const IntFieldInfo &Initializer);
841 bool emitFieldInitializer(
const FieldInfo &
Field,
842 const RealFieldInfo &Contents,
843 const RealFieldInfo &Initializer);
844 bool emitFieldInitializer(
const FieldInfo &
Field,
845 const StructFieldInfo &Contents,
846 const StructFieldInfo &Initializer);
848 bool emitStructInitializer(
const StructInfo &Structure,
849 const StructInitializer &Initializer);
852 bool emitStructValues(
const StructInfo &Structure,
unsigned *
Count =
nullptr);
853 bool addStructField(StringRef Name,
const StructInfo &Structure);
854 bool parseDirectiveStructValue(
const StructInfo &Structure,
855 StringRef Directive, SMLoc DirLoc);
856 bool parseDirectiveNamedStructValue(
const StructInfo &Structure,
857 StringRef Directive, SMLoc DirLoc,
861 bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
862 DirectiveKind DirKind, SMLoc NameLoc);
864 bool parseDirectiveOrg();
866 bool emitAlignTo(int64_t Alignment);
867 bool parseDirectiveAlign();
868 bool parseDirectiveEven();
871 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
872 bool parseDirectiveExitMacro(SMLoc DirectiveLoc, StringRef Directive,
874 bool parseDirectiveEndMacro(StringRef Directive);
875 bool parseDirectiveMacro(StringRef Name, SMLoc NameLoc);
877 bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind,
878 StringRef Name, SMLoc NameLoc);
879 bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind);
880 bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
881 bool parseDirectiveNestedEnds();
883 bool parseDirectiveExtern();
889 bool parseDirectiveComm(
bool IsLocal);
891 bool parseDirectiveComment(SMLoc DirectiveLoc);
893 bool parseDirectiveInclude();
896 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
898 bool parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
901 bool parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
902 bool CaseInsensitive);
904 bool parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined);
906 bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
908 bool parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
910 bool parseDirectiveElseIfdef(SMLoc DirectiveLoc,
bool expect_defined);
913 bool parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
914 bool CaseInsensitive);
915 bool parseDirectiveElse(SMLoc DirectiveLoc);
916 bool parseDirectiveEndIf(SMLoc DirectiveLoc);
917 bool parseEscapedString(std::string &
Data)
override;
918 bool parseAngleBracketString(std::string &
Data)
override;
921 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
922 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
923 raw_svector_ostream &OS);
924 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
925 SMLoc ExitLoc, raw_svector_ostream &OS);
926 bool parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Directive);
927 bool parseDirectiveFor(SMLoc DirectiveLoc, StringRef Directive);
928 bool parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive);
929 bool parseDirectiveWhile(SMLoc DirectiveLoc);
932 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
936 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
939 bool parseDirectiveEnd(SMLoc DirectiveLoc);
942 bool parseDirectiveError(SMLoc DirectiveLoc);
944 bool parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
946 bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
bool ExpectDefined);
949 bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
950 bool CaseInsensitive);
952 bool parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero);
955 bool parseDirectiveRadix(SMLoc DirectiveLoc);
958 bool parseDirectiveEcho(SMLoc DirectiveLoc);
960 void initializeDirectiveKindMap();
961 void initializeBuiltinSymbolMaps();
974MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
975 const MCAsmInfo &MAI,
struct tm TM,
unsigned CB)
976 : MCAsmParser(Ctx, Out, SM, MAI), CurBuffer(CB ? CB : SM.getMainFileID()),
980 SavedDiagHandler =
SrcMgr.getDiagHandler();
981 SavedDiagContext =
SrcMgr.getDiagContext();
984 Lexer.setBuffer(
SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
985 EndStatementAtEOFStack.push_back(
true);
988 switch (Ctx.getObjectFileType()) {
989 case MCContext::IsCOFF:
990 PlatformParser.reset(createCOFFMasmParser());
993 report_fatal_error(
"llvm-ml currently supports only COFF output.");
997 initializeDirectiveKindMap();
998 PlatformParser->Initialize(*
this);
999 initializeBuiltinSymbolMaps();
1001 NumOfMacroInstantiations = 0;
1004MasmParser::~MasmParser() {
1005 assert((HadError || ActiveMacros.empty()) &&
1006 "Unexpected active macro instantiation!");
1013void MasmParser::printMacroInstantiations() {
1015 for (std::vector<MacroInstantiation *>::const_reverse_iterator
1016 it = ActiveMacros.rbegin(),
1017 ie = ActiveMacros.rend();
1020 "while in macro instantiation");
1023void MasmParser::Note(SMLoc L,
const Twine &
Msg, SMRange
Range) {
1024 printPendingErrors();
1026 printMacroInstantiations();
1029bool MasmParser::Warning(SMLoc L,
const Twine &
Msg, SMRange
Range) {
1030 if (getTargetParser().getTargetOptions().MCNoWarn)
1032 if (getTargetParser().getTargetOptions().MCFatalWarnings)
1035 printMacroInstantiations();
1039bool MasmParser::printError(SMLoc L,
const Twine &
Msg, SMRange
Range) {
1042 printMacroInstantiations();
1046bool MasmParser::enterIncludeFile(
const std::string &
Filename) {
1047 std::string IncludedFile;
1055 EndStatementAtEOFStack.push_back(
true);
1059void MasmParser::jumpToLoc(SMLoc Loc,
unsigned InBuffer,
1060 bool EndStatementAtEOF) {
1066bool MasmParser::expandMacros() {
1067 const AsmToken &Tok = getTok();
1070 const llvm::MCAsmMacro *
M =
getContext().lookupMacro(IDLower);
1073 const SMLoc MacroLoc = Tok.
getLoc();
1076 if (handleMacroInvocation(M, MacroLoc)) {
1083 std::optional<std::string> ExpandedValue;
1085 if (
auto BuiltinIt = BuiltinSymbolMap.find(IDLower);
1086 BuiltinIt != BuiltinSymbolMap.end()) {
1088 evaluateBuiltinTextMacro(BuiltinIt->getValue(), Tok.
getLoc());
1089 }
else if (
auto BuiltinFuncIt = BuiltinFunctionMap.find(IDLower);
1090 BuiltinFuncIt != BuiltinFunctionMap.end()) {
1092 if (parseIdentifier(Name)) {
1096 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), Name, Res)) {
1099 ExpandedValue = Res;
1100 }
else if (
auto VarIt = Variables.
find(IDLower);
1101 VarIt != Variables.
end() && VarIt->getValue().IsText) {
1102 ExpandedValue = VarIt->getValue().TextValue;
1107 std::unique_ptr<MemoryBuffer> Instantiation =
1115 EndStatementAtEOFStack.push_back(
false);
1120const AsmToken &MasmParser::Lex(ExpandKind ExpandNextToken) {
1122 Error(Lexer.getErrLoc(), Lexer.getErr());
1123 bool StartOfStatement =
false;
1128 if (!getTok().getString().
empty() && getTok().getString().
front() !=
'\n' &&
1131 StartOfStatement =
true;
1134 const AsmToken *tok = &Lexer.Lex();
1137 if (StartOfStatement) {
1140 size_t ReadCount = Lexer.peekTokens(Buf);
1172 if (ParentIncludeLoc != SMLoc()) {
1173 EndStatementAtEOFStack.pop_back();
1174 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1177 EndStatementAtEOFStack.pop_back();
1178 assert(EndStatementAtEOFStack.empty());
1184const AsmToken MasmParser::peekTok(
bool ShouldSkipSpace) {
1188 size_t ReadCount = Lexer.peekTokens(Buf, ShouldSkipSpace);
1190 if (ReadCount == 0) {
1194 if (ParentIncludeLoc != SMLoc()) {
1195 EndStatementAtEOFStack.pop_back();
1196 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1197 return peekTok(ShouldSkipSpace);
1199 EndStatementAtEOFStack.pop_back();
1200 assert(EndStatementAtEOFStack.empty());
1207bool MasmParser::Run(
bool NoInitialTextSection,
bool NoFinalize) {
1209 if (!NoInitialTextSection)
1216 AsmCond StartingCondState = TheCondState;
1226 ParseStatementInfo
Info(&AsmStrRewrites);
1227 bool HasError = parseStatement(Info,
nullptr);
1232 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
1236 printPendingErrors();
1239 if (HasError && !getLexer().justConsumedEOL())
1240 eatToEndOfStatement();
1243 printPendingErrors();
1246 assert(!hasPendingError() &&
"unexpected error from parseStatement");
1250 printError(getTok().getLoc(),
"unmatched .ifs or .elses");
1259 for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
1260 if (std::get<2>(LocSym)->isUndefined()) {
1263 CppHashInfo = std::get<1>(LocSym);
1264 printError(std::get<0>(LocSym),
"directional label undefined");
1271 if (!HadError && !NoFinalize)
1272 Out.
finish(Lexer.getLoc());
1277bool MasmParser::checkForValidSection() {
1278 if (!ParsingMSInlineAsm && !(getStreamer().getCurrentFragment() &&
1279 getStreamer().getCurrentSectionOnly())) {
1281 return Error(getTok().getLoc(),
1282 "expected section directive before assembly directive");
1288void MasmParser::eatToEndOfStatement() {
1292 if (ParentIncludeLoc == SMLoc()) {
1296 EndStatementAtEOFStack.pop_back();
1297 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1308SmallVector<StringRef, 1>
1310 SmallVector<StringRef, 1> Refs;
1311 const char *
Start = getTok().getLoc().getPointer();
1312 while (Lexer.isNot(EndTok)) {
1315 if (ParentIncludeLoc == SMLoc()) {
1320 EndStatementAtEOFStack.pop_back();
1321 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1323 Start = getTok().getLoc().getPointer();
1333 SmallVector<StringRef, 1> Refs = parseStringRefsTo(EndTok);
1335 for (StringRef S : Refs) {
1336 Str.append(S.str());
1341StringRef MasmParser::parseStringToEndOfStatement() {
1342 const char *
Start = getTok().getLoc().getPointer();
1347 const char *End = getTok().getLoc().getPointer();
1348 return StringRef(Start, End - Start);
1356bool MasmParser::parseParenExpr(
const MCExpr *&Res, SMLoc &EndLoc) {
1357 if (parseExpression(Res))
1359 EndLoc = Lexer.getTok().getEndLoc();
1360 return parseRParen();
1368bool MasmParser::parseBracketExpr(
const MCExpr *&Res, SMLoc &EndLoc) {
1369 if (parseExpression(Res))
1371 EndLoc = getTok().getEndLoc();
1372 if (parseToken(
AsmToken::RBrac,
"expected ']' in brackets expression"))
1385bool MasmParser::parsePrimaryExpr(
const MCExpr *&Res, SMLoc &EndLoc,
1386 AsmTypeInfo *TypeInfo) {
1387 SMLoc FirstTokenLoc = getLexer().getLoc();
1389 switch (FirstTokenKind) {
1391 return TokError(
"unknown token in expression");
1397 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1405 if (parseIdentifier(Identifier)) {
1408 if (Lexer.getMAI().getDollarIsPC()) {
1415 EndLoc = FirstTokenLoc;
1418 return Error(FirstTokenLoc,
"invalid token in expression");
1423 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1429 if (
Identifier.equals_insensitive(
"imagerel")) {
1430 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1432 if (
const MCExpr *ModifiedRes =
1437 return Error(FirstTokenLoc,
"cannot apply 'imagerel' to this expression");
1442 bool Before =
Identifier.equals_insensitive(
"@b");
1445 return Error(FirstTokenLoc,
"Expected @@ label before @B reference");
1455 return Error(getLexer().getLoc(),
"expected a symbol reference");
1460 if (
Split.second.empty()) {
1463 if (lookUpField(SymbolName,
Split.second, Info)) {
1464 std::pair<StringRef, StringRef> BaseMember =
Split.second.split(
'.');
1465 StringRef
Base = BaseMember.first,
Member = BaseMember.second;
1466 lookUpField(
Base, Member, Info);
1477 auto BuiltinIt = BuiltinSymbolMap.find(
SymbolName.lower());
1478 const BuiltinSymbol
Symbol = (BuiltinIt == BuiltinSymbolMap.end())
1480 : BuiltinIt->getValue();
1481 if (Symbol != BI_NO_SYMBOL) {
1482 const MCExpr *
Value = evaluateBuiltinValue(Symbol, FirstTokenLoc);
1492 if (VarIt != Variables.
end())
1503 DoInline = TV->inlineAssignedExpr();
1511 const MCExpr *SymRef =
1521 if (
Info.Type.Name.empty()) {
1523 if (TypeIt != KnownType.
end()) {
1524 Info.Type = TypeIt->second;
1528 *TypeInfo =
Info.Type;
1533 return TokError(
"literal value out of range for directive");
1535 int64_t
IntVal = getTok().getIntVal();
1537 EndLoc = Lexer.getTok().getEndLoc();
1543 SMLoc ValueLoc = getTok().getLoc();
1545 if (parseEscapedString(
Value))
1547 if (
Value.size() > 8)
1548 return Error(ValueLoc,
"literal value out of range");
1550 for (
const unsigned char CharVal :
Value)
1551 IntValue = (IntValue << 8) | CharVal;
1556 APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
1559 EndLoc = Lexer.getTok().getEndLoc();
1569 EndLoc = Lexer.getTok().getEndLoc();
1575 return parseParenExpr(Res, EndLoc);
1577 if (!PlatformParser->HasBracketExpressions())
1578 return TokError(
"brackets expression not supported on this target");
1580 return parseBracketExpr(Res, EndLoc);
1583 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1589 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1595 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1602bool MasmParser::parseExpression(
const MCExpr *&Res) {
1604 return parseExpression(Res, EndLoc);
1615 "Argument to the function cannot be a NULL value");
1617 while ((*CharPtr !=
'>') && (*CharPtr !=
'\n') && (*CharPtr !=
'\r') &&
1618 (*CharPtr !=
'\0')) {
1619 if (*CharPtr ==
'!')
1623 if (*CharPtr ==
'>') {
1633 for (
size_t Pos = 0; Pos < BracketContents.
size(); Pos++) {
1634 if (BracketContents[Pos] ==
'!')
1636 Res += BracketContents[Pos];
1651bool MasmParser::parseExpression(
const MCExpr *&Res, SMLoc &EndLoc) {
1654 if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
1655 parseBinOpRHS(1, Res, EndLoc))
1661 if (Res->evaluateAsAbsolute(
Value))
1667bool MasmParser::parseParenExpression(
const MCExpr *&Res, SMLoc &EndLoc) {
1669 return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
1672bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
1675 SMLoc StartLoc = Lexer.getLoc();
1676 if (parseExpression(Expr))
1679 if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
1680 return Error(StartLoc,
"expected absolute expression");
1687 bool ShouldUseLogicalShr,
1688 bool EndExpressionAtGreater) {
1716 if (EndExpressionAtGreater)
1757 if (EndExpressionAtGreater)
1768 AngleBracketDepth > 0);
1773bool MasmParser::parseBinOpRHS(
unsigned Precedence,
const MCExpr *&Res,
1775 SMLoc StartLoc = Lexer.getLoc();
1779 TokKind = StringSwitch<AsmToken::TokenKind>(Lexer.getTok().getString())
1795 unsigned TokPrec = getBinOpPrecedence(TokKind, Kind);
1799 if (TokPrec < Precedence)
1806 if (getTargetParser().parsePrimaryExpr(
RHS, EndLoc))
1812 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
1813 if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1,
RHS, EndLoc))
1826bool MasmParser::parseStatement(ParseStatementInfo &Info,
1827 MCAsmParserSemaCallback *SI) {
1828 assert(!hasPendingError() &&
"parseStatement started with pending error");
1834 if (getTok().getString().
empty() || getTok().getString().
front() ==
'\r' ||
1835 getTok().getString().
front() ==
'\n')
1844 SMLoc ExpansionLoc = getTok().getLoc();
1851 AsmToken
ID = getTok();
1852 SMLoc IDLoc =
ID.getLoc();
1855 return parseCppHashLineFilenameComment(IDLoc);
1862 IDVal = getTok().getString();
1865 return Error(IDLoc,
"unexpected token at start of statement");
1866 }
else if (parseIdentifier(IDVal, StartOfStatement)) {
1867 if (!TheCondState.
Ignore) {
1869 return Error(IDLoc,
"unexpected token at start of statement");
1878 DirectiveKindMap.find(IDVal.
lower());
1879 DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
1881 : DirKindIt->getValue();
1887 return parseDirectiveIf(IDLoc, DirKind);
1889 return parseDirectiveIfb(IDLoc,
true);
1891 return parseDirectiveIfb(IDLoc,
false);
1893 return parseDirectiveIfdef(IDLoc,
true);
1895 return parseDirectiveIfdef(IDLoc,
false);
1897 return parseDirectiveIfidn(IDLoc,
false,
1900 return parseDirectiveIfidn(IDLoc,
false,
1903 return parseDirectiveIfidn(IDLoc,
true,
1906 return parseDirectiveIfidn(IDLoc,
true,
1910 return parseDirectiveElseIf(IDLoc, DirKind);
1912 return parseDirectiveElseIfb(IDLoc,
true);
1914 return parseDirectiveElseIfb(IDLoc,
false);
1916 return parseDirectiveElseIfdef(IDLoc,
true);
1918 return parseDirectiveElseIfdef(IDLoc,
false);
1920 return parseDirectiveElseIfidn(IDLoc,
false,
1923 return parseDirectiveElseIfidn(IDLoc,
false,
1926 return parseDirectiveElseIfidn(IDLoc,
true,
1929 return parseDirectiveElseIfidn(IDLoc,
true,
1932 return parseDirectiveElse(IDLoc);
1934 return parseDirectiveEndIf(IDLoc);
1939 if (TheCondState.
Ignore) {
1940 eatToEndOfStatement();
1950 if (checkForValidSection())
1958 return Error(IDLoc,
"invalid use of pseudo-symbol '.' as a label");
1966 if (ParsingMSInlineAsm && SI) {
1967 StringRef RewrittenLabel =
1968 SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc,
true);
1970 "We should have an internal name here.");
1973 IDVal = RewrittenLabel;
1976 if (IDVal ==
"@@") {
1999 if (!getTargetParser().isParsingMSInlineAsm())
2009 return handleMacroEntry(M, IDLoc, ArgumentEndTok);
2014 if (DirKind != DK_NO_DIRECTIVE) {
2030 return parseDirectiveNestedEnds();
2035 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2038 return (*Handler.second)(Handler.first, IDVal, IDLoc);
2044 ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(ID);
2046 "Should only return Failure iff there was an error");
2058 return parseDirectiveAscii(IDVal,
false);
2061 return parseDirectiveAscii(IDVal,
true);
2065 return parseDirectiveValue(IDVal, 1);
2069 return parseDirectiveValue(IDVal, 2);
2073 return parseDirectiveValue(IDVal, 4);
2076 return parseDirectiveValue(IDVal, 6);
2080 return parseDirectiveValue(IDVal, 8);
2082 return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4);
2084 return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8);
2086 return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10);
2089 return parseDirectiveNestedStruct(IDVal, DirKind);
2091 return parseDirectiveNestedEnds();
2093 return parseDirectiveAlign();
2095 return parseDirectiveEven();
2097 return parseDirectiveOrg();
2099 return parseDirectiveExtern();
2101 return parseDirectiveSymbolAttribute(
MCSA_Global);
2103 return parseDirectiveComm(
false);
2105 return parseDirectiveComment(IDLoc);
2107 return parseDirectiveInclude();
2109 return parseDirectiveRepeat(IDLoc, IDVal);
2111 return parseDirectiveWhile(IDLoc);
2113 return parseDirectiveFor(IDLoc, IDVal);
2115 return parseDirectiveForc(IDLoc, IDVal);
2117 Info.ExitValue =
"";
2118 return parseDirectiveExitMacro(IDLoc, IDVal, *
Info.ExitValue);
2120 Info.ExitValue =
"";
2121 return parseDirectiveEndMacro(IDVal);
2123 return parseDirectivePurgeMacro(IDLoc);
2125 return parseDirectiveEnd(IDLoc);
2127 return parseDirectiveError(IDLoc);
2129 return parseDirectiveErrorIfb(IDLoc,
true);
2131 return parseDirectiveErrorIfb(IDLoc,
false);
2133 return parseDirectiveErrorIfdef(IDLoc,
true);
2135 return parseDirectiveErrorIfdef(IDLoc,
false);
2137 return parseDirectiveErrorIfidn(IDLoc,
false,
2140 return parseDirectiveErrorIfidn(IDLoc,
false,
2143 return parseDirectiveErrorIfidn(IDLoc,
true,
2146 return parseDirectiveErrorIfidn(IDLoc,
true,
2149 return parseDirectiveErrorIfe(IDLoc,
true);
2151 return parseDirectiveErrorIfe(IDLoc,
false);
2153 return parseDirectiveRadix(IDLoc);
2155 return parseDirectiveEcho(IDLoc);
2158 return Error(IDLoc,
"unknown directive");
2162 auto IDIt = Structs.
find(IDVal.
lower());
2163 if (IDIt != Structs.
end())
2164 return parseDirectiveStructValue(IDIt->getValue(), IDVal,
2168 const AsmToken nextTok = getTok();
2169 const StringRef nextVal = nextTok.
getString();
2170 const SMLoc nextLoc = nextTok.
getLoc();
2172 const AsmToken afterNextTok = peekTok();
2183 getTargetParser().flushPendingInstructions(getStreamer());
2189 return parseDirectiveEnds(IDVal, IDLoc);
2194 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2196 if (Handler.first) {
2199 return (*Handler.second)(Handler.first, nextVal, nextLoc);
2204 DirKindIt = DirectiveKindMap.find(nextVal.
lower());
2205 DirKind = (DirKindIt == DirectiveKindMap.end())
2207 : DirKindIt->getValue();
2214 return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
2216 Lex(DoNotExpandMacros);
2217 return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
2228 return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc);
2239 return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc);
2250 return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc);
2260 return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc);
2271 return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc);
2274 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), 4,
2278 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8,
2282 return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(),
2287 return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc);
2290 return parseDirectiveEnds(IDVal, IDLoc);
2293 return parseDirectiveMacro(IDVal, IDLoc);
2297 auto NextIt = Structs.
find(nextVal.
lower());
2298 if (NextIt != Structs.
end()) {
2300 return parseDirectiveNamedStructValue(NextIt->getValue(),
2301 nextVal, nextLoc, IDVal);
2305 if (ParsingMSInlineAsm && (IDVal ==
"_emit" || IDVal ==
"__emit" ||
2306 IDVal ==
"_EMIT" || IDVal ==
"__EMIT"))
2307 return parseDirectiveMSEmit(IDLoc, Info, IDVal.
size());
2310 if (ParsingMSInlineAsm && (IDVal ==
"align" || IDVal ==
"ALIGN"))
2311 return parseDirectiveMSAlign(IDLoc, Info);
2313 if (ParsingMSInlineAsm && (IDVal ==
"even" || IDVal ==
"EVEN"))
2315 if (checkForValidSection())
2319 std::string OpcodeStr = IDVal.
lower();
2320 ParseInstructionInfo IInfo(
Info.AsmRewrites);
2321 bool ParseHadError = getTargetParser().parseInstruction(IInfo, OpcodeStr, ID,
2322 Info.ParsedOperands);
2323 Info.ParseError = ParseHadError;
2326 if (getShowParsedOperands()) {
2327 SmallString<256> Str;
2328 raw_svector_ostream OS(Str);
2329 OS <<
"parsed instruction: [";
2330 for (
unsigned i = 0; i !=
Info.ParsedOperands.size(); ++i) {
2333 Info.ParsedOperands[i]->print(OS, MAI);
2341 if (hasPendingError() || ParseHadError)
2345 if (!ParseHadError) {
2347 if (getTargetParser().matchAndEmitInstruction(
2348 IDLoc,
Info.Opcode,
Info.ParsedOperands, Out, ErrorInfo,
2349 getTargetParser().isParsingMSInlineAsm()))
2356bool MasmParser::parseCurlyBlockScope(
2357 SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
2362 SMLoc StartLoc = Lexer.getLoc();
2375bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
2380 "Lexing Cpp line comment: Expected Integer");
2381 int64_t LineNumber = getTok().getIntVal();
2384 "Lexing Cpp line comment: Expected String");
2385 StringRef
Filename = getTok().getString();
2393 CppHashInfo.Loc =
L;
2395 CppHashInfo.LineNumber = LineNumber;
2396 CppHashInfo.Buf = CurBuffer;
2397 if (FirstCppHashFilename.
empty())
2404void MasmParser::DiagHandler(
const SMDiagnostic &Diag,
void *
Context) {
2405 const MasmParser *Parser =
static_cast<const MasmParser *
>(
Context);
2406 raw_ostream &OS =
errs();
2409 SMLoc DiagLoc = Diag.
getLoc();
2411 unsigned CppHashBuf =
2412 Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
2416 if (!Parser->SavedDiagHandler)
2422 if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
2423 DiagBuf != CppHashBuf) {
2424 if (Parser->SavedDiagHandler)
2425 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2427 Diag.
print(
nullptr, OS);
2434 const std::string &
Filename = std::string(Parser->CppHashInfo.Filename);
2437 int CppHashLocLineNo =
2438 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2440 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2446 if (Parser->SavedDiagHandler)
2447 Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
2449 NewDiag.print(
nullptr, OS);
2455 return isAlnum(
C) ||
C ==
'_' ||
C ==
'$' ||
C ==
'@' ||
C ==
'?';
2458bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
2461 const std::vector<std::string> &Locals, SMLoc L) {
2463 if (NParameters !=
A.size())
2464 return Error(L,
"Wrong number of arguments");
2465 StringMap<std::string> LocalSymbols;
2468 for (StringRef
Local : Locals) {
2469 raw_string_ostream LocalName(Name);
2476 std::optional<char> CurrentQuote;
2477 while (!Body.
empty()) {
2479 std::size_t End = Body.
size(), Pos = 0;
2480 std::size_t IdentifierPos = End;
2481 for (; Pos != End; ++Pos) {
2484 if (Body[Pos] ==
'&')
2489 if (IdentifierPos == End)
2490 IdentifierPos = Pos;
2492 IdentifierPos = End;
2496 if (!CurrentQuote) {
2497 if (Body[Pos] ==
'\'' || Body[Pos] ==
'"')
2498 CurrentQuote = Body[Pos];
2499 }
else if (Body[Pos] == CurrentQuote) {
2500 if (Pos + 1 != End && Body[Pos + 1] == CurrentQuote) {
2505 CurrentQuote.reset();
2509 if (IdentifierPos != End) {
2512 Pos = IdentifierPos;
2513 IdentifierPos = End;
2517 OS << Body.
slice(0, Pos);
2524 bool InitialAmpersand = (Body[
I] ==
'&');
2525 if (InitialAmpersand) {
2532 const char *Begin = Body.
data() + Pos;
2534 const std::string ArgumentLower =
Argument.lower();
2538 if (Parameters[Index].
Name.equals_insensitive(ArgumentLower))
2541 if (Index == NParameters) {
2542 if (InitialAmpersand)
2544 auto it = LocalSymbols.
find(ArgumentLower);
2545 if (it != LocalSymbols.
end())
2551 for (
const AsmToken &Token :
A[Index]) {
2561 OS << Token.getIntVal();
2563 OS << Token.getString();
2567 if (Pos < End && Body[Pos] ==
'&') {
2578bool MasmParser::parseMacroArgument(
const MCAsmMacroParameter *MP,
2579 MCAsmMacroArgument &MA,
2582 if (Lexer.isNot(EndTok)) {
2583 SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok);
2584 for (StringRef S : Str) {
2591 SMLoc StrLoc = Lexer.getLoc(), EndLoc;
2593 const char *StrChar = StrLoc.
getPointer() + 1;
2594 const char *EndChar = EndLoc.
getPointer() - 1;
2595 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
2602 unsigned ParenLevel = 0;
2606 return TokError(
"unexpected token");
2623 MA.push_back(getTok());
2627 if (ParenLevel != 0)
2628 return TokError(
"unbalanced parentheses in argument");
2630 if (MA.empty() && MP) {
2632 return TokError(
"missing value for required parameter '" + MP->
Name +
2642bool MasmParser::parseMacroArguments(
const MCAsmMacro *M,
2643 MCAsmMacroArguments &
A,
2645 const unsigned NParameters =
M ?
M->Parameters.size() : 0;
2646 bool NamedParametersFound =
false;
2647 SmallVector<SMLoc, 4> FALocs;
2649 A.resize(NParameters);
2650 FALocs.
resize(NParameters);
2655 for (
unsigned Parameter = 0; !NParameters ||
Parameter < NParameters;
2657 SMLoc IDLoc = Lexer.getLoc();
2658 MCAsmMacroParameter FA;
2661 if (parseIdentifier(FA.
Name))
2662 return Error(IDLoc,
"invalid argument identifier for formal argument");
2665 return TokError(
"expected '=' after formal parameter identifier");
2669 NamedParametersFound =
true;
2672 if (NamedParametersFound && FA.
Name.
empty())
2673 return Error(IDLoc,
"cannot mix positional and keyword arguments");
2677 assert(M &&
"expected macro to be defined");
2679 for (FAI = 0; FAI < NParameters; ++FAI)
2680 if (
M->Parameters[FAI].Name == FA.
Name)
2683 if (FAI >= NParameters) {
2684 return Error(IDLoc,
"parameter named '" + FA.
Name +
2685 "' does not exist for macro '" +
M->Name +
"'");
2689 const MCAsmMacroParameter *MP =
nullptr;
2690 if (M && PI < NParameters)
2691 MP = &
M->Parameters[PI];
2693 SMLoc StrLoc = Lexer.getLoc();
2696 const MCExpr *AbsoluteExp;
2700 if (parseExpression(AbsoluteExp, EndLoc))
2702 if (!AbsoluteExp->evaluateAsAbsolute(
Value,
2703 getStreamer().getAssemblerPtr()))
2704 return Error(StrLoc,
"expected absolute expression");
2708 StringRef(StrChar, EndChar - StrChar),
Value);
2709 FA.
Value.push_back(newToken);
2710 }
else if (parseMacroArgument(MP, FA.
Value, EndTok)) {
2712 return addErrorSuffix(
" in '" +
M->Name +
"' macro");
2717 if (!FA.
Value.empty()) {
2722 if (FALocs.
size() <= PI)
2725 FALocs[PI] = Lexer.getLoc();
2731 if (Lexer.is(EndTok)) {
2733 for (
unsigned FAI = 0; FAI < NParameters; ++FAI) {
2735 if (
M->Parameters[FAI].Required) {
2736 Error(FALocs[FAI].
isValid() ? FALocs[FAI] : Lexer.getLoc(),
2737 "missing value for required parameter "
2739 M->Parameters[FAI].Name +
"' in macro '" +
M->Name +
"'");
2743 if (!
M->Parameters[FAI].Value.empty())
2744 A[FAI] =
M->Parameters[FAI].Value;
2754 return TokError(
"too many positional arguments");
2757bool MasmParser::handleMacroEntry(
const MCAsmMacro *M, SMLoc NameLoc,
2762 if (ActiveMacros.size() == MaxNestingDepth) {
2763 std::ostringstream MaxNestingDepthError;
2764 MaxNestingDepthError <<
"macros cannot be nested more than "
2765 << MaxNestingDepth <<
" levels deep."
2766 <<
" Use -asm-macro-max-nesting-depth to increase "
2768 return TokError(MaxNestingDepthError.str());
2771 MCAsmMacroArguments
A;
2772 if (parseMacroArguments(M,
A, ArgumentEndTok) || parseToken(ArgumentEndTok))
2777 SmallString<256> Buf;
2778 StringRef Body =
M->Body;
2779 raw_svector_ostream OS(Buf);
2781 if (expandMacro(OS, Body,
M->Parameters,
A,
M->Locals, getTok().getLoc()))
2788 std::unique_ptr<MemoryBuffer> Instantiation =
2793 MacroInstantiation *
MI =
new MacroInstantiation{
2794 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
2795 ActiveMacros.push_back(
MI);
2797 ++NumOfMacroInstantiations;
2802 EndStatementAtEOFStack.push_back(
true);
2808void MasmParser::handleMacroExit() {
2810 EndStatementAtEOFStack.pop_back();
2811 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer,
2812 EndStatementAtEOFStack.back());
2816 delete ActiveMacros.back();
2817 ActiveMacros.pop_back();
2820bool MasmParser::handleMacroInvocation(
const MCAsmMacro *M, SMLoc NameLoc) {
2822 return Error(NameLoc,
"cannot invoke macro procedure as function");
2825 "' requires arguments in parentheses") ||
2830 std::string ExitValue;
2833 ParseStatementInfo
Info(&AsmStrRewrites);
2834 bool HasError = parseStatement(Info,
nullptr);
2836 if (!HasError &&
Info.ExitValue) {
2837 ExitValue = std::move(*
Info.ExitValue);
2844 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
2848 printPendingErrors();
2851 if (HasError && !getLexer().justConsumedEOL())
2852 eatToEndOfStatement();
2857 std::unique_ptr<MemoryBuffer> MacroValue =
2865 EndStatementAtEOFStack.push_back(
false);
2874bool MasmParser::parseIdentifier(StringRef &Res,
2875 IdentifierPositionKind Position) {
2882 SMLoc PrefixLoc = getLexer().getLoc();
2886 AsmToken nextTok = peekTok(
false);
2899 StringRef(PrefixLoc.
getPointer(), getTok().getIdentifier().
size() + 1);
2907 Res = getTok().getIdentifier();
2911 ExpandKind ExpandNextToken = ExpandMacros;
2912 if (Position == StartOfStatement &&
2913 StringSwitch<bool>(Res)
2914 .CaseLower(
"echo",
true)
2915 .CasesLower({
"ifdef",
"ifndef",
"elseifdef",
"elseifndef"},
true)
2917 ExpandNextToken = DoNotExpandMacros;
2919 Lex(ExpandNextToken);
2929bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
2930 DirectiveKind DirKind, SMLoc NameLoc) {
2931 auto BuiltinIt = BuiltinSymbolMap.find(
Name.lower());
2932 if (BuiltinIt != BuiltinSymbolMap.end())
2933 return Error(NameLoc,
"cannot redefine a built-in symbol");
2936 if (Var.Name.empty()) {
2940 SMLoc StartLoc = Lexer.getLoc();
2946 if (!parseTextList(
Value, IDVal))
2947 return setTextVariable(Var, Name,
Value, NameLoc, Variable::REDEFINABLE);
2948 return TokError(
"expected <text> in '" + Twine(IDVal) +
"' directive");
2955 if (!parseAngleBracketString(
Value))
2956 return setTextVariable(Var, Name,
Value, NameLoc, Variable::REDEFINABLE);
2966 if (parseExpression(Expr, EndLoc))
2967 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
2968 StringRef ExprAsString = StringRef(
2972 if (!Expr->evaluateAsAbsolute(
Value, getStreamer().getAssemblerPtr())) {
2973 if (DirKind == DK_ASSIGN)
2976 "expected absolute expression; not all symbols have known values",
2977 {StartLoc, EndLoc});
2980 return setTextVariable(Var, Name, ExprAsString, NameLoc,
2981 Variable::REDEFINABLE);
2984 auto *Sym =
static_cast<MCSymbolCOFF *
>(
getContext().parseSymbol(Var.Name));
2985 const MCConstantExpr *PrevValue =
2989 if (Var.IsText || !PrevValue || PrevValue->
getValue() !=
Value) {
2990 switch (Var.Redefinable) {
2991 case Variable::NOT_REDEFINABLE:
2992 return Error(getTok().getLoc(),
"invalid variable redefinition");
2993 case Variable::WARN_ON_REDEFINITION:
2994 if (
Warning(NameLoc,
"redefining '" + Name +
2995 "', already defined on the command line"))
3004 Var.TextValue.clear();
3005 Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE
3008 Sym->
setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE);
3010 Sym->setExternal(
false);
3015bool MasmParser::parseEscapedString(std::string &
Data) {
3020 char Quote = getTok().getString().front();
3021 StringRef Str = getTok().getStringContents();
3022 Data.reserve(Str.size());
3023 for (
size_t i = 0, e = Str.size(); i != e; ++i) {
3024 Data.push_back(Str[i]);
3025 if (Str[i] == Quote) {
3029 if (i + 1 == Str.size())
3030 return Error(getTok().getLoc(),
"missing quotation mark in string");
3031 if (Str[i + 1] == Quote)
3040bool MasmParser::parseAngleBracketString(std::string &
Data) {
3041 SMLoc EndLoc, StartLoc = getTok().getLoc();
3043 const char *StartChar = StartLoc.
getPointer() + 1;
3044 const char *EndChar = EndLoc.
getPointer() - 1;
3045 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
3056bool MasmParser::parseTextItem(std::string &
Data) {
3057 switch (getTok().getKind()) {
3064 Data = std::to_string(Res);
3071 return parseAngleBracketString(
Data);
3075 SMLoc StartLoc = getTok().getLoc();
3076 if (parseIdentifier(ID))
3080 bool Expanded =
false;
3083 auto BuiltinIt = BuiltinSymbolMap.find(
ID.lower());
3084 if (BuiltinIt != BuiltinSymbolMap.end()) {
3085 std::optional<std::string> BuiltinText =
3086 evaluateBuiltinTextMacro(BuiltinIt->getValue(), StartLoc);
3091 Data = std::move(*BuiltinText);
3098 auto BuiltinFuncIt = BuiltinFunctionMap.find(
ID.lower());
3099 if (BuiltinFuncIt != BuiltinFunctionMap.end()) {
3101 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), ID,
Data)) {
3110 auto VarIt = Variables.
find(
ID.lower());
3111 if (VarIt != Variables.
end()) {
3112 const Variable &Var = VarIt->getValue();
3117 Data = Var.TextValue;
3139bool MasmParser::parseTextList(std::string &Result, StringRef IDVal) {
3140 std::string TextItem;
3141 if (parseTextItem(TextItem))
3145 Lex(DoNotExpandMacros);
3147 Lex(DoNotExpandMacros);
3148 if (parseTextItem(TextItem))
3149 return TokError(
"expected text item in '" + Twine(IDVal) +
"' directive");
3156bool MasmParser::setTextVariable(Variable &Var, StringRef Name, StringRef
Value,
3158 Variable::RedefinableKind Redefinable) {
3159 if (!Var.IsText || Var.TextValue !=
Value) {
3160 switch (Var.Redefinable) {
3161 case Variable::NOT_REDEFINABLE:
3162 return Error(getTok().getLoc(),
"invalid variable redefinition");
3163 case Variable::WARN_ON_REDEFINITION:
3164 if (
Warning(NameLoc,
"redefining '" + Name +
3165 "', already defined on the command line"))
3173 Var.TextValue =
Value.str();
3174 Var.Redefinable = Redefinable;
3180bool MasmParser::parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated) {
3181 auto parseOp = [&]() ->
bool {
3183 if (checkForValidSection() || parseEscapedString(
Data))
3185 getStreamer().emitBytes(
Data);
3187 getStreamer().emitBytes(StringRef(
"\0", 1));
3191 if (parseMany(parseOp))
3192 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3196bool MasmParser::emitIntValue(
const MCExpr *
Value,
unsigned Size) {
3200 int64_t IntValue = MCE->getValue();
3202 return Error(MCE->getLoc(),
"out of range literal value");
3203 getStreamer().emitIntValue(IntValue,
Size);
3208 getStreamer().emitIntValue(0,
Size);
3216bool MasmParser::parseScalarInitializer(
unsigned Size,
3217 SmallVectorImpl<const MCExpr *> &
Values,
3218 unsigned StringPadLength) {
3221 if (parseEscapedString(
Value))
3224 for (
const unsigned char CharVal :
Value)
3228 for (
size_t i =
Value.size(); i < StringPadLength; ++i)
3231 const MCExpr *
Value;
3232 if (parseExpression(
Value))
3235 getTok().getString().equals_insensitive(
"dup")) {
3240 "cannot repeat value a non-constant number of times");
3241 const int64_t Repetitions = MCE->
getValue();
3242 if (Repetitions < 0)
3244 "cannot repeat value a negative number of times");
3248 "parentheses required for 'dup' contents") ||
3249 parseScalarInstList(
Size, DuplicatedValues) || parseRParen())
3252 for (
int i = 0; i < Repetitions; ++i)
3261bool MasmParser::parseScalarInstList(
unsigned Size,
3262 SmallVectorImpl<const MCExpr *> &
Values,
3264 while (getTok().
isNot(EndToken) &&
3277bool MasmParser::emitIntegralValues(
unsigned Size,
unsigned *
Count) {
3279 if (checkForValidSection() || parseScalarInstList(
Size,
Values))
3291bool MasmParser::addIntegralField(StringRef Name,
unsigned Size) {
3292 StructInfo &
Struct = StructInProgress.
back();
3294 IntFieldInfo &IntInfo =
Field.Contents.IntInfo;
3298 if (parseScalarInstList(
Size, IntInfo.Values))
3301 Field.SizeOf =
Field.Type * IntInfo.Values.size();
3302 Field.LengthOf = IntInfo.Values.size();
3305 Struct.NextOffset = FieldEnd;
3313bool MasmParser::parseDirectiveValue(StringRef IDVal,
unsigned Size) {
3314 if (StructInProgress.
empty()) {
3316 if (emitIntegralValues(
Size))
3317 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3318 }
else if (addIntegralField(
"",
Size)) {
3319 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3327bool MasmParser::parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
3328 StringRef Name, SMLoc NameLoc) {
3329 if (StructInProgress.
empty()) {
3332 getStreamer().emitLabel(Sym);
3335 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3343 }
else if (addIntegralField(Name,
Size)) {
3344 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3350bool MasmParser::parseRealValue(
const fltSemantics &Semantics, APInt &Res) {
3356 SignLoc = getLexer().getLoc();
3360 SignLoc = getLexer().getLoc();
3365 return TokError(Lexer.getErr());
3368 return TokError(
"unexpected token in directive");
3372 StringRef IDVal = getTok().getString();
3381 return TokError(
"invalid floating point literal");
3385 unsigned SizeInBits =
Value.getSizeInBits(Semantics);
3386 if (SizeInBits != (IDVal.
size() << 2))
3387 return TokError(
"invalid floating point literal");
3392 Res = APInt(SizeInBits, IDVal, 16);
3394 return Warning(SignLoc,
"MASM-style hex floats ignore explicit sign");
3397 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3399 return TokError(
"invalid floating point literal");
3407 Res =
Value.bitcastToAPInt();
3412bool MasmParser::parseRealInstList(
const fltSemantics &Semantics,
3413 SmallVectorImpl<APInt> &ValuesAsInt,
3415 while (getTok().
isNot(EndToken) ||
3418 const AsmToken NextTok = peekTok();
3421 const MCExpr *
Value;
3427 "cannot repeat value a non-constant number of times");
3428 const int64_t Repetitions = MCE->
getValue();
3429 if (Repetitions < 0)
3431 "cannot repeat value a negative number of times");
3435 "parentheses required for 'dup' contents") ||
3436 parseRealInstList(Semantics, DuplicatedValues) || parseRParen())
3439 for (
int i = 0; i < Repetitions; ++i)
3440 ValuesAsInt.
append(DuplicatedValues.
begin(), DuplicatedValues.
end());
3443 if (parseRealValue(Semantics, AsInt))
3458bool MasmParser::emitRealValues(
const fltSemantics &Semantics,
3460 if (checkForValidSection())
3464 if (parseRealInstList(Semantics, ValuesAsInt))
3467 for (
const APInt &AsInt : ValuesAsInt) {
3468 getStreamer().emitIntValue(AsInt);
3471 *
Count = ValuesAsInt.size();
3476bool MasmParser::addRealField(StringRef Name,
const fltSemantics &Semantics,
3478 StructInfo &
Struct = StructInProgress.
back();
3480 RealFieldInfo &RealInfo =
Field.Contents.RealInfo;
3484 if (parseRealInstList(Semantics, RealInfo.AsIntValues))
3487 Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
3488 Field.LengthOf = RealInfo.AsIntValues.size();
3493 Struct.NextOffset = FieldEnd;
3501bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
3502 const fltSemantics &Semantics,
3504 if (StructInProgress.
empty()) {
3506 if (emitRealValues(Semantics))
3507 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3508 }
else if (addRealField(
"", Semantics,
Size)) {
3509 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3516bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
3517 const fltSemantics &Semantics,
3518 unsigned Size, StringRef Name,
3520 if (StructInProgress.
empty()) {
3523 getStreamer().emitLabel(Sym);
3525 if (emitRealValues(Semantics, &
Count))
3526 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3534 }
else if (addRealField(Name, Semantics,
Size)) {
3535 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3540bool MasmParser::parseOptionalAngleBracketOpen() {
3541 const AsmToken Tok = getTok();
3543 AngleBracketDepth++;
3547 AngleBracketDepth++;
3551 AngleBracketDepth++;
3558bool MasmParser::parseAngleBracketClose(
const Twine &
Msg) {
3559 const AsmToken Tok = getTok();
3565 AngleBracketDepth--;
3569bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3570 const IntFieldInfo &Contents,
3571 FieldInitializer &Initializer) {
3572 SMLoc Loc = getTok().getLoc();
3577 return Error(Loc,
"Cannot initialize scalar field with array value");
3581 }
else if (parseOptionalAngleBracketOpen()) {
3583 return Error(Loc,
"Cannot initialize scalar field with array value");
3585 parseAngleBracketClose())
3587 }
else if (
Field.LengthOf > 1 &&
Field.Type > 1) {
3588 return Error(Loc,
"Cannot initialize array field with scalar value");
3589 }
else if (parseScalarInitializer(
Field.Type,
Values,
3595 return Error(Loc,
"Initializer too long for field; expected at most " +
3596 std::to_string(
Field.LengthOf) +
" elements, got " +
3597 std::to_string(
Values.size()));
3600 Values.append(Contents.Values.begin() +
Values.size(), Contents.Values.end());
3602 Initializer = FieldInitializer(std::move(
Values));
3606bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3607 const RealFieldInfo &Contents,
3608 FieldInitializer &Initializer) {
3609 const fltSemantics *Semantics;
3610 switch (
Field.Type) {
3612 Semantics = &APFloat::IEEEsingle();
3615 Semantics = &APFloat::IEEEdouble();
3618 Semantics = &APFloat::x87DoubleExtended();
3624 SMLoc Loc = getTok().getLoc();
3628 if (
Field.LengthOf == 1)
3629 return Error(Loc,
"Cannot initialize scalar field with array value");
3633 }
else if (parseOptionalAngleBracketOpen()) {
3634 if (
Field.LengthOf == 1)
3635 return Error(Loc,
"Cannot initialize scalar field with array value");
3637 parseAngleBracketClose())
3639 }
else if (
Field.LengthOf > 1) {
3640 return Error(Loc,
"Cannot initialize array field with scalar value");
3643 if (parseRealValue(*Semantics, AsIntValues.
back()))
3647 if (AsIntValues.
size() >
Field.LengthOf) {
3648 return Error(Loc,
"Initializer too long for field; expected at most " +
3649 std::to_string(
Field.LengthOf) +
" elements, got " +
3650 std::to_string(AsIntValues.
size()));
3653 AsIntValues.
append(Contents.AsIntValues.begin() + AsIntValues.
size(),
3654 Contents.AsIntValues.end());
3656 Initializer = FieldInitializer(std::move(AsIntValues));
3660bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3661 const StructFieldInfo &Contents,
3662 FieldInitializer &Initializer) {
3663 SMLoc Loc = getTok().getLoc();
3665 std::vector<StructInitializer> Initializers;
3666 if (
Field.LengthOf > 1) {
3668 if (parseStructInstList(Contents.Structure, Initializers,
3672 }
else if (parseOptionalAngleBracketOpen()) {
3673 if (parseStructInstList(Contents.Structure, Initializers,
3675 parseAngleBracketClose())
3678 return Error(Loc,
"Cannot initialize array field with scalar value");
3681 Initializers.emplace_back();
3682 if (parseStructInitializer(Contents.Structure, Initializers.back()))
3686 if (Initializers.size() >
Field.LengthOf) {
3687 return Error(Loc,
"Initializer too long for field; expected at most " +
3688 std::to_string(
Field.LengthOf) +
" elements, got " +
3689 std::to_string(Initializers.size()));
3693 Initializers.size()));
3695 Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
3699bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3700 FieldInitializer &Initializer) {
3701 switch (
Field.Contents.FT) {
3703 return parseFieldInitializer(
Field,
Field.Contents.IntInfo, Initializer);
3705 return parseFieldInitializer(
Field,
Field.Contents.RealInfo, Initializer);
3707 return parseFieldInitializer(
Field,
Field.Contents.StructInfo, Initializer);
3712bool MasmParser::parseStructInitializer(
const StructInfo &Structure,
3713 StructInitializer &Initializer) {
3714 const AsmToken FirstToken = getTok();
3716 std::optional<AsmToken::TokenKind> EndToken;
3719 }
else if (parseOptionalAngleBracketOpen()) {
3721 AngleBracketDepth++;
3728 return Error(FirstToken.
getLoc(),
"Expected struct initializer");
3731 auto &FieldInitializers = Initializer.FieldInitializers;
3732 size_t FieldIndex = 0;
3735 while (getTok().
isNot(*EndToken) && FieldIndex < Structure.Fields.size()) {
3736 const FieldInfo &
Field = Structure.Fields[FieldIndex++];
3740 FieldInitializers.push_back(
Field.Contents);
3744 FieldInitializers.emplace_back(
Field.Contents.FT);
3745 if (parseFieldInitializer(
Field, FieldInitializers.back()))
3749 SMLoc CommaLoc = getTok().getLoc();
3752 if (FieldIndex == Structure.Fields.size())
3753 return Error(CommaLoc,
"'" + Structure.Name +
3754 "' initializer initializes too many fields");
3760 FieldInitializers.push_back(
Field.Contents);
3764 return parseAngleBracketClose();
3766 return parseToken(*EndToken);
3772bool MasmParser::parseStructInstList(
3773 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
3775 while (getTok().
isNot(EndToken) ||
3778 const AsmToken NextTok = peekTok();
3781 const MCExpr *
Value;
3787 "cannot repeat value a non-constant number of times");
3788 const int64_t Repetitions = MCE->
getValue();
3789 if (Repetitions < 0)
3791 "cannot repeat value a negative number of times");
3793 std::vector<StructInitializer> DuplicatedValues;
3795 "parentheses required for 'dup' contents") ||
3796 parseStructInstList(Structure, DuplicatedValues) || parseRParen())
3799 for (
int i = 0; i < Repetitions; ++i)
3802 Initializers.emplace_back();
3803 if (parseStructInitializer(Structure, Initializers.back()))
3816bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3817 const IntFieldInfo &Contents) {
3819 for (
const MCExpr *
Value : Contents.Values) {
3826bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3827 const RealFieldInfo &Contents) {
3828 for (
const APInt &AsInt : Contents.AsIntValues) {
3835bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3836 const StructFieldInfo &Contents) {
3837 for (
const auto &Initializer : Contents.Initializers) {
3839 for (
const auto &SubField : Contents.Structure.Fields) {
3840 getStreamer().emitZeros(SubField.Offset -
Offset);
3841 Offset = SubField.Offset + SubField.SizeOf;
3842 emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
3848bool MasmParser::emitFieldValue(
const FieldInfo &
Field) {
3849 switch (
Field.Contents.FT) {
3851 return emitFieldValue(
Field,
Field.Contents.IntInfo);
3853 return emitFieldValue(
Field,
Field.Contents.RealInfo);
3855 return emitFieldValue(
Field,
Field.Contents.StructInfo);
3860bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3861 const IntFieldInfo &Contents,
3862 const IntFieldInfo &Initializer) {
3863 for (
const auto &
Value : Initializer.Values) {
3868 for (
const auto &
Value :
3876bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3877 const RealFieldInfo &Contents,
3878 const RealFieldInfo &Initializer) {
3879 for (
const auto &AsInt : Initializer.AsIntValues) {
3884 for (
const auto &AsInt :
3892bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3893 const StructFieldInfo &Contents,
3894 const StructFieldInfo &Initializer) {
3895 for (
const auto &Init : Initializer.Initializers) {
3896 if (emitStructInitializer(Contents.Structure, Init))
3901 Initializer.Initializers.size())) {
3902 if (emitStructInitializer(Contents.Structure, Init))
3908bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3909 const FieldInitializer &Initializer) {
3910 switch (
Field.Contents.FT) {
3912 return emitFieldInitializer(
Field,
Field.Contents.IntInfo,
3913 Initializer.IntInfo);
3915 return emitFieldInitializer(
Field,
Field.Contents.RealInfo,
3916 Initializer.RealInfo);
3918 return emitFieldInitializer(
Field,
Field.Contents.StructInfo,
3919 Initializer.StructInfo);
3924bool MasmParser::emitStructInitializer(
const StructInfo &Structure,
3925 const StructInitializer &Initializer) {
3926 if (!Structure.Initializable)
3927 return Error(getLexer().getLoc(),
3928 "cannot initialize a value of type '" + Structure.Name +
3929 "'; 'org' was used in the type's declaration");
3931 for (
const auto &Init : Initializer.FieldInitializers) {
3932 const auto &
Field = Structure.Fields[
Index++];
3935 if (emitFieldInitializer(
Field, Init))
3940 Structure.Fields, Initializer.FieldInitializers.size())) {
3943 if (emitFieldValue(
Field))
3947 if (
Offset != Structure.Size)
3948 getStreamer().emitZeros(Structure.Size -
Offset);
3953bool MasmParser::emitStructValues(
const StructInfo &Structure,
3955 std::vector<StructInitializer> Initializers;
3956 if (parseStructInstList(Structure, Initializers))
3959 for (
const auto &Initializer : Initializers) {
3960 if (emitStructInitializer(Structure, Initializer))
3965 *
Count = Initializers.size();
3970bool MasmParser::addStructField(StringRef Name,
const StructInfo &Structure) {
3971 StructInfo &OwningStruct = StructInProgress.
back();
3973 OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
3974 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
3976 StructInfo.Structure = Structure;
3977 Field.Type = Structure.Size;
3979 if (parseStructInstList(Structure, StructInfo.Initializers))
3982 Field.LengthOf = StructInfo.Initializers.size();
3986 if (!OwningStruct.IsUnion) {
3987 OwningStruct.NextOffset = FieldEnd;
3989 OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd);
3997bool MasmParser::parseDirectiveStructValue(
const StructInfo &Structure,
3998 StringRef Directive, SMLoc DirLoc) {
3999 if (StructInProgress.
empty()) {
4000 if (emitStructValues(Structure))
4002 }
else if (addStructField(
"", Structure)) {
4003 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4011bool MasmParser::parseDirectiveNamedStructValue(
const StructInfo &Structure,
4012 StringRef Directive,
4013 SMLoc DirLoc, StringRef Name) {
4014 if (StructInProgress.
empty()) {
4017 getStreamer().emitLabel(Sym);
4019 if (emitStructValues(Structure, &
Count))
4022 Type.Name = Structure.Name;
4024 Type.ElementSize = Structure.Size;
4027 }
else if (addStructField(Name, Structure)) {
4028 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4040bool MasmParser::parseDirectiveStruct(StringRef Directive,
4041 DirectiveKind DirKind, StringRef Name,
4045 AsmToken NextTok = getTok();
4046 int64_t AlignmentValue = 1;
4049 parseAbsoluteExpression(AlignmentValue)) {
4050 return addErrorSuffix(
" in alignment value for '" + Twine(Directive) +
4054 return Error(NextTok.
getLoc(),
"alignment must be a power of two; was " +
4055 std::to_string(AlignmentValue));
4061 QualifierLoc = getTok().getLoc();
4062 if (parseIdentifier(Qualifier))
4063 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4064 if (!
Qualifier.equals_insensitive(
"nonunique"))
4065 return Error(QualifierLoc,
"Unrecognized qualifier for '" +
4067 "' directive; expected none or NONUNIQUE");
4071 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4073 StructInProgress.
emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
4081bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
4082 DirectiveKind DirKind) {
4083 if (StructInProgress.
empty())
4084 return TokError(
"missing name in top-level '" + Twine(Directive) +
4089 Name = getTok().getIdentifier();
4093 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4097 StructInProgress.
reserve(StructInProgress.
size() + 1);
4098 StructInProgress.
emplace_back(Name, DirKind == DK_UNION,
4099 StructInProgress.
back().Alignment);
4103bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
4104 if (StructInProgress.
empty())
4105 return Error(NameLoc,
"ENDS directive without matching STRUC/STRUCT/UNION");
4106 if (StructInProgress.
size() > 1)
4107 return Error(NameLoc,
"unexpected name in nested ENDS directive");
4108 if (StructInProgress.
back().Name.compare_insensitive(Name))
4109 return Error(NameLoc,
"mismatched name in ENDS directive; expected '" +
4110 StructInProgress.
back().Name +
"'");
4111 StructInfo Structure = StructInProgress.
pop_back_val();
4115 Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
4116 Structs[
Name.lower()] = std::move(Structure);
4119 return addErrorSuffix(
" in ENDS directive");
4124bool MasmParser::parseDirectiveNestedEnds() {
4125 if (StructInProgress.
empty())
4126 return TokError(
"ENDS directive without matching STRUC/STRUCT/UNION");
4127 if (StructInProgress.
size() == 1)
4128 return TokError(
"missing name in top-level ENDS directive");
4131 return addErrorSuffix(
" in nested ENDS directive");
4133 StructInfo Structure = StructInProgress.
pop_back_val();
4135 Structure.Size =
llvm::alignTo(Structure.Size, Structure.Alignment);
4137 StructInfo &ParentStruct = StructInProgress.
back();
4138 if (Structure.Name.
empty()) {
4141 const size_t OldFields = ParentStruct.Fields.size();
4142 ParentStruct.Fields.insert(
4143 ParentStruct.Fields.end(),
4144 std::make_move_iterator(Structure.Fields.begin()),
4145 std::make_move_iterator(Structure.Fields.end()));
4146 for (
const auto &FieldByName : Structure.FieldsByName) {
4147 ParentStruct.FieldsByName[FieldByName.getKey()] =
4148 FieldByName.getValue() + OldFields;
4151 unsigned FirstFieldOffset = 0;
4152 if (!Structure.Fields.empty() && !ParentStruct.IsUnion) {
4154 ParentStruct.NextOffset,
4155 std::min(ParentStruct.Alignment, Structure.AlignmentSize));
4158 if (ParentStruct.IsUnion) {
4159 ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
4164 const unsigned StructureEnd = FirstFieldOffset + Structure.Size;
4165 if (!ParentStruct.IsUnion) {
4166 ParentStruct.NextOffset = StructureEnd;
4168 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4171 FieldInfo &
Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
4172 Structure.AlignmentSize);
4173 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
4174 Field.Type = Structure.Size;
4176 Field.SizeOf = Structure.Size;
4179 if (!ParentStruct.IsUnion) {
4180 ParentStruct.NextOffset = StructureEnd;
4182 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4184 StructInfo.Structure = Structure;
4185 StructInfo.Initializers.emplace_back();
4186 auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
4187 for (
const auto &SubField : Structure.Fields) {
4188 FieldInitializers.push_back(SubField.Contents);
4197bool MasmParser::parseDirectiveOrg() {
4199 SMLoc OffsetLoc = Lexer.getLoc();
4200 if (checkForValidSection() || parseExpression(
Offset))
4203 return addErrorSuffix(
" in 'org' directive");
4205 if (StructInProgress.
empty()) {
4207 if (checkForValidSection())
4208 return addErrorSuffix(
" in 'org' directive");
4210 getStreamer().emitValueToOffset(
Offset, 0, OffsetLoc);
4213 StructInfo &Structure = StructInProgress.
back();
4215 if (!
Offset->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr()))
4216 return Error(OffsetLoc,
4217 "expected absolute expression in 'org' directive");
4221 "expected non-negative value in struct's 'org' directive; was " +
4222 std::to_string(OffsetRes));
4223 Structure.NextOffset =
static_cast<unsigned>(OffsetRes);
4226 Structure.Initializable =
false;
4232bool MasmParser::emitAlignTo(int64_t Alignment) {
4233 if (StructInProgress.
empty()) {
4235 if (checkForValidSection())
4240 const MCSection *
Section = getStreamer().getCurrentSectionOnly();
4242 getStreamer().emitCodeAlignment(
Align(Alignment),
4243 getTargetParser().getSTI(),
4247 getStreamer().emitValueToAlignment(
Align(Alignment), 0,
4253 StructInfo &Structure = StructInProgress.
back();
4254 Structure.NextOffset =
llvm::alignTo(Structure.NextOffset, Alignment);
4262bool MasmParser::parseDirectiveAlign() {
4263 SMLoc AlignmentLoc = getLexer().getLoc();
4269 "align directive with no operand is ignored") &&
4272 if (parseAbsoluteExpression(Alignment) || parseEOL())
4273 return addErrorSuffix(
" in align directive");
4276 bool ReturnVal =
false;
4283 ReturnVal |=
Error(AlignmentLoc,
"alignment must be a power of 2; was " +
4284 std::to_string(Alignment));
4286 if (emitAlignTo(Alignment))
4287 ReturnVal |= addErrorSuffix(
" in align directive");
4294bool MasmParser::parseDirectiveEven() {
4295 if (parseEOL() || emitAlignTo(2))
4296 return addErrorSuffix(
" in even directive");
4307bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
4311 return Error(Lexer.getLoc(),
4312 "Vararg parameter '" +
Parameters.back().Name +
4313 "' should be last in the list of parameters");
4317 return TokError(
"expected identifier in 'macro' directive");
4320 for (
const MCAsmMacroParameter& CurrParam : Parameters)
4321 if (CurrParam.Name.equals_insensitive(
Parameter.Name))
4322 return TokError(
"macro '" + Name +
"' has multiple parameters"
4332 ParamLoc = Lexer.getLoc();
4333 if (parseMacroArgument(
nullptr,
Parameter.Value))
4339 QualLoc = Lexer.getLoc();
4340 if (parseIdentifier(Qualifier))
4341 return Error(QualLoc,
"missing parameter qualifier for "
4343 Parameter.Name +
"' in macro '" + Name +
4346 if (
Qualifier.equals_insensitive(
"req"))
4348 else if (
Qualifier.equals_insensitive(
"vararg"))
4351 return Error(QualLoc,
4352 Qualifier +
" is not a valid parameter qualifier for '" +
4353 Parameter.Name +
"' in macro '" + Name +
"'");
4366 std::vector<std::string>
Locals;
4368 getTok().getIdentifier().equals_insensitive(
"local")) {
4373 if (parseIdentifier(ID))
4385 AsmToken EndToken, StartToken = getTok();
4386 unsigned MacroDepth = 0;
4387 bool IsMacroFunction =
false;
4397 return Error(NameLoc,
"no matching 'endm' in definition");
4402 if (getTok().getIdentifier().equals_insensitive(
"endm")) {
4403 if (MacroDepth == 0) {
4404 EndToken = getTok();
4407 return TokError(
"unexpected token in '" + EndToken.
getIdentifier() +
4414 }
else if (getTok().getIdentifier().equals_insensitive(
"exitm")) {
4416 IsMacroFunction =
true;
4418 }
else if (isMacroLikeDirective()) {
4426 eatToEndOfStatement();
4430 return Error(NameLoc,
"macro '" + Name +
"' is already defined");
4435 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4436 MCAsmMacro
Macro(Name, Body, std::move(Parameters), std::move(Locals),
4446bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
4447 StringRef Directive,
4448 std::string &
Value) {
4449 SMLoc EndLoc = getTok().getLoc();
4451 return Error(EndLoc,
4452 "unable to parse text item in '" + Directive +
"' directive");
4453 eatToEndOfStatement();
4455 if (!isInsideMacroInstantiation())
4456 return TokError(
"unexpected '" + Directive +
"' in file, "
4457 "no current macro definition");
4460 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4461 TheCondState = TheCondStack.back();
4462 TheCondStack.pop_back();
4471bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
4473 return TokError(
"unexpected token in '" + Directive +
"' directive");
4477 if (isInsideMacroInstantiation()) {
4484 return TokError(
"unexpected '" + Directive +
"' in file, "
4485 "no current macro definition");
4490bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4494 if (parseTokenLoc(NameLoc) ||
4495 check(parseIdentifier(Name), NameLoc,
4496 "expected identifier in 'purge' directive"))
4500 <<
"Un-defining macro: " << Name <<
"\n");
4502 return Error(NameLoc,
"macro '" + Name +
"' is not defined");
4513bool MasmParser::parseDirectiveExtern() {
4515 auto parseOp = [&]() ->
bool {
4517 SMLoc NameLoc = getTok().getLoc();
4519 return Error(NameLoc,
"expected name");
4524 SMLoc TypeLoc = getTok().getLoc();
4525 if (parseIdentifier(TypeName))
4526 return Error(TypeLoc,
"expected type");
4527 if (!
TypeName.equals_insensitive(
"proc")) {
4529 if (lookUpType(TypeName,
Type))
4530 return Error(TypeLoc,
"unrecognized type");
4534 static_cast<MCSymbolCOFF *
>(Sym)->setExternal(
true);
4535 getStreamer().emitSymbolAttribute(Sym,
MCSA_Extern);
4540 if (parseMany(parseOp))
4541 return addErrorSuffix(
" in directive 'extern'");
4547bool MasmParser::parseDirectiveSymbolAttribute(
MCSymbolAttr Attr) {
4548 auto parseOp = [&]() ->
bool {
4549 SMLoc Loc = getTok().getLoc();
4552 return Error(Loc,
"expected identifier");
4556 return Error(Loc,
"non-local symbol required");
4558 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
4559 return Error(Loc,
"unable to emit symbol attribute");
4563 if (parseMany(parseOp))
4564 return addErrorSuffix(
" in directive");
4570bool MasmParser::parseDirectiveComm(
bool IsLocal) {
4571 if (checkForValidSection())
4574 SMLoc IDLoc = getLexer().getLoc();
4577 return TokError(
"expected identifier in directive");
4580 return TokError(
"unexpected token in directive");
4584 SMLoc SizeLoc = getLexer().getLoc();
4585 if (parseAbsoluteExpression(
Size))
4588 int64_t Pow2Alignment = 0;
4589 SMLoc Pow2AlignmentLoc;
4592 Pow2AlignmentLoc = getLexer().getLoc();
4593 if (parseAbsoluteExpression(Pow2Alignment))
4598 return Error(Pow2AlignmentLoc,
"alignment not supported on this target");
4601 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
4604 return Error(Pow2AlignmentLoc,
"alignment must be a power of 2");
4605 Pow2Alignment =
Log2_64(Pow2Alignment);
4615 return Error(SizeLoc,
"invalid '.comm' or '.lcomm' directive size, can't "
4616 "be less than zero");
4621 if (Pow2Alignment < 0)
4622 return Error(Pow2AlignmentLoc,
"invalid '.comm' or '.lcomm' directive "
4623 "alignment, can't be less than zero");
4627 return Error(IDLoc,
"invalid symbol redefinition");
4631 getStreamer().emitLocalCommonSymbol(Sym,
Size,
4632 Align(1ULL << Pow2Alignment));
4636 getStreamer().emitCommonSymbol(Sym,
Size,
Align(1ULL << Pow2Alignment));
4644bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
4646 size_t DelimiterEnd = FirstLine.find_first_of(
"\b\t\v\f\r\x1A ");
4647 assert(DelimiterEnd != std::string::npos);
4648 StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd);
4649 if (Delimiter.
empty())
4650 return Error(DirectiveLoc,
"no delimiter in 'comment' directive");
4653 return Error(DirectiveLoc,
"unmatched delimiter in 'comment' directive");
4663bool MasmParser::parseDirectiveInclude() {
4666 SMLoc IncludeLoc = getTok().getLoc();
4668 if (parseAngleBracketString(
Filename))
4670 if (check(
Filename.
empty(),
"missing filename in 'include' directive") ||
4672 "unexpected token in 'include' directive") ||
4675 check(enterIncludeFile(
Filename), IncludeLoc,
4676 "Could not find include file '" +
Filename +
"'"))
4684bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
4685 TheCondStack.push_back(TheCondState);
4687 if (TheCondState.
Ignore) {
4688 eatToEndOfStatement();
4691 if (parseAbsoluteExpression(ExprValue) || parseEOL())
4700 ExprValue = ExprValue == 0;
4704 TheCondState.
CondMet = ExprValue;
4713bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4714 TheCondStack.push_back(TheCondState);
4717 if (TheCondState.
Ignore) {
4718 eatToEndOfStatement();
4721 if (parseTextItem(Str))
4722 return TokError(
"expected text item parameter for 'ifb' directive");
4727 TheCondState.
CondMet = ExpectBlank == Str.empty();
4736bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4737 bool CaseInsensitive) {
4738 std::string String1, String2;
4740 if (parseTextItem(String1)) {
4742 return TokError(
"expected text item parameter for 'ifidn' directive");
4743 return TokError(
"expected text item parameter for 'ifdif' directive");
4749 "expected comma after first string for 'ifidn' directive");
4750 return TokError(
"expected comma after first string for 'ifdif' directive");
4754 if (parseTextItem(String2)) {
4756 return TokError(
"expected text item parameter for 'ifidn' directive");
4757 return TokError(
"expected text item parameter for 'ifdif' directive");
4760 TheCondStack.push_back(TheCondState);
4762 if (CaseInsensitive)
4764 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4766 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4775bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined) {
4776 TheCondStack.push_back(TheCondState);
4779 if (TheCondState.
Ignore) {
4780 eatToEndOfStatement();
4782 bool is_defined =
false;
4784 SMLoc StartLoc, EndLoc;
4786 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4789 if (check(parseIdentifier(Name),
"expected identifier after 'ifdef'") ||
4793 if (BuiltinSymbolMap.contains(
Name.lower())) {
4803 TheCondState.
CondMet = (is_defined == expect_defined);
4812bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
4813 DirectiveKind DirKind) {
4816 return Error(DirectiveLoc,
"Encountered a .elseif that doesn't follow an"
4817 " .if or an .elseif");
4820 bool LastIgnoreState =
false;
4821 if (!TheCondStack.empty())
4822 LastIgnoreState = TheCondStack.back().Ignore;
4823 if (LastIgnoreState || TheCondState.
CondMet) {
4824 TheCondState.
Ignore =
true;
4825 eatToEndOfStatement();
4828 if (parseAbsoluteExpression(ExprValue))
4840 ExprValue = ExprValue == 0;
4844 TheCondState.
CondMet = ExprValue;
4853bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4856 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4857 " if or an elseif");
4860 bool LastIgnoreState =
false;
4861 if (!TheCondStack.empty())
4862 LastIgnoreState = TheCondStack.back().Ignore;
4863 if (LastIgnoreState || TheCondState.
CondMet) {
4864 TheCondState.
Ignore =
true;
4865 eatToEndOfStatement();
4868 if (parseTextItem(Str)) {
4870 return TokError(
"expected text item parameter for 'elseifb' directive");
4871 return TokError(
"expected text item parameter for 'elseifnb' directive");
4877 TheCondState.
CondMet = ExpectBlank == Str.empty();
4887bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
4888 bool expect_defined) {
4891 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4892 " if or an elseif");
4895 bool LastIgnoreState =
false;
4896 if (!TheCondStack.empty())
4897 LastIgnoreState = TheCondStack.back().Ignore;
4898 if (LastIgnoreState || TheCondState.
CondMet) {
4899 TheCondState.
Ignore =
true;
4900 eatToEndOfStatement();
4902 bool is_defined =
false;
4904 SMLoc StartLoc, EndLoc;
4906 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4909 if (check(parseIdentifier(Name),
4910 "expected identifier after 'elseifdef'") ||
4914 if (BuiltinSymbolMap.contains(
Name.lower())) {
4924 TheCondState.
CondMet = (is_defined == expect_defined);
4933bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4934 bool CaseInsensitive) {
4937 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4938 " if or an elseif");
4941 bool LastIgnoreState =
false;
4942 if (!TheCondStack.empty())
4943 LastIgnoreState = TheCondStack.back().Ignore;
4944 if (LastIgnoreState || TheCondState.
CondMet) {
4945 TheCondState.
Ignore =
true;
4946 eatToEndOfStatement();
4948 std::string String1, String2;
4950 if (parseTextItem(String1)) {
4953 "expected text item parameter for 'elseifidn' directive");
4954 return TokError(
"expected text item parameter for 'elseifdif' directive");
4960 "expected comma after first string for 'elseifidn' directive");
4962 "expected comma after first string for 'elseifdif' directive");
4966 if (parseTextItem(String2)) {
4969 "expected text item parameter for 'elseifidn' directive");
4970 return TokError(
"expected text item parameter for 'elseifdif' directive");
4973 if (CaseInsensitive)
4975 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4977 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4986bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
4992 return Error(DirectiveLoc,
"Encountered an else that doesn't follow an if"
4995 bool LastIgnoreState =
false;
4996 if (!TheCondStack.empty())
4997 LastIgnoreState = TheCondStack.back().Ignore;
4998 if (LastIgnoreState || TheCondState.
CondMet)
4999 TheCondState.
Ignore =
true;
5001 TheCondState.
Ignore =
false;
5008bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5020bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
5021 if (!TheCondStack.empty()) {
5022 if (TheCondStack.back().Ignore) {
5023 eatToEndOfStatement();
5028 std::string Message =
".err directive invoked in source file";
5033 return Error(DirectiveLoc, Message);
5038bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
5039 if (!TheCondStack.empty()) {
5040 if (TheCondStack.back().Ignore) {
5041 eatToEndOfStatement();
5047 if (parseTextItem(
Text))
5048 return Error(getTok().getLoc(),
"missing text item in '.errb' directive");
5050 std::string Message =
".errb directive invoked in source file";
5053 return addErrorSuffix(
" in '.errb' directive");
5058 if (
Text.empty() == ExpectBlank)
5059 return Error(DirectiveLoc, Message);
5065bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
5066 bool ExpectDefined) {
5067 if (!TheCondStack.empty()) {
5068 if (TheCondStack.back().Ignore) {
5069 eatToEndOfStatement();
5074 bool IsDefined =
false;
5076 SMLoc StartLoc, EndLoc;
5078 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
5081 if (check(parseIdentifier(Name),
"expected identifier after '.errdef'"))
5084 if (BuiltinSymbolMap.contains(
Name.lower())) {
5094 std::string Message =
".errdef directive invoked in source file";
5097 return addErrorSuffix(
" in '.errdef' directive");
5102 if (IsDefined == ExpectDefined)
5103 return Error(DirectiveLoc, Message);
5109bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
5110 bool CaseInsensitive) {
5111 if (!TheCondStack.empty()) {
5112 if (TheCondStack.back().Ignore) {
5113 eatToEndOfStatement();
5118 std::string String1, String2;
5120 if (parseTextItem(String1)) {
5122 return TokError(
"expected string parameter for '.erridn' directive");
5123 return TokError(
"expected string parameter for '.errdif' directive");
5129 "expected comma after first string for '.erridn' directive");
5131 "expected comma after first string for '.errdif' directive");
5135 if (parseTextItem(String2)) {
5137 return TokError(
"expected string parameter for '.erridn' directive");
5138 return TokError(
"expected string parameter for '.errdif' directive");
5141 std::string Message;
5143 Message =
".erridn directive invoked in source file";
5145 Message =
".errdif directive invoked in source file";
5148 return addErrorSuffix(
" in '.erridn' directive");
5153 if (CaseInsensitive)
5155 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
5157 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
5160 if ((CaseInsensitive &&
5161 ExpectEqual == StringRef(String1).equals_insensitive(String2)) ||
5162 (ExpectEqual == (String1 == String2)))
5163 return Error(DirectiveLoc, Message);
5169bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero) {
5170 if (!TheCondStack.empty()) {
5171 if (TheCondStack.back().Ignore) {
5172 eatToEndOfStatement();
5178 if (parseAbsoluteExpression(ExprValue))
5179 return addErrorSuffix(
" in '.erre' directive");
5181 std::string Message =
".erre directive invoked in source file";
5184 return addErrorSuffix(
" in '.erre' directive");
5189 if ((ExprValue == 0) == ExpectZero)
5190 return Error(DirectiveLoc, Message);
5196bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5201 return Error(DirectiveLoc,
"Encountered a .endif that doesn't follow "
5203 if (!TheCondStack.empty()) {
5204 TheCondState = TheCondStack.back();
5205 TheCondStack.pop_back();
5211void MasmParser::initializeDirectiveKindMap() {
5212 DirectiveKindMap[
"="] = DK_ASSIGN;
5213 DirectiveKindMap[
"equ"] = DK_EQU;
5214 DirectiveKindMap[
"textequ"] = DK_TEXTEQU;
5218 DirectiveKindMap[
"byte"] = DK_BYTE;
5219 DirectiveKindMap[
"sbyte"] = DK_SBYTE;
5220 DirectiveKindMap[
"word"] = DK_WORD;
5221 DirectiveKindMap[
"sword"] = DK_SWORD;
5222 DirectiveKindMap[
"dword"] = DK_DWORD;
5223 DirectiveKindMap[
"sdword"] = DK_SDWORD;
5224 DirectiveKindMap[
"fword"] = DK_FWORD;
5225 DirectiveKindMap[
"qword"] = DK_QWORD;
5226 DirectiveKindMap[
"sqword"] = DK_SQWORD;
5227 DirectiveKindMap[
"real4"] = DK_REAL4;
5228 DirectiveKindMap[
"real8"] = DK_REAL8;
5229 DirectiveKindMap[
"real10"] = DK_REAL10;
5230 DirectiveKindMap[
"align"] = DK_ALIGN;
5231 DirectiveKindMap[
"even"] = DK_EVEN;
5232 DirectiveKindMap[
"org"] = DK_ORG;
5233 DirectiveKindMap[
"extern"] = DK_EXTERN;
5234 DirectiveKindMap[
"extrn"] = DK_EXTERN;
5235 DirectiveKindMap[
"public"] = DK_PUBLIC;
5237 DirectiveKindMap[
"comment"] = DK_COMMENT;
5238 DirectiveKindMap[
"include"] = DK_INCLUDE;
5239 DirectiveKindMap[
"repeat"] = DK_REPEAT;
5240 DirectiveKindMap[
"rept"] = DK_REPEAT;
5241 DirectiveKindMap[
"while"] = DK_WHILE;
5242 DirectiveKindMap[
"for"] = DK_FOR;
5243 DirectiveKindMap[
"irp"] = DK_FOR;
5244 DirectiveKindMap[
"forc"] = DK_FORC;
5245 DirectiveKindMap[
"irpc"] = DK_FORC;
5246 DirectiveKindMap[
"if"] = DK_IF;
5247 DirectiveKindMap[
"ife"] = DK_IFE;
5248 DirectiveKindMap[
"ifb"] = DK_IFB;
5249 DirectiveKindMap[
"ifnb"] = DK_IFNB;
5250 DirectiveKindMap[
"ifdef"] = DK_IFDEF;
5251 DirectiveKindMap[
"ifndef"] = DK_IFNDEF;
5252 DirectiveKindMap[
"ifdif"] = DK_IFDIF;
5253 DirectiveKindMap[
"ifdifi"] = DK_IFDIFI;
5254 DirectiveKindMap[
"ifidn"] = DK_IFIDN;
5255 DirectiveKindMap[
"ifidni"] = DK_IFIDNI;
5256 DirectiveKindMap[
"elseif"] = DK_ELSEIF;
5257 DirectiveKindMap[
"elseifdef"] = DK_ELSEIFDEF;
5258 DirectiveKindMap[
"elseifndef"] = DK_ELSEIFNDEF;
5259 DirectiveKindMap[
"elseifdif"] = DK_ELSEIFDIF;
5260 DirectiveKindMap[
"elseifidn"] = DK_ELSEIFIDN;
5261 DirectiveKindMap[
"else"] = DK_ELSE;
5262 DirectiveKindMap[
"end"] = DK_END;
5263 DirectiveKindMap[
"endif"] = DK_ENDIF;
5307 DirectiveKindMap[
"macro"] = DK_MACRO;
5308 DirectiveKindMap[
"exitm"] = DK_EXITM;
5309 DirectiveKindMap[
"endm"] = DK_ENDM;
5310 DirectiveKindMap[
"purge"] = DK_PURGE;
5311 DirectiveKindMap[
".err"] = DK_ERR;
5312 DirectiveKindMap[
".errb"] = DK_ERRB;
5313 DirectiveKindMap[
".errnb"] = DK_ERRNB;
5314 DirectiveKindMap[
".errdef"] = DK_ERRDEF;
5315 DirectiveKindMap[
".errndef"] = DK_ERRNDEF;
5316 DirectiveKindMap[
".errdif"] = DK_ERRDIF;
5317 DirectiveKindMap[
".errdifi"] = DK_ERRDIFI;
5318 DirectiveKindMap[
".erridn"] = DK_ERRIDN;
5319 DirectiveKindMap[
".erridni"] = DK_ERRIDNI;
5320 DirectiveKindMap[
".erre"] = DK_ERRE;
5321 DirectiveKindMap[
".errnz"] = DK_ERRNZ;
5322 DirectiveKindMap[
".pushframe"] = DK_PUSHFRAME;
5323 DirectiveKindMap[
".pushreg"] = DK_PUSHREG;
5324 DirectiveKindMap[
".push2reg"] = DK_PUSH2REGS;
5325 DirectiveKindMap[
".pop2reg"] = DK_PUSH2REGS;
5326 DirectiveKindMap[
".popreg"] = DK_PUSHREG;
5327 DirectiveKindMap[
".savereg"] = DK_SAVEREG;
5328 DirectiveKindMap[
".restorereg"] = DK_SAVEREG;
5329 DirectiveKindMap[
".savexmm128"] = DK_SAVEXMM128;
5330 DirectiveKindMap[
".restorexmm128"] = DK_SAVEXMM128;
5331 DirectiveKindMap[
".setframe"] = DK_SETFRAME;
5332 DirectiveKindMap[
".unsetframe"] = DK_SETFRAME;
5333 DirectiveKindMap[
".radix"] = DK_RADIX;
5334 DirectiveKindMap[
"db"] = DK_DB;
5335 DirectiveKindMap[
"dd"] = DK_DD;
5336 DirectiveKindMap[
"df"] = DK_DF;
5337 DirectiveKindMap[
"dq"] = DK_DQ;
5338 DirectiveKindMap[
"dw"] = DK_DW;
5339 DirectiveKindMap[
"echo"] = DK_ECHO;
5340 DirectiveKindMap[
"struc"] = DK_STRUCT;
5341 DirectiveKindMap[
"struct"] = DK_STRUCT;
5342 DirectiveKindMap[
"union"] = DK_UNION;
5343 DirectiveKindMap[
"ends"] = DK_ENDS;
5346bool MasmParser::isMacroLikeDirective() {
5348 bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier())
5349 .CasesLower({
"repeat",
"rept"},
true)
5350 .CaseLower(
"while",
true)
5351 .CasesLower({
"for",
"irp"},
true)
5352 .CasesLower({
"forc",
"irpc"},
true)
5358 peekTok().getIdentifier().equals_insensitive(
"macro"))
5364MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5365 AsmToken EndToken, StartToken = getTok();
5367 unsigned NestLevel = 0;
5371 printError(DirectiveLoc,
"no matching 'endm' in definition");
5375 if (isMacroLikeDirective())
5380 getTok().getIdentifier().equals_insensitive(
"endm")) {
5381 if (NestLevel == 0) {
5382 EndToken = getTok();
5385 printError(getTok().getLoc(),
"unexpected token in 'endm' directive");
5394 eatToEndOfStatement();
5399 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5403 return &MacroLikeBodies.back();
5406bool MasmParser::expandStatement(SMLoc Loc) {
5408 SMLoc EndLoc = getTok().getLoc();
5413 StringMap<std::string> BuiltinValues;
5414 for (
const auto &S : BuiltinSymbolMap) {
5415 const BuiltinSymbol &Sym = S.getValue();
5416 if (std::optional<std::string>
Text = evaluateBuiltinTextMacro(Sym, Loc)) {
5417 BuiltinValues[S.getKey().lower()] = std::move(*
Text);
5420 for (
const auto &
B : BuiltinValues) {
5421 MCAsmMacroParameter
P;
5422 MCAsmMacroArgument
A;
5423 P.Name =
B.getKey();
5431 for (
const auto &V : Variables) {
5434 MCAsmMacroParameter
P;
5435 MCAsmMacroArgument
A;
5444 MacroLikeBodies.emplace_back(StringRef(), Body, Parameters);
5445 MCAsmMacro
M = MacroLikeBodies.back();
5448 SmallString<80> Buf;
5449 raw_svector_ostream OS(Buf);
5450 if (expandMacro(OS,
M.Body,
M.Parameters,
Arguments,
M.Locals, EndLoc))
5452 std::unique_ptr<MemoryBuffer>
Expansion =
5458 EndStatementAtEOFStack.push_back(
false);
5463void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5464 raw_svector_ostream &OS) {
5465 instantiateMacroLikeBody(M, DirectiveLoc, getTok().getLoc(), OS);
5467void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5469 raw_svector_ostream &OS) {
5472 std::unique_ptr<MemoryBuffer> Instantiation =
5477 MacroInstantiation *
MI =
new MacroInstantiation{DirectiveLoc, CurBuffer,
5478 ExitLoc, TheCondStack.size()};
5479 ActiveMacros.push_back(
MI);
5484 EndStatementAtEOFStack.push_back(
true);
5492bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) {
5493 const MCExpr *CountExpr;
5494 SMLoc CountLoc = getTok().getLoc();
5495 if (parseExpression(CountExpr))
5499 if (!CountExpr->evaluateAsAbsolute(
Count, getStreamer().getAssemblerPtr())) {
5500 return Error(CountLoc,
"unexpected token in '" + Dir +
"' directive");
5503 if (check(
Count < 0, CountLoc,
"Count is negative") || parseEOL())
5507 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5513 SmallString<256> Buf;
5514 raw_svector_ostream OS(Buf);
5516 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5519 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5528bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) {
5529 const MCExpr *CondExpr;
5530 SMLoc CondLoc = getTok().getLoc();
5531 if (parseExpression(CondExpr))
5535 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5541 SmallString<256> Buf;
5542 raw_svector_ostream OS(Buf);
5544 if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr()))
5545 return Error(CondLoc,
"expected absolute expression in 'while' directive");
5549 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5551 instantiateMacroLikeBody(M, DirectiveLoc, DirectiveLoc, OS);
5561bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
5563 MCAsmMacroArguments
A;
5564 if (check(parseIdentifier(
Parameter.Name),
5565 "expected identifier in '" + Dir +
"' directive"))
5574 ParamLoc = Lexer.getLoc();
5575 if (parseMacroArgument(
nullptr,
Parameter.Value))
5581 QualLoc = Lexer.getLoc();
5582 if (parseIdentifier(Qualifier))
5583 return Error(QualLoc,
"missing parameter qualifier for "
5588 if (
Qualifier.equals_insensitive(
"req"))
5591 return Error(QualLoc,
5592 Qualifier +
" is not a valid parameter qualifier for '" +
5593 Parameter.Name +
"' in '" + Dir +
"' directive");
5598 "expected comma in '" + Dir +
"' directive") ||
5600 "values in '" + Dir +
5601 "' directive must be enclosed in angle brackets"))
5607 return addErrorSuffix(
" in arguments for '" + Dir +
"' directive");
5616 "values in '" + Dir +
5617 "' directive must be enclosed in angle brackets") ||
5622 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5628 SmallString<256> Buf;
5629 raw_svector_ostream OS(Buf);
5631 for (
const MCAsmMacroArgument &Arg :
A) {
5632 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5636 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5645bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
5649 if (check(parseIdentifier(
Parameter.Name),
5650 "expected identifier in '" + Directive +
"' directive") ||
5652 "expected comma in '" + Directive +
"' directive"))
5654 if (parseAngleBracketString(Argument)) {
5662 for (; End <
Argument.size(); ++End) {
5672 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5678 SmallString<256> Buf;
5679 raw_svector_ostream OS(Buf);
5681 StringRef
Values(Argument);
5682 for (std::size_t
I = 0, End =
Values.size();
I != End; ++
I) {
5683 MCAsmMacroArgument Arg;
5686 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5690 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5695bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
5697 const MCExpr *
Value;
5698 SMLoc ExprLoc = getLexer().getLoc();
5699 if (parseExpression(
Value))
5703 return Error(ExprLoc,
"unexpected expression in _emit");
5706 return Error(ExprLoc,
"literal value out of range for directive");
5712bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
5713 const MCExpr *
Value;
5714 SMLoc ExprLoc = getLexer().getLoc();
5715 if (parseExpression(
Value))
5719 return Error(ExprLoc,
"unexpected expression in align");
5722 return Error(ExprLoc,
"literal value not a power of two greater then zero");
5728bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
5729 const SMLoc Loc = getLexer().getLoc();
5731 StringRef RadixString = StringRef(RadixStringRaw).trim();
5735 "radix must be a decimal number in the range 2 to 16; was " +
5738 if (Radix < 2 || Radix > 16)
5739 return Error(Loc,
"radix must be in the range 2 to 16; was " +
5740 std::to_string(Radix));
5741 getLexer().setMasmDefaultRadix(Radix);
5747bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) {
5750 if (!StringRef(Message).ends_with(
"\n"))
5778bool MasmParser::defineMacro(StringRef Name, StringRef
Value) {
5780 if (Var.Name.empty())
5782 return setTextVariable(Var, Name,
Value, SMLoc(),
5783 Variable::WARN_ON_REDEFINITION);
5786bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info)
const {
5787 const std::pair<StringRef, StringRef> BaseMember =
Name.split(
'.');
5788 const StringRef
Base = BaseMember.first,
Member = BaseMember.second;
5789 return lookUpField(
Base, Member, Info);
5792bool MasmParser::lookUpField(StringRef
Base, StringRef Member,
5793 AsmFieldInfo &Info)
const {
5797 AsmFieldInfo BaseInfo;
5798 if (
Base.contains(
'.') && !lookUpField(
Base, BaseInfo))
5801 auto StructIt = Structs.
find(
Base.lower());
5802 auto TypeIt = KnownType.
find(
Base.lower());
5803 if (TypeIt != KnownType.
end()) {
5804 StructIt = Structs.
find(TypeIt->second.Name.lower());
5806 if (StructIt != Structs.
end())
5807 return lookUpField(StructIt->second, Member, Info);
5812bool MasmParser::lookUpField(
const StructInfo &Structure, StringRef Member,
5813 AsmFieldInfo &Info)
const {
5815 Info.Type.Name = Structure.Name;
5816 Info.Type.Size = Structure.Size;
5817 Info.Type.ElementSize = Structure.Size;
5818 Info.Type.Length = 1;
5822 std::pair<StringRef, StringRef>
Split =
Member.split(
'.');
5823 const StringRef FieldName =
Split.first, FieldMember =
Split.second;
5825 auto StructIt = Structs.
find(FieldName.
lower());
5826 if (StructIt != Structs.
end())
5827 return lookUpField(StructIt->second, FieldMember, Info);
5829 auto FieldIt = Structure.FieldsByName.
find(FieldName.
lower());
5830 if (FieldIt == Structure.FieldsByName.
end())
5833 const FieldInfo &
Field = Structure.Fields[FieldIt->second];
5834 if (FieldMember.empty()) {
5839 if (
Field.Contents.FT == FT_STRUCT)
5840 Info.Type.Name =
Field.Contents.StructInfo.Structure.Name;
5842 Info.Type.Name =
"";
5846 if (
Field.Contents.FT != FT_STRUCT)
5848 const StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
5850 if (lookUpField(StructInfo.Structure, FieldMember, Info))
5857bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info)
const {
5858 unsigned Size = StringSwitch<unsigned>(Name)
5859 .CasesLower({
"byte",
"db",
"sbyte"}, 1)
5860 .CasesLower({
"word",
"dw",
"sword"}, 2)
5861 .CasesLower({
"dword",
"dd",
"sdword"}, 4)
5862 .CasesLower({
"fword",
"df"}, 6)
5863 .CasesLower({
"qword",
"dq",
"sqword"}, 8)
5864 .CaseLower(
"real4", 4)
5865 .CaseLower(
"real8", 8)
5866 .CaseLower(
"real10", 10)
5876 auto StructIt = Structs.
find(
Name.lower());
5877 if (StructIt != Structs.
end()) {
5878 const StructInfo &Structure = StructIt->second;
5880 Info.ElementSize = Structure.Size;
5882 Info.Size = Structure.Size;
5889bool MasmParser::parseMSInlineAsm(
5890 std::string &AsmString,
unsigned &NumOutputs,
unsigned &NumInputs,
5891 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5892 SmallVectorImpl<std::string> &Constraints,
5893 SmallVectorImpl<std::string> &Clobbers,
const MCInstrInfo *MII,
5894 MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
5895 SmallVector<void *, 4> InputDecls;
5896 SmallVector<void *, 4> OutputDecls;
5897 SmallVector<bool, 4> InputDeclsAddressOf;
5898 SmallVector<bool, 4> OutputDeclsAddressOf;
5899 SmallVector<std::string, 4> InputConstraints;
5900 SmallVector<std::string, 4> OutputConstraints;
5909 unsigned InputIdx = 0;
5910 unsigned OutputIdx = 0;
5913 if (parseCurlyBlockScope(AsmStrRewrites))
5916 ParseStatementInfo
Info(&AsmStrRewrites);
5917 bool StatementErr = parseStatement(Info, &SI);
5919 if (StatementErr ||
Info.ParseError) {
5921 printPendingErrors();
5926 assert(!hasPendingError() &&
"unexpected error from parseStatement");
5928 if (
Info.Opcode == ~0U)
5934 for (
unsigned i = 1, e =
Info.ParsedOperands.size(); i != e; ++i) {
5935 MCParsedAsmOperand &Operand = *
Info.ParsedOperands[i];
5939 !getTargetParser().omitRegisterFromClobberLists(Operand.
getReg())) {
5940 unsigned NumDefs =
Desc.getNumDefs();
5949 if (SymName.
empty())
5957 if (Operand.
isImm()) {
5965 bool isOutput = (i == 1) &&
Desc.mayStore();
5971 OutputConstraints.
push_back((
"=" + Constraint).str());
5977 if (
Desc.operands()[i - 1].isBranchTarget())
5989 NumOutputs = OutputDecls.
size();
5990 NumInputs = InputDecls.
size();
5995 Clobbers.
assign(ClobberRegs.
size(), std::string());
5996 for (
unsigned I = 0,
E = ClobberRegs.
size();
I !=
E; ++
I) {
5997 raw_string_ostream OS(Clobbers[
I]);
6002 if (NumOutputs || NumInputs) {
6003 unsigned NumExprs = NumOutputs + NumInputs;
6004 OpDecls.resize(NumExprs);
6005 Constraints.
resize(NumExprs);
6006 for (
unsigned i = 0; i < NumOutputs; ++i) {
6007 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
6008 Constraints[i] = OutputConstraints[i];
6010 for (
unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++
j) {
6011 OpDecls[
j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
6012 Constraints[
j] = InputConstraints[i];
6017 std::string AsmStringIR;
6018 raw_string_ostream OS(AsmStringIR);
6019 StringRef ASMString =
6021 const char *AsmStart = ASMString.
begin();
6022 const char *AsmEnd = ASMString.
end();
6024 for (
auto I = AsmStrRewrites.
begin(),
E = AsmStrRewrites.
end();
I !=
E; ++
I) {
6025 const AsmRewrite &AR = *
I;
6032 assert(Loc >= AsmStart &&
"Expected Loc to be at or after Start!");
6035 if (
unsigned Len = Loc - AsmStart)
6036 OS << StringRef(AsmStart, Len);
6040 AsmStart = Loc + AR.
Len;
6044 unsigned AdditionalSkip = 0;
6066 size_t OffsetLen = OffsetName.
size();
6067 auto rewrite_it = std::find_if(
6068 I, AsmStrRewrites.
end(), [&](
const AsmRewrite &FusingAR) {
6069 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6070 (FusingAR.Kind == AOK_Input ||
6071 FusingAR.Kind == AOK_CallInput);
6073 if (rewrite_it == AsmStrRewrites.
end()) {
6074 OS <<
"offset " << OffsetName;
6076 OS <<
"${" << InputIdx++ <<
":P}";
6077 rewrite_it->Done =
true;
6079 OS <<
'$' << InputIdx++;
6080 rewrite_it->Done =
true;
6092 OS <<
'$' << InputIdx++;
6095 OS <<
"${" << InputIdx++ <<
":P}";
6098 OS <<
'$' << OutputIdx++;
6103 case 8: OS <<
"byte ptr ";
break;
6104 case 16: OS <<
"word ptr ";
break;
6105 case 32: OS <<
"dword ptr ";
break;
6106 case 64: OS <<
"qword ptr ";
break;
6107 case 80: OS <<
"xword ptr ";
break;
6108 case 128: OS <<
"xmmword ptr ";
break;
6109 case 256: OS <<
"ymmword ptr ";
break;
6119 if (
getContext().getAsmInfo().getAlignmentIsInBytes())
6124 unsigned Val = AR.
Val;
6126 assert(Val < 10 &&
"Expected alignment less then 2^10.");
6127 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6139 AsmStart = Loc + AR.
Len + AdditionalSkip;
6143 if (AsmStart != AsmEnd)
6144 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6146 AsmString = OS.
str();
6150void MasmParser::initializeBuiltinSymbolMaps() {
6152 BuiltinSymbolMap[
"@version"] = BI_VERSION;
6153 BuiltinSymbolMap[
"@line"] = BI_LINE;
6154 BuiltinSymbolMap[
"@unwindversion"] = BI_UNWINDVERSION;
6157 BuiltinSymbolMap[
"@date"] = BI_DATE;
6158 BuiltinSymbolMap[
"@time"] = BI_TIME;
6159 BuiltinSymbolMap[
"@filecur"] = BI_FILECUR;
6160 BuiltinSymbolMap[
"@filename"] = BI_FILENAME;
6161 BuiltinSymbolMap[
"@curseg"] = BI_CURSEG;
6164 BuiltinFunctionMap[
"@catstr"] = BI_CATSTR;
6167 if (
getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
6185const MCExpr *MasmParser::evaluateBuiltinValue(BuiltinSymbol Symbol,
6195 if (ActiveMacros.empty())
6199 ActiveMacros.front()->ExitBuffer);
6202 case BI_UNWINDVERSION:
6209std::optional<std::string>
6210MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
6216 char TmpBuffer[
sizeof(
"mm/dd/yy")];
6217 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%D", &TM);
6218 return std::string(TmpBuffer, Len);
6222 char TmpBuffer[
sizeof(
"hh:mm:ss")];
6223 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%T", &TM);
6224 return std::string(TmpBuffer, Len);
6229 ActiveMacros.empty() ? CurBuffer : ActiveMacros.front()->ExitBuffer)
6237 return getStreamer().getCurrentSectionOnly()->getName().str();
6242bool MasmParser::evaluateBuiltinMacroFunction(BuiltinFunction
Function,
6246 "' requires arguments in parentheses")) {
6257 MCAsmMacro
M(Name,
"",
P, {},
true);
6259 MCAsmMacroArguments
A;
6268 for (
const MCAsmMacroArgument &Arg :
A) {
6269 for (
const AsmToken &Tok : Arg) {
6287 struct tm TM,
unsigned CB) {
6288 return new MasmParser(SM,
C, Out, MAI, TM, CB);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
AMDGPU Lower Kernel Arguments
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc)
This function checks if the next token is <string> type or arithmetic.
static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI, AsmToken::TokenKind K, MCBinaryExpr::Opcode &Kind, bool ShouldUseLogicalShr)
static std::string angleBracketString(StringRef AltMacroStr)
creating a string without the escape characters '!'.
static int rewritesSort(const AsmRewrite *AsmRewriteA, const AsmRewrite *AsmRewriteB)
This file implements the BitVector class.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Value * getPointer(Value *Ptr)
const std::string FatArchTraits< MachO::fat_arch >::StructName
static bool isMacroParameterChar(char C)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static constexpr StringLiteral Filename
OptimizedStructLayoutField Field
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallString class.
This file defines the SmallVector class.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
unsigned getBitWidth() const
Return the number of bits in the APInt.
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
ConditionalAssemblyType TheCond
LLVM_ABI SMLoc getLoc() const
bool isNot(TokenKind K) const
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
StringRef getStringContents() const
Get the contents of a string token (without quotes).
bool is(TokenKind K) const
LLVM_ABI SMLoc getEndLoc() const
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
This class is intended to be used as a base class for asm properties and features specific to the tar...
bool preserveAsmComments() const
Return true if assembly (inline or otherwise) should be parsed.
bool shouldUseLogicalShr() const
StringRef getInternalSymbolPrefix() const
virtual bool useCodeAlign(const MCSection &Sec) const
Generic assembler parser interface, for use by target specific assembly parsers.
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
@ AShr
Arithmetic shift right.
@ LShr
Logical shift right.
@ GTE
Signed greater than or equal comparison (result is either 0 or some target-specific non-zero value).
@ GT
Signed greater than comparison (result is either 0 or some target-specific non-zero value)
@ Xor
Bitwise exclusive or.
@ LT
Signed less than comparison (result is either 0 or some target-specific non-zero value).
@ LTE
Signed less than or equal comparison (result is either 0 or some target-specific non-zero value).
@ NE
Inequality comparison.
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
LLVM_ABI MCSymbol * createDirectionalLocalSymbol(unsigned LocalLabelVal)
Create the definition of a directional local symbol for numbered label (used for "1:" definitions).
const MCAsmInfo & getAsmInfo() const
virtual void printRegName(raw_ostream &OS, MCRegister Reg)
Print the assembler register name.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
virtual bool isReg() const =0
isReg - Is this a register operand?
virtual bool needAddressOf() const
needAddressOf - Do we need to emit code to get the address of the variable/label?
virtual MCRegister getReg() const =0
virtual bool isOffsetOfLocal() const
isOffsetOfLocal - Do we need to emit code to get the offset of the local variable,...
virtual StringRef getSymName()
virtual bool isImm() const =0
isImm - Is this an immediate operand?
unsigned getMCOperandNum()
StringRef getConstraint()
virtual void * getOpDecl()
Streaming machine code generation interface.
virtual void addBlankLine()
Emit a blank line to a .s file to pretty it up.
virtual void addExplicitComment(const Twine &T)
Add explicit comment T.
virtual void initSections(const MCSubtargetInfo &STI)
Create the default sections and set the initial one.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
void finish(SMLoc EndLoc=SMLoc())
Finish emission of machine code.
const MCSymbol & getSymbol() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
bool isUndefined() const
isUndefined - Check if this symbol undefined (i.e., implicitly defined).
StringRef getName() const
getName - Get the symbol name.
bool isVariable() const
isVariable - Check if this is a variable symbol.
LLVM_ABI void setVariableValue(const MCExpr *Value)
void setRedefinable(bool Value)
Mark this symbol as redefinable.
void redefineIfPossible()
Prepare this symbol to be redefined.
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
static const MCUnaryExpr * createLNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createPlus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createMinus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
StringRef getBuffer() const
constexpr bool isFailure() const
constexpr bool isSuccess() const
LLVM_ABI void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true, bool ShowLocation=true) const
SourceMgr::DiagKind getKind() const
StringRef getLineContents() const
StringRef getMessage() const
ArrayRef< std::pair< unsigned, unsigned > > getRanges() const
const SourceMgr * getSourceMgr() const
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
constexpr const char * getPointer() const
constexpr bool isValid() const
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
LLVM_ABI void printIncludeStackForDiagnostic(SMLoc Loc, raw_ostream &OS) const
Prints the include stack of a buffer unless it is a macro instantiation buffer.
unsigned getMainFileID() const
const MemoryBuffer * getMemoryBuffer(unsigned i) const
LLVM_ABI void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
SMLoc getParentIncludeLoc(unsigned i) const
LLVM_ABI unsigned FindBufferContainingLoc(SMLoc Loc) const
Return the ID of the buffer containing the specified location.
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
void setDiagHandler(DiagHandlerTy DH, void *Ctx=nullptr)
Specify a diagnostic handler to be invoked every time PrintMessage is called.
LLVM_ABI unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, std::string &IncludedFile)
Search for a file with the specified name in the current directory or in one of the IncludeDirs.
unsigned FindLineNumber(SMLoc Loc, unsigned BufferID=0) const
Find the line number for the specified location in the specified file.
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
iterator find(StringRef Key)
bool contains(StringRef Key) const
contains - Return true if the element is in the map, false otherwise.
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
ValueTy lookup(StringRef Key) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
StringMapIterBase< ValueTy, true > const_iterator
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Represent a constant reference to a string, i.e.
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
std::string str() const
Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
Check if the string is empty.
LLVM_ABI std::string upper() const
Convert the given ASCII string to uppercase.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
Get the string size.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
LLVM_ABI std::string lower() const
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
StringRef str() const
Return a StringRef for the vector contents.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
LLVM_ABI SimpleSymbol parseSymbol(StringRef SymName)
Get symbol classification by parsing the name of a symbol.
std::variant< std::monostate, DecisionParameters, BranchParameters > Parameters
The type of MC/DC-specific parameters.
@ Parameter
An inlay hint that is for a parameter.
LLVM_ABI Instruction & front() const
LLVM_ABI StringRef stem(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get stem.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
RelativeUniformCounterPtr Values
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI MCAsmParser * createMCMasmParser(SourceMgr &, MCContext &, MCStreamer &, const MCAsmInfo &, struct tm, unsigned CB=0)
Create an MCAsmParser instance for parsing Microsoft MASM-style assembly.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
std::vector< MCAsmMacroParameter > MCAsmMacroParameters
auto unique(Range &&R, Predicate P)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI SourceMgr SrcMgr
auto dyn_cast_or_null(const Y &Val)
cl::opt< unsigned > AsmMacroMaxNestingDepth
const char AsmRewritePrecedence[]
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool isAlnum(char C)
Checks whether character C is either a decimal digit or an uppercase or lowercase letter as classifie...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, bool Upper=false)
format_hex_no_prefix - Output N as a fixed width hexadecimal.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
bool isSpace(char C)
Checks whether character C is whitespace in the "C" locale.
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
@ MCSA_Global
.type _foo, @gnu_unique_object
@ MCSA_Extern
.extern (XCOFF)
std::vector< AsmToken > Value
uint64_t Offset
The offset of this field in the final layout.