diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-11-19 20:06:13 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-11-19 20:06:13 +0000 |
| commit | c0981da47d5696fe36474fcf86b4ce03ae3ff818 (patch) | |
| tree | f42add1021b9f2ac6a69ac7cf6c4499962739a45 /llvm/lib/Target/WebAssembly/AsmParser | |
| parent | 344a3780b2e33f6ca763666c380202b18aab72a3 (diff) | |
Diffstat (limited to 'llvm/lib/Target/WebAssembly/AsmParser')
3 files changed, 59 insertions, 25 deletions
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp index eb1dd879941a..7d1e6c553f81 100644 --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -31,9 +31,9 @@ #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolWasm.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Support/Endian.h" #include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetRegistry.h" using namespace llvm; @@ -431,10 +431,10 @@ public: bool checkForP2AlignIfLoadStore(OperandVector &Operands, StringRef InstName) { // FIXME: there is probably a cleaner way to do this. - auto IsLoadStore = InstName.find(".load") != StringRef::npos || - InstName.find(".store") != StringRef::npos || - InstName.find("prefetch") != StringRef::npos; - auto IsAtomic = InstName.find("atomic.") != StringRef::npos; + auto IsLoadStore = InstName.contains(".load") || + InstName.contains(".store") || + InstName.contains("prefetch"); + auto IsAtomic = InstName.contains("atomic."); if (IsLoadStore || IsAtomic) { // Parse load/store operands of the form: offset:p2align=align if (IsLoadStore && isNext(AsmToken::Colon)) { @@ -450,7 +450,7 @@ public: // v128.{load,store}{8,16,32,64}_lane has both a memarg and a lane // index. We need to avoid parsing an extra alignment operand for the // lane index. - auto IsLoadStoreLane = InstName.find("_lane") != StringRef::npos; + auto IsLoadStoreLane = InstName.contains("_lane"); if (IsLoadStoreLane && Operands.size() == 4) return false; // Alignment not specified (or atomics, must use default alignment). @@ -1114,6 +1114,8 @@ public: void onEndOfFunction(SMLoc ErrorLoc) { TC.endOfFunction(ErrorLoc); + // Reset the type checker state. + TC.Clear(); // Automatically output a .size directive, so it becomes optional for the // user. diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp index 2f9245a7c66c..a6b5d4252f2f 100644 --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp @@ -31,10 +31,10 @@ #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolWasm.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Endian.h" #include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetRegistry.h" using namespace llvm; @@ -74,6 +74,9 @@ bool WebAssemblyAsmTypeCheck::typeError(SMLoc ErrorLoc, const Twine &Msg) { // which are mostly not helpful. if (TypeErrorThisFunction) return true; + // If we're currently in unreachable code, we surpress errors as well. + if (Unreachable) + return true; TypeErrorThisFunction = true; dumpTypeStack("current stack: "); return Parser.Error(ErrorLoc, Msg); @@ -89,8 +92,7 @@ bool WebAssemblyAsmTypeCheck::popType(SMLoc ErrorLoc, : StringRef( "empty stack while popping value")); } - auto PVT = Stack.back(); - Stack.pop_back(); + auto PVT = Stack.pop_back_val(); if (EVT.hasValue() && EVT.getValue() != PVT) { return typeError( ErrorLoc, StringRef("popped ") + WebAssembly::typeToString(PVT) + @@ -155,8 +157,12 @@ bool WebAssemblyAsmTypeCheck::getGlobal(SMLoc ErrorLoc, const MCInst &Inst, break; case wasm::WASM_SYMBOL_TYPE_FUNCTION: case wasm::WASM_SYMBOL_TYPE_DATA: - if (SymRef->getKind() == MCSymbolRefExpr::VK_GOT) { + switch (SymRef->getKind()) { + case MCSymbolRefExpr::VK_GOT: + case MCSymbolRefExpr::VK_WASM_GOT_TLS: Type = is64 ? wasm::ValType::I64 : wasm::ValType::I32; + return false; + default: break; } LLVM_FALLTHROUGH; @@ -167,17 +173,18 @@ bool WebAssemblyAsmTypeCheck::getGlobal(SMLoc ErrorLoc, const MCInst &Inst, return false; } -void WebAssemblyAsmTypeCheck::endOfFunction(SMLoc ErrorLoc) { +bool WebAssemblyAsmTypeCheck::endOfFunction(SMLoc ErrorLoc) { // Check the return types. for (auto RVT : llvm::reverse(ReturnTypes)) { - popType(ErrorLoc, RVT); + if (popType(ErrorLoc, RVT)) + return true; } if (!Stack.empty()) { - typeError(ErrorLoc, - std::to_string(Stack.size()) + " superfluous return values"); + return typeError(ErrorLoc, std::to_string(Stack.size()) + + " superfluous return values"); } - // Reset the type checker state. - Clear(); + Unreachable = true; + return false; } bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst) { @@ -213,13 +220,20 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst) { if (popType(ErrorLoc, {})) return true; } else if (Name == "end_block" || Name == "end_loop" || Name == "end_if" || - Name == "else") { + Name == "else" || Name == "end_try") { if (checkEnd(ErrorLoc)) return true; + if (Name == "end_block") + Unreachable = false; + } else if (Name == "return") { + if (endOfFunction(ErrorLoc)) + return true; } else if (Name == "call_indirect" || Name == "return_call_indirect") { // Function value. if (popType(ErrorLoc, wasm::ValType::I32)) return true; if (checkSig(ErrorLoc, LastSig)) return true; + if (Name == "return_call_indirect" && endOfFunction(ErrorLoc)) + return true; } else if (Name == "call" || Name == "return_call") { const MCSymbolRefExpr *SymRef; if (getSymRef(ErrorLoc, Inst, SymRef)) @@ -230,9 +244,25 @@ bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst) { return typeError(ErrorLoc, StringRef("symbol ") + WasmSym->getName() + " missing .functype"); if (checkSig(ErrorLoc, *Sig)) return true; + if (Name == "return_call" && endOfFunction(ErrorLoc)) + return true; + } else if (Name == "catch") { + const MCSymbolRefExpr *SymRef; + if (getSymRef(ErrorLoc, Inst, SymRef)) + return true; + const auto *WasmSym = cast<MCSymbolWasm>(&SymRef->getSymbol()); + const auto *Sig = WasmSym->getSignature(); + if (!Sig || WasmSym->getType() != wasm::WASM_SYMBOL_TYPE_TAG) + return typeError(ErrorLoc, StringRef("symbol ") + WasmSym->getName() + + " missing .tagtype"); + // catch instruction pushes values whose types are specified in the tag's + // "params" part + Stack.insert(Stack.end(), Sig->Params.begin(), Sig->Params.end()); } else if (Name == "ref.null") { auto VT = static_cast<wasm::ValType>(Inst.getOperand(0).getImm()); Stack.push_back(VT); + } else if (Name == "unreachable") { + Unreachable = true; } else { // The current instruction is a stack instruction which doesn't have // explicit operands that indicate push/pop types, so we get those from diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h index a15a69b50418..aa35213ccca3 100644 --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h @@ -32,15 +32,9 @@ class WebAssemblyAsmTypeCheck final { SmallVector<wasm::ValType, 4> ReturnTypes; wasm::WasmSignature LastSig; bool TypeErrorThisFunction = false; + bool Unreachable = false; bool is64; - void Clear() { - Stack.clear(); - LocalTypes.clear(); - ReturnTypes.clear(); - TypeErrorThisFunction = false; - } - void dumpTypeStack(Twine Msg); bool typeError(SMLoc ErrorLoc, const Twine &Msg); bool popType(SMLoc ErrorLoc, Optional<wasm::ValType> EVT); @@ -57,8 +51,16 @@ public: void funcDecl(const wasm::WasmSignature &Sig); void localDecl(const SmallVector<wasm::ValType, 4> &Locals); void setLastSig(const wasm::WasmSignature &Sig) { LastSig = Sig; } - void endOfFunction(SMLoc ErrorLoc); + bool endOfFunction(SMLoc ErrorLoc); bool typeCheck(SMLoc ErrorLoc, const MCInst &Inst); + + void Clear() { + Stack.clear(); + LocalTypes.clear(); + ReturnTypes.clear(); + TypeErrorThisFunction = false; + Unreachable = false; + } }; } // end namespace llvm |
