Simplify the linking of recursive data.

Now the ValueMapper has two callbacks. The first one maps the
declaration. The ValueMapper records the mapping and then materializes
the body/initializer.

llvm-svn: 254209
This commit is contained in:
Rafael Espindola 2015-11-27 20:28:19 +00:00
parent 54dd84d48f
commit 19b52383c5
5 changed files with 58 additions and 50 deletions

View File

@ -47,9 +47,8 @@ private:
class LambdaMaterializer final : public ValueMaterializer {
public:
LambdaMaterializer(MaterializerFtor M) : M(std::move(M)) {}
Value* materializeValueFor(Value *V) final {
return M(V);
}
Value *materializeDeclFor(Value *V) final { return M(V); }
private:
MaterializerFtor M;
};

View File

@ -46,10 +46,15 @@ namespace llvm {
ValueMaterializer &operator=(const ValueMaterializer&) = default;
public:
/// materializeValueFor - The client should implement this method if they
/// want to generate a mapped Value on demand. For example, if linking
/// lazily.
virtual Value *materializeValueFor(Value *V) = 0;
/// The client should implement this method if they want to generate a
/// mapped Value on demand. For example, if linking lazily.
virtual Value *materializeDeclFor(Value *V) = 0;
/// If the data being mapped is recursive, the above function can map
/// just the declaration and this is called to compute the initializer.
/// It is called after the mapping is recorded, so it doesn't need to worry
/// about recursion.
virtual void materializeInitFor(GlobalValue *New, GlobalValue *Old);
};
/// RemapFlags - These are flags that the value mapping APIs allow.

View File

