[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