75typedef std::vector<AsmToken> MCAsmMacroArgument;
76typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments;
79struct MacroInstantiation {
81 SMLoc InstantiationLoc;
90 size_t CondStackDepth;
93struct ParseStatementInfo {
98 unsigned Opcode = ~0
U;
101 bool ParseError =
false;
104 std::optional<std::string> ExitValue;
106 SmallVectorImpl<AsmRewrite> *AsmRewrites =
nullptr;
108 ParseStatementInfo() =
delete;
109 ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
110 : AsmRewrites(rewrites) {}
122 bool IsUnion =
false;
123 bool Initializable =
true;
124 unsigned Alignment = 0;
125 unsigned AlignmentSize = 0;
126 unsigned NextOffset = 0;
128 std::vector<FieldInfo> Fields;
129 StringMap<size_t> FieldsByName;
131 FieldInfo &addField(StringRef FieldName, FieldType FT,
132 unsigned FieldAlignmentSize);
134 StructInfo() =
default;
135 StructInfo(StringRef
StructName,
bool Union,
unsigned AlignmentValue);
143struct StructInitializer;
147 IntFieldInfo() =
default;
151struct RealFieldInfo {
154 RealFieldInfo() =
default;
158struct StructFieldInfo {
159 std::vector<StructInitializer> Initializers;
160 StructInfo Structure;
162 StructFieldInfo() =
default;
163 StructFieldInfo(std::vector<StructInitializer> V, StructInfo S);
166class FieldInitializer {
170 IntFieldInfo IntInfo;
171 RealFieldInfo RealInfo;
172 StructFieldInfo StructInfo;
176 FieldInitializer(FieldType FT);
180 FieldInitializer(std::vector<StructInitializer> &&Initializers,
181 struct StructInfo Structure);
183 FieldInitializer(
const FieldInitializer &Initializer);
184 FieldInitializer(FieldInitializer &&Initializer);
186 FieldInitializer &operator=(
const FieldInitializer &Initializer);
187 FieldInitializer &operator=(FieldInitializer &&Initializer);
190struct StructInitializer {
191 std::vector<FieldInitializer> FieldInitializers;
202 unsigned LengthOf = 0;
207 FieldInitializer Contents;
209 FieldInfo(FieldType FT) : Contents(FT) {}
212StructFieldInfo::StructFieldInfo(std::vector<StructInitializer> V,
214 Initializers = std::move(V);
215 Structure = std::move(S);
218StructInfo::StructInfo(StringRef
StructName,
bool Union,
219 unsigned AlignmentValue)
222FieldInfo &StructInfo::addField(
StringRef FieldName, FieldType FT,
223 unsigned FieldAlignmentSize) {
224 if (!FieldName.
empty())
225 FieldsByName[FieldName.
lower()] = Fields.size();
226 Fields.emplace_back(FT);
227 FieldInfo &
Field = Fields.back();
229 llvm::alignTo(NextOffset, std::min(Alignment, FieldAlignmentSize));
233 AlignmentSize = std::max(AlignmentSize, FieldAlignmentSize);
237FieldInitializer::~FieldInitializer() {
240 IntInfo.~IntFieldInfo();
243 RealInfo.~RealFieldInfo();
246 StructInfo.~StructFieldInfo();
251FieldInitializer::FieldInitializer(FieldType FT) : FT(FT) {
254 new (&IntInfo) IntFieldInfo();
257 new (&RealInfo) RealFieldInfo();
260 new (&StructInfo) StructFieldInfo();
267 new (&IntInfo) IntFieldInfo(std::move(
Values));
272 new (&RealInfo) RealFieldInfo(std::move(AsIntValues));
275FieldInitializer::FieldInitializer(
276 std::vector<StructInitializer> &&Initializers,
struct StructInfo Structure)
278 new (&StructInfo) StructFieldInfo(std::move(Initializers), Structure);
281FieldInitializer::FieldInitializer(
const FieldInitializer &Initializer)
282 : FT(Initializer.FT) {
285 new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
288 new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
291 new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
296FieldInitializer::FieldInitializer(FieldInitializer &&Initializer)
297 : FT(Initializer.FT) {
300 new (&IntInfo) IntFieldInfo(Initializer.IntInfo);
303 new (&RealInfo) RealFieldInfo(Initializer.RealInfo);
306 new (&StructInfo) StructFieldInfo(Initializer.StructInfo);
312FieldInitializer::operator=(
const FieldInitializer &Initializer) {
313 if (FT != Initializer.FT) {
316 IntInfo.~IntFieldInfo();
319 RealInfo.~RealFieldInfo();
322 StructInfo.~StructFieldInfo();
329 IntInfo = Initializer.IntInfo;
332 RealInfo = Initializer.RealInfo;
335 StructInfo = Initializer.StructInfo;
341FieldInitializer &FieldInitializer::operator=(FieldInitializer &&Initializer) {
342 if (FT != Initializer.FT) {
345 IntInfo.~IntFieldInfo();
348 RealInfo.~RealFieldInfo();
351 StructInfo.~StructFieldInfo();
358 IntInfo = Initializer.IntInfo;
361 RealInfo = Initializer.RealInfo;
364 StructInfo = Initializer.StructInfo;
373class MasmParser :
public MCAsmParser {
376 void *SavedDiagContext;
377 std::unique_ptr<MCAsmParserExtension> PlatformParser;
386 BitVector EndStatementAtEOFStack;
388 AsmCond TheCondState;
389 std::vector<AsmCond> TheCondStack;
394 StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
398 enum RedefinableKind { NOT_REDEFINABLE, WARN_ON_REDEFINITION, REDEFINABLE };
401 RedefinableKind Redefinable = REDEFINABLE;
403 std::string TextValue;
405 StringMap<Variable> Variables;
411 StringMap<StructInfo> Structs;
414 StringMap<AsmTypeInfo> KnownType;
417 std::vector<MacroInstantiation*> ActiveMacros;
420 std::deque<MCAsmMacro> MacroLikeBodies;
423 unsigned NumOfMacroInstantiations;
426 struct CppHashInfoTy {
431 CppHashInfoTy() : LineNumber(0), Buf(0) {}
433 CppHashInfoTy CppHashInfo;
436 StringRef FirstCppHashFilename;
443 unsigned AssemblerDialect = 1U;
446 bool ParsingMSInlineAsm =
false;
449 unsigned AngleBracketDepth = 0
U;
452 uint16_t LocalCounter = 0;
455 MasmParser(SourceMgr &
SM, MCContext &Ctx, MCStreamer &Out,
456 const MCAsmInfo &MAI,
struct tm TM,
unsigned CB = 0);
457 MasmParser(
const MasmParser &) =
delete;
458 MasmParser &operator=(
const MasmParser &) =
delete;
459 ~MasmParser()
override;
461 bool Run(
bool NoInitialTextSection,
bool NoFinalize =
false)
override;
463 void addDirectiveHandler(StringRef Directive,
464 ExtensionDirectiveHandler Handler)
override {
465 ExtensionDirectiveMap[Directive] = std::move(Handler);
466 DirectiveKindMap.try_emplace(Directive, DK_HANDLER_DIRECTIVE);
469 void addAliasForDirective(StringRef Directive, StringRef Alias)
override {
470 DirectiveKindMap[Directive] = DirectiveKindMap[Alias];
476 unsigned getAssemblerDialect()
override {
477 if (AssemblerDialect == ~0U)
478 return MAI.getAssemblerDialect();
480 return AssemblerDialect;
482 void setAssemblerDialect(
unsigned i)
override {
483 AssemblerDialect = i;
486 void Note(SMLoc L,
const Twine &
Msg, SMRange
Range = {})
override;
488 bool printError(SMLoc L,
const Twine &
Msg, SMRange
Range = {})
override;
490 enum ExpandKind { ExpandMacros, DoNotExpandMacros };
491 const AsmToken &Lex(ExpandKind ExpandNextToken);
492 const AsmToken &Lex()
override {
return Lex(ExpandMacros); }
494 void setParsingMSInlineAsm(
bool V)
override {
495 ParsingMSInlineAsm =
V;
498 Lexer.setLexMasmIntegers(V);
500 bool isParsingMSInlineAsm()
override {
return ParsingMSInlineAsm; }
502 bool isParsingMasm()
const override {
return true; }
504 bool defineMacro(StringRef Name, StringRef
Value)
override;
506 bool lookUpField(StringRef Name, AsmFieldInfo &Info)
const override;
507 bool lookUpField(StringRef
Base, StringRef Member,
508 AsmFieldInfo &Info)
const override;
510 bool lookUpType(StringRef Name, AsmTypeInfo &Info)
const override;
512 bool parseMSInlineAsm(std::string &AsmString,
unsigned &NumOutputs,
514 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
515 SmallVectorImpl<std::string> &Constraints,
516 SmallVectorImpl<std::string> &Clobbers,
517 const MCInstrInfo *MII, MCInstPrinter *IP,
518 MCAsmParserSemaCallback &SI)
override;
520 bool parseExpression(
const MCExpr *&Res);
521 bool parseExpression(
const MCExpr *&Res, SMLoc &EndLoc)
override;
522 bool parsePrimaryExpr(
const MCExpr *&Res, SMLoc &EndLoc,
523 AsmTypeInfo *TypeInfo)
override;
524 bool parseParenExpression(
const MCExpr *&Res, SMLoc &EndLoc)
override;
525 bool parseAbsoluteExpression(int64_t &Res)
override;
529 bool parseRealValue(
const fltSemantics &Semantics, APInt &Res);
533 enum IdentifierPositionKind { StandardPosition, StartOfStatement };
534 bool parseIdentifier(StringRef &Res, IdentifierPositionKind Position);
535 bool parseIdentifier(StringRef &Res)
override {
536 return parseIdentifier(Res, StandardPosition);
538 void eatToEndOfStatement()
override;
540 bool checkForValidSection()
override;
546 const AsmToken peekTok(
bool ShouldSkipSpace =
true);
548 bool parseStatement(ParseStatementInfo &Info,
549 MCAsmParserSemaCallback *SI);
550 bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites);
551 bool parseCppHashLineFilenameComment(SMLoc L);
553 bool expandMacro(raw_svector_ostream &OS, StringRef Body,
556 const std::vector<std::string> &Locals, SMLoc L);
559 bool isInsideMacroInstantiation() {
return !ActiveMacros.empty();}
565 bool handleMacroEntry(
566 const MCAsmMacro *M, SMLoc NameLoc,
573 bool handleMacroInvocation(
const MCAsmMacro *M, SMLoc NameLoc);
576 void handleMacroExit();
580 parseMacroArgument(
const MCAsmMacroParameter *MP, MCAsmMacroArgument &MA,
585 parseMacroArguments(
const MCAsmMacro *M, MCAsmMacroArguments &
A,
588 void printMacroInstantiations();
590 bool expandStatement(SMLoc Loc);
593 SMRange
Range = {})
const {
599 bool lookUpField(
const StructInfo &Structure, StringRef Member,
600 AsmFieldInfo &Info)
const;
603 bool enterIncludeFile(
const std::string &
Filename);
611 void jumpToLoc(SMLoc Loc,
unsigned InBuffer = 0,
612 bool EndStatementAtEOF =
true);
624 StringRef parseStringToEndOfStatement()
override;
626 bool parseTextItem(std::string &
Data);
627 bool parseTextList(std::string &Result, StringRef IDVal);
628 bool setTextVariable(Variable &Var, StringRef Name, StringRef
Value,
629 SMLoc NameLoc, Variable::RedefinableKind Redefinable);
634 bool parseBinOpRHS(
unsigned Precedence,
const MCExpr *&Res, SMLoc &EndLoc);
635 bool parseParenExpr(
const MCExpr *&Res, SMLoc &EndLoc);
636 bool parseBracketExpr(
const MCExpr *&Res, SMLoc &EndLoc);
641 DK_HANDLER_DIRECTIVE,
732 StringMap<DirectiveKind> DirectiveKindMap;
734 bool isMacroLikeDirective();
761 StringMap<BuiltinSymbol> BuiltinSymbolMap;
763 const MCExpr *evaluateBuiltinValue(BuiltinSymbol Symbol, SMLoc StartLoc);
765 std::optional<std::string> evaluateBuiltinTextMacro(BuiltinSymbol Symbol,
769 enum BuiltinFunction {
776 StringMap<BuiltinFunction> BuiltinFunctionMap;
778 bool evaluateBuiltinMacroFunction(BuiltinFunction Function, StringRef Name,
782 bool parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated);
785 bool emitIntValue(
const MCExpr *
Value,
unsigned Size);
786 bool parseScalarInitializer(
unsigned Size,
787 SmallVectorImpl<const MCExpr *> &
Values,
788 unsigned StringPadLength = 0);
789 bool parseScalarInstList(
790 unsigned Size, SmallVectorImpl<const MCExpr *> &
Values,
792 bool emitIntegralValues(
unsigned Size,
unsigned *
Count =
nullptr);
793 bool addIntegralField(StringRef Name,
unsigned Size);
794 bool parseDirectiveValue(StringRef IDVal,
unsigned Size);
795 bool parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
796 StringRef Name, SMLoc NameLoc);
799 bool emitRealValues(
const fltSemantics &Semantics,
unsigned *
Count =
nullptr);
800 bool addRealField(StringRef Name,
const fltSemantics &Semantics,
size_t Size);
801 bool parseDirectiveRealValue(StringRef IDVal,
const fltSemantics &Semantics,
803 bool parseRealInstList(
804 const fltSemantics &Semantics, SmallVectorImpl<APInt> &
Values,
806 bool parseDirectiveNamedRealValue(StringRef TypeName,
807 const fltSemantics &Semantics,
808 unsigned Size, StringRef Name,
811 bool parseOptionalAngleBracketOpen();
812 bool parseAngleBracketClose(
const Twine &
Msg =
"expected '>'");
814 bool parseFieldInitializer(
const FieldInfo &
Field,
815 FieldInitializer &Initializer);
816 bool parseFieldInitializer(
const FieldInfo &
Field,
817 const IntFieldInfo &Contents,
818 FieldInitializer &Initializer);
819 bool parseFieldInitializer(
const FieldInfo &
Field,
820 const RealFieldInfo &Contents,
821 FieldInitializer &Initializer);
822 bool parseFieldInitializer(
const FieldInfo &
Field,
823 const StructFieldInfo &Contents,
824 FieldInitializer &Initializer);
826 bool parseStructInitializer(
const StructInfo &Structure,
827 StructInitializer &Initializer);
828 bool parseStructInstList(
829 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
832 bool emitFieldValue(
const FieldInfo &
Field);
833 bool emitFieldValue(
const FieldInfo &
Field,
const IntFieldInfo &Contents);
834 bool emitFieldValue(
const FieldInfo &
Field,
const RealFieldInfo &Contents);
835 bool emitFieldValue(
const FieldInfo &
Field,
const StructFieldInfo &Contents);
837 bool emitFieldInitializer(
const FieldInfo &
Field,
838 const FieldInitializer &Initializer);
839 bool emitFieldInitializer(
const FieldInfo &
Field,
840 const IntFieldInfo &Contents,
841 const IntFieldInfo &Initializer);
842 bool emitFieldInitializer(
const FieldInfo &
Field,
843 const RealFieldInfo &Contents,
844 const RealFieldInfo &Initializer);
845 bool emitFieldInitializer(
const FieldInfo &
Field,
846 const StructFieldInfo &Contents,
847 const StructFieldInfo &Initializer);
849 bool emitStructInitializer(
const StructInfo &Structure,
850 const StructInitializer &Initializer);
853 bool emitStructValues(
const StructInfo &Structure,
unsigned *
Count =
nullptr);
854 bool addStructField(StringRef Name,
const StructInfo &Structure);
855 bool parseDirectiveStructValue(
const StructInfo &Structure,
856 StringRef Directive, SMLoc DirLoc);
857 bool parseDirectiveNamedStructValue(
const StructInfo &Structure,
858 StringRef Directive, SMLoc DirLoc,
862 bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
863 DirectiveKind DirKind, SMLoc NameLoc);
865 bool parseDirectiveOrg();
867 bool emitAlignTo(int64_t Alignment);
868 bool parseDirectiveAlign();
869 bool parseDirectiveEven();
872 bool parseDirectivePurgeMacro(SMLoc DirectiveLoc);
873 bool parseDirectiveExitMacro(SMLoc DirectiveLoc, StringRef Directive,
875 bool parseDirectiveEndMacro(StringRef Directive);
876 bool parseDirectiveMacro(StringRef Name, SMLoc NameLoc);
878 bool parseDirectiveStruct(StringRef Directive, DirectiveKind DirKind,
879 StringRef Name, SMLoc NameLoc);
880 bool parseDirectiveNestedStruct(StringRef Directive, DirectiveKind DirKind);
881 bool parseDirectiveEnds(StringRef Name, SMLoc NameLoc);
882 bool parseDirectiveNestedEnds();
884 bool parseDirectiveExtern();
890 bool parseDirectiveComm(
bool IsLocal);
892 bool parseDirectiveComment(SMLoc DirectiveLoc);
894 bool parseDirectiveInclude();
897 bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
899 bool parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
902 bool parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
903 bool CaseInsensitive);
905 bool parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined);
907 bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
909 bool parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
911 bool parseDirectiveElseIfdef(SMLoc DirectiveLoc,
bool expect_defined);
914 bool parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
915 bool CaseInsensitive);
916 bool parseDirectiveElse(SMLoc DirectiveLoc);
917 bool parseDirectiveEndIf(SMLoc DirectiveLoc);
918 bool parseEscapedString(std::string &
Data)
override;
919 bool parseAngleBracketString(std::string &
Data)
override;
922 MCAsmMacro *parseMacroLikeBody(SMLoc DirectiveLoc);
923 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
924 raw_svector_ostream &OS);
925 void instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
926 SMLoc ExitLoc, raw_svector_ostream &OS);
927 bool parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Directive);
928 bool parseDirectiveFor(SMLoc DirectiveLoc, StringRef Directive);
929 bool parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive);
930 bool parseDirectiveWhile(SMLoc DirectiveLoc);
933 bool parseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
937 bool parseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
940 bool parseDirectiveEnd(SMLoc DirectiveLoc);
943 bool parseDirectiveError(SMLoc DirectiveLoc);
945 bool parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank);
947 bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
bool ExpectDefined);
950 bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
951 bool CaseInsensitive);
953 bool parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero);
956 bool parseDirectiveRadix(SMLoc DirectiveLoc);
959 bool parseDirectiveEcho(SMLoc DirectiveLoc);
961 void initializeDirectiveKindMap();
962 void initializeBuiltinSymbolMaps();
975MasmParser::MasmParser(SourceMgr &
SM, MCContext &Ctx, MCStreamer &Out,
976 const MCAsmInfo &MAI,
struct tm TM,
unsigned CB)
977 : MCAsmParser(Ctx, Out,
SM, MAI), CurBuffer(CB ? CB :
SM.getMainFileID()),
981 SavedDiagHandler =
SrcMgr.getDiagHandler();
982 SavedDiagContext =
SrcMgr.getDiagContext();
985 Lexer.setBuffer(
SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer());
986 EndStatementAtEOFStack.push_back(
true);
989 switch (Ctx.getObjectFileType()) {
990 case MCContext::IsCOFF:
991 PlatformParser.reset(createCOFFMasmParser());
994 report_fatal_error(
"llvm-ml currently supports only COFF output.");
998 initializeDirectiveKindMap();
999 PlatformParser->Initialize(*
this);
1000 initializeBuiltinSymbolMaps();
1002 NumOfMacroInstantiations = 0;
1005MasmParser::~MasmParser() {
1006 assert((HadError || ActiveMacros.empty()) &&
1007 "Unexpected active macro instantiation!");
1014void MasmParser::printMacroInstantiations() {
1016 for (std::vector<MacroInstantiation *>::const_reverse_iterator
1017 it = ActiveMacros.rbegin(),
1018 ie = ActiveMacros.rend();
1021 "while in macro instantiation");
1024void MasmParser::Note(SMLoc L,
const Twine &
Msg, SMRange
Range) {
1025 printPendingErrors();
1027 printMacroInstantiations();
1030bool MasmParser::Warning(SMLoc L,
const Twine &
Msg, SMRange
Range) {
1031 if (getTargetParser().getTargetOptions().MCNoWarn)
1033 if (getTargetParser().getTargetOptions().MCFatalWarnings)
1036 printMacroInstantiations();
1040bool MasmParser::printError(SMLoc L,
const Twine &
Msg, SMRange
Range) {
1043 printMacroInstantiations();
1047bool MasmParser::enterIncludeFile(
const std::string &
Filename) {
1048 std::string IncludedFile;
1056 EndStatementAtEOFStack.push_back(
true);
1060void MasmParser::jumpToLoc(SMLoc Loc,
unsigned InBuffer,
1061 bool EndStatementAtEOF) {
1067bool MasmParser::expandMacros() {
1068 const AsmToken &Tok = getTok();
1071 const llvm::MCAsmMacro *
M =
getContext().lookupMacro(IDLower);
1074 const SMLoc MacroLoc = Tok.
getLoc();
1077 if (handleMacroInvocation(M, MacroLoc)) {
1084 std::optional<std::string> ExpandedValue;
1086 if (
auto BuiltinIt = BuiltinSymbolMap.find(IDLower);
1087 BuiltinIt != BuiltinSymbolMap.end()) {
1089 evaluateBuiltinTextMacro(BuiltinIt->getValue(), Tok.
getLoc());
1090 }
else if (
auto BuiltinFuncIt = BuiltinFunctionMap.find(IDLower);
1091 BuiltinFuncIt != BuiltinFunctionMap.end()) {
1093 if (parseIdentifier(Name)) {
1097 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), Name, Res)) {
1100 ExpandedValue = Res;
1101 }
else if (
auto VarIt = Variables.
find(IDLower);
1102 VarIt != Variables.
end() && VarIt->getValue().IsText) {
1103 ExpandedValue = VarIt->getValue().TextValue;
1108 std::unique_ptr<MemoryBuffer> Instantiation =
1116 EndStatementAtEOFStack.push_back(
false);
1121const AsmToken &MasmParser::Lex(ExpandKind ExpandNextToken) {
1123 Error(Lexer.getErrLoc(), Lexer.getErr());
1124 bool StartOfStatement =
false;
1129 if (!getTok().getString().
empty() && getTok().getString().
front() !=
'\n' &&
1132 StartOfStatement =
true;
1135 const AsmToken *tok = &Lexer.Lex();
1138 if (StartOfStatement) {
1141 size_t ReadCount = Lexer.peekTokens(Buf);
1173 if (ParentIncludeLoc != SMLoc()) {
1174 EndStatementAtEOFStack.pop_back();
1175 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1178 EndStatementAtEOFStack.pop_back();
1179 assert(EndStatementAtEOFStack.empty());
1185const AsmToken MasmParser::peekTok(
bool ShouldSkipSpace) {
1189 size_t ReadCount = Lexer.peekTokens(Buf, ShouldSkipSpace);
1191 if (ReadCount == 0) {
1195 if (ParentIncludeLoc != SMLoc()) {
1196 EndStatementAtEOFStack.pop_back();
1197 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1198 return peekTok(ShouldSkipSpace);
1200 EndStatementAtEOFStack.pop_back();
1201 assert(EndStatementAtEOFStack.empty());
1208bool MasmParser::Run(
bool NoInitialTextSection,
bool NoFinalize) {
1210 if (!NoInitialTextSection)
1217 AsmCond StartingCondState = TheCondState;
1227 ParseStatementInfo
Info(&AsmStrRewrites);
1228 bool HasError = parseStatement(Info,
nullptr);
1233 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
1237 printPendingErrors();
1240 if (HasError && !getLexer().justConsumedEOL())
1241 eatToEndOfStatement();
1244 printPendingErrors();
1247 assert(!hasPendingError() &&
"unexpected error from parseStatement");
1251 printError(getTok().getLoc(),
"unmatched .ifs or .elses");
1260 for (std::tuple<SMLoc, CppHashInfoTy, MCSymbol *> &LocSym : DirLabels) {
1261 if (std::get<2>(LocSym)->isUndefined()) {
1264 CppHashInfo = std::get<1>(LocSym);
1265 printError(std::get<0>(LocSym),
"directional label undefined");
1272 if (!HadError && !NoFinalize)
1273 Out.
finish(Lexer.getLoc());
1278bool MasmParser::checkForValidSection() {
1279 if (!ParsingMSInlineAsm && !(getStreamer().getCurrentFragment() &&
1280 getStreamer().getCurrentSectionOnly())) {
1282 return Error(getTok().getLoc(),
1283 "expected section directive before assembly directive");
1289void MasmParser::eatToEndOfStatement() {
1293 if (ParentIncludeLoc == SMLoc()) {
1297 EndStatementAtEOFStack.pop_back();
1298 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1309SmallVector<StringRef, 1>
1311 SmallVector<StringRef, 1> Refs;
1312 const char *
Start = getTok().getLoc().getPointer();
1313 while (Lexer.isNot(EndTok)) {
1316 if (ParentIncludeLoc == SMLoc()) {
1321 EndStatementAtEOFStack.pop_back();
1322 jumpToLoc(ParentIncludeLoc, 0, EndStatementAtEOFStack.back());
1324 Start = getTok().getLoc().getPointer();
1334 SmallVector<StringRef, 1> Refs = parseStringRefsTo(EndTok);
1336 for (StringRef S : Refs) {
1337 Str.append(S.str());
1342StringRef MasmParser::parseStringToEndOfStatement() {
1343 const char *
Start = getTok().getLoc().getPointer();
1348 const char *End = getTok().getLoc().getPointer();
1349 return StringRef(Start, End - Start);
1357bool MasmParser::parseParenExpr(
const MCExpr *&Res, SMLoc &EndLoc) {
1358 if (parseExpression(Res))
1360 EndLoc = Lexer.getTok().getEndLoc();
1361 return parseRParen();
1369bool MasmParser::parseBracketExpr(
const MCExpr *&Res, SMLoc &EndLoc) {
1370 if (parseExpression(Res))
1372 EndLoc = getTok().getEndLoc();
1373 if (parseToken(
AsmToken::RBrac,
"expected ']' in brackets expression"))
1386bool MasmParser::parsePrimaryExpr(
const MCExpr *&Res, SMLoc &EndLoc,
1387 AsmTypeInfo *TypeInfo) {
1388 SMLoc FirstTokenLoc = getLexer().getLoc();
1390 switch (FirstTokenKind) {
1392 return TokError(
"unknown token in expression");
1398 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1406 if (parseIdentifier(Identifier)) {
1409 if (Lexer.getMAI().getDollarIsPC()) {
1416 EndLoc = FirstTokenLoc;
1419 return Error(FirstTokenLoc,
"invalid token in expression");
1424 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1432 bool Before =
Identifier.equals_insensitive(
"@b");
1435 return Error(FirstTokenLoc,
"Expected @@ label before @B reference");
1445 return Error(getLexer().getLoc(),
"expected a symbol reference");
1450 if (
Split.second.empty()) {
1453 if (lookUpField(SymbolName,
Split.second, Info)) {
1454 std::pair<StringRef, StringRef> BaseMember =
Split.second.split(
'.');
1455 StringRef
Base = BaseMember.first,
Member = BaseMember.second;
1456 lookUpField(
Base, Member, Info);
1467 auto BuiltinIt = BuiltinSymbolMap.find(
SymbolName.lower());
1468 const BuiltinSymbol
Symbol = (BuiltinIt == BuiltinSymbolMap.end())
1470 : BuiltinIt->getValue();
1471 if (Symbol != BI_NO_SYMBOL) {
1472 const MCExpr *
Value = evaluateBuiltinValue(Symbol, FirstTokenLoc);
1482 if (VarIt != Variables.
end())
1493 DoInline = TV->inlineAssignedExpr();
1501 const MCExpr *SymRef =
1511 if (
Info.Type.Name.empty()) {
1513 if (TypeIt != KnownType.
end()) {
1514 Info.Type = TypeIt->second;
1518 *TypeInfo =
Info.Type;
1523 return TokError(
"literal value out of range for directive");
1525 int64_t
IntVal = getTok().getIntVal();
1527 EndLoc = Lexer.getTok().getEndLoc();
1533 SMLoc ValueLoc = getTok().getLoc();
1535 if (parseEscapedString(
Value))
1537 if (
Value.size() > 8)
1538 return Error(ValueLoc,
"literal value out of range");
1539 uint64_t IntValue = 0;
1540 for (
const unsigned char CharVal :
Value)
1541 IntValue = (IntValue << 8) | CharVal;
1546 APFloat RealVal(APFloat::IEEEdouble(), getTok().getString());
1547 uint64_t
IntVal = RealVal.bitcastToAPInt().getZExtValue();
1549 EndLoc = Lexer.getTok().getEndLoc();
1559 EndLoc = Lexer.getTok().getEndLoc();
1565 return parseParenExpr(Res, EndLoc);
1567 if (!PlatformParser->HasBracketExpressions())
1568 return TokError(
"brackets expression not supported on this target");
1570 return parseBracketExpr(Res, EndLoc);
1573 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1579 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1585 if (parsePrimaryExpr(Res, EndLoc,
nullptr))
1592bool MasmParser::parseExpression(
const MCExpr *&Res) {
1594 return parseExpression(Res, EndLoc);
1605 "Argument to the function cannot be a NULL value");
1607 while ((*CharPtr !=
'>') && (*CharPtr !=
'\n') && (*CharPtr !=
'\r') &&
1608 (*CharPtr !=
'\0')) {
1609 if (*CharPtr ==
'!')
1613 if (*CharPtr ==
'>') {
1623 for (
size_t Pos = 0; Pos < BracketContents.
size(); Pos++) {
1624 if (BracketContents[Pos] ==
'!')
1626 Res += BracketContents[Pos];
1641bool MasmParser::parseExpression(
const MCExpr *&Res, SMLoc &EndLoc) {
1644 if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
1645 parseBinOpRHS(1, Res, EndLoc))
1651 if (Res->evaluateAsAbsolute(
Value))
1657bool MasmParser::parseParenExpression(
const MCExpr *&Res, SMLoc &EndLoc) {
1659 return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
1662bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
1665 SMLoc StartLoc = Lexer.getLoc();
1666 if (parseExpression(Expr))
1669 if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
1670 return Error(StartLoc,
"expected absolute expression");
1677 bool ShouldUseLogicalShr,
1678 bool EndExpressionAtGreater) {
1706 if (EndExpressionAtGreater)
1747 if (EndExpressionAtGreater)
1758 AngleBracketDepth > 0);
1763bool MasmParser::parseBinOpRHS(
unsigned Precedence,
const MCExpr *&Res,
1765 SMLoc StartLoc = Lexer.getLoc();
1769 TokKind = StringSwitch<AsmToken::TokenKind>(Lexer.getTok().getString())
1785 unsigned TokPrec = getBinOpPrecedence(TokKind, Kind);
1789 if (TokPrec < Precedence)
1796 if (getTargetParser().parsePrimaryExpr(
RHS, EndLoc))
1802 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
1803 if (TokPrec < NextTokPrec && parseBinOpRHS(TokPrec + 1,
RHS, EndLoc))
1816bool MasmParser::parseStatement(ParseStatementInfo &Info,
1817 MCAsmParserSemaCallback *SI) {
1818 assert(!hasPendingError() &&
"parseStatement started with pending error");
1824 if (getTok().getString().
empty() || getTok().getString().
front() ==
'\r' ||
1825 getTok().getString().
front() ==
'\n')
1834 SMLoc ExpansionLoc = getTok().getLoc();
1841 AsmToken
ID = getTok();
1842 SMLoc IDLoc =
ID.getLoc();
1845 return parseCppHashLineFilenameComment(IDLoc);
1852 IDVal = getTok().getString();
1855 return Error(IDLoc,
"unexpected token at start of statement");
1856 }
else if (parseIdentifier(IDVal, StartOfStatement)) {
1857 if (!TheCondState.
Ignore) {
1859 return Error(IDLoc,
"unexpected token at start of statement");
1868 DirectiveKindMap.find(IDVal.
lower());
1869 DirectiveKind DirKind = (DirKindIt == DirectiveKindMap.end())
1871 : DirKindIt->getValue();
1877 return parseDirectiveIf(IDLoc, DirKind);
1879 return parseDirectiveIfb(IDLoc,
true);
1881 return parseDirectiveIfb(IDLoc,
false);
1883 return parseDirectiveIfdef(IDLoc,
true);
1885 return parseDirectiveIfdef(IDLoc,
false);
1887 return parseDirectiveIfidn(IDLoc,
false,
1890 return parseDirectiveIfidn(IDLoc,
false,
1893 return parseDirectiveIfidn(IDLoc,
true,
1896 return parseDirectiveIfidn(IDLoc,
true,
1900 return parseDirectiveElseIf(IDLoc, DirKind);
1902 return parseDirectiveElseIfb(IDLoc,
true);
1904 return parseDirectiveElseIfb(IDLoc,
false);
1906 return parseDirectiveElseIfdef(IDLoc,
true);
1908 return parseDirectiveElseIfdef(IDLoc,
false);
1910 return parseDirectiveElseIfidn(IDLoc,
false,
1913 return parseDirectiveElseIfidn(IDLoc,
false,
1916 return parseDirectiveElseIfidn(IDLoc,
true,
1919 return parseDirectiveElseIfidn(IDLoc,
true,
1922 return parseDirectiveElse(IDLoc);
1924 return parseDirectiveEndIf(IDLoc);
1929 if (TheCondState.
Ignore) {
1930 eatToEndOfStatement();
1940 if (checkForValidSection())
1948 return Error(IDLoc,
"invalid use of pseudo-symbol '.' as a label");
1956 if (ParsingMSInlineAsm && SI) {
1957 StringRef RewrittenLabel =
1958 SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc,
true);
1960 "We should have an internal name here.");
1963 IDVal = RewrittenLabel;
1966 if (IDVal ==
"@@") {
1989 if (!getTargetParser().isParsingMSInlineAsm())
1999 return handleMacroEntry(M, IDLoc, ArgumentEndTok);
2004 if (DirKind != DK_NO_DIRECTIVE) {
2020 return parseDirectiveNestedEnds();
2025 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2028 return (*Handler.second)(Handler.first, IDVal, IDLoc);
2034 ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(ID);
2036 "Should only return Failure iff there was an error");
2048 return parseDirectiveAscii(IDVal,
false);
2051 return parseDirectiveAscii(IDVal,
true);
2055 return parseDirectiveValue(IDVal, 1);
2059 return parseDirectiveValue(IDVal, 2);
2063 return parseDirectiveValue(IDVal, 4);
2066 return parseDirectiveValue(IDVal, 6);
2070 return parseDirectiveValue(IDVal, 8);
2072 return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle(), 4);
2074 return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble(), 8);
2076 return parseDirectiveRealValue(IDVal, APFloat::x87DoubleExtended(), 10);
2079 return parseDirectiveNestedStruct(IDVal, DirKind);
2081 return parseDirectiveNestedEnds();
2083 return parseDirectiveAlign();
2085 return parseDirectiveEven();
2087 return parseDirectiveOrg();
2089 return parseDirectiveExtern();
2091 return parseDirectiveSymbolAttribute(
MCSA_Global);
2093 return parseDirectiveComm(
false);
2095 return parseDirectiveComment(IDLoc);
2097 return parseDirectiveInclude();
2099 return parseDirectiveRepeat(IDLoc, IDVal);
2101 return parseDirectiveWhile(IDLoc);
2103 return parseDirectiveFor(IDLoc, IDVal);
2105 return parseDirectiveForc(IDLoc, IDVal);
2107 Info.ExitValue =
"";
2108 return parseDirectiveExitMacro(IDLoc, IDVal, *
Info.ExitValue);
2110 Info.ExitValue =
"";
2111 return parseDirectiveEndMacro(IDVal);
2113 return parseDirectivePurgeMacro(IDLoc);
2115 return parseDirectiveEnd(IDLoc);
2117 return parseDirectiveError(IDLoc);
2119 return parseDirectiveErrorIfb(IDLoc,
true);
2121 return parseDirectiveErrorIfb(IDLoc,
false);
2123 return parseDirectiveErrorIfdef(IDLoc,
true);
2125 return parseDirectiveErrorIfdef(IDLoc,
false);
2127 return parseDirectiveErrorIfidn(IDLoc,
false,
2130 return parseDirectiveErrorIfidn(IDLoc,
false,
2133 return parseDirectiveErrorIfidn(IDLoc,
true,
2136 return parseDirectiveErrorIfidn(IDLoc,
true,
2139 return parseDirectiveErrorIfe(IDLoc,
true);
2141 return parseDirectiveErrorIfe(IDLoc,
false);
2143 return parseDirectiveRadix(IDLoc);
2145 return parseDirectiveEcho(IDLoc);
2148 return Error(IDLoc,
"unknown directive");
2152 auto IDIt = Structs.
find(IDVal.
lower());
2153 if (IDIt != Structs.
end())
2154 return parseDirectiveStructValue(IDIt->getValue(), IDVal,
2158 const AsmToken nextTok = getTok();
2159 const StringRef nextVal = nextTok.
getString();
2160 const SMLoc nextLoc = nextTok.
getLoc();
2162 const AsmToken afterNextTok = peekTok();
2173 getTargetParser().flushPendingInstructions(getStreamer());
2179 return parseDirectiveEnds(IDVal, IDLoc);
2184 std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
2186 if (Handler.first) {
2189 return (*Handler.second)(Handler.first, nextVal, nextLoc);
2194 DirKindIt = DirectiveKindMap.find(nextVal.
lower());
2195 DirKind = (DirKindIt == DirectiveKindMap.end())
2197 : DirKindIt->getValue();
2204 return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
2206 Lex(DoNotExpandMacros);
2207 return parseDirectiveEquate(nextVal, IDVal, DirKind, IDLoc);
2218 return parseDirectiveNamedValue(nextVal, 1, IDVal, IDLoc);
2229 return parseDirectiveNamedValue(nextVal, 2, IDVal, IDLoc);
2240 return parseDirectiveNamedValue(nextVal, 4, IDVal, IDLoc);
2250 return parseDirectiveNamedValue(nextVal, 6, IDVal, IDLoc);
2261 return parseDirectiveNamedValue(nextVal, 8, IDVal, IDLoc);
2264 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEsingle(), 4,
2268 return parseDirectiveNamedRealValue(nextVal, APFloat::IEEEdouble(), 8,
2272 return parseDirectiveNamedRealValue(nextVal, APFloat::x87DoubleExtended(),
2277 return parseDirectiveStruct(nextVal, DirKind, IDVal, IDLoc);
2280 return parseDirectiveEnds(IDVal, IDLoc);
2283 return parseDirectiveMacro(IDVal, IDLoc);
2287 auto NextIt = Structs.
find(nextVal.
lower());
2288 if (NextIt != Structs.
end()) {
2290 return parseDirectiveNamedStructValue(NextIt->getValue(),
2291 nextVal, nextLoc, IDVal);
2295 if (ParsingMSInlineAsm && (IDVal ==
"_emit" || IDVal ==
"__emit" ||
2296 IDVal ==
"_EMIT" || IDVal ==
"__EMIT"))
2297 return parseDirectiveMSEmit(IDLoc, Info, IDVal.
size());
2300 if (ParsingMSInlineAsm && (IDVal ==
"align" || IDVal ==
"ALIGN"))
2301 return parseDirectiveMSAlign(IDLoc, Info);
2303 if (ParsingMSInlineAsm && (IDVal ==
"even" || IDVal ==
"EVEN"))
2305 if (checkForValidSection())
2309 std::string OpcodeStr = IDVal.
lower();
2310 ParseInstructionInfo IInfo(
Info.AsmRewrites);
2311 bool ParseHadError = getTargetParser().parseInstruction(IInfo, OpcodeStr, ID,
2312 Info.ParsedOperands);
2313 Info.ParseError = ParseHadError;
2316 if (getShowParsedOperands()) {
2317 SmallString<256> Str;
2318 raw_svector_ostream OS(Str);
2319 OS <<
"parsed instruction: [";
2320 for (
unsigned i = 0; i !=
Info.ParsedOperands.size(); ++i) {
2323 Info.ParsedOperands[i]->print(OS, MAI);
2331 if (hasPendingError() || ParseHadError)
2335 if (!ParseHadError) {
2337 if (getTargetParser().matchAndEmitInstruction(
2338 IDLoc,
Info.Opcode,
Info.ParsedOperands, Out, ErrorInfo,
2339 getTargetParser().isParsingMSInlineAsm()))
2346bool MasmParser::parseCurlyBlockScope(
2347 SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
2352 SMLoc StartLoc = Lexer.getLoc();
2365bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
2370 "Lexing Cpp line comment: Expected Integer");
2371 int64_t LineNumber = getTok().getIntVal();
2374 "Lexing Cpp line comment: Expected String");
2375 StringRef
Filename = getTok().getString();
2383 CppHashInfo.Loc =
L;
2385 CppHashInfo.LineNumber = LineNumber;
2386 CppHashInfo.Buf = CurBuffer;
2387 if (FirstCppHashFilename.
empty())
2394void MasmParser::DiagHandler(
const SMDiagnostic &Diag,
void *
Context) {
2395 const MasmParser *Parser =
static_cast<const MasmParser *
>(
Context);
2396 raw_ostream &OS =
errs();
2399 SMLoc DiagLoc = Diag.
getLoc();
2401 unsigned CppHashBuf =
2402 Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashInfo.Loc);
2406 if (!Parser->SavedDiagHandler)
2412 if (!Parser->CppHashInfo.LineNumber || &DiagSrcMgr != &Parser->SrcMgr ||
2413 DiagBuf != CppHashBuf) {
2414 if (Parser->SavedDiagHandler)
2415 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
2417 Diag.
print(
nullptr, OS);
2424 const std::string &
Filename = std::string(Parser->CppHashInfo.Filename);
2427 int CppHashLocLineNo =
2428 Parser->SrcMgr.FindLineNumber(Parser->CppHashInfo.Loc, CppHashBuf);
2430 Parser->CppHashInfo.LineNumber - 1 + (DiagLocLineNo - CppHashLocLineNo);
2436 if (Parser->SavedDiagHandler)
2437 Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
2439 NewDiag.print(
nullptr, OS);
2445 return isAlnum(
C) ||
C ==
'_' ||
C ==
'$' ||
C ==
'@' ||
C ==
'?';
2448bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
2451 const std::vector<std::string> &Locals, SMLoc L) {
2453 if (NParameters !=
A.size())
2454 return Error(L,
"Wrong number of arguments");
2455 StringMap<std::string> LocalSymbols;
2458 for (StringRef
Local : Locals) {
2459 raw_string_ostream LocalName(Name);
2466 std::optional<char> CurrentQuote;
2467 while (!Body.
empty()) {
2469 std::size_t End = Body.
size(), Pos = 0;
2470 std::size_t IdentifierPos = End;
2471 for (; Pos != End; ++Pos) {
2474 if (Body[Pos] ==
'&')
2479 if (IdentifierPos == End)
2480 IdentifierPos = Pos;
2482 IdentifierPos = End;
2486 if (!CurrentQuote) {
2487 if (Body[Pos] ==
'\'' || Body[Pos] ==
'"')
2488 CurrentQuote = Body[Pos];
2489 }
else if (Body[Pos] == CurrentQuote) {
2490 if (Pos + 1 != End && Body[Pos + 1] == CurrentQuote) {
2495 CurrentQuote.reset();
2499 if (IdentifierPos != End) {
2502 Pos = IdentifierPos;
2503 IdentifierPos = End;
2507 OS << Body.
slice(0, Pos);
2514 bool InitialAmpersand = (Body[
I] ==
'&');
2515 if (InitialAmpersand) {
2522 const char *Begin = Body.
data() + Pos;
2524 const std::string ArgumentLower =
Argument.lower();
2528 if (Parameters[Index].
Name.equals_insensitive(ArgumentLower))
2531 if (Index == NParameters) {
2532 if (InitialAmpersand)
2534 auto it = LocalSymbols.
find(ArgumentLower);
2535 if (it != LocalSymbols.
end())
2541 for (
const AsmToken &Token :
A[Index]) {
2551 OS << Token.getIntVal();
2553 OS << Token.getString();
2557 if (Pos < End && Body[Pos] ==
'&') {
2568bool MasmParser::parseMacroArgument(
const MCAsmMacroParameter *MP,
2569 MCAsmMacroArgument &MA,
2572 if (Lexer.isNot(EndTok)) {
2573 SmallVector<StringRef, 1> Str = parseStringRefsTo(EndTok);
2574 for (StringRef S : Str) {
2581 SMLoc StrLoc = Lexer.getLoc(), EndLoc;
2583 const char *StrChar = StrLoc.
getPointer() + 1;
2584 const char *EndChar = EndLoc.
getPointer() - 1;
2585 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
2592 unsigned ParenLevel = 0;
2596 return TokError(
"unexpected token");
2613 MA.push_back(getTok());
2617 if (ParenLevel != 0)
2618 return TokError(
"unbalanced parentheses in argument");
2620 if (MA.empty() && MP) {
2622 return TokError(
"missing value for required parameter '" + MP->
Name +
2632bool MasmParser::parseMacroArguments(
const MCAsmMacro *M,
2633 MCAsmMacroArguments &
A,
2635 const unsigned NParameters =
M ?
M->Parameters.size() : 0;
2636 bool NamedParametersFound =
false;
2637 SmallVector<SMLoc, 4> FALocs;
2639 A.resize(NParameters);
2640 FALocs.
resize(NParameters);
2645 for (
unsigned Parameter = 0; !NParameters ||
Parameter < NParameters;
2647 SMLoc IDLoc = Lexer.getLoc();
2648 MCAsmMacroParameter FA;
2651 if (parseIdentifier(FA.
Name))
2652 return Error(IDLoc,
"invalid argument identifier for formal argument");
2655 return TokError(
"expected '=' after formal parameter identifier");
2659 NamedParametersFound =
true;
2662 if (NamedParametersFound && FA.
Name.
empty())
2663 return Error(IDLoc,
"cannot mix positional and keyword arguments");
2667 assert(M &&
"expected macro to be defined");
2669 for (FAI = 0; FAI < NParameters; ++FAI)
2670 if (
M->Parameters[FAI].Name == FA.
Name)
2673 if (FAI >= NParameters) {
2674 return Error(IDLoc,
"parameter named '" + FA.
Name +
2675 "' does not exist for macro '" +
M->Name +
"'");
2679 const MCAsmMacroParameter *MP =
nullptr;
2680 if (M && PI < NParameters)
2681 MP = &
M->Parameters[PI];
2683 SMLoc StrLoc = Lexer.getLoc();
2686 const MCExpr *AbsoluteExp;
2690 if (parseExpression(AbsoluteExp, EndLoc))
2692 if (!AbsoluteExp->evaluateAsAbsolute(
Value,
2693 getStreamer().getAssemblerPtr()))
2694 return Error(StrLoc,
"expected absolute expression");
2698 StringRef(StrChar, EndChar - StrChar),
Value);
2699 FA.
Value.push_back(newToken);
2700 }
else if (parseMacroArgument(MP, FA.
Value, EndTok)) {
2702 return addErrorSuffix(
" in '" +
M->Name +
"' macro");
2707 if (!FA.
Value.empty()) {
2712 if (FALocs.
size() <= PI)
2715 FALocs[PI] = Lexer.getLoc();
2721 if (Lexer.is(EndTok)) {
2723 for (
unsigned FAI = 0; FAI < NParameters; ++FAI) {
2725 if (
M->Parameters[FAI].Required) {
2726 Error(FALocs[FAI].
isValid() ? FALocs[FAI] : Lexer.getLoc(),
2727 "missing value for required parameter "
2729 M->Parameters[FAI].Name +
"' in macro '" +
M->Name +
"'");
2733 if (!
M->Parameters[FAI].Value.empty())
2734 A[FAI] =
M->Parameters[FAI].Value;
2744 return TokError(
"too many positional arguments");
2747bool MasmParser::handleMacroEntry(
const MCAsmMacro *M, SMLoc NameLoc,
2752 if (ActiveMacros.size() == MaxNestingDepth) {
2753 std::ostringstream MaxNestingDepthError;
2754 MaxNestingDepthError <<
"macros cannot be nested more than "
2755 << MaxNestingDepth <<
" levels deep."
2756 <<
" Use -asm-macro-max-nesting-depth to increase "
2758 return TokError(MaxNestingDepthError.str());
2761 MCAsmMacroArguments
A;
2762 if (parseMacroArguments(M,
A, ArgumentEndTok) || parseToken(ArgumentEndTok))
2767 SmallString<256> Buf;
2768 StringRef Body =
M->Body;
2769 raw_svector_ostream OS(Buf);
2771 if (expandMacro(OS, Body,
M->Parameters,
A,
M->Locals, getTok().getLoc()))
2778 std::unique_ptr<MemoryBuffer> Instantiation =
2783 MacroInstantiation *
MI =
new MacroInstantiation{
2784 NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()};
2785 ActiveMacros.push_back(
MI);
2787 ++NumOfMacroInstantiations;
2792 EndStatementAtEOFStack.push_back(
true);
2798void MasmParser::handleMacroExit() {
2800 EndStatementAtEOFStack.pop_back();
2801 jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer,
2802 EndStatementAtEOFStack.back());
2806 delete ActiveMacros.back();
2807 ActiveMacros.pop_back();
2810bool MasmParser::handleMacroInvocation(
const MCAsmMacro *M, SMLoc NameLoc) {
2812 return Error(NameLoc,
"cannot invoke macro procedure as function");
2815 "' requires arguments in parentheses") ||
2820 std::string ExitValue;
2823 ParseStatementInfo
Info(&AsmStrRewrites);
2824 bool HasError = parseStatement(Info,
nullptr);
2826 if (!HasError &&
Info.ExitValue) {
2827 ExitValue = std::move(*
Info.ExitValue);
2834 if (HasError && !hasPendingError() && Lexer.getTok().is(
AsmToken::Error))
2838 printPendingErrors();
2841 if (HasError && !getLexer().justConsumedEOL())
2842 eatToEndOfStatement();
2847 std::unique_ptr<MemoryBuffer> MacroValue =
2855 EndStatementAtEOFStack.push_back(
false);
2864bool MasmParser::parseIdentifier(StringRef &Res,
2865 IdentifierPositionKind Position) {
2872 SMLoc PrefixLoc = getLexer().getLoc();
2876 AsmToken nextTok = peekTok(
false);
2889 StringRef(PrefixLoc.
getPointer(), getTok().getIdentifier().
size() + 1);
2897 Res = getTok().getIdentifier();
2901 ExpandKind ExpandNextToken = ExpandMacros;
2902 if (Position == StartOfStatement &&
2903 StringSwitch<bool>(Res)
2904 .CaseLower(
"echo",
true)
2905 .CasesLower({
"ifdef",
"ifndef",
"elseifdef",
"elseifndef"},
true)
2907 ExpandNextToken = DoNotExpandMacros;
2909 Lex(ExpandNextToken);
2919bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
2920 DirectiveKind DirKind, SMLoc NameLoc) {
2921 auto BuiltinIt = BuiltinSymbolMap.find(
Name.lower());
2922 if (BuiltinIt != BuiltinSymbolMap.end())
2923 return Error(NameLoc,
"cannot redefine a built-in symbol");
2926 if (Var.Name.empty()) {
2930 SMLoc StartLoc = Lexer.getLoc();
2936 if (!parseTextList(
Value, IDVal))
2937 return setTextVariable(Var, Name,
Value, NameLoc, Variable::REDEFINABLE);
2938 return TokError(
"expected <text> in '" + Twine(IDVal) +
"' directive");
2945 if (!parseAngleBracketString(
Value))
2946 return setTextVariable(Var, Name,
Value, NameLoc, Variable::REDEFINABLE);
2956 if (parseExpression(Expr, EndLoc))
2957 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
2958 StringRef ExprAsString = StringRef(
2962 if (!Expr->evaluateAsAbsolute(
Value, getStreamer().getAssemblerPtr())) {
2963 if (DirKind == DK_ASSIGN)
2966 "expected absolute expression; not all symbols have known values",
2967 {StartLoc, EndLoc});
2970 return setTextVariable(Var, Name, ExprAsString, NameLoc,
2971 Variable::REDEFINABLE);
2974 auto *Sym =
static_cast<MCSymbolCOFF *
>(
getContext().parseSymbol(Var.Name));
2975 const MCConstantExpr *PrevValue =
2979 if (Var.IsText || !PrevValue || PrevValue->
getValue() !=
Value) {
2980 switch (Var.Redefinable) {
2981 case Variable::NOT_REDEFINABLE:
2982 return Error(getTok().getLoc(),
"invalid variable redefinition");
2983 case Variable::WARN_ON_REDEFINITION:
2984 if (
Warning(NameLoc,
"redefining '" + Name +
2985 "', already defined on the command line"))
2994 Var.TextValue.clear();
2995 Var.Redefinable = (DirKind == DK_ASSIGN) ? Variable::REDEFINABLE
2998 Sym->
setRedefinable(Var.Redefinable != Variable::NOT_REDEFINABLE);
3000 Sym->setExternal(
false);
3005bool MasmParser::parseEscapedString(std::string &
Data) {
3010 char Quote = getTok().getString().front();
3011 StringRef Str = getTok().getStringContents();
3012 Data.reserve(Str.size());
3013 for (
size_t i = 0, e = Str.size(); i != e; ++i) {
3014 Data.push_back(Str[i]);
3015 if (Str[i] == Quote) {
3019 if (i + 1 == Str.size())
3020 return Error(getTok().getLoc(),
"missing quotation mark in string");
3021 if (Str[i + 1] == Quote)
3030bool MasmParser::parseAngleBracketString(std::string &
Data) {
3031 SMLoc EndLoc, StartLoc = getTok().getLoc();
3033 const char *StartChar = StartLoc.
getPointer() + 1;
3034 const char *EndChar = EndLoc.
getPointer() - 1;
3035 jumpToLoc(EndLoc, CurBuffer, EndStatementAtEOFStack.back());
3046bool MasmParser::parseTextItem(std::string &
Data) {
3047 switch (getTok().getKind()) {
3054 Data = std::to_string(Res);
3061 return parseAngleBracketString(
Data);
3065 SMLoc StartLoc = getTok().getLoc();
3066 if (parseIdentifier(ID))
3070 bool Expanded =
false;
3073 auto BuiltinIt = BuiltinSymbolMap.find(
ID.lower());
3074 if (BuiltinIt != BuiltinSymbolMap.end()) {
3075 std::optional<std::string> BuiltinText =
3076 evaluateBuiltinTextMacro(BuiltinIt->getValue(), StartLoc);
3081 Data = std::move(*BuiltinText);
3088 auto BuiltinFuncIt = BuiltinFunctionMap.find(
ID.lower());
3089 if (BuiltinFuncIt != BuiltinFunctionMap.end()) {
3091 if (evaluateBuiltinMacroFunction(BuiltinFuncIt->getValue(), ID,
Data)) {
3100 auto VarIt = Variables.
find(
ID.lower());
3101 if (VarIt != Variables.
end()) {
3102 const Variable &Var = VarIt->getValue();
3107 Data = Var.TextValue;
3129bool MasmParser::parseTextList(std::string &Result, StringRef IDVal) {
3130 std::string TextItem;
3131 if (parseTextItem(TextItem))
3135 Lex(DoNotExpandMacros);
3137 Lex(DoNotExpandMacros);
3138 if (parseTextItem(TextItem))
3139 return TokError(
"expected text item in '" + Twine(IDVal) +
"' directive");
3146bool MasmParser::setTextVariable(Variable &Var, StringRef Name, StringRef
Value,
3148 Variable::RedefinableKind Redefinable) {
3149 if (!Var.IsText || Var.TextValue !=
Value) {
3150 switch (Var.Redefinable) {
3151 case Variable::NOT_REDEFINABLE:
3152 return Error(getTok().getLoc(),
"invalid variable redefinition");
3153 case Variable::WARN_ON_REDEFINITION:
3154 if (
Warning(NameLoc,
"redefining '" + Name +
3155 "', already defined on the command line"))
3163 Var.TextValue =
Value.str();
3164 Var.Redefinable = Redefinable;
3170bool MasmParser::parseDirectiveAscii(StringRef IDVal,
bool ZeroTerminated) {
3171 auto parseOp = [&]() ->
bool {
3173 if (checkForValidSection() || parseEscapedString(
Data))
3175 getStreamer().emitBytes(
Data);
3177 getStreamer().emitBytes(StringRef(
"\0", 1));
3181 if (parseMany(parseOp))
3182 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3186bool MasmParser::emitIntValue(
const MCExpr *
Value,
unsigned Size) {
3190 int64_t IntValue = MCE->getValue();
3192 return Error(MCE->getLoc(),
"out of range literal value");
3193 getStreamer().emitIntValue(IntValue,
Size);
3198 getStreamer().emitIntValue(0,
Size);
3206bool MasmParser::parseScalarInitializer(
unsigned Size,
3207 SmallVectorImpl<const MCExpr *> &
Values,
3208 unsigned StringPadLength) {
3211 if (parseEscapedString(
Value))
3214 for (
const unsigned char CharVal :
Value)
3218 for (
size_t i =
Value.size(); i < StringPadLength; ++i)
3221 const MCExpr *
Value;
3222 if (parseExpression(
Value))
3225 getTok().getString().equals_insensitive(
"dup")) {
3230 "cannot repeat value a non-constant number of times");
3231 const int64_t Repetitions = MCE->
getValue();
3232 if (Repetitions < 0)
3234 "cannot repeat value a negative number of times");
3238 "parentheses required for 'dup' contents") ||
3239 parseScalarInstList(
Size, DuplicatedValues) || parseRParen())
3242 for (
int i = 0; i < Repetitions; ++i)
3251bool MasmParser::parseScalarInstList(
unsigned Size,
3252 SmallVectorImpl<const MCExpr *> &
Values,
3254 while (getTok().
isNot(EndToken) &&
3267bool MasmParser::emitIntegralValues(
unsigned Size,
unsigned *
Count) {
3269 if (checkForValidSection() || parseScalarInstList(
Size,
Values))
3281bool MasmParser::addIntegralField(StringRef Name,
unsigned Size) {
3282 StructInfo &
Struct = StructInProgress.
back();
3284 IntFieldInfo &IntInfo =
Field.Contents.IntInfo;
3288 if (parseScalarInstList(
Size, IntInfo.Values))
3291 Field.SizeOf =
Field.Type * IntInfo.Values.size();
3292 Field.LengthOf = IntInfo.Values.size();
3295 Struct.NextOffset = FieldEnd;
3303bool MasmParser::parseDirectiveValue(StringRef IDVal,
unsigned Size) {
3304 if (StructInProgress.
empty()) {
3306 if (emitIntegralValues(
Size))
3307 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3308 }
else if (addIntegralField(
"",
Size)) {
3309 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3317bool MasmParser::parseDirectiveNamedValue(StringRef TypeName,
unsigned Size,
3318 StringRef Name, SMLoc NameLoc) {
3319 if (StructInProgress.
empty()) {
3322 getStreamer().emitLabel(Sym);
3325 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3333 }
else if (addIntegralField(Name,
Size)) {
3334 return addErrorSuffix(
" in '" + Twine(TypeName) +
"' directive");
3340bool MasmParser::parseRealValue(
const fltSemantics &Semantics, APInt &Res) {
3346 SignLoc = getLexer().getLoc();
3350 SignLoc = getLexer().getLoc();
3355 return TokError(Lexer.getErr());
3358 return TokError(
"unexpected token in directive");
3362 StringRef IDVal = getTok().getString();
3371 return TokError(
"invalid floating point literal");
3375 unsigned SizeInBits =
Value.getSizeInBits(Semantics);
3376 if (SizeInBits != (IDVal.
size() << 2))
3377 return TokError(
"invalid floating point literal");
3382 Res = APInt(SizeInBits, IDVal, 16);
3384 return Warning(SignLoc,
"MASM-style hex floats ignore explicit sign");
3387 Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven)
3389 return TokError(
"invalid floating point literal");
3397 Res =
Value.bitcastToAPInt();
3402bool MasmParser::parseRealInstList(
const fltSemantics &Semantics,
3403 SmallVectorImpl<APInt> &ValuesAsInt,
3405 while (getTok().
isNot(EndToken) ||
3408 const AsmToken NextTok = peekTok();
3411 const MCExpr *
Value;
3417 "cannot repeat value a non-constant number of times");
3418 const int64_t Repetitions = MCE->
getValue();
3419 if (Repetitions < 0)
3421 "cannot repeat value a negative number of times");
3425 "parentheses required for 'dup' contents") ||
3426 parseRealInstList(Semantics, DuplicatedValues) || parseRParen())
3429 for (
int i = 0; i < Repetitions; ++i)
3430 ValuesAsInt.
append(DuplicatedValues.
begin(), DuplicatedValues.
end());
3433 if (parseRealValue(Semantics, AsInt))
3448bool MasmParser::emitRealValues(
const fltSemantics &Semantics,
3450 if (checkForValidSection())
3454 if (parseRealInstList(Semantics, ValuesAsInt))
3457 for (
const APInt &AsInt : ValuesAsInt) {
3458 getStreamer().emitIntValue(AsInt);
3461 *
Count = ValuesAsInt.size();
3466bool MasmParser::addRealField(StringRef Name,
const fltSemantics &Semantics,
3468 StructInfo &
Struct = StructInProgress.
back();
3470 RealFieldInfo &RealInfo =
Field.Contents.RealInfo;
3474 if (parseRealInstList(Semantics, RealInfo.AsIntValues))
3477 Field.Type = RealInfo.AsIntValues.back().getBitWidth() / 8;
3478 Field.LengthOf = RealInfo.AsIntValues.size();
3483 Struct.NextOffset = FieldEnd;
3491bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
3492 const fltSemantics &Semantics,
3494 if (StructInProgress.
empty()) {
3496 if (emitRealValues(Semantics))
3497 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3498 }
else if (addRealField(
"", Semantics,
Size)) {
3499 return addErrorSuffix(
" in '" + Twine(IDVal) +
"' directive");
3506bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
3507 const fltSemantics &Semantics,
3508 unsigned Size, StringRef Name,
3510 if (StructInProgress.
empty()) {
3513 getStreamer().emitLabel(Sym);
3515 if (emitRealValues(Semantics, &
Count))
3516 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3524 }
else if (addRealField(Name, Semantics,
Size)) {
3525 return addErrorSuffix(
" in '" + TypeName +
"' directive");
3530bool MasmParser::parseOptionalAngleBracketOpen() {
3531 const AsmToken Tok = getTok();
3533 AngleBracketDepth++;
3537 AngleBracketDepth++;
3541 AngleBracketDepth++;
3548bool MasmParser::parseAngleBracketClose(
const Twine &
Msg) {
3549 const AsmToken Tok = getTok();
3555 AngleBracketDepth--;
3559bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3560 const IntFieldInfo &Contents,
3561 FieldInitializer &Initializer) {
3562 SMLoc Loc = getTok().getLoc();
3567 return Error(Loc,
"Cannot initialize scalar field with array value");
3571 }
else if (parseOptionalAngleBracketOpen()) {
3573 return Error(Loc,
"Cannot initialize scalar field with array value");
3575 parseAngleBracketClose())
3577 }
else if (
Field.LengthOf > 1 &&
Field.Type > 1) {
3578 return Error(Loc,
"Cannot initialize array field with scalar value");
3579 }
else if (parseScalarInitializer(
Field.Type,
Values,
3585 return Error(Loc,
"Initializer too long for field; expected at most " +
3586 std::to_string(
Field.LengthOf) +
" elements, got " +
3587 std::to_string(
Values.size()));
3590 Values.append(Contents.Values.begin() +
Values.size(), Contents.Values.end());
3592 Initializer = FieldInitializer(std::move(
Values));
3596bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3597 const RealFieldInfo &Contents,
3598 FieldInitializer &Initializer) {
3599 const fltSemantics *Semantics;
3600 switch (
Field.Type) {
3602 Semantics = &APFloat::IEEEsingle();
3605 Semantics = &APFloat::IEEEdouble();
3608 Semantics = &APFloat::x87DoubleExtended();
3614 SMLoc Loc = getTok().getLoc();
3618 if (
Field.LengthOf == 1)
3619 return Error(Loc,
"Cannot initialize scalar field with array value");
3623 }
else if (parseOptionalAngleBracketOpen()) {
3624 if (
Field.LengthOf == 1)
3625 return Error(Loc,
"Cannot initialize scalar field with array value");
3627 parseAngleBracketClose())
3629 }
else if (
Field.LengthOf > 1) {
3630 return Error(Loc,
"Cannot initialize array field with scalar value");
3633 if (parseRealValue(*Semantics, AsIntValues.
back()))
3637 if (AsIntValues.
size() >
Field.LengthOf) {
3638 return Error(Loc,
"Initializer too long for field; expected at most " +
3639 std::to_string(
Field.LengthOf) +
" elements, got " +
3640 std::to_string(AsIntValues.
size()));
3643 AsIntValues.
append(Contents.AsIntValues.begin() + AsIntValues.
size(),
3644 Contents.AsIntValues.end());
3646 Initializer = FieldInitializer(std::move(AsIntValues));
3650bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3651 const StructFieldInfo &Contents,
3652 FieldInitializer &Initializer) {
3653 SMLoc Loc = getTok().getLoc();
3655 std::vector<StructInitializer> Initializers;
3656 if (
Field.LengthOf > 1) {
3658 if (parseStructInstList(Contents.Structure, Initializers,
3662 }
else if (parseOptionalAngleBracketOpen()) {
3663 if (parseStructInstList(Contents.Structure, Initializers,
3665 parseAngleBracketClose())
3668 return Error(Loc,
"Cannot initialize array field with scalar value");
3671 Initializers.emplace_back();
3672 if (parseStructInitializer(Contents.Structure, Initializers.back()))
3676 if (Initializers.size() >
Field.LengthOf) {
3677 return Error(Loc,
"Initializer too long for field; expected at most " +
3678 std::to_string(
Field.LengthOf) +
" elements, got " +
3679 std::to_string(Initializers.size()));
3683 Initializers.size()));
3685 Initializer = FieldInitializer(std::move(Initializers), Contents.Structure);
3689bool MasmParser::parseFieldInitializer(
const FieldInfo &
Field,
3690 FieldInitializer &Initializer) {
3691 switch (
Field.Contents.FT) {
3693 return parseFieldInitializer(
Field,
Field.Contents.IntInfo, Initializer);
3695 return parseFieldInitializer(
Field,
Field.Contents.RealInfo, Initializer);
3697 return parseFieldInitializer(
Field,
Field.Contents.StructInfo, Initializer);
3702bool MasmParser::parseStructInitializer(
const StructInfo &Structure,
3703 StructInitializer &Initializer) {
3704 const AsmToken FirstToken = getTok();
3706 std::optional<AsmToken::TokenKind> EndToken;
3709 }
else if (parseOptionalAngleBracketOpen()) {
3711 AngleBracketDepth++;
3718 return Error(FirstToken.
getLoc(),
"Expected struct initializer");
3721 auto &FieldInitializers = Initializer.FieldInitializers;
3722 size_t FieldIndex = 0;
3725 while (getTok().
isNot(*EndToken) && FieldIndex < Structure.Fields.size()) {
3726 const FieldInfo &
Field = Structure.Fields[FieldIndex++];
3730 FieldInitializers.push_back(
Field.Contents);
3734 FieldInitializers.emplace_back(
Field.Contents.FT);
3735 if (parseFieldInitializer(
Field, FieldInitializers.back()))
3739 SMLoc CommaLoc = getTok().getLoc();
3742 if (FieldIndex == Structure.Fields.size())
3743 return Error(CommaLoc,
"'" + Structure.Name +
3744 "' initializer initializes too many fields");
3750 FieldInitializers.push_back(
Field.Contents);
3754 return parseAngleBracketClose();
3756 return parseToken(*EndToken);
3762bool MasmParser::parseStructInstList(
3763 const StructInfo &Structure, std::vector<StructInitializer> &Initializers,
3765 while (getTok().
isNot(EndToken) ||
3768 const AsmToken NextTok = peekTok();
3771 const MCExpr *
Value;
3777 "cannot repeat value a non-constant number of times");
3778 const int64_t Repetitions = MCE->
getValue();
3779 if (Repetitions < 0)
3781 "cannot repeat value a negative number of times");
3783 std::vector<StructInitializer> DuplicatedValues;
3785 "parentheses required for 'dup' contents") ||
3786 parseStructInstList(Structure, DuplicatedValues) || parseRParen())
3789 for (
int i = 0; i < Repetitions; ++i)
3792 Initializers.emplace_back();
3793 if (parseStructInitializer(Structure, Initializers.back()))
3806bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3807 const IntFieldInfo &Contents) {
3809 for (
const MCExpr *
Value : Contents.Values) {
3816bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3817 const RealFieldInfo &Contents) {
3818 for (
const APInt &AsInt : Contents.AsIntValues) {
3825bool MasmParser::emitFieldValue(
const FieldInfo &
Field,
3826 const StructFieldInfo &Contents) {
3827 for (
const auto &Initializer : Contents.Initializers) {
3829 for (
const auto &SubField : Contents.Structure.Fields) {
3830 getStreamer().emitZeros(SubField.Offset -
Offset);
3831 Offset = SubField.Offset + SubField.SizeOf;
3832 emitFieldInitializer(SubField, Initializer.FieldInitializers[Index++]);
3838bool MasmParser::emitFieldValue(
const FieldInfo &
Field) {
3839 switch (
Field.Contents.FT) {
3841 return emitFieldValue(
Field,
Field.Contents.IntInfo);
3843 return emitFieldValue(
Field,
Field.Contents.RealInfo);
3845 return emitFieldValue(
Field,
Field.Contents.StructInfo);
3850bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3851 const IntFieldInfo &Contents,
3852 const IntFieldInfo &Initializer) {
3853 for (
const auto &
Value : Initializer.Values) {
3858 for (
const auto &
Value :
3866bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3867 const RealFieldInfo &Contents,
3868 const RealFieldInfo &Initializer) {
3869 for (
const auto &AsInt : Initializer.AsIntValues) {
3874 for (
const auto &AsInt :
3882bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3883 const StructFieldInfo &Contents,
3884 const StructFieldInfo &Initializer) {
3885 for (
const auto &Init : Initializer.Initializers) {
3886 if (emitStructInitializer(Contents.Structure, Init))
3891 Initializer.Initializers.size())) {
3892 if (emitStructInitializer(Contents.Structure, Init))
3898bool MasmParser::emitFieldInitializer(
const FieldInfo &
Field,
3899 const FieldInitializer &Initializer) {
3900 switch (
Field.Contents.FT) {
3902 return emitFieldInitializer(
Field,
Field.Contents.IntInfo,
3903 Initializer.IntInfo);
3905 return emitFieldInitializer(
Field,
Field.Contents.RealInfo,
3906 Initializer.RealInfo);
3908 return emitFieldInitializer(
Field,
Field.Contents.StructInfo,
3909 Initializer.StructInfo);
3914bool MasmParser::emitStructInitializer(
const StructInfo &Structure,
3915 const StructInitializer &Initializer) {
3916 if (!Structure.Initializable)
3917 return Error(getLexer().getLoc(),
3918 "cannot initialize a value of type '" + Structure.Name +
3919 "'; 'org' was used in the type's declaration");
3921 for (
const auto &Init : Initializer.FieldInitializers) {
3922 const auto &
Field = Structure.Fields[
Index++];
3925 if (emitFieldInitializer(
Field, Init))
3930 Structure.Fields, Initializer.FieldInitializers.size())) {
3933 if (emitFieldValue(
Field))
3937 if (
Offset != Structure.Size)
3938 getStreamer().emitZeros(Structure.Size -
Offset);
3943bool MasmParser::emitStructValues(
const StructInfo &Structure,
3945 std::vector<StructInitializer> Initializers;
3946 if (parseStructInstList(Structure, Initializers))
3949 for (
const auto &Initializer : Initializers) {
3950 if (emitStructInitializer(Structure, Initializer))
3955 *
Count = Initializers.size();
3960bool MasmParser::addStructField(StringRef Name,
const StructInfo &Structure) {
3961 StructInfo &OwningStruct = StructInProgress.
back();
3963 OwningStruct.addField(Name, FT_STRUCT, Structure.AlignmentSize);
3964 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
3966 StructInfo.Structure = Structure;
3967 Field.Type = Structure.Size;
3969 if (parseStructInstList(Structure, StructInfo.Initializers))
3972 Field.LengthOf = StructInfo.Initializers.size();
3976 if (!OwningStruct.IsUnion) {
3977 OwningStruct.NextOffset = FieldEnd;
3979 OwningStruct.Size = std::max(OwningStruct.Size, FieldEnd);
3987bool MasmParser::parseDirectiveStructValue(
const StructInfo &Structure,
3988 StringRef Directive, SMLoc DirLoc) {
3989 if (StructInProgress.
empty()) {
3990 if (emitStructValues(Structure))
3992 }
else if (addStructField(
"", Structure)) {
3993 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4001bool MasmParser::parseDirectiveNamedStructValue(
const StructInfo &Structure,
4002 StringRef Directive,
4003 SMLoc DirLoc, StringRef Name) {
4004 if (StructInProgress.
empty()) {
4007 getStreamer().emitLabel(Sym);
4009 if (emitStructValues(Structure, &
Count))
4012 Type.Name = Structure.Name;
4014 Type.ElementSize = Structure.Size;
4017 }
else if (addStructField(Name, Structure)) {
4018 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4030bool MasmParser::parseDirectiveStruct(StringRef Directive,
4031 DirectiveKind DirKind, StringRef Name,
4035 AsmToken NextTok = getTok();
4036 int64_t AlignmentValue = 1;
4039 parseAbsoluteExpression(AlignmentValue)) {
4040 return addErrorSuffix(
" in alignment value for '" + Twine(Directive) +
4044 return Error(NextTok.
getLoc(),
"alignment must be a power of two; was " +
4045 std::to_string(AlignmentValue));
4051 QualifierLoc = getTok().getLoc();
4052 if (parseIdentifier(Qualifier))
4053 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4054 if (!
Qualifier.equals_insensitive(
"nonunique"))
4055 return Error(QualifierLoc,
"Unrecognized qualifier for '" +
4057 "' directive; expected none or NONUNIQUE");
4061 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4063 StructInProgress.
emplace_back(Name, DirKind == DK_UNION, AlignmentValue);
4071bool MasmParser::parseDirectiveNestedStruct(StringRef Directive,
4072 DirectiveKind DirKind) {
4073 if (StructInProgress.
empty())
4074 return TokError(
"missing name in top-level '" + Twine(Directive) +
4079 Name = getTok().getIdentifier();
4083 return addErrorSuffix(
" in '" + Twine(Directive) +
"' directive");
4087 StructInProgress.
reserve(StructInProgress.
size() + 1);
4088 StructInProgress.
emplace_back(Name, DirKind == DK_UNION,
4089 StructInProgress.
back().Alignment);
4093bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
4094 if (StructInProgress.
empty())
4095 return Error(NameLoc,
"ENDS directive without matching STRUC/STRUCT/UNION");
4096 if (StructInProgress.
size() > 1)
4097 return Error(NameLoc,
"unexpected name in nested ENDS directive");
4098 if (StructInProgress.
back().Name.compare_insensitive(Name))
4099 return Error(NameLoc,
"mismatched name in ENDS directive; expected '" +
4100 StructInProgress.
back().Name +
"'");
4101 StructInfo Structure = StructInProgress.
pop_back_val();
4105 Structure.Size, std::min(Structure.Alignment, Structure.AlignmentSize));
4106 Structs[
Name.lower()] = std::move(Structure);
4109 return addErrorSuffix(
" in ENDS directive");
4114bool MasmParser::parseDirectiveNestedEnds() {
4115 if (StructInProgress.
empty())
4116 return TokError(
"ENDS directive without matching STRUC/STRUCT/UNION");
4117 if (StructInProgress.
size() == 1)
4118 return TokError(
"missing name in top-level ENDS directive");
4121 return addErrorSuffix(
" in nested ENDS directive");
4123 StructInfo Structure = StructInProgress.
pop_back_val();
4125 Structure.Size =
llvm::alignTo(Structure.Size, Structure.Alignment);
4127 StructInfo &ParentStruct = StructInProgress.
back();
4128 if (Structure.Name.
empty()) {
4131 const size_t OldFields = ParentStruct.Fields.size();
4132 ParentStruct.Fields.insert(
4133 ParentStruct.Fields.end(),
4134 std::make_move_iterator(Structure.Fields.begin()),
4135 std::make_move_iterator(Structure.Fields.end()));
4136 for (
const auto &FieldByName : Structure.FieldsByName) {
4137 ParentStruct.FieldsByName[FieldByName.getKey()] =
4138 FieldByName.getValue() + OldFields;
4141 unsigned FirstFieldOffset = 0;
4142 if (!Structure.Fields.empty() && !ParentStruct.IsUnion) {
4144 ParentStruct.NextOffset,
4145 std::min(ParentStruct.Alignment, Structure.AlignmentSize));
4148 if (ParentStruct.IsUnion) {
4149 ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
4154 const unsigned StructureEnd = FirstFieldOffset + Structure.Size;
4155 if (!ParentStruct.IsUnion) {
4156 ParentStruct.NextOffset = StructureEnd;
4158 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4161 FieldInfo &
Field = ParentStruct.addField(Structure.Name, FT_STRUCT,
4162 Structure.AlignmentSize);
4163 StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
4164 Field.Type = Structure.Size;
4166 Field.SizeOf = Structure.Size;
4169 if (!ParentStruct.IsUnion) {
4170 ParentStruct.NextOffset = StructureEnd;
4172 ParentStruct.Size = std::max(ParentStruct.Size, StructureEnd);
4174 StructInfo.Structure = Structure;
4175 StructInfo.Initializers.emplace_back();
4176 auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
4177 for (
const auto &SubField : Structure.Fields) {
4178 FieldInitializers.push_back(SubField.Contents);
4187bool MasmParser::parseDirectiveOrg() {
4189 SMLoc OffsetLoc = Lexer.getLoc();
4190 if (checkForValidSection() || parseExpression(
Offset))
4193 return addErrorSuffix(
" in 'org' directive");
4195 if (StructInProgress.
empty()) {
4197 if (checkForValidSection())
4198 return addErrorSuffix(
" in 'org' directive");
4200 getStreamer().emitValueToOffset(
Offset, 0, OffsetLoc);
4203 StructInfo &Structure = StructInProgress.
back();
4205 if (!
Offset->evaluateAsAbsolute(OffsetRes, getStreamer().getAssemblerPtr()))
4206 return Error(OffsetLoc,
4207 "expected absolute expression in 'org' directive");
4211 "expected non-negative value in struct's 'org' directive; was " +
4212 std::to_string(OffsetRes));
4213 Structure.NextOffset =
static_cast<unsigned>(OffsetRes);
4216 Structure.Initializable =
false;
4222bool MasmParser::emitAlignTo(int64_t Alignment) {
4223 if (StructInProgress.
empty()) {
4225 if (checkForValidSection())
4230 const MCSection *
Section = getStreamer().getCurrentSectionOnly();
4232 getStreamer().emitCodeAlignment(
Align(Alignment),
4233 getTargetParser().getSTI(),
4237 getStreamer().emitValueToAlignment(
Align(Alignment), 0,
4243 StructInfo &Structure = StructInProgress.
back();
4244 Structure.NextOffset =
llvm::alignTo(Structure.NextOffset, Alignment);
4252bool MasmParser::parseDirectiveAlign() {
4253 SMLoc AlignmentLoc = getLexer().getLoc();
4259 "align directive with no operand is ignored") &&
4262 if (parseAbsoluteExpression(Alignment) || parseEOL())
4263 return addErrorSuffix(
" in align directive");
4266 bool ReturnVal =
false;
4273 ReturnVal |=
Error(AlignmentLoc,
"alignment must be a power of 2; was " +
4274 std::to_string(Alignment));
4276 if (emitAlignTo(Alignment))
4277 ReturnVal |= addErrorSuffix(
" in align directive");
4284bool MasmParser::parseDirectiveEven() {
4285 if (parseEOL() || emitAlignTo(2))
4286 return addErrorSuffix(
" in even directive");
4297bool MasmParser::parseDirectiveMacro(StringRef Name, SMLoc NameLoc) {
4301 return Error(Lexer.getLoc(),
4302 "Vararg parameter '" +
Parameters.back().Name +
4303 "' should be last in the list of parameters");
4307 return TokError(
"expected identifier in 'macro' directive");
4310 for (
const MCAsmMacroParameter& CurrParam : Parameters)
4311 if (CurrParam.Name.equals_insensitive(
Parameter.Name))
4312 return TokError(
"macro '" + Name +
"' has multiple parameters"
4322 ParamLoc = Lexer.getLoc();
4323 if (parseMacroArgument(
nullptr,
Parameter.Value))
4329 QualLoc = Lexer.getLoc();
4330 if (parseIdentifier(Qualifier))
4331 return Error(QualLoc,
"missing parameter qualifier for "
4333 Parameter.Name +
"' in macro '" + Name +
4336 if (
Qualifier.equals_insensitive(
"req"))
4338 else if (
Qualifier.equals_insensitive(
"vararg"))
4341 return Error(QualLoc,
4342 Qualifier +
" is not a valid parameter qualifier for '" +
4343 Parameter.Name +
"' in macro '" + Name +
"'");
4356 std::vector<std::string>
Locals;
4358 getTok().getIdentifier().equals_insensitive(
"local")) {
4363 if (parseIdentifier(ID))
4375 AsmToken EndToken, StartToken = getTok();
4376 unsigned MacroDepth = 0;
4377 bool IsMacroFunction =
false;
4387 return Error(NameLoc,
"no matching 'endm' in definition");
4392 if (getTok().getIdentifier().equals_insensitive(
"endm")) {
4393 if (MacroDepth == 0) {
4394 EndToken = getTok();
4397 return TokError(
"unexpected token in '" + EndToken.
getIdentifier() +
4404 }
else if (getTok().getIdentifier().equals_insensitive(
"exitm")) {
4406 IsMacroFunction =
true;
4408 }
else if (isMacroLikeDirective()) {
4416 eatToEndOfStatement();
4420 return Error(NameLoc,
"macro '" + Name +
"' is already defined");
4425 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
4426 MCAsmMacro
Macro(Name, Body, std::move(Parameters), std::move(Locals),
4436bool MasmParser::parseDirectiveExitMacro(SMLoc DirectiveLoc,
4437 StringRef Directive,
4438 std::string &
Value) {
4439 SMLoc EndLoc = getTok().getLoc();
4441 return Error(EndLoc,
4442 "unable to parse text item in '" + Directive +
"' directive");
4443 eatToEndOfStatement();
4445 if (!isInsideMacroInstantiation())
4446 return TokError(
"unexpected '" + Directive +
"' in file, "
4447 "no current macro definition");
4450 while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) {
4451 TheCondState = TheCondStack.back();
4452 TheCondStack.pop_back();
4461bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
4463 return TokError(
"unexpected token in '" + Directive +
"' directive");
4467 if (isInsideMacroInstantiation()) {
4474 return TokError(
"unexpected '" + Directive +
"' in file, "
4475 "no current macro definition");
4480bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
4484 if (parseTokenLoc(NameLoc) ||
4485 check(parseIdentifier(Name), NameLoc,
4486 "expected identifier in 'purge' directive"))
4490 <<
"Un-defining macro: " << Name <<
"\n");
4492 return Error(NameLoc,
"macro '" + Name +
"' is not defined");
4503bool MasmParser::parseDirectiveExtern() {
4505 auto parseOp = [&]() ->
bool {
4507 SMLoc NameLoc = getTok().getLoc();
4509 return Error(NameLoc,
"expected name");
4514 SMLoc TypeLoc = getTok().getLoc();
4515 if (parseIdentifier(TypeName))
4516 return Error(TypeLoc,
"expected type");
4517 if (!
TypeName.equals_insensitive(
"proc")) {
4519 if (lookUpType(TypeName,
Type))
4520 return Error(TypeLoc,
"unrecognized type");
4524 static_cast<MCSymbolCOFF *
>(Sym)->setExternal(
true);
4525 getStreamer().emitSymbolAttribute(Sym,
MCSA_Extern);
4530 if (parseMany(parseOp))
4531 return addErrorSuffix(
" in directive 'extern'");
4537bool MasmParser::parseDirectiveSymbolAttribute(
MCSymbolAttr Attr) {
4538 auto parseOp = [&]() ->
bool {
4539 SMLoc Loc = getTok().getLoc();
4542 return Error(Loc,
"expected identifier");
4546 return Error(Loc,
"non-local symbol required");
4548 if (!getStreamer().emitSymbolAttribute(Sym, Attr))
4549 return Error(Loc,
"unable to emit symbol attribute");
4553 if (parseMany(parseOp))
4554 return addErrorSuffix(
" in directive");
4560bool MasmParser::parseDirectiveComm(
bool IsLocal) {
4561 if (checkForValidSection())
4564 SMLoc IDLoc = getLexer().getLoc();
4567 return TokError(
"expected identifier in directive");
4570 return TokError(
"unexpected token in directive");
4574 SMLoc SizeLoc = getLexer().getLoc();
4575 if (parseAbsoluteExpression(
Size))
4578 int64_t Pow2Alignment = 0;
4579 SMLoc Pow2AlignmentLoc;
4582 Pow2AlignmentLoc = getLexer().getLoc();
4583 if (parseAbsoluteExpression(Pow2Alignment))
4588 return Error(Pow2AlignmentLoc,
"alignment not supported on this target");
4591 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
4594 return Error(Pow2AlignmentLoc,
"alignment must be a power of 2");
4595 Pow2Alignment =
Log2_64(Pow2Alignment);
4605 return Error(SizeLoc,
"invalid '.comm' or '.lcomm' directive size, can't "
4606 "be less than zero");
4611 if (Pow2Alignment < 0)
4612 return Error(Pow2AlignmentLoc,
"invalid '.comm' or '.lcomm' directive "
4613 "alignment, can't be less than zero");
4617 return Error(IDLoc,
"invalid symbol redefinition");
4621 getStreamer().emitLocalCommonSymbol(Sym,
Size,
4622 Align(1ULL << Pow2Alignment));
4626 getStreamer().emitCommonSymbol(Sym,
Size,
Align(1ULL << Pow2Alignment));
4634bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
4636 size_t DelimiterEnd = FirstLine.find_first_of(
"\b\t\v\f\r\x1A ");
4637 assert(DelimiterEnd != std::string::npos);
4638 StringRef Delimiter = StringRef(FirstLine).take_front(DelimiterEnd);
4639 if (Delimiter.
empty())
4640 return Error(DirectiveLoc,
"no delimiter in 'comment' directive");
4643 return Error(DirectiveLoc,
"unmatched delimiter in 'comment' directive");
4653bool MasmParser::parseDirectiveInclude() {
4656 SMLoc IncludeLoc = getTok().getLoc();
4658 if (parseAngleBracketString(
Filename))
4660 if (check(
Filename.
empty(),
"missing filename in 'include' directive") ||
4662 "unexpected token in 'include' directive") ||
4665 check(enterIncludeFile(
Filename), IncludeLoc,
4666 "Could not find include file '" +
Filename +
"'"))
4674bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
4675 TheCondStack.push_back(TheCondState);
4677 if (TheCondState.
Ignore) {
4678 eatToEndOfStatement();
4681 if (parseAbsoluteExpression(ExprValue) || parseEOL())
4690 ExprValue = ExprValue == 0;
4694 TheCondState.
CondMet = ExprValue;
4703bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4704 TheCondStack.push_back(TheCondState);
4707 if (TheCondState.
Ignore) {
4708 eatToEndOfStatement();
4711 if (parseTextItem(Str))
4712 return TokError(
"expected text item parameter for 'ifb' directive");
4717 TheCondState.
CondMet = ExpectBlank == Str.empty();
4726bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4727 bool CaseInsensitive) {
4728 std::string String1, String2;
4730 if (parseTextItem(String1)) {
4732 return TokError(
"expected text item parameter for 'ifidn' directive");
4733 return TokError(
"expected text item parameter for 'ifdif' directive");
4739 "expected comma after first string for 'ifidn' directive");
4740 return TokError(
"expected comma after first string for 'ifdif' directive");
4744 if (parseTextItem(String2)) {
4746 return TokError(
"expected text item parameter for 'ifidn' directive");
4747 return TokError(
"expected text item parameter for 'ifdif' directive");
4750 TheCondStack.push_back(TheCondState);
4752 if (CaseInsensitive)
4754 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4756 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4765bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc,
bool expect_defined) {
4766 TheCondStack.push_back(TheCondState);
4769 if (TheCondState.
Ignore) {
4770 eatToEndOfStatement();
4772 bool is_defined =
false;
4774 SMLoc StartLoc, EndLoc;
4776 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4779 if (check(parseIdentifier(Name),
"expected identifier after 'ifdef'") ||
4783 if (BuiltinSymbolMap.contains(
Name.lower())) {
4793 TheCondState.
CondMet = (is_defined == expect_defined);
4802bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
4803 DirectiveKind DirKind) {
4806 return Error(DirectiveLoc,
"Encountered a .elseif that doesn't follow an"
4807 " .if or an .elseif");
4810 bool LastIgnoreState =
false;
4811 if (!TheCondStack.empty())
4812 LastIgnoreState = TheCondStack.back().Ignore;
4813 if (LastIgnoreState || TheCondState.
CondMet) {
4814 TheCondState.
Ignore =
true;
4815 eatToEndOfStatement();
4818 if (parseAbsoluteExpression(ExprValue))
4830 ExprValue = ExprValue == 0;
4834 TheCondState.
CondMet = ExprValue;
4843bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
4846 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4847 " if or an elseif");
4850 bool LastIgnoreState =
false;
4851 if (!TheCondStack.empty())
4852 LastIgnoreState = TheCondStack.back().Ignore;
4853 if (LastIgnoreState || TheCondState.
CondMet) {
4854 TheCondState.
Ignore =
true;
4855 eatToEndOfStatement();
4858 if (parseTextItem(Str)) {
4860 return TokError(
"expected text item parameter for 'elseifb' directive");
4861 return TokError(
"expected text item parameter for 'elseifnb' directive");
4867 TheCondState.
CondMet = ExpectBlank == Str.empty();
4877bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
4878 bool expect_defined) {
4881 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4882 " if or an elseif");
4885 bool LastIgnoreState =
false;
4886 if (!TheCondStack.empty())
4887 LastIgnoreState = TheCondStack.back().Ignore;
4888 if (LastIgnoreState || TheCondState.
CondMet) {
4889 TheCondState.
Ignore =
true;
4890 eatToEndOfStatement();
4892 bool is_defined =
false;
4894 SMLoc StartLoc, EndLoc;
4896 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
4899 if (check(parseIdentifier(Name),
4900 "expected identifier after 'elseifdef'") ||
4904 if (BuiltinSymbolMap.contains(
Name.lower())) {
4914 TheCondState.
CondMet = (is_defined == expect_defined);
4923bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
4924 bool CaseInsensitive) {
4927 return Error(DirectiveLoc,
"Encountered an elseif that doesn't follow an"
4928 " if or an elseif");
4931 bool LastIgnoreState =
false;
4932 if (!TheCondStack.empty())
4933 LastIgnoreState = TheCondStack.back().Ignore;
4934 if (LastIgnoreState || TheCondState.
CondMet) {
4935 TheCondState.
Ignore =
true;
4936 eatToEndOfStatement();
4938 std::string String1, String2;
4940 if (parseTextItem(String1)) {
4943 "expected text item parameter for 'elseifidn' directive");
4944 return TokError(
"expected text item parameter for 'elseifdif' directive");
4950 "expected comma after first string for 'elseifidn' directive");
4952 "expected comma after first string for 'elseifdif' directive");
4956 if (parseTextItem(String2)) {
4959 "expected text item parameter for 'elseifidn' directive");
4960 return TokError(
"expected text item parameter for 'elseifdif' directive");
4963 if (CaseInsensitive)
4965 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
4967 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
4976bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
4982 return Error(DirectiveLoc,
"Encountered an else that doesn't follow an if"
4985 bool LastIgnoreState =
false;
4986 if (!TheCondStack.empty())
4987 LastIgnoreState = TheCondStack.back().Ignore;
4988 if (LastIgnoreState || TheCondState.
CondMet)
4989 TheCondState.
Ignore =
true;
4991 TheCondState.
Ignore =
false;
4998bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
5010bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
5011 if (!TheCondStack.empty()) {
5012 if (TheCondStack.back().Ignore) {
5013 eatToEndOfStatement();
5018 std::string Message =
".err directive invoked in source file";
5023 return Error(DirectiveLoc, Message);
5028bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc,
bool ExpectBlank) {
5029 if (!TheCondStack.empty()) {
5030 if (TheCondStack.back().Ignore) {
5031 eatToEndOfStatement();
5037 if (parseTextItem(
Text))
5038 return Error(getTok().getLoc(),
"missing text item in '.errb' directive");
5040 std::string Message =
".errb directive invoked in source file";
5043 return addErrorSuffix(
" in '.errb' directive");
5048 if (
Text.empty() == ExpectBlank)
5049 return Error(DirectiveLoc, Message);
5055bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
5056 bool ExpectDefined) {
5057 if (!TheCondStack.empty()) {
5058 if (TheCondStack.back().Ignore) {
5059 eatToEndOfStatement();
5064 bool IsDefined =
false;
5066 SMLoc StartLoc, EndLoc;
5068 getTargetParser().tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
5071 if (check(parseIdentifier(Name),
"expected identifier after '.errdef'"))
5074 if (BuiltinSymbolMap.contains(
Name.lower())) {
5084 std::string Message =
".errdef directive invoked in source file";
5087 return addErrorSuffix(
" in '.errdef' directive");
5092 if (IsDefined == ExpectDefined)
5093 return Error(DirectiveLoc, Message);
5099bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc,
bool ExpectEqual,
5100 bool CaseInsensitive) {
5101 if (!TheCondStack.empty()) {
5102 if (TheCondStack.back().Ignore) {
5103 eatToEndOfStatement();
5108 std::string String1, String2;
5110 if (parseTextItem(String1)) {
5112 return TokError(
"expected string parameter for '.erridn' directive");
5113 return TokError(
"expected string parameter for '.errdif' directive");
5119 "expected comma after first string for '.erridn' directive");
5121 "expected comma after first string for '.errdif' directive");
5125 if (parseTextItem(String2)) {
5127 return TokError(
"expected string parameter for '.erridn' directive");
5128 return TokError(
"expected string parameter for '.errdif' directive");
5131 std::string Message;
5133 Message =
".erridn directive invoked in source file";
5135 Message =
".errdif directive invoked in source file";
5138 return addErrorSuffix(
" in '.erridn' directive");
5143 if (CaseInsensitive)
5145 ExpectEqual == (StringRef(String1).equals_insensitive(String2));
5147 TheCondState.
CondMet = ExpectEqual == (String1 == String2);
5150 if ((CaseInsensitive &&
5151 ExpectEqual == StringRef(String1).equals_insensitive(String2)) ||
5152 (ExpectEqual == (String1 == String2)))
5153 return Error(DirectiveLoc, Message);
5159bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc,
bool ExpectZero) {
5160 if (!TheCondStack.empty()) {
5161 if (TheCondStack.back().Ignore) {
5162 eatToEndOfStatement();
5168 if (parseAbsoluteExpression(ExprValue))
5169 return addErrorSuffix(
" in '.erre' directive");
5171 std::string Message =
".erre directive invoked in source file";
5174 return addErrorSuffix(
" in '.erre' directive");
5179 if ((ExprValue == 0) == ExpectZero)
5180 return Error(DirectiveLoc, Message);
5186bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
5191 return Error(DirectiveLoc,
"Encountered a .endif that doesn't follow "
5193 if (!TheCondStack.empty()) {
5194 TheCondState = TheCondStack.back();
5195 TheCondStack.pop_back();
5201void MasmParser::initializeDirectiveKindMap() {
5202 DirectiveKindMap[
"="] = DK_ASSIGN;
5203 DirectiveKindMap[
"equ"] = DK_EQU;
5204 DirectiveKindMap[
"textequ"] = DK_TEXTEQU;
5208 DirectiveKindMap[
"byte"] = DK_BYTE;
5209 DirectiveKindMap[
"sbyte"] = DK_SBYTE;
5210 DirectiveKindMap[
"word"] = DK_WORD;
5211 DirectiveKindMap[
"sword"] = DK_SWORD;
5212 DirectiveKindMap[
"dword"] = DK_DWORD;
5213 DirectiveKindMap[
"sdword"] = DK_SDWORD;
5214 DirectiveKindMap[
"fword"] = DK_FWORD;
5215 DirectiveKindMap[
"qword"] = DK_QWORD;
5216 DirectiveKindMap[
"sqword"] = DK_SQWORD;
5217 DirectiveKindMap[
"real4"] = DK_REAL4;
5218 DirectiveKindMap[
"real8"] = DK_REAL8;
5219 DirectiveKindMap[
"real10"] = DK_REAL10;
5220 DirectiveKindMap[
"align"] = DK_ALIGN;
5221 DirectiveKindMap[
"even"] = DK_EVEN;
5222 DirectiveKindMap[
"org"] = DK_ORG;
5223 DirectiveKindMap[
"extern"] = DK_EXTERN;
5224 DirectiveKindMap[
"extrn"] = DK_EXTERN;
5225 DirectiveKindMap[
"public"] = DK_PUBLIC;
5227 DirectiveKindMap[
"comment"] = DK_COMMENT;
5228 DirectiveKindMap[
"include"] = DK_INCLUDE;
5229 DirectiveKindMap[
"repeat"] = DK_REPEAT;
5230 DirectiveKindMap[
"rept"] = DK_REPEAT;
5231 DirectiveKindMap[
"while"] = DK_WHILE;
5232 DirectiveKindMap[
"for"] = DK_FOR;
5233 DirectiveKindMap[
"irp"] = DK_FOR;
5234 DirectiveKindMap[
"forc"] = DK_FORC;
5235 DirectiveKindMap[
"irpc"] = DK_FORC;
5236 DirectiveKindMap[
"if"] = DK_IF;
5237 DirectiveKindMap[
"ife"] = DK_IFE;
5238 DirectiveKindMap[
"ifb"] = DK_IFB;
5239 DirectiveKindMap[
"ifnb"] = DK_IFNB;
5240 DirectiveKindMap[
"ifdef"] = DK_IFDEF;
5241 DirectiveKindMap[
"ifndef"] = DK_IFNDEF;
5242 DirectiveKindMap[
"ifdif"] = DK_IFDIF;
5243 DirectiveKindMap[
"ifdifi"] = DK_IFDIFI;
5244 DirectiveKindMap[
"ifidn"] = DK_IFIDN;
5245 DirectiveKindMap[
"ifidni"] = DK_IFIDNI;
5246 DirectiveKindMap[
"elseif"] = DK_ELSEIF;
5247 DirectiveKindMap[
"elseifdef"] = DK_ELSEIFDEF;
5248 DirectiveKindMap[
"elseifndef"] = DK_ELSEIFNDEF;
5249 DirectiveKindMap[
"elseifdif"] = DK_ELSEIFDIF;
5250 DirectiveKindMap[
"elseifidn"] = DK_ELSEIFIDN;
5251 DirectiveKindMap[
"else"] = DK_ELSE;
5252 DirectiveKindMap[
"end"] = DK_END;
5253 DirectiveKindMap[
"endif"] = DK_ENDIF;
5297 DirectiveKindMap[
"macro"] = DK_MACRO;
5298 DirectiveKindMap[
"exitm"] = DK_EXITM;
5299 DirectiveKindMap[
"endm"] = DK_ENDM;
5300 DirectiveKindMap[
"purge"] = DK_PURGE;
5301 DirectiveKindMap[
".err"] = DK_ERR;
5302 DirectiveKindMap[
".errb"] = DK_ERRB;
5303 DirectiveKindMap[
".errnb"] = DK_ERRNB;
5304 DirectiveKindMap[
".errdef"] = DK_ERRDEF;
5305 DirectiveKindMap[
".errndef"] = DK_ERRNDEF;
5306 DirectiveKindMap[
".errdif"] = DK_ERRDIF;
5307 DirectiveKindMap[
".errdifi"] = DK_ERRDIFI;
5308 DirectiveKindMap[
".erridn"] = DK_ERRIDN;
5309 DirectiveKindMap[
".erridni"] = DK_ERRIDNI;
5310 DirectiveKindMap[
".erre"] = DK_ERRE;
5311 DirectiveKindMap[
".errnz"] = DK_ERRNZ;
5312 DirectiveKindMap[
".pushframe"] = DK_PUSHFRAME;
5313 DirectiveKindMap[
".pushreg"] = DK_PUSHREG;
5314 DirectiveKindMap[
".push2reg"] = DK_PUSH2REGS;
5315 DirectiveKindMap[
".pop2reg"] = DK_PUSH2REGS;
5316 DirectiveKindMap[
".popreg"] = DK_PUSHREG;
5317 DirectiveKindMap[
".savereg"] = DK_SAVEREG;
5318 DirectiveKindMap[
".restorereg"] = DK_SAVEREG;
5319 DirectiveKindMap[
".savexmm128"] = DK_SAVEXMM128;
5320 DirectiveKindMap[
".restorexmm128"] = DK_SAVEXMM128;
5321 DirectiveKindMap[
".setframe"] = DK_SETFRAME;
5322 DirectiveKindMap[
".unsetframe"] = DK_SETFRAME;
5323 DirectiveKindMap[
".radix"] = DK_RADIX;
5324 DirectiveKindMap[
"db"] = DK_DB;
5325 DirectiveKindMap[
"dd"] = DK_DD;
5326 DirectiveKindMap[
"df"] = DK_DF;
5327 DirectiveKindMap[
"dq"] = DK_DQ;
5328 DirectiveKindMap[
"dw"] = DK_DW;
5329 DirectiveKindMap[
"echo"] = DK_ECHO;
5330 DirectiveKindMap[
"struc"] = DK_STRUCT;
5331 DirectiveKindMap[
"struct"] = DK_STRUCT;
5332 DirectiveKindMap[
"union"] = DK_UNION;
5333 DirectiveKindMap[
"ends"] = DK_ENDS;
5336bool MasmParser::isMacroLikeDirective() {
5338 bool IsMacroLike = StringSwitch<bool>(getTok().getIdentifier())
5339 .CasesLower({
"repeat",
"rept"},
true)
5340 .CaseLower(
"while",
true)
5341 .CasesLower({
"for",
"irp"},
true)
5342 .CasesLower({
"forc",
"irpc"},
true)
5348 peekTok().getIdentifier().equals_insensitive(
"macro"))
5354MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
5355 AsmToken EndToken, StartToken = getTok();
5357 unsigned NestLevel = 0;
5361 printError(DirectiveLoc,
"no matching 'endm' in definition");
5365 if (isMacroLikeDirective())
5370 getTok().getIdentifier().equals_insensitive(
"endm")) {
5371 if (NestLevel == 0) {
5372 EndToken = getTok();
5375 printError(getTok().getLoc(),
"unexpected token in 'endm' directive");
5384 eatToEndOfStatement();
5389 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
5393 return &MacroLikeBodies.back();
5396bool MasmParser::expandStatement(SMLoc Loc) {
5398 SMLoc EndLoc = getTok().getLoc();
5403 StringMap<std::string> BuiltinValues;
5404 for (
const auto &S : BuiltinSymbolMap) {
5405 const BuiltinSymbol &Sym = S.getValue();
5406 if (std::optional<std::string>
Text = evaluateBuiltinTextMacro(Sym, Loc)) {
5407 BuiltinValues[S.getKey().lower()] = std::move(*
Text);
5410 for (
const auto &
B : BuiltinValues) {
5411 MCAsmMacroParameter
P;
5412 MCAsmMacroArgument
A;
5413 P.Name =
B.getKey();
5421 for (
const auto &V : Variables) {
5424 MCAsmMacroParameter
P;
5425 MCAsmMacroArgument
A;
5434 MacroLikeBodies.emplace_back(StringRef(), Body, Parameters);
5435 MCAsmMacro
M = MacroLikeBodies.back();
5438 SmallString<80> Buf;
5439 raw_svector_ostream OS(Buf);
5440 if (expandMacro(OS,
M.Body,
M.Parameters,
Arguments,
M.Locals, EndLoc))
5442 std::unique_ptr<MemoryBuffer>
Expansion =
5448 EndStatementAtEOFStack.push_back(
false);
5453void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5454 raw_svector_ostream &OS) {
5455 instantiateMacroLikeBody(M, DirectiveLoc, getTok().getLoc(), OS);
5457void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
5459 raw_svector_ostream &OS) {
5462 std::unique_ptr<MemoryBuffer> Instantiation =
5467 MacroInstantiation *
MI =
new MacroInstantiation{DirectiveLoc, CurBuffer,
5468 ExitLoc, TheCondStack.size()};
5469 ActiveMacros.push_back(
MI);
5474 EndStatementAtEOFStack.push_back(
true);
5482bool MasmParser::parseDirectiveRepeat(SMLoc DirectiveLoc, StringRef Dir) {
5483 const MCExpr *CountExpr;
5484 SMLoc CountLoc = getTok().getLoc();
5485 if (parseExpression(CountExpr))
5489 if (!CountExpr->evaluateAsAbsolute(
Count, getStreamer().getAssemblerPtr())) {
5490 return Error(CountLoc,
"unexpected token in '" + Dir +
"' directive");
5493 if (check(
Count < 0, CountLoc,
"Count is negative") || parseEOL())
5497 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5503 SmallString<256> Buf;
5504 raw_svector_ostream OS(Buf);
5506 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5509 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5518bool MasmParser::parseDirectiveWhile(SMLoc DirectiveLoc) {
5519 const MCExpr *CondExpr;
5520 SMLoc CondLoc = getTok().getLoc();
5521 if (parseExpression(CondExpr))
5525 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5531 SmallString<256> Buf;
5532 raw_svector_ostream OS(Buf);
5534 if (!CondExpr->evaluateAsAbsolute(Condition, getStreamer().getAssemblerPtr()))
5535 return Error(CondLoc,
"expected absolute expression in 'while' directive");
5539 if (expandMacro(OS,
M->Body, {}, {},
M->Locals, getTok().getLoc()))
5541 instantiateMacroLikeBody(M, DirectiveLoc, DirectiveLoc, OS);
5551bool MasmParser::parseDirectiveFor(SMLoc DirectiveLoc, StringRef Dir) {
5553 MCAsmMacroArguments
A;
5554 if (check(parseIdentifier(
Parameter.Name),
5555 "expected identifier in '" + Dir +
"' directive"))
5564 ParamLoc = Lexer.getLoc();
5565 if (parseMacroArgument(
nullptr,
Parameter.Value))
5571 QualLoc = Lexer.getLoc();
5572 if (parseIdentifier(Qualifier))
5573 return Error(QualLoc,
"missing parameter qualifier for "
5578 if (
Qualifier.equals_insensitive(
"req"))
5581 return Error(QualLoc,
5582 Qualifier +
" is not a valid parameter qualifier for '" +
5583 Parameter.Name +
"' in '" + Dir +
"' directive");
5588 "expected comma in '" + Dir +
"' directive") ||
5590 "values in '" + Dir +
5591 "' directive must be enclosed in angle brackets"))
5597 return addErrorSuffix(
" in arguments for '" + Dir +
"' directive");
5606 "values in '" + Dir +
5607 "' directive must be enclosed in angle brackets") ||
5612 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5618 SmallString<256> Buf;
5619 raw_svector_ostream OS(Buf);
5621 for (
const MCAsmMacroArgument &Arg :
A) {
5622 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5626 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5635bool MasmParser::parseDirectiveForc(SMLoc DirectiveLoc, StringRef Directive) {
5639 if (check(parseIdentifier(
Parameter.Name),
5640 "expected identifier in '" + Directive +
"' directive") ||
5642 "expected comma in '" + Directive +
"' directive"))
5644 if (parseAngleBracketString(Argument)) {
5652 for (; End <
Argument.size(); ++End) {
5662 MCAsmMacro *
M = parseMacroLikeBody(DirectiveLoc);
5668 SmallString<256> Buf;
5669 raw_svector_ostream OS(Buf);
5671 StringRef
Values(Argument);
5672 for (std::size_t
I = 0, End =
Values.size();
I != End; ++
I) {
5673 MCAsmMacroArgument Arg;
5676 if (expandMacro(OS,
M->Body, Parameter, Arg,
M->Locals, getTok().getLoc()))
5680 instantiateMacroLikeBody(M, DirectiveLoc, OS);
5685bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
5687 const MCExpr *
Value;
5688 SMLoc ExprLoc = getLexer().getLoc();
5689 if (parseExpression(
Value))
5693 return Error(ExprLoc,
"unexpected expression in _emit");
5694 uint64_t IntValue = MCE->
getValue();
5696 return Error(ExprLoc,
"literal value out of range for directive");
5702bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
5703 const MCExpr *
Value;
5704 SMLoc ExprLoc = getLexer().getLoc();
5705 if (parseExpression(
Value))
5709 return Error(ExprLoc,
"unexpected expression in align");
5710 uint64_t IntValue = MCE->
getValue();
5712 return Error(ExprLoc,
"literal value not a power of two greater then zero");
5718bool MasmParser::parseDirectiveRadix(SMLoc DirectiveLoc) {
5719 const SMLoc Loc = getLexer().getLoc();
5721 StringRef RadixString = StringRef(RadixStringRaw).trim();
5725 "radix must be a decimal number in the range 2 to 16; was " +
5728 if (Radix < 2 || Radix > 16)
5729 return Error(Loc,
"radix must be in the range 2 to 16; was " +
5730 std::to_string(Radix));
5731 getLexer().setMasmDefaultRadix(Radix);
5737bool MasmParser::parseDirectiveEcho(SMLoc DirectiveLoc) {
5740 if (!StringRef(Message).ends_with(
"\n"))
5768bool MasmParser::defineMacro(StringRef Name, StringRef
Value) {
5770 if (Var.Name.empty())
5772 return setTextVariable(Var, Name,
Value, SMLoc(),
5773 Variable::WARN_ON_REDEFINITION);
5776bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info)
const {
5777 const std::pair<StringRef, StringRef> BaseMember =
Name.split(
'.');
5778 const StringRef
Base = BaseMember.first,
Member = BaseMember.second;
5779 return lookUpField(
Base, Member, Info);
5782bool MasmParser::lookUpField(StringRef
Base, StringRef Member,
5783 AsmFieldInfo &Info)
const {
5787 AsmFieldInfo BaseInfo;
5788 if (
Base.contains(
'.') && !lookUpField(
Base, BaseInfo))
5791 auto StructIt = Structs.
find(
Base.lower());
5792 auto TypeIt = KnownType.
find(
Base.lower());
5793 if (TypeIt != KnownType.
end()) {
5794 StructIt = Structs.
find(TypeIt->second.Name.lower());
5796 if (StructIt != Structs.
end())
5797 return lookUpField(StructIt->second, Member, Info);
5802bool MasmParser::lookUpField(
const StructInfo &Structure, StringRef Member,
5803 AsmFieldInfo &Info)
const {
5805 Info.Type.Name = Structure.Name;
5806 Info.Type.Size = Structure.Size;
5807 Info.Type.ElementSize = Structure.Size;
5808 Info.Type.Length = 1;
5812 std::pair<StringRef, StringRef>
Split =
Member.split(
'.');
5813 const StringRef FieldName =
Split.first, FieldMember =
Split.second;
5815 auto StructIt = Structs.
find(FieldName.
lower());
5816 if (StructIt != Structs.
end())
5817 return lookUpField(StructIt->second, FieldMember, Info);
5819 auto FieldIt = Structure.FieldsByName.
find(FieldName.
lower());
5820 if (FieldIt == Structure.FieldsByName.
end())
5823 const FieldInfo &
Field = Structure.Fields[FieldIt->second];
5824 if (FieldMember.empty()) {
5829 if (
Field.Contents.FT == FT_STRUCT)
5830 Info.Type.Name =
Field.Contents.StructInfo.Structure.Name;
5832 Info.Type.Name =
"";
5836 if (
Field.Contents.FT != FT_STRUCT)
5838 const StructFieldInfo &StructInfo =
Field.Contents.StructInfo;
5840 if (lookUpField(StructInfo.Structure, FieldMember, Info))
5847bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info)
const {
5848 unsigned Size = StringSwitch<unsigned>(Name)
5849 .CasesLower({
"byte",
"db",
"sbyte"}, 1)
5850 .CasesLower({
"word",
"dw",
"sword"}, 2)
5851 .CasesLower({
"dword",
"dd",
"sdword"}, 4)
5852 .CasesLower({
"fword",
"df"}, 6)
5853 .CasesLower({
"qword",
"dq",
"sqword"}, 8)
5854 .CaseLower(
"real4", 4)
5855 .CaseLower(
"real8", 8)
5856 .CaseLower(
"real10", 10)
5866 auto StructIt = Structs.
find(
Name.lower());
5867 if (StructIt != Structs.
end()) {
5868 const StructInfo &Structure = StructIt->second;
5870 Info.ElementSize = Structure.Size;
5872 Info.Size = Structure.Size;
5879bool MasmParser::parseMSInlineAsm(
5880 std::string &AsmString,
unsigned &NumOutputs,
unsigned &NumInputs,
5881 SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
5882 SmallVectorImpl<std::string> &Constraints,
5883 SmallVectorImpl<std::string> &Clobbers,
const MCInstrInfo *MII,
5884 MCInstPrinter *IP, MCAsmParserSemaCallback &SI) {
5885 SmallVector<void *, 4> InputDecls;
5886 SmallVector<void *, 4> OutputDecls;
5887 SmallVector<bool, 4> InputDeclsAddressOf;
5888 SmallVector<bool, 4> OutputDeclsAddressOf;
5889 SmallVector<std::string, 4> InputConstraints;
5890 SmallVector<std::string, 4> OutputConstraints;
5899 unsigned InputIdx = 0;
5900 unsigned OutputIdx = 0;
5903 if (parseCurlyBlockScope(AsmStrRewrites))
5906 ParseStatementInfo
Info(&AsmStrRewrites);
5907 bool StatementErr = parseStatement(Info, &SI);
5909 if (StatementErr ||
Info.ParseError) {
5911 printPendingErrors();
5916 assert(!hasPendingError() &&
"unexpected error from parseStatement");
5918 if (
Info.Opcode == ~0U)
5924 for (
unsigned i = 1, e =
Info.ParsedOperands.size(); i != e; ++i) {
5925 MCParsedAsmOperand &Operand = *
Info.ParsedOperands[i];
5929 !getTargetParser().omitRegisterFromClobberLists(Operand.
getReg())) {
5930 unsigned NumDefs =
Desc.getNumDefs();
5939 if (SymName.
empty())
5947 if (Operand.
isImm()) {
5955 bool isOutput = (i == 1) &&
Desc.mayStore();
5961 OutputConstraints.
push_back((
"=" + Constraint).str());
5967 if (
Desc.operands()[i - 1].isBranchTarget())
5979 NumOutputs = OutputDecls.
size();
5980 NumInputs = InputDecls.
size();
5985 Clobbers.
assign(ClobberRegs.
size(), std::string());
5986 for (
unsigned I = 0,
E = ClobberRegs.
size();
I !=
E; ++
I) {
5987 raw_string_ostream OS(Clobbers[
I]);
5992 if (NumOutputs || NumInputs) {
5993 unsigned NumExprs = NumOutputs + NumInputs;
5994 OpDecls.resize(NumExprs);
5995 Constraints.
resize(NumExprs);
5996 for (
unsigned i = 0; i < NumOutputs; ++i) {
5997 OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
5998 Constraints[i] = OutputConstraints[i];
6000 for (
unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++
j) {
6001 OpDecls[
j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
6002 Constraints[
j] = InputConstraints[i];
6007 std::string AsmStringIR;
6008 raw_string_ostream OS(AsmStringIR);
6009 StringRef ASMString =
6011 const char *AsmStart = ASMString.
begin();
6012 const char *AsmEnd = ASMString.
end();
6014 for (
auto I = AsmStrRewrites.
begin(),
E = AsmStrRewrites.
end();
I !=
E; ++
I) {
6015 const AsmRewrite &AR = *
I;
6022 assert(Loc >= AsmStart &&
"Expected Loc to be at or after Start!");
6025 if (
unsigned Len = Loc - AsmStart)
6026 OS << StringRef(AsmStart, Len);
6030 AsmStart = Loc + AR.
Len;
6034 unsigned AdditionalSkip = 0;
6056 size_t OffsetLen = OffsetName.
size();
6057 auto rewrite_it = std::find_if(
6058 I, AsmStrRewrites.
end(), [&](
const AsmRewrite &FusingAR) {
6059 return FusingAR.Loc == OffsetLoc && FusingAR.Len == OffsetLen &&
6060 (FusingAR.Kind == AOK_Input ||
6061 FusingAR.Kind == AOK_CallInput);
6063 if (rewrite_it == AsmStrRewrites.
end()) {
6064 OS <<
"offset " << OffsetName;
6066 OS <<
"${" << InputIdx++ <<
":P}";
6067 rewrite_it->Done =
true;
6069 OS <<
'$' << InputIdx++;
6070 rewrite_it->Done =
true;
6082 OS <<
'$' << InputIdx++;
6085 OS <<
"${" << InputIdx++ <<
":P}";
6088 OS <<
'$' << OutputIdx++;
6093 case 8: OS <<
"byte ptr ";
break;
6094 case 16: OS <<
"word ptr ";
break;
6095 case 32: OS <<
"dword ptr ";
break;
6096 case 64: OS <<
"qword ptr ";
break;
6097 case 80: OS <<
"xword ptr ";
break;
6098 case 128: OS <<
"xmmword ptr ";
break;
6099 case 256: OS <<
"ymmword ptr ";
break;
6109 if (
getContext().getAsmInfo().getAlignmentIsInBytes())
6114 unsigned Val = AR.
Val;
6116 assert(Val < 10 &&
"Expected alignment less then 2^10.");
6117 AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
6129 AsmStart = Loc + AR.
Len + AdditionalSkip;
6133 if (AsmStart != AsmEnd)
6134 OS << StringRef(AsmStart, AsmEnd - AsmStart);
6136 AsmString = OS.
str();
6140void MasmParser::initializeBuiltinSymbolMaps() {
6142 BuiltinSymbolMap[
"@version"] = BI_VERSION;
6143 BuiltinSymbolMap[
"@line"] = BI_LINE;
6144 BuiltinSymbolMap[
"@unwindversion"] = BI_UNWINDVERSION;
6147 BuiltinSymbolMap[
"@date"] = BI_DATE;
6148 BuiltinSymbolMap[
"@time"] = BI_TIME;
6149 BuiltinSymbolMap[
"@filecur"] = BI_FILECUR;
6150 BuiltinSymbolMap[
"@filename"] = BI_FILENAME;
6151 BuiltinSymbolMap[
"@curseg"] = BI_CURSEG;
6154 BuiltinFunctionMap[
"@catstr"] = BI_CATSTR;
6157 if (
getContext().getSubtargetInfo()->getTargetTriple().getArch() ==
6175const MCExpr *MasmParser::evaluateBuiltinValue(BuiltinSymbol Symbol,
6185 if (ActiveMacros.empty())
6189 ActiveMacros.front()->ExitBuffer);
6192 case BI_UNWINDVERSION:
6199std::optional<std::string>
6200MasmParser::evaluateBuiltinTextMacro(BuiltinSymbol Symbol, SMLoc StartLoc) {
6206 char TmpBuffer[
sizeof(
"mm/dd/yy")];
6207 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%D", &TM);
6208 return std::string(TmpBuffer, Len);
6212 char TmpBuffer[
sizeof(
"hh:mm:ss")];
6213 const size_t Len = strftime(TmpBuffer,
sizeof(TmpBuffer),
"%T", &TM);
6214 return std::string(TmpBuffer, Len);
6219 ActiveMacros.empty() ? CurBuffer : ActiveMacros.front()->ExitBuffer)
6227 return getStreamer().getCurrentSectionOnly()->getName().str();
6232bool MasmParser::evaluateBuiltinMacroFunction(BuiltinFunction Function,
6236 "' requires arguments in parentheses")) {
6247 MCAsmMacro
M(Name,
"",
P, {},
true);
6249 MCAsmMacroArguments
A;
6258 for (
const MCAsmMacroArgument &Arg :
A) {
6259 for (
const AsmToken &Tok : Arg) {
6277 struct tm TM,
unsigned CB) {
6278 return new MasmParser(
SM,
C, Out, MAI, TM, CB);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
AMDGPU Lower Kernel Arguments
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc)
This function checks if the next token is <string> type or arithmetic.
static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI, AsmToken::TokenKind K, MCBinaryExpr::Opcode &Kind, bool ShouldUseLogicalShr)
static std::string angleBracketString(StringRef AltMacroStr)
creating a string without the escape characters '!'.
static int rewritesSort(const AsmRewrite *AsmRewriteA, const AsmRewrite *AsmRewriteB)
This file implements the BitVector class.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Value * getPointer(Value *Ptr)
const std::string FatArchTraits< MachO::fat_arch >::StructName
static bool isMacroParameterChar(char C)
static constexpr unsigned SM(unsigned Version)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static constexpr StringLiteral Filename
OptimizedStructLayoutField Field
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallString class.
This file defines the SmallVector class.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
unsigned getBitWidth() const
Return the number of bits in the APInt.
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
ConditionalAssemblyType TheCond
LLVM_ABI SMLoc getLoc() const
bool isNot(TokenKind K) const
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
StringRef getStringContents() const
Get the contents of a string token (without quotes).
bool is(TokenKind K) const
LLVM_ABI SMLoc getEndLoc() const
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
This class is intended to be used as a base class for asm properties and features specific to the tar...
bool preserveAsmComments() const
Return true if assembly (inline or otherwise) should be parsed.
bool shouldUseLogicalShr() const
StringRef getInternalSymbolPrefix() const
virtual bool useCodeAlign(const MCSection &Sec) const
Generic assembler parser interface, for use by target specific assembly parsers.
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
@ AShr
Arithmetic shift right.
@ LShr
Logical shift right.
@ GTE
Signed greater than or equal comparison (result is either 0 or some target-specific non-zero value).
@ GT
Signed greater than comparison (result is either 0 or some target-specific non-zero value)
@ Xor
Bitwise exclusive or.
@ LT
Signed less than comparison (result is either 0 or some target-specific non-zero value).
@ LTE
Signed less than or equal comparison (result is either 0 or some target-specific non-zero value).
@ NE
Inequality comparison.
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
LLVM_ABI MCSymbol * createDirectionalLocalSymbol(unsigned LocalLabelVal)
Create the definition of a directional local symbol for numbered label (used for "1:" definitions).
const MCAsmInfo & getAsmInfo() const
virtual void printRegName(raw_ostream &OS, MCRegister Reg)
Print the assembler register name.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
virtual bool isReg() const =0
isReg - Is this a register operand?
virtual bool needAddressOf() const
needAddressOf - Do we need to emit code to get the address of the variable/label?
virtual MCRegister getReg() const =0
virtual bool isOffsetOfLocal() const
isOffsetOfLocal - Do we need to emit code to get the offset of the local variable,...
virtual StringRef getSymName()
virtual bool isImm() const =0
isImm - Is this an immediate operand?
unsigned getMCOperandNum()
StringRef getConstraint()
virtual void * getOpDecl()
Streaming machine code generation interface.
virtual void addBlankLine()
Emit a blank line to a .s file to pretty it up.
virtual void addExplicitComment(const Twine &T)
Add explicit comment T.
virtual void initSections(const MCSubtargetInfo &STI)
Create the default sections and set the initial one.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
void finish(SMLoc EndLoc=SMLoc())
Finish emission of machine code.
const MCSymbol & getSymbol() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
bool isUndefined() const
isUndefined - Check if this symbol undefined (i.e., implicitly defined).
StringRef getName() const
getName - Get the symbol name.
bool isVariable() const
isVariable - Check if this is a variable symbol.
LLVM_ABI void setVariableValue(const MCExpr *Value)
void setRedefinable(bool Value)
Mark this symbol as redefinable.
void redefineIfPossible()
Prepare this symbol to be redefined.
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
static const MCUnaryExpr * createLNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createPlus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCUnaryExpr * createMinus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
StringRef getBuffer() const
constexpr bool isFailure() const
constexpr bool isSuccess() const
LLVM_ABI void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true, bool ShowLocation=true) const
SourceMgr::DiagKind getKind() const
StringRef getLineContents() const
StringRef getMessage() const
ArrayRef< std::pair< unsigned, unsigned > > getRanges() const
const SourceMgr * getSourceMgr() const
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
constexpr const char * getPointer() const
constexpr bool isValid() const
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
LLVM_ABI void printIncludeStackForDiagnostic(SMLoc Loc, raw_ostream &OS) const
Prints the include stack of a buffer unless it is a macro instantiation buffer.
unsigned getMainFileID() const
const MemoryBuffer * getMemoryBuffer(unsigned i) const
LLVM_ABI void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
SMLoc getParentIncludeLoc(unsigned i) const
LLVM_ABI unsigned FindBufferContainingLoc(SMLoc Loc) const
Return the ID of the buffer containing the specified location.
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
void setDiagHandler(DiagHandlerTy DH, void *Ctx=nullptr)
Specify a diagnostic handler to be invoked every time PrintMessage is called.
LLVM_ABI unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, std::string &IncludedFile)
Search for a file with the specified name in the current directory or in one of the IncludeDirs.
unsigned FindLineNumber(SMLoc Loc, unsigned BufferID=0) const
Find the line number for the specified location in the specified file.
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
iterator find(StringRef Key)
bool contains(StringRef Key) const
contains - Return true if the element is in the map, false otherwise.
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
ValueTy lookup(StringRef Key) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
StringMapIterBase< ValueTy, true > const_iterator
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Represent a constant reference to a string, i.e.
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
std::string str() const
Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
Check if the string is empty.
LLVM_ABI std::string upper() const
Convert the given ASCII string to uppercase.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
Get the string size.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
LLVM_ABI std::string lower() const
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
StringRef str() const
Return a StringRef for the vector contents.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
LLVM_ABI SimpleSymbol parseSymbol(StringRef SymName)
Get symbol classification by parsing the name of a symbol.
std::variant< std::monostate, DecisionParameters, BranchParameters > Parameters
The type of MC/DC-specific parameters.
@ Parameter
An inlay hint that is for a parameter.
LLVM_ABI Instruction & front() const
LLVM_ABI StringRef stem(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get stem.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
RelativeUniformCounterPtr Values
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI MCAsmParser * createMCMasmParser(SourceMgr &, MCContext &, MCStreamer &, const MCAsmInfo &, struct tm, unsigned CB=0)
Create an MCAsmParser instance for parsing Microsoft MASM-style assembly.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
std::vector< MCAsmMacroParameter > MCAsmMacroParameters
auto unique(Range &&R, Predicate P)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI SourceMgr SrcMgr
auto dyn_cast_or_null(const Y &Val)
cl::opt< unsigned > AsmMacroMaxNestingDepth
const char AsmRewritePrecedence[]
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool isAlnum(char C)
Checks whether character C is either a decimal digit or an uppercase or lowercase letter as classifie...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, bool Upper=false)
format_hex_no_prefix - Output N as a fixed width hexadecimal.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
bool isSpace(char C)
Checks whether character C is whitespace in the "C" locale.
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
@ MCSA_Global
.type _foo, @gnu_unique_object
@ MCSA_Extern
.extern (XCOFF)
std::vector< AsmToken > Value
uint64_t Offset
The offset of this field in the final layout.