use function address as global variable initializer

Hi

I would like to initialize a global variable to the address of a function. Looking at how clang compiles the C code below, i see @main_ptr = global i8* bitcast (i32 ()* @main to i8*), align 8

but how do i generate i8* bitcast (i32 ()* @main to i8*), align 8 in LLVM IR and use it as initializer to a GlobalVariable.

I know i will need to use the bitcast instruction. but as far i as i understand, every instruction in LLVM needs to be created with an insertion point. what should be the insertion point of this bitcast instruction. also, do i just give the LLVM main Function* to the bitcast instruction as its value ?

I am new to LLVM. please help.

Thank you,
Trent

i.e.

  • C code *

typedef int (*INVOKE_MAIN)(void);

int main();

void *main_ptr = main;

int main()
{
((INVOKE_MAIN)(main_ptr))();
return 0;
}

generated LLVM code

@main_ptr = global i8* bitcast (i32 ()* @main to i8*), align 8

; Function Attrs: nounwind uwtable
define i32 @main() #0 {
entry:
%retval = alloca i32, align 4
store i32 0, i32* %retval
%0 = load i8** @main_ptr, align 8
%1 = bitcast i8* %0 to i32 ()*
%call = call i32 %1()
ret i32 0
}

Hi,

but how do i generate i8* bitcast (i32 ()* @main to i8*), align 8 in LLVM IR
and use it as initializer to a GlobalVariable.

LLVM has a "C++" backend which is amazingly helpful in these
situations. You use llc to compile the bitcode you want to emit with
"-march=cpp" and get back some C++ code that would generate the
original IR. In this case:

PointerType* PointerTy_0 =
PointerType::get(IntegerType::get(mod->getContext(), 8), 0);
Constant* const_ptr_5 = ConstantExpr::getCast(Instruction::BitCast,
func_main, PointerTy_0);
gvar_ptr_main_ptr->setInitializer(const_ptr_5);

It's not pretty (I'd suggest using ConstantExpr::getBitCast instead,
for example), but it often shows you where you should start looking.

I know i will need to use the bitcast instruction. but as far i as i
understand, every instruction in LLVM needs to be created with an insertion
point.

A subclass of Instruction needs an insertion-point, but because @main
(like other globals) is actually a Constant, you can also create a
bitcast that's a Constant too (in this case a ConstantExpr), and they
don't need an insertion point.

also, do i just give the LLVM main Function* to the bitcast instruction as its
value ?

You could do. For a bitcast Instruction, you just need a subclass of
Value, which both other Instructions and Constants (including
Functions) are. For a Constant bitcast, you need another Constant (so
Function works there too).

The class diagrams at
LLVM: llvm::Value Class Reference can actually
be quite useful for ideas on what's possible.

Cheers.

Tim.