davide created this revision.
davide added reviewers: rjmccall, rsmith, pete, ab, jckarter.
davide requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Given these two files:

  #import <objc/NSObject.h>
  
  @interface Bar : NSObject<NSObject>
  @end
  
  @implementation Bar
  @end
  
  id bar()
  {
      return [Bar class];
  }

and

  #import <objc/NSObject.h>
  
  @interface Foo : NSObject<NSObject>
  @end
  
  @implementation Foo
  @end
  
  id foo()
  {
      return [Foo class];
  }

built with:

`xcrun --sdk macosx.internal clang++ foo.m bar.m -o lib.dylib -lobjc 
-dynamiclib -O2 -Wl,-dead_strip`

if you run nm on it, you'll see 2 copies of all the protocol metadata:

  $ nm -j lib.dylib | uniq -c | grep 2
     2 __OBJC_$_PROP_LIST_NSObject
     2 __OBJC_$_PROTOCOL_INSTANCE_METHODS_NSObject
     2 __OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_NSObject
     2 __OBJC_$_PROTOCOL_METHOD_TYPES_NSObject

This is because some metadata is emitted with `internal` linkage and `default` 
visibility, e.g.:

  @"_OBJC_$_PROP_LIST_NSObject" = internal global { i32, i32, [4 x 
%struct._prop_t] } 

This patch changes `clang` to emit protocol metadata as `weak hidden`, so that 
`ld64` can deduplicate them.

Fixes rdar://problem/85042564


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D113456

Files:
  clang/lib/CodeGen/CGObjCMac.cpp
  clang/test/CodeGenObjC/direct-properties.m
  clang/test/CodeGenObjC/encode-test-2.m
  clang/test/CodeGenObjC/metadata-class-properties.m
  clang/test/CodeGenObjC/metadata-symbols-32.m
  clang/test/CodeGenObjC/metadata-symbols-64.m
  clang/test/CodeGenObjC/property-category-impl.m
  clang/test/CodeGenObjC/property-list-in-class.m
  clang/test/CodeGenObjC/property-list-in-extension.m
  clang/test/CodeGenObjC/protocols.m
  clang/test/CodeGenObjC/sections.m

Index: clang/test/CodeGenObjC/sections.m
===================================================================
--- clang/test/CodeGenObjC/sections.m
+++ clang/test/CodeGenObjC/sections.m
@@ -34,7 +34,7 @@
   return [I class] == @protocol(P);
 }
 
-// CHECK-COFF: @"_OBJC_$_CLASS_METHODS_I" = private
+// CHECK-COFF: @"_OBJC_$_CLASS_METHODS_I" = weak hidden
 // CHECK-COFF: @"OBJC_CLASSLIST_SUP_REFS_$_" = private {{.*}}, section ".objc_superrefs$B"
 // CHECK-COFF: @OBJC_SELECTOR_REFERENCES_ = private {{.*}}, section ".objc_selrefs$B"
 // CHECK-COFF: @"OBJC_CLASSLIST_REFERENCES_$_" = private {{.*}}, section ".objc_classrefs$B"
@@ -47,7 +47,7 @@
 // CHECK-COFF: @"OBJC_LABEL_NONLAZY_CATEGORY_$" = private {{.*}}, section ".objc_nlcatlist$B"
 // CHECK-COFF: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !".objc_imageinfo$B"}
 
-// CHECK-ELF: @"_OBJC_$_CLASS_METHODS_I" = private
+// CHECK-ELF: @"_OBJC_$_CLASS_METHODS_I" = weak hidden
 // CHECK-ELF: @"OBJC_CLASSLIST_SUP_REFS_$_" = private {{.*}}, section "objc_superrefs"
 // CHECK-ELF: @OBJC_SELECTOR_REFERENCES_ = private {{.*}}, section "objc_selrefs"
 // CHECK-ELF: @"OBJC_CLASSLIST_REFERENCES_$_" = private {{.*}}, section "objc_classrefs"
@@ -60,7 +60,7 @@
 // CHECK-ELF: @"OBJC_LABEL_NONLAZY_CATEGORY_$" = private {{.*}}, section "objc_nlcatlist"
 // CHECK-ELF: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !"objc_imageinfo"}
 
