Lower LLVM's 'unreachable' terminator to ISD::TRAP, and lower ISD::TRAP to
wasm's 'unreachable' expression.
WebAssembly type-checks expressions, but a noreturn function with a
return type that doesn't match the context will cause a check
failure. So we lower LLVM 'unreachable' to ISD::TRAP and then lower that
to WebAssembly's 'unreachable' expression, which typechecks in any
context and causes a trap if executed.
Differential Revision: http://reviews.llvm.org/D14515
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252566
91177308-0d34-0410-b5e6-
96231b3b80d8
for (auto T : MVT::integer_valuetypes())
for (auto Ext : {ISD::EXTLOAD, ISD::ZEXTLOAD, ISD::SEXTLOAD})
setLoadExtAction(Ext, T, MVT::i1, Promote);
+
+ // Trap lowers to wasm unreachable
+ setOperationAction(ISD::TRAP, MVT::Other, Legal);
}
FastISel *WebAssemblyTargetLowering::createFastISel(
def RETURN_#vt : I<(outs), (ins vt:$val), [(WebAssemblyreturn vt:$val)],
"return $val">;
}
-let isReturn = 1, isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in {
+
+let isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in {
+let isReturn = 1 in {
defm : RETURN<I32>;
defm : RETURN<I64>;
defm : RETURN<F32>;
defm : RETURN<F64>;
def RETURN_VOID : I<(outs), (ins), [(WebAssemblyreturn)], "return">;
-} // isReturn = 1, isTerminator = 1, hasCtrlDep = 1, isBarrier = 1
+} // isReturn = 1
+ def UNREACHABLE : I<(outs), (ins), [(trap)], "unreachable">;
+} // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1
: "e-p:32:32-i64:64-n32:64-S128",
TT, CPU, FS, Options, RM, CM, OL),
TLOF(make_unique<WebAssemblyTargetObjectFile>()) {
+ // WebAssembly type-checks expressions, but a noreturn function with a return
+ // type that doesn't match the context will cause a check failure. So we lower
+ // LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's
+ // 'unreachable' expression which is meant for that case.
+ this->Options.TrapUnreachable = true;
+
initAsmInfo();
// We need a reducible CFG, so disable some optimizations which tend to
--- /dev/null
+; RUN: llc < %s -asm-verbose=false | FileCheck %s
+; RUN: llc < %s -asm-verbose=false -fast-isel | FileCheck %s
+
+; Test that LLVM unreachable instruction and trap intrinsic are lowered to
+; wasm unreachable
+
+target datalayout = "e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown"
+
+declare void @llvm.trap()
+declare void @llvm.debugtrap()
+declare void @abort()
+
+; CHECK-LABEL: f1:
+; CHECK: call $abort
+; CHECK: unreachable
+define i32 @f1() {
+ call void @abort()
+ unreachable
+}
+
+; CHECK-LABEL: f2:
+; CHECK: unreachable
+define void @f2() {
+ call void @llvm.trap()
+ ret void
+}
+
+; CHECK-LABEL: f3:
+; CHECK: unreachable
+define void @f3() {
+ call void @llvm.debugtrap()
+ ret void
+}