[llvm-commits] CVS: llvm/lib/ExecutionEngine/JIT/Emitter.cpp JIT.cpp JIT.h

Chris Lattner lattner at cs.uiuc.edu
Fri Dec 19 21:37:11 PST 2003


Changes in directory llvm/lib/ExecutionEngine/JIT:

Emitter.cpp updated: 1.37 -> 1.38
JIT.cpp updated: 1.28 -> 1.29
JIT.h updated: 1.20 -> 1.21

---
Log message:

Implement PR135, lazy emission of global variables



---
Diffs of the changes:  (+78 -15)

Index: llvm/lib/ExecutionEngine/JIT/Emitter.cpp
diff -u llvm/lib/ExecutionEngine/JIT/Emitter.cpp:1.37 llvm/lib/ExecutionEngine/JIT/Emitter.cpp:1.38
--- llvm/lib/ExecutionEngine/JIT/Emitter.cpp:1.37	Fri Dec 19 19:46:27 2003
+++ llvm/lib/ExecutionEngine/JIT/Emitter.cpp	Fri Dec 19 21:36:47 2003
@@ -248,7 +248,11 @@
 uint64_t Emitter::getGlobalValueAddress(GlobalValue *V) {
   // Try looking up the function to see if it is already compiled, if not return
   // 0.
-  return (intptr_t)TheJIT->getPointerToGlobalIfAvailable(V);
+  if (isa<Function>(V))
+    return (intptr_t)TheJIT->getPointerToGlobalIfAvailable(V);
+  else {
+    return (intptr_t)TheJIT->getOrEmitGlobalVariable(cast<GlobalVariable>(V));
+  }
 }
 uint64_t Emitter::getGlobalValueAddress(const std::string &Name) {
   return (intptr_t)TheJIT->getPointerToNamedFunction(Name);


Index: llvm/lib/ExecutionEngine/JIT/JIT.cpp
diff -u llvm/lib/ExecutionEngine/JIT/JIT.cpp:1.28 llvm/lib/ExecutionEngine/JIT/JIT.cpp:1.29
--- llvm/lib/ExecutionEngine/JIT/JIT.cpp:1.28	Fri Dec 19 19:46:27 2003
+++ llvm/lib/ExecutionEngine/JIT/JIT.cpp	Fri Dec 19 21:36:47 2003
@@ -13,13 +13,16 @@
 //===----------------------------------------------------------------------===//
 
 #include "JIT.h"
+#include "llvm/DerivedTypes.h"
 #include "llvm/Function.h"
+#include "llvm/GlobalVariable.h"
 #include "llvm/ModuleProvider.h"
 #include "llvm/CodeGen/MachineCodeEmitter.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/ExecutionEngine/GenericValue.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetJITInfo.h"
+#include "Support/DynamicLinker.h"
 using namespace llvm;
 
 JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji)
@@ -39,8 +42,6 @@
               << "' doesn't support machine code emission!\n";
     abort();
   }
-
-  emitGlobals();
 }
 
 JIT::~JIT() {
@@ -81,22 +82,36 @@
   isAlreadyCodeGenerating = true;
   PM.run(*F);
   isAlreadyCodeGenerating = false;
+
+  // If the function referred to a global variable that had not yet been
+  // emitted, it allocates memory for the global, but doesn't emit it yet.  Emit
+  // all of these globals now.
+  while (!PendingGlobals.empty()) {
+    const GlobalVariable *GV = PendingGlobals.back();
+    PendingGlobals.pop_back();
+    EmitGlobalVariable(GV);
+  }
 }
 
 /// getPointerToFunction - This method is used to get the address of the
 /// specified function, compiling it if neccesary.
 ///
 void *JIT::getPointerToFunction(Function *F) {
-  void *&Addr = GlobalAddress[F];   // Check if function already code gen'd
-  if (Addr) return Addr;
+  if (void *Addr = getPointerToGlobalIfAvailable(F))
+    return Addr;   // Check if function already code gen'd
 
   // Make sure we read in the function if it exists in this Module
   MP->materializeFunction(F);
 
-  if (F->isExternal())
-    return Addr = getPointerToNamedFunction(F->getName());
+  if (F->isExternal()) {
+    void *Addr = getPointerToNamedFunction(F->getName());
+    addGlobalMapping(F, Addr);
+    return Addr;
+  }
 
   runJITOnFunction(F);
+
+  void *Addr = getPointerToGlobalIfAvailable(F);
   assert(Addr && "Code generation didn't add function to GlobalAddress table!");
   return Addr;
 }
