7309b80c4b6a654cd776f2a3133eecd2f4ed2805
[oota-llvm.git] / lib / ExecutionEngine / JIT / JIT.cpp
1 //===-- JIT.cpp - LLVM Just in Time Compiler ------------------------------===//
2 //
3 // This file implements the top-level support for creating a Just-In-Time
4 // compiler for the current architecture.
5 //
6 //===----------------------------------------------------------------------===//
7
8 #include "VM.h"
9 #include "llvm/Module.h"
10 #include "llvm/ModuleProvider.h"
11 #include "llvm/ExecutionEngine/GenericValue.h"
12 #include "llvm/Target/TargetMachine.h"
13 #include "llvm/Target/TargetMachineImpls.h"
14 #include "Support/CommandLine.h"
15
16 // FIXME: REMOVE THIS
17 #include "llvm/PassManager.h"
18
19 #if !defined(ENABLE_X86_JIT) && !defined(ENABLE_SPARC_JIT)
20 #define NO_JITS_ENABLED
21 #endif
22
23 namespace {
24   enum ArchName { x86, Sparc };
25
26 #ifndef NO_JITS_ENABLED
27   cl::opt<ArchName>
28   Arch("march", cl::desc("Architecture to JIT to:"), cl::Prefix,
29        cl::values(
30 #ifdef ENABLE_X86_JIT
31                   clEnumVal(x86, "  IA-32 (Pentium and above)"),
32 #endif
33 #ifdef ENABLE_SPARC_JIT
34                   clEnumValN(Sparc, "sparc", "  Sparc-V9"),
35 #endif
36                   0),
37 #if defined(ENABLE_X86_JIT)
38   cl::init(x86)
39 #elif defined(ENABLE_SPARC_JIT)
40   cl::init(Sparc)
41 #endif
42        );
43 #endif /* NO_JITS_ENABLED */
44 }
45
46 /// create - Create an return a new JIT compiler if there is one available
47 /// for the current target.  Otherwise, return null.
48 ///
49 ExecutionEngine *VM::create(ModuleProvider *MP) {
50   TargetMachine* (*TargetMachineAllocator)(const Module &) = 0;
51
52   // Allow a command-line switch to override what *should* be the default target
53   // machine for this platform. This allows for debugging a Sparc JIT on X86 --
54   // our X86 machines are much faster at recompiling LLVM and linking LLI.
55 #ifdef NO_JITS_ENABLED
56   return 0;
57 #endif
58
59   switch (Arch) {
60 #ifdef ENABLE_X86_JIT
61   case x86:
62     TargetMachineAllocator = allocateX86TargetMachine;
63     break;
64 #endif
65 #ifdef ENABLE_SPARC_JIT
66   case Sparc:
67     TargetMachineAllocator = allocateSparcTargetMachine;
68     break;
69 #endif
70   default:
71     assert(0 && "-march flag not supported on this host!");
72   }
73
74   // Allocate a target...
75   TargetMachine *Target = TargetMachineAllocator(*MP->getModule());
76   assert(Target && "Could not allocate target machine!");
77   
78   // Create the virtual machine object...
79   return new VM(MP, Target);
80 }
81
82 VM::VM(ModuleProvider *MP, TargetMachine *tm) : ExecutionEngine(MP), TM(*tm),
83   PM(MP)
84 {
85   setTargetData(TM.getTargetData());
86
87   // Initialize MCE
88   MCE = createEmitter(*this);
89
90   setupPassManager();
91
92 #ifdef ENABLE_SPARC_JIT
93   // THIS GOES BEYOND UGLY HACKS
94   if (TM.getName() == "UltraSparc-Native") {
95     extern Pass *createPreSelectionPass(TargetMachine &TM);
96     PassManager PM;
97     // Specialize LLVM code for this target machine and then
98     // run basic dataflow optimizations on LLVM code.
99     PM.add(createPreSelectionPass(TM));
100     // We cannot utilize function-at-a-time loading here because PreSelection
101     // is a ModulePass.
102     MP->materializeModule();
103     PM.run(*MP->getModule());
104   }
105 #endif
106
107   emitGlobals();
108 }
109
110 /// run - Start execution with the specified function and arguments.
111 ///
112 GenericValue VM::run(Function *F, const std::vector<GenericValue> &ArgValues)
113 {
114   assert (F && "Function *F was null at entry to run()");
115
116   int (*PF)(int, char **, const char **) =
117     (int(*)(int, char **, const char **))getPointerToFunction(F);
118   assert(PF != 0 && "Pointer to fn's code was null after getPointerToFunction");
119
120   // Call the function.
121   int ExitCode = PF(ArgValues[0].IntVal, (char **) GVTOP (ArgValues[1]),
122                     (const char **) GVTOP (ArgValues[2]));
123
124   // Run any atexit handlers now!
125   runAtExitHandlers();
126
127   GenericValue rv;
128   rv.IntVal = ExitCode;
129   return rv;
130 }