1//===-- MCJIT.cpp - MC-based Just-in-Time Compiler ------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "MCJIT.h"
11#include "MCJITMemoryManager.h"
12#include "llvm/DerivedTypes.h"
13#include "llvm/Function.h"
14#include "llvm/ExecutionEngine/GenericValue.h"
15#include "llvm/ExecutionEngine/MCJIT.h"
16#include "llvm/ExecutionEngine/JITMemoryManager.h"
17#include "llvm/MC/MCAsmInfo.h"
18#include "llvm/Support/ErrorHandling.h"
19#include "llvm/Support/DynamicLibrary.h"
20#include "llvm/Support/MemoryBuffer.h"
21#include "llvm/Support/MutexGuard.h"
22#include "llvm/Target/TargetData.h"
23
24using namespace llvm;
25
26namespace {
27
28static struct RegisterJIT {
29  RegisterJIT() { MCJIT::Register(); }
30} JITRegistrator;
31
32}
33
34extern "C" void LLVMLinkInMCJIT() {
35}
36
37ExecutionEngine *MCJIT::createJIT(Module *M,
38                                  std::string *ErrorStr,
39                                  JITMemoryManager *JMM,
40                                  bool GVsWithCode,
41                                  TargetMachine *TM) {
42  // Try to register the program as a source of symbols to resolve against.
43  //
44  // FIXME: Don't do this here.
45  sys::DynamicLibrary::LoadLibraryPermanently(0, NULL);
46
47  return new MCJIT(M, TM, new MCJITMemoryManager(JMM), GVsWithCode);
48}
49
50MCJIT::MCJIT(Module *m, TargetMachine *tm, RTDyldMemoryManager *MM,
51             bool AllocateGVsWithCode)
52  : ExecutionEngine(m), TM(tm), Ctx(0), MemMgr(MM), Dyld(MM),
53    isCompiled(false), M(m), OS(Buffer)  {
54
55  setTargetData(TM->getTargetData());
56}
57
58MCJIT::~MCJIT() {
59  delete MemMgr;
60  delete TM;
61}
62
63void MCJIT::emitObject(Module *m) {
64  /// Currently, MCJIT only supports a single module and the module passed to
65  /// this function call is expected to be the contained module.  The module
66  /// is passed as a parameter here to prepare for multiple module support in
67  /// the future.
68  assert(M == m);
69
70  // Get a thread lock to make sure we aren't trying to compile multiple times
71  MutexGuard locked(lock);
72
73  // FIXME: Track compilation state on a per-module basis when multiple modules
74  //        are supported.
75  // Re-compilation is not supported
76  if (isCompiled)
77    return;
78
79  PassManager PM;
80
81  PM.add(new TargetData(*TM->getTargetData()));
82
83  // Turn the machine code intermediate representation into bytes in memory
84  // that may be executed.
85  if (TM->addPassesToEmitMC(PM, Ctx, OS, false)) {
86    report_fatal_error("Target does not support MC emission!");
87  }
88
89  // Initialize passes.
90  // FIXME: When we support multiple modules, we'll want to move the code
91  // gen and finalization out of the constructor here and do it more
92  // on-demand as part of getPointerToFunction().
93  PM.run(*m);
94  // Flush the output buffer so the SmallVector gets its data.
95  OS.flush();
96
97  // Load the object into the dynamic linker.
98  MemoryBuffer* MB = MemoryBuffer::getMemBuffer(StringRef(Buffer.data(),
99                                                          Buffer.size()),
100                                                "", false);
101  if (Dyld.loadObject(MB))
102    report_fatal_error(Dyld.getErrorString());
103
104  // Resolve any relocations.
105  Dyld.resolveRelocations();
106
107  // FIXME: Add support for per-module compilation state
108  isCompiled = true;
109}
110
111void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) {
112  report_fatal_error("not yet implemented");
113}
114
115void *MCJIT::getPointerToFunction(Function *F) {
116  // FIXME: This should really return a uint64_t since it's a pointer in the
117  // target address space, not our local address space. That's part of the
118  // ExecutionEngine interface, though. Fix that when the old JIT finally
119  // dies.
120
121  // FIXME: Add support for per-module compilation state
122  if (!isCompiled)
123    emitObject(M);
124
125  if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
126    bool AbortOnFailure = !F->hasExternalWeakLinkage();
127    void *Addr = getPointerToNamedFunction(F->getName(), AbortOnFailure);
128    addGlobalMapping(F, Addr);
129    return Addr;
130  }
131
132  // FIXME: Should the Dyld be retaining module information? Probably not.
133  // FIXME: Should we be using the mangler for this? Probably.
134  //
135  // This is the accessor for the target address, so make sure to check the
136  // load address of the symbol, not the local address.
137  StringRef BaseName = F->getName();
138  if (BaseName[0] == '\1')
139    return (void*)Dyld.getSymbolLoadAddress(BaseName.substr(1));
140  return (void*)Dyld.getSymbolLoadAddress((TM->getMCAsmInfo()->getGlobalPrefix()
141                                       + BaseName).str());
142}
143
144void *MCJIT::recompileAndRelinkFunction(Function *F) {
145  report_fatal_error("not yet implemented");
146}
147
148void MCJIT::freeMachineCodeForFunction(Function *F) {
149  report_fatal_error("not yet implemented");
150}
151
152GenericValue MCJIT::runFunction(Function *F,
153                                const std::vector<GenericValue> &ArgValues) {
154  assert(F && "Function *F was null at entry to run()");
155
156  void *FPtr = getPointerToFunction(F);
157  assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
158  FunctionType *FTy = F->getFunctionType();
159  Type *RetTy = FTy->getReturnType();
160
161  assert((FTy->getNumParams() == ArgValues.size() ||
162          (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&
163         "Wrong number of arguments passed into function!");
164  assert(FTy->getNumParams() == ArgValues.size() &&
165         "This doesn't support passing arguments through varargs (yet)!");
166
167  // Handle some common cases first.  These cases correspond to common `main'
168  // prototypes.
169  if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
170    switch (ArgValues.size()) {
171    case 3:
172      if (FTy->getParamType(0)->isIntegerTy(32) &&
173          FTy->getParamType(1)->isPointerTy() &&
174          FTy->getParamType(2)->isPointerTy()) {
175        int (*PF)(int, char **, const char **) =
176          (int(*)(int, char **, const char **))(intptr_t)FPtr;
177
178        // Call the function.
179        GenericValue rv;
180        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
181                                 (char **)GVTOP(ArgValues[1]),
182                                 (const char **)GVTOP(ArgValues[2])));
183        return rv;
184      }
185      break;
186    case 2:
187      if (FTy->getParamType(0)->isIntegerTy(32) &&
188          FTy->getParamType(1)->isPointerTy()) {
189        int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr;
190
191        // Call the function.
192        GenericValue rv;
193        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
194                                 (char **)GVTOP(ArgValues[1])));
195        return rv;
196      }
197      break;
198    case 1:
199      if (FTy->getNumParams() == 1 &&
200          FTy->getParamType(0)->isIntegerTy(32)) {
201        GenericValue rv;
202        int (*PF)(int) = (int(*)(int))(intptr_t)FPtr;
203        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
204        return rv;
205      }
206      break;
207    }
208  }
209
210  // Handle cases where no arguments are passed first.
211  if (ArgValues.empty()) {
212    GenericValue rv;
213    switch (RetTy->getTypeID()) {
214    default: llvm_unreachable("Unknown return type for function call!");
215    case Type::IntegerTyID: {
216      unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth();
217      if (BitWidth == 1)
218        rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)());
219      else if (BitWidth <= 8)
220        rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)());
221      else if (BitWidth <= 16)
222        rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)());
223      else if (BitWidth <= 32)
224        rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)());
225      else if (BitWidth <= 64)
226        rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)());
227      else
228        llvm_unreachable("Integer types > 64 bits not supported");
229      return rv;
230    }
231    case Type::VoidTyID:
232      rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)());
233      return rv;
234    case Type::FloatTyID:
235      rv.FloatVal = ((float(*)())(intptr_t)FPtr)();
236      return rv;
237    case Type::DoubleTyID:
238      rv.DoubleVal = ((double(*)())(intptr_t)FPtr)();
239      return rv;
240    case Type::X86_FP80TyID:
241    case Type::FP128TyID:
242    case Type::PPC_FP128TyID:
243      llvm_unreachable("long double not supported yet");
244    case Type::PointerTyID:
245      return PTOGV(((void*(*)())(intptr_t)FPtr)());
246    }
247  }
248
249  llvm_unreachable("Full-featured argument passing not supported yet!");
250}
251
252void *MCJIT::getPointerToNamedFunction(const std::string &Name,
253                                       bool AbortOnFailure) {
254  // FIXME: Add support for per-module compilation state
255  if (!isCompiled)
256    emitObject(M);
257
258  if (!isSymbolSearchingDisabled() && MemMgr) {
259    void *ptr = MemMgr->getPointerToNamedFunction(Name, false);
260    if (ptr)
261      return ptr;
262  }
263
264  /// If a LazyFunctionCreator is installed, use it to get/create the function.
265  if (LazyFunctionCreator)
266    if (void *RP = LazyFunctionCreator(Name))
267      return RP;
268
269  if (AbortOnFailure) {
270    report_fatal_error("Program used external function '"+Name+
271                       "' which could not be resolved!");
272  }
273  return 0;
274}
275