From aec6b2c20e4850f2309042e46dec63e46b383fbd Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Thu, 8 Oct 2015 20:26:34 +0000 Subject: [PATCH] [CodeGen] [CodeGen] Attach function attributes to functions created in CGBlocks.cpp. This commit fixes a bug in clang's code-gen where it creates the following functions but doesn't attach function attributes to them: __copy_helper_block_ __destroy_helper_block_ __Block_byref_object_copy_ __Block_byref_object_dispose_ rdar://problem/20828324 Differential Revision: http://reviews.llvm.org/D13525 llvm-svn: 249735 --- clang/lib/CodeGen/CGBlocks.cpp | 11 ++++++++++ clang/lib/CodeGen/CodeGenModule.cpp | 9 ++++---- clang/lib/CodeGen/TargetInfo.cpp | 16 +++++++-------- clang/test/CodeGenObjC/arc-blocks.m | 32 ++++++++++++++--------------- 4 files changed, 40 insertions(+), 28 deletions(-) diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 7644ab9beeec..cfb09e72c7b4 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -1345,6 +1345,9 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { nullptr, SC_Static, false, false); + + CGM.SetInternalFunctionAttributes(nullptr, Fn, FI); + auto NL = ApplyDebugLocation::CreateEmpty(*this); StartFunction(FD, C.VoidTy, Fn, FI, args); // Create a scope with an artificial location for the body of this function. @@ -1516,6 +1519,9 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { SourceLocation(), II, C.VoidTy, nullptr, SC_Static, false, false); + + CGM.SetInternalFunctionAttributes(nullptr, Fn, FI); + // Create a scope with an artificial location for the body of this function. auto NL = ApplyDebugLocation::CreateEmpty(*this); StartFunction(FD, C.VoidTy, Fn, FI, args); @@ -1798,6 +1804,8 @@ generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo, SC_Static, false, false); + CGF.CGM.SetInternalFunctionAttributes(nullptr, Fn, FI); + CGF.StartFunction(FD, R, Fn, FI, args); if (generator.needsCopy()) { @@ -1869,6 +1877,9 @@ generateByrefDisposeHelper(CodeGenFunction &CGF, SourceLocation(), II, R, nullptr, SC_Static, false, false); + + CGF.CGM.SetInternalFunctionAttributes(nullptr, Fn, FI); + CGF.StartFunction(FD, R, Fn, FI, args); if (generator.needsDispose()) { diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index dd8e76ec50c3..8c5491b5d916 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -867,12 +867,12 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, void CodeGenModule::SetCommonAttributes(const Decl *D, llvm::GlobalValue *GV) { - if (const auto *ND = dyn_cast(D)) + if (const auto *ND = dyn_cast_or_null(D)) setGlobalVisibility(GV, ND); else GV->setVisibility(llvm::GlobalValue::DefaultVisibility); - if (D->hasAttr()) + if (D && D->hasAttr()) addUsedGlobal(GV); } @@ -890,8 +890,9 @@ void CodeGenModule::setNonAliasAttributes(const Decl *D, llvm::GlobalObject *GO) { SetCommonAttributes(D, GO); - if (const SectionAttr *SA = D->getAttr()) - GO->setSection(SA->getName()); + if (D) + if (const SectionAttr *SA = D->getAttr()) + GO->setSection(SA->getName()); getTargetCodeGenInfo().setTargetAttributes(D, GO, *this); } diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 07c706b49a9d..8a42a015602a 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -1528,7 +1528,7 @@ bool X86_32TargetCodeGenInfo::isStructReturnInRegABI( void X86_32TargetCodeGenInfo::setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const { - if (const FunctionDecl *FD = dyn_cast(D)) { + if (const FunctionDecl *FD = dyn_cast_or_null(D)) { if (FD->hasAttr()) { // Get the LLVM function. llvm::Function *Fn = cast(GV); @@ -1898,7 +1898,7 @@ public: static void addStackProbeSizeTargetAttribute(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) { - if (isa(D)) { + if (D && isa(D)) { if (CGM.getCodeGenOpts().StackProbeSize != 4096) { llvm::Function *Fn = cast(GV); @@ -4745,7 +4745,7 @@ public: void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const override { - const FunctionDecl *FD = dyn_cast(D); + const FunctionDecl *FD = dyn_cast_or_null(D); if (!FD) return; @@ -5303,7 +5303,7 @@ Address NVPTXABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, void NVPTXTargetCodeGenInfo:: setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const{ - const FunctionDecl *FD = dyn_cast(D); + const FunctionDecl *FD = dyn_cast_or_null(D); if (!FD) return; llvm::Function *F = cast(GV); @@ -5737,7 +5737,7 @@ public: void MSP430TargetCodeGenInfo::setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const { - if (const FunctionDecl *FD = dyn_cast(D)) { + if (const FunctionDecl *FD = dyn_cast_or_null(D)) { if (const MSP430InterruptAttr *attr = FD->getAttr()) { // Handle 'interrupt' attribute: llvm::Function *F = cast(GV); @@ -5796,7 +5796,7 @@ public: void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const override { - const FunctionDecl *FD = dyn_cast(D); + const FunctionDecl *FD = dyn_cast_or_null(D); if (!FD) return; llvm::Function *Fn = cast(GV); if (FD->hasAttr()) { @@ -6143,7 +6143,7 @@ public: void TCETargetCodeGenInfo::setTargetAttributes( const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const { - const FunctionDecl *FD = dyn_cast(D); + const FunctionDecl *FD = dyn_cast_or_null(D); if (!FD) return; llvm::Function *F = cast(GV); @@ -6325,7 +6325,7 @@ void AMDGPUTargetCodeGenInfo::setTargetAttributes( const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const { - const FunctionDecl *FD = dyn_cast(D); + const FunctionDecl *FD = dyn_cast_or_null(D); if (!FD) return; diff --git a/clang/test/CodeGenObjC/arc-blocks.m b/clang/test/CodeGenObjC/arc-blocks.m index ba76c1cbc950..e7bf01dbb0ea 100644 --- a/clang/test/CodeGenObjC/arc-blocks.m +++ b/clang/test/CodeGenObjC/arc-blocks.m @@ -43,7 +43,7 @@ void test2(id x) { extern void test2_helper(id (^)(void)); test2_helper(^{ return x; }); -// CHECK-LABEL: define internal void @__copy_helper_block_ +// CHECK-LABEL: define internal void @__copy_helper_block_(i8*, i8*) #{{[0-9]+}} { // CHECK: [[T0:%.*]] = load i8*, i8** // CHECK-NEXT: [[SRC:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]* // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** @@ -53,7 +53,7 @@ void test2(id x) { // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) [[NUW]] // CHECK-NEXT: ret void -// CHECK-LABEL: define internal void @__destroy_helper_block_ +// CHECK-LABEL: define internal void @__destroy_helper_block_(i8*) #{{[0-9]+}} { // CHECK: [[T0:%.*]] = load i8*, i8** // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]* // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[T1]], i32 0, i32 5 @@ -134,7 +134,7 @@ void test4(void) { // CHECK-NEXT: call void @objc_release(i8* [[T0]]) // CHECK: ret void - // CHECK-LABEL: define internal void @__Block_byref_object_copy_ + // CHECK-LABEL: define internal void @__Block_byref_object_copy_(i8*, i8*) #{{[0-9]+}} { // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* {{%.*}}, i32 0, i32 6 // CHECK-NEXT: load i8*, i8** // CHECK-NEXT: bitcast i8* {{%.*}} to [[BYREF_T]]* @@ -143,7 +143,7 @@ void test4(void) { // CHECK-NEXT: store i8* [[T2]], i8** [[T0]] // CHECK-NEXT: store i8* null, i8** [[T1]] - // CHECK-LABEL: define internal void @__Block_byref_object_dispose_ + // CHECK-LABEL: define internal void @__Block_byref_object_dispose_(i8*) #{{[0-9]+}} { // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* {{%.*}}, i32 0, i32 6 // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]] // CHECK-NEXT: call void @objc_release(i8* [[T1]]) @@ -155,10 +155,10 @@ void test4(void) { // CHECK-NEXT: call void @objc_release(i8* [[T0]]) // CHECK-NEXT: ret void - // CHECK-LABEL: define internal void @__copy_helper_block_ + // CHECK-LABEL: define internal void @__copy_helper_block_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} { // CHECK: call void @_Block_object_assign(i8* {{%.*}}, i8* {{%.*}}, i32 8) - // CHECK-LABEL: define internal void @__destroy_helper_block_ + // CHECK-LABEL: define internal void @__destroy_helper_block_.{{[0-9]+}}(i8*) #{{[0-9]+}} { // CHECK: call void @_Block_object_dispose(i8* {{%.*}}, i32 8) } @@ -221,14 +221,14 @@ void test6(void) { // CHECK-NEXT: call void @llvm.lifetime.end(i64 48, i8* [[VARPTR2]]) // CHECK-NEXT: ret void - // CHECK-LABEL: define internal void @__Block_byref_object_copy_ + // CHECK-LABEL: define internal void @__Block_byref_object_copy_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} { // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* {{%.*}}, i32 0, i32 6 // CHECK-NEXT: load i8*, i8** // CHECK-NEXT: bitcast i8* {{%.*}} to [[BYREF_T]]* // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* {{%.*}}, i32 0, i32 6 // CHECK-NEXT: call void @objc_moveWeak(i8** [[T0]], i8** [[T1]]) - // CHECK-LABEL: define internal void @__Block_byref_object_dispose_ + // CHECK-LABEL: define internal void @__Block_byref_object_dispose_.{{[0-9]+}}(i8*) #{{[0-9]+}} { // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* {{%.*}}, i32 0, i32 6 // CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) @@ -237,11 +237,11 @@ void test6(void) { // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[SLOT]], i8* null) // CHECK-NEXT: ret void - // CHECK-LABEL: define internal void @__copy_helper_block_ + // CHECK-LABEL: define internal void @__copy_helper_block_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} { // 0x8 - FIELD_IS_BYREF (no FIELD_IS_WEAK because clang in control) // CHECK: call void @_Block_object_assign(i8* {{%.*}}, i8* {{%.*}}, i32 8) - // CHECK-LABEL: define internal void @__destroy_helper_block_ + // CHECK-LABEL: define internal void @__destroy_helper_block_.{{[0-9]+}}(i8*) #{{[0-9]+}} { // 0x8 - FIELD_IS_BYREF (no FIELD_IS_WEAK because clang in control) // CHECK: call void @_Block_object_dispose(i8* {{%.*}}, i32 8) } @@ -277,12 +277,12 @@ void test7(void) { // CHECK-NEXT: call void @objc_release(i8* [[T0]]) // CHECK: ret void - // CHECK-LABEL: define internal void @__copy_helper_block_ + // CHECK-LABEL: define internal void @__copy_helper_block_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} { // CHECK: getelementptr // CHECK-NEXT: getelementptr // CHECK-NEXT: call void @objc_copyWeak( - // CHECK-LABEL: define internal void @__destroy_helper_block_ + // CHECK-LABEL: define internal void @__destroy_helper_block_.{{[0-9]+}}(i8*) #{{[0-9]+}} { // CHECK: getelementptr // CHECK-NEXT: call void @objc_destroyWeak( } @@ -374,7 +374,7 @@ void test10a(void) { // We can also use _Block_object_assign/destroy with // BLOCK_FIELD_IS_BLOCK as long as we don't pass BLOCK_BYREF_CALLER. -// CHECK-LABEL: define internal void @__Block_byref_object_copy +// CHECK-LABEL: define internal void @__Block_byref_object_copy_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} { // CHECK: [[D0:%.*]] = load i8*, i8** {{%.*}} // CHECK-NEXT: [[D1:%.*]] = bitcast i8* [[D0]] to [[BYREF_T]]* // CHECK-NEXT: [[D2:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[D1]], i32 0, i32 6 @@ -388,7 +388,7 @@ void test10a(void) { // CHECK-NEXT: store void ()* [[T3]], void ()** [[D2]], align 8 // CHECK: ret void -// CHECK-LABEL: define internal void @__Block_byref_object_dispose +// CHECK-LABEL: define internal void @__Block_byref_object_dispose_.{{[0-9]+}}(i8*) #{{[0-9]+}} { // CHECK: [[T0:%.*]] = load i8*, i8** {{%.*}} // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BYREF_T]]* // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[T1]], i32 0, i32 6 @@ -648,7 +648,7 @@ void test18(id x) { extern void test18_helper(id (^)(void)); test18_helper(^{ return x; }); -// CHECK-UNOPT-LABEL: define internal void @__copy_helper_block_ +// CHECK-UNOPT-LABEL: define internal void @__copy_helper_block_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} { // CHECK-UNOPT: [[T0:%.*]] = load i8*, i8** // CHECK-UNOPT-NEXT: [[SRC:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]* // CHECK-UNOPT-NEXT: [[T0:%.*]] = load i8*, i8** @@ -660,7 +660,7 @@ void test18(id x) { // CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[T1]], i8* [[T2]]) [[NUW]] // CHECK-UNOPT-NEXT: ret void -// CHECK-UNOPT-LABEL: define internal void @__destroy_helper_block_ +// CHECK-UNOPT-LABEL: define internal void @__destroy_helper_block_.{{[0-9]+}}(i8*) #{{[0-9]+}} { // CHECK-UNOPT: [[T0:%.*]] = load i8*, i8** // CHECK-UNOPT-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]* // CHECK-UNOPT-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[T1]], i32 0, i32 5