xref: /aosp_15_r20/external/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- ExternalFunctions.cpp - Implement External Functions --------------===//
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 //  This file contains both code to deal with invoking "external" functions, but
11*9880d681SAndroid Build Coastguard Worker //  also contains code that implements "exported" external functions.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //  There are currently two mechanisms for handling external functions in the
14*9880d681SAndroid Build Coastguard Worker //  Interpreter.  The first is to implement lle_* wrapper functions that are
15*9880d681SAndroid Build Coastguard Worker //  specific to well-known library functions which manually translate the
16*9880d681SAndroid Build Coastguard Worker //  arguments from GenericValues and make the call.  If such a wrapper does
17*9880d681SAndroid Build Coastguard Worker //  not exist, and libffi is available, then the Interpreter will attempt to
18*9880d681SAndroid Build Coastguard Worker //  invoke the function using libffi, after finding its address.
19*9880d681SAndroid Build Coastguard Worker //
20*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
21*9880d681SAndroid Build Coastguard Worker 
22*9880d681SAndroid Build Coastguard Worker #include "Interpreter.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Config/config.h"     // Detect libffi
24*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DataLayout.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DerivedTypes.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/DynamicLibrary.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ManagedStatic.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Mutex.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/UniqueLock.h"
32*9880d681SAndroid Build Coastguard Worker #include <cmath>
33*9880d681SAndroid Build Coastguard Worker #include <csignal>
34*9880d681SAndroid Build Coastguard Worker #include <cstdio>
35*9880d681SAndroid Build Coastguard Worker #include <cstring>
36*9880d681SAndroid Build Coastguard Worker #include <map>
37*9880d681SAndroid Build Coastguard Worker 
38*9880d681SAndroid Build Coastguard Worker #ifdef HAVE_FFI_CALL
39*9880d681SAndroid Build Coastguard Worker #ifdef HAVE_FFI_H
40*9880d681SAndroid Build Coastguard Worker #include <ffi.h>
41*9880d681SAndroid Build Coastguard Worker #define USE_LIBFFI
42*9880d681SAndroid Build Coastguard Worker #elif HAVE_FFI_FFI_H
43*9880d681SAndroid Build Coastguard Worker #include <ffi/ffi.h>
44*9880d681SAndroid Build Coastguard Worker #define USE_LIBFFI
45*9880d681SAndroid Build Coastguard Worker #endif
46*9880d681SAndroid Build Coastguard Worker #endif
47*9880d681SAndroid Build Coastguard Worker 
48*9880d681SAndroid Build Coastguard Worker using namespace llvm;
49*9880d681SAndroid Build Coastguard Worker 
50*9880d681SAndroid Build Coastguard Worker static ManagedStatic<sys::Mutex> FunctionsLock;
51*9880d681SAndroid Build Coastguard Worker 
52*9880d681SAndroid Build Coastguard Worker typedef GenericValue (*ExFunc)(FunctionType *, ArrayRef<GenericValue>);
53*9880d681SAndroid Build Coastguard Worker static ManagedStatic<std::map<const Function *, ExFunc> > ExportedFunctions;
54*9880d681SAndroid Build Coastguard Worker static ManagedStatic<std::map<std::string, ExFunc> > FuncNames;
55*9880d681SAndroid Build Coastguard Worker 
56*9880d681SAndroid Build Coastguard Worker #ifdef USE_LIBFFI
57*9880d681SAndroid Build Coastguard Worker typedef void (*RawFunc)();
58*9880d681SAndroid Build Coastguard Worker static ManagedStatic<std::map<const Function *, RawFunc> > RawFunctions;
59*9880d681SAndroid Build Coastguard Worker #endif
60*9880d681SAndroid Build Coastguard Worker 
61*9880d681SAndroid Build Coastguard Worker static Interpreter *TheInterpreter;
62*9880d681SAndroid Build Coastguard Worker 
getTypeID(Type * Ty)63*9880d681SAndroid Build Coastguard Worker static char getTypeID(Type *Ty) {
64*9880d681SAndroid Build Coastguard Worker   switch (Ty->getTypeID()) {
65*9880d681SAndroid Build Coastguard Worker   case Type::VoidTyID:    return 'V';
66*9880d681SAndroid Build Coastguard Worker   case Type::IntegerTyID:
67*9880d681SAndroid Build Coastguard Worker     switch (cast<IntegerType>(Ty)->getBitWidth()) {
68*9880d681SAndroid Build Coastguard Worker       case 1:  return 'o';
69*9880d681SAndroid Build Coastguard Worker       case 8:  return 'B';
70*9880d681SAndroid Build Coastguard Worker       case 16: return 'S';
71*9880d681SAndroid Build Coastguard Worker       case 32: return 'I';
72*9880d681SAndroid Build Coastguard Worker       case 64: return 'L';
73*9880d681SAndroid Build Coastguard Worker       default: return 'N';
74*9880d681SAndroid Build Coastguard Worker     }
75*9880d681SAndroid Build Coastguard Worker   case Type::FloatTyID:   return 'F';
76*9880d681SAndroid Build Coastguard Worker   case Type::DoubleTyID:  return 'D';
77*9880d681SAndroid Build Coastguard Worker   case Type::PointerTyID: return 'P';
78*9880d681SAndroid Build Coastguard Worker   case Type::FunctionTyID:return 'M';
79*9880d681SAndroid Build Coastguard Worker   case Type::StructTyID:  return 'T';
80*9880d681SAndroid Build Coastguard Worker   case Type::ArrayTyID:   return 'A';
81*9880d681SAndroid Build Coastguard Worker   default: return 'U';
82*9880d681SAndroid Build Coastguard Worker   }
83*9880d681SAndroid Build Coastguard Worker }
84*9880d681SAndroid Build Coastguard Worker 
85*9880d681SAndroid Build Coastguard Worker // Try to find address of external function given a Function object.
86*9880d681SAndroid Build Coastguard Worker // Please note, that interpreter doesn't know how to assemble a
87*9880d681SAndroid Build Coastguard Worker // real call in general case (this is JIT job), that's why it assumes,
88*9880d681SAndroid Build Coastguard Worker // that all external functions has the same (and pretty "general") signature.
89*9880d681SAndroid Build Coastguard Worker // The typical example of such functions are "lle_X_" ones.
lookupFunction(const Function * F)90*9880d681SAndroid Build Coastguard Worker static ExFunc lookupFunction(const Function *F) {
91*9880d681SAndroid Build Coastguard Worker   // Function not found, look it up... start by figuring out what the
92*9880d681SAndroid Build Coastguard Worker   // composite function name should be.
93*9880d681SAndroid Build Coastguard Worker   std::string ExtName = "lle_";
94*9880d681SAndroid Build Coastguard Worker   FunctionType *FT = F->getFunctionType();
95*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = FT->getNumContainedTypes(); i != e; ++i)
96*9880d681SAndroid Build Coastguard Worker     ExtName += getTypeID(FT->getContainedType(i));
97*9880d681SAndroid Build Coastguard Worker   ExtName += ("_" + F->getName()).str();
98*9880d681SAndroid Build Coastguard Worker 
99*9880d681SAndroid Build Coastguard Worker   sys::ScopedLock Writer(*FunctionsLock);
100*9880d681SAndroid Build Coastguard Worker   ExFunc FnPtr = (*FuncNames)[ExtName];
101*9880d681SAndroid Build Coastguard Worker   if (!FnPtr)
102*9880d681SAndroid Build Coastguard Worker     FnPtr = (*FuncNames)[("lle_X_" + F->getName()).str()];
103*9880d681SAndroid Build Coastguard Worker   if (!FnPtr)  // Try calling a generic function... if it exists...
104*9880d681SAndroid Build Coastguard Worker     FnPtr = (ExFunc)(intptr_t)sys::DynamicLibrary::SearchForAddressOfSymbol(
105*9880d681SAndroid Build Coastguard Worker         ("lle_X_" + F->getName()).str());
106*9880d681SAndroid Build Coastguard Worker   if (FnPtr)
107*9880d681SAndroid Build Coastguard Worker     ExportedFunctions->insert(std::make_pair(F, FnPtr));  // Cache for later
108*9880d681SAndroid Build Coastguard Worker   return FnPtr;
109*9880d681SAndroid Build Coastguard Worker }
110*9880d681SAndroid Build Coastguard Worker 
111*9880d681SAndroid Build Coastguard Worker #ifdef USE_LIBFFI
ffiTypeFor(Type * Ty)112*9880d681SAndroid Build Coastguard Worker static ffi_type *ffiTypeFor(Type *Ty) {
113*9880d681SAndroid Build Coastguard Worker   switch (Ty->getTypeID()) {
114*9880d681SAndroid Build Coastguard Worker     case Type::VoidTyID: return &ffi_type_void;
115*9880d681SAndroid Build Coastguard Worker     case Type::IntegerTyID:
116*9880d681SAndroid Build Coastguard Worker       switch (cast<IntegerType>(Ty)->getBitWidth()) {
117*9880d681SAndroid Build Coastguard Worker         case 8:  return &ffi_type_sint8;
118*9880d681SAndroid Build Coastguard Worker         case 16: return &ffi_type_sint16;
119*9880d681SAndroid Build Coastguard Worker         case 32: return &ffi_type_sint32;
120*9880d681SAndroid Build Coastguard Worker         case 64: return &ffi_type_sint64;
121*9880d681SAndroid Build Coastguard Worker       }
122*9880d681SAndroid Build Coastguard Worker     case Type::FloatTyID:   return &ffi_type_float;
123*9880d681SAndroid Build Coastguard Worker     case Type::DoubleTyID:  return &ffi_type_double;
124*9880d681SAndroid Build Coastguard Worker     case Type::PointerTyID: return &ffi_type_pointer;
125*9880d681SAndroid Build Coastguard Worker     default: break;
126*9880d681SAndroid Build Coastguard Worker   }
127*9880d681SAndroid Build Coastguard Worker   // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
128*9880d681SAndroid Build Coastguard Worker   report_fatal_error("Type could not be mapped for use with libffi.");
129*9880d681SAndroid Build Coastguard Worker   return NULL;
130*9880d681SAndroid Build Coastguard Worker }
131*9880d681SAndroid Build Coastguard Worker 
ffiValueFor(Type * Ty,const GenericValue & AV,void * ArgDataPtr)132*9880d681SAndroid Build Coastguard Worker static void *ffiValueFor(Type *Ty, const GenericValue &AV,
133*9880d681SAndroid Build Coastguard Worker                          void *ArgDataPtr) {
134*9880d681SAndroid Build Coastguard Worker   switch (Ty->getTypeID()) {
135*9880d681SAndroid Build Coastguard Worker     case Type::IntegerTyID:
136*9880d681SAndroid Build Coastguard Worker       switch (cast<IntegerType>(Ty)->getBitWidth()) {
137*9880d681SAndroid Build Coastguard Worker         case 8: {
138*9880d681SAndroid Build Coastguard Worker           int8_t *I8Ptr = (int8_t *) ArgDataPtr;
139*9880d681SAndroid Build Coastguard Worker           *I8Ptr = (int8_t) AV.IntVal.getZExtValue();
140*9880d681SAndroid Build Coastguard Worker           return ArgDataPtr;
141*9880d681SAndroid Build Coastguard Worker         }
142*9880d681SAndroid Build Coastguard Worker         case 16: {
143*9880d681SAndroid Build Coastguard Worker           int16_t *I16Ptr = (int16_t *) ArgDataPtr;
144*9880d681SAndroid Build Coastguard Worker           *I16Ptr = (int16_t) AV.IntVal.getZExtValue();
145*9880d681SAndroid Build Coastguard Worker           return ArgDataPtr;
146*9880d681SAndroid Build Coastguard Worker         }
147*9880d681SAndroid Build Coastguard Worker         case 32: {
148*9880d681SAndroid Build Coastguard Worker           int32_t *I32Ptr = (int32_t *) ArgDataPtr;
149*9880d681SAndroid Build Coastguard Worker           *I32Ptr = (int32_t) AV.IntVal.getZExtValue();
150*9880d681SAndroid Build Coastguard Worker           return ArgDataPtr;
151*9880d681SAndroid Build Coastguard Worker         }
152*9880d681SAndroid Build Coastguard Worker         case 64: {
153*9880d681SAndroid Build Coastguard Worker           int64_t *I64Ptr = (int64_t *) ArgDataPtr;
154*9880d681SAndroid Build Coastguard Worker           *I64Ptr = (int64_t) AV.IntVal.getZExtValue();
155*9880d681SAndroid Build Coastguard Worker           return ArgDataPtr;
156*9880d681SAndroid Build Coastguard Worker         }
157*9880d681SAndroid Build Coastguard Worker       }
158*9880d681SAndroid Build Coastguard Worker     case Type::FloatTyID: {
159*9880d681SAndroid Build Coastguard Worker       float *FloatPtr = (float *) ArgDataPtr;
160*9880d681SAndroid Build Coastguard Worker       *FloatPtr = AV.FloatVal;
161*9880d681SAndroid Build Coastguard Worker       return ArgDataPtr;
162*9880d681SAndroid Build Coastguard Worker     }
163*9880d681SAndroid Build Coastguard Worker     case Type::DoubleTyID: {
164*9880d681SAndroid Build Coastguard Worker       double *DoublePtr = (double *) ArgDataPtr;
165*9880d681SAndroid Build Coastguard Worker       *DoublePtr = AV.DoubleVal;
166*9880d681SAndroid Build Coastguard Worker       return ArgDataPtr;
167*9880d681SAndroid Build Coastguard Worker     }
168*9880d681SAndroid Build Coastguard Worker     case Type::PointerTyID: {
169*9880d681SAndroid Build Coastguard Worker       void **PtrPtr = (void **) ArgDataPtr;
170*9880d681SAndroid Build Coastguard Worker       *PtrPtr = GVTOP(AV);
171*9880d681SAndroid Build Coastguard Worker       return ArgDataPtr;
172*9880d681SAndroid Build Coastguard Worker     }
173*9880d681SAndroid Build Coastguard Worker     default: break;
174*9880d681SAndroid Build Coastguard Worker   }
175*9880d681SAndroid Build Coastguard Worker   // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
176*9880d681SAndroid Build Coastguard Worker   report_fatal_error("Type value could not be mapped for use with libffi.");
177*9880d681SAndroid Build Coastguard Worker   return NULL;
178*9880d681SAndroid Build Coastguard Worker }
179*9880d681SAndroid Build Coastguard Worker 
ffiInvoke(RawFunc Fn,Function * F,ArrayRef<GenericValue> ArgVals,const DataLayout & TD,GenericValue & Result)180*9880d681SAndroid Build Coastguard Worker static bool ffiInvoke(RawFunc Fn, Function *F, ArrayRef<GenericValue> ArgVals,
181*9880d681SAndroid Build Coastguard Worker                       const DataLayout &TD, GenericValue &Result) {
182*9880d681SAndroid Build Coastguard Worker   ffi_cif cif;
183*9880d681SAndroid Build Coastguard Worker   FunctionType *FTy = F->getFunctionType();
184*9880d681SAndroid Build Coastguard Worker   const unsigned NumArgs = F->arg_size();
185*9880d681SAndroid Build Coastguard Worker 
186*9880d681SAndroid Build Coastguard Worker   // TODO: We don't have type information about the remaining arguments, because
187*9880d681SAndroid Build Coastguard Worker   // this information is never passed into ExecutionEngine::runFunction().
188*9880d681SAndroid Build Coastguard Worker   if (ArgVals.size() > NumArgs && F->isVarArg()) {
189*9880d681SAndroid Build Coastguard Worker     report_fatal_error("Calling external var arg function '" + F->getName()
190*9880d681SAndroid Build Coastguard Worker                       + "' is not supported by the Interpreter.");
191*9880d681SAndroid Build Coastguard Worker   }
192*9880d681SAndroid Build Coastguard Worker 
193*9880d681SAndroid Build Coastguard Worker   unsigned ArgBytes = 0;
194*9880d681SAndroid Build Coastguard Worker 
195*9880d681SAndroid Build Coastguard Worker   std::vector<ffi_type*> args(NumArgs);
196*9880d681SAndroid Build Coastguard Worker   for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
197*9880d681SAndroid Build Coastguard Worker        A != E; ++A) {
198*9880d681SAndroid Build Coastguard Worker     const unsigned ArgNo = A->getArgNo();
199*9880d681SAndroid Build Coastguard Worker     Type *ArgTy = FTy->getParamType(ArgNo);
200*9880d681SAndroid Build Coastguard Worker     args[ArgNo] = ffiTypeFor(ArgTy);
201*9880d681SAndroid Build Coastguard Worker     ArgBytes += TD.getTypeStoreSize(ArgTy);
202*9880d681SAndroid Build Coastguard Worker   }
203*9880d681SAndroid Build Coastguard Worker 
204*9880d681SAndroid Build Coastguard Worker   SmallVector<uint8_t, 128> ArgData;
205*9880d681SAndroid Build Coastguard Worker   ArgData.resize(ArgBytes);
206*9880d681SAndroid Build Coastguard Worker   uint8_t *ArgDataPtr = ArgData.data();
207*9880d681SAndroid Build Coastguard Worker   SmallVector<void*, 16> values(NumArgs);
208*9880d681SAndroid Build Coastguard Worker   for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
209*9880d681SAndroid Build Coastguard Worker        A != E; ++A) {
210*9880d681SAndroid Build Coastguard Worker     const unsigned ArgNo = A->getArgNo();
211*9880d681SAndroid Build Coastguard Worker     Type *ArgTy = FTy->getParamType(ArgNo);
212*9880d681SAndroid Build Coastguard Worker     values[ArgNo] = ffiValueFor(ArgTy, ArgVals[ArgNo], ArgDataPtr);
213*9880d681SAndroid Build Coastguard Worker     ArgDataPtr += TD.getTypeStoreSize(ArgTy);
214*9880d681SAndroid Build Coastguard Worker   }
215*9880d681SAndroid Build Coastguard Worker 
216*9880d681SAndroid Build Coastguard Worker   Type *RetTy = FTy->getReturnType();
217*9880d681SAndroid Build Coastguard Worker   ffi_type *rtype = ffiTypeFor(RetTy);
218*9880d681SAndroid Build Coastguard Worker 
219*9880d681SAndroid Build Coastguard Worker   if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, &args[0]) == FFI_OK) {
220*9880d681SAndroid Build Coastguard Worker     SmallVector<uint8_t, 128> ret;
221*9880d681SAndroid Build Coastguard Worker     if (RetTy->getTypeID() != Type::VoidTyID)
222*9880d681SAndroid Build Coastguard Worker       ret.resize(TD.getTypeStoreSize(RetTy));
223*9880d681SAndroid Build Coastguard Worker     ffi_call(&cif, Fn, ret.data(), values.data());
224*9880d681SAndroid Build Coastguard Worker     switch (RetTy->getTypeID()) {
225*9880d681SAndroid Build Coastguard Worker       case Type::IntegerTyID:
226*9880d681SAndroid Build Coastguard Worker         switch (cast<IntegerType>(RetTy)->getBitWidth()) {
227*9880d681SAndroid Build Coastguard Worker           case 8:  Result.IntVal = APInt(8 , *(int8_t *) ret.data()); break;
228*9880d681SAndroid Build Coastguard Worker           case 16: Result.IntVal = APInt(16, *(int16_t*) ret.data()); break;
229*9880d681SAndroid Build Coastguard Worker           case 32: Result.IntVal = APInt(32, *(int32_t*) ret.data()); break;
230*9880d681SAndroid Build Coastguard Worker           case 64: Result.IntVal = APInt(64, *(int64_t*) ret.data()); break;
231*9880d681SAndroid Build Coastguard Worker         }
232*9880d681SAndroid Build Coastguard Worker         break;
233*9880d681SAndroid Build Coastguard Worker       case Type::FloatTyID:   Result.FloatVal   = *(float *) ret.data(); break;
234*9880d681SAndroid Build Coastguard Worker       case Type::DoubleTyID:  Result.DoubleVal  = *(double*) ret.data(); break;
235*9880d681SAndroid Build Coastguard Worker       case Type::PointerTyID: Result.PointerVal = *(void **) ret.data(); break;
236*9880d681SAndroid Build Coastguard Worker       default: break;
237*9880d681SAndroid Build Coastguard Worker     }
238*9880d681SAndroid Build Coastguard Worker     return true;
239*9880d681SAndroid Build Coastguard Worker   }
240*9880d681SAndroid Build Coastguard Worker 
241*9880d681SAndroid Build Coastguard Worker   return false;
242*9880d681SAndroid Build Coastguard Worker }
243*9880d681SAndroid Build Coastguard Worker #endif // USE_LIBFFI
244*9880d681SAndroid Build Coastguard Worker 
callExternalFunction(Function * F,ArrayRef<GenericValue> ArgVals)245*9880d681SAndroid Build Coastguard Worker GenericValue Interpreter::callExternalFunction(Function *F,
246*9880d681SAndroid Build Coastguard Worker                                                ArrayRef<GenericValue> ArgVals) {
247*9880d681SAndroid Build Coastguard Worker   TheInterpreter = this;
248*9880d681SAndroid Build Coastguard Worker 
249*9880d681SAndroid Build Coastguard Worker   unique_lock<sys::Mutex> Guard(*FunctionsLock);
250*9880d681SAndroid Build Coastguard Worker 
251*9880d681SAndroid Build Coastguard Worker   // Do a lookup to see if the function is in our cache... this should just be a
252*9880d681SAndroid Build Coastguard Worker   // deferred annotation!
253*9880d681SAndroid Build Coastguard Worker   std::map<const Function *, ExFunc>::iterator FI = ExportedFunctions->find(F);
254*9880d681SAndroid Build Coastguard Worker   if (ExFunc Fn = (FI == ExportedFunctions->end()) ? lookupFunction(F)
255*9880d681SAndroid Build Coastguard Worker                                                    : FI->second) {
256*9880d681SAndroid Build Coastguard Worker     Guard.unlock();
257*9880d681SAndroid Build Coastguard Worker     return Fn(F->getFunctionType(), ArgVals);
258*9880d681SAndroid Build Coastguard Worker   }
259*9880d681SAndroid Build Coastguard Worker 
260*9880d681SAndroid Build Coastguard Worker #ifdef USE_LIBFFI
261*9880d681SAndroid Build Coastguard Worker   std::map<const Function *, RawFunc>::iterator RF = RawFunctions->find(F);
262*9880d681SAndroid Build Coastguard Worker   RawFunc RawFn;
263*9880d681SAndroid Build Coastguard Worker   if (RF == RawFunctions->end()) {
264*9880d681SAndroid Build Coastguard Worker     RawFn = (RawFunc)(intptr_t)
265*9880d681SAndroid Build Coastguard Worker       sys::DynamicLibrary::SearchForAddressOfSymbol(F->getName());
266*9880d681SAndroid Build Coastguard Worker     if (!RawFn)
267*9880d681SAndroid Build Coastguard Worker       RawFn = (RawFunc)(intptr_t)getPointerToGlobalIfAvailable(F);
268*9880d681SAndroid Build Coastguard Worker     if (RawFn != 0)
269*9880d681SAndroid Build Coastguard Worker       RawFunctions->insert(std::make_pair(F, RawFn));  // Cache for later
270*9880d681SAndroid Build Coastguard Worker   } else {
271*9880d681SAndroid Build Coastguard Worker     RawFn = RF->second;
272*9880d681SAndroid Build Coastguard Worker   }
273*9880d681SAndroid Build Coastguard Worker 
274*9880d681SAndroid Build Coastguard Worker   Guard.unlock();
275*9880d681SAndroid Build Coastguard Worker 
276*9880d681SAndroid Build Coastguard Worker   GenericValue Result;
277*9880d681SAndroid Build Coastguard Worker   if (RawFn != 0 && ffiInvoke(RawFn, F, ArgVals, getDataLayout(), Result))
278*9880d681SAndroid Build Coastguard Worker     return Result;
279*9880d681SAndroid Build Coastguard Worker #endif // USE_LIBFFI
280*9880d681SAndroid Build Coastguard Worker 
281*9880d681SAndroid Build Coastguard Worker   if (F->getName() == "__main")
282*9880d681SAndroid Build Coastguard Worker     errs() << "Tried to execute an unknown external function: "
283*9880d681SAndroid Build Coastguard Worker       << *F->getType() << " __main\n";
284*9880d681SAndroid Build Coastguard Worker   else
285*9880d681SAndroid Build Coastguard Worker     report_fatal_error("Tried to execute an unknown external function: " +
286*9880d681SAndroid Build Coastguard Worker                        F->getName());
287*9880d681SAndroid Build Coastguard Worker #ifndef USE_LIBFFI
288*9880d681SAndroid Build Coastguard Worker   errs() << "Recompiling LLVM with --enable-libffi might help.\n";
289*9880d681SAndroid Build Coastguard Worker #endif
290*9880d681SAndroid Build Coastguard Worker   return GenericValue();
291*9880d681SAndroid Build Coastguard Worker }
292*9880d681SAndroid Build Coastguard Worker 
293*9880d681SAndroid Build Coastguard Worker 
294*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
295*9880d681SAndroid Build Coastguard Worker //  Functions "exported" to the running application...
296*9880d681SAndroid Build Coastguard Worker //
297*9880d681SAndroid Build Coastguard Worker 
298*9880d681SAndroid Build Coastguard Worker // void atexit(Function*)
lle_X_atexit(FunctionType * FT,ArrayRef<GenericValue> Args)299*9880d681SAndroid Build Coastguard Worker static GenericValue lle_X_atexit(FunctionType *FT,
300*9880d681SAndroid Build Coastguard Worker                                  ArrayRef<GenericValue> Args) {
301*9880d681SAndroid Build Coastguard Worker   assert(Args.size() == 1);
302*9880d681SAndroid Build Coastguard Worker   TheInterpreter->addAtExitHandler((Function*)GVTOP(Args[0]));
303*9880d681SAndroid Build Coastguard Worker   GenericValue GV;
304*9880d681SAndroid Build Coastguard Worker   GV.IntVal = 0;
305*9880d681SAndroid Build Coastguard Worker   return GV;
306*9880d681SAndroid Build Coastguard Worker }
307*9880d681SAndroid Build Coastguard Worker 
308*9880d681SAndroid Build Coastguard Worker // void exit(int)
lle_X_exit(FunctionType * FT,ArrayRef<GenericValue> Args)309*9880d681SAndroid Build Coastguard Worker static GenericValue lle_X_exit(FunctionType *FT, ArrayRef<GenericValue> Args) {
310*9880d681SAndroid Build Coastguard Worker   TheInterpreter->exitCalled(Args[0]);
311*9880d681SAndroid Build Coastguard Worker   return GenericValue();
312*9880d681SAndroid Build Coastguard Worker }
313*9880d681SAndroid Build Coastguard Worker 
314*9880d681SAndroid Build Coastguard Worker // void abort(void)
lle_X_abort(FunctionType * FT,ArrayRef<GenericValue> Args)315*9880d681SAndroid Build Coastguard Worker static GenericValue lle_X_abort(FunctionType *FT, ArrayRef<GenericValue> Args) {
316*9880d681SAndroid Build Coastguard Worker   //FIXME: should we report or raise here?
317*9880d681SAndroid Build Coastguard Worker   //report_fatal_error("Interpreted program raised SIGABRT");
318*9880d681SAndroid Build Coastguard Worker   raise (SIGABRT);
319*9880d681SAndroid Build Coastguard Worker   return GenericValue();
320*9880d681SAndroid Build Coastguard Worker }
321*9880d681SAndroid Build Coastguard Worker 
322*9880d681SAndroid Build Coastguard Worker // int sprintf(char *, const char *, ...) - a very rough implementation to make
323*9880d681SAndroid Build Coastguard Worker // output useful.
lle_X_sprintf(FunctionType * FT,ArrayRef<GenericValue> Args)324*9880d681SAndroid Build Coastguard Worker static GenericValue lle_X_sprintf(FunctionType *FT,
325*9880d681SAndroid Build Coastguard Worker                                   ArrayRef<GenericValue> Args) {
326*9880d681SAndroid Build Coastguard Worker   char *OutputBuffer = (char *)GVTOP(Args[0]);
327*9880d681SAndroid Build Coastguard Worker   const char *FmtStr = (const char *)GVTOP(Args[1]);
328*9880d681SAndroid Build Coastguard Worker   unsigned ArgNo = 2;
329*9880d681SAndroid Build Coastguard Worker 
330*9880d681SAndroid Build Coastguard Worker   // printf should return # chars printed.  This is completely incorrect, but
331*9880d681SAndroid Build Coastguard Worker   // close enough for now.
332*9880d681SAndroid Build Coastguard Worker   GenericValue GV;
333*9880d681SAndroid Build Coastguard Worker   GV.IntVal = APInt(32, strlen(FmtStr));
334*9880d681SAndroid Build Coastguard Worker   while (1) {
335*9880d681SAndroid Build Coastguard Worker     switch (*FmtStr) {
336*9880d681SAndroid Build Coastguard Worker     case 0: return GV;             // Null terminator...
337*9880d681SAndroid Build Coastguard Worker     default:                       // Normal nonspecial character
338*9880d681SAndroid Build Coastguard Worker       sprintf(OutputBuffer++, "%c", *FmtStr++);
339*9880d681SAndroid Build Coastguard Worker       break;
340*9880d681SAndroid Build Coastguard Worker     case '\\': {                   // Handle escape codes
341*9880d681SAndroid Build Coastguard Worker       sprintf(OutputBuffer, "%c%c", *FmtStr, *(FmtStr+1));
342*9880d681SAndroid Build Coastguard Worker       FmtStr += 2; OutputBuffer += 2;
343*9880d681SAndroid Build Coastguard Worker       break;
344*9880d681SAndroid Build Coastguard Worker     }
345*9880d681SAndroid Build Coastguard Worker     case '%': {                    // Handle format specifiers
346*9880d681SAndroid Build Coastguard Worker       char FmtBuf[100] = "", Buffer[1000] = "";
347*9880d681SAndroid Build Coastguard Worker       char *FB = FmtBuf;
348*9880d681SAndroid Build Coastguard Worker       *FB++ = *FmtStr++;
349*9880d681SAndroid Build Coastguard Worker       char Last = *FB++ = *FmtStr++;
350*9880d681SAndroid Build Coastguard Worker       unsigned HowLong = 0;
351*9880d681SAndroid Build Coastguard Worker       while (Last != 'c' && Last != 'd' && Last != 'i' && Last != 'u' &&
352*9880d681SAndroid Build Coastguard Worker              Last != 'o' && Last != 'x' && Last != 'X' && Last != 'e' &&
353*9880d681SAndroid Build Coastguard Worker              Last != 'E' && Last != 'g' && Last != 'G' && Last != 'f' &&
354*9880d681SAndroid Build Coastguard Worker              Last != 'p' && Last != 's' && Last != '%') {
355*9880d681SAndroid Build Coastguard Worker         if (Last == 'l' || Last == 'L') HowLong++;  // Keep track of l's
356*9880d681SAndroid Build Coastguard Worker         Last = *FB++ = *FmtStr++;
357*9880d681SAndroid Build Coastguard Worker       }
358*9880d681SAndroid Build Coastguard Worker       *FB = 0;
359*9880d681SAndroid Build Coastguard Worker 
360*9880d681SAndroid Build Coastguard Worker       switch (Last) {
361*9880d681SAndroid Build Coastguard Worker       case '%':
362*9880d681SAndroid Build Coastguard Worker         memcpy(Buffer, "%", 2); break;
363*9880d681SAndroid Build Coastguard Worker       case 'c':
364*9880d681SAndroid Build Coastguard Worker         sprintf(Buffer, FmtBuf, uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
365*9880d681SAndroid Build Coastguard Worker         break;
366*9880d681SAndroid Build Coastguard Worker       case 'd': case 'i':
367*9880d681SAndroid Build Coastguard Worker       case 'u': case 'o':
368*9880d681SAndroid Build Coastguard Worker       case 'x': case 'X':
369*9880d681SAndroid Build Coastguard Worker         if (HowLong >= 1) {
370*9880d681SAndroid Build Coastguard Worker           if (HowLong == 1 &&
371*9880d681SAndroid Build Coastguard Worker               TheInterpreter->getDataLayout().getPointerSizeInBits() == 64 &&
372*9880d681SAndroid Build Coastguard Worker               sizeof(long) < sizeof(int64_t)) {
373*9880d681SAndroid Build Coastguard Worker             // Make sure we use %lld with a 64 bit argument because we might be
374*9880d681SAndroid Build Coastguard Worker             // compiling LLI on a 32 bit compiler.
375*9880d681SAndroid Build Coastguard Worker             unsigned Size = strlen(FmtBuf);
376*9880d681SAndroid Build Coastguard Worker             FmtBuf[Size] = FmtBuf[Size-1];
377*9880d681SAndroid Build Coastguard Worker             FmtBuf[Size+1] = 0;
378*9880d681SAndroid Build Coastguard Worker             FmtBuf[Size-1] = 'l';
379*9880d681SAndroid Build Coastguard Worker           }
380*9880d681SAndroid Build Coastguard Worker           sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal.getZExtValue());
381*9880d681SAndroid Build Coastguard Worker         } else
382*9880d681SAndroid Build Coastguard Worker           sprintf(Buffer, FmtBuf,uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
383*9880d681SAndroid Build Coastguard Worker         break;
384*9880d681SAndroid Build Coastguard Worker       case 'e': case 'E': case 'g': case 'G': case 'f':
385*9880d681SAndroid Build Coastguard Worker         sprintf(Buffer, FmtBuf, Args[ArgNo++].DoubleVal); break;
386*9880d681SAndroid Build Coastguard Worker       case 'p':
387*9880d681SAndroid Build Coastguard Worker         sprintf(Buffer, FmtBuf, (void*)GVTOP(Args[ArgNo++])); break;
388*9880d681SAndroid Build Coastguard Worker       case 's':
389*9880d681SAndroid Build Coastguard Worker         sprintf(Buffer, FmtBuf, (char*)GVTOP(Args[ArgNo++])); break;
390*9880d681SAndroid Build Coastguard Worker       default:
391*9880d681SAndroid Build Coastguard Worker         errs() << "<unknown printf code '" << *FmtStr << "'!>";
392*9880d681SAndroid Build Coastguard Worker         ArgNo++; break;
393*9880d681SAndroid Build Coastguard Worker       }
394*9880d681SAndroid Build Coastguard Worker       size_t Len = strlen(Buffer);
395*9880d681SAndroid Build Coastguard Worker       memcpy(OutputBuffer, Buffer, Len + 1);
396*9880d681SAndroid Build Coastguard Worker       OutputBuffer += Len;
397*9880d681SAndroid Build Coastguard Worker       }
398*9880d681SAndroid Build Coastguard Worker       break;
399*9880d681SAndroid Build Coastguard Worker     }
400*9880d681SAndroid Build Coastguard Worker   }
401*9880d681SAndroid Build Coastguard Worker   return GV;
402*9880d681SAndroid Build Coastguard Worker }
403*9880d681SAndroid Build Coastguard Worker 
404*9880d681SAndroid Build Coastguard Worker // int printf(const char *, ...) - a very rough implementation to make output
405*9880d681SAndroid Build Coastguard Worker // useful.
lle_X_printf(FunctionType * FT,ArrayRef<GenericValue> Args)406*9880d681SAndroid Build Coastguard Worker static GenericValue lle_X_printf(FunctionType *FT,
407*9880d681SAndroid Build Coastguard Worker                                  ArrayRef<GenericValue> Args) {
408*9880d681SAndroid Build Coastguard Worker   char Buffer[10000];
409*9880d681SAndroid Build Coastguard Worker   std::vector<GenericValue> NewArgs;
410*9880d681SAndroid Build Coastguard Worker   NewArgs.push_back(PTOGV((void*)&Buffer[0]));
411*9880d681SAndroid Build Coastguard Worker   NewArgs.insert(NewArgs.end(), Args.begin(), Args.end());
412*9880d681SAndroid Build Coastguard Worker   GenericValue GV = lle_X_sprintf(FT, NewArgs);
413*9880d681SAndroid Build Coastguard Worker   outs() << Buffer;
414*9880d681SAndroid Build Coastguard Worker   return GV;
415*9880d681SAndroid Build Coastguard Worker }
416*9880d681SAndroid Build Coastguard Worker 
417*9880d681SAndroid Build Coastguard Worker // int sscanf(const char *format, ...);
lle_X_sscanf(FunctionType * FT,ArrayRef<GenericValue> args)418*9880d681SAndroid Build Coastguard Worker static GenericValue lle_X_sscanf(FunctionType *FT,
419*9880d681SAndroid Build Coastguard Worker                                  ArrayRef<GenericValue> args) {
420*9880d681SAndroid Build Coastguard Worker   assert(args.size() < 10 && "Only handle up to 10 args to sscanf right now!");
421*9880d681SAndroid Build Coastguard Worker 
422*9880d681SAndroid Build Coastguard Worker   char *Args[10];
423*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < args.size(); ++i)
424*9880d681SAndroid Build Coastguard Worker     Args[i] = (char*)GVTOP(args[i]);
425*9880d681SAndroid Build Coastguard Worker 
426*9880d681SAndroid Build Coastguard Worker   GenericValue GV;
427*9880d681SAndroid Build Coastguard Worker   GV.IntVal = APInt(32, sscanf(Args[0], Args[1], Args[2], Args[3], Args[4],
428*9880d681SAndroid Build Coastguard Worker                     Args[5], Args[6], Args[7], Args[8], Args[9]));
429*9880d681SAndroid Build Coastguard Worker   return GV;
430*9880d681SAndroid Build Coastguard Worker }
431*9880d681SAndroid Build Coastguard Worker 
432*9880d681SAndroid Build Coastguard Worker // int scanf(const char *format, ...);
lle_X_scanf(FunctionType * FT,ArrayRef<GenericValue> args)433*9880d681SAndroid Build Coastguard Worker static GenericValue lle_X_scanf(FunctionType *FT, ArrayRef<GenericValue> args) {
434*9880d681SAndroid Build Coastguard Worker   assert(args.size() < 10 && "Only handle up to 10 args to scanf right now!");
435*9880d681SAndroid Build Coastguard Worker 
436*9880d681SAndroid Build Coastguard Worker   char *Args[10];
437*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < args.size(); ++i)
438*9880d681SAndroid Build Coastguard Worker     Args[i] = (char*)GVTOP(args[i]);
439*9880d681SAndroid Build Coastguard Worker 
440*9880d681SAndroid Build Coastguard Worker   GenericValue GV;
441*9880d681SAndroid Build Coastguard Worker   GV.IntVal = APInt(32, scanf( Args[0], Args[1], Args[2], Args[3], Args[4],
442*9880d681SAndroid Build Coastguard Worker                     Args[5], Args[6], Args[7], Args[8], Args[9]));
443*9880d681SAndroid Build Coastguard Worker   return GV;
444*9880d681SAndroid Build Coastguard Worker }
445*9880d681SAndroid Build Coastguard Worker 
446*9880d681SAndroid Build Coastguard Worker // int fprintf(FILE *, const char *, ...) - a very rough implementation to make
447*9880d681SAndroid Build Coastguard Worker // output useful.
lle_X_fprintf(FunctionType * FT,ArrayRef<GenericValue> Args)448*9880d681SAndroid Build Coastguard Worker static GenericValue lle_X_fprintf(FunctionType *FT,
449*9880d681SAndroid Build Coastguard Worker                                   ArrayRef<GenericValue> Args) {
450*9880d681SAndroid Build Coastguard Worker   assert(Args.size() >= 2);
451*9880d681SAndroid Build Coastguard Worker   char Buffer[10000];
452*9880d681SAndroid Build Coastguard Worker   std::vector<GenericValue> NewArgs;
453*9880d681SAndroid Build Coastguard Worker   NewArgs.push_back(PTOGV(Buffer));
454*9880d681SAndroid Build Coastguard Worker   NewArgs.insert(NewArgs.end(), Args.begin()+1, Args.end());
455*9880d681SAndroid Build Coastguard Worker   GenericValue GV = lle_X_sprintf(FT, NewArgs);
456*9880d681SAndroid Build Coastguard Worker 
457*9880d681SAndroid Build Coastguard Worker   fputs(Buffer, (FILE *) GVTOP(Args[0]));
458*9880d681SAndroid Build Coastguard Worker   return GV;
459*9880d681SAndroid Build Coastguard Worker }
460*9880d681SAndroid Build Coastguard Worker 
lle_X_memset(FunctionType * FT,ArrayRef<GenericValue> Args)461*9880d681SAndroid Build Coastguard Worker static GenericValue lle_X_memset(FunctionType *FT,
462*9880d681SAndroid Build Coastguard Worker                                  ArrayRef<GenericValue> Args) {
463*9880d681SAndroid Build Coastguard Worker   int val = (int)Args[1].IntVal.getSExtValue();
464*9880d681SAndroid Build Coastguard Worker   size_t len = (size_t)Args[2].IntVal.getZExtValue();
465*9880d681SAndroid Build Coastguard Worker   memset((void *)GVTOP(Args[0]), val, len);
466*9880d681SAndroid Build Coastguard Worker   // llvm.memset.* returns void, lle_X_* returns GenericValue,
467*9880d681SAndroid Build Coastguard Worker   // so here we return GenericValue with IntVal set to zero
468*9880d681SAndroid Build Coastguard Worker   GenericValue GV;
469*9880d681SAndroid Build Coastguard Worker   GV.IntVal = 0;
470*9880d681SAndroid Build Coastguard Worker   return GV;
471*9880d681SAndroid Build Coastguard Worker }
472*9880d681SAndroid Build Coastguard Worker 
lle_X_memcpy(FunctionType * FT,ArrayRef<GenericValue> Args)473*9880d681SAndroid Build Coastguard Worker static GenericValue lle_X_memcpy(FunctionType *FT,
474*9880d681SAndroid Build Coastguard Worker                                  ArrayRef<GenericValue> Args) {
475*9880d681SAndroid Build Coastguard Worker   memcpy(GVTOP(Args[0]), GVTOP(Args[1]),
476*9880d681SAndroid Build Coastguard Worker          (size_t)(Args[2].IntVal.getLimitedValue()));
477*9880d681SAndroid Build Coastguard Worker 
478*9880d681SAndroid Build Coastguard Worker   // llvm.memcpy* returns void, lle_X_* returns GenericValue,
479*9880d681SAndroid Build Coastguard Worker   // so here we return GenericValue with IntVal set to zero
480*9880d681SAndroid Build Coastguard Worker   GenericValue GV;
481*9880d681SAndroid Build Coastguard Worker   GV.IntVal = 0;
482*9880d681SAndroid Build Coastguard Worker   return GV;
483*9880d681SAndroid Build Coastguard Worker }
484*9880d681SAndroid Build Coastguard Worker 
initializeExternalFunctions()485*9880d681SAndroid Build Coastguard Worker void Interpreter::initializeExternalFunctions() {
486*9880d681SAndroid Build Coastguard Worker   sys::ScopedLock Writer(*FunctionsLock);
487*9880d681SAndroid Build Coastguard Worker   (*FuncNames)["lle_X_atexit"]       = lle_X_atexit;
488*9880d681SAndroid Build Coastguard Worker   (*FuncNames)["lle_X_exit"]         = lle_X_exit;
489*9880d681SAndroid Build Coastguard Worker   (*FuncNames)["lle_X_abort"]        = lle_X_abort;
490*9880d681SAndroid Build Coastguard Worker 
491*9880d681SAndroid Build Coastguard Worker   (*FuncNames)["lle_X_printf"]       = lle_X_printf;
492*9880d681SAndroid Build Coastguard Worker   (*FuncNames)["lle_X_sprintf"]      = lle_X_sprintf;
493*9880d681SAndroid Build Coastguard Worker   (*FuncNames)["lle_X_sscanf"]       = lle_X_sscanf;
494*9880d681SAndroid Build Coastguard Worker   (*FuncNames)["lle_X_scanf"]        = lle_X_scanf;
495*9880d681SAndroid Build Coastguard Worker   (*FuncNames)["lle_X_fprintf"]      = lle_X_fprintf;
496*9880d681SAndroid Build Coastguard Worker   (*FuncNames)["lle_X_memset"]       = lle_X_memset;
497*9880d681SAndroid Build Coastguard Worker   (*FuncNames)["lle_X_memcpy"]       = lle_X_memcpy;
498*9880d681SAndroid Build Coastguard Worker }
499