Index: lib/Transforms/IPO/LowerTypeTests.cpp =================================================================== --- lib/Transforms/IPO/LowerTypeTests.cpp +++ lib/Transforms/IPO/LowerTypeTests.cpp @@ -956,6 +956,18 @@ 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 + for (auto &U : F->uses()) { + if (isa(U.getUser())) { + GlobalAlias *A = cast(U.getUser()); + StringRef AliasName = A->getName(); + A->eraseFromParent(); + Function::Create(F->getFunctionType(), GlobalValue::ExternalLinkage, + AliasName, &M); + } + } } else { // Function definition without type metadata, where some other translation // unit contained a declaration with type metadata. This normally happens @@ -1673,6 +1685,48 @@ } } + // Parse alias data to 1) remove aliases from the list of exported functions + // and 2) save which aliases should be created after the jump table functions + // they point to are created. + struct AliasInfo { + StringRef AliasName; + StringRef Aliasee; + GlobalValue::VisibilityTypes Visibility; + bool Weak; + }; + std::vector Aliases; + 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(AliasName) || + !ExportedFunctions.count(Aliasee) || + ExportedFunctions[Aliasee].Linkage != CFL_Definition) + continue; + + ExportedFunctions.erase(AliasName); + M.getFunction(AliasName)->removeFromParent(); + + GlobalValue::VisibilityTypes Visibility = + static_cast( + cast(AliasMD->getOperand(2)) + ->getValue() + ->getUniqueInteger() + .getZExtValue()); + bool Weak = + static_cast(cast(AliasMD->getOperand(3)) + ->getValue() + ->getUniqueInteger() + .getZExtValue()); + + Aliases.push_back({AliasName, Aliasee, Visibility, Weak}); + } + } + } + for (GlobalObject &GO : M.global_objects()) { if (isa(GO) && GO.isDeclarationForLinker()) continue; @@ -1804,6 +1858,18 @@ allocateByteArrays(); + std::sort(Aliases.begin(), Aliases.end(), [](AliasInfo A1, AliasInfo A2) { + return A1.AliasName.equals_lower(A2.AliasName); + }); + for (auto &A : Aliases) { + if (!M.getNamedAlias(A.Aliasee)) + continue; + auto *Alias = GlobalAlias::create(A.AliasName, M.getNamedAlias(A.Aliasee)); + Alias->setVisibility(A.Visibility); + if (A.Weak) + Alias->setLinkage(GlobalValue::WeakAnyLinkage); + } + return true; } Index: lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp =================================================================== --- lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ 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: test/Transforms/LowerTypeTests/Inputs/import-alias.yaml =================================================================== --- /dev/null +++ test/Transforms/LowerTypeTests/Inputs/import-alias.yaml @@ -0,0 +1,11 @@ +--- +TypeIdMap: + typeid1: + TTRes: + Kind: AllOnes + SizeM1BitWidth: 7 +WithGlobalValueDeadStripping: false +CfiFunctionDefs: + - f +CfiFunctionDecls: +... Index: test/Transforms/LowerTypeTests/export-alias.ll =================================================================== --- /dev/null +++ test/Transforms/LowerTypeTests/export-alias.ll @@ -0,0 +1,16 @@ +; 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 + +target triple = "x86_64-unknown-linux" + +!cfi.functions = !{!0, !2, !3} +!aliases = !{!4, !5} + +!0 = !{!"f", i8 0, !1} +!1 = !{i64 0, !"typeid1"} +!2 = !{!"alias1", i8 1, !1} +!3 = !{!"alias2", i8 1, !1} +!4 = !{!"alias1", !"f", i8 0, i8 1} +!5 = !{!"alias2", !"f", i8 1, i8 0} Index: test/Transforms/LowerTypeTests/import-alias.ll =================================================================== --- /dev/null +++ test/Transforms/LowerTypeTests/import-alias.ll @@ -0,0 +1,13 @@ +; RUN: opt -S %s -lowertypetests -lowertypetests-summary-action=import -lowertypetests-read-summary=%S/Inputs/import-alias.yaml | FileCheck %s +; +; CHECK: define hidden void @f.cfi +; CHECK: declare void @f() +; CHECK: declare void @alias() + +target triple = "x86_64-unknown-linux" + +@alias = alias void (), void ()* @f + +define void @f() { + ret void +}