How to call a JITed LLVM function with unknown type? - llvm

I am implementing a front-end for a JIT compiler using LLVM. I started by following the Kaleidoscope example in the LLVM tutorial. I know how to generate and JIT LLVM IR using the LLVM C++ API. I also know how to call the JITed function, using the "getPointerToFunction" method of llvm::ExecutionEngine.
getPointerToFunction returns a void* which I must then cast to the correct function type. For example, in my compiler I have unit test that looks like the following:
void* compiled_func = compiler.get_function("f");
auto f = reinterpret_cast<int32_t(*)(int32_t)>(compiled_func);
int32_t result = f(10);
The problem is that I have to know the function signature beforehand. In the example above, I have a function "f" which takes takes a 32-bit integer and returns a 32-bit integer. Since I create "f" myself, I know what the function type is, so I'm able to call the JIT'ed function. However, in general, I do not know what the function signature is (or what the struct types are) that are entered by the user. The user can create arbitrary functions, with arbitrary arguments and return types, so I don't know what function pointer type to cast the void* from LLVM's getPointerToFunction. My runtime needs to be able to call those functions (for a Read-Evaluate-Print loop, for example). How can I handle such arbitrary functions from my JIT runtime?
Thanks

There's not much information you get can from compiled_func - as you wrote, it's just a void*. But when you write "in general, I do not know what the function signature is", that's not accurate - you've just compiled that function, so you should have access to the LLVM Function object, which can be queried about its type. It's true that it's an LLVM IR type and not a C++ type, but you can often know which translates to which.
For example, if we borrow code from the tutorial's section on JITting Kaleidoscope:
if (Function *LF = F->Codegen()) {
LF->dump(); // Dump the function for exposition purposes.
// JIT the function, returning a function pointer.
void *FPtr = TheExecutionEngine->getPointerToFunction(LF);
// Cast it to the right type (takes no arguments, returns a double) so we
// can call it as a native function.
double (*FP)() = (double (*)())(intptr_t)FPtr;
fprintf(stderr, "Evaluated to %f\n", FP());
}
Then yes, FPtr was "assumed" to be of type double (), but there's also LF of type Function* here, so you could have done something like:
Type* RetTy = LF->getReturnType();
if (RetTy->isDoubleTy()) {
double (*FP)() = (double (*)())(intptr_t)FPtr;
fprintf(stderr, "Evaluated to %f\n", FP());
} else if (RetTy->isIntegerTy(32)) {
int (*FP)() = (int (*)())(intptr_t)FPtr;
fprintf(stderr, "Evaluated to %d\n", FP());
} else ...
And in much the same way, you can query a function about its parameter types.
A bit cumbersome? You can use your execution engine to invoke the function, via its handy runFunction method, which receives a vector of GenericValues and returns a GenericValue. You should still query the Function type to find what the underlying type under each GenericValue should be.

Related

Explaining C++ (C Binding Library) Function

