ba1ecdf31a04d22cb36766fec212076b6d576b69
[oota-llvm.git] / lib / ExecutionEngine / JIT / VM.cpp
1 //===-- VM.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/Function.h"
10 #include "llvm/ModuleProvider.h"
11 #include "llvm/CodeGen/MachineCodeEmitter.h"
12 #include "llvm/Target/TargetMachine.h"
13
14 VM::~VM() {
15   delete MCE;
16   delete &TM;
17 }
18
19 /// setupPassManager - Initialize the VM PassManager object with all of the
20 /// passes needed for the target to generate code.
21 ///
22 void VM::setupPassManager() {
23   // Compile LLVM Code down to machine code in the intermediate representation
24   if (TM.addPassesToJITCompile(PM)) {
25     std::cerr << "lli: target '" << TM.getName()
26               << "' doesn't support JIT compilation!\n";
27     abort();
28   }
29
30   // Turn the machine code intermediate representation into bytes in memory that
31   // may be executed.
32   //
33   if (TM.addPassesToEmitMachineCode(PM, *MCE)) {
34     std::cerr << "lli: target '" << TM.getName()
35               << "' doesn't support machine code emission!\n";
36     abort();
37   }
38 }
39
40 /// runJITOnFunction - Run the FunctionPassManager full of
41 /// just-in-time compilation passes on F, hopefully filling in
42 /// GlobalAddress[F] with the address of F's machine code.
43 ///
44 void VM::runJITOnFunction (Function *F) {
45   static bool isAlreadyCodeGenerating = false;
46   assert(!isAlreadyCodeGenerating && "ERROR: RECURSIVE COMPILATION DETECTED!");
47
48   // JIT the function
49   isAlreadyCodeGenerating = true;
50   PM.run(*F);
51   isAlreadyCodeGenerating = false;
52 }
53
54 /// getPointerToFunction - This method is used to get the address of the
55 /// specified function, compiling it if neccesary.
56 ///
57 void *VM::getPointerToFunction(Function *F) {
58   void *&Addr = GlobalAddress[F];   // Check if function already code gen'd
59   if (Addr) return Addr;
60
61   // Make sure we read in the function if it exists in this Module
62   MP->materializeFunction(F);
63
64   if (F->isExternal())
65     return Addr = getPointerToNamedFunction(F->getName());
66
67   runJITOnFunction (F);
68   assert(Addr && "Code generation didn't add function to GlobalAddress table!");
69   return Addr;
70 }
71
72 /// recompileAndRelinkFunction - This method is used to force a function
73 /// which has already been compiled, to be compiled again, possibly
74 /// after it has been modified. Then the entry to the old copy is overwritten
75 /// with a branch to the new copy. If there was no old copy, this acts
76 /// just like VM::getPointerToFunction().
77 ///
78 void *VM::recompileAndRelinkFunction(Function *F) {
79   void *&Addr = GlobalAddress[F];   // Check if function already code gen'd
80
81   // If it's not already compiled (this is kind of weird) there is no
82   // reason to patch it up.
83   if (!Addr) { return getPointerToFunction (F); }
84
85   void *OldAddr = Addr;
86   Addr = 0;
87   runJITOnFunction (F);
88   assert(Addr && "Code generation didn't add function to GlobalAddress table!");
89   TM.replaceMachineCodeForFunction (OldAddr, Addr);
90   return Addr;
91 }