LLVM  16.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"
33 #include "llvm/Support/Mutex.h"
35 #include <cassert>
36 #include <cmath>
37 #include <csignal>
38 #include <cstdint>
39 #include <cstdio>
40 #include <cstring>
41 #include <map>
42 #include <mutex>
43 #include <string>
44 #include <utility>
45 #include <vector>
46 
47 #ifdef HAVE_FFI_CALL
48 #ifdef HAVE_FFI_H
49 #include <ffi.h>
50 #define USE_LIBFFI
51 #elif HAVE_FFI_FFI_H
52 #include <ffi/ffi.h>
53 #define USE_LIBFFI
54 #endif
55 #endif
56 
57 using namespace llvm;
58 
59 namespace {
60 
62 typedef void (*RawFunc)();
63 
64 struct Functions {
65  sys::Mutex Lock;
66  std::map<const Function *, ExFunc> ExportedFunctions;
67  std::map<std::string, ExFunc> FuncNames;
68 #ifdef USE_LIBFFI
69  std::map<const Function *, RawFunc> RawFunctions;
70 #endif
71 };
72 
73 Functions &getFunctions() {
74  static Functions F;
75  return F;
76 }
77 
78 } // anonymous namespace
79 
81 
82 static char getTypeID(Type *Ty) {
83  switch (Ty->getTypeID()) {
84  case Type::VoidTyID: return 'V';
85  case Type::IntegerTyID:
86  switch (cast<IntegerType>(Ty)->getBitWidth()) {
87  case 1: return 'o';
88  case 8: return 'B';
89  case 16: return 'S';
90  case 32: return 'I';
91  case 64: return 'L';
92  default: return 'N';
93  }
94  case Type::FloatTyID: return 'F';
95  case Type::DoubleTyID: return 'D';
96  case Type::PointerTyID: return 'P';
97  case Type::FunctionTyID:return 'M';
98  case Type::StructTyID: return 'T';
99  case Type::ArrayTyID: return 'A';
100  default: return 'U';
101  }
102 }
103 
104 // Try to find address of external function given a Function object.
105 // Please note, that interpreter doesn't know how to assemble a
106 // real call in general case (this is JIT job), that's why it assumes,
107 // that all external functions has the same (and pretty "general") signature.
108 // The typical example of such functions are "lle_X_" ones.
109 static ExFunc lookupFunction(const Function *F) {
110  // Function not found, look it up... start by figuring out what the
111  // composite function name should be.
112  std::string ExtName = "lle_";
113  FunctionType *FT = F->getFunctionType();
114  ExtName += getTypeID(FT->getReturnType());
115  for (Type *T : FT->params())
116  ExtName += getTypeID(T);
117  ExtName += ("_" + F->getName()).str();
118 
119  auto &Fns = getFunctions();
120  sys::ScopedLock Writer(Fns.Lock);
121  ExFunc FnPtr = Fns.FuncNames[ExtName];
122  if (!FnPtr)
123  FnPtr = Fns.FuncNames[("lle_X_" + F->getName()).str()];
124  if (!FnPtr) // Try calling a generic function... if it exists...
126  ("lle_X_" + F->getName()).str());
127  if (FnPtr)
128  Fns.ExportedFunctions.insert(std::make_pair(F, FnPtr)); // Cache for later
129  return FnPtr;
130 }
131 
132 #ifdef USE_LIBFFI
133 static ffi_type *ffiTypeFor(Type *Ty) {
134  switch (Ty->getTypeID()) {
135  case Type::VoidTyID: return &ffi_type_void;
136  case Type::IntegerTyID:
137  switch (cast<IntegerType>(Ty)->getBitWidth()) {
138  case 8: return &ffi_type_sint8;
139  case 16: return &ffi_type_sint16;
140  case 32: return &ffi_type_sint32;
141  case 64: return &ffi_type_sint64;
142  }
143  llvm_unreachable("Unhandled integer type bitwidth");
144  case Type::FloatTyID: return &ffi_type_float;
145  case Type::DoubleTyID: return &ffi_type_double;
146  case Type::PointerTyID: return &ffi_type_pointer;
147  default: break;
148  }
149  // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
150  report_fatal_error("Type could not be mapped for use with libffi.");
151  return NULL;
152 }
153 
154 static void *ffiValueFor(Type *Ty, const GenericValue &AV,
155  void *ArgDataPtr) {
156  switch (Ty->getTypeID()) {
157  case Type::IntegerTyID:
158  switch (cast<IntegerType>(Ty)->getBitWidth()) {
159  case 8: {
160  int8_t *I8Ptr = (int8_t *) ArgDataPtr;
161  *I8Ptr = (int8_t) AV.IntVal.getZExtValue();
162  return ArgDataPtr;
163  }
164  case 16: {
165  int16_t *I16Ptr = (int16_t *) ArgDataPtr;
166  *I16Ptr = (int16_t) AV.IntVal.getZExtValue();
167  return ArgDataPtr;
168  }
169  case 32: {
170  int32_t *I32Ptr = (int32_t *) ArgDataPtr;
171  *I32Ptr = (int32_t) AV.IntVal.getZExtValue();
172  return ArgDataPtr;
173  }
174  case 64: {
175  int64_t *I64Ptr = (int64_t *) ArgDataPtr;
176  *I64Ptr = (int64_t) AV.IntVal.getZExtValue();
177  return ArgDataPtr;
178  }
179  }
180  llvm_unreachable("Unhandled integer type bitwidth");
181  case Type::FloatTyID: {
182  float *FloatPtr = (float *) ArgDataPtr;
183  *FloatPtr = AV.FloatVal;
184  return ArgDataPtr;
185  }
186  case Type::DoubleTyID: {
187  double *DoublePtr = (double *) ArgDataPtr;
188  *DoublePtr = AV.DoubleVal;
189  return ArgDataPtr;
190  }
191  case Type::PointerTyID: {
192  void **PtrPtr = (void **) ArgDataPtr;
193  *PtrPtr = GVTOP(AV);
194  return ArgDataPtr;
195  }
196  default: break;
197  }
198  // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc.
199  report_fatal_error("Type value could not be mapped for use with libffi.");
200  return NULL;
201 }
202 
203 static bool ffiInvoke(RawFunc Fn, Function *F, ArrayRef<GenericValue> ArgVals,
204  const DataLayout &TD, GenericValue &Result) {
205  ffi_cif cif;
206  FunctionType *FTy = F->getFunctionType();
207  const unsigned NumArgs = F->arg_size();
208 
209  // TODO: We don't have type information about the remaining arguments, because
210  // this information is never passed into ExecutionEngine::runFunction().
211  if (ArgVals.size() > NumArgs && F->isVarArg()) {
212  report_fatal_error("Calling external var arg function '" + F->getName()
213  + "' is not supported by the Interpreter.");
214  }
215 
216  unsigned ArgBytes = 0;
217 
218  std::vector<ffi_type*> args(NumArgs);
219  for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
220  A != E; ++A) {
221  const unsigned ArgNo = A->getArgNo();
222  Type *ArgTy = FTy->getParamType(ArgNo);
223  args[ArgNo] = ffiTypeFor(ArgTy);
224  ArgBytes += TD.getTypeStoreSize(ArgTy);
225  }
226 
228  ArgData.resize(ArgBytes);
229  uint8_t *ArgDataPtr = ArgData.data();
231  for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end();
232  A != E; ++A) {
233  const unsigned ArgNo = A->getArgNo();
234  Type *ArgTy = FTy->getParamType(ArgNo);
235  values[ArgNo] = ffiValueFor(ArgTy, ArgVals[ArgNo], ArgDataPtr);
236  ArgDataPtr += TD.getTypeStoreSize(ArgTy);
237  }
238 
239  Type *RetTy = FTy->getReturnType();
240  ffi_type *rtype = ffiTypeFor(RetTy);
241 
242  if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, args.data()) ==
243  FFI_OK) {
245  if (RetTy->getTypeID() != Type::VoidTyID)
246  ret.resize(TD.getTypeStoreSize(RetTy));
247  ffi_call(&cif, Fn, ret.data(), values.data());
248  switch (RetTy->getTypeID()) {
249  case Type::IntegerTyID:
250  switch (cast<IntegerType>(RetTy)->getBitWidth()) {
251  case 8: Result.IntVal = APInt(8 , *(int8_t *) ret.data()); break;
252  case 16: Result.IntVal = APInt(16, *(int16_t*) ret.data()); break;
253  case 32: Result.IntVal = APInt(32, *(int32_t*) ret.data()); break;
254  case 64: Result.IntVal = APInt(64, *(int64_t*) ret.data()); break;
255  }
256  break;
257  case Type::FloatTyID: Result.FloatVal = *(float *) ret.data(); break;
258  case Type::DoubleTyID: Result.DoubleVal = *(double*) ret.data(); break;
259  case Type::PointerTyID: Result.PointerVal = *(void **) ret.data(); break;
260  default: break;
261  }
262  return true;
263  }
264 
265  return false;
266 }
267 #endif // USE_LIBFFI
268 
270  ArrayRef<GenericValue> ArgVals) {
271  TheInterpreter = this;
272 
273  auto &Fns = getFunctions();
274  std::unique_lock<sys::Mutex> Guard(Fns.Lock);
275 
276  // Do a lookup to see if the function is in our cache... this should just be a
277  // deferred annotation!
278  std::map<const Function *, ExFunc>::iterator FI =
279  Fns.ExportedFunctions.find(F);
280  if (ExFunc Fn = (FI == Fns.ExportedFunctions.end()) ? lookupFunction(F)
281  : FI->second) {
282  Guard.unlock();
283  return Fn(F->getFunctionType(), ArgVals);
284  }
285 
286 #ifdef USE_LIBFFI
287  std::map<const Function *, RawFunc>::iterator RF = Fns.RawFunctions.find(F);
288  RawFunc RawFn;
289  if (RF == Fns.RawFunctions.end()) {
290  RawFn = (RawFunc)(intptr_t)
291  sys::DynamicLibrary::SearchForAddressOfSymbol(std::string(F->getName()));
292  if (!RawFn)
293  RawFn = (RawFunc)(intptr_t)getPointerToGlobalIfAvailable(F);
294  if (RawFn != 0)
295  Fns.RawFunctions.insert(std::make_pair(F, RawFn)); // Cache for later
296  } else {
297  RawFn = RF->second;
298  }
299 
300  Guard.unlock();
301 
302  GenericValue Result;
303  if (RawFn != 0 && ffiInvoke(RawFn, F, ArgVals, getDataLayout(), Result))
304  return Result;
305 #endif // USE_LIBFFI
306 
307  if (F->getName() == "__main")
308  errs() << "Tried to execute an unknown external function: "
309  << *F->getType() << " __main\n";
310  else
311  report_fatal_error("Tried to execute an unknown external function: " +
312  F->getName());
313 #ifndef USE_LIBFFI
314  errs() << "Recompiling LLVM with --enable-libffi might help.\n";
315 #endif
316  return GenericValue();
317 }
318 
319 //===----------------------------------------------------------------------===//
320 // Functions "exported" to the running application...
321 //
322 
323 // void atexit(Function*)
326  assert(Args.size() == 1);
328  GenericValue GV;
329  GV.IntVal = 0;
330  return GV;
331 }
332 
333 // void exit(int)
336  return GenericValue();
337 }
338 
339 // void abort(void)
341  //FIXME: should we report or raise here?
342  //report_fatal_error("Interpreted program raised SIGABRT");
343  raise (SIGABRT);
344  return GenericValue();
345 }
346 
347 // int sprintf(char *, const char *, ...) - a very rough implementation to make
348 // output useful.
351  char *OutputBuffer = (char *)GVTOP(Args[0]);
352  const char *FmtStr = (const char *)GVTOP(Args[1]);
353  unsigned ArgNo = 2;
354 
355  // printf should return # chars printed. This is completely incorrect, but
356  // close enough for now.
357  GenericValue GV;
358  GV.IntVal = APInt(32, strlen(FmtStr));
359  while (true) {
360  switch (*FmtStr) {
361  case 0: return GV; // Null terminator...
362  default: // Normal nonspecial character
363  sprintf(OutputBuffer++, "%c", *FmtStr++);
364  break;
365  case '\\': { // Handle escape codes
366  sprintf(OutputBuffer, "%c%c", *FmtStr, *(FmtStr+1));
367  FmtStr += 2; OutputBuffer += 2;
368  break;
369  }
370  case '%': { // Handle format specifiers
371  char FmtBuf[100] = "", Buffer[1000] = "";
372  char *FB = FmtBuf;
373  *FB++ = *FmtStr++;
374  char Last = *FB++ = *FmtStr++;
375  unsigned HowLong = 0;
376  while (Last != 'c' && Last != 'd' && Last != 'i' && Last != 'u' &&
377  Last != 'o' && Last != 'x' && Last != 'X' && Last != 'e' &&
378  Last != 'E' && Last != 'g' && Last != 'G' && Last != 'f' &&
379  Last != 'p' && Last != 's' && Last != '%') {
380  if (Last == 'l' || Last == 'L') HowLong++; // Keep track of l's
381  Last = *FB++ = *FmtStr++;
382  }
383  *FB = 0;
384 
385  switch (Last) {
386  case '%':
387  memcpy(Buffer, "%", 2); break;
388  case 'c':
389  sprintf(Buffer, FmtBuf, uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
390  break;
391  case 'd': case 'i':
392  case 'u': case 'o':
393  case 'x': case 'X':
394  if (HowLong >= 1) {
395  if (HowLong == 1 &&
397  sizeof(long) < sizeof(int64_t)) {
398  // Make sure we use %lld with a 64 bit argument because we might be
399  // compiling LLI on a 32 bit compiler.
400  unsigned Size = strlen(FmtBuf);
401  FmtBuf[Size] = FmtBuf[Size-1];
402  FmtBuf[Size+1] = 0;
403  FmtBuf[Size-1] = 'l';
404  }
405  sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal.getZExtValue());
406  } else
407  sprintf(Buffer, FmtBuf,uint32_t(Args[ArgNo++].IntVal.getZExtValue()));
408  break;
409  case 'e': case 'E': case 'g': case 'G': case 'f':
410  sprintf(Buffer, FmtBuf, Args[ArgNo++].DoubleVal); break;
411  case 'p':
412  sprintf(Buffer, FmtBuf, (void*)GVTOP(Args[ArgNo++])); break;
413  case 's':
414  sprintf(Buffer, FmtBuf, (char*)GVTOP(Args[ArgNo++])); break;
415  default:
416  errs() << "<unknown printf code '" << *FmtStr << "'!>";
417  ArgNo++; break;
418  }
419  size_t Len = strlen(Buffer);
420  memcpy(OutputBuffer, Buffer, Len + 1);
421  OutputBuffer += Len;
422  }
423  break;
424  }
425  }
426  return GV;
427 }
428 
429 // int printf(const char *, ...) - a very rough implementation to make output
430 // useful.
433  char Buffer[10000];
434  std::vector<GenericValue> NewArgs;
435  NewArgs.push_back(PTOGV((void*)&Buffer[0]));
436  llvm::append_range(NewArgs, Args);
437  GenericValue GV = lle_X_sprintf(FT, NewArgs);
438  outs() << Buffer;
439  return GV;
440 }
441 
442 // int sscanf(const char *format, ...);
444  ArrayRef<GenericValue> args) {
445  assert(args.size() < 10 && "Only handle up to 10 args to sscanf right now!");
446 
447  char *Args[10];
448  for (unsigned i = 0; i < args.size(); ++i)
449  Args[i] = (char*)GVTOP(args[i]);
450 
451  GenericValue GV;
452  GV.IntVal = APInt(32, sscanf(Args[0], Args[1], Args[2], Args[3], Args[4],
453  Args[5], Args[6], Args[7], Args[8], Args[9]));
454  return GV;
455 }
456 
457 // int scanf(const char *format, ...);
459  assert(args.size() < 10 && "Only handle up to 10 args to scanf right now!");
460 
461  char *Args[10];
462  for (unsigned i = 0; i < args.size(); ++i)
463  Args[i] = (char*)GVTOP(args[i]);
464 
465  GenericValue GV;
466  GV.IntVal = APInt(32, scanf( Args[0], Args[1], Args[2], Args[3], Args[4],
467  Args[5], Args[6], Args[7], Args[8], Args[9]));
468  return GV;
469 }
470 
471 // int fprintf(FILE *, const char *, ...) - a very rough implementation to make
472 // output useful.
475  assert(Args.size() >= 2);
476  char Buffer[10000];
477  std::vector<GenericValue> NewArgs;
478  NewArgs.push_back(PTOGV(Buffer));
479  NewArgs.insert(NewArgs.end(), Args.begin()+1, Args.end());
480  GenericValue GV = lle_X_sprintf(FT, NewArgs);
481 
482  fputs(Buffer, (FILE *) GVTOP(Args[0]));
483  return GV;
484 }
485 
488  int val = (int)Args[1].IntVal.getSExtValue();
489  size_t len = (size_t)Args[2].IntVal.getZExtValue();
490  memset((void *)GVTOP(Args[0]), val, len);
491  // llvm.memset.* 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 
500  memcpy(GVTOP(Args[0]), GVTOP(Args[1]),
501  (size_t)(Args[2].IntVal.getLimitedValue()));
502 
503  // llvm.memcpy* returns void, lle_X_* returns GenericValue,
504  // so here we return GenericValue with IntVal set to zero
505  GenericValue GV;
506  GV.IntVal = 0;
507  return GV;
508 }
509 
510 void Interpreter::initializeExternalFunctions() {
511  auto &Fns = getFunctions();
512  sys::ScopedLock Writer(Fns.Lock);
513  Fns.FuncNames["lle_X_atexit"] = lle_X_atexit;
514  Fns.FuncNames["lle_X_exit"] = lle_X_exit;
515  Fns.FuncNames["lle_X_abort"] = lle_X_abort;
516 
517  Fns.FuncNames["lle_X_printf"] = lle_X_printf;
518  Fns.FuncNames["lle_X_sprintf"] = lle_X_sprintf;
519  Fns.FuncNames["lle_X_sscanf"] = lle_X_sscanf;
520  Fns.FuncNames["lle_X_scanf"] = lle_X_scanf;
521  Fns.FuncNames["lle_X_fprintf"] = lle_X_fprintf;
522  Fns.FuncNames["lle_X_memset"] = lle_X_memset;
523  Fns.FuncNames["lle_X_memcpy"] = lle_X_memcpy;
524 }
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:28
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
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::DataLayout
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:113
intptr_t
llvm::Function
Definition: Function.h:60
llvm::PseudoProbeReservedId::Last
@ Last
llvm::Type::VoidTyID
@ VoidTyID
type with no size
Definition: Type.h:63
TheInterpreter
static Interpreter * TheInterpreter
Definition: ExternalFunctions.cpp:80
Interpreter.h
llvm::SmallVector< uint8_t, 128 >
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:474
ErrorHandling.h
lle_X_atexit
static GenericValue lle_X_atexit(FunctionType *FT, ArrayRef< GenericValue > Args)
Definition: ExternalFunctions.cpp:324
llvm::Type::getTypeID
TypeID getTypeID() const
Return the type id for the type.
Definition: Type.h:136
lle_X_exit
static GenericValue lle_X_exit(FunctionType *FT, ArrayRef< GenericValue > Args)
Definition: ExternalFunctions.cpp:334
APInt.h
DynamicLibrary.h
lookupFunction
static ExFunc lookupFunction(const Function *F)
Definition: ExternalFunctions.cpp:109
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:100
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:891
lle_X_sprintf
static GenericValue lle_X_sprintf(FunctionType *FT, ArrayRef< GenericValue > Args)
Definition: ExternalFunctions.cpp:349
F
#define F(x, y, z)
Definition: MD5.cpp:55
lle_X_sscanf
static GenericValue lle_X_sscanf(FunctionType *FT, ArrayRef< GenericValue > args)
Definition: ExternalFunctions.cpp:443
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:883
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::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:145
llvm::APInt::getZExtValue
uint64_t getZExtValue() const
Get zero extended value.
Definition: APInt.h:1486
llvm::SmallVectorImpl::resize
void resize(size_type N)
Definition: SmallVector.h:642
llvm::FunctionType::params
ArrayRef< Type * > params() const
Definition: DerivedTypes.h:130
GenericValue.h
lle_X_memcpy
static GenericValue lle_X_memcpy(FunctionType *FT, ArrayRef< GenericValue > Args)
Definition: ExternalFunctions.cpp:498
llvm::Type::PointerTyID
@ PointerTyID
Pointers.
Definition: Type.h:73
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:218
llvm::sys::SmartMutex< false >
Type.h
llvm::ExecutionEngine::getDataLayout
const DataLayout & getDataLayout() const
Definition: ExecutionEngine.h:196
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
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:705
llvm::sys::ScopedLock
SmartScopedLock< false > ScopedLock
Definition: Mutex.h:71
llvm::FunctionType::getParamType
Type * getParamType(unsigned i) const
Parameter type accessors.
Definition: DerivedTypes.h:135
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:340
llvm::APInt
Class for arbitrary precision integers.
Definition: APInt.h:75
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:143
uint32_t
llvm::append_range
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
Definition: STLExtras.h:1988
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:65
lle_X_fprintf
static GenericValue lle_X_fprintf(FunctionType *FT, ArrayRef< GenericValue > Args)
Definition: ExternalFunctions.cpp:473
Casting.h
Function.h
getTypeID
static char getTypeID(Type *Ty)
Definition: ExternalFunctions.cpp:82
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:458
llvm::ArrayRef::size
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:164
llvm::Interpreter::callExternalFunction
GenericValue callExternalFunction(Function *F, ArrayRef< GenericValue > ArgVals)
Definition: ExternalFunctions.cpp:269
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:412
llvm::AMDGPU::HSAMD::Kernel::Key::Args
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Definition: AMDGPUMetadata.h:394
lle_X_memset
static GenericValue lle_X_memset(FunctionType *FT, ArrayRef< GenericValue > Args)
Definition: ExternalFunctions.cpp:486
raw_ostream.h
lle_X_printf
static GenericValue lle_X_printf(FunctionType *FT, ArrayRef< GenericValue > Args)
Definition: ExternalFunctions.cpp:431
llvm::FunctionType::getReturnType
Type * getReturnType() const
Definition: DerivedTypes.h:124
llvm::FunctionType
Class to represent function types.
Definition: DerivedTypes.h:103