40#define DEBUG_TYPE "wasm-asm-parser"
59 SMLoc StartLoc, EndLoc;
78 std::vector<unsigned> List;
88 std::vector<CaLOpElem> List;
92 std::vector<uint8_t> List;
105 WebAssemblyOperand(SMLoc Start, SMLoc End, TokOp
T)
106 : Kind(Token), StartLoc(
Start), EndLoc(End), Tok(
T) {}
107 WebAssemblyOperand(SMLoc Start, SMLoc End, IntOp
I)
108 : Kind(Integer), StartLoc(
Start), EndLoc(End),
Int(
I) {}
109 WebAssemblyOperand(SMLoc Start, SMLoc End, FltOp
F)
110 : Kind(Float), StartLoc(
Start), EndLoc(End), Flt(
F) {}
111 WebAssemblyOperand(SMLoc Start, SMLoc End, SymOp S)
112 : Kind(Symbol), StartLoc(
Start), EndLoc(End), Sym(S) {}
113 WebAssemblyOperand(SMLoc Start, SMLoc End, BrLOp
B)
114 : Kind(BrList), StartLoc(
Start), EndLoc(End), BrL(
B) {}
115 WebAssemblyOperand(SMLoc Start, SMLoc End, CaLOp
C)
116 : Kind(CatchList), StartLoc(
Start), EndLoc(End), CaL(
C) {}
117 WebAssemblyOperand(SMLoc Start, SMLoc End, TyLOp
T)
118 : Kind(TypeList), StartLoc(
Start), EndLoc(End), TyL(
T) {}
120 ~WebAssemblyOperand()
override {
129 bool isToken()
const override {
return Kind == Token; }
130 bool isImm()
const override {
return Kind == Integer || Kind == Symbol; }
131 bool isFPImm()
const {
return Kind == Float; }
132 bool isMem()
const override {
return false; }
133 bool isReg()
const override {
return false; }
134 bool isBrList()
const {
return Kind == BrList; }
135 bool isCatchList()
const {
return Kind == CatchList; }
136 bool isTypeList()
const {
return Kind == TypeList; }
138 MCRegister
getReg()
const override {
148 SMLoc getStartLoc()
const override {
return StartLoc; }
149 SMLoc getEndLoc()
const override {
return EndLoc; }
151 void addRegOperands(MCInst &,
unsigned)
const {
156 void addImmOperands(MCInst &Inst,
unsigned N)
const {
157 assert(
N == 1 &&
"Invalid number of operands!");
160 else if (Kind == Symbol)
166 void addFPImmf32Operands(MCInst &Inst,
unsigned N)
const {
167 assert(
N == 1 &&
"Invalid number of operands!");
175 void addFPImmf64Operands(MCInst &Inst,
unsigned N)
const {
176 assert(
N == 1 &&
"Invalid number of operands!");
183 void addBrListOperands(MCInst &Inst,
unsigned N)
const {
184 assert(
N == 1 && isBrList() &&
"Invalid BrList!");
185 for (
auto Br : BrL.List)
189 void addCatchListOperands(MCInst &Inst,
unsigned N)
const {
190 assert(
N == 1 && isCatchList() &&
"Invalid CatchList!");
192 for (
auto Ca : CaL.List) {
201 void addTypeListOperands(MCInst &Inst,
unsigned N)
const {
202 assert(
N == 1 && isTypeList() &&
"Invalid TypeList!");
204 for (
auto Ty : TyL.List)
208 void print(raw_ostream &OS,
const MCAsmInfo &MAI)
const override {
211 OS <<
"Tok:" << Tok.Tok;
214 OS <<
"Int:" <<
Int.Val;
217 OS <<
"Flt:" << Flt.Val;
220 OS <<
"Sym:" << Sym.Exp;
223 OS <<
"BrList:" << BrL.List.size();
226 OS <<
"CaList:" << CaL.List.size();
229 OS <<
"TyList:" << TyL.List.size();
243 auto *Sym =
static_cast<MCSymbolWasm *
>(Ctx.lookupSymbol(Name));
245 if (!Sym->isFunctionTable())
246 Ctx.reportError(
SMLoc(),
"symbol is not a wasm funcref table");
248 Sym =
static_cast<MCSymbolWasm *
>(Ctx.getOrCreateSymbol(Name));
273 } CurrentState = FileStart;
289 wasm::WasmSignature Sig;
291 std::vector<Nested> NestingStack;
293 MCSymbolWasm *DefaultFunctionTable =
nullptr;
294 MCSymbol *LastFunctionLabel =
nullptr;
298 WebAssemblyAsmTypeCheck TC;
303 WebAssemblyAsmParser(
const MCSubtargetInfo &STI, MCAsmParser &Parser,
304 const MCInstrInfo &MII)
305 : MCTargetAsmParser(STI, MII), Parser(Parser), Lexer(Parser.getLexer()),
306 Is64(STI.getTargetTriple().isArch64Bit()), TC(Parser, MII, Is64),
307 SkipTypeCheck(Parser.
getContext().getTargetOptions().MCNoTypeCheck) {
308 setAvailableFeatures(ComputeAvailableFeatures(STI.
getFeatureBits()));
311 auto &
SM = Parser.getSourceManager();
313 SM.getBufferInfo(
SM.getMainFileID()).Buffer->getBufferIdentifier();
314 if (BufferName ==
"<inline asm>")
315 SkipTypeCheck =
true;
318 void Initialize(MCAsmParser &Parser)
override {
322 getContext(),
"__indirect_function_table", Is64);
325 DefaultFunctionTable->setOmitFromLinkingSection();
328#define GET_ASSEMBLER_HEADER
329#include "WebAssemblyGenAsmMatcher.inc"
335 ParseStatus tryParseRegister(MCRegister &
Reg, SMLoc &StartLoc,
336 SMLoc &EndLoc)
override {
340 bool error(
const Twine &
Msg,
const AsmToken &Tok) {
344 bool error(
const Twine &
Msg, SMLoc Loc = SMLoc()) {
345 return Parser.Error(Loc.isValid() ? Loc : Lexer.getTok().getLoc(),
Msg);
348 std::pair<StringRef, StringRef> nestingString(NestingType NT) {
351 return {
"function",
"end_function"};
353 return {
"block",
"end_block"};
355 return {
"loop",
"end_loop"};
357 return {
"try",
"end_try/delegate"};
359 return {
"catch_all",
"end_try"};
361 return {
"try_table",
"end_try_table"};
363 return {
"if",
"end_if"};
365 return {
"else",
"end_if"};
371 void push(NestingType NT, wasm::WasmSignature Sig = wasm::WasmSignature()) {
372 NestingStack.push_back({
NT, Sig});
375 bool pop(StringRef Ins, NestingType NT1, NestingType NT2 = Undefined) {
376 if (NestingStack.empty())
377 return error(Twine(
"End of block construct with no start: ") + Ins);
378 auto Top = NestingStack.back();
379 if (Top.NT != NT1 && Top.NT != NT2)
380 return error(Twine(
"Block construct type mismatch, expected: ") +
381 nestingString(Top.NT).second +
", instead got: " + Ins);
382 TC.setLastSig(Top.Sig);
383 NestingStack.pop_back();
389 bool popAndPushWithSameSignature(StringRef Ins, NestingType PopNT,
390 NestingType PushNT) {
391 if (NestingStack.empty())
392 return error(Twine(
"End of block construct with no start: ") + Ins);
393 auto Sig = NestingStack.back().Sig;
400 bool ensureEmptyNestingStack(SMLoc Loc = SMLoc()) {
401 auto Err = !NestingStack.empty();
402 while (!NestingStack.empty()) {
403 error(Twine(
"Unmatched block construct(s) at function end: ") +
404 nestingString(NestingStack.back().NT).first,
406 NestingStack.pop_back();
412 auto Ok = Lexer.is(Kind);
420 return error(std::string(
"Expected ") + KindName +
", instead got: ",
425 StringRef expectIdent() {
427 error(
"Expected identifier, got: ", Lexer.getTok());
430 auto Name = Lexer.getTok().getString();
435 StringRef expectStringOrIdent() {
437 auto Str = Lexer.getTok().getStringContents();
442 auto Name = Lexer.getTok().getString();
446 error(
"Expected string or identifier, got: ", Lexer.getTok());
450 bool parseRegTypeList(SmallVectorImpl<wasm::ValType> &Types) {
454 return error(
"unknown type: ", Lexer.getTok());
463 void parseSingleInteger(
bool IsNegative,
OperandVector &Operands) {
464 auto &
Int = Lexer.getTok();
465 int64_t Val =
Int.getIntVal();
468 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
469 Int.getLoc(),
Int.getEndLoc(), WebAssemblyOperand::IntOp{Val}));
473 bool parseSingleFloat(
bool IsNegative,
OperandVector &Operands) {
474 auto &Flt = Lexer.getTok();
476 if (Flt.getString().getAsDouble(Val,
false))
477 return error(
"Cannot parse real: ", Flt);
480 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
481 Flt.getLoc(), Flt.getEndLoc(), WebAssemblyOperand::FltOp{Val}));
486 bool parseSpecialFloatMaybe(
bool IsNegative,
OperandVector &Operands) {
489 auto &Flt = Lexer.getTok();
490 auto S = Flt.getString();
492 if (S.compare_insensitive(
"infinity") == 0) {
493 Val = std::numeric_limits<double>::infinity();
494 }
else if (S.compare_insensitive(
"nan") == 0) {
495 Val = std::numeric_limits<double>::quiet_NaN();
501 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
502 Flt.getLoc(), Flt.getEndLoc(), WebAssemblyOperand::FltOp{Val}));
508 auto &Tok = Lexer.getTok();
512 Order = StringSwitch<int64_t>(S)
518 return error(
"memory ordering requires relaxed-atomics feature: ",
525 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
530 bool checkForP2AlignIfLoadStore(
OperandVector &Operands, StringRef InstName) {
532 auto IsLoadStore = InstName.
contains(
".load") ||
535 auto IsAtomic = InstName.
contains(
"atomic.");
536 if (IsLoadStore || IsAtomic) {
539 auto Id = expectIdent();
541 return error(
"Expected p2align, instead got: " + Id);
545 return error(
"Expected integer constant");
546 parseSingleInteger(
false, Operands);
551 auto IsLoadStoreLane = InstName.
contains(
"_lane");
552 if (IsLoadStoreLane && Operands.
size() == 4)
558 auto Tok = Lexer.getTok();
559 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
566 void addBlockTypeOperand(
OperandVector &Operands, SMLoc NameLoc,
568 if (
BT == WebAssembly::BlockType::Void) {
569 TC.setLastSig(wasm::WasmSignature{});
573 NestingStack.back().Sig = Sig;
575 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
576 NameLoc, NameLoc, WebAssemblyOperand::IntOp{
static_cast<int64_t
>(
BT)}));
579 bool parseLimits(wasm::WasmLimits *Limits) {
580 auto Tok = Lexer.getTok();
582 return error(
"Expected integer constant, instead got: ", Tok);
590 auto Tok = Lexer.getTok();
592 return error(
"Expected integer constant, instead got: ", Tok);
601 bool parseFunctionTableOperand(std::unique_ptr<WebAssemblyOperand> *
Op) {
609 auto &Tok = Lexer.getTok();
614 *
Op = std::make_unique<WebAssemblyOperand>(
621 *
Op = std::make_unique<WebAssemblyOperand>(
622 SMLoc(), SMLoc(), WebAssemblyOperand::SymOp{Val});
629 *
Op = std::make_unique<WebAssemblyOperand>(SMLoc(), SMLoc(),
630 WebAssemblyOperand::IntOp{0});
634 bool parseInstruction(ParseInstructionInfo & , StringRef Name,
644 auto &Sep = Lexer.getTok();
645 if (Sep.getLoc().getPointer() !=
Name.end() ||
649 Name = StringRef(
Name.begin(),
Name.size() + Sep.getString().size());
652 auto &
Id = Lexer.getTok();
654 Id.getLoc().getPointer() !=
Name.end())
655 return error(
"Incomplete instruction name: ", Id);
656 Name = StringRef(
Name.begin(),
Name.size() +
Id.getString().size());
661 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
663 WebAssemblyOperand::TokOp{Name}));
667 bool ExpectBlockType =
false;
668 bool ExpectFuncType =
false;
669 bool ExpectCatchList =
false;
670 std::unique_ptr<WebAssemblyOperand> FunctionTable;
671 if (Name ==
"block") {
673 ExpectBlockType =
true;
674 }
else if (Name ==
"loop") {
676 ExpectBlockType =
true;
677 }
else if (Name ==
"try") {
679 ExpectBlockType =
true;
680 }
else if (Name ==
"if") {
682 ExpectBlockType =
true;
683 }
else if (Name ==
"else") {
684 if (popAndPushWithSameSignature(Name, If, Else))
686 }
else if (Name ==
"catch") {
687 if (popAndPushWithSameSignature(Name, Try, Try))
689 }
else if (Name ==
"catch_all") {
690 if (popAndPushWithSameSignature(Name, Try, CatchAll))
692 }
else if (Name ==
"try_table") {
694 ExpectBlockType =
true;
695 ExpectCatchList =
true;
696 }
else if (Name ==
"end_if") {
697 if (pop(Name, If, Else))
699 }
else if (Name ==
"end_try") {
700 if (pop(Name, Try, CatchAll))
702 }
else if (Name ==
"end_try_table") {
703 if (pop(Name, TryTable))
705 }
else if (Name ==
"delegate") {
708 }
else if (Name ==
"end_loop") {
711 }
else if (Name ==
"end_block") {
712 if (pop(Name, Block))
714 }
else if (Name ==
"end_function") {
715 ensureLocals(getStreamer());
716 CurrentState = EndFunction;
717 if (pop(Name, Function) || ensureEmptyNestingStack())
719 }
else if (Name ==
"call_indirect" || Name ==
"return_call_indirect") {
723 if (parseFunctionTableOperand(&FunctionTable))
725 ExpectFuncType =
true;
726 }
else if (Name ==
"call_ref" || Name ==
"return_call_ref") {
729 ExpectFuncType =
true;
730 }
else if (Name ==
"ref.test") {
733 ExpectFuncType =
true;
734 }
else if (Name ==
"ref.cast") {
737 ExpectFuncType =
true;
738 }
else if (Name ==
"select") {
742 auto Op = std::make_unique<WebAssemblyOperand>(
743 Lexer.getLoc(), Lexer.getLoc(), WebAssemblyOperand::TyLOp{});
745 auto &
Id = Lexer.getTok();
748 return error(
"unknown value type in select operand list: ", Id);
749 Op->TyL.List.push_back(
static_cast<uint8_t
>(*Ty));
750 Op->EndLoc =
Id.getEndLoc();
756 if (
Name.contains(
"atomic.")) {
757 if (addMemOrderOrDefault(Operands))
762 auto PeekCatchList = [&]() {
765 AsmToken NextTok = Lexer.peekTok();
771 if (ExpectFuncType ||
778 auto Loc = Parser.getTok();
780 if (parseSignature(Signature))
783 TC.setLastSig(*Signature);
785 NestingStack.back().Sig = *Signature;
786 ExpectBlockType =
false;
789 auto *WasmSym =
static_cast<MCSymbolWasm *
>(Sym);
790 WasmSym->setSignature(Signature);
794 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
795 Loc.getLoc(), Loc.getEndLoc(), WebAssemblyOperand::SymOp{Expr}));
805 if (ExpectCatchList && PeekCatchList()) {
806 if (ExpectBlockType) {
807 ExpectBlockType =
false;
808 addBlockTypeOperand(Operands, NameLoc, WebAssembly::BlockType::Void);
810 if (parseCatchList(Operands))
812 ExpectCatchList =
false;
816 auto &Tok = Lexer.getTok();
819 if (!parseSpecialFloatMaybe(
false, Operands))
821 auto &
Id = Lexer.getTok();
822 if (ExpectBlockType) {
825 if (
BT == WebAssembly::BlockType::Invalid)
826 return error(
"Unknown block type: ", Id);
827 addBlockTypeOperand(Operands, NameLoc,
BT);
828 ExpectBlockType =
false;
832 if (ExpectCatchList && PeekCatchList()) {
833 if (parseCatchList(Operands))
835 ExpectCatchList =
false;
842 if (Parser.parseExpression(Val, End))
843 return error(
"Cannot parse symbol: ", Lexer.getTok());
844 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
845 Start, End, WebAssemblyOperand::SymOp{Val}));
846 if (checkForP2AlignIfLoadStore(Operands, Name))
854 parseSingleInteger(
true, Operands);
855 if (checkForP2AlignIfLoadStore(Operands, Name))
858 if (parseSingleFloat(
true, Operands))
860 }
else if (!parseSpecialFloatMaybe(
true, Operands)) {
862 return error(
"Expected numeric constant instead got: ",
867 parseSingleInteger(
false, Operands);
868 if (checkForP2AlignIfLoadStore(Operands, Name))
872 if (parseSingleFloat(
false, Operands))
878 auto Op = std::make_unique<WebAssemblyOperand>(
882 Op->BrL.List.push_back(Lexer.getTok().getIntVal());
892 return error(
"Unexpected token in operand: ", Tok);
905 addBlockTypeOperand(Operands, NameLoc, WebAssembly::BlockType::Void);
908 Operands.
push_back(std::make_unique<WebAssemblyOperand>(
909 NameLoc, NameLoc, WebAssemblyOperand::CaLOp{}));
912 Operands.
push_back(std::move(FunctionTable));
917 bool parseSignature(wasm::WasmSignature *Signature) {
920 if (parseRegTypeList(Signature->
Params))
928 if (parseRegTypeList(Signature->
Returns))
936 auto Op = std::make_unique<WebAssemblyOperand>(
937 Lexer.getTok().getLoc(), SMLoc(), WebAssemblyOperand::CaLOp{});
944 auto CatchStr = expectIdent();
945 if (CatchStr.empty())
947 uint8_t CatchOpcode =
948 StringSwitch<uint8_t>(CatchStr)
954 if (CatchOpcode == 0xff)
956 "Expected catch/catch_ref/catch_all/catch_all_ref, instead got: " +
959 const MCExpr *
Tag =
nullptr;
962 if (Parser.parseExpression(
Tag))
963 return error(
"Cannot parse symbol: ", Lexer.getTok());
966 auto &DestTok = Lexer.getTok();
968 return error(
"Expected integer constant, instead got: ", DestTok);
969 unsigned Dest = DestTok.getIntVal();
972 EndLoc = Lexer.getTok().getEndLoc();
976 Op->CaL.List.push_back({CatchOpcode,
Tag, Dest});
984 bool checkDataSection() {
985 if (CurrentState != DataSection) {
986 auto *WS =
static_cast<const MCSectionWasm *
>(
987 getStreamer().getCurrentSectionOnly());
988 if (WS && WS->isText())
989 return error(
"data directive must occur in a data segment: ",
992 CurrentState = DataSection;
999 ParseStatus parseDirective(AsmToken DirectiveID)
override {
1001 auto &Out = getStreamer();
1003 reinterpret_cast<WebAssemblyTargetStreamer &
>(*Out.getTargetStreamer());
1004 auto &Ctx = Out.getContext();
1006 if (DirectiveID.
getString() ==
".globaltype") {
1007 auto SymName = expectIdent();
1008 if (SymName.empty())
1012 auto TypeTok = Lexer.getTok();
1018 return error(
"Unknown type in .globaltype directive: ", TypeTok);
1022 bool Mutable =
true;
1024 TypeTok = Lexer.getTok();
1025 auto Id = expectIdent();
1028 if (Id ==
"immutable")
1032 return error(
"Unknown type in .globaltype modifier: ", TypeTok);
1038 WasmSym->setGlobalType(wasm::WasmGlobalType{uint8_t(*
Type), Mutable});
1040 TOut.emitGlobalType(WasmSym);
1044 if (DirectiveID.
getString() ==
".tabletype") {
1046 auto SymName = expectIdent();
1047 if (SymName.empty())
1052 auto ElemTypeTok = Lexer.getTok();
1053 auto ElemTypeName = expectIdent();
1054 if (ElemTypeName.empty())
1056 std::optional<wasm::ValType> ElemType =
1059 return error(
"Unknown type in .tabletype directive: ", ElemTypeTok);
1061 wasm::WasmLimits Limits = defaultLimits();
1073 wasm::WasmTableType
Type = {*ElemType, Limits};
1074 WasmSym->setTableType(
Type);
1075 TOut.emitTableType(WasmSym);
1079 if (DirectiveID.
getString() ==
".functype") {
1085 auto SymName = expectIdent();
1086 if (SymName.empty())
1090 if (WasmSym->isDefined()) {
1101 if (CurrentState != FunctionLabel) {
1103 if (ensureEmptyNestingStack())
1107 CurrentState = FunctionStart;
1108 LastFunctionLabel = WasmSym;
1111 if (parseSignature(Signature))
1113 if (CurrentState == FunctionStart)
1114 TC.funcDecl(*Signature);
1115 WasmSym->setSignature(Signature);
1117 TOut.emitFunctionType(WasmSym);
1122 if (DirectiveID.
getString() ==
".export_name") {
1123 auto SymName = expectIdent();
1124 if (SymName.empty())
1128 auto ExportName = expectStringOrIdent();
1129 if (ExportName.empty())
1134 TOut.emitExportName(WasmSym, ExportName);
1138 if (DirectiveID.
getString() ==
".import_module") {
1139 auto SymName = expectIdent();
1140 if (SymName.empty())
1144 auto ImportModule = expectStringOrIdent();
1145 if (ImportModule.empty())
1150 TOut.emitImportModule(WasmSym, ImportModule);
1154 if (DirectiveID.
getString() ==
".import_name") {
1155 auto SymName = expectIdent();
1156 if (SymName.empty())
1160 StringRef ImportName = expectStringOrIdent();
1161 if (ImportName.
empty())
1166 TOut.emitImportName(WasmSym, ImportName);
1170 if (DirectiveID.
getString() ==
".tagtype") {
1171 auto SymName = expectIdent();
1172 if (SymName.empty())
1177 if (parseRegTypeList(Signature->
Params))
1179 WasmSym->setSignature(Signature);
1181 TOut.emitTagType(WasmSym);
1186 if (DirectiveID.
getString() ==
".local") {
1187 if (CurrentState != FunctionStart)
1188 return error(
".local directive should follow the start of a function: ",
1191 if (parseRegTypeList(Locals))
1193 TC.localDecl(Locals);
1194 TOut.emitLocal(Locals);
1195 CurrentState = FunctionLocals;
1199 if (DirectiveID.
getString() ==
".int8" ||
1203 if (checkDataSection())
1207 if (Parser.parseExpression(Val, End))
1208 return error(
"Cannot parse .int expression: ", Lexer.getTok());
1211 Out.emitValue(Val, NumBits / 8, End);
1215 if (DirectiveID.
getString() ==
".asciz") {
1216 if (checkDataSection())
1219 if (Parser.parseEscapedString(S))
1220 return error(
"Cannot parse string constant: ", Lexer.getTok());
1221 Out.emitBytes(StringRef(S.c_str(), S.length() + 1));
1229 void ensureLocals(MCStreamer &Out) {
1230 if (CurrentState == FunctionStart) {
1234 auto &TOut =
reinterpret_cast<WebAssemblyTargetStreamer &
>(
1237 CurrentState = FunctionLocals;
1241 bool matchAndEmitInstruction(SMLoc IDLoc,
unsigned & ,
1243 uint64_t &ErrorInfo,
1244 bool MatchingInlineAsm)
override {
1247 FeatureBitset MissingFeatures;
1248 unsigned MatchResult = MatchInstructionImpl(
1249 Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm);
1250 switch (MatchResult) {
1251 case Match_Success: {
1259 for (
unsigned E =
Desc.getNumOperands();
I <
E; ++
I) {
1262 if (
Op.getImm() == -1) {
1268 assert(
I < 2 &&
"Default p2align set but operand not found");
1275 static_cast<uint16_t
>(Inst.
getOpcode()));
1281 TC.typeCheck(IDLoc, Inst, Operands);
1283 if (CurrentState == EndFunction) {
1284 onEndOfFunction(IDLoc);
1286 CurrentState = Instructions;
1290 case Match_MissingFeature: {
1291 assert(MissingFeatures.
count() > 0 &&
"Expected missing features");
1292 SmallString<128> Message;
1293 raw_svector_ostream OS(Message);
1294 OS <<
"instruction requires:";
1295 for (
unsigned I = 0,
E = MissingFeatures.
size();
I !=
E; ++
I)
1296 if (MissingFeatures.
test(
I))
1298 return Parser.Error(IDLoc, Message);
1300 case Match_MnemonicFail:
1301 return Parser.Error(IDLoc,
"invalid instruction");
1302 case Match_NearMisses:
1303 return Parser.Error(IDLoc,
"ambiguous instruction");
1304 case Match_InvalidTiedOperand:
1305 case Match_InvalidOperand: {
1306 SMLoc ErrorLoc = IDLoc;
1307 if (ErrorInfo != ~0ULL) {
1308 if (ErrorInfo >= Operands.
size())
1309 return Parser.Error(IDLoc,
"too few operands for instruction");
1310 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
1311 if (ErrorLoc == SMLoc())
1314 return Parser.Error(ErrorLoc,
"invalid operand for instruction");
1320 void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc)
override {
1322 auto *CWS =
static_cast<const MCSectionWasm *
>(
1323 getStreamer().getCurrentSectionOnly());
1327 auto *WasmSym =
static_cast<MCSymbolWasm *
>(
Symbol);
1332 "Wasm doesn\'t support data symbols in text sections");
1339 auto SymName =
Symbol->getName();
1340 if (SymName.starts_with(
".L"))
1347 std::string SecName = (
".text." + SymName).str();
1349 auto *Group = CWS->getGroup();
1355 WasmSym->setComdat(
true);
1358 getStreamer().switchSection(WS);
1363 if (WasmSym->isFunction()) {
1373 ensureEmptyNestingStack(IDLoc);
1374 CurrentState = FunctionLabel;
1375 LastFunctionLabel =
Symbol;
1380 void onEndOfFunction(SMLoc ErrorLoc) {
1382 TC.endOfFunction(ErrorLoc,
true);
1387 void onEndOfFile()
override { ensureEmptyNestingStack(); }
1398#define GET_REGISTER_MATCHER
1399#define GET_SUBTARGET_FEATURE_NAME
1400#define GET_MATCHER_IMPLEMENTATION
1401#include "WebAssemblyGenAsmMatcher.inc"
1405 for (
auto &ME : MatchTable0) {
1406 if (ME.Opcode ==
Opc) {
1407 return ME.getMnemonic();
1410 assert(
false &&
"mnemonic not found");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_EXTERNAL_VISIBILITY
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
static constexpr unsigned SM(unsigned Version)
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyAsmParser()
StringRef getMnemonic(unsigned Opc)
static const char * getSubtargetFeatureName(uint64_t Val)
This file is part of the WebAssembly Assembler.
This file contains the declaration of the WebAssemblyMCAsmInfo class.
This file provides WebAssembly-specific target descriptions.
This file contains the declaration of the WebAssembly-specific type parsing utility functions.
This file registers the WebAssembly target.
This file declares WebAssembly-specific target streamer classes.
LLVM_ABI SMLoc getLoc() const
int64_t getIntVal() const
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
bool is(TokenKind K) const
TokenKind getKind() 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.
constexpr bool test(unsigned I) const
constexpr size_t size() const
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
Context object for machine code objects.
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
LLVM_ABI wasm::WasmSignature * createWasmSignature()
Allocates and returns a new WasmSignature instance (with empty parameter and return type lists).
StringRef allocateString(StringRef s)
Allocates a copy of the given string on the allocator managed by this context and returns the result.
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
unsigned getOpcode() const
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
const MCOperand & getOperand(unsigned i) const
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createSFPImm(uint32_t Val)
static MCOperand createImm(int64_t Val)
static MCOperand createDFPImm(uint64_t Val)
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
Wrapper class representing physical registers. Should be passed by value.
static constexpr unsigned NonUniqueID
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
MCTargetStreamer * getTargetStreamer()
bool checkFeatures(StringRef FS) const
Check whether the subtarget features are enabled/disabled as per the provided string,...
const FeatureBitset & getFeatureBits() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
void setFunctionTable(bool is64)
MCTargetAsmParser - Generic interface to target specific assembly parsers.
static constexpr StatusTy Failure
static constexpr StatusTy NoMatch
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
constexpr const char * getPointer() const
static SectionKind getText()
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
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.
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
#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.
@ C
The default llvm calling convention, compatible with C.
int32_t getWasm64Opcode(uint32_t Opcode)
MCSymbolWasm * getOrCreateFunctionTableSymbol(MCContext &Ctx, const WebAssemblySubtarget *Subtarget)
Returns the __indirect_function_table, for use in call_indirect and in function bitcasts.
BlockType parseBlockType(StringRef Type)
BlockType
Used as immediate MachineOperands for block signatures.
@ OPERAND_P2ALIGN
p2align immediate for load and store address alignment.
unsigned GetDefaultP2AlignAny(unsigned Opc)
Return the default p2align value for a load or store with the given opcode.
std::optional< wasm::ValType > parseType(StringRef Type)
@ WASM_OPCODE_CATCH_ALL_REF
@ WASM_LIMITS_FLAG_HAS_MAX
@ WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_FUNCTION
This is an optimization pass for GlobalISel generic memory operations.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
static bool isMem(const MachineInstr &MI, unsigned Op)
LLVM_ABI std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \t\n\v\f\r")
getToken - This function extracts one token from source, ignoring any leading characters that appear ...
SmallVectorImpl< std::unique_ptr< MCParsedAsmOperand > > OperandVector
Target & getTheWebAssemblyTarget32()
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
Target & getTheWebAssemblyTarget64()
To bit_cast(const From &from) noexcept
DWARFExpression::Operation Op
@ MCSA_NoDeadStrip
.no_dead_strip (MachO)
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...
SmallVector< ValType, 1 > Returns
SmallVector< ValType, 4 > Params