Only lower __builtin_setjmp / __builtin_longjmp to

llvm.eh.sjlj.setjmp / llvm.eh.sjlj.longjmp, if the backend is known to
support them outside the Exception Handling context. The default
handling in LLVM codegen doesn't work and will create incorrect code.
The ARM backend on the other hand will assert if the intrinsics are
used.

llvm-svn: 230255
This commit is contained in:
Joerg Sonnenberger 2015-02-23 20:23:47 +00:00
parent 0100e6c08c
commit 096feeb741
6 changed files with 74 additions and 17 deletions

View File

@ -448,8 +448,8 @@ BUILTIN(__builtin_extract_return_addr, "v*v*", "n")
BUILTIN(__builtin_frame_address, "v*IUi", "n")
BUILTIN(__builtin___clear_cache, "vc*c*", "n")
BUILTIN(__builtin_flt_rounds, "i", "nc")
BUILTIN(__builtin_setjmp, "iv**", "j")
BUILTIN(__builtin_longjmp, "vv**i", "r")
BUILTIN(__builtin_setjmp, "iv**", "Fj")
BUILTIN(__builtin_longjmp, "vv**i", "Fr")
BUILTIN(__builtin_unwind_init, "v", "")
BUILTIN(__builtin_eh_return_data_regno, "iIi", "nc")
BUILTIN(__builtin_snprintf, "ic*zcC*.", "nFp:2:")

View File

@ -859,6 +859,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Builder.CreateZExt(Result, Int64Ty, "extend.zext"));
}
case Builtin::BI__builtin_setjmp: {
if (!getTargetHooks().hasSjLjLowering(*this))
break;
// Buffer is a void**.
Value *Buf = EmitScalarExpr(E->getArg(0));
@ -881,6 +883,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Builder.CreateCall(F, Buf));
}
case Builtin::BI__builtin_longjmp: {
if (!getTargetHooks().hasSjLjLowering(*this))
break;
Value *Buf = EmitScalarExpr(E->getArg(0));
Buf = Builder.CreateBitCast(Buf, Int8PtrTy);

View File

@ -665,6 +665,9 @@ public:
return llvm::ConstantInt::get(CGM.Int32Ty, Sig);
}
bool hasSjLjLowering(CodeGen::CodeGenFunction &CGF) const override {
return true;
}
};
}
@ -1599,6 +1602,10 @@ public:
unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
return HasAVX ? 32 : 16;
}
bool hasSjLjLowering(CodeGen::CodeGenFunction &CGF) const override {
return true;
}
};
class PS4TargetCodeGenInfo : public X86_64TargetCodeGenInfo {
@ -3116,6 +3123,10 @@ public:
unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
return 16; // Natural alignment for Altivec vectors.
}
bool hasSjLjLowering(CodeGen::CodeGenFunction &CGF) const override {
return true;
}
};
}
@ -3328,6 +3339,10 @@ public:
unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
return 16; // Natural alignment for Altivec and VSX vectors.
}
bool hasSjLjLowering(CodeGen::CodeGenFunction &CGF) const override {
return true;
}
};
class PPC64TargetCodeGenInfo : public DefaultTargetCodeGenInfo {
@ -3345,6 +3360,10 @@ public:
unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
return 16; // Natural alignment for Altivec vectors.
}
bool hasSjLjLowering(CodeGen::CodeGenFunction &CGF) const override {
return true;
}
};
}
@ -4462,6 +4481,12 @@ public:
llvm::AttributeSet::FunctionIndex,
B));
}
bool hasSjLjLowering(CodeGen::CodeGenFunction &CGF) const override {
return false;
// FIXME: backend implementation too restricted, even on Darwin.
// return CGF.getTarget().getTriple().isOSDarwin();
}
};
class WindowsARMTargetCodeGenInfo : public ARMTargetCodeGenInfo {

View File

@ -225,6 +225,13 @@ public:
virtual unsigned getOpenMPSimdDefaultAlignment(QualType Type) const {
return 0;
}
/// Control whether __builtin_longjmp / __builtin_setjmp are lowered to
/// llvm.eh.sjlj.longjmp / llvm.eh.sjlj.setjmp or the normal library
/// function.
virtual bool hasSjLjLowering(CodeGen::CodeGenFunction &CGF) const {
return false;
}
};
}

View File

@ -1,15 +0,0 @@
/* RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
*
* __builtin_longjmp/setjmp should get transformed into intrinsics.
*/
// CHECK-NOT: builtin_longjmp
void jumpaway(int *ptr) {
__builtin_longjmp(ptr,1);
}
int main(void) {
__builtin_setjmp(0);
jumpaway(0);
}

View File

@ -0,0 +1,36 @@
// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm < %s| FileCheck %s -check-prefix=SUPPORTED
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm < %s| FileCheck %s -check-prefix=SUPPORTED
// RUN: %clang_cc1 -triple powerpc-unknown-unknown -emit-llvm < %s| FileCheck %s -check-prefix=SUPPORTED
// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -emit-llvm < %s| FileCheck %s -check-prefix=SUPPORTED
// RUN: %clang_cc1 -triple arm-unknown-unknown -emit-llvm < %s| FileCheck %s -check-prefix=UNSUPPORTED
// RUN: %clang_cc1 -triple aarch64-unknown-unknown -emit-llvm < %s| FileCheck %s -check-prefix=UNSUPPORTED
// RUN: %clang_cc1 -triple mips-unknown-unknown -emit-llvm < %s| FileCheck %s -check-prefix=UNSUPPORTED
// RUN: %clang_cc1 -triple mips64-unknown-unknown -emit-llvm < %s| FileCheck %s -check-prefix=UNSUPPORTED
// Check that __builtin_longjmp and __builtin_setjmp are lowerd into
// IR intrinsics on those architectures that can handle them.
// Check that they are lowered to the libcalls on other architectures.
typedef void *jmp_buf;
jmp_buf buf;
// SUPPORTED: define{{.*}} void @do_jump()
// SUPPORTED: call{{.*}} void @llvm.eh.sjlj.longjmp
// UNSUPPORTED: define{{.*}} void @do_jump()
// UNSUPPORTED: call{{.*}} void @longjmp
// SUPPORTED: define{{.*}} void @do_setjmp()
// SUPPORTED: call{{.*}} i32 @llvm.eh.sjlj.setjmp
// UNSUPPORTED: define{{.*}} void @do_setjmp()
// UNSUPPORTED: call{{.*}} i32 @setjmp
void do_jump(void) {
__builtin_longjmp(buf, 1);
}
void f(void);
void do_setjmp(void) {
if (!__builtin_setjmp(buf))
f();
}