ExternalFunctions.cpp revision 3574eca1b02600bac4e625297f4ecf745f4c4f32
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" 237720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner#include "llvm/DerivedTypes.h" 24b8d15b2ad0a2266b275a00f07410e6c9d9ca6695Misha Brukman#include "llvm/Module.h" 25f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky#include "llvm/Config/config.h" // Detect libffi 267d696d80409aad20bb5da0fc4eccab941dd371d4Torok Edwin#include "llvm/Support/ErrorHandling.h" 271f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/DynamicLibrary.h" 283574eca1b02600bac4e625297f4ecf745f4c4f32Micah Villmow#include "llvm/DataLayout.h" 29936baaa5aeddb78ff41b1f655101b4d88c47473bChuck Rose III#include "llvm/Support/ManagedStatic.h" 301f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Mutex.h" 31b56a6bc96a483b47da71b24efaa4380d463bbe17Brian Gaeke#include <csignal> 324520dd2b7b20af07d5a3e4d06d964a532044eb10Duncan Sands#include <cstdio> 33b8d15b2ad0a2266b275a00f07410e6c9d9ca6695Misha Brukman#include <map> 3497af751deb9b26fd42fbcee082da9ccc4ded5b45Jeff Cohen#include <cmath> 35ae9f3a3b7c915f725aef5a7250e88eaeddda03c6Anton Korobeynikov#include <cstring> 36621deadee8967ab3a56c5478bb810b7200c48edbZhou Sheng 3793f70fc291c56287bff7aefd924d171f005fdcc7Nick Lewycky#ifdef HAVE_FFI_CALL 38f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky#ifdef HAVE_FFI_H 39f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky#include <ffi.h> 4093f70fc291c56287bff7aefd924d171f005fdcc7Nick Lewycky#define USE_LIBFFI 41f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky#elif HAVE_FFI_FFI_H 42f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky#include <ffi/ffi.h> 4393f70fc291c56287bff7aefd924d171f005fdcc7Nick Lewycky#define USE_LIBFFI 44f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky#endif 45621deadee8967ab3a56c5478bb810b7200c48edbZhou Sheng#endif 4632aaee684d3fd24a7fb6e385877f113f2bd41ed6Tanya Lattner 47f7a743d7ed6e96af4c836e512c9cd59812c8186eChris Lattnerusing namespace llvm; 48d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 49c226570bdedff961d9c470951f477373cdb86437Owen Andersonstatic ManagedStatic<sys::Mutex> FunctionsLock; 50c226570bdedff961d9c470951f477373cdb86437Owen Anderson 51db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattnertypedef GenericValue (*ExFunc)(FunctionType *, 52f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky const std::vector<GenericValue> &); 53f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewyckystatic ManagedStatic<std::map<const Function *, ExFunc> > ExportedFunctions; 54697954c15da58bd8b186dbafdedd8b06db770201Chris Lattnerstatic 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)); 97a7b0cb759433c715065440ee2a963a04db7f2b0bBenjamin Kramer ExtName += "_" + F->getName().str(); 987720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner 99a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson sys::ScopedLock Writer(*FunctionsLock); 1004721f1304f3d49e44c78c9eed882a34ad7388be0Chris Lattner ExFunc FnPtr = FuncNames[ExtName]; 1014721f1304f3d49e44c78c9eed882a34ad7388be0Chris Lattner if (FnPtr == 0) 102a7b0cb759433c715065440ee2a963a04db7f2b0bBenjamin Kramer FnPtr = FuncNames["lle_X_" + F->getName().str()]; 1037720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner if (FnPtr == 0) // Try calling a generic function... if it exists... 1048f60302ee5e45c90fba7b8c771986106e3618129Daniel Dunbar FnPtr = (ExFunc)(intptr_t) 105a7b0cb759433c715065440ee2a963a04db7f2b0bBenjamin Kramer sys::DynamicLibrary::SearchForAddressOfSymbol("lle_X_" + 106a7b0cb759433c715065440ee2a963a04db7f2b0bBenjamin Kramer F->getName().str()); 1077720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner if (FnPtr != 0) 108f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky ExportedFunctions->insert(std::make_pair(F, FnPtr)); // Cache for later 1097720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner return FnPtr; 1107720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner} 1117720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner 11293f70fc291c56287bff7aefd924d171f005fdcc7Nick Lewycky#ifdef USE_LIBFFI 113db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattnerstatic ffi_type *ffiTypeFor(Type *Ty) { 114f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky switch (Ty->getTypeID()) { 115f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::VoidTyID: return &ffi_type_void; 116f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::IntegerTyID: 117f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky switch (cast<IntegerType>(Ty)->getBitWidth()) { 118f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case 8: return &ffi_type_sint8; 119f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case 16: return &ffi_type_sint16; 120f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case 32: return &ffi_type_sint32; 121f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case 64: return &ffi_type_sint64; 122f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 123f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::FloatTyID: return &ffi_type_float; 124f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::DoubleTyID: return &ffi_type_double; 125f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::PointerTyID: return &ffi_type_pointer; 126f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky default: break; 127f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 128f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc. 12975361b69f3f327842b9dad69fa7f28ae3b688412Chris Lattner report_fatal_error("Type could not be mapped for use with libffi."); 130f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return NULL; 131f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky} 132f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 133db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattnerstatic void *ffiValueFor(Type *Ty, const GenericValue &AV, 134f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky void *ArgDataPtr) { 135f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky switch (Ty->getTypeID()) { 136f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::IntegerTyID: 137f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky switch (cast<IntegerType>(Ty)->getBitWidth()) { 138f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case 8: { 139f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky int8_t *I8Ptr = (int8_t *) ArgDataPtr; 140f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky *I8Ptr = (int8_t) AV.IntVal.getZExtValue(); 141f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return ArgDataPtr; 142f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 143f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case 16: { 144f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky int16_t *I16Ptr = (int16_t *) ArgDataPtr; 145f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky *I16Ptr = (int16_t) AV.IntVal.getZExtValue(); 146f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return ArgDataPtr; 147f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 148f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case 32: { 149f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky int32_t *I32Ptr = (int32_t *) ArgDataPtr; 150f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky *I32Ptr = (int32_t) AV.IntVal.getZExtValue(); 151f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return ArgDataPtr; 152f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 153f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case 64: { 154f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky int64_t *I64Ptr = (int64_t *) ArgDataPtr; 155f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky *I64Ptr = (int64_t) AV.IntVal.getZExtValue(); 156f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return ArgDataPtr; 157f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 158f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 159f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::FloatTyID: { 160f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky float *FloatPtr = (float *) ArgDataPtr; 161b5106f5c33b79827ce2d329e0ac9f2780b9fe222Nick Lewycky *FloatPtr = AV.FloatVal; 162f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return ArgDataPtr; 163f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 164f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::DoubleTyID: { 165f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky double *DoublePtr = (double *) ArgDataPtr; 166f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky *DoublePtr = AV.DoubleVal; 167f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return ArgDataPtr; 168f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 169f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::PointerTyID: { 170f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky void **PtrPtr = (void **) ArgDataPtr; 171f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky *PtrPtr = GVTOP(AV); 172f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return ArgDataPtr; 173f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 174f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky default: break; 175f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 176f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc. 17775361b69f3f327842b9dad69fa7f28ae3b688412Chris Lattner report_fatal_error("Type value could not be mapped for use with libffi."); 178f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return NULL; 179f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky} 180f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 181f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewyckystatic bool ffiInvoke(RawFunc Fn, Function *F, 182f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky const std::vector<GenericValue> &ArgVals, 1833574eca1b02600bac4e625297f4ecf745f4c4f32Micah Villmow const DataLayout *TD, GenericValue &Result) { 184f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky ffi_cif cif; 185db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner FunctionType *FTy = F->getFunctionType(); 186f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky const unsigned NumArgs = F->arg_size(); 187f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 188f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky // TODO: We don't have type information about the remaining arguments, because 189f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky // this information is never passed into ExecutionEngine::runFunction(). 190f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky if (ArgVals.size() > NumArgs && F->isVarArg()) { 19175361b69f3f327842b9dad69fa7f28ae3b688412Chris Lattner report_fatal_error("Calling external var arg function '" + F->getName() 1927d696d80409aad20bb5da0fc4eccab941dd371d4Torok Edwin + "' is not supported by the Interpreter."); 193f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 194f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 195f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky unsigned ArgBytes = 0; 196f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 197f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky std::vector<ffi_type*> args(NumArgs); 198f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end(); 199f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky A != E; ++A) { 200f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky const unsigned ArgNo = A->getArgNo(); 201db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner Type *ArgTy = FTy->getParamType(ArgNo); 202f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky args[ArgNo] = ffiTypeFor(ArgTy); 203f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky ArgBytes += TD->getTypeStoreSize(ArgTy); 204f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 205f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 2067de3bd273ec3f4f027089285106095e8700e226dNick Lewycky SmallVector<uint8_t, 128> ArgData; 2077de3bd273ec3f4f027089285106095e8700e226dNick Lewycky ArgData.resize(ArgBytes); 2087de3bd273ec3f4f027089285106095e8700e226dNick Lewycky uint8_t *ArgDataPtr = ArgData.data(); 2097de3bd273ec3f4f027089285106095e8700e226dNick Lewycky SmallVector<void*, 16> values(NumArgs); 210f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end(); 211f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky A != E; ++A) { 212f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky const unsigned ArgNo = A->getArgNo(); 213db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner Type *ArgTy = FTy->getParamType(ArgNo); 214f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky values[ArgNo] = ffiValueFor(ArgTy, ArgVals[ArgNo], ArgDataPtr); 215f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky ArgDataPtr += TD->getTypeStoreSize(ArgTy); 216f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 217f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 218db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner Type *RetTy = FTy->getReturnType(); 219f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky ffi_type *rtype = ffiTypeFor(RetTy); 220f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 221f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, &args[0]) == FFI_OK) { 2227de3bd273ec3f4f027089285106095e8700e226dNick Lewycky SmallVector<uint8_t, 128> ret; 223f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky if (RetTy->getTypeID() != Type::VoidTyID) 2247de3bd273ec3f4f027089285106095e8700e226dNick Lewycky ret.resize(TD->getTypeStoreSize(RetTy)); 2257de3bd273ec3f4f027089285106095e8700e226dNick Lewycky ffi_call(&cif, Fn, ret.data(), values.data()); 226f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky switch (RetTy->getTypeID()) { 227f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky case Type::IntegerTyID: 228f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky switch (cast<IntegerType>(RetTy)->getBitWidth()) { 2297de3bd273ec3f4f027089285106095e8700e226dNick Lewycky case 8: Result.IntVal = APInt(8 , *(int8_t *) ret.data()); break; 2307de3bd273ec3f4f027089285106095e8700e226dNick Lewycky case 16: Result.IntVal = APInt(16, *(int16_t*) ret.data()); break; 2317de3bd273ec3f4f027089285106095e8700e226dNick Lewycky case 32: Result.IntVal = APInt(32, *(int32_t*) ret.data()); break; 2327de3bd273ec3f4f027089285106095e8700e226dNick Lewycky case 64: Result.IntVal = APInt(64, *(int64_t*) ret.data()); break; 233f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 234f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky break; 2357de3bd273ec3f4f027089285106095e8700e226dNick Lewycky case Type::FloatTyID: Result.FloatVal = *(float *) ret.data(); break; 2367de3bd273ec3f4f027089285106095e8700e226dNick Lewycky case Type::DoubleTyID: Result.DoubleVal = *(double*) ret.data(); break; 2377de3bd273ec3f4f027089285106095e8700e226dNick Lewycky case Type::PointerTyID: Result.PointerVal = *(void **) ret.data(); break; 238f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky default: break; 239f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 240f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return true; 241f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } 242f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 243f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return false; 244f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky} 24593f70fc291c56287bff7aefd924d171f005fdcc7Nick Lewycky#endif // USE_LIBFFI 246f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 2474e7dd8f7c4c0dc930ca64343316625cf464fb2d7Chris LattnerGenericValue Interpreter::callExternalFunction(Function *F, 24844edb6bdd2edc48eb31ed160a09006b610cead67Chris Lattner const std::vector<GenericValue> &ArgVals) { 249e43db88b2d12f2aebbe62aca8465a46c92292fceChris Lattner TheInterpreter = this; 250e43db88b2d12f2aebbe62aca8465a46c92292fceChris Lattner 251c226570bdedff961d9c470951f477373cdb86437Owen Anderson FunctionsLock->acquire(); 252c226570bdedff961d9c470951f477373cdb86437Owen Anderson 2532fbfdcffd3e0cf41422aaa6c526c37cb02b81341Chris Lattner // Do a lookup to see if the function is in our cache... this should just be a 254d5d96b9fcd779806555cf5db602f80d5a308a471Misha Brukman // deferred annotation! 255f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky std::map<const Function *, ExFunc>::iterator FI = ExportedFunctions->find(F); 256f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky if (ExFunc Fn = (FI == ExportedFunctions->end()) ? lookupFunction(F) 257c226570bdedff961d9c470951f477373cdb86437Owen Anderson : FI->second) { 258c226570bdedff961d9c470951f477373cdb86437Owen Anderson FunctionsLock->release(); 259f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return Fn(F->getFunctionType(), ArgVals); 260c226570bdedff961d9c470951f477373cdb86437Owen Anderson } 261f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 26293f70fc291c56287bff7aefd924d171f005fdcc7Nick Lewycky#ifdef USE_LIBFFI 263f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky std::map<const Function *, RawFunc>::iterator RF = RawFunctions->find(F); 264f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky RawFunc RawFn; 265f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky if (RF == RawFunctions->end()) { 266f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky RawFn = (RawFunc)(intptr_t) 267f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky sys::DynamicLibrary::SearchForAddressOfSymbol(F->getName()); 268820580dfa9ed3e70d3eda06138a59fd903f61b7aTorok Edwin if (!RawFn) 2693472766f9eb7d66f234c390ce1b3a8b76f0ee9ceDuncan Sands RawFn = (RawFunc)(intptr_t)getPointerToGlobalIfAvailable(F); 270f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky if (RawFn != 0) 271f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky RawFunctions->insert(std::make_pair(F, RawFn)); // Cache for later 272f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky } else { 273f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky RawFn = RF->second; 2747720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner } 275e4a5743d87bb5b389c4505c51714364062704a7bDaniel Dunbar 276c226570bdedff961d9c470951f477373cdb86437Owen Anderson FunctionsLock->release(); 2777720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner 278f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky GenericValue Result; 2793574eca1b02600bac4e625297f4ecf745f4c4f32Micah Villmow if (RawFn != 0 && ffiInvoke(RawFn, F, ArgVals, getDataLayout(), Result)) 280f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return Result; 28193f70fc291c56287bff7aefd924d171f005fdcc7Nick Lewycky#endif // USE_LIBFFI 282f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 2837d696d80409aad20bb5da0fc4eccab941dd371d4Torok Edwin if (F->getName() == "__main") 284c74fe78c2d267e05ba79c9dd83b0888cfa35c3f5David Greene errs() << "Tried to execute an unknown external function: " 2850cd0d881604775f3f97048645f040b2ef4f61e4bChris Lattner << *F->getType() << " __main\n"; 2867d696d80409aad20bb5da0fc4eccab941dd371d4Torok Edwin else 28775361b69f3f327842b9dad69fa7f28ae3b688412Chris Lattner report_fatal_error("Tried to execute an unknown external function: " + 2880cd0d881604775f3f97048645f040b2ef4f61e4bChris Lattner F->getName()); 2890e49fe814065ce382c34f4ba884be4a51f9c6e4cNick Lewycky#ifndef USE_LIBFFI 290c74fe78c2d267e05ba79c9dd83b0888cfa35c3f5David Greene errs() << "Recompiling LLVM with --enable-libffi might help.\n"; 2910e49fe814065ce382c34f4ba884be4a51f9c6e4cNick Lewycky#endif 292f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky return GenericValue(); 2937720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner} 2947720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner 2957720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner 2967720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner//===----------------------------------------------------------------------===// 297b408b1255646f31895dcbf099184e087bfa1ca39Chris Lattner// Functions "exported" to the running application... 2987720c8e1a7a252e983e3f3e7f841d7901dfea80cChris Lattner// 299482cccd37e71ad69845d954b548bd46c2ee15155Daniel Dunbar 30044edb6bdd2edc48eb31ed160a09006b610cead67Chris Lattner// void atexit(Function*) 3014bf6c19e94e4c7eb888d94c1aa322d23dbcc93baNAKAMURA Takumistatic 302db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris LattnerGenericValue lle_X_atexit(FunctionType *FT, 303f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky const std::vector<GenericValue> &Args) { 30444edb6bdd2edc48eb31ed160a09006b610cead67Chris Lattner assert(Args.size() == 1); 30544edb6bdd2edc48eb31ed160a09006b610cead67Chris Lattner TheInterpreter->addAtExitHandler((Function*)GVTOP(Args[0])); 30644edb6bdd2edc48eb31ed160a09006b610cead67Chris Lattner GenericValue GV; 307bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer GV.IntVal = 0; 30844edb6bdd2edc48eb31ed160a09006b610cead67Chris Lattner return GV; 309f8f2afb8cc5f080b291faad678e0a256ea44d15fChris Lattner} 310f8f2afb8cc5f080b291faad678e0a256ea44d15fChris Lattner 311005cbce20e55077d7e02255812e5df068188d302Chris Lattner// void exit(int) 3124bf6c19e94e4c7eb888d94c1aa322d23dbcc93baNAKAMURA Takumistatic 313db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris LattnerGenericValue lle_X_exit(FunctionType *FT, 314f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky const std::vector<GenericValue> &Args) { 315e43db88b2d12f2aebbe62aca8465a46c92292fceChris Lattner TheInterpreter->exitCalled(Args[0]); 316e43db88b2d12f2aebbe62aca8465a46c92292fceChris Lattner return GenericValue(); 317e43db88b2d12f2aebbe62aca8465a46c92292fceChris Lattner} 318e43db88b2d12f2aebbe62aca8465a46c92292fceChris Lattner 319005cbce20e55077d7e02255812e5df068188d302Chris Lattner// void abort(void) 3204bf6c19e94e4c7eb888d94c1aa322d23dbcc93baNAKAMURA Takumistatic 321db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris LattnerGenericValue lle_X_abort(FunctionType *FT, 322f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky const std::vector<GenericValue> &Args) { 3237d696d80409aad20bb5da0fc4eccab941dd371d4Torok Edwin //FIXME: should we report or raise here? 32475361b69f3f327842b9dad69fa7f28ae3b688412Chris Lattner //report_fatal_error("Interpreted program raised SIGABRT"); 325b56a6bc96a483b47da71b24efaa4380d463bbe17Brian Gaeke raise (SIGABRT); 3261ee34a5a5ba52557697e7eb607e8bd5d4ce0d492Chris Lattner return GenericValue(); 3271ee34a5a5ba52557697e7eb607e8bd5d4ce0d492Chris Lattner} 3281ee34a5a5ba52557697e7eb607e8bd5d4ce0d492Chris Lattner 329f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky// int sprintf(char *, const char *, ...) - a very rough implementation to make 330e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner// output useful. 3314bf6c19e94e4c7eb888d94c1aa322d23dbcc93baNAKAMURA Takumistatic 332db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris LattnerGenericValue lle_X_sprintf(FunctionType *FT, 333f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky const std::vector<GenericValue> &Args) { 334b111874b386f5e3d807a8f78edb010b40d507115Chris Lattner char *OutputBuffer = (char *)GVTOP(Args[0]); 335b111874b386f5e3d807a8f78edb010b40d507115Chris Lattner const char *FmtStr = (const char *)GVTOP(Args[1]); 336e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner unsigned ArgNo = 2; 33708845a242c574d695566cbc61e46da1c86c810acChris Lattner 33808845a242c574d695566cbc61e46da1c86c810acChris Lattner // printf should return # chars printed. This is completely incorrect, but 33908845a242c574d695566cbc61e46da1c86c810acChris Lattner // close enough for now. 340e4a5743d87bb5b389c4505c51714364062704a7bDaniel Dunbar GenericValue GV; 341bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer GV.IntVal = APInt(32, strlen(FmtStr)); 34208845a242c574d695566cbc61e46da1c86c810acChris Lattner while (1) { 34308845a242c574d695566cbc61e46da1c86c810acChris Lattner switch (*FmtStr) { 34408845a242c574d695566cbc61e46da1c86c810acChris Lattner case 0: return GV; // Null terminator... 34508845a242c574d695566cbc61e46da1c86c810acChris Lattner default: // Normal nonspecial character 346e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner sprintf(OutputBuffer++, "%c", *FmtStr++); 34708845a242c574d695566cbc61e46da1c86c810acChris Lattner break; 34808845a242c574d695566cbc61e46da1c86c810acChris Lattner case '\\': { // Handle escape codes 349e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner sprintf(OutputBuffer, "%c%c", *FmtStr, *(FmtStr+1)); 350e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner FmtStr += 2; OutputBuffer += 2; 35108845a242c574d695566cbc61e46da1c86c810acChris Lattner break; 35208845a242c574d695566cbc61e46da1c86c810acChris Lattner } 35308845a242c574d695566cbc61e46da1c86c810acChris Lattner case '%': { // Handle format specifiers 354ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner char FmtBuf[100] = "", Buffer[1000] = ""; 355ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner char *FB = FmtBuf; 356ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner *FB++ = *FmtStr++; 357ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner char Last = *FB++ = *FmtStr++; 358ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner unsigned HowLong = 0; 359ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner while (Last != 'c' && Last != 'd' && Last != 'i' && Last != 'u' && 360ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner Last != 'o' && Last != 'x' && Last != 'X' && Last != 'e' && 361ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner Last != 'E' && Last != 'g' && Last != 'G' && Last != 'f' && 362ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner Last != 'p' && Last != 's' && Last != '%') { 363ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner if (Last == 'l' || Last == 'L') HowLong++; // Keep track of l's 364ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner Last = *FB++ = *FmtStr++; 36508845a242c574d695566cbc61e46da1c86c810acChris Lattner } 366ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner *FB = 0; 367d1c881a8d4da8b4d99c2a40512fbcca652ab445eMisha Brukman 368ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner switch (Last) { 369ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner case '%': 37012ea66a7277240c5b045ed14c140f94d453eea0eBenjamin Kramer memcpy(Buffer, "%", 2); break; 371ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner case 'c': 372bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer sprintf(Buffer, FmtBuf, uint32_t(Args[ArgNo++].IntVal.getZExtValue())); 373bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer break; 374ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner case 'd': case 'i': 375ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner case 'u': case 'o': 376ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner case 'x': case 'X': 37769ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner if (HowLong >= 1) { 3781543e40cea50d244979f0667f453cf3466a6106cChris Lattner if (HowLong == 1 && 3793574eca1b02600bac4e625297f4ecf745f4c4f32Micah Villmow TheInterpreter->getDataLayout()->getPointerSizeInBits() == 64 && 38019b7e0e0cabfa6dfc559c64e3d6ed053832c4047Reid Spencer sizeof(long) < sizeof(int64_t)) { 38169ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner // Make sure we use %lld with a 64 bit argument because we might be 38269ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner // compiling LLI on a 32 bit compiler. 38369ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner unsigned Size = strlen(FmtBuf); 38469ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner FmtBuf[Size] = FmtBuf[Size-1]; 38569ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner FmtBuf[Size+1] = 0; 38669ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner FmtBuf[Size-1] = 'l'; 38769ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner } 388bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal.getZExtValue()); 38969ab7a8ac6c52465f7b886fb11e390330e8cf10fChris Lattner } else 390bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer sprintf(Buffer, FmtBuf,uint32_t(Args[ArgNo++].IntVal.getZExtValue())); 391bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer break; 392ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner case 'e': case 'E': case 'g': case 'G': case 'f': 393ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner sprintf(Buffer, FmtBuf, Args[ArgNo++].DoubleVal); break; 394ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner case 'p': 395b111874b386f5e3d807a8f78edb010b40d507115Chris Lattner sprintf(Buffer, FmtBuf, (void*)GVTOP(Args[ArgNo++])); break; 396d1c881a8d4da8b4d99c2a40512fbcca652ab445eMisha Brukman case 's': 397b111874b386f5e3d807a8f78edb010b40d507115Chris Lattner sprintf(Buffer, FmtBuf, (char*)GVTOP(Args[ArgNo++])); break; 398d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner default: 399c74fe78c2d267e05ba79c9dd83b0888cfa35c3f5David Greene errs() << "<unknown printf code '" << *FmtStr << "'!>"; 400ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner ArgNo++; break; 401ea38c0e85c29783fdaf3b6c25fe7e3aa43688521Chris Lattner } 40212ea66a7277240c5b045ed14c140f94d453eea0eBenjamin Kramer size_t Len = strlen(Buffer); 40312ea66a7277240c5b045ed14c140f94d453eea0eBenjamin Kramer memcpy(OutputBuffer, Buffer, Len + 1); 40412ea66a7277240c5b045ed14c140f94d453eea0eBenjamin Kramer OutputBuffer += Len; 40508845a242c574d695566cbc61e46da1c86c810acChris Lattner } 40608845a242c574d695566cbc61e46da1c86c810acChris Lattner break; 40708845a242c574d695566cbc61e46da1c86c810acChris Lattner } 40808845a242c574d695566cbc61e46da1c86c810acChris Lattner } 40908845a242c574d695566cbc61e46da1c86c810acChris Lattner} 41008845a242c574d695566cbc61e46da1c86c810acChris Lattner 411f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky// int printf(const char *, ...) - a very rough implementation to make output 412f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky// useful. 4134bf6c19e94e4c7eb888d94c1aa322d23dbcc93baNAKAMURA Takumistatic 414db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris LattnerGenericValue lle_X_printf(FunctionType *FT, 415f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky const std::vector<GenericValue> &Args) { 416e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner char Buffer[10000]; 417f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky std::vector<GenericValue> NewArgs; 418b3b0727032e58c8b8f3017c2b3f560616c6905afReid Spencer NewArgs.push_back(PTOGV((void*)&Buffer[0])); 419e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner NewArgs.insert(NewArgs.end(), Args.begin(), Args.end()); 42097e0c22330f1856a7e026d162040aafdb2a70d0eReid Spencer GenericValue GV = lle_X_sprintf(FT, NewArgs); 421d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner outs() << Buffer; 422e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner return GV; 423e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner} 424e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner 425665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner// int sscanf(const char *format, ...); 4264bf6c19e94e4c7eb888d94c1aa322d23dbcc93baNAKAMURA Takumistatic 427db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris LattnerGenericValue lle_X_sscanf(FunctionType *FT, 428f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky const std::vector<GenericValue> &args) { 429665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner assert(args.size() < 10 && "Only handle up to 10 args to sscanf right now!"); 430665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner 431f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner char *Args[10]; 432665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner for (unsigned i = 0; i < args.size(); ++i) 433f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner Args[i] = (char*)GVTOP(args[i]); 434665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner 435665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner GenericValue GV; 436bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer GV.IntVal = APInt(32, sscanf(Args[0], Args[1], Args[2], Args[3], Args[4], 437bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer Args[5], Args[6], Args[7], Args[8], Args[9])); 438f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner return GV; 439f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner} 440f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner 441f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner// int scanf(const char *format, ...); 4424bf6c19e94e4c7eb888d94c1aa322d23dbcc93baNAKAMURA Takumistatic 443db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris LattnerGenericValue lle_X_scanf(FunctionType *FT, 444f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky const std::vector<GenericValue> &args) { 445f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner assert(args.size() < 10 && "Only handle up to 10 args to scanf right now!"); 446f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner 447f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner char *Args[10]; 448f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner for (unsigned i = 0; i < args.size(); ++i) 449f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner Args[i] = (char*)GVTOP(args[i]); 450f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner 451f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner GenericValue GV; 452bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer GV.IntVal = APInt(32, scanf( Args[0], Args[1], Args[2], Args[3], Args[4], 453bfcd5992d8ae20812e61fe3b017b79254236a8baReid Spencer Args[5], Args[6], Args[7], Args[8], Args[9])); 454665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner return GV; 455665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner} 456665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner 457f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky// int fprintf(FILE *, const char *, ...) - a very rough implementation to make 458f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky// output useful. 4594bf6c19e94e4c7eb888d94c1aa322d23dbcc93baNAKAMURA Takumistatic 460db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris LattnerGenericValue lle_X_fprintf(FunctionType *FT, 461f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky const std::vector<GenericValue> &Args) { 4629dbf6dddcec7a627fabfc722e124311321de8fa0Chris Lattner assert(Args.size() >= 2); 463cf9b4f0f41242d8a7d4079ab9e6b163f54b621f1Chris Lattner char Buffer[10000]; 464f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky std::vector<GenericValue> NewArgs; 465b111874b386f5e3d807a8f78edb010b40d507115Chris Lattner NewArgs.push_back(PTOGV(Buffer)); 466cf9b4f0f41242d8a7d4079ab9e6b163f54b621f1Chris Lattner NewArgs.insert(NewArgs.end(), Args.begin()+1, Args.end()); 46797e0c22330f1856a7e026d162040aafdb2a70d0eReid Spencer GenericValue GV = lle_X_sprintf(FT, NewArgs); 468cf9b4f0f41242d8a7d4079ab9e6b163f54b621f1Chris Lattner 469f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky fputs(Buffer, (FILE *) GVTOP(Args[0])); 470cf9b4f0f41242d8a7d4079ab9e6b163f54b621f1Chris Lattner return GV; 471cf9b4f0f41242d8a7d4079ab9e6b163f54b621f1Chris Lattner} 472cf9b4f0f41242d8a7d4079ab9e6b163f54b621f1Chris Lattner 473da82ed52ac02497d343b898cca0bb2cf303f062dChris Lattnervoid Interpreter::initializeExternalFunctions() { 474a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson sys::ScopedLock Writer(*FunctionsLock); 475f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky FuncNames["lle_X_atexit"] = lle_X_atexit; 4760f279b245dc5f84a6b7c89900fd0d48e324452e7Chris Lattner FuncNames["lle_X_exit"] = lle_X_exit; 4771ee34a5a5ba52557697e7eb607e8bd5d4ce0d492Chris Lattner FuncNames["lle_X_abort"] = lle_X_abort; 478f9c5c5c7a25a3c549cbbc523bf2c8f4e895c20b6Nick Lewycky 4790f279b245dc5f84a6b7c89900fd0d48e324452e7Chris Lattner FuncNames["lle_X_printf"] = lle_X_printf; 480e7c6f726c8d18ff8803d9b3dc3a8443496002044Chris Lattner FuncNames["lle_X_sprintf"] = lle_X_sprintf; 481665ee88504ae8e4440fd1609f3d88c3481cebe12Chris Lattner FuncNames["lle_X_sscanf"] = lle_X_sscanf; 482f9a88b684d8ca368ad51695c61a3580f4700da52Chris Lattner FuncNames["lle_X_scanf"] = lle_X_scanf; 483cf9b4f0f41242d8a7d4079ab9e6b163f54b621f1Chris Lattner FuncNames["lle_X_fprintf"] = lle_X_fprintf; 4844721f1304f3d49e44c78c9eed882a34ad7388be0Chris Lattner} 485