aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Brobecker <brobecker@gnat.com>2010-01-29 14:39:04 +0000
committerJoel Brobecker <brobecker@gnat.com>2010-01-29 14:39:04 +0000
commite4e2711a4aea4b4c12347d12ad9987432ff4b21f (patch)
treeef3cc5cd9585f1470781ee74ff6d56d681a0b885
parentcba6fab54a80261d8f1e6831bc5c560481cfc107 (diff)
downloadfsf-binutils-gdb-e4e2711a4aea4b4c12347d12ad9987432ff4b21f.zip
fsf-binutils-gdb-e4e2711a4aea4b4c12347d12ad9987432ff4b21f.tar.gz
fsf-binutils-gdb-e4e2711a4aea4b4c12347d12ad9987432ff4b21f.tar.bz2
amd64 - function returning record with field straddling 2 registers
gdb/ChangeLog: From Paul Hilfinger <hilfinger@adacore.com> * 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.
-rw-r--r--gdb/ChangeLog7
-rw-r--r--gdb/amd64-tdep.c30
-rw-r--r--gdb/testsuite/ChangeLog4
-rw-r--r--gdb/testsuite/gdb.ada/rec_return.exp46
-rw-r--r--gdb/testsuite/gdb.ada/rec_return/foo.adb24
-rw-r--r--gdb/testsuite/gdb.ada/rec_return/pck.adb27
-rw-r--r--gdb/testsuite/gdb.ada/rec_return/pck.ads28
7 files changed, 166 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index da9d6f2..d7b426d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,10 @@
+2010-01-29 Paul Hilfinger <hilfinger@adacore.com>
+
+ 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 <brobecker@adacore.com>
Implement return values on amd64-windows.
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index fc621e0..2b15141 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 99c2134..d92ded2 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2010-01-29 Joel Brobecker <brobecker@adacore.com>
+ * gdb.ada/rec_return: New testcase.
+
+2010-01-29 Joel Brobecker <brobecker@adacore.com>
+
* gdb.ada/call_pn: New testcase.
2010-01-28 Daniel Jacobowitz <dan@codesourcery.com>
diff --git a/gdb/testsuite/gdb.ada/rec_return.exp b/gdb/testsuite/gdb.ada/rec_return.exp
new file mode 100644
index 0000000..8d7035c
--- /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 <http://www.gnu.org/licenses/>.
+
+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 0000000..a32d817
--- /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 <http://www.gnu.org/licenses/>.
+
+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 0000000..fb42164
--- /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 <http://www.gnu.org/licenses/>.
+
+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 0000000..a890f4a1
--- /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 <http://www.gnu.org/licenses/>.
+
+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;
+