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);
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] = 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;
487 bool Warning(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,
728 StringMap<DirectiveKind> DirectiveKindMap;
730 bool isMacroLikeDirective();
756 StringMap<BuiltinSymbol> BuiltinSymbolMap;
758 const MCExpr *evaluateBuiltinValue(BuiltinSymbol Symbol, SMLoc StartLoc);
760 std::optional<std::string> evaluateBuiltinTextMacro(BuiltinSymbol Symbol,
764 enum BuiltinFunction {
771 StringMap<BuiltinFunction> BuiltinFunctionMap;
773 bool evaluateBuiltinMacroFunction(BuiltinFunction Function, StringRef Name,
777 bool parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated);
780 bool emitIntValue(
const MCExpr *
Value,
unsigned Size);
781 bool parseScalarInitializer(
unsigned Size,
782 SmallVectorImpl<const MCExpr *> &Values,
783 unsigned StringPadLength = 0);
784 bool parseScalarInstList(
785 unsigned Size, SmallVectorImpl<const MCExpr *> &Values,
787 bool emitIntegralValues(
unsigned Size,
unsigned *
Count =
nullptr);
788 bool addIntegralField(StringRef Name,
unsigned Size);
789 bool parseDirectiveValue(StringRef IDVal,
unsigned Size);
790 bool parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
791 StringRef Name, SMLoc NameLoc);
794 bool emitRealValues(
const fltSemantics &Semantics,
unsigned *
Count =
nullptr);
795 bool addRealField(StringRef Name,
const fltSemantics &Semantics,
size_t Size);
796 bool parseDirectiveRealValue(StringRef IDVal,
const fltSemantics &Semantics,
798 bool parseRealInstList(
799 const fltSemantics &Semantics, SmallVectorImpl<APInt> &Values,
801 bool parseDirectiveNamedRealValue(StringRef TypeName,
802 const fltSemantics &Semantics,
803 unsigned Size, StringRef Name,
806 bool parseOptionalAngleBracketOpen();
807 bool parseAngleBracketClose(
const Twine &Msg =
"expected '>'");
809 bool parseFieldInitializer(
const FieldInfo &
Field,
810 FieldInitializer &Initializer);
811 bool parseFieldInitializer(
const FieldInfo &
Field,
812 const IntFieldInfo &Contents,
813 FieldInitializer &Initializer);
814 bool parseFieldInitializer(
const FieldInfo &
Field,
815 const RealFieldInfo &Contents,
816 FieldInitializer &Initializer);
817 bool parseFieldInitializer(
const FieldInfo &
Field,
818 const StructFieldInfo &Contents,
819 FieldInitializer &Initializer);
821 bool parseStructInitializer(
const StructInfo &Structure,
822 StructInitializer &Initializer);
823 bool parseStructInstList(
824 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
827 bool emitFieldValue(
const FieldInfo &
Field);
828 bool emitFieldValue(
const FieldInfo &
Field,
const IntFieldInfo &Contents);
829 bool emitFieldValue(
const FieldInfo &
Field,
const RealFieldInfo &Contents);
830 bool emitFieldValue(
const FieldInfo &
Field,
const StructFieldInfo &Contents);
832 bool emitFieldInitializer(
const FieldInfo &
Field,
833 const FieldInitializer &Initializer);
834 bool emitFieldInitializer(
const FieldInfo &
Field,
835 const IntFieldInfo &Contents,
836 const IntFieldInfo &Initializer);
837 bool emitFieldInitializer(
const FieldInfo &
Field,
838 const RealFieldInfo &Contents,
839 const RealFieldInfo &Initializer);
840 bool emitFieldInitializer(
const FieldInfo &
Field,
841 const StructFieldInfo &Contents,
842 const StructFieldInfo &Initializer);
844 bool emitStructInitializer(
const StructInfo &Structure,
845 const StructInitializer &Initializer);
848 bool emitStructValues(
const StructInfo &Structure,
unsigned *
Count =
nullptr);
849 bool addStructField(StringRef Name,
const StructInfo &Structure);
850 bool parseDirectiveStructValue(
const StructInfo &Structure,
851 StringRef Directive, SMLoc DirLoc);
852 bool parseDirectiveNamedStructValue(
const StructInfo &Structure,
853 StringRef Directive, SMLoc DirLoc,
857 bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
858 DirectiveKind DirKind, SMLoc NameLoc);
860 bool parseDirectiveOrg();
862 bool emitAlignTo(int64_t Alignment);
863 bool parseDirectiveAlign();
864 bool parseDirectiveEven();
867 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
868 bool parseDirectiveExitMacro(SMLoc DirectiveLoc, StringRef Directive,
870 bool parseDirectiveEndMacro(StringRef Directive);
871 bool parseDirectiveMacro(StringRef Name, SMLoc NameLoc);
873 bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind,
874 StringRef Name, SMLoc NameLoc);
875 bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind);
876 bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
877 bool parseDirectiveNestedEnds();
879 bool parseDirectiveExtern();
885 bool parseDirectiveComm(
bool IsLocal);
887 bool parseDirectiveComment(SMLoc DirectiveLoc);
889 bool parseDirectiveInclude();
892 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
894 bool parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
897 bool parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
898 bool CaseInsensitive);
900 bool parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined);
902 bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
904 bool parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
906 bool parseDirectiveElseIfdef(SMLoc DirectiveLoc,
bool expect_defined);
909 bool parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
910 bool CaseInsensitive);
911 bool parseDirectiveElse(SMLoc DirectiveLoc);
912 bool parseDirectiveEndIf(SMLoc DirectiveLoc);
913 bool parseEscapedString(std::string &
Data)
override;
914 bool parseAngleBracketString(std::string &
Data)
override;
917 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
918 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
919 raw_svector_ostream &OS);
920 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
921 SMLoc ExitLoc, raw_svector_ostream &OS);
922 bool parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Directive);
923 bool parseDirectiveFor(SMLoc DirectiveLoc, StringRef Directive);
924 bool parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive);
925 bool parseDirectiveWhile(SMLoc DirectiveLoc);
928 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &
Info,
932 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &
Info);
935 bool parseDirectiveEnd(SMLoc DirectiveLoc);
938 bool parseDirectiveError(SMLoc DirectiveLoc);
940 bool parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
942 bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
bool ExpectDefined);
945 bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
946 bool CaseInsensitive);
948 bool parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero);
951 bool parseDirectiveRadix(SMLoc DirectiveLoc);
954 bool parseDirectiveEcho(SMLoc DirectiveLoc);
956 void initializeDirectiveKindMap();
957 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;
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);
2402 if (!Parser->SavedDiagHandler && DiagCurBuffer &&
2411 if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
2412 DiagBuf != CppHashBuf) {
2413 if (Parser->SavedDiagHandler)
2414 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2416 Diag.
print(
nullptr, OS);
2423 const std::string &
Filename = std::string(Parser->CppHashInfo.Filename);
2426 int CppHashLocLineNo =
2427 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2429 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2435 if (Parser->SavedDiagHandler)
2436 Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
2438 NewDiag.print(
nullptr, OS);
2444 return isAlnum(
C) ||
C ==
'_' ||
C ==
'$' ||
C ==
'@' ||
C ==
'?';
2447bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
2450 const std::vector<std::string> &Locals, SMLoc L) {
2452 if (NParameters !=
A.size())
2453 return Error(L,
"Wrong number of arguments");
2454 StringMap<std::string> LocalSymbols;
2457 for (StringRef
Local : Locals) {
2458 raw_string_ostream LocalName(Name);
2465 std::optional<char> CurrentQuote;
2466 while (!Body.
empty()) {
2468 std::size_t End = Body.
size(), Pos = 0;
2469 std::size_t IdentifierPos = End;
2470 for (; Pos != End; ++Pos) {
2473 if (Body[Pos] ==
'&')
2478 if (IdentifierPos == End)
2479 IdentifierPos = Pos;
2481 IdentifierPos = End;
2485 if (!CurrentQuote) {
2486 if (Body[Pos] ==
'\'' || Body[Pos] ==
'"')
2487 CurrentQuote = Body[Pos];
2488 }
else if (Body[Pos] == CurrentQuote) {
2489 if (Pos + 1 != End && Body[Pos + 1] == CurrentQuote) {
2494 CurrentQuote.reset();
2498 if (IdentifierPos != End) {
2501 Pos = IdentifierPos;
2502 IdentifierPos = End;
2506 OS << Body.
slice(0, Pos);
2513 bool InitialAmpersand = (Body[
I] ==
'&');
2514 if (InitialAmpersand) {
2521 const char *Begin = Body.
data() + Pos;
2523 const std::string ArgumentLower =
Argument.lower();
2527 if (Parameters[Index].
Name.equals_insensitive(ArgumentLower))
2530 if (Index == NParameters) {
2531 if (InitialAmpersand)
2533 auto it = LocalSymbols.
find(ArgumentLower);
2534 if (it != LocalSymbols.
end())
2540 for (
const AsmToken &Token :
A[Index]) {
2550 OS << Token.getIntVal();
2552 OS << Token.getString();
2556 if (Pos < End && Body[Pos] ==
'&') {
2567bool MasmParser::parseMacroArgument(
const MCAsmMacroParameter *MP,
2568 MCAsmMacroArgument &MA,
2571 if (Lexer.isNot(EndTok)) {
2572 SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok);
2573 for (StringRef S : Str) {
2580 SMLoc StrLoc = Lexer.getLoc(), EndLoc;
2582 const char *StrChar = StrLoc.
getPointer() + 1;
2583 const char *EndChar = EndLoc.
getPointer() - 1;
2584 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
2591 unsigned ParenLevel = 0;
2595 return TokError(
"unexpected token");
2612 MA.push_back(getTok());
2616 if (ParenLevel != 0)
2617 return TokError(
"unbalanced parentheses in argument");
2619 if (MA.empty() && MP) {
2621 return TokError(
"missing value for required parameter '" + MP->
Name +
2631bool MasmParser::parseMacroArguments(
const MCAsmMacro *M,
2632 MCAsmMacroArguments &
A,
2634 const unsigned NParameters =
M ?
M->Parameters.size() : 0;
2635 bool NamedParametersFound =
false;
2636 SmallVector<SMLoc, 4> FALocs;
2638 A.resize(NParameters);
2639 FALocs.
resize(NParameters);
2644 for (
unsigned Parameter = 0; !NParameters ||
Parameter < NParameters;
2646 SMLoc IDLoc = Lexer.getLoc();
2647 MCAsmMacroParameter FA;
2650 if (parseIdentifier(FA.
Name))
2651 return Error(IDLoc,
"invalid argument identifier for formal argument");
2654 return TokError(
"expected '=' after formal parameter identifier");
2658 NamedParametersFound =
true;
2661 if (NamedParametersFound && FA.
Name.
empty())
2662 return Error(IDLoc,
"cannot mix positional and keyword arguments");
2666 assert(M &&
"expected macro to be defined");
2668 for (FAI = 0; FAI < NParameters; ++FAI)
2669 if (
M->Parameters[FAI].Name == FA.
Name)
2672 if (FAI >= NParameters) {
2673 return Error(IDLoc,
"parameter named '" + FA.
Name +
2674 "' does not exist for macro '" +
M->Name +
"'");
2678 const MCAsmMacroParameter *MP =
nullptr;
2679 if (M && PI < NParameters)
2680 MP = &
M->Parameters[PI];
2682 SMLoc StrLoc = Lexer.getLoc();
2685 const MCExpr *AbsoluteExp;
2689 if (parseExpression(AbsoluteExp, EndLoc))
2691 if (!AbsoluteExp->evaluateAsAbsolute(
Value,
2692 getStreamer().getAssemblerPtr()))
2693 return Error(StrLoc,
"expected absolute expression");
2697 StringRef(StrChar, EndChar - StrChar),
Value);
2698 FA.
Value.push_back(newToken);
2699 }
else if (parseMacroArgument(MP, FA.
Value, EndTok)) {
2701 return addErrorSuffix(
" in '" +
M->Name +
"' macro");
2706 if (!FA.
Value.empty()) {
2711 if (FALocs.
size() <= PI)
2714 FALocs[PI] = Lexer.getLoc();
2720 if (Lexer.is(EndTok)) {
2722 for (
unsigned FAI = 0; FAI < NParameters; ++FAI) {
2724 if (
M->Parameters[FAI].Required) {
2725 Error(FALocs[FAI].
isValid() ? FALocs[FAI] : Lexer.getLoc(),
2726 "missing value for required parameter "
2728 M->Parameters[FAI].Name +
"' in macro '" +
M->Name +
"'");
2732 if (!
M->Parameters[FAI].Value.empty())
2733 A[FAI] =
M->Parameters[FAI].Value;
2743 return TokError(
"too many positional arguments");
2746bool MasmParser::handleMacroEntry(
const MCAsmMacro *M, SMLoc NameLoc,
2751 if (ActiveMacros.size() == MaxNestingDepth) {
2752 std::ostringstream MaxNestingDepthError;
2753 MaxNestingDepthError <<
"macros cannot be nested more than "
2754 << MaxNestingDepth <<
" levels deep."
2755 <<
" Use -asm-macro-max-nesting-depth to increase "
2757 return TokError(MaxNestingDepthError.str());
2760 MCAsmMacroArguments
A;
2761 if (parseMacroArguments(M,
A, ArgumentEndTok) || parseToken(ArgumentEndTok))
2766 SmallString<256> Buf;
2767 StringRef Body =
M->Body;
2768 raw_svector_ostream OS(Buf);
2770 if (expandMacro(OS, Body,
M->Parameters,
A,
M->Locals, getTok().getLoc()))
2777 std::unique_ptr<MemoryBuffer> Instantiation =
2782 MacroInstantiation *
MI =
new MacroInstantiation{
2783 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
2784 ActiveMacros.push_back(
MI);
2786 ++NumOfMacroInstantiations;
2791 EndStatementAtEOFStack.push_back(
true);
2797void MasmParser::handleMacroExit() {
2799 EndStatementAtEOFStack.pop_back();
2800 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer,
2801 EndStatementAtEOFStack.back());
2805 delete ActiveMacros.back();
2806 ActiveMacros.pop_back();
2809bool MasmParser::handleMacroInvocation(
const MCAsmMacro *M, SMLoc NameLoc) {
2811 return Error(NameLoc,
"cannot invoke macro procedure as function");
2814 "' requires arguments in parentheses") ||
2819 std::string ExitValue;
2822 ParseStatementInfo
Info(&AsmStrRewrites);
2823 bool HasError = parseStatement(
Info,
nullptr);
2825 if (!HasError &&
Info.ExitValue) {
2826 ExitValue = std::move(*
Info.ExitValue);
2833 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
2837 printPendingErrors();
2840 if (HasError && !getLexer().justConsumedEOL())
2841 eatToEndOfStatement();
2846 std::unique_ptr<MemoryBuffer> MacroValue =
2854 EndStatementAtEOFStack.push_back(
false);
2863bool MasmParser::parseIdentifier(StringRef &Res,
2864 IdentifierPositionKind Position) {
2871 SMLoc PrefixLoc = getLexer().getLoc();
2875 AsmToken nextTok = peekTok(
false);
2888 StringRef(PrefixLoc.
getPointer(), getTok().getIdentifier().
size() + 1);
2896 Res = getTok().getIdentifier();
2900 ExpandKind ExpandNextToken = ExpandMacros;
2901 if (Position == StartOfStatement &&
2902 StringSwitch<bool>(Res)
2903 .CaseLower(
"echo",
true)
2904 .CasesLower({
"ifdef",
"ifndef",
"elseifdef",
"elseifndef"},
true)
2906 ExpandNextToken = DoNotExpandMacros;
2908 Lex(ExpandNextToken);
2918bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
2919 DirectiveKind DirKind, SMLoc NameLoc) {
2920 auto BuiltinIt = BuiltinSymbolMap.find(
Name.lower());
2921 if (BuiltinIt != BuiltinSymbolMap.end())
2922 return Error(NameLoc,
"cannot redefine a built-in symbol");
2925 if (Var.Name.empty()) {
2929 SMLoc StartLoc = Lexer.getLoc();
2930 if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) {
2933 std::string TextItem;
2934 if (!parseTextItem(TextItem)) {
2938 auto parseItem = [&]() ->
bool {
2939 if (parseTextItem(TextItem))
2940 return TokError(
"expected text item");
2945 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
2947 if (!Var.IsText || Var.TextValue !=
Value) {
2948 switch (Var.Redefinable) {
2949 case Variable::NOT_REDEFINABLE:
2950 return Error(getTok().getLoc(),
"invalid variable redefinition");
2951 case Variable::WARN_ON_REDEFINITION:
2952 if (
Warning(NameLoc,
"redefining '" + Name +
2953 "', already defined on the command line")) {
2962 Var.TextValue =
Value;
2963 Var.Redefinable = Variable::REDEFINABLE;
2968 if (DirKind == DK_TEXTEQU)
2969 return TokError(
"expected <text> in '" + Twine(IDVal) +
"' directive");
2974 if (parseExpression(Expr, EndLoc))
2975 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
2976 StringRef ExprAsString = StringRef(
2980 if (!Expr->evaluateAsAbsolute(
Value, getStreamer().getAssemblerPtr())) {
2981 if (DirKind == DK_ASSIGN)
2984 "expected absolute expression; not all symbols have known values",
2985 {StartLoc, EndLoc});
2988 if (!Var.IsText || Var.TextValue != ExprAsString) {
2989 switch (Var.Redefinable) {
2990 case Variable::NOT_REDEFINABLE:
2991 return Error(getTok().getLoc(),
"invalid variable redefinition");
2992 case Variable::WARN_ON_REDEFINITION:
2993 if (
Warning(NameLoc,
"redefining '" + Name +
2994 "', already defined on the command line")) {
3004 Var.TextValue = ExprAsString.
str();
3005 Var.Redefinable = Variable::REDEFINABLE;
3010 auto *Sym =
static_cast<MCSymbolCOFF *
>(
getContext().parseSymbol(Var.Name));
3011 const MCConstantExpr *PrevValue =
3015 if (Var.IsText || !PrevValue || PrevValue->
getValue() !=
Value) {
3016 switch (Var.Redefinable) {
3017 case Variable::NOT_REDEFINABLE:
3018 return Error(getTok().getLoc(),
"invalid variable redefinition");
3019 case Variable::WARN_ON_REDEFINITION:
3020 if (
Warning(NameLoc,
"redefining '" + Name +
3021 "', already defined on the command line")) {
3031 Var.TextValue.clear();
3032 Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE
3035 Sym->
setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE);
3037 Sym->setExternal(
false);
3042bool MasmParser::parseEscapedString(std::string &
Data) {
3047 char Quote = getTok().getString().front();
3048 StringRef Str = getTok().getStringContents();
3049 Data.reserve(Str.size());
3050 for (
size_t i = 0, e = Str.size(); i != e; ++i) {
3051 Data.push_back(Str[i]);
3052 if (Str[i] == Quote) {
3056 if (i + 1 == Str.size())
3057 return Error(getTok().getLoc(),
"missing quotation mark in string");
3058 if (Str[i + 1] == Quote)
3067bool MasmParser::parseAngleBracketString(std::string &
Data) {
3068 SMLoc EndLoc, StartLoc = getTok().getLoc();
3070 const char *StartChar = StartLoc.
getPointer() + 1;
3071 const char *EndChar = EndLoc.
getPointer() - 1;
3072 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
3083bool MasmParser::parseTextItem(std::string &
Data) {
3084 switch (getTok().getKind()) {
3091 Data = std::to_string(Res);
3098 return parseAngleBracketString(
Data);
3102 SMLoc StartLoc = getTok().getLoc();
3103 if (parseIdentifier(
ID))
3107 bool Expanded =
false;
3110 auto BuiltinIt = BuiltinSymbolMap.find(
ID.lower());
3111 if (BuiltinIt != BuiltinSymbolMap.end()) {
3112 std::optional<std::string> BuiltinText =
3113 evaluateBuiltinTextMacro(BuiltinIt->getValue(), StartLoc);
3118 Data = std::move(*BuiltinText);
3125 auto BuiltinFuncIt = BuiltinFunctionMap.find(
ID.lower());
3126 if (BuiltinFuncIt != BuiltinFunctionMap.end()) {
3128 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(),
ID,
Data)) {
3137 auto VarIt = Variables.
find(
ID.lower());
3138 if (VarIt != Variables.
end()) {
3139 const Variable &Var = VarIt->getValue();
3144 Data = Var.TextValue;
3167bool MasmParser::parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated) {
3168 auto parseOp = [&]() ->
bool {
3170 if (checkForValidSection() || parseEscapedString(
Data))
3172 getStreamer().emitBytes(
Data);
3174 getStreamer().emitBytes(StringRef(
"\0", 1));
3178 if (parseMany(parseOp))
3179 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3183bool MasmParser::emitIntValue(
const MCExpr *
Value,
unsigned Size) {
3187 int64_t IntValue = MCE->getValue();
3189 return Error(MCE->getLoc(),
"out of range literal value");
3190 getStreamer().emitIntValue(IntValue,
Size);
3195 getStreamer().emitIntValue(0,
Size);
3203bool MasmParser::parseScalarInitializer(
unsigned Size,
3204 SmallVectorImpl<const MCExpr *> &Values,
3205 unsigned StringPadLength) {
3208 if (parseEscapedString(
Value))
3211 for (
const unsigned char CharVal :
Value)
3215 for (
size_t i =
Value.size(); i < StringPadLength; ++i)
3218 const MCExpr *
Value;
3219 if (parseExpression(
Value))
3222 getTok().getString().equals_insensitive(
"dup")) {
3227 "cannot repeat value a non-constant number of times");
3228 const int64_t Repetitions = MCE->
getValue();
3229 if (Repetitions < 0)
3231 "cannot repeat value a negative number of times");
3235 "parentheses required for 'dup' contents") ||
3236 parseScalarInstList(
Size, DuplicatedValues) || parseRParen())
3239 for (
int i = 0; i < Repetitions; ++i)
3248bool MasmParser::parseScalarInstList(
unsigned Size,
3249 SmallVectorImpl<const MCExpr *> &Values,
3251 while (getTok().
isNot(EndToken) &&
3254 parseScalarInitializer(
Size, Values);
3264bool MasmParser::emitIntegralValues(
unsigned Size,
unsigned *
Count) {
3266 if (checkForValidSection() || parseScalarInstList(
Size, Values))
3269 for (
const auto *
Value : Values) {
3273 *
Count = Values.size();
3278bool MasmParser::addIntegralField(StringRef Name,
unsigned Size) {
3279 StructInfo &
Struct = StructInProgress.
back();
3281 IntFieldInfo &IntInfo =
Field.Contents.IntInfo;
3285 if (parseScalarInstList(
Size, IntInfo.Values))
3288 Field.SizeOf =
Field.Type * IntInfo.Values.size();
3289 Field.LengthOf = IntInfo.Values.size();
3292 Struct.NextOffset = FieldEnd;
3300bool MasmParser::parseDirectiveValue(StringRef IDVal,
unsigned Size) {
3301 if (StructInProgress.
empty()) {
3303 if (emitIntegralValues(
Size))
3304 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3305 }
else if (addIntegralField(
"",
Size)) {
3306 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3314bool MasmParser::parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
3315 StringRef Name, SMLoc NameLoc) {
3316 if (StructInProgress.
empty()) {
3319 getStreamer().emitLabel(Sym);
3322 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3330 }
else if (addIntegralField(Name,
Size)) {
3331 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3337bool MasmParser::parseRealValue(
const fltSemantics &Semantics, APInt &Res) {
3343 SignLoc = getLexer().getLoc();
3347 SignLoc = getLexer().getLoc();
3352 return TokError(Lexer.getErr());
3355 return TokError(
"unexpected token in directive");
3359 StringRef IDVal = getTok().getString();
3368 return TokError(
"invalid floating point literal");
3372 unsigned SizeInBits =
Value.getSizeInBits(Semantics);
3373 if (SizeInBits != (IDVal.
size() << 2))
3374 return TokError(
"invalid floating point literal");
3379 Res = APInt(SizeInBits, IDVal, 16);
3381 return Warning(SignLoc,
"MASM-style hex floats ignore explicit sign");
3384 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3386 return TokError(
"invalid floating point literal");
3394 Res =
Value.bitcastToAPInt();
3399bool MasmParser::parseRealInstList(
const fltSemantics &Semantics,
3400 SmallVectorImpl<APInt> &ValuesAsInt,
3402 while (getTok().
isNot(EndToken) ||
3405 const AsmToken NextTok = peekTok();
3408 const MCExpr *
Value;
3414 "cannot repeat value a non-constant number of times");
3415 const int64_t Repetitions = MCE->
getValue();
3416 if (Repetitions < 0)
3418 "cannot repeat value a negative number of times");
3422 "parentheses required for 'dup' contents") ||
3423 parseRealInstList(Semantics, DuplicatedValues) || parseRParen())
3426 for (
int i = 0; i < Repetitions; ++i)
3427 ValuesAsInt.
append(DuplicatedValues.
begin(), DuplicatedValues.
end());
3430 if (parseRealValue(Semantics, AsInt))
3445bool MasmParser::emitRealValues(
const fltSemantics &Semantics,
3447 if (checkForValidSection())
3451 if (parseRealInstList(Semantics, ValuesAsInt))
3454 for (
const APInt &AsInt : ValuesAsInt) {
3455 getStreamer().emitIntValue(AsInt);
3458 *
Count = ValuesAsInt.size();
3463bool MasmParser::addRealField(StringRef Name,
const fltSemantics &Semantics,
3465 StructInfo &
Struct = StructInProgress.
back();
3467 RealFieldInfo &RealInfo =
Field.Contents.RealInfo;
3471 if (parseRealInstList(Semantics, RealInfo.AsIntValues))
3474 Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
3475 Field.LengthOf = RealInfo.AsIntValues.size();
3480 Struct.NextOffset = FieldEnd;
3488bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
3489 const fltSemantics &Semantics,
3491 if (StructInProgress.
empty()) {
3493 if (emitRealValues(Semantics))
3494 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3495 }
else if (addRealField(
"", Semantics,
Size)) {
3496 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3503bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
3504 const fltSemantics &Semantics,
3505 unsigned Size, StringRef Name,
3507 if (StructInProgress.
empty()) {
3510 getStreamer().emitLabel(Sym);
3512 if (emitRealValues(Semantics, &
Count))
3513 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3521 }
else if (addRealField(Name, Semantics,
Size)) {
3522 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3527bool MasmParser::parseOptionalAngleBracketOpen() {
3528 const AsmToken Tok = getTok();
3530 AngleBracketDepth++;
3534 AngleBracketDepth++;
3538 AngleBracketDepth++;
3545bool MasmParser::parseAngleBracketClose(
const Twine &Msg) {
3546 const AsmToken Tok = getTok();
3552 AngleBracketDepth--;
3556bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3557 const IntFieldInfo &Contents,
3558 FieldInitializer &Initializer) {
3559 SMLoc Loc = getTok().getLoc();
3564 return Error(Loc,
"Cannot initialize scalar field with array value");
3568 }
else if (parseOptionalAngleBracketOpen()) {
3570 return Error(Loc,
"Cannot initialize scalar field with array value");
3572 parseAngleBracketClose())
3574 }
else if (
Field.LengthOf > 1 &&
Field.Type > 1) {
3575 return Error(Loc,
"Cannot initialize array field with scalar value");
3576 }
else if (parseScalarInitializer(
Field.Type, Values,
3582 return Error(Loc,
"Initializer too long for field; expected at most " +
3583 std::to_string(
Field.LengthOf) +
" elements, got " +
3584 std::to_string(Values.
size()));
3587 Values.
append(Contents.Values.begin() + Values.
size(), Contents.Values.end());
3589 Initializer = FieldInitializer(std::move(Values));
3593bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3594 const RealFieldInfo &Contents,
3595 FieldInitializer &Initializer) {
3596 const fltSemantics *Semantics;
3597 switch (
Field.Type) {
3599 Semantics = &APFloat::IEEEsingle();
3602 Semantics = &APFloat::IEEEdouble();
3605 Semantics = &APFloat::x87DoubleExtended();
3611 SMLoc Loc = getTok().getLoc();
3615 if (
Field.LengthOf == 1)
3616 return Error(Loc,
"Cannot initialize scalar field with array value");
3620 }
else if (parseOptionalAngleBracketOpen()) {
3621 if (
Field.LengthOf == 1)
3622 return Error(Loc,
"Cannot initialize scalar field with array value");
3624 parseAngleBracketClose())
3626 }
else if (
Field.LengthOf > 1) {
3627 return Error(Loc,
"Cannot initialize array field with scalar value");
3630 if (parseRealValue(*Semantics, AsIntValues.
back()))
3634 if (AsIntValues.
size() >
Field.LengthOf) {
3635 return Error(Loc,
"Initializer too long for field; expected at most " +
3636 std::to_string(
Field.LengthOf) +
" elements, got " +
3637 std::to_string(AsIntValues.
size()));
3640 AsIntValues.
append(Contents.AsIntValues.begin() + AsIntValues.
size(),
3641 Contents.AsIntValues.end());
3643 Initializer = FieldInitializer(std::move(AsIntValues));
3647bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3648 const StructFieldInfo &Contents,
3649 FieldInitializer &Initializer) {
3650 SMLoc Loc = getTok().getLoc();
3652 std::vector<StructInitializer> Initializers;
3653 if (
Field.LengthOf > 1) {
3655 if (parseStructInstList(Contents.Structure, Initializers,
3659 }
else if (parseOptionalAngleBracketOpen()) {
3660 if (parseStructInstList(Contents.Structure, Initializers,
3662 parseAngleBracketClose())
3665 return Error(Loc,
"Cannot initialize array field with scalar value");
3668 Initializers.emplace_back();
3669 if (parseStructInitializer(Contents.Structure, Initializers.back()))
3673 if (Initializers.size() >
Field.LengthOf) {
3674 return Error(Loc,
"Initializer too long for field; expected at most " +
3675 std::to_string(
Field.LengthOf) +
" elements, got " +
3676 std::to_string(Initializers.size()));
3680 Initializers.size()));
3682 Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
3686bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3687 FieldInitializer &Initializer) {
3688 switch (
Field.Contents.FT) {
3690 return parseFieldInitializer(
Field,
Field.Contents.IntInfo, Initializer);
3692 return parseFieldInitializer(
Field,
Field.Contents.RealInfo, Initializer);
3694 return parseFieldInitializer(
Field,
Field.Contents.StructInfo, Initializer);
3699bool MasmParser::parseStructInitializer(
const StructInfo &Structure,
3700 StructInitializer &Initializer) {
3701 const AsmToken FirstToken = getTok();
3703 std::optional<AsmToken::TokenKind> EndToken;
3706 }
else if (parseOptionalAngleBracketOpen()) {
3708 AngleBracketDepth++;
3715 return Error(FirstToken.
getLoc(),
"Expected struct initializer");
3718 auto &FieldInitializers = Initializer.FieldInitializers;
3719 size_t FieldIndex = 0;
3722 while (getTok().
isNot(*EndToken) && FieldIndex < Structure.Fields.size()) {
3723 const FieldInfo &
Field = Structure.Fields[FieldIndex++];
3727 FieldInitializers.push_back(
Field.Contents);
3731 FieldInitializers.emplace_back(
Field.Contents.FT);
3732 if (parseFieldInitializer(
Field, FieldInitializers.back()))
3736 SMLoc CommaLoc = getTok().getLoc();
3739 if (FieldIndex == Structure.Fields.size())
3740 return Error(CommaLoc,
"'" + Structure.Name +
3741 "' initializer initializes too many fields");
3747 FieldInitializers.push_back(
Field.Contents);
3751 return parseAngleBracketClose();
3753 return parseToken(*EndToken);
3759bool MasmParser::parseStructInstList(
3760 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
3762 while (getTok().
isNot(EndToken) ||
3765 const AsmToken NextTok = peekTok();
3768 const MCExpr *
Value;
3774 "cannot repeat value a non-constant number of times");
3775 const int64_t Repetitions = MCE->
getValue();
3776 if (Repetitions < 0)
3778 "cannot repeat value a negative number of times");
3780 std::vector<StructInitializer> DuplicatedValues;
3782 "parentheses required for 'dup' contents") ||
3783 parseStructInstList(Structure, DuplicatedValues) || parseRParen())
3786 for (
int i = 0; i < Repetitions; ++i)
3789 Initializers.emplace_back();
3790 if (parseStructInitializer(Structure, Initializers.back()))
3803bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3804 const IntFieldInfo &Contents) {
3806 for (
const MCExpr *
Value : Contents.Values) {
3813bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3814 const RealFieldInfo &Contents) {
3815 for (
const APInt &AsInt : Contents.AsIntValues) {
3822bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3823 const StructFieldInfo &Contents) {
3824 for (
const auto &Initializer : Contents.Initializers) {
3826 for (
const auto &SubField : Contents.Structure.Fields) {
3827 getStreamer().emitZeros(SubField.Offset -
Offset);
3828 Offset = SubField.Offset + SubField.SizeOf;
3829 emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
3835bool MasmParser::emitFieldValue(
const FieldInfo &
Field) {
3836 switch (
Field.Contents.FT) {
3838 return emitFieldValue(
Field,
Field.Contents.IntInfo);
3840 return emitFieldValue(
Field,
Field.Contents.RealInfo);
3842 return emitFieldValue(
Field,
Field.Contents.StructInfo);
3847bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3848 const IntFieldInfo &Contents,
3849 const IntFieldInfo &Initializer) {
3850 for (
const auto &
Value : Initializer.Values) {
3855 for (
const auto &
Value :
3863bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3864 const RealFieldInfo &Contents,
3865 const RealFieldInfo &Initializer) {
3866 for (
const auto &AsInt : Initializer.AsIntValues) {
3871 for (
const auto &AsInt :
3879bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3880 const StructFieldInfo &Contents,
3881 const StructFieldInfo &Initializer) {
3882 for (
const auto &Init : Initializer.Initializers) {
3883 if (emitStructInitializer(Contents.Structure, Init))
3888 Initializer.Initializers.size())) {
3889 if (emitStructInitializer(Contents.Structure, Init))
3895bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3896 const FieldInitializer &Initializer) {
3897 switch (
Field.Contents.FT) {
3899 return emitFieldInitializer(
Field,
Field.Contents.IntInfo,
3900 Initializer.IntInfo);
3902 return emitFieldInitializer(
Field,
Field.Contents.RealInfo,
3903 Initializer.RealInfo);
3905 return emitFieldInitializer(
Field,
Field.Contents.StructInfo,
3906 Initializer.StructInfo);
3911bool MasmParser::emitStructInitializer(
const StructInfo &Structure,
3912 const StructInitializer &Initializer) {
3913 if (!Structure.Initializable)
3914 return Error(getLexer().getLoc(),
3915 "cannot initialize a value of type '" + Structure.Name +
3916 "'; 'org' was used in the type's declaration");
3918 for (
const auto &Init : Initializer.FieldInitializers) {
3919 const auto &
Field = Structure.Fields[
Index++];
3922 if (emitFieldInitializer(
Field, Init))
3927 Structure.Fields, Initializer.FieldInitializers.size())) {
3930 if (emitFieldValue(
Field))
3934 if (
Offset != Structure.Size)
3935 getStreamer().emitZeros(Structure.Size -
Offset);
3940bool MasmParser::emitStructValues(
const StructInfo &Structure,
3942 std::vector<StructInitializer> Initializers;
3943 if (parseStructInstList(Structure, Initializers))
3946 for (
const auto &Initializer : Initializers) {
3947 if (emitStructInitializer(Structure, Initializer))
3952 *
Count = Initializers.size();
3957bool MasmParser::addStructField(StringRef Name,
const StructInfo &Structure) {
3958 StructInfo &OwningStruct = StructInProgress.
back();
3960 OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
3961 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
3963 StructInfo.Structure = Structure;
3964 Field.Type = Structure.Size;
3966 if (parseStructInstList(Structure, StructInfo.Initializers))
3969 Field.LengthOf = StructInfo.Initializers.size();
3973 if (!OwningStruct.IsUnion) {
3974 OwningStruct.NextOffset = FieldEnd;
3976 OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd);
3984bool MasmParser::parseDirectiveStructValue(
const StructInfo &Structure,
3985 StringRef Directive, SMLoc DirLoc) {
3986 if (StructInProgress.
empty()) {
3987 if (emitStructValues(Structure))
3989 }
else if (addStructField(
"", Structure)) {
3990 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
3998bool MasmParser::parseDirectiveNamedStructValue(
const StructInfo &Structure,
3999 StringRef Directive,
4000 SMLoc DirLoc, StringRef Name) {
4001 if (StructInProgress.
empty()) {
4004 getStreamer().emitLabel(Sym);
4006 if (emitStructValues(Structure, &
Count))
4009 Type.Name = Structure.Name;
4011 Type.ElementSize = Structure.Size;
4014 }
else if (addStructField(Name, Structure)) {
4015 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4027bool MasmParser::parseDirectiveStruct(StringRef Directive,
4028 DirectiveKind DirKind, StringRef Name,
4032 AsmToken NextTok = getTok();
4033 int64_t AlignmentValue = 1;
4036 parseAbsoluteExpression(AlignmentValue)) {
4037 return addErrorSuffix(
" in alignment value for '" + Twine(Directive) +
4041 return Error(NextTok.
getLoc(),
"alignment must be a power of two; was " +
4042 std::to_string(AlignmentValue));
4048 QualifierLoc = getTok().getLoc();
4049 if (parseIdentifier(Qualifier))
4050 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4051 if (!
Qualifier.equals_insensitive(
"nonunique"))
4052 return Error(QualifierLoc,
"Unrecognized qualifier for '" +
4054 "' directive; expected none or NONUNIQUE");
4058 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4060 StructInProgress.
emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
4068bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
4069 DirectiveKind DirKind) {
4070 if (StructInProgress.
empty())
4071 return TokError(
"missing name in top-level '" + Twine(Directive) +
4076 Name = getTok().getIdentifier();
4080 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4084 StructInProgress.
reserve(StructInProgress.
size() + 1);
4085 StructInProgress.
emplace_back(Name, DirKind == DK_UNION,
4086 StructInProgress.
back().Alignment);
4090bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
4091 if (StructInProgress.
empty())
4092 return Error(NameLoc,
"ENDS directive without matching STRUC/STRUCT/UNION");
4093 if (StructInProgress.
size() > 1)
4094 return Error(NameLoc,
"unexpected name in nested ENDS directive");
4095 if (StructInProgress.
back().Name.compare_insensitive(Name))
4096 return Error(NameLoc,
"mismatched name in ENDS directive; expected '" +
4097 StructInProgress.
back().Name +
"'");
4098 StructInfo Structure = StructInProgress.
pop_back_val();
4102 Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
4103 Structs[
Name.lower()] = Structure;
4106 return addErrorSuffix(
" in ENDS directive");
4111bool MasmParser::parseDirectiveNestedEnds() {
4112 if (StructInProgress.
empty())
4113 return TokError(
"ENDS directive without matching STRUC/STRUCT/UNION");
4114 if (StructInProgress.
size() == 1)
4115 return TokError(
"missing name in top-level ENDS directive");
4118 return addErrorSuffix(
" in nested ENDS directive");
4120 StructInfo Structure = StructInProgress.
pop_back_val();
4122 Structure.Size =
llvm::alignTo(Structure.Size, Structure.Alignment);
4124 StructInfo &ParentStruct = StructInProgress.
back();
4125 if (Structure.Name.
empty()) {
4128 const size_t OldFields = ParentStruct.Fields.size();
4129 ParentStruct.Fields.insert(
4130 ParentStruct.Fields.end(),
4131 std::make_move_iterator(Structure.Fields.begin()),
4132 std::make_move_iterator(Structure.Fields.end()));
4133 for (
const auto &FieldByName : Structure.FieldsByName) {
4134 ParentStruct.FieldsByName[FieldByName.getKey()] =
4135 FieldByName.getValue() + OldFields;
4138 unsigned FirstFieldOffset = 0;
4139 if (!Structure.Fields.empty() && !ParentStruct.IsUnion) {
4141 ParentStruct.NextOffset,
4142 std::min(ParentStruct.Alignment, Structure.AlignmentSize));
4145 if (ParentStruct.IsUnion) {
4146 ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
4151 const unsigned StructureEnd = FirstFieldOffset + Structure.Size;
4152 if (!ParentStruct.IsUnion) {
4153 ParentStruct.NextOffset = StructureEnd;
4155 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4158 FieldInfo &
Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
4159 Structure.AlignmentSize);
4160 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
4161 Field.Type = Structure.Size;
4163 Field.SizeOf = Structure.Size;
4166 if (!ParentStruct.IsUnion) {
4167 ParentStruct.NextOffset = StructureEnd;
4169 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4171 StructInfo.Structure = Structure;
4172 StructInfo.Initializers.emplace_back();
4173 auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
4174 for (
const auto &SubField : Structure.Fields) {
4175 FieldInitializers.push_back(SubField.Contents);
4184bool MasmParser::parseDirectiveOrg() {
4186 SMLoc OffsetLoc = Lexer.getLoc();
4187 if (checkForValidSection() || parseExpression(
Offset))
4190 return addErrorSuffix(
" in 'org' directive");
4192 if (StructInProgress.
empty()) {
4194 if (checkForValidSection())
4195 return addErrorSuffix(
" in 'org' directive");
4197 getStreamer().emitValueToOffset(
Offset, 0, OffsetLoc);
4200 StructInfo &Structure = StructInProgress.
back();
4202 if (!
Offset->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr()))
4203 return Error(OffsetLoc,
4204 "expected absolute expression in 'org' directive");
4208 "expected non-negative value in struct's 'org' directive; was " +
4209 std::to_string(OffsetRes));
4210 Structure.NextOffset =
static_cast<unsigned>(OffsetRes);
4213 Structure.Initializable =
false;
4219bool MasmParser::emitAlignTo(int64_t Alignment) {
4220 if (StructInProgress.
empty()) {
4222 if (checkForValidSection())
4227 const MCSection *
Section = getStreamer().getCurrentSectionOnly();
4229 getStreamer().emitCodeAlignment(
Align(Alignment),
4230 &getTargetParser().getSTI(),
4234 getStreamer().emitValueToAlignment(
Align(Alignment), 0,
4240 StructInfo &Structure = StructInProgress.
back();
4241 Structure.NextOffset =
llvm::alignTo(Structure.NextOffset, Alignment);
4249bool MasmParser::parseDirectiveAlign() {
4250 SMLoc AlignmentLoc = getLexer().getLoc();
4256 "align directive with no operand is ignored") &&
4259 if (parseAbsoluteExpression(Alignment) || parseEOL())
4260 return addErrorSuffix(
" in align directive");
4263 bool ReturnVal =
false;
4270 ReturnVal |=
Error(AlignmentLoc,
"alignment must be a power of 2; was " +
4271 std::to_string(Alignment));
4273 if (emitAlignTo(Alignment))
4274 ReturnVal |= addErrorSuffix(
" in align directive");
4281bool MasmParser::parseDirectiveEven() {
4282 if (parseEOL() || emitAlignTo(2))
4283 return addErrorSuffix(
" in even directive");
4294bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
4298 return Error(Lexer.getLoc(),
4299 "Vararg parameter '" +
Parameters.back().Name +
4300 "' should be last in the list of parameters");
4304 return TokError(
"expected identifier in 'macro' directive");
4307 for (
const MCAsmMacroParameter& CurrParam : Parameters)
4308 if (CurrParam.Name.equals_insensitive(
Parameter.Name))
4309 return TokError(
"macro '" + Name +
"' has multiple parameters"
4319 ParamLoc = Lexer.getLoc();
4320 if (parseMacroArgument(
nullptr,
Parameter.Value))
4326 QualLoc = Lexer.getLoc();
4327 if (parseIdentifier(Qualifier))
4328 return Error(QualLoc,
"missing parameter qualifier for "
4330 Parameter.Name +
"' in macro '" + Name +
4333 if (
Qualifier.equals_insensitive(
"req"))
4335 else if (
Qualifier.equals_insensitive(
"vararg"))
4338 return Error(QualLoc,
4339 Qualifier +
" is not a valid parameter qualifier for '" +
4340 Parameter.Name +
"' in macro '" + Name +
"'");
4353 std::vector<std::string>
Locals;
4355 getTok().getIdentifier().equals_insensitive(
"local")) {
4360 if (parseIdentifier(
ID))
4372 AsmToken EndToken, StartToken = getTok();
4373 unsigned MacroDepth = 0;
4374 bool IsMacroFunction =
false;
4384 return Error(NameLoc,
"no matching 'endm' in definition");
4389 if (getTok().getIdentifier().equals_insensitive(
"endm")) {
4390 if (MacroDepth == 0) {
4391 EndToken = getTok();
4394 return TokError(
"unexpected token in '" + EndToken.
getIdentifier() +
4401 }
else if (getTok().getIdentifier().equals_insensitive(
"exitm")) {
4403 IsMacroFunction =
true;
4405 }
else if (isMacroLikeDirective()) {
4413 eatToEndOfStatement();
4417 return Error(NameLoc,
"macro '" + Name +
"' is already defined");
4422 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4423 MCAsmMacro
Macro(Name, Body, std::move(Parameters), std::move(Locals),
4433bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
4434 StringRef Directive,
4435 std::string &
Value) {
4436 SMLoc EndLoc = getTok().getLoc();
4438 return Error(EndLoc,
4439 "unable to parse text item in '" + Directive +
"' directive");
4440 eatToEndOfStatement();
4442 if (!isInsideMacroInstantiation())
4443 return TokError(
"unexpected '" + Directive +
"' in file, "
4444 "no current macro definition");
4447 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4448 TheCondState = TheCondStack.back();
4449 TheCondStack.pop_back();
4458bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
4460 return TokError(
"unexpected token in '" + Directive +
"' directive");
4464 if (isInsideMacroInstantiation()) {
4471 return TokError(
"unexpected '" + Directive +
"' in file, "
4472 "no current macro definition");
4477bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4481 if (parseTokenLoc(NameLoc) ||
4482 check(parseIdentifier(Name), NameLoc,
4483 "expected identifier in 'purge' directive"))
4487 <<
"Un-defining macro: " << Name <<
"\n");
4489 return Error(NameLoc,
"macro '" + Name +
"' is not defined");
4500bool MasmParser::parseDirectiveExtern() {
4502 auto parseOp = [&]() ->
bool {
4504 SMLoc NameLoc = getTok().getLoc();
4506 return Error(NameLoc,
"expected name");
4511 SMLoc TypeLoc = getTok().getLoc();
4512 if (parseIdentifier(TypeName))
4513 return Error(TypeLoc,
"expected type");
4514 if (!
TypeName.equals_insensitive(
"proc")) {
4516 if (lookUpType(TypeName,
Type))
4517 return Error(TypeLoc,
"unrecognized type");
4521 static_cast<MCSymbolCOFF *
>(Sym)->setExternal(
true);
4522 getStreamer().emitSymbolAttribute(Sym,
MCSA_Extern);
4527 if (parseMany(parseOp))
4528 return addErrorSuffix(
" in directive 'extern'");
4534bool MasmParser::parseDirectiveSymbolAttribute(
MCSymbolAttr Attr) {
4535 auto parseOp = [&]() ->
bool {
4536 SMLoc Loc = getTok().getLoc();
4539 return Error(Loc,
"expected identifier");
4543 return Error(Loc,
"non-local symbol required");
4545 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
4546 return Error(Loc,
"unable to emit symbol attribute");
4550 if (parseMany(parseOp))
4551 return addErrorSuffix(
" in directive");
4557bool MasmParser::parseDirectiveComm(
bool IsLocal) {
4558 if (checkForValidSection())
4561 SMLoc IDLoc = getLexer().getLoc();
4564 return TokError(
"expected identifier in directive");
4567 return TokError(
"unexpected token in directive");
4571 SMLoc SizeLoc = getLexer().getLoc();
4572 if (parseAbsoluteExpression(
Size))
4575 int64_t Pow2Alignment = 0;
4576 SMLoc Pow2AlignmentLoc;
4579 Pow2AlignmentLoc = getLexer().getLoc();
4580 if (parseAbsoluteExpression(Pow2Alignment))
4585 return Error(Pow2AlignmentLoc,
"alignment not supported on this target");
4588 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
4591 return Error(Pow2AlignmentLoc,
"alignment must be a power of 2");
4592 Pow2Alignment =
Log2_64(Pow2Alignment);
4602 return Error(SizeLoc,
"invalid '.comm' or '.lcomm' directive size, can't "
4603 "be less than zero");
4608 if (Pow2Alignment < 0)
4609 return Error(Pow2AlignmentLoc,
"invalid '.comm' or '.lcomm' directive "
4610 "alignment, can't be less than zero");
4614 return Error(IDLoc,
"invalid symbol redefinition");
4618 getStreamer().emitLocalCommonSymbol(Sym,
Size,
4619 Align(1ULL << Pow2Alignment));
4623 getStreamer().emitCommonSymbol(Sym,
Size,
Align(1ULL << Pow2Alignment));
4631bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
4633 size_t DelimiterEnd = FirstLine.find_first_of(
"\b\t\v\f\r\x1A ");
4634 assert(DelimiterEnd != std::string::npos);
4635 StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd);
4636 if (Delimiter.
empty())
4637 return Error(DirectiveLoc,
"no delimiter in 'comment' directive");
4640 return Error(DirectiveLoc,
"unmatched delimiter in 'comment' directive");
4650bool MasmParser::parseDirectiveInclude() {
4653 SMLoc IncludeLoc = getTok().getLoc();
4655 if (parseAngleBracketString(Filename))
4657 if (check(
Filename.empty(),
"missing filename in 'include' directive") ||
4659 "unexpected token in 'include' directive") ||
4662 check(enterIncludeFile(Filename), IncludeLoc,
4663 "Could not find include file '" + Filename +
"'"))
4671bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
4672 TheCondStack.push_back(TheCondState);
4674 if (TheCondState.
Ignore) {
4675 eatToEndOfStatement();
4678 if (parseAbsoluteExpression(ExprValue) || parseEOL())
4687 ExprValue = ExprValue == 0;
4691 TheCondState.
CondMet = ExprValue;
4700bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4701 TheCondStack.push_back(TheCondState);
4704 if (TheCondState.
Ignore) {
4705 eatToEndOfStatement();
4708 if (parseTextItem(Str))
4709 return TokError(
"expected text item parameter for 'ifb' directive");
4714 TheCondState.
CondMet = ExpectBlank == Str.empty();
4723bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4724 bool CaseInsensitive) {
4725 std::string String1, String2;
4727 if (parseTextItem(String1)) {
4729 return TokError(
"expected text item parameter for 'ifidn' directive");
4730 return TokError(
"expected text item parameter for 'ifdif' directive");
4736 "expected comma after first string for 'ifidn' directive");
4737 return TokError(
"expected comma after first string for 'ifdif' directive");
4741 if (parseTextItem(String2)) {
4743 return TokError(
"expected text item parameter for 'ifidn' directive");
4744 return TokError(
"expected text item parameter for 'ifdif' directive");
4747 TheCondStack.push_back(TheCondState);
4749 if (CaseInsensitive)
4751 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4753 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4762bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined) {
4763 TheCondStack.push_back(TheCondState);
4766 if (TheCondState.
Ignore) {
4767 eatToEndOfStatement();
4769 bool is_defined =
false;
4771 SMLoc StartLoc, EndLoc;
4773 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4776 if (check(parseIdentifier(Name),
"expected identifier after 'ifdef'") ||
4780 if (BuiltinSymbolMap.contains(
Name.lower())) {
4790 TheCondState.
CondMet = (is_defined == expect_defined);
4799bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
4800 DirectiveKind DirKind) {
4803 return Error(DirectiveLoc,
"Encountered a .elseif that doesn't follow an"
4804 " .if or an .elseif");
4807 bool LastIgnoreState =
false;
4808 if (!TheCondStack.empty())
4809 LastIgnoreState = TheCondStack.back().Ignore;
4810 if (LastIgnoreState || TheCondState.
CondMet) {
4811 TheCondState.
Ignore =
true;
4812 eatToEndOfStatement();
4815 if (parseAbsoluteExpression(ExprValue))
4827 ExprValue = ExprValue == 0;
4831 TheCondState.
CondMet = ExprValue;
4840bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4843 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4844 " if or an elseif");
4847 bool LastIgnoreState =
false;
4848 if (!TheCondStack.empty())
4849 LastIgnoreState = TheCondStack.back().Ignore;
4850 if (LastIgnoreState || TheCondState.
CondMet) {
4851 TheCondState.
Ignore =
true;
4852 eatToEndOfStatement();
4855 if (parseTextItem(Str)) {
4857 return TokError(
"expected text item parameter for 'elseifb' directive");
4858 return TokError(
"expected text item parameter for 'elseifnb' directive");
4864 TheCondState.
CondMet = ExpectBlank == Str.empty();
4874bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
4875 bool expect_defined) {
4878 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4879 " if or an elseif");
4882 bool LastIgnoreState =
false;
4883 if (!TheCondStack.empty())
4884 LastIgnoreState = TheCondStack.back().Ignore;
4885 if (LastIgnoreState || TheCondState.
CondMet) {
4886 TheCondState.
Ignore =
true;
4887 eatToEndOfStatement();
4889 bool is_defined =
false;
4891 SMLoc StartLoc, EndLoc;
4893 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4896 if (check(parseIdentifier(Name),
4897 "expected identifier after 'elseifdef'") ||
4901 if (BuiltinSymbolMap.contains(
Name.lower())) {
4911 TheCondState.
CondMet = (is_defined == expect_defined);
4920bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4921 bool CaseInsensitive) {
4924 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4925 " if or an elseif");
4928 bool LastIgnoreState =
false;
4929 if (!TheCondStack.empty())
4930 LastIgnoreState = TheCondStack.back().Ignore;
4931 if (LastIgnoreState || TheCondState.
CondMet) {
4932 TheCondState.
Ignore =
true;
4933 eatToEndOfStatement();
4935 std::string String1, String2;
4937 if (parseTextItem(String1)) {
4940 "expected text item parameter for 'elseifidn' directive");
4941 return TokError(
"expected text item parameter for 'elseifdif' directive");
4947 "expected comma after first string for 'elseifidn' directive");
4949 "expected comma after first string for 'elseifdif' directive");
4953 if (parseTextItem(String2)) {
4956 "expected text item parameter for 'elseifidn' directive");
4957 return TokError(
"expected text item parameter for 'elseifdif' directive");
4960 if (CaseInsensitive)
4962 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4964 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4973bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
4979 return Error(DirectiveLoc,
"Encountered an else that doesn't follow an if"
4982 bool LastIgnoreState =
false;
4983 if (!TheCondStack.empty())
4984 LastIgnoreState = TheCondStack.back().Ignore;
4985 if (LastIgnoreState || TheCondState.
CondMet)
4986 TheCondState.
Ignore =
true;
4988 TheCondState.
Ignore =
false;
4995bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5007bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
5008 if (!TheCondStack.empty()) {
5009 if (TheCondStack.back().Ignore) {
5010 eatToEndOfStatement();
5015 std::string Message =
".err directive invoked in source file";
5020 return Error(DirectiveLoc, Message);
5025bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
5026 if (!TheCondStack.empty()) {
5027 if (TheCondStack.back().Ignore) {
5028 eatToEndOfStatement();
5034 if (parseTextItem(Text))
5035 return Error(getTok().getLoc(),
"missing text item in '.errb' directive");
5037 std::string Message =
".errb directive invoked in source file";
5040 return addErrorSuffix(
" in '.errb' directive");
5045 if (
Text.empty() == ExpectBlank)
5046 return Error(DirectiveLoc, Message);
5052bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
5053 bool ExpectDefined) {
5054 if (!TheCondStack.empty()) {
5055 if (TheCondStack.back().Ignore) {
5056 eatToEndOfStatement();
5061 bool IsDefined =
false;
5063 SMLoc StartLoc, EndLoc;
5065 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
5068 if (check(parseIdentifier(Name),
"expected identifier after '.errdef'"))
5071 if (BuiltinSymbolMap.contains(
Name.lower())) {
5081 std::string Message =
".errdef directive invoked in source file";
5084 return addErrorSuffix(
" in '.errdef' directive");
5089 if (IsDefined == ExpectDefined)
5090 return Error(DirectiveLoc, Message);
5096bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
5097 bool CaseInsensitive) {
5098 if (!TheCondStack.empty()) {
5099 if (TheCondStack.back().Ignore) {
5100 eatToEndOfStatement();
5105 std::string String1, String2;
5107 if (parseTextItem(String1)) {
5109 return TokError(
"expected string parameter for '.erridn' directive");
5110 return TokError(
"expected string parameter for '.errdif' directive");
5116 "expected comma after first string for '.erridn' directive");
5118 "expected comma after first string for '.errdif' directive");
5122 if (parseTextItem(String2)) {
5124 return TokError(
"expected string parameter for '.erridn' directive");
5125 return TokError(
"expected string parameter for '.errdif' directive");
5128 std::string Message;
5130 Message =
".erridn directive invoked in source file";
5132 Message =
".errdif directive invoked in source file";
5135 return addErrorSuffix(
" in '.erridn' directive");
5140 if (CaseInsensitive)
5142 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
5144 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
5147 if ((CaseInsensitive &&
5148 ExpectEqual == StringRef(String1).equals_insensitive(String2)) ||
5149 (ExpectEqual == (String1 == String2)))
5150 return Error(DirectiveLoc, Message);
5156bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero) {
5157 if (!TheCondStack.empty()) {
5158 if (TheCondStack.back().Ignore) {
5159 eatToEndOfStatement();
5165 if (parseAbsoluteExpression(ExprValue))
5166 return addErrorSuffix(
" in '.erre' directive");
5168 std::string Message =
".erre directive invoked in source file";
5171 return addErrorSuffix(
" in '.erre' directive");
5176 if ((ExprValue == 0) == ExpectZero)
5177 return Error(DirectiveLoc, Message);
5183bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5188 return Error(DirectiveLoc,
"Encountered a .endif that doesn't follow "
5190 if (!TheCondStack.empty()) {
5191 TheCondState = TheCondStack.back();
5192 TheCondStack.pop_back();
5198void MasmParser::initializeDirectiveKindMap() {
5199 DirectiveKindMap[
"="] = DK_ASSIGN;
5200 DirectiveKindMap[
"equ"] = DK_EQU;
5201 DirectiveKindMap[
"textequ"] = DK_TEXTEQU;
5205 DirectiveKindMap[
"byte"] = DK_BYTE;
5206 DirectiveKindMap[
"sbyte"] = DK_SBYTE;
5207 DirectiveKindMap[
"word"] = DK_WORD;
5208 DirectiveKindMap[
"sword"] = DK_SWORD;
5209 DirectiveKindMap[
"dword"] = DK_DWORD;
5210 DirectiveKindMap[
"sdword"] = DK_SDWORD;
5211 DirectiveKindMap[
"fword"] = DK_FWORD;
5212 DirectiveKindMap[
"qword"] = DK_QWORD;
5213 DirectiveKindMap[
"sqword"] = DK_SQWORD;
5214 DirectiveKindMap[
"real4"] = DK_REAL4;
5215 DirectiveKindMap[
"real8"] = DK_REAL8;
5216 DirectiveKindMap[
"real10"] = DK_REAL10;
5217 DirectiveKindMap[
"align"] = DK_ALIGN;
5218 DirectiveKindMap[
"even"] = DK_EVEN;
5219 DirectiveKindMap[
"org"] = DK_ORG;
5220 DirectiveKindMap[
"extern"] = DK_EXTERN;
5221 DirectiveKindMap[
"extrn"] = DK_EXTERN;
5222 DirectiveKindMap[
"public"] = DK_PUBLIC;
5224 DirectiveKindMap[
"comment"] = DK_COMMENT;
5225 DirectiveKindMap[
"include"] = DK_INCLUDE;
5226 DirectiveKindMap[
"repeat"] = DK_REPEAT;
5227 DirectiveKindMap[
"rept"] = DK_REPEAT;
5228 DirectiveKindMap[
"while"] = DK_WHILE;
5229 DirectiveKindMap[
"for"] = DK_FOR;
5230 DirectiveKindMap[
"irp"] = DK_FOR;
5231 DirectiveKindMap[
"forc"] = DK_FORC;
5232 DirectiveKindMap[
"irpc"] = DK_FORC;
5233 DirectiveKindMap[
"if"] = DK_IF;
5234 DirectiveKindMap[
"ife"] = DK_IFE;
5235 DirectiveKindMap[
"ifb"] = DK_IFB;
5236 DirectiveKindMap[
"ifnb"] = DK_IFNB;
5237 DirectiveKindMap[
"ifdef"] = DK_IFDEF;
5238 DirectiveKindMap[
"ifndef"] = DK_IFNDEF;
5239 DirectiveKindMap[
"ifdif"] = DK_IFDIF;
5240 DirectiveKindMap[
"ifdifi"] = DK_IFDIFI;
5241 DirectiveKindMap[
"ifidn"] = DK_IFIDN;
5242 DirectiveKindMap[
"ifidni"] = DK_IFIDNI;
5243 DirectiveKindMap[
"elseif"] = DK_ELSEIF;
5244 DirectiveKindMap[
"elseifdef"] = DK_ELSEIFDEF;
5245 DirectiveKindMap[
"elseifndef"] = DK_ELSEIFNDEF;
5246 DirectiveKindMap[
"elseifdif"] = DK_ELSEIFDIF;
5247 DirectiveKindMap[
"elseifidn"] = DK_ELSEIFIDN;
5248 DirectiveKindMap[
"else"] = DK_ELSE;
5249 DirectiveKindMap[
"end"] = DK_END;
5250 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[
".savereg"] = DK_SAVEREG;
5308 DirectiveKindMap[
".savexmm128"] = DK_SAVEXMM128;
5309 DirectiveKindMap[
".setframe"] = DK_SETFRAME;
5310 DirectiveKindMap[
".radix"] = DK_RADIX;
5311 DirectiveKindMap[
"db"] = DK_DB;
5312 DirectiveKindMap[
"dd"] = DK_DD;
5313 DirectiveKindMap[
"df"] = DK_DF;
5314 DirectiveKindMap[
"dq"] = DK_DQ;
5315 DirectiveKindMap[
"dw"] = DK_DW;
5316 DirectiveKindMap[
"echo"] = DK_ECHO;
5317 DirectiveKindMap[
"struc"] = DK_STRUCT;
5318 DirectiveKindMap[
"struct"] = DK_STRUCT;
5319 DirectiveKindMap[
"union"] = DK_UNION;
5320 DirectiveKindMap[
"ends"] = DK_ENDS;
5323bool MasmParser::isMacroLikeDirective() {
5325 bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier())
5326 .CasesLower({
"repeat",
"rept"},
true)
5327 .CaseLower(
"while",
true)
5328 .CasesLower({
"for",
"irp"},
true)
5329 .CasesLower({
"forc",
"irpc"},
true)
5335 peekTok().getIdentifier().equals_insensitive(
"macro"))
5341MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5342 AsmToken EndToken, StartToken = getTok();
5344 unsigned NestLevel = 0;
5348 printError(DirectiveLoc,
"no matching 'endm' in definition");
5352 if (isMacroLikeDirective())
5357 getTok().getIdentifier().equals_insensitive(
"endm")) {
5358 if (NestLevel == 0) {
5359 EndToken = getTok();
5362 printError(getTok().getLoc(),
"unexpected token in 'endm' directive");
5371 eatToEndOfStatement();
5376 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5380 return &MacroLikeBodies.back();
5383bool MasmParser::expandStatement(SMLoc Loc) {
5385 SMLoc EndLoc = getTok().getLoc();
5390 StringMap<std::string> BuiltinValues;
5391 for (
const auto &S : BuiltinSymbolMap) {
5392 const BuiltinSymbol &Sym = S.getValue();
5393 if (std::optional<std::string> Text = evaluateBuiltinTextMacro(Sym, Loc)) {
5394 BuiltinValues[S.getKey().lower()] = std::move(*Text);
5397 for (
const auto &
B : BuiltinValues) {
5398 MCAsmMacroParameter
P;
5399 MCAsmMacroArgument
A;
5400 P.Name =
B.getKey();
5408 for (
const auto &V : Variables) {
5411 MCAsmMacroParameter
P;
5412 MCAsmMacroArgument
A;
5421 MacroLikeBodies.emplace_back(StringRef(), Body, Parameters);
5422 MCAsmMacro
M = MacroLikeBodies.back();
5425 SmallString<80> Buf;
5426 raw_svector_ostream OS(Buf);
5427 if (expandMacro(OS,
M.Body,
M.Parameters,
Arguments,
M.Locals, EndLoc))
5429 std::unique_ptr<MemoryBuffer>
Expansion =
5435 EndStatementAtEOFStack.push_back(
false);
5440void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5441 raw_svector_ostream &OS) {
5442 instantiateMacroLikeBody(M, DirectiveLoc, getTok().getLoc(), OS);
5444void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5446 raw_svector_ostream &OS) {
5449 std::unique_ptr<MemoryBuffer> Instantiation =
5454 MacroInstantiation *
MI =
new MacroInstantiation{DirectiveLoc, CurBuffer,
5455 ExitLoc, TheCondStack.size()};
5456 ActiveMacros.push_back(
MI);
5461 EndStatementAtEOFStack.push_back(
true);
5469bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) {
5470 const MCExpr *CountExpr;
5471 SMLoc CountLoc = getTok().getLoc();
5472 if (parseExpression(CountExpr))
5476 if (!CountExpr->evaluateAsAbsolute(
Count, getStreamer().getAssemblerPtr())) {
5477 return Error(CountLoc,
"unexpected token in '" + Dir +
"' directive");
5480 if (check(
Count < 0, CountLoc,
"Count is negative") || parseEOL())
5484 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5490 SmallString<256> Buf;
5491 raw_svector_ostream OS(Buf);
5493 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5496 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5505bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) {
5506 const MCExpr *CondExpr;
5507 SMLoc CondLoc = getTok().getLoc();
5508 if (parseExpression(CondExpr))
5512 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5518 SmallString<256> Buf;
5519 raw_svector_ostream OS(Buf);
5521 if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr()))
5522 return Error(CondLoc,
"expected absolute expression in 'while' directive");
5526 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5528 instantiateMacroLikeBody(M, DirectiveLoc, DirectiveLoc, OS);
5538bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
5540 MCAsmMacroArguments
A;
5541 if (check(parseIdentifier(
Parameter.Name),
5542 "expected identifier in '" + Dir +
"' directive"))
5551 ParamLoc = Lexer.getLoc();
5552 if (parseMacroArgument(
nullptr,
Parameter.Value))
5558 QualLoc = Lexer.getLoc();
5559 if (parseIdentifier(Qualifier))
5560 return Error(QualLoc,
"missing parameter qualifier for "
5565 if (
Qualifier.equals_insensitive(
"req"))
5568 return Error(QualLoc,
5569 Qualifier +
" is not a valid parameter qualifier for '" +
5570 Parameter.Name +
"' in '" + Dir +
"' directive");
5575 "expected comma in '" + Dir +
"' directive") ||
5577 "values in '" + Dir +
5578 "' directive must be enclosed in angle brackets"))
5584 return addErrorSuffix(
" in arguments for '" + Dir +
"' directive");
5593 "values in '" + Dir +
5594 "' directive must be enclosed in angle brackets") ||
5599 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5605 SmallString<256> Buf;
5606 raw_svector_ostream OS(Buf);
5608 for (
const MCAsmMacroArgument &Arg :
A) {
5609 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5613 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5622bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
5626 if (check(parseIdentifier(
Parameter.Name),
5627 "expected identifier in '" + Directive +
"' directive") ||
5629 "expected comma in '" + Directive +
"' directive"))
5631 if (parseAngleBracketString(Argument)) {
5639 for (; End <
Argument.size(); ++End) {
5649 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5655 SmallString<256> Buf;
5656 raw_svector_ostream OS(Buf);
5658 StringRef Values(Argument);
5659 for (std::size_t
I = 0, End = Values.
size();
I != End; ++
I) {
5660 MCAsmMacroArgument Arg;
5663 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5667 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5672bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &
Info,
5674 const MCExpr *
Value;
5675 SMLoc ExprLoc = getLexer().getLoc();
5676 if (parseExpression(
Value))
5680 return Error(ExprLoc,
"unexpected expression in _emit");
5681 uint64_t IntValue = MCE->
getValue();
5683 return Error(ExprLoc,
"literal value out of range for directive");
5689bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &
Info) {
5690 const MCExpr *
Value;
5691 SMLoc ExprLoc = getLexer().getLoc();
5692 if (parseExpression(
Value))
5696 return Error(ExprLoc,
"unexpected expression in align");
5697 uint64_t IntValue = MCE->
getValue();
5699 return Error(ExprLoc,
"literal value not a power of two greater then zero");
5705bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
5706 const SMLoc Loc = getLexer().getLoc();
5708 StringRef RadixString = StringRef(RadixStringRaw).trim();
5712 "radix must be a decimal number in the range 2 to 16; was " +
5715 if (Radix < 2 || Radix > 16)
5716 return Error(Loc,
"radix must be in the range 2 to 16; was " +
5717 std::to_string(Radix));
5718 getLexer().setMasmDefaultRadix(Radix);
5724bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) {
5727 if (!StringRef(Message).ends_with(
"\n"))
5755bool MasmParser::defineMacro(StringRef Name, StringRef
Value) {
5757 if (Var.Name.empty()) {
5759 }
else if (Var.Redefinable == Variable::NOT_REDEFINABLE) {
5760 return Error(SMLoc(),
"invalid variable redefinition");
5761 }
else if (Var.Redefinable == Variable::WARN_ON_REDEFINITION &&
5762 Warning(SMLoc(),
"redefining '" + Name +
5763 "', already defined on the command line")) {
5766 Var.Redefinable = Variable::WARN_ON_REDEFINITION;
5768 Var.TextValue =
Value.str();
5772bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &
Info)
const {
5773 const std::pair<StringRef, StringRef> BaseMember =
Name.split(
'.');
5774 const StringRef
Base = BaseMember.first,
Member = BaseMember.second;
5775 return lookUpField(
Base, Member,
Info);
5778bool MasmParser::lookUpField(StringRef
Base, StringRef Member,
5779 AsmFieldInfo &
Info)
const {
5783 AsmFieldInfo BaseInfo;
5784 if (
Base.contains(
'.') && !lookUpField(
Base, BaseInfo))
5787 auto StructIt = Structs.
find(
Base.lower());
5788 auto TypeIt = KnownType.
find(
Base.lower());
5789 if (TypeIt != KnownType.
end()) {
5790 StructIt = Structs.
find(TypeIt->second.Name.lower());
5792 if (StructIt != Structs.
end())
5793 return lookUpField(StructIt->second, Member,
Info);
5798bool MasmParser::lookUpField(
const StructInfo &Structure, StringRef Member,
5799 AsmFieldInfo &
Info)
const {
5801 Info.Type.Name = Structure.Name;
5802 Info.Type.Size = Structure.Size;
5803 Info.Type.ElementSize = Structure.Size;
5804 Info.Type.Length = 1;
5808 std::pair<StringRef, StringRef>
Split =
Member.split(
'.');
5809 const StringRef FieldName =
Split.first, FieldMember =
Split.second;
5811 auto StructIt = Structs.
find(FieldName.
lower());
5812 if (StructIt != Structs.
end())
5813 return lookUpField(StructIt->second, FieldMember,
Info);
5815 auto FieldIt = Structure.FieldsByName.
find(FieldName.
lower());
5816 if (FieldIt == Structure.FieldsByName.
end())
5819 const FieldInfo &
Field = Structure.Fields[FieldIt->second];
5820 if (FieldMember.empty()) {
5825 if (
Field.Contents.FT == FT_STRUCT)
5826 Info.Type.Name =
Field.Contents.StructInfo.Structure.Name;
5828 Info.Type.Name =
"";
5832 if (
Field.Contents.FT != FT_STRUCT)
5834 const StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
5836 if (lookUpField(StructInfo.Structure, FieldMember,
Info))
5843bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &
Info)
const {
5844 unsigned Size = StringSwitch<unsigned>(Name)
5845 .CasesLower({
"byte",
"db",
"sbyte"}, 1)
5846 .CasesLower({
"word",
"dw",
"sword"}, 2)
5847 .CasesLower({
"dword",
"dd",
"sdword"}, 4)
5848 .CasesLower({
"fword",
"df"}, 6)
5849 .CasesLower({
"qword",
"dq",
"sqword"}, 8)
5850 .CaseLower(
"real4", 4)
5851 .CaseLower(
"real8", 8)
5852 .CaseLower(
"real10", 10)
5862 auto StructIt = Structs.
find(
Name.lower());
5863 if (StructIt != Structs.
end()) {
5864 const StructInfo &Structure = StructIt->second;
5866 Info.ElementSize = Structure.Size;
5868 Info.Size = Structure.Size;
5875bool MasmParser::parseMSInlineAsm(
5876 std::string &AsmString,
unsigned &NumOutputs,
unsigned &NumInputs,
5877 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5878 SmallVectorImpl<std::string> &Constraints,
5879 SmallVectorImpl<std::string> &Clobbers,
const MCInstrInfo *MII,
5880 MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
5881 SmallVector<void *, 4> InputDecls;
5882 SmallVector<void *, 4> OutputDecls;
5885 SmallVector<std::string, 4> InputConstraints;
5886 SmallVector<std::string, 4> OutputConstraints;
5895 unsigned InputIdx = 0;
5896 unsigned OutputIdx = 0;
5899 if (parseCurlyBlockScope(AsmStrRewrites))
5902 ParseStatementInfo
Info(&AsmStrRewrites);
5903 bool StatementErr = parseStatement(
Info, &SI);
5905 if (StatementErr ||
Info.ParseError) {
5907 printPendingErrors();
5912 assert(!hasPendingError() &&
"unexpected error from parseStatement");
5914 if (
Info.Opcode == ~0U)
5920 for (
unsigned i = 1, e =
Info.ParsedOperands.size(); i != e; ++i) {
5921 MCParsedAsmOperand &Operand = *
Info.ParsedOperands[i];
5925 !getTargetParser().omitRegisterFromClobberLists(Operand.
getReg())) {
5926 unsigned NumDefs =
Desc.getNumDefs();
5935 if (SymName.
empty())
5943 if (Operand.
isImm()) {
5951 bool isOutput = (i == 1) &&
Desc.mayStore();
5957 OutputConstraints.
push_back((
"=" + Constraint).str());
5963 if (
Desc.operands()[i - 1].isBranchTarget())
5975 NumOutputs = OutputDecls.
size();
5976 NumInputs = InputDecls.
size();
5981 Clobbers.
assign(ClobberRegs.
size(), std::string());
5982 for (
unsigned I = 0,
E = ClobberRegs.
size();
I !=
E; ++
I) {
5983 raw_string_ostream OS(Clobbers[
I]);
5988 if (NumOutputs || NumInputs) {
5989 unsigned NumExprs = NumOutputs + NumInputs;
5990 OpDecls.resize(NumExprs);
5991 Constraints.
resize(NumExprs);
5992 for (
unsigned i = 0; i < NumOutputs; ++i) {
5993 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
5994 Constraints[i] = OutputConstraints[i];
5996 for (
unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++
j) {
5997 OpDecls[
j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
5998 Constraints[
j] = InputConstraints[i];
6003 std::string AsmStringIR;
6004 raw_string_ostream OS(AsmStringIR);
6005 StringRef ASMString =
6007 const char *AsmStart = ASMString.
begin();
6008 const char *AsmEnd = ASMString.
end();
6010 for (
auto I = AsmStrRewrites.
begin(),
E = AsmStrRewrites.
end();
I !=
E; ++
I) {
6011 const AsmRewrite &AR = *
I;
6018 assert(Loc >= AsmStart &&
"Expected Loc to be at or after Start!");
6021 if (
unsigned Len = Loc - AsmStart)
6022 OS << StringRef(AsmStart, Len);
6026 AsmStart = Loc + AR.
Len;
6030 unsigned AdditionalSkip = 0;
6052 size_t OffsetLen = OffsetName.
size();
6053 auto rewrite_it = std::find_if(
6054 I, AsmStrRewrites.
end(), [&](
const AsmRewrite &FusingAR) {
6055 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6056 (FusingAR.Kind == AOK_Input ||
6057 FusingAR.Kind == AOK_CallInput);
6059 if (rewrite_it == AsmStrRewrites.
end()) {
6060 OS <<
"offset " << OffsetName;
6062 OS <<
"${" << InputIdx++ <<
":P}";
6063 rewrite_it->Done =
true;
6065 OS <<
'$' << InputIdx++;
6066 rewrite_it->Done =
true;
6078 OS <<
'$' << InputIdx++;
6081 OS <<
"${" << InputIdx++ <<
":P}";
6084 OS <<
'$' << OutputIdx++;
6089 case 8: OS <<
"byte ptr ";
break;
6090 case 16: OS <<
"word ptr ";
break;
6091 case 32: OS <<
"dword ptr ";
break;
6092 case 64: OS <<
"qword ptr ";
break;
6093 case 80: OS <<
"xword ptr ";
break;
6094 case 128: OS <<
"xmmword ptr ";
break;
6095 case 256: OS <<
"ymmword ptr ";
break;
6105 if (
getContext().getAsmInfo()->getAlignmentIsInBytes())
6110 unsigned Val = AR.
Val;
6112 assert(Val < 10 &&
"Expected alignment less then 2^10.");
6113 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6125 AsmStart = Loc + AR.
Len + AdditionalSkip;
6129 if (AsmStart != AsmEnd)
6130 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6132 AsmString = OS.
str();
6136void MasmParser::initializeBuiltinSymbolMaps() {
6138 BuiltinSymbolMap[
"@version"] = BI_VERSION;
6139 BuiltinSymbolMap[
"@line"] = BI_LINE;
6142 BuiltinSymbolMap[
"@date"] = BI_DATE;
6143 BuiltinSymbolMap[
"@time"] = BI_TIME;
6144 BuiltinSymbolMap[
"@filecur"] = BI_FILECUR;
6145 BuiltinSymbolMap[
"@filename"] = BI_FILENAME;
6146 BuiltinSymbolMap[
"@curseg"] = BI_CURSEG;
6149 BuiltinFunctionMap[
"@catstr"] = BI_CATSTR;
6152 if (
getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
6170const MCExpr *MasmParser::evaluateBuiltinValue(BuiltinSymbol Symbol,
6180 if (ActiveMacros.empty())
6184 ActiveMacros.front()->ExitBuffer);
6191std::optional<std::string>
6192MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
6198 char TmpBuffer[
sizeof(
"mm/dd/yy")];
6199 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%D", &TM);
6200 return std::string(TmpBuffer, Len);
6204 char TmpBuffer[
sizeof(
"hh:mm:ss")];
6205 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%T", &TM);
6206 return std::string(TmpBuffer, Len);
6211 ActiveMacros.empty() ? CurBuffer : ActiveMacros.front()->ExitBuffer)
6219 return getStreamer().getCurrentSectionOnly()->getName().str();
6224bool MasmParser::evaluateBuiltinMacroFunction(BuiltinFunction Function,
6228 "' requires arguments in parentheses")) {
6239 MCAsmMacro
M(Name,
"",
P, {},
true);
6241 MCAsmMacroArguments
A;
6250 for (
const MCAsmMacroArgument &Arg :
A) {
6251 for (
const AsmToken &Tok : Arg) {
6269 struct tm TM,
unsigned CB) {
6270 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")
Analysis containing CSE Info
Value * getPointer(Value *Ptr)
const std::string FatArchTraits< MachO::fat_arch >::StructName
static bool isMacroParameterChar(char C)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
OptimizedStructLayoutField Field
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
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.
StringRef getPrivateLabelPrefix() const
bool shouldUseLogicalShr() const
virtual bool useCodeAlign(const MCSection &Sec) const
Generic interface for extending the MCAsmParser, which is implemented by target and object file assem...
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 initSections(bool NoExecStack, const MCSubtargetInfo &STI)
Create the default sections and set the initial one.
virtual void addExplicitComment(const Twine &T)
Add explicit comment T.
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.
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 void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const
Prints the names of included files and the line of the file they were included from.
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.
StringRef - 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
str - 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
empty - 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
size - Get the string size.
constexpr const char * data() const
data - 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.
Context & getContext() const
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.
FunctionAddr VTableAddr Value
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.
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.
auto dyn_cast_or_null(const Y &Val)
cl::opt< unsigned > AsmMacroMaxNestingDepth
MCAsmParserExtension * createCOFFMasmParser()
const char AsmRewritePrecedence[]
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionAddr VTableAddr Count
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
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.
uint64_t Size
The required size of this field in bytes.