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