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