I'm trying to make some improvements to a interpreter for microcontrollers that I'm working on. For executing built-in functions I currently have something like this (albeit a bit faster):
function executeBuiltin(functionName, functionArgs) {
if (functionName=="foo") foo(getIntFromArg(functionArgs[0]));
if (functionName=="bar") bar(getIntFromArg(functionArgs[0]),getBoolFromArg(functionArgs[1]),getFloatFromArg(functionArgs[2]));
if (functionName=="baz") baz();
...
}
But it is for an embedded device (ARM) with very limited resources, and I need to cut down on the code size drastically. What I'd like to do is to have a general-purpose function for calling other functions with different arguments - something like this:
function executeBuiltin(functionName, functionArgs) {
functionData = fast_lookup(functionName);
call_with_args(functionData.functionPointer, functionData.functionArgumentTypes, functionArgs);
}
So I want to be able to call a standard C function and pass it whatever arguments it needs (which could all be of different types). For this, I need a call_with_args
function.
I want to avoid re-writing every function to take argc+argv. Ideally each function that was called would be an entirely standard C function.
There's a discussion about this here - but has anything changed since 1993 when that post was written? Especially as I'm running on ARM where arguments are in registers rather than on the stack. Even if it's not in standard C, is there anything GCC specific that can be done?
UPDATE: It seems that despite behaviour being 'undefined' according to the spec, it looks like because of the way C calls work, you can pass more arguments to a function than it is expecting and everything will be fine, so you can unpack all the arguments into an array of uint32s, and can then just pass each uint32 to the function.
That makes writing 'nice' code for calls much easier, and it appears to work pretty well (on 32 bit platforms). The only problem seems to be when passing 64 bit numbers and compiling for 64bit x86 as it seems to do something particularly strange in that case.