Author: Josh Learn Date: 2021-11-12T16:21:21-08:00 New Revision: 7611e16fce9ce36b6bd6dceda691f6bc7e754347
URL: https://github.com/llvm/llvm-project/commit/7611e16fce9ce36b6bd6dceda691f6bc7e754347 DIFF: https://github.com/llvm/llvm-project/commit/7611e16fce9ce36b6bd6dceda691f6bc7e754347.diff LOG: [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 Added: clang/test/CodeGenObjC/category-class-empty.m Modified: clang/lib/CodeGen/CGObjCMac.cpp clang/test/CodeGenObjC/non-lazy-classes.m Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 36555ce3cbd9..5b925359ac25 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -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 = diff --git a/clang/test/CodeGenObjC/category-class-empty.m b/clang/test/CodeGenObjC/category-class-empty.m new file mode 100644 index 000000000000..d89a3e7eac42 --- /dev/null +++ b/clang/test/CodeGenObjC/category-class-empty.m @@ -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 + diff --git a/clang/test/CodeGenObjC/non-lazy-classes.m b/clang/test/CodeGenObjC/non-lazy-classes.m index fc861f0017c0..4d5a3c0494e3 100644 --- a/clang/test/CodeGenObjC/non-lazy-classes.m +++ b/clang/test/CodeGenObjC/non-lazy-classes.m @@ -42,4 +42,7 @@ @interface E @end @implementation E @end __attribute__((objc_nonlazy_class)) -@implementation E (MyCat) @end +@implementation E (MyCat) +-(void) load { +} +@end _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits