LLVM  8.0.1
ExternalFunctions.cpp
Go to the documentation of this file.
1 //===-- ExternalFunctions.cpp - Implement External Functions --------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains both code to deal with invoking "external" functions, but
11 // also contains code that implements "exported" external functions.
12 //
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.
19 //
20 //===----------------------------------------------------------------------===//
21 
22 #include "Interpreter.h"
23 #include "llvm/ADT/APInt.h"
24 #include "llvm/ADT/ArrayRef.h"
25 #include "llvm/Config/config.h" // Detect libffi
27 #include "llvm/IR/DataLayout.h"
28 #include "llvm/IR/DerivedTypes.h"
29 #include "llvm/IR/Function.h"
30 #include "llvm/IR/Type.h"
31 #include "llvm/Support/Casting.h"
35 #include "llvm/Support/Mutex.h"
38 #include <cassert>
39 #include <cmath>
40 #include <csignal>
41 #include <cstdint>
42 #include <cstdio>
43 #include <cstring>
44 #include <map>
45 #include <string>
46 #include <utility>
47 #include <vector>
48 
49 #ifdef HAVE_FFI_CALL
50 #ifdef HAVE_FFI_H
51 #include <ffi.h>
52 #define USE_LIBFFI
53 #elif HAVE_FFI_FFI_H
54 #include <ffi/ffi.h>
55 #define USE_LIBFFI
56 #endif
57 #endif
58 
59 using namespace llvm;
60 
62 
66 
67 #ifdef USE_LIBFFI
68 typedef void (*RawFunc)();
70 #endif
71 
73 
74 static char getTypeID(Type *Ty) {
75  switch (Ty->getTypeID()) {
76  case Type::VoidTyID: return 'V';
77  case Type::IntegerTyID:
78  switch (cast<IntegerType>(Ty)->getBitWidth()) {
79  case 1: return 'o';
80  case 8: return 'B';
81  case 16: return 'S';
82  case 32: return 'I';
83  case 64: return 'L';
84  default: return 'N';
85  }
86  case Type::FloatTyID: return 'F';
87  case Type::DoubleTyID: return 'D';
88  case Type::PointerTyID: return 'P';
89  case Type::FunctionTyID:return 'M';
90  case Type::StructTyID: return 'T';
91  case Type::ArrayTyID: return 'A';
92  default: return 'U';
93  }
94 }
95 
96 // Try to find address of external function given a Function object.
97 // Please note, that interpreter doesn't know how to assemble a
98 // real call in general case (this is JIT job), that's why it assumes,
99 // that all external functions has the same (and pretty "general") signature.
100 // The typical example of such functions are "lle_X_" ones.
101 static ExFunc lookupFunction(const Function *F) {
102  // Function not found, look it up... start by figuring out what the
103  // composite function name should be.
104  std::string ExtName = "lle_";
105  FunctionType *FT = F->getFunctionType();
106  ExtName += getTypeID(FT->getReturnType());
107  for (Type *T : FT->params())
108  ExtName += getTypeID(T);
109  ExtName += ("_" + F->getName()).str();
110 
111  sys::ScopedLock Writer(*FunctionsLock);
112  ExFunc FnPtr = (*FuncNames)[ExtName];
113  if (!FnPtr)
114  FnPtr = (*FuncNames)[("lle_X_" + F->getName()).str()];
115  if (!FnPtr) // Try calling a generic function... if it exists...
117  ("lle_X_" + F->getName()).str());
118  if (FnPtr)
119  ExportedFunctions->insert(std::make_pair(F, FnPtr)); // Cache for later
120  return FnPtr;
121 }
122 
123 #ifdef USE_LIBFFI
124 static ffi_type *ffiTypeFor(Type *Ty) {
125  switch (Ty->getTypeID()) {
126  case Type::VoidTyID: return &ffi_type_void;
127  case Type::IntegerTyID:
128  switch (cast<IntegerType>(Ty)->getBitWidth()) {
129  case 8: return &ffi_type_sint8;
130  case 16: return &ffi_type_sint16;
131  case 32: return &ffi_type_sint32;
132  case 64: return &ffi_type_sint64;
133  }
134  case Type::FloatTyID: return &ffi_type_float;
135  case Type::DoubleTyID: return &ffi_type_double;
136  case Type::PointerTyID: return &ffi_type_pointer;
137  default: break;
138  }
139  // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
140  report_fatal_error("Type could not be mapped for use with libffi.");
141  return NULL;
142 }
143 
144 static void *ffiValueFor(Type *Ty, const GenericValue &AV,
145  void *ArgDataPtr) {
146  switch (Ty->getTypeID()) {
147  case Type::IntegerTyID:
148  switch (cast<IntegerType>(Ty)->getBitWidth()) {
149  case 8: {
150  int8_t *I8Ptr = (int8_t *) ArgDataPtr;
151  *I8Ptr = (int8_t) AV.IntVal.getZExtValue();
152  return ArgDataPtr;
153  }
154  case 16: {
155  int16_t *I16Ptr = (int16_t *) ArgDataPtr;
156  *I16Ptr = (int16_t) AV.IntVal.getZExtValue();
157  return ArgDataPtr;
158  }
159  case 32: {
160  int32_t *I32Ptr = (int32_t *) ArgDataPtr;
161  *I32Ptr = (int32_t) AV.IntVal.getZExtValue();
162  return ArgDataPtr;
163  }
164  case 64: {
165  int64_t *I64Ptr = (int64_t *) ArgDataPtr;
166  *I64Ptr = (int64_t) AV.IntVal.getZExtValue();
167  return ArgDataPtr;
168  }
169  }
170  case Type::FloatTyID: {
171  float *FloatPtr = (float *) ArgDataPtr;
172  *FloatPtr = AV.FloatVal;
173  return ArgDataPtr;
174  }
175  case Type::DoubleTyID: {
176  double *DoublePtr = (double *) ArgDataPtr;
177  *DoublePtr = AV.DoubleVal;
178  return ArgDataPtr;
179  }
180  case Type::PointerTyID: {
181  void **PtrPtr = (void **) ArgDataPtr;
182  *PtrPtr = GVTOP(AV);
183  return ArgDataPtr;
184  }
185  default: break;
186  }
187  // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
188  report_fatal_error("Type value could not be mapped for use with libffi.");
189  return NULL;
190 }
191 
192 static bool ffiInvoke(RawFunc Fn, Function *F, ArrayRef<GenericValue> ArgVals,
193  const DataLayout &TD, GenericValue &Result) {
194  ffi_cif cif;
195  FunctionType *FTy = F->getFunctionType();
196  const unsigned NumArgs = F->arg_size();
197 
198  // TODO: We don't have type information about the remaining arguments, because
199  // this information is never passed into ExecutionEngine::runFunction().
200  if (ArgVals.size() > NumArgs && F->isVarArg()) {
201  report_fatal_error("Calling external var arg function '" + F->getName()
202  + "' is not supported by the Interpreter.");
203  }
204 
205  unsigned ArgBytes = 0;
206 
207  std::vector<ffi_type*> args(NumArgs);
208  for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
209  A != E; ++A) {
210  const unsigned ArgNo = A->getArgNo();
211  Type *ArgTy = FTy->getParamType(ArgNo);
212  args[ArgNo] = ffiTypeFor(ArgTy);
213  ArgBytes += TD.getTypeStoreSize(ArgTy);
214  }
215 
217  ArgData.resize(ArgBytes);
218  uint8_t *ArgDataPtr = ArgData.data();
220  for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
221  A != E; ++A) {
222  const unsigned ArgNo = A->getArgNo();
223  Type *ArgTy = FTy->getParamType(ArgNo);
224  values[ArgNo] = ffiValueFor(ArgTy, ArgVals[ArgNo], ArgDataPtr);
225  ArgDataPtr += TD.getTypeStoreSize(ArgTy);
226  }
227 
228  Type *RetTy = FTy->getReturnType();
229  ffi_type *rtype = ffiTypeFor(RetTy);
230 
231  if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, args.data()) ==
232  FFI_OK) {
234  if (RetTy->getTypeID() != Type::VoidTyID)
235  ret.resize(TD.getTypeStoreSize(RetTy));
236  ffi_call(&cif, Fn, ret.data(), values.data());
237  switch (RetTy->getTypeID()) {
238  case Type::IntegerTyID:
239  switch (cast<IntegerType>(RetTy)->getBitWidth()) {
240  case 8: Result.IntVal = APInt(8 , *(int8_t *) ret.data()); break;
241  case 16: Result.IntVal = APInt(16, *(int16_t*) ret.data()); break;
242  case 32: Result.IntVal = APInt(32, *(int32_t*) ret.data()); break;
243  case 64: Result.IntVal = APInt(64, *(int64_t*) ret.data()); break;
244  }
245  break;
246  case Type::FloatTyID: Result.FloatVal = *(float *) ret.data(); break;
247  case Type::DoubleTyID: Result.DoubleVal = *(double*) ret.data(); break;
248  case Type::PointerTyID: Result.PointerVal = *(void **) ret.data(); break;
249  default: break;
250  }
251  return true;
252  }
253 
254  return false;
255 }
256 #endif // USE_LIBFFI
257 
259  ArrayRef<GenericValue> ArgVals) {
260  TheInterpreter = this;
261 
262  unique_lock<sys::Mutex> Guard(*FunctionsLock);
263 
264  // Do a lookup to see if the function is in our cache... this should just be a
265  // deferred annotation!
266  std::map<const Function *, ExFunc>::iterator FI = ExportedFunctions->find(F);
267  if (ExFunc Fn = (FI == ExportedFunctions->end()) ? lookupFunction(F)
268  : FI->second) {
269  Guard.unlock();
270  return Fn(F->getFunctionType(), ArgVals);
271  }
272 
273 #ifdef USE_LIBFFI
274  std::map<const Function *, RawFunc>::iterator RF = RawFunctions->find(F);
275  RawFunc RawFn;
276  if (RF == RawFunctions->end()) {
277  RawFn = (RawFunc)(intptr_t)
279  if (!RawFn)
280  RawFn = (RawFunc)(intptr_t)getPointerToGlobalIfAvailable(F);
281  if (RawFn != 0)
282  RawFunctions->insert(std::make_pair(F, RawFn)); // Cache for later
283  } else {
284  RawFn = RF->second;
285  }
286 
287  Guard.unlock();
288 
289  GenericValue Result;
290  if (RawFn != 0 && ffiInvoke(RawFn, F, ArgVals, getDataLayout(), Result))
291  return Result;
292 #endif // USE_LIBFFI
293 
294  if (F->getName() == "__main")
295  errs() << "Tried to execute an unknown external function: "
296  << *F->getType() << " __main\n";
297  else
298  report_fatal_error("Tried to execute an unknown external function: " +
299  F->getName());
300 #ifndef USE_LIBFFI
301  errs() << "Recompiling LLVM with --enable-libffi might help.\n";
302 #endif
303  return GenericValue();
304 }
305 
306 //===----------------------------------------------------------------------===//
307 // Functions "exported" to the running application...
308 //
309 
310 // void atexit(Function*)
313  assert(Args.size() == 1);
314  TheInterpreter->addAtExitHandler((Function*)GVTOP(Args[0]));
315  GenericValue GV;
316  GV.IntVal = 0;
317  return GV;
318 }
319 
320 // void exit(int)
322  TheInterpreter->exitCalled(Args[0]);
323  return GenericValue();
324 }
325 
326 // void abort(void)
328  //FIXME: should we report or raise here?
329  //report_fatal_error("Interpreted program raised SIGABRT");
330  raise (SIGABRT);
331  return GenericValue();
332 }
333 
334 // int sprintf(char *, const char *, ...) - a very rough implementation to make
335 // output useful.
338  char *OutputBuffer = (char *)GVTOP(Args[0]);
339  const char *FmtStr = (const char *)GVTOP(Args[1]);
340  unsigned ArgNo = 2;
341 
342  // printf should return # chars printed. This is completely incorrect, but
343  // close enough for now.
344  GenericValue GV;
345  GV.IntVal = APInt(32, strlen(FmtStr));
346  while (true) {
347  switch (*FmtStr) {
348  case 0: return GV; // Null terminator...
349  default: // Normal nonspecial character
350  sprintf(OutputBuffer++, "%c", *FmtStr++);
351  break;
352  case '\\': { // Handle escape codes
353  sprintf(OutputBuffer, "%c%c", *FmtStr, *(FmtStr+1));
354  FmtStr += 2; OutputBuffer += 2;
355  break;
356  }
357  case '%': { // Handle format specifiers
358  char FmtBuf[100] = "", Buffer[1000] = "";
359  char *FB = FmtBuf;
360  *FB++ = *FmtStr++;
361  char Last = *FB++ = *FmtStr++;
362  unsigned HowLong = 0;
363  while (Last != 'c' && Last != 'd' && Last != 'i' && Last != 'u' &&
364  Last != 'o' && Last != 'x' && Last != 'X' && Last != 'e' &&
365  Last != 'E' && Last != 'g' && Last != 'G' && Last != 'f' &&
366  Last != 'p' && Last != 's' && Last != '%') {
367  if (Last == 'l' || Last == 'L') HowLong++; // Keep track of l's
368  Last = *FB++ = *FmtStr++;
369  }
370  *FB = 0;
371 
372  switch (Last) {
373  case '%':
374  memcpy(Buffer, "%", 2); break;
375  case 'c':
376  sprintf(Buffer, FmtBuf, uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
377  break;
378  case 'd': case 'i':
379  case 'u': case 'o':
380  case 'x': case 'X':
381  if (HowLong >= 1) {
382  if (HowLong == 1 &&
383  TheInterpreter->getDataLayout().getPointerSizeInBits() == 64 &&
384  sizeof(long) < sizeof(int64_t)) {
385  // Make sure we use %lld with a 64 bit argument because we might be
386  // compiling LLI on a 32 bit compiler.
387  unsigned Size = strlen(FmtBuf);
388  FmtBuf[Size] = FmtBuf[Size-1];
389  FmtBuf[Size+1] = 0;
390  FmtBuf[Size-1] = 'l';
391  }
392  sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal.getZExtValue());
393  } else
394  sprintf(Buffer, FmtBuf,uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
395  break;
396  case 'e': case 'E': case 'g': case 'G': case 'f':
397  sprintf(Buffer, FmtBuf, Args[ArgNo++].DoubleVal); break;
398  case 'p':
399  sprintf(Buffer, FmtBuf, (void*)GVTOP(Args[ArgNo++])); break;
400  case 's':
401  sprintf(Buffer, FmtBuf, (char*)GVTOP(Args[ArgNo++])); break;
402  default:
403  errs() << "<unknown printf code '" << *FmtStr << "'!>";
404  ArgNo++; break;
405  }
406  size_t Len = strlen(Buffer);
407  memcpy(OutputBuffer, Buffer, Len + 1);
408  OutputBuffer += Len;
409  }
410  break;
411  }
412  }
413  return GV;
414 }
415 
416 // int printf(const char *, ...) - a very rough implementation to make output
417 // useful.
420  char Buffer[10000];
421  std::vector<GenericValue> NewArgs;
422  NewArgs.push_back(PTOGV((void*)&Buffer[0]));
423  NewArgs.insert(NewArgs.end(), Args.begin(), Args.end());
424  GenericValue GV = lle_X_sprintf(FT, NewArgs);
425  outs() << Buffer;
426  return GV;
427 }
428 
429 // int sscanf(const char *format, ...);
431  ArrayRef<GenericValue> args) {
432  assert(args.size() < 10 && "Only handle up to 10 args to sscanf right now!");
433 
434  char *Args[10];
435  for (unsigned i = 0; i < args.size(); ++i)
436  Args[i] = (char*)GVTOP(args[i]);
437 
438  GenericValue GV;
439  GV.IntVal = APInt(32, sscanf(Args[0], Args[1], Args[2], Args[3], Args[4],
440  Args[5], Args[6], Args[7], Args[8], Args[9]));
441  return GV;
442 }
443 
444 // int scanf(const char *format, ...);
446  assert(args.size() < 10 && "Only handle up to 10 args to scanf right now!");
447 
448  char *Args[10];
449  for (unsigned i = 0; i < args.size(); ++i)
450  Args[i] = (char*)GVTOP(args[i]);
451 
452  GenericValue GV;
453  GV.IntVal = APInt(32, scanf( Args[0], Args[1], Args[2], Args[3], Args[4],
454  Args[5], Args[6], Args[7], Args[8], Args[9]));
455  return GV;
456 }
457 
458 // int fprintf(FILE *, const char *, ...) - a very rough implementation to make
459 // output useful.
462  assert(Args.size() >= 2);
463  char Buffer[10000];
464  std::vector<GenericValue> NewArgs;
465  NewArgs.push_back(PTOGV(Buffer));
466  NewArgs.insert(NewArgs.end(), Args.begin()+1, Args.end());
467  GenericValue GV = lle_X_sprintf(FT, NewArgs);
468 
469  fputs(Buffer, (FILE *) GVTOP(Args[0]));
470  return GV;
471 }
472 
475  int val = (int)Args[1].IntVal.getSExtValue();
476  size_t len = (size_t)Args[2].IntVal.getZExtValue();
477  memset((void *)GVTOP(Args[0]), val, len);
478  // llvm.memset.* returns void, lle_X_* returns GenericValue,
479  // so here we return GenericValue with IntVal set to zero
480  GenericValue GV;
481  GV.IntVal = 0;
482  return GV;
483 }
484 
487  memcpy(GVTOP(Args[0]), GVTOP(Args[1]),
488  (size_t)(Args[2].IntVal.getLimitedValue()));
489 
490  // llvm.memcpy* returns void, lle_X_* returns GenericValue,
491  // so here we return GenericValue with IntVal set to zero
492  GenericValue GV;
493  GV.IntVal = 0;
494  return GV;
495 }
496 
497 void Interpreter::initializeExternalFunctions() {
498  sys::ScopedLock Writer(*FunctionsLock);
499  (*FuncNames)["lle_X_atexit"] = lle_X_atexit;
500  (*FuncNames)["lle_X_exit"] = lle_X_exit;
501  (*FuncNames)["lle_X_abort"] = lle_X_abort;
502 
503  (*FuncNames)["lle_X_printf"] = lle_X_printf;
504  (*FuncNames)["lle_X_sprintf"] = lle_X_sprintf;
505  (*FuncNames)["lle_X_sscanf"] = lle_X_sscanf;
506  (*FuncNames)["lle_X_scanf"] = lle_X_scanf;
507  (*FuncNames)["lle_X_fprintf"] = lle_X_fprintf;
508  (*FuncNames)["lle_X_memset"] = lle_X_memset;
509  (*FuncNames)["lle_X_memcpy"] = lle_X_memcpy;
510 }
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
Definition: Function.h:177
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:111
PointerTy PointerVal
Definition: GenericValue.h:32
static void * SearchForAddressOfSymbol(const char *symbolName)
This function will search through all previously loaded dynamic libraries for the symbol symbolName...
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1563
This class represents an incoming formal argument to a Function.
Definition: Argument.h:30
static Interpreter * TheInterpreter
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
This class represents lattice values for constants.
Definition: AllocatorList.h:24
Type * getParamType(unsigned i) const
Parameter type accessors.
Definition: DerivedTypes.h:135
static GenericValue lle_X_atexit(FunctionType *FT, ArrayRef< GenericValue > Args)
iterator begin() const
Definition: ArrayRef.h:137
2: 32-bit floating point type
Definition: Type.h:59
void * getPointerToGlobalIfAvailable(StringRef S)
getPointerToGlobalIfAvailable - This returns the address of the specified global value if it is has a...
static GenericValue lle_X_exit(FunctionType *FT, ArrayRef< GenericValue > Args)
arg_iterator arg_end()
Definition: Function.h:680
unsigned getPointerSizeInBits(unsigned AS=0) const
Layout pointer size, in bits FIXME: The defaults need to be removed once all of the backends/clients ...
Definition: DataLayout.h:363
13: Structures
Definition: Type.h:73
F(f)
const DataLayout & getDataLayout() const
static GenericValue lle_X_sprintf(FunctionType *FT, ArrayRef< GenericValue > Args)
15: Pointers
Definition: Type.h:75
12: Functions
Definition: Type.h:72
static ExFunc lookupFunction(const Function *F)
TypeID getTypeID() const
Return the type id for the type.
Definition: Type.h:138
static GenericValue lle_X_sscanf(FunctionType *FT, ArrayRef< GenericValue > args)
This file implements a class to represent arbitrary precision integral constant values and operations...
Class to represent function types.
Definition: DerivedTypes.h:103
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
11: Arbitrary bit width integers
Definition: Type.h:71
raw_ostream & outs()
This returns a reference to a raw_ostream for standard output.
0: type with no size
Definition: Type.h:57
static ManagedStatic< sys::Mutex > FunctionsLock
static GenericValue lle_X_memcpy(FunctionType *FT, ArrayRef< GenericValue > Args)
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
static ManagedStatic< std::map< const Function *, ExFunc > > ExportedFunctions
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:149
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
Definition: CommandLine.h:643
static ManagedStatic< std::map< std::string, ExFunc > > FuncNames
GenericValue(* ExFunc)(FunctionType *, ArrayRef< GenericValue >)
ArrayRef< Type * > params() const
Definition: DerivedTypes.h:130
A pared-down imitation of std::unique_lock from C++11.
Definition: UniqueLock.h:29
void exitCalled(GenericValue GV)
Definition: Execution.cpp:820
size_t arg_size() const
Definition: Function.h:698
arg_iterator arg_begin()
Definition: Function.h:671
static GenericValue lle_X_abort(FunctionType *FT, ArrayRef< GenericValue > Args)
void * GVTOP(const GenericValue &GV)
Definition: GenericValue.h:51
14: Arrays
Definition: Type.h:74
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
iterator end() const
Definition: ArrayRef.h:138
Type * getReturnType() const
Definition: DerivedTypes.h:124
static GenericValue lle_X_fprintf(FunctionType *FT, ArrayRef< GenericValue > Args)
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition: Function.h:164
GenericValue PTOGV(void *P)
Definition: GenericValue.h:50
Class for arbitrary precision integers.
Definition: APInt.h:70
static char getTypeID(Type *Ty)
pointer data()
Return a pointer to the vector&#39;s buffer, even if empty().
Definition: SmallVector.h:149
StringRef getName() const
Return a constant reference to the value&#39;s name.
Definition: Value.cpp:214
uint32_t Size
Definition: Profile.cpp:47
3: 64-bit floating point type
Definition: Type.h:60
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static GenericValue lle_X_memset(FunctionType *FT, ArrayRef< GenericValue > Args)
static GenericValue lle_X_printf(FunctionType *FT, ArrayRef< GenericValue > Args)
uint64_t getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type...
Definition: DataLayout.h:419
void addAtExitHandler(Function *F)
Definition: Interpreter.h:179
GenericValue callExternalFunction(Function *F, ArrayRef< GenericValue > ArgVals)
static GenericValue lle_X_scanf(FunctionType *FT, ArrayRef< GenericValue > args)
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:61
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:274
void resize(size_type N)
Definition: SmallVector.h:351