blob: 6fd366ede518228840c12e963bb41cfbb942dbf6 [file] [log] [blame]
Chris Lattnerbd199fb2002-12-24 00:01:05 +00001//===-- jello.cpp - LLVM Just in Time Compiler ----------------------------===//
2//
3// This tool implements a just-in-time compiler for LLVM, allowing direct
4// execution of LLVM bytecode in an efficient manner.
5//
6//===----------------------------------------------------------------------===//
7
8#include "VM.h"
9#include "llvm/Target/TargetMachine.h"
10#include "llvm/CodeGen/MachineCodeEmitter.h"
11#include "llvm/Function.h"
12#include <dlfcn.h> // dlsym access
13
14
15VM::~VM() {
16 delete MCE;
17 delete &TM;
18}
19
20/// setupPassManager - Initialize the VM PassManager object with all of the
21/// passes needed for the target to generate code.
22///
23void VM::setupPassManager() {
24 // Compile LLVM Code down to machine code in the intermediate representation
25 if (TM.addPassesToJITCompile(PM)) {
26 std::cerr << "lli: target '" << TM.getName()
27 << "' doesn't support JIT compilation!\n";
28 abort();
29 }
30
31 // Turn the machine code intermediate representation into bytes in memory that
32 // may be executed.
33 //
34 if (TM.addPassesToEmitMachineCode(PM, *MCE)) {
35 std::cerr << "lli: target '" << TM.getName()
36 << "' doesn't support machine code emission!\n";
37 abort();
38 }
39}
40
41void *VM::resolveFunctionReference(void *RefAddr) {
42 Function *F = FunctionRefs[RefAddr];
43 assert(F && "Reference address not known!");
44
45 void *Addr = getPointerToFunction(F);
46 assert(Addr && "Pointer to function unknown!");
47
48 FunctionRefs.erase(RefAddr);
49 return Addr;
50}
51
52const std::string &VM::getFunctionReferencedName(void *RefAddr) {
53 return FunctionRefs[RefAddr]->getName();
54}
55
56static void NoopFn() {}
57
Chris Lattner0d448c02003-01-13 01:00:48 +000058/// getPointerToNamedFunction - This method returns the address of the specified
59/// function by using the dlsym function call. As such it is only useful for
60/// resolving library symbols, not code generated symbols.
61///
62void *VM::getPointerToNamedFunction(const std::string &Name) {
63 // If it's an external function, look it up in the process image...
64 void *Ptr = dlsym(0, Name.c_str());
65 if (Ptr == 0) {
66 std::cerr << "WARNING: Cannot resolve fn '" << Name
67 << "' using a dummy noop function instead!\n";
68 Ptr = (void*)NoopFn;
69 }
70
71 return Ptr;
72}
73
Chris Lattnerbd199fb2002-12-24 00:01:05 +000074/// getPointerToFunction - This method is used to get the address of the
75/// specified function, compiling it if neccesary.
76///
77void *VM::getPointerToFunction(const Function *F) {
78 void *&Addr = GlobalAddress[F]; // Function already code gen'd
79 if (Addr) return Addr;
80
Chris Lattner0d448c02003-01-13 01:00:48 +000081 if (F->isExternal())
82 return Addr = getPointerToNamedFunction(F->getName());
Chris Lattnerbd199fb2002-12-24 00:01:05 +000083
Chris Lattner66a84942003-05-08 21:08:43 +000084 static bool isAlreadyCodeGenerating = false;
85 if (isAlreadyCodeGenerating) {
Chris Lattner6125fdd2003-05-09 03:30:07 +000086 // Generate a function stub instead of reentering...
87 void *SAddr = emitStubForFunction(*F);
88 assert(SAddr && "Target machine doesn't support function stub generation!");
89 return SAddr;
Chris Lattner66a84942003-05-08 21:08:43 +000090 }
91
92 // FIXME: JIT all of the functions in the module. Eventually this will JIT
93 // functions on demand. This has the effect of populating all of the
94 // non-external functions into the GlobalAddress table.
95 isAlreadyCodeGenerating = true;
Chris Lattnerbd199fb2002-12-24 00:01:05 +000096 PM.run(getModule());
Chris Lattner66a84942003-05-08 21:08:43 +000097 isAlreadyCodeGenerating = false;
Chris Lattnerbd199fb2002-12-24 00:01:05 +000098
99 assert(Addr && "Code generation didn't add function to GlobalAddress table!");
100 return Addr;
101}