Skip to content

Commit 9843295

Browse files
committed
[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 llvm-svn: 350365
1 parent b8687c2 commit 9843295

File tree

4 files changed

+77
-59
lines changed

4 files changed

+77
-59
lines changed

llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp

Lines changed: 59 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -95,23 +95,32 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
9595

9696
case WebAssembly::END_LOOP:
9797
case WebAssembly::END_LOOP_S:
98-
assert(!ControlFlowStack.empty() && "End marker mismatch!");
99-
ControlFlowStack.pop_back();
98+
if (ControlFlowStack.empty()) {
99+
printAnnotation(OS, "End marker mismatch!");
100+
} else {
101+
ControlFlowStack.pop_back();
102+
}
100103
break;
101104

102105
case WebAssembly::END_BLOCK:
103106
case WebAssembly::END_BLOCK_S:
104-
assert(!ControlFlowStack.empty() && "End marker mismatch!");
105-
printAnnotation(
106-
OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
107+
if (ControlFlowStack.empty()) {
108+
printAnnotation(OS, "End marker mismatch!");
109+
} else {
110+
printAnnotation(
111+
OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
112+
}
107113
break;
108114

109115
case WebAssembly::END_TRY:
110116
case WebAssembly::END_TRY_S:
111-
assert(!ControlFlowStack.empty() && "End marker mismatch!");
112-
printAnnotation(
113-
OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
114-
LastSeenEHInst = END_TRY;
117+
if (ControlFlowStack.empty()) {
118+
printAnnotation(OS, "End marker mismatch!");
119+
} else {
120+
printAnnotation(
121+
OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
122+
LastSeenEHInst = END_TRY;
123+
}
115124
break;
116125

117126
case WebAssembly::CATCH_I32:
@@ -123,8 +132,12 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
123132
// There can be multiple catch instructions for one try instruction, so we
124133
// print a label only for the first 'catch' label.
125134
if (LastSeenEHInst != CATCH) {
126-
assert(!EHPadStack.empty() && "try-catch mismatch!");
127-
printAnnotation(OS, "catch" + utostr(EHPadStack.pop_back_val()) + ':');
135+
if (EHPadStack.empty()) {
136+
printAnnotation(OS, "try-catch mismatch!");
137+
} else {
138+
printAnnotation(OS,
139+
"catch" + utostr(EHPadStack.pop_back_val()) + ':');
140+
}
128141
}
129142
LastSeenEHInst = CATCH;
130143
break;
@@ -152,8 +165,9 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
152165
continue;
153166

154167
if (Opc == WebAssembly::RETHROW || Opc == WebAssembly::RETHROW_S) {
155-
assert(Depth <= EHPadStack.size() && "Invalid depth argument!");
156-
if (Depth == EHPadStack.size()) {
168+
if (Depth > EHPadStack.size()) {
169+
printAnnotation(OS, "Invalid depth argument!");
170+
} else if (Depth == EHPadStack.size()) {
157171
// This can happen when rethrow instruction breaks out of all nests
158172
// and throws up to the current function's caller.
159173
printAnnotation(OS, utostr(Depth) + ": " + "to caller");
@@ -164,11 +178,14 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
164178
}
165179

166180
} else {
167-
assert(Depth < ControlFlowStack.size() && "Invalid depth argument!");
168-
const auto &Pair = ControlFlowStack.rbegin()[Depth];
169-
printAnnotation(OS, utostr(Depth) + ": " +
170-
(Pair.second ? "up" : "down") + " to label" +
171-
utostr(Pair.first));
181+
if (Depth >= ControlFlowStack.size()) {
182+
printAnnotation(OS, "Invalid depth argument!");
183+
} else {
184+
const auto &Pair = ControlFlowStack.rbegin()[Depth];
185+
printAnnotation(OS, utostr(Depth) + ": " +
186+
(Pair.second ? "up" : "down") + " to label" +
187+
utostr(Pair.first));
188+
}
172189
}
173190
}
174191
}
@@ -256,47 +273,38 @@ void WebAssemblyInstPrinter::printWebAssemblyP2AlignOperand(const MCInst *MI,
256273
void WebAssemblyInstPrinter::printWebAssemblySignatureOperand(const MCInst *MI,
257274
unsigned OpNo,
258275
raw_ostream &O) {
259-
int64_t Imm = MI->getOperand(OpNo).getImm();
260-
switch (WebAssembly::ExprType(Imm)) {
261-
case WebAssembly::ExprType::Void:
262-
break;
263-
case WebAssembly::ExprType::I32:
264-
O << "i32";
265-
break;
266-
case WebAssembly::ExprType::I64:
267-
O << "i64";
268-
break;
269-
case WebAssembly::ExprType::F32:
270-
O << "f32";
271-
break;
272-
case WebAssembly::ExprType::F64:
273-
O << "f64";
274-
break;
275-
case WebAssembly::ExprType::V128:
276-
O << "v128";
277-
break;
278-
case WebAssembly::ExprType::ExceptRef:
279-
O << "except_ref";
280-
break;
281-
default:
282-
llvm_unreachable("invalid WebAssembly::ExprType");
283-
}
276+
auto Imm = static_cast<unsigned>(MI->getOperand(OpNo).getImm());
277+
if (Imm != wasm::WASM_TYPE_NORESULT)
278+
O << WebAssembly::anyTypeToString(Imm);
284279
}
285280

286-
const char *llvm::WebAssembly::TypeToString(wasm::ValType Ty) {
281+
// We have various enums representing a subset of these types, use this
282+
// function to convert any of them to text.
283+
const char *llvm::WebAssembly::anyTypeToString(unsigned Ty) {
287284
switch (Ty) {
288-
case wasm::ValType::I32:
285+
case wasm::WASM_TYPE_I32:
289286
return "i32";
290-
case wasm::ValType::I64:
287+
case wasm::WASM_TYPE_I64:
291288
return "i64";
292-
case wasm::ValType::F32:
289+
case wasm::WASM_TYPE_F32:
293290
return "f32";
294-
case wasm::ValType::F64:
291+
case wasm::WASM_TYPE_F64:
295292
return "f64";
296-
case wasm::ValType::V128:
293+
case wasm::WASM_TYPE_V128:
297294
return "v128";
298-
case wasm::ValType::EXCEPT_REF:
295+
case wasm::WASM_TYPE_ANYFUNC:
296+
return "anyfunc";
297+
case wasm::WASM_TYPE_FUNC:
298+
return "func";
299+
case wasm::WASM_TYPE_EXCEPT_REF:
299300
return "except_ref";
301+
case wasm::WASM_TYPE_NORESULT:
302+
return "void";
303+
default:
304+
return "invalid_type";
300305
}
301-
llvm_unreachable("Unknown wasm::ValType");
306+
}
307+
308+
const char *llvm::WebAssembly::typeToString(wasm::ValType Ty) {
309+
return anyTypeToString(static_cast<unsigned>(Ty));
302310
}

llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ class WebAssemblyInstPrinter final : public MCInstPrinter {
5656

5757
namespace WebAssembly {
5858

59-
const char *TypeToString(wasm::ValType Ty);
59+
const char *typeToString(wasm::ValType Ty);
60+
const char *anyTypeToString(unsigned Ty);
6061

6162
} // end namespace WebAssembly
6263

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ static void printTypes(formatted_raw_ostream &OS,
4747
First = false;
4848
else
4949
OS << ", ";
50-
OS << WebAssembly::TypeToString(Type);
50+
OS << WebAssembly::typeToString(Type);
5151
}
5252
OS << '\n';
5353
}
@@ -76,7 +76,7 @@ void WebAssemblyTargetAsmStreamer::emitParamList(
7676
for (auto &Ty : Params) {
7777
if (&Ty != &Params[0])
7878
OS << ", ";
79-
OS << WebAssembly::TypeToString(Ty);
79+
OS << WebAssembly::typeToString(Ty);
8080
}
8181
}
8282

@@ -86,7 +86,7 @@ void WebAssemblyTargetAsmStreamer::emitReturnList(
8686
for (auto &Ty : Returns) {
8787
if (&Ty != &Returns[0])
8888
OS << ", ";
89-
OS << WebAssembly::TypeToString(Ty);
89+
OS << WebAssembly::typeToString(Ty);
9090
}
9191
}
9292

@@ -99,10 +99,10 @@ void WebAssemblyTargetAsmStreamer::emitFunctionType(const MCSymbolWasm *Sym) {
9999

100100
void WebAssemblyTargetAsmStreamer::emitGlobalType(const MCSymbolWasm *Sym) {
101101
assert(Sym->isGlobal());
102-
OS << "\t.globaltype\t" << Sym->getName() << ", " <<
103-
WebAssembly::TypeToString(
104-
static_cast<wasm::ValType>(Sym->getGlobalType().Type)) <<
105-
'\n';
102+
OS << "\t.globaltype\t" << Sym->getName() << ", "
103+
<< WebAssembly::typeToString(
104+
static_cast<wasm::ValType>(Sym->getGlobalType().Type))
105+
<< '\n';
106106
}
107107

108108
void WebAssemblyTargetAsmStreamer::emitEventType(const MCSymbolWasm *Sym) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# RUN: llvm-mc --disassemble %s -triple=wasm32-unknown-unknown | FileCheck %s
2+
3+
# CHECK: .text
4+
5+
# CHECK: block invalid_type
6+
0x02 0x00
7+
8+
# CHECK: br 16 # Invalid depth argument!
9+
0x0C 0x10

0 commit comments

Comments
 (0)