Index: include/llvm/IR/FunctionInfo.h =================================================================== --- include/llvm/IR/FunctionInfo.h +++ include/llvm/IR/FunctionInfo.h @@ -223,6 +223,22 @@ return ModulePathStringTable.insert(std::make_pair(ModPath, ModId)) .first->first(); } + + /// Check if the given Module has any functions available for exporting + /// in the index. + bool hasExportedFunctions(const Module *M) { + for (const Function &SF : *M) { + std::string FuncName = SF.getName().str(); + if (SF.hasLocalLinkage()) + FuncName = getGlobalNameForLocal(SF.getName(), + getModuleId(M->getModuleIdentifier())); + for (const auto &FI : getFunctionInfoList(FuncName)) { + if (M->getModuleIdentifier() == FI->functionSummary()->modulePath()) + return true; + } + } + return false; + } }; } // End llvm namespace Index: include/llvm/Linker/Linker.h =================================================================== --- include/llvm/Linker/Linker.h +++ include/llvm/Linker/Linker.h @@ -14,6 +14,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/FunctionInfo.h" namespace llvm { class Module; @@ -76,8 +77,13 @@ /// \brief Link \p Src into the composite. The source is destroyed. /// Passing OverrideSymbols as true will have symbols from Src /// shadow those in the Dest. + /// For ThinLTO function importing/exporting the \p FunctionInfoIndex + /// is passed. If a \p FuncToImport is provided, only that single + /// function is imported from the source module. /// Returns true on error. - bool linkInModule(Module *Src, unsigned Flags = Flags::None); + bool linkInModule(Module *Src, unsigned Flags = Flags::None, + FunctionInfoIndex *Index = nullptr, + Function *FuncToImport = nullptr); /// \brief Set the composite to the passed-in module. void setModule(Module *Dst); Index: lib/Linker/LinkModules.cpp =================================================================== --- lib/Linker/LinkModules.cpp +++ lib/Linker/LinkModules.cpp @@ -369,12 +369,17 @@ TypeMapTy &TypeMap; Module *DstM; std::vector &LazilyLinkGlobalValues; + ModuleLinker *ModLinker; public: - ValueMaterializerTy(TypeMapTy &TypeMap, Module *DstM, - std::vector &LazilyLinkGlobalValues) - : ValueMaterializer(), TypeMap(TypeMap), DstM(DstM), - LazilyLinkGlobalValues(LazilyLinkGlobalValues) {} + ValueMaterializerTy(TypeMapTy &TypeMap, Module *DstM, + std::vector &LazilyLinkGlobalValues, + ModuleLinker *ModLinker) + : ValueMaterializer(), + TypeMap(TypeMap), + DstM(DstM), + LazilyLinkGlobalValues(LazilyLinkGlobalValues), + ModLinker(ModLinker) {} Value *materializeValueFor(Value *V) override; }; @@ -427,12 +432,42 @@ /// For symbol clashes, prefer those from Src. unsigned Flags; + /// Function index passed into ModuleLinker for using in function + /// importing/exporting handling. + FunctionInfoIndex *ImportIndex; + + /// Function to import from source module, all other functions are + /// imported as declarations instead of definitions. + Function *ImportFunction; + + /// Set to true if the given FunctionInfoIndex contains any functions + /// from this source module, in which case we must conservatively assume + /// that any of its functions may be imported into another module + /// as part of a different backend compilation process. + bool HasExportedFunctions; + public: - ModuleLinker(Module *dstM, Linker::IdentifiedStructTypeSet &Set, Module *srcM, - DiagnosticHandlerFunction DiagnosticHandler, unsigned Flags) - : DstM(dstM), SrcM(srcM), TypeMap(Set), - ValMaterializer(TypeMap, DstM, LazilyLinkGlobalValues), - DiagnosticHandler(DiagnosticHandler), Flags(Flags) {} + ModuleLinker(Module *dstM, Linker::IdentifiedStructTypeSet &Set, Module *srcM, + DiagnosticHandlerFunction DiagnosticHandler, unsigned Flags, + FunctionInfoIndex *Index = nullptr, + Function *FuncToImport = nullptr) + : DstM(dstM), + SrcM(srcM), + TypeMap(Set), + ValMaterializer(TypeMap, DstM, LazilyLinkGlobalValues, this), + DiagnosticHandler(DiagnosticHandler), + Flags(Flags), + ImportIndex(Index), + ImportFunction(FuncToImport) { + assert(ImportIndex || + !ImportFunction && "Expect a FunctionInfoIndex when importing"); + // If we have a FunctionInfoIndex but no function to import, + // then this is the primary module being compiled in a ThinLTO + // backend compilation, and we need to see if it has functions that + // may be exported to another backend compilation. + if (ImportIndex && !ImportFunction) + HasExportedFunctions = ImportIndex->hasExportedFunctions(SrcM); + } bool run(); @@ -442,6 +477,14 @@ return Flags & Linker::InternalizeLinkedSymbols; } + /// Handles cloning of a global values from the source module into + /// the destination module, including setting the attributes and visibility. + GlobalValue *copyGlobalValueProto(TypeMapTy &TypeMap, const GlobalValue *SGV, + const GlobalValue *DGV = nullptr); + + /// Check if we should promote the given local value to global scope. + bool doPromoteLocalToGlobal(const GlobalValue *SGV); + private: bool shouldLinkFromSource(bool &LinkFromSrc, const GlobalValue &Dest, const GlobalValue &Src); @@ -508,6 +551,42 @@ void linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src); bool linkGlobalValueBody(GlobalValue &Src); + /// Functions that take care of cloning a specific global value type + /// into the destination module. + GlobalVariable *copyGlobalVariableProto(TypeMapTy &TypeMap, + const GlobalVariable *SGVar); + Function *copyFunctionProto(TypeMapTy &TypeMap, const Function *SF); + GlobalValue *copyGlobalAliasProto(TypeMapTy &TypeMap, const GlobalAlias *SGA); + + /// Helper methods to check if we are importing from or potentially + /// exporting from the current source module. + bool isPerformingImport() { return ImportFunction != nullptr; } + bool isModuleExporting() { return HasExportedFunctions; } + + /// If we are importing from the source module, checks if we should + /// import SGV as a definition, otherwise import as a declaration. + bool doImportAsDefinition(const GlobalValue *SGV); + + /// Get the name for SGV that should be used in the linked destination + /// module. Specifically, this handles the case where we need to rename + /// a local that is being promoted to global scope. + StringRef getName(const GlobalValue *SGV); + + /// Get the new linkage for SGV that should be used in the linked destination + /// module. Specifically, for ThinLTO importing or exporting it may need + /// to be adjusted. + GlobalValue::LinkageTypes getLinkage(const GlobalValue *SGV); + + /// Copies the necessary global value attributes and name from the source + /// to the newly cloned global value. + void copyGVAttributes(GlobalValue *NewGV, const GlobalValue *SrcGV); + + /// Updates the visibility for the new global cloned from the source + /// and, if applicable, linked with an existing destination global. + /// Handles visibility change required for promoted locals. + void setVisibility(GlobalValue *NewGV, const GlobalValue *SGV, + const GlobalValue *DGV = nullptr); + void linkNamedMDNodes(); void stripReplacedSubprograms(); }; @@ -519,6 +598,9 @@ static void forceRenaming(GlobalValue *GV, StringRef Name) { // If the global doesn't force its name or if it already has the right name, // there is nothing for us to do. + // Note that any required local to global promotion should already be done, + // so promoted locals will not skip this handling as their linkage is no + // longer local. if (GV->hasLocalLinkage() || GV->getName() == Name) return; @@ -536,9 +618,23 @@ /// copy additional attributes (those not needed to construct a GlobalValue) /// from the SrcGV to the DestGV. -static void copyGVAttributes(GlobalValue *DestGV, const GlobalValue *SrcGV) { - DestGV->copyAttributesFrom(SrcGV); - forceRenaming(DestGV, SrcGV->getName()); +void ModuleLinker::copyGVAttributes(GlobalValue *NewGV, + const GlobalValue *SrcGV) { + auto *GA = dyn_cast(SrcGV); + // Check for the special case of converting an alias (definition) to a + // non-alias (declaration). This can happen when we are importing and + // encounter a weak_any alias (weak_any defs may not be imported, see + // comments in ModuleLinker::getLinkage) or an alias whose base object is + // being imported as a declaration. In that case copy the attributes from the + // base object. + if (GA && !dyn_cast(NewGV)) { + assert(isPerformingImport() && + (GA->hasWeakAnyLinkage() || + !doImportAsDefinition(GA->getBaseObject()))); + NewGV->copyAttributesFrom(GA->getBaseObject()); + } else + NewGV->copyAttributesFrom(SrcGV); + forceRenaming(NewGV, getName(SrcGV)); } static bool isLessConstraining(GlobalValue::VisibilityTypes a, @@ -554,17 +650,161 @@ return false; } +bool ModuleLinker::doImportAsDefinition(const GlobalValue *SGV) { + if (!isPerformingImport()) return false; + // Always import GlobalVariable definitions. The linkage changes + // described in ModuleLinker::getLinkage ensure the correct behavior (e.g. + // global variables with external linkage are transformed to + // available_externally defintions, which are ultimately turned into + // declaratios after the EliminateAvailableExternally pass). + if (dyn_cast(SGV) && !SGV->isDeclaration()) return true; + // Only import the function requested for importing. + auto *SF = dyn_cast(SGV); + if (SF && SF == ImportFunction) return true; + // Otherwise no. + return false; +} + +bool ModuleLinker::doPromoteLocalToGlobal(const GlobalValue *SGV) { + assert(SGV->hasLocalLinkage()); + // Both the imported references and the original local variable must + // be promoted. + if (!isPerformingImport() && !isModuleExporting()) return false; + + // Local const variables never need to be promoted unless they are address + // taken. The imported uses can simply use the clone created in this module. + // For now we are conservative in determining which variables are not + // address taken by checking the unnamed addr flag. To be more aggressive, + // the address taken information must be checked earlier during parsing + // of the module and recorded in the function index for use when importing + // from that module. + auto *GVar = dyn_cast(SGV); + if (GVar && GVar->isConstant() && GVar->hasUnnamedAddr()) return false; + + // Eventually we only need to promote functions in the exporting module that + // are referenced by a potentially exported function (i.e. one that is in the + // function index). + return true; +} + +StringRef ModuleLinker::getName(const GlobalValue *SGV) { + // For locals that must be promoted to global scope, ensure that + // the promoted name uniquely identifies the copy in the original module, + // using the ID assigned during combined index creation. When importing, + // we rename all locals (not just those that are promoted) in order to + // avoid naming conflicts between locals imported from different modules. + if (SGV->hasLocalLinkage() && + (doPromoteLocalToGlobal(SGV) || isPerformingImport())) + return FunctionInfoIndex::getGlobalNameForLocal( + SGV->getName(), + ImportIndex->getModuleId(SGV->getParent()->getModuleIdentifier())); + return SGV->getName(); +} + +GlobalValue::LinkageTypes ModuleLinker::getLinkage(const GlobalValue *SGV) { + // Any local variable that is referenced by an exported function needs + // to be promoted to global scope. Since we don't currently know which + // functions reference which local variables/functions, we must treat + // all as potentially exported if this module is exporting anything. + if (isModuleExporting()) { + if (SGV->hasLocalLinkage() && doPromoteLocalToGlobal(SGV)) + return GlobalValue::ExternalLinkage; + return SGV->getLinkage(); + } + + // Otherwise, if we aren't importing, no linkage change is needed. + if (!isPerformingImport()) return SGV->getLinkage(); + + switch (SGV->getLinkage()) { + case GlobalValue::ExternalLinkage: + // External defnitions are converted to available_externally + // definitions upon import, so that they are available for inlining + // and/or optimization, but are turned into declarations later + // during the EliminateAvailableExternally pass. + if (doImportAsDefinition(SGV)) + return GlobalValue::AvailableExternallyLinkage; + // An imported external declaration stays external. + return SGV->getLinkage(); + + case GlobalValue::AvailableExternallyLinkage: + // An imported available_externally definition converts + // to external if imported as a declaration. + if (!doImportAsDefinition(SGV)) return GlobalValue::ExternalLinkage; + // An imported available_externally declaration stays that way. + return SGV->getLinkage(); + + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + // These both stay the same when importing the definition. + // The ThinLTO pass will eventually force-import their definitions. + return SGV->getLinkage(); + + case GlobalValue::WeakAnyLinkage: + // Can't import weak_any definitions correctly, or we might change the + // program semantics, since the linker will pick the first weak_any + // definition and importing would change the order they are seen by the + // linker. The module linking caller needs to enforce this. + assert(!doImportAsDefinition(SGV)); + // If imported as a declaration, it becomes external_weak. + return GlobalValue::ExternalWeakLinkage; + + case GlobalValue::WeakODRLinkage: + // For weak_odr linkage, there is a guarantee that all copies will be + // equivalent, so the issue described above for weak_any does not exist, + // and the definition can be imported. It can be treated similarly + // to an imported externally visible global value. + if (doImportAsDefinition(SGV)) + return GlobalValue::AvailableExternallyLinkage; + else + return GlobalValue::ExternalLinkage; + + case GlobalValue::AppendingLinkage: + // It would be incorrect to import an appending linkage variable, + // since it would cause global constructors/destructors to be + // executed multiple times. This should have already been handled + // by linkGlobalValueProto. + assert(false && "Cannot import appending linkage variable"); + + case GlobalValue::InternalLinkage: + case GlobalValue::PrivateLinkage: + // If we are promoting the local to global scope, it is handled + // similarly to a normal externally visible global. + if (doPromoteLocalToGlobal(SGV)) { + if (doImportAsDefinition(SGV)) + return GlobalValue::AvailableExternallyLinkage; + else + return GlobalValue::ExternalLinkage; + } + // A non-promoted imported local definition stays local. + // The ThinLTO pass will eventually force-import their definitions. + return SGV->getLinkage(); + + case GlobalValue::ExternalWeakLinkage: + // External weak doesn't apply to definitions, must be a declaration. + assert(!doImportAsDefinition(SGV)); + // Linkage stays external_weak. + return SGV->getLinkage(); + + case GlobalValue::CommonLinkage: + // Linkage stays common on definitions. + // The ThinLTO pass will eventually force-import their definitions. + return SGV->getLinkage(); + } + + llvm_unreachable("unknown linkage type"); +} + /// Loop through the global variables in the src module and merge them into the /// dest module. -static GlobalVariable *copyGlobalVariableProto(TypeMapTy &TypeMap, Module &DstM, - const GlobalVariable *SGVar) { +GlobalVariable *ModuleLinker::copyGlobalVariableProto( + TypeMapTy &TypeMap, const GlobalVariable *SGVar) { // No linking to be performed or linking from the source: simply create an // identical version of the symbol over in the dest module... the // initializer will be filled in later by LinkGlobalInits. GlobalVariable *NewDGV = new GlobalVariable( - DstM, TypeMap.get(SGVar->getType()->getElementType()), - SGVar->isConstant(), SGVar->getLinkage(), /*init*/ nullptr, - SGVar->getName(), /*insertbefore*/ nullptr, SGVar->getThreadLocalMode(), + *DstM, TypeMap.get(SGVar->getType()->getElementType()), + SGVar->isConstant(), getLinkage(SGVar), /*init*/ nullptr, getName(SGVar), + /*insertbefore*/ nullptr, SGVar->getThreadLocalMode(), SGVar->getType()->getAddressSpace()); return NewDGV; @@ -572,34 +812,75 @@ /// Link the function in the source module into the destination module if /// needed, setting up mapping information. -static Function *copyFunctionProto(TypeMapTy &TypeMap, Module &DstM, - const Function *SF) { +Function *ModuleLinker::copyFunctionProto(TypeMapTy &TypeMap, + const Function *SF) { // If there is no linkage to be performed or we are linking from the source, // bring SF over. - return Function::Create(TypeMap.get(SF->getFunctionType()), SF->getLinkage(), - SF->getName(), &DstM); + return Function::Create(TypeMap.get(SF->getFunctionType()), getLinkage(SF), + getName(SF), DstM); } /// Set up prototypes for any aliases that come over from the source module. -static GlobalAlias *copyGlobalAliasProto(TypeMapTy &TypeMap, Module &DstM, - const GlobalAlias *SGA) { +GlobalValue *ModuleLinker::copyGlobalAliasProto(TypeMapTy &TypeMap, + const GlobalAlias *SGA) { + // If we are importing and encounter a weak_any alias, or an alias to + // an object being imported as a declaration, we must import the alias + // as a declaration as well, which involves converting it to a non-alias. + // See comments in ModuleLinker::getLinkage for why we cannot import + // weak_any defintions. + if (isPerformingImport() && (SGA->hasWeakAnyLinkage() || + !doImportAsDefinition(SGA->getBaseObject()))) { + // Need to convert to declaration. All aliases must be definitions. + const GlobalValue *GVal = SGA->getBaseObject(); + GlobalValue *NewGV; + if (auto *GVar = dyn_cast(GVal)) + NewGV = copyGlobalVariableProto(TypeMap, GVar); + else { + auto *F = dyn_cast(GVal); + assert(F); + NewGV = copyFunctionProto(TypeMap, F); + } + // Set the linkage to ExternalWeak, see also comments in + // ModuleLinker::getLinkage. + if (SGA->hasWeakAnyLinkage()) + NewGV->setLinkage(GlobalValue::ExternalWeakLinkage); + // Don't attempt to link body, needs to be a declaration. + DoNotLinkFromSource.insert(SGA); + return NewGV; + } // If there is no linkage to be performed or we're linking from the source, // bring over SGA. auto *Ty = TypeMap.get(SGA->getValueType()); return GlobalAlias::create(Ty, SGA->getType()->getPointerAddressSpace(), - SGA->getLinkage(), SGA->getName(), &DstM); + getLinkage(SGA), getName(SGA), DstM); } -static GlobalValue *copyGlobalValueProto(TypeMapTy &TypeMap, Module &DstM, - const GlobalValue *SGV) { +void ModuleLinker::setVisibility(GlobalValue *NewGV, const GlobalValue *SGV, + const GlobalValue *DGV) { + GlobalValue::VisibilityTypes Visibility = SGV->getVisibility(); + if (DGV) + Visibility = isLessConstraining(Visibility, DGV->getVisibility()) + ? DGV->getVisibility() + : Visibility; + // For promoted locals, mark them hidden so that they can later be + // stripped from the symbol table to reduce bloat. + if (SGV->hasLocalLinkage() && doPromoteLocalToGlobal(SGV)) + Visibility = GlobalValue::HiddenVisibility; + NewGV->setVisibility(Visibility); +} + +GlobalValue *ModuleLinker::copyGlobalValueProto(TypeMapTy &TypeMap, + const GlobalValue *SGV, + const GlobalValue *DGV) { GlobalValue *NewGV; if (auto *SGVar = dyn_cast(SGV)) - NewGV = copyGlobalVariableProto(TypeMap, DstM, SGVar); + NewGV = copyGlobalVariableProto(TypeMap, SGVar); else if (auto *SF = dyn_cast(SGV)) - NewGV = copyFunctionProto(TypeMap, DstM, SF); + NewGV = copyFunctionProto(TypeMap, SF); else - NewGV = copyGlobalAliasProto(TypeMap, DstM, cast(SGV)); + NewGV = copyGlobalAliasProto(TypeMap, cast(SGV)); copyGVAttributes(NewGV, SGV); + setVisibility(NewGV, SGV, DGV); return NewGV; } @@ -608,7 +889,7 @@ if (!SGV) return nullptr; - GlobalValue *DGV = copyGlobalValueProto(TypeMap, *DstM, SGV); + GlobalValue *DGV = ModLinker->copyGlobalValueProto(TypeMap, SGV); if (Comdat *SC = SGV->getComdat()) { if (auto *DGO = dyn_cast(DGV)) { @@ -742,10 +1023,20 @@ // We always have to add Src if it has appending linkage. if (Src.hasAppendingLinkage()) { + // Caller should have already determined that we can't link from source + // when importing (see comments in linkGlobalValueProto). + assert(!isPerformingImport()); LinkFromSrc = true; return false; } + if (isPerformingImport() && isa(&Src)) { + // For functions, LinkFromSrc iff this is the function requested + // for importing. For variables, decide below normally. + LinkFromSrc = (&Src == ImportFunction); + return false; + } + bool SrcIsDeclaration = Src.isDeclarationForLinker(); bool DestIsDeclaration = Dest.isDeclarationForLinker(); @@ -1040,13 +1331,21 @@ GlobalValue *DGV = getLinkedToGlobal(SGV); // Handle the ultra special appending linkage case first. + assert(!DGV || SGV->hasAppendingLinkage() == DGV->hasAppendingLinkage()); + if (SGV->hasAppendingLinkage() && isPerformingImport()) { + // Don't want to append to global_ctors list, for example, when we + // are importing for ThinLTO, otherwise the global ctors and dtors + // get executed multiple times for local variables (the latter causing + // double frees). + DoNotLinkFromSource.insert(SGV); + return false; + } if (DGV && DGV->hasAppendingLinkage()) return linkAppendingVarProto(cast(DGV), cast(SGV)); bool LinkFromSrc = true; Comdat *C = nullptr; - GlobalValue::VisibilityTypes Visibility = SGV->getVisibility(); bool HasUnnamedAddr = SGV->hasUnnamedAddr(); if (const Comdat *SC = SGV->getComdat()) { @@ -1070,12 +1369,7 @@ ConstantExpr::getBitCast(DGV, TypeMap.get(SGV->getType())); } - if (DGV) { - Visibility = isLessConstraining(Visibility, DGV->getVisibility()) - ? DGV->getVisibility() - : Visibility; - HasUnnamedAddr = HasUnnamedAddr && DGV->hasUnnamedAddr(); - } + if (DGV) HasUnnamedAddr = HasUnnamedAddr && DGV->hasUnnamedAddr(); if (!LinkFromSrc && !DGV) return false; @@ -1083,10 +1377,12 @@ GlobalValue *NewGV; if (!LinkFromSrc) { NewGV = DGV; + // When linking from source we setVisibility from copyGlobalValueProto. + setVisibility(NewGV, SGV, DGV); } else { // If the GV is to be lazily linked, don't create it just yet. // The ValueMaterializerTy will deal with creating it if it's used. - if (!DGV && !shouldOverrideFromSrc() && + if (!DGV && !shouldOverrideFromSrc() && SGV != ImportFunction && (SGV->hasLocalLinkage() || SGV->hasLinkOnceLinkage() || SGV->hasAvailableExternallyLinkage())) { DoNotLinkFromSource.insert(SGV); @@ -1100,7 +1396,7 @@ return false; } - NewGV = copyGlobalValueProto(TypeMap, *DstM, SGV); + NewGV = copyGlobalValueProto(TypeMap, SGV, DGV); if (DGV && isa(DGV)) if (auto *NewF = dyn_cast(NewGV)) @@ -1108,7 +1404,6 @@ } NewGV->setUnnamedAddr(HasUnnamedAddr); - NewGV->setVisibility(Visibility); if (auto *NewGO = dyn_cast(NewGV)) { if (C) @@ -1613,6 +1908,9 @@ if (DoNotLinkFromSource.count(&SF)) continue; + // When importing, only materialize the function requested for import. + if (isPerformingImport() && &SF != ImportFunction) continue; + if (linkGlobalValueBody(SF)) return true; } @@ -1646,6 +1944,7 @@ while (!LazilyLinkGlobalValues.empty()) { GlobalValue *SGV = LazilyLinkGlobalValues.back(); LazilyLinkGlobalValues.pop_back(); + if (isPerformingImport() && !doImportAsDefinition(SGV)) continue; // Skip declarations that ValueMaterializer may have created in // case we link in only some of SrcM. @@ -1779,9 +2078,10 @@ Composite = nullptr; } -bool Linker::linkInModule(Module *Src, unsigned Flags) { +bool Linker::linkInModule(Module *Src, unsigned Flags, FunctionInfoIndex *Index, + Function *FuncToImport) { ModuleLinker TheLinker(Composite, IdentifiedStructTypes, Src, - DiagnosticHandler, Flags); + DiagnosticHandler, Flags, Index, FuncToImport); bool RetCode = TheLinker.run(); Composite->dropTriviallyDeadConstantArrays(); return RetCode; Index: lib/Transforms/IPO/ElimAvailExtern.cpp =================================================================== --- lib/Transforms/IPO/ElimAvailExtern.cpp +++ lib/Transforms/IPO/ElimAvailExtern.cpp @@ -48,9 +48,45 @@ return new EliminateAvailableExternally(); } +static void convertAliasToDeclaration(GlobalAlias &GA, Module &M) { + GlobalValue *GVal = GA.getBaseObject(); + GlobalValue *NewGV; + if (auto *GVar = dyn_cast(GVal)) { + GlobalVariable *NewGVar = new GlobalVariable( + M, GVar->getType()->getElementType(), GVar->isConstant(), + GVar->getLinkage(), /*init*/ nullptr, GA.getName(), GVar, + GVar->getThreadLocalMode(), GVar->getType()->getAddressSpace()); + NewGV = NewGVar; + NewGV->copyAttributesFrom(GVar); + } else { + auto *F = dyn_cast(GVal); + assert(F); + Function *NewF = Function::Create(F->getFunctionType(), F->getLinkage(), + GA.getName(), &M); + NewGV = NewF; + NewGV->copyAttributesFrom(F); + } + GA.replaceAllUsesWith(ConstantExpr::getBitCast(NewGV, GA.getType())); + GA.eraseFromParent(); +} + bool EliminateAvailableExternally::runOnModule(Module &M) { bool Changed = false; + // Convert any aliases that alias with an available externally + // value (which will be turned into declarations later on in this routine) + // into declarations themselves. All aliases must be definitions, and + // must alias with a definition. So this involves creating a declaration + // equivalent to the alias's base object. + for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E;) { + // Increment the iterator first since we may delete the current alias. + GlobalAlias &GA = *(I++); + GlobalValue *GVal = GA.getBaseObject(); + if (!GVal->hasAvailableExternallyLinkage()) continue; + convertAliasToDeclaration(GA, M); + Changed = true; + } + // Drop initializers of available externally global variables. for (GlobalVariable &GV :M.globals()) { if (!GV.hasAvailableExternallyLinkage()) @@ -64,6 +100,7 @@ GV.removeDeadConstantUsers(); GV.setLinkage(GlobalValue::ExternalLinkage); NumVariables++; + Changed = true; } // Drop the bodies of available externally functions. @@ -75,6 +112,7 @@ F.deleteBody(); F.removeDeadConstantUsers(); NumFunctions++; + Changed = true; } return Changed; Index: test/Linker/Inputs/funcimport.ll =================================================================== --- /dev/null +++ test/Linker/Inputs/funcimport.ll @@ -0,0 +1,28 @@ +define i32 @main() #0 { +entry: + call void (...) @weakalias() + call void (...) @analias() + %call = call i32 (...) @referencestatics() + %call1 = call i32 (...) @referenceglobals() + %call2 = call i32 (...) @referencecommon() + call void (...) @setfuncptr() + call void (...) @callfuncptr() + call void (...) @callweakfunc() + ret i32 0 +} + +declare void @weakalias(...) #1 + +declare void @analias(...) #1 + +declare i32 @referencestatics(...) #1 + +declare i32 @referenceglobals(...) #1 + +declare i32 @referencecommon(...) #1 + +declare void @setfuncptr(...) #1 + +declare void @callfuncptr(...) #1 + +declare void @callweakfunc(...) #1 Index: test/Linker/funcimport.ll =================================================================== --- /dev/null +++ test/Linker/funcimport.ll @@ -0,0 +1,160 @@ +; Do setup work for all below tests: generate bitcode and combined index +; RUN: llvm-as -function-summary %s -o %t.bc +; RUN: llvm-as -function-summary %p/Inputs/funcimport.ll -o %t2.bc +; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc + +; Ensure statics are promoted/renamed correctly from this file (all but +; constant variable need promotion). +; RUN: llvm-link %t.bc -functionindex=%t3.thinlto.bc -S | FileCheck %s --check-prefix=EXPORTSTATIC +; EXPORTSTATIC: @staticvar.llvm.1 = hidden global +; EXPORTSTATIC: @staticconstvar = internal unnamed_addr constant +; EXPORTSTATIC: @P.llvm.1 = hidden global void ()* null +; EXPORTSTATIC: define hidden i32 @staticfunc.llvm.1 +; EXPORTSTATIC: define hidden void @staticfunc2.llvm.1 + +; Ensure that both weak alias to an imported function and strong alias to a +; non-imported function are correctly turned into declarations. +; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc1:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB1 +; IMPORTGLOB1: define available_externally void @globalfunc1 +; IMPORTGLOB1: declare void @globalfunc2 +; IMPORTGLOB1: declare extern_weak void @weakalias +; IMPORTGLOB1: declare void @analias + +; Ensure that both weak alias to a non-imported function is correctly +; turned into a declaration, but that strong alias to an imported function +; is imported as alias. +; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc2:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB2 +; IMPORTGLOB2: @analias = alias void (...), bitcast (void ()* @globalfunc2 +; IMPORTGLOB2: declare void @globalfunc1 +; IMPORTGLOB2: define available_externally void @globalfunc2 +; IMPORTGLOB2: declare extern_weak void @weakalias + +; Ensure that strong alias imported in second pass of importing ends up +; as an alias. +; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc1:%t.bc -import=globalfunc2:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB3 +; IMPORTGLOB3: @analias = alias void (...), bitcast (void ()* @globalfunc2 +; IMPORTGLOB3: define available_externally void @globalfunc1 +; IMPORTGLOB3: define available_externally void @globalfunc2 +; IMPORTGLOB3: declare extern_weak void @weakalias + +; Ensure that imported static variable and function references are correctly +; promoted and renamed (including static constant variable). +; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=referencestatics:%t.bc -S | FileCheck %s --check-prefix=IMPORTSTATIC +; IMPORTSTATIC: @staticvar.llvm.1 = available_externally hidden global +; IMPORTSTATIC: @staticconstvar.llvm.1 = internal unnamed_addr constant +; IMPORTSTATIC: define available_externally i32 @referencestatics +; IMPORTSTATIC: %call = call i32 @staticfunc.llvm.1 +; IMPORTSTATIC: %0 = load i32, i32* @staticvar.llvm.1 +; IMPORTSTATIC: declare hidden i32 @staticfunc.llvm.1 + +; Ensure that imported global (external) function and variable references +; are handled correctly (including referenced variable imported as +; available_externally definition) +; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=referenceglobals:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOBALS +; IMPORTGLOBALS: @globalvar = available_externally global +; IMPORTGLOBALS: declare void @globalfunc1() +; IMPORTGLOBALS: define available_externally i32 @referenceglobals + +; Ensure that common variable correctly imported as common defition. +; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=referencecommon:%t.bc -S | FileCheck %s --check-prefix=IMPORTCOMMON +; IMPORTCOMMON: @commonvar = common global +; IMPORTCOMMON: define available_externally i32 @referencecommon + +; Ensure that imported static function pointer correctly promoted and renamed. +; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=callfuncptr:%t.bc -S | FileCheck %s --check-prefix=IMPORTFUNCPTR +; IMPORTFUNCPTR: @P.llvm.1 = available_externally hidden global void ()* null +; IMPORTFUNCPTR: define available_externally void @callfuncptr +; IMPORTFUNCPTR: %0 = load void ()*, void ()** @P.llvm.1 + +; Ensure that imported weak function reference/definition handled properly. +; Imported weak_any definition should be skipped with warning, and imported +; reference should turned into an external_weak declaration. +; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=callweakfunc:%t.bc -import=weakfunc:%t.bc -S 2>&1 | FileCheck %s --check-prefix=IMPORTWEAKFUNC +; IMPORTWEAKFUNC: Ignoring import request for weak-any function weakfunc +; IMPORTWEAKFUNC: declare extern_weak void @weakfunc +; IMPORTWEAKFUNC: define available_externally void @callweakfunc + +@globalvar = global i32 1, align 4 +@staticvar = internal global i32 1, align 4 +@staticconstvar = internal unnamed_addr constant [2 x i32] [i32 10, i32 20], align 4 +@commonvar = common global i32 0, align 4 +@P = internal global void ()* null, align 8 + +@weakalias = weak alias void (...), bitcast (void ()* @globalfunc1 to void (...)*) +@analias = alias void (...), bitcast (void ()* @globalfunc2 to void (...)*) + +define void @globalfunc1() #0 { +entry: + ret void +} + +define void @globalfunc2() #0 { +entry: + ret void +} + +define i32 @referencestatics(i32 %i) #0 { +entry: + %i.addr = alloca i32, align 4 + store i32 %i, i32* %i.addr, align 4 + %call = call i32 @staticfunc() + %0 = load i32, i32* @staticvar, align 4 + %add = add nsw i32 %call, %0 + %1 = load i32, i32* %i.addr, align 4 + %idxprom = sext i32 %1 to i64 + %arrayidx = getelementptr inbounds [2 x i32], [2 x i32]* @staticconstvar, i64 0, i64 %idxprom + %2 = load i32, i32* %arrayidx, align 4 + %add1 = add nsw i32 %add, %2 + ret i32 %add1 +} + +define i32 @referenceglobals(i32 %i) #0 { +entry: + %i.addr = alloca i32, align 4 + store i32 %i, i32* %i.addr, align 4 + call void @globalfunc1() + %0 = load i32, i32* @globalvar, align 4 + ret i32 %0 +} + +define i32 @referencecommon(i32 %i) #0 { +entry: + %i.addr = alloca i32, align 4 + store i32 %i, i32* %i.addr, align 4 + %0 = load i32, i32* @commonvar, align 4 + ret i32 %0 +} + +define void @setfuncptr() #0 { +entry: + store void ()* @staticfunc2, void ()** @P, align 8 + ret void +} + +define void @callfuncptr() #0 { +entry: + %0 = load void ()*, void ()** @P, align 8 + call void %0() + ret void +} + +define weak void @weakfunc() #0 { +entry: + ret void +} + +define void @callweakfunc() #0 { +entry: + call void @weakfunc() + ret void +} + +define internal i32 @staticfunc() #0 { +entry: + ret i32 1 +} + +define internal void @staticfunc2() #0 { +entry: + ret void +} Index: tools/llvm-link/CMakeLists.txt =================================================================== --- tools/llvm-link/CMakeLists.txt +++ tools/llvm-link/CMakeLists.txt @@ -3,6 +3,7 @@ Core IRReader Linker + Object Support ) Index: tools/llvm-link/LLVMBuild.txt =================================================================== --- tools/llvm-link/LLVMBuild.txt +++ tools/llvm-link/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Tool name = llvm-link parent = Tools -required_libraries = AsmParser BitReader BitWriter IRReader Linker +required_libraries = AsmParser BitReader BitWriter IRReader Linker Object Index: tools/llvm-link/llvm-link.cpp =================================================================== --- tools/llvm-link/llvm-link.cpp +++ tools/llvm-link/llvm-link.cpp @@ -18,10 +18,12 @@ #include "llvm/IR/AutoUpgrade.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" +#include "llvm/IR/FunctionInfo.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" #include "llvm/IRReader/IRReader.h" +#include "llvm/Object/FunctionIndexObjectFile.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" @@ -43,6 +45,23 @@ cl::desc( "input bitcode file which can override previously defined symbol(s)")); +// Option to simulate function importing for testing. This enables using +// llvm-link to simulate ThinLTO backend processes. +static cl::list Imports( + "import", cl::ZeroOrMore, cl::value_desc("function:filename"), + cl::desc("Pair of function name and filename, where function should be " + "imported from bitcode in filename")); + +// Option to support testing of function importing. The function index +// must be specified in the case were we request imports via the -import +// option, as well as when compiling any module with functions that may be +// exported (imported by a different llvm-link -import invocation), to ensure +// consistent promotion and renaming of locals. +static cl::opt FunctionIndex("functionindex", + cl::desc("Function index filename"), + cl::init(""), + cl::value_desc("filename")); + static cl::opt OutputFilename("o", cl::desc("Override output filename"), cl::init("-"), cl::value_desc("filename")); @@ -118,6 +137,86 @@ errs() << '\n'; } +/// Load a function index if requested by the -functionindex option. +static ErrorOr> loadIndex( + LLVMContext &Context) { + assert(!FunctionIndex.empty()); + ErrorOr> FileOrErr = + MemoryBuffer::getFileOrSTDIN(FunctionIndex); + std::error_code EC = FileOrErr.getError(); + if (EC) return EC; + MemoryBufferRef BufferRef = (FileOrErr.get())->getMemBufferRef(); + ErrorOr> ObjOrErr = + object::FunctionIndexObjectFile::create(BufferRef, Context); + EC = ObjOrErr.getError(); + if (EC) return EC; + + object::FunctionIndexObjectFile &Obj = **ObjOrErr; + return Obj.takeIndex(); +} + +/// Import any functions requested via the -import option. +static bool importFunctions(const char *argv0, LLVMContext &Context, + Linker &L) { + for (const auto &Import : Imports) { + // Identify the requested function and its bitcode source file. + size_t Idx = Import.find(':'); + if (Idx == std::string::npos) { + errs() << "Import parameter bad format: " << Import << "\n"; + return false; + } + std::string FunctionName = Import.substr(0, Idx); + std::string FileName = Import.substr(Idx + 1, std::string::npos); + + // Load the specified source module. + std::unique_ptr M = loadFile(argv0, FileName, Context); + if (!M.get()) { + errs() << argv0 << ": error loading file '" << FileName << "'\n"; + return false; + } + + if (verifyModule(*M, &errs())) { + errs() << argv0 << ": " << FileName + << ": error: input module is broken!\n"; + return false; + } + + Function *F = M->getFunction(FunctionName); + if (!F) { + errs() << "Ignoring import request for non-existent function " + << FunctionName << " from " << FileName << "\n"; + continue; + } + // We cannot import weak_any functions without possibly affecting the + // order they are seen and selected by the linker, changing program + // semantics. + if (F->hasWeakAnyLinkage()) { + errs() << "Ignoring import request for weak-any function " << FunctionName + << " from " << FileName << "\n"; + continue; + } + + if (Verbose) + errs() << "Importing " << FunctionName << " from " << FileName << "\n"; + + std::unique_ptr Index; + if (!FunctionIndex.empty()) { + ErrorOr> IndexOrErr = + loadIndex(Context); + std::error_code EC = IndexOrErr.getError(); + if (EC) { + errs() << EC.message() << '\n'; + return false; + } + Index = std::move(IndexOrErr.get()); + } + + // Link in the specified function. + if (L.linkInModule(M.get(), false, Index.get(), F)) return false; + } + return true; +} + static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L, const cl::list &Files, unsigned Flags) { @@ -135,11 +234,24 @@ return false; } + // If a function index is supplied, load it so linkInModule can treat + // local functions/variables as exported and promote if necessary. + std::unique_ptr Index; + if (!FunctionIndex.empty()) { + ErrorOr> IndexOrErr = + loadIndex(Context); + std::error_code EC = IndexOrErr.getError(); + if (EC) { + errs() << EC.message() << '\n'; + return false; + } + Index = std::move(IndexOrErr.get()); + } + if (Verbose) errs() << "Linking in '" << File << "'\n"; - if (L.linkInModule(M.get(), ApplicableFlags)) - return false; + if (L.linkInModule(M.get(), ApplicableFlags, Index.get())) return false; // All linker flags apply to linking of subsequent files. ApplicableFlags = Flags; } @@ -174,6 +286,9 @@ Flags | Linker::Flags::OverrideFromSrc)) return 1; + // Import any functions requested via -import + if (!importFunctions(argv[0], Context, L)) return 1; + if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite; std::error_code EC;