[clang] 7611e16 - [clang][objc][codegen] Skip emitting ObjC category metadata when the

Akira Hatanaka via cfe-commits cfe-commits at lists.llvm.org
Fri Nov 12 16:25:08 PST 2021


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"
+
+ at interface A
+ at end
+__attribute__((objc_direct_members))
+ at interface A(foo)
+- (void)foo_myStuff;
+ at end
+ at implementation A(foo)
+- (void)foo_myStuff {
+}
+ at 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))
- at implementation E (MyCat) @end
+ at implementation E (MyCat)
+-(void) load {
+}
+ at end


        


More information about the cfe-commits mailing list