CodeGen: use COMDAT for block copy/destroy helpers
authorSaleem Abdulrasool <compnerd@compnerd.org>
Fri, 22 Feb 2019 16:29:50 +0000 (16:29 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Fri, 22 Feb 2019 16:29:50 +0000 (16:29 +0000)
SVN r339438 added support to deduplicate the helpers by using a consistent
naming scheme and using LinkOnceODR semantics.  This works on ELF by means of
weak linking semantics, and entirely does not work on PE/COFF where you end up
with multiply defined strong symbols, which is a strong error on PE/COFF.
Assign the functions a COMDAT group so that they can be uniqued by the linker.
This fixes the use of blocks in CoreFoundation on Windows.

llvm-svn: 354678

clang/lib/CodeGen/CGBlocks.cpp
clang/test/CodeGen/blocks-1.c

index f4f5f6f..1c10c46 100644 (file)
@@ -2016,6 +2016,8 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
   llvm::Function *Fn =
     llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage,
                            FuncName, &CGM.getModule());
+  if (CGM.supportsCOMDAT())
+    Fn->setComdat(CGM.getModule().getOrInsertComdat(FuncName));
 
   IdentifierInfo *II = &C.Idents.get(FuncName);
 
@@ -2207,6 +2209,8 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
   llvm::Function *Fn =
     llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage,
                            FuncName, &CGM.getModule());
+  if (CGM.supportsCOMDAT())
+    Fn->setComdat(CGM.getModule().getOrInsertComdat(FuncName));
 
   IdentifierInfo *II = &C.Idents.get(FuncName);
 
index 8589a7b..0df1379 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o %t -fblocks
+// RUN: %clang_cc1 -triple thumbv7-apple-ios %s -emit-llvm -o %t -fblocks
 // RUN: grep "_Block_object_dispose" %t | count 12
 // RUN: grep "__copy_helper_block_" %t | count 9
 // RUN: grep "__destroy_helper_block_" %t | count 9
@@ -7,6 +7,15 @@
 // RUN: grep "i32 135)" %t | count 2
 // RUN: grep "_Block_object_assign" %t | count 5
 
+// RUN: %clang_cc1 -triple thumbv7-unknown-windows %s -emit-llvm -o %t -fblocks
+// RUN: grep "_Block_object_dispose" %t | count 12
+// RUN: grep "__copy_helper_block_" %t | count 11
+// RUN: grep "__destroy_helper_block_" %t | count 11
+// RUN: grep "__Block_byref_object_copy_" %t | count 2
+// RUN: grep "__Block_byref_object_dispose_" %t | count 2
+// RUN: grep "i32 135)" %t | count 2
+// RUN: grep "_Block_object_assign" %t | count 5
+
 int printf(const char *, ...);
 
 void test1() {