@@ -107,8 +122,8 @@
 //
 void *JIT::getPointerToFunctionOrStub(Function *F) {
   // If we have already code generated the function, just return the address.
-  std::map<const GlobalValue*, void *>::iterator I = GlobalAddress.find(F);
-  if (I != GlobalAddress.end()) return I->second;
+  if (void *Addr = getPointerToGlobalIfAvailable(F))
+    return Addr;
 
   // If the target supports "stubs" for functions, get a stub now.
   if (void *Ptr = TJI.getJITStubForFunction(F, *MCE))
@@ -118,6 +133,33 @@
   return getPointerToFunction(F);
 }
 
+/// getOrEmitGlobalVariable - Return the address of the specified global
+/// variable, possibly emitting it to memory if needed.  This is used by the
+/// Emitter.
+void *JIT::getOrEmitGlobalVariable(const GlobalVariable *GV) {
+  void *Ptr = getPointerToGlobalIfAvailable(GV);
+  if (Ptr) return Ptr;
+
+  // If the global is external, just remember the address.
+  if (GV->isExternal()) {
+    Ptr = GetAddressOfSymbol(GV->getName().c_str());
+    if (Ptr == 0) {
+      std::cerr << "Could not resolve external global address: "
+                << GV->getName() << "\n";
+      abort();
+    }
+  } else {
+    // If the global hasn't been emitted to memory yet, allocate space.  We will
+    // actually initialize the global after current function has finished
+    // compilation.
+    Ptr =new char[getTargetData().getTypeSize(GV->getType()->getElementType())];
+    PendingGlobals.push_back(GV);
+  }
+  addGlobalMapping(GV, Ptr);
+  return Ptr;
+}
+
+
 /// recompileAndRelinkFunction - This method is used to force a function
 /// which has already been compiled, to be compiled again, possibly
 /// after it has been modified. Then the entry to the old copy is overwritten
@@ -125,16 +167,23 @@
 /// just like JIT::getPointerToFunction().
 ///
 void *JIT::recompileAndRelinkFunction(Function *F) {
-  void *&Addr = GlobalAddress[F];   // Check if function already code gen'd
+  void *OldAddr = getPointerToGlobalIfAvailable(F);
 
-  // If it's not already compiled (this is kind of weird) there is no
-  // reason to patch it up.
-  if (!Addr) { return getPointerToFunction (F); }
+  // If it's not already compiled there is no reason to patch it up.
+  if (OldAddr == 0) { return getPointerToFunction(F); }
 
-  void *OldAddr = Addr;
-  Addr = 0;
+  // Delete the old function mapping.
+  addGlobalMapping(F, 0);
+
+  // Destroy the machine code for this function.  FIXME: this should be
+  // incorporated into the code generator!
   MachineFunction::destruct(F);
+
+  // Recodegen the function
   runJITOnFunction(F);
+
+  // Update state, forward the old function to the new function.
+  void *Addr = getPointerToGlobalIfAvailable(F);
   assert(Addr && "Code generation didn't add function to GlobalAddress table!");
   TJI.replaceMachineCodeForFunction(OldAddr, Addr);
   return Addr;


Index: llvm/lib/ExecutionEngine/JIT/JIT.h
diff -u llvm/lib/ExecutionEngine/JIT/JIT.h:1.20 llvm/lib/ExecutionEngine/JIT/JIT.h:1.21
--- llvm/lib/ExecutionEngine/JIT/JIT.h:1.20	Fri Dec 19 19:46:27 2003
+++ llvm/lib/ExecutionEngine/JIT/JIT.h	Fri Dec 19 21:36:47 2003
@@ -34,6 +34,11 @@
   FunctionPassManager PM;  // Passes to compile a function
   MachineCodeEmitter *MCE; // MCE object
 
+  /// PendingGlobals - Global variables which have had memory allocated for them
+  /// while a function was code generated, but which have not been initialized
+  /// yet.
+  std::vector<const GlobalVariable*> PendingGlobals;
+
   JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji);
 public:
   ~JIT();
@@ -68,6 +73,11 @@
   /// compiling it if necessary.
   ///
   void *getPointerToFunction(Function *F);
+
+  /// getOrEmitGlobalVariable - Return the address of the specified global
+  /// variable, possibly emitting it to memory if needed.  This is used by the
+  /// Emitter.
+  void *getOrEmitGlobalVariable(const GlobalVariable *GV);
 
   /// getPointerToFunctionOrStub - If the specified function has been
   /// code-gen'd, return a pointer to the function.  If not, compile it, or use





More information about the llvm-commits mailing list