[llvm] c55b6c5 - [WebAssembly] Handle _setjmp and _longjmp in SjLj
Heejin Ahn via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 13 14:46:04 PDT 2021
Author: Heejin Ahn
Date: 2021-09-13T14:20:04-07:00
New Revision: c55b6c593b32c45947bd44fc5c38b4b5e01f4d66
URL: https://github.com/llvm/llvm-project/commit/c55b6c593b32c45947bd44fc5c38b4b5e01f4d66
DIFF: https://github.com/llvm/llvm-project/commit/c55b6c593b32c45947bd44fc5c38b4b5e01f4d66.diff
LOG: [WebAssembly] Handle _setjmp and _longjmp in SjLj
In some platforms `_setjmp` and `_longjmp` are used instead of `setjmp`
and `longjmp`. This CL adds support for them.
Fixes https://github.com/emscripten-core/emscripten/issues/14999.
Reviewed By: dschuff
Differential Revision: https://reviews.llvm.org/D109669
Added:
Modified:
llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
index dd8909bc416bf..33a9c608a9a6b 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
@@ -831,6 +831,33 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) {
Function *SetjmpF = M.getFunction("setjmp");
Function *LongjmpF = M.getFunction("longjmp");
+ // In some platforms _setjmp and _longjmp are used instead. Change these to
+ // use setjmp/longjmp instead, because we laster detect these functions by
+ // their names.
+ Function *SetjmpF2 = M.getFunction("_setjmp");
+ Function *LongjmpF2 = M.getFunction("_longjmp");
+ if (SetjmpF2) {
+ if (SetjmpF) {
+ if (SetjmpF->getFunctionType() != SetjmpF2->getFunctionType())
+ report_fatal_error("setjmp and _setjmp have
diff erent function types");
+ } else {
+ SetjmpF = Function::Create(SetjmpF2->getFunctionType(),
+ GlobalValue::ExternalLinkage, "setjmp", M);
+ }
+ SetjmpF2->replaceAllUsesWith(SetjmpF);
+ }
+ if (LongjmpF2) {
+ if (LongjmpF) {
+ if (LongjmpF->getFunctionType() != LongjmpF2->getFunctionType())
+ report_fatal_error(
+ "longjmp and _longjmp have
diff erent function types");
+ } else {
+ LongjmpF = Function::Create(LongjmpF2->getFunctionType(),
+ GlobalValue::ExternalLinkage, "setjmp", M);
+ }
+ LongjmpF2->replaceAllUsesWith(LongjmpF);
+ }
+
auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
assert(TPC && "Expected a TargetPassConfig");
auto &TM = TPC->getTM<WebAssemblyTargetMachine>();
diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll
index 1186b58373f2b..fcfd503234065 100644
--- a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll
+++ b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll
@@ -282,12 +282,30 @@ entry:
ret void
}
+; Test if _setjmp and _longjmp calls are treated in the same way as setjmp and
+; longjmp
+define void @_setjmp__longjmp() {
+; CHECK-LABEL: @_setjmp__longjmp
+; These calls should have been transformed away
+; CHECK-NOT: call i32 @_setjmp
+; CHECK-NOT: call void @_longjmp
+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
+ %arraydecay1 = getelementptr inbounds [1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* %buf, i32 0, i32 0
+ call void @_longjmp(%struct.__jmp_buf_tag* %arraydecay1, i32 1) #1
+ unreachable
+}
+
; Function Attrs: nounwind
declare void @foo() #2
; Function Attrs: returns_twice
declare i32 @setjmp(%struct.__jmp_buf_tag*) #0
+declare i32 @_setjmp(%struct.__jmp_buf_tag*) #0
; Function Attrs: noreturn
declare void @longjmp(%struct.__jmp_buf_tag*, i32) #1
+declare void @_longjmp(%struct.__jmp_buf_tag*, i32) #1
declare i32 @__gxx_personality_v0(...)
declare i8* @__cxa_begin_catch(i8*)
declare void @__cxa_end_catch()
More information about the llvm-commits
mailing list