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