Index: llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp +++ llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp @@ -956,6 +956,21 @@ FDecl = Function::Create(F->getFunctionType(), GlobalValue::ExternalLinkage, Name, &M); FDecl->setVisibility(Visibility); + + // Delete aliases pointing to this function, they'll be re-created in the + // merged output + SmallVector ToErase; + for (auto &U : F->uses()) { + if (auto *A = dyn_cast(U.getUser())) { + Function *AliasDecl = Function::Create( + F->getFunctionType(), GlobalValue::ExternalLinkage, "", &M); + AliasDecl->takeName(A); + A->replaceAllUsesWith(AliasDecl); + ToErase.push_back(A); + } + } + for (auto *A : ToErase) + A->eraseFromParent(); } else { // Function definition without type metadata, where some other translation // unit contained a declaration with type metadata. This normally happens @@ -1804,6 +1819,49 @@ allocateByteArrays(); + // Parse alias data to replace stand-in function declarations for aliases + // with an alias to the intended target. + if (ExportSummary) { + if (NamedMDNode *AliasesMD = M.getNamedMetadata("aliases")) { + for (auto AliasMD : AliasesMD->operands()) { + assert(AliasMD->getNumOperands() >= 4); + StringRef AliasName = + cast(AliasMD->getOperand(0))->getString(); + StringRef Aliasee = cast(AliasMD->getOperand(1))->getString(); + + if (!ExportedFunctions.count(Aliasee) || + ExportedFunctions[Aliasee].Linkage != CFL_Definition || + !M.getNamedAlias(Aliasee)) + continue; + + GlobalValue::VisibilityTypes Visibility = + static_cast( + cast(AliasMD->getOperand(2)) + ->getValue() + ->getUniqueInteger() + .getZExtValue()); + bool Weak = + static_cast(cast(AliasMD->getOperand(3)) + ->getValue() + ->getUniqueInteger() + .getZExtValue()); + + auto *Alias = GlobalAlias::create("", M.getNamedAlias(Aliasee)); + Alias->setVisibility(Visibility); + if (Weak) + Alias->setLinkage(GlobalValue::WeakAnyLinkage); + + if (auto *F = M.getFunction(AliasName)) { + Alias->takeName(F); + F->replaceAllUsesWith(Alias); + F->eraseFromParent(); + } else { + Alias->setName(AliasName); + } + } + } + } + return true; } Index: llvm/trunk/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ llvm/trunk/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp @@ -357,6 +357,31 @@ NMD->addOperand(MD); } + SmallVector FunctionAliases; + for (auto &A : M.aliases()) { + if (!isa(A.getAliasee())) + continue; + + auto *F = cast(A.getAliasee()); + auto &Ctx = MergedM->getContext(); + SmallVector Elts; + + Elts.push_back(MDString::get(Ctx, A.getName())); + Elts.push_back(MDString::get(Ctx, F->getName())); + Elts.push_back(ConstantAsMetadata::get( + llvm::ConstantInt::get(Type::getInt8Ty(Ctx), A.getVisibility()))); + Elts.push_back(ConstantAsMetadata::get( + llvm::ConstantInt::get(Type::getInt8Ty(Ctx), A.isWeakForLinker()))); + + FunctionAliases.push_back(MDTuple::get(Ctx, Elts)); + } + + if (!FunctionAliases.empty()) { + NamedMDNode *NMD = MergedM->getOrInsertNamedMetadata("aliases"); + for (auto MD : FunctionAliases) + NMD->addOperand(MD); + } + simplifyExternals(*MergedM); // FIXME: Try to re-use BSI and PFI from the original module here. Index: llvm/trunk/test/Transforms/LowerTypeTests/Inputs/import-alias.yaml =================================================================== --- llvm/trunk/test/Transforms/LowerTypeTests/Inputs/import-alias.yaml +++ llvm/trunk/test/Transforms/LowerTypeTests/Inputs/import-alias.yaml @@ -0,0 +1,11 @@ +--- +TypeIdMap: + typeid1: + TTRes: + Kind: AllOnes + SizeM1BitWidth: 7 +WithGlobalValueDeadStripping: false +CfiFunctionDefs: + - f +CfiFunctionDecls: +... Index: llvm/trunk/test/Transforms/LowerTypeTests/export-alias.ll =================================================================== --- llvm/trunk/test/Transforms/LowerTypeTests/export-alias.ll +++ llvm/trunk/test/Transforms/LowerTypeTests/export-alias.ll @@ -0,0 +1,21 @@ +; RUN: opt -S %s -lowertypetests -lowertypetests-summary-action=export -lowertypetests-read-summary=%S/Inputs/use-typeid1-typeid2.yaml | FileCheck %s +; +; CHECK: @alias1 = weak alias void (), void ()* @f +; CHECK: @alias2 = hidden alias void (), void ()* @f +; CHECK: declare !type !1 void @alias3() +; CHECK-NOT: @alias3 = alias + +target triple = "x86_64-unknown-linux" + +!cfi.functions = !{!0, !2, !3} +!aliases = !{!4, !5, !6} + +!0 = !{!"f", i8 0, !1} +!1 = !{i64 0, !"typeid1"} +!2 = !{!"alias1", i8 1, !1} +; alias2 not included here, this could happen if the only reference to alias2 +; is in a module compiled without cfi-icall +!3 = !{!"alias3", i8 1, !1} +!4 = !{!"alias1", !"f", i8 0, i8 1} +!5 = !{!"alias2", !"f", i8 1, i8 0} +!6 = !{!"alias3", !"not_present", i8 0, i8 0} Index: llvm/trunk/test/Transforms/LowerTypeTests/import-alias.ll =================================================================== --- llvm/trunk/test/Transforms/LowerTypeTests/import-alias.ll +++ llvm/trunk/test/Transforms/LowerTypeTests/import-alias.ll @@ -0,0 +1,30 @@ +; RUN: opt -S %s -lowertypetests -lowertypetests-summary-action=import -lowertypetests-read-summary=%S/Inputs/import-alias.yaml | FileCheck %s +; +; Check that the definitions for @f and @f_alias are removed from this module +; but @g_alias remains. +; +; CHECK: @g_alias = alias void (), void ()* @g +; CHECK: define hidden void @f.cfi +; CHECK: declare void @f() +; CHECK: declare void @f_alias() + +target triple = "x86_64-unknown-linux" + +@f_alias = alias void (), void ()* @f +@g_alias = alias void (), void ()* @g + +; Definition moved to the merged module +define void @f() { + ret void +} + +; Definition not moved to the merged module +define void @g() { + ret void +} + +define void @uses_aliases() { + call void @f_alias() + call void @g_alias() + ret void +} Index: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/function-alias.ll =================================================================== --- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/function-alias.ll +++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/function-alias.ll @@ -0,0 +1,25 @@ +; RUN: opt -thinlto-bc -o %t %s +; RUN: llvm-modextract -n 1 -o - %t | llvm-dis | FileCheck --check-prefix=CHECK1 %s + +target triple = "x86_64-unknown-linux-gnu" + +define hidden void @Func() !type !0 { + ret void +} + +; CHECK1: !aliases = !{![[A1:[0-9]+]], ![[A2:[0-9]+]], ![[A3:[0-9]+]]} + +; CHECK1: ![[A1]] = !{!"Alias", !"Func", i8 1, i8 0} +; CHECK1: ![[A2]] = !{!"Hidden_Alias", !"Func", i8 1, i8 0} +; CHECK1: ![[A3]] = !{!"Weak_Alias", !"Func", i8 0, i8 1} +@Alias = hidden alias void (), void ()* @Func +@Hidden_Alias = hidden alias void (), void ()* @Func +@Weak_Alias = weak alias void (), void ()* @Func + +@Variable = global i32 0 + +; Only generate summary alias information for aliases to functions +; CHECK1-NOT: Variable_Alias +@Variable_Alias = alias i32, i32* @Variable + +!0 = !{i64 0, !"_ZTSFvvE"}