40#define DEBUG_TYPE "wasm-asm-parser"
48 : Parser(Parser), MII(MII), is64(is64) {
57 LocalTypes.
insert(LocalTypes.
end(), Locals.begin(), Locals.end());
60void WebAssemblyAsmTypeCheck::dumpTypeStack(
Twine Msg) {
63 for (
auto VT : Stack) {
67 dbgs() << Msg << s <<
'\n';
71bool WebAssemblyAsmTypeCheck::typeError(
SMLoc ErrorLoc,
const Twine &Msg) {
74 if (TypeErrorThisFunction)
79 TypeErrorThisFunction =
true;
80 dumpTypeStack(
"current stack: ");
81 return Parser.
Error(ErrorLoc, Msg);
84bool WebAssemblyAsmTypeCheck::popType(
SMLoc ErrorLoc,
85 std::optional<wasm::ValType>
EVT) {
87 return typeError(ErrorLoc,
90 :
StringRef(
"empty stack while popping value"));
94 return typeError(ErrorLoc,
101bool WebAssemblyAsmTypeCheck::popRefType(
SMLoc ErrorLoc) {
103 return typeError(ErrorLoc,
StringRef(
"empty stack while popping reftype"));
107 return typeError(ErrorLoc,
StringRef(
"popped ") +
109 ", expected reftype");
114bool WebAssemblyAsmTypeCheck::getLocal(
SMLoc ErrorLoc,
const MCInst &Inst,
117 if (Local >= LocalTypes.
size())
118 return typeError(ErrorLoc,
StringRef(
"no local type specified for index ") +
119 std::to_string(Local));
124bool WebAssemblyAsmTypeCheck::checkEnd(
SMLoc ErrorLoc,
bool PopVals) {
126 return typeError(ErrorLoc,
"end: insufficient values on the type stack");
130 if (popType(ErrorLoc, VT))
136 for (
size_t i = 0; i < LastSig.
Returns.
size(); i++) {
147bool WebAssemblyAsmTypeCheck::checkSig(
SMLoc ErrorLoc,
150 if (popType(ErrorLoc, VT))
return true;
155bool WebAssemblyAsmTypeCheck::getSymRef(
SMLoc ErrorLoc,
const MCInst &Inst,
159 return typeError(ErrorLoc,
StringRef(
"expected expression operand"));
160 SymRef = dyn_cast<MCSymbolRefExpr>(
Op.getExpr());
162 return typeError(ErrorLoc,
StringRef(
"expected symbol operand"));
166bool WebAssemblyAsmTypeCheck::getGlobal(
SMLoc ErrorLoc,
const MCInst &Inst,
169 if (getSymRef(ErrorLoc, Inst, SymRef))
171 auto WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
188 return typeError(ErrorLoc,
StringRef(
"symbol ") + WasmSym->getName() +
189 " missing .globaltype");
194bool WebAssemblyAsmTypeCheck::getTable(
SMLoc ErrorLoc,
const MCInst &Inst,
197 if (getSymRef(ErrorLoc, Inst, SymRef))
199 auto WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
202 return typeError(ErrorLoc,
StringRef(
"symbol ") + WasmSym->getName() +
203 " missing .tabletype");
211 if (popType(ErrorLoc, RVT))
214 if (!Stack.
empty()) {
215 return typeError(ErrorLoc, std::to_string(Stack.
size()) +
216 " superfluous return values");
226 dumpTypeStack(
"typechecking " +
Name +
": ");
228 if (
Name ==
"local.get") {
232 }
else if (
Name ==
"local.set") {
235 if (popType(ErrorLoc,
Type))
237 }
else if (
Name ==
"local.tee") {
240 if (popType(ErrorLoc,
Type))
243 }
else if (
Name ==
"global.get") {
247 }
else if (
Name ==
"global.set") {
250 if (popType(ErrorLoc,
Type))
252 }
else if (
Name ==
"table.get") {
258 }
else if (
Name ==
"table.set") {
261 if (popType(ErrorLoc,
Type))
265 }
else if (
Name ==
"table.fill") {
270 if (popType(ErrorLoc,
Type))
274 }
else if (
Name ==
"drop") {
275 if (popType(ErrorLoc, {}))
277 }
else if (
Name ==
"end_block" ||
Name ==
"end_loop" ||
Name ==
"end_if" ||
278 Name ==
"else" ||
Name ==
"end_try") {
279 if (checkEnd(ErrorLoc,
Name ==
"else"))
281 if (
Name ==
"end_block")
283 }
else if (
Name ==
"return") {
286 }
else if (
Name ==
"call_indirect" ||
Name ==
"return_call_indirect") {
289 if (checkSig(ErrorLoc, LastSig))
return true;
292 }
else if (
Name ==
"call" ||
Name ==
"return_call") {
294 if (getSymRef(
Operands[1]->getStartLoc(), Inst, SymRef))
296 auto WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
297 auto Sig = WasmSym->getSignature();
301 " missing .functype");
302 if (checkSig(ErrorLoc, *Sig))
return true;
305 }
else if (
Name ==
"catch") {
307 if (getSymRef(
Operands[1]->getStartLoc(), Inst, SymRef))
309 const auto *WasmSym = cast<MCSymbolWasm>(&SymRef->
getSymbol());
310 const auto *Sig = WasmSym->getSignature();
314 " missing .tagtype");
318 }
else if (
Name ==
"unreachable") {
320 }
else if (
Name ==
"ref.is_null") {
321 if (popRefType(ErrorLoc))
329 assert(RegOpc != -1 &&
"Failed to get register version of MC instruction");
330 const auto &II = MII.
get(RegOpc);
332 for (
unsigned I = II.getNumOperands();
I > II.getNumDefs();
I--) {
333 const auto &Op = II.operands()[
I - 1];
336 if (popType(ErrorLoc, VT))
341 for (
unsigned I = 0;
I < II.getNumDefs();
I++) {
342 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)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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)
WebAssemblyAsmTypeCheck(MCAsmParser &Parser, const MCInstrInfo &MII, bool is64)
bool typeCheck(SMLoc ErrorLoc, const MCInst &Inst, OperandVector &Operands)
void localDecl(const SmallVector< wasm::ValType, 4 > &Locals)
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