-// CHECK-MACHO: @"_OBJC_$_CLASS_METHODS_I" = internal {{.*}}, section "__DATA, __objc_const"
+// CHECK-MACHO: @"_OBJC_$_CLASS_METHODS_I" = weak hidden {{.*}}, section "__DATA, __objc_const"
 // CHECK-MACHO: @"OBJC_CLASSLIST_SUP_REFS_$_" = private {{.*}}, section "__DATA,__objc_superrefs,regular,no_dead_strip"
 // CHECK-MACHO: @OBJC_SELECTOR_REFERENCES_ = internal {{.*}}, section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip"
 // CHECK-MACHO: @"OBJC_CLASSLIST_REFERENCES_$_" = internal {{.*}}, section "__DATA,__objc_classrefs,regular,no_dead_strip"
Index: clang/test/CodeGenObjC/protocols.m
===================================================================
--- clang/test/CodeGenObjC/protocols.m
+++ clang/test/CodeGenObjC/protocols.m
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
 
-// CHECK: @"_OBJC_$_PROTOCOL_METHOD_TYPES_P1" = internal global
+// CHECK: @"_OBJC_$_PROTOCOL_METHOD_TYPES_P1" = weak hidden global
 // CHECK: @[[PROTO_P1:"_OBJC_PROTOCOL_\$_P1"]] = weak hidden
 // CHECK: @[[LABEL_PROTO_P1:"_OBJC_LABEL_PROTOCOL_\$_P1"]] = weak hidden global %{{.*}}* @[[PROTO_P1]]
 // CHECK: @[[PROTO_P2:"_OBJC_PROTOCOL_\$_P2"]] = weak hidden
Index: clang/test/CodeGenObjC/property-list-in-extension.m
===================================================================
--- clang/test/CodeGenObjC/property-list-in-extension.m
+++ clang/test/CodeGenObjC/property-list-in-extension.m
@@ -18,7 +18,7 @@
 // Metadata for _myprop should be present, and PROP_LIST for Foo should have
 // only one entry.
 // CHECK: = private unnamed_addr constant [12 x i8] c"Ti,V_myprop\00",
-// CHECK: @"_OBJC_$_PROP_LIST_Foo" = internal global { i32, i32, [1 x %struct._prop_t] }
+// CHECK: @"_OBJC_$_PROP_LIST_Foo" = weak hidden global { i32, i32, [1 x %struct._prop_t] }
 
 // Readonly property in interface made readwrite in a category:
 __attribute__((objc_root_class))
@@ -44,4 +44,4 @@
 // CHECK: [[evolvingsetter:@OBJC_PROP_NAME_ATTR[^ ]+]] = private unnamed_addr constant [18 x i8] c"Ti,V_evolvingprop\00",
 // CHECK: [[booleanmetadata:@OBJC_PROP_NAME_ATTR[^ ]+]] = private unnamed_addr constant [34 x i8] c"Ti,N,GisBooleanProp,V_booleanProp\00"
 // CHECK: [[weakmetadata:@OBJC_PROP_NAME_ATTR[^ ]+]] = private unnamed_addr constant [23 x i8] c"T@\22Foo\22,W,N,V_weakProp\00"
-// CHECK: @"_OBJC_$_PROP_LIST_FooRO" = internal global { i32, i32, [3 x %struct._prop_t] }{{.*}}[[evolvinggetter]]{{.*}}[[evolvingsetter]]{{.*}}[[booleanmetadata]]
+// CHECK: @"_OBJC_$_PROP_LIST_FooRO" = weak hidden global { i32, i32, [3 x %struct._prop_t] }{{.*}}[[evolvinggetter]]{{.*}}[[evolvingsetter]]{{.*}}[[booleanmetadata]]
Index: clang/test/CodeGenObjC/property-list-in-class.m
===================================================================
--- clang/test/CodeGenObjC/property-list-in-class.m
+++ clang/test/CodeGenObjC/property-list-in-class.m
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s
-// CHECK: _OBJC_$_PROP_LIST_C2" = internal global { i32, i32, [3 x %struct._prop_t] } { i32 16, i32 3
+// CHECK: _OBJC_$_PROP_LIST_C2" = weak hidden global { i32, i32, [3 x %struct._prop_t] } { i32 16, i32 3
 
 @protocol P 
 @property int i;
Index: clang/test/CodeGenObjC/property-category-impl.m
===================================================================
--- clang/test/CodeGenObjC/property-category-impl.m
+++ clang/test/CodeGenObjC/property-category-impl.m
@@ -15,6 +15,6 @@
 @end
 
 
-// CHECK: _OBJC_$_PROP_LIST_Foo_$_Category" = internal global
+// CHECK: _OBJC_$_PROP_LIST_Foo_$_Category" = weak hidden global
 // CHECK: _OBJC_$_CATEGORY_Foo_$_Category" = internal global
 // CHECK: _OBJC_$_PROP_LIST_Foo_$_Category
