From: Joel Brobecker Date: Fri, 29 Jan 2010 14:39:04 +0000 (+0000) Subject: amd64 - function returning record with field straddling 2 registers X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e4e2711a4aea4b4c12347d12ad9987432ff4b21f;p=binutils-gdb.git amd64 - function returning record with field straddling 2 registers gdb/ChangeLog: From Paul Hilfinger * amd64-tdep.c (amd_classify_aggregate): Handle the case of a record of length <= 16 in which a field straddles the two eightbytes. gdb/testsuite/ChangeLog: * gdb.ada/rec_return: New testcase. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index da9d6f2cb5f..d7b426d7f57 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2010-01-29 Paul Hilfinger + + amd64 - function returning record with field straddling 2 registers. + * amd64-tdep.c (amd_classify_aggregate): Handle the case of + a record of length <= 16 in which a field straddles the two + eightbytes. + 2010-01-29 Joel Brobecker Implement return values on amd64-windows. diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index fc621e0ee2d..2b151415490 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -347,6 +347,12 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2]) struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i)); int pos = TYPE_FIELD_BITPOS (type, i) / 64; enum amd64_reg_class subclass[2]; + int bitsize = TYPE_FIELD_BITSIZE (type, i); + int endpos; + + if (bitsize == 0) + bitsize = TYPE_LENGTH (subtype) * 8; + endpos = (TYPE_FIELD_BITPOS (type, i) + bitsize - 1) / 64; /* Ignore static fields. */ if (field_is_static (&TYPE_FIELD (type, i))) @@ -356,6 +362,30 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2]) amd64_classify (subtype, subclass); class[pos] = amd64_merge_classes (class[pos], subclass[0]); + if (bitsize <= 64 && pos == 0 && endpos == 1) + /* This is a bit of an odd case: We have a field that would + normally fit in one of the two eightbytes, except that + it is placed in a way that this field straddles them. + This has been seen with a structure containing an array. + + The ABI is a bit unclear in this case, but we assume that + this field's class (stored in subclass[0]) must also be merged + into class[1]. In other words, our field has a piece stored + in the second eight-byte, and thus its class applies to + the second eight-byte as well. + + In the case where the field length exceeds 8 bytes, + it should not be necessary to merge the field class + into class[1]. As LEN > 8, subclass[1] is necessarily + different from AMD64_NO_CLASS. If subclass[1] is equal + to subclass[0], then the normal class[1]/subclass[1] + merging will take care of everything. For subclass[1] + to be different from subclass[0], I can only see the case + where we have a SSE/SSEUP or X87/X87UP pair, which both + use up all 16 bytes of the aggregate, and are already + handled just fine (because each portion sits on its own + 8-byte). */ + class[1] = amd64_merge_classes (class[1], subclass[0]); if (pos == 0) class[1] = amd64_merge_classes (class[1], subclass[1]); } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 99c2134102d..d92ded29722 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2010-01-29 Joel Brobecker + + * gdb.ada/rec_return: New testcase. + 2010-01-29 Joel Brobecker * gdb.ada/call_pn: New testcase. diff --git a/gdb/testsuite/gdb.ada/rec_return.exp b/gdb/testsuite/gdb.ada/rec_return.exp new file mode 100644 index 00000000000..8d7035cf384 --- /dev/null +++ b/gdb/testsuite/gdb.ada/rec_return.exp @@ -0,0 +1,46 @@ +# Copyright 2010 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +if $tracelevel then { + strace $tracelevel +} + +load_lib "ada.exp" + +set testdir "rec_return" +set testfile "${testdir}/foo" +set srcfile ${srcdir}/${subdir}/${testfile}.adb +set binfile ${objdir}/${subdir}/${testfile} + +file mkdir ${objdir}/${subdir}/${testdir} +if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug ]] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +set bp_location [gdb_get_line_number "STOP" ${testdir}/foo.adb] +if ![runto "foo.adb:$bp_location" ] then { + perror "Couldn't run ${testfile}" + return +} + +gdb_test "print bar" \ + "= \\(x => 42, s => \"ABCDEFGH\"\\)" \ + "print bar" + diff --git a/gdb/testsuite/gdb.ada/rec_return/foo.adb b/gdb/testsuite/gdb.ada/rec_return/foo.adb new file mode 100644 index 00000000000..a32d81721ea --- /dev/null +++ b/gdb/testsuite/gdb.ada/rec_return/foo.adb @@ -0,0 +1,24 @@ +-- Copyright 2010 Free Software Foundation, Inc. +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . + +with Pck; use Pck; + +procedure Foo is + Q: Rec; +begin + Q := Bar; -- STOP HERE + Do_Nothing (Q'Address); +end Foo; + diff --git a/gdb/testsuite/gdb.ada/rec_return/pck.adb b/gdb/testsuite/gdb.ada/rec_return/pck.adb new file mode 100644 index 00000000000..fb421642771 --- /dev/null +++ b/gdb/testsuite/gdb.ada/rec_return/pck.adb @@ -0,0 +1,27 @@ +-- Copyright 2010 Free Software Foundation, Inc. +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . + +package body Pck is + function Bar return Rec is + begin + return (X => 42, S => "ABCDEFGH"); + end Bar; + + procedure Do_Nothing (A : System.Address) is + begin + null; + end Do_Nothing; +end Pck; + diff --git a/gdb/testsuite/gdb.ada/rec_return/pck.ads b/gdb/testsuite/gdb.ada/rec_return/pck.ads new file mode 100644 index 00000000000..a890f4a1fc4 --- /dev/null +++ b/gdb/testsuite/gdb.ada/rec_return/pck.ads @@ -0,0 +1,28 @@ +-- Copyright 2010 Free Software Foundation, Inc. +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . + +with System; + +package Pck is + type Rec is record + X: Integer; + S: String (1..8); + end record; + + function Bar return Rec; + procedure Do_Nothing (A : System.Address); + +end Pck; +