[llvm] 786da40 - [WebAssembly] Don't copy noreturn attr to invokes
Heejin Ahn via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 27 21:05:11 PST 2022
Author: Heejin Ahn
Date: 2022-01-27T21:04:43-08:00
New Revision: 786da40667dc311b07a666abe3f5ca29d871de40
URL: https://github.com/llvm/llvm-project/commit/786da40667dc311b07a666abe3f5ca29d871de40
DIFF: https://github.com/llvm/llvm-project/commit/786da40667dc311b07a666abe3f5ca29d871de40.diff
LOG: [WebAssembly] Don't copy noreturn attr to invokes
When we create an invoke wrapper call, if the original call instruction
has a `noreturn` attribute, we shouldn't copy it, because we expect
invoke wrapper calls to return. This generated incorrect `free` call
before an invoke wrapper call that calls `__cxa_throw`, because
`__cxa_throw` has `noreturn` attribute.
Reviewed By: dschuff
Differential Revision: https://reviews.llvm.org/D118274
Added:
Modified:
llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
index 85fe6ea40a66..dc52c69fb566 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
@@ -560,6 +560,9 @@ Value *WebAssemblyLowerEmscriptenEHSjLj::wrapInvoke(CallBase *CI) {
NEltArg = NEltArg.getValue() + 1;
FnAttrs.addAllocSizeAttr(SizeArg, NEltArg);
}
+ // In case the callee has 'noreturn' attribute, We need to remove it, because
+ // we expect invoke wrappers to return.
+ FnAttrs.removeAttribute(Attribute::NoReturn);
// Reconstruct the AttributesList based on the vector we constructed.
AttributeList NewCallAL = AttributeList::get(
diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll
index 9d03ee6d71a7..e529468ad6fa 100644
--- a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll
+++ b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll
@@ -7,6 +7,7 @@ target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-unknown"
%struct.__jmp_buf_tag = type { [6 x i32], i32, [32 x i32] }
+ at _ZTIi = external constant i8*
; There is a function call (@foo) that can either throw an exception or longjmp
; and there is also a setjmp call. When @foo throws, we have to check both for
@@ -220,6 +221,54 @@ return: ; preds = %entry, %if.end
; CHECK-NEXT: unreachable
}
+; int jmpval = setjmp(buf);
+; if (jmpval != 0)
+; return;
+; try {
+; throw 3;
+; } catch (...) {
+; }
+define void @setjmp_with_throw_try_catch() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+; CHECK-LABEL: @setjmp_with_throw_try_catch
+entry:
+ %buf = alloca [1 x %struct.__jmp_buf_tag], align 16
+ %arraydecay = getelementptr inbounds [1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* %buf, i32 0, i32 0
+ %call = call i32 @setjmp(%struct.__jmp_buf_tag* %arraydecay) #0
+ %cmp = icmp ne i32 %call, 0
+ br i1 %cmp, label %try.cont, label %if.end
+
+if.end: ; preds = %entry
+ %exception = call i8* @__cxa_allocate_exception(i32 4) #2
+ %0 = bitcast i8* %exception to i32*
+ store i32 3, i32* %0, align 16
+ invoke void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #1
+ to label %unreachable unwind label %lpad
+; When invoke @__cxa_throw is converted to a call to the invoke wrapper,
+; "noreturn" attribute should be removed, and there should be no 'free' call
+; before the call. We insert a 'free' call that frees 'setjmpTable' before every
+; function-exiting instruction. And invoke wrapper calls shouldn't be treated as
+; noreturn instructions, because they are supposed to return.
+; CHECK: if.end:
+; CHECK-NOT: tail call void @free
+; CHECK-NOT: call cc99 void @"__invoke_void_i8*_i8*_i8*"(void (i8*, i8*, i8*)* @__cxa_throw, i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #
+; CHECK: call cc99 void @"__invoke_void_i8*_i8*_i8*"(void (i8*, i8*, i8*)* @__cxa_throw, i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null)
+
+lpad: ; preds = %if.end
+ %1 = landingpad { i8*, i32 }
+ catch i8* null
+ %2 = extractvalue { i8*, i32 } %1, 0
+ %3 = extractvalue { i8*, i32 } %1, 1
+ %4 = call i8* @__cxa_begin_catch(i8* %2) #2
+ call void @__cxa_end_catch()
+ br label %try.cont
+
+try.cont: ; preds = %entry, %lpad
+ ret void
+
+unreachable: ; preds = %if.end
+ unreachable
+}
+
declare void @foo()
; Function Attrs: returns_twice
declare i32 @setjmp(%struct.__jmp_buf_tag*)
@@ -229,6 +278,8 @@ declare i32 @__gxx_personality_v0(...)
declare i8* @__cxa_begin_catch(i8*)
declare void @__cxa_end_catch()
declare void @__cxa_throw(i8*, i8*, i8*)
+declare i8* @__cxa_allocate_exception(i32)
attributes #0 = { returns_twice }
attributes #1 = { noreturn }
+attributes #2 = { nounwind }
More information about the llvm-commits
mailing list