Index: clang/test/CodeGenObjC/metadata-symbols-64.m
===================================================================
--- clang/test/CodeGenObjC/metadata-symbols-64.m
+++ clang/test/CodeGenObjC/metadata-symbols-64.m
@@ -8,20 +8,20 @@
 // CHECK: @OBJC_CLASS_NAME_{{[0-9]*}} = private unnamed_addr constant {{.*}} section "__TEXT,__objc_classname,cstring_literals", align 1
 // CHECK: @OBJC_METH_VAR_NAME_{{[0-9]*}} = private unnamed_addr constant {{.*}} section "__TEXT,__objc_methname,cstring_literals", align 1
 // CHECK: @OBJC_METH_VAR_TYPE_{{[0-9]*}} = private unnamed_addr constant {{.*}} section "__TEXT,__objc_methtype,cstring_literals", align 1
-// CHECK: @"_OBJC_$_CLASS_METHODS_A" = internal global {{.*}} section "__DATA, __objc_const", align 8
-// CHECK: @"_OBJC_$_PROTOCOL_INSTANCE_METHODS_P" = internal global {{.*}} section "__DATA, __objc_const", align 8
-// CHECK: @"_OBJC_$_PROTOCOL_CLASS_METHODS_P" = internal global {{.*}} section "__DATA, __objc_const", align 8
+// CHECK: @"_OBJC_$_CLASS_METHODS_A" = weak hidden global {{.*}} section "__DATA, __objc_const", align 8
+// CHECK: @"_OBJC_$_PROTOCOL_INSTANCE_METHODS_P" = weak hidden global {{.*}} section "__DATA, __objc_const", align 8
+// CHECK: @"_OBJC_$_PROTOCOL_CLASS_METHODS_P" = weak hidden global {{.*}} section "__DATA, __objc_const", align 8
 // CHECK: @"_OBJC_PROTOCOL_$_P" = weak hidden global {{.*}}, align 8
 // CHECK: @"_OBJC_LABEL_PROTOCOL_$_P" = weak hidden global {{.*}} section "__DATA,__objc_protolist,coalesced,no_dead_strip", align 8
 // CHECK: @"_OBJC_CLASS_PROTOCOLS_$_A" = internal global {{.*}} section "__DATA, __objc_const", align 8
 // CHECK: @"_OBJC_METACLASS_RO_$_A" = internal global {{.*}} section "__DATA, __objc_const", align 8
-// CHECK: @"_OBJC_$_INSTANCE_METHODS_A" = internal global {{.*}} section "__DATA, __objc_const", align 8
+// CHECK: @"_OBJC_$_INSTANCE_METHODS_A" = weak hidden global {{.*}} section "__DATA, __objc_const", align 8
 // CHECK: @"_OBJC_$_INSTANCE_VARIABLES_A" = internal global {{.*}} section "__DATA, __objc_const", align 8
 // CHECK: @OBJC_PROP_NAME_ATTR_{{[0-9]*}} = private unnamed_addr constant {{.*}} section "__TEXT,__objc_methname,cstring_literals", align 1
-// CHECK: @"_OBJC_$_PROP_LIST_A" = internal global {{.*}} section "__DATA, __objc_const", align 8
+// CHECK: @"_OBJC_$_PROP_LIST_A" = weak hidden global {{.*}} section "__DATA, __objc_const", align 8
 // CHECK: @"_OBJC_CLASS_RO_$_A" = internal global {{.*}} section "__DATA, __objc_const", align 8
-// CHECK: @"_OBJC_$_CATEGORY_INSTANCE_METHODS_A_$_Cat" = internal global {{.*}} section "__DATA, __objc_const", align 8
-// CHECK: @"_OBJC_$_CATEGORY_CLASS_METHODS_A_$_Cat" = internal global {{.*}} section "__DATA, __objc_const", align 8
+// CHECK: @"_OBJC_$_CATEGORY_INSTANCE_METHODS_A_$_Cat" = weak hidden global {{.*}} section "__DATA, __objc_const", align 8
+// CHECK: @"_OBJC_$_CATEGORY_CLASS_METHODS_A_$_Cat" = weak hidden global {{.*}} section "__DATA, __objc_const", align 8
 // CHECK: @"_OBJC_$_CATEGORY_A_$_Cat" = internal global {{.*}} section "__DATA, __objc_const", align 8
 // CHECK: @"OBJC_CLASSLIST_SUP_REFS_$_{{[0-9]*}}" = private global {{.*}} section "__DATA,__objc_superrefs,regular,no_dead_strip", align 8
 // CHECK: @OBJC_SELECTOR_REFERENCES_ = internal externally_initialized global {{.*}} section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip"
