SymbolRewriter: allow rewriting with comdats
authorSaleem Abdulrasool <compnerd@compnerd.org>
Tue, 27 Jan 2015 22:57:39 +0000 (22:57 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Tue, 27 Jan 2015 22:57:39 +0000 (22:57 +0000)
COMDATs must be identically named to the symbol.  When support for COMDATs was
introduced, the symbol rewriter was not updated, resulting in rewriting failing
for symbols which were placed into COMDATs.  This corrects the behaviour and
adds test cases for this.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@227261 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Utils/SymbolRewriter.cpp
test/SymbolRewriter/rewrite.ll
test/SymbolRewriter/rewrite.map

index c93cdc4b52e21f8c0c828d4450ae052ebe2d5960..d36283ea3ae120b1b6208e755e8d7c0a9531667e 100644 (file)
@@ -79,6 +79,19 @@ static cl::list<std::string> RewriteMapFiles("rewrite-map-file",
 
 namespace llvm {
 namespace SymbolRewriter {
+void rewriteComdat(Module &M, GlobalObject *GO, const std::string &Source,
+                   const std::string &Target) {
+  if (Comdat *CD = GO->getComdat()) {
+    auto &Comdats = M.getComdatSymbolTable();
+
+    Comdat *C = M.getOrInsertComdat(Target);
+    C->setSelectionKind(CD->getSelectionKind());
+    GO->setComdat(C);
+
+    Comdats.erase(Comdats.find(Source));
+  }
+}
+
 template <RewriteDescriptor::Type DT, typename ValueType,
           ValueType *(llvm::Module::*Get)(StringRef) const>
 class ExplicitRewriteDescriptor : public RewriteDescriptor {
@@ -102,10 +115,14 @@ template <RewriteDescriptor::Type DT, typename ValueType,
 bool ExplicitRewriteDescriptor<DT, ValueType, Get>::performOnModule(Module &M) {
   bool Changed = false;
   if (ValueType *S = (M.*Get)(Source)) {
+    if (GlobalObject *GO = dyn_cast<GlobalObject>(S))
+      rewriteComdat(M, GO, Source, Target);
+
     if (Value *T = (M.*Get)(Target))
       S->setValueName(T->getValueName());
     else
       S->setName(Target);
+
     Changed = true;
   }
   return Changed;
@@ -148,6 +165,9 @@ performOnModule(Module &M) {
     if (C.getName() == Name)
       continue;
 
+    if (GlobalObject *GO = dyn_cast<GlobalObject>(&C))
+      rewriteComdat(M, GO, C.getName(), Name);
+
     if (Value *V = (M.*Get)(Name))
       C.setValueName(V->getValueName());
     else
index 716fff9f284cf25d2f66525c6575b0dcb329b48f..e8a0db6d606c013ae9aae77602e2ada68444553b 100644 (file)
@@ -28,12 +28,40 @@ entry:
   ret void
 }
 
+$source_comdat_function = comdat any
+define dllexport void @source_comdat_function() comdat($source_comdat_function) {
+entry:
+  ret void
+}
+
+$source_comdat_function_1 = comdat exactmatch
+define dllexport void @source_comdat_function_1() comdat($source_comdat_function_1) {
+entry:
+  ret void
+}
+
+$source_comdat_variable = comdat largest
+@source_comdat_variable = global i32 32, comdat($source_comdat_variable)
+
+$source_comdat_variable_1 = comdat noduplicates
+@source_comdat_variable_1 = global i32 64, comdat($source_comdat_variable_1)
+
+; CHECK: $target_comdat_function = comdat any
+; CHECK: $target_comdat_function_1 = comdat exactmatch
+; CHECK: $target_comdat_variable = comdat largest
+; CHECK: $target_comdat_variable_1 = comdat noduplicates
+
 ; CHECK: @target_variable = external global i32
 ; CHECK-NOT: @source_variable = external global i32
 ; CHECK: @target_pattern_variable = external global i32
 ; CHECK-NOT: @source_pattern_variable = external global i32
 ; CHECK: @target_pattern_multiple_variable_matches = external global i32
 ; CHECK-NOT: @source_pattern_multiple_variable_matches = external global i32
+; CHECK: @target_comdat_variable = global i32 32, comdat
+; CHECK-NOT: @source_comdat_variable = global i32 32, comdat
+; CHECK: @target_comdat_variable_1 = global i32 64, comdat
+; CHECK-NOT: @source_comdat_variable_1 = global i32 64, comdat
+
 ; CHECK: declare void @target_function()
 ; CHECK-NOT: declare void @source_function()
 ; CHECK: declare void @target_pattern_function()
@@ -57,3 +85,8 @@ entry:
 ; CHECK:   ret i32 %res
 ; CHECK: }
 
+; CHECK: define dllexport void @target_comdat_function() comdat
+; CHECK-NOT: define dllexport void @source_comdat_function() comdat
+; CHECK: define dllexport void @target_comdat_function_1() comdat
+; CHECK-NOT: define dllexport void @source_comdat_function_1() comdat
+
index ef6dfc8ca2b99d35fb76a62dba2555a951db0b7c..8094939d088d10b5b63608bb46d00d06b4abff97 100644 (file)
@@ -44,3 +44,23 @@ global alias: {
   target: _ZN1SD1Ev,
 }
 
+function: {
+  source: source_comdat_function,
+  target: target_comdat_function,
+}
+
+function: {
+  source: source_comdat_function_(.*),
+  transform: target_comdat_function_\1,
+}
+
+global variable: {
+  source: source_comdat_variable,
+  target: target_comdat_variable,
+}
+
+global variable: {
+  source: source_comdat_variable_(.*),
+  transform: target_comdat_variable_\1,
+}
+