I am writing an LLVM pass where I want to print out the values of function arguments. I am only focusing on integers and pointers to integers (which will also involve char, I guess but that is not a problem for my purposes). If the argument is a pointer, I want to dereference it and print the value that is pointed to by the pointer. To guard against null pointers, in normal C code I can do:
function foo(int* bar, int** baz) {
if (bar) {
printf("bar: %d\n", *bar);
}
if (baz) {
printf("baz: %d\n", **baz);
}
}
Is there a way to do something similar in LLVM? Currently I am doing the following to actually load the value by dereferencing the pointer. I am working off a StoreInst that LLVM generates to set up the values of function parameters. For example, for the function above, there would be something like:
%bar.addr = alloca i32*, align 8
%baz.addr = alloca i32**, align 8
store i32* %bar, i32** %bar.addr, align 8
store i32** %baz, i32*** %baz.addr, align 8
So using that StoreInst, I am doing something like this:
auto *value = store->getValueOperand();
auto *type = value->getType();
int indirection = 0;
while (type->isPointerTy()) {
indirection++;
type = type->getPointerElementType();
}
Value* load = value;
unsigned int bitWidth = type->getIntegerBitWidth(); // I have already verified earlier on that
// this eventually resolves to an IntegerType
while (indirection > 0) {
load = (indirection == 1) ? irb.CreateLoad(getIntegerType(bitWidth), load)
: irb.CreateLoad(getPointerToIntegerType(indirection - 1, bitWidth), load);
--indirection;
}
value = load;
The getIntegerType is just a convenience function that returns an IntegerType with the provided bit-width and using the current LLVM context. The getPointerToIntegerType function is as follows:
Type* getPointerToIntegerType(int indirection, unsigned int bitWidth) {
Type* type = getIntegerType(bitWidth);
while (indirection > 0) {
type = PointerType::get(type, 0);
--indirection;
}
return type;
}
Using this I get the following load instructions after the store instructions (I've omitted some stuff from the call instructions for brevity):
store i32* %bar, i32** %bar.addr, align 8
%1 = load i32, i32* %bar
call void (i8, ...) @__print_argument_value(...)
store i32** %baz, i32*** %baz.addr, align 8
%2 = load i32*, i32** %baz
%3 = load i32, i32* %2
call void (i8, ...) @__print_argument_value(...)
This works perfectly as long as the pointers are not null. Is there an easy way I can generate IR to guard the call to __print_argument_value? I did write out an explicit if (bar) { ... } and a if (baz) { ... } and then looked at the generated IR to see how LLVM generates it. I saw that it performs an icmp ne of the pointer (the .addr variable) against null. Then if the result is true, it breaks to a label if.then where it calls the function, or else to the label if.end which skips over it.
The problem is that I'm having a hard time trying to figure out how I can generate IR like that from my LLVM pass. Are there any examples I can look at? I did look up the documentation but I still can't figure out how to put the pieces together using the LLVM API even though I know what the IR should look like. I saw some documentation about to PHI nodes which I don't see in my IR from the explicit null check, but I am not entirely clear on what they are and how they would help me.
PS: Please excuse any weirdness in the C/C++ code; I usually program in Java.
Aucun commentaire:
Enregistrer un commentaire