12fbfdcffd3e0cf41422aaa6c526c37cb02b81341Chris Lattner//===-- ExternalFunctions.cpp - Implement External Functions --------------===// 2d1c881a8d4da8b4d99c2a40512fbcca652ab445eMisha Brukman// 3b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// The LLVM Compiler Infrastructure 4b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// 54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source 64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details. 7d1c881a8d4da8b4d99c2a40512fbcca652ab445eMisha Brukman// 8b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//===----------------------------------------------------------------------===// 9d1c881a8d4da8b4d99c2a40512fbcca652ab445eMisha Brukman// 102fbfdcffd3e0cf41422aaa6c526c37cb02b81341Chris Lattner// This file contains both code to deal with invoking "external" functions, but 112fbfdcffd3e0cf41422aaa6c526c37cb02b81341Chris Lattner// also contains code that implements "exported" external functions. 127720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner// 13f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky// There are currently two mechanisms for handling external functions in the 14f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky// Interpreter. The first is to implement lle_* wrapper functions that are 15f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky// specific to well-known library functions which manually translate the 16f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky// arguments from GenericValues and make the call. If such a wrapper does 17f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky// not exist, and libffi is available, then the Interpreter will attempt to 18f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky// invoke the function using libffi, after finding its address. 197720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner// 207720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner//===----------------------------------------------------------------------===// 217720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner 227720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner#include "Interpreter.h" 23d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Config/config.h" // Detect libffi 240b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/DataLayout.h" 250b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/DerivedTypes.h" 260b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Module.h" 271f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/DynamicLibrary.h" 28d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/ErrorHandling.h" 29936baaa5aeddb78ff41b1f655101b4d88c47473bChuck Rose III#include "llvm/Support/ManagedStatic.h" 301f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Mutex.h" 3137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/Support/UniqueLock.h" 32d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include <cmath> 33b56a6bc96a483b47da71b24efaa4380d463bbe17Brian Gaeke#include <csignal> 344520dd2b7b20af07d5a3e4d06d964a532044eb10Duncan Sands#include <cstdio> 35ae9f3a3b7c915f725aef5a7250e88eaeddda03c6Anton Korobeynikov#include <cstring> 36d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include <map> 37621deadee8967ab3a56c5478bb810b7200c48edbZhou Sheng 3893f70fc291c56287bff7aefd924d171f005fdcc7Nick Lewycky#ifdef HAVE_FFI_CALL 39f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky#ifdef HAVE_FFI_H 40f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky#include <ffi.h> 4193f70fc291c56287bff7aefd924d171f005fdcc7Nick Lewycky#define USE_LIBFFI 42f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky#elif HAVE_FFI_FFI_H 43f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky#include <ffi/ffi.h> 4493f70fc291c56287bff7aefd924d171f005fdcc7Nick Lewycky#define USE_LIBFFI 45f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky#endif 46621deadee8967ab3a56c5478bb810b7200c48edbZhou Sheng#endif 4732aaee684d3fd24a7fb6e385877f113f2bd41ed6Tanya Lattner 48f7a743d7ed6e96af4c836e512c9cd59812c8186eChris Lattnerusing namespace llvm; 49d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 50c226570bdedff961d9c470951f477373cdb86437Owen Andersonstatic ManagedStatic<sys::Mutex> FunctionsLock; 51c226570bdedff961d9c470951f477373cdb86437Owen Anderson 526948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainartypedef GenericValue (*ExFunc)(FunctionType *, ArrayRef<GenericValue>); 53f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewyckystatic ManagedStatic<std::map<const Function *, ExFunc> > ExportedFunctions; 5437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic ManagedStatic<std::map<std::string, ExFunc> > FuncNames; 557720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner 5693f70fc291c56287bff7aefd924d171f005fdcc7Nick Lewycky#ifdef USE_LIBFFI 57a9ad04191cb56c42944b17980b8b2bb2afe11ab2Dan Gohmantypedef void (*RawFunc)(); 58f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewyckystatic ManagedStatic<std::map<const Function *, RawFunc> > RawFunctions; 59f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky#endif 60f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 61e43db88b2d12f2aebbe62aca8465a46c92292fceChris Lattnerstatic Interpreter *TheInterpreter; 62e43db88b2d12f2aebbe62aca8465a46c92292fceChris Lattner 63db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattnerstatic char getTypeID(Type *Ty) { 64f70c22b019494723d0e706f93d6542dfaa6e73a5Chris Lattner switch (Ty->getTypeID()) { 657720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner case Type::VoidTyID: return 'V'; 66a54b7cbd452b3adb2f51346140d996b29c2cdb30Reid Spencer case Type::IntegerTyID: 67a54b7cbd452b3adb2f51346140d996b29c2cdb30Reid Spencer switch (cast<IntegerType>(Ty)->getBitWidth()) { 68a54b7cbd452b3adb2f51346140d996b29c2cdb30Reid Spencer case 1: return 'o'; 69a54b7cbd452b3adb2f51346140d996b29c2cdb30Reid Spencer case 8: return 'B'; 70a54b7cbd452b3adb2f51346140d996b29c2cdb30Reid Spencer case 16: return 'S'; 71a54b7cbd452b3adb2f51346140d996b29c2cdb30Reid Spencer case 32: return 'I'; 72a54b7cbd452b3adb2f51346140d996b29c2cdb30Reid Spencer case 64: return 'L'; 73a54b7cbd452b3adb2f51346140d996b29c2cdb30Reid Spencer default: return 'N'; 74a54b7cbd452b3adb2f51346140d996b29c2cdb30Reid Spencer } 757720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner case Type::FloatTyID: return 'F'; 767720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner case Type::DoubleTyID: return 'D'; 777720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner case Type::PointerTyID: return 'P'; 78e49661bdf5b7a913d4e368cf511381e524ae403aReid Spencer case Type::FunctionTyID:return 'M'; 797720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner case Type::StructTyID: return 'T'; 807720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner case Type::ArrayTyID: return 'A'; 817720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner default: return 'U'; 827720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner } 837720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner} 847720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner 8542346f58d810204606ea5ec3d2e583b0a6da2531Anton Korobeynikov// Try to find address of external function given a Function object. 8642346f58d810204606ea5ec3d2e583b0a6da2531Anton Korobeynikov// Please note, that interpreter doesn't know how to assemble a 8742346f58d810204606ea5ec3d2e583b0a6da2531Anton Korobeynikov// real call in general case (this is JIT job), that's why it assumes, 8842346f58d810204606ea5ec3d2e583b0a6da2531Anton Korobeynikov// that all external functions has the same (and pretty "general") signature. 8942346f58d810204606ea5ec3d2e583b0a6da2531Anton Korobeynikov// The typical example of such functions are "lle_X_" ones. 9058a6faac65d2e5f60a650c6f99bb6c615ad9fbc6Brian Gaekestatic ExFunc lookupFunction(const Function *F) { 917720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner // Function not found, look it up... start by figuring out what the 927720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner // composite function name should be. 93697954c15da58bd8b186dbafdedd8b06db770201Chris Lattner std::string ExtName = "lle_"; 94db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner FunctionType *FT = F->getFunctionType(); 9558a6faac65d2e5f60a650c6f99bb6c615ad9fbc6Brian Gaeke for (unsigned i = 0, e = FT->getNumContainedTypes(); i != e; ++i) 9658a6faac65d2e5f60a650c6f99bb6c615ad9fbc6Brian Gaeke ExtName += getTypeID(FT->getContainedType(i)); 970c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar ExtName += ("_" + F->getName()).str(); 987720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner 99a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson sys::ScopedLock Writer(*FunctionsLock); 10037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ExFunc FnPtr = (*FuncNames)[ExtName]; 101dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!FnPtr) 1020c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar FnPtr = (*FuncNames)[("lle_X_" + F->getName()).str()]; 103dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!FnPtr) // Try calling a generic function... if it exists... 1040c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar FnPtr = (ExFunc)(intptr_t)sys::DynamicLibrary::SearchForAddressOfSymbol( 1050c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar ("lle_X_" + F->getName()).str()); 106dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (FnPtr) 107f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky ExportedFunctions->insert(std::make_pair(F, FnPtr)); // Cache for later 1087720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner return FnPtr; 1097720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner} 1107720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner 11193f70fc291c56287bff7aefd924d171f005fdcc7Nick Lewycky#ifdef USE_LIBFFI 112db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattnerstatic ffi_type *ffiTypeFor(Type *Ty) { 113f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky switch (Ty->getTypeID()) { 114f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::VoidTyID: return &ffi_type_void; 115f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::IntegerTyID: 116f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky switch (cast<IntegerType>(Ty)->getBitWidth()) { 117f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case 8: return &ffi_type_sint8; 118f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case 16: return &ffi_type_sint16; 119f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case 32: return &ffi_type_sint32; 120f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case 64: return &ffi_type_sint64; 121f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 122f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::FloatTyID: return &ffi_type_float; 123f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::DoubleTyID: return &ffi_type_double; 124f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::PointerTyID: return &ffi_type_pointer; 125f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky default: break; 126f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 127f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc. 12875361b69f3f327842b9dad69fa7f28ae3b688412Chris Lattner report_fatal_error("Type could not be mapped for use with libffi."); 129f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return NULL; 130f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky} 131f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 132db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattnerstatic void *ffiValueFor(Type *Ty, const GenericValue &AV, 133f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky void *ArgDataPtr) { 134f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky switch (Ty->getTypeID()) { 135f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::IntegerTyID: 136f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky switch (cast<IntegerType>(Ty)->getBitWidth()) { 137f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case 8: { 138f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky int8_t *I8Ptr = (int8_t *) ArgDataPtr; 139f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky *I8Ptr = (int8_t) AV.IntVal.getZExtValue(); 140f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return ArgDataPtr; 141f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 142f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case 16: { 143f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky int16_t *I16Ptr = (int16_t *) ArgDataPtr; 144f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky *I16Ptr = (int16_t) AV.IntVal.getZExtValue(); 145f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return ArgDataPtr; 146f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 147f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case 32: { 148f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky int32_t *I32Ptr = (int32_t *) ArgDataPtr; 149f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky *I32Ptr = (int32_t) AV.IntVal.getZExtValue(); 150f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return ArgDataPtr; 151f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 152f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case 64: { 153f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky int64_t *I64Ptr = (int64_t *) ArgDataPtr; 154f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky *I64Ptr = (int64_t) AV.IntVal.getZExtValue(); 155f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return ArgDataPtr; 156f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 157f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 158f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::FloatTyID: { 159f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky float *FloatPtr = (float *) ArgDataPtr; 160b5106f5c33b79827ce2d329e0ac9f2780b9fe222Nick Lewycky *FloatPtr = AV.FloatVal; 161f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return ArgDataPtr; 162f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 163f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::DoubleTyID: { 164f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky double *DoublePtr = (double *) ArgDataPtr; 165f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky *DoublePtr = AV.DoubleVal; 166f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return ArgDataPtr; 167f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 168f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::PointerTyID: { 169f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky void **PtrPtr = (void **) ArgDataPtr; 170f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky *PtrPtr = GVTOP(AV); 171f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return ArgDataPtr; 172f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 173f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky default: break; 174f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 175f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc. 17675361b69f3f327842b9dad69fa7f28ae3b688412Chris Lattner report_fatal_error("Type value could not be mapped for use with libffi."); 177f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return NULL; 178f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky} 179f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 1806948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstatic bool ffiInvoke(RawFunc Fn, Function *F, ArrayRef<GenericValue> ArgVals, 181cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar const DataLayout &TD, GenericValue &Result) { 182f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky ffi_cif cif; 183db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner FunctionType *FTy = F->getFunctionType(); 184f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky const unsigned NumArgs = F->arg_size(); 185f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 186f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky // TODO: We don't have type information about the remaining arguments, because 187f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky // this information is never passed into ExecutionEngine::runFunction(). 188f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky if (ArgVals.size() > NumArgs && F->isVarArg()) { 18975361b69f3f327842b9dad69fa7f28ae3b688412Chris Lattner report_fatal_error("Calling external var arg function '" + F->getName() 1907d696d80409aad20bb5da0fc4eccab941dd371d4Torok Edwin + "' is not supported by the Interpreter."); 191f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 192f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 193f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky unsigned ArgBytes = 0; 194f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 195f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky std::vector<ffi_type*> args(NumArgs); 196f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end(); 197f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky A != E; ++A) { 198f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky const unsigned ArgNo = A->getArgNo(); 199db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner Type *ArgTy = FTy->getParamType(ArgNo); 200f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky args[ArgNo] = ffiTypeFor(ArgTy); 201cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar ArgBytes += TD.getTypeStoreSize(ArgTy); 202f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 203f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 2047de3bd273ec3f4f027089285106095e8700e226dNick Lewycky SmallVector<uint8_t, 128> ArgData; 2057de3bd273ec3f4f027089285106095e8700e226dNick Lewycky ArgData.resize(ArgBytes); 2067de3bd273ec3f4f027089285106095e8700e226dNick Lewycky uint8_t *ArgDataPtr = ArgData.data(); 2077de3bd273ec3f4f027089285106095e8700e226dNick Lewycky SmallVector<void*, 16> values(NumArgs); 208f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end(); 209f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky A != E; ++A) { 210f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky const unsigned ArgNo = A->getArgNo(); 211db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner Type *ArgTy = FTy->getParamType(ArgNo); 212f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky values[ArgNo] = ffiValueFor(ArgTy, ArgVals[ArgNo], ArgDataPtr); 213cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar ArgDataPtr += TD.getTypeStoreSize(ArgTy); 214f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 215f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 216db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner Type *RetTy = FTy->getReturnType(); 217f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky ffi_type *rtype = ffiTypeFor(RetTy); 218f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 219f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, &args[0]) == FFI_OK) { 2207de3bd273ec3f4f027089285106095e8700e226dNick Lewycky SmallVector<uint8_t, 128> ret; 221f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky if (RetTy->getTypeID() != Type::VoidTyID) 222cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar ret.resize(TD.getTypeStoreSize(RetTy)); 2237de3bd273ec3f4f027089285106095e8700e226dNick Lewycky ffi_call(&cif, Fn, ret.data(), values.data()); 224f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky switch (RetTy->getTypeID()) { 225f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::IntegerTyID: 226f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky switch (cast<IntegerType>(RetTy)->getBitWidth()) { 2277de3bd273ec3f4f027089285106095e8700e226dNick Lewycky case 8: Result.IntVal = APInt(8 , *(int8_t *) ret.data()); break; 2287de3bd273ec3f4f027089285106095e8700e226dNick Lewycky case 16: Result.IntVal = APInt(16, *(int16_t*) ret.data()); break; 2297de3bd273ec3f4f027089285106095e8700e226dNick Lewycky case 32: Result.IntVal = APInt(32, *(int32_t*) ret.data()); break; 2307de3bd273ec3f4f027089285106095e8700e226dNick Lewycky case 64: Result.IntVal = APInt(64, *(int64_t*) ret.data()); break; 231f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 232f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky break; 2337de3bd273ec3f4f027089285106095e8700e226dNick Lewycky case Type::FloatTyID: Result.FloatVal = *(float *) ret.data(); break; 2347de3bd273ec3f4f027089285106095e8700e226dNick Lewycky case Type::DoubleTyID: Result.DoubleVal = *(double*) ret.data(); break; 2357de3bd273ec3f4f027089285106095e8700e226dNick Lewycky case Type::PointerTyID: Result.PointerVal = *(void **) ret.data(); break; 236f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky default: break; 237f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 238f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return true; 239f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 240f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 241f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return false; 242f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky} 24393f70fc291c56287bff7aefd924d171f005fdcc7Nick Lewycky#endif // USE_LIBFFI 244f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 2454e7dd8f7c4c0dc930ca64343316625cf464fb2d7Chris LattnerGenericValue Interpreter::callExternalFunction(Function *F, 2466948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar ArrayRef<GenericValue> ArgVals) { 247e43db88b2d12f2aebbe62aca8465a46c92292fceChris Lattner TheInterpreter = this; 248e43db88b2d12f2aebbe62aca8465a46c92292fceChris Lattner 24937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines unique_lock<sys::Mutex> Guard(*FunctionsLock); 250c226570bdedff961d9c470951f477373cdb86437Owen Anderson 2512fbfdcffd3e0cf41422aaa6c526c37cb02b81341Chris Lattner // Do a lookup to see if the function is in our cache... this should just be a 252d5d96b9fcd779806555cf5db602f80d5a308a471Misha Brukman // deferred annotation! 253f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky std::map<const Function *, ExFunc>::iterator FI = ExportedFunctions->find(F); 254f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky if (ExFunc Fn = (FI == ExportedFunctions->end()) ? lookupFunction(F) 255c226570bdedff961d9c470951f477373cdb86437Owen Anderson : FI->second) { 25637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Guard.unlock(); 257f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return Fn(F->getFunctionType(), ArgVals); 258c226570bdedff961d9c470951f477373cdb86437Owen Anderson } 259f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 26093f70fc291c56287bff7aefd924d171f005fdcc7Nick Lewycky#ifdef USE_LIBFFI 261f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky std::map<const Function *, RawFunc>::iterator RF = RawFunctions->find(F); 262f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky RawFunc RawFn; 263f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky if (RF == RawFunctions->end()) { 264f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky RawFn = (RawFunc)(intptr_t) 265f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky sys::DynamicLibrary::SearchForAddressOfSymbol(F->getName()); 266820580dfa9ed3e70d3eda06138a59fd903f61b7aTorok Edwin if (!RawFn) 2673472766f9eb7d66f234c390ce1b3a8b76f0ee9ceDuncan Sands RawFn = (RawFunc)(intptr_t)getPointerToGlobalIfAvailable(F); 268f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky if (RawFn != 0) 269f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky RawFunctions->insert(std::make_pair(F, RawFn)); // Cache for later 270f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } else { 271f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky RawFn = RF->second; 2727720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner } 273e4a5743d87bb5b389c4505c51714364062704a7bDaniel Dunbar 27437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Guard.unlock(); 2757720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner 276f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky GenericValue Result; 2773574eca1b02600bac4e625297f4ecf745f4c4f32Micah Villmow if (RawFn != 0 && ffiInvoke(RawFn, F, ArgVals, getDataLayout(), Result)) 278f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return Result; 27993f70fc291c56287bff7aefd924d171f005fdcc7Nick Lewycky#endif // USE_LIBFFI 280f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 2817d696d80409aad20bb5da0fc4eccab941dd371d4Torok Edwin if (F->getName() == "__main") 282c74fe78c2d267e05ba79c9dd83b0888cfa35c3f5David Greene errs() << "Tried to execute an unknown external function: " 2830cd0d881604775f3f97048645f040b2ef4f61e4bChris Lattner << *F->getType() << " __main\n"; 2847d696d80409aad20bb5da0fc4eccab941dd371d4Torok Edwin else 28575361b69f3f327842b9dad69fa7f28ae3b688412Chris Lattner report_fatal_error("Tried to execute an unknown external function: " + 2860cd0d881604775f3f97048645f040b2ef4f61e4bChris Lattner F->getName()); 2870e49fe814065ce382c34f4ba884be4a51f9c6e4cNick Lewycky#ifndef USE_LIBFFI 288c74fe78c2d267e05ba79c9dd83b0888cfa35c3f5David Greene errs() << "Recompiling LLVM with --enable-libffi might help.\n"; 2890e49fe814065ce382c34f4ba884be4a51f9c6e4cNick Lewycky#endif 290f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return GenericValue(); 2917720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner} 2927720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner 2937720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner 2947720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner//===----------------------------------------------------------------------===// 295b408b1255646f31895dcbf099184e087bfa1ca39Chris Lattner// Functions "exported" to the running application... 2967720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner// 297482cccd37e71ad69845d954b548bd46c2ee15155Daniel Dunbar 29844edb6bdd2edc48eb31ed160a09006b610cead67Chris Lattner// void atexit(Function*) 2996948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstatic GenericValue lle_X_atexit(FunctionType *FT, 3006948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar ArrayRef<GenericValue> Args) { 30144edb6bdd2edc48eb31ed160a09006b610cead67Chris Lattner assert(Args.size() == 1); 30244edb6bdd2edc48eb31ed160a09006b610cead67Chris Lattner TheInterpreter->addAtExitHandler((Function*)GVTOP(Args[0])); 30344edb6bdd2edc48eb31ed160a09006b610cead67Chris Lattner GenericValue GV; 304bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer GV.IntVal = 0; 30544edb6bdd2edc48eb31ed160a09006b610cead67Chris Lattner return GV; 306f8f2afb8cc5f080b291faad678e0a256ea44d15fChris Lattner} 307f8f2afb8cc5f080b291faad678e0a256ea44d15fChris Lattner 308005cbce20e55077d7e02255812e5df068188d302Chris Lattner// void exit(int) 3096948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstatic GenericValue lle_X_exit(FunctionType *FT, ArrayRef<GenericValue> Args) { 310e43db88b2d12f2aebbe62aca8465a46c92292fceChris Lattner TheInterpreter->exitCalled(Args[0]); 311e43db88b2d12f2aebbe62aca8465a46c92292fceChris Lattner return GenericValue(); 312e43db88b2d12f2aebbe62aca8465a46c92292fceChris Lattner} 313e43db88b2d12f2aebbe62aca8465a46c92292fceChris Lattner 314005cbce20e55077d7e02255812e5df068188d302Chris Lattner// void abort(void) 3156948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstatic GenericValue lle_X_abort(FunctionType *FT, ArrayRef<GenericValue> Args) { 3167d696d80409aad20bb5da0fc4eccab941dd371d4Torok Edwin //FIXME: should we report or raise here? 31775361b69f3f327842b9dad69fa7f28ae3b688412Chris Lattner //report_fatal_error("Interpreted program raised SIGABRT"); 318b56a6bc96a483b47da71b24efaa4380d463bbe17Brian Gaeke raise (SIGABRT); 3191ee34a5a5ba52557697e7eb607e8bd5d4ce0d492Chris Lattner return GenericValue(); 3201ee34a5a5ba52557697e7eb607e8bd5d4ce0d492Chris Lattner} 3211ee34a5a5ba52557697e7eb607e8bd5d4ce0d492Chris Lattner 322f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky// int sprintf(char *, const char *, ...) - a very rough implementation to make 323e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner// output useful. 3246948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstatic GenericValue lle_X_sprintf(FunctionType *FT, 3256948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar ArrayRef<GenericValue> Args) { 326b111874b386f5e3d807a8f78edb010b40d507115Chris Lattner char *OutputBuffer = (char *)GVTOP(Args[0]); 327b111874b386f5e3d807a8f78edb010b40d507115Chris Lattner const char *FmtStr = (const char *)GVTOP(Args[1]); 328e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner unsigned ArgNo = 2; 32908845a242c574d695566cbc61e46da1c86c810acChris Lattner 33008845a242c574d695566cbc61e46da1c86c810acChris Lattner // printf should return # chars printed. This is completely incorrect, but 33108845a242c574d695566cbc61e46da1c86c810acChris Lattner // close enough for now. 332e4a5743d87bb5b389c4505c51714364062704a7bDaniel Dunbar GenericValue GV; 333bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer GV.IntVal = APInt(32, strlen(FmtStr)); 33408845a242c574d695566cbc61e46da1c86c810acChris Lattner while (1) { 33508845a242c574d695566cbc61e46da1c86c810acChris Lattner switch (*FmtStr) { 33608845a242c574d695566cbc61e46da1c86c810acChris Lattner case 0: return GV; // Null terminator... 33708845a242c574d695566cbc61e46da1c86c810acChris Lattner default: // Normal nonspecial character 338e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner sprintf(OutputBuffer++, "%c", *FmtStr++); 33908845a242c574d695566cbc61e46da1c86c810acChris Lattner break; 34008845a242c574d695566cbc61e46da1c86c810acChris Lattner case '\\': { // Handle escape codes 341e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner sprintf(OutputBuffer, "%c%c", *FmtStr, *(FmtStr+1)); 342e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner FmtStr += 2; OutputBuffer += 2; 34308845a242c574d695566cbc61e46da1c86c810acChris Lattner break; 34408845a242c574d695566cbc61e46da1c86c810acChris Lattner } 34508845a242c574d695566cbc61e46da1c86c810acChris Lattner case '%': { // Handle format specifiers 346ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner char FmtBuf[100] = "", Buffer[1000] = ""; 347ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner char *FB = FmtBuf; 348ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner *FB++ = *FmtStr++; 349ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner char Last = *FB++ = *FmtStr++; 350ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner unsigned HowLong = 0; 351ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner while (Last != 'c' && Last != 'd' && Last != 'i' && Last != 'u' && 352ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner Last != 'o' && Last != 'x' && Last != 'X' && Last != 'e' && 353ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner Last != 'E' && Last != 'g' && Last != 'G' && Last != 'f' && 354ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner Last != 'p' && Last != 's' && Last != '%') { 355ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner if (Last == 'l' || Last == 'L') HowLong++; // Keep track of l's 356ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner Last = *FB++ = *FmtStr++; 35708845a242c574d695566cbc61e46da1c86c810acChris Lattner } 358ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner *FB = 0; 359d1c881a8d4da8b4d99c2a40512fbcca652ab445eMisha Brukman 360ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner switch (Last) { 361ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner case '%': 36212ea66a7277240c5b045ed14c140f94d453eea0eBenjamin Kramer memcpy(Buffer, "%", 2); break; 363ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner case 'c': 364bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer sprintf(Buffer, FmtBuf, uint32_t(Args[ArgNo++].IntVal.getZExtValue())); 365bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer break; 366ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner case 'd': case 'i': 367ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner case 'u': case 'o': 368ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner case 'x': case 'X': 36969ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner if (HowLong >= 1) { 3701543e40cea50d244979f0667f453cf3466a6106cChris Lattner if (HowLong == 1 && 371cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar TheInterpreter->getDataLayout().getPointerSizeInBits() == 64 && 37219b7e0e0cabfa6dfc559c64e3d6ed053832c4047Reid Spencer sizeof(long) < sizeof(int64_t)) { 37369ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner // Make sure we use %lld with a 64 bit argument because we might be 37469ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner // compiling LLI on a 32 bit compiler. 37569ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner unsigned Size = strlen(FmtBuf); 37669ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner FmtBuf[Size] = FmtBuf[Size-1]; 37769ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner FmtBuf[Size+1] = 0; 37869ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner FmtBuf[Size-1] = 'l'; 37969ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner } 380bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal.getZExtValue()); 38169ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner } else 382bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer sprintf(Buffer, FmtBuf,uint32_t(Args[ArgNo++].IntVal.getZExtValue())); 383bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer break; 384ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner case 'e': case 'E': case 'g': case 'G': case 'f': 385ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner sprintf(Buffer, FmtBuf, Args[ArgNo++].DoubleVal); break; 386ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner case 'p': 387b111874b386f5e3d807a8f78edb010b40d507115Chris Lattner sprintf(Buffer, FmtBuf, (void*)GVTOP(Args[ArgNo++])); break; 388d1c881a8d4da8b4d99c2a40512fbcca652ab445eMisha Brukman case 's': 389b111874b386f5e3d807a8f78edb010b40d507115Chris Lattner sprintf(Buffer, FmtBuf, (char*)GVTOP(Args[ArgNo++])); break; 390d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner default: 391c74fe78c2d267e05ba79c9dd83b0888cfa35c3f5David Greene errs() << "<unknown printf code '" << *FmtStr << "'!>"; 392ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner ArgNo++; break; 393ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner } 39412ea66a7277240c5b045ed14c140f94d453eea0eBenjamin Kramer size_t Len = strlen(Buffer); 39512ea66a7277240c5b045ed14c140f94d453eea0eBenjamin Kramer memcpy(OutputBuffer, Buffer, Len + 1); 39612ea66a7277240c5b045ed14c140f94d453eea0eBenjamin Kramer OutputBuffer += Len; 39708845a242c574d695566cbc61e46da1c86c810acChris Lattner } 39808845a242c574d695566cbc61e46da1c86c810acChris Lattner break; 39908845a242c574d695566cbc61e46da1c86c810acChris Lattner } 40008845a242c574d695566cbc61e46da1c86c810acChris Lattner } 4014ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky return GV; 40208845a242c574d695566cbc61e46da1c86c810acChris Lattner} 40308845a242c574d695566cbc61e46da1c86c810acChris Lattner 404f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky// int printf(const char *, ...) - a very rough implementation to make output 405f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky// useful. 4066948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstatic GenericValue lle_X_printf(FunctionType *FT, 4076948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar ArrayRef<GenericValue> Args) { 408e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner char Buffer[10000]; 409f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky std::vector<GenericValue> NewArgs; 410b3b0727032e58c8b8f3017c2b3f560616c6905afReid Spencer NewArgs.push_back(PTOGV((void*)&Buffer[0])); 411e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner NewArgs.insert(NewArgs.end(), Args.begin(), Args.end()); 41297e0c22330f1856a7e026d162040aafdb2a70d0eReid Spencer GenericValue GV = lle_X_sprintf(FT, NewArgs); 413d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner outs() << Buffer; 414e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner return GV; 415e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner} 416e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner 417665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner// int sscanf(const char *format, ...); 4186948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstatic GenericValue lle_X_sscanf(FunctionType *FT, 4196948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar ArrayRef<GenericValue> args) { 420665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner assert(args.size() < 10 && "Only handle up to 10 args to sscanf right now!"); 421665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner 422f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner char *Args[10]; 423665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner for (unsigned i = 0; i < args.size(); ++i) 424f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner Args[i] = (char*)GVTOP(args[i]); 425665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner 426665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner GenericValue GV; 427bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer GV.IntVal = APInt(32, sscanf(Args[0], Args[1], Args[2], Args[3], Args[4], 4284ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky Args[5], Args[6], Args[7], Args[8], Args[9])); 429f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner return GV; 430f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner} 431f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner 432f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner// int scanf(const char *format, ...); 4336948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstatic GenericValue lle_X_scanf(FunctionType *FT, ArrayRef<GenericValue> args) { 434f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner assert(args.size() < 10 && "Only handle up to 10 args to scanf right now!"); 435f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner 436f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner char *Args[10]; 437f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner for (unsigned i = 0; i < args.size(); ++i) 438f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner Args[i] = (char*)GVTOP(args[i]); 439f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner 440f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner GenericValue GV; 441bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer GV.IntVal = APInt(32, scanf( Args[0], Args[1], Args[2], Args[3], Args[4], 4424ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky Args[5], Args[6], Args[7], Args[8], Args[9])); 443665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner return GV; 444665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner} 445665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner 446f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky// int fprintf(FILE *, const char *, ...) - a very rough implementation to make 447f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky// output useful. 4486948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstatic GenericValue lle_X_fprintf(FunctionType *FT, 4496948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar ArrayRef<GenericValue> Args) { 4509dbf6dddcec7a627fabfc722e124311321de8fa0Chris Lattner assert(Args.size() >= 2); 451cf9b4f0f41242d8a7d4079ab9e6b163f54b621f1Chris Lattner char Buffer[10000]; 452f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky std::vector<GenericValue> NewArgs; 453b111874b386f5e3d807a8f78edb010b40d507115Chris Lattner NewArgs.push_back(PTOGV(Buffer)); 454cf9b4f0f41242d8a7d4079ab9e6b163f54b621f1Chris Lattner NewArgs.insert(NewArgs.end(), Args.begin()+1, Args.end()); 45597e0c22330f1856a7e026d162040aafdb2a70d0eReid Spencer GenericValue GV = lle_X_sprintf(FT, NewArgs); 456cf9b4f0f41242d8a7d4079ab9e6b163f54b621f1Chris Lattner 457f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky fputs(Buffer, (FILE *) GVTOP(Args[0])); 458cf9b4f0f41242d8a7d4079ab9e6b163f54b621f1Chris Lattner return GV; 459cf9b4f0f41242d8a7d4079ab9e6b163f54b621f1Chris Lattner} 460cf9b4f0f41242d8a7d4079ab9e6b163f54b621f1Chris Lattner 461cf47239da30ea57aaddc591018d0c0a2858088d8Benjamin Kramerstatic GenericValue lle_X_memset(FunctionType *FT, 4626948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar ArrayRef<GenericValue> Args) { 4634ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky int val = (int)Args[1].IntVal.getSExtValue(); 4644ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky size_t len = (size_t)Args[2].IntVal.getZExtValue(); 465cf47239da30ea57aaddc591018d0c0a2858088d8Benjamin Kramer memset((void *)GVTOP(Args[0]), val, len); 4664ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky // llvm.memset.* returns void, lle_X_* returns GenericValue, 4674ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky // so here we return GenericValue with IntVal set to zero 4684ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky GenericValue GV; 4694ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky GV.IntVal = 0; 4704ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky return GV; 4714ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky} 4724ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky 473cf47239da30ea57aaddc591018d0c0a2858088d8Benjamin Kramerstatic GenericValue lle_X_memcpy(FunctionType *FT, 4746948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar ArrayRef<GenericValue> Args) { 4754ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky memcpy(GVTOP(Args[0]), GVTOP(Args[1]), 4764ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky (size_t)(Args[2].IntVal.getLimitedValue())); 4774ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky 478cf47239da30ea57aaddc591018d0c0a2858088d8Benjamin Kramer // llvm.memcpy* returns void, lle_X_* returns GenericValue, 4794ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky // so here we return GenericValue with IntVal set to zero 4804ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky GenericValue GV; 4814ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky GV.IntVal = 0; 4824ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky return GV; 4834ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky} 4844ca0ce2594a3e3d420be548cb3b6e4e8f51e229fElena Demikhovsky 485da82ed52ac02497d343b898cca0bb2cf303f062dChris Lattnervoid Interpreter::initializeExternalFunctions() { 486a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson sys::ScopedLock Writer(*FunctionsLock); 48737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines (*FuncNames)["lle_X_atexit"] = lle_X_atexit; 48837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines (*FuncNames)["lle_X_exit"] = lle_X_exit; 48937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines (*FuncNames)["lle_X_abort"] = lle_X_abort; 49037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 49137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines (*FuncNames)["lle_X_printf"] = lle_X_printf; 49237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines (*FuncNames)["lle_X_sprintf"] = lle_X_sprintf; 49337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines (*FuncNames)["lle_X_sscanf"] = lle_X_sscanf; 49437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines (*FuncNames)["lle_X_scanf"] = lle_X_scanf; 49537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines (*FuncNames)["lle_X_fprintf"] = lle_X_fprintf; 49637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines (*FuncNames)["lle_X_memset"] = lle_X_memset; 49737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines (*FuncNames)["lle_X_memcpy"] = lle_X_memcpy; 4984721f1304f3d49e44c78c9eed882a34ad7388be0Chris Lattner} 499