41 #define DEBUG_TYPE "wasm-asm-parser"
52 SMLoc StartLoc, EndLoc;
71 std::vector<unsigned>
List;
82 WebAssemblyOperand(KindTy K,
SMLoc Start,
SMLoc End, TokOp
T)
83 :
Kind(K), StartLoc(Start), EndLoc(End), Tok(
T) {}
84 WebAssemblyOperand(KindTy K,
SMLoc Start,
SMLoc End, IntOp
I)
85 :
Kind(K), StartLoc(Start), EndLoc(End),
Int(
I) {}
86 WebAssemblyOperand(KindTy K,
SMLoc Start,
SMLoc End, FltOp
F)
87 :
Kind(K), StartLoc(Start), EndLoc(End), Flt(
F) {}
88 WebAssemblyOperand(KindTy K,
SMLoc Start,
SMLoc End, SymOp
S)
89 :
Kind(K), StartLoc(Start), EndLoc(End), Sym(
S) {}
90 WebAssemblyOperand(KindTy K,
SMLoc Start,
SMLoc End)
91 :
Kind(K), StartLoc(Start), EndLoc(End), BrL() {}
93 ~WebAssemblyOperand() {
98 bool isToken()
const override {
return Kind == Token; }
100 bool isFPImm()
const {
return Kind ==
Float; }
101 bool isMem()
const override {
return false; }
102 bool isReg()
const override {
return false; }
103 bool isBrList()
const {
return Kind == BrList; }
105 unsigned getReg()
const override {
115 SMLoc getStartLoc()
const override {
return StartLoc; }
116 SMLoc getEndLoc()
const override {
return EndLoc; }
118 void addRegOperands(
MCInst &,
unsigned)
const {
123 void addImmOperands(
MCInst &Inst,
unsigned N)
const {
124 assert(
N == 1 &&
"Invalid number of operands!");
133 void addFPImmf32Operands(
MCInst &Inst,
unsigned N)
const {
134 assert(
N == 1 &&
"Invalid number of operands!");
142 void addFPImmf64Operands(
MCInst &Inst,
unsigned N)
const {
143 assert(
N == 1 &&
"Invalid number of operands!");
150 void addBrListOperands(
MCInst &Inst,
unsigned N)
const {
151 assert(
N == 1 && isBrList() &&
"Invalid BrList!");
152 for (
auto Br : BrL.List)
159 OS <<
"Tok:" << Tok.Tok;
162 OS <<
"Int:" <<
Int.Val;
165 OS <<
"Flt:" << Flt.Val;
168 OS <<
"Sym:" << Sym.Exp;
171 OS <<
"BrList:" << BrL.List.size();
202 std::vector<std::unique_ptr<wasm::WasmSignature>> Signatures;
203 std::vector<std::unique_ptr<std::string>> Names;
218 } CurrentState = FileStart;
235 std::vector<Nested> NestingStack;
238 MCSymbol *LastFunctionLabel =
nullptr;
250 Lexer(Parser.getLexer()),
251 is64(STI.getTargetTriple().isArch64Bit()),
252 TC(Parser, MII, is64), SkipTypeCheck(
Options.MCNoTypeCheck) {
253 setAvailableFeatures(ComputeAvailableFeatures(STI.
getFeatureBits()));
258 SM.
getBufferInfo(SM.getMainFileID()).Buffer->getBufferIdentifier();
259 if (BufferName ==
"<inline asm>")
260 SkipTypeCheck =
true;
266 DefaultFunctionTable = GetOrCreateFunctionTableSymbol(
267 getContext(),
"__indirect_function_table");
272 #define GET_ASSEMBLER_HEADER
273 #include "WebAssemblyGenAsmMatcher.inc"
276 bool ParseRegister(
unsigned & ,
SMLoc & ,
294 void addSignature(std::unique_ptr<wasm::WasmSignature> &&Sig) {
299 std::unique_ptr<std::string>
N = std::make_unique<std::string>(
Name);
301 return *Names.back();
304 std::pair<StringRef, StringRef> nestingString(NestingType
NT) {
307 return {
"function",
"end_function"};
309 return {
"block",
"end_block"};
311 return {
"loop",
"end_loop"};
313 return {
"try",
"end_try/delegate"};
315 return {
"catch_all",
"end_try"};
317 return {
"if",
"end_if"};
319 return {
"else",
"end_if"};
327 bool pop(
StringRef Ins, NestingType NT1, NestingType NT2 = Undefined) {
328 if (NestingStack.empty())
329 return error(
Twine(
"End of block construct with no start: ") +
Ins);
330 auto Top = NestingStack.back();
331 if (Top.NT != NT1 && Top.NT != NT2)
332 return error(
Twine(
"Block construct type mismatch, expected: ") +
333 nestingString(Top.NT).second +
", instead got: " +
Ins);
335 NestingStack.pop_back();
339 bool ensureEmptyNestingStack() {
340 auto Err = !NestingStack.empty();
341 while (!NestingStack.empty()) {
342 error(
Twine(
"Unmatched block construct(s) at function end: ") +
343 nestingString(NestingStack.back().NT).first);
344 NestingStack.pop_back();
358 return error(std::string(
"Expected ") + KindName +
", instead got: ",
365 error(
"Expected identifier, got: ", Lexer.
getTok());
378 Types.push_back(*
Type);
388 int64_t Val =
Int.getIntVal();
391 Operands.push_back(std::make_unique<WebAssemblyOperand>(
393 WebAssemblyOperand::IntOp{Val}));
398 auto &Flt = Lexer.
getTok();
400 if (Flt.getString().getAsDouble(Val,
false))
401 return error(
"Cannot parse real: ", Flt);
404 Operands.push_back(std::make_unique<WebAssemblyOperand>(
406 WebAssemblyOperand::FltOp{Val}));
414 auto &Flt = Lexer.
getTok();
415 auto S = Flt.getString();
417 if (
S.compare_insensitive(
"infinity") == 0) {
418 Val = std::numeric_limits<double>::infinity();
419 }
else if (
S.compare_insensitive(
"nan") == 0) {
420 Val = std::numeric_limits<double>::quiet_NaN();
426 Operands.push_back(std::make_unique<WebAssemblyOperand>(
428 WebAssemblyOperand::FltOp{Val}));
435 auto IsLoadStore = InstName.
contains(
".load") ||
438 auto IsAtomic = InstName.
contains(
"atomic.");
439 if (IsLoadStore || IsAtomic) {
442 auto Id = expectIdent();
444 return error(
"Expected p2align, instead got: " +
Id);
448 return error(
"Expected integer constant");
449 parseSingleInteger(
false,
Operands);
454 auto IsLoadStoreLane = InstName.
contains(
"_lane");
455 if (IsLoadStoreLane &&
Operands.size() == 4)
461 auto Tok = Lexer.
getTok();
462 Operands.push_back(std::make_unique<WebAssemblyOperand>(
464 WebAssemblyOperand::IntOp{-1}));
475 NestingStack.back().Sig = Sig;
477 Operands.push_back(std::make_unique<WebAssemblyOperand>(
479 WebAssemblyOperand::IntOp{
static_cast<int64_t
>(
BT)}));
483 auto Tok = Lexer.
getTok();
485 return error(
"Expected integer constant, instead got: ", Tok);
493 auto Tok = Lexer.
getTok();
495 return error(
"Expected integer constant, instead got: ", Tok);
504 bool parseFunctionTableOperand(std::unique_ptr<WebAssemblyOperand> *
Op) {
510 auto &Tok = Lexer.
getTok();
513 GetOrCreateFunctionTableSymbol(getContext(), Tok.
getString());
515 *
Op = std::make_unique<WebAssemblyOperand>(
517 WebAssemblyOperand::SymOp{Val});
523 *
Op = std::make_unique<WebAssemblyOperand>(
525 WebAssemblyOperand::SymOp{Val});
535 WebAssemblyOperand::IntOp{0});
550 auto &Sep = Lexer.
getTok();
551 if (Sep.getLoc().getPointer() !=
Name.end() ||
560 Id.getLoc().getPointer() !=
Name.end())
561 return error(
"Incomplete instruction name: ",
Id);
567 Operands.push_back(std::make_unique<WebAssemblyOperand>(
569 WebAssemblyOperand::TokOp{Name}));
573 bool ExpectBlockType =
false;
574 bool ExpectFuncType =
false;
575 std::unique_ptr<WebAssemblyOperand> FunctionTable;
576 if (
Name ==
"block") {
578 ExpectBlockType =
true;
579 }
else if (
Name ==
"loop") {
581 ExpectBlockType =
true;
582 }
else if (
Name ==
"try") {
584 ExpectBlockType =
true;
585 }
else if (
Name ==
"if") {
587 ExpectBlockType =
true;
588 }
else if (
Name ==
"else") {
592 }
else if (
Name ==
"catch") {
596 }
else if (
Name ==
"catch_all") {
600 }
else if (
Name ==
"end_if") {
603 }
else if (
Name ==
"end_try") {
604 if (pop(
Name, Try, CatchAll))
606 }
else if (
Name ==
"delegate") {
609 }
else if (
Name ==
"end_loop") {
612 }
else if (
Name ==
"end_block") {
613 if (pop(
Name, Block))
615 }
else if (
Name ==
"end_function") {
616 ensureLocals(getStreamer());
617 CurrentState = EndFunction;
620 }
else if (
Name ==
"call_indirect" ||
Name ==
"return_call_indirect") {
624 if (parseFunctionTableOperand(&FunctionTable))
626 ExpectFuncType =
true;
634 auto Loc = Parser.
getTok();
635 auto Signature = std::make_unique<wasm::WasmSignature>();
636 if (parseSignature(Signature.get()))
639 ExpectBlockType =
false;
642 NestingStack.back().Sig = *Signature.get();
643 auto &Ctx = getContext();
646 auto *WasmSym = cast<MCSymbolWasm>(Sym);
647 WasmSym->setSignature(Signature.get());
652 Operands.push_back(std::make_unique<WebAssemblyOperand>(
654 WebAssemblyOperand::SymOp{Expr}));
658 auto &Tok = Lexer.
getTok();
661 if (!parseSpecialFloatMaybe(
false,
Operands))
664 if (ExpectBlockType) {
668 return error(
"Unknown block type: ",
Id);
677 return error(
"Cannot parse symbol: ", Lexer.
getTok());
678 Operands.push_back(std::make_unique<WebAssemblyOperand>(
680 WebAssemblyOperand::SymOp{Val}));
693 if (parseSingleFloat(
true,
Operands))
695 }
else if (!parseSpecialFloatMaybe(
true,
Operands)) {
697 return error(
"Expected numeric constant instead got: ",
702 parseSingleInteger(
false,
Operands);
707 if (parseSingleFloat(
false,
Operands))
713 auto Op = std::make_unique<WebAssemblyOperand>(
727 return error(
"Unexpected token in operand: ", Tok);
734 if (ExpectBlockType &&
Operands.size() == 1) {
747 if (parseRegTypeList(Signature->
Params))
755 if (parseRegTypeList(Signature->
Returns))
762 bool CheckDataSection() {
763 if (CurrentState != DataSection) {
764 auto WS = cast<MCSectionWasm>(getStreamer().getCurrentSection().first);
765 if (WS && WS->getKind().isText())
766 return error(
"data directive must occur in a data segment: ",
769 CurrentState = DataSection;
776 bool ParseDirective(
AsmToken DirectiveID)
override {
784 auto &Out = getStreamer();
787 auto &Ctx = Out.getContext();
791 if (DirectiveID.
getString() ==
".globaltype") {
792 auto SymName = expectIdent();
797 auto TypeTok = Lexer.
getTok();
803 return error(
"Unknown type in .globaltype directive: ", TypeTok);
810 auto Id = expectIdent();
811 if (
Id ==
"immutable")
815 return error(
"Unknown type in .globaltype modifier: ", TypeTok);
822 TOut.emitGlobalType(WasmSym);
826 if (DirectiveID.
getString() ==
".tabletype") {
828 auto SymName = expectIdent();
834 auto ElemTypeTok = Lexer.
getTok();
835 auto ElemTypeName = expectIdent();
836 if (ElemTypeName.empty())
840 return error(
"Unknown type in .tabletype directive: ", ElemTypeTok);
851 WasmSym->setTableType(
Type);
852 TOut.emitTableType(WasmSym);
856 if (DirectiveID.
getString() ==
".functype") {
862 auto SymName = expectIdent();
866 if (WasmSym->isDefined()) {
868 if (ensureEmptyNestingStack())
870 CurrentState = FunctionStart;
871 LastFunctionLabel = WasmSym;
874 auto Signature = std::make_unique<wasm::WasmSignature>();
875 if (parseSignature(Signature.get()))
878 WasmSym->setSignature(Signature.get());
881 TOut.emitFunctionType(WasmSym);
886 if (DirectiveID.
getString() ==
".export_name") {
887 auto SymName = expectIdent();
892 auto ExportName = expectIdent();
894 WasmSym->setExportName(storeName(ExportName));
895 TOut.emitExportName(WasmSym, ExportName);
898 if (DirectiveID.
getString() ==
".import_module") {
899 auto SymName = expectIdent();
904 auto ImportModule = expectIdent();
906 WasmSym->setImportModule(storeName(ImportModule));
907 TOut.emitImportModule(WasmSym, ImportModule);
910 if (DirectiveID.
getString() ==
".import_name") {
911 auto SymName = expectIdent();
916 auto ImportName = expectIdent();
918 WasmSym->setImportName(storeName(ImportName));
919 TOut.emitImportName(WasmSym, ImportName);
922 if (DirectiveID.
getString() ==
".tagtype") {
923 auto SymName = expectIdent();
927 auto Signature = std::make_unique<wasm::WasmSignature>();
928 if (parseRegTypeList(Signature->
Params))
930 WasmSym->setSignature(Signature.get());
933 TOut.emitTagType(WasmSym);
938 if (DirectiveID.
getString() ==
".local") {
939 if (CurrentState != FunctionStart)
940 return error(
".local directive should follow the start of a function: ",
943 if (parseRegTypeList(Locals))
946 TOut.emitLocal(Locals);
947 CurrentState = FunctionLocals;
951 if (DirectiveID.
getString() ==
".int8" ||
955 if (CheckDataSection())
return true;
959 return error(
"Cannot parse .int expression: ", Lexer.
getTok());
962 Out.emitValue(Val, NumBits / 8, End);
966 if (DirectiveID.
getString() ==
".asciz") {
967 if (CheckDataSection())
return true;
970 return error(
"Cannot parse string constant: ", Lexer.
getTok());
971 Out.emitBytes(
StringRef(
S.c_str(),
S.length() + 1));
980 if (CurrentState == FunctionStart) {
987 CurrentState = FunctionLocals;
991 bool MatchAndEmitInstruction(
SMLoc IDLoc,
unsigned & ,
994 bool MatchingInlineAsm)
override {
998 unsigned MatchResult = MatchInstructionImpl(
1000 switch (MatchResult) {
1001 case Match_Success: {
1007 if (Op0.getImm() == -1)
1023 if (CurrentState == EndFunction) {
1024 onEndOfFunction(IDLoc);
1030 case Match_MissingFeature: {
1031 assert(MissingFeatures.
count() > 0 &&
"Expected missing features");
1034 OS <<
"instruction requires:";
1035 for (
unsigned i = 0,
e = MissingFeatures.
size();
i !=
e; ++
i)
1036 if (MissingFeatures.
test(
i))
1038 return Parser.
Error(IDLoc, Message);
1040 case Match_MnemonicFail:
1041 return Parser.
Error(IDLoc,
"invalid instruction");
1042 case Match_NearMisses:
1043 return Parser.
Error(IDLoc,
"ambiguous instruction");
1044 case Match_InvalidTiedOperand:
1045 case Match_InvalidOperand: {
1046 SMLoc ErrorLoc = IDLoc;
1049 return Parser.
Error(IDLoc,
"too few operands for instruction");
1051 if (ErrorLoc ==
SMLoc())
1054 return Parser.
Error(ErrorLoc,
"invalid operand for instruction");
1062 auto CWS = cast<MCSectionWasm>(getStreamer().getCurrentSection().first);
1063 if (!CWS || !CWS->getKind().isText())
1066 auto WasmSym = cast<MCSymbolWasm>(
Symbol);
1071 "Wasm doesn\'t support data symbols in text sections");
1078 auto SymName =
Symbol->getName();
1079 if (SymName.startswith(
".L"))
1086 auto SecName =
".text." + SymName;
1088 auto *Group = CWS->getGroup();
1094 WasmSym->setComdat(
true);
1098 getStreamer().switchSection(WS);
1100 if (getContext().getGenDwarfForAssembly())
1101 getContext().addGenDwarfSection(WS);
1104 void onEndOfFunction(
SMLoc ErrorLoc) {
1112 if (!LastFunctionLabel)
return;
1113 auto TempSym = getContext().createLinkerPrivateTempSymbol();
1114 getStreamer().emitLabel(TempSym);
1119 getStreamer().emitELFSize(LastFunctionLabel, Expr);
1122 void onEndOfFile()
override { ensureEmptyNestingStack(); }
1132 #define GET_REGISTER_MATCHER
1133 #define GET_SUBTARGET_FEATURE_NAME
1134 #define GET_MATCHER_IMPLEMENTATION
1135 #include "WebAssemblyGenAsmMatcher.inc"
1139 for (
auto &ME : MatchTable0) {
1140 if (ME.Opcode == Opc) {
1141 return ME.getMnemonic();
1144 assert(
false &&
"mnemonic not found");