I'm trying to understand a Function/Method in a Library in order to port it to Java however some parameters don't make any sense to me and reading the source code the library is based on is not helping.
Function (Note the API has few comments (We can also ignore the calc handle since it's got a supplier method))
Ssr calc_ssr(CalcHandle *calc, NoteInfo *rows, size_t num_rows, float music_rate, float score_goal) {
std::vector<NoteInfo> note_info(rows, rows + num_rows);
auto skillsets = MinaSDCalc(
note_info,
music_rate,
score_goal,
reinterpret_cast<Calc*>(calc)
);
return skillset_vector_to_ssr(skillsets);
}
NoteInfo Struct
struct NoteInfo
{
unsigned int notes;
float rowTime;
};
MinaSDCalc
// Function to generate SSR rating
auto
MinaSDCalc(const std::vector<NoteInfo>& NoteInfo,
const float musicrate,
const float goal,
Calc* calc) -> std::vector<float>
{
if (NoteInfo.size() <= 1) {
return dimples_the_all_zero_output;
}
calc->ssr = true;
calc->debugmode = false;
return calc->CalcMain(NoteInfo, musicrate, min(goal, ssr_goal_cap));
}
Calc expected input file data (Only care about the #Notes: ...)
Pastebin
Question
What is NoteInfo in calc_ssr, I don't know any C or C++ so the *rows to me just seems like a pointer to a Noteinfo instance, however the MinaSDCalc methods requires an Array/Vector which using a pointer to a single instance doesn't make sense to me (pairing this with the fact that NoteInfo needs another parameter rowTime which I think is time of Note occurrence in the file which means that value must not be constant otherwise the produced result would be inaccurate)
Github Project: https://github.com/kangalioo/minacalc-standalone (The code alone may not explain enough but it's worth a try; best to look at API.h and discern what's used from there. Though I do warn you a lot of the Code is esoteric)
Sorry if this doesn't make much sense but I've been looking into this since June/July and this API is the closest abstraction from the bare C++ code I could find.
NoteInfo * rows here is pass by pointer. So, rows actually is a pointer to an instance of type NoteInfo. This is one of the ways to pass arrays in c++ to a function. Since arrays are contiguous in memory so we can just increment the pointer by one and get the next element of the array.
for example look at these three ways to do exactly one thing, parameter to pass an array to a function :-
1. void myFunction(int *param) {}
2. void myFunction(int param[10]) {}
3. void myFunction(int param[]) {}
Look into this link for more understanding : https://www.tutorialspoint.com/cplusplus/cpp_passing_arrays_to_functions.htm
Also search for pass by pointer and pass by reference to look into different ways of passing arguments in c++.
2.however the MinaSDCalc methods requires an Array/Vector which using a pointer to a single instance doesn't make sense to me: as to this question of yours, you can now see MinaSDCalc is actually getting an array and not a single instance as passing the pointer is also one of the ways of passing an array in c++.

How to call a specific function from an array of functions?

I'm working on building a watch based on the Arduino/ATMega. The primary goal for now is to switch between "modes” (different functions) by pressing a button on the side. Initially, I had a long if statement like this:
if (counter == 0)
mode1();
enter code
else if (counter == 1)
mode2();
.... Repeat....
But that seems inefficient. So, I tried to make an array of the functions without actually calling them, and then call the indexed function later. The code segment is as follows (Apologies for the mess, it’s very much a WIP)
int Modes[3] = {showTime,flashlight,antiAnxiety} //these are all void functions that are defined earlier.
int scroller(){
int counter = 0;
int timeLeft = millis()+5000;
while (timer <= millis()){
...more code...
}
Modes[counter]();
}
However, when I try to compile that, I get an error:
Error: expression cannot be used as a function.
That logic works in Python, so I’m assuming there’s a concept I don’t know that gets abstracted away in higher-level languages. I’m quite willing to learn it, I just need to know what it is.
The type is wrong - instead of int you need void (*)() as type (because you have an array of void someFunction() function pointers, not an array of integers - and while the former can be converted to the latter in a way, as memory address, you cannot call an integer).
void (*Modes[3])() = {showTime, flashlight, antiAnxiety};
This code becomes easier to understand with a type definition:
typedef void (*func_type)();
func_type Modes[3] = {showTime, flashlight, antiAnxiety};

__builtin_return_address won't take a variable as argument

This is perplexing. Using g++ 4.9.1:
int main()
{
void* r1 = __builtin_return_address(0); // fine
unsigned int foo = 0;
void* r2 = __builtin_return_address(foo); // does not compile
}
The error returned is error: invalid argument to ‘__builtin_return_address’
The documentation says that this function takes an unsigned int. I know the __builtin functions have all kinds of weirdness, and this just might be how life is, but I need to be able to step through this thing with an incrementing variable for a stack dumper I'm trying to implement. If it only accepts constant arguments, that's not really possible.
Is there a workaround or a better way?
Just make your own huge switch/case or if/else tree up to as many levels as you may need. You can use macros to make it simpler.

Function name generation and calling in C++

I have 10 functions with generic names which return references like:
int& function0();
int& function1();
...int& functionN();
As you can see only one letter changes in the function name. Each function does a different job. My use case is given some length, say L, I have to call functions from 0 to L. So I want to somehow generate these function names and call them instead of hardcoding all the function calls based on L. So if in a loop where index i is from 0 to L, for each i I want to call functioni().
One approach that I tried was to store these functions into an array of function pointers but that does not work as these functions return references and array of references is not possible. I also tried to use macro concatenation to generate function names but that is also not possible because macro cannot substitute the value of some variable at preprocessing (MACRO(function,i) does not substitute value of i, concatenates to functioni).
How can I do such thing in C++?
That's not possible in C++, but in your case an array of function pointers seems like a good solution:
typedef int& (* functionPtr)();
functionPtr functions[N];
// or without typedef: int& (* functions[N])();
functions[0] = foo; // assign a function named foo to index 0
int& i = functions[0](); // call function at index 0
You could store an array of function pointers, as answered by Zenith.
In C++11, you could have an array of function closures, e.g. use std::function and lambda expressions. You could have some std::map<std:string,std::function<int&(void)>> associating names to closures.
You could wrap the calls in some function like
int& dofunction(int n) {
switch 0: return function0();
switch 1: return function1();
/// etc...
};
and you could write some small script (e.g. in awk, python, shell, etc....) to generate the C++ code of the above dofunction.
At last, on some operating systems (e.g. Linux and most POSIX), you could retrieve a function pointer at runtime by its name using dlopen(3) (with a NULL filename) then dlsym. You would then declare extern "C" int& function0(); (to avoid name mangling -otherwise you need to pass the mangled name to dlsym) and you need to link the program with -rdynamic -ldl; see C++ dlopen mini howto.

D language function call with argument

I am learning D and have mostly experience in C#. Specifically I am trying to use the Derelict3 Binding to SDL2. I have been able to get some basic functionality working just fine but I have become stumped on how to create an array argument for a specific call.
The library contains a call
SDL_RenderDrawLines(SDL_Renderer*, const(SDL_Point)*, int) //Derelict3 Binding
And I have been unable to correctly form the argument for
const(SDL_Point)*
The SDL Documentation for this function states that this argument is an array of SDL_Point, but I am unclear how to create an appropriate array to pass to this function.
Here is an example of what I have at the moment:
void DrawShape(SDL_Renderer* renderer)
{
SDL_Point a = { x:10, y:10};
SDL_Point b = { x:500, y:500};
const(SDL_Point[2]) points = [a,b];
Uint8 q = 255;
SDL_SetRenderDrawColor(renderer,q,q,q,q);
SDL_RenderDrawLines(renderer,points,1);
}
And the compiler complains that I am not passing the correct type of argument for const(SDL_Point)* in points.
Error: function pointer SDL_RenderDrawLines (SDL_Renderer*, const(SDL_Point)*, int)
is not callable using argument types (SDL_Renderer*, const(SDL_Point[2u]), int)
I suspect this is a fundamental misunderstanding on my part so any help would be appreciated.
Arrays aren't implicitly castable to pointers in D. Instead, each array (both static and dynamic) has an intrinsic .ptr property that is a pointer to its first element.
Change your code to:
SDL_RenderDrawLines(renderer,points.ptr,1);
given that the call asks for a pointer and length, I feel it is safer to define you own wrapper:
SDL_RenderDrawLines(SDL_Renderer* rend, const SDL_Point[] points){
SDL_RenderDrawLines(rend,points.ptr,points.length);
}
(why it isn't defined I don't know, any performance hit from the extra function call is just a -inline away from being resolved)