If a char parameter is passed to a routine in Aarch64 is the top of the word undefined? and is the same true for if a char value is returned? I think the answer is yes but it would be good to be certain. This means if the char is used in some arithmetic the UXTB, or SXTB for signed, modifiers as described at A64 Shift and Extend Operations: Operand Modifiers must be used in an instruction using a register containing a char passed into or returned from a routine.
I presume the same is true for short as well so a signed short might for instance come in with the top two bytes containing zero
According to AAPCS64, the unused bits have "unspecified value". This is actually a good thing overall, since it removes the need for the caller to explicitly clear those bits before calling a function which doesn't care anyway (because it can use something like UXTB or SXTB). This applies to char, short, int, float, or anything else that doesn't use the full 8 bytes of an X or D register or procedure-call stack slot.
Finally, note that this is different from the 32-bit AAPCS behaviour, where small values have to be zero- or sign-extended.
Thanks very much for that and the reference. That seems to be pretty definitive though unspecfied sounds a bit like they hadn't made up their minds as compared to undefined where one is saying it explicitly. The modifiers in the Aarch64 instructions make it all much easier than for the 32-bit instruction set so zero or sign extended must have made more sense then.
A bit of a niggle occurred to me whilst reading that document. Surely that wouldn't apply to pointers in ILP32? One wouldn't want to be always worrying about the tops of those pointers when they are passed as parameters. I can't see that they would have the top 'unspecified'.
It's not that they hadn't made up their minds as such: it is designed to simplify the argument placement when calling functions that probably don't require it anyway. I think it's a very deliberate decision. (Yes, the extend-mode modifiers make this approach feasible in A64, but less so in ARM and Thumb.)
I haven't experimented much with ILP32, but it does indeed look like the callee has to zero-extend the pointer before using it, so our interpretations agree, at least. (The ILP32 changes are labelled "beta", but I don't know what that really means in this context, and the date on the document is over a year ago.) It does say that the link register and frame pointer use 64-bit stack slots even on ILP32, which is interesting. I'm curious about the reasoning behind that.
I think it would be a big mistake for ILP32 to require that subroutines assume that the top of the pointer parameters might be rubbish. I very much hope that is just an oversight. That will work fine for the integer types because of those modifiers but there's no such modifier for the base register in loads and stores. I know this would be different from how integer type are handled but pointers are very important.
It is a bit strange about the frame format for ilp32, I don't see that there is any real requirement for compatibility with lp64.
I wonder if the frame layout remains the same as LP64 to keep the stack pointer 16-byte aligned even with empty frames.
Ok, according to a reliable source, another (more significant) reason for the frame layout is that the frame pointer is callee-saved, so any non-leaf callee would have to preserve it in full anyway. (The link register is preserved in full to allow stp and ldp to be used when setting up the frame.)
There are also a few considerations regarding the unspecified-bits policy that I hadn't thought about. One of them is security; a C callee can't easily check that its inputs are valid for a small type because the C compiler would optimise away the checks. Another consideration is how stacked arguments would be handled; in this case, the unspecified-bits approach is slightly nicer because the caller doesn't have to do much to prepare the value (just str w0, [...]) and the callee can just load it as a W register.
Security. Gah you're right.And that would apply to passing over pointers in ilp32 mode as well. I suppose one could have an optimization option, and if a hacker can generate a wrong address they've pretty much got control anyway. I can see the point in the default being to make no assumptions though, I keep on being surprised by the exploits that are found and used..