Download Summary

Transcript
Chapter 7
The generic value
In the previous example, we cast the returned function pointer to a proper prototype
in order to call the function with a C-style function call. However, when dealing with
multiple functions in a multitude of signatures and argument types, we need a more
flexible way to execute functions.
The execution engine provides another way to call JIT-compiled functions.
The runFunction() method compiles and runs a function with the arguments
determined by a vector of GenericValue—it needs no prior invocation to
getPointerToFunction().
The GenericValue struct is defined in <llvm_source>/include/llvm/
ExecutionEngine/GenericValue.h and is capable of holding any common
type. Let's change our last example to use runFunction() instead of
getPointerToFunction() and castings.
First, create the sum-jit-gv.cpp file to hold this new version and add the
GenericValue header file on top:
#include "llvm/ExecutionEngine/GenericValue.h"
Copy the rest from sum-jit.cpp, and let's focus on the modifications. After the
SumFn Function pointer initialization, create FnArgs—a vector of GenericValue—
and populate it with integer values by using the APInt interface (<llvm_source>/
include/llvm/ADT/APInt.h). Use two 32-bit width integers to adhere to the
original prototype, sum(i32 %a, i32 %b):
(...)
Function *SumFn = M->getFunction("sum");
std::vector<GenericValue> FnArgs(2);
FnArgs[0].IntVal = APInt(32,4);
FnArgs[1].IntVal = APInt(32,5);
Call runFunction() with the function parameter and the argument vector. Here,
the function is JIT compiled and executed. The result is also GenericValue and can
be accessed accordingly (the i32 type):
GenericValue Res = EE->runFunction(SumFn, FnArgs);
outs() << "Sum result: " << Res.IntVal << "\n";
We repeat the same process for the second addition:
FnArgs[0].IntVal = Res.IntVal;
FnArgs[1].IntVal = APInt(32,6);
Res = EE->runFunction(SumFn, FnArgs);
outs() << "Sum result: " << Res.IntVal << "\n";
(...)
[ 189 ]