40#define DEBUG_TYPE "wasm-asm-parser"
48 : Parser(Parser), MII(MII), is64(is64) {
58 LocalTypes.
insert(LocalTypes.
end(), Locals.begin(), Locals.end());
61void WebAssemblyAsmTypeCheck::dumpTypeStack(
Twine Msg) {
64 for (
auto VT : Stack) {
68 dbgs() << Msg << s <<
'\n';
72bool WebAssemblyAsmTypeCheck::typeError(
SMLoc ErrorLoc,
const Twine &Msg) {
75 if (TypeErrorThisFunction)
80 TypeErrorThisFunction =
true;
81 dumpTypeStack(
"current stack: ");
82 return Parser.
Error(ErrorLoc, Msg);
85bool WebAssemblyAsmTypeCheck::popType(
SMLoc ErrorLoc,
86 std::optional<wasm::ValType>
EVT) {
88 return typeError(ErrorLoc,
91 :
StringRef(
"empty stack while popping value"));
95 return typeError(ErrorLoc,
102bool WebAssemblyAsmTypeCheck::popRefType(
SMLoc ErrorLoc) {
104 return typeError(ErrorLoc,
StringRef(
"empty stack while popping reftype"));
108 return typeError(ErrorLoc,
StringRef(
"popped ") +
110 ", expected reftype");
115bool WebAssemblyAsmTypeCheck::getLocal(
SMLoc ErrorLoc,
const MCInst &Inst,
118 if (Local >= LocalTypes.
size())
119 return typeError(ErrorLoc,
StringRef(
"no local type specified for index ") +
120 std::to_string(Local));
125bool WebAssemblyAsmTypeCheck::checkEnd(
SMLoc ErrorLoc,
bool PopVals) {
127 return typeError(ErrorLoc,
"end: insufficient values on the type stack");
131 if (popType(ErrorLoc, VT))
137 for (
size_t i = 0; i < LastSig.
Returns.
size(); i++) {
148bool WebAssemblyAsmTypeCheck::checkSig(
SMLoc ErrorLoc,
151 if (popType(ErrorLoc, VT))
return true;
156bool WebAssemblyAsmTypeCheck::getSymRef(
SMLoc ErrorLoc,
const MCInst &Inst,
160 return typeError(ErrorLoc,
StringRef(
"expected expression operand"));
161 SymRef = dyn_cast<MCSymbolRefExpr>(
Op.getExpr());
163 return typeError(ErrorLoc,
StringRef(
"expected symbol operand"));
167bool WebAssemblyAsmTypeCheck::getGlobal(
SMLoc ErrorLoc,
const MCInst &Inst,
170 if (getSymRef(ErrorLoc, Inst, SymRef))
172 auto WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
189 return typeError(ErrorLoc,
StringRef(
"symbol ") + WasmSym->getName() +
190 " missing .globaltype");
195bool WebAssemblyAsmTypeCheck::getTable(
SMLoc ErrorLoc,
const MCInst &Inst,
198 if (getSymRef(ErrorLoc, Inst, SymRef))
200 auto WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
203 return typeError(ErrorLoc,
StringRef(
"symbol ") + WasmSym->getName() +
204 " missing .tabletype");
212 if (popType(ErrorLoc, RVT))
215 if (!Stack.
empty()) {
216 return typeError(ErrorLoc, std::to_string(Stack.
size()) +
217 " superfluous return values");
227 dumpTypeStack(
"typechecking " +
Name +
": ");
229 if (
Name ==
"local.get") {
233 }
else if (
Name ==
"local.set") {
236 if (popType(ErrorLoc,
Type))
238 }
else if (
Name ==
"local.tee") {
241 if (popType(ErrorLoc,
Type))
244 }
else if (
Name ==
"global.get") {
248 }
else if (
Name ==
"global.set") {
251 if (popType(ErrorLoc,
Type))
253 }
else if (
Name ==
"table.get") {
259 }
else if (
Name ==
"table.set") {
262 if (popType(ErrorLoc,
Type))
266 }
else if (
Name ==
"table.fill") {
271 if (popType(ErrorLoc,
Type))
275 }
else if (
Name ==
"drop") {
276 if (popType(ErrorLoc, {}))
278 }
else if (
Name ==
"end_block" ||
Name ==
"end_loop" ||
Name ==
"end_if" ||
279 Name ==
"else" ||
Name ==
"end_try") {
280 if (checkEnd(ErrorLoc,
Name ==
"else"))
282 if (
Name ==
"end_block")
284 }
else if (
Name ==
"return") {
287 }
else if (
Name ==
"call_indirect" ||
Name ==
"return_call_indirect") {
290 if (checkSig(ErrorLoc, LastSig))
return true;
293 }
else if (
Name ==
"call" ||
Name ==
"return_call") {
295 if (getSymRef(
Operands[1]->getStartLoc(), Inst, SymRef))
297 auto WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
298 auto Sig = WasmSym->getSignature();
302 " missing .functype");
303 if (checkSig(ErrorLoc, *Sig))
return true;
306 }
else if (
Name ==
"catch") {
308 if (getSymRef(
Operands[1]->getStartLoc(), Inst, SymRef))
310 const auto *WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
311 const auto *Sig = WasmSym->getSignature();
315 " missing .tagtype");
319 }
else if (
Name ==
"unreachable") {
321 }
else if (
Name ==
"ref.is_null") {
322 if (popRefType(ErrorLoc))
330 assert(RegOpc != -1 &&
"Failed to get register version of MC instruction");
331 const auto &II = MII.
get(RegOpc);
333 for (
unsigned I = II.getNumOperands();
I > II.getNumDefs();
I--) {
334 const auto &Op = II.operands()[
I - 1];
337 if (popType(ErrorLoc, VT))
342 for (
unsigned I = 0;
I < II.getNumDefs();
I++) {
343 const auto &Op = II.operands()[
I];
mir Rename Register Operands
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringRef GetMnemonic(unsigned Opc)
StringRef GetMnemonic(unsigned Opc)
This file is part of the WebAssembly Assembler.
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.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
Generic assembler parser interface, for use by target specific assembly parsers.
bool Error(SMLoc L, const Twine &Msg, SMRange Range=std::nullopt)
Return an error at the location L, with the message Msg.
Instances of this class represent a single low-level machine instruction.
unsigned getOpcode() const
const MCOperand & getOperand(unsigned i) const
Interface to description of machine instruction set.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Represent a reference to a symbol from inside an expression.
const MCSymbol & getSymbol() const
VariantKind getKind() const
Represents a location in source code.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
bool endOfFunction(SMLoc ErrorLoc)
void funcDecl(const wasm::WasmSignature &Sig)
void localDecl(const SmallVectorImpl< wasm::ValType > &Locals)
WebAssemblyAsmTypeCheck(MCAsmParser &Parser, const MCInstrInfo &MII, bool is64)
bool typeCheck(SMLoc ErrorLoc, const MCInst &Inst, OperandVector &Operands)
const char * typeToString(wasm::ValType Type)
wasm::ValType regClassToValType(unsigned RC)
bool isRefType(wasm::ValType Type)
int getRegisterOpcode(unsigned short Opcode)
@ WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_FUNCTION
This is an optimization pass for GlobalISel generic memory operations.
auto reverse(ContainerTy &&C)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
SmallVector< ValType, 1 > Returns
SmallVector< ValType, 4 > Params