mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 13:50:11 +00:00
[clang][objc][codegen] Skip emitting ObjC category metadata when the
category is empty Currently, if we create a category in ObjC that is empty, we still emit runtime metadata for that category. This is a scenario that could commonly be run into when using __attribute__((objc_direct_members)), which elides the need for much of the category metadata. This is slightly wasteful and can be easily skipped by checking the category metadata contents during CodeGen. rdar://66177182 Differential Revision: https://reviews.llvm.org/D113455
This commit is contained in:
parent
cb0e14ce6d
commit
7611e16fce
@ -6672,33 +6672,53 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
|
||||
}
|
||||
}
|
||||
|
||||
values.add(emitMethodList(listName, MethodListType::CategoryInstanceMethods,
|
||||
instanceMethods));
|
||||
values.add(emitMethodList(listName, MethodListType::CategoryClassMethods,
|
||||
classMethods));
|
||||
auto instanceMethodList = emitMethodList(
|
||||
listName, MethodListType::CategoryInstanceMethods, instanceMethods);
|
||||
auto classMethodList = emitMethodList(
|
||||
listName, MethodListType::CategoryClassMethods, classMethods);
|
||||
values.add(instanceMethodList);
|
||||
values.add(classMethodList);
|
||||
// Keep track of whether we have actual metadata to emit.
|
||||
bool isEmptyCategory =
|
||||
instanceMethodList->isNullValue() && classMethodList->isNullValue();
|
||||
|
||||
const ObjCCategoryDecl *Category =
|
||||
Interface->FindCategoryDeclaration(OCD->getIdentifier());
|
||||
Interface->FindCategoryDeclaration(OCD->getIdentifier());
|
||||
if (Category) {
|
||||
SmallString<256> ExtName;
|
||||
llvm::raw_svector_ostream(ExtName) << Interface->getObjCRuntimeNameAsString() << "_$_"
|
||||
<< OCD->getName();
|
||||
values.add(EmitProtocolList("_OBJC_CATEGORY_PROTOCOLS_$_"
|
||||
+ Interface->getObjCRuntimeNameAsString() + "_$_"
|
||||
+ Category->getName(),
|
||||
Category->protocol_begin(),
|
||||
Category->protocol_end()));
|
||||
values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(),
|
||||
OCD, Category, ObjCTypes, false));
|
||||
values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
|
||||
OCD, Category, ObjCTypes, true));
|
||||
llvm::raw_svector_ostream(ExtName)
|
||||
<< Interface->getObjCRuntimeNameAsString() << "_$_" << OCD->getName();
|
||||
auto protocolList =
|
||||
EmitProtocolList("_OBJC_CATEGORY_PROTOCOLS_$_" +
|
||||
Interface->getObjCRuntimeNameAsString() + "_$_" +
|
||||
Category->getName(),
|
||||
Category->protocol_begin(), Category->protocol_end());
|
||||
auto propertyList = EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(),
|
||||
OCD, Category, ObjCTypes, false);
|
||||
auto classPropertyList =
|
||||
EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), OCD,
|
||||
Category, ObjCTypes, true);
|
||||
values.add(protocolList);
|
||||
values.add(propertyList);
|
||||
values.add(classPropertyList);
|
||||
isEmptyCategory &= protocolList->isNullValue() &&
|
||||
propertyList->isNullValue() &&
|
||||
classPropertyList->isNullValue();
|
||||
} else {
|
||||
values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy);
|
||||
values.addNullPointer(ObjCTypes.PropertyListPtrTy);
|
||||
values.addNullPointer(ObjCTypes.PropertyListPtrTy);
|
||||
}
|
||||
|
||||
unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
|
||||
if (isEmptyCategory) {
|
||||
// Empty category, don't emit any metadata.
|
||||
values.abandon();
|
||||
MethodDefinitions.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned Size =
|
||||
CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
|
||||
values.addInt(ObjCTypes.IntTy, Size);
|
||||
|
||||
llvm::GlobalVariable *GCATV =
|
||||
|
16
clang/test/CodeGenObjC/category-class-empty.m
Normal file
16
clang/test/CodeGenObjC/category-class-empty.m
Normal file
@ -0,0 +1,16 @@
|
||||
// RUN: %clang_cc1 -triple i386-apple-darwin9 -O0 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s
|
||||
// PR7431
|
||||
|
||||
// CHECK-NOT: @"OBJC_LABEL_CATEGORY_$" = private global [1 x i8*] [i8* bitcast (%struct._category_t* @"_OBJC_$_CATEGORY_A_$_foo"
|
||||
|
||||
@interface A
|
||||
@end
|
||||
__attribute__((objc_direct_members))
|
||||
@interface A(foo)
|
||||
- (void)foo_myStuff;
|
||||
@end
|
||||
@implementation A(foo)
|
||||
- (void)foo_myStuff {
|
||||
}
|
||||
@end
|
||||
|
@ -42,4 +42,7 @@ __attribute__((objc_nonlazy_class))
|
||||
@implementation E @end
|
||||
|
||||
__attribute__((objc_nonlazy_class))
|
||||
@implementation E (MyCat) @end
|
||||
@implementation E (MyCat)
|
||||
-(void) load {
|
||||
}
|
||||
@end
|
||||
|
Loading…
Reference in New Issue
Block a user