forked from OSchip/llvm-project
[ObjC] Use empty Objective-C collection literal constants when
available. Original patch by Douglas Gregor with minor modifications. rdar://problem/20689633 llvm-svn: 300389
This commit is contained in:
parent
2561885f57
commit
dad5266044
|
@ -326,6 +326,20 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/// Are the empty collection symbols available?
|
||||
bool hasEmptyCollections() const {
|
||||
switch (getKind()) {
|
||||
default:
|
||||
return false;
|
||||
case MacOSX:
|
||||
return getVersion() >= VersionTuple(10, 11);
|
||||
case iOS:
|
||||
return getVersion() >= VersionTuple(9);
|
||||
case WatchOS:
|
||||
return getVersion() >= VersionTuple(2);
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Try to parse an Objective-C runtime specification from the given
|
||||
/// string.
|
||||
///
|
||||
|
|
|
@ -117,10 +117,22 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
|
|||
const ObjCArrayLiteral *ALE = dyn_cast<ObjCArrayLiteral>(E);
|
||||
if (!ALE)
|
||||
DLE = cast<ObjCDictionaryLiteral>(E);
|
||||
|
||||
// Compute the type of the array we're initializing.
|
||||
|
||||
// Optimize empty collections by referencing constants, when available.
|
||||
uint64_t NumElements =
|
||||
ALE ? ALE->getNumElements() : DLE->getNumElements();
|
||||
if (NumElements == 0 && CGM.getLangOpts().ObjCRuntime.hasEmptyCollections()) {
|
||||
StringRef ConstantName = ALE ? "__NSArray0__" : "__NSDictionary0__";
|
||||
QualType IdTy(CGM.getContext().getObjCIdType());
|
||||
llvm::Constant *Constant =
|
||||
CGM.CreateRuntimeVariable(ConvertType(IdTy), ConstantName);
|
||||
LValue LV = LValue::MakeAddr(Constant, IdTy,
|
||||
Context.getTypeAlignInChars(IdTy), Context);
|
||||
return Builder.CreateBitCast(EmitLoadOfScalar(LV, E->getLocStart()),
|
||||
ConvertType(E->getType()));
|
||||
}
|
||||
|
||||
// Compute the type of the array we're initializing.
|
||||
llvm::APInt APNumElements(Context.getTypeSize(Context.getSizeType()),
|
||||
NumElements);
|
||||
QualType ElementType = Context.getObjCIdType().withConst();
|
||||
|
|
|
@ -5980,9 +5980,21 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
|
|||
} else if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(E)) {
|
||||
D = BoxedExpr->getBoxingMethod();
|
||||
} else if (ObjCArrayLiteral *ArrayLit = dyn_cast<ObjCArrayLiteral>(E)) {
|
||||
// Don't do reclaims if we're using the zero-element array
|
||||
// constant.
|
||||
if (ArrayLit->getNumElements() == 0 &&
|
||||
Context.getLangOpts().ObjCRuntime.hasEmptyCollections())
|
||||
return E;
|
||||
|
||||
D = ArrayLit->getArrayWithObjectsMethod();
|
||||
} else if (ObjCDictionaryLiteral *DictLit
|
||||
= dyn_cast<ObjCDictionaryLiteral>(E)) {
|
||||
// Don't do reclaims if we're using the zero-element dictionary
|
||||
// constant.
|
||||
if (DictLit->getNumElements() == 0 &&
|
||||
Context.getLangOpts().ObjCRuntime.hasEmptyCollections())
|
||||
return E;
|
||||
|
||||
D = DictLit->getDictWithObjectsMethod();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-macosx10.10.0 -fobjc-runtime=macosx-10.10.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITHOUT-EMPTY-COLLECTIONS %s
|
||||
// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-macosx10.11.0 -fobjc-runtime=macosx-10.11.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITH-EMPTY-COLLECTIONS %s
|
||||
|
||||
// RUN: %clang_cc1 -I %S/Inputs -triple arm64-apple-ios8.0 -fobjc-runtime=ios-8.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITHOUT-EMPTY-COLLECTIONS %s
|
||||
// RUN: %clang_cc1 -I %S/Inputs -triple arm64-apple-ios9.0 -fobjc-runtime=ios-9.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITH-EMPTY-COLLECTIONS %s
|
||||
|
||||
// RUN: %clang_cc1 -I %S/Inputs -triple armv7k-apple-watchos2.0 -fobjc-runtime=watchos-1.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITHOUT-EMPTY-COLLECTIONS %s
|
||||
// RUN: %clang_cc1 -I %S/Inputs -triple armv7k-apple-watchos2.0 -fobjc-runtime=watchos-2.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITH-EMPTY-COLLECTIONS %s
|
||||
|
||||
// RUN: %clang_cc1 -I %S/Inputs -triple arm64-apple-tvos8.0 -fobjc-runtime=ios-8.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITHOUT-EMPTY-COLLECTIONS %s
|
||||
// RUN: %clang_cc1 -I %S/Inputs -triple arm64-apple-tvos9.0 -fobjc-runtime=ios-9.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITH-EMPTY-COLLECTIONS %s
|
||||
|
||||
#include "literal-support.h"
|
||||
|
||||
void test_empty_array() {
|
||||
// CHECK-WITHOUT-EMPTY-COLLECTIONS-LABEL: define void @test_empty_array
|
||||
// CHECK-WITHOUT-EMPTY-COLLECTIONS-NOT: ret void
|
||||
// CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*objc_msgSend}}
|
||||
// CHECK-WITHOUT-EMPTY-COLLECTIONS-NOT: ret void
|
||||
// CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*objc_retainAutoreleasedReturnValue}}
|
||||
// CHECK-WITHOUT-EMPTY-COLLECTIONS: ret void
|
||||
|
||||
// CHECK-WITH-EMPTY-COLLECTIONS-LABEL: define void @test_empty_array
|
||||
// CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
|
||||
// CHECK-WITH-EMPTY-COLLECTIONS: load {{.*}} @__NSArray0__
|
||||
// CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
|
||||
// CHECK-WITH-EMPTY-COLLECTIONS: {{call.*objc_retain\(}}
|
||||
// CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
|
||||
// CHECK-WITH-EMPTY-COLLECTIONS: call void @objc_storeStrong
|
||||
// CHECK-WITH-EMPTY-COLLECTIONS-NEXT: ret void
|
||||
NSArray *arr = @[];
|
||||
}
|
||||
|
||||
void test_empty_dictionary() {
|
||||
// CHECK-WITHOUT-EMPTY-COLLECTIONS-LABEL: define void @test_empty_dictionary
|
||||
// CHECK-WITHOUT-EMPTY-COLLECTIONS-NOT: ret void
|
||||
// CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*objc_msgSend}}
|
||||
// CHECK-WITHOUT-EMPTY-COLLECTIONS-NOT: ret void
|
||||
// CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*objc_retainAutoreleasedReturnValue}}
|
||||
// CHECK-WITHOUT-EMPTY-COLLECTIONS: ret void
|
||||
|
||||
// CHECK-WITH-EMPTY-COLLECTIONS-LABEL: define void @test_empty_dictionary
|
||||
// CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
|
||||
// CHECK-WITH-EMPTY-COLLECTIONS: load {{.*}} @__NSDictionary0__
|
||||
// CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
|
||||
// CHECK-WITH-EMPTY-COLLECTIONS: {{call.*objc_retain\(}}
|
||||
// CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
|
||||
// CHECK-WITH-EMPTY-COLLECTIONS: call void @objc_storeStrong
|
||||
// CHECK-WITH-EMPTY-COLLECTIONS-NEXT: ret void
|
||||
NSDictionary *dict = @{};
|
||||
}
|
Loading…
Reference in New Issue