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