Objective-C IRGen. Use llvm::WeakVH

for caching couple of global symbols used
for generation of CF/NS string meta-data
so they are not released prematuely in certain
corner cases. // rdar:// 13598026.
Reviewed by John M.

llvm-svn: 179599
This commit is contained in:
Fariborz Jahanian 2013-04-16 15:25:39 +00:00
parent 3c4a251ce8
commit d1b6778e69
3 changed files with 61 additions and 12 deletions

View File

@ -2279,6 +2279,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty); llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty);
llvm::Constant *Zeros[] = { Zero, Zero }; llvm::Constant *Zeros[] = { Zero, Zero };
llvm::Value *V;
// If we don't already have it, get __CFConstantStringClassReference. // If we don't already have it, get __CFConstantStringClassReference.
if (!CFConstantStringClassRef) { if (!CFConstantStringClassRef) {
@ -2287,9 +2288,11 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
llvm::Constant *GV = CreateRuntimeVariable(Ty, llvm::Constant *GV = CreateRuntimeVariable(Ty,
"__CFConstantStringClassReference"); "__CFConstantStringClassReference");
// Decay array -> ptr // Decay array -> ptr
CFConstantStringClassRef = V = llvm::ConstantExpr::getGetElementPtr(GV, Zeros);
llvm::ConstantExpr::getGetElementPtr(GV, Zeros); CFConstantStringClassRef = V;
} }
else
V = CFConstantStringClassRef;
QualType CFTy = getContext().getCFConstantStringType(); QualType CFTy = getContext().getCFConstantStringType();
@ -2299,7 +2302,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
llvm::Constant *Fields[4]; llvm::Constant *Fields[4];
// Class pointer. // Class pointer.
Fields[0] = CFConstantStringClassRef; Fields[0] = cast<llvm::ConstantExpr>(V);
// Flags. // Flags.
llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy); llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy);
@ -2386,7 +2389,7 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) {
llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty); llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty);
llvm::Constant *Zeros[] = { Zero, Zero }; llvm::Constant *Zeros[] = { Zero, Zero };
llvm::Value *V;
// If we don't already have it, get _NSConstantStringClassReference. // If we don't already have it, get _NSConstantStringClassReference.
if (!ConstantStringClassRef) { if (!ConstantStringClassRef) {
std::string StringClass(getLangOpts().ObjCConstantStringClass); std::string StringClass(getLangOpts().ObjCConstantStringClass);
@ -2399,8 +2402,8 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) {
GV = getObjCRuntime().GetClassGlobal(str); GV = getObjCRuntime().GetClassGlobal(str);
// Make sure the result is of the correct type. // Make sure the result is of the correct type.
llvm::Type *PTy = llvm::PointerType::getUnqual(Ty); llvm::Type *PTy = llvm::PointerType::getUnqual(Ty);
ConstantStringClassRef = V = llvm::ConstantExpr::getBitCast(GV, PTy);
llvm::ConstantExpr::getBitCast(GV, PTy); ConstantStringClassRef = V;
} else { } else {
std::string str = std::string str =
StringClass.empty() ? "_NSConstantStringClassReference" StringClass.empty() ? "_NSConstantStringClassReference"
@ -2408,10 +2411,12 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) {
llvm::Type *PTy = llvm::ArrayType::get(Ty, 0); llvm::Type *PTy = llvm::ArrayType::get(Ty, 0);
GV = CreateRuntimeVariable(PTy, str); GV = CreateRuntimeVariable(PTy, str);
// Decay array -> ptr // Decay array -> ptr
ConstantStringClassRef = V = llvm::ConstantExpr::getGetElementPtr(GV, Zeros);
llvm::ConstantExpr::getGetElementPtr(GV, Zeros); ConstantStringClassRef = V;
} }
} }
else
V = ConstantStringClassRef;
if (!NSConstantStringType) { if (!NSConstantStringType) {
// Construct the type for a constant NSString. // Construct the type for a constant NSString.
@ -2450,7 +2455,7 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) {
llvm::Constant *Fields[3]; llvm::Constant *Fields[3];
// Class pointer. // Class pointer.
Fields[0] = ConstantStringClassRef; Fields[0] = cast<llvm::ConstantExpr>(V);
// String pointer. // String pointer.
llvm::Constant *C = llvm::Constant *C =

View File

@ -346,11 +346,11 @@ class CodeGenModule : public CodeGenTypeCache {
/// CFConstantStringClassRef - Cached reference to the class for constant /// CFConstantStringClassRef - Cached reference to the class for constant
/// strings. This value has type int * but is actually an Obj-C class pointer. /// strings. This value has type int * but is actually an Obj-C class pointer.
llvm::Constant *CFConstantStringClassRef; llvm::WeakVH CFConstantStringClassRef;
/// ConstantStringClassRef - Cached reference to the class for constant /// ConstantStringClassRef - Cached reference to the class for constant
/// strings. This value has type int * but is actually an Obj-C class pointer. /// strings. This value has type int * but is actually an Obj-C class pointer.
llvm::Constant *ConstantStringClassRef; llvm::WeakVH ConstantStringClassRef;
/// \brief The LLVM type corresponding to NSConstantString. /// \brief The LLVM type corresponding to NSConstantString.
llvm::StructType *NSConstantStringType; llvm::StructType *NSConstantStringType;

View File

@ -0,0 +1,44 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
// rdar://13598026
@interface NSObject @end
@class NSString;
int __CFConstantStringClassReference[24];
@interface Bar : NSObject
+(void)format:(NSString *)format,...;
@end
@interface Foo : NSObject
@end
static inline void _inlineFunction() {
[Bar format:@" "];
}
@implementation Foo
+(NSString *)someMethod {
return @"";
}
-(void)someMethod {
_inlineFunction();
}
@end
// CHECK: @__CFConstantStringClassReference = common global [24 x i32] zeroinitializer, align 16
// CHECK: @_unnamed_cfstring_{{.*}} = private constant %struct.NSConstantString { i32* getelementptr inbounds ([24 x i32]* @__CFConstantStringClassReference, i32 0, i32 0)
// CHECK: define internal void @_inlineFunction()
// CHECK-NEXT: entry:
// CHECK-NEXT: [[ZERO:%.*]] = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_
// CHECK-NEXT: [[ONE:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_"
// CHECK-NEXT: [[TWO:%.*]] = bitcast %struct._class_t* [[ZERO]] to i8*
// CHECK-NEXT: call{{.*}}@objc_msgSend{{.*}}(i8* [[TWO]], i8* [[ONE]], [[ZERO]]* bitcast (%struct.NSConstantString* @_unnamed_cfstring_{{.*}}
// CHECK-NEXT: ret void