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