Get pointer element type in LLVM C API - llvm

I want build LLVM load instruction in LLVM C API.
In the LLVM docs, it say LLVMBuildLoad() is deprecated, use LLVMBuildLoad2() instead.
So I use LLVMBuildLoad2() to build load instruction, but that require get the element type of pointer, so I see LLVMGetElementType() can do this.
But LLVM docs says the usage of LLVMGetElementType in pointer types is deprecated
PointerType::getNonOpaquePointerElementType() can do this, but I do not found in LLVM C API, and LLVMBuildLoad() is defined as
LLVMValueRef LLVMBuildLoad(LLVMBuilderRef B, LLVMValueRef PointerVal,
const char *Name) {
Value *V = unwrap(PointerVal);
PointerType *Ty = cast<PointerType>(V->getType());
return wrap(
unwrap(B)->CreateLoad(Ty->getNonOpaquePointerElementType(), V, Name));
}
but LLVMBuildLoad() is deprecated
How could I build load instruction when I only have pointer value?
Edit:
I found Segmentation fault when I use LLVMBuildLoad() !
but LLVMBuildLoad2() does not.

Well, After reading https://llvm.org/docs/OpaquePointers.html I understand I am using LLVM-15, and opaque pointers mode are enabled by default.
So the value of LLVMBuildAlloca has a ptr type, which is a incomplete type, cannot be dereferenced or get type by getNonOpaquePointerElementType().
So getNonOpaquePointerElementType()(used by LLVMBuildLoad()) return NULL and segmentation fault.
after add the following code to disable opaque pointers mode
LLVMContextSetOpaquePointers(LLVMGetGlobalContext(), 0);
There are no segmentation fault in LLVMBuildLoad()
I think I should use opaque pointers, and keep track type of values, then call LLVMBuildLoad2() instead.
Also, LLVMBuildLoad will fail if give it a pointer to void or opaque struct ...

Related

OpenCL C++ context properties syntax

I'm trying to learn OpenCL using the C++ bindings. The only thing I haven't understood so far is the following syntax. Trying to create a context based on a device type:
cl::Context context(CL_DEVICE_TYPE_CPU, properties);
I'm using nvidia's ICD, which as I understand won't let you create a context without defining the platform, so I need the second argument. From the standard, cl_context_properties should be a list of property names, followed by the corresponding values, ended by 0. There's only one cl_context_properties in the standard (table 4.4), which is the property CL_CONTEXT_PLATFORM and has property value of cl_platform_id type. Based on that I thought therefore that this should be OK:
cl_context_properties properties[] =
{ CL_CONTEXT_PLATFORM, platforms[0], 0};
where platforms is my vector of platforms. But it will fail to compile unless instead of platforms[0] I put:
(cl_context_properties)(platforms[0])()
This is from the example code in the cl.hpp header file.
1) It looks like platforms is being cast to type cl_context_properties. Why is this necessary?
2) Why is there an extra set of brackets () at the end?
Please assume that I'm not a C++ expert (definitely true). I know it's only a small thing but I don't like writing code that I don't understand fully.
I have not any experience related to OpenCL.
So mainly my answer is about C++ using.
Why cast is necessary?
The cast is necessary, because you're declaring C array properties[] where each element should be of type cl_context_properties.
Since cl_platform_id has different type it should be cast to appropriate type, exactly - cl_context_properties.
You're using C-style cast that looks like this:
(type_to_cast_to)(expression_to_be_cast).
If expression_to_be_cast is just a variable like in you case you can omit parentheses around expression_to_be_cast:
cl_context_properties properties[] =
{ CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[0], 0};
Why is there an extra set of brackets () at the end?
You should use the brackets since variable platform[0] is of type cl::Platform which is not plain type (like int, char, double for example) and cl::Platform class is a wrapper. You should invoke operator() of this class in order to get underlying data of type cl_platform_id that you need.
So next code should be simpler:
cl_context_properties properties[] =
{ CL_CONTEXT_PLATFORM, static_cast<cl_context_properties>(platforms[0]()), 0};
Here you're doing cast with C++ style cast static_cast which is preferable cast in C++ ( you can read about it here ) of object returned by invocation of operator() on object platforms[0].
The operator() is defined in class cl::detail::Wrapper< T > (class reference) which is parent class for class cl::Platform

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)

How to call a JITed LLVM function with unknown type?

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.

Dereferencing a pointer to a variable with an unknown type

