#include "Interpreter.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Config/config.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cmath>
#include <csignal>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <map>
#include <mutex>
#include <string>
#include <utility>
#include <vector>
#ifdef HAVE_FFI_CALL
#ifdef HAVE_FFI_H
#include <ffi.h>
#define USE_LIBFFI
#elif HAVE_FFI_FFI_H
#include <ffi/ffi.h>
#define USE_LIBFFI
#endif
#endif
usingnamespacellvm;
namespace {
ExFunc;
RawFunc;
struct Functions { … };
Functions &getFunctions() { … }
}
static Interpreter *TheInterpreter;
static char getTypeID(Type *Ty) { … }
static ExFunc lookupFunction(const Function *F) { … }
#ifdef USE_LIBFFI
static ffi_type *ffiTypeFor(Type *Ty) {
switch (Ty->getTypeID()) {
case Type::VoidTyID: return &ffi_type_void;
case Type::IntegerTyID:
switch (cast<IntegerType>(Ty)->getBitWidth()) {
case 8: return &ffi_type_sint8;
case 16: return &ffi_type_sint16;
case 32: return &ffi_type_sint32;
case 64: return &ffi_type_sint64;
}
llvm_unreachable("Unhandled integer type bitwidth");
case Type::FloatTyID: return &ffi_type_float;
case Type::DoubleTyID: return &ffi_type_double;
case Type::PointerTyID: return &ffi_type_pointer;
default: break;
}
report_fatal_error("Type could not be mapped for use with libffi.");
return NULL;
}
static void *ffiValueFor(Type *Ty, const GenericValue &AV,
void *ArgDataPtr) {
switch (Ty->getTypeID()) {
case Type::IntegerTyID:
switch (cast<IntegerType>(Ty)->getBitWidth()) {
case 8: {
int8_t *I8Ptr = (int8_t *) ArgDataPtr;
*I8Ptr = (int8_t) AV.IntVal.getZExtValue();
return ArgDataPtr;
}
case 16: {
int16_t *I16Ptr = (int16_t *) ArgDataPtr;
*I16Ptr = (int16_t) AV.IntVal.getZExtValue();
return ArgDataPtr;
}
case 32: {
int32_t *I32Ptr = (int32_t *) ArgDataPtr;
*I32Ptr = (int32_t) AV.IntVal.getZExtValue();
return ArgDataPtr;
}
case 64: {
int64_t *I64Ptr = (int64_t *) ArgDataPtr;
*I64Ptr = (int64_t) AV.IntVal.getZExtValue();
return ArgDataPtr;
}
}
llvm_unreachable("Unhandled integer type bitwidth");
case Type::FloatTyID: {
float *FloatPtr = (float *) ArgDataPtr;
*FloatPtr = AV.FloatVal;
return ArgDataPtr;
}
case Type::DoubleTyID: {
double *DoublePtr = (double *) ArgDataPtr;
*DoublePtr = AV.DoubleVal;
return ArgDataPtr;
}
case Type::PointerTyID: {
void **PtrPtr = (void **) ArgDataPtr;
*PtrPtr = GVTOP(AV);
return ArgDataPtr;
}
default: break;
}
report_fatal_error("Type value could not be mapped for use with libffi.");
return NULL;
}
static bool ffiInvoke(RawFunc Fn, Function *F, ArrayRef<GenericValue> ArgVals,
const DataLayout &TD, GenericValue &Result) {
ffi_cif cif;
FunctionType *FTy = F->getFunctionType();
const unsigned NumArgs = F->arg_size();
if (ArgVals.size() > NumArgs && F->isVarArg()) {
report_fatal_error("Calling external var arg function '" + F->getName()
+ "' is not supported by the Interpreter.");
}
unsigned ArgBytes = 0;
std::vector<ffi_type*> args(NumArgs);
for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
A != E; ++A) {
const unsigned ArgNo = A->getArgNo();
Type *ArgTy = FTy->getParamType(ArgNo);
args[ArgNo] = ffiTypeFor(ArgTy);
ArgBytes += TD.getTypeStoreSize(ArgTy);
}
SmallVector<uint8_t, 128> ArgData;
ArgData.resize(ArgBytes);
uint8_t *ArgDataPtr = ArgData.data();
SmallVector<void*, 16> values(NumArgs);
for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
A != E; ++A) {
const unsigned ArgNo = A->getArgNo();
Type *ArgTy = FTy->getParamType(ArgNo);
values[ArgNo] = ffiValueFor(ArgTy, ArgVals[ArgNo], ArgDataPtr);
ArgDataPtr += TD.getTypeStoreSize(ArgTy);
}
Type *RetTy = FTy->getReturnType();
ffi_type *rtype = ffiTypeFor(RetTy);
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, args.data()) ==
FFI_OK) {
SmallVector<uint8_t, 128> ret;
if (RetTy->getTypeID() != Type::VoidTyID)
ret.resize(TD.getTypeStoreSize(RetTy));
ffi_call(&cif, Fn, ret.data(), values.data());
switch (RetTy->getTypeID()) {
case Type::IntegerTyID:
switch (cast<IntegerType>(RetTy)->getBitWidth()) {
case 8: Result.IntVal = APInt(8 , *(int8_t *) ret.data()); break;
case 16: Result.IntVal = APInt(16, *(int16_t*) ret.data()); break;
case 32: Result.IntVal = APInt(32, *(int32_t*) ret.data()); break;
case 64: Result.IntVal = APInt(64, *(int64_t*) ret.data()); break;
}
break;
case Type::FloatTyID: Result.FloatVal = *(float *) ret.data(); break;
case Type::DoubleTyID: Result.DoubleVal = *(double*) ret.data(); break;
case Type::PointerTyID: Result.PointerVal = *(void **) ret.data(); break;
default: break;
}
return true;
}
return false;
}
#endif
GenericValue Interpreter::callExternalFunction(Function *F,
ArrayRef<GenericValue> ArgVals) { … }
static GenericValue lle_X_atexit(FunctionType *FT,
ArrayRef<GenericValue> Args) { … }
static GenericValue lle_X_exit(FunctionType *FT, ArrayRef<GenericValue> Args) { … }
static GenericValue lle_X_abort(FunctionType *FT, ArrayRef<GenericValue> Args) { … }
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
static GenericValue lle_X_sprintf(FunctionType *FT,
ArrayRef<GenericValue> Args) { … }
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
static GenericValue lle_X_printf(FunctionType *FT,
ArrayRef<GenericValue> Args) { … }
static GenericValue lle_X_sscanf(FunctionType *FT,
ArrayRef<GenericValue> args) { … }
static GenericValue lle_X_scanf(FunctionType *FT, ArrayRef<GenericValue> args) { … }
static GenericValue lle_X_fprintf(FunctionType *FT,
ArrayRef<GenericValue> Args) { … }
static GenericValue lle_X_memset(FunctionType *FT,
ArrayRef<GenericValue> Args) { … }
static GenericValue lle_X_memcpy(FunctionType *FT,
ArrayRef<GenericValue> Args) { … }
void Interpreter::initializeExternalFunctions() { … }