summaryrefslogtreecommitdiff
path: root/lib/Linker
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Linker')
-rw-r--r--lib/Linker/IRMover.cpp828
-rw-r--r--lib/Linker/LinkModules.cpp607
-rw-r--r--lib/Linker/Makefile15
3 files changed, 409 insertions, 1041 deletions
diff --git a/lib/Linker/IRMover.cpp b/lib/Linker/IRMover.cpp
index 8dd59f9e0e3e2..4935868c00f47 100644
--- a/lib/Linker/IRMover.cpp
+++ b/lib/Linker/IRMover.cpp
@@ -16,8 +16,11 @@
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/GVMaterializer.h"
+#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/TypeFinder.h"
+#include "llvm/Support/Error.h"
#include "llvm/Transforms/Utils/Cloning.h"
+#include <utility>
using namespace llvm;
//===----------------------------------------------------------------------===//
@@ -345,43 +348,40 @@ class IRLinker;
/// speeds up linking for modules with many/ lazily linked functions of which
/// few get used.
class GlobalValueMaterializer final : public ValueMaterializer {
- IRLinker *TheIRLinker;
+ IRLinker &TheIRLinker;
public:
- GlobalValueMaterializer(IRLinker *TheIRLinker) : TheIRLinker(TheIRLinker) {}
- Value *materializeDeclFor(Value *V) override;
- void materializeInitFor(GlobalValue *New, GlobalValue *Old) override;
- Metadata *mapTemporaryMetadata(Metadata *MD) override;
- void replaceTemporaryMetadata(const Metadata *OrigMD,
- Metadata *NewMD) override;
- bool isMetadataNeeded(Metadata *MD) override;
+ GlobalValueMaterializer(IRLinker &TheIRLinker) : TheIRLinker(TheIRLinker) {}
+ Value *materialize(Value *V) override;
};
class LocalValueMaterializer final : public ValueMaterializer {
- IRLinker *TheIRLinker;
+ IRLinker &TheIRLinker;
public:
- LocalValueMaterializer(IRLinker *TheIRLinker) : TheIRLinker(TheIRLinker) {}
- Value *materializeDeclFor(Value *V) override;
- void materializeInitFor(GlobalValue *New, GlobalValue *Old) override;
- Metadata *mapTemporaryMetadata(Metadata *MD) override;
- void replaceTemporaryMetadata(const Metadata *OrigMD,
- Metadata *NewMD) override;
- bool isMetadataNeeded(Metadata *MD) override;
+ LocalValueMaterializer(IRLinker &TheIRLinker) : TheIRLinker(TheIRLinker) {}
+ Value *materialize(Value *V) override;
};
+/// Type of the Metadata map in \a ValueToValueMapTy.
+typedef DenseMap<const Metadata *, TrackingMDRef> MDMapT;
+
/// This is responsible for keeping track of the state used for moving data
/// from SrcM to DstM.
class IRLinker {
Module &DstM;
- Module &SrcM;
+ std::unique_ptr<Module> SrcM;
+ /// See IRMover::move().
std::function<void(GlobalValue &, IRMover::ValueAdder)> AddLazyFor;
TypeMapTy TypeMap;
GlobalValueMaterializer GValMaterializer;
LocalValueMaterializer LValMaterializer;
+ /// A metadata map that's shared between IRLinker instances.
+ MDMapT &SharedMDs;
+
/// Mapping of values from what they used to be in Src, to what they are now
/// in DstM. ValueToValueMapTy is a ValueMap, which involves some overhead
/// due to the use of Value handles which the Linker doesn't actually need,
@@ -402,52 +402,30 @@ class IRLinker {
/// references.
bool DoneLinkingBodies = false;
- bool HasError = false;
-
- /// Flag indicating that we are just linking metadata (after function
- /// importing).
- bool IsMetadataLinkingPostpass;
-
- /// Flags to pass to value mapper invocations.
- RemapFlags ValueMapperFlags = RF_MoveDistinctMDs;
-
- /// Association between metadata values created during bitcode parsing and
- /// the value id. Used to correlate temporary metadata created during
- /// function importing with the final metadata parsed during the subsequent
- /// metadata linking postpass.
- DenseMap<const Metadata *, unsigned> MetadataToIDs;
+ /// The Error encountered during materialization. We use an Optional here to
+ /// avoid needing to manage an unconsumed success value.
+ Optional<Error> FoundError;
+ void setError(Error E) {
+ if (E)
+ FoundError = std::move(E);
+ }
- /// Association between metadata value id and temporary metadata that
- /// remains unmapped after function importing. Saved during function
- /// importing and consumed during the metadata linking postpass.
- DenseMap<unsigned, MDNode *> *ValIDToTempMDMap;
+ /// Most of the errors produced by this module are inconvertible StringErrors.
+ /// This convenience function lets us return one of those more easily.
+ Error stringErr(const Twine &T) {
+ return make_error<StringError>(T, inconvertibleErrorCode());
+ }
- /// Set of subprogram metadata that does not need to be linked into the
- /// destination module, because the functions were not imported directly
- /// or via an inlined body in an imported function.
- SmallPtrSet<const Metadata *, 16> UnneededSubprograms;
+ /// Entry point for mapping values and alternate context for mapping aliases.
+ ValueMapper Mapper;
+ unsigned AliasMCID;
/// Handles cloning of a global values from the source module into
/// the destination module, including setting the attributes and visibility.
GlobalValue *copyGlobalValueProto(const GlobalValue *SGV, bool ForDefinition);
- /// Helper method for setting a message and returning an error code.
- bool emitError(const Twine &Message) {
- SrcM.getContext().diagnose(LinkDiagnosticInfo(DS_Error, Message));
- HasError = true;
- return true;
- }
-
void emitWarning(const Twine &Message) {
- SrcM.getContext().diagnose(LinkDiagnosticInfo(DS_Warning, Message));
- }
-
- /// Check whether we should be linking metadata from the source module.
- bool shouldLinkMetadata() {
- // ValIDToTempMDMap will be non-null when we are importing or otherwise want
- // to link metadata lazily, and then when linking the metadata.
- // We only want to return true for the former case.
- return ValIDToTempMDMap == nullptr || IsMetadataLinkingPostpass;
+ SrcM->getContext().diagnose(LinkDiagnosticInfo(DS_Warning, Message));
}
/// Given a global in the source module, return the global in the
@@ -474,18 +452,23 @@ class IRLinker {
void computeTypeMapping();
- Constant *linkAppendingVarProto(GlobalVariable *DstGV,
- const GlobalVariable *SrcGV);
+ Expected<Constant *> linkAppendingVarProto(GlobalVariable *DstGV,
+ const GlobalVariable *SrcGV);
+ /// Given the GlobaValue \p SGV in the source module, and the matching
+ /// GlobalValue \p DGV (if any), return true if the linker will pull \p SGV
+ /// into the destination module.
+ ///
+ /// Note this code may call the client-provided \p AddLazyFor.
bool shouldLink(GlobalValue *DGV, GlobalValue &SGV);
- Constant *linkGlobalValueProto(GlobalValue *GV, bool ForAlias);
+ Expected<Constant *> linkGlobalValueProto(GlobalValue *GV, bool ForAlias);
- bool linkModuleFlagsMetadata();
+ Error linkModuleFlagsMetadata();
void linkGlobalInit(GlobalVariable &Dst, GlobalVariable &Src);
- bool linkFunctionBody(Function &Dst, Function &Src);
+ Error linkFunctionBody(Function &Dst, Function &Src);
void linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src);
- bool linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src);
+ Error linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src);
/// Functions that take care of cloning a specific global value type
/// into the destination module.
@@ -495,70 +478,26 @@ class IRLinker {
void linkNamedMDNodes();
- /// Populate the UnneededSubprograms set with the DISubprogram metadata
- /// from the source module that we don't need to link into the dest module,
- /// because the functions were not imported directly or via an inlined body
- /// in an imported function.
- void findNeededSubprograms(ValueToValueMapTy &ValueMap);
-
- /// The value mapper leaves nulls in the list of subprograms for any
- /// in the UnneededSubprograms map. Strip those out after metadata linking.
- void stripNullSubprograms();
-
public:
- IRLinker(Module &DstM, IRMover::IdentifiedStructTypeSet &Set, Module &SrcM,
+ IRLinker(Module &DstM, MDMapT &SharedMDs,
+ IRMover::IdentifiedStructTypeSet &Set, std::unique_ptr<Module> SrcM,
ArrayRef<GlobalValue *> ValuesToLink,
- std::function<void(GlobalValue &, IRMover::ValueAdder)> AddLazyFor,
- DenseMap<unsigned, MDNode *> *ValIDToTempMDMap = nullptr,
- bool IsMetadataLinkingPostpass = false)
- : DstM(DstM), SrcM(SrcM), AddLazyFor(AddLazyFor), TypeMap(Set),
- GValMaterializer(this), LValMaterializer(this),
- IsMetadataLinkingPostpass(IsMetadataLinkingPostpass),
- ValIDToTempMDMap(ValIDToTempMDMap) {
+ std::function<void(GlobalValue &, IRMover::ValueAdder)> AddLazyFor)
+ : DstM(DstM), SrcM(std::move(SrcM)), AddLazyFor(std::move(AddLazyFor)),
+ TypeMap(Set), GValMaterializer(*this), LValMaterializer(*this),
+ SharedMDs(SharedMDs),
+ Mapper(ValueMap, RF_MoveDistinctMDs | RF_IgnoreMissingLocals, &TypeMap,
+ &GValMaterializer),
+ AliasMCID(Mapper.registerAlternateMappingContext(AliasValueMap,
+ &LValMaterializer)) {
+ ValueMap.getMDMap() = std::move(SharedMDs);
for (GlobalValue *GV : ValuesToLink)
maybeAdd(GV);
-
- // If appropriate, tell the value mapper that it can expect to see
- // temporary metadata.
- if (!shouldLinkMetadata())
- ValueMapperFlags = ValueMapperFlags | RF_HaveUnmaterializedMetadata;
- }
-
- ~IRLinker() {
- // In the case where we are not linking metadata, we unset the CanReplace
- // flag on all temporary metadata in the MetadataToIDs map to ensure
- // none was replaced while being a map key. Now that we are destructing
- // the map, set the flag back to true, so that it is replaceable during
- // metadata linking.
- if (!shouldLinkMetadata()) {
- for (auto MDI : MetadataToIDs) {
- Metadata *MD = const_cast<Metadata *>(MDI.first);
- MDNode *Node = dyn_cast<MDNode>(MD);
- assert((Node && Node->isTemporary()) &&
- "Found non-temp metadata in map when not linking metadata");
- Node->setCanReplace(true);
- }
- }
}
+ ~IRLinker() { SharedMDs = std::move(*ValueMap.getMDMap()); }
- bool run();
- Value *materializeDeclFor(Value *V, bool ForAlias);
- void materializeInitFor(GlobalValue *New, GlobalValue *Old, bool ForAlias);
-
- /// Save the mapping between the given temporary metadata and its metadata
- /// value id. Used to support metadata linking as a postpass for function
- /// importing.
- Metadata *mapTemporaryMetadata(Metadata *MD);
-
- /// Replace any temporary metadata saved for the source metadata's id with
- /// the new non-temporary metadata. Used when metadata linking as a postpass
- /// for function importing.
- void replaceTemporaryMetadata(const Metadata *OrigMD, Metadata *NewMD);
-
- /// Indicates whether we need to map the given metadata into the destination
- /// module. Used to prevent linking of metadata only needed by functions not
- /// linked into the dest module.
- bool isMetadataNeeded(Metadata *MD);
+ Error run();
+ Value *materialize(Value *V, bool ForAlias);
};
}
@@ -583,133 +522,59 @@ static void forceRenaming(GlobalValue *GV, StringRef Name) {
}
}
-Value *GlobalValueMaterializer::materializeDeclFor(Value *V) {
- return TheIRLinker->materializeDeclFor(V, false);
-}
-
-void GlobalValueMaterializer::materializeInitFor(GlobalValue *New,
- GlobalValue *Old) {
- TheIRLinker->materializeInitFor(New, Old, false);
-}
-
-Metadata *GlobalValueMaterializer::mapTemporaryMetadata(Metadata *MD) {
- return TheIRLinker->mapTemporaryMetadata(MD);
-}
-
-void GlobalValueMaterializer::replaceTemporaryMetadata(const Metadata *OrigMD,
- Metadata *NewMD) {
- TheIRLinker->replaceTemporaryMetadata(OrigMD, NewMD);
+Value *GlobalValueMaterializer::materialize(Value *SGV) {
+ return TheIRLinker.materialize(SGV, false);
}
-bool GlobalValueMaterializer::isMetadataNeeded(Metadata *MD) {
- return TheIRLinker->isMetadataNeeded(MD);
+Value *LocalValueMaterializer::materialize(Value *SGV) {
+ return TheIRLinker.materialize(SGV, true);
}
-Value *LocalValueMaterializer::materializeDeclFor(Value *V) {
- return TheIRLinker->materializeDeclFor(V, true);
-}
-
-void LocalValueMaterializer::materializeInitFor(GlobalValue *New,
- GlobalValue *Old) {
- TheIRLinker->materializeInitFor(New, Old, true);
-}
-
-Metadata *LocalValueMaterializer::mapTemporaryMetadata(Metadata *MD) {
- return TheIRLinker->mapTemporaryMetadata(MD);
-}
-
-void LocalValueMaterializer::replaceTemporaryMetadata(const Metadata *OrigMD,
- Metadata *NewMD) {
- TheIRLinker->replaceTemporaryMetadata(OrigMD, NewMD);
-}
-
-bool LocalValueMaterializer::isMetadataNeeded(Metadata *MD) {
- return TheIRLinker->isMetadataNeeded(MD);
-}
-
-Value *IRLinker::materializeDeclFor(Value *V, bool ForAlias) {
+Value *IRLinker::materialize(Value *V, bool ForAlias) {
auto *SGV = dyn_cast<GlobalValue>(V);
if (!SGV)
return nullptr;
- return linkGlobalValueProto(SGV, ForAlias);
-}
+ Expected<Constant *> NewProto = linkGlobalValueProto(SGV, ForAlias);
+ if (!NewProto) {
+ setError(NewProto.takeError());
+ return nullptr;
+ }
+ if (!*NewProto)
+ return nullptr;
+
+ GlobalValue *New = dyn_cast<GlobalValue>(*NewProto);
+ if (!New)
+ return *NewProto;
-void IRLinker::materializeInitFor(GlobalValue *New, GlobalValue *Old,
- bool ForAlias) {
// If we already created the body, just return.
if (auto *F = dyn_cast<Function>(New)) {
if (!F->isDeclaration())
- return;
+ return New;
} else if (auto *V = dyn_cast<GlobalVariable>(New)) {
- if (V->hasInitializer())
- return;
+ if (V->hasInitializer() || V->hasAppendingLinkage())
+ return New;
} else {
auto *A = cast<GlobalAlias>(New);
if (A->getAliasee())
- return;
+ return New;
}
- if (ForAlias || shouldLink(New, *Old))
- linkGlobalValueBody(*New, *Old);
-}
-
-Metadata *IRLinker::mapTemporaryMetadata(Metadata *MD) {
- if (!ValIDToTempMDMap)
- return nullptr;
- // If this temporary metadata has a value id recorded during function
- // parsing, record that in the ValIDToTempMDMap if one was provided.
- if (MetadataToIDs.count(MD)) {
- unsigned Idx = MetadataToIDs[MD];
- // Check if we created a temp MD when importing a different function from
- // this module. If so, reuse it the same temporary metadata, otherwise
- // add this temporary metadata to the map.
- if (!ValIDToTempMDMap->count(Idx)) {
- MDNode *Node = cast<MDNode>(MD);
- assert(Node->isTemporary());
- (*ValIDToTempMDMap)[Idx] = Node;
- }
- return (*ValIDToTempMDMap)[Idx];
- }
- return nullptr;
-}
-
-void IRLinker::replaceTemporaryMetadata(const Metadata *OrigMD,
- Metadata *NewMD) {
- if (!ValIDToTempMDMap)
- return;
-#ifndef NDEBUG
- auto *N = dyn_cast_or_null<MDNode>(NewMD);
- assert(!N || !N->isTemporary());
-#endif
- // If a mapping between metadata value ids and temporary metadata
- // created during function importing was provided, and the source
- // metadata has a value id recorded during metadata parsing, replace
- // the temporary metadata with the final mapped metadata now.
- if (MetadataToIDs.count(OrigMD)) {
- unsigned Idx = MetadataToIDs[OrigMD];
- // Nothing to do if we didn't need to create a temporary metadata during
- // function importing.
- if (!ValIDToTempMDMap->count(Idx))
- return;
- MDNode *TempMD = (*ValIDToTempMDMap)[Idx];
- TempMD->replaceAllUsesWith(NewMD);
- MDNode::deleteTemporary(TempMD);
- ValIDToTempMDMap->erase(Idx);
- }
-}
-
-bool IRLinker::isMetadataNeeded(Metadata *MD) {
- // Currently only DISubprogram metadata is marked as being unneeded.
- if (UnneededSubprograms.empty())
- return true;
- MDNode *Node = dyn_cast<MDNode>(MD);
- if (!Node)
- return true;
- DISubprogram *SP = getDISubprogram(Node);
- if (!SP)
- return true;
- return !UnneededSubprograms.count(SP);
+ // When linking a global for an alias, it will always be linked. However we
+ // need to check if it was not already scheduled to satify 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)
+ return New;
+
+ if (ForAlias || shouldLink(New, *SGV))
+ setError(linkGlobalValueBody(*New, *SGV));
+
+ return New;
}
/// Loop through the global variables in the src module and merge them into the
@@ -719,7 +584,7 @@ GlobalVariable *IRLinker::copyGlobalVariableProto(const GlobalVariable *SGVar) {
// 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()),
+ new GlobalVariable(DstM, TypeMap.get(SGVar->getValueType()),
SGVar->isConstant(), GlobalValue::ExternalLinkage,
/*init*/ nullptr, SGVar->getName(),
/*insertbefore*/ nullptr, SGVar->getThreadLocalMode(),
@@ -759,7 +624,7 @@ GlobalValue *IRLinker::copyGlobalValueProto(const GlobalValue *SGV,
NewGV = copyGlobalAliasProto(cast<GlobalAlias>(SGV));
else
NewGV = new GlobalVariable(
- DstM, TypeMap.get(SGV->getType()->getElementType()),
+ DstM, TypeMap.get(SGV->getValueType()),
/*isConstant*/ false, GlobalValue::ExternalLinkage,
/*init*/ nullptr, SGV->getName(),
/*insertbefore*/ nullptr, SGV->getThreadLocalMode(),
@@ -768,12 +633,17 @@ GlobalValue *IRLinker::copyGlobalValueProto(const GlobalValue *SGV,
if (ForDefinition)
NewGV->setLinkage(SGV->getLinkage());
- else if (SGV->hasExternalWeakLinkage() || SGV->hasWeakLinkage() ||
- SGV->hasLinkOnceLinkage())
+ else if (SGV->hasExternalWeakLinkage())
NewGV->setLinkage(GlobalValue::ExternalWeakLinkage);
NewGV->copyAttributesFrom(SGV);
+ if (auto *NewGO = dyn_cast<GlobalObject>(NewGV)) {
+ // Metadata for global variables and function declarations is copied eagerly.
+ if (isa<GlobalVariable>(SGV) || SGV->isDeclaration())
+ NewGO->copyMetadata(cast<GlobalObject>(SGV), 0);
+ }
+
// Remove these copied constants in case this stays a declaration, since
// they point to the source module. If the def is linked the values will
// be mapped in during linkFunctionBody.
@@ -791,7 +661,7 @@ GlobalValue *IRLinker::copyGlobalValueProto(const GlobalValue *SGV,
/// types 'Foo' but one got renamed when the module was loaded into the same
/// LLVMContext.
void IRLinker::computeTypeMapping() {
- for (GlobalValue &SGV : SrcM.globals()) {
+ for (GlobalValue &SGV : SrcM->globals()) {
GlobalValue *DGV = getLinkedToGlobal(&SGV);
if (!DGV)
continue;
@@ -802,16 +672,16 @@ void IRLinker::computeTypeMapping() {
}
// Unify the element type of appending arrays.
- ArrayType *DAT = cast<ArrayType>(DGV->getType()->getElementType());
- ArrayType *SAT = cast<ArrayType>(SGV.getType()->getElementType());
+ ArrayType *DAT = cast<ArrayType>(DGV->getValueType());
+ ArrayType *SAT = cast<ArrayType>(SGV.getValueType());
TypeMap.addTypeMapping(DAT->getElementType(), SAT->getElementType());
}
- for (GlobalValue &SGV : SrcM)
+ for (GlobalValue &SGV : *SrcM)
if (GlobalValue *DGV = getLinkedToGlobal(&SGV))
TypeMap.addTypeMapping(DGV->getType(), SGV.getType());
- for (GlobalValue &SGV : SrcM.aliases())
+ for (GlobalValue &SGV : SrcM->aliases())
if (GlobalValue *DGV = getLinkedToGlobal(&SGV))
TypeMap.addTypeMapping(DGV->getType(), SGV.getType());
@@ -819,7 +689,7 @@ void IRLinker::computeTypeMapping() {
// At this point, the destination module may have a type "%foo = { i32 }" for
// example. When the source module got loaded into the same LLVMContext, if
// it had the same type, it would have been renamed to "%foo.42 = { i32 }".
- std::vector<StructType *> Types = SrcM.getIdentifiedStructTypes();
+ std::vector<StructType *> Types = SrcM->getIdentifiedStructTypes();
for (StructType *ST : Types) {
if (!ST->hasName())
continue;
@@ -871,12 +741,16 @@ static void getArrayElements(const Constant *C,
}
/// If there were any appending global variables, link them together now.
-/// Return true on error.
-Constant *IRLinker::linkAppendingVarProto(GlobalVariable *DstGV,
- const GlobalVariable *SrcGV) {
- Type *EltTy = cast<ArrayType>(TypeMap.get(SrcGV->getType()->getElementType()))
+Expected<Constant *>
+IRLinker::linkAppendingVarProto(GlobalVariable *DstGV,
+ const GlobalVariable *SrcGV) {
+ Type *EltTy = cast<ArrayType>(TypeMap.get(SrcGV->getValueType()))
->getElementType();
+ // FIXME: This upgrade is done during linking to support the C API. Once the
+ // old form is deprecated, we should move this upgrade to
+ // llvm::UpgradeGlobalVariable() and simplify the logic here and in
+ // Mapper::mapAppendingVariable() in ValueMapper.cpp.
StringRef Name = SrcGV->getName();
bool IsNewStructor = false;
bool IsOldStructor = false;
@@ -894,55 +768,40 @@ Constant *IRLinker::linkAppendingVarProto(GlobalVariable *DstGV,
EltTy = StructType::get(SrcGV->getContext(), Tys, false);
}
+ uint64_t DstNumElements = 0;
if (DstGV) {
- ArrayType *DstTy = cast<ArrayType>(DstGV->getType()->getElementType());
+ ArrayType *DstTy = cast<ArrayType>(DstGV->getValueType());
+ DstNumElements = DstTy->getNumElements();
- if (!SrcGV->hasAppendingLinkage() || !DstGV->hasAppendingLinkage()) {
- emitError(
+ if (!SrcGV->hasAppendingLinkage() || !DstGV->hasAppendingLinkage())
+ return stringErr(
"Linking globals named '" + SrcGV->getName() +
- "': can only link appending global with another appending global!");
- return nullptr;
- }
+ "': can only link appending global with another appending "
+ "global!");
// Check to see that they two arrays agree on type.
- if (EltTy != DstTy->getElementType()) {
- emitError("Appending variables with different element types!");
- return nullptr;
- }
- if (DstGV->isConstant() != SrcGV->isConstant()) {
- emitError("Appending variables linked with different const'ness!");
- return nullptr;
- }
+ if (EltTy != DstTy->getElementType())
+ return stringErr("Appending variables with different element types!");
+ if (DstGV->isConstant() != SrcGV->isConstant())
+ return stringErr("Appending variables linked with different const'ness!");
- if (DstGV->getAlignment() != SrcGV->getAlignment()) {
- emitError(
+ if (DstGV->getAlignment() != SrcGV->getAlignment())
+ return stringErr(
"Appending variables with different alignment need to be linked!");
- return nullptr;
- }
- if (DstGV->getVisibility() != SrcGV->getVisibility()) {
- emitError(
+ if (DstGV->getVisibility() != SrcGV->getVisibility())
+ return stringErr(
"Appending variables with different visibility need to be linked!");
- return nullptr;
- }
- if (DstGV->hasUnnamedAddr() != SrcGV->hasUnnamedAddr()) {
- emitError(
+ if (DstGV->hasGlobalUnnamedAddr() != SrcGV->hasGlobalUnnamedAddr())
+ return stringErr(
"Appending variables with different unnamed_addr need to be linked!");
- return nullptr;
- }
- if (StringRef(DstGV->getSection()) != SrcGV->getSection()) {
- emitError(
+ if (DstGV->getSection() != SrcGV->getSection())
+ return stringErr(
"Appending variables with different section name need to be linked!");
- return nullptr;
- }
}
- SmallVector<Constant *, 16> DstElements;
- if (DstGV)
- getArrayElements(DstGV->getInitializer(), DstElements);
-
SmallVector<Constant *, 16> SrcElements;
getArrayElements(SrcGV->getInitializer(), SrcElements);
@@ -958,7 +817,7 @@ Constant *IRLinker::linkAppendingVarProto(GlobalVariable *DstGV,
return !shouldLink(DGV, *Key);
}),
SrcElements.end());
- uint64_t NewSize = DstElements.size() + SrcElements.size();
+ uint64_t NewSize = DstNumElements + SrcElements.size();
ArrayType *NewType = ArrayType::get(EltTy, NewSize);
// Create the new global variable.
@@ -972,28 +831,9 @@ Constant *IRLinker::linkAppendingVarProto(GlobalVariable *DstGV,
Constant *Ret = ConstantExpr::getBitCast(NG, TypeMap.get(SrcGV->getType()));
- // Stop recursion.
- ValueMap[SrcGV] = Ret;
-
- for (auto *V : SrcElements) {
- Constant *NewV;
- if (IsOldStructor) {
- auto *S = cast<ConstantStruct>(V);
- auto *E1 = MapValue(S->getOperand(0), ValueMap, ValueMapperFlags,
- &TypeMap, &GValMaterializer);
- auto *E2 = MapValue(S->getOperand(1), ValueMap, ValueMapperFlags,
- &TypeMap, &GValMaterializer);
- Value *Null = Constant::getNullValue(VoidPtrTy);
- NewV =
- ConstantStruct::get(cast<StructType>(EltTy), E1, E2, Null, nullptr);
- } else {
- NewV =
- MapValue(V, ValueMap, ValueMapperFlags, &TypeMap, &GValMaterializer);
- }
- DstElements.push_back(NewV);
- }
-
- NG->setInitializer(ConstantArray::get(NewType, DstElements));
+ Mapper.scheduleMapAppendingVariable(*NG,
+ DstGV ? DstGV->getInitializer() : nullptr,
+ IsOldStructor, SrcElements);
// Replace any uses of the two global variables with uses of the new
// global.
@@ -1005,52 +845,31 @@ Constant *IRLinker::linkAppendingVarProto(GlobalVariable *DstGV,
return Ret;
}
-static bool useExistingDest(GlobalValue &SGV, GlobalValue *DGV,
- bool ShouldLink) {
- if (!DGV)
- return false;
-
- if (SGV.isDeclaration())
- return true;
-
- if (DGV->isDeclarationForLinker() && !SGV.isDeclarationForLinker())
- return false;
-
- if (ShouldLink)
- return false;
-
- return true;
-}
-
bool IRLinker::shouldLink(GlobalValue *DGV, GlobalValue &SGV) {
- // Already imported all the values. Just map to the Dest value
- // in case it is referenced in the metadata.
- if (IsMetadataLinkingPostpass) {
- assert(!ValuesToLink.count(&SGV) &&
- "Source value unexpectedly requested for link during metadata link");
- return false;
- }
-
- if (ValuesToLink.count(&SGV))
- return true;
-
- if (SGV.hasLocalLinkage())
+ if (ValuesToLink.count(&SGV) || SGV.hasLocalLinkage())
return true;
- if (DGV && !DGV->isDeclaration())
+ if (DGV && !DGV->isDeclarationForLinker())
return false;
if (SGV.hasAvailableExternallyLinkage())
return true;
- if (DoneLinkingBodies)
+ if (SGV.isDeclaration() || DoneLinkingBodies)
return false;
- AddLazyFor(SGV, [this](GlobalValue &GV) { maybeAdd(&GV); });
- return ValuesToLink.count(&SGV);
+ // Callback to the client to give a chance to lazily add the Global to the
+ // list of value to link.
+ bool LazilyAdded = false;
+ AddLazyFor(SGV, [this, &LazilyAdded](GlobalValue &GV) {
+ maybeAdd(&GV);
+ LazilyAdded = true;
+ });
+ return LazilyAdded;
}
-Constant *IRLinker::linkGlobalValueProto(GlobalValue *SGV, bool ForAlias) {
+Expected<Constant *> IRLinker::linkGlobalValueProto(GlobalValue *SGV,
+ bool ForAlias) {
GlobalValue *DGV = getLinkedToGlobal(SGV);
bool ShouldLink = shouldLink(DGV, *SGV);
@@ -1066,9 +885,8 @@ Constant *IRLinker::linkGlobalValueProto(GlobalValue *SGV, bool ForAlias) {
return cast<Constant>(I->second);
}
- DGV = nullptr;
- if (ShouldLink || !ForAlias)
- DGV = getLinkedToGlobal(SGV);
+ if (!ShouldLink && ForAlias)
+ DGV = nullptr;
// Handle the ultra special appending linkage case first.
assert(!DGV || SGV->hasAppendingLinkage() == DGV->hasAppendingLinkage());
@@ -1077,7 +895,7 @@ Constant *IRLinker::linkGlobalValueProto(GlobalValue *SGV, bool ForAlias) {
cast<GlobalVariable>(SGV));
GlobalValue *NewGV;
- if (useExistingDest(*SGV, DGV, ShouldLink)) {
+ if (DGV && !ShouldLink) {
NewGV = DGV;
} else {
// If we are done linking global value bodies (i.e. we are performing
@@ -1087,9 +905,17 @@ Constant *IRLinker::linkGlobalValueProto(GlobalValue *SGV, bool ForAlias) {
return nullptr;
NewGV = copyGlobalValueProto(SGV, ShouldLink);
- if (!ForAlias)
+ if (ShouldLink || !ForAlias)
forceRenaming(NewGV, SGV->getName());
}
+
+ // Overloaded intrinsics have overloaded types names as part of their
+ // names. If we renamed overloaded types we should rename the intrinsic
+ // as well.
+ if (Function *F = dyn_cast<Function>(NewGV))
+ if (auto Remangled = Intrinsic::remangleIntrinsicFunction(F))
+ NewGV = Remangled.getValue();
+
if (ShouldLink || ForAlias) {
if (const Comdat *SC = SGV->getComdat()) {
if (auto *GO = dyn_cast<GlobalObject>(NewGV)) {
@@ -1119,196 +945,74 @@ Constant *IRLinker::linkGlobalValueProto(GlobalValue *SGV, bool ForAlias) {
/// referenced are in Dest.
void IRLinker::linkGlobalInit(GlobalVariable &Dst, GlobalVariable &Src) {
// Figure out what the initializer looks like in the dest module.
- Dst.setInitializer(MapValue(Src.getInitializer(), ValueMap, ValueMapperFlags,
- &TypeMap, &GValMaterializer));
+ Mapper.scheduleMapGlobalInitializer(Dst, *Src.getInitializer());
}
/// Copy the source function over into the dest function and fix up references
/// to values. At this point we know that Dest is an external function, and
/// that Src is not.
-bool IRLinker::linkFunctionBody(Function &Dst, Function &Src) {
+Error IRLinker::linkFunctionBody(Function &Dst, Function &Src) {
assert(Dst.isDeclaration() && !Src.isDeclaration());
// Materialize if needed.
if (std::error_code EC = Src.materialize())
- return emitError(EC.message());
-
- if (!shouldLinkMetadata())
- // This is only supported for lazy links. Do after materialization of
- // a function and before remapping metadata on instructions below
- // in RemapInstruction, as the saved mapping is used to handle
- // the temporary metadata hanging off instructions.
- SrcM.getMaterializer()->saveMetadataList(MetadataToIDs,
- /* OnlyTempMD = */ true);
+ return errorCodeToError(EC);
- // Link in the prefix data.
+ // Link in the operands without remapping.
if (Src.hasPrefixData())
- Dst.setPrefixData(MapValue(Src.getPrefixData(), ValueMap, ValueMapperFlags,
- &TypeMap, &GValMaterializer));
-
- // Link in the prologue data.
+ Dst.setPrefixData(Src.getPrefixData());
if (Src.hasPrologueData())
- Dst.setPrologueData(MapValue(Src.getPrologueData(), ValueMap,
- ValueMapperFlags, &TypeMap,
- &GValMaterializer));
-
- // Link in the personality function.
+ Dst.setPrologueData(Src.getPrologueData());
if (Src.hasPersonalityFn())
- Dst.setPersonalityFn(MapValue(Src.getPersonalityFn(), ValueMap,
- ValueMapperFlags, &TypeMap,
- &GValMaterializer));
-
- // Go through and convert function arguments over, remembering the mapping.
- Function::arg_iterator DI = Dst.arg_begin();
- for (Argument &Arg : Src.args()) {
- DI->setName(Arg.getName()); // Copy the name over.
-
- // Add a mapping to our mapping.
- ValueMap[&Arg] = &*DI;
- ++DI;
- }
+ Dst.setPersonalityFn(Src.getPersonalityFn());
- // Copy over the metadata attachments.
- SmallVector<std::pair<unsigned, MDNode *>, 8> MDs;
- Src.getAllMetadata(MDs);
- for (const auto &I : MDs)
- Dst.setMetadata(I.first, MapMetadata(I.second, ValueMap, ValueMapperFlags,
- &TypeMap, &GValMaterializer));
+ // Copy over the metadata attachments without remapping.
+ Dst.copyMetadata(&Src, 0);
- // Splice the body of the source function into the dest function.
+ // Steal arguments and splice the body of Src into Dst.
+ Dst.stealArgumentListFrom(Src);
Dst.getBasicBlockList().splice(Dst.end(), Src.getBasicBlockList());
- // At this point, all of the instructions and values of the function are now
- // copied over. The only problem is that they are still referencing values in
- // the Source function as operands. Loop through all of the operands of the
- // functions and patch them up to point to the local versions.
- for (BasicBlock &BB : Dst)
- for (Instruction &I : BB)
- RemapInstruction(&I, ValueMap, RF_IgnoreMissingEntries | ValueMapperFlags,
- &TypeMap, &GValMaterializer);
-
- // There is no need to map the arguments anymore.
- for (Argument &Arg : Src.args())
- ValueMap.erase(&Arg);
-
- return false;
+ // Everything has been moved over. Remap it.
+ Mapper.scheduleRemapFunction(Dst);
+ return Error::success();
}
void IRLinker::linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src) {
- Constant *Aliasee = Src.getAliasee();
- Constant *Val = MapValue(Aliasee, AliasValueMap, ValueMapperFlags, &TypeMap,
- &LValMaterializer);
- Dst.setAliasee(Val);
+ Mapper.scheduleMapGlobalAliasee(Dst, *Src.getAliasee(), AliasMCID);
}
-bool IRLinker::linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src) {
+Error IRLinker::linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src) {
if (auto *F = dyn_cast<Function>(&Src))
return linkFunctionBody(cast<Function>(Dst), *F);
if (auto *GVar = dyn_cast<GlobalVariable>(&Src)) {
linkGlobalInit(cast<GlobalVariable>(Dst), *GVar);
- return false;
+ return Error::success();
}
linkAliasBody(cast<GlobalAlias>(Dst), cast<GlobalAlias>(Src));
- return false;
-}
-
-void IRLinker::findNeededSubprograms(ValueToValueMapTy &ValueMap) {
- // Track unneeded nodes to make it simpler to handle the case
- // where we are checking if an already-mapped SP is needed.
- NamedMDNode *CompileUnits = SrcM.getNamedMetadata("llvm.dbg.cu");
- if (!CompileUnits)
- return;
- for (unsigned I = 0, E = CompileUnits->getNumOperands(); I != E; ++I) {
- auto *CU = cast<DICompileUnit>(CompileUnits->getOperand(I));
- assert(CU && "Expected valid compile unit");
- // Ensure that we don't remove subprograms referenced by DIImportedEntity.
- // It is not legal to have a DIImportedEntity with a null entity or scope.
- // FIXME: The DISubprogram for functions not linked in but kept due to
- // being referenced by a DIImportedEntity should also get their
- // IsDefinition flag is unset.
- SmallPtrSet<DISubprogram *, 8> ImportedEntitySPs;
- for (auto *IE : CU->getImportedEntities()) {
- if (auto *SP = dyn_cast<DISubprogram>(IE->getEntity()))
- ImportedEntitySPs.insert(SP);
- if (auto *SP = dyn_cast<DISubprogram>(IE->getScope()))
- ImportedEntitySPs.insert(SP);
- }
- for (auto *Op : CU->getSubprograms()) {
- // Unless we were doing function importing and deferred metadata linking,
- // any needed SPs should have been mapped as they would be reached
- // from the function linked in (either on the function itself for linked
- // function bodies, or from DILocation on inlined instructions).
- assert(!(ValueMap.MD()[Op] && IsMetadataLinkingPostpass) &&
- "DISubprogram shouldn't be mapped yet");
- if (!ValueMap.MD()[Op] && !ImportedEntitySPs.count(Op))
- UnneededSubprograms.insert(Op);
- }
- }
- if (!IsMetadataLinkingPostpass)
- return;
- // In the case of metadata linking as a postpass (e.g. for function
- // importing), see which DISubprogram MD from the source has an associated
- // temporary metadata node, which means the SP was needed by an imported
- // function.
- for (auto MDI : MetadataToIDs) {
- const MDNode *Node = dyn_cast<MDNode>(MDI.first);
- if (!Node)
- continue;
- DISubprogram *SP = getDISubprogram(Node);
- if (!SP || !ValIDToTempMDMap->count(MDI.second))
- continue;
- UnneededSubprograms.erase(SP);
- }
-}
-
-// Squash null subprograms from compile unit subprogram lists.
-void IRLinker::stripNullSubprograms() {
- NamedMDNode *CompileUnits = DstM.getNamedMetadata("llvm.dbg.cu");
- if (!CompileUnits)
- return;
- for (unsigned I = 0, E = CompileUnits->getNumOperands(); I != E; ++I) {
- auto *CU = cast<DICompileUnit>(CompileUnits->getOperand(I));
- assert(CU && "Expected valid compile unit");
-
- SmallVector<Metadata *, 16> NewSPs;
- NewSPs.reserve(CU->getSubprograms().size());
- bool FoundNull = false;
- for (DISubprogram *SP : CU->getSubprograms()) {
- if (!SP) {
- FoundNull = true;
- continue;
- }
- NewSPs.push_back(SP);
- }
- if (FoundNull)
- CU->replaceSubprograms(MDTuple::get(CU->getContext(), NewSPs));
- }
+ return Error::success();
}
/// Insert all of the named MDNodes in Src into the Dest module.
void IRLinker::linkNamedMDNodes() {
- findNeededSubprograms(ValueMap);
- const NamedMDNode *SrcModFlags = SrcM.getModuleFlagsMetadata();
- for (const NamedMDNode &NMD : SrcM.named_metadata()) {
+ const NamedMDNode *SrcModFlags = SrcM->getModuleFlagsMetadata();
+ for (const NamedMDNode &NMD : SrcM->named_metadata()) {
// Don't link module flags here. Do them separately.
if (&NMD == SrcModFlags)
continue;
NamedMDNode *DestNMD = DstM.getOrInsertNamedMetadata(NMD.getName());
// Add Src elements into Dest node.
- for (const MDNode *op : NMD.operands())
- DestNMD->addOperand(MapMetadata(
- op, ValueMap, ValueMapperFlags | RF_NullMapMissingGlobalValues,
- &TypeMap, &GValMaterializer));
+ for (const MDNode *Op : NMD.operands())
+ DestNMD->addOperand(Mapper.mapMDNode(*Op));
}
- stripNullSubprograms();
}
/// Merge the linker flags in Src into the Dest module.
-bool IRLinker::linkModuleFlagsMetadata() {
+Error IRLinker::linkModuleFlagsMetadata() {
// If the source module has no module flags, we are done.
- const NamedMDNode *SrcModFlags = SrcM.getModuleFlagsMetadata();
+ const NamedMDNode *SrcModFlags = SrcM->getModuleFlagsMetadata();
if (!SrcModFlags)
- return false;
+ return Error::success();
// If the destination module doesn't have module flags yet, then just copy
// over the source module's flags.
@@ -1317,7 +1021,7 @@ bool IRLinker::linkModuleFlagsMetadata() {
for (unsigned I = 0, E = SrcModFlags->getNumOperands(); I != E; ++I)
DstModFlags->addOperand(SrcModFlags->getOperand(I));
- return false;
+ return Error::success();
}
// First build a map of the existing module flags and requirements.
@@ -1373,10 +1077,9 @@ bool IRLinker::linkModuleFlagsMetadata() {
if (DstBehaviorValue == Module::Override) {
// Diagnose inconsistent flags which both have override behavior.
if (SrcBehaviorValue == Module::Override &&
- SrcOp->getOperand(2) != DstOp->getOperand(2)) {
- emitError("linking module flags '" + ID->getString() +
- "': IDs have conflicting override values");
- }
+ SrcOp->getOperand(2) != DstOp->getOperand(2))
+ return stringErr("linking module flags '" + ID->getString() +
+ "': IDs have conflicting override values");
continue;
} else if (SrcBehaviorValue == Module::Override) {
// Update the destination flag to that of the source.
@@ -1386,11 +1089,9 @@ bool IRLinker::linkModuleFlagsMetadata() {
}
// Diagnose inconsistent merge behavior types.
- if (SrcBehaviorValue != DstBehaviorValue) {
- emitError("linking module flags '" + ID->getString() +
- "': IDs have conflicting behaviors");
- continue;
- }
+ if (SrcBehaviorValue != DstBehaviorValue)
+ return stringErr("linking module flags '" + ID->getString() +
+ "': IDs have conflicting behaviors");
auto replaceDstValue = [&](MDNode *New) {
Metadata *FlagOps[] = {DstOp->getOperand(0), ID, New};
@@ -1406,10 +1107,9 @@ bool IRLinker::linkModuleFlagsMetadata() {
llvm_unreachable("not possible");
case Module::Error: {
// Emit an error if the values differ.
- if (SrcOp->getOperand(2) != DstOp->getOperand(2)) {
- emitError("linking module flags '" + ID->getString() +
- "': IDs have conflicting values");
- }
+ if (SrcOp->getOperand(2) != DstOp->getOperand(2))
+ return stringErr("linking module flags '" + ID->getString() +
+ "': IDs have conflicting values");
continue;
}
case Module::Warning: {
@@ -1452,14 +1152,11 @@ bool IRLinker::linkModuleFlagsMetadata() {
Metadata *ReqValue = Requirement->getOperand(1);
MDNode *Op = Flags[Flag].first;
- if (!Op || Op->getOperand(2) != ReqValue) {
- emitError("linking module flags '" + Flag->getString() +
- "': does not have the required value");
- continue;
- }
+ if (!Op || Op->getOperand(2) != ReqValue)
+ return stringErr("linking module flags '" + Flag->getString() +
+ "': does not have the required value");
}
-
- return HasError;
+ return Error::success();
}
// This function returns true if the triples match.
@@ -1483,41 +1180,47 @@ static std::string mergeTriples(const Triple &SrcTriple,
return DstTriple.str();
}
-bool IRLinker::run() {
+Error IRLinker::run() {
+ // Ensure metadata materialized before value mapping.
+ if (SrcM->getMaterializer())
+ if (std::error_code EC = SrcM->getMaterializer()->materializeMetadata())
+ return errorCodeToError(EC);
+
// Inherit the target data from the source module if the destination module
// doesn't have one already.
if (DstM.getDataLayout().isDefault())
- DstM.setDataLayout(SrcM.getDataLayout());
+ DstM.setDataLayout(SrcM->getDataLayout());
- if (SrcM.getDataLayout() != DstM.getDataLayout()) {
+ if (SrcM->getDataLayout() != DstM.getDataLayout()) {
emitWarning("Linking two modules of different data layouts: '" +
- SrcM.getModuleIdentifier() + "' is '" +
- SrcM.getDataLayoutStr() + "' whereas '" +
+ SrcM->getModuleIdentifier() + "' is '" +
+ SrcM->getDataLayoutStr() + "' whereas '" +
DstM.getModuleIdentifier() + "' is '" +
DstM.getDataLayoutStr() + "'\n");
}
// Copy the target triple from the source to dest if the dest's is empty.
- if (DstM.getTargetTriple().empty() && !SrcM.getTargetTriple().empty())
- DstM.setTargetTriple(SrcM.getTargetTriple());
+ if (DstM.getTargetTriple().empty() && !SrcM->getTargetTriple().empty())
+ DstM.setTargetTriple(SrcM->getTargetTriple());
- Triple SrcTriple(SrcM.getTargetTriple()), DstTriple(DstM.getTargetTriple());
+ Triple SrcTriple(SrcM->getTargetTriple()), DstTriple(DstM.getTargetTriple());
- if (!SrcM.getTargetTriple().empty() && !triplesMatch(SrcTriple, DstTriple))
+ if (!SrcM->getTargetTriple().empty() && !triplesMatch(SrcTriple, DstTriple))
emitWarning("Linking two modules of different target triples: " +
- SrcM.getModuleIdentifier() + "' is '" + SrcM.getTargetTriple() +
- "' whereas '" + DstM.getModuleIdentifier() + "' is '" +
- DstM.getTargetTriple() + "'\n");
+ SrcM->getModuleIdentifier() + "' is '" +
+ SrcM->getTargetTriple() + "' whereas '" +
+ DstM.getModuleIdentifier() + "' is '" + DstM.getTargetTriple() +
+ "'\n");
DstM.setTargetTriple(mergeTriples(SrcTriple, DstTriple));
// Append the module inline asm string.
- if (!SrcM.getModuleInlineAsm().empty()) {
+ if (!SrcM->getModuleInlineAsm().empty()) {
if (DstM.getModuleInlineAsm().empty())
- DstM.setModuleInlineAsm(SrcM.getModuleInlineAsm());
+ DstM.setModuleInlineAsm(SrcM->getModuleInlineAsm());
else
DstM.setModuleInlineAsm(DstM.getModuleInlineAsm() + "\n" +
- SrcM.getModuleInlineAsm());
+ SrcM->getModuleInlineAsm());
}
// Loop over all of the linked values to compute type mappings.
@@ -1534,54 +1237,23 @@ bool IRLinker::run() {
continue;
assert(!GV->isDeclaration());
- MapValue(GV, ValueMap, ValueMapperFlags, &TypeMap, &GValMaterializer);
- if (HasError)
- return true;
+ Mapper.mapValue(*GV);
+ if (FoundError)
+ return std::move(*FoundError);
}
// Note that we are done linking global value bodies. This prevents
// metadata linking from creating new references.
DoneLinkingBodies = true;
+ Mapper.addFlags(RF_NullMapMissingGlobalValues);
// Remap all of the named MDNodes in Src into the DstM module. We do this
// after linking GlobalValues so that MDNodes that reference GlobalValues
// are properly remapped.
- if (shouldLinkMetadata()) {
- // Even if just linking metadata we should link decls above in case
- // any are referenced by metadata. IRLinker::shouldLink ensures that
- // we don't actually link anything from source.
- if (IsMetadataLinkingPostpass) {
- // Ensure metadata materialized
- if (SrcM.getMaterializer()->materializeMetadata())
- return true;
- SrcM.getMaterializer()->saveMetadataList(MetadataToIDs,
- /* OnlyTempMD = */ false);
- }
-
- linkNamedMDNodes();
-
- if (IsMetadataLinkingPostpass) {
- // Handle anything left in the ValIDToTempMDMap, such as metadata nodes
- // not reached by the dbg.cu NamedMD (i.e. only reached from
- // instructions).
- // Walk the MetadataToIDs once to find the set of new (imported) MD
- // that still has corresponding temporary metadata, and invoke metadata
- // mapping on each one.
- for (auto MDI : MetadataToIDs) {
- if (!ValIDToTempMDMap->count(MDI.second))
- continue;
- MapMetadata(MDI.first, ValueMap, ValueMapperFlags, &TypeMap,
- &GValMaterializer);
- }
- assert(ValIDToTempMDMap->empty());
- }
-
- // Merge the module flags into the DstM module.
- if (linkModuleFlagsMetadata())
- return true;
- }
+ linkNamedMDNodes();
- return false;
+ // Merge the module flags into the DstM module.
+ return linkModuleFlagsMetadata();
}
IRMover::StructTypeKeyInfo::KeyTy::KeyTy(ArrayRef<Type *> E, bool P)
@@ -1591,11 +1263,7 @@ IRMover::StructTypeKeyInfo::KeyTy::KeyTy(const StructType *ST)
: ETypes(ST->elements()), IsPacked(ST->isPacked()) {}
bool IRMover::StructTypeKeyInfo::KeyTy::operator==(const KeyTy &That) const {
- if (IsPacked != That.IsPacked)
- return false;
- if (ETypes != That.ETypes)
- return false;
- return true;
+ return IsPacked == That.IsPacked && ETypes == That.ETypes;
}
bool IRMover::StructTypeKeyInfo::KeyTy::operator!=(const KeyTy &That) const {
@@ -1628,12 +1296,8 @@ bool IRMover::StructTypeKeyInfo::isEqual(const KeyTy &LHS,
bool IRMover::StructTypeKeyInfo::isEqual(const StructType *LHS,
const StructType *RHS) {
- if (RHS == getEmptyKey())
- return LHS == getEmptyKey();
-
- if (RHS == getTombstoneKey())
- return LHS == getTombstoneKey();
-
+ if (RHS == getEmptyKey() || RHS == getTombstoneKey())
+ return LHS == RHS;
return KeyTy(LHS) == KeyTy(RHS);
}
@@ -1660,18 +1324,14 @@ IRMover::IdentifiedStructTypeSet::findNonOpaque(ArrayRef<Type *> ETypes,
bool IsPacked) {
IRMover::StructTypeKeyInfo::KeyTy Key(ETypes, IsPacked);
auto I = NonOpaqueStructTypes.find_as(Key);
- if (I == NonOpaqueStructTypes.end())
- return nullptr;
- return *I;
+ return I == NonOpaqueStructTypes.end() ? nullptr : *I;
}
bool IRMover::IdentifiedStructTypeSet::hasType(StructType *Ty) {
if (Ty->isOpaque())
return OpaqueStructTypes.count(Ty);
auto I = NonOpaqueStructTypes.find(Ty);
- if (I == NonOpaqueStructTypes.end())
- return false;
- return *I == Ty;
+ return I == NonOpaqueStructTypes.end() ? false : *I == Ty;
}
IRMover::IRMover(Module &M) : Composite(M) {
@@ -1685,14 +1345,12 @@ IRMover::IRMover(Module &M) : Composite(M) {
}
}
-bool IRMover::move(
- Module &Src, ArrayRef<GlobalValue *> ValuesToLink,
- std::function<void(GlobalValue &, ValueAdder Add)> AddLazyFor,
- DenseMap<unsigned, MDNode *> *ValIDToTempMDMap,
- bool IsMetadataLinkingPostpass) {
- IRLinker TheIRLinker(Composite, IdentifiedStructTypes, Src, ValuesToLink,
- AddLazyFor, ValIDToTempMDMap, IsMetadataLinkingPostpass);
- bool RetCode = TheIRLinker.run();
+Error IRMover::move(
+ std::unique_ptr<Module> Src, ArrayRef<GlobalValue *> ValuesToLink,
+ std::function<void(GlobalValue &, ValueAdder Add)> AddLazyFor) {
+ IRLinker TheIRLinker(Composite, SharedMDs, IdentifiedStructTypes,
+ std::move(Src), ValuesToLink, std::move(AddLazyFor));
+ Error E = TheIRLinker.run();
Composite.dropTriviallyDeadConstantArrays();
- return RetCode;
+ return E;
}
diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp
index 6ffa71e147790..fae9c95ebe8fb 100644
--- a/lib/Linker/LinkModules.cpp
+++ b/lib/Linker/LinkModules.cpp
@@ -11,13 +11,15 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Linker/Linker.h"
#include "LinkDiagnosticInfo.h"
#include "llvm-c/Linker.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/Linker/Linker.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Transforms/Utils/FunctionImportUtils.h"
using namespace llvm;
namespace {
@@ -26,7 +28,7 @@ namespace {
/// entrypoint for this file.
class ModuleLinker {
IRMover &Mover;
- Module &SrcM;
+ std::unique_ptr<Module> SrcM;
SetVector<GlobalValue *> ValuesToLink;
StringSet<> Internalize;
@@ -34,31 +36,19 @@ class ModuleLinker {
/// For symbol clashes, prefer those from Src.
unsigned Flags;
- /// Function index passed into ModuleLinker for using in function
- /// importing/exporting handling.
- const FunctionInfoIndex *ImportIndex;
-
/// Functions to import from source module, all other functions are
/// imported as declarations instead of definitions.
- DenseSet<const GlobalValue *> *FunctionsToImport;
-
- /// 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 = false;
-
- /// Association between metadata value id and temporary metadata that
- /// remains unmapped after function importing. Saved during function
- /// importing and consumed during the metadata linking postpass.
- DenseMap<unsigned, MDNode *> *ValIDToTempMDMap;
+ DenseSet<const GlobalValue *> *GlobalsToImport;
/// Used as the callback for lazy linking.
/// The mover has just hit GV and we have to decide if it, and other members
/// of the same comdat, should be linked. Every member to be linked is passed
/// to Add.
- void addLazyFor(GlobalValue &GV, IRMover::ValueAdder Add);
+ void addLazyFor(GlobalValue &GV, const IRMover::ValueAdder &Add);
+ bool shouldLinkReferencedLinkOnce() {
+ return !(Flags & Linker::DontForceLinkLinkonceODR);
+ }
bool shouldOverrideFromSrc() { return Flags & Linker::OverrideFromSrc; }
bool shouldLinkOnlyNeeded() { return Flags & Linker::LinkOnlyNeeded; }
bool shouldInternalizeLinkedSymbols() {
@@ -70,7 +60,7 @@ class ModuleLinker {
/// Should we have mover and linker error diag info?
bool emitError(const Twine &Message) {
- SrcM.getContext().diagnose(LinkDiagnosticInfo(DS_Error, Message));
+ SrcM->getContext().diagnose(LinkDiagnosticInfo(DS_Error, Message));
return true;
}
@@ -85,8 +75,8 @@ class ModuleLinker {
ComdatsChosen;
bool getComdatResult(const Comdat *SrcC, Comdat::SelectionKind &SK,
bool &LinkFromSrc);
- // Keep track of the global value members of each comdat in source.
- DenseMap<const Comdat *, std::vector<GlobalValue *>> ComdatMembers;
+ // Keep track of the lazy linked global members of each comdat in source.
+ DenseMap<const Comdat *, std::vector<GlobalValue *>> LazyComdatMembers;
/// Given a global in the source module, return the global in the
/// destination module that is being linked to, if any.
@@ -111,289 +101,36 @@ class ModuleLinker {
return DGV;
}
+ /// Drop GV if it is a member of a comdat that we are dropping.
+ /// This can happen with COFF's largest selection kind.
+ void dropReplacedComdat(GlobalValue &GV,
+ const DenseSet<const Comdat *> &ReplacedDstComdats);
+
bool linkIfNeeded(GlobalValue &GV);
/// Helper method to check if we are importing from the current source
/// module.
- bool isPerformingImport() const { return FunctionsToImport != nullptr; }
+ bool isPerformingImport() const { return GlobalsToImport != nullptr; }
/// 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);
public:
- ModuleLinker(IRMover &Mover, Module &SrcM, unsigned Flags,
- const FunctionInfoIndex *Index = nullptr,
- DenseSet<const GlobalValue *> *FunctionsToImport = nullptr,
- DenseMap<unsigned, MDNode *> *ValIDToTempMDMap = nullptr)
- : Mover(Mover), SrcM(SrcM), Flags(Flags), ImportIndex(Index),
- FunctionsToImport(FunctionsToImport),
- ValIDToTempMDMap(ValIDToTempMDMap) {
- assert((ImportIndex || !FunctionsToImport) &&
- "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 && !FunctionsToImport)
- HasExportedFunctions = ImportIndex->hasExportedFunctions(SrcM);
- assert((ValIDToTempMDMap || !FunctionsToImport) &&
- "Function importing must provide a ValIDToTempMDMap");
- }
+ ModuleLinker(IRMover &Mover, std::unique_ptr<Module> SrcM, unsigned Flags,
+ DenseSet<const GlobalValue *> *GlobalsToImport = nullptr)
+ : Mover(Mover), SrcM(std::move(SrcM)), Flags(Flags),
+ GlobalsToImport(GlobalsToImport) {}
bool run();
};
-
-/// Class to handle necessary GlobalValue changes required by ThinLTO including
-/// linkage changes and any necessary renaming.
-class ThinLTOGlobalProcessing {
- /// The Module which we are exporting or importing functions from.
- Module &M;
-
- /// Function index passed in for function importing/exporting handling.
- const FunctionInfoIndex *ImportIndex;
-
- /// Functions to import from this module, all other functions will be
- /// imported as declarations instead of definitions.
- DenseSet<const GlobalValue *> *FunctionsToImport;
-
- /// 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 = false;
-
- /// Populated during ThinLTO global processing with locals promoted
- /// to global scope in an exporting module, which now need to be linked
- /// in if calling from the ModuleLinker.
- SetVector<GlobalValue *> NewExportedValues;
-
- /// Check if we should promote the given local value to global scope.
- bool doPromoteLocalToGlobal(const GlobalValue *SGV);
-
- /// Helper methods to check if we are importing from or potentially
- /// exporting from the current source module.
- bool isPerformingImport() const { return FunctionsToImport != nullptr; }
- bool isModuleExporting() const { 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.
- std::string getName(const GlobalValue *SGV);
-
- /// Process globals so that they can be used in ThinLTO. This includes
- /// promoting local variables so that they can be reference externally by
- /// thin lto imported globals and converting strong external globals to
- /// available_externally.
- void processGlobalsForThinLTO();
- void processGlobalForThinLTO(GlobalValue &GV);
-
- /// 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);
-
-public:
- ThinLTOGlobalProcessing(
- Module &M, const FunctionInfoIndex *Index,
- DenseSet<const GlobalValue *> *FunctionsToImport = nullptr)
- : M(M), ImportIndex(Index), FunctionsToImport(FunctionsToImport) {
- // 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 (!FunctionsToImport)
- HasExportedFunctions = ImportIndex->hasExportedFunctions(M);
- }
-
- bool run();
-
- /// Access the promoted globals that are now exported and need to be linked.
- SetVector<GlobalValue *> &getNewExportedValues() { return NewExportedValues; }
-};
-}
-
-/// Checks if we should import SGV as a definition, otherwise import as a
-/// declaration.
-static bool
-doImportAsDefinitionImpl(const GlobalValue *SGV,
- DenseSet<const GlobalValue *> *FunctionsToImport) {
- auto *GA = dyn_cast<GlobalAlias>(SGV);
- if (GA) {
- if (GA->hasWeakAnyLinkage())
- return false;
- const GlobalObject *GO = GA->getBaseObject();
- if (!GO->hasLinkOnceODRLinkage())
- return false;
- return doImportAsDefinitionImpl(GO, FunctionsToImport);
- }
- // Always import GlobalVariable definitions, except for the special
- // case of WeakAny which are imported as ExternalWeak declarations
- // (see comments in ModuleLinker::getLinkage). The linkage changes
- // described in ModuleLinker::getLinkage ensure the correct behavior (e.g.
- // global variables with external linkage are transformed to
- // available_externally definitions, which are ultimately turned into
- // declarations after the EliminateAvailableExternally pass).
- if (isa<GlobalVariable>(SGV) && !SGV->isDeclaration() &&
- !SGV->hasWeakAnyLinkage())
- return true;
- // Only import the function requested for importing.
- auto *SF = dyn_cast<Function>(SGV);
- if (SF && FunctionsToImport->count(SF))
- return true;
- // Otherwise no.
- return false;
-}
-
-bool ThinLTOGlobalProcessing::doImportAsDefinition(const GlobalValue *SGV) {
- if (!isPerformingImport())
- return false;
- return doImportAsDefinitionImpl(SGV, FunctionsToImport);
}
bool ModuleLinker::doImportAsDefinition(const GlobalValue *SGV) {
if (!isPerformingImport())
return false;
- return doImportAsDefinitionImpl(SGV, FunctionsToImport);
-}
-
-bool ThinLTOGlobalProcessing::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<GlobalVariable>(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;
-}
-
-std::string ThinLTOGlobalProcessing::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
-ThinLTOGlobalProcessing::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) && !dyn_cast<GlobalAlias>(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) && !dyn_cast<GlobalAlias>(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 linkIfNeeded, and we will assert in shouldLinkFromSource
- // if we try to import, so we simply return AppendingLinkage.
- return GlobalValue::AppendingLinkage;
-
- 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) && !dyn_cast<GlobalAlias>(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");
+ return FunctionImportGlobalProcessing::doImportAsDefinition(SGV,
+ GlobalsToImport);
}
static GlobalValue::VisibilityTypes
@@ -466,15 +203,13 @@ bool ModuleLinker::computeResultingSelectionKind(StringRef ComdatName,
const GlobalVariable *DstGV;
const GlobalVariable *SrcGV;
if (getComdatLeader(DstM, ComdatName, DstGV) ||
- getComdatLeader(SrcM, ComdatName, SrcGV))
+ getComdatLeader(*SrcM, ComdatName, SrcGV))
return true;
const DataLayout &DstDL = DstM.getDataLayout();
- const DataLayout &SrcDL = SrcM.getDataLayout();
- uint64_t DstSize =
- DstDL.getTypeAllocSize(DstGV->getType()->getPointerElementType());
- uint64_t SrcSize =
- SrcDL.getTypeAllocSize(SrcGV->getType()->getPointerElementType());
+ const DataLayout &SrcDL = SrcM->getDataLayout();
+ uint64_t DstSize = DstDL.getTypeAllocSize(DstGV->getValueType());
+ uint64_t SrcSize = SrcDL.getTypeAllocSize(SrcGV->getValueType());
if (Result == Comdat::SelectionKind::ExactMatch) {
if (SrcGV->getInitializer() != DstGV->getInitializer())
return emitError("Linking COMDATs named '" + ComdatName +
@@ -537,31 +272,15 @@ bool ModuleLinker::shouldLinkFromSource(bool &LinkFromSrc,
return false;
}
- bool SrcIsDeclaration = Src.isDeclarationForLinker();
- bool DestIsDeclaration = Dest.isDeclarationForLinker();
-
if (isPerformingImport()) {
- if (isa<Function>(&Src)) {
- // For functions, LinkFromSrc iff this is a function requested
- // for importing. For variables, decide below normally.
- LinkFromSrc = FunctionsToImport->count(&Src);
- return false;
- }
-
- // Check if this is an alias with an already existing definition
- // in Dest, which must have come from a prior importing pass from
- // the same Src module. Unlike imported function and variable
- // definitions, which are imported as available_externally and are
- // not definitions for the linker, that is not a valid linkage for
- // imported aliases which must be definitions. Simply use the existing
- // Dest copy.
- if (isa<GlobalAlias>(&Src) && !DestIsDeclaration) {
- assert(isa<GlobalAlias>(&Dest));
- LinkFromSrc = false;
- return false;
- }
+ // LinkFromSrc iff this is a global requested for importing.
+ LinkFromSrc = GlobalsToImport->count(&Src);
+ return false;
}
+ bool SrcIsDeclaration = Src.isDeclarationForLinker();
+ bool DestIsDeclaration = Dest.isDeclarationForLinker();
+
if (SrcIsDeclaration) {
// If Src is external or if both Src & Dest are external.. Just link the
// external globals, we aren't adding anything.
@@ -598,8 +317,8 @@ bool ModuleLinker::shouldLinkFromSource(bool &LinkFromSrc,
}
const DataLayout &DL = Dest.getParent()->getDataLayout();
- uint64_t DestSize = DL.getTypeAllocSize(Dest.getType()->getElementType());
- uint64_t SrcSize = DL.getTypeAllocSize(Src.getType()->getElementType());
+ uint64_t DestSize = DL.getTypeAllocSize(Dest.getValueType());
+ uint64_t SrcSize = DL.getTypeAllocSize(Src.getValueType());
LinkFromSrc = SrcSize > DestSize;
return false;
}
@@ -658,9 +377,10 @@ bool ModuleLinker::linkIfNeeded(GlobalValue &GV) {
DGV->setVisibility(Visibility);
GV.setVisibility(Visibility);
- bool HasUnnamedAddr = GV.hasUnnamedAddr() && DGV->hasUnnamedAddr();
- DGV->setUnnamedAddr(HasUnnamedAddr);
- GV.setUnnamedAddr(HasUnnamedAddr);
+ GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::getMinUnnamedAddr(
+ DGV->getUnnamedAddr(), GV.getUnnamedAddr());
+ DGV->setUnnamedAddr(UnnamedAddr);
+ GV.setUnnamedAddr(UnnamedAddr);
}
// Don't want to append to global_ctors list, for example, when we
@@ -670,12 +390,12 @@ bool ModuleLinker::linkIfNeeded(GlobalValue &GV) {
if (GV.hasAppendingLinkage() && isPerformingImport())
return false;
- if (isPerformingImport() && !doImportAsDefinition(&GV))
- return false;
-
- if (!DGV && !shouldOverrideFromSrc() &&
- (GV.hasLocalLinkage() || GV.hasLinkOnceLinkage() ||
- GV.hasAvailableExternallyLinkage()))
+ if (isPerformingImport()) {
+ if (!doImportAsDefinition(&GV))
+ return false;
+ } else if (!DGV && !shouldOverrideFromSrc() &&
+ (GV.hasLocalLinkage() || GV.hasLinkOnceLinkage() ||
+ GV.hasAvailableExternallyLinkage()))
return false;
if (GV.isDeclaration())
@@ -685,9 +405,8 @@ bool ModuleLinker::linkIfNeeded(GlobalValue &GV) {
bool LinkFromSrc;
Comdat::SelectionKind SK;
std::tie(SK, LinkFromSrc) = ComdatsChosen[SC];
- if (LinkFromSrc)
- ValuesToLink.insert(&GV);
- return false;
+ if (!LinkFromSrc)
+ return false;
}
bool LinkFromSrc = true;
@@ -698,9 +417,15 @@ bool ModuleLinker::linkIfNeeded(GlobalValue &GV) {
return false;
}
-void ModuleLinker::addLazyFor(GlobalValue &GV, IRMover::ValueAdder Add) {
+void ModuleLinker::addLazyFor(GlobalValue &GV, const IRMover::ValueAdder &Add) {
+ if (!shouldLinkReferencedLinkOnce())
+ // For ThinLTO we don't import more than what was required.
+ // The client has to guarantee that the linkonce will be availabe at link
+ // time (by promoting it to weak for instance).
+ return;
+
// Add these to the internalize list
- if (!GV.hasLinkOnceLinkage())
+ if (!GV.hasLinkOnceLinkage() && !shouldLinkOnlyNeeded())
return;
if (shouldInternalizeLinkedSymbols())
@@ -710,43 +435,59 @@ void ModuleLinker::addLazyFor(GlobalValue &GV, IRMover::ValueAdder Add) {
const Comdat *SC = GV.getComdat();
if (!SC)
return;
- for (GlobalValue *GV2 : ComdatMembers[SC]) {
- if (!GV2->hasLocalLinkage() && shouldInternalizeLinkedSymbols())
+ for (GlobalValue *GV2 : LazyComdatMembers[SC]) {
+ GlobalValue *DGV = getLinkedToGlobal(GV2);
+ bool LinkFromSrc = true;
+ if (DGV && shouldLinkFromSource(LinkFromSrc, *DGV, *GV2))
+ return;
+ if (!LinkFromSrc)
+ continue;
+ if (shouldInternalizeLinkedSymbols())
Internalize.insert(GV2->getName());
Add(*GV2);
}
}
-void ThinLTOGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {
- if (GV.hasLocalLinkage() &&
- (doPromoteLocalToGlobal(&GV) || isPerformingImport())) {
- GV.setName(getName(&GV));
- GV.setLinkage(getLinkage(&GV));
- if (!GV.hasLocalLinkage())
- GV.setVisibility(GlobalValue::HiddenVisibility);
- if (isModuleExporting())
- NewExportedValues.insert(&GV);
+void ModuleLinker::dropReplacedComdat(
+ GlobalValue &GV, const DenseSet<const Comdat *> &ReplacedDstComdats) {
+ Comdat *C = GV.getComdat();
+ if (!C)
+ return;
+ if (!ReplacedDstComdats.count(C))
+ return;
+ if (GV.use_empty()) {
+ GV.eraseFromParent();
return;
}
- GV.setLinkage(getLinkage(&GV));
-}
-
-void ThinLTOGlobalProcessing::processGlobalsForThinLTO() {
- for (GlobalVariable &GV : M.globals())
- processGlobalForThinLTO(GV);
- for (Function &SF : M)
- processGlobalForThinLTO(SF);
- for (GlobalAlias &GA : M.aliases())
- processGlobalForThinLTO(GA);
-}
-bool ThinLTOGlobalProcessing::run() {
- processGlobalsForThinLTO();
- return false;
+ if (auto *F = dyn_cast<Function>(&GV)) {
+ F->deleteBody();
+ } else if (auto *Var = dyn_cast<GlobalVariable>(&GV)) {
+ Var->setInitializer(nullptr);
+ } else {
+ auto &Alias = cast<GlobalAlias>(GV);
+ Module &M = *Alias.getParent();
+ PointerType &Ty = *cast<PointerType>(Alias.getType());
+ GlobalValue *Declaration;
+ if (auto *FTy = dyn_cast<FunctionType>(Alias.getValueType())) {
+ Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage, "", &M);
+ } else {
+ Declaration =
+ new GlobalVariable(M, Ty.getElementType(), /*isConstant*/ false,
+ GlobalValue::ExternalLinkage,
+ /*Initializer*/ nullptr);
+ }
+ Declaration->takeName(&Alias);
+ Alias.replaceAllUsesWith(Declaration);
+ Alias.eraseFromParent();
+ }
}
bool ModuleLinker::run() {
- for (const auto &SMEC : SrcM.getComdatSymbolTable()) {
+ Module &DstM = Mover.getModule();
+ DenseSet<const Comdat *> ReplacedDstComdats;
+
+ for (const auto &SMEC : SrcM->getComdatSymbolTable()) {
const Comdat &C = SMEC.getValue();
if (ComdatsChosen.count(&C))
continue;
@@ -755,50 +496,79 @@ bool ModuleLinker::run() {
if (getComdatResult(&C, SK, LinkFromSrc))
return true;
ComdatsChosen[&C] = std::make_pair(SK, LinkFromSrc);
+
+ if (!LinkFromSrc)
+ continue;
+
+ Module::ComdatSymTabType &ComdatSymTab = DstM.getComdatSymbolTable();
+ Module::ComdatSymTabType::iterator DstCI = ComdatSymTab.find(C.getName());
+ if (DstCI == ComdatSymTab.end())
+ continue;
+
+ // The source comdat is replacing the dest one.
+ const Comdat *DstC = &DstCI->second;
+ ReplacedDstComdats.insert(DstC);
}
- for (GlobalVariable &GV : SrcM.globals())
- if (const Comdat *SC = GV.getComdat())
- ComdatMembers[SC].push_back(&GV);
+ // Alias have to go first, since we are not able to find their comdats
+ // otherwise.
+ for (auto I = DstM.alias_begin(), E = DstM.alias_end(); I != E;) {
+ GlobalAlias &GV = *I++;
+ dropReplacedComdat(GV, ReplacedDstComdats);
+ }
+
+ for (auto I = DstM.global_begin(), E = DstM.global_end(); I != E;) {
+ GlobalVariable &GV = *I++;
+ dropReplacedComdat(GV, ReplacedDstComdats);
+ }
+
+ for (auto I = DstM.begin(), E = DstM.end(); I != E;) {
+ Function &GV = *I++;
+ dropReplacedComdat(GV, ReplacedDstComdats);
+ }
+
+ for (GlobalVariable &GV : SrcM->globals())
+ if (GV.hasLinkOnceLinkage())
+ if (const Comdat *SC = GV.getComdat())
+ LazyComdatMembers[SC].push_back(&GV);
- for (Function &SF : SrcM)
- if (const Comdat *SC = SF.getComdat())
- ComdatMembers[SC].push_back(&SF);
+ for (Function &SF : *SrcM)
+ if (SF.hasLinkOnceLinkage())
+ if (const Comdat *SC = SF.getComdat())
+ LazyComdatMembers[SC].push_back(&SF);
- for (GlobalAlias &GA : SrcM.aliases())
- if (const Comdat *SC = GA.getComdat())
- ComdatMembers[SC].push_back(&GA);
+ for (GlobalAlias &GA : SrcM->aliases())
+ if (GA.hasLinkOnceLinkage())
+ if (const Comdat *SC = GA.getComdat())
+ LazyComdatMembers[SC].push_back(&GA);
// Insert all of the globals in src into the DstM module... without linking
// initializers (which could refer to functions not yet mapped over).
- for (GlobalVariable &GV : SrcM.globals())
+ for (GlobalVariable &GV : SrcM->globals())
if (linkIfNeeded(GV))
return true;
- for (Function &SF : SrcM)
+ for (Function &SF : *SrcM)
if (linkIfNeeded(SF))
return true;
- for (GlobalAlias &GA : SrcM.aliases())
+ for (GlobalAlias &GA : SrcM->aliases())
if (linkIfNeeded(GA))
return true;
- if (ImportIndex) {
- ThinLTOGlobalProcessing ThinLTOProcessing(SrcM, ImportIndex,
- FunctionsToImport);
- if (ThinLTOProcessing.run())
- return true;
- for (auto *GV : ThinLTOProcessing.getNewExportedValues())
- ValuesToLink.insert(GV);
- }
-
for (unsigned I = 0; I < ValuesToLink.size(); ++I) {
GlobalValue *GV = ValuesToLink[I];
const Comdat *SC = GV->getComdat();
if (!SC)
continue;
- for (GlobalValue *GV2 : ComdatMembers[SC])
- ValuesToLink.insert(GV2);
+ for (GlobalValue *GV2 : LazyComdatMembers[SC]) {
+ GlobalValue *DGV = getLinkedToGlobal(GV2);
+ bool LinkFromSrc = true;
+ if (DGV && shouldLinkFromSource(LinkFromSrc, *DGV, *GV2))
+ return true;
+ if (LinkFromSrc)
+ ValuesToLink.insert(GV2);
+ }
}
if (shouldInternalizeLinkedSymbols()) {
@@ -806,13 +576,21 @@ bool ModuleLinker::run() {
Internalize.insert(GV->getName());
}
- if (Mover.move(SrcM, ValuesToLink.getArrayRef(),
- [this](GlobalValue &GV, IRMover::ValueAdder Add) {
- addLazyFor(GV, Add);
- },
- ValIDToTempMDMap, false))
+ // FIXME: Propagate Errors through to the caller instead of emitting
+ // diagnostics.
+ bool HasErrors = false;
+ if (Error E = Mover.move(std::move(SrcM), ValuesToLink.getArrayRef(),
+ [this](GlobalValue &GV, IRMover::ValueAdder Add) {
+ addLazyFor(GV, Add);
+ })) {
+ handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
+ DstM.getContext().diagnose(LinkDiagnosticInfo(DS_Error, EIB.message()));
+ HasErrors = true;
+ });
+ }
+ if (HasErrors)
return true;
- Module &DstM = Mover.getModule();
+
for (auto &P : Internalize) {
GlobalValue *GV = DstM.getNamedValue(P.first());
GV->setLinkage(GlobalValue::InternalLinkage);
@@ -824,30 +602,11 @@ bool ModuleLinker::run() {
Linker::Linker(Module &M) : Mover(M) {}
bool Linker::linkInModule(std::unique_ptr<Module> Src, unsigned Flags,
- const FunctionInfoIndex *Index,
- DenseSet<const GlobalValue *> *FunctionsToImport,
- DenseMap<unsigned, MDNode *> *ValIDToTempMDMap) {
- ModuleLinker ModLinker(Mover, *Src, Flags, Index, FunctionsToImport,
- ValIDToTempMDMap);
- return ModLinker.run();
-}
-
-bool Linker::linkInModuleForCAPI(Module &Src) {
- ModuleLinker ModLinker(Mover, Src, 0, nullptr, nullptr);
+ DenseSet<const GlobalValue *> *GlobalsToImport) {
+ ModuleLinker ModLinker(Mover, std::move(Src), Flags, GlobalsToImport);
return ModLinker.run();
}
-bool Linker::linkInMetadata(Module &Src,
- DenseMap<unsigned, MDNode *> *ValIDToTempMDMap) {
- SetVector<GlobalValue *> ValuesToLink;
- if (Mover.move(
- Src, ValuesToLink.getArrayRef(),
- [this](GlobalValue &GV, IRMover::ValueAdder Add) { assert(false); },
- ValIDToTempMDMap, true))
- return true;
- return false;
-}
-
//===----------------------------------------------------------------------===//
// LinkModules entrypoint.
//===----------------------------------------------------------------------===//
@@ -863,44 +622,10 @@ bool Linker::linkModules(Module &Dest, std::unique_ptr<Module> Src,
return L.linkInModule(std::move(Src), Flags);
}
-bool llvm::renameModuleForThinLTO(Module &M, const FunctionInfoIndex *Index) {
- ThinLTOGlobalProcessing ThinLTOProcessing(M, Index);
- return ThinLTOProcessing.run();
-}
-
//===----------------------------------------------------------------------===//
// C API.
//===----------------------------------------------------------------------===//
-static void diagnosticHandler(const DiagnosticInfo &DI, void *C) {
- auto *Message = reinterpret_cast<std::string *>(C);
- raw_string_ostream Stream(*Message);
- DiagnosticPrinterRawOStream DP(Stream);
- DI.print(DP);
-}
-
-LLVMBool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src,
- LLVMLinkerMode Unused, char **OutMessages) {
- Module *D = unwrap(Dest);
- LLVMContext &Ctx = D->getContext();
-
- LLVMContext::DiagnosticHandlerTy OldDiagnosticHandler =
- Ctx.getDiagnosticHandler();
- void *OldDiagnosticContext = Ctx.getDiagnosticContext();
- std::string Message;
- Ctx.setDiagnosticHandler(diagnosticHandler, &Message, true);
-
- Linker L(*D);
- Module *M = unwrap(Src);
- LLVMBool Result = L.linkInModuleForCAPI(*M);
-
- Ctx.setDiagnosticHandler(OldDiagnosticHandler, OldDiagnosticContext, true);
-
- if (OutMessages && Result)
- *OutMessages = strdup(Message.c_str());
- return Result;
-}
-
LLVMBool LLVMLinkModules2(LLVMModuleRef Dest, LLVMModuleRef Src) {
Module *D = unwrap(Dest);
std::unique_ptr<Module> M(unwrap(Src));
diff --git a/lib/Linker/Makefile b/lib/Linker/Makefile
deleted file mode 100644
index 19e646b748302..0000000000000
--- a/lib/Linker/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-##===- lib/Linker/Makefile ---------------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../..
-LIBRARYNAME = LLVMLinker
-BUILD_ARCHIVE := 1
-
-include $(LEVEL)/Makefile.common
-