Hi Shen,
Let’s say we have two modules M1.bc and M2.bc, and in M1 we want to call function foo(defined in M2.bc)with the function type
int foo(float, char*){…}
what basic steps do I need to do to make M1.bc call foo remotely?
There’s currently no built in support for calling functions with signatures other than void(), int(), or int(int, char*).
To call a function with a different signature you have a couple of options:
(1) Generate a wrapper, encode the args, then decode the return:
void wrapper(void *inputs, void *output) {
// args = decode(inputs)
int result = foo(args…);
// output = encode(result)
}
Then on the client end you have to write data to the inputs slab, send it to the server, call wrapper, read the outputs slab back, then decode it.
(2) If you know the signature of the function that you want to be able to call ahead of time, you can extend the JIT server’s RPC endpoint to handle your function type. (We would just need to make the RPC endpoint in OrcRemoteTargetServer publicly visible for this to work, but that’s an easy change):
// Declare your function pointer type.
typedef int (MyFuncType)(float, char);
// Write a handler to call into a function of your type.
int callMyFunc(JITTargetAddress MyFuncAddr, float Arg1, std::string Arg2) {
MyFuncType MyFunc = (MyFuncType)MyFuncAddr;
return MyFunc(Arg1, Arg2.c_str());
}
// Write an RPC function definition.
class CallMyFunc : public llvm::orc::rpc::Function<CallMyFunc, int(JITTargetAddress, float, std::string)> {
public:
static const char *getName() { return “CallMyFunc”; }
};
// Register the callMyFunc function as a handler for CallMyFunc (the RPC definition) with the RPC endpoint.
OrcRemoteTargetServer Server(…);
Server.getRPCEndpoint().addHandler(callMyFunc);
Now on your client you could write:
int Result = Client.getRPCEndpoint.callB(3.141, “pi”);
(3) If you don’t know the signature of the function at server build type, you can write the code from part (2) and JIT it into the server after you connect. This would require us extending the OrcRemoteTargetRPC API with a “RegisterRPCExtension” function, but that should also be pretty easy.
BTW, does the RPCUtility supports handling pointers now?
It does not, and I doubt it ever will - I expect it to remain limited to value types only.
The aim of Orc RPC is to be good enough for basic cases, and especially for testing purposes, but we don’t want it growing into a fully featured RPC library. That kind of use case would be better supported by writing a new client/server (out of tree) on top of a fully featured RPC library like GRPC or Cap’n Proto.
Cheers,
Lang.