Simplify the linking of recursive data.
authorRafael Espindola <rafael.espindola@gmail.com>
Fri, 27 Nov 2015 20:28:19 +0000 (20:28 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Fri, 27 Nov 2015 20:28:19 +0000 (20:28 +0000)
Now the ValueMapper has two callbacks. The first one maps the
declaration. The ValueMapper records the mapping and then materializes
the body/initializer.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254209 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
include/llvm/Transforms/Utils/ValueMapper.h
lib/Linker/LinkModules.cpp
lib/Transforms/Utils/ValueMapper.cpp
tools/gold/gold-plugin.cpp

index 8f4e844032c0d941bb45f9c059a36ed413ebbe11..242d2420162fd646702590c2d92fe97714f00925 100644 (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;
   };
index 17ce4f4ab73dda73284d7ecf19bc86da5f26ee4d..5687bd21e9984f6859cbbb071bd0e377d534f715 100644 (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.
index bd445dd367f4848bd75d08e21e6e5f1fbcbc58f7..afb39a1ae6df4898f16d48c3d3f52ca7d8e06685 100644 (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;
index c8d13385b1d491456851ec2e9e94c3b8232c0611..0a63c1d5153ccf8b51cfe23950d4c7ec0f2d55b6 100644 (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
index e563376ca9abda504ee14452246d4608a52c8034..b8318be27ce0033287a046a28cbefdf6d58ce39c 100644 (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;