Hello, 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: http://homes.cs.washington.edu/~asampson/blog/clangpass.html. 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! Jan
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. Regards, John Criswell On 10/28/14, 5:16 AM, Jan Teske wrote:> Hello, > > 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: > http://homes.cs.washington.edu/~asampson/blog/clangpass.html. 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! > Jan > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev-- John Criswell Assistant Professor Department of Computer Science, University of Rochester http://www.cs.rochester.edu/u/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. BR, Jan On 10/29/2014 05:06 PM, John Criswell wrote:> 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. > > Regards, > > John Criswell > > On 10/28/14, 5:16 AM, Jan Teske wrote: >> Hello, >> >> 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: >> http://homes.cs.washington.edu/~asampson/blog/clangpass.html. 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! Jan >> _______________________________________________ LLVM Developers >> mailing list LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > >