diff options
author | Mark Wielaard <mark@klomp.org> | 2024-03-19 22:43:10 +0000 |
---|---|---|
committer | Mark Wielaard <mark@klomp.org> | 2024-03-19 23:46:13 +0100 |
commit | 6583e50b1f145db9895882af52365b2e587440d8 (patch) | |
tree | a1021d0f11d86d455cd898a623d9753b6ba6a261 | |
parent | ec5ce487c15dcd709d033dd5693b468ac34223ce (diff) |
funcretval-structupstream/users/mark/try-funcretval-struct
-rw-r--r-- | backends/riscv_retval.c | 123 | ||||
-rw-r--r-- | tests/Makefile.am | 7 | ||||
-rw-r--r-- | tests/funcretval_test_struct.c | 86 | ||||
-rwxr-xr-x | tests/funcretval_test_struct_riscv.bz2 | bin | 0 -> 3821 bytes | |||
-rwxr-xr-x | tests/run-funcretval-struct-native.sh | 22 | ||||
-rwxr-xr-x | tests/run-funcretval-struct.sh | 35 |
6 files changed, 262 insertions, 11 deletions
diff --git a/backends/riscv_retval.c b/backends/riscv_retval.c index 0a1e02f8..50c451a4 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 9141074f..9315ec3b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -162,6 +162,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \ run-addr2line-C-test.sh \ run-addr2line-i-test.sh run-addr2line-i-lex-test.sh \ run-addr2line-i-demangle-test.sh run-addr2line-alt-debugpath.sh \ + run-funcretval-struct.sh \ run-varlocs.sh run-exprlocs.sh run-varlocs-vars.sh run-funcretval.sh \ run-backtrace-native.sh run-backtrace-data.sh run-backtrace-dwarf.sh \ run-backtrace-native-biarch.sh run-backtrace-native-core.sh \ @@ -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 \ @@ -478,6 +483,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ testfile_aarch64_core.bz2 testfile_i686_core.bz2 \ addrx_constx-4.dwo.bz2 addrx_constx-5.dwo.bz2 \ testfile-addrx_constx-4.bz2 testfile-addrx_constx-5.bz2 \ + run-funcretval-struct.sh funcretval_test_struct_riscv.bz2 \ run-funcretval.sh funcretval_test.c funcretval_test_aarch64.bz2 \ run-backtrace-data.sh run-backtrace-dwarf.sh cleanup-13.c \ run-backtrace-native.sh run-backtrace-native-biarch.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 00000000..df94bde0 --- /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/funcretval_test_struct_riscv.bz2 b/tests/funcretval_test_struct_riscv.bz2 Binary files differnew file mode 100755 index 00000000..de3e5ba9 --- /dev/null +++ b/tests/funcretval_test_struct_riscv.bz2 diff --git a/tests/run-funcretval-struct-native.sh b/tests/run-funcretval-struct-native.sh new file mode 100755 index 00000000..798edb3b --- /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 diff --git a/tests/run-funcretval-struct.sh b/tests/run-funcretval-struct.sh new file mode 100755 index 00000000..abd1c720 --- /dev/null +++ b/tests/run-funcretval-struct.sh @@ -0,0 +1,35 @@ +#! /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 + +# The test files are the native funcretval_test_struct files +# funcretval_test_struct.c +# See also run-funcretval-struct-native.sh + +testfiles funcretval_test_struct_riscv + +testrun_compare ${abs_top_builddir}/tests/funcretval \ + -e funcretval_test_struct_riscv <<\EOF +() main: return value location: {0x5a, 0} +() dmkpt: return value location: {0x90, 0x2a} {0x93, 0x8} {0x90, 0x2b} {0x93, 0x8} +() mkpt: return value location: {0x90, 0x2a} +() ldiv: return value location: {0x5a, 0} {0x93, 0x8} {0x5b, 0} {0x93, 0x8} +() div: return value location: {0x5a, 0} +EOF + +exit 0 |