I didn't know exactly how to explain the problem that I am having right now, so sorry if I am being vague in the title of the question.
What I am having right now is a list of virtual addresses that are being stored in variables. For example, I'm having
0x8c334dd
stored in a char variable. This address is the address of another variable that has data on it. What I want to do is to go to that address and get the data that is stored on it.
My assumption was that dereferencing the pointer would have been the best way to go, unfortunately I don't know the type of the variable that the address is pointing to, so how does dereferencing works in this case? I cannot do: *(char *) 8c334dd because I don't know the type of the variable that the address is pointing to...
If I cast it as an (int *) I get some of the data of some of the variables that some addresses are pointing to (remember that I have several addresses) but for others I am just getting an address, and I need the data (this variables are structs, chars, etc).
I am working with the ELF Symbol Table
In general, C++ or C have no way of knowing what type of pointer you have.
The usual way to solve this problem is to make the pointer point to a struct, and have a known position in the struct indicate the type of the data. Usually the known position is the first position in the struct.
Example:
// signature value; use any value unlikely to happen by chance
#define VAR_SIG 0x11223344
typedef enum
{
vartypeInvalid = 0,
vartypeInt,
vartypeFloat,
vartypeDouble,
vartypeString,
vartypeMax // not a valid vartype
} VARTYPE;
typedef struct
{
VARTYPE type;
#ifdef DEBUG
uint32_t sig;
#endif // DEBUG
union data
{
int i;
float f;
double d;
char *s;
};
} VAR;
You can then do a sanity check: you can see if the type field has a value greater than vartypeInvalid and less than vartypeMax (and you will never need to edit those names in the sanity check code; if you add more types, you add them before vartypeMax in the list). Also, for a DEBUG build, you can check that the signature field sig contains some specific signature value. (This means that your init code to init a VAR instance needs to always set the sig field, of course.)
If you do something like this, then how do you initialize it? Runtime code will always work:
VAR v;
#ifdef DEBUG
v.sig = VAR_SIG;
#endif // DEBUG
v.type = vartypeFloat;
v.data = 3.14f;
What if you want to initialize it at compile time? It's easy if you want to initialize it with an integer value, because the int type is the first type in the union:
VAR v =
{
vartypeInt,
#ifdef DEBUG
VAR_SIG,
#endif // DEBUG
1234
};
If you are using a C99 compliant version of C, you can actually initialize the struct with a field name and have it assign any type. But Microsoft C isn't C99 compliant, so the above is a nightmare if you want to init your struct with a float or double value. (If you cast the float value to an integer, C won't just change the type, it will round the value; and there is no trick I know of to portably get a 32-bit integer value that correctly represents a 32-bit float at compile time in a C program.)
Compile time float packing/punning
If you are working with pointers, though, that's easy. Just make the first field name in the union be a pointer type, cast the pointer to void * and init the struct as above (the pointer would go where 1234 went above).
If you are reading tables written by someone else's code, and you don't have a way to add a type identifier field, I don't have a general answer for you. I guess you could try reading the pointer out as different types, and see which one(s) work?
Just wanted to add something, for people out there working with the ELF symbol table, I've found the DIEs in the DWARF file easier to work with. You can get the addresses, types and names of variables using DWARF instead of ELF, and libdwarf has good documentation.

Accessing elements in LLVM arrays

I am trying to get started with LLVM in order to add just-in-time compilation for my code, but finding it very difficult find references on how to do the things I want in LLVM, despite having checked through the Kaleidoscope tutorial, the language reference manual, the programmer's manual and the doxygen documentation. Are there more references to LLVM's C++ API than these?
Now for the concrete question. I have allocated an array object with two elements (which I assume corresponds to double[2] in C++):
const llvm::Type* double_t = llvm::Type::getDoubleTy(llvm::getGlobalContext());
const llvm::Type* array_t = llvm::ArrayType::get(double_t,2)
Later in the code, I create a function, where this array is one of the arguments. Then, in my function I extract the first element in the array and return it to the user:
llvm::Function::arg_iterator AI = jit_function_->arg_begin();
llvm::Value *x = AI;
llvm::Value *x0 = Builder.CreateExtractValue(x,0);
Builder.CreateRet(x0);
The code jits fine, but when I try to run it, it doesn't work. For example:
typedef double (*GenType)(double[2]);
GenType FP = GenType(intptr_t(TheExecutionEngine->getPointerToFunction(jit_function_)));
double y[2] = {10,20};
double r = FP(y);
printf("r = %g\n", r);
The return value is just nonsense and I can't see what I'm doing wrong. If I pass the values in the array (10 and 20) as scalar arguments to the function, it works fine.
I think I am able to answer my own question. For the first part of the question, a good reference to LLVM (in addition to the ones mentioned above) is to write what you want in plain C and compile it with Clang and look at the LLVM output: clang -S -emit-llvm test.c -o -.
For the concrete question, my problem was that I assumed that I was passing an array of two doubles to the jitted function, while in fact I was passing a pointer to an array with two values. So the solution is to change:
const llvm::Type* array_t = llvm::ArrayType::get(double_t,2);
to
const llvm::Type* array_t = llvm::PointerType::getUnqual(llvm::ArrayType::get(double_t,2));
And to add an additional dereferencing by changing
llvm::Value *x0 = Builder.CreateExtractValue(x,0);
to
llvm::Value *x0 = Builder.CreateExtractValue(Builder.CreateLoad(x),0);
If you're using LLVM 3.0 or 3.1, CreateExtractValue takes an ArrayRef with the indices.