109467b48Spatrick //===-- ExternalFunctions.cpp - Implement External Functions --------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick //  This file contains both code to deal with invoking "external" functions, but
1009467b48Spatrick //  also contains code that implements "exported" external functions.
1109467b48Spatrick //
1209467b48Spatrick //  There are currently two mechanisms for handling external functions in the
1309467b48Spatrick //  Interpreter.  The first is to implement lle_* wrapper functions that are
1409467b48Spatrick //  specific to well-known library functions which manually translate the
1509467b48Spatrick //  arguments from GenericValues and make the call.  If such a wrapper does
1609467b48Spatrick //  not exist, and libffi is available, then the Interpreter will attempt to
1709467b48Spatrick //  invoke the function using libffi, after finding its address.
1809467b48Spatrick //
1909467b48Spatrick //===----------------------------------------------------------------------===//
2009467b48Spatrick 
2109467b48Spatrick #include "Interpreter.h"
2209467b48Spatrick #include "llvm/ADT/APInt.h"
2309467b48Spatrick #include "llvm/ADT/ArrayRef.h"
2409467b48Spatrick #include "llvm/Config/config.h" // Detect libffi
2509467b48Spatrick #include "llvm/ExecutionEngine/GenericValue.h"
2609467b48Spatrick #include "llvm/IR/DataLayout.h"
2709467b48Spatrick #include "llvm/IR/DerivedTypes.h"
2809467b48Spatrick #include "llvm/IR/Function.h"
2909467b48Spatrick #include "llvm/IR/Type.h"
3009467b48Spatrick #include "llvm/Support/Casting.h"
3109467b48Spatrick #include "llvm/Support/DynamicLibrary.h"
3209467b48Spatrick #include "llvm/Support/ErrorHandling.h"
3309467b48Spatrick #include "llvm/Support/Mutex.h"
3409467b48Spatrick #include "llvm/Support/raw_ostream.h"
3509467b48Spatrick #include <cassert>
3609467b48Spatrick #include <cmath>
3709467b48Spatrick #include <csignal>
3809467b48Spatrick #include <cstdint>
3909467b48Spatrick #include <cstdio>
4009467b48Spatrick #include <cstring>
4109467b48Spatrick #include <map>
4209467b48Spatrick #include <mutex>
4309467b48Spatrick #include <string>
4409467b48Spatrick #include <utility>
4509467b48Spatrick #include <vector>
4609467b48Spatrick 
4709467b48Spatrick #ifdef HAVE_FFI_CALL
4809467b48Spatrick #ifdef HAVE_FFI_H
4909467b48Spatrick #include <ffi.h>
5009467b48Spatrick #define USE_LIBFFI
5109467b48Spatrick #elif HAVE_FFI_FFI_H
5209467b48Spatrick #include <ffi/ffi.h>
5309467b48Spatrick #define USE_LIBFFI
5409467b48Spatrick #endif
5509467b48Spatrick #endif
5609467b48Spatrick 
5709467b48Spatrick using namespace llvm;
5809467b48Spatrick 
59*d415bd75Srobert namespace {
6009467b48Spatrick 
6109467b48Spatrick typedef GenericValue (*ExFunc)(FunctionType *, ArrayRef<GenericValue>);
6209467b48Spatrick typedef void (*RawFunc)();
63*d415bd75Srobert 
64*d415bd75Srobert struct Functions {
65*d415bd75Srobert   sys::Mutex Lock;
66*d415bd75Srobert   std::map<const Function *, ExFunc> ExportedFunctions;
67*d415bd75Srobert   std::map<std::string, ExFunc> FuncNames;
68*d415bd75Srobert #ifdef USE_LIBFFI
69*d415bd75Srobert   std::map<const Function *, RawFunc> RawFunctions;
7009467b48Spatrick #endif
71*d415bd75Srobert };
72*d415bd75Srobert 
getFunctions()73*d415bd75Srobert Functions &getFunctions() {
74*d415bd75Srobert   static Functions F;
75*d415bd75Srobert   return F;
76*d415bd75Srobert }
77*d415bd75Srobert 
78*d415bd75Srobert } // anonymous namespace
7909467b48Spatrick 
8009467b48Spatrick static Interpreter *TheInterpreter;
8109467b48Spatrick 
getTypeID(Type * Ty)8209467b48Spatrick static char getTypeID(Type *Ty) {
8309467b48Spatrick   switch (Ty->getTypeID()) {
8409467b48Spatrick   case Type::VoidTyID:    return 'V';
8509467b48Spatrick   case Type::IntegerTyID:
8609467b48Spatrick     switch (cast<IntegerType>(Ty)->getBitWidth()) {
8709467b48Spatrick       case 1:  return 'o';
8809467b48Spatrick       case 8:  return 'B';
8909467b48Spatrick       case 16: return 'S';
9009467b48Spatrick       case 32: return 'I';
9109467b48Spatrick       case 64: return 'L';
9209467b48Spatrick       default: return 'N';
9309467b48Spatrick     }
9409467b48Spatrick   case Type::FloatTyID:   return 'F';
9509467b48Spatrick   case Type::DoubleTyID:  return 'D';
9609467b48Spatrick   case Type::PointerTyID: return 'P';
9709467b48Spatrick   case Type::FunctionTyID:return 'M';
9809467b48Spatrick   case Type::StructTyID:  return 'T';
9909467b48Spatrick   case Type::ArrayTyID:   return 'A';
10009467b48Spatrick   default: return 'U';
10109467b48Spatrick   }
10209467b48Spatrick }
10309467b48Spatrick 
10409467b48Spatrick // Try to find address of external function given a Function object.
10509467b48Spatrick // Please note, that interpreter doesn't know how to assemble a
10609467b48Spatrick // real call in general case (this is JIT job), that's why it assumes,
10709467b48Spatrick // that all external functions has the same (and pretty "general") signature.
10809467b48Spatrick // The typical example of such functions are "lle_X_" ones.
lookupFunction(const Function * F)10909467b48Spatrick static ExFunc lookupFunction(const Function *F) {
11009467b48Spatrick   // Function not found, look it up... start by figuring out what the
11109467b48Spatrick   // composite function name should be.
11209467b48Spatrick   std::string ExtName = "lle_";
11309467b48Spatrick   FunctionType *FT = F->getFunctionType();
11409467b48Spatrick   ExtName += getTypeID(FT->getReturnType());
11509467b48Spatrick   for (Type *T : FT->params())
11609467b48Spatrick     ExtName += getTypeID(T);
11709467b48Spatrick   ExtName += ("_" + F->getName()).str();
11809467b48Spatrick 
119*d415bd75Srobert   auto &Fns = getFunctions();
120*d415bd75Srobert   sys::ScopedLock Writer(Fns.Lock);
121*d415bd75Srobert   ExFunc FnPtr = Fns.FuncNames[ExtName];
12209467b48Spatrick   if (!FnPtr)
123*d415bd75Srobert     FnPtr = Fns.FuncNames[("lle_X_" + F->getName()).str()];
12409467b48Spatrick   if (!FnPtr)  // Try calling a generic function... if it exists...
12509467b48Spatrick     FnPtr = (ExFunc)(intptr_t)sys::DynamicLibrary::SearchForAddressOfSymbol(
12609467b48Spatrick         ("lle_X_" + F->getName()).str());
12709467b48Spatrick   if (FnPtr)
128*d415bd75Srobert     Fns.ExportedFunctions.insert(std::make_pair(F, FnPtr)); // Cache for later
12909467b48Spatrick   return FnPtr;
13009467b48Spatrick }
13109467b48Spatrick 
13209467b48Spatrick #ifdef USE_LIBFFI
ffiTypeFor(Type * Ty)13309467b48Spatrick static ffi_type *ffiTypeFor(Type *Ty) {
13409467b48Spatrick   switch (Ty->getTypeID()) {
13509467b48Spatrick     case Type::VoidTyID: return &ffi_type_void;
13609467b48Spatrick     case Type::IntegerTyID:
13709467b48Spatrick       switch (cast<IntegerType>(Ty)->getBitWidth()) {
13809467b48Spatrick         case 8:  return &ffi_type_sint8;
13909467b48Spatrick         case 16: return &ffi_type_sint16;
14009467b48Spatrick         case 32: return &ffi_type_sint32;
14109467b48Spatrick         case 64: return &ffi_type_sint64;
14209467b48Spatrick       }
14373471bf0Spatrick       llvm_unreachable("Unhandled integer type bitwidth");
14409467b48Spatrick     case Type::FloatTyID:   return &ffi_type_float;
14509467b48Spatrick     case Type::DoubleTyID:  return &ffi_type_double;
14609467b48Spatrick     case Type::PointerTyID: return &ffi_type_pointer;
14709467b48Spatrick     default: break;
14809467b48Spatrick   }
14909467b48Spatrick   // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
15009467b48Spatrick   report_fatal_error("Type could not be mapped for use with libffi.");
15109467b48Spatrick   return NULL;
15209467b48Spatrick }
15309467b48Spatrick 
ffiValueFor(Type * Ty,const GenericValue & AV,void * ArgDataPtr)15409467b48Spatrick static void *ffiValueFor(Type *Ty, const GenericValue &AV,
15509467b48Spatrick                          void *ArgDataPtr) {
15609467b48Spatrick   switch (Ty->getTypeID()) {
15709467b48Spatrick     case Type::IntegerTyID:
15809467b48Spatrick       switch (cast<IntegerType>(Ty)->getBitWidth()) {
15909467b48Spatrick         case 8: {
16009467b48Spatrick           int8_t *I8Ptr = (int8_t *) ArgDataPtr;
16109467b48Spatrick           *I8Ptr = (int8_t) AV.IntVal.getZExtValue();
16209467b48Spatrick           return ArgDataPtr;
16309467b48Spatrick         }
16409467b48Spatrick         case 16: {
16509467b48Spatrick           int16_t *I16Ptr = (int16_t *) ArgDataPtr;
16609467b48Spatrick           *I16Ptr = (int16_t) AV.IntVal.getZExtValue();
16709467b48Spatrick           return ArgDataPtr;
16809467b48Spatrick         }
16909467b48Spatrick         case 32: {
17009467b48Spatrick           int32_t *I32Ptr = (int32_t *) ArgDataPtr;
17109467b48Spatrick           *I32Ptr = (int32_t) AV.IntVal.getZExtValue();
17209467b48Spatrick           return ArgDataPtr;
17309467b48Spatrick         }
17409467b48Spatrick         case 64: {
17509467b48Spatrick           int64_t *I64Ptr = (int64_t *) ArgDataPtr;
17609467b48Spatrick           *I64Ptr = (int64_t) AV.IntVal.getZExtValue();
17709467b48Spatrick           return ArgDataPtr;
17809467b48Spatrick         }
17909467b48Spatrick       }
18073471bf0Spatrick       llvm_unreachable("Unhandled integer type bitwidth");
18109467b48Spatrick     case Type::FloatTyID: {
18209467b48Spatrick       float *FloatPtr = (float *) ArgDataPtr;
18309467b48Spatrick       *FloatPtr = AV.FloatVal;
18409467b48Spatrick       return ArgDataPtr;
18509467b48Spatrick     }
18609467b48Spatrick     case Type::DoubleTyID: {
18709467b48Spatrick       double *DoublePtr = (double *) ArgDataPtr;
18809467b48Spatrick       *DoublePtr = AV.DoubleVal;
18909467b48Spatrick       return ArgDataPtr;
19009467b48Spatrick     }
19109467b48Spatrick     case Type::PointerTyID: {
19209467b48Spatrick       void **PtrPtr = (void **) ArgDataPtr;
19309467b48Spatrick       *PtrPtr = GVTOP(AV);
19409467b48Spatrick       return ArgDataPtr;
19509467b48Spatrick     }
19609467b48Spatrick     default: break;
19709467b48Spatrick   }
19809467b48Spatrick   // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
19909467b48Spatrick   report_fatal_error("Type value could not be mapped for use with libffi.");
20009467b48Spatrick   return NULL;
20109467b48Spatrick }
20209467b48Spatrick 
ffiInvoke(RawFunc Fn,Function * F,ArrayRef<GenericValue> ArgVals,const DataLayout & TD,GenericValue & Result)20309467b48Spatrick static bool ffiInvoke(RawFunc Fn, Function *F, ArrayRef<GenericValue> ArgVals,
20409467b48Spatrick                       const DataLayout &TD, GenericValue &Result) {
20509467b48Spatrick   ffi_cif cif;
20609467b48Spatrick   FunctionType *FTy = F->getFunctionType();
20709467b48Spatrick   const unsigned NumArgs = F->arg_size();
20809467b48Spatrick 
20909467b48Spatrick   // TODO: We don't have type information about the remaining arguments, because
21009467b48Spatrick   // this information is never passed into ExecutionEngine::runFunction().
21109467b48Spatrick   if (ArgVals.size() > NumArgs && F->isVarArg()) {
21209467b48Spatrick     report_fatal_error("Calling external var arg function '" + F->getName()
21309467b48Spatrick                       + "' is not supported by the Interpreter.");
21409467b48Spatrick   }
21509467b48Spatrick 
21609467b48Spatrick   unsigned ArgBytes = 0;
21709467b48Spatrick 
21809467b48Spatrick   std::vector<ffi_type*> args(NumArgs);
21909467b48Spatrick   for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
22009467b48Spatrick        A != E; ++A) {
22109467b48Spatrick     const unsigned ArgNo = A->getArgNo();
22209467b48Spatrick     Type *ArgTy = FTy->getParamType(ArgNo);
22309467b48Spatrick     args[ArgNo] = ffiTypeFor(ArgTy);
22409467b48Spatrick     ArgBytes += TD.getTypeStoreSize(ArgTy);
22509467b48Spatrick   }
22609467b48Spatrick 
22709467b48Spatrick   SmallVector<uint8_t, 128> ArgData;
22809467b48Spatrick   ArgData.resize(ArgBytes);
22909467b48Spatrick   uint8_t *ArgDataPtr = ArgData.data();
23009467b48Spatrick   SmallVector<void*, 16> values(NumArgs);
23109467b48Spatrick   for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
23209467b48Spatrick        A != E; ++A) {
23309467b48Spatrick     const unsigned ArgNo = A->getArgNo();
23409467b48Spatrick     Type *ArgTy = FTy->getParamType(ArgNo);
23509467b48Spatrick     values[ArgNo] = ffiValueFor(ArgTy, ArgVals[ArgNo], ArgDataPtr);
23609467b48Spatrick     ArgDataPtr += TD.getTypeStoreSize(ArgTy);
23709467b48Spatrick   }
23809467b48Spatrick 
23909467b48Spatrick   Type *RetTy = FTy->getReturnType();
24009467b48Spatrick   ffi_type *rtype = ffiTypeFor(RetTy);
24109467b48Spatrick 
24209467b48Spatrick   if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, args.data()) ==
24309467b48Spatrick       FFI_OK) {
24409467b48Spatrick     SmallVector<uint8_t, 128> ret;
24509467b48Spatrick     if (RetTy->getTypeID() != Type::VoidTyID)
24609467b48Spatrick       ret.resize(TD.getTypeStoreSize(RetTy));
24709467b48Spatrick     ffi_call(&cif, Fn, ret.data(), values.data());
24809467b48Spatrick     switch (RetTy->getTypeID()) {
24909467b48Spatrick       case Type::IntegerTyID:
25009467b48Spatrick         switch (cast<IntegerType>(RetTy)->getBitWidth()) {
25109467b48Spatrick           case 8:  Result.IntVal = APInt(8 , *(int8_t *) ret.data()); break;
25209467b48Spatrick           case 16: Result.IntVal = APInt(16, *(int16_t*) ret.data()); break;
25309467b48Spatrick           case 32: Result.IntVal = APInt(32, *(int32_t*) ret.data()); break;
25409467b48Spatrick           case 64: Result.IntVal = APInt(64, *(int64_t*) ret.data()); break;
25509467b48Spatrick         }
25609467b48Spatrick         break;
25709467b48Spatrick       case Type::FloatTyID:   Result.FloatVal   = *(float *) ret.data(); break;
25809467b48Spatrick       case Type::DoubleTyID:  Result.DoubleVal  = *(double*) ret.data(); break;
25909467b48Spatrick       case Type::PointerTyID: Result.PointerVal = *(void **) ret.data(); break;
26009467b48Spatrick       default: break;
26109467b48Spatrick     }
26209467b48Spatrick     return true;
26309467b48Spatrick   }
26409467b48Spatrick 
26509467b48Spatrick   return false;
26609467b48Spatrick }
26709467b48Spatrick #endif // USE_LIBFFI
26809467b48Spatrick 
callExternalFunction(Function * F,ArrayRef<GenericValue> ArgVals)26909467b48Spatrick GenericValue Interpreter::callExternalFunction(Function *F,
27009467b48Spatrick                                                ArrayRef<GenericValue> ArgVals) {
27109467b48Spatrick   TheInterpreter = this;
27209467b48Spatrick 
273*d415bd75Srobert   auto &Fns = getFunctions();
274*d415bd75Srobert   std::unique_lock<sys::Mutex> Guard(Fns.Lock);
27509467b48Spatrick 
27609467b48Spatrick   // Do a lookup to see if the function is in our cache... this should just be a
27709467b48Spatrick   // deferred annotation!
278*d415bd75Srobert   std::map<const Function *, ExFunc>::iterator FI =
279*d415bd75Srobert       Fns.ExportedFunctions.find(F);
280*d415bd75Srobert   if (ExFunc Fn = (FI == Fns.ExportedFunctions.end()) ? lookupFunction(F)
28109467b48Spatrick                                                       : FI->second) {
28209467b48Spatrick     Guard.unlock();
28309467b48Spatrick     return Fn(F->getFunctionType(), ArgVals);
28409467b48Spatrick   }
28509467b48Spatrick 
28609467b48Spatrick #ifdef USE_LIBFFI
287*d415bd75Srobert   std::map<const Function *, RawFunc>::iterator RF = Fns.RawFunctions.find(F);
28809467b48Spatrick   RawFunc RawFn;
289*d415bd75Srobert   if (RF == Fns.RawFunctions.end()) {
29009467b48Spatrick     RawFn = (RawFunc)(intptr_t)
291097a140dSpatrick       sys::DynamicLibrary::SearchForAddressOfSymbol(std::string(F->getName()));
29209467b48Spatrick     if (!RawFn)
29309467b48Spatrick       RawFn = (RawFunc)(intptr_t)getPointerToGlobalIfAvailable(F);
29409467b48Spatrick     if (RawFn != 0)
295*d415bd75Srobert       Fns.RawFunctions.insert(std::make_pair(F, RawFn)); // Cache for later
29609467b48Spatrick   } else {
29709467b48Spatrick     RawFn = RF->second;
29809467b48Spatrick   }
29909467b48Spatrick 
30009467b48Spatrick   Guard.unlock();
30109467b48Spatrick 
30209467b48Spatrick   GenericValue Result;
30309467b48Spatrick   if (RawFn != 0 && ffiInvoke(RawFn, F, ArgVals, getDataLayout(), Result))
30409467b48Spatrick     return Result;
30509467b48Spatrick #endif // USE_LIBFFI
30609467b48Spatrick 
30709467b48Spatrick   if (F->getName() == "__main")
30809467b48Spatrick     errs() << "Tried to execute an unknown external function: "
30909467b48Spatrick       << *F->getType() << " __main\n";
31009467b48Spatrick   else
31109467b48Spatrick     report_fatal_error("Tried to execute an unknown external function: " +
31209467b48Spatrick                        F->getName());
31309467b48Spatrick #ifndef USE_LIBFFI
31409467b48Spatrick   errs() << "Recompiling LLVM with --enable-libffi might help.\n";
31509467b48Spatrick #endif
31609467b48Spatrick   return GenericValue();
31709467b48Spatrick }
31809467b48Spatrick 
31909467b48Spatrick //===----------------------------------------------------------------------===//
32009467b48Spatrick //  Functions "exported" to the running application...
32109467b48Spatrick //
32209467b48Spatrick 
32309467b48Spatrick // void atexit(Function*)
lle_X_atexit(FunctionType * FT,ArrayRef<GenericValue> Args)32409467b48Spatrick static GenericValue lle_X_atexit(FunctionType *FT,
32509467b48Spatrick                                  ArrayRef<GenericValue> Args) {
32609467b48Spatrick   assert(Args.size() == 1);
32709467b48Spatrick   TheInterpreter->addAtExitHandler((Function*)GVTOP(Args[0]));
32809467b48Spatrick   GenericValue GV;
32909467b48Spatrick   GV.IntVal = 0;
33009467b48Spatrick   return GV;
33109467b48Spatrick }
33209467b48Spatrick 
33309467b48Spatrick // void exit(int)
lle_X_exit(FunctionType * FT,ArrayRef<GenericValue> Args)33409467b48Spatrick static GenericValue lle_X_exit(FunctionType *FT, ArrayRef<GenericValue> Args) {
33509467b48Spatrick   TheInterpreter->exitCalled(Args[0]);
33609467b48Spatrick   return GenericValue();
33709467b48Spatrick }
33809467b48Spatrick 
33909467b48Spatrick // void abort(void)
lle_X_abort(FunctionType * FT,ArrayRef<GenericValue> Args)34009467b48Spatrick static GenericValue lle_X_abort(FunctionType *FT, ArrayRef<GenericValue> Args) {
34109467b48Spatrick   //FIXME: should we report or raise here?
34209467b48Spatrick   //report_fatal_error("Interpreted program raised SIGABRT");
34309467b48Spatrick   raise (SIGABRT);
34409467b48Spatrick   return GenericValue();
34509467b48Spatrick }
34609467b48Spatrick 
34709467b48Spatrick // int sprintf(char *, const char *, ...) - a very rough implementation to make
34809467b48Spatrick // output useful.
lle_X_sprintf(FunctionType * FT,ArrayRef<GenericValue> Args)34909467b48Spatrick static GenericValue lle_X_sprintf(FunctionType *FT,
35009467b48Spatrick                                   ArrayRef<GenericValue> Args) {
35109467b48Spatrick   char *OutputBuffer = (char *)GVTOP(Args[0]);
35209467b48Spatrick   const char *FmtStr = (const char *)GVTOP(Args[1]);
35309467b48Spatrick   unsigned ArgNo = 2;
35409467b48Spatrick 
35509467b48Spatrick   // printf should return # chars printed.  This is completely incorrect, but
35609467b48Spatrick   // close enough for now.
35709467b48Spatrick   GenericValue GV;
35809467b48Spatrick   GV.IntVal = APInt(32, strlen(FmtStr));
35909467b48Spatrick   while (true) {
36009467b48Spatrick     switch (*FmtStr) {
36109467b48Spatrick     case 0: return GV;             // Null terminator...
36209467b48Spatrick     default:                       // Normal nonspecial character
36309467b48Spatrick       sprintf(OutputBuffer++, "%c", *FmtStr++);
36409467b48Spatrick       break;
36509467b48Spatrick     case '\\': {                   // Handle escape codes
36609467b48Spatrick       sprintf(OutputBuffer, "%c%c", *FmtStr, *(FmtStr+1));
36709467b48Spatrick       FmtStr += 2; OutputBuffer += 2;
36809467b48Spatrick       break;
36909467b48Spatrick     }
37009467b48Spatrick     case '%': {                    // Handle format specifiers
37109467b48Spatrick       char FmtBuf[100] = "", Buffer[1000] = "";
37209467b48Spatrick       char *FB = FmtBuf;
37309467b48Spatrick       *FB++ = *FmtStr++;
37409467b48Spatrick       char Last = *FB++ = *FmtStr++;
37509467b48Spatrick       unsigned HowLong = 0;
37609467b48Spatrick       while (Last != 'c' && Last != 'd' && Last != 'i' && Last != 'u' &&
37709467b48Spatrick              Last != 'o' && Last != 'x' && Last != 'X' && Last != 'e' &&
37809467b48Spatrick              Last != 'E' && Last != 'g' && Last != 'G' && Last != 'f' &&
37909467b48Spatrick              Last != 'p' && Last != 's' && Last != '%') {
38009467b48Spatrick         if (Last == 'l' || Last == 'L') HowLong++;  // Keep track of l's
38109467b48Spatrick         Last = *FB++ = *FmtStr++;
38209467b48Spatrick       }
38309467b48Spatrick       *FB = 0;
38409467b48Spatrick 
38509467b48Spatrick       switch (Last) {
38609467b48Spatrick       case '%':
38709467b48Spatrick         memcpy(Buffer, "%", 2); break;
38809467b48Spatrick       case 'c':
38909467b48Spatrick         sprintf(Buffer, FmtBuf, uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
39009467b48Spatrick         break;
39109467b48Spatrick       case 'd': case 'i':
39209467b48Spatrick       case 'u': case 'o':
39309467b48Spatrick       case 'x': case 'X':
39409467b48Spatrick         if (HowLong >= 1) {
39509467b48Spatrick           if (HowLong == 1 &&
39609467b48Spatrick               TheInterpreter->getDataLayout().getPointerSizeInBits() == 64 &&
39709467b48Spatrick               sizeof(long) < sizeof(int64_t)) {
39809467b48Spatrick             // Make sure we use %lld with a 64 bit argument because we might be
39909467b48Spatrick             // compiling LLI on a 32 bit compiler.
40009467b48Spatrick             unsigned Size = strlen(FmtBuf);
40109467b48Spatrick             FmtBuf[Size] = FmtBuf[Size-1];
40209467b48Spatrick             FmtBuf[Size+1] = 0;
40309467b48Spatrick             FmtBuf[Size-1] = 'l';
40409467b48Spatrick           }
40509467b48Spatrick           sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal.getZExtValue());
40609467b48Spatrick         } else
40709467b48Spatrick           sprintf(Buffer, FmtBuf,uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
40809467b48Spatrick         break;
40909467b48Spatrick       case 'e': case 'E': case 'g': case 'G': case 'f':
41009467b48Spatrick         sprintf(Buffer, FmtBuf, Args[ArgNo++].DoubleVal); break;
41109467b48Spatrick       case 'p':
41209467b48Spatrick         sprintf(Buffer, FmtBuf, (void*)GVTOP(Args[ArgNo++])); break;
41309467b48Spatrick       case 's':
41409467b48Spatrick         sprintf(Buffer, FmtBuf, (char*)GVTOP(Args[ArgNo++])); break;
41509467b48Spatrick       default:
41609467b48Spatrick         errs() << "<unknown printf code '" << *FmtStr << "'!>";
41709467b48Spatrick         ArgNo++; break;
41809467b48Spatrick       }
41909467b48Spatrick       size_t Len = strlen(Buffer);
42009467b48Spatrick       memcpy(OutputBuffer, Buffer, Len + 1);
42109467b48Spatrick       OutputBuffer += Len;
42209467b48Spatrick       }
42309467b48Spatrick       break;
42409467b48Spatrick     }
42509467b48Spatrick   }
42609467b48Spatrick   return GV;
42709467b48Spatrick }
42809467b48Spatrick 
42909467b48Spatrick // int printf(const char *, ...) - a very rough implementation to make output
43009467b48Spatrick // useful.
lle_X_printf(FunctionType * FT,ArrayRef<GenericValue> Args)43109467b48Spatrick static GenericValue lle_X_printf(FunctionType *FT,
43209467b48Spatrick                                  ArrayRef<GenericValue> Args) {
43309467b48Spatrick   char Buffer[10000];
43409467b48Spatrick   std::vector<GenericValue> NewArgs;
43509467b48Spatrick   NewArgs.push_back(PTOGV((void*)&Buffer[0]));
43673471bf0Spatrick   llvm::append_range(NewArgs, Args);
43709467b48Spatrick   GenericValue GV = lle_X_sprintf(FT, NewArgs);
43809467b48Spatrick   outs() << Buffer;
43909467b48Spatrick   return GV;
44009467b48Spatrick }
44109467b48Spatrick 
44209467b48Spatrick // int sscanf(const char *format, ...);
lle_X_sscanf(FunctionType * FT,ArrayRef<GenericValue> args)44309467b48Spatrick static GenericValue lle_X_sscanf(FunctionType *FT,
44409467b48Spatrick                                  ArrayRef<GenericValue> args) {
44509467b48Spatrick   assert(args.size() < 10 && "Only handle up to 10 args to sscanf right now!");
44609467b48Spatrick 
44709467b48Spatrick   char *Args[10];
44809467b48Spatrick   for (unsigned i = 0; i < args.size(); ++i)
44909467b48Spatrick     Args[i] = (char*)GVTOP(args[i]);
45009467b48Spatrick 
45109467b48Spatrick   GenericValue GV;
45209467b48Spatrick   GV.IntVal = APInt(32, sscanf(Args[0], Args[1], Args[2], Args[3], Args[4],
45309467b48Spatrick                     Args[5], Args[6], Args[7], Args[8], Args[9]));
45409467b48Spatrick   return GV;
45509467b48Spatrick }
45609467b48Spatrick 
45709467b48Spatrick // int scanf(const char *format, ...);
lle_X_scanf(FunctionType * FT,ArrayRef<GenericValue> args)45809467b48Spatrick static GenericValue lle_X_scanf(FunctionType *FT, ArrayRef<GenericValue> args) {
45909467b48Spatrick   assert(args.size() < 10 && "Only handle up to 10 args to scanf right now!");
46009467b48Spatrick 
46109467b48Spatrick   char *Args[10];
46209467b48Spatrick   for (unsigned i = 0; i < args.size(); ++i)
46309467b48Spatrick     Args[i] = (char*)GVTOP(args[i]);
46409467b48Spatrick 
46509467b48Spatrick   GenericValue GV;
46609467b48Spatrick   GV.IntVal = APInt(32, scanf( Args[0], Args[1], Args[2], Args[3], Args[4],
46709467b48Spatrick                     Args[5], Args[6], Args[7], Args[8], Args[9]));
46809467b48Spatrick   return GV;
46909467b48Spatrick }
47009467b48Spatrick 
47109467b48Spatrick // int fprintf(FILE *, const char *, ...) - a very rough implementation to make
47209467b48Spatrick // output useful.
lle_X_fprintf(FunctionType * FT,ArrayRef<GenericValue> Args)47309467b48Spatrick static GenericValue lle_X_fprintf(FunctionType *FT,
47409467b48Spatrick                                   ArrayRef<GenericValue> Args) {
47509467b48Spatrick   assert(Args.size() >= 2);
47609467b48Spatrick   char Buffer[10000];
47709467b48Spatrick   std::vector<GenericValue> NewArgs;
47809467b48Spatrick   NewArgs.push_back(PTOGV(Buffer));
47909467b48Spatrick   NewArgs.insert(NewArgs.end(), Args.begin()+1, Args.end());
48009467b48Spatrick   GenericValue GV = lle_X_sprintf(FT, NewArgs);
48109467b48Spatrick 
48209467b48Spatrick   fputs(Buffer, (FILE *) GVTOP(Args[0]));
48309467b48Spatrick   return GV;
48409467b48Spatrick }
48509467b48Spatrick 
lle_X_memset(FunctionType * FT,ArrayRef<GenericValue> Args)48609467b48Spatrick static GenericValue lle_X_memset(FunctionType *FT,
48709467b48Spatrick                                  ArrayRef<GenericValue> Args) {
48809467b48Spatrick   int val = (int)Args[1].IntVal.getSExtValue();
48909467b48Spatrick   size_t len = (size_t)Args[2].IntVal.getZExtValue();
49009467b48Spatrick   memset((void *)GVTOP(Args[0]), val, len);
49109467b48Spatrick   // llvm.memset.* returns void, lle_X_* returns GenericValue,
49209467b48Spatrick   // so here we return GenericValue with IntVal set to zero
49309467b48Spatrick   GenericValue GV;
49409467b48Spatrick   GV.IntVal = 0;
49509467b48Spatrick   return GV;
49609467b48Spatrick }
49709467b48Spatrick 
lle_X_memcpy(FunctionType * FT,ArrayRef<GenericValue> Args)49809467b48Spatrick static GenericValue lle_X_memcpy(FunctionType *FT,
49909467b48Spatrick                                  ArrayRef<GenericValue> Args) {
50009467b48Spatrick   memcpy(GVTOP(Args[0]), GVTOP(Args[1]),
50109467b48Spatrick          (size_t)(Args[2].IntVal.getLimitedValue()));
50209467b48Spatrick 
50309467b48Spatrick   // llvm.memcpy* returns void, lle_X_* returns GenericValue,
50409467b48Spatrick   // so here we return GenericValue with IntVal set to zero
50509467b48Spatrick   GenericValue GV;
50609467b48Spatrick   GV.IntVal = 0;
50709467b48Spatrick   return GV;
50809467b48Spatrick }
50909467b48Spatrick 
initializeExternalFunctions()51009467b48Spatrick void Interpreter::initializeExternalFunctions() {
511*d415bd75Srobert   auto &Fns = getFunctions();
512*d415bd75Srobert   sys::ScopedLock Writer(Fns.Lock);
513*d415bd75Srobert   Fns.FuncNames["lle_X_atexit"]       = lle_X_atexit;
514*d415bd75Srobert   Fns.FuncNames["lle_X_exit"]         = lle_X_exit;
515*d415bd75Srobert   Fns.FuncNames["lle_X_abort"]        = lle_X_abort;
51609467b48Spatrick 
517*d415bd75Srobert   Fns.FuncNames["lle_X_printf"]       = lle_X_printf;
518*d415bd75Srobert   Fns.FuncNames["lle_X_sprintf"]      = lle_X_sprintf;
519*d415bd75Srobert   Fns.FuncNames["lle_X_sscanf"]       = lle_X_sscanf;
520*d415bd75Srobert   Fns.FuncNames["lle_X_scanf"]        = lle_X_scanf;
521*d415bd75Srobert   Fns.FuncNames["lle_X_fprintf"]      = lle_X_fprintf;
522*d415bd75Srobert   Fns.FuncNames["lle_X_memset"]       = lle_X_memset;
523*d415bd75Srobert   Fns.FuncNames["lle_X_memcpy"]       = lle_X_memcpy;
52409467b48Spatrick }
525