17330f729Sjoerg //===-- ExternalFunctions.cpp - Implement External Functions --------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file contains both code to deal with invoking "external" functions, but
107330f729Sjoerg // also contains code that implements "exported" external functions.
117330f729Sjoerg //
127330f729Sjoerg // There are currently two mechanisms for handling external functions in the
137330f729Sjoerg // Interpreter. The first is to implement lle_* wrapper functions that are
147330f729Sjoerg // specific to well-known library functions which manually translate the
157330f729Sjoerg // arguments from GenericValues and make the call. If such a wrapper does
167330f729Sjoerg // not exist, and libffi is available, then the Interpreter will attempt to
177330f729Sjoerg // invoke the function using libffi, after finding its address.
187330f729Sjoerg //
197330f729Sjoerg //===----------------------------------------------------------------------===//
207330f729Sjoerg
217330f729Sjoerg #include "Interpreter.h"
227330f729Sjoerg #include "llvm/ADT/APInt.h"
237330f729Sjoerg #include "llvm/ADT/ArrayRef.h"
247330f729Sjoerg #include "llvm/Config/config.h" // Detect libffi
257330f729Sjoerg #include "llvm/ExecutionEngine/GenericValue.h"
267330f729Sjoerg #include "llvm/IR/DataLayout.h"
277330f729Sjoerg #include "llvm/IR/DerivedTypes.h"
287330f729Sjoerg #include "llvm/IR/Function.h"
297330f729Sjoerg #include "llvm/IR/Type.h"
307330f729Sjoerg #include "llvm/Support/Casting.h"
317330f729Sjoerg #include "llvm/Support/DynamicLibrary.h"
327330f729Sjoerg #include "llvm/Support/ErrorHandling.h"
337330f729Sjoerg #include "llvm/Support/ManagedStatic.h"
347330f729Sjoerg #include "llvm/Support/Mutex.h"
357330f729Sjoerg #include "llvm/Support/raw_ostream.h"
367330f729Sjoerg #include <cassert>
377330f729Sjoerg #include <cmath>
387330f729Sjoerg #include <csignal>
397330f729Sjoerg #include <cstdint>
407330f729Sjoerg #include <cstdio>
417330f729Sjoerg #include <cstring>
427330f729Sjoerg #include <map>
437330f729Sjoerg #include <mutex>
447330f729Sjoerg #include <string>
457330f729Sjoerg #include <utility>
467330f729Sjoerg #include <vector>
477330f729Sjoerg
487330f729Sjoerg #ifdef HAVE_FFI_CALL
497330f729Sjoerg #ifdef HAVE_FFI_H
507330f729Sjoerg #include <ffi.h>
517330f729Sjoerg #define USE_LIBFFI
527330f729Sjoerg #elif HAVE_FFI_FFI_H
537330f729Sjoerg #include <ffi/ffi.h>
547330f729Sjoerg #define USE_LIBFFI
557330f729Sjoerg #endif
567330f729Sjoerg #endif
577330f729Sjoerg
587330f729Sjoerg using namespace llvm;
597330f729Sjoerg
607330f729Sjoerg static ManagedStatic<sys::Mutex> FunctionsLock;
617330f729Sjoerg
627330f729Sjoerg typedef GenericValue (*ExFunc)(FunctionType *, ArrayRef<GenericValue>);
637330f729Sjoerg static ManagedStatic<std::map<const Function *, ExFunc> > ExportedFunctions;
647330f729Sjoerg static ManagedStatic<std::map<std::string, ExFunc> > FuncNames;
657330f729Sjoerg
667330f729Sjoerg #ifdef USE_LIBFFI
677330f729Sjoerg typedef void (*RawFunc)();
687330f729Sjoerg static ManagedStatic<std::map<const Function *, RawFunc> > RawFunctions;
697330f729Sjoerg #endif
707330f729Sjoerg
717330f729Sjoerg static Interpreter *TheInterpreter;
727330f729Sjoerg
getTypeID(Type * Ty)737330f729Sjoerg static char getTypeID(Type *Ty) {
747330f729Sjoerg switch (Ty->getTypeID()) {
757330f729Sjoerg case Type::VoidTyID: return 'V';
767330f729Sjoerg case Type::IntegerTyID:
777330f729Sjoerg switch (cast<IntegerType>(Ty)->getBitWidth()) {
787330f729Sjoerg case 1: return 'o';
797330f729Sjoerg case 8: return 'B';
807330f729Sjoerg case 16: return 'S';
817330f729Sjoerg case 32: return 'I';
827330f729Sjoerg case 64: return 'L';
837330f729Sjoerg default: return 'N';
847330f729Sjoerg }
857330f729Sjoerg case Type::FloatTyID: return 'F';
867330f729Sjoerg case Type::DoubleTyID: return 'D';
877330f729Sjoerg case Type::PointerTyID: return 'P';
887330f729Sjoerg case Type::FunctionTyID:return 'M';
897330f729Sjoerg case Type::StructTyID: return 'T';
907330f729Sjoerg case Type::ArrayTyID: return 'A';
917330f729Sjoerg default: return 'U';
927330f729Sjoerg }
937330f729Sjoerg }
947330f729Sjoerg
957330f729Sjoerg // Try to find address of external function given a Function object.
967330f729Sjoerg // Please note, that interpreter doesn't know how to assemble a
977330f729Sjoerg // real call in general case (this is JIT job), that's why it assumes,
987330f729Sjoerg // that all external functions has the same (and pretty "general") signature.
997330f729Sjoerg // The typical example of such functions are "lle_X_" ones.
lookupFunction(const Function * F)1007330f729Sjoerg static ExFunc lookupFunction(const Function *F) {
1017330f729Sjoerg // Function not found, look it up... start by figuring out what the
1027330f729Sjoerg // composite function name should be.
1037330f729Sjoerg std::string ExtName = "lle_";
1047330f729Sjoerg FunctionType *FT = F->getFunctionType();
1057330f729Sjoerg ExtName += getTypeID(FT->getReturnType());
1067330f729Sjoerg for (Type *T : FT->params())
1077330f729Sjoerg ExtName += getTypeID(T);
1087330f729Sjoerg ExtName += ("_" + F->getName()).str();
1097330f729Sjoerg
1107330f729Sjoerg sys::ScopedLock Writer(*FunctionsLock);
1117330f729Sjoerg ExFunc FnPtr = (*FuncNames)[ExtName];
1127330f729Sjoerg if (!FnPtr)
1137330f729Sjoerg FnPtr = (*FuncNames)[("lle_X_" + F->getName()).str()];
1147330f729Sjoerg if (!FnPtr) // Try calling a generic function... if it exists...
1157330f729Sjoerg FnPtr = (ExFunc)(intptr_t)sys::DynamicLibrary::SearchForAddressOfSymbol(
1167330f729Sjoerg ("lle_X_" + F->getName()).str());
1177330f729Sjoerg if (FnPtr)
1187330f729Sjoerg ExportedFunctions->insert(std::make_pair(F, FnPtr)); // Cache for later
1197330f729Sjoerg return FnPtr;
1207330f729Sjoerg }
1217330f729Sjoerg
1227330f729Sjoerg #ifdef USE_LIBFFI
ffiTypeFor(Type * Ty)1237330f729Sjoerg static ffi_type *ffiTypeFor(Type *Ty) {
1247330f729Sjoerg switch (Ty->getTypeID()) {
1257330f729Sjoerg case Type::VoidTyID: return &ffi_type_void;
1267330f729Sjoerg case Type::IntegerTyID:
1277330f729Sjoerg switch (cast<IntegerType>(Ty)->getBitWidth()) {
1287330f729Sjoerg case 8: return &ffi_type_sint8;
1297330f729Sjoerg case 16: return &ffi_type_sint16;
1307330f729Sjoerg case 32: return &ffi_type_sint32;
1317330f729Sjoerg case 64: return &ffi_type_sint64;
1327330f729Sjoerg }
1337330f729Sjoerg case Type::FloatTyID: return &ffi_type_float;
1347330f729Sjoerg case Type::DoubleTyID: return &ffi_type_double;
1357330f729Sjoerg case Type::PointerTyID: return &ffi_type_pointer;
1367330f729Sjoerg default: break;
1377330f729Sjoerg }
1387330f729Sjoerg // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
1397330f729Sjoerg report_fatal_error("Type could not be mapped for use with libffi.");
1407330f729Sjoerg return NULL;
1417330f729Sjoerg }
1427330f729Sjoerg
ffiValueFor(Type * Ty,const GenericValue & AV,void * ArgDataPtr)1437330f729Sjoerg static void *ffiValueFor(Type *Ty, const GenericValue &AV,
1447330f729Sjoerg void *ArgDataPtr) {
1457330f729Sjoerg switch (Ty->getTypeID()) {
1467330f729Sjoerg case Type::IntegerTyID:
1477330f729Sjoerg switch (cast<IntegerType>(Ty)->getBitWidth()) {
1487330f729Sjoerg case 8: {
1497330f729Sjoerg int8_t *I8Ptr = (int8_t *) ArgDataPtr;
1507330f729Sjoerg *I8Ptr = (int8_t) AV.IntVal.getZExtValue();
1517330f729Sjoerg return ArgDataPtr;
1527330f729Sjoerg }
1537330f729Sjoerg case 16: {
1547330f729Sjoerg int16_t *I16Ptr = (int16_t *) ArgDataPtr;
1557330f729Sjoerg *I16Ptr = (int16_t) AV.IntVal.getZExtValue();
1567330f729Sjoerg return ArgDataPtr;
1577330f729Sjoerg }
1587330f729Sjoerg case 32: {
1597330f729Sjoerg int32_t *I32Ptr = (int32_t *) ArgDataPtr;
1607330f729Sjoerg *I32Ptr = (int32_t) AV.IntVal.getZExtValue();
1617330f729Sjoerg return ArgDataPtr;
1627330f729Sjoerg }
1637330f729Sjoerg case 64: {
1647330f729Sjoerg int64_t *I64Ptr = (int64_t *) ArgDataPtr;
1657330f729Sjoerg *I64Ptr = (int64_t) AV.IntVal.getZExtValue();
1667330f729Sjoerg return ArgDataPtr;
1677330f729Sjoerg }
1687330f729Sjoerg }
1697330f729Sjoerg case Type::FloatTyID: {
1707330f729Sjoerg float *FloatPtr = (float *) ArgDataPtr;
1717330f729Sjoerg *FloatPtr = AV.FloatVal;
1727330f729Sjoerg return ArgDataPtr;
1737330f729Sjoerg }
1747330f729Sjoerg case Type::DoubleTyID: {
1757330f729Sjoerg double *DoublePtr = (double *) ArgDataPtr;
1767330f729Sjoerg *DoublePtr = AV.DoubleVal;
1777330f729Sjoerg return ArgDataPtr;
1787330f729Sjoerg }
1797330f729Sjoerg case Type::PointerTyID: {
1807330f729Sjoerg void **PtrPtr = (void **) ArgDataPtr;
1817330f729Sjoerg *PtrPtr = GVTOP(AV);
1827330f729Sjoerg return ArgDataPtr;
1837330f729Sjoerg }
1847330f729Sjoerg default: break;
1857330f729Sjoerg }
1867330f729Sjoerg // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
1877330f729Sjoerg report_fatal_error("Type value could not be mapped for use with libffi.");
1887330f729Sjoerg return NULL;
1897330f729Sjoerg }
1907330f729Sjoerg
ffiInvoke(RawFunc Fn,Function * F,ArrayRef<GenericValue> ArgVals,const DataLayout & TD,GenericValue & Result)1917330f729Sjoerg static bool ffiInvoke(RawFunc Fn, Function *F, ArrayRef<GenericValue> ArgVals,
1927330f729Sjoerg const DataLayout &TD, GenericValue &Result) {
1937330f729Sjoerg ffi_cif cif;
1947330f729Sjoerg FunctionType *FTy = F->getFunctionType();
1957330f729Sjoerg const unsigned NumArgs = F->arg_size();
1967330f729Sjoerg
1977330f729Sjoerg // TODO: We don't have type information about the remaining arguments, because
1987330f729Sjoerg // this information is never passed into ExecutionEngine::runFunction().
1997330f729Sjoerg if (ArgVals.size() > NumArgs && F->isVarArg()) {
2007330f729Sjoerg report_fatal_error("Calling external var arg function '" + F->getName()
2017330f729Sjoerg + "' is not supported by the Interpreter.");
2027330f729Sjoerg }
2037330f729Sjoerg
2047330f729Sjoerg unsigned ArgBytes = 0;
2057330f729Sjoerg
2067330f729Sjoerg std::vector<ffi_type*> args(NumArgs);
2077330f729Sjoerg for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
2087330f729Sjoerg A != E; ++A) {
2097330f729Sjoerg const unsigned ArgNo = A->getArgNo();
2107330f729Sjoerg Type *ArgTy = FTy->getParamType(ArgNo);
2117330f729Sjoerg args[ArgNo] = ffiTypeFor(ArgTy);
2127330f729Sjoerg ArgBytes += TD.getTypeStoreSize(ArgTy);
2137330f729Sjoerg }
2147330f729Sjoerg
2157330f729Sjoerg SmallVector<uint8_t, 128> ArgData;
2167330f729Sjoerg ArgData.resize(ArgBytes);
2177330f729Sjoerg uint8_t *ArgDataPtr = ArgData.data();
2187330f729Sjoerg SmallVector<void*, 16> values(NumArgs);
2197330f729Sjoerg for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
2207330f729Sjoerg A != E; ++A) {
2217330f729Sjoerg const unsigned ArgNo = A->getArgNo();
2227330f729Sjoerg Type *ArgTy = FTy->getParamType(ArgNo);
2237330f729Sjoerg values[ArgNo] = ffiValueFor(ArgTy, ArgVals[ArgNo], ArgDataPtr);
2247330f729Sjoerg ArgDataPtr += TD.getTypeStoreSize(ArgTy);
2257330f729Sjoerg }
2267330f729Sjoerg
2277330f729Sjoerg Type *RetTy = FTy->getReturnType();
2287330f729Sjoerg ffi_type *rtype = ffiTypeFor(RetTy);
2297330f729Sjoerg
2307330f729Sjoerg if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, args.data()) ==
2317330f729Sjoerg FFI_OK) {
2327330f729Sjoerg SmallVector<uint8_t, 128> ret;
2337330f729Sjoerg if (RetTy->getTypeID() != Type::VoidTyID)
2347330f729Sjoerg ret.resize(TD.getTypeStoreSize(RetTy));
2357330f729Sjoerg ffi_call(&cif, Fn, ret.data(), values.data());
2367330f729Sjoerg switch (RetTy->getTypeID()) {
2377330f729Sjoerg case Type::IntegerTyID:
2387330f729Sjoerg switch (cast<IntegerType>(RetTy)->getBitWidth()) {
2397330f729Sjoerg case 8: Result.IntVal = APInt(8 , *(int8_t *) ret.data()); break;
2407330f729Sjoerg case 16: Result.IntVal = APInt(16, *(int16_t*) ret.data()); break;
2417330f729Sjoerg case 32: Result.IntVal = APInt(32, *(int32_t*) ret.data()); break;
2427330f729Sjoerg case 64: Result.IntVal = APInt(64, *(int64_t*) ret.data()); break;
2437330f729Sjoerg }
2447330f729Sjoerg break;
2457330f729Sjoerg case Type::FloatTyID: Result.FloatVal = *(float *) ret.data(); break;
2467330f729Sjoerg case Type::DoubleTyID: Result.DoubleVal = *(double*) ret.data(); break;
2477330f729Sjoerg case Type::PointerTyID: Result.PointerVal = *(void **) ret.data(); break;
2487330f729Sjoerg default: break;
2497330f729Sjoerg }
2507330f729Sjoerg return true;
2517330f729Sjoerg }
2527330f729Sjoerg
2537330f729Sjoerg return false;
2547330f729Sjoerg }
2557330f729Sjoerg #endif // USE_LIBFFI
2567330f729Sjoerg
callExternalFunction(Function * F,ArrayRef<GenericValue> ArgVals)2577330f729Sjoerg GenericValue Interpreter::callExternalFunction(Function *F,
2587330f729Sjoerg ArrayRef<GenericValue> ArgVals) {
2597330f729Sjoerg TheInterpreter = this;
2607330f729Sjoerg
2617330f729Sjoerg std::unique_lock<sys::Mutex> Guard(*FunctionsLock);
2627330f729Sjoerg
2637330f729Sjoerg // Do a lookup to see if the function is in our cache... this should just be a
2647330f729Sjoerg // deferred annotation!
2657330f729Sjoerg std::map<const Function *, ExFunc>::iterator FI = ExportedFunctions->find(F);
2667330f729Sjoerg if (ExFunc Fn = (FI == ExportedFunctions->end()) ? lookupFunction(F)
2677330f729Sjoerg : FI->second) {
2687330f729Sjoerg Guard.unlock();
2697330f729Sjoerg return Fn(F->getFunctionType(), ArgVals);
2707330f729Sjoerg }
2717330f729Sjoerg
2727330f729Sjoerg #ifdef USE_LIBFFI
2737330f729Sjoerg std::map<const Function *, RawFunc>::iterator RF = RawFunctions->find(F);
2747330f729Sjoerg RawFunc RawFn;
2757330f729Sjoerg if (RF == RawFunctions->end()) {
2767330f729Sjoerg RawFn = (RawFunc)(intptr_t)
277*82d56013Sjoerg sys::DynamicLibrary::SearchForAddressOfSymbol(std::string(F->getName()));
2787330f729Sjoerg if (!RawFn)
2797330f729Sjoerg RawFn = (RawFunc)(intptr_t)getPointerToGlobalIfAvailable(F);
2807330f729Sjoerg if (RawFn != 0)
2817330f729Sjoerg RawFunctions->insert(std::make_pair(F, RawFn)); // Cache for later
2827330f729Sjoerg } else {
2837330f729Sjoerg RawFn = RF->second;
2847330f729Sjoerg }
2857330f729Sjoerg
2867330f729Sjoerg Guard.unlock();
2877330f729Sjoerg
2887330f729Sjoerg GenericValue Result;
2897330f729Sjoerg if (RawFn != 0 && ffiInvoke(RawFn, F, ArgVals, getDataLayout(), Result))
2907330f729Sjoerg return Result;
2917330f729Sjoerg #endif // USE_LIBFFI
2927330f729Sjoerg
2937330f729Sjoerg if (F->getName() == "__main")
2947330f729Sjoerg errs() << "Tried to execute an unknown external function: "
2957330f729Sjoerg << *F->getType() << " __main\n";
2967330f729Sjoerg else
2977330f729Sjoerg report_fatal_error("Tried to execute an unknown external function: " +
2987330f729Sjoerg F->getName());
2997330f729Sjoerg #ifndef USE_LIBFFI
3007330f729Sjoerg errs() << "Recompiling LLVM with --enable-libffi might help.\n";
3017330f729Sjoerg #endif
3027330f729Sjoerg return GenericValue();
3037330f729Sjoerg }
3047330f729Sjoerg
3057330f729Sjoerg //===----------------------------------------------------------------------===//
3067330f729Sjoerg // Functions "exported" to the running application...
3077330f729Sjoerg //
3087330f729Sjoerg
3097330f729Sjoerg // void atexit(Function*)
lle_X_atexit(FunctionType * FT,ArrayRef<GenericValue> Args)3107330f729Sjoerg static GenericValue lle_X_atexit(FunctionType *FT,
3117330f729Sjoerg ArrayRef<GenericValue> Args) {
3127330f729Sjoerg assert(Args.size() == 1);
3137330f729Sjoerg TheInterpreter->addAtExitHandler((Function*)GVTOP(Args[0]));
3147330f729Sjoerg GenericValue GV;
3157330f729Sjoerg GV.IntVal = 0;
3167330f729Sjoerg return GV;
3177330f729Sjoerg }
3187330f729Sjoerg
3197330f729Sjoerg // void exit(int)
lle_X_exit(FunctionType * FT,ArrayRef<GenericValue> Args)3207330f729Sjoerg static GenericValue lle_X_exit(FunctionType *FT, ArrayRef<GenericValue> Args) {
3217330f729Sjoerg TheInterpreter->exitCalled(Args[0]);
3227330f729Sjoerg return GenericValue();
3237330f729Sjoerg }
3247330f729Sjoerg
3257330f729Sjoerg // void abort(void)
lle_X_abort(FunctionType * FT,ArrayRef<GenericValue> Args)3267330f729Sjoerg static GenericValue lle_X_abort(FunctionType *FT, ArrayRef<GenericValue> Args) {
3277330f729Sjoerg //FIXME: should we report or raise here?
3287330f729Sjoerg //report_fatal_error("Interpreted program raised SIGABRT");
3297330f729Sjoerg raise (SIGABRT);
3307330f729Sjoerg return GenericValue();
3317330f729Sjoerg }
3327330f729Sjoerg
3337330f729Sjoerg // int sprintf(char *, const char *, ...) - a very rough implementation to make
3347330f729Sjoerg // output useful.
lle_X_sprintf(FunctionType * FT,ArrayRef<GenericValue> Args)3357330f729Sjoerg static GenericValue lle_X_sprintf(FunctionType *FT,
3367330f729Sjoerg ArrayRef<GenericValue> Args) {
3377330f729Sjoerg char *OutputBuffer = (char *)GVTOP(Args[0]);
3387330f729Sjoerg const char *FmtStr = (const char *)GVTOP(Args[1]);
3397330f729Sjoerg unsigned ArgNo = 2;
3407330f729Sjoerg
3417330f729Sjoerg // printf should return # chars printed. This is completely incorrect, but
3427330f729Sjoerg // close enough for now.
3437330f729Sjoerg GenericValue GV;
3447330f729Sjoerg GV.IntVal = APInt(32, strlen(FmtStr));
3457330f729Sjoerg while (true) {
3467330f729Sjoerg switch (*FmtStr) {
3477330f729Sjoerg case 0: return GV; // Null terminator...
3487330f729Sjoerg default: // Normal nonspecial character
3497330f729Sjoerg sprintf(OutputBuffer++, "%c", *FmtStr++);
3507330f729Sjoerg break;
3517330f729Sjoerg case '\\': { // Handle escape codes
3527330f729Sjoerg sprintf(OutputBuffer, "%c%c", *FmtStr, *(FmtStr+1));
3537330f729Sjoerg FmtStr += 2; OutputBuffer += 2;
3547330f729Sjoerg break;
3557330f729Sjoerg }
3567330f729Sjoerg case '%': { // Handle format specifiers
3577330f729Sjoerg char FmtBuf[100] = "", Buffer[1000] = "";
3587330f729Sjoerg char *FB = FmtBuf;
3597330f729Sjoerg *FB++ = *FmtStr++;
3607330f729Sjoerg char Last = *FB++ = *FmtStr++;
3617330f729Sjoerg unsigned HowLong = 0;
3627330f729Sjoerg while (Last != 'c' && Last != 'd' && Last != 'i' && Last != 'u' &&
3637330f729Sjoerg Last != 'o' && Last != 'x' && Last != 'X' && Last != 'e' &&
3647330f729Sjoerg Last != 'E' && Last != 'g' && Last != 'G' && Last != 'f' &&
3657330f729Sjoerg Last != 'p' && Last != 's' && Last != '%') {
3667330f729Sjoerg if (Last == 'l' || Last == 'L') HowLong++; // Keep track of l's
3677330f729Sjoerg Last = *FB++ = *FmtStr++;
3687330f729Sjoerg }
3697330f729Sjoerg *FB = 0;
3707330f729Sjoerg
3717330f729Sjoerg switch (Last) {
3727330f729Sjoerg case '%':
3737330f729Sjoerg memcpy(Buffer, "%", 2); break;
3747330f729Sjoerg case 'c':
3757330f729Sjoerg sprintf(Buffer, FmtBuf, uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
3767330f729Sjoerg break;
3777330f729Sjoerg case 'd': case 'i':
3787330f729Sjoerg case 'u': case 'o':
3797330f729Sjoerg case 'x': case 'X':
3807330f729Sjoerg if (HowLong >= 1) {
3817330f729Sjoerg if (HowLong == 1 &&
3827330f729Sjoerg TheInterpreter->getDataLayout().getPointerSizeInBits() == 64 &&
3837330f729Sjoerg sizeof(long) < sizeof(int64_t)) {
3847330f729Sjoerg // Make sure we use %lld with a 64 bit argument because we might be
3857330f729Sjoerg // compiling LLI on a 32 bit compiler.
3867330f729Sjoerg unsigned Size = strlen(FmtBuf);
3877330f729Sjoerg FmtBuf[Size] = FmtBuf[Size-1];
3887330f729Sjoerg FmtBuf[Size+1] = 0;
3897330f729Sjoerg FmtBuf[Size-1] = 'l';
3907330f729Sjoerg }
3917330f729Sjoerg sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal.getZExtValue());
3927330f729Sjoerg } else
3937330f729Sjoerg sprintf(Buffer, FmtBuf,uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
3947330f729Sjoerg break;
3957330f729Sjoerg case 'e': case 'E': case 'g': case 'G': case 'f':
3967330f729Sjoerg sprintf(Buffer, FmtBuf, Args[ArgNo++].DoubleVal); break;
3977330f729Sjoerg case 'p':
3987330f729Sjoerg sprintf(Buffer, FmtBuf, (void*)GVTOP(Args[ArgNo++])); break;
3997330f729Sjoerg case 's':
4007330f729Sjoerg sprintf(Buffer, FmtBuf, (char*)GVTOP(Args[ArgNo++])); break;
4017330f729Sjoerg default:
4027330f729Sjoerg errs() << "<unknown printf code '" << *FmtStr << "'!>";
4037330f729Sjoerg ArgNo++; break;
4047330f729Sjoerg }
4057330f729Sjoerg size_t Len = strlen(Buffer);
4067330f729Sjoerg memcpy(OutputBuffer, Buffer, Len + 1);
4077330f729Sjoerg OutputBuffer += Len;
4087330f729Sjoerg }
4097330f729Sjoerg break;
4107330f729Sjoerg }
4117330f729Sjoerg }
4127330f729Sjoerg return GV;
4137330f729Sjoerg }
4147330f729Sjoerg
4157330f729Sjoerg // int printf(const char *, ...) - a very rough implementation to make output
4167330f729Sjoerg // useful.
lle_X_printf(FunctionType * FT,ArrayRef<GenericValue> Args)4177330f729Sjoerg static GenericValue lle_X_printf(FunctionType *FT,
4187330f729Sjoerg ArrayRef<GenericValue> Args) {
4197330f729Sjoerg char Buffer[10000];
4207330f729Sjoerg std::vector<GenericValue> NewArgs;
4217330f729Sjoerg NewArgs.push_back(PTOGV((void*)&Buffer[0]));
422*82d56013Sjoerg llvm::append_range(NewArgs, Args);
4237330f729Sjoerg GenericValue GV = lle_X_sprintf(FT, NewArgs);
4247330f729Sjoerg outs() << Buffer;
4257330f729Sjoerg return GV;
4267330f729Sjoerg }
4277330f729Sjoerg
4287330f729Sjoerg // int sscanf(const char *format, ...);
lle_X_sscanf(FunctionType * FT,ArrayRef<GenericValue> args)4297330f729Sjoerg static GenericValue lle_X_sscanf(FunctionType *FT,
4307330f729Sjoerg ArrayRef<GenericValue> args) {
4317330f729Sjoerg assert(args.size() < 10 && "Only handle up to 10 args to sscanf right now!");
4327330f729Sjoerg
4337330f729Sjoerg char *Args[10];
4347330f729Sjoerg for (unsigned i = 0; i < args.size(); ++i)
4357330f729Sjoerg Args[i] = (char*)GVTOP(args[i]);
4367330f729Sjoerg
4377330f729Sjoerg GenericValue GV;
4387330f729Sjoerg GV.IntVal = APInt(32, sscanf(Args[0], Args[1], Args[2], Args[3], Args[4],
4397330f729Sjoerg Args[5], Args[6], Args[7], Args[8], Args[9]));
4407330f729Sjoerg return GV;
4417330f729Sjoerg }
4427330f729Sjoerg
4437330f729Sjoerg // int scanf(const char *format, ...);
lle_X_scanf(FunctionType * FT,ArrayRef<GenericValue> args)4447330f729Sjoerg static GenericValue lle_X_scanf(FunctionType *FT, ArrayRef<GenericValue> args) {
4457330f729Sjoerg assert(args.size() < 10 && "Only handle up to 10 args to scanf right now!");
4467330f729Sjoerg
4477330f729Sjoerg char *Args[10];
4487330f729Sjoerg for (unsigned i = 0; i < args.size(); ++i)
4497330f729Sjoerg Args[i] = (char*)GVTOP(args[i]);
4507330f729Sjoerg
4517330f729Sjoerg GenericValue GV;
4527330f729Sjoerg GV.IntVal = APInt(32, scanf( Args[0], Args[1], Args[2], Args[3], Args[4],
4537330f729Sjoerg Args[5], Args[6], Args[7], Args[8], Args[9]));
4547330f729Sjoerg return GV;
4557330f729Sjoerg }
4567330f729Sjoerg
4577330f729Sjoerg // int fprintf(FILE *, const char *, ...) - a very rough implementation to make
4587330f729Sjoerg // output useful.
lle_X_fprintf(FunctionType * FT,ArrayRef<GenericValue> Args)4597330f729Sjoerg static GenericValue lle_X_fprintf(FunctionType *FT,
4607330f729Sjoerg ArrayRef<GenericValue> Args) {
4617330f729Sjoerg assert(Args.size() >= 2);
4627330f729Sjoerg char Buffer[10000];
4637330f729Sjoerg std::vector<GenericValue> NewArgs;
4647330f729Sjoerg NewArgs.push_back(PTOGV(Buffer));
4657330f729Sjoerg NewArgs.insert(NewArgs.end(), Args.begin()+1, Args.end());
4667330f729Sjoerg GenericValue GV = lle_X_sprintf(FT, NewArgs);
4677330f729Sjoerg
4687330f729Sjoerg fputs(Buffer, (FILE *) GVTOP(Args[0]));
4697330f729Sjoerg return GV;
4707330f729Sjoerg }
4717330f729Sjoerg
lle_X_memset(FunctionType * FT,ArrayRef<GenericValue> Args)4727330f729Sjoerg static GenericValue lle_X_memset(FunctionType *FT,
4737330f729Sjoerg ArrayRef<GenericValue> Args) {
4747330f729Sjoerg int val = (int)Args[1].IntVal.getSExtValue();
4757330f729Sjoerg size_t len = (size_t)Args[2].IntVal.getZExtValue();
4767330f729Sjoerg memset((void *)GVTOP(Args[0]), val, len);
4777330f729Sjoerg // llvm.memset.* returns void, lle_X_* returns GenericValue,
4787330f729Sjoerg // so here we return GenericValue with IntVal set to zero
4797330f729Sjoerg GenericValue GV;
4807330f729Sjoerg GV.IntVal = 0;
4817330f729Sjoerg return GV;
4827330f729Sjoerg }
4837330f729Sjoerg
lle_X_memcpy(FunctionType * FT,ArrayRef<GenericValue> Args)4847330f729Sjoerg static GenericValue lle_X_memcpy(FunctionType *FT,
4857330f729Sjoerg ArrayRef<GenericValue> Args) {
4867330f729Sjoerg memcpy(GVTOP(Args[0]), GVTOP(Args[1]),
4877330f729Sjoerg (size_t)(Args[2].IntVal.getLimitedValue()));
4887330f729Sjoerg
4897330f729Sjoerg // llvm.memcpy* returns void, lle_X_* returns GenericValue,
4907330f729Sjoerg // so here we return GenericValue with IntVal set to zero
4917330f729Sjoerg GenericValue GV;
4927330f729Sjoerg GV.IntVal = 0;
4937330f729Sjoerg return GV;
4947330f729Sjoerg }
4957330f729Sjoerg
initializeExternalFunctions()4967330f729Sjoerg void Interpreter::initializeExternalFunctions() {
4977330f729Sjoerg sys::ScopedLock Writer(*FunctionsLock);
4987330f729Sjoerg (*FuncNames)["lle_X_atexit"] = lle_X_atexit;
4997330f729Sjoerg (*FuncNames)["lle_X_exit"] = lle_X_exit;
5007330f729Sjoerg (*FuncNames)["lle_X_abort"] = lle_X_abort;
5017330f729Sjoerg
5027330f729Sjoerg (*FuncNames)["lle_X_printf"] = lle_X_printf;
5037330f729Sjoerg (*FuncNames)["lle_X_sprintf"] = lle_X_sprintf;
5047330f729Sjoerg (*FuncNames)["lle_X_sscanf"] = lle_X_sscanf;
5057330f729Sjoerg (*FuncNames)["lle_X_scanf"] = lle_X_scanf;
5067330f729Sjoerg (*FuncNames)["lle_X_fprintf"] = lle_X_fprintf;
5077330f729Sjoerg (*FuncNames)["lle_X_memset"] = lle_X_memset;
5087330f729Sjoerg (*FuncNames)["lle_X_memcpy"] = lle_X_memcpy;
5097330f729Sjoerg }
510