summaryrefslogtreecommitdiff
path: root/elfutils-0.190-riscv-flatten.patch
diff options
context:
space:
mode:
Diffstat (limited to 'elfutils-0.190-riscv-flatten.patch')
-rw-r--r--elfutils-0.190-riscv-flatten.patch359
1 files changed, 359 insertions, 0 deletions
diff --git a/elfutils-0.190-riscv-flatten.patch b/elfutils-0.190-riscv-flatten.patch
new file mode 100644
index 0000000..a96d339
--- /dev/null
+++ b/elfutils-0.190-riscv-flatten.patch
@@ -0,0 +1,359 @@
+From e39336df6588c3f9853be7d02819aee262ba2121 Mon Sep 17 00:00:00 2001
+From: Mark Wielaard <mark@klomp.org>
+Date: Tue, 19 Mar 2024 22:43:10 +0000
+Subject: [PATCH] riscv: Partial implementation of flatten_aggregate
+
+dwfl_module_return_value_location would fail on riscv for functions
+which return a (small) struct. This patch implements the simplest
+cases of flatten_aggregate in backends/riscv_retval.c. It just handles
+structs containing one or two members of the same base type which fit
+completely or in pieces in one or two general or floating point
+registers.
+
+It also adds a specific test case run-funcretval-struct.sh containing
+small structs of ints, longs, floats and doubles. All these testscases
+now work for riscv. There is already a slightly more extensive
+testcase for this in tests/run-funcretval.sh but that only has a
+testcase for aarch64.
+
+ * backends/riscv_retval.c (flatten_aggregate_arg): Implement
+ for the simple cases where we have a struct with one or two
+ members of the same base type.
+ (pass_by_flattened_arg): Likewise. Call either
+ pass_in_gpr_lp64 or pass_in_fpr_lp64d.
+ (riscv_return_value_location_lp64ifd): Call
+ flatten_aggregate_arg including size.
+ * tests/Makefile.am (TESTS): Add run-funcretval-struct.sh
+ and run-funcretval-struct-native.sh.
+ (check_PROGRAMS): Add funcretval_test_struct.
+ (funcretval_test_struct_SOURCES): New.
+ (EXTRA_DIST): Add run-funcretval-struct.sh,
+ funcretval_test_struct_riscv.bz2 and
+ run-funcretval-struct-native.sh.
+ * tests/funcretval_test_struct_riscv.bz2: New test binary.
+ * tests/run-funcretval-struct-native.sh: New test.
+ * tests/run-funcretval-struct.sh: Likewise.
+
+https://sourceware.org/bugzilla/show_bug.cgi?id=31142
+
+Signed-off-by: Mark Wielaard <mark@klomp.org>
+---
+ backends/riscv_retval.c | 123 ++++++++++++++++++++++---
+ tests/Makefile.am | 7 ++
+ tests/funcretval_test_struct.c | 86 +++++++++++++++++
+ tests/funcretval_test_struct_riscv.bz2 | Bin 0 -> 3821 bytes
+ tests/run-funcretval-struct-native.sh | 22 +++++
+ tests/run-funcretval-struct.sh | 35 +++++++
+ 6 files changed, 262 insertions(+), 11 deletions(-)
+ create mode 100644 tests/funcretval_test_struct.c
+ create mode 100755 tests/funcretval_test_struct_riscv.bz2
+ create mode 100755 tests/run-funcretval-struct-native.sh
+ create mode 100755 tests/run-funcretval-struct.sh
+
+Fedora NOTE: Both the riscv specific test files weren't included
+ (funcretval_test_struct_riscv.bz2 and run-funcretval-struct.sh)
+ Because it contained a binary test. The native test is included
+ though.
+
+diff --git a/backends/riscv_retval.c b/backends/riscv_retval.c
+index 0a1e02f81cd2..50c451a4ba32 100644
+--- a/backends/riscv_retval.c
++++ b/backends/riscv_retval.c
+@@ -1,6 +1,7 @@
+ /* Function return value location for Linux/RISC-V ABI.
+ Copyright (C) 2018 Sifive, Inc.
+ Copyright (C) 2013 Red Hat, Inc.
++ Copyright (C) 2024 Mark J. Wielaard <mark@klomp.org>
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+@@ -105,23 +106,123 @@ pass_in_fpr_lp64d (const Dwarf_Op **locp, Dwarf_Word size)
+ return size <= 8 ? 1 : 4;
+ }
+
++/* Checks if we can "flatten" the given type, Only handles the simple
++ cases where we have a struct with one or two the same base type
++ elements. */
+ static int
+-flatten_aggregate_arg (Dwarf_Die *typedie __attribute__ ((unused)),
+- Dwarf_Die *arg0 __attribute__ ((unused)),
+- Dwarf_Die *arg1 __attribute__ ((unused)))
++flatten_aggregate_arg (Dwarf_Die *typedie,
++ Dwarf_Word size,
++ Dwarf_Die *arg0,
++ Dwarf_Die *arg1)
+ {
+- /* ??? */
++ int tag0, tag1;
++ Dwarf_Die member;
++ Dwarf_Word encoding0, encoding1;
++ Dwarf_Attribute attr;
++ Dwarf_Word size0, size1;
++
++ if (size < 8 || size > 16)
++ return 0;
++
++ if (dwarf_child (typedie, arg0) != 0)
++ return 0;
++
++ tag0 = dwarf_tag (arg0);
++ while (tag0 != -1 && tag0 != DW_TAG_member)
++ {
++ if (dwarf_siblingof (arg0, arg0) != 0)
++ return 0;
++ tag0 = dwarf_tag (arg0);
++ }
++
++ if (tag0 != DW_TAG_member)
++ return 0;
++
++ /* Remember where we are. */
++ member = *arg0;
++
++ tag0 = dwarf_peeled_die_type (arg0, arg0);
++ if (tag0 != DW_TAG_base_type)
++ return 0;
++
++ if (dwarf_attr_integrate (arg0, DW_AT_encoding, &attr) == NULL
++ || dwarf_formudata (&attr, &encoding0) != 0)
++ return 0;
++
++ if (dwarf_bytesize_aux (arg0, &size0) != 0)
++ return 0;
++
++ if (size == size0)
++ return 1; /* This one member is the whole size. */
++
++ if (size != 2 * size0)
++ return 0; /* We only handle two of the same. */
++
++ /* Look for another member with the same encoding. */
++ if (dwarf_siblingof (&member, arg1) != 0)
++ return 0;
++
++ tag1 = dwarf_tag (arg1);
++ while (tag1 != -1 && tag1 != DW_TAG_member)
++ {
++ if (dwarf_siblingof (arg1, arg1) != 0)
++ return 0;
++ tag1 = dwarf_tag (arg1);
++ }
++
++ if (tag1 != DW_TAG_member)
++ return 0;
++
++ tag1 = dwarf_peeled_die_type (arg1, arg1);
++ if (tag1 != DW_TAG_base_type)
++ return 0; /* We can only handle two equal base types for now. */
++
++ if (dwarf_attr_integrate (arg1, DW_AT_encoding, &attr) == NULL
++ || dwarf_formudata (&attr, &encoding1) != 0
++ || encoding0 != encoding1)
++ return 0; /* We can only handle two of the same for now. */
++
++ if (dwarf_bytesize_aux (arg1, &size1) != 0)
++ return 0;
++
++ if (size0 != size1)
++ return 0; /* We can only handle two of the same for now. */
++
+ return 1;
+ }
+
++/* arg0 and arg1 should be the peeled die types found by
++ flatten_aggregate_arg. */
+ static int
+-pass_by_flattened_arg (const Dwarf_Op **locp __attribute__ ((unused)),
+- Dwarf_Word size __attribute__ ((unused)),
+- Dwarf_Die *arg0 __attribute__ ((unused)),
+- Dwarf_Die *arg1 __attribute__ ((unused)))
++pass_by_flattened_arg (const Dwarf_Op **locp,
++ Dwarf_Word size,
++ Dwarf_Die *arg0,
++ Dwarf_Die *arg1 __attribute__((unused)))
+ {
+- /* ??? */
+- return -2;
++ /* For now we just assume arg0 and arg1 are the same type and
++ encoding. */
++ Dwarf_Word encoding;
++ Dwarf_Attribute attr;
++
++ if (dwarf_attr_integrate (arg0, DW_AT_encoding, &attr) == NULL
++ || dwarf_formudata (&attr, &encoding) != 0)
++ return -1;
++
++ switch (encoding)
++ {
++ case DW_ATE_boolean:
++ case DW_ATE_signed:
++ case DW_ATE_unsigned:
++ case DW_ATE_unsigned_char:
++ case DW_ATE_signed_char:
++ return pass_in_gpr_lp64 (locp, size);
++
++ case DW_ATE_float:
++ return pass_in_fpr_lp64d (locp, size);
++
++ default:
++ return -1;
++ }
+ }
+
+ int
+@@ -158,7 +259,7 @@ riscv_return_value_location_lp64ifd (int fp, Dwarf_Die *functypedie,
+ provided the floating-point real is no more than FLEN bits wide and
+ the integer is no more than XLEN bits wide. */
+ if (tag == DW_TAG_structure_type
+- && flatten_aggregate_arg (&typedie, &arg0, &arg1))
++ && flatten_aggregate_arg (&typedie, size, &arg0, &arg1))
+ return pass_by_flattened_arg (locp, size, &arg0, &arg1);
+ /* Aggregates larger than 2*XLEN bits are passed by reference. */
+ else if (size > 16)
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 9141074fe44c..9315ec3bbe4c 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -284,6 +285,10 @@ funcretval_test__11_SOURCES = funcretval_test++11.cxx
+ TESTS += run-funcretval++11.sh
+ endif
+
++check_PROGRAMS += funcretval_test_struct
++funcretval_test_struct_SOURCES = funcretval_test_struct.c
++TESTS += run-funcretval-struct-native.sh
++
+ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
+ run-ar-N.sh \
+ run-show-die-info.sh run-get-files.sh run-get-lines.sh \
+@@ -635,6 +641,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
+ testfile_nvidia_linemap.bz2 \
+ testfile-largealign.o.bz2 run-strip-largealign.sh \
+ run-funcretval++11.sh \
++ run-funcretval-struct-native.sh \
+ test-ar-duplicates.a.bz2 \
+ run-dwfl-core-noncontig.sh testcore-noncontig.bz2 \
+ testfile-dwarf5-line-clang.bz2 \
+diff --git a/tests/funcretval_test_struct.c b/tests/funcretval_test_struct.c
+new file mode 100644
+index 000000000000..df94bde0a42d
+--- /dev/null
++++ b/tests/funcretval_test_struct.c
+@@ -0,0 +1,86 @@
++/* Copyright (C) 2024 Mark J. Wielaard <mark@klomp.org>
++ This file is part of elfutils.
++
++ This file 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.
++
++ elfutils 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/>. */
++
++typedef struct
++ {
++ int q;
++ int r;
++ } div_t;
++
++typedef struct
++ {
++ long q;
++ long r;
++ } ldiv_t;
++
++typedef struct
++ {
++ float x;
++ float y;
++ } point_t;
++
++typedef struct
++ {
++ double x;
++ double y;
++ } dpoint_t;
++
++div_t __attribute__((__noinline__))
++div (int n, int d)
++{
++ div_t r;
++ r.q = n / d;
++ r.r = n % d;
++ return r;
++}
++
++ldiv_t __attribute__((__noinline__))
++ldiv (long n, long d)
++{
++ ldiv_t r;
++ r.q = n / d;
++ r.r = n % d;
++ return r;
++}
++
++point_t __attribute__((__noinline__))
++mkpt (float x, float y)
++{
++ point_t r;
++ r.x = x;
++ r.y = y;
++ return r;
++}
++
++dpoint_t __attribute__((__noinline__))
++dmkpt (double x, double y)
++{
++ dpoint_t r;
++ r.x = x;
++ r.y = y;
++ return r;
++}
++
++int
++main (void)
++{
++ div_t d = div (3, 2);
++ ldiv_t ld = ldiv (3, 2);
++ point_t p = mkpt (3.0f, 1.0f);
++ dpoint_t dp = dmkpt (3.0d, 1.0d);
++
++ return d.q - (int) p.y + ld.q - (int) dp.y;
++}
+
+diff --git a/tests/run-funcretval-struct-native.sh b/tests/run-funcretval-struct-native.sh
+new file mode 100755
+index 000000000000..798edb3b61b3
+--- /dev/null
++++ b/tests/run-funcretval-struct-native.sh
+@@ -0,0 +1,22 @@
++#! /bin/sh
++# Copyright (C) 2024 Mark J. Wielaard <mark@klomp.org>
++# This file is part of elfutils.
++#
++# This file 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.
++#
++# elfutils 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/>.
++
++. $srcdir/test-subr.sh
++
++# Just run it, we don't know what the native representation is.
++# But it should at least work and not error out.
++testrun $abs_builddir/funcretval -e $abs_builddir/funcretval_test_struct
+--
+2.44.0
+