Home | History | Annotate | Download | only in Orc
      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 
     13 namespace {
     14 
     15 static struct RegisterJIT {
     16   RegisterJIT() { llvm::orc::OrcMCJITReplacement::Register(); }
     17 } JITRegistrator;
     18 
     19 }
     20 
     21 extern "C" void LLVMLinkInOrcMCJITReplacement() {}
     22 
     23 namespace llvm {
     24 namespace orc {
     25 
     26 GenericValue
     27 OrcMCJITReplacement::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