Generating GetElementPtr inlined in a function argument list programmatically

Hello LLVMDev List,

It’s my first time sending a message to the List - I have been working on a tool for my research project using LLVM. Thanks for your awesome work!

I have come across some bytecode like the following with an GetElementPtr instruction in brackets:

Bytecode:
%3 = call i32 @_Z4funcPKc(i8* getelementptr inbounds ([5 x i8]* @.str2, i32 0, i32 0))

C++ code:
func(“bleh”);

However when I am generating bytecode programmatically, I can not have the GetElementPtr value “inlined” in the function argument list:

Bytecode:

%bbname = getelementptr inbounds [29 x i8]* @bbname10, i32 0, i32 0
call void @incrementFaultSiteCount(i8* %bbname, i32 2)

C++ code: (What I mean to generate)
incrementFaultSiteCount(“BBName”, 2);

My question is:

  • What is this phenomenon called, is it called “inlined/expanded function argument”?
  • It seems the “inlined” GetElementPtr instruction is just more concise and saves the need for a name for a register holding the value of the pointer. Is this correct?
  • I’m now generating the aforementioned instructions (non-inlined) with the following code snippet with LLVM 3.2. Is there a way to generate “inlined” GetElementPtr instructions when calling a function just like the first example programmatically?

Hello LLVMDev List,

It’s my first time sending a message to the List - I have been working on a tool for my research project using LLVM. Thanks for your awesome work!

I have come across some bytecode like the following with an GetElementPtr instruction in brackets:

Bytecode:
%3 = call i32 @_Z4funcPKc(i8* getelementptr inbounds ([5 x i8]* @.str2, i32 0, i32 0))

C++ code:
func(“bleh”);

However when I am generating bytecode programmatically, I can not have the GetElementPtr value “inlined” in the function argument list:

Bytecode:

%bbname = getelementptr inbounds [29 x i8]* @bbname10, i32 0, i32 0
call void @incrementFaultSiteCount(i8* %bbname, i32 2)

C++ code: (What I mean to generate)
incrementFaultSiteCount(“BBName”, 2);

My question is:

  • What is this phenomenon called, is it called “inlined/expanded function argument”?

This is a constant expression cast. It will only happen for a constant arguments, in this case the address of global @bbname. You should get these if you run instcombine on it.

http://llvm.org/docs/LangRef.html#constant-expressions

Err not a cast, just a constant expression getelementptr

I forgot to mention you can also create ConstantExprs directly if you want

Hi Tommy,

%3 = call i32 @_Z4funcPKc(i8* getelementptr inbounds ([5 x i8]* @.str2, i32
0, i32 0))

- What is this phenomenon called, is it called "inlined/expanded function
argument"?

This is the syntax used when the getelementptr is a
GetElementPtrConstantExpr rather than an Instruction, and that's
generally true for the inlined forms: if you can make an expression
out of Constants in some way then it'll be "inlined".

- I'm now generating the aforementioned instructions (non-inlined) with the
following code snippet with LLVM 3.2. Is there a way to generate "inlined"
GetElementPtr instructions when calling a function just like the first
example programmatically?

Yep, the function you want is GetElementPtrConstantExpr::Create.
Incidentally, in these cases the "cpp" backend can be very useful. If
you can write LLVM IR to do what you want it will give you back some
C++ code that emits the IR.

For example:
$ cat simple.ll
@var = global [5 x i32] zeroinitializer
define i32* @foo() {
  ret i32* getelementptr(i32* @var, i32 0, i32 1)
}
$ llc simple.ll -o - -march=cpp
    [...]
    GlobalVariable* gvar_array_var = new GlobalVariable(/*Module=*/*mod, [...]);
    [...]
    std::vector<Constant*> const_ptr_5_indices;
    ConstantInt* const_int32_6 = ConstantInt::get(mod->getContext(),
APInt(32, StringRef("0"), 10));
    const_ptr_5_indices.push_back(const_int32_6);
    ConstantInt* const_int32_7 = ConstantInt::get(mod->getContext(),
APInt(32, StringRef("1"), 10));
    const_ptr_5_indices.push_back(const_int32_7);
    Constant* const_ptr_5 =
ConstantExpr::getGetElementPtr(gvar_array_var, const_ptr_5_indices);
    [...]
    ReturnInst::Create(mod->getContext(), const_ptr_5, label_8);

Obviously the code is auto-generated and usually not the best, but it
usually gives you enough information about what you need to do.

Cheers.

Tim.