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