75typedef std::vector<AsmToken> MCAsmMacroArgument;
76typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
79struct MacroInstantiation {
81 SMLoc InstantiationLoc;
90 size_t CondStackDepth;
93struct ParseStatementInfo {
98 unsigned Opcode = ~0
U;
101 bool ParseError =
false;
104 std::optional<std::string> ExitValue;
106 SmallVectorImpl<AsmRewrite> *AsmRewrites =
nullptr;
108 ParseStatementInfo() =
delete;
109 ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
110 : AsmRewrites(rewrites) {}
122 bool IsUnion =
false;
123 bool Initializable =
true;
124 unsigned Alignment = 0;
125 unsigned AlignmentSize = 0;
126 unsigned NextOffset = 0;
128 std::vector<FieldInfo> Fields;
129 StringMap<size_t> FieldsByName;
131 FieldInfo &addField(StringRef FieldName, FieldType FT,
132 unsigned FieldAlignmentSize);
134 StructInfo() =
default;
135 StructInfo(StringRef
StructName,
bool Union,
unsigned AlignmentValue);
143struct StructInitializer;
147 IntFieldInfo() =
default;
151struct RealFieldInfo {
154 RealFieldInfo() =
default;
158struct StructFieldInfo {
159 std::vector<StructInitializer> Initializers;
160 StructInfo Structure;
162 StructFieldInfo() =
default;
163 StructFieldInfo(std::vector<StructInitializer> V, StructInfo S);
166class FieldInitializer {
170 IntFieldInfo IntInfo;
171 RealFieldInfo RealInfo;
172 StructFieldInfo StructInfo;
176 FieldInitializer(FieldType FT);
180 FieldInitializer(std::vector<StructInitializer> &&Initializers,
181 struct StructInfo Structure);
183 FieldInitializer(
const FieldInitializer &Initializer);
184 FieldInitializer(FieldInitializer &&Initializer);
186 FieldInitializer &operator=(
const FieldInitializer &Initializer);
187 FieldInitializer &operator=(FieldInitializer &&Initializer);
190struct StructInitializer {
191 std::vector<FieldInitializer> FieldInitializers;
202 unsigned LengthOf = 0;
207 FieldInitializer Contents;
209 FieldInfo(FieldType FT) : Contents(FT) {}
212StructFieldInfo::StructFieldInfo(std::vector<StructInitializer> V,
214 Initializers = std::move(V);
215 Structure = std::move(S);
218StructInfo::StructInfo(StringRef
StructName,
bool Union,
219 unsigned AlignmentValue)
222FieldInfo &StructInfo::addField(
StringRef FieldName, FieldType FT,
223 unsigned FieldAlignmentSize) {
224 if (!FieldName.
empty())
225 FieldsByName[FieldName.
lower()] = Fields.size();
226 Fields.emplace_back(FT);
227 FieldInfo &
Field = Fields.back();
229 llvm::alignTo(NextOffset, std::min(Alignment, FieldAlignmentSize));
233 AlignmentSize = std::max(AlignmentSize, FieldAlignmentSize);
237FieldInitializer::~FieldInitializer() {
240 IntInfo.~IntFieldInfo();
243 RealInfo.~RealFieldInfo();
246 StructInfo.~StructFieldInfo();
251FieldInitializer::FieldInitializer(FieldType FT) : FT(FT) {
254 new (&IntInfo) IntFieldInfo();
257 new (&RealInfo) RealFieldInfo();
260 new (&StructInfo) StructFieldInfo();
267 new (&IntInfo) IntFieldInfo(std::move(
Values));
272 new (&RealInfo) RealFieldInfo(std::move(AsIntValues));
275FieldInitializer::FieldInitializer(
276 std::vector<StructInitializer> &&Initializers,
struct StructInfo Structure)
278 new (&StructInfo) StructFieldInfo(std::move(Initializers), Structure);
281FieldInitializer::FieldInitializer(
const FieldInitializer &Initializer)
282 : FT(Initializer.FT) {
285 new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
288 new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
291 new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
296FieldInitializer::FieldInitializer(FieldInitializer &&Initializer)
297 : FT(Initializer.FT) {
300 new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
303 new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
306 new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
312FieldInitializer::operator=(
const FieldInitializer &Initializer) {
313 if (FT != Initializer.FT) {
316 IntInfo.~IntFieldInfo();
319 RealInfo.~RealFieldInfo();
322 StructInfo.~StructFieldInfo();
329 IntInfo = Initializer.IntInfo;
332 RealInfo = Initializer.RealInfo;
335 StructInfo = Initializer.StructInfo;
341FieldInitializer &FieldInitializer::operator=(FieldInitializer &&Initializer) {
342 if (FT != Initializer.FT) {
345 IntInfo.~IntFieldInfo();
348 RealInfo.~RealFieldInfo();
351 StructInfo.~StructFieldInfo();
358 IntInfo = Initializer.IntInfo;
361 RealInfo = Initializer.RealInfo;
364 StructInfo = Initializer.StructInfo;
373class MasmParser :
public MCAsmParser {
376 void *SavedDiagContext;
377 std::unique_ptr<MCAsmParserExtension> PlatformParser;
386 BitVector EndStatementAtEOFStack;
388 AsmCond TheCondState;
389 std::vector<AsmCond> TheCondStack;
394 StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
398 enum RedefinableKind { NOT_REDEFINABLE, WARN_ON_REDEFINITION, REDEFINABLE };
401 RedefinableKind Redefinable = REDEFINABLE;
403 std::string TextValue;
405 StringMap<Variable> Variables;
411 StringMap<StructInfo> Structs;
414 StringMap<AsmTypeInfo> KnownType;
417 std::vector<MacroInstantiation*> ActiveMacros;
420 std::deque<MCAsmMacro> MacroLikeBodies;
423 unsigned NumOfMacroInstantiations;
426 struct CppHashInfoTy {
431 CppHashInfoTy() : LineNumber(0), Buf(0) {}
433 CppHashInfoTy CppHashInfo;
436 StringRef FirstCppHashFilename;
443 unsigned AssemblerDialect = 1U;
446 bool ParsingMSInlineAsm =
false;
449 unsigned AngleBracketDepth = 0
U;
452 uint16_t LocalCounter = 0;
455 MasmParser(SourceMgr &
SM, MCContext &Ctx, MCStreamer &Out,
456 const MCAsmInfo &MAI,
struct tm TM,
unsigned CB = 0);
457 MasmParser(
const MasmParser &) =
delete;
458 MasmParser &operator=(
const MasmParser &) =
delete;
459 ~MasmParser()
override;
461 bool Run(
bool NoInitialTextSection,
bool NoFinalize =
false)
override;
463 void addDirectiveHandler(StringRef Directive,
464 ExtensionDirectiveHandler Handler)
override {
465 ExtensionDirectiveMap[Directive] = std::move(Handler);
466 DirectiveKindMap.try_emplace(Directive, DK_HANDLER_DIRECTIVE);
469 void addAliasForDirective(StringRef Directive, StringRef Alias)
override {
470 DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
476 unsigned getAssemblerDialect()
override {
477 if (AssemblerDialect == ~0U)
478 return MAI.getAssemblerDialect();
480 return AssemblerDialect;
482 void setAssemblerDialect(
unsigned i)
override {
483 AssemblerDialect = i;
486 void Note(SMLoc L,
const Twine &
Msg, SMRange
Range = {})
override;
488 bool printError(SMLoc L,
const Twine &
Msg, SMRange
Range = {})
override;
490 enum ExpandKind { ExpandMacros, DoNotExpandMacros };
491 const AsmToken &Lex(ExpandKind ExpandNextToken);
492 const AsmToken &Lex()
override {
return Lex(ExpandMacros); }
494 void setParsingMSInlineAsm(
bool V)
override {
495 ParsingMSInlineAsm =
V;
498 Lexer.setLexMasmIntegers(V);
500 bool isParsingMSInlineAsm()
override {
return ParsingMSInlineAsm; }
502 bool isParsingMasm()
const override {
return true; }
504 bool defineMacro(StringRef Name, StringRef
Value)
override;
506 bool lookUpField(StringRef Name, AsmFieldInfo &Info)
const override;
507 bool lookUpField(StringRef
Base, StringRef Member,
508 AsmFieldInfo &Info)
const override;
510 bool lookUpType(StringRef Name, AsmTypeInfo &Info)
const override;
512 bool parseMSInlineAsm(std::string &AsmString,
unsigned &NumOutputs,
514 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
515 SmallVectorImpl<std::string> &Constraints,
516 SmallVectorImpl<std::string> &Clobbers,
517 const MCInstrInfo *MII, MCInstPrinter *IP,
518 MCAsmParserSemaCallback &SI)
override;
520 bool parseExpression(
const MCExpr *&Res);
521 bool parseExpression(
const MCExpr *&Res, SMLoc &EndLoc)
override;
522 bool parsePrimaryExpr(
const MCExpr *&Res, SMLoc &EndLoc,
523 AsmTypeInfo *TypeInfo)
override;
524 bool parseParenExpression(
const MCExpr *&Res, SMLoc &EndLoc)
override;
525 bool parseAbsoluteExpression(int64_t &Res)
override;
529 bool parseRealValue(
const fltSemantics &Semantics, APInt &Res);
533 enum IdentifierPositionKind { StandardPosition, StartOfStatement };
534 bool parseIdentifier(StringRef &Res, IdentifierPositionKind Position);
535 bool parseIdentifier(StringRef &Res)
override {
536 return parseIdentifier(Res, StandardPosition);
538 void eatToEndOfStatement()
override;
540 bool checkForValidSection()
override;
546 const AsmToken peekTok(
bool ShouldSkipSpace =
true);
548 bool parseStatement(ParseStatementInfo &Info,
549 MCAsmParserSemaCallback *SI);
550 bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
551 bool parseCppHashLineFilenameComment(SMLoc L);
553 bool expandMacro(raw_svector_ostream &OS, StringRef Body,
556 const std::vector<std::string> &Locals, SMLoc L);
559 bool isInsideMacroInstantiation() {
return !ActiveMacros.empty();}
565 bool handleMacroEntry(
566 const MCAsmMacro *M, SMLoc NameLoc,
573 bool handleMacroInvocation(
const MCAsmMacro *M, SMLoc NameLoc);
576 void handleMacroExit();
580 parseMacroArgument(
const MCAsmMacroParameter *MP, MCAsmMacroArgument &MA,
585 parseMacroArguments(
const MCAsmMacro *M, MCAsmMacroArguments &
A,
588 void printMacroInstantiations();
590 bool expandStatement(SMLoc Loc);
593 SMRange
Range = {})
const {
599 bool lookUpField(
const StructInfo &Structure, StringRef Member,
600 AsmFieldInfo &Info)
const;
603 bool enterIncludeFile(
const std::string &
Filename);
611 void jumpToLoc(SMLoc Loc,
unsigned InBuffer = 0,
612 bool EndStatementAtEOF =
true);
624 StringRef parseStringToEndOfStatement()
override;
626 bool parseTextItem(std::string &
Data);
631 bool parseBinOpRHS(
unsigned Precedence,
const MCExpr *&Res, SMLoc &EndLoc);
632 bool parseParenExpr(
const MCExpr *&Res, SMLoc &EndLoc);
633 bool parseBracketExpr(
const MCExpr *&Res, SMLoc &EndLoc);
638 DK_HANDLER_DIRECTIVE,
729 StringMap<DirectiveKind> DirectiveKindMap;
731 bool isMacroLikeDirective();
758 StringMap<BuiltinSymbol> BuiltinSymbolMap;
760 const MCExpr *evaluateBuiltinValue(BuiltinSymbol Symbol, SMLoc StartLoc);
762 std::optional<std::string> evaluateBuiltinTextMacro(BuiltinSymbol Symbol,
766 enum BuiltinFunction {
773 StringMap<BuiltinFunction> BuiltinFunctionMap;
775 bool evaluateBuiltinMacroFunction(BuiltinFunction Function, StringRef Name,
779 bool parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated);
782 bool emitIntValue(
const MCExpr *
Value,
unsigned Size);
783 bool parseScalarInitializer(
unsigned Size,
784 SmallVectorImpl<const MCExpr *> &
Values,
785 unsigned StringPadLength = 0);
786 bool parseScalarInstList(
787 unsigned Size, SmallVectorImpl<const MCExpr *> &
Values,
789 bool emitIntegralValues(
unsigned Size,
unsigned *
Count =
nullptr);
790 bool addIntegralField(StringRef Name,
unsigned Size);
791 bool parseDirectiveValue(StringRef IDVal,
unsigned Size);
792 bool parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
793 StringRef Name, SMLoc NameLoc);
796 bool emitRealValues(
const fltSemantics &Semantics,
unsigned *
Count =
nullptr);
797 bool addRealField(StringRef Name,
const fltSemantics &Semantics,
size_t Size);
798 bool parseDirectiveRealValue(StringRef IDVal,
const fltSemantics &Semantics,
800 bool parseRealInstList(
801 const fltSemantics &Semantics, SmallVectorImpl<APInt> &
Values,
803 bool parseDirectiveNamedRealValue(StringRef TypeName,
804 const fltSemantics &Semantics,
805 unsigned Size, StringRef Name,
808 bool parseOptionalAngleBracketOpen();
809 bool parseAngleBracketClose(
const Twine &
Msg =
"expected '>'");
811 bool parseFieldInitializer(
const FieldInfo &
Field,
812 FieldInitializer &Initializer);
813 bool parseFieldInitializer(
const FieldInfo &
Field,
814 const IntFieldInfo &Contents,
815 FieldInitializer &Initializer);
816 bool parseFieldInitializer(
const FieldInfo &
Field,
817 const RealFieldInfo &Contents,
818 FieldInitializer &Initializer);
819 bool parseFieldInitializer(
const FieldInfo &
Field,
820 const StructFieldInfo &Contents,
821 FieldInitializer &Initializer);
823 bool parseStructInitializer(
const StructInfo &Structure,
824 StructInitializer &Initializer);
825 bool parseStructInstList(
826 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
829 bool emitFieldValue(
const FieldInfo &
Field);
830 bool emitFieldValue(
const FieldInfo &
Field,
const IntFieldInfo &Contents);
831 bool emitFieldValue(
const FieldInfo &
Field,
const RealFieldInfo &Contents);
832 bool emitFieldValue(
const FieldInfo &
Field,
const StructFieldInfo &Contents);
834 bool emitFieldInitializer(
const FieldInfo &
Field,
835 const FieldInitializer &Initializer);
836 bool emitFieldInitializer(
const FieldInfo &
Field,
837 const IntFieldInfo &Contents,
838 const IntFieldInfo &Initializer);
839 bool emitFieldInitializer(
const FieldInfo &
Field,
840 const RealFieldInfo &Contents,
841 const RealFieldInfo &Initializer);
842 bool emitFieldInitializer(
const FieldInfo &
Field,
843 const StructFieldInfo &Contents,
844 const StructFieldInfo &Initializer);
846 bool emitStructInitializer(
const StructInfo &Structure,
847 const StructInitializer &Initializer);
850 bool emitStructValues(
const StructInfo &Structure,
unsigned *
Count =
nullptr);
851 bool addStructField(StringRef Name,
const StructInfo &Structure);
852 bool parseDirectiveStructValue(
const StructInfo &Structure,
853 StringRef Directive, SMLoc DirLoc);
854 bool parseDirectiveNamedStructValue(
const StructInfo &Structure,
855 StringRef Directive, SMLoc DirLoc,
859 bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
860 DirectiveKind DirKind, SMLoc NameLoc);
862 bool parseDirectiveOrg();
864 bool emitAlignTo(int64_t Alignment);
865 bool parseDirectiveAlign();
866 bool parseDirectiveEven();
869 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
870 bool parseDirectiveExitMacro(SMLoc DirectiveLoc, StringRef Directive,
872 bool parseDirectiveEndMacro(StringRef Directive);
873 bool parseDirectiveMacro(StringRef Name, SMLoc NameLoc);
875 bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind,
876 StringRef Name, SMLoc NameLoc);
877 bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind);
878 bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
879 bool parseDirectiveNestedEnds();
881 bool parseDirectiveExtern();
887 bool parseDirectiveComm(
bool IsLocal);
889 bool parseDirectiveComment(SMLoc DirectiveLoc);
891 bool parseDirectiveInclude();
894 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
896 bool parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
899 bool parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
900 bool CaseInsensitive);
902 bool parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined);
904 bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
906 bool parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
908 bool parseDirectiveElseIfdef(SMLoc DirectiveLoc,
bool expect_defined);
911 bool parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
912 bool CaseInsensitive);
913 bool parseDirectiveElse(SMLoc DirectiveLoc);
914 bool parseDirectiveEndIf(SMLoc DirectiveLoc);
915 bool parseEscapedString(std::string &
Data)
override;
916 bool parseAngleBracketString(std::string &
Data)
override;
919 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
920 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
921 raw_svector_ostream &OS);
922 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
923 SMLoc ExitLoc, raw_svector_ostream &OS);
924 bool parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Directive);
925 bool parseDirectiveFor(SMLoc DirectiveLoc, StringRef Directive);
926 bool parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive);
927 bool parseDirectiveWhile(SMLoc DirectiveLoc);
930 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
934 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
937 bool parseDirectiveEnd(SMLoc DirectiveLoc);
940 bool parseDirectiveError(SMLoc DirectiveLoc);
942 bool parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
944 bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
bool ExpectDefined);
947 bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
948 bool CaseInsensitive);
950 bool parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero);
953 bool parseDirectiveRadix(SMLoc DirectiveLoc);
956 bool parseDirectiveEcho(SMLoc DirectiveLoc);
958 void initializeDirectiveKindMap();
959 void initializeBuiltinSymbolMaps();
972MasmParser::MasmParser(SourceMgr &
SM, MCContext &Ctx, MCStreamer &Out,
973 const MCAsmInfo &MAI,
struct tm TM,
unsigned CB)
974 : MCAsmParser(Ctx, Out,
SM, MAI), CurBuffer(CB ? CB :
SM.getMainFileID()),
978 SavedDiagHandler =
SrcMgr.getDiagHandler();
979 SavedDiagContext =
SrcMgr.getDiagContext();
982 Lexer.setBuffer(
SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
983 EndStatementAtEOFStack.push_back(
true);
986 switch (Ctx.getObjectFileType()) {
987 case MCContext::IsCOFF:
988 PlatformParser.reset(createCOFFMasmParser());
991 report_fatal_error(
"llvm-ml currently supports only COFF output.");
995 initializeDirectiveKindMap();
996 PlatformParser->Initialize(*
this);
997 initializeBuiltinSymbolMaps();
999 NumOfMacroInstantiations = 0;
1002MasmParser::~MasmParser() {
1003 assert((HadError || ActiveMacros.empty()) &&
1004 "Unexpected active macro instantiation!");
1011void MasmParser::printMacroInstantiations() {
1013 for (std::vector<MacroInstantiation *>::const_reverse_iterator
1014 it = ActiveMacros.rbegin(),
1015 ie = ActiveMacros.rend();
1018 "while in macro instantiation");
1021void MasmParser::Note(SMLoc L,
const Twine &
Msg, SMRange
Range) {
1022 printPendingErrors();
1024 printMacroInstantiations();
1027bool MasmParser::Warning(SMLoc L,
const Twine &
Msg, SMRange
Range) {
1028 if (getTargetParser().getTargetOptions().MCNoWarn)
1030 if (getTargetParser().getTargetOptions().MCFatalWarnings)
1033 printMacroInstantiations();
1037bool MasmParser::printError(SMLoc L,
const Twine &
Msg, SMRange
Range) {
1040 printMacroInstantiations();
1044bool MasmParser::enterIncludeFile(
const std::string &
Filename) {
1045 std::string IncludedFile;
1053 EndStatementAtEOFStack.push_back(
true);
1057void MasmParser::jumpToLoc(SMLoc Loc,
unsigned InBuffer,
1058 bool EndStatementAtEOF) {
1064bool MasmParser::expandMacros() {
1065 const AsmToken &Tok = getTok();
1068 const llvm::MCAsmMacro *
M =
getContext().lookupMacro(IDLower);
1071 const SMLoc MacroLoc = Tok.
getLoc();
1074 if (handleMacroInvocation(M, MacroLoc)) {
1081 std::optional<std::string> ExpandedValue;
1083 if (
auto BuiltinIt = BuiltinSymbolMap.find(IDLower);
1084 BuiltinIt != BuiltinSymbolMap.end()) {
1086 evaluateBuiltinTextMacro(BuiltinIt->getValue(), Tok.
getLoc());
1087 }
else if (
auto BuiltinFuncIt = BuiltinFunctionMap.find(IDLower);
1088 BuiltinFuncIt != BuiltinFunctionMap.end()) {
1090 if (parseIdentifier(Name)) {
1094 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), Name, Res)) {
1097 ExpandedValue = Res;
1098 }
else if (
auto VarIt = Variables.
find(IDLower);
1099 VarIt != Variables.
end() && VarIt->getValue().IsText) {
1100 ExpandedValue = VarIt->getValue().TextValue;
1105 std::unique_ptr<MemoryBuffer> Instantiation =
1113 EndStatementAtEOFStack.push_back(
false);
1118const AsmToken &MasmParser::Lex(ExpandKind ExpandNextToken) {
1120 Error(Lexer.getErrLoc(), Lexer.getErr());
1121 bool StartOfStatement =
false;
1126 if (!getTok().getString().
empty() && getTok().getString().
front() !=
'\n' &&
1129 StartOfStatement =
true;
1132 const AsmToken *tok = &Lexer.Lex();
1135 if (StartOfStatement) {
1138 size_t ReadCount = Lexer.peekTokens(Buf);
1170 if (ParentIncludeLoc != SMLoc()) {
1171 EndStatementAtEOFStack.pop_back();
1172 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1175 EndStatementAtEOFStack.pop_back();
1176 assert(EndStatementAtEOFStack.empty());
1182const AsmToken MasmParser::peekTok(
bool ShouldSkipSpace) {
1186 size_t ReadCount = Lexer.peekTokens(Buf, ShouldSkipSpace);
1188 if (ReadCount == 0) {
1192 if (ParentIncludeLoc != SMLoc()) {
1193 EndStatementAtEOFStack.pop_back();
1194 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1195 return peekTok(ShouldSkipSpace);
1197 EndStatementAtEOFStack.pop_back();
1198 assert(EndStatementAtEOFStack.empty());
1205bool MasmParser::Run(
bool NoInitialTextSection,
bool NoFinalize) {
1207 if (!NoInitialTextSection)
1214 AsmCond StartingCondState = TheCondState;
1224 ParseStatementInfo
Info(&AsmStrRewrites);
1225 bool HasError = parseStatement(Info,
nullptr);
1230 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
1234 printPendingErrors();
1237 if (HasError && !getLexer().justConsumedEOL())
1238 eatToEndOfStatement();
1241 printPendingErrors();
1244 assert(!hasPendingError() &&
"unexpected error from parseStatement");
1248 printError(getTok().getLoc(),
"unmatched .ifs or .elses");
1257 for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
1258 if (std::get<2>(LocSym)->isUndefined()) {
1261 CppHashInfo = std::get<1>(LocSym);
1262 printError(std::get<0>(LocSym),
"directional label undefined");
1269 if (!HadError && !NoFinalize)
1270 Out.
finish(Lexer.getLoc());
1275bool MasmParser::checkForValidSection() {
1276 if (!ParsingMSInlineAsm && !(getStreamer().getCurrentFragment() &&
1277 getStreamer().getCurrentSectionOnly())) {
1279 return Error(getTok().getLoc(),
1280 "expected section directive before assembly directive");
1286void MasmParser::eatToEndOfStatement() {
1290 if (ParentIncludeLoc == SMLoc()) {
1294 EndStatementAtEOFStack.pop_back();
1295 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1306SmallVector<StringRef, 1>
1308 SmallVector<StringRef, 1> Refs;
1309 const char *
Start = getTok().getLoc().getPointer();
1310 while (Lexer.isNot(EndTok)) {
1313 if (ParentIncludeLoc == SMLoc()) {
1318 EndStatementAtEOFStack.pop_back();
1319 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1321 Start = getTok().getLoc().getPointer();
1331 SmallVector<StringRef, 1> Refs = parseStringRefsTo(EndTok);
1333 for (StringRef S : Refs) {
1334 Str.append(S.str());
1339StringRef MasmParser::parseStringToEndOfStatement() {
1340 const char *
Start = getTok().getLoc().getPointer();
1345 const char *End = getTok().getLoc().getPointer();
1346 return StringRef(Start, End - Start);
1354bool MasmParser::parseParenExpr(
const MCExpr *&Res, SMLoc &EndLoc) {
1355 if (parseExpression(Res))
1357 EndLoc = Lexer.getTok().getEndLoc();
1358 return parseRParen();
1366bool MasmParser::parseBracketExpr(
const MCExpr *&Res, SMLoc &EndLoc) {
1367 if (parseExpression(Res))
1369 EndLoc = getTok().getEndLoc();
1370 if (parseToken(
AsmToken::RBrac,
"expected ']' in brackets expression"))
1383bool MasmParser::parsePrimaryExpr(
const MCExpr *&Res, SMLoc &EndLoc,
1384 AsmTypeInfo *TypeInfo) {
1385 SMLoc FirstTokenLoc = getLexer().getLoc();
1387 switch (FirstTokenKind) {
1389 return TokError(
"unknown token in expression");
1395 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1403 if (parseIdentifier(Identifier)) {
1406 if (Lexer.getMAI().getDollarIsPC()) {
1413 EndLoc = FirstTokenLoc;
1416 return Error(FirstTokenLoc,
"invalid token in expression");
1421 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1429 bool Before =
Identifier.equals_insensitive(
"@b");
1432 return Error(FirstTokenLoc,
"Expected @@ label before @B reference");
1442 return Error(getLexer().getLoc(),
"expected a symbol reference");
1447 if (
Split.second.empty()) {
1450 if (lookUpField(SymbolName,
Split.second, Info)) {
1451 std::pair<StringRef, StringRef> BaseMember =
Split.second.split(
'.');
1452 StringRef
Base = BaseMember.first,
Member = BaseMember.second;
1453 lookUpField(
Base, Member, Info);
1464 auto BuiltinIt = BuiltinSymbolMap.find(
SymbolName.lower());
1465 const BuiltinSymbol
Symbol = (BuiltinIt == BuiltinSymbolMap.end())
1467 : BuiltinIt->getValue();
1468 if (Symbol != BI_NO_SYMBOL) {
1469 const MCExpr *
Value = evaluateBuiltinValue(Symbol, FirstTokenLoc);
1479 if (VarIt != Variables.
end())
1490 DoInline = TV->inlineAssignedExpr();
1498 const MCExpr *SymRef =
1508 if (
Info.Type.Name.empty()) {
1510 if (TypeIt != KnownType.
end()) {
1511 Info.Type = TypeIt->second;
1515 *TypeInfo =
Info.Type;
1520 return TokError(
"literal value out of range for directive");
1522 int64_t
IntVal = getTok().getIntVal();
1524 EndLoc = Lexer.getTok().getEndLoc();
1530 SMLoc ValueLoc = getTok().getLoc();
1532 if (parseEscapedString(
Value))
1534 if (
Value.size() > 8)
1535 return Error(ValueLoc,
"literal value out of range");
1536 uint64_t IntValue = 0;
1537 for (
const unsigned char CharVal :
Value)
1538 IntValue = (IntValue << 8) | CharVal;
1543 APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
1544 uint64_t
IntVal = RealVal.bitcastToAPInt().getZExtValue();
1546 EndLoc = Lexer.getTok().getEndLoc();
1556 EndLoc = Lexer.getTok().getEndLoc();
1562 return parseParenExpr(Res, EndLoc);
1564 if (!PlatformParser->HasBracketExpressions())
1565 return TokError(
"brackets expression not supported on this target");
1567 return parseBracketExpr(Res, EndLoc);
1570 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1576 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1582 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1589bool MasmParser::parseExpression(
const MCExpr *&Res) {
1591 return parseExpression(Res, EndLoc);
1602 "Argument to the function cannot be a NULL value");
1604 while ((*CharPtr !=
'>') && (*CharPtr !=
'\n') && (*CharPtr !=
'\r') &&
1605 (*CharPtr !=
'\0')) {
1606 if (*CharPtr ==
'!')
1610 if (*CharPtr ==
'>') {
1620 for (
size_t Pos = 0; Pos < BracketContents.
size(); Pos++) {
1621 if (BracketContents[Pos] ==
'!')
1623 Res += BracketContents[Pos];
1638bool MasmParser::parseExpression(
const MCExpr *&Res, SMLoc &EndLoc) {
1641 if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
1642 parseBinOpRHS(1, Res, EndLoc))
1648 if (Res->evaluateAsAbsolute(
Value))
1654bool MasmParser::parseParenExpression(
const MCExpr *&Res, SMLoc &EndLoc) {
1656 return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
1659bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
1662 SMLoc StartLoc = Lexer.getLoc();
1663 if (parseExpression(Expr))
1666 if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
1667 return Error(StartLoc,
"expected absolute expression");
1674 bool ShouldUseLogicalShr,
1675 bool EndExpressionAtGreater) {
1703 if (EndExpressionAtGreater)
1744 if (EndExpressionAtGreater)
1755 AngleBracketDepth > 0);
1760bool MasmParser::parseBinOpRHS(
unsigned Precedence,
const MCExpr *&Res,
1762 SMLoc StartLoc = Lexer.getLoc();
1766 TokKind = StringSwitch<AsmToken::TokenKind>(Lexer.getTok().getString())
1782 unsigned TokPrec = getBinOpPrecedence(TokKind, Kind);
1786 if (TokPrec < Precedence)
1793 if (getTargetParser().parsePrimaryExpr(
RHS, EndLoc))
1799 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
1800 if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1,
RHS, EndLoc))
1813bool MasmParser::parseStatement(ParseStatementInfo &Info,
1814 MCAsmParserSemaCallback *SI) {
1815 assert(!hasPendingError() &&
"parseStatement started with pending error");
1821 if (getTok().getString().
empty() || getTok().getString().
front() ==
'\r' ||
1822 getTok().getString().
front() ==
'\n')
1831 SMLoc ExpansionLoc = getTok().getLoc();
1838 AsmToken
ID = getTok();
1839 SMLoc IDLoc =
ID.getLoc();
1842 return parseCppHashLineFilenameComment(IDLoc);
1849 IDVal = getTok().getString();
1852 return Error(IDLoc,
"unexpected token at start of statement");
1853 }
else if (parseIdentifier(IDVal, StartOfStatement)) {
1854 if (!TheCondState.
Ignore) {
1856 return Error(IDLoc,
"unexpected token at start of statement");
1865 DirectiveKindMap.find(IDVal.
lower());
1866 DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
1868 : DirKindIt->getValue();
1874 return parseDirectiveIf(IDLoc, DirKind);
1876 return parseDirectiveIfb(IDLoc,
true);
1878 return parseDirectiveIfb(IDLoc,
false);
1880 return parseDirectiveIfdef(IDLoc,
true);
1882 return parseDirectiveIfdef(IDLoc,
false);
1884 return parseDirectiveIfidn(IDLoc,
false,
1887 return parseDirectiveIfidn(IDLoc,
false,
1890 return parseDirectiveIfidn(IDLoc,
true,
1893 return parseDirectiveIfidn(IDLoc,
true,
1897 return parseDirectiveElseIf(IDLoc, DirKind);
1899 return parseDirectiveElseIfb(IDLoc,
true);
1901 return parseDirectiveElseIfb(IDLoc,
false);
1903 return parseDirectiveElseIfdef(IDLoc,
true);
1905 return parseDirectiveElseIfdef(IDLoc,
false);
1907 return parseDirectiveElseIfidn(IDLoc,
false,
1910 return parseDirectiveElseIfidn(IDLoc,
false,
1913 return parseDirectiveElseIfidn(IDLoc,
true,
1916 return parseDirectiveElseIfidn(IDLoc,
true,
1919 return parseDirectiveElse(IDLoc);
1921 return parseDirectiveEndIf(IDLoc);
1926 if (TheCondState.
Ignore) {
1927 eatToEndOfStatement();
1937 if (checkForValidSection())
1945 return Error(IDLoc,
"invalid use of pseudo-symbol '.' as a label");
1953 if (ParsingMSInlineAsm && SI) {
1954 StringRef RewrittenLabel =
1955 SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc,
true);
1957 "We should have an internal name here.");
1960 IDVal = RewrittenLabel;
1963 if (IDVal ==
"@@") {
1986 if (!getTargetParser().isParsingMSInlineAsm())
1996 return handleMacroEntry(M, IDLoc, ArgumentEndTok);
2001 if (DirKind != DK_NO_DIRECTIVE) {
2017 return parseDirectiveNestedEnds();
2022 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2025 return (*Handler.second)(Handler.first, IDVal, IDLoc);
2031 ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(
ID);
2033 "Should only return Failure iff there was an error");
2045 return parseDirectiveAscii(IDVal,
false);
2048 return parseDirectiveAscii(IDVal,
true);
2052 return parseDirectiveValue(IDVal, 1);
2056 return parseDirectiveValue(IDVal, 2);
2060 return parseDirectiveValue(IDVal, 4);
2063 return parseDirectiveValue(IDVal, 6);
2067 return parseDirectiveValue(IDVal, 8);
2069 return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4);
2071 return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8);
2073 return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10);
2076 return parseDirectiveNestedStruct(IDVal, DirKind);
2078 return parseDirectiveNestedEnds();
2080 return parseDirectiveAlign();
2082 return parseDirectiveEven();
2084 return parseDirectiveOrg();
2086 return parseDirectiveExtern();
2088 return parseDirectiveSymbolAttribute(
MCSA_Global);
2090 return parseDirectiveComm(
false);
2092 return parseDirectiveComment(IDLoc);
2094 return parseDirectiveInclude();
2096 return parseDirectiveRepeat(IDLoc, IDVal);
2098 return parseDirectiveWhile(IDLoc);
2100 return parseDirectiveFor(IDLoc, IDVal);
2102 return parseDirectiveForc(IDLoc, IDVal);
2104 Info.ExitValue =
"";
2105 return parseDirectiveExitMacro(IDLoc, IDVal, *
Info.ExitValue);
2107 Info.ExitValue =
"";
2108 return parseDirectiveEndMacro(IDVal);
2110 return parseDirectivePurgeMacro(IDLoc);
2112 return parseDirectiveEnd(IDLoc);
2114 return parseDirectiveError(IDLoc);
2116 return parseDirectiveErrorIfb(IDLoc,
true);
2118 return parseDirectiveErrorIfb(IDLoc,
false);
2120 return parseDirectiveErrorIfdef(IDLoc,
true);
2122 return parseDirectiveErrorIfdef(IDLoc,
false);
2124 return parseDirectiveErrorIfidn(IDLoc,
false,
2127 return parseDirectiveErrorIfidn(IDLoc,
false,
2130 return parseDirectiveErrorIfidn(IDLoc,
true,
2133 return parseDirectiveErrorIfidn(IDLoc,
true,
2136 return parseDirectiveErrorIfe(IDLoc,
true);
2138 return parseDirectiveErrorIfe(IDLoc,
false);
2140 return parseDirectiveRadix(IDLoc);
2142 return parseDirectiveEcho(IDLoc);
2145 return Error(IDLoc,
"unknown directive");
2149 auto IDIt = Structs.
find(IDVal.
lower());
2150 if (IDIt != Structs.
end())
2151 return parseDirectiveStructValue(IDIt->getValue(), IDVal,
2155 const AsmToken nextTok = getTok();
2156 const StringRef nextVal = nextTok.
getString();
2157 const SMLoc nextLoc = nextTok.
getLoc();
2159 const AsmToken afterNextTok = peekTok();
2170 getTargetParser().flushPendingInstructions(getStreamer());
2176 return parseDirectiveEnds(IDVal, IDLoc);
2181 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2183 if (Handler.first) {
2186 return (*Handler.second)(Handler.first, nextVal, nextLoc);
2191 DirKindIt = DirectiveKindMap.find(nextVal.
lower());
2192 DirKind = (DirKindIt == DirectiveKindMap.end())
2194 : DirKindIt->getValue();
2202 return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
2213 return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc);
2224 return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc);
2235 return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc);
2245 return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc);
2256 return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc);
2259 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), 4,
2263 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8,
2267 return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(),
2272 return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc);
2275 return parseDirectiveEnds(IDVal, IDLoc);
2278 return parseDirectiveMacro(IDVal, IDLoc);
2282 auto NextIt = Structs.
find(nextVal.
lower());
2283 if (NextIt != Structs.
end()) {
2285 return parseDirectiveNamedStructValue(NextIt->getValue(),
2286 nextVal, nextLoc, IDVal);
2290 if (ParsingMSInlineAsm && (IDVal ==
"_emit" || IDVal ==
"__emit" ||
2291 IDVal ==
"_EMIT" || IDVal ==
"__EMIT"))
2292 return parseDirectiveMSEmit(IDLoc, Info, IDVal.
size());
2295 if (ParsingMSInlineAsm && (IDVal ==
"align" || IDVal ==
"ALIGN"))
2296 return parseDirectiveMSAlign(IDLoc, Info);
2298 if (ParsingMSInlineAsm && (IDVal ==
"even" || IDVal ==
"EVEN"))
2300 if (checkForValidSection())
2304 std::string OpcodeStr = IDVal.
lower();
2305 ParseInstructionInfo IInfo(
Info.AsmRewrites);
2306 bool ParseHadError = getTargetParser().parseInstruction(IInfo, OpcodeStr,
ID,
2307 Info.ParsedOperands);
2308 Info.ParseError = ParseHadError;
2311 if (getShowParsedOperands()) {
2312 SmallString<256> Str;
2313 raw_svector_ostream OS(Str);
2314 OS <<
"parsed instruction: [";
2315 for (
unsigned i = 0; i !=
Info.ParsedOperands.size(); ++i) {
2318 Info.ParsedOperands[i]->print(OS, MAI);
2326 if (hasPendingError() || ParseHadError)
2330 if (!ParseHadError) {
2332 if (getTargetParser().matchAndEmitInstruction(
2333 IDLoc,
Info.Opcode,
Info.ParsedOperands, Out, ErrorInfo,
2334 getTargetParser().isParsingMSInlineAsm()))
2341bool MasmParser::parseCurlyBlockScope(
2342 SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
2347 SMLoc StartLoc = Lexer.getLoc();
2360bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
2365 "Lexing Cpp line comment: Expected Integer");
2366 int64_t LineNumber = getTok().getIntVal();
2369 "Lexing Cpp line comment: Expected String");
2370 StringRef
Filename = getTok().getString();
2378 CppHashInfo.Loc =
L;
2380 CppHashInfo.LineNumber = LineNumber;
2381 CppHashInfo.Buf = CurBuffer;
2382 if (FirstCppHashFilename.
empty())
2389void MasmParser::DiagHandler(
const SMDiagnostic &Diag,
void *
Context) {
2390 const MasmParser *Parser =
static_cast<const MasmParser *
>(
Context);
2391 raw_ostream &OS =
errs();
2394 SMLoc DiagLoc = Diag.
getLoc();
2396 unsigned CppHashBuf =
2397 Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
2401 if (!Parser->SavedDiagHandler)
2407 if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
2408 DiagBuf != CppHashBuf) {
2409 if (Parser->SavedDiagHandler)
2410 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2412 Diag.
print(
nullptr, OS);
2419 const std::string &
Filename = std::string(Parser->CppHashInfo.Filename);
2422 int CppHashLocLineNo =
2423 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2425 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2431 if (Parser->SavedDiagHandler)
2432 Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
2434 NewDiag.print(
nullptr, OS);
2440 return isAlnum(
C) ||
C ==
'_' ||
C ==
'$' ||
C ==
'@' ||
C ==
'?';
2443bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
2446 const std::vector<std::string> &Locals, SMLoc L) {
2448 if (NParameters !=
A.size())
2449 return Error(L,
"Wrong number of arguments");
2450 StringMap<std::string> LocalSymbols;
2453 for (StringRef
Local : Locals) {
2454 raw_string_ostream LocalName(Name);
2461 std::optional<char> CurrentQuote;
2462 while (!Body.
empty()) {
2464 std::size_t End = Body.
size(), Pos = 0;
2465 std::size_t IdentifierPos = End;
2466 for (; Pos != End; ++Pos) {
2469 if (Body[Pos] ==
'&')
2474 if (IdentifierPos == End)
2475 IdentifierPos = Pos;
2477 IdentifierPos = End;
2481 if (!CurrentQuote) {
2482 if (Body[Pos] ==
'\'' || Body[Pos] ==
'"')
2483 CurrentQuote = Body[Pos];
2484 }
else if (Body[Pos] == CurrentQuote) {
2485 if (Pos + 1 != End && Body[Pos + 1] == CurrentQuote) {
2490 CurrentQuote.reset();
2494 if (IdentifierPos != End) {
2497 Pos = IdentifierPos;
2498 IdentifierPos = End;
2502 OS << Body.
slice(0, Pos);
2509 bool InitialAmpersand = (Body[
I] ==
'&');
2510 if (InitialAmpersand) {
2517 const char *Begin = Body.
data() + Pos;
2519 const std::string ArgumentLower =
Argument.lower();
2523 if (Parameters[Index].
Name.equals_insensitive(ArgumentLower))
2526 if (Index == NParameters) {
2527 if (InitialAmpersand)
2529 auto it = LocalSymbols.
find(ArgumentLower);
2530 if (it != LocalSymbols.
end())
2536 for (
const AsmToken &Token :
A[Index]) {
2546 OS << Token.getIntVal();
2548 OS << Token.getString();
2552 if (Pos < End && Body[Pos] ==
'&') {
2563bool MasmParser::parseMacroArgument(
const MCAsmMacroParameter *MP,
2564 MCAsmMacroArgument &MA,
2567 if (Lexer.isNot(EndTok)) {
2568 SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok);
2569 for (StringRef S : Str) {
2576 SMLoc StrLoc = Lexer.getLoc(), EndLoc;
2578 const char *StrChar = StrLoc.
getPointer() + 1;
2579 const char *EndChar = EndLoc.
getPointer() - 1;
2580 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
2587 unsigned ParenLevel = 0;
2591 return TokError(
"unexpected token");
2608 MA.push_back(getTok());
2612 if (ParenLevel != 0)
2613 return TokError(
"unbalanced parentheses in argument");
2615 if (MA.empty() && MP) {
2617 return TokError(
"missing value for required parameter '" + MP->
Name +
2627bool MasmParser::parseMacroArguments(
const MCAsmMacro *M,
2628 MCAsmMacroArguments &
A,
2630 const unsigned NParameters =
M ?
M->Parameters.size() : 0;
2631 bool NamedParametersFound =
false;
2632 SmallVector<SMLoc, 4> FALocs;
2634 A.resize(NParameters);
2635 FALocs.
resize(NParameters);
2640 for (
unsigned Parameter = 0; !NParameters ||
Parameter < NParameters;
2642 SMLoc IDLoc = Lexer.getLoc();
2643 MCAsmMacroParameter FA;
2646 if (parseIdentifier(FA.
Name))
2647 return Error(IDLoc,
"invalid argument identifier for formal argument");
2650 return TokError(
"expected '=' after formal parameter identifier");
2654 NamedParametersFound =
true;
2657 if (NamedParametersFound && FA.
Name.
empty())
2658 return Error(IDLoc,
"cannot mix positional and keyword arguments");
2662 assert(M &&
"expected macro to be defined");
2664 for (FAI = 0; FAI < NParameters; ++FAI)
2665 if (
M->Parameters[FAI].Name == FA.
Name)
2668 if (FAI >= NParameters) {
2669 return Error(IDLoc,
"parameter named '" + FA.
Name +
2670 "' does not exist for macro '" +
M->Name +
"'");
2674 const MCAsmMacroParameter *MP =
nullptr;
2675 if (M && PI < NParameters)
2676 MP = &
M->Parameters[PI];
2678 SMLoc StrLoc = Lexer.getLoc();
2681 const MCExpr *AbsoluteExp;
2685 if (parseExpression(AbsoluteExp, EndLoc))
2687 if (!AbsoluteExp->evaluateAsAbsolute(
Value,
2688 getStreamer().getAssemblerPtr()))
2689 return Error(StrLoc,
"expected absolute expression");
2693 StringRef(StrChar, EndChar - StrChar),
Value);
2694 FA.
Value.push_back(newToken);
2695 }
else if (parseMacroArgument(MP, FA.
Value, EndTok)) {
2697 return addErrorSuffix(
" in '" +
M->Name +
"' macro");
2702 if (!FA.
Value.empty()) {
2707 if (FALocs.
size() <= PI)
2710 FALocs[PI] = Lexer.getLoc();
2716 if (Lexer.is(EndTok)) {
2718 for (
unsigned FAI = 0; FAI < NParameters; ++FAI) {
2720 if (
M->Parameters[FAI].Required) {
2721 Error(FALocs[FAI].
isValid() ? FALocs[FAI] : Lexer.getLoc(),
2722 "missing value for required parameter "
2724 M->Parameters[FAI].Name +
"' in macro '" +
M->Name +
"'");
2728 if (!
M->Parameters[FAI].Value.empty())
2729 A[FAI] =
M->Parameters[FAI].Value;
2739 return TokError(
"too many positional arguments");
2742bool MasmParser::handleMacroEntry(
const MCAsmMacro *M, SMLoc NameLoc,
2747 if (ActiveMacros.size() == MaxNestingDepth) {
2748 std::ostringstream MaxNestingDepthError;
2749 MaxNestingDepthError <<
"macros cannot be nested more than "
2750 << MaxNestingDepth <<
" levels deep."
2751 <<
" Use -asm-macro-max-nesting-depth to increase "
2753 return TokError(MaxNestingDepthError.str());
2756 MCAsmMacroArguments
A;
2757 if (parseMacroArguments(M,
A, ArgumentEndTok) || parseToken(ArgumentEndTok))
2762 SmallString<256> Buf;
2763 StringRef Body =
M->Body;
2764 raw_svector_ostream OS(Buf);
2766 if (expandMacro(OS, Body,
M->Parameters,
A,
M->Locals, getTok().getLoc()))
2773 std::unique_ptr<MemoryBuffer> Instantiation =
2778 MacroInstantiation *
MI =
new MacroInstantiation{
2779 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
2780 ActiveMacros.push_back(
MI);
2782 ++NumOfMacroInstantiations;
2787 EndStatementAtEOFStack.push_back(
true);
2793void MasmParser::handleMacroExit() {
2795 EndStatementAtEOFStack.pop_back();
2796 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer,
2797 EndStatementAtEOFStack.back());
2801 delete ActiveMacros.back();
2802 ActiveMacros.pop_back();
2805bool MasmParser::handleMacroInvocation(
const MCAsmMacro *M, SMLoc NameLoc) {
2807 return Error(NameLoc,
"cannot invoke macro procedure as function");
2810 "' requires arguments in parentheses") ||
2815 std::string ExitValue;
2818 ParseStatementInfo
Info(&AsmStrRewrites);
2819 bool HasError = parseStatement(Info,
nullptr);
2821 if (!HasError &&
Info.ExitValue) {
2822 ExitValue = std::move(*
Info.ExitValue);
2829 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
2833 printPendingErrors();
2836 if (HasError && !getLexer().justConsumedEOL())
2837 eatToEndOfStatement();
2842 std::unique_ptr<MemoryBuffer> MacroValue =
2850 EndStatementAtEOFStack.push_back(
false);
2859bool MasmParser::parseIdentifier(StringRef &Res,
2860 IdentifierPositionKind Position) {
2867 SMLoc PrefixLoc = getLexer().getLoc();
2871 AsmToken nextTok = peekTok(
false);
2884 StringRef(PrefixLoc.
getPointer(), getTok().getIdentifier().
size() + 1);
2892 Res = getTok().getIdentifier();
2896 ExpandKind ExpandNextToken = ExpandMacros;
2897 if (Position == StartOfStatement &&
2898 StringSwitch<bool>(Res)
2899 .CaseLower(
"echo",
true)
2900 .CasesLower({
"ifdef",
"ifndef",
"elseifdef",
"elseifndef"},
true)
2902 ExpandNextToken = DoNotExpandMacros;
2904 Lex(ExpandNextToken);
2914bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
2915 DirectiveKind DirKind, SMLoc NameLoc) {
2916 auto BuiltinIt = BuiltinSymbolMap.find(
Name.lower());
2917 if (BuiltinIt != BuiltinSymbolMap.end())
2918 return Error(NameLoc,
"cannot redefine a built-in symbol");
2921 if (Var.Name.empty()) {
2925 SMLoc StartLoc = Lexer.getLoc();
2926 if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) {
2929 std::string TextItem;
2930 if (!parseTextItem(TextItem)) {
2934 auto parseItem = [&]() ->
bool {
2935 if (parseTextItem(TextItem))
2936 return TokError(
"expected text item");
2941 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
2943 if (!Var.IsText || Var.TextValue !=
Value) {
2944 switch (Var.Redefinable) {
2945 case Variable::NOT_REDEFINABLE:
2946 return Error(getTok().getLoc(),
"invalid variable redefinition");
2947 case Variable::WARN_ON_REDEFINITION:
2948 if (
Warning(NameLoc,
"redefining '" + Name +
2949 "', already defined on the command line")) {
2958 Var.TextValue =
Value;
2959 Var.Redefinable = Variable::REDEFINABLE;
2964 if (DirKind == DK_TEXTEQU)
2965 return TokError(
"expected <text> in '" + Twine(IDVal) +
"' directive");
2970 if (parseExpression(Expr, EndLoc))
2971 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
2972 StringRef ExprAsString = StringRef(
2976 if (!Expr->evaluateAsAbsolute(
Value, getStreamer().getAssemblerPtr())) {
2977 if (DirKind == DK_ASSIGN)
2980 "expected absolute expression; not all symbols have known values",
2981 {StartLoc, EndLoc});
2984 if (!Var.IsText || Var.TextValue != ExprAsString) {
2985 switch (Var.Redefinable) {
2986 case Variable::NOT_REDEFINABLE:
2987 return Error(getTok().getLoc(),
"invalid variable redefinition");
2988 case Variable::WARN_ON_REDEFINITION:
2989 if (
Warning(NameLoc,
"redefining '" + Name +
2990 "', already defined on the command line")) {
3000 Var.TextValue = ExprAsString.
str();
3001 Var.Redefinable = Variable::REDEFINABLE;
3006 auto *Sym =
static_cast<MCSymbolCOFF *
>(
getContext().parseSymbol(Var.Name));
3007 const MCConstantExpr *PrevValue =
3011 if (Var.IsText || !PrevValue || PrevValue->
getValue() !=
Value) {
3012 switch (Var.Redefinable) {
3013 case Variable::NOT_REDEFINABLE:
3014 return Error(getTok().getLoc(),
"invalid variable redefinition");
3015 case Variable::WARN_ON_REDEFINITION:
3016 if (
Warning(NameLoc,
"redefining '" + Name +
3017 "', already defined on the command line")) {
3027 Var.TextValue.clear();
3028 Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE
3031 Sym->
setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE);
3033 Sym->setExternal(
false);
3038bool MasmParser::parseEscapedString(std::string &
Data) {
3043 char Quote = getTok().getString().front();
3044 StringRef Str = getTok().getStringContents();
3045 Data.reserve(Str.size());
3046 for (
size_t i = 0, e = Str.size(); i != e; ++i) {
3047 Data.push_back(Str[i]);
3048 if (Str[i] == Quote) {
3052 if (i + 1 == Str.size())
3053 return Error(getTok().getLoc(),
"missing quotation mark in string");
3054 if (Str[i + 1] == Quote)
3063bool MasmParser::parseAngleBracketString(std::string &
Data) {
3064 SMLoc EndLoc, StartLoc = getTok().getLoc();
3066 const char *StartChar = StartLoc.
getPointer() + 1;
3067 const char *EndChar = EndLoc.
getPointer() - 1;
3068 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
3079bool MasmParser::parseTextItem(std::string &
Data) {
3080 switch (getTok().getKind()) {
3087 Data = std::to_string(Res);
3094 return parseAngleBracketString(
Data);
3098 SMLoc StartLoc = getTok().getLoc();
3099 if (parseIdentifier(
ID))
3103 bool Expanded =
false;
3106 auto BuiltinIt = BuiltinSymbolMap.find(
ID.lower());
3107 if (BuiltinIt != BuiltinSymbolMap.end()) {
3108 std::optional<std::string> BuiltinText =
3109 evaluateBuiltinTextMacro(BuiltinIt->getValue(), StartLoc);
3114 Data = std::move(*BuiltinText);
3121 auto BuiltinFuncIt = BuiltinFunctionMap.find(
ID.lower());
3122 if (BuiltinFuncIt != BuiltinFunctionMap.end()) {
3124 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(),
ID,
Data)) {
3133 auto VarIt = Variables.
find(
ID.lower());
3134 if (VarIt != Variables.
end()) {
3135 const Variable &Var = VarIt->getValue();
3140 Data = Var.TextValue;
3163bool MasmParser::parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated) {
3164 auto parseOp = [&]() ->
bool {
3166 if (checkForValidSection() || parseEscapedString(
Data))
3168 getStreamer().emitBytes(
Data);
3170 getStreamer().emitBytes(StringRef(
"\0", 1));
3174 if (parseMany(parseOp))
3175 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3179bool MasmParser::emitIntValue(
const MCExpr *
Value,
unsigned Size) {
3183 int64_t IntValue = MCE->getValue();
3185 return Error(MCE->getLoc(),
"out of range literal value");
3186 getStreamer().emitIntValue(IntValue,
Size);
3191 getStreamer().emitIntValue(0,
Size);
3199bool MasmParser::parseScalarInitializer(
unsigned Size,
3200 SmallVectorImpl<const MCExpr *> &
Values,
3201 unsigned StringPadLength) {
3204 if (parseEscapedString(
Value))
3207 for (
const unsigned char CharVal :
Value)
3211 for (
size_t i =
Value.size(); i < StringPadLength; ++i)
3214 const MCExpr *
Value;
3215 if (parseExpression(
Value))
3218 getTok().getString().equals_insensitive(
"dup")) {
3223 "cannot repeat value a non-constant number of times");
3224 const int64_t Repetitions = MCE->
getValue();
3225 if (Repetitions < 0)
3227 "cannot repeat value a negative number of times");
3231 "parentheses required for 'dup' contents") ||
3232 parseScalarInstList(
Size, DuplicatedValues) || parseRParen())
3235 for (
int i = 0; i < Repetitions; ++i)
3244bool MasmParser::parseScalarInstList(
unsigned Size,
3245 SmallVectorImpl<const MCExpr *> &
Values,
3247 while (getTok().
isNot(EndToken) &&
3260bool MasmParser::emitIntegralValues(
unsigned Size,
unsigned *
Count) {
3262 if (checkForValidSection() || parseScalarInstList(
Size,
Values))
3274bool MasmParser::addIntegralField(StringRef Name,
unsigned Size) {
3275 StructInfo &
Struct = StructInProgress.
back();
3277 IntFieldInfo &IntInfo =
Field.Contents.IntInfo;
3281 if (parseScalarInstList(
Size, IntInfo.Values))
3284 Field.SizeOf =
Field.Type * IntInfo.Values.size();
3285 Field.LengthOf = IntInfo.Values.size();
3288 Struct.NextOffset = FieldEnd;
3296bool MasmParser::parseDirectiveValue(StringRef IDVal,
unsigned Size) {
3297 if (StructInProgress.
empty()) {
3299 if (emitIntegralValues(
Size))
3300 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3301 }
else if (addIntegralField(
"",
Size)) {
3302 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3310bool MasmParser::parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
3311 StringRef Name, SMLoc NameLoc) {
3312 if (StructInProgress.
empty()) {
3315 getStreamer().emitLabel(Sym);
3318 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3326 }
else if (addIntegralField(Name,
Size)) {
3327 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3333bool MasmParser::parseRealValue(
const fltSemantics &Semantics, APInt &Res) {
3339 SignLoc = getLexer().getLoc();
3343 SignLoc = getLexer().getLoc();
3348 return TokError(Lexer.getErr());
3351 return TokError(
"unexpected token in directive");
3355 StringRef IDVal = getTok().getString();
3364 return TokError(
"invalid floating point literal");
3368 unsigned SizeInBits =
Value.getSizeInBits(Semantics);
3369 if (SizeInBits != (IDVal.
size() << 2))
3370 return TokError(
"invalid floating point literal");
3375 Res = APInt(SizeInBits, IDVal, 16);
3377 return Warning(SignLoc,
"MASM-style hex floats ignore explicit sign");
3380 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3382 return TokError(
"invalid floating point literal");
3390 Res =
Value.bitcastToAPInt();
3395bool MasmParser::parseRealInstList(
const fltSemantics &Semantics,
3396 SmallVectorImpl<APInt> &ValuesAsInt,
3398 while (getTok().
isNot(EndToken) ||
3401 const AsmToken NextTok = peekTok();
3404 const MCExpr *
Value;
3410 "cannot repeat value a non-constant number of times");
3411 const int64_t Repetitions = MCE->
getValue();
3412 if (Repetitions < 0)
3414 "cannot repeat value a negative number of times");
3418 "parentheses required for 'dup' contents") ||
3419 parseRealInstList(Semantics, DuplicatedValues) || parseRParen())
3422 for (
int i = 0; i < Repetitions; ++i)
3423 ValuesAsInt.
append(DuplicatedValues.
begin(), DuplicatedValues.
end());
3426 if (parseRealValue(Semantics, AsInt))
3441bool MasmParser::emitRealValues(
const fltSemantics &Semantics,
3443 if (checkForValidSection())
3447 if (parseRealInstList(Semantics, ValuesAsInt))
3450 for (
const APInt &AsInt : ValuesAsInt) {
3451 getStreamer().emitIntValue(AsInt);
3454 *
Count = ValuesAsInt.size();
3459bool MasmParser::addRealField(StringRef Name,
const fltSemantics &Semantics,
3461 StructInfo &
Struct = StructInProgress.
back();
3463 RealFieldInfo &RealInfo =
Field.Contents.RealInfo;
3467 if (parseRealInstList(Semantics, RealInfo.AsIntValues))
3470 Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
3471 Field.LengthOf = RealInfo.AsIntValues.size();
3476 Struct.NextOffset = FieldEnd;
3484bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
3485 const fltSemantics &Semantics,
3487 if (StructInProgress.
empty()) {
3489 if (emitRealValues(Semantics))
3490 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3491 }
else if (addRealField(
"", Semantics,
Size)) {
3492 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3499bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
3500 const fltSemantics &Semantics,
3501 unsigned Size, StringRef Name,
3503 if (StructInProgress.
empty()) {
3506 getStreamer().emitLabel(Sym);
3508 if (emitRealValues(Semantics, &
Count))
3509 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3517 }
else if (addRealField(Name, Semantics,
Size)) {
3518 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3523bool MasmParser::parseOptionalAngleBracketOpen() {
3524 const AsmToken Tok = getTok();
3526 AngleBracketDepth++;
3530 AngleBracketDepth++;
3534 AngleBracketDepth++;
3541bool MasmParser::parseAngleBracketClose(
const Twine &
Msg) {
3542 const AsmToken Tok = getTok();
3548 AngleBracketDepth--;
3552bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3553 const IntFieldInfo &Contents,
3554 FieldInitializer &Initializer) {
3555 SMLoc Loc = getTok().getLoc();
3560 return Error(Loc,
"Cannot initialize scalar field with array value");
3564 }
else if (parseOptionalAngleBracketOpen()) {
3566 return Error(Loc,
"Cannot initialize scalar field with array value");
3568 parseAngleBracketClose())
3570 }
else if (
Field.LengthOf > 1 &&
Field.Type > 1) {
3571 return Error(Loc,
"Cannot initialize array field with scalar value");
3572 }
else if (parseScalarInitializer(
Field.Type,
Values,
3578 return Error(Loc,
"Initializer too long for field; expected at most " +
3579 std::to_string(
Field.LengthOf) +
" elements, got " +
3580 std::to_string(
Values.size()));
3583 Values.append(Contents.Values.begin() +
Values.size(), Contents.Values.end());
3585 Initializer = FieldInitializer(std::move(
Values));
3589bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3590 const RealFieldInfo &Contents,
3591 FieldInitializer &Initializer) {
3592 const fltSemantics *Semantics;
3593 switch (
Field.Type) {
3595 Semantics = &APFloat::IEEEsingle();
3598 Semantics = &APFloat::IEEEdouble();
3601 Semantics = &APFloat::x87DoubleExtended();
3607 SMLoc Loc = getTok().getLoc();
3611 if (
Field.LengthOf == 1)
3612 return Error(Loc,
"Cannot initialize scalar field with array value");
3616 }
else if (parseOptionalAngleBracketOpen()) {
3617 if (
Field.LengthOf == 1)
3618 return Error(Loc,
"Cannot initialize scalar field with array value");
3620 parseAngleBracketClose())
3622 }
else if (
Field.LengthOf > 1) {
3623 return Error(Loc,
"Cannot initialize array field with scalar value");
3626 if (parseRealValue(*Semantics, AsIntValues.
back()))
3630 if (AsIntValues.
size() >
Field.LengthOf) {
3631 return Error(Loc,
"Initializer too long for field; expected at most " +
3632 std::to_string(
Field.LengthOf) +
" elements, got " +
3633 std::to_string(AsIntValues.
size()));
3636 AsIntValues.
append(Contents.AsIntValues.begin() + AsIntValues.
size(),
3637 Contents.AsIntValues.end());
3639 Initializer = FieldInitializer(std::move(AsIntValues));
3643bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3644 const StructFieldInfo &Contents,
3645 FieldInitializer &Initializer) {
3646 SMLoc Loc = getTok().getLoc();
3648 std::vector<StructInitializer> Initializers;
3649 if (
Field.LengthOf > 1) {
3651 if (parseStructInstList(Contents.Structure, Initializers,
3655 }
else if (parseOptionalAngleBracketOpen()) {
3656 if (parseStructInstList(Contents.Structure, Initializers,
3658 parseAngleBracketClose())
3661 return Error(Loc,
"Cannot initialize array field with scalar value");
3664 Initializers.emplace_back();
3665 if (parseStructInitializer(Contents.Structure, Initializers.back()))
3669 if (Initializers.size() >
Field.LengthOf) {
3670 return Error(Loc,
"Initializer too long for field; expected at most " +
3671 std::to_string(
Field.LengthOf) +
" elements, got " +
3672 std::to_string(Initializers.size()));
3676 Initializers.size()));
3678 Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
3682bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3683 FieldInitializer &Initializer) {
3684 switch (
Field.Contents.FT) {
3686 return parseFieldInitializer(
Field,
Field.Contents.IntInfo, Initializer);
3688 return parseFieldInitializer(
Field,
Field.Contents.RealInfo, Initializer);
3690 return parseFieldInitializer(
Field,
Field.Contents.StructInfo, Initializer);
3695bool MasmParser::parseStructInitializer(
const StructInfo &Structure,
3696 StructInitializer &Initializer) {
3697 const AsmToken FirstToken = getTok();
3699 std::optional<AsmToken::TokenKind> EndToken;
3702 }
else if (parseOptionalAngleBracketOpen()) {
3704 AngleBracketDepth++;
3711 return Error(FirstToken.
getLoc(),
"Expected struct initializer");
3714 auto &FieldInitializers = Initializer.FieldInitializers;
3715 size_t FieldIndex = 0;
3718 while (getTok().
isNot(*EndToken) && FieldIndex < Structure.Fields.size()) {
3719 const FieldInfo &
Field = Structure.Fields[FieldIndex++];
3723 FieldInitializers.push_back(
Field.Contents);
3727 FieldInitializers.emplace_back(
Field.Contents.FT);
3728 if (parseFieldInitializer(
Field, FieldInitializers.back()))
3732 SMLoc CommaLoc = getTok().getLoc();
3735 if (FieldIndex == Structure.Fields.size())
3736 return Error(CommaLoc,
"'" + Structure.Name +
3737 "' initializer initializes too many fields");
3743 FieldInitializers.push_back(
Field.Contents);
3747 return parseAngleBracketClose();
3749 return parseToken(*EndToken);
3755bool MasmParser::parseStructInstList(
3756 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
3758 while (getTok().
isNot(EndToken) ||
3761 const AsmToken NextTok = peekTok();
3764 const MCExpr *
Value;
3770 "cannot repeat value a non-constant number of times");
3771 const int64_t Repetitions = MCE->
getValue();
3772 if (Repetitions < 0)
3774 "cannot repeat value a negative number of times");
3776 std::vector<StructInitializer> DuplicatedValues;
3778 "parentheses required for 'dup' contents") ||
3779 parseStructInstList(Structure, DuplicatedValues) || parseRParen())
3782 for (
int i = 0; i < Repetitions; ++i)
3785 Initializers.emplace_back();
3786 if (parseStructInitializer(Structure, Initializers.back()))
3799bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3800 const IntFieldInfo &Contents) {
3802 for (
const MCExpr *
Value : Contents.Values) {
3809bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3810 const RealFieldInfo &Contents) {
3811 for (
const APInt &AsInt : Contents.AsIntValues) {
3818bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3819 const StructFieldInfo &Contents) {
3820 for (
const auto &Initializer : Contents.Initializers) {
3822 for (
const auto &SubField : Contents.Structure.Fields) {
3823 getStreamer().emitZeros(SubField.Offset -
Offset);
3824 Offset = SubField.Offset + SubField.SizeOf;
3825 emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
3831bool MasmParser::emitFieldValue(
const FieldInfo &
Field) {
3832 switch (
Field.Contents.FT) {
3834 return emitFieldValue(
Field,
Field.Contents.IntInfo);
3836 return emitFieldValue(
Field,
Field.Contents.RealInfo);
3838 return emitFieldValue(
Field,
Field.Contents.StructInfo);
3843bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3844 const IntFieldInfo &Contents,
3845 const IntFieldInfo &Initializer) {
3846 for (
const auto &
Value : Initializer.Values) {
3851 for (
const auto &
Value :
3859bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3860 const RealFieldInfo &Contents,
3861 const RealFieldInfo &Initializer) {
3862 for (
const auto &AsInt : Initializer.AsIntValues) {
3867 for (
const auto &AsInt :
3875bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3876 const StructFieldInfo &Contents,
3877 const StructFieldInfo &Initializer) {
3878 for (
const auto &Init : Initializer.Initializers) {
3879 if (emitStructInitializer(Contents.Structure, Init))
3884 Initializer.Initializers.size())) {
3885 if (emitStructInitializer(Contents.Structure, Init))
3891bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3892 const FieldInitializer &Initializer) {
3893 switch (
Field.Contents.FT) {
3895 return emitFieldInitializer(
Field,
Field.Contents.IntInfo,
3896 Initializer.IntInfo);
3898 return emitFieldInitializer(
Field,
Field.Contents.RealInfo,
3899 Initializer.RealInfo);
3901 return emitFieldInitializer(
Field,
Field.Contents.StructInfo,
3902 Initializer.StructInfo);
3907bool MasmParser::emitStructInitializer(
const StructInfo &Structure,
3908 const StructInitializer &Initializer) {
3909 if (!Structure.Initializable)
3910 return Error(getLexer().getLoc(),
3911 "cannot initialize a value of type '" + Structure.Name +
3912 "'; 'org' was used in the type's declaration");
3914 for (
const auto &Init : Initializer.FieldInitializers) {
3915 const auto &
Field = Structure.Fields[
Index++];
3918 if (emitFieldInitializer(
Field, Init))
3923 Structure.Fields, Initializer.FieldInitializers.size())) {
3926 if (emitFieldValue(
Field))
3930 if (
Offset != Structure.Size)
3931 getStreamer().emitZeros(Structure.Size -
Offset);
3936bool MasmParser::emitStructValues(
const StructInfo &Structure,
3938 std::vector<StructInitializer> Initializers;
3939 if (parseStructInstList(Structure, Initializers))
3942 for (
const auto &Initializer : Initializers) {
3943 if (emitStructInitializer(Structure, Initializer))
3948 *
Count = Initializers.size();
3953bool MasmParser::addStructField(StringRef Name,
const StructInfo &Structure) {
3954 StructInfo &OwningStruct = StructInProgress.
back();
3956 OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
3957 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
3959 StructInfo.Structure = Structure;
3960 Field.Type = Structure.Size;
3962 if (parseStructInstList(Structure, StructInfo.Initializers))
3965 Field.LengthOf = StructInfo.Initializers.size();
3969 if (!OwningStruct.IsUnion) {
3970 OwningStruct.NextOffset = FieldEnd;
3972 OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd);
3980bool MasmParser::parseDirectiveStructValue(
const StructInfo &Structure,
3981 StringRef Directive, SMLoc DirLoc) {
3982 if (StructInProgress.
empty()) {
3983 if (emitStructValues(Structure))
3985 }
else if (addStructField(
"", Structure)) {
3986 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
3994bool MasmParser::parseDirectiveNamedStructValue(
const StructInfo &Structure,
3995 StringRef Directive,
3996 SMLoc DirLoc, StringRef Name) {
3997 if (StructInProgress.
empty()) {
4000 getStreamer().emitLabel(Sym);
4002 if (emitStructValues(Structure, &
Count))
4005 Type.Name = Structure.Name;
4007 Type.ElementSize = Structure.Size;
4010 }
else if (addStructField(Name, Structure)) {
4011 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4023bool MasmParser::parseDirectiveStruct(StringRef Directive,
4024 DirectiveKind DirKind, StringRef Name,
4028 AsmToken NextTok = getTok();
4029 int64_t AlignmentValue = 1;
4032 parseAbsoluteExpression(AlignmentValue)) {
4033 return addErrorSuffix(
" in alignment value for '" + Twine(Directive) +
4037 return Error(NextTok.
getLoc(),
"alignment must be a power of two; was " +
4038 std::to_string(AlignmentValue));
4044 QualifierLoc = getTok().getLoc();
4045 if (parseIdentifier(Qualifier))
4046 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4047 if (!
Qualifier.equals_insensitive(
"nonunique"))
4048 return Error(QualifierLoc,
"Unrecognized qualifier for '" +
4050 "' directive; expected none or NONUNIQUE");
4054 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4056 StructInProgress.
emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
4064bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
4065 DirectiveKind DirKind) {
4066 if (StructInProgress.
empty())
4067 return TokError(
"missing name in top-level '" + Twine(Directive) +
4072 Name = getTok().getIdentifier();
4076 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4080 StructInProgress.
reserve(StructInProgress.
size() + 1);
4081 StructInProgress.
emplace_back(Name, DirKind == DK_UNION,
4082 StructInProgress.
back().Alignment);
4086bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
4087 if (StructInProgress.
empty())
4088 return Error(NameLoc,
"ENDS directive without matching STRUC/STRUCT/UNION");
4089 if (StructInProgress.
size() > 1)
4090 return Error(NameLoc,
"unexpected name in nested ENDS directive");
4091 if (StructInProgress.
back().Name.compare_insensitive(Name))
4092 return Error(NameLoc,
"mismatched name in ENDS directive; expected '" +
4093 StructInProgress.
back().Name +
"'");
4094 StructInfo Structure = StructInProgress.
pop_back_val();
4098 Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
4099 Structs[
Name.lower()] = std::move(Structure);
4102 return addErrorSuffix(
" in ENDS directive");
4107bool MasmParser::parseDirectiveNestedEnds() {
4108 if (StructInProgress.
empty())
4109 return TokError(
"ENDS directive without matching STRUC/STRUCT/UNION");
4110 if (StructInProgress.
size() == 1)
4111 return TokError(
"missing name in top-level ENDS directive");
4114 return addErrorSuffix(
" in nested ENDS directive");
4116 StructInfo Structure = StructInProgress.
pop_back_val();
4118 Structure.Size =
llvm::alignTo(Structure.Size, Structure.Alignment);
4120 StructInfo &ParentStruct = StructInProgress.
back();
4121 if (Structure.Name.
empty()) {
4124 const size_t OldFields = ParentStruct.Fields.size();
4125 ParentStruct.Fields.insert(
4126 ParentStruct.Fields.end(),
4127 std::make_move_iterator(Structure.Fields.begin()),
4128 std::make_move_iterator(Structure.Fields.end()));
4129 for (
const auto &FieldByName : Structure.FieldsByName) {
4130 ParentStruct.FieldsByName[FieldByName.getKey()] =
4131 FieldByName.getValue() + OldFields;
4134 unsigned FirstFieldOffset = 0;
4135 if (!Structure.Fields.empty() && !ParentStruct.IsUnion) {
4137 ParentStruct.NextOffset,
4138 std::min(ParentStruct.Alignment, Structure.AlignmentSize));
4141 if (ParentStruct.IsUnion) {
4142 ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
4147 const unsigned StructureEnd = FirstFieldOffset + Structure.Size;
4148 if (!ParentStruct.IsUnion) {
4149 ParentStruct.NextOffset = StructureEnd;
4151 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4154 FieldInfo &
Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
4155 Structure.AlignmentSize);
4156 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
4157 Field.Type = Structure.Size;
4159 Field.SizeOf = Structure.Size;
4162 if (!ParentStruct.IsUnion) {
4163 ParentStruct.NextOffset = StructureEnd;
4165 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4167 StructInfo.Structure = Structure;
4168 StructInfo.Initializers.emplace_back();
4169 auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
4170 for (
const auto &SubField : Structure.Fields) {
4171 FieldInitializers.push_back(SubField.Contents);
4180bool MasmParser::parseDirectiveOrg() {
4182 SMLoc OffsetLoc = Lexer.getLoc();
4183 if (checkForValidSection() || parseExpression(
Offset))
4186 return addErrorSuffix(
" in 'org' directive");
4188 if (StructInProgress.
empty()) {
4190 if (checkForValidSection())
4191 return addErrorSuffix(
" in 'org' directive");
4193 getStreamer().emitValueToOffset(
Offset, 0, OffsetLoc);
4196 StructInfo &Structure = StructInProgress.
back();
4198 if (!
Offset->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr()))
4199 return Error(OffsetLoc,
4200 "expected absolute expression in 'org' directive");
4204 "expected non-negative value in struct's 'org' directive; was " +
4205 std::to_string(OffsetRes));
4206 Structure.NextOffset =
static_cast<unsigned>(OffsetRes);
4209 Structure.Initializable =
false;
4215bool MasmParser::emitAlignTo(int64_t Alignment) {
4216 if (StructInProgress.
empty()) {
4218 if (checkForValidSection())
4223 const MCSection *
Section = getStreamer().getCurrentSectionOnly();
4225 getStreamer().emitCodeAlignment(
Align(Alignment),
4226 getTargetParser().getSTI(),
4230 getStreamer().emitValueToAlignment(
Align(Alignment), 0,
4236 StructInfo &Structure = StructInProgress.
back();
4237 Structure.NextOffset =
llvm::alignTo(Structure.NextOffset, Alignment);
4245bool MasmParser::parseDirectiveAlign() {
4246 SMLoc AlignmentLoc = getLexer().getLoc();
4252 "align directive with no operand is ignored") &&
4255 if (parseAbsoluteExpression(Alignment) || parseEOL())
4256 return addErrorSuffix(
" in align directive");
4259 bool ReturnVal =
false;
4266 ReturnVal |=
Error(AlignmentLoc,
"alignment must be a power of 2; was " +
4267 std::to_string(Alignment));
4269 if (emitAlignTo(Alignment))
4270 ReturnVal |= addErrorSuffix(
" in align directive");
4277bool MasmParser::parseDirectiveEven() {
4278 if (parseEOL() || emitAlignTo(2))
4279 return addErrorSuffix(
" in even directive");
4290bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
4294 return Error(Lexer.getLoc(),
4295 "Vararg parameter '" +
Parameters.back().Name +
4296 "' should be last in the list of parameters");
4300 return TokError(
"expected identifier in 'macro' directive");
4303 for (
const MCAsmMacroParameter& CurrParam : Parameters)
4304 if (CurrParam.Name.equals_insensitive(
Parameter.Name))
4305 return TokError(
"macro '" + Name +
"' has multiple parameters"
4315 ParamLoc = Lexer.getLoc();
4316 if (parseMacroArgument(
nullptr,
Parameter.Value))
4322 QualLoc = Lexer.getLoc();
4323 if (parseIdentifier(Qualifier))
4324 return Error(QualLoc,
"missing parameter qualifier for "
4326 Parameter.Name +
"' in macro '" + Name +
4329 if (
Qualifier.equals_insensitive(
"req"))
4331 else if (
Qualifier.equals_insensitive(
"vararg"))
4334 return Error(QualLoc,
4335 Qualifier +
" is not a valid parameter qualifier for '" +
4336 Parameter.Name +
"' in macro '" + Name +
"'");
4349 std::vector<std::string>
Locals;
4351 getTok().getIdentifier().equals_insensitive(
"local")) {
4356 if (parseIdentifier(
ID))
4368 AsmToken EndToken, StartToken = getTok();
4369 unsigned MacroDepth = 0;
4370 bool IsMacroFunction =
false;
4380 return Error(NameLoc,
"no matching 'endm' in definition");
4385 if (getTok().getIdentifier().equals_insensitive(
"endm")) {
4386 if (MacroDepth == 0) {
4387 EndToken = getTok();
4390 return TokError(
"unexpected token in '" + EndToken.
getIdentifier() +
4397 }
else if (getTok().getIdentifier().equals_insensitive(
"exitm")) {
4399 IsMacroFunction =
true;
4401 }
else if (isMacroLikeDirective()) {
4409 eatToEndOfStatement();
4413 return Error(NameLoc,
"macro '" + Name +
"' is already defined");
4418 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4419 MCAsmMacro
Macro(Name, Body, std::move(Parameters), std::move(Locals),
4429bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
4430 StringRef Directive,
4431 std::string &
Value) {
4432 SMLoc EndLoc = getTok().getLoc();
4434 return Error(EndLoc,
4435 "unable to parse text item in '" + Directive +
"' directive");
4436 eatToEndOfStatement();
4438 if (!isInsideMacroInstantiation())
4439 return TokError(
"unexpected '" + Directive +
"' in file, "
4440 "no current macro definition");
4443 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4444 TheCondState = TheCondStack.back();
4445 TheCondStack.pop_back();
4454bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
4456 return TokError(
"unexpected token in '" + Directive +
"' directive");
4460 if (isInsideMacroInstantiation()) {
4467 return TokError(
"unexpected '" + Directive +
"' in file, "
4468 "no current macro definition");
4473bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4477 if (parseTokenLoc(NameLoc) ||
4478 check(parseIdentifier(Name), NameLoc,
4479 "expected identifier in 'purge' directive"))
4483 <<
"Un-defining macro: " << Name <<
"\n");
4485 return Error(NameLoc,
"macro '" + Name +
"' is not defined");
4496bool MasmParser::parseDirectiveExtern() {
4498 auto parseOp = [&]() ->
bool {
4500 SMLoc NameLoc = getTok().getLoc();
4502 return Error(NameLoc,
"expected name");
4507 SMLoc TypeLoc = getTok().getLoc();
4508 if (parseIdentifier(TypeName))
4509 return Error(TypeLoc,
"expected type");
4510 if (!
TypeName.equals_insensitive(
"proc")) {
4512 if (lookUpType(TypeName,
Type))
4513 return Error(TypeLoc,
"unrecognized type");
4517 static_cast<MCSymbolCOFF *
>(Sym)->setExternal(
true);
4518 getStreamer().emitSymbolAttribute(Sym,
MCSA_Extern);
4523 if (parseMany(parseOp))
4524 return addErrorSuffix(
" in directive 'extern'");
4530bool MasmParser::parseDirectiveSymbolAttribute(
MCSymbolAttr Attr) {
4531 auto parseOp = [&]() ->
bool {
4532 SMLoc Loc = getTok().getLoc();
4535 return Error(Loc,
"expected identifier");
4539 return Error(Loc,
"non-local symbol required");
4541 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
4542 return Error(Loc,
"unable to emit symbol attribute");
4546 if (parseMany(parseOp))
4547 return addErrorSuffix(
" in directive");
4553bool MasmParser::parseDirectiveComm(
bool IsLocal) {
4554 if (checkForValidSection())
4557 SMLoc IDLoc = getLexer().getLoc();
4560 return TokError(
"expected identifier in directive");
4563 return TokError(
"unexpected token in directive");
4567 SMLoc SizeLoc = getLexer().getLoc();
4568 if (parseAbsoluteExpression(
Size))
4571 int64_t Pow2Alignment = 0;
4572 SMLoc Pow2AlignmentLoc;
4575 Pow2AlignmentLoc = getLexer().getLoc();
4576 if (parseAbsoluteExpression(Pow2Alignment))
4581 return Error(Pow2AlignmentLoc,
"alignment not supported on this target");
4584 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
4587 return Error(Pow2AlignmentLoc,
"alignment must be a power of 2");
4588 Pow2Alignment =
Log2_64(Pow2Alignment);
4598 return Error(SizeLoc,
"invalid '.comm' or '.lcomm' directive size, can't "
4599 "be less than zero");
4604 if (Pow2Alignment < 0)
4605 return Error(Pow2AlignmentLoc,
"invalid '.comm' or '.lcomm' directive "
4606 "alignment, can't be less than zero");
4610 return Error(IDLoc,
"invalid symbol redefinition");
4614 getStreamer().emitLocalCommonSymbol(Sym,
Size,
4615 Align(1ULL << Pow2Alignment));
4619 getStreamer().emitCommonSymbol(Sym,
Size,
Align(1ULL << Pow2Alignment));
4627bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
4629 size_t DelimiterEnd = FirstLine.find_first_of(
"\b\t\v\f\r\x1A ");
4630 assert(DelimiterEnd != std::string::npos);
4631 StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd);
4632 if (Delimiter.
empty())
4633 return Error(DirectiveLoc,
"no delimiter in 'comment' directive");
4636 return Error(DirectiveLoc,
"unmatched delimiter in 'comment' directive");
4646bool MasmParser::parseDirectiveInclude() {
4649 SMLoc IncludeLoc = getTok().getLoc();
4651 if (parseAngleBracketString(
Filename))
4653 if (check(
Filename.
empty(),
"missing filename in 'include' directive") ||
4655 "unexpected token in 'include' directive") ||
4658 check(enterIncludeFile(
Filename), IncludeLoc,
4659 "Could not find include file '" +
Filename +
"'"))
4667bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
4668 TheCondStack.push_back(TheCondState);
4670 if (TheCondState.
Ignore) {
4671 eatToEndOfStatement();
4674 if (parseAbsoluteExpression(ExprValue) || parseEOL())
4683 ExprValue = ExprValue == 0;
4687 TheCondState.
CondMet = ExprValue;
4696bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4697 TheCondStack.push_back(TheCondState);
4700 if (TheCondState.
Ignore) {
4701 eatToEndOfStatement();
4704 if (parseTextItem(Str))
4705 return TokError(
"expected text item parameter for 'ifb' directive");
4710 TheCondState.
CondMet = ExpectBlank == Str.empty();
4719bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4720 bool CaseInsensitive) {
4721 std::string String1, String2;
4723 if (parseTextItem(String1)) {
4725 return TokError(
"expected text item parameter for 'ifidn' directive");
4726 return TokError(
"expected text item parameter for 'ifdif' directive");
4732 "expected comma after first string for 'ifidn' directive");
4733 return TokError(
"expected comma after first string for 'ifdif' directive");
4737 if (parseTextItem(String2)) {
4739 return TokError(
"expected text item parameter for 'ifidn' directive");
4740 return TokError(
"expected text item parameter for 'ifdif' directive");
4743 TheCondStack.push_back(TheCondState);
4745 if (CaseInsensitive)
4747 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4749 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4758bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined) {
4759 TheCondStack.push_back(TheCondState);
4762 if (TheCondState.
Ignore) {
4763 eatToEndOfStatement();
4765 bool is_defined =
false;
4767 SMLoc StartLoc, EndLoc;
4769 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4772 if (check(parseIdentifier(Name),
"expected identifier after 'ifdef'") ||
4776 if (BuiltinSymbolMap.contains(
Name.lower())) {
4786 TheCondState.
CondMet = (is_defined == expect_defined);
4795bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
4796 DirectiveKind DirKind) {
4799 return Error(DirectiveLoc,
"Encountered a .elseif that doesn't follow an"
4800 " .if or an .elseif");
4803 bool LastIgnoreState =
false;
4804 if (!TheCondStack.empty())
4805 LastIgnoreState = TheCondStack.back().Ignore;
4806 if (LastIgnoreState || TheCondState.
CondMet) {
4807 TheCondState.
Ignore =
true;
4808 eatToEndOfStatement();
4811 if (parseAbsoluteExpression(ExprValue))
4823 ExprValue = ExprValue == 0;
4827 TheCondState.
CondMet = ExprValue;
4836bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4839 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4840 " if or an elseif");
4843 bool LastIgnoreState =
false;
4844 if (!TheCondStack.empty())
4845 LastIgnoreState = TheCondStack.back().Ignore;
4846 if (LastIgnoreState || TheCondState.
CondMet) {
4847 TheCondState.
Ignore =
true;
4848 eatToEndOfStatement();
4851 if (parseTextItem(Str)) {
4853 return TokError(
"expected text item parameter for 'elseifb' directive");
4854 return TokError(
"expected text item parameter for 'elseifnb' directive");
4860 TheCondState.
CondMet = ExpectBlank == Str.empty();
4870bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
4871 bool expect_defined) {
4874 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4875 " if or an elseif");
4878 bool LastIgnoreState =
false;
4879 if (!TheCondStack.empty())
4880 LastIgnoreState = TheCondStack.back().Ignore;
4881 if (LastIgnoreState || TheCondState.
CondMet) {
4882 TheCondState.
Ignore =
true;
4883 eatToEndOfStatement();
4885 bool is_defined =
false;
4887 SMLoc StartLoc, EndLoc;
4889 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4892 if (check(parseIdentifier(Name),
4893 "expected identifier after 'elseifdef'") ||
4897 if (BuiltinSymbolMap.contains(
Name.lower())) {
4907 TheCondState.
CondMet = (is_defined == expect_defined);
4916bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4917 bool CaseInsensitive) {
4920 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4921 " if or an elseif");
4924 bool LastIgnoreState =
false;
4925 if (!TheCondStack.empty())
4926 LastIgnoreState = TheCondStack.back().Ignore;
4927 if (LastIgnoreState || TheCondState.
CondMet) {
4928 TheCondState.
Ignore =
true;
4929 eatToEndOfStatement();
4931 std::string String1, String2;
4933 if (parseTextItem(String1)) {
4936 "expected text item parameter for 'elseifidn' directive");
4937 return TokError(
"expected text item parameter for 'elseifdif' directive");
4943 "expected comma after first string for 'elseifidn' directive");
4945 "expected comma after first string for 'elseifdif' directive");
4949 if (parseTextItem(String2)) {
4952 "expected text item parameter for 'elseifidn' directive");
4953 return TokError(
"expected text item parameter for 'elseifdif' directive");
4956 if (CaseInsensitive)
4958 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4960 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4969bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
4975 return Error(DirectiveLoc,
"Encountered an else that doesn't follow an if"
4978 bool LastIgnoreState =
false;
4979 if (!TheCondStack.empty())
4980 LastIgnoreState = TheCondStack.back().Ignore;
4981 if (LastIgnoreState || TheCondState.
CondMet)
4982 TheCondState.
Ignore =
true;
4984 TheCondState.
Ignore =
false;
4991bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5003bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
5004 if (!TheCondStack.empty()) {
5005 if (TheCondStack.back().Ignore) {
5006 eatToEndOfStatement();
5011 std::string Message =
".err directive invoked in source file";
5016 return Error(DirectiveLoc, Message);
5021bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
5022 if (!TheCondStack.empty()) {
5023 if (TheCondStack.back().Ignore) {
5024 eatToEndOfStatement();
5030 if (parseTextItem(
Text))
5031 return Error(getTok().getLoc(),
"missing text item in '.errb' directive");
5033 std::string Message =
".errb directive invoked in source file";
5036 return addErrorSuffix(
" in '.errb' directive");
5041 if (
Text.empty() == ExpectBlank)
5042 return Error(DirectiveLoc, Message);
5048bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
5049 bool ExpectDefined) {
5050 if (!TheCondStack.empty()) {
5051 if (TheCondStack.back().Ignore) {
5052 eatToEndOfStatement();
5057 bool IsDefined =
false;
5059 SMLoc StartLoc, EndLoc;
5061 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
5064 if (check(parseIdentifier(Name),
"expected identifier after '.errdef'"))
5067 if (BuiltinSymbolMap.contains(
Name.lower())) {
5077 std::string Message =
".errdef directive invoked in source file";
5080 return addErrorSuffix(
" in '.errdef' directive");
5085 if (IsDefined == ExpectDefined)
5086 return Error(DirectiveLoc, Message);
5092bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
5093 bool CaseInsensitive) {
5094 if (!TheCondStack.empty()) {
5095 if (TheCondStack.back().Ignore) {
5096 eatToEndOfStatement();
5101 std::string String1, String2;
5103 if (parseTextItem(String1)) {
5105 return TokError(
"expected string parameter for '.erridn' directive");
5106 return TokError(
"expected string parameter for '.errdif' directive");
5112 "expected comma after first string for '.erridn' directive");
5114 "expected comma after first string for '.errdif' directive");
5118 if (parseTextItem(String2)) {
5120 return TokError(
"expected string parameter for '.erridn' directive");
5121 return TokError(
"expected string parameter for '.errdif' directive");
5124 std::string Message;
5126 Message =
".erridn directive invoked in source file";
5128 Message =
".errdif directive invoked in source file";
5131 return addErrorSuffix(
" in '.erridn' directive");
5136 if (CaseInsensitive)
5138 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
5140 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
5143 if ((CaseInsensitive &&
5144 ExpectEqual == StringRef(String1).equals_insensitive(String2)) ||
5145 (ExpectEqual == (String1 == String2)))
5146 return Error(DirectiveLoc, Message);
5152bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero) {
5153 if (!TheCondStack.empty()) {
5154 if (TheCondStack.back().Ignore) {
5155 eatToEndOfStatement();
5161 if (parseAbsoluteExpression(ExprValue))
5162 return addErrorSuffix(
" in '.erre' directive");
5164 std::string Message =
".erre directive invoked in source file";
5167 return addErrorSuffix(
" in '.erre' directive");
5172 if ((ExprValue == 0) == ExpectZero)
5173 return Error(DirectiveLoc, Message);
5179bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5184 return Error(DirectiveLoc,
"Encountered a .endif that doesn't follow "
5186 if (!TheCondStack.empty()) {
5187 TheCondState = TheCondStack.back();
5188 TheCondStack.pop_back();
5194void MasmParser::initializeDirectiveKindMap() {
5195 DirectiveKindMap[
"="] = DK_ASSIGN;
5196 DirectiveKindMap[
"equ"] = DK_EQU;
5197 DirectiveKindMap[
"textequ"] = DK_TEXTEQU;
5201 DirectiveKindMap[
"byte"] = DK_BYTE;
5202 DirectiveKindMap[
"sbyte"] = DK_SBYTE;
5203 DirectiveKindMap[
"word"] = DK_WORD;
5204 DirectiveKindMap[
"sword"] = DK_SWORD;
5205 DirectiveKindMap[
"dword"] = DK_DWORD;
5206 DirectiveKindMap[
"sdword"] = DK_SDWORD;
5207 DirectiveKindMap[
"fword"] = DK_FWORD;
5208 DirectiveKindMap[
"qword"] = DK_QWORD;
5209 DirectiveKindMap[
"sqword"] = DK_SQWORD;
5210 DirectiveKindMap[
"real4"] = DK_REAL4;
5211 DirectiveKindMap[
"real8"] = DK_REAL8;
5212 DirectiveKindMap[
"real10"] = DK_REAL10;
5213 DirectiveKindMap[
"align"] = DK_ALIGN;
5214 DirectiveKindMap[
"even"] = DK_EVEN;
5215 DirectiveKindMap[
"org"] = DK_ORG;
5216 DirectiveKindMap[
"extern"] = DK_EXTERN;
5217 DirectiveKindMap[
"extrn"] = DK_EXTERN;
5218 DirectiveKindMap[
"public"] = DK_PUBLIC;
5220 DirectiveKindMap[
"comment"] = DK_COMMENT;
5221 DirectiveKindMap[
"include"] = DK_INCLUDE;
5222 DirectiveKindMap[
"repeat"] = DK_REPEAT;
5223 DirectiveKindMap[
"rept"] = DK_REPEAT;
5224 DirectiveKindMap[
"while"] = DK_WHILE;
5225 DirectiveKindMap[
"for"] = DK_FOR;
5226 DirectiveKindMap[
"irp"] = DK_FOR;
5227 DirectiveKindMap[
"forc"] = DK_FORC;
5228 DirectiveKindMap[
"irpc"] = DK_FORC;
5229 DirectiveKindMap[
"if"] = DK_IF;
5230 DirectiveKindMap[
"ife"] = DK_IFE;
5231 DirectiveKindMap[
"ifb"] = DK_IFB;
5232 DirectiveKindMap[
"ifnb"] = DK_IFNB;
5233 DirectiveKindMap[
"ifdef"] = DK_IFDEF;
5234 DirectiveKindMap[
"ifndef"] = DK_IFNDEF;
5235 DirectiveKindMap[
"ifdif"] = DK_IFDIF;
5236 DirectiveKindMap[
"ifdifi"] = DK_IFDIFI;
5237 DirectiveKindMap[
"ifidn"] = DK_IFIDN;
5238 DirectiveKindMap[
"ifidni"] = DK_IFIDNI;
5239 DirectiveKindMap[
"elseif"] = DK_ELSEIF;
5240 DirectiveKindMap[
"elseifdef"] = DK_ELSEIFDEF;
5241 DirectiveKindMap[
"elseifndef"] = DK_ELSEIFNDEF;
5242 DirectiveKindMap[
"elseifdif"] = DK_ELSEIFDIF;
5243 DirectiveKindMap[
"elseifidn"] = DK_ELSEIFIDN;
5244 DirectiveKindMap[
"else"] = DK_ELSE;
5245 DirectiveKindMap[
"end"] = DK_END;
5246 DirectiveKindMap[
"endif"] = DK_ENDIF;
5290 DirectiveKindMap[
"macro"] = DK_MACRO;
5291 DirectiveKindMap[
"exitm"] = DK_EXITM;
5292 DirectiveKindMap[
"endm"] = DK_ENDM;
5293 DirectiveKindMap[
"purge"] = DK_PURGE;
5294 DirectiveKindMap[
".err"] = DK_ERR;
5295 DirectiveKindMap[
".errb"] = DK_ERRB;
5296 DirectiveKindMap[
".errnb"] = DK_ERRNB;
5297 DirectiveKindMap[
".errdef"] = DK_ERRDEF;
5298 DirectiveKindMap[
".errndef"] = DK_ERRNDEF;
5299 DirectiveKindMap[
".errdif"] = DK_ERRDIF;
5300 DirectiveKindMap[
".errdifi"] = DK_ERRDIFI;
5301 DirectiveKindMap[
".erridn"] = DK_ERRIDN;
5302 DirectiveKindMap[
".erridni"] = DK_ERRIDNI;
5303 DirectiveKindMap[
".erre"] = DK_ERRE;
5304 DirectiveKindMap[
".errnz"] = DK_ERRNZ;
5305 DirectiveKindMap[
".pushframe"] = DK_PUSHFRAME;
5306 DirectiveKindMap[
".pushreg"] = DK_PUSHREG;
5307 DirectiveKindMap[
".push2reg"] = DK_PUSH2REGS;
5308 DirectiveKindMap[
".pop2reg"] = DK_PUSH2REGS;
5309 DirectiveKindMap[
".popreg"] = DK_PUSHREG;
5310 DirectiveKindMap[
".savereg"] = DK_SAVEREG;
5311 DirectiveKindMap[
".restorereg"] = DK_SAVEREG;
5312 DirectiveKindMap[
".savexmm128"] = DK_SAVEXMM128;
5313 DirectiveKindMap[
".restorexmm128"] = DK_SAVEXMM128;
5314 DirectiveKindMap[
".setframe"] = DK_SETFRAME;
5315 DirectiveKindMap[
".unsetframe"] = DK_SETFRAME;
5316 DirectiveKindMap[
".radix"] = DK_RADIX;
5317 DirectiveKindMap[
"db"] = DK_DB;
5318 DirectiveKindMap[
"dd"] = DK_DD;
5319 DirectiveKindMap[
"df"] = DK_DF;
5320 DirectiveKindMap[
"dq"] = DK_DQ;
5321 DirectiveKindMap[
"dw"] = DK_DW;
5322 DirectiveKindMap[
"echo"] = DK_ECHO;
5323 DirectiveKindMap[
"struc"] = DK_STRUCT;
5324 DirectiveKindMap[
"struct"] = DK_STRUCT;
5325 DirectiveKindMap[
"union"] = DK_UNION;
5326 DirectiveKindMap[
"ends"] = DK_ENDS;
5329bool MasmParser::isMacroLikeDirective() {
5331 bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier())
5332 .CasesLower({
"repeat",
"rept"},
true)
5333 .CaseLower(
"while",
true)
5334 .CasesLower({
"for",
"irp"},
true)
5335 .CasesLower({
"forc",
"irpc"},
true)
5341 peekTok().getIdentifier().equals_insensitive(
"macro"))
5347MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5348 AsmToken EndToken, StartToken = getTok();
5350 unsigned NestLevel = 0;
5354 printError(DirectiveLoc,
"no matching 'endm' in definition");
5358 if (isMacroLikeDirective())
5363 getTok().getIdentifier().equals_insensitive(
"endm")) {
5364 if (NestLevel == 0) {
5365 EndToken = getTok();
5368 printError(getTok().getLoc(),
"unexpected token in 'endm' directive");
5377 eatToEndOfStatement();
5382 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5386 return &MacroLikeBodies.back();
5389bool MasmParser::expandStatement(SMLoc Loc) {
5391 SMLoc EndLoc = getTok().getLoc();
5396 StringMap<std::string> BuiltinValues;
5397 for (
const auto &S : BuiltinSymbolMap) {
5398 const BuiltinSymbol &Sym = S.getValue();
5399 if (std::optional<std::string>
Text = evaluateBuiltinTextMacro(Sym, Loc)) {
5400 BuiltinValues[S.getKey().lower()] = std::move(*
Text);
5403 for (
const auto &
B : BuiltinValues) {
5404 MCAsmMacroParameter
P;
5405 MCAsmMacroArgument
A;
5406 P.Name =
B.getKey();
5414 for (
const auto &V : Variables) {
5417 MCAsmMacroParameter
P;
5418 MCAsmMacroArgument
A;
5427 MacroLikeBodies.emplace_back(StringRef(), Body, Parameters);
5428 MCAsmMacro
M = MacroLikeBodies.back();
5431 SmallString<80> Buf;
5432 raw_svector_ostream OS(Buf);
5433 if (expandMacro(OS,
M.Body,
M.Parameters,
Arguments,
M.Locals, EndLoc))
5435 std::unique_ptr<MemoryBuffer>
Expansion =
5441 EndStatementAtEOFStack.push_back(
false);
5446void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5447 raw_svector_ostream &OS) {
5448 instantiateMacroLikeBody(M, DirectiveLoc, getTok().getLoc(), OS);
5450void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5452 raw_svector_ostream &OS) {
5455 std::unique_ptr<MemoryBuffer> Instantiation =
5460 MacroInstantiation *
MI =
new MacroInstantiation{DirectiveLoc, CurBuffer,
5461 ExitLoc, TheCondStack.size()};
5462 ActiveMacros.push_back(
MI);
5467 EndStatementAtEOFStack.push_back(
true);
5475bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) {
5476 const MCExpr *CountExpr;
5477 SMLoc CountLoc = getTok().getLoc();
5478 if (parseExpression(CountExpr))
5482 if (!CountExpr->evaluateAsAbsolute(
Count, getStreamer().getAssemblerPtr())) {
5483 return Error(CountLoc,
"unexpected token in '" + Dir +
"' directive");
5486 if (check(
Count < 0, CountLoc,
"Count is negative") || parseEOL())
5490 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5496 SmallString<256> Buf;
5497 raw_svector_ostream OS(Buf);
5499 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5502 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5511bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) {
5512 const MCExpr *CondExpr;
5513 SMLoc CondLoc = getTok().getLoc();
5514 if (parseExpression(CondExpr))
5518 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5524 SmallString<256> Buf;
5525 raw_svector_ostream OS(Buf);
5527 if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr()))
5528 return Error(CondLoc,
"expected absolute expression in 'while' directive");
5532 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5534 instantiateMacroLikeBody(M, DirectiveLoc, DirectiveLoc, OS);
5544bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
5546 MCAsmMacroArguments
A;
5547 if (check(parseIdentifier(
Parameter.Name),
5548 "expected identifier in '" + Dir +
"' directive"))
5557 ParamLoc = Lexer.getLoc();
5558 if (parseMacroArgument(
nullptr,
Parameter.Value))
5564 QualLoc = Lexer.getLoc();
5565 if (parseIdentifier(Qualifier))
5566 return Error(QualLoc,
"missing parameter qualifier for "
5571 if (
Qualifier.equals_insensitive(
"req"))
5574 return Error(QualLoc,
5575 Qualifier +
" is not a valid parameter qualifier for '" +
5576 Parameter.Name +
"' in '" + Dir +
"' directive");
5581 "expected comma in '" + Dir +
"' directive") ||
5583 "values in '" + Dir +
5584 "' directive must be enclosed in angle brackets"))
5590 return addErrorSuffix(
" in arguments for '" + Dir +
"' directive");
5599 "values in '" + Dir +
5600 "' directive must be enclosed in angle brackets") ||
5605 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5611 SmallString<256> Buf;
5612 raw_svector_ostream OS(Buf);
5614 for (
const MCAsmMacroArgument &Arg :
A) {
5615 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5619 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5628bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
5632 if (check(parseIdentifier(
Parameter.Name),
5633 "expected identifier in '" + Directive +
"' directive") ||
5635 "expected comma in '" + Directive +
"' directive"))
5637 if (parseAngleBracketString(Argument)) {
5645 for (; End <
Argument.size(); ++End) {
5655 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5661 SmallString<256> Buf;
5662 raw_svector_ostream OS(Buf);
5664 StringRef
Values(Argument);
5665 for (std::size_t
I = 0, End =
Values.size();
I != End; ++
I) {
5666 MCAsmMacroArgument Arg;
5669 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5673 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5678bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
5680 const MCExpr *
Value;
5681 SMLoc ExprLoc = getLexer().getLoc();
5682 if (parseExpression(
Value))
5686 return Error(ExprLoc,
"unexpected expression in _emit");
5687 uint64_t IntValue = MCE->
getValue();
5689 return Error(ExprLoc,
"literal value out of range for directive");
5695bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
5696 const MCExpr *
Value;
5697 SMLoc ExprLoc = getLexer().getLoc();
5698 if (parseExpression(
Value))
5702 return Error(ExprLoc,
"unexpected expression in align");
5703 uint64_t IntValue = MCE->
getValue();
5705 return Error(ExprLoc,
"literal value not a power of two greater then zero");
5711bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
5712 const SMLoc Loc = getLexer().getLoc();
5714 StringRef RadixString = StringRef(RadixStringRaw).trim();
5718 "radix must be a decimal number in the range 2 to 16; was " +
5721 if (Radix < 2 || Radix > 16)
5722 return Error(Loc,
"radix must be in the range 2 to 16; was " +
5723 std::to_string(Radix));
5724 getLexer().setMasmDefaultRadix(Radix);
5730bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) {
5733 if (!StringRef(Message).ends_with(
"\n"))
5761bool MasmParser::defineMacro(StringRef Name, StringRef
Value) {
5763 if (Var.Name.empty()) {
5765 }
else if (Var.Redefinable == Variable::NOT_REDEFINABLE) {
5766 return Error(SMLoc(),
"invalid variable redefinition");
5767 }
else if (Var.Redefinable == Variable::WARN_ON_REDEFINITION &&
5768 Warning(SMLoc(),
"redefining '" + Name +
5769 "', already defined on the command line")) {
5772 Var.Redefinable = Variable::WARN_ON_REDEFINITION;
5774 Var.TextValue =
Value.str();
5778bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info)
const {
5779 const std::pair<StringRef, StringRef> BaseMember =
Name.split(
'.');
5780 const StringRef
Base = BaseMember.first,
Member = BaseMember.second;
5781 return lookUpField(
Base, Member, Info);
5784bool MasmParser::lookUpField(StringRef
Base, StringRef Member,
5785 AsmFieldInfo &Info)
const {
5789 AsmFieldInfo BaseInfo;
5790 if (
Base.contains(
'.') && !lookUpField(
Base, BaseInfo))
5793 auto StructIt = Structs.
find(
Base.lower());
5794 auto TypeIt = KnownType.
find(
Base.lower());
5795 if (TypeIt != KnownType.
end()) {
5796 StructIt = Structs.
find(TypeIt->second.Name.lower());
5798 if (StructIt != Structs.
end())
5799 return lookUpField(StructIt->second, Member, Info);
5804bool MasmParser::lookUpField(
const StructInfo &Structure, StringRef Member,
5805 AsmFieldInfo &Info)
const {
5807 Info.Type.Name = Structure.Name;
5808 Info.Type.Size = Structure.Size;
5809 Info.Type.ElementSize = Structure.Size;
5810 Info.Type.Length = 1;
5814 std::pair<StringRef, StringRef>
Split =
Member.split(
'.');
5815 const StringRef FieldName =
Split.first, FieldMember =
Split.second;
5817 auto StructIt = Structs.
find(FieldName.
lower());
5818 if (StructIt != Structs.
end())
5819 return lookUpField(StructIt->second, FieldMember, Info);
5821 auto FieldIt = Structure.FieldsByName.
find(FieldName.
lower());
5822 if (FieldIt == Structure.FieldsByName.
end())
5825 const FieldInfo &
Field = Structure.Fields[FieldIt->second];
5826 if (FieldMember.empty()) {
5831 if (
Field.Contents.FT == FT_STRUCT)
5832 Info.Type.Name =
Field.Contents.StructInfo.Structure.Name;
5834 Info.Type.Name =
"";
5838 if (
Field.Contents.FT != FT_STRUCT)
5840 const StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
5842 if (lookUpField(StructInfo.Structure, FieldMember, Info))
5849bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info)
const {
5850 unsigned Size = StringSwitch<unsigned>(Name)
5851 .CasesLower({
"byte",
"db",
"sbyte"}, 1)
5852 .CasesLower({
"word",
"dw",
"sword"}, 2)
5853 .CasesLower({
"dword",
"dd",
"sdword"}, 4)
5854 .CasesLower({
"fword",
"df"}, 6)
5855 .CasesLower({
"qword",
"dq",
"sqword"}, 8)
5856 .CaseLower(
"real4", 4)
5857 .CaseLower(
"real8", 8)
5858 .CaseLower(
"real10", 10)
5868 auto StructIt = Structs.
find(
Name.lower());
5869 if (StructIt != Structs.
end()) {
5870 const StructInfo &Structure = StructIt->second;
5872 Info.ElementSize = Structure.Size;
5874 Info.Size = Structure.Size;
5881bool MasmParser::parseMSInlineAsm(
5882 std::string &AsmString,
unsigned &NumOutputs,
unsigned &NumInputs,
5883 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5884 SmallVectorImpl<std::string> &Constraints,
5885 SmallVectorImpl<std::string> &Clobbers,
const MCInstrInfo *MII,
5886 MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
5887 SmallVector<void *, 4> InputDecls;
5888 SmallVector<void *, 4> OutputDecls;
5891 SmallVector<std::string, 4> InputConstraints;
5892 SmallVector<std::string, 4> OutputConstraints;
5901 unsigned InputIdx = 0;
5902 unsigned OutputIdx = 0;
5905 if (parseCurlyBlockScope(AsmStrRewrites))
5908 ParseStatementInfo
Info(&AsmStrRewrites);
5909 bool StatementErr = parseStatement(Info, &SI);
5911 if (StatementErr ||
Info.ParseError) {
5913 printPendingErrors();
5918 assert(!hasPendingError() &&
"unexpected error from parseStatement");
5920 if (
Info.Opcode == ~0U)
5926 for (
unsigned i = 1, e =
Info.ParsedOperands.size(); i != e; ++i) {
5927 MCParsedAsmOperand &Operand = *
Info.ParsedOperands[i];
5931 !getTargetParser().omitRegisterFromClobberLists(Operand.
getReg())) {
5932 unsigned NumDefs =
Desc.getNumDefs();
5941 if (SymName.
empty())
5949 if (Operand.
isImm()) {
5957 bool isOutput = (i == 1) &&
Desc.mayStore();
5963 OutputConstraints.
push_back((
"=" + Constraint).str());
5969 if (
Desc.operands()[i - 1].isBranchTarget())
5981 NumOutputs = OutputDecls.
size();
5982 NumInputs = InputDecls.
size();
5987 Clobbers.
assign(ClobberRegs.
size(), std::string());
5988 for (
unsigned I = 0,
E = ClobberRegs.
size();
I !=
E; ++
I) {
5989 raw_string_ostream OS(Clobbers[
I]);
5994 if (NumOutputs || NumInputs) {
5995 unsigned NumExprs = NumOutputs + NumInputs;
5996 OpDecls.resize(NumExprs);
5997 Constraints.
resize(NumExprs);
5998 for (
unsigned i = 0; i < NumOutputs; ++i) {
5999 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
6000 Constraints[i] = OutputConstraints[i];
6002 for (
unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++
j) {
6003 OpDecls[
j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
6004 Constraints[
j] = InputConstraints[i];
6009 std::string AsmStringIR;
6010 raw_string_ostream OS(AsmStringIR);
6011 StringRef ASMString =
6013 const char *AsmStart = ASMString.
begin();
6014 const char *AsmEnd = ASMString.
end();
6016 for (
auto I = AsmStrRewrites.
begin(),
E = AsmStrRewrites.
end();
I !=
E; ++
I) {
6017 const AsmRewrite &AR = *
I;
6024 assert(Loc >= AsmStart &&
"Expected Loc to be at or after Start!");
6027 if (
unsigned Len = Loc - AsmStart)
6028 OS << StringRef(AsmStart, Len);
6032 AsmStart = Loc + AR.
Len;
6036 unsigned AdditionalSkip = 0;
6058 size_t OffsetLen = OffsetName.
size();
6059 auto rewrite_it = std::find_if(
6060 I, AsmStrRewrites.
end(), [&](
const AsmRewrite &FusingAR) {
6061 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6062 (FusingAR.Kind == AOK_Input ||
6063 FusingAR.Kind == AOK_CallInput);
6065 if (rewrite_it == AsmStrRewrites.
end()) {
6066 OS <<
"offset " << OffsetName;
6068 OS <<
"${" << InputIdx++ <<
":P}";
6069 rewrite_it->Done =
true;
6071 OS <<
'$' << InputIdx++;
6072 rewrite_it->Done =
true;
6084 OS <<
'$' << InputIdx++;
6087 OS <<
"${" << InputIdx++ <<
":P}";
6090 OS <<
'$' << OutputIdx++;
6095 case 8: OS <<
"byte ptr ";
break;
6096 case 16: OS <<
"word ptr ";
break;
6097 case 32: OS <<
"dword ptr ";
break;
6098 case 64: OS <<
"qword ptr ";
break;
6099 case 80: OS <<
"xword ptr ";
break;
6100 case 128: OS <<
"xmmword ptr ";
break;
6101 case 256: OS <<
"ymmword ptr ";
break;
6111 if (
getContext().getAsmInfo().getAlignmentIsInBytes())
6116 unsigned Val = AR.
Val;
6118 assert(Val < 10 &&
"Expected alignment less then 2^10.");
6119 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6131 AsmStart = Loc + AR.
Len + AdditionalSkip;
6135 if (AsmStart != AsmEnd)
6136 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6138 AsmString = OS.
str();
6142void MasmParser::initializeBuiltinSymbolMaps() {
6144 BuiltinSymbolMap[
"@version"] = BI_VERSION;
6145 BuiltinSymbolMap[
"@line"] = BI_LINE;
6146 BuiltinSymbolMap[
"@unwindversion"] = BI_UNWINDVERSION;
6149 BuiltinSymbolMap[
"@date"] = BI_DATE;
6150 BuiltinSymbolMap[
"@time"] = BI_TIME;
6151 BuiltinSymbolMap[
"@filecur"] = BI_FILECUR;
6152 BuiltinSymbolMap[
"@filename"] = BI_FILENAME;
6153 BuiltinSymbolMap[
"@curseg"] = BI_CURSEG;
6156 BuiltinFunctionMap[
"@catstr"] = BI_CATSTR;
6159 if (
getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
6177const MCExpr *MasmParser::evaluateBuiltinValue(BuiltinSymbol Symbol,
6187 if (ActiveMacros.empty())
6191 ActiveMacros.front()->ExitBuffer);
6194 case BI_UNWINDVERSION:
6201std::optional<std::string>
6202MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
6208 char TmpBuffer[
sizeof(
"mm/dd/yy")];
6209 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%D", &TM);
6210 return std::string(TmpBuffer, Len);
6214 char TmpBuffer[
sizeof(
"hh:mm:ss")];
6215 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%T", &TM);
6216 return std::string(TmpBuffer, Len);
6221 ActiveMacros.empty() ? CurBuffer : ActiveMacros.front()->ExitBuffer)
6229 return getStreamer().getCurrentSectionOnly()->getName().str();
6234bool MasmParser::evaluateBuiltinMacroFunction(BuiltinFunction Function,
6238 "' requires arguments in parentheses")) {
6249 MCAsmMacro
M(Name,
"",
P, {},
true);
6251 MCAsmMacroArguments
A;
6260 for (
const MCAsmMacroArgument &Arg :
A) {
6261 for (
const AsmToken &Tok : Arg) {
6279 struct tm TM,
unsigned CB) {
6280 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< 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)
static constexpr unsigned SM(unsigned Version)
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
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.