Storing values in global variables


I have written a pass that works nicely if I use it with the opt tool,
as proposed by the "Writing an LLVM Pass" tutorial. Now I want to
execute this pass directly when clang is executed. I use the technique
described here: The pass
is loaded and executed, when I run clang with the right command line.
But clang proceeds to crash.

It always crashes because of assertions that test types (e.g. the
types of arguments of a call). So far i figured out that this is
because while the types are the same, their contexts differ and thus
they do not have the same address in memory. I guess, this is a
problem now but not when using the opt way, because when I use opt the
global context and the module context are the same.

Anyway, it seems I have to fix my (until now quite careless) use of
the different contexts. And this is where I could need help. The
special case I am stuck at is about storing a value in a global
variable. Here is some code:

IRBuilder<> builder(pi);
Value *elem = builder.CreateCall(...);
Value *elem_ptr = builder.CreateGEP(global_array, idx);
builder.CreateStore(get_crypted_funcptr(func, builder), elem_ptr);

I get a IRBuilder before some instruction (pi) in main. The element I
want to store (elem) is created by some call instruction which I
create via the builder. To store elem in global_array, I need a
pointer, which I get via a GEP instruction which is also created by
the bulder. Now the store fails.

Both elem and the element pointed to by elem_ptr have the same type.
But their contexts are different. elem has module context (I guess
this is because builder has module context) and elem_ptr points to an
element with global context (I guess this is because it's a global
variable with external linkage). Since both contexts are different,
the CreateStore fails at a type-check assertion.

Does that mean I cannot store any values in a global variable? I guess
not. So what would be the correct way to go in this case? The only one
I can think of is trying to give every value the global context. But I
don't think that would be right.

Thanks in advance!

Dear Jan,

I can't see it in your code, but my guess is that, somewhere in your pass, you're grabbing the global context using getGlobalContext() and then using that to create some LLVM value (e.g., a global variable, a GEP, etc.).

Passes should avoid using getGlobalContext() to get a context. Instead, they should get a pointer to the LLVMContext in which the Module or Function they are transforming belongs, and then create all new values (including global variables) within that context.


John Criswell

Hello John,

thank you very much for the hint! I replaced all calls to
getGlobalContext() by calls that retrieve the module context and now
it works.