162b7fd13SChris Lattner //===-- ExternalFunctions.cpp - Implement External Functions --------------===//
2baf08eb2SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6482202a6SJohn Criswell //
7482202a6SJohn Criswell //===----------------------------------------------------------------------===//
8482202a6SJohn Criswell //
962b7fd13SChris Lattner //  This file contains both code to deal with invoking "external" functions, but
1062b7fd13SChris Lattner //  also contains code that implements "exported" external functions.
11baf08eb2SChris Lattner //
12a89ec99fSNick Lewycky //  There are currently two mechanisms for handling external functions in the
13a89ec99fSNick Lewycky //  Interpreter.  The first is to implement lle_* wrapper functions that are
14a89ec99fSNick Lewycky //  specific to well-known library functions which manually translate the
15a89ec99fSNick Lewycky //  arguments from GenericValues and make the call.  If such a wrapper does
16a89ec99fSNick Lewycky //  not exist, and libffi is available, then the Interpreter will attempt to
17a89ec99fSNick Lewycky //  invoke the function using libffi, after finding its address.
18baf08eb2SChris Lattner //
19baf08eb2SChris Lattner //===----------------------------------------------------------------------===//
20baf08eb2SChris Lattner 
21baf08eb2SChris Lattner #include "Interpreter.h"
2233d7b762SEugene Zelenko #include "llvm/ADT/APInt.h"
2333d7b762SEugene Zelenko #include "llvm/ADT/ArrayRef.h"
24ed0881b2SChandler Carruth #include "llvm/Config/config.h" // Detect libffi
2533d7b762SEugene Zelenko #include "llvm/ExecutionEngine/GenericValue.h"
269fb823bbSChandler Carruth #include "llvm/IR/DataLayout.h"
279fb823bbSChandler Carruth #include "llvm/IR/DerivedTypes.h"
2833d7b762SEugene Zelenko #include "llvm/IR/Function.h"
2933d7b762SEugene Zelenko #include "llvm/IR/Type.h"
3033d7b762SEugene Zelenko #include "llvm/Support/Casting.h"
31447762daSMichael J. Spencer #include "llvm/Support/DynamicLibrary.h"
32ed0881b2SChandler Carruth #include "llvm/Support/ErrorHandling.h"
331a39a2d1SChuck Rose III #include "llvm/Support/ManagedStatic.h"
34447762daSMichael J. Spencer #include "llvm/Support/Mutex.h"
356bda14b3SChandler Carruth #include "llvm/Support/raw_ostream.h"
3633d7b762SEugene Zelenko #include <cassert>
37ed0881b2SChandler Carruth #include <cmath>
384e106f06SBrian Gaeke #include <csignal>
3933d7b762SEugene Zelenko #include <cstdint>
4026ff6f9cSDuncan Sands #include <cstdio>
41579f0713SAnton Korobeynikov #include <cstring>
42ed0881b2SChandler Carruth #include <map>
433d5360a4SBenjamin Kramer #include <mutex>
4433d7b762SEugene Zelenko #include <string>
4533d7b762SEugene Zelenko #include <utility>
4633d7b762SEugene Zelenko #include <vector>
473115ba39SZhou Sheng 
48e54da991SNick Lewycky #ifdef HAVE_FFI_CALL
49a89ec99fSNick Lewycky #ifdef HAVE_FFI_H
50a89ec99fSNick Lewycky #include <ffi.h>
51e54da991SNick Lewycky #define USE_LIBFFI
52a89ec99fSNick Lewycky #elif HAVE_FFI_FFI_H
53a89ec99fSNick Lewycky #include <ffi/ffi.h>
54e54da991SNick Lewycky #define USE_LIBFFI
553115ba39SZhou Sheng #endif
56a89ec99fSNick Lewycky #endif
579a8602ceSTanya Lattner 
5818099661SChris Lattner using namespace llvm;
59960707c3SBrian Gaeke 
60da19a13aSOwen Anderson static ManagedStatic<sys::Mutex> FunctionsLock;
61da19a13aSOwen Anderson 
62bd7b1c89SBenjamin Kramer typedef GenericValue (*ExFunc)(FunctionType *, ArrayRef<GenericValue>);
63a89ec99fSNick Lewycky static ManagedStatic<std::map<const Function *, ExFunc> > ExportedFunctions;
643b1fd57eSChris Bieneman static ManagedStatic<std::map<std::string, ExFunc> > FuncNames;
65baf08eb2SChris Lattner 
66e54da991SNick Lewycky #ifdef USE_LIBFFI
671432ef86SDan Gohman typedef void (*RawFunc)();
68a89ec99fSNick Lewycky static ManagedStatic<std::map<const Function *, RawFunc> > RawFunctions;
69a89ec99fSNick Lewycky #endif
70a89ec99fSNick Lewycky 
7115157b88SChris Lattner static Interpreter *TheInterpreter;
7215157b88SChris Lattner 
getTypeID(Type * Ty)73229907cdSChris Lattner static char getTypeID(Type *Ty) {
746b727599SChris Lattner   switch (Ty->getTypeID()) {
75baf08eb2SChris Lattner   case Type::VoidTyID:    return 'V';
767a9c62baSReid Spencer   case Type::IntegerTyID:
777a9c62baSReid Spencer     switch (cast<IntegerType>(Ty)->getBitWidth()) {
787a9c62baSReid Spencer       case 1:  return 'o';
797a9c62baSReid Spencer       case 8:  return 'B';
807a9c62baSReid Spencer       case 16: return 'S';
817a9c62baSReid Spencer       case 32: return 'I';
827a9c62baSReid Spencer       case 64: return 'L';
837a9c62baSReid Spencer       default: return 'N';
847a9c62baSReid Spencer     }
85baf08eb2SChris Lattner   case Type::FloatTyID:   return 'F';
86baf08eb2SChris Lattner   case Type::DoubleTyID:  return 'D';
87baf08eb2SChris Lattner   case Type::PointerTyID: return 'P';
88f94811afSChris Lattner   case Type::FunctionTyID:return 'M';
89baf08eb2SChris Lattner   case Type::StructTyID:  return 'T';
90baf08eb2SChris Lattner   case Type::ArrayTyID:   return 'A';
91baf08eb2SChris Lattner   default: return 'U';
92baf08eb2SChris Lattner   }
93baf08eb2SChris Lattner }
94baf08eb2SChris Lattner 
95187bf73bSAnton Korobeynikov // Try to find address of external function given a Function object.
96187bf73bSAnton Korobeynikov // Please note, that interpreter doesn't know how to assemble a
97187bf73bSAnton Korobeynikov // real call in general case (this is JIT job), that's why it assumes,
98187bf73bSAnton Korobeynikov // that all external functions has the same (and pretty "general") signature.
99187bf73bSAnton Korobeynikov // The typical example of such functions are "lle_X_" ones.
lookupFunction(const Function * F)1006cc20deaSBrian Gaeke static ExFunc lookupFunction(const Function *F) {
101baf08eb2SChris Lattner   // Function not found, look it up... start by figuring out what the
102baf08eb2SChris Lattner   // composite function name should be.
1037f74a56eSChris Lattner   std::string ExtName = "lle_";
104229907cdSChris Lattner   FunctionType *FT = F->getFunctionType();
10562df5eedSJames Y Knight   ExtName += getTypeID(FT->getReturnType());
10662df5eedSJames Y Knight   for (Type *T : FT->params())
10762df5eedSJames Y Knight     ExtName += getTypeID(T);
108075759aaSYaron Keren   ExtName += ("_" + F->getName()).str();
109baf08eb2SChris Lattner 
1105c96ef7cSOwen Anderson   sys::ScopedLock Writer(*FunctionsLock);
1113b1fd57eSChris Bieneman   ExFunc FnPtr = (*FuncNames)[ExtName];
112353eda48SCraig Topper   if (!FnPtr)
113075759aaSYaron Keren     FnPtr = (*FuncNames)[("lle_X_" + F->getName()).str()];
114353eda48SCraig Topper   if (!FnPtr)  // Try calling a generic function... if it exists...
115075759aaSYaron Keren     FnPtr = (ExFunc)(intptr_t)sys::DynamicLibrary::SearchForAddressOfSymbol(
116075759aaSYaron Keren         ("lle_X_" + F->getName()).str());
117353eda48SCraig Topper   if (FnPtr)
118a89ec99fSNick Lewycky     ExportedFunctions->insert(std::make_pair(F, FnPtr));  // Cache for later
119baf08eb2SChris Lattner   return FnPtr;
120baf08eb2SChris Lattner }
121baf08eb2SChris Lattner 
122e54da991SNick Lewycky #ifdef USE_LIBFFI
ffiTypeFor(Type * Ty)123229907cdSChris Lattner static ffi_type *ffiTypeFor(Type *Ty) {
124a89ec99fSNick Lewycky   switch (Ty->getTypeID()) {
125a89ec99fSNick Lewycky     case Type::VoidTyID: return &ffi_type_void;
126a89ec99fSNick Lewycky     case Type::IntegerTyID:
127a89ec99fSNick Lewycky       switch (cast<IntegerType>(Ty)->getBitWidth()) {
128a89ec99fSNick Lewycky         case 8:  return &ffi_type_sint8;
129a89ec99fSNick Lewycky         case 16: return &ffi_type_sint16;
130a89ec99fSNick Lewycky         case 32: return &ffi_type_sint32;
131a89ec99fSNick Lewycky         case 64: return &ffi_type_sint64;
132a89ec99fSNick Lewycky       }
133*52396577SSimon Pilgrim       llvm_unreachable("Unhandled integer type bitwidth");
134a89ec99fSNick Lewycky     case Type::FloatTyID:   return &ffi_type_float;
135a89ec99fSNick Lewycky     case Type::DoubleTyID:  return &ffi_type_double;
136a89ec99fSNick Lewycky     case Type::PointerTyID: return &ffi_type_pointer;
137a89ec99fSNick Lewycky     default: break;
138a89ec99fSNick Lewycky   }
139a89ec99fSNick Lewycky   // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
1402104b8d3SChris Lattner   report_fatal_error("Type could not be mapped for use with libffi.");
141a89ec99fSNick Lewycky   return NULL;
142a89ec99fSNick Lewycky }
143a89ec99fSNick Lewycky 
ffiValueFor(Type * Ty,const GenericValue & AV,void * ArgDataPtr)144229907cdSChris Lattner static void *ffiValueFor(Type *Ty, const GenericValue &AV,
145a89ec99fSNick Lewycky                          void *ArgDataPtr) {
146a89ec99fSNick Lewycky   switch (Ty->getTypeID()) {
147a89ec99fSNick Lewycky     case Type::IntegerTyID:
148a89ec99fSNick Lewycky       switch (cast<IntegerType>(Ty)->getBitWidth()) {
149a89ec99fSNick Lewycky         case 8: {
150a89ec99fSNick Lewycky           int8_t *I8Ptr = (int8_t *) ArgDataPtr;
151a89ec99fSNick Lewycky           *I8Ptr = (int8_t) AV.IntVal.getZExtValue();
152a89ec99fSNick Lewycky           return ArgDataPtr;
153a89ec99fSNick Lewycky         }
154a89ec99fSNick Lewycky         case 16: {
155a89ec99fSNick Lewycky           int16_t *I16Ptr = (int16_t *) ArgDataPtr;
156a89ec99fSNick Lewycky           *I16Ptr = (int16_t) AV.IntVal.getZExtValue();
157a89ec99fSNick Lewycky           return ArgDataPtr;
158a89ec99fSNick Lewycky         }
159a89ec99fSNick Lewycky         case 32: {
160a89ec99fSNick Lewycky           int32_t *I32Ptr = (int32_t *) ArgDataPtr;
161a89ec99fSNick Lewycky           *I32Ptr = (int32_t) AV.IntVal.getZExtValue();
162a89ec99fSNick Lewycky           return ArgDataPtr;
163a89ec99fSNick Lewycky         }
164a89ec99fSNick Lewycky         case 64: {
165a89ec99fSNick Lewycky           int64_t *I64Ptr = (int64_t *) ArgDataPtr;
166a89ec99fSNick Lewycky           *I64Ptr = (int64_t) AV.IntVal.getZExtValue();
167a89ec99fSNick Lewycky           return ArgDataPtr;
168a89ec99fSNick Lewycky         }
169a89ec99fSNick Lewycky       }
170*52396577SSimon Pilgrim       llvm_unreachable("Unhandled integer type bitwidth");
171a89ec99fSNick Lewycky     case Type::FloatTyID: {
172a89ec99fSNick Lewycky       float *FloatPtr = (float *) ArgDataPtr;
17341ee7928SNick Lewycky       *FloatPtr = AV.FloatVal;
174a89ec99fSNick Lewycky       return ArgDataPtr;
175a89ec99fSNick Lewycky     }
176a89ec99fSNick Lewycky     case Type::DoubleTyID: {
177a89ec99fSNick Lewycky       double *DoublePtr = (double *) ArgDataPtr;
178a89ec99fSNick Lewycky       *DoublePtr = AV.DoubleVal;
179a89ec99fSNick Lewycky       return ArgDataPtr;
180a89ec99fSNick Lewycky     }
181a89ec99fSNick Lewycky     case Type::PointerTyID: {
182a89ec99fSNick Lewycky       void **PtrPtr = (void **) ArgDataPtr;
183a89ec99fSNick Lewycky       *PtrPtr = GVTOP(AV);
184a89ec99fSNick Lewycky       return ArgDataPtr;
185a89ec99fSNick Lewycky     }
186a89ec99fSNick Lewycky     default: break;
187a89ec99fSNick Lewycky   }
188a89ec99fSNick Lewycky   // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
1892104b8d3SChris Lattner   report_fatal_error("Type value could not be mapped for use with libffi.");
190a89ec99fSNick Lewycky   return NULL;
191a89ec99fSNick Lewycky }
192a89ec99fSNick Lewycky 
ffiInvoke(RawFunc Fn,Function * F,ArrayRef<GenericValue> ArgVals,const DataLayout & TD,GenericValue & Result)193bd7b1c89SBenjamin Kramer static bool ffiInvoke(RawFunc Fn, Function *F, ArrayRef<GenericValue> ArgVals,
194a3fcefb6SMehdi Amini                       const DataLayout &TD, GenericValue &Result) {
195a89ec99fSNick Lewycky   ffi_cif cif;
196229907cdSChris Lattner   FunctionType *FTy = F->getFunctionType();
197a89ec99fSNick Lewycky   const unsigned NumArgs = F->arg_size();
198a89ec99fSNick Lewycky 
199a89ec99fSNick Lewycky   // TODO: We don't have type information about the remaining arguments, because
200a89ec99fSNick Lewycky   // this information is never passed into ExecutionEngine::runFunction().
201a89ec99fSNick Lewycky   if (ArgVals.size() > NumArgs && F->isVarArg()) {
2022104b8d3SChris Lattner     report_fatal_error("Calling external var arg function '" + F->getName()
203ccb29cd2STorok Edwin                       + "' is not supported by the Interpreter.");
204a89ec99fSNick Lewycky   }
205a89ec99fSNick Lewycky 
206a89ec99fSNick Lewycky   unsigned ArgBytes = 0;
207a89ec99fSNick Lewycky 
208a89ec99fSNick Lewycky   std::vector<ffi_type*> args(NumArgs);
209a89ec99fSNick Lewycky   for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
210a89ec99fSNick Lewycky        A != E; ++A) {
211a89ec99fSNick Lewycky     const unsigned ArgNo = A->getArgNo();
212229907cdSChris Lattner     Type *ArgTy = FTy->getParamType(ArgNo);
213a89ec99fSNick Lewycky     args[ArgNo] = ffiTypeFor(ArgTy);
214731ad628SMehdi Amini     ArgBytes += TD.getTypeStoreSize(ArgTy);
215a89ec99fSNick Lewycky   }
216a89ec99fSNick Lewycky 
217bf4c56d8SNick Lewycky   SmallVector<uint8_t, 128> ArgData;
218bf4c56d8SNick Lewycky   ArgData.resize(ArgBytes);
219bf4c56d8SNick Lewycky   uint8_t *ArgDataPtr = ArgData.data();
220bf4c56d8SNick Lewycky   SmallVector<void*, 16> values(NumArgs);
221a89ec99fSNick Lewycky   for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
222a89ec99fSNick Lewycky        A != E; ++A) {
223a89ec99fSNick Lewycky     const unsigned ArgNo = A->getArgNo();
224229907cdSChris Lattner     Type *ArgTy = FTy->getParamType(ArgNo);
225a89ec99fSNick Lewycky     values[ArgNo] = ffiValueFor(ArgTy, ArgVals[ArgNo], ArgDataPtr);
226731ad628SMehdi Amini     ArgDataPtr += TD.getTypeStoreSize(ArgTy);
227a89ec99fSNick Lewycky   }
228a89ec99fSNick Lewycky 
229229907cdSChris Lattner   Type *RetTy = FTy->getReturnType();
230a89ec99fSNick Lewycky   ffi_type *rtype = ffiTypeFor(RetTy);
231a89ec99fSNick Lewycky 
232a4d5b34fSLang Hames   if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, args.data()) ==
233a4d5b34fSLang Hames       FFI_OK) {
234bf4c56d8SNick Lewycky     SmallVector<uint8_t, 128> ret;
235a89ec99fSNick Lewycky     if (RetTy->getTypeID() != Type::VoidTyID)
236731ad628SMehdi Amini       ret.resize(TD.getTypeStoreSize(RetTy));
237bf4c56d8SNick Lewycky     ffi_call(&cif, Fn, ret.data(), values.data());
238a89ec99fSNick Lewycky     switch (RetTy->getTypeID()) {
239a89ec99fSNick Lewycky       case Type::IntegerTyID:
240a89ec99fSNick Lewycky         switch (cast<IntegerType>(RetTy)->getBitWidth()) {
241bf4c56d8SNick Lewycky           case 8:  Result.IntVal = APInt(8 , *(int8_t *) ret.data()); break;
242bf4c56d8SNick Lewycky           case 16: Result.IntVal = APInt(16, *(int16_t*) ret.data()); break;
243bf4c56d8SNick Lewycky           case 32: Result.IntVal = APInt(32, *(int32_t*) ret.data()); break;
244bf4c56d8SNick Lewycky           case 64: Result.IntVal = APInt(64, *(int64_t*) ret.data()); break;
245a89ec99fSNick Lewycky         }
246a89ec99fSNick Lewycky         break;
247bf4c56d8SNick Lewycky       case Type::FloatTyID:   Result.FloatVal   = *(float *) ret.data(); break;
248bf4c56d8SNick Lewycky       case Type::DoubleTyID:  Result.DoubleVal  = *(double*) ret.data(); break;
249bf4c56d8SNick Lewycky       case Type::PointerTyID: Result.PointerVal = *(void **) ret.data(); break;
250a89ec99fSNick Lewycky       default: break;
251a89ec99fSNick Lewycky     }
252a89ec99fSNick Lewycky     return true;
253a89ec99fSNick Lewycky   }
254a89ec99fSNick Lewycky 
255a89ec99fSNick Lewycky   return false;
256a89ec99fSNick Lewycky }
257e54da991SNick Lewycky #endif // USE_LIBFFI
258a89ec99fSNick Lewycky 
callExternalFunction(Function * F,ArrayRef<GenericValue> ArgVals)25928edd69eSChris Lattner GenericValue Interpreter::callExternalFunction(Function *F,
260bd7b1c89SBenjamin Kramer                                                ArrayRef<GenericValue> ArgVals) {
26115157b88SChris Lattner   TheInterpreter = this;
26215157b88SChris Lattner 
2633d5360a4SBenjamin Kramer   std::unique_lock<sys::Mutex> Guard(*FunctionsLock);
264da19a13aSOwen Anderson 
26562b7fd13SChris Lattner   // Do a lookup to see if the function is in our cache... this should just be a
266aa7d26c8SMisha Brukman   // deferred annotation!
267a89ec99fSNick Lewycky   std::map<const Function *, ExFunc>::iterator FI = ExportedFunctions->find(F);
268a89ec99fSNick Lewycky   if (ExFunc Fn = (FI == ExportedFunctions->end()) ? lookupFunction(F)
269da19a13aSOwen Anderson                                                    : FI->second) {
270c4c5180fSDylan Noblesmith     Guard.unlock();
271a89ec99fSNick Lewycky     return Fn(F->getFunctionType(), ArgVals);
272da19a13aSOwen Anderson   }
273a89ec99fSNick Lewycky 
274e54da991SNick Lewycky #ifdef USE_LIBFFI
275a89ec99fSNick Lewycky   std::map<const Function *, RawFunc>::iterator RF = RawFunctions->find(F);
276a89ec99fSNick Lewycky   RawFunc RawFn;
277a89ec99fSNick Lewycky   if (RF == RawFunctions->end()) {
278a89ec99fSNick Lewycky     RawFn = (RawFunc)(intptr_t)
2792eb80a99SSylvestre Ledru       sys::DynamicLibrary::SearchForAddressOfSymbol(std::string(F->getName()));
280921e80b1STorok Edwin     if (!RawFn)
28161b798a5STorok Edwin       RawFn = (RawFunc)(intptr_t)getPointerToGlobalIfAvailable(F);
282a89ec99fSNick Lewycky     if (RawFn != 0)
283a89ec99fSNick Lewycky       RawFunctions->insert(std::make_pair(F, RawFn));  // Cache for later
284a89ec99fSNick Lewycky   } else {
285a89ec99fSNick Lewycky     RawFn = RF->second;
2869a8602ceSTanya Lattner   }
2879a8602ceSTanya Lattner 
288c4c5180fSDylan Noblesmith   Guard.unlock();
289da19a13aSOwen Anderson 
290a89ec99fSNick Lewycky   GenericValue Result;
291cdfe20b9SMicah Villmow   if (RawFn != 0 && ffiInvoke(RawFn, F, ArgVals, getDataLayout(), Result))
2929a8602ceSTanya Lattner     return Result;
293e54da991SNick Lewycky #endif // USE_LIBFFI
294a89ec99fSNick Lewycky 
295ccb29cd2STorok Edwin   if (F->getName() == "__main")
2961df14c41SDavid Greene     errs() << "Tried to execute an unknown external function: "
2970f214ebeSChris Lattner       << *F->getType() << " __main\n";
298ccb29cd2STorok Edwin   else
2992104b8d3SChris Lattner     report_fatal_error("Tried to execute an unknown external function: " +
3000f214ebeSChris Lattner                        F->getName());
3017efd07fdSNick Lewycky #ifndef USE_LIBFFI
3021df14c41SDavid Greene   errs() << "Recompiling LLVM with --enable-libffi might help.\n";
3037efd07fdSNick Lewycky #endif
304a89ec99fSNick Lewycky   return GenericValue();
305baf08eb2SChris Lattner }
306baf08eb2SChris Lattner 
307baf08eb2SChris Lattner //===----------------------------------------------------------------------===//
308f94811afSChris Lattner //  Functions "exported" to the running application...
309baf08eb2SChris Lattner //
31086ec7baeSDaniel Dunbar 
3114a5bb957SChris Lattner // void atexit(Function*)
lle_X_atexit(FunctionType * FT,ArrayRef<GenericValue> Args)312bd7b1c89SBenjamin Kramer static GenericValue lle_X_atexit(FunctionType *FT,
313bd7b1c89SBenjamin Kramer                                  ArrayRef<GenericValue> Args) {
3144a5bb957SChris Lattner   assert(Args.size() == 1);
3154a5bb957SChris Lattner   TheInterpreter->addAtExitHandler((Function*)GVTOP(Args[0]));
3164a5bb957SChris Lattner   GenericValue GV;
317c45e1047SReid Spencer   GV.IntVal = 0;
3184a5bb957SChris Lattner   return GV;
319d299dbacSChris Lattner }
320d299dbacSChris Lattner 
3210313db6bSChris Lattner // void exit(int)
lle_X_exit(FunctionType * FT,ArrayRef<GenericValue> Args)322bd7b1c89SBenjamin Kramer static GenericValue lle_X_exit(FunctionType *FT, ArrayRef<GenericValue> Args) {
32315157b88SChris Lattner   TheInterpreter->exitCalled(Args[0]);
32415157b88SChris Lattner   return GenericValue();
32515157b88SChris Lattner }
32615157b88SChris Lattner 
3270313db6bSChris Lattner // void abort(void)
lle_X_abort(FunctionType * FT,ArrayRef<GenericValue> Args)328bd7b1c89SBenjamin Kramer static GenericValue lle_X_abort(FunctionType *FT, ArrayRef<GenericValue> Args) {
329ccb29cd2STorok Edwin   //FIXME: should we report or raise here?
3302104b8d3SChris Lattner   //report_fatal_error("Interpreted program raised SIGABRT");
3314e106f06SBrian Gaeke   raise (SIGABRT);
3321319429fSChris Lattner   return GenericValue();
3331319429fSChris Lattner }
3341319429fSChris Lattner 
335a89ec99fSNick Lewycky // int sprintf(char *, const char *, ...) - a very rough implementation to make
33660a9a23aSChris Lattner // output useful.
lle_X_sprintf(FunctionType * FT,ArrayRef<GenericValue> Args)337bd7b1c89SBenjamin Kramer static GenericValue lle_X_sprintf(FunctionType *FT,
338bd7b1c89SBenjamin Kramer                                   ArrayRef<GenericValue> Args) {
339d49518c5SChris Lattner   char *OutputBuffer = (char *)GVTOP(Args[0]);
340d49518c5SChris Lattner   const char *FmtStr = (const char *)GVTOP(Args[1]);
34160a9a23aSChris Lattner   unsigned ArgNo = 2;
342490d2a84SChris Lattner 
343490d2a84SChris Lattner   // printf should return # chars printed.  This is completely incorrect, but
344490d2a84SChris Lattner   // close enough for now.
345c45e1047SReid Spencer   GenericValue GV;
346c45e1047SReid Spencer   GV.IntVal = APInt(32, strlen(FmtStr));
34733d7b762SEugene Zelenko   while (true) {
348490d2a84SChris Lattner     switch (*FmtStr) {
349490d2a84SChris Lattner     case 0: return GV;             // Null terminator...
350490d2a84SChris Lattner     default:                       // Normal nonspecial character
35160a9a23aSChris Lattner       sprintf(OutputBuffer++, "%c", *FmtStr++);
352490d2a84SChris Lattner       break;
353490d2a84SChris Lattner     case '\\': {                   // Handle escape codes
35460a9a23aSChris Lattner       sprintf(OutputBuffer, "%c%c", *FmtStr, *(FmtStr+1));
35560a9a23aSChris Lattner       FmtStr += 2; OutputBuffer += 2;
356490d2a84SChris Lattner       break;
357490d2a84SChris Lattner     }
358490d2a84SChris Lattner     case '%': {                    // Handle format specifiers
35931e9e4d2SChris Lattner       char FmtBuf[100] = "", Buffer[1000] = "";
36031e9e4d2SChris Lattner       char *FB = FmtBuf;
36131e9e4d2SChris Lattner       *FB++ = *FmtStr++;
36231e9e4d2SChris Lattner       char Last = *FB++ = *FmtStr++;
36331e9e4d2SChris Lattner       unsigned HowLong = 0;
36431e9e4d2SChris Lattner       while (Last != 'c' && Last != 'd' && Last != 'i' && Last != 'u' &&
36531e9e4d2SChris Lattner              Last != 'o' && Last != 'x' && Last != 'X' && Last != 'e' &&
36631e9e4d2SChris Lattner              Last != 'E' && Last != 'g' && Last != 'G' && Last != 'f' &&
36731e9e4d2SChris Lattner              Last != 'p' && Last != 's' && Last != '%') {
36831e9e4d2SChris Lattner         if (Last == 'l' || Last == 'L') HowLong++;  // Keep track of l's
36931e9e4d2SChris Lattner         Last = *FB++ = *FmtStr++;
370490d2a84SChris Lattner       }
37131e9e4d2SChris Lattner       *FB = 0;
372490d2a84SChris Lattner 
37331e9e4d2SChris Lattner       switch (Last) {
37431e9e4d2SChris Lattner       case '%':
37529063eacSBenjamin Kramer         memcpy(Buffer, "%", 2); break;
3765cc31881SChris Lattner       case 'c':
377c45e1047SReid Spencer         sprintf(Buffer, FmtBuf, uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
378c45e1047SReid Spencer         break;
3795cc31881SChris Lattner       case 'd': case 'i':
3805cc31881SChris Lattner       case 'u': case 'o':
3815cc31881SChris Lattner       case 'x': case 'X':
38233b3b966SChris Lattner         if (HowLong >= 1) {
38347985409SChris Lattner           if (HowLong == 1 &&
384a3fcefb6SMehdi Amini               TheInterpreter->getDataLayout().getPointerSizeInBits() == 64 &&
3856e64180fSReid Spencer               sizeof(long) < sizeof(int64_t)) {
38633b3b966SChris Lattner             // Make sure we use %lld with a 64 bit argument because we might be
38733b3b966SChris Lattner             // compiling LLI on a 32 bit compiler.
38833b3b966SChris Lattner             unsigned Size = strlen(FmtBuf);
38933b3b966SChris Lattner             FmtBuf[Size] = FmtBuf[Size-1];
39033b3b966SChris Lattner             FmtBuf[Size+1] = 0;
39133b3b966SChris Lattner             FmtBuf[Size-1] = 'l';
39233b3b966SChris Lattner           }
393c45e1047SReid Spencer           sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal.getZExtValue());
39433b3b966SChris Lattner         } else
395c45e1047SReid Spencer           sprintf(Buffer, FmtBuf,uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
396c45e1047SReid Spencer         break;
3975cc31881SChris Lattner       case 'e': case 'E': case 'g': case 'G': case 'f':
39831e9e4d2SChris Lattner         sprintf(Buffer, FmtBuf, Args[ArgNo++].DoubleVal); break;
39951862ef7SChris Lattner       case 'p':
400d49518c5SChris Lattner         sprintf(Buffer, FmtBuf, (void*)GVTOP(Args[ArgNo++])); break;
40131e9e4d2SChris Lattner       case 's':
402d49518c5SChris Lattner         sprintf(Buffer, FmtBuf, (char*)GVTOP(Args[ArgNo++])); break;
403471ba48cSChris Lattner       default:
4041df14c41SDavid Greene         errs() << "<unknown printf code '" << *FmtStr << "'!>";
405490d2a84SChris Lattner         ArgNo++; break;
406490d2a84SChris Lattner       }
40729063eacSBenjamin Kramer       size_t Len = strlen(Buffer);
40829063eacSBenjamin Kramer       memcpy(OutputBuffer, Buffer, Len + 1);
40929063eacSBenjamin Kramer       OutputBuffer += Len;
4105cc31881SChris Lattner       }
411490d2a84SChris Lattner       break;
412490d2a84SChris Lattner     }
413490d2a84SChris Lattner   }
414843657c3SElena Demikhovsky   return GV;
415490d2a84SChris Lattner }
416490d2a84SChris Lattner 
417a89ec99fSNick Lewycky // int printf(const char *, ...) - a very rough implementation to make output
418a89ec99fSNick Lewycky // useful.
lle_X_printf(FunctionType * FT,ArrayRef<GenericValue> Args)419bd7b1c89SBenjamin Kramer static GenericValue lle_X_printf(FunctionType *FT,
420bd7b1c89SBenjamin Kramer                                  ArrayRef<GenericValue> Args) {
42160a9a23aSChris Lattner   char Buffer[10000];
422a89ec99fSNick Lewycky   std::vector<GenericValue> NewArgs;
423a68c374eSReid Spencer   NewArgs.push_back(PTOGV((void*)&Buffer[0]));
4241d0bc055SKazu Hirata   llvm::append_range(NewArgs, Args);
4258c3d3dceSReid Spencer   GenericValue GV = lle_X_sprintf(FT, NewArgs);
426471ba48cSChris Lattner   outs() << Buffer;
42760a9a23aSChris Lattner   return GV;
42860a9a23aSChris Lattner }
42960a9a23aSChris Lattner 
4305dec4600SChris Lattner // int sscanf(const char *format, ...);
lle_X_sscanf(FunctionType * FT,ArrayRef<GenericValue> args)431bd7b1c89SBenjamin Kramer static GenericValue lle_X_sscanf(FunctionType *FT,
432bd7b1c89SBenjamin Kramer                                  ArrayRef<GenericValue> args) {
4335dec4600SChris Lattner   assert(args.size() < 10 && "Only handle up to 10 args to sscanf right now!");
4345dec4600SChris Lattner 
435d3183715SChris Lattner   char *Args[10];
4365dec4600SChris Lattner   for (unsigned i = 0; i < args.size(); ++i)
437d3183715SChris Lattner     Args[i] = (char*)GVTOP(args[i]);
4385dec4600SChris Lattner 
4395dec4600SChris Lattner   GenericValue GV;
440c45e1047SReid Spencer   GV.IntVal = APInt(32, sscanf(Args[0], Args[1], Args[2], Args[3], Args[4],
441c45e1047SReid Spencer                     Args[5], Args[6], Args[7], Args[8], Args[9]));
442d3183715SChris Lattner   return GV;
443d3183715SChris Lattner }
444d3183715SChris Lattner 
445d3183715SChris Lattner // int scanf(const char *format, ...);
lle_X_scanf(FunctionType * FT,ArrayRef<GenericValue> args)446bd7b1c89SBenjamin Kramer static GenericValue lle_X_scanf(FunctionType *FT, ArrayRef<GenericValue> args) {
447d3183715SChris Lattner   assert(args.size() < 10 && "Only handle up to 10 args to scanf right now!");
448d3183715SChris Lattner 
449d3183715SChris Lattner   char *Args[10];
450d3183715SChris Lattner   for (unsigned i = 0; i < args.size(); ++i)
451d3183715SChris Lattner     Args[i] = (char*)GVTOP(args[i]);
452d3183715SChris Lattner 
453d3183715SChris Lattner   GenericValue GV;
454c45e1047SReid Spencer   GV.IntVal = APInt(32, scanf( Args[0], Args[1], Args[2], Args[3], Args[4],
455c45e1047SReid Spencer                     Args[5], Args[6], Args[7], Args[8], Args[9]));
4565dec4600SChris Lattner   return GV;
4575dec4600SChris Lattner }
4585dec4600SChris Lattner 
459a89ec99fSNick Lewycky // int fprintf(FILE *, const char *, ...) - a very rough implementation to make
460a89ec99fSNick Lewycky // output useful.
lle_X_fprintf(FunctionType * FT,ArrayRef<GenericValue> Args)461bd7b1c89SBenjamin Kramer static GenericValue lle_X_fprintf(FunctionType *FT,
462bd7b1c89SBenjamin Kramer                                   ArrayRef<GenericValue> Args) {
4631610666eSChris Lattner   assert(Args.size() >= 2);
464c3a84099SChris Lattner   char Buffer[10000];
465a89ec99fSNick Lewycky   std::vector<GenericValue> NewArgs;
466d49518c5SChris Lattner   NewArgs.push_back(PTOGV(Buffer));
467c3a84099SChris Lattner   NewArgs.insert(NewArgs.end(), Args.begin()+1, Args.end());
4688c3d3dceSReid Spencer   GenericValue GV = lle_X_sprintf(FT, NewArgs);
469c3a84099SChris Lattner 
470a89ec99fSNick Lewycky   fputs(Buffer, (FILE *) GVTOP(Args[0]));
471c3a84099SChris Lattner   return GV;
472c3a84099SChris Lattner }
473c3a84099SChris Lattner 
lle_X_memset(FunctionType * FT,ArrayRef<GenericValue> Args)474fcb71664SBenjamin Kramer static GenericValue lle_X_memset(FunctionType *FT,
475bd7b1c89SBenjamin Kramer                                  ArrayRef<GenericValue> Args) {
476843657c3SElena Demikhovsky   int val = (int)Args[1].IntVal.getSExtValue();
477843657c3SElena Demikhovsky   size_t len = (size_t)Args[2].IntVal.getZExtValue();
478843657c3SElena Demikhovsky   memset((void *)GVTOP(Args[0]), val, len);
479843657c3SElena Demikhovsky   // llvm.memset.* returns void, lle_X_* returns GenericValue,
480843657c3SElena Demikhovsky   // so here we return GenericValue with IntVal set to zero
481843657c3SElena Demikhovsky   GenericValue GV;
482843657c3SElena Demikhovsky   GV.IntVal = 0;
483843657c3SElena Demikhovsky   return GV;
484843657c3SElena Demikhovsky }
485843657c3SElena Demikhovsky 
lle_X_memcpy(FunctionType * FT,ArrayRef<GenericValue> Args)486fcb71664SBenjamin Kramer static GenericValue lle_X_memcpy(FunctionType *FT,
487bd7b1c89SBenjamin Kramer                                  ArrayRef<GenericValue> Args) {
488843657c3SElena Demikhovsky   memcpy(GVTOP(Args[0]), GVTOP(Args[1]),
489843657c3SElena Demikhovsky          (size_t)(Args[2].IntVal.getLimitedValue()));
490843657c3SElena Demikhovsky 
491fcb71664SBenjamin Kramer   // llvm.memcpy* returns void, lle_X_* returns GenericValue,
492843657c3SElena Demikhovsky   // so here we return GenericValue with IntVal set to zero
493843657c3SElena Demikhovsky   GenericValue GV;
494843657c3SElena Demikhovsky   GV.IntVal = 0;
495843657c3SElena Demikhovsky   return GV;
496843657c3SElena Demikhovsky }
497843657c3SElena Demikhovsky 
initializeExternalFunctions()498470754e3SChris Lattner void Interpreter::initializeExternalFunctions() {
4995c96ef7cSOwen Anderson   sys::ScopedLock Writer(*FunctionsLock);
5003b1fd57eSChris Bieneman   (*FuncNames)["lle_X_atexit"]       = lle_X_atexit;
5013b1fd57eSChris Bieneman   (*FuncNames)["lle_X_exit"]         = lle_X_exit;
5023b1fd57eSChris Bieneman   (*FuncNames)["lle_X_abort"]        = lle_X_abort;
503a89ec99fSNick Lewycky 
5043b1fd57eSChris Bieneman   (*FuncNames)["lle_X_printf"]       = lle_X_printf;
5053b1fd57eSChris Bieneman   (*FuncNames)["lle_X_sprintf"]      = lle_X_sprintf;
5063b1fd57eSChris Bieneman   (*FuncNames)["lle_X_sscanf"]       = lle_X_sscanf;
5073b1fd57eSChris Bieneman   (*FuncNames)["lle_X_scanf"]        = lle_X_scanf;
5083b1fd57eSChris Bieneman   (*FuncNames)["lle_X_fprintf"]      = lle_X_fprintf;
5093b1fd57eSChris Bieneman   (*FuncNames)["lle_X_memset"]       = lle_X_memset;
5103b1fd57eSChris Bieneman   (*FuncNames)["lle_X_memcpy"]       = lle_X_memcpy;
5117fd51b54SChris Lattner }
512