Index: clang/test/CodeGenObjC/metadata-symbols-32.m
===================================================================
--- clang/test/CodeGenObjC/metadata-symbols-32.m
+++ clang/test/CodeGenObjC/metadata-symbols-32.m
@@ -15,7 +15,7 @@
 // CHECK: @OBJC_INSTANCE_VARIABLES_A = private global {{.*}}section "__OBJC,__instance_vars,regular,no_dead_strip", align 4
 // CHECK: @OBJC_INSTANCE_METHODS_A = private global {{.*}}section "__OBJC,__inst_meth,regular,no_dead_strip", align 4
 // CHECK: @OBJC_PROP_NAME_ATTR_{{[0-9]*}} = private unnamed_addr constant {{.*}}section "__TEXT,__cstring,cstring_literals", align 1
-// CHECK: @"_OBJC_$_PROP_LIST_A" = private global {{.*}}section "__OBJC,__property,regular,no_dead_strip", align 4
+// CHECK: @"_OBJC_$_PROP_LIST_A" = weak hidden global {{.*}}section "__OBJC,__property,regular,no_dead_strip", align 4
 // CHECK: @OBJC_CLASSEXT_A = private global {{.*}}section "__OBJC,__class_ext,regular,no_dead_strip", align 4
 // CHECK: @OBJC_CLASS_A = private global {{.*}}section "__OBJC,__class,regular,no_dead_strip", align 4
 // CHECK: @OBJC_CATEGORY_INSTANCE_METHODS_A_Cat = private global {{.*}}section "__OBJC,__cat_inst_meth,regular,no_dead_strip", align 4
Index: clang/test/CodeGenObjC/metadata-class-properties.m
===================================================================
--- clang/test/CodeGenObjC/metadata-class-properties.m
+++ clang/test/CodeGenObjC/metadata-class-properties.m
@@ -2,12 +2,12 @@
 // RUN: %clang_cc1 -triple x86_64-apple-macosx10.10  -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NULL %s
 // RUN: %clang_cc1 -triple x86_64-apple-macosx10.11  -emit-llvm -o - -fobjc-runtime=macosx-fragile-10.5 %s | FileCheck -check-prefix=CHECK-FRAGILE %s
 
-// CHECK: @"_OBJC_$_CLASS_PROP_LIST_Proto" = internal global {{.*}} section "__DATA, __objc_const", align 8
+// CHECK: @"_OBJC_$_CLASS_PROP_LIST_Proto" = weak hidden global {{.*}} section "__DATA, __objc_const", align 8
 // CHECK: @"_OBJC_PROTOCOL_$_Proto" = {{.*}} global %struct._protocol_t { {{.*}} i32 96, i32 {{.*}} @"_OBJC_$_CLASS_PROP_LIST_Proto" {{.*}} }
-// CHECK: @"_OBJC_$_CLASS_PROP_LIST_Foo_$_Category" = internal global {{.*}} section "__DATA, __objc_const", align 8
+// CHECK: @"_OBJC_$_CLASS_PROP_LIST_Foo_$_Category" = weak hidden global {{.*}} section "__DATA, __objc_const", align 8
 // CHECK: @"_OBJC_$_CATEGORY_Foo_$_Category" = internal global %struct._category_t { {{.*}} @"_OBJC_$_CLASS_PROP_LIST_Foo_$_Category" {{.*}}, i32 64 }, section "__DATA, __objc_const", align 8
 
-// CHECK: @"_OBJC_$_CLASS_PROP_LIST_C" = internal global {{.*}} section "__DATA, __objc_const", align 8
+// CHECK: @"_OBJC_$_CLASS_PROP_LIST_C" = weak hidden global {{.*}} section "__DATA, __objc_const", align 8
 // CHECK: @"_OBJC_METACLASS_RO_$_C" = internal global %struct._class_ro_t { {{.*}} @"_OBJC_$_CLASS_PROP_LIST_C" {{.*}} }, section "__DATA, __objc_const", align 8
 
 // CHECK: !{i32 1, !"Objective-C Class Properties", i32 64}
@@ -22,12 +22,12 @@
 
 // CHECK-NULL: !{i32 1, !"Objective-C Class Properties", i32 64}
 
