]> granicus.if.org Git - llvm/commitdiff
LowerTypeTests: Drop function type metadata only if we're going to replace it.
authorPeter Collingbourne <peter@pcc.me.uk>
Thu, 20 Jul 2017 18:02:05 +0000 (18:02 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Thu, 20 Jul 2017 18:02:05 +0000 (18:02 +0000)
Previously we were (mis)handling jump table members with a prevailing
definition in a full LTO module and a non-prevailing definition in a
ThinLTO module by dropping type metadata on those functions entirely,
which would cause type tests involving such functions to fail.

This patch causes us to drop metadata only if we are about to replace
it with metadata from cfi.functions.

We also want to replace metadata for available_externally functions,
which can arise in the opposite scenario (prevailing ThinLTO
definition, non-prevailing full LTO definition). The simplest way
to handle that is to remove the definition; there's little value in
keeping it around at this point (i.e. after most optimization passes
have already run) and later code will try to use the function's linkage
to create an alias, which would result in invalid IR if the function
is available_externally.

Fixes PR33832.

Differential Revision: https://reviews.llvm.org/D35604

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

lib/Transforms/IPO/LowerTypeTests.cpp
test/Transforms/LowerTypeTests/export-icall.ll

index 693df5e7ba925d258fad49a918cc49e7bd672771..cdda8a68ecc9872c703eca4ac51fbea972e93277 100644 (file)
@@ -1512,14 +1512,27 @@ bool LowerTypeTestsModule::lower() {
               FunctionType::get(Type::getVoidTy(M.getContext()), false),
               GlobalVariable::ExternalLinkage, FunctionName, &M);
 
-        if (Linkage == CFL_Definition)
-          F->eraseMetadata(LLVMContext::MD_type);
+        // If the function is available_externally, remove its definition so
+        // that it is handled the same way as a declaration. Later we will try
+        // to create an alias using this function's linkage, which will fail if
+        // the linkage is available_externally. This will also result in us
+        // following the code path below to replace the type metadata.
+        if (F->hasAvailableExternallyLinkage()) {
+          F->setLinkage(GlobalValue::ExternalLinkage);
+          F->deleteBody();
+          F->setComdat(nullptr);
+          F->clearMetadata();
+        }
 
+        // If the function in the full LTO module is a declaration, replace its
+        // type metadata with the type metadata we found in cfi.functions. That
+        // metadata is presumed to be more accurate than the metadata attached
+        // to the declaration.
         if (F->isDeclaration()) {
           if (Linkage == CFL_WeakDeclaration)
             F->setLinkage(GlobalValue::ExternalWeakLinkage);
 
-          SmallVector<MDNode *, 2> Types;
+          F->eraseMetadata(LLVMContext::MD_type);
           for (unsigned I = 2; I < FuncMD->getNumOperands(); ++I)
             F->addMetadata(LLVMContext::MD_type,
                            *cast<MDNode>(FuncMD->getOperand(I).get()));
index ad36048993067cc2bdc457d37914e54a8dce0713..0a1af66883c4ebd12a8d64fdb29d90240b47c645 100644 (file)
@@ -9,8 +9,14 @@ define void @h(i8 %x) !type !2 {
 }
 
 declare !type !8 void @f(i32 %x)
+define available_externally void @f2(i32 %x) !type !8 {
+  ret void
+}
+define void @f3(i32 %x) !type !8 {
+  ret void
+}
 
-!cfi.functions = !{!0, !1, !3, !4, !5, !6}
+!cfi.functions = !{!0, !1, !3, !9, !10, !4, !5, !6}
 
 ; declaration of @h with a different type is ignored
 !0 = !{!"h", i8 1, !7}
@@ -19,8 +25,10 @@ declare !type !8 void @f(i32 %x)
 !1 = !{!"h", i8 2, !8}
 !2 = !{i64 0, !"typeid1"}
 
-; definition of @f replaces types on the IR declaration above
+; definitions of @f and @f2 replace types on the IR declarations above
 !3 = !{!"f", i8 0, !2}
+!9 = !{!"f2", i8 0, !2}
+!10 = !{!"f3", i8 0, !2}
 !4 = !{!"external", i8 1, !2}
 !5 = !{!"external_weak", i8 2, !2}
 !6 = !{!"g", i8 0, !7}
@@ -30,10 +38,11 @@ declare !type !8 void @f(i32 %x)
 
 ; CHECK-DAG: @__typeid_typeid1_global_addr = hidden alias i8, bitcast (void ()* [[JT1:.*]] to i8*)
 ; CHECK-DAG: @__typeid_typeid1_align = hidden alias i8, inttoptr (i8 3 to i8*)
-; CHECK-DAG: @__typeid_typeid1_size_m1 = hidden alias i8, inttoptr (i64 3 to i8*)
+; CHECK-DAG: @__typeid_typeid1_size_m1 = hidden alias i8, inttoptr (i64 4 to i8*)
 
 ; CHECK-DAG: @h                    = alias void (i8), bitcast (void ()* [[JT1]] to void (i8)*)
 ; CHECK-DAG: @f                    = alias void (i32), {{.*}}getelementptr {{.*}}void ()* [[JT1]]
+; CHECK-DAG: @f2                   = alias void (i32), {{.*}}getelementptr {{.*}}void ()* [[JT1]]
 ; CHECK-DAG: @external.cfi_jt      = hidden alias void (), {{.*}}getelementptr {{.*}}void ()* [[JT1]]
 ; CHECK-DAG: @external_weak.cfi_jt = hidden alias void (), {{.*}}getelementptr {{.*}}void ()* [[JT1]]
 
@@ -45,6 +54,9 @@ declare !type !8 void @f(i32 %x)
 ; CHECK-DAG: declare !type !{{.*}} void @external()
 ; CHECK-DAG: declare !type !{{.*}} void @external_weak()
 ; CHECK-DAG: declare !type !{{.*}} void @f.cfi(i32)
+; CHECK-DAG: declare !type !{{.*}} void @f2.cfi(i32)
+; CHECK-DAG: define void @f3(i32 {{.*}}) !type !3
+; CHECK-DAG: !3 = !{i64 0, !"typeid3"}
 ; CHECK-DAG: declare !type !{{.*}} void @g.cfi()
 
 
@@ -62,6 +74,7 @@ declare !type !8 void @f(i32 %x)
 
 ; SUMMARY:      CfiFunctionDefs:
 ; SUMMARY-NEXT:   - f
+; SUMMARY-NEXT:   - f2
 ; SUMMARY-NEXT:   - g
 ; SUMMARY-NEXT:   - h
 ; SUMMARY-NEXT: CfiFunctionDecls: