41#define DEBUG_TYPE "wasm-asm-parser"
60 SMLoc StartLoc, EndLoc;
79 std::vector<unsigned> List;
89 std::vector<CaLOpElem> List;
93 std::vector<uint8_t> List;
106 WebAssemblyOperand(SMLoc Start, SMLoc End, TokOp
T)
107 : Kind(Token), StartLoc(
Start), EndLoc(End), Tok(
T) {}
108 WebAssemblyOperand(SMLoc Start, SMLoc End, IntOp
I)
109 : Kind(Integer), StartLoc(
Start), EndLoc(End),
Int(
I) {}
110 WebAssemblyOperand(SMLoc Start, SMLoc End, FltOp
F)
111 : Kind(Float), StartLoc(
Start), EndLoc(End), Flt(
F) {}
112 WebAssemblyOperand(SMLoc Start, SMLoc End, SymOp S)
113 : Kind(Symbol), StartLoc(
Start), EndLoc(End), Sym(S) {}
114 WebAssemblyOperand(SMLoc Start, SMLoc End, BrLOp
B)
115 : Kind(BrList), StartLoc(
Start), EndLoc(End), BrL(
B) {}
116 WebAssemblyOperand(SMLoc Start, SMLoc End, CaLOp
C)
117 : Kind(CatchList), StartLoc(
Start), EndLoc(End), CaL(
C) {}
118 WebAssemblyOperand(SMLoc Start, SMLoc End, TyLOp
T)
119 : Kind(TypeList), StartLoc(
Start), EndLoc(End), TyL(
T) {}
121 ~WebAssemblyOperand()
override {
130 bool isToken()
const override {
return Kind == Token; }
131 bool isImm()
const override {
return Kind == Integer || Kind == Symbol; }
132 bool isFPImm()
const {
return Kind == Float; }
133 bool isMem()
const override {
return false; }
134 bool isReg()
const override {
return false; }
135 bool isBrList()
const {
return Kind == BrList; }
136 bool isCatchList()
const {
return Kind == CatchList; }
137 bool isTypeList()
const {
return Kind == TypeList; }
139 MCRegister
getReg()
const override {
149 SMLoc getStartLoc()
const override {
return StartLoc; }
150 SMLoc getEndLoc()
const override {
return EndLoc; }
152 void addRegOperands(MCInst &,
unsigned)
const {
157 void addImmOperands(MCInst &Inst,
unsigned N)
const {
158 assert(
N == 1 &&
"Invalid number of operands!");
161 else if (Kind == Symbol)
167 void addFPImmf32Operands(MCInst &Inst,
unsigned N)
const {
168 assert(
N == 1 &&
"Invalid number of operands!");
176 void addFPImmf64Operands(MCInst &Inst,
unsigned N)
const {
177 assert(
N == 1 &&
"Invalid number of operands!");
184 void addBrListOperands(MCInst &Inst,
unsigned N)
const {
185 assert(
N == 1 && isBrList() &&
"Invalid BrList!");
186 for (
auto Br : BrL.List)
190 void addCatchListOperands(MCInst &Inst,
unsigned N)
const {
191 assert(
N == 1 && isCatchList() &&
"Invalid CatchList!");
193 for (
auto Ca : CaL.List) {
202 void addTypeListOperands(MCInst &Inst,
unsigned N)
const {
203 assert(
N == 1 && isTypeList() &&
"Invalid TypeList!");
205 for (
auto Ty : TyL.List)
209 void print(raw_ostream &OS,
const MCAsmInfo &MAI)
const override {
212 OS <<
"Tok:" << Tok.Tok;
215 OS <<
"Int:" <<
Int.Val;
218 OS <<
"Flt:" << Flt.Val;
221 OS <<
"Sym:" << Sym.Exp;
224 OS <<
"BrList:" << BrL.List.size();
227 OS <<
"CaList:" << CaL.List.size();
230 OS <<
"TyList:" << TyL.List.size();
244 auto *Sym =
static_cast<MCSymbolWasm *
>(Ctx.lookupSymbol(Name));
246 if (!Sym->isFunctionTable())
247 Ctx.reportError(
SMLoc(),
"symbol is not a wasm funcref table");
249 Sym =
static_cast<MCSymbolWasm *
>(Ctx.getOrCreateSymbol(Name));
274 } CurrentState = FileStart;
290 wasm::WasmSignature Sig;
292 std::vector<Nested> NestingStack;
294 MCSymbolWasm *DefaultFunctionTable =
nullptr;
295 MCSymbol *LastFunctionLabel =
nullptr;
299 WebAssemblyAsmTypeCheck TC;
304 WebAssemblyAsmParser(
const MCSubtargetInfo &STI, MCAsmParser &Parser,
305 const MCInstrInfo &MII)
306 : MCTargetAsmParser(STI, MII), Parser(Parser), Lexer(Parser.getLexer()),
307 Is64(STI.getTargetTriple().isArch64Bit()), TC(Parser, MII, Is64),
308 SkipTypeCheck(Parser.
getContext().getTargetOptions().MCNoTypeCheck) {
309 setAvailableFeatures(ComputeAvailableFeatures(STI.
getFeatureBits()));
312 auto &SM = Parser.getSourceManager();
314 SM.getBufferInfo(SM.getMainFileID()).Buffer->getBufferIdentifier();
315 if (BufferName ==
"<inline asm>")
316 SkipTypeCheck =
true;
319 void Initialize(MCAsmParser &Parser)
override {
323 getContext(),
"__indirect_function_table", Is64);
326 DefaultFunctionTable->setOmitFromLinkingSection();
329#define GET_ASSEMBLER_HEADER
330#include "WebAssemblyGenAsmMatcher.inc"
336 ParseStatus tryParseRegister(MCRegister &
Reg, SMLoc &StartLoc,
337 SMLoc &EndLoc)
override {
341 bool error(
const Twine &
Msg,
const AsmToken &Tok) {
345 bool error(
const Twine &
Msg, SMLoc Loc = SMLoc()) {
346 return Parser.Error(Loc.isValid() ? Loc : Lexer.getTok().getLoc(),
Msg);
349 std::pair<StringRef, StringRef> nestingString(NestingType NT) {
352 return {
"function",
"end_function"};
354 return {
"block",
"end_block"};
356 return {
"loop",
"end_loop"};
358 return {
"try",
"end_try/delegate"};
360 return {
"catch_all",
"end_try"};
362 return {
"try_table",
"end_try_table"};
364 return {
"if",
"end_if"};
366 return {
"else",
"end_if"};
372 void push(NestingType NT, wasm::WasmSignature Sig = wasm::WasmSignature()) {
373 NestingStack.push_back({
NT, Sig});
376 bool pop(StringRef Ins, NestingType NT1, NestingType NT2 = Undefined) {
377 if (NestingStack.empty())
378 return error(Twine(
"End of block construct with no start: ") + Ins);
379 auto Top = NestingStack.back();
380 if (Top.NT != NT1 && Top.NT != NT2)
381 return error(Twine(
"Block construct type mismatch, expected: ") +
382 nestingString(Top.NT).second +
", instead got: " + Ins);
383 TC.setLastSig(Top.Sig);
384 NestingStack.pop_back();
390 bool popAndPushWithSameSignature(StringRef Ins, NestingType PopNT,
391 NestingType PushNT) {
392 if (NestingStack.empty())
393 return error(Twine(
"End of block construct with no start: ") + Ins);
394 auto Sig = NestingStack.back().Sig;
401 bool ensureEmptyNestingStack(SMLoc Loc = SMLoc()) {
402 auto Err = !NestingStack.empty();
403 while (!NestingStack.empty()) {
404 error(Twine(
"Unmatched block construct(s) at function end: ") +
405 nestingString(NestingStack.back().NT).first,
407 NestingStack.pop_back();
413 auto Ok = Lexer.is(Kind);
421 return error(std::string(
"Expected ") + KindName +
", instead got: ",
426 StringRef expectIdent() {
428 error(
"Expected identifier, got: ", Lexer.getTok());
431 auto Name = Lexer.getTok().getString();
436 StringRef expectStringOrIdent() {
438 auto Str = Lexer.getTok().getStringContents();
443 auto Name = Lexer.getTok().getString();
447 error(
"Expected string or identifier, got: ", Lexer.getTok());
451 bool parseRegTypeList(SmallVectorImpl<wasm::ValType> &Types) {
453 auto Type = WebAssembly::parseType(Lexer.getTok().getString());
455 return error(
"unknown type: ", Lexer.getTok());
465 auto &
Int = Lexer.getTok();
466 int64_t Val =
Int.getIntVal();
469 Operands.push_back(std::make_unique<WebAssemblyOperand>(
470 Int.getLoc(),
Int.getEndLoc(), WebAssemblyOperand::IntOp{Val}));
475 auto &Flt = Lexer.getTok();
477 if (Flt.getString().getAsDouble(Val,
false))
478 return error(
"Cannot parse real: ", Flt);
481 Operands.push_back(std::make_unique<WebAssemblyOperand>(
482 Flt.getLoc(), Flt.getEndLoc(), WebAssemblyOperand::FltOp{Val}));
490 auto &Flt = Lexer.getTok();
491 auto S = Flt.getString();
493 if (S.compare_insensitive(
"infinity") == 0) {
494 Val = std::numeric_limits<double>::infinity();
495 }
else if (S.compare_insensitive(
"nan") == 0) {
496 Val = std::numeric_limits<double>::quiet_NaN();
502 Operands.push_back(std::make_unique<WebAssemblyOperand>(
503 Flt.getLoc(), Flt.getEndLoc(), WebAssemblyOperand::FltOp{Val}));
509 auto &Tok = Lexer.getTok();
513 Order = StringSwitch<int64_t>(S)
519 return error(
"memory ordering requires relaxed-atomics feature: ",
526 Operands.push_back(std::make_unique<WebAssemblyOperand>(
533 auto IsLoadStore = InstName.
contains(
".load") ||
536 auto IsAtomic = InstName.
contains(
"atomic.");
537 if (IsLoadStore || IsAtomic) {
540 auto Id = expectIdent();
542 return error(
"Expected p2align, instead got: " + Id);
546 return error(
"Expected integer constant");
547 parseSingleInteger(
false,
Operands);
552 auto IsLoadStoreLane = InstName.
contains(
"_lane");
553 if (IsLoadStoreLane &&
Operands.size() == 4)
559 auto Tok = Lexer.getTok();
560 Operands.push_back(std::make_unique<WebAssemblyOperand>(
568 WebAssembly::BlockType
BT) {
569 if (
BT == WebAssembly::BlockType::Void) {
570 TC.setLastSig(wasm::WasmSignature{});
574 NestingStack.back().Sig = Sig;
576 Operands.push_back(std::make_unique<WebAssemblyOperand>(
577 NameLoc, NameLoc, WebAssemblyOperand::IntOp{
static_cast<int64_t
>(
BT)}));
580 bool parseLimits(wasm::WasmLimits *Limits) {
581 auto Tok = Lexer.getTok();
583 return error(
"Expected integer constant, instead got: ", Tok);
591 auto Tok = Lexer.getTok();
593 return error(
"Expected integer constant, instead got: ", Tok);
602 bool parseFunctionTableOperand(std::unique_ptr<WebAssemblyOperand> *
Op) {
610 auto &Tok = Lexer.getTok();
615 *
Op = std::make_unique<WebAssemblyOperand>(
622 *
Op = std::make_unique<WebAssemblyOperand>(
623 SMLoc(), SMLoc(), WebAssemblyOperand::SymOp{Val});
630 *
Op = std::make_unique<WebAssemblyOperand>(SMLoc(), SMLoc(),
631 WebAssemblyOperand::IntOp{0});
635 bool parseInstruction(ParseInstructionInfo & , StringRef Name,
645 auto &Sep = Lexer.getTok();
646 if (Sep.getLoc().getPointer() !=
Name.end() ||
650 Name = StringRef(
Name.begin(),
Name.size() + Sep.getString().size());
653 auto &
Id = Lexer.getTok();
655 Id.getLoc().getPointer() !=
Name.end())
656 return error(
"Incomplete instruction name: ", Id);
657 Name = StringRef(
Name.begin(),
Name.size() +
Id.getString().size());
662 Operands.push_back(std::make_unique<WebAssemblyOperand>(
664 WebAssemblyOperand::TokOp{Name}));
668 bool ExpectBlockType =
false;
669 bool ExpectFuncType =
false;
670 bool ExpectCatchList =
false;
671 std::unique_ptr<WebAssemblyOperand> FunctionTable;
672 if (Name ==
"block") {
674 ExpectBlockType =
true;
675 }
else if (Name ==
"loop") {
677 ExpectBlockType =
true;
678 }
else if (Name ==
"try") {
680 ExpectBlockType =
true;
681 }
else if (Name ==
"if") {
683 ExpectBlockType =
true;
684 }
else if (Name ==
"else") {
685 if (popAndPushWithSameSignature(Name, If, Else))
687 }
else if (Name ==
"catch") {
688 if (popAndPushWithSameSignature(Name, Try, Try))
690 }
else if (Name ==
"catch_all") {
691 if (popAndPushWithSameSignature(Name, Try, CatchAll))
693 }
else if (Name ==
"try_table") {
695 ExpectBlockType =
true;
696 ExpectCatchList =
true;
697 }
else if (Name ==
"end_if") {
698 if (pop(Name, If, Else))
700 }
else if (Name ==
"end_try") {
701 if (pop(Name, Try, CatchAll))
703 }
else if (Name ==
"end_try_table") {
704 if (pop(Name, TryTable))
706 }
else if (Name ==
"delegate") {
709 }
else if (Name ==
"end_loop") {
712 }
else if (Name ==
"end_block") {
713 if (pop(Name, Block))
715 }
else if (Name ==
"end_function") {
716 ensureLocals(getStreamer());
717 CurrentState = EndFunction;
718 if (pop(Name, Function) || ensureEmptyNestingStack())
720 }
else if (Name ==
"call_indirect" || Name ==
"return_call_indirect") {
724 if (parseFunctionTableOperand(&FunctionTable))
726 ExpectFuncType =
true;
727 }
else if (Name ==
"call_ref" || Name ==
"return_call_ref") {
730 ExpectFuncType =
true;
731 }
else if (Name ==
"ref.test") {
734 ExpectFuncType =
true;
735 }
else if (Name ==
"ref.cast") {
738 ExpectFuncType =
true;
739 }
else if (Name ==
"select") {
743 auto Op = std::make_unique<WebAssemblyOperand>(
744 Lexer.getLoc(), Lexer.getLoc(), WebAssemblyOperand::TyLOp{});
746 auto &
Id = Lexer.getTok();
747 auto Ty = WebAssembly::parseType(
Id.getString());
749 return error(
"unknown value type in select operand list: ", Id);
750 Op->TyL.List.push_back(
static_cast<uint8_t
>(*Ty));
751 Op->EndLoc =
Id.getEndLoc();
757 if (
Name.contains(
"atomic.")) {
763 auto PeekCatchList = [&]() {
766 AsmToken NextTok = Lexer.peekTok();
772 if (ExpectFuncType ||
779 auto Loc = Parser.getTok();
781 if (parseSignature(Signature))
784 TC.setLastSig(*Signature);
786 NestingStack.back().Sig = *Signature;
787 ExpectBlockType =
false;
790 auto *WasmSym =
static_cast<MCSymbolWasm *
>(Sym);
791 WasmSym->setSignature(Signature);
795 Operands.push_back(std::make_unique<WebAssemblyOperand>(
796 Loc.getLoc(), Loc.getEndLoc(), WebAssemblyOperand::SymOp{Expr}));
806 if (ExpectCatchList && PeekCatchList()) {
807 if (ExpectBlockType) {
808 ExpectBlockType =
false;
809 addBlockTypeOperand(
Operands, NameLoc, WebAssembly::BlockType::Void);
813 ExpectCatchList =
false;
817 auto &Tok = Lexer.getTok();
820 if (!parseSpecialFloatMaybe(
false,
Operands))
822 auto &
Id = Lexer.getTok();
823 if (ExpectBlockType) {
825 auto BT = WebAssembly::parseBlockType(
Id.getString());
826 if (
BT == WebAssembly::BlockType::Invalid)
827 return error(
"Unknown block type: ", Id);
829 ExpectBlockType =
false;
833 if (ExpectCatchList && PeekCatchList()) {
836 ExpectCatchList =
false;
843 if (Parser.parseExpression(Val, End))
844 return error(
"Cannot parse symbol: ", Lexer.getTok());
845 Operands.push_back(std::make_unique<WebAssemblyOperand>(
846 Start, End, WebAssemblyOperand::SymOp{Val}));
847 if (checkForP2AlignIfLoadStore(
Operands, Name))
856 if (checkForP2AlignIfLoadStore(
Operands, Name))
859 if (parseSingleFloat(
true,
Operands))
861 }
else if (!parseSpecialFloatMaybe(
true,
Operands)) {
863 return error(
"Expected numeric constant instead got: ",
868 parseSingleInteger(
false,
Operands);
869 if (checkForP2AlignIfLoadStore(
Operands, Name))
873 if (parseSingleFloat(
false,
Operands))
879 auto Op = std::make_unique<WebAssemblyOperand>(
883 Op->BrL.List.push_back(Lexer.getTok().getIntVal());
893 return error(
"Unexpected token in operand: ", Tok);
906 addBlockTypeOperand(
Operands, NameLoc, WebAssembly::BlockType::Void);
909 Operands.push_back(std::make_unique<WebAssemblyOperand>(
910 NameLoc, NameLoc, WebAssemblyOperand::CaLOp{}));
913 Operands.push_back(std::move(FunctionTable));
918 bool parseSignature(wasm::WasmSignature *Signature) {
921 if (parseRegTypeList(Signature->
Params))
929 if (parseRegTypeList(Signature->
Returns))
937 auto Op = std::make_unique<WebAssemblyOperand>(
938 Lexer.getTok().getLoc(), SMLoc(), WebAssemblyOperand::CaLOp{});
945 auto CatchStr = expectIdent();
946 if (CatchStr.empty())
948 uint8_t CatchOpcode =
949 StringSwitch<uint8_t>(CatchStr)
955 if (CatchOpcode == 0xff)
957 "Expected catch/catch_ref/catch_all/catch_all_ref, instead got: " +
960 const MCExpr *
Tag =
nullptr;
963 if (Parser.parseExpression(
Tag))
964 return error(
"Cannot parse symbol: ", Lexer.getTok());
967 auto &DestTok = Lexer.getTok();
969 return error(
"Expected integer constant, instead got: ", DestTok);
970 unsigned Dest = DestTok.getIntVal();
973 EndLoc = Lexer.getTok().getEndLoc();
977 Op->CaL.List.push_back({CatchOpcode,
Tag, Dest});
985 bool checkDataSection() {
986 if (CurrentState != DataSection) {
987 auto *WS =
static_cast<const MCSectionWasm *
>(
988 getStreamer().getCurrentSectionOnly());
989 if (WS && WS->isText())
990 return error(
"data directive must occur in a data segment: ",
993 CurrentState = DataSection;
1000 ParseStatus parseDirective(AsmToken DirectiveID)
override {
1002 auto &Out = getStreamer();
1004 reinterpret_cast<WebAssemblyTargetStreamer &
>(*Out.getTargetStreamer());
1005 auto &Ctx = Out.getContext();
1007 if (DirectiveID.
getString() ==
".globaltype") {
1008 auto SymName = expectIdent();
1009 if (SymName.empty())
1013 auto TypeTok = Lexer.getTok();
1017 auto Type = WebAssembly::parseType(TypeName);
1019 return error(
"Unknown type in .globaltype directive: ", TypeTok);
1023 bool Mutable =
true;
1025 TypeTok = Lexer.getTok();
1026 auto Id = expectIdent();
1029 if (Id ==
"immutable")
1033 return error(
"Unknown type in .globaltype modifier: ", TypeTok);
1039 WasmSym->setGlobalType(wasm::WasmGlobalType{uint8_t(*
Type), Mutable});
1041 TOut.emitGlobalType(WasmSym);
1045 if (DirectiveID.
getString() ==
".tabletype") {
1047 auto SymName = expectIdent();
1048 if (SymName.empty())
1053 auto ElemTypeTok = Lexer.getTok();
1054 auto ElemTypeName = expectIdent();
1055 if (ElemTypeName.empty())
1057 std::optional<wasm::ValType> ElemType =
1058 WebAssembly::parseType(ElemTypeName);
1060 return error(
"Unknown type in .tabletype directive: ", ElemTypeTok);
1062 wasm::WasmLimits Limits = defaultLimits();
1074 wasm::WasmTableType
Type = {*ElemType, Limits};
1075 WasmSym->setTableType(
Type);
1076 TOut.emitTableType(WasmSym);
1080 if (DirectiveID.
getString() ==
".functype") {
1086 auto SymName = expectIdent();
1087 if (SymName.empty())
1091 if (WasmSym->isDefined()) {
1102 if (CurrentState != FunctionLabel) {
1104 if (ensureEmptyNestingStack())
1108 CurrentState = FunctionStart;
1109 LastFunctionLabel = WasmSym;
1112 if (parseSignature(Signature))
1114 if (CurrentState == FunctionStart)
1115 TC.funcDecl(*Signature);
1116 WasmSym->setSignature(Signature);
1118 TOut.emitFunctionType(WasmSym);
1123 if (DirectiveID.
getString() ==
".export_name") {
1124 auto SymName = expectIdent();
1125 if (SymName.empty())
1129 auto ExportName = expectStringOrIdent();
1130 if (ExportName.empty())
1135 TOut.emitExportName(WasmSym, ExportName);
1139 if (DirectiveID.
getString() ==
".import_module") {
1140 auto SymName = expectIdent();
1141 if (SymName.empty())
1145 auto ImportModule = expectStringOrIdent();
1146 if (ImportModule.empty())
1151 TOut.emitImportModule(WasmSym, ImportModule);
1155 if (DirectiveID.
getString() ==
".import_name") {
1156 auto SymName = expectIdent();
1157 if (SymName.empty())
1161 StringRef ImportName = expectStringOrIdent();
1162 if (ImportName.
empty())
1167 TOut.emitImportName(WasmSym, ImportName);
1171 if (DirectiveID.
getString() ==
".tagtype") {
1172 auto SymName = expectIdent();
1173 if (SymName.empty())
1178 if (parseRegTypeList(Signature->
Params))
1180 WasmSym->setSignature(Signature);
1182 TOut.emitTagType(WasmSym);
1187 if (DirectiveID.
getString() ==
".local") {
1188 if (CurrentState != FunctionStart)
1189 return error(
".local directive should follow the start of a function: ",
1192 if (parseRegTypeList(Locals))
1194 TC.localDecl(Locals);
1195 TOut.emitLocal(Locals);
1196 CurrentState = FunctionLocals;
1200 if (DirectiveID.
getString() ==
".int8" ||
1204 if (checkDataSection())
1208 if (Parser.parseExpression(Val, End))
1209 return error(
"Cannot parse .int expression: ", Lexer.getTok());
1212 Out.emitValue(Val, NumBits / 8, End);
1216 if (DirectiveID.
getString() ==
".asciz") {
1217 if (checkDataSection())
1220 if (Parser.parseEscapedString(S))
1221 return error(
"Cannot parse string constant: ", Lexer.getTok());
1222 Out.emitBytes(StringRef(S.c_str(), S.length() + 1));
1230 void ensureLocals(MCStreamer &Out) {
1231 if (CurrentState == FunctionStart) {
1235 auto &TOut =
reinterpret_cast<WebAssemblyTargetStreamer &
>(
1238 CurrentState = FunctionLocals;
1242 bool matchAndEmitInstruction(SMLoc IDLoc,
unsigned & ,
1244 uint64_t &ErrorInfo,
1245 bool MatchingInlineAsm)
override {
1248 FeatureBitset MissingFeatures;
1249 unsigned MatchResult = MatchInstructionImpl(
1250 Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm);
1251 switch (MatchResult) {
1252 case Match_Success: {
1256 auto Align = WebAssembly::GetDefaultP2AlignAny(Inst.
getOpcode());
1260 for (
unsigned E =
Desc.getNumOperands();
I <
E; ++
I) {
1261 if (
Desc.operands()[
I].OperandType == WebAssembly::OPERAND_P2ALIGN) {
1263 if (
Op.getImm() == -1) {
1269 assert(
I < 2 &&
"Default p2align set but operand not found");
1275 auto Opc64 = WebAssembly::getWasm64Opcode(
1276 static_cast<uint16_t
>(Inst.
getOpcode()));
1282 TC.typeCheck(IDLoc, Inst,
Operands);
1284 if (CurrentState == EndFunction) {
1285 onEndOfFunction(IDLoc);
1287 CurrentState = Instructions;
1291 case Match_MissingFeature: {
1292 assert(MissingFeatures.
count() > 0 &&
"Expected missing features");
1293 SmallString<128> Message;
1294 raw_svector_ostream OS(Message);
1295 OS <<
"instruction requires:";
1296 for (
unsigned I = 0,
E = MissingFeatures.
size();
I !=
E; ++
I)
1297 if (MissingFeatures.
test(
I))
1299 return Parser.Error(IDLoc, Message);
1301 case Match_MnemonicFail:
1302 return Parser.Error(IDLoc,
"invalid instruction");
1303 case Match_NearMisses:
1304 return Parser.Error(IDLoc,
"ambiguous instruction");
1305 case Match_InvalidTiedOperand:
1306 case Match_InvalidOperand: {
1307 SMLoc ErrorLoc = IDLoc;
1308 if (ErrorInfo != ~0ULL) {
1310 return Parser.Error(IDLoc,
"too few operands for instruction");
1311 ErrorLoc =
Operands[ErrorInfo]->getStartLoc();
1312 if (ErrorLoc == SMLoc())
1315 return Parser.Error(ErrorLoc,
"invalid operand for instruction");
1321 void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc)
override {
1323 auto *CWS =
static_cast<const MCSectionWasm *
>(
1324 getStreamer().getCurrentSectionOnly());
1328 auto *WasmSym =
static_cast<MCSymbolWasm *
>(
Symbol);
1333 "Wasm doesn\'t support data symbols in text sections");
1340 auto SymName =
Symbol->getName();
1341 if (SymName.starts_with(
".L"))
1348 std::string SecName = (
".text." + SymName).str();
1350 auto *Group = CWS->getGroup();
1356 WasmSym->setComdat(
true);
1359 getStreamer().switchSection(WS);
1364 if (WasmSym->isFunction()) {
1374 ensureEmptyNestingStack(IDLoc);
1375 CurrentState = FunctionLabel;
1376 LastFunctionLabel =
Symbol;
1381 void onEndOfFunction(SMLoc ErrorLoc) {
1383 TC.endOfFunction(ErrorLoc,
true);
1388 void onEndOfFile()
override { ensureEmptyNestingStack(); }
1399#define GET_REGISTER_MATCHER
1400#define GET_SUBTARGET_FEATURE_NAME
1401#define GET_MATCHER_IMPLEMENTATION
1402#include "WebAssemblyGenAsmMatcher.inc"
1406 for (
auto &ME : MatchTable0) {
1407 if (ME.Opcode ==
Opc) {
1408 return ME.getMnemonic();
1411 assert(
false &&
"mnemonic not found");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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)
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()
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.
MCSymbolWasm * getOrCreateFunctionTableSymbol(MCContext &Ctx, const WebAssemblySubtarget *Subtarget)
Returns the __indirect_function_table, for use in call_indirect and in function bitcasts.
@ 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