On 16/11/2011 18:07, Phil Clayton wrote:
The calling conventions for x86_64 appear to pass via registers not only the initial floating point arguments but also the initial int/pointer arguments: http://en.wikipedia.org/wiki/X86_calling_conventions So I suspect all arguments, not just floating point, would be an issue for callbacks on x86_64?
There is a separate issue with floats/doubles on x86_64 when calling from SML to C but that doesn't relate to callbacks. It looks like an exception is meant to be raised but isn't currently. (Perhaps the preprocessor symbol X86_64 should be HOSTARCHITECTURE_X86_64 in foreign.cpp?)
But now I have confused myself. If x86_64 calling conventions pass initial int/pointer args via registers as well as floating point args, what is it about double/float args that is problematic? (Comment foreign.cpp, line 1037.) Also, a comment (foreign.cpp, line 1041) suggests that the size of doubles is the issue but on x86_64 but pointers are also 8 bytes.
Right. Those preprocessor symbols are wrong. I think I changed them elsewhere in the code and somehow those got missed. I think the issue is that on X86/32 all arguments are passed on the stack but on the X86/64 integer-like arguments are passed in the general registers but floating point values are passed in floating-point registers. The code in apply_rec casts everything to (void*) which means that the foreign function will always be called with the arguments in the general registers even if it is expecting them in FP registers. This is frankly horrible and really this should be changed. Instead of interpreting the type information when the foreign function is called it should compile a stub which will convert the arguments into the correct format. I did find a project that would do something like that but it didn't deal with call-backs at all.
David