Constant function pointers and inlining


I've been working on turning PHP scripts into LLVM IR and I've gotten
to the stage where I'm able to construct LLVM code that calls the PHP
opcode handlers that I've pre-compiled to LLVM IR in the correct
order. However, the PHP API is designed so that the handlers are not
globally accessible (qualified by "static" in the C source). Instead
they're supposed to be accessed like this (in C):

  zend_op op;
  op.opcode = ... // set the opcode number etc.
  zend_vm_set_opcode_handler(&op); // let the engine figure out which
handler should be used
  op->handler(...); // execute it

Now, the compiler can't know that zend_vm_set_opcode_handler() always
sets the handler to be the same but I do so I'm trying to do this at
compile time (of the PHP function). However, once I get the
GenericValue that points to the handler, I don't really know how to
turn that to a constant function pointer in LLVM. What I do is rather

  Value* handler = ConstantExpr::getIntToPtr(
      (unsigned int) engine->runFunction(get_handler, args).PointerVal),
    PointerType::get(handler_type, 0));

  /* ^^^^^ Is there a better way to do the conversion? ^^^^^^ */

  Value* result = builder.CreateCall2(handler,

And as a result I get handler calls like this:

  %execute_result9 = tail call i32 inttoptr (i32 54000728 to i32
(%struct.zend_execute_data*, i8***)*)( %struct.zend_execute_data*
%execute_data, i8*** %1 )

However, I haven't able to make LLVM inline these calls. Is there some
reason why that's impossible or have I just not found the right
optimization passes to apply?


Ok, so I moved on to use the
ExecutionEngine::getGlobalValueAtAddress() to do the job:

  void* handler_raw = GVTOP(engine->runFunction(get_handler, args));
  Function* handler = (Function*) engine->getGlobalValueAtAddress(handler_raw);

That works great except that I have to make sure that the handler in
question has already been JIT compiled; otherwise handler_raw will
just contain a pointer to the corresponding codegen call instruction,
which getGlobalValueAtAddress() doesn't recognize.

Right now I'm ensuring compilation by calling
engine->getPointerToGlobal(mod->getFunction(handler_name)) beforehand
but that's no good because the whole point is that I'm not supposed to
know the handler_name string since it's internal to the Zend (PHP)
engine. Any ideas how I could force compilation and return the true
address of the handler from within the "get_handler" function without
actually calling the handler?