forked from OSchip/llvm-project
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:
parent
3c4a251ce8
commit
d1b6778e69
|
@ -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 =
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue