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:")
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));
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);
return llvm::ConstantInt::get(CGM.Int32Ty, Sig);
}
+ bool hasSjLjLowering(CodeGen::CodeGenFunction &CGF) const override {
+ return true;
+ }
};
}
unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
return HasAVX ? 32 : 16;
}
+
+ bool hasSjLjLowering(CodeGen::CodeGenFunction &CGF) const override {
+ return true;
+ }
};
class PS4TargetCodeGenInfo : public X86_64TargetCodeGenInfo {
unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
return 16; // Natural alignment for Altivec vectors.
}
+
+ bool hasSjLjLowering(CodeGen::CodeGenFunction &CGF) const override {
+ return true;
+ }
};
}
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 {
unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
return 16; // Natural alignment for Altivec vectors.
}
+
+ bool hasSjLjLowering(CodeGen::CodeGenFunction &CGF) const override {
+ return true;
+ }
};
}
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 {
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;
+ }
};
}
+++ /dev/null
-/* 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);
-}
--- /dev/null
+// 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();
+}