xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
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