-// CHECK-FRAGILE: @"OBJC_$_CLASS_PROP_PROTO_LIST_Proto" = private global {{.*}} section "__OBJC,__property,regular,no_dead_strip", align 8
+// CHECK-FRAGILE: @"OBJC_$_CLASS_PROP_PROTO_LIST_Proto" = weak hidden global {{.*}} section "__OBJC,__property,regular,no_dead_strip", align 8
 // CHECK-FRAGILE: @_OBJC_PROTOCOLEXT_Proto = internal global %struct._objc_protocol_extension { i32 48, {{.*}} @"OBJC_$_CLASS_PROP_PROTO_LIST_Proto" {{.*}} }, align 8
-// CHECK-FRAGILE: @"_OBJC_$_CLASS_PROP_LIST_Foo_Category" = private global {{.*}} section "__OBJC,__property,regular,no_dead_strip", align 8
+// CHECK-FRAGILE: @"_OBJC_$_CLASS_PROP_LIST_Foo_Category" = weak hidden global {{.*}} section "__OBJC,__property,regular,no_dead_strip", align 8
 // CHECK-FRAGILE: @OBJC_CATEGORY_Foo_Category = private global %struct._objc_category { {{.*}}, i32 64, {{.*}} @"_OBJC_$_CLASS_PROP_LIST_Foo_Category" {{.*}} }, section "__OBJC,__category,regular,no_dead_strip", align 8
 
-// CHECK-FRAGILE: @"_OBJC_$_CLASS_PROP_LIST_C" = private global {{.*}} section "__OBJC,__property,regular,no_dead_strip", align 8
+// CHECK-FRAGILE: @"_OBJC_$_CLASS_PROP_LIST_C" = weak hidden global {{.*}} section "__OBJC,__property,regular,no_dead_strip", align 8
 // CHECK-FRAGILE: @OBJC_CLASSEXT_C = private global %struct._objc_class_extension { {{.*}} @"_OBJC_$_CLASS_PROP_LIST_C" {{.*}} }, section "__OBJC,__class_ext,regular,no_dead_strip", align 8
 
 // CHECK-FRAGILE: !{i32 1, !"Objective-C Class Properties", i32 64}
Index: clang/test/CodeGenObjC/encode-test-2.m
===================================================================
--- clang/test/CodeGenObjC/encode-test-2.m
+++ clang/test/CodeGenObjC/encode-test-2.m
@@ -7,7 +7,7 @@
 // CHECK: private unnamed_addr constant [13 x i8] c"{Intf=@@@@#}\00",
 
 // CHECK: @[[PROP_NAME_ATTR:.*]] = private unnamed_addr constant [5 x i8] c"T@,D\00",
-// CHECK: @"_OBJC_$_PROP_LIST_C0" = internal global { i32, i32, [1 x %{{.*}}] } { i32 8, i32 1, [1 x %{{.*}}] [%{{.*}} { {{.*}}, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @[[PROP_NAME_ATTR]], i32 0, i32 0) }] },
+// CHECK: @"_OBJC_$_PROP_LIST_C0" = weak hidden global { i32, i32, [1 x %{{.*}}] } { i32 8, i32 1, [1 x %{{.*}}] [%{{.*}} { {{.*}}, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @[[PROP_NAME_ATTR]], i32 0, i32 0) }] },
 
 @protocol X, Y, Z;
 @class Foo;
Index: clang/test/CodeGenObjC/direct-properties.m
===================================================================
--- clang/test/CodeGenObjC/direct-properties.m
+++ clang/test/CodeGenObjC/direct-properties.m
@@ -16,7 +16,7 @@
 @synthesize i = _i;
 @end
 
-// CHECK: @"_OBJC_$_PROP_LIST_B" = internal global { i32, i32, [1 x %struct._prop_t] } { i32 16, i32 1
+// CHECK: @"_OBJC_$_PROP_LIST_B" = weak hidden global { i32, i32, [1 x %struct._prop_t] } { i32 16, i32 1
 @implementation B
 @synthesize i = _i;
 @synthesize j = _j;
Index: clang/lib/CodeGen/CGObjCMac.cpp
===================================================================
--- clang/lib/CodeGen/CGObjCMac.cpp
+++ clang/lib/CodeGen/CGObjCMac.cpp
@@ -3291,6 +3291,8 @@
 
   llvm::GlobalVariable *GV =
       CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
+  GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
+  GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
 }
 
@@ -3312,6 +3314,8 @@
 
   llvm::GlobalVariable *GV =
       CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
+  GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
+  GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
 }
 
@@ -6812,6 +6816,8 @@
   methodArray.finishAndAddTo(values);
 
   llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM);
+  GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
+  GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
   CGM.addCompilerUsedGlobal(GV);
   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to