diff --git a/clang/test/CodeGen/exceptions-strictfp.c b/clang/test/CodeGen/exceptions-strictfp.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/exceptions-strictfp.c @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -triple armv7-apple-unknown -ffp-exception-behavior=strict -fexperimental-strict-floating-point -emit-llvm -o - %s -fexceptions -fsjlj-exceptions -fblocks | FileCheck %s + +// Verify strictfp attributes on invoke calls (and therefore also on +// function definitions). + +// rdar://problem/8621849 +void test1() { + extern void test1_helper(void (^)(int)); + + // CHECK: define arm_aapcscc void @test1() [[STRICTFP0:#[0-9]+]] personality i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*) + + __block int x = 10; + + // CHECK: invoke arm_aapcscc void @test1_helper({{.*}}) [[STRICTFP1:#[0-9]+]] + test1_helper(^(int v) { x = v; }); + + // CHECK: landingpad { i8*, i32 } + // CHECK-NEXT: cleanup +} + +void test2_helper(); +void test2() { + // CHECK: define arm_aapcscc void @test2() [[STRICTFP0]] personality i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*) { + __block int x = 10; + ^{ (void)x; }; + + // CHECK: invoke arm_aapcscc void @test2_helper({{.*}}) [[STRICTFP1:#[0-9]+]] + test2_helper(5, 6, 7); + + // CHECK: landingpad { i8*, i32 } + // CHECK-NEXT: cleanup +} +void test2_helper(int x, int y) { +} + +// CHECK: attributes [[STRICTFP0]] = { {{.*}}strictfp{{.*}} } +// CHECK: attributes [[STRICTFP1]] = { strictfp } diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -301,7 +301,7 @@ } } - void setConstrainedFPCallAttr(CallInst *I) { + void setConstrainedFPCallAttr(CallBase *I) { I->addAttribute(AttributeList::FunctionIndex, Attribute::StrictFP); } @@ -1023,16 +1023,21 @@ ArrayRef Args, ArrayRef OpBundles, const Twine &Name = "") { - return Insert( - InvokeInst::Create(Ty, Callee, NormalDest, UnwindDest, Args, OpBundles), - Name); + InvokeInst *II = + InvokeInst::Create(Ty, Callee, NormalDest, UnwindDest, Args, OpBundles); + if (IsFPConstrained) + setConstrainedFPCallAttr(II); + return Insert(II, Name); } InvokeInst *CreateInvoke(FunctionType *Ty, Value *Callee, BasicBlock *NormalDest, BasicBlock *UnwindDest, ArrayRef Args = None, const Twine &Name = "") { - return Insert(InvokeInst::Create(Ty, Callee, NormalDest, UnwindDest, Args), - Name); + InvokeInst *II = + InvokeInst::Create(Ty, Callee, NormalDest, UnwindDest, Args); + if (IsFPConstrained) + setConstrainedFPCallAttr(II); + return Insert(II, Name); } InvokeInst *CreateInvoke(FunctionCallee Callee, BasicBlock *NormalDest,