Hello, 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 complicated: Value* handler = ConstantExpr::getIntToPtr( ConstantInt::get(Type::Int32Ty, (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, execute_data, tsrlm_ref, "execute_result"); 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? Thanks, Joonas
On Thu, Jun 19, 2008 at 4:38 PM, Joonas Govenius <joonas.govenius at gmail.com> wrote:> 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 > complicated: > > Value* handler = ConstantExpr::getIntToPtr( > ConstantInt::get(Type::Int32Ty, > (unsigned int) engine->runFunction(get_handler, args).PointerVal), > PointerType::get(handler_type, 0)); >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? Thanks, Joonas
Maybe Matching Threads
- [LLVMdev] Load from abs address generated bad code on LLVM 2.4
- [LLVMdev] Instrumenting virtual function calls
- [LLVMdev] Load from abs address generated bad code on LLVM 2.4
- [LLVMdev] Instrumenting virtual function calls
- [LLVMdev] Instrumenting virtual function calls