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