Index: llvm/trunk/include/llvm/IR/GlobalAlias.h =================================================================== --- llvm/trunk/include/llvm/IR/GlobalAlias.h +++ llvm/trunk/include/llvm/IR/GlobalAlias.h @@ -58,10 +58,6 @@ // Linkage, Type, Parent and AddressSpace taken from the Aliasee. static GlobalAlias *create(const Twine &Name, GlobalValue *Aliasee); - void copyAttributesFrom(const GlobalValue *Src) { - GlobalValue::copyAttributesFrom(Src); - } - /// removeFromParent - This method unlinks 'this' from the containing module, /// but does not delete it. /// Index: llvm/trunk/include/llvm/IR/GlobalIFunc.h =================================================================== --- llvm/trunk/include/llvm/IR/GlobalIFunc.h +++ llvm/trunk/include/llvm/IR/GlobalIFunc.h @@ -46,10 +46,6 @@ LinkageTypes Linkage, const Twine &Name, Constant *Resolver, Module *Parent); - void copyAttributesFrom(const GlobalIFunc *Src) { - GlobalValue::copyAttributesFrom(Src); - } - /// This method unlinks 'this' from the containing module, but does not /// delete it. void removeFromParent(); Index: llvm/trunk/include/llvm/IR/GlobalIndirectSymbol.h =================================================================== --- llvm/trunk/include/llvm/IR/GlobalIndirectSymbol.h +++ llvm/trunk/include/llvm/IR/GlobalIndirectSymbol.h @@ -42,6 +42,10 @@ /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + void copyAttributesFrom(const GlobalValue *Src) { + GlobalValue::copyAttributesFrom(Src); + } + /// These methods set and retrieve indirect symbol. void setIndirectSymbol(Constant *Symbol) { setOperand(0, Symbol); Index: llvm/trunk/include/llvm/Transforms/Utils/ValueMapper.h =================================================================== --- llvm/trunk/include/llvm/Transforms/Utils/ValueMapper.h +++ llvm/trunk/include/llvm/Transforms/Utils/ValueMapper.h @@ -22,7 +22,7 @@ class Constant; class Function; -class GlobalAlias; +class GlobalIndirectSymbol; class GlobalVariable; class Instruction; class MDNode; @@ -120,7 +120,7 @@ /// instance: /// - \a scheduleMapGlobalInitializer() /// - \a scheduleMapAppendingVariable() -/// - \a scheduleMapGlobalAliasee() +/// - \a scheduleMapGlobalIndirectSymbol() /// - \a scheduleRemapFunction() /// /// Sometimes a callback needs a different mapping context. Such a context can @@ -180,8 +180,9 @@ bool IsOldCtorDtor, ArrayRef NewMembers, unsigned MappingContextID = 0); - void scheduleMapGlobalAliasee(GlobalAlias &GA, Constant &Aliasee, - unsigned MappingContextID = 0); + void scheduleMapGlobalIndirectSymbol(GlobalIndirectSymbol &GIS, + Constant &Target, + unsigned MappingContextID = 0); void scheduleRemapFunction(Function &F, unsigned MappingContextID = 0); }; Index: llvm/trunk/lib/Linker/IRMover.cpp =================================================================== --- llvm/trunk/lib/Linker/IRMover.cpp +++ llvm/trunk/lib/Linker/IRMover.cpp @@ -398,7 +398,7 @@ /// due to the use of Value handles which the Linker doesn't actually need, /// but this allows us to reuse the ValueMapper code. ValueToValueMapTy ValueMap; - ValueToValueMapTy AliasValueMap; + ValueToValueMapTy IndirectSymbolValueMap; DenseSet ValuesToLink; std::vector Worklist; @@ -437,7 +437,7 @@ /// Entry point for mapping values and alternate context for mapping aliases. ValueMapper Mapper; - unsigned AliasMCID; + unsigned IndirectSymbolMCID; /// Handles cloning of a global values from the source module into /// the destination module, including setting the attributes and visibility. @@ -480,13 +480,15 @@ /// /// Note this code may call the client-provided \p AddLazyFor. bool shouldLink(GlobalValue *DGV, GlobalValue &SGV); - Expected linkGlobalValueProto(GlobalValue *GV, bool ForAlias); + Expected linkGlobalValueProto(GlobalValue *GV, + bool ForIndirectSymbol); Error linkModuleFlagsMetadata(); void linkGlobalVariable(GlobalVariable &Dst, GlobalVariable &Src); Error linkFunctionBody(Function &Dst, Function &Src); - void linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src); + void linkIndirectSymbolBody(GlobalIndirectSymbol &Dst, + GlobalIndirectSymbol &Src); Error linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src); /// Replace all types in the source AttributeList with the @@ -497,7 +499,7 @@ /// into the destination module. GlobalVariable *copyGlobalVariableProto(const GlobalVariable *SGVar); Function *copyFunctionProto(const Function *SF); - GlobalValue *copyGlobalAliasProto(const GlobalAlias *SGA); + GlobalValue *copyGlobalIndirectSymbolProto(const GlobalIndirectSymbol *SGIS); /// Perform "replace all uses with" operations. These work items need to be /// performed as part of materialization, but we postpone them to happen after @@ -524,8 +526,8 @@ SharedMDs(SharedMDs), IsPerformingImport(IsPerformingImport), Mapper(ValueMap, RF_MoveDistinctMDs | RF_IgnoreMissingLocals, &TypeMap, &GValMaterializer), - AliasMCID(Mapper.registerAlternateMappingContext(AliasValueMap, - &LValMaterializer)) { + IndirectSymbolMCID(Mapper.registerAlternateMappingContext( + IndirectSymbolValueMap, &LValMaterializer)) { ValueMap.getMDMap() = std::move(SharedMDs); for (GlobalValue *GV : ValuesToLink) maybeAdd(GV); @@ -535,7 +537,7 @@ ~IRLinker() { SharedMDs = std::move(*ValueMap.getMDMap()); } Error run(); - Value *materialize(Value *V, bool ForAlias); + Value *materialize(Value *V, bool ForIndirectSymbol); }; } @@ -568,12 +570,12 @@ return TheIRLinker.materialize(SGV, true); } -Value *IRLinker::materialize(Value *V, bool ForAlias) { +Value *IRLinker::materialize(Value *V, bool ForIndirectSymbol) { auto *SGV = dyn_cast(V); if (!SGV) return nullptr; - Expected NewProto = linkGlobalValueProto(SGV, ForAlias); + Expected NewProto = linkGlobalValueProto(SGV, ForIndirectSymbol); if (!NewProto) { setError(NewProto.takeError()); return nullptr; @@ -593,23 +595,23 @@ if (V->hasInitializer() || V->hasAppendingLinkage()) return New; } else { - auto *A = cast(New); - if (A->getAliasee()) + auto *IS = cast(New); + if (IS->getIndirectSymbol()) return New; } - // When linking a global for an alias, it will always be linked. However we - // need to check if it was not already scheduled to satisfy a reference from a - // regular global value initializer. We know if it has been schedule if the - // "New" GlobalValue that is mapped here for the alias is the same as the one - // already mapped. If there is an entry in the ValueMap but the value is - // different, it means that the value already had a definition in the - // destination module (linkonce for instance), but we need a new definition - // for the alias ("New" will be different. - if (ForAlias && ValueMap.lookup(SGV) == New) + // When linking a global for an indirect symbol, it will always be linked. + // However we need to check if it was not already scheduled to satisfy a + // reference from a regular global value initializer. We know if it has been + // schedule if the "New" GlobalValue that is mapped here for the indirect + // symbol is the same as the one already mapped. If there is an entry in the + // ValueMap but the value is different, it means that the value already had a + // definition in the destination module (linkonce for instance), but we need a + // new definition for the indirect symbol ("New" will be different. + if (ForIndirectSymbol && ValueMap.lookup(SGV) == New) return New; - if (ForAlias || shouldLink(New, *SGV)) + if (ForIndirectSymbol || shouldLink(New, *SGV)) setError(linkGlobalValueBody(*New, *SGV)); return New; @@ -660,16 +662,24 @@ return F; } -/// Set up prototypes for any aliases that come over from the source module. -GlobalValue *IRLinker::copyGlobalAliasProto(const GlobalAlias *SGA) { +/// Set up prototypes for any indirect symbols that come over from the source +/// module. +GlobalValue * +IRLinker::copyGlobalIndirectSymbolProto(const GlobalIndirectSymbol *SGIS) { // If there is no linkage to be performed or we're linking from the source, // bring over SGA. - auto *Ty = TypeMap.get(SGA->getValueType()); - auto *GA = - GlobalAlias::create(Ty, SGA->getType()->getPointerAddressSpace(), - GlobalValue::ExternalLinkage, SGA->getName(), &DstM); - GA->copyAttributesFrom(SGA); - return GA; + auto *Ty = TypeMap.get(SGIS->getValueType()); + GlobalIndirectSymbol *GIS; + if (isa(SGIS)) + GIS = GlobalAlias::create(Ty, SGIS->getType()->getPointerAddressSpace(), + GlobalValue::ExternalLinkage, SGIS->getName(), + &DstM); + else + GIS = GlobalIFunc::create(Ty, SGIS->getType()->getPointerAddressSpace(), + GlobalValue::ExternalLinkage, SGIS->getName(), + nullptr, &DstM); + GIS->copyAttributesFrom(SGIS); + return GIS; } GlobalValue *IRLinker::copyGlobalValueProto(const GlobalValue *SGV, @@ -681,7 +691,7 @@ NewGV = copyFunctionProto(SF); } else { if (ForDefinition) - NewGV = copyGlobalAliasProto(cast(SGV)); + NewGV = copyGlobalIndirectSymbolProto(cast(SGV)); else if (SGV->getValueType()->isFunctionTy()) NewGV = Function::Create(cast(TypeMap.get(SGV->getValueType())), @@ -940,7 +950,7 @@ } Expected IRLinker::linkGlobalValueProto(GlobalValue *SGV, - bool ForAlias) { + bool ForIndirectSymbol) { GlobalValue *DGV = getLinkedToGlobal(SGV); bool ShouldLink = shouldLink(DGV, *SGV); @@ -951,12 +961,12 @@ if (I != ValueMap.end()) return cast(I->second); - I = AliasValueMap.find(SGV); - if (I != AliasValueMap.end()) + I = IndirectSymbolValueMap.find(SGV); + if (I != IndirectSymbolValueMap.end()) return cast(I->second); } - if (!ShouldLink && ForAlias) + if (!ShouldLink && ForIndirectSymbol) DGV = nullptr; // Handle the ultra special appending linkage case first. @@ -975,8 +985,8 @@ if (DoneLinkingBodies) return nullptr; - NewGV = copyGlobalValueProto(SGV, ShouldLink || ForAlias); - if (ShouldLink || !ForAlias) + NewGV = copyGlobalValueProto(SGV, ShouldLink || ForIndirectSymbol); + if (ShouldLink || !ForIndirectSymbol) forceRenaming(NewGV, SGV->getName()); } @@ -987,7 +997,7 @@ if (auto Remangled = Intrinsic::remangleIntrinsicFunction(F)) NewGV = Remangled.getValue(); - if (ShouldLink || ForAlias) { + if (ShouldLink || ForIndirectSymbol) { if (const Comdat *SC = SGV->getComdat()) { if (auto *GO = dyn_cast(NewGV)) { Comdat *DC = DstM.getOrInsertComdat(SC->getName()); @@ -997,7 +1007,7 @@ } } - if (!ShouldLink && ForAlias) + if (!ShouldLink && ForIndirectSymbol) NewGV->setLinkage(GlobalValue::InternalLinkage); Constant *C = NewGV; @@ -1060,8 +1070,10 @@ return Error::success(); } -void IRLinker::linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src) { - Mapper.scheduleMapGlobalAliasee(Dst, *Src.getAliasee(), AliasMCID); +void IRLinker::linkIndirectSymbolBody(GlobalIndirectSymbol &Dst, + GlobalIndirectSymbol &Src) { + Mapper.scheduleMapGlobalIndirectSymbol(Dst, *Src.getIndirectSymbol(), + IndirectSymbolMCID); } Error IRLinker::linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src) { @@ -1071,7 +1083,7 @@ linkGlobalVariable(cast(Dst), *GVar); return Error::success(); } - linkAliasBody(cast(Dst), cast(Src)); + linkIndirectSymbolBody(cast(Dst), cast(Src)); return Error::success(); } @@ -1411,7 +1423,7 @@ // Already mapped. if (ValueMap.find(GV) != ValueMap.end() || - AliasValueMap.find(GV) != AliasValueMap.end()) + IndirectSymbolValueMap.find(GV) != IndirectSymbolValueMap.end()) continue; assert(!GV->isDeclaration()); Index: llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp +++ llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp @@ -27,8 +27,8 @@ #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" -#include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalObject.h" +#include "llvm/IR/GlobalIndirectSymbol.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instruction.h" @@ -66,7 +66,7 @@ enum EntryKind { MapGlobalInit, MapAppendingVar, - MapGlobalAliasee, + MapGlobalIndirectSymbol, RemapFunction }; struct GVInitTy { @@ -77,9 +77,9 @@ GlobalVariable *GV; Constant *InitPrefix; }; - struct GlobalAliaseeTy { - GlobalAlias *GA; - Constant *Aliasee; + struct GlobalIndirectSymbolTy { + GlobalIndirectSymbol *GIS; + Constant *Target; }; unsigned Kind : 2; @@ -89,7 +89,7 @@ union { GVInitTy GVInit; AppendingGVTy AppendingGV; - GlobalAliaseeTy GlobalAliasee; + GlobalIndirectSymbolTy GlobalIndirectSymbol; Function *RemapF; } Data; }; @@ -161,8 +161,8 @@ bool IsOldCtorDtor, ArrayRef NewMembers, unsigned MCID); - void scheduleMapGlobalAliasee(GlobalAlias &GA, Constant &Aliasee, - unsigned MCID); + void scheduleMapGlobalIndirectSymbol(GlobalIndirectSymbol &GIS, Constant &Target, + unsigned MCID); void scheduleRemapFunction(Function &F, unsigned MCID); void flush(); @@ -172,7 +172,7 @@ void mapAppendingVariable(GlobalVariable &GV, Constant *InitPrefix, bool IsOldCtorDtor, ArrayRef NewMembers); - void mapGlobalAliasee(GlobalAlias &GA, Constant &Aliasee); + void mapGlobalIndirectSymbol(GlobalIndirectSymbol &GIS, Constant &Target); void remapFunction(Function &F, ValueToValueMapTy &VM); ValueToValueMapTy &getVM() { return *MCs[CurrentMCID].VM; } @@ -846,9 +846,9 @@ AppendingInits.resize(PrefixSize); break; } - case WorklistEntry::MapGlobalAliasee: - E.Data.GlobalAliasee.GA->setAliasee( - mapConstant(E.Data.GlobalAliasee.Aliasee)); + case WorklistEntry::MapGlobalIndirectSymbol: + E.Data.GlobalIndirectSymbol.GIS->setIndirectSymbol( + mapConstant(E.Data.GlobalIndirectSymbol.Target)); break; case WorklistEntry::RemapFunction: remapFunction(*E.Data.RemapF); @@ -1041,16 +1041,16 @@ AppendingInits.append(NewMembers.begin(), NewMembers.end()); } -void Mapper::scheduleMapGlobalAliasee(GlobalAlias &GA, Constant &Aliasee, - unsigned MCID) { - assert(AlreadyScheduled.insert(&GA).second && "Should not reschedule"); +void Mapper::scheduleMapGlobalIndirectSymbol(GlobalIndirectSymbol &GIS, + Constant &Target, unsigned MCID) { + assert(AlreadyScheduled.insert(&GIS).second && "Should not reschedule"); assert(MCID < MCs.size() && "Invalid mapping context"); WorklistEntry WE; - WE.Kind = WorklistEntry::MapGlobalAliasee; + WE.Kind = WorklistEntry::MapGlobalIndirectSymbol; WE.MCID = MCID; - WE.Data.GlobalAliasee.GA = &GA; - WE.Data.GlobalAliasee.Aliasee = &Aliasee; + WE.Data.GlobalIndirectSymbol.GIS = &GIS; + WE.Data.GlobalIndirectSymbol.Target = &Target; Worklist.push_back(WE); } @@ -1147,9 +1147,10 @@ GV, InitPrefix, IsOldCtorDtor, NewMembers, MCID); } -void ValueMapper::scheduleMapGlobalAliasee(GlobalAlias &GA, Constant &Aliasee, - unsigned MCID) { - getAsMapper(pImpl)->scheduleMapGlobalAliasee(GA, Aliasee, MCID); +void ValueMapper::scheduleMapGlobalIndirectSymbol(GlobalIndirectSymbol &GIS, + Constant &Target, + unsigned MCID) { + getAsMapper(pImpl)->scheduleMapGlobalIndirectSymbol(GIS, Target, MCID); } void ValueMapper::scheduleRemapFunction(Function &F, unsigned MCID) { Index: llvm/trunk/test/LTO/Resolution/X86/Inputs/ifunc2.ll =================================================================== --- llvm/trunk/test/LTO/Resolution/X86/Inputs/ifunc2.ll +++ llvm/trunk/test/LTO/Resolution/X86/Inputs/ifunc2.ll @@ -0,0 +1,6 @@ +target datalayout = "e-p:64:64" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @foo_resolver() { + ret i32 2 +} Index: llvm/trunk/test/LTO/Resolution/X86/ifunc2.ll =================================================================== --- llvm/trunk/test/LTO/Resolution/X86/ifunc2.ll +++ llvm/trunk/test/LTO/Resolution/X86/ifunc2.ll @@ -0,0 +1,19 @@ +; RUN: llvm-as -o %t1.o %s +; RUN: llvm-as -o %t2.o %S/Inputs/ifunc2.ll +; RUN: llvm-lto2 run %t1.o %t2.o -r %t1.o,foo,p -r %t1.o,foo_resolver, -r %t2.o,foo_resolver,p -save-temps -o %t3.o +; RUN: llvm-dis -o - %t3.o.0.0.preopt.bc | FileCheck %s + +target datalayout = "e-p:64:64" +target triple = "x86_64-unknown-linux-gnu" + +; CHECK: @foo = ifunc i32 (), i32 ()* @foo_resolver.2 +@foo = ifunc i32 (), i32 ()* @foo_resolver + +; CHECK: define internal i32 @foo_resolver.2() { +; CHECK-NEXT: ret i32 1 +define weak i32 @foo_resolver() { + ret i32 1 +} + +; CHECK: define i32 @foo_resolver() { +; CHECK-NEXT: ret i32 2