@ -366,19 +366,13 @@ class ModuleLinker;
/// speeds up linking for modules with many/ lazily linked functions of which
/// few get used.
class ValueMaterializerTy final : public ValueMaterializer {
TypeMapTy &TypeMap;
Module *DstM;
std::vector<GlobalValue *> &LazilyLinkGlobalValues;
ModuleLinker *ModLinker;
public:
ValueMaterializerTy(TypeMapTy &TypeMap, Module *DstM,
std::vector<GlobalValue *> &LazilyLinkGlobalValues,
ModuleLinker *ModLinker)
: ValueMaterializer(), TypeMap(TypeMap), DstM(DstM),
LazilyLinkGlobalValues(LazilyLinkGlobalValues), ModLinker(ModLinker) {}
ValueMaterializerTy(ModuleLinker *ModLinker) : ModLinker(ModLinker) {}
Value *materializeValueFor(Value *V) override;
Value *materializeDeclFor(Value *V) override;
void materializeInitFor(GlobalValue *New, GlobalValue *Old) override;
};
class LinkDiagnosticInfo : public DiagnosticInfo {
@ -418,9 +412,6 @@ class ModuleLinker {
// Set of items not to link in from source.
SmallPtrSet<const Value *, 16> DoNotLinkFromSource;
// Vector of GlobalValues to lazily link in.
std::vector<GlobalValue *> LazilyLinkGlobalValues;
DiagnosticHandlerFunction DiagnosticHandler;
/// For symbol clashes, prefer those from Src.
@ -450,8 +441,7 @@ public:
DiagnosticHandlerFunction DiagnosticHandler, unsigned Flags,
const FunctionInfoIndex *Index = nullptr,
Function *FuncToImport = nullptr)
: DstM(dstM), SrcM(srcM), TypeMap(Set),
ValMaterializer(TypeMap, DstM, LazilyLinkGlobalValues, this),
: DstM(dstM), SrcM(srcM), TypeMap(Set), ValMaterializer(this),
DiagnosticHandler(DiagnosticHandler), Flags(Flags), ImportIndex(Index),
ImportFunction(FuncToImport), HasExportedFunctions(false),
DoneLinkingBodies(false) {
@ -466,7 +456,10 @@ public:
}
bool run();
Value *materializeDeclFor(Value *V);
void materializeInitFor(GlobalValue *New, GlobalValue *Old);
private:
bool shouldOverrideFromSrc() { return Flags & Linker::OverrideFromSrc; }
bool shouldLinkOnlyNeeded() { return Flags & Linker::LinkOnlyNeeded; }
bool shouldInternalizeLinkedSymbols() {
@ -484,7 +477,6 @@ public:
/// Check if all global value body linking is complete.
bool doneLinkingBodies() { return DoneLinkingBodies; }
private:
bool shouldLinkFromSource(bool &LinkFromSrc, const GlobalValue &Dest,
const GlobalValue &Src);
@ -901,7 +893,11 @@ GlobalValue *ModuleLinker::copyGlobalValueProto(TypeMapTy &TypeMap,
return NewGV;
}
Value *ValueMaterializerTy::materializeValueFor(Value *V) {
Value *ValueMaterializerTy::materializeDeclFor(Value *V) {
return ModLinker->materializeDeclFor(V);
}
Value *ModuleLinker::materializeDeclFor(Value *V) {
auto *SGV = dyn_cast<GlobalValue>(V);
if (!SGV)
return nullptr;
@ -909,10 +905,10 @@ Value *ValueMaterializerTy::materializeValueFor(Value *V) {
// If we are done linking global value bodies (i.e. we are performing
// metadata linking), don't link in the global value due to this
// reference, simply map it to null.
if (ModLinker->doneLinkingBodies())
if (doneLinkingBodies())
return nullptr;
GlobalValue *DGV = ModLinker->copyGlobalValueProto(TypeMap, SGV);
GlobalValue *DGV = copyGlobalValueProto(TypeMap, SGV);
if (Comdat *SC = SGV->getComdat()) {
if (auto *DGO = dyn_cast<GlobalObject>(DGV)) {
@ -921,10 +917,27 @@ Value *ValueMaterializerTy::materializeValueFor(Value *V) {
}
}
LazilyLinkGlobalValues.push_back(SGV);
return DGV;
}
void ValueMaterializerTy::materializeInitFor(GlobalValue *New,
GlobalValue *Old) {
return ModLinker->materializeInitFor(New, Old);
}
void ModuleLinker::materializeInitFor(GlobalValue *New, GlobalValue *Old) {
if (isPerformingImport() && !doImportAsDefinition(Old))
return;
// Skip declarations that ValueMaterializer may have created in
// case we link in only some of SrcM.
if (shouldLinkOnlyNeeded() && Old->isDeclaration())
return;
assert(!Old->isDeclaration() && "users should not pass down decls");
linkGlobalValueBody(*Old);
}
bool ModuleLinker::getComdatLeader(Module *M, StringRef ComdatName,
const GlobalVariable *&GVar) {
const GlobalValue *GVal = M->getNamedValue(ComdatName);
@ -1602,10 +1615,10 @@ bool ModuleLinker::linkGlobalValueBody(GlobalValue &Src) {
// are linked in. Otherwise, linkonce and other lazy linked GVs will
// not be materialized if they aren't referenced.
for (auto *SGV : ComdatMembers[SC]) {
if (ValueMap[SGV])
auto *DGV = cast_or_null<GlobalValue>(ValueMap[SGV]);
if (DGV && !DGV->isDeclaration())
continue;
Value *NewV = ValMaterializer.materializeValueFor(SGV);
ValueMap[SGV] = NewV;
MapValue(SGV, ValueMap, RF_MoveDistinctMDs, &TypeMap, &ValMaterializer);
}
}
if (shouldInternalizeLinkedSymbols())
@ -1939,23 +1952,6 @@ bool ModuleLinker::run() {
linkGlobalValueBody(Src);
}
// Process vector of lazily linked in functions.
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.
if (shouldLinkOnlyNeeded() && SGV->isDeclaration())
continue;
assert(!SGV->isDeclaration() && "users should not pass down decls");
if (linkGlobalValueBody(*SGV))
return true;
}
// Note that we are done linking global value bodies. This prevents
// metadata linking from creating new references.
DoneLinkingBodies = true;

View File

@ -25,6 +25,8 @@ using namespace llvm;
// Out of line method to get vtable etc for class.
void ValueMapTypeRemapper::anchor() {}
void ValueMaterializer::anchor() {}
void ValueMaterializer::materializeInitFor(GlobalValue *New, GlobalValue *Old) {
}
Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM, RemapFlags Flags,
ValueMapTypeRemapper *TypeMapper,
@ -36,8 +38,14 @@ Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM, RemapFlags Flags,
// If we have a materializer and it can materialize a value, use that.
if (Materializer) {
if (Value *NewV = Materializer->materializeValueFor(const_cast<Value*>(V)))
return VM[V] = NewV;
if (Value *NewV =
Materializer->materializeDeclFor(const_cast<Value *>(V))) {
VM[V] = NewV;
if (auto *GV = dyn_cast<GlobalValue>(V))
Materializer->materializeInitFor(cast<GlobalValue>(NewV),
const_cast<GlobalValue *>(GV));
return NewV;
}
}
// Global values do not need to be seeded into the VM if they

View File

@ -554,11 +554,11 @@ class LocalValueMaterializer final : public ValueMaterializer {
public:
LocalValueMaterializer(DenseSet<GlobalValue *> &Dropped) : Dropped(Dropped) {}
Value *materializeValueFor(Value *V) override;
Value *materializeDeclFor(Value *V) override;
};
}
Value *LocalValueMaterializer::materializeValueFor(Value *V) {
Value *LocalValueMaterializer::materializeDeclFor(Value *V) {
auto *GO = dyn_cast<GlobalObject>(V);
if (!GO)
return nullptr;