1//===-------- OrcMCJITReplacement.cpp - Orc-based MCJIT replacement -------===//
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 "OrcMCJITReplacement.h"
11#include "llvm/ExecutionEngine/GenericValue.h"
12
13namespace {
14
15static struct RegisterJIT {
16  RegisterJIT() { llvm::orc::OrcMCJITReplacement::Register(); }
17} JITRegistrator;
18
19}
20
21extern "C" void LLVMLinkInOrcMCJITReplacement() {}
22
23namespace llvm {
24namespace orc {
25
26GenericValue
27OrcMCJITReplacement::runFunction(Function *F,
28                                 ArrayRef<GenericValue> ArgValues) {
29  assert(F && "Function *F was null at entry to run()");
30
31  void *FPtr = getPointerToFunction(F);
32  assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
33  FunctionType *FTy = F->getFunctionType();
34  Type *RetTy = FTy->getReturnType();
35
36  assert((FTy->getNumParams() == ArgValues.size() ||
37          (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&
38         "Wrong number of arguments passed into function!");
39  assert(FTy->getNumParams() == ArgValues.size() &&
40         "This doesn't support passing arguments through varargs (yet)!");
41
42  // Handle some common cases first.  These cases correspond to common `main'
43  // prototypes.
44  if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
45    switch (ArgValues.size()) {
46    case 3:
47      if (FTy->getParamType(0)->isIntegerTy(32) &&
48          FTy->getParamType(1)->isPointerTy() &&
49          FTy->getParamType(2)->isPointerTy()) {
50        int (*PF)(int, char **, const char **) =
51            (int (*)(int, char **, const char **))(intptr_t)FPtr;
52
53        // Call the function.
54        GenericValue rv;
55        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
56                                 (char **)GVTOP(ArgValues[1]),
57                                 (const char **)GVTOP(ArgValues[2])));
58        return rv;
59      }
60      break;
61    case 2:
62      if (FTy->getParamType(0)->isIntegerTy(32) &&
63          FTy->getParamType(1)->isPointerTy()) {
64        int (*PF)(int, char **) = (int (*)(int, char **))(intptr_t)FPtr;
65
66        // Call the function.
67        GenericValue rv;
68        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
69                                 (char **)GVTOP(ArgValues[1])));
70        return rv;
71      }
72      break;
73    case 1:
74      if (FTy->getNumParams() == 1 && FTy->getParamType(0)->isIntegerTy(32)) {
75        GenericValue rv;
76        int (*PF)(int) = (int (*)(int))(intptr_t)FPtr;
77        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
78        return rv;
79      }
80      break;
81    }
82  }
83
84  // Handle cases where no arguments are passed first.
85  if (ArgValues.empty()) {
86    GenericValue rv;
87    switch (RetTy->getTypeID()) {
88    default:
89      llvm_unreachable("Unknown return type for function call!");
90    case Type::IntegerTyID: {
91      unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth();
92      if (BitWidth == 1)
93        rv.IntVal = APInt(BitWidth, ((bool (*)())(intptr_t)FPtr)());
94      else if (BitWidth <= 8)
95        rv.IntVal = APInt(BitWidth, ((char (*)())(intptr_t)FPtr)());
96      else if (BitWidth <= 16)
97        rv.IntVal = APInt(BitWidth, ((short (*)())(intptr_t)FPtr)());
98      else if (BitWidth <= 32)
99        rv.IntVal = APInt(BitWidth, ((int (*)())(intptr_t)FPtr)());
100      else if (BitWidth <= 64)
101        rv.IntVal = APInt(BitWidth, ((int64_t (*)())(intptr_t)FPtr)());
102      else
103        llvm_unreachable("Integer types > 64 bits not supported");
104      return rv;
105    }
106    case Type::VoidTyID:
107      rv.IntVal = APInt(32, ((int (*)())(intptr_t)FPtr)());
108      return rv;
109    case Type::FloatTyID:
110      rv.FloatVal = ((float (*)())(intptr_t)FPtr)();
111      return rv;
112    case Type::DoubleTyID:
113      rv.DoubleVal = ((double (*)())(intptr_t)FPtr)();
114      return rv;
115    case Type::X86_FP80TyID:
116    case Type::FP128TyID:
117    case Type::PPC_FP128TyID:
118      llvm_unreachable("long double not supported yet");
119    case Type::PointerTyID:
120      return PTOGV(((void *(*)())(intptr_t)FPtr)());
121    }
122  }
123
124  llvm_unreachable("Full-featured argument passing not supported yet!");
125}
126
127} // End namespace orc.
128} // End namespace llvm.
129