Clarification on 8-, and 16-bit integer return values

263 views
Skip to first unread message

Hans Wennborg

unread,
Feb 4, 2016, 8:57:24 PM2/4/16
to x86-6...@googlegroups.com
The current x86_64 psABI doesn't seem to define whether 8- or 16-bit
integer return values should be extended to a wider type when returned
from a function (i.e. what should the high bits of %rax be). It seems
the behaviour for _Bool is defined by Footnote 16 on page 23 of
https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-r249.pdf, but
for char or short, it is not defined as far as I can tell.

There is a proposal here:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=46942#c4 which would
define it. Was there any progress made on that?

For i386, this is defined in Table 2.4, page 14 of
https://01.org/sites/default/files/file_attach/intel386-psabi-1.0.pdf

It seems unfortunate that it's not completely clear how e.g. a char
value should be returned form a function. I'm working on a patch here:
http://reviews.llvm.org/D16907 that will change LLVM's behaviour to be
more in line with GCC's.

Thanks,
Hans

H.J. Lu

unread,
Feb 5, 2016, 9:52:43 AM2/5/16
to Hans Wennborg, x86-6...@googlegroups.com
On Thu, Feb 4, 2016 at 5:57 PM, Hans Wennborg <ha...@chromium.org> wrote:
> The current x86_64 psABI doesn't seem to define whether 8- or 16-bit
> integer return values should be extended to a wider type when returned
> from a function (i.e. what should the high bits of %rax be). It seems
> the behaviour for _Bool is defined by Footnote 16 on page 23 of
> https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-r249.pdf, but
> for char or short, it is not defined as far as I can tell.
>
> There is a proposal here:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=46942#c4 which would
> define it. Was there any progress made on that?

Here is my proposal:

---
When a value of type _Bool is returned in a register, bit 0 contains the truth
value and bits 1 to 7 shall be zero. When an argument of type _Bool is passed
in a register or on the stack, bit 0 contains the truth value and bits
1 to 31 shall be
zero.

When a value of type signed/unsigned char or short is returned in a register,
bits 0 to 7 for char and bits 0 to 15 for short contain the value and other
bits are left unspecified. When an argument of signed/unsigned type char or
short is passed in a register or on the stack, it shall be sign/zero extended to
signed/unsigned int.
---

Let's put it in x86-64 psABI.


--
H.J.

Hans Wennborg

unread,
Feb 5, 2016, 4:23:12 PM2/5/16
to H.J. Lu, x86-6...@googlegroups.com
On Fri, Feb 5, 2016 at 6:52 AM, H.J. Lu <hjl....@gmail.com> wrote:
> On Thu, Feb 4, 2016 at 5:57 PM, Hans Wennborg <ha...@chromium.org> wrote:
>> The current x86_64 psABI doesn't seem to define whether 8- or 16-bit
>> integer return values should be extended to a wider type when returned
>> from a function (i.e. what should the high bits of %rax be). It seems
>> the behaviour for _Bool is defined by Footnote 16 on page 23 of
>> https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-r249.pdf, but
>> for char or short, it is not defined as far as I can tell.
>>
>> There is a proposal here:
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=46942#c4 which would
>> define it. Was there any progress made on that?
>
> Here is my proposal:
>
> ---
> When a value of type _Bool is returned in a register, bit 0 contains the truth
> value and bits 1 to 7 shall be zero.

Should we spell out that the other bits are left unspecified, as you
do for char/short below?

> When an argument of type _Bool is passed
> in a register or on the stack, bit 0 contains the truth value and bits
> 1 to 31 shall be
> zero.
>
> When a value of type signed/unsigned char or short is returned in a register,
> bits 0 to 7 for char and bits 0 to 15 for short contain the value and other
> bits are left unspecified. When an argument of signed/unsigned type char or
> short is passed in a register or on the stack, it shall be sign/zero extended to
> signed/unsigned int.
> ---
>
> Let's put it in x86-64 psABI.

Sounds good to me. Being new to this group, I don't know if that
carries any weight, though :-)

Cheers,
Hans

H.J. Lu

