LLVM  14.0.0git
ExternalFunctions.cpp
Go to the documentation of this file.
1 //===-- ExternalFunctions.cpp - Implement External Functions --------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains both code to deal with invoking "external" functions, but
10 // also contains code that implements "exported" external functions.
11 //
12 // There are currently two mechanisms for handling external functions in the
13 // Interpreter. The first is to implement lle_* wrapper functions that are
14 // specific to well-known library functions which manually translate the
15 // arguments from GenericValues and make the call. If such a wrapper does
16 // not exist, and libffi is available, then the Interpreter will attempt to
17 // invoke the function using libffi, after finding its address.
18 //
19 //===----------------------------------------------------------------------===//
20 
21 #include "Interpreter.h"
22 #include "llvm/ADT/APInt.h"
23 #include "llvm/ADT/ArrayRef.h"
24 #include "llvm/Config/config.h" // Detect libffi
26 #include "llvm/IR/DataLayout.h"
27 #include "llvm/IR/DerivedTypes.h"
28 #include "llvm/IR/Function.h"
29 #include "llvm/IR/Type.h"
30 #include "llvm/Support/Casting.h"
34 #include "llvm/Support/Mutex.h"
36 #include <cassert>
37 #include <cmath>
38 #include <csignal>
39 #include <cstdint>
40 #include <cstdio>
41 #include <cstring>
42 #include <map>
43 #include <mutex>
44 #include <string>
45 #include <utility>
46 #include <vector>
47 
48 #ifdef HAVE_FFI_CALL
49 #ifdef HAVE_FFI_H
50 #include <ffi.h>
51 #define USE_LIBFFI
52 #elif HAVE_FFI_FFI_H
53 #include <ffi/ffi.h>
54 #define USE_LIBFFI
55 #endif
56 #endif
57 
58 using namespace llvm;
59 
61 
65 
66 #ifdef USE_LIBFFI
67 typedef void (*RawFunc)();
69 #endif
70 
72 
73 static char getTypeID(Type *Ty) {
74  switch (Ty->getTypeID()) {
75  case Type::VoidTyID: return 'V';
76  case Type::IntegerTyID:
77  switch (cast<IntegerType>(Ty)->getBitWidth()) {
78  case 1: return 'o';
79  case 8: return 'B';
80  case 16: return 'S';
81  case 32: return 'I';
82  case 64: return 'L';
83  default: return 'N';
84  }
85  case Type::FloatTyID: return 'F';
86  case Type::DoubleTyID: return 'D';
87  case Type::PointerTyID: return 'P';
88  case Type::FunctionTyID:return 'M';
89  case Type::StructTyID: return 'T';
90  case Type::ArrayTyID: return 'A';
91  default: return 'U';
92  }
93 }
94 
95 // Try to find address of external function given a Function object.
96 // Please note, that interpreter doesn't know how to assemble a
97 // real call in general case (this is JIT job), that's why it assumes,
98 // that all external functions has the same (and pretty "general") signature.
99 // The typical example of such functions are "lle_X_" ones.
100 static ExFunc lookupFunction(const Function *F) {
101  // Function not found, look it up... start by figuring out what the
102  // composite function name should be.
103  std::string ExtName = "lle_";
104  FunctionType *FT = F->getFunctionType();
105  ExtName += getTypeID(FT->getReturnType());
106  for (Type *T : FT->params())
107  ExtName += getTypeID(T);
108  ExtName += ("_" + F->getName()).str();
109 
111  ExFunc FnPtr = (*FuncNames)[ExtName];
112  if (!FnPtr)
113  FnPtr = (*FuncNames)[("lle_X_" + F->getName()).str()];
114  if (!FnPtr) // Try calling a generic function... if it exists...
116  ("lle_X_" + F->getName()).str());
117  if (FnPtr)
118  ExportedFunctions->insert(std::make_pair(F, FnPtr)); // Cache for later
119  return FnPtr;
120 }
121 
122 #ifdef USE_LIBFFI
123 static ffi_type *ffiTypeFor(Type *Ty) {
124  switch (Ty->getTypeID()) {
125  case Type::VoidTyID: return &ffi_type_void;
126  case Type::IntegerTyID:
127  switch (cast<IntegerType>(Ty)->getBitWidth()) {
128  case 8: return &ffi_type_sint8;
129  case 16: return &ffi_type_sint16;
130  case 32: return &ffi_type_sint32;
131  case 64: return &ffi_type_sint64;
132  }
133  llvm_unreachable("Unhandled integer type bitwidth");
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  llvm_unreachable("Unhandled integer type bitwidth");
171  case Type::FloatTyID: {
172  float *FloatPtr = (float *) ArgDataPtr;
173  *FloatPtr = AV.FloatVal;
174  return ArgDataPtr;
175  }
176  case Type::DoubleTyID: {
177  double *DoublePtr = (double *) ArgDataPtr;
178  *DoublePtr = AV.DoubleVal;
179  return ArgDataPtr;
180  }
181  case Type::PointerTyID: {
182  void **PtrPtr = (void **) ArgDataPtr;
183  *PtrPtr = GVTOP(AV);
184  return ArgDataPtr;
185  }
186  default: break;
187  }
188  // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
189  report_fatal_error("Type value could not be mapped for use with libffi.");
190  return NULL;
191 }
192 
193 static bool ffiInvoke(RawFunc Fn, Function *F, ArrayRef<GenericValue> ArgVals,
194  const DataLayout &TD, GenericValue &Result) {
195  ffi_cif cif;
196  FunctionType *FTy = F->getFunctionType();
197  const unsigned NumArgs = F->arg_size();
198 
199  // TODO: We don't have type information about the remaining arguments, because
200  // this information is never passed into ExecutionEngine::runFunction().
201  if (ArgVals.size() > NumArgs && F->isVarArg()) {
202  report_fatal_error("Calling external var arg function '" + F->getName()
203  + "' is not supported by the Interpreter.");
204  }
205 
206  unsigned ArgBytes = 0;
207 
208  std::vector<ffi_type*> args(NumArgs);
209  for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
210  A != E; ++A) {
211  const unsigned ArgNo = A->getArgNo();
212  Type *ArgTy = FTy->getParamType(ArgNo);
213  args[ArgNo] = ffiTypeFor(ArgTy);
214  ArgBytes += TD.getTypeStoreSize(ArgTy);
215  }
216 
218  ArgData.resize(ArgBytes);
219  uint8_t *ArgDataPtr = ArgData.data();
221  for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
222  A != E; ++A) {
223  const unsigned ArgNo = A->getArgNo();
224  Type *ArgTy = FTy->getParamType(ArgNo);
225  values[ArgNo] = ffiValueFor(ArgTy, ArgVals[ArgNo], ArgDataPtr);
226  ArgDataPtr += TD.getTypeStoreSize(ArgTy);
227  }
228 
229  Type *RetTy = FTy->getReturnType();
230  ffi_type *rtype = ffiTypeFor(RetTy);
231 
232  if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, args.data()) ==
233  FFI_OK) {
235  if (RetTy->getTypeID() != Type::VoidTyID)
236  ret.resize(TD.getTypeStoreSize(RetTy));
237  ffi_call(&cif, Fn, ret.data(), values.data());
238  switch (RetTy->getTypeID()) {
239  case Type::IntegerTyID:
240  switch (cast<IntegerType>(RetTy)->getBitWidth()) {
241  case 8: Result.IntVal = APInt(8 , *(int8_t *) ret.data()); break;
242  case 16: Result.IntVal = APInt(16, *(int16_t*) ret.data()); break;
243  case 32: Result.IntVal = APInt(32, *(int32_t*) ret.data()); break;
244  case 64: Result.IntVal = APInt(64, *(int64_t*) ret.data()); break;
245  }
246  break;
247  case Type::FloatTyID: Result.FloatVal = *(float *) ret.data(); break;
248  case Type::DoubleTyID: Result.DoubleVal = *(double*) ret.data(); break;
249  case Type::PointerTyID: Result.PointerVal = *(void **) ret.data(); break;
250  default: break;
251  }
252  return true;
253  }
254 
255  return false;
256 }
257 #endif // USE_LIBFFI
258 
260  ArrayRef<GenericValue> ArgVals) {
261  TheInterpreter = this;
262 
263  std::unique_lock<sys::Mutex> Guard(*FunctionsLock);
264 
265  // Do a lookup to see if the function is in our cache... this should just be a
266  // deferred annotation!
267  std::map<const Function *, ExFunc>::iterator FI = ExportedFunctions->find(F);
268  if (ExFunc Fn = (FI == ExportedFunctions->end()) ? lookupFunction(F)
269  : FI->second) {
270  Guard.unlock();
271  return Fn(F->getFunctionType(), ArgVals);
272  }
273 
274 #ifdef USE_LIBFFI
275  std::map<const Function *, RawFunc>::iterator RF = RawFunctions->find(F);
276  RawFunc RawFn;
277  if (RF == RawFunctions->end()) {
278  RawFn = (RawFunc)(intptr_t)
279  sys::DynamicLibrary::SearchForAddressOfSymbol(std::string(F->getName()));
280  if (!RawFn)
281  RawFn = (RawFunc)(intptr_t)getPointerToGlobalIfAvailable(F);
282  if (RawFn != 0)
283  RawFunctions->insert(std::make_pair(F, RawFn)); // Cache for later
284  } else {
285  RawFn = RF->second;
286  }
287 
288  Guard.unlock();
289 
290  GenericValue Result;
291  if (RawFn != 0 && ffiInvoke(RawFn, F, ArgVals, getDataLayout(), Result))
292  return Result;
293 #endif // USE_LIBFFI
294 
295  if (F->getName() == "__main")
296  errs() << "Tried to execute an unknown external function: "
297  << *F->getType() << " __main\n";
298  else
299  report_fatal_error("Tried to execute an unknown external function: " +
300  F->getName());
301 #ifndef USE_LIBFFI
302  errs() << "Recompiling LLVM with --enable-libffi might help.\n";
303 #endif
304  return GenericValue();
305 }
306 
307 //===----------------------------------------------------------------------===//
308 // Functions "exported" to the running application...
309 //
310 
311 // void atexit(Function*)
314  assert(Args.size() == 1);
316  GenericValue GV;
317  GV.IntVal = 0;
318  return GV;
319 }
320 
321 // void exit(int)
324  return GenericValue();
325 }
326 
327 // void abort(void)
329  //FIXME: should we report or raise here?
330  //report_fatal_error("Interpreted program raised SIGABRT");
331  raise (SIGABRT);
332  return GenericValue();
333 }
334 
335 // int sprintf(char *, const char *, ...) - a very rough implementation to make
336 // output useful.
339  char *OutputBuffer = (char *)GVTOP(Args[0]);
340  const char *FmtStr = (const char *)GVTOP(Args[1]);
341  unsigned ArgNo = 2;
342 
343  // printf should return # chars printed. This is completely incorrect, but
344  // close enough for now.
345  GenericValue GV;
346  GV.IntVal = APInt(32, strlen(FmtStr));
347  while (true) {
348  switch (*FmtStr) {
349  case 0: return GV; // Null terminator...
350  default: // Normal nonspecial character
351  sprintf(OutputBuffer++, "%c", *FmtStr++);
352  break;
353  case '\\': { // Handle escape codes
354  sprintf(OutputBuffer, "%c%c", *FmtStr, *(FmtStr+1));
355  FmtStr += 2; OutputBuffer += 2;
356  break;
357  }
358  case '%': { // Handle format specifiers
359  char FmtBuf[100] = "", Buffer[1000] = "";
360  char *FB = FmtBuf;
361  *FB++ = *FmtStr++;
362  char Last = *FB++ = *FmtStr++;
363  unsigned HowLong = 0;
364  while (Last != 'c' && Last != 'd' && Last != 'i' && Last != 'u' &&
365  Last != 'o' && Last != 'x' && Last != 'X' && Last != 'e' &&
366  Last != 'E' && Last != 'g' && Last != 'G' && Last != 'f' &&
367  Last != 'p' && Last != 's' && Last != '%') {
368  if (Last == 'l' || Last == 'L') HowLong++; // Keep track of l's
369  Last = *FB++ = *FmtStr++;
370  }
371  *FB = 0;
372 
373  switch (Last) {
374  case '%':
375  memcpy(Buffer, "%", 2); break;
376  case 'c':
377  sprintf(Buffer, FmtBuf, uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
378  break;
379  case 'd': case 'i':
380  case 'u': case 'o':
381  case 'x': case 'X':
382  if (HowLong >= 1) {
383  if (HowLong == 1 &&
385  sizeof(long) < sizeof(int64_t)) {
386  // Make sure we use %lld with a 64 bit argument because we might be
387  // compiling LLI on a 32 bit compiler.
388  unsigned Size = strlen(FmtBuf);
389  FmtBuf[Size] = FmtBuf[Size-1];
390  FmtBuf[Size+1] = 0;
391  FmtBuf[Size-1] = 'l';
392  }
393  sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal.getZExtValue());
394  } else
395  sprintf(Buffer, FmtBuf,uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
396  break;
397  case 'e': case 'E': case 'g': case 'G': case 'f':
398  sprintf(Buffer, FmtBuf, Args[ArgNo++].DoubleVal); break;
399  case 'p':
400  sprintf(Buffer, FmtBuf, (void*)GVTOP(Args[ArgNo++])); break;
401  case 's':
402  sprintf(Buffer, FmtBuf, (char*)GVTOP(Args[ArgNo++])); break;
403  default:
404  errs() << "<unknown printf code '" << *FmtStr << "'!>";
405  ArgNo++; break;
406  }
407  size_t Len = strlen(Buffer);
408  memcpy(OutputBuffer, Buffer, Len + 1);
409  OutputBuffer += Len;
410  }
411  break;
412  }
413  }
414  return GV;
415 }
416 
417 // int printf(const char *, ...) - a very rough implementation to make output
418 // useful.
421  char Buffer[10000];
422  std::vector<GenericValue> NewArgs;
423  NewArgs.push_back(PTOGV((void*)&Buffer[0]));
424  llvm::append_range(NewArgs, Args);
425  GenericValue GV = lle_X_sprintf(FT, NewArgs);
426  outs() << Buffer;
427  return GV;
428 }
429 
430 // int sscanf(const char *format, ...);
432  ArrayRef<GenericValue> args) {
433  assert(args.size() < 10 && "Only handle up to 10 args to sscanf right now!");
434 
435  char *Args[10];
436  for (unsigned i = 0; i < args.size(); ++i)
437  Args[i] = (char*)GVTOP(args[i]);
438 
439  GenericValue GV;
440  GV.IntVal = APInt(32, sscanf(Args[0], Args[1], Args[2], Args[3], Args[4],
441  Args[5], Args[6], Args[7], Args[8], Args[9]));
442  return GV;
443 }
444 
445 // int scanf(const char *format, ...);
447  assert(args.size() < 10 && "Only handle up to 10 args to scanf right now!");
448 
449  char *Args[10];
450  for (unsigned i = 0; i < args.size(); ++i)
451  Args[i] = (char*)GVTOP(args[i]);
452 
453  GenericValue GV;
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]));
456  return GV;
457 }
458 
459 // int fprintf(FILE *, const char *, ...) - a very rough implementation to make
460 // output useful.
463  assert(Args.size() >= 2);
464  char Buffer[10000];
465  std::vector<GenericValue> NewArgs;
466  NewArgs.push_back(PTOGV(Buffer));
467  NewArgs.insert(NewArgs.end(), Args.begin()+1, Args.end());
468  GenericValue GV = lle_X_sprintf(FT, NewArgs);
469 
470  fputs(Buffer, (FILE *) GVTOP(Args[0]));
471  return GV;
472 }
473 
476  int val = (int)Args[1].IntVal.getSExtValue();
477  size_t len = (size_t)Args[2].IntVal.getZExtValue();
478  memset((void *)GVTOP(Args[0]), val, len);
479  // llvm.memset.* returns void, lle_X_* returns GenericValue,
480  // so here we return GenericValue with IntVal set to zero
481  GenericValue GV;
482  GV.IntVal = 0;
483  return GV;
484 }
485 
488  memcpy(GVTOP(Args[0]), GVTOP(Args[1]),
489  (size_t)(Args[2].IntVal.getLimitedValue()));
490 
491  // llvm.memcpy* returns void, lle_X_* returns GenericValue,
492  // so here we return GenericValue with IntVal set to zero
493  GenericValue GV;
494  GV.IntVal = 0;
495  return GV;
496 }
497 
498 void Interpreter::initializeExternalFunctions() {
500  (*FuncNames)["lle_X_atexit"] = lle_X_atexit;
501  (*FuncNames)["lle_X_exit"] = lle_X_exit;
502  (*FuncNames)["lle_X_abort"] = lle_X_abort;
503 
504  (*FuncNames)["lle_X_printf"] = lle_X_printf;
505  (*FuncNames)["lle_X_sprintf"] = lle_X_sprintf;
506  (*FuncNames)["lle_X_sscanf"] = lle_X_sscanf;
507  (*FuncNames)["lle_X_scanf"] = lle_X_scanf;
508  (*FuncNames)["lle_X_fprintf"] = lle_X_fprintf;
509  (*FuncNames)["lle_X_memset"] = lle_X_memset;
510  (*FuncNames)["lle_X_memcpy"] = lle_X_memcpy;
511 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
i
i
Definition: README.txt:29
llvm::Type::ArrayTyID
@ ArrayTyID
Arrays.
Definition: Type.h:75
llvm::Argument
This class represents an incoming formal argument to a Function.
Definition: Argument.h:29
llvm::Type::FloatTyID
@ FloatTyID
32-bit floating point type
Definition: Type.h:58
llvm::Type::DoubleTyID
@ DoubleTyID
64-bit floating point type
Definition: Type.h:59
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::DataLayout
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:112
intptr_t
llvm::Function
Definition: Function.h:61
llvm::Type::VoidTyID
@ VoidTyID
type with no size
Definition: Type.h:63
TheInterpreter
static Interpreter * TheInterpreter
Definition: ExternalFunctions.cpp:71
Interpreter.h
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::DataLayout::getTypeStoreSize
TypeSize getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type.
Definition: DataLayout.h:466
ErrorHandling.h
lle_X_atexit
static GenericValue lle_X_atexit(FunctionType *FT, ArrayRef< GenericValue > Args)
Definition: ExternalFunctions.cpp:312
ManagedStatic.h
llvm::Type::getTypeID
TypeID getTypeID() const
Return the type id for the type.
Definition: Type.h:135
lle_X_exit
static GenericValue lle_X_exit(FunctionType *FT, ArrayRef< GenericValue > Args)
Definition: ExternalFunctions.cpp:322
APInt.h
DynamicLibrary.h
lookupFunction
static ExFunc lookupFunction(const Function *F)
Definition: ExternalFunctions.cpp:100
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
T
#define T
Definition: Mips16ISelLowering.cpp:341
ret
to esp esp setne al movzbw ax esp setg cl movzbw cx cmove cx cl jne LBB1_2 esp ret(also really horrible code on ppc). This is due to the expand code for 64-bit compares. GCC produces multiple branches
getBitWidth
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
Definition: ValueTracking.cpp:89
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:892
lle_X_sprintf
static GenericValue lle_X_sprintf(FunctionType *FT, ArrayRef< GenericValue > Args)
Definition: ExternalFunctions.cpp:337
F
#define F(x, y, z)
Definition: MD5.cpp:56
lle_X_sscanf
static GenericValue lle_X_sscanf(FunctionType *FT, ArrayRef< GenericValue > args)
Definition: ExternalFunctions.cpp:431
llvm::Interpreter::addAtExitHandler
void addAtExitHandler(Function *F)
Definition: Interpreter.h:179
llvm::Interpreter::exitCalled
void exitCalled(GenericValue GV)
Definition: Execution.cpp:875
llvm::GenericValue
Definition: GenericValue.h:23
llvm::GenericValue::IntVal
APInt IntVal
Definition: GenericValue.h:35
llvm::Type::FunctionTyID
@ FunctionTyID
Functions.
Definition: Type.h:72
llvm::outs
raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
Definition: raw_ostream.cpp:884
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::ARM_PROC::A
@ A
Definition: ARMBaseInfo.h:34
int
Clang compiles this i1 i64 store i64 i64 store i64 i64 store i64 i64 store i64 align Which gets codegen d xmm0 movaps rbp movaps rbp movaps rbp movaps rbp rbp rbp rbp rbp It would be better to have movq s of instead of the movaps s LLVM produces ret int
Definition: README.txt:536
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
llvm::ManagedStatic
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:83
llvm::GVTOP
void * GVTOP(const GenericValue &GV)
Definition: GenericValue.h:50
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
llvm::APInt::getZExtValue
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1631
llvm::SmallVectorImpl::resize
void resize(size_type N)
Definition: SmallVector.h:606
llvm::FunctionType::params
ArrayRef< Type * > params() const
Definition: DerivedTypes.h:129
GenericValue.h
lle_X_memcpy
static GenericValue lle_X_memcpy(FunctionType *FT, ArrayRef< GenericValue > Args)
Definition: ExternalFunctions.cpp:486
llvm::Type::PointerTyID
@ PointerTyID
Pointers.
Definition: Type.h:73
ExportedFunctions
static ManagedStatic< std::map< const Function *, ExFunc > > ExportedFunctions
Definition: ExternalFunctions.cpp:63
llvm::sys::DynamicLibrary::SearchForAddressOfSymbol
static void * SearchForAddressOfSymbol(const char *symbolName)
This function will search through all previously loaded dynamic libraries for the symbol symbolName.
Definition: DynamicLibrary.cpp:177
FuncNames
static ManagedStatic< std::map< std::string, ExFunc > > FuncNames
Definition: ExternalFunctions.cpp:64
Type.h
llvm::ExecutionEngine::getDataLayout
const DataLayout & getDataLayout() const
Definition: ExecutionEngine.h:197
val
The initial backend is deliberately restricted to z10 We should add support for later architectures at some point If an asm ties an i32 r result to an i64 the input will be treated as an leaving the upper bits uninitialised For i64 store i32 val
Definition: README.txt:15
FunctionsLock
static ManagedStatic< sys::Mutex > FunctionsLock
Definition: ExternalFunctions.cpp:60
llvm::cl::values
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
Definition: CommandLine.h:699
llvm::sys::ScopedLock
SmartScopedLock< false > ScopedLock
Definition: Mutex.h:73
ExFunc
GenericValue(* ExFunc)(FunctionType *, ArrayRef< GenericValue >)
Definition: ExternalFunctions.cpp:62
llvm::FunctionType::getParamType
Type * getParamType(unsigned i) const
Parameter type accessors.
Definition: DerivedTypes.h:134
ArrayRef.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
lle_X_abort
static GenericValue lle_X_abort(FunctionType *FT, ArrayRef< GenericValue > Args)
Definition: ExternalFunctions.cpp:328
llvm::APInt
Class for arbitrary precision integers.
Definition: APInt.h:70
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
DataLayout.h
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
uint32_t
llvm::append_range
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
Definition: STLExtras.h:1744
Mutex.h
llvm::GenericValue::DoubleVal
double DoubleVal
Definition: GenericValue.h:29
llvm::Type::IntegerTyID
@ IntegerTyID
Arbitrary bit width integers.
Definition: Type.h:71
llvm::GenericValue::FloatVal
float FloatVal
Definition: GenericValue.h:30
llvm::tgtok::IntVal
@ IntVal
Definition: TGLexer.h:64
lle_X_fprintf
static GenericValue lle_X_fprintf(FunctionType *FT, ArrayRef< GenericValue > Args)
Definition: ExternalFunctions.cpp:461
Casting.h
Function.h
getTypeID
static char getTypeID(Type *Ty)
Definition: ExternalFunctions.cpp:73
llvm::ExecutionEngine::getPointerToGlobalIfAvailable
void * getPointerToGlobalIfAvailable(StringRef S)
getPointerToGlobalIfAvailable - This returns the address of the specified global value if it is has a...
Definition: ExecutionEngine.cpp:285
llvm::Type::StructTyID
@ StructTyID
Structures.
Definition: Type.h:74
llvm::Interpreter
Definition: Interpreter.h:74
llvm::PTOGV
GenericValue PTOGV(void *P)
Definition: GenericValue.h:49
lle_X_scanf
static GenericValue lle_X_scanf(FunctionType *FT, ArrayRef< GenericValue > args)
Definition: ExternalFunctions.cpp:446
llvm::ArrayRef::size
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
llvm::Interpreter::callExternalFunction
GenericValue callExternalFunction(Function *F, ArrayRef< GenericValue > ArgVals)
Definition: ExternalFunctions.cpp:259
DerivedTypes.h
llvm::DataLayout::getPointerSizeInBits
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:404
llvm::AMDGPU::HSAMD::Kernel::Key::Args
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Definition: AMDGPUMetadata.h:389
lle_X_memset
static GenericValue lle_X_memset(FunctionType *FT, ArrayRef< GenericValue > Args)
Definition: ExternalFunctions.cpp:474
raw_ostream.h
lle_X_printf
static GenericValue lle_X_printf(FunctionType *FT, ArrayRef< GenericValue > Args)
Definition: ExternalFunctions.cpp:419
llvm::FunctionType::getReturnType
Type * getReturnType() const
Definition: DerivedTypes.h:123
llvm::FunctionType
Class to represent function types.
Definition: DerivedTypes.h:102