]>
git.proxmox.com Git - rustc.git/blob - src/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
1 //===-- ExternalFunctions.cpp - Implement External Functions --------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains both code to deal with invoking "external" functions, but
11 // also contains code that implements "exported" external functions.
13 // There are currently two mechanisms for handling external functions in the
14 // Interpreter. The first is to implement lle_* wrapper functions that are
15 // specific to well-known library functions which manually translate the
16 // arguments from GenericValues and make the call. If such a wrapper does
17 // not exist, and libffi is available, then the Interpreter will attempt to
18 // invoke the function using libffi, after finding its address.
20 //===----------------------------------------------------------------------===//
22 #include "Interpreter.h"
23 #include "llvm/Config/config.h" // Detect libffi
24 #include "llvm/IR/DataLayout.h"
25 #include "llvm/IR/DerivedTypes.h"
26 #include "llvm/IR/Module.h"
27 #include "llvm/Support/DynamicLibrary.h"
28 #include "llvm/Support/ErrorHandling.h"
29 #include "llvm/Support/ManagedStatic.h"
30 #include "llvm/Support/Mutex.h"
31 #include "llvm/Support/UniqueLock.h"
50 static ManagedStatic
<sys::Mutex
> FunctionsLock
;
52 typedef GenericValue (*ExFunc
)(FunctionType
*,
53 const std::vector
<GenericValue
> &);
54 static ManagedStatic
<std::map
<const Function
*, ExFunc
> > ExportedFunctions
;
55 static ManagedStatic
<std::map
<std::string
, ExFunc
> > FuncNames
;
58 typedef void (*RawFunc
)();
59 static ManagedStatic
<std::map
<const Function
*, RawFunc
> > RawFunctions
;
62 static Interpreter
*TheInterpreter
;
64 static char getTypeID(Type
*Ty
) {
65 switch (Ty
->getTypeID()) {
66 case Type::VoidTyID
: return 'V';
67 case Type::IntegerTyID
:
68 switch (cast
<IntegerType
>(Ty
)->getBitWidth()) {
76 case Type::FloatTyID
: return 'F';
77 case Type::DoubleTyID
: return 'D';
78 case Type::PointerTyID
: return 'P';
79 case Type::FunctionTyID
:return 'M';
80 case Type::StructTyID
: return 'T';
81 case Type::ArrayTyID
: return 'A';
86 // Try to find address of external function given a Function object.
87 // Please note, that interpreter doesn't know how to assemble a
88 // real call in general case (this is JIT job), that's why it assumes,
89 // that all external functions has the same (and pretty "general") signature.
90 // The typical example of such functions are "lle_X_" ones.
91 static ExFunc
lookupFunction(const Function
*F
) {
92 // Function not found, look it up... start by figuring out what the
93 // composite function name should be.
94 std::string ExtName
= "lle_";
95 FunctionType
*FT
= F
->getFunctionType();
96 for (unsigned i
= 0, e
= FT
->getNumContainedTypes(); i
!= e
; ++i
)
97 ExtName
+= getTypeID(FT
->getContainedType(i
));
98 ExtName
+= "_" + F
->getName().str();
100 sys::ScopedLock
Writer(*FunctionsLock
);
101 ExFunc FnPtr
= (*FuncNames
)[ExtName
];
103 FnPtr
= (*FuncNames
)["lle_X_" + F
->getName().str()];
104 if (!FnPtr
) // Try calling a generic function... if it exists...
105 FnPtr
= (ExFunc
)(intptr_t)
106 sys::DynamicLibrary::SearchForAddressOfSymbol("lle_X_" +
109 ExportedFunctions
->insert(std::make_pair(F
, FnPtr
)); // Cache for later
114 static ffi_type
*ffiTypeFor(Type
*Ty
) {
115 switch (Ty
->getTypeID()) {
116 case Type::VoidTyID
: return &ffi_type_void
;
117 case Type::IntegerTyID
:
118 switch (cast
<IntegerType
>(Ty
)->getBitWidth()) {
119 case 8: return &ffi_type_sint8
;
120 case 16: return &ffi_type_sint16
;
121 case 32: return &ffi_type_sint32
;
122 case 64: return &ffi_type_sint64
;
124 case Type::FloatTyID
: return &ffi_type_float
;
125 case Type::DoubleTyID
: return &ffi_type_double
;
126 case Type::PointerTyID
: return &ffi_type_pointer
;
129 // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
130 report_fatal_error("Type could not be mapped for use with libffi.");
134 static void *ffiValueFor(Type
*Ty
, const GenericValue
&AV
,
136 switch (Ty
->getTypeID()) {
137 case Type::IntegerTyID
:
138 switch (cast
<IntegerType
>(Ty
)->getBitWidth()) {
140 int8_t *I8Ptr
= (int8_t *) ArgDataPtr
;
141 *I8Ptr
= (int8_t) AV
.IntVal
.getZExtValue();
145 int16_t *I16Ptr
= (int16_t *) ArgDataPtr
;
146 *I16Ptr
= (int16_t) AV
.IntVal
.getZExtValue();
150 int32_t *I32Ptr
= (int32_t *) ArgDataPtr
;
151 *I32Ptr
= (int32_t) AV
.IntVal
.getZExtValue();
155 int64_t *I64Ptr
= (int64_t *) ArgDataPtr
;
156 *I64Ptr
= (int64_t) AV
.IntVal
.getZExtValue();
160 case Type::FloatTyID
: {
161 float *FloatPtr
= (float *) ArgDataPtr
;
162 *FloatPtr
= AV
.FloatVal
;
165 case Type::DoubleTyID
: {
166 double *DoublePtr
= (double *) ArgDataPtr
;
167 *DoublePtr
= AV
.DoubleVal
;
170 case Type::PointerTyID
: {
171 void **PtrPtr
= (void **) ArgDataPtr
;
177 // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
178 report_fatal_error("Type value could not be mapped for use with libffi.");
182 static bool ffiInvoke(RawFunc Fn
, Function
*F
,
183 const std::vector
<GenericValue
> &ArgVals
,
184 const DataLayout
*TD
, GenericValue
&Result
) {
186 FunctionType
*FTy
= F
->getFunctionType();
187 const unsigned NumArgs
= F
->arg_size();
189 // TODO: We don't have type information about the remaining arguments, because
190 // this information is never passed into ExecutionEngine::runFunction().
191 if (ArgVals
.size() > NumArgs
&& F
->isVarArg()) {
192 report_fatal_error("Calling external var arg function '" + F
->getName()
193 + "' is not supported by the Interpreter.");
196 unsigned ArgBytes
= 0;
198 std::vector
<ffi_type
*> args(NumArgs
);
199 for (Function::const_arg_iterator A
= F
->arg_begin(), E
= F
->arg_end();
201 const unsigned ArgNo
= A
->getArgNo();
202 Type
*ArgTy
= FTy
->getParamType(ArgNo
);
203 args
[ArgNo
] = ffiTypeFor(ArgTy
);
204 ArgBytes
+= TD
->getTypeStoreSize(ArgTy
);
207 SmallVector
<uint8_t, 128> ArgData
;
208 ArgData
.resize(ArgBytes
);
209 uint8_t *ArgDataPtr
= ArgData
.data();
210 SmallVector
<void*, 16> values(NumArgs
);
211 for (Function::const_arg_iterator A
= F
->arg_begin(), E
= F
->arg_end();
213 const unsigned ArgNo
= A
->getArgNo();
214 Type
*ArgTy
= FTy
->getParamType(ArgNo
);
215 values
[ArgNo
] = ffiValueFor(ArgTy
, ArgVals
[ArgNo
], ArgDataPtr
);
216 ArgDataPtr
+= TD
->getTypeStoreSize(ArgTy
);
219 Type
*RetTy
= FTy
->getReturnType();
220 ffi_type
*rtype
= ffiTypeFor(RetTy
);
222 if (ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, NumArgs
, rtype
, &args
[0]) == FFI_OK
) {
223 SmallVector
<uint8_t, 128> ret
;
224 if (RetTy
->getTypeID() != Type::VoidTyID
)
225 ret
.resize(TD
->getTypeStoreSize(RetTy
));
226 ffi_call(&cif
, Fn
, ret
.data(), values
.data());
227 switch (RetTy
->getTypeID()) {
228 case Type::IntegerTyID
:
229 switch (cast
<IntegerType
>(RetTy
)->getBitWidth()) {
230 case 8: Result
.IntVal
= APInt(8 , *(int8_t *) ret
.data()); break;
231 case 16: Result
.IntVal
= APInt(16, *(int16_t*) ret
.data()); break;
232 case 32: Result
.IntVal
= APInt(32, *(int32_t*) ret
.data()); break;
233 case 64: Result
.IntVal
= APInt(64, *(int64_t*) ret
.data()); break;
236 case Type::FloatTyID
: Result
.FloatVal
= *(float *) ret
.data(); break;
237 case Type::DoubleTyID
: Result
.DoubleVal
= *(double*) ret
.data(); break;
238 case Type::PointerTyID
: Result
.PointerVal
= *(void **) ret
.data(); break;
248 GenericValue
Interpreter::callExternalFunction(Function
*F
,
249 const std::vector
<GenericValue
> &ArgVals
) {
250 TheInterpreter
= this;
252 unique_lock
<sys::Mutex
> Guard(*FunctionsLock
);
254 // Do a lookup to see if the function is in our cache... this should just be a
255 // deferred annotation!
256 std::map
<const Function
*, ExFunc
>::iterator FI
= ExportedFunctions
->find(F
);
257 if (ExFunc Fn
= (FI
== ExportedFunctions
->end()) ? lookupFunction(F
)
260 return Fn(F
->getFunctionType(), ArgVals
);
264 std::map
<const Function
*, RawFunc
>::iterator RF
= RawFunctions
->find(F
);
266 if (RF
== RawFunctions
->end()) {
267 RawFn
= (RawFunc
)(intptr_t)
268 sys::DynamicLibrary::SearchForAddressOfSymbol(F
->getName());
270 RawFn
= (RawFunc
)(intptr_t)getPointerToGlobalIfAvailable(F
);
272 RawFunctions
->insert(std::make_pair(F
, RawFn
)); // Cache for later
280 if (RawFn
!= 0 && ffiInvoke(RawFn
, F
, ArgVals
, getDataLayout(), Result
))
284 if (F
->getName() == "__main")
285 errs() << "Tried to execute an unknown external function: "
286 << *F
->getType() << " __main\n";
288 report_fatal_error("Tried to execute an unknown external function: " +
291 errs() << "Recompiling LLVM with --enable-libffi might help.\n";
293 return GenericValue();
297 //===----------------------------------------------------------------------===//
298 // Functions "exported" to the running application...
301 // void atexit(Function*)
303 GenericValue
lle_X_atexit(FunctionType
*FT
,
304 const std::vector
<GenericValue
> &Args
) {
305 assert(Args
.size() == 1);
306 TheInterpreter
->addAtExitHandler((Function
*)GVTOP(Args
[0]));
314 GenericValue
lle_X_exit(FunctionType
*FT
,
315 const std::vector
<GenericValue
> &Args
) {
316 TheInterpreter
->exitCalled(Args
[0]);
317 return GenericValue();
322 GenericValue
lle_X_abort(FunctionType
*FT
,
323 const std::vector
<GenericValue
> &Args
) {
324 //FIXME: should we report or raise here?
325 //report_fatal_error("Interpreted program raised SIGABRT");
327 return GenericValue();
330 // int sprintf(char *, const char *, ...) - a very rough implementation to make
333 GenericValue
lle_X_sprintf(FunctionType
*FT
,
334 const std::vector
<GenericValue
> &Args
) {
335 char *OutputBuffer
= (char *)GVTOP(Args
[0]);
336 const char *FmtStr
= (const char *)GVTOP(Args
[1]);
339 // printf should return # chars printed. This is completely incorrect, but
340 // close enough for now.
342 GV
.IntVal
= APInt(32, strlen(FmtStr
));
345 case 0: return GV
; // Null terminator...
346 default: // Normal nonspecial character
347 sprintf(OutputBuffer
++, "%c", *FmtStr
++);
349 case '\\': { // Handle escape codes
350 sprintf(OutputBuffer
, "%c%c", *FmtStr
, *(FmtStr
+1));
351 FmtStr
+= 2; OutputBuffer
+= 2;
354 case '%': { // Handle format specifiers
355 char FmtBuf
[100] = "", Buffer
[1000] = "";
358 char Last
= *FB
++ = *FmtStr
++;
359 unsigned HowLong
= 0;
360 while (Last
!= 'c' && Last
!= 'd' && Last
!= 'i' && Last
!= 'u' &&
361 Last
!= 'o' && Last
!= 'x' && Last
!= 'X' && Last
!= 'e' &&
362 Last
!= 'E' && Last
!= 'g' && Last
!= 'G' && Last
!= 'f' &&
363 Last
!= 'p' && Last
!= 's' && Last
!= '%') {
364 if (Last
== 'l' || Last
== 'L') HowLong
++; // Keep track of l's
365 Last
= *FB
++ = *FmtStr
++;
371 memcpy(Buffer
, "%", 2); break;
373 sprintf(Buffer
, FmtBuf
, uint32_t(Args
[ArgNo
++].IntVal
.getZExtValue()));
380 TheInterpreter
->getDataLayout()->getPointerSizeInBits() == 64 &&
381 sizeof(long) < sizeof(int64_t)) {
382 // Make sure we use %lld with a 64 bit argument because we might be
383 // compiling LLI on a 32 bit compiler.
384 unsigned Size
= strlen(FmtBuf
);
385 FmtBuf
[Size
] = FmtBuf
[Size
-1];
387 FmtBuf
[Size
-1] = 'l';
389 sprintf(Buffer
, FmtBuf
, Args
[ArgNo
++].IntVal
.getZExtValue());
391 sprintf(Buffer
, FmtBuf
,uint32_t(Args
[ArgNo
++].IntVal
.getZExtValue()));
393 case 'e': case 'E': case 'g': case 'G': case 'f':
394 sprintf(Buffer
, FmtBuf
, Args
[ArgNo
++].DoubleVal
); break;
396 sprintf(Buffer
, FmtBuf
, (void*)GVTOP(Args
[ArgNo
++])); break;
398 sprintf(Buffer
, FmtBuf
, (char*)GVTOP(Args
[ArgNo
++])); break;
400 errs() << "<unknown printf code '" << *FmtStr
<< "'!>";
403 size_t Len
= strlen(Buffer
);
404 memcpy(OutputBuffer
, Buffer
, Len
+ 1);
413 // int printf(const char *, ...) - a very rough implementation to make output
416 GenericValue
lle_X_printf(FunctionType
*FT
,
417 const std::vector
<GenericValue
> &Args
) {
419 std::vector
<GenericValue
> NewArgs
;
420 NewArgs
.push_back(PTOGV((void*)&Buffer
[0]));
421 NewArgs
.insert(NewArgs
.end(), Args
.begin(), Args
.end());
422 GenericValue GV
= lle_X_sprintf(FT
, NewArgs
);
427 // int sscanf(const char *format, ...);
429 GenericValue
lle_X_sscanf(FunctionType
*FT
,
430 const std::vector
<GenericValue
> &args
) {
431 assert(args
.size() < 10 && "Only handle up to 10 args to sscanf right now!");
434 for (unsigned i
= 0; i
< args
.size(); ++i
)
435 Args
[i
] = (char*)GVTOP(args
[i
]);
438 GV
.IntVal
= APInt(32, sscanf(Args
[0], Args
[1], Args
[2], Args
[3], Args
[4],
439 Args
[5], Args
[6], Args
[7], Args
[8], Args
[9]));
443 // int scanf(const char *format, ...);
445 GenericValue
lle_X_scanf(FunctionType
*FT
,
446 const std::vector
<GenericValue
> &args
) {
447 assert(args
.size() < 10 && "Only handle up to 10 args to scanf right now!");
450 for (unsigned i
= 0; i
< args
.size(); ++i
)
451 Args
[i
] = (char*)GVTOP(args
[i
]);
454 GV
.IntVal
= APInt(32, scanf( Args
[0], Args
[1], Args
[2], Args
[3], Args
[4],
455 Args
[5], Args
[6], Args
[7], Args
[8], Args
[9]));
459 // int fprintf(FILE *, const char *, ...) - a very rough implementation to make
462 GenericValue
lle_X_fprintf(FunctionType
*FT
,
463 const std::vector
<GenericValue
> &Args
) {
464 assert(Args
.size() >= 2);
466 std::vector
<GenericValue
> NewArgs
;
467 NewArgs
.push_back(PTOGV(Buffer
));
468 NewArgs
.insert(NewArgs
.end(), Args
.begin()+1, Args
.end());
469 GenericValue GV
= lle_X_sprintf(FT
, NewArgs
);
471 fputs(Buffer
, (FILE *) GVTOP(Args
[0]));
475 static GenericValue
lle_X_memset(FunctionType
*FT
,
476 const std::vector
<GenericValue
> &Args
) {
477 int val
= (int)Args
[1].IntVal
.getSExtValue();
478 size_t len
= (size_t)Args
[2].IntVal
.getZExtValue();
479 memset((void *)GVTOP(Args
[0]), val
, len
);
480 // llvm.memset.* returns void, lle_X_* returns GenericValue,
481 // so here we return GenericValue with IntVal set to zero
487 static GenericValue
lle_X_memcpy(FunctionType
*FT
,
488 const std::vector
<GenericValue
> &Args
) {
489 memcpy(GVTOP(Args
[0]), GVTOP(Args
[1]),
490 (size_t)(Args
[2].IntVal
.getLimitedValue()));
492 // llvm.memcpy* returns void, lle_X_* returns GenericValue,
493 // so here we return GenericValue with IntVal set to zero
499 void Interpreter::initializeExternalFunctions() {
500 sys::ScopedLock
Writer(*FunctionsLock
);
501 (*FuncNames
)["lle_X_atexit"] = lle_X_atexit
;
502 (*FuncNames
)["lle_X_exit"] = lle_X_exit
;
503 (*FuncNames
)["lle_X_abort"] = lle_X_abort
;
505 (*FuncNames
)["lle_X_printf"] = lle_X_printf
;
506 (*FuncNames
)["lle_X_sprintf"] = lle_X_sprintf
;
507 (*FuncNames
)["lle_X_sscanf"] = lle_X_sscanf
;
508 (*FuncNames
)["lle_X_scanf"] = lle_X_scanf
;
509 (*FuncNames
)["lle_X_fprintf"] = lle_X_fprintf
;
510 (*FuncNames
)["lle_X_memset"] = lle_X_memset
;
511 (*FuncNames
)["lle_X_memcpy"] = lle_X_memcpy
;