unread,
Feb 5, 2016, 7:07:30 PM2/5/16
to Hans Wennborg, x86-6...@googlegroups.com
Here is a patch against x86-64 psABI revision 249.


--
H.J.
0001-Clarify-how-to-pass-and-return-_Bool-char-short.patch

Hans Wennborg

unread,
Feb 5, 2016, 9:34:06 PM2/5/16
to H.J. Lu, x86-6...@googlegroups.com
Sorry for being nitpicky, but I think the footnote is more confusing
than the text in the signed/unsigned char paragraph:

"\footnote{Other bits are left unspecified, hence the consumer side of
those values can rely on it being 0 or 1 when truncated to 8 bit.}"

This makes it sound like the consumer can rely on the truncated value
to be 1 or 0 *because* the other bits are unspecified, which doesn't
make sense.

How about:

"When a value of type \code{_Bool} is returned in a register, bit 0
contains the truth value and bits 1 to 7 shall be zero\footnote{Hence
the consumer side of those values can rely on it being 0 or 1 when
truncated to 8 bits.} and other bits are left unspecified."

Thanks,
Hans

H.J. Lu

unread,
Feb 6, 2016, 11:19:03 AM2/6/16
to Hans Wennborg, x86-6...@googlegroups.com
Like this?

--
H.J.
0001-Clarify-how-to-pass-and-return-_Bool-char-short.patch

Michael Matz

unread,
Feb 8, 2016, 8:36:50 AM2/8/16
to H.J. Lu, Hans Wennborg, x86-6...@googlegroups.com
Hi,

On Sat, 6 Feb 2016, H.J. Lu wrote:

> >>>> When an argument of type _Bool is passed in a register or on the
> >>>> stack, bit 0 contains the truth value and bits 1 to 31 shall be
> >>>> zero.
>
> Like this?

I'm generally sympathetic to this, except for one thing: you change the
rules for how a _Bool is passed as argument compared to when we last
changed it. Formerly the lower 8 bits are relieable, after the change the
low 32 bits are. If a compiler only ensured the former, interoperability
would now be broken with objects from a compiler using the latter.

I know that gcc ensures the stricter requirement, ICC seems to do so
as well, what about other compilers? (If it weren't for this change, I'd
apply it right away).


Ciao,
Michael.

Hans Wennborg

unread,
Feb 8, 2016, 12:02:10 PM2/8/16
to H.J. Lu, x86-6...@googlegroups.com
Yes, that looks good to me.

Hans Wennborg

unread,
Feb 8, 2016, 12:04:39 PM2/8/16
to Michael Matz, H.J. Lu, x86-6...@googlegroups.com
LLVM also always extends _Bool arguments to 32 bits when calling a function.

Michael Matz

unread,
Feb 29, 2016, 9:30:53 AM2/29/16
to H.J. Lu, Hans Wennborg, x86-6...@googlegroups.com
Hi,
So, thinking more about this, also the other part for 8 and 16 bit types
creates a stricter contract (requiring zero/sigh bits in the upper part)
than what the psABI right now gives you. So also for these compilers we'd
require checking that they in fact follow it already before putting in
these new restrictions.


Ciao,
Michael.

Hans Wennborg

unread,
Feb 29, 2016, 11:50:59 AM2/29/16
to Michael Matz, H.J. Lu, x86-6...@googlegroups.com
LLVM does sign- or zero-extend 8- and 16-bit arguments when passed to
a function. (In the called function, it doesn't (yet?) rely on them
having been extended, though.)

I can't say for sure about GCC, but from what I understand, it's doing
the same. See also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=46942

Thanks,
Hans

Hans Wennborg

unread,
Mar 8, 2016, 4:16:56 PM3/8/16
to Michael Matz, H.J. Lu, x86-6...@googlegroups.com
I learned that LLVM does rely on 8- and 16-bit arguments having been
sign/zero-extended when passed to a function in registers since 2007:
http://reviews.llvm.org/rL34623

It would be great if we could get some clarification from the psABI on this.

Thanks,
Hans
Reply all
Reply to author
Forward
0 new messages