From: Wouter van Oortmerssen Date: Thu, 3 Jan 2019 22:59:59 +0000 (+0000) Subject: [WebAssembly] Made InstPrinter more robust X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f3361c432e1b3055f01c4bb5c7d55104a541e956;p=llvm [WebAssembly] Made InstPrinter more robust Summary: Instead of asserting on certain kinds of malformed instructions, it now still print, but instead adds an annotation indicating the problem, and/or indicates invalid_type etc. We're using the InstPrinter from many contexts that can't always guarantee values are within range (e.g. the disassembler), where having output is more valueable than asserting. Reviewers: dschuff, aheejin Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits Differential Revision: https://reviews.llvm.org/D56223 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@350365 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp b/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp index a2882673060..2a357238deb 100644 --- a/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp +++ b/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp @@ -95,23 +95,32 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, case WebAssembly::END_LOOP: case WebAssembly::END_LOOP_S: - assert(!ControlFlowStack.empty() && "End marker mismatch!"); - ControlFlowStack.pop_back(); + if (ControlFlowStack.empty()) { + printAnnotation(OS, "End marker mismatch!"); + } else { + ControlFlowStack.pop_back(); + } break; case WebAssembly::END_BLOCK: case WebAssembly::END_BLOCK_S: - assert(!ControlFlowStack.empty() && "End marker mismatch!"); - printAnnotation( - OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':'); + if (ControlFlowStack.empty()) { + printAnnotation(OS, "End marker mismatch!"); + } else { + printAnnotation( + OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':'); + } break; case WebAssembly::END_TRY: case WebAssembly::END_TRY_S: - assert(!ControlFlowStack.empty() && "End marker mismatch!"); - printAnnotation( - OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':'); - LastSeenEHInst = END_TRY; + if (ControlFlowStack.empty()) { + printAnnotation(OS, "End marker mismatch!"); + } else { + printAnnotation( + OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':'); + LastSeenEHInst = END_TRY; + } break; case WebAssembly::CATCH_I32: @@ -123,8 +132,12 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, // There can be multiple catch instructions for one try instruction, so we // print a label only for the first 'catch' label. if (LastSeenEHInst != CATCH) { - assert(!EHPadStack.empty() && "try-catch mismatch!"); - printAnnotation(OS, "catch" + utostr(EHPadStack.pop_back_val()) + ':'); + if (EHPadStack.empty()) { + printAnnotation(OS, "try-catch mismatch!"); + } else { + printAnnotation(OS, + "catch" + utostr(EHPadStack.pop_back_val()) + ':'); + } } LastSeenEHInst = CATCH; break; @@ -152,8 +165,9 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, continue; if (Opc == WebAssembly::RETHROW || Opc == WebAssembly::RETHROW_S) { - assert(Depth <= EHPadStack.size() && "Invalid depth argument!"); - if (Depth == EHPadStack.size()) { + if (Depth > EHPadStack.size()) { + printAnnotation(OS, "Invalid depth argument!"); + } else if (Depth == EHPadStack.size()) { // This can happen when rethrow instruction breaks out of all nests // and throws up to the current function's caller. printAnnotation(OS, utostr(Depth) + ": " + "to caller"); @@ -164,11 +178,14 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, } } else { - assert(Depth < ControlFlowStack.size() && "Invalid depth argument!"); - const auto &Pair = ControlFlowStack.rbegin()[Depth]; - printAnnotation(OS, utostr(Depth) + ": " + - (Pair.second ? "up" : "down") + " to label" + - utostr(Pair.first)); + if (Depth >= ControlFlowStack.size()) { + printAnnotation(OS, "Invalid depth argument!"); + } else { + const auto &Pair = ControlFlowStack.rbegin()[Depth]; + printAnnotation(OS, utostr(Depth) + ": " + + (Pair.second ? "up" : "down") + " to label" + + utostr(Pair.first)); + } } } } @@ -256,47 +273,38 @@ void WebAssemblyInstPrinter::printWebAssemblyP2AlignOperand(const MCInst *MI, void WebAssemblyInstPrinter::printWebAssemblySignatureOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { - int64_t Imm = MI->getOperand(OpNo).getImm(); - switch (WebAssembly::ExprType(Imm)) { - case WebAssembly::ExprType::Void: - break; - case WebAssembly::ExprType::I32: - O << "i32"; - break; - case WebAssembly::ExprType::I64: - O << "i64"; - break; - case WebAssembly::ExprType::F32: - O << "f32"; - break; - case WebAssembly::ExprType::F64: - O << "f64"; - break; - case WebAssembly::ExprType::V128: - O << "v128"; - break; - case WebAssembly::ExprType::ExceptRef: - O << "except_ref"; - break; - default: - llvm_unreachable("invalid WebAssembly::ExprType"); - } + auto Imm = static_cast(MI->getOperand(OpNo).getImm()); + if (Imm != wasm::WASM_TYPE_NORESULT) + O << WebAssembly::anyTypeToString(Imm); } -const char *llvm::WebAssembly::TypeToString(wasm::ValType Ty) { +// We have various enums representing a subset of these types, use this +// function to convert any of them to text. +const char *llvm::WebAssembly::anyTypeToString(unsigned Ty) { switch (Ty) { - case wasm::ValType::I32: + case wasm::WASM_TYPE_I32: return "i32"; - case wasm::ValType::I64: + case wasm::WASM_TYPE_I64: return "i64"; - case wasm::ValType::F32: + case wasm::WASM_TYPE_F32: return "f32"; - case wasm::ValType::F64: + case wasm::WASM_TYPE_F64: return "f64"; - case wasm::ValType::V128: + case wasm::WASM_TYPE_V128: return "v128"; - case wasm::ValType::EXCEPT_REF: + case wasm::WASM_TYPE_ANYFUNC: + return "anyfunc"; + case wasm::WASM_TYPE_FUNC: + return "func"; + case wasm::WASM_TYPE_EXCEPT_REF: return "except_ref"; + case wasm::WASM_TYPE_NORESULT: + return "void"; + default: + return "invalid_type"; } - llvm_unreachable("Unknown wasm::ValType"); +} + +const char *llvm::WebAssembly::typeToString(wasm::ValType Ty) { + return anyTypeToString(static_cast(Ty)); } diff --git a/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h b/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h index fd968bc9ea3..5ad45c7d5c7 100644 --- a/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h +++ b/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h @@ -56,7 +56,8 @@ public: namespace WebAssembly { -const char *TypeToString(wasm::ValType Ty); +const char *typeToString(wasm::ValType Ty); +const char *anyTypeToString(unsigned Ty); } // end namespace WebAssembly diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp index 70ac5027254..50143fb0ece 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp @@ -47,7 +47,7 @@ static void printTypes(formatted_raw_ostream &OS, First = false; else OS << ", "; - OS << WebAssembly::TypeToString(Type); + OS << WebAssembly::typeToString(Type); } OS << '\n'; } @@ -76,7 +76,7 @@ void WebAssemblyTargetAsmStreamer::emitParamList( for (auto &Ty : Params) { if (&Ty != &Params[0]) OS << ", "; - OS << WebAssembly::TypeToString(Ty); + OS << WebAssembly::typeToString(Ty); } } @@ -86,7 +86,7 @@ void WebAssemblyTargetAsmStreamer::emitReturnList( for (auto &Ty : Returns) { if (&Ty != &Returns[0]) OS << ", "; - OS << WebAssembly::TypeToString(Ty); + OS << WebAssembly::typeToString(Ty); } } @@ -99,10 +99,10 @@ void WebAssemblyTargetAsmStreamer::emitFunctionType(const MCSymbolWasm *Sym) { void WebAssemblyTargetAsmStreamer::emitGlobalType(const MCSymbolWasm *Sym) { assert(Sym->isGlobal()); - OS << "\t.globaltype\t" << Sym->getName() << ", " << - WebAssembly::TypeToString( - static_cast(Sym->getGlobalType().Type)) << - '\n'; + OS << "\t.globaltype\t" << Sym->getName() << ", " + << WebAssembly::typeToString( + static_cast(Sym->getGlobalType().Type)) + << '\n'; } void WebAssemblyTargetAsmStreamer::emitEventType(const MCSymbolWasm *Sym) { diff --git a/test/MC/Disassembler/WebAssembly/wasm-error.txt b/test/MC/Disassembler/WebAssembly/wasm-error.txt new file mode 100644 index 00000000000..6468a4f0c18 --- /dev/null +++ b/test/MC/Disassembler/WebAssembly/wasm-error.txt @@ -0,0 +1,9 @@ +# RUN: llvm-mc --disassemble %s -triple=wasm32-unknown-unknown | FileCheck %s + +# CHECK: .text + +# CHECK: block invalid_type +0x02 0x00 + +# CHECK: br 16 # Invalid depth argument! +0x0C 0x10