forked from OSchip/llvm-project
[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
This commit is contained in:
parent
ab2241f1b8
commit
aec6b2c20e
|
@ -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()) {
|
||||
|
|
|
@ -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<NamedDecl>(D))
|
||||
if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
|
||||
setGlobalVisibility(GV, ND);
|
||||
else
|
||||
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
|
||||
|
||||
if (D->hasAttr<UsedAttr>())
|
||||
if (D && D->hasAttr<UsedAttr>())
|
||||
addUsedGlobal(GV);
|
||||
}
|
||||
|
||||
|
@ -890,6 +890,7 @@ void CodeGenModule::setNonAliasAttributes(const Decl *D,
|
|||
llvm::GlobalObject *GO) {
|
||||
SetCommonAttributes(D, GO);
|
||||
|
||||
if (D)
|
||||
if (const SectionAttr *SA = D->getAttr<SectionAttr>())
|
||||
GO->setSection(SA->getName());
|
||||
|
||||
|
|
|
@ -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<FunctionDecl>(D)) {
|
||||
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
|
||||
if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
|
||||
// Get the LLVM function.
|
||||
llvm::Function *Fn = cast<llvm::Function>(GV);
|
||||
|
@ -1898,7 +1898,7 @@ public:
|
|||
static void addStackProbeSizeTargetAttribute(const Decl *D,
|
||||
llvm::GlobalValue *GV,
|
||||
CodeGen::CodeGenModule &CGM) {
|
||||
if (isa<FunctionDecl>(D)) {
|
||||
if (D && isa<FunctionDecl>(D)) {
|
||||
if (CGM.getCodeGenOpts().StackProbeSize != 4096) {
|
||||
llvm::Function *Fn = cast<llvm::Function>(GV);
|
||||
|
||||
|
@ -4745,7 +4745,7 @@ public:
|
|||
|
||||
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
|
||||
CodeGen::CodeGenModule &CGM) const override {
|
||||
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
|
||||
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(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<FunctionDecl>(D);
|
||||
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
|
||||
if (!FD) return;
|
||||
|
||||
llvm::Function *F = cast<llvm::Function>(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<FunctionDecl>(D)) {
|
||||
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
|
||||
if (const MSP430InterruptAttr *attr = FD->getAttr<MSP430InterruptAttr>()) {
|
||||
// Handle 'interrupt' attribute:
|
||||
llvm::Function *F = cast<llvm::Function>(GV);
|
||||
|
@ -5796,7 +5796,7 @@ public:
|
|||
|
||||
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
|
||||
CodeGen::CodeGenModule &CGM) const override {
|
||||
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
|
||||
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
|
||||
if (!FD) return;
|
||||
llvm::Function *Fn = cast<llvm::Function>(GV);
|
||||
if (FD->hasAttr<Mips16Attr>()) {
|
||||
|
@ -6143,7 +6143,7 @@ public:
|
|||
|
||||
void TCETargetCodeGenInfo::setTargetAttributes(
|
||||
const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
|
||||
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
|
||||
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
|
||||
if (!FD) return;
|
||||
|
||||
llvm::Function *F = cast<llvm::Function>(GV);
|
||||
|
@ -6325,7 +6325,7 @@ void AMDGPUTargetCodeGenInfo::setTargetAttributes(
|
|||
const Decl *D,
|
||||
llvm::GlobalValue *GV,
|
||||
CodeGen::CodeGenModule &M) const {
|
||||
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
|
||||
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
|
||||
if (!FD)
|
||||
return;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue