106f32e7eSjoerg //===-- ExternalFunctions.cpp - Implement External Functions --------------===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg //  This file contains both code to deal with invoking "external" functions, but
1006f32e7eSjoerg //  also contains code that implements "exported" external functions.
1106f32e7eSjoerg //
1206f32e7eSjoerg //  There are currently two mechanisms for handling external functions in the
1306f32e7eSjoerg //  Interpreter.  The first is to implement lle_* wrapper functions that are
1406f32e7eSjoerg //  specific to well-known library functions which manually translate the
1506f32e7eSjoerg //  arguments from GenericValues and make the call.  If such a wrapper does
1606f32e7eSjoerg //  not exist, and libffi is available, then the Interpreter will attempt to
1706f32e7eSjoerg //  invoke the function using libffi, after finding its address.
1806f32e7eSjoerg //
1906f32e7eSjoerg //===----------------------------------------------------------------------===//
2006f32e7eSjoerg 
2106f32e7eSjoerg #include "Interpreter.h"
2206f32e7eSjoerg #include "llvm/ADT/APInt.h"
2306f32e7eSjoerg #include "llvm/ADT/ArrayRef.h"
2406f32e7eSjoerg #include "llvm/Config/config.h" // Detect libffi
2506f32e7eSjoerg #include "llvm/ExecutionEngine/GenericValue.h"
2606f32e7eSjoerg #include "llvm/IR/DataLayout.h"
2706f32e7eSjoerg #include "llvm/IR/DerivedTypes.h"
2806f32e7eSjoerg #include "llvm/IR/Function.h"
2906f32e7eSjoerg #include "llvm/IR/Type.h"
3006f32e7eSjoerg #include "llvm/Support/Casting.h"
3106f32e7eSjoerg #include "llvm/Support/DynamicLibrary.h"
3206f32e7eSjoerg #include "llvm/Support/ErrorHandling.h"
3306f32e7eSjoerg #include "llvm/Support/ManagedStatic.h"
3406f32e7eSjoerg #include "llvm/Support/Mutex.h"
3506f32e7eSjoerg #include "llvm/Support/raw_ostream.h"
3606f32e7eSjoerg #include <cassert>
3706f32e7eSjoerg #include <cmath>
3806f32e7eSjoerg #include <csignal>
3906f32e7eSjoerg #include <cstdint>
4006f32e7eSjoerg #include <cstdio>
4106f32e7eSjoerg #include <cstring>
4206f32e7eSjoerg #include <map>
4306f32e7eSjoerg #include <mutex>
4406f32e7eSjoerg #include <string>
4506f32e7eSjoerg #include <utility>
4606f32e7eSjoerg #include <vector>
4706f32e7eSjoerg 
4806f32e7eSjoerg #ifdef HAVE_FFI_CALL
4906f32e7eSjoerg #ifdef HAVE_FFI_H
5006f32e7eSjoerg #include <ffi.h>
5106f32e7eSjoerg #define USE_LIBFFI
5206f32e7eSjoerg #elif HAVE_FFI_FFI_H
5306f32e7eSjoerg #include <ffi/ffi.h>
5406f32e7eSjoerg #define USE_LIBFFI
5506f32e7eSjoerg #endif
5606f32e7eSjoerg #endif
5706f32e7eSjoerg 
5806f32e7eSjoerg using namespace llvm;
5906f32e7eSjoerg 
6006f32e7eSjoerg static ManagedStatic<sys::Mutex> FunctionsLock;
6106f32e7eSjoerg 
6206f32e7eSjoerg typedef GenericValue (*ExFunc)(FunctionType *, ArrayRef<GenericValue>);
6306f32e7eSjoerg static ManagedStatic<std::map<const Function *, ExFunc> > ExportedFunctions;
6406f32e7eSjoerg static ManagedStatic<std::map<std::string, ExFunc> > FuncNames;
6506f32e7eSjoerg 
6606f32e7eSjoerg #ifdef USE_LIBFFI
6706f32e7eSjoerg typedef void (*RawFunc)();
6806f32e7eSjoerg static ManagedStatic<std::map<const Function *, RawFunc> > RawFunctions;
6906f32e7eSjoerg #endif
7006f32e7eSjoerg 
7106f32e7eSjoerg static Interpreter *TheInterpreter;
7206f32e7eSjoerg 
getTypeID(Type * Ty)7306f32e7eSjoerg static char getTypeID(Type *Ty) {
7406f32e7eSjoerg   switch (Ty->getTypeID()) {
7506f32e7eSjoerg   case Type::VoidTyID:    return 'V';
7606f32e7eSjoerg   case Type::IntegerTyID:
7706f32e7eSjoerg     switch (cast<IntegerType>(Ty)->getBitWidth()) {
7806f32e7eSjoerg       case 1:  return 'o';
7906f32e7eSjoerg       case 8:  return 'B';
8006f32e7eSjoerg       case 16: return 'S';
8106f32e7eSjoerg       case 32: return 'I';
8206f32e7eSjoerg       case 64: return 'L';
8306f32e7eSjoerg       default: return 'N';
8406f32e7eSjoerg     }
8506f32e7eSjoerg   case Type::FloatTyID:   return 'F';
8606f32e7eSjoerg   case Type::DoubleTyID:  return 'D';
8706f32e7eSjoerg   case Type::PointerTyID: return 'P';
8806f32e7eSjoerg   case Type::FunctionTyID:return 'M';
8906f32e7eSjoerg   case Type::StructTyID:  return 'T';
9006f32e7eSjoerg   case Type::ArrayTyID:   return 'A';
9106f32e7eSjoerg   default: return 'U';
9206f32e7eSjoerg   }
9306f32e7eSjoerg }
9406f32e7eSjoerg 
9506f32e7eSjoerg // Try to find address of external function given a Function object.
9606f32e7eSjoerg // Please note, that interpreter doesn't know how to assemble a
9706f32e7eSjoerg // real call in general case (this is JIT job), that's why it assumes,
9806f32e7eSjoerg // that all external functions has the same (and pretty "general") signature.
9906f32e7eSjoerg // The typical example of such functions are "lle_X_" ones.
lookupFunction(const Function * F)10006f32e7eSjoerg static ExFunc lookupFunction(const Function *F) {
10106f32e7eSjoerg   // Function not found, look it up... start by figuring out what the
10206f32e7eSjoerg   // composite function name should be.
10306f32e7eSjoerg   std::string ExtName = "lle_";
10406f32e7eSjoerg   FunctionType *FT = F->getFunctionType();
10506f32e7eSjoerg   ExtName += getTypeID(FT->getReturnType());
10606f32e7eSjoerg   for (Type *T : FT->params())
10706f32e7eSjoerg     ExtName += getTypeID(T);
10806f32e7eSjoerg   ExtName += ("_" + F->getName()).str();
10906f32e7eSjoerg 
11006f32e7eSjoerg   sys::ScopedLock Writer(*FunctionsLock);
11106f32e7eSjoerg   ExFunc FnPtr = (*FuncNames)[ExtName];
11206f32e7eSjoerg   if (!FnPtr)
11306f32e7eSjoerg     FnPtr = (*FuncNames)[("lle_X_" + F->getName()).str()];
11406f32e7eSjoerg   if (!FnPtr)  // Try calling a generic function... if it exists...
11506f32e7eSjoerg     FnPtr = (ExFunc)(intptr_t)sys::DynamicLibrary::SearchForAddressOfSymbol(
11606f32e7eSjoerg         ("lle_X_" + F->getName()).str());
11706f32e7eSjoerg   if (FnPtr)
11806f32e7eSjoerg     ExportedFunctions->insert(std::make_pair(F, FnPtr));  // Cache for later
11906f32e7eSjoerg   return FnPtr;
12006f32e7eSjoerg }
12106f32e7eSjoerg 
12206f32e7eSjoerg #ifdef USE_LIBFFI
ffiTypeFor(Type * Ty)12306f32e7eSjoerg static ffi_type *ffiTypeFor(Type *Ty) {
12406f32e7eSjoerg   switch (Ty->getTypeID()) {
12506f32e7eSjoerg     case Type::VoidTyID: return &ffi_type_void;
12606f32e7eSjoerg     case Type::IntegerTyID:
12706f32e7eSjoerg       switch (cast<IntegerType>(Ty)->getBitWidth()) {
12806f32e7eSjoerg         case 8:  return &ffi_type_sint8;
12906f32e7eSjoerg         case 16: return &ffi_type_sint16;
13006f32e7eSjoerg         case 32: return &ffi_type_sint32;
13106f32e7eSjoerg         case 64: return &ffi_type_sint64;
13206f32e7eSjoerg       }
13306f32e7eSjoerg     case Type::FloatTyID:   return &ffi_type_float;
13406f32e7eSjoerg     case Type::DoubleTyID:  return &ffi_type_double;
13506f32e7eSjoerg     case Type::PointerTyID: return &ffi_type_pointer;
13606f32e7eSjoerg     default: break;
13706f32e7eSjoerg   }
13806f32e7eSjoerg   // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
13906f32e7eSjoerg   report_fatal_error("Type could not be mapped for use with libffi.");
14006f32e7eSjoerg   return NULL;
14106f32e7eSjoerg }
14206f32e7eSjoerg 
ffiValueFor(Type * Ty,const GenericValue & AV,void * ArgDataPtr)14306f32e7eSjoerg static void *ffiValueFor(Type *Ty, const GenericValue &AV,
14406f32e7eSjoerg                          void *ArgDataPtr) {
14506f32e7eSjoerg   switch (Ty->getTypeID()) {
14606f32e7eSjoerg     case Type::IntegerTyID:
14706f32e7eSjoerg       switch (cast<IntegerType>(Ty)->getBitWidth()) {
14806f32e7eSjoerg         case 8: {
14906f32e7eSjoerg           int8_t *I8Ptr = (int8_t *) ArgDataPtr;
15006f32e7eSjoerg           *I8Ptr = (int8_t) AV.IntVal.getZExtValue();
15106f32e7eSjoerg           return ArgDataPtr;
15206f32e7eSjoerg         }
15306f32e7eSjoerg         case 16: {
15406f32e7eSjoerg           int16_t *I16Ptr = (int16_t *) ArgDataPtr;
15506f32e7eSjoerg           *I16Ptr = (int16_t) AV.IntVal.getZExtValue();
15606f32e7eSjoerg           return ArgDataPtr;
15706f32e7eSjoerg         }
15806f32e7eSjoerg         case 32: {
15906f32e7eSjoerg           int32_t *I32Ptr = (int32_t *) ArgDataPtr;
16006f32e7eSjoerg           *I32Ptr = (int32_t) AV.IntVal.getZExtValue();
16106f32e7eSjoerg           return ArgDataPtr;
16206f32e7eSjoerg         }
16306f32e7eSjoerg         case 64: {
16406f32e7eSjoerg           int64_t *I64Ptr = (int64_t *) ArgDataPtr;
16506f32e7eSjoerg           *I64Ptr = (int64_t) AV.IntVal.getZExtValue();
16606f32e7eSjoerg           return ArgDataPtr;
16706f32e7eSjoerg         }
16806f32e7eSjoerg       }
16906f32e7eSjoerg     case Type::FloatTyID: {
17006f32e7eSjoerg       float *FloatPtr = (float *) ArgDataPtr;
17106f32e7eSjoerg       *FloatPtr = AV.FloatVal;
17206f32e7eSjoerg       return ArgDataPtr;
17306f32e7eSjoerg     }
17406f32e7eSjoerg     case Type::DoubleTyID: {
17506f32e7eSjoerg       double *DoublePtr = (double *) ArgDataPtr;
17606f32e7eSjoerg       *DoublePtr = AV.DoubleVal;
17706f32e7eSjoerg       return ArgDataPtr;
17806f32e7eSjoerg     }
17906f32e7eSjoerg     case Type::PointerTyID: {
18006f32e7eSjoerg       void **PtrPtr = (void **) ArgDataPtr;
18106f32e7eSjoerg       *PtrPtr = GVTOP(AV);
18206f32e7eSjoerg       return ArgDataPtr;
18306f32e7eSjoerg     }
18406f32e7eSjoerg     default: break;
18506f32e7eSjoerg   }
18606f32e7eSjoerg   // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
18706f32e7eSjoerg   report_fatal_error("Type value could not be mapped for use with libffi.");
18806f32e7eSjoerg   return NULL;
18906f32e7eSjoerg }
19006f32e7eSjoerg 
ffiInvoke(RawFunc Fn,Function * F,ArrayRef<GenericValue> ArgVals,const DataLayout & TD,GenericValue & Result)19106f32e7eSjoerg static bool ffiInvoke(RawFunc Fn, Function *F, ArrayRef<GenericValue> ArgVals,
19206f32e7eSjoerg                       const DataLayout &TD, GenericValue &Result) {
19306f32e7eSjoerg   ffi_cif cif;
19406f32e7eSjoerg   FunctionType *FTy = F->getFunctionType();
19506f32e7eSjoerg   const unsigned NumArgs = F->arg_size();
19606f32e7eSjoerg 
19706f32e7eSjoerg   // TODO: We don't have type information about the remaining arguments, because
19806f32e7eSjoerg   // this information is never passed into ExecutionEngine::runFunction().
19906f32e7eSjoerg   if (ArgVals.size() > NumArgs && F->isVarArg()) {
20006f32e7eSjoerg     report_fatal_error("Calling external var arg function '" + F->getName()
20106f32e7eSjoerg                       + "' is not supported by the Interpreter.");
20206f32e7eSjoerg   }
20306f32e7eSjoerg 
20406f32e7eSjoerg   unsigned ArgBytes = 0;
20506f32e7eSjoerg 
20606f32e7eSjoerg   std::vector<ffi_type*> args(NumArgs);
20706f32e7eSjoerg   for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
20806f32e7eSjoerg        A != E; ++A) {
20906f32e7eSjoerg     const unsigned ArgNo = A->getArgNo();
21006f32e7eSjoerg     Type *ArgTy = FTy->getParamType(ArgNo);
21106f32e7eSjoerg     args[ArgNo] = ffiTypeFor(ArgTy);
21206f32e7eSjoerg     ArgBytes += TD.getTypeStoreSize(ArgTy);
21306f32e7eSjoerg   }
21406f32e7eSjoerg 
21506f32e7eSjoerg   SmallVector<uint8_t, 128> ArgData;
21606f32e7eSjoerg   ArgData.resize(ArgBytes);
21706f32e7eSjoerg   uint8_t *ArgDataPtr = ArgData.data();
21806f32e7eSjoerg   SmallVector<void*, 16> values(NumArgs);
21906f32e7eSjoerg   for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
22006f32e7eSjoerg        A != E; ++A) {
22106f32e7eSjoerg     const unsigned ArgNo = A->getArgNo();
22206f32e7eSjoerg     Type *ArgTy = FTy->getParamType(ArgNo);
22306f32e7eSjoerg     values[ArgNo] = ffiValueFor(ArgTy, ArgVals[ArgNo], ArgDataPtr);
22406f32e7eSjoerg     ArgDataPtr += TD.getTypeStoreSize(ArgTy);
22506f32e7eSjoerg   }
22606f32e7eSjoerg 
22706f32e7eSjoerg   Type *RetTy = FTy->getReturnType();
22806f32e7eSjoerg   ffi_type *rtype = ffiTypeFor(RetTy);
22906f32e7eSjoerg 
23006f32e7eSjoerg   if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, args.data()) ==
23106f32e7eSjoerg       FFI_OK) {
23206f32e7eSjoerg     SmallVector<uint8_t, 128> ret;
23306f32e7eSjoerg     if (RetTy->getTypeID() != Type::VoidTyID)
23406f32e7eSjoerg       ret.resize(TD.getTypeStoreSize(RetTy));
23506f32e7eSjoerg     ffi_call(&cif, Fn, ret.data(), values.data());
23606f32e7eSjoerg     switch (RetTy->getTypeID()) {
23706f32e7eSjoerg       case Type::IntegerTyID:
23806f32e7eSjoerg         switch (cast<IntegerType>(RetTy)->getBitWidth()) {
23906f32e7eSjoerg           case 8:  Result.IntVal = APInt(8 , *(int8_t *) ret.data()); break;
24006f32e7eSjoerg           case 16: Result.IntVal = APInt(16, *(int16_t*) ret.data()); break;
24106f32e7eSjoerg           case 32: Result.IntVal = APInt(32, *(int32_t*) ret.data()); break;
24206f32e7eSjoerg           case 64: Result.IntVal = APInt(64, *(int64_t*) ret.data()); break;
24306f32e7eSjoerg         }
24406f32e7eSjoerg         break;
24506f32e7eSjoerg       case Type::FloatTyID:   Result.FloatVal   = *(float *) ret.data(); break;
24606f32e7eSjoerg       case Type::DoubleTyID:  Result.DoubleVal  = *(double*) ret.data(); break;
24706f32e7eSjoerg       case Type::PointerTyID: Result.PointerVal = *(void **) ret.data(); break;
24806f32e7eSjoerg       default: break;
24906f32e7eSjoerg     }
25006f32e7eSjoerg     return true;
25106f32e7eSjoerg   }
25206f32e7eSjoerg 
25306f32e7eSjoerg   return false;
25406f32e7eSjoerg }
25506f32e7eSjoerg #endif // USE_LIBFFI
25606f32e7eSjoerg 
callExternalFunction(Function * F,ArrayRef<GenericValue> ArgVals)25706f32e7eSjoerg GenericValue Interpreter::callExternalFunction(Function *F,
25806f32e7eSjoerg                                                ArrayRef<GenericValue> ArgVals) {
25906f32e7eSjoerg   TheInterpreter = this;
26006f32e7eSjoerg 
26106f32e7eSjoerg   std::unique_lock<sys::Mutex> Guard(*FunctionsLock);
26206f32e7eSjoerg 
26306f32e7eSjoerg   // Do a lookup to see if the function is in our cache... this should just be a
26406f32e7eSjoerg   // deferred annotation!
26506f32e7eSjoerg   std::map<const Function *, ExFunc>::iterator FI = ExportedFunctions->find(F);
26606f32e7eSjoerg   if (ExFunc Fn = (FI == ExportedFunctions->end()) ? lookupFunction(F)
26706f32e7eSjoerg                                                    : FI->second) {
26806f32e7eSjoerg     Guard.unlock();
26906f32e7eSjoerg     return Fn(F->getFunctionType(), ArgVals);
27006f32e7eSjoerg   }
27106f32e7eSjoerg 
27206f32e7eSjoerg #ifdef USE_LIBFFI
27306f32e7eSjoerg   std::map<const Function *, RawFunc>::iterator RF = RawFunctions->find(F);
27406f32e7eSjoerg   RawFunc RawFn;
27506f32e7eSjoerg   if (RF == RawFunctions->end()) {
27606f32e7eSjoerg     RawFn = (RawFunc)(intptr_t)
277*da58b97aSjoerg       sys::DynamicLibrary::SearchForAddressOfSymbol(std::string(F->getName()));
27806f32e7eSjoerg     if (!RawFn)
27906f32e7eSjoerg       RawFn = (RawFunc)(intptr_t)getPointerToGlobalIfAvailable(F);
28006f32e7eSjoerg     if (RawFn != 0)
28106f32e7eSjoerg       RawFunctions->insert(std::make_pair(F, RawFn));  // Cache for later
28206f32e7eSjoerg   } else {
28306f32e7eSjoerg     RawFn = RF->second;
28406f32e7eSjoerg   }
28506f32e7eSjoerg 
28606f32e7eSjoerg   Guard.unlock();
28706f32e7eSjoerg 
28806f32e7eSjoerg   GenericValue Result;
28906f32e7eSjoerg   if (RawFn != 0 && ffiInvoke(RawFn, F, ArgVals, getDataLayout(), Result))
29006f32e7eSjoerg     return Result;
29106f32e7eSjoerg #endif // USE_LIBFFI
29206f32e7eSjoerg 
29306f32e7eSjoerg   if (F->getName() == "__main")
29406f32e7eSjoerg     errs() << "Tried to execute an unknown external function: "
29506f32e7eSjoerg       << *F->getType() << " __main\n";
29606f32e7eSjoerg   else
29706f32e7eSjoerg     report_fatal_error("Tried to execute an unknown external function: " +
29806f32e7eSjoerg                        F->getName());
29906f32e7eSjoerg #ifndef USE_LIBFFI
30006f32e7eSjoerg   errs() << "Recompiling LLVM with --enable-libffi might help.\n";
30106f32e7eSjoerg #endif
30206f32e7eSjoerg   return GenericValue();
30306f32e7eSjoerg }
30406f32e7eSjoerg 
30506f32e7eSjoerg //===----------------------------------------------------------------------===//
30606f32e7eSjoerg //  Functions "exported" to the running application...
30706f32e7eSjoerg //
30806f32e7eSjoerg 
30906f32e7eSjoerg // void atexit(Function*)
lle_X_atexit(FunctionType * FT,ArrayRef<GenericValue> Args)31006f32e7eSjoerg static GenericValue lle_X_atexit(FunctionType *FT,
31106f32e7eSjoerg                                  ArrayRef<GenericValue> Args) {
31206f32e7eSjoerg   assert(Args.size() == 1);
31306f32e7eSjoerg   TheInterpreter->addAtExitHandler((Function*)GVTOP(Args[0]));
31406f32e7eSjoerg   GenericValue GV;
31506f32e7eSjoerg   GV.IntVal = 0;
31606f32e7eSjoerg   return GV;
31706f32e7eSjoerg }
31806f32e7eSjoerg 
31906f32e7eSjoerg // void exit(int)
lle_X_exit(FunctionType * FT,ArrayRef<GenericValue> Args)32006f32e7eSjoerg static GenericValue lle_X_exit(FunctionType *FT, ArrayRef<GenericValue> Args) {
32106f32e7eSjoerg   TheInterpreter->exitCalled(Args[0]);
32206f32e7eSjoerg   return GenericValue();
32306f32e7eSjoerg }
32406f32e7eSjoerg 
32506f32e7eSjoerg // void abort(void)
lle_X_abort(FunctionType * FT,ArrayRef<GenericValue> Args)32606f32e7eSjoerg static GenericValue lle_X_abort(FunctionType *FT, ArrayRef<GenericValue> Args) {
32706f32e7eSjoerg   //FIXME: should we report or raise here?
32806f32e7eSjoerg   //report_fatal_error("Interpreted program raised SIGABRT");
32906f32e7eSjoerg   raise (SIGABRT);
33006f32e7eSjoerg   return GenericValue();
33106f32e7eSjoerg }
33206f32e7eSjoerg 
33306f32e7eSjoerg // int sprintf(char *, const char *, ...) - a very rough implementation to make
33406f32e7eSjoerg // output useful.
lle_X_sprintf(FunctionType * FT,ArrayRef<GenericValue> Args)33506f32e7eSjoerg static GenericValue lle_X_sprintf(FunctionType *FT,
33606f32e7eSjoerg                                   ArrayRef<GenericValue> Args) {
33706f32e7eSjoerg   char *OutputBuffer = (char *)GVTOP(Args[0]);
33806f32e7eSjoerg   const char *FmtStr = (const char *)GVTOP(Args[1]);
33906f32e7eSjoerg   unsigned ArgNo = 2;
34006f32e7eSjoerg 
34106f32e7eSjoerg   // printf should return # chars printed.  This is completely incorrect, but
34206f32e7eSjoerg   // close enough for now.
34306f32e7eSjoerg   GenericValue GV;
34406f32e7eSjoerg   GV.IntVal = APInt(32, strlen(FmtStr));
34506f32e7eSjoerg   while (true) {
34606f32e7eSjoerg     switch (*FmtStr) {
34706f32e7eSjoerg     case 0: return GV;             // Null terminator...
34806f32e7eSjoerg     default:                       // Normal nonspecial character
34906f32e7eSjoerg       sprintf(OutputBuffer++, "%c", *FmtStr++);
35006f32e7eSjoerg       break;
35106f32e7eSjoerg     case '\\': {                   // Handle escape codes
35206f32e7eSjoerg       sprintf(OutputBuffer, "%c%c", *FmtStr, *(FmtStr+1));
35306f32e7eSjoerg       FmtStr += 2; OutputBuffer += 2;
35406f32e7eSjoerg       break;
35506f32e7eSjoerg     }
35606f32e7eSjoerg     case '%': {                    // Handle format specifiers
35706f32e7eSjoerg       char FmtBuf[100] = "", Buffer[1000] = "";
35806f32e7eSjoerg       char *FB = FmtBuf;
35906f32e7eSjoerg       *FB++ = *FmtStr++;
36006f32e7eSjoerg       char Last = *FB++ = *FmtStr++;
36106f32e7eSjoerg       unsigned HowLong = 0;
36206f32e7eSjoerg       while (Last != 'c' && Last != 'd' && Last != 'i' && Last != 'u' &&
36306f32e7eSjoerg              Last != 'o' && Last != 'x' && Last != 'X' && Last != 'e' &&
36406f32e7eSjoerg              Last != 'E' && Last != 'g' && Last != 'G' && Last != 'f' &&
36506f32e7eSjoerg              Last != 'p' && Last != 's' && Last != '%') {
36606f32e7eSjoerg         if (Last == 'l' || Last == 'L') HowLong++;  // Keep track of l's
36706f32e7eSjoerg         Last = *FB++ = *FmtStr++;
36806f32e7eSjoerg       }
36906f32e7eSjoerg       *FB = 0;
37006f32e7eSjoerg 
37106f32e7eSjoerg       switch (Last) {
37206f32e7eSjoerg       case '%':
37306f32e7eSjoerg         memcpy(Buffer, "%", 2); break;
37406f32e7eSjoerg       case 'c':
37506f32e7eSjoerg         sprintf(Buffer, FmtBuf, uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
37606f32e7eSjoerg         break;
37706f32e7eSjoerg       case 'd': case 'i':
37806f32e7eSjoerg       case 'u': case 'o':
37906f32e7eSjoerg       case 'x': case 'X':
38006f32e7eSjoerg         if (HowLong >= 1) {
38106f32e7eSjoerg           if (HowLong == 1 &&
38206f32e7eSjoerg               TheInterpreter->getDataLayout().getPointerSizeInBits() == 64 &&
38306f32e7eSjoerg               sizeof(long) < sizeof(int64_t)) {
38406f32e7eSjoerg             // Make sure we use %lld with a 64 bit argument because we might be
38506f32e7eSjoerg             // compiling LLI on a 32 bit compiler.
38606f32e7eSjoerg             unsigned Size = strlen(FmtBuf);
38706f32e7eSjoerg             FmtBuf[Size] = FmtBuf[Size-1];
38806f32e7eSjoerg             FmtBuf[Size+1] = 0;
38906f32e7eSjoerg             FmtBuf[Size-1] = 'l';
39006f32e7eSjoerg           }
39106f32e7eSjoerg           sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal.getZExtValue());
39206f32e7eSjoerg         } else
39306f32e7eSjoerg           sprintf(Buffer, FmtBuf,uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
39406f32e7eSjoerg         break;
39506f32e7eSjoerg       case 'e': case 'E': case 'g': case 'G': case 'f':
39606f32e7eSjoerg         sprintf(Buffer, FmtBuf, Args[ArgNo++].DoubleVal); break;
39706f32e7eSjoerg       case 'p':
39806f32e7eSjoerg         sprintf(Buffer, FmtBuf, (void*)GVTOP(Args[ArgNo++])); break;
39906f32e7eSjoerg       case 's':
40006f32e7eSjoerg         sprintf(Buffer, FmtBuf, (char*)GVTOP(Args[ArgNo++])); break;
40106f32e7eSjoerg       default:
40206f32e7eSjoerg         errs() << "<unknown printf code '" << *FmtStr << "'!>";
40306f32e7eSjoerg         ArgNo++; break;
40406f32e7eSjoerg       }
40506f32e7eSjoerg       size_t Len = strlen(Buffer);
40606f32e7eSjoerg       memcpy(OutputBuffer, Buffer, Len + 1);
40706f32e7eSjoerg       OutputBuffer += Len;
40806f32e7eSjoerg       }
40906f32e7eSjoerg       break;
41006f32e7eSjoerg     }
41106f32e7eSjoerg   }
41206f32e7eSjoerg   return GV;
41306f32e7eSjoerg }
41406f32e7eSjoerg 
41506f32e7eSjoerg // int printf(const char *, ...) - a very rough implementation to make output
41606f32e7eSjoerg // useful.
lle_X_printf(FunctionType * FT,ArrayRef<GenericValue> Args)41706f32e7eSjoerg static GenericValue lle_X_printf(FunctionType *FT,
41806f32e7eSjoerg                                  ArrayRef<GenericValue> Args) {
41906f32e7eSjoerg   char Buffer[10000];
42006f32e7eSjoerg   std::vector<GenericValue> NewArgs;
42106f32e7eSjoerg   NewArgs.push_back(PTOGV((void*)&Buffer[0]));
422*da58b97aSjoerg   llvm::append_range(NewArgs, Args);
42306f32e7eSjoerg   GenericValue GV = lle_X_sprintf(FT, NewArgs);
42406f32e7eSjoerg   outs() << Buffer;
42506f32e7eSjoerg   return GV;
42606f32e7eSjoerg }
42706f32e7eSjoerg 
42806f32e7eSjoerg // int sscanf(const char *format, ...);
lle_X_sscanf(FunctionType * FT,ArrayRef<GenericValue> args)42906f32e7eSjoerg static GenericValue lle_X_sscanf(FunctionType *FT,
43006f32e7eSjoerg                                  ArrayRef<GenericValue> args) {
43106f32e7eSjoerg   assert(args.size() < 10 && "Only handle up to 10 args to sscanf right now!");
43206f32e7eSjoerg 
43306f32e7eSjoerg   char *Args[10];
43406f32e7eSjoerg   for (unsigned i = 0; i < args.size(); ++i)
43506f32e7eSjoerg     Args[i] = (char*)GVTOP(args[i]);
43606f32e7eSjoerg 
43706f32e7eSjoerg   GenericValue GV;
43806f32e7eSjoerg   GV.IntVal = APInt(32, sscanf(Args[0], Args[1], Args[2], Args[3], Args[4],
43906f32e7eSjoerg                     Args[5], Args[6], Args[7], Args[8], Args[9]));
44006f32e7eSjoerg   return GV;
44106f32e7eSjoerg }
44206f32e7eSjoerg 
44306f32e7eSjoerg // int scanf(const char *format, ...);
lle_X_scanf(FunctionType * FT,ArrayRef<GenericValue> args)44406f32e7eSjoerg static GenericValue lle_X_scanf(FunctionType *FT, ArrayRef<GenericValue> args) {
44506f32e7eSjoerg   assert(args.size() < 10 && "Only handle up to 10 args to scanf right now!");
44606f32e7eSjoerg 
44706f32e7eSjoerg   char *Args[10];
44806f32e7eSjoerg   for (unsigned i = 0; i < args.size(); ++i)
44906f32e7eSjoerg     Args[i] = (char*)GVTOP(args[i]);
45006f32e7eSjoerg 
45106f32e7eSjoerg   GenericValue GV;
45206f32e7eSjoerg   GV.IntVal = APInt(32, scanf( Args[0], Args[1], Args[2], Args[3], Args[4],
45306f32e7eSjoerg                     Args[5], Args[6], Args[7], Args[8], Args[9]));
45406f32e7eSjoerg   return GV;
45506f32e7eSjoerg }
45606f32e7eSjoerg 
45706f32e7eSjoerg // int fprintf(FILE *, const char *, ...) - a very rough implementation to make
45806f32e7eSjoerg // output useful.
lle_X_fprintf(FunctionType * FT,ArrayRef<GenericValue> Args)45906f32e7eSjoerg static GenericValue lle_X_fprintf(FunctionType *FT,
46006f32e7eSjoerg                                   ArrayRef<GenericValue> Args) {
46106f32e7eSjoerg   assert(Args.size() >= 2);
46206f32e7eSjoerg   char Buffer[10000];
46306f32e7eSjoerg   std::vector<GenericValue> NewArgs;
46406f32e7eSjoerg   NewArgs.push_back(PTOGV(Buffer));
46506f32e7eSjoerg   NewArgs.insert(NewArgs.end(), Args.begin()+1, Args.end());
46606f32e7eSjoerg   GenericValue GV = lle_X_sprintf(FT, NewArgs);
46706f32e7eSjoerg 
46806f32e7eSjoerg   fputs(Buffer, (FILE *) GVTOP(Args[0]));
46906f32e7eSjoerg   return GV;
47006f32e7eSjoerg }
47106f32e7eSjoerg 
lle_X_memset(FunctionType * FT,ArrayRef<GenericValue> Args)47206f32e7eSjoerg static GenericValue lle_X_memset(FunctionType *FT,
47306f32e7eSjoerg                                  ArrayRef<GenericValue> Args) {
47406f32e7eSjoerg   int val = (int)Args[1].IntVal.getSExtValue();
47506f32e7eSjoerg   size_t len = (size_t)Args[2].IntVal.getZExtValue();
47606f32e7eSjoerg   memset((void *)GVTOP(Args[0]), val, len);
47706f32e7eSjoerg   // llvm.memset.* returns void, lle_X_* returns GenericValue,
47806f32e7eSjoerg   // so here we return GenericValue with IntVal set to zero
47906f32e7eSjoerg   GenericValue GV;
48006f32e7eSjoerg   GV.IntVal = 0;
48106f32e7eSjoerg   return GV;
48206f32e7eSjoerg }
48306f32e7eSjoerg 
lle_X_memcpy(FunctionType * FT,ArrayRef<GenericValue> Args)48406f32e7eSjoerg static GenericValue lle_X_memcpy(FunctionType *FT,
48506f32e7eSjoerg                                  ArrayRef<GenericValue> Args) {
48606f32e7eSjoerg   memcpy(GVTOP(Args[0]), GVTOP(Args[1]),
48706f32e7eSjoerg          (size_t)(Args[2].IntVal.getLimitedValue()));
48806f32e7eSjoerg 
48906f32e7eSjoerg   // llvm.memcpy* returns void, lle_X_* returns GenericValue,
49006f32e7eSjoerg   // so here we return GenericValue with IntVal set to zero
49106f32e7eSjoerg   GenericValue GV;
49206f32e7eSjoerg   GV.IntVal = 0;
49306f32e7eSjoerg   return GV;
49406f32e7eSjoerg }
49506f32e7eSjoerg 
initializeExternalFunctions()49606f32e7eSjoerg void Interpreter::initializeExternalFunctions() {
49706f32e7eSjoerg   sys::ScopedLock Writer(*FunctionsLock);
49806f32e7eSjoerg   (*FuncNames)["lle_X_atexit"]       = lle_X_atexit;
49906f32e7eSjoerg   (*FuncNames)["lle_X_exit"]         = lle_X_exit;
50006f32e7eSjoerg   (*FuncNames)["lle_X_abort"]        = lle_X_abort;
50106f32e7eSjoerg 
50206f32e7eSjoerg   (*FuncNames)["lle_X_printf"]       = lle_X_printf;
50306f32e7eSjoerg   (*FuncNames)["lle_X_sprintf"]      = lle_X_sprintf;
50406f32e7eSjoerg   (*FuncNames)["lle_X_sscanf"]       = lle_X_sscanf;
50506f32e7eSjoerg   (*FuncNames)["lle_X_scanf"]        = lle_X_scanf;
50606f32e7eSjoerg   (*FuncNames)["lle_X_fprintf"]      = lle_X_fprintf;
50706f32e7eSjoerg   (*FuncNames)["lle_X_memset"]       = lle_X_memset;
50806f32e7eSjoerg   (*FuncNames)["lle_X_memcpy"]       = lle_X_memcpy;
50906f32e7eSjoerg }
510