gdb: Add $_cimag and $_creal internal functions

Add two new internal functions $_cimag and $_creal that extract the
imaginary and real parts of a complex value.

These internal functions can take a complex value of any type 'float
complex', 'double complex', or 'long double complex' and return a
suitable floating point value 'float', 'double', or 'long double'.
So we can now do this:

    (gdb) p z1
    $1 = 1.5 + 4.5 * I
    (gdb) p $_cimag (z1)
    $4 = 4.5
    (gdb) p $_creal (z1)
    $4 = 1.5

The components of a complex value are not strictly named types in
DWARF, as the complex type is itself the base type.  However, once we
are able to extract the components it makes sense to be able to ask
what the type of these components is and get a sensible answer back,
rather than the error we would currently get.  Currently GDB says:

    (gdb) ptype z1
    type = complex double
    (gdb) p $_cimag (z1)
    $4 = 4.5
    (gdb) ptype $
    type = <invalid type code 9>

With the changes in dwarf2read.c, GDB now says:

    (gdb) ptype z1
    type = complex double
    (gdb) p $_cimag (z1)
    $4 = 4.5
    (gdb) ptype $
    type = double

Which seems to make more sense.

gdb/ChangeLog:

	* NEWS: Mention new internal functions.
	* dwarf2read.c (dwarf2_init_complex_target_type): New function.
	(read_base_type): Use dwarf2_init_complex_target_type.
	* value.c (creal_internal_fn): New function.
	(cimag_internal_fn): New function.
	(_initialize_values): Register new internal functions.

gdb/doc/ChangeLog:

	* gdb.texinfo (Convenience Funs): Document '$_creal' and
	'$_cimag'.

gdb/testsuite/ChangeLog:

	* gdb.base/complex-parts.c: New file.
	* gdb.base/complex-parts.exp: New file.
This commit is contained in:
Andrew Burgess 2019-03-14 13:58:58 +00:00
parent c29705b71a
commit 8bdc16587e
10 changed files with 234 additions and 2 deletions

View File

@ -1,3 +1,12 @@
2019-04-01 Andrew Burgess <andrew.burgess@embecosm.com>
* NEWS: Mention new internal functions.
* dwarf2read.c (dwarf2_init_complex_target_type): New function.
(read_base_type): Use dwarf2_init_complex_target_type.
* value.c (creal_internal_fn): New function.
(cimag_internal_fn): New function.
(_initialize_values): Register new internal functions.
2019-04-01 Philippe Waroquiers <philippe.waroquiers@skynet.be>
* infrun.c (stop_all_threads): If debug_infrun, always

View File

@ -16,6 +16,9 @@
* Support for Pointer Authentication on AArch64 Linux.
* Two new convernience functions $_cimag and $_creal that extract the
imaginary and real parts respectively from complex numbers.
* Python API
** The gdb.Value type has a new method 'format_string' which returns a
@ -24,7 +27,6 @@
'array_indexes', 'symbols', 'unions', 'deref_refs', 'actual_objects',
'static_members', 'max_elements', 'repeat_threshold', and 'format'.
*** Changes in GDB 8.3
* GDB and GDBserver now support access to additional registers on

View File

@ -1,3 +1,8 @@
2019-04-01 Andrew Burgess <andrew.burgess@embecosm.com>
* gdb.texinfo (Convenience Funs): Document '$_creal' and
'$_cimag'.
2019-03-30 Eli Zaretskii <eliz@gnu.org>
* gdb.texinfo (Convenience Vars): Document $_gdb_major and

View File

@ -11401,6 +11401,17 @@ an enumerated type:
Visiting node of type NODE_INTEGER
@end smallexample
@item $_cimag(@var{value})
@itemx $_creal(@var{value})
@findex $_cimag@r{, convenience function}
@findex $_creal@r{, convenience function}
Return the imaginary (@code{$_cimag}) or real (@code{$_creal}) part of
the complex number @var{value}.
The type of the imaginary or real part depends on the type of the
complex number, e.g., using @code{$_cimag} on a @code{float complex}
will return an imaginary part of type @code{float}.
@end table
@value{GDBN} provides the ability to list and get help on

View File

@ -17530,6 +17530,40 @@ dwarf2_init_integer_type (struct dwarf2_cu *cu, struct objfile *objfile,
return type;
}
/* Initialise and return a floating point type of size BITS suitable for
use as a component of a complex number. The NAME_HINT is passed through
when initialising the floating point type and is the name of the complex
type.
As DWARF doesn't currently provide an explicit name for the components
of a complex number, but it can be helpful to have these components
named, we try to select a suitable name based on the size of the
component. */
static struct type *
dwarf2_init_complex_target_type (struct dwarf2_cu *cu,
struct objfile *objfile,
int bits, const char *name_hint)
{
gdbarch *gdbarch = get_objfile_arch (objfile);
struct type *tt = nullptr;
switch (bits)
{
case 32:
tt = builtin_type (gdbarch)->builtin_float;
break;
case 64:
tt = builtin_type (gdbarch)->builtin_double;
break;
case 128:
tt = builtin_type (gdbarch)->builtin_long_double;
break;
}
const char *name = (tt == nullptr) ? nullptr : TYPE_NAME (tt);
return dwarf2_init_float_type (objfile, bits, name, name_hint);
}
/* Find a representation of a given base type and install
it in the TYPE field of the die. */
@ -17569,7 +17603,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
type = init_boolean_type (objfile, bits, 1, name);
break;
case DW_ATE_complex_float:
type = dwarf2_init_float_type (objfile, bits / 2, NULL, name);
type = dwarf2_init_complex_target_type (cu, objfile, bits / 2, name);
type = init_complex_type (objfile, name, type);
break;
case DW_ATE_decimal_float:

View File

@ -1,3 +1,8 @@
2019-04-01 Andrew Burgess <andrew.burgess@embecosm.com>
* gdb.base/complex-parts.c: New file.
* gdb.base/complex-parts.exp: New file.
2019-04-01 Tom Tromey <tromey@adacore.com>
PR symtab/23331:

View File

@ -0,0 +1,50 @@
/* Copyright 2019 Free Software Foundation, Inc.
This file is part of GDB.
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/>. */
/* Unlike the other 'complex.c' test, this one uses the "standard" header
file to pull in the complex types. The testing is around printing the
complex numbers, and using the convenience function $_cimag and $_creal
to extract the parts of the complex numbers. */
#include <complex.h>
void
keep_around (volatile void *ptr)
{
asm ("" ::: "memory");
}
int
main (void)
{
double complex z1 = 1.5 + 4.5 * I;
float complex z2 = 2.5 - 5.5 * I;
long double complex z3 = 3.5 + 6.5 * I;
double d1 = 1.5;
float f1 = 2.5;
int i1 = 3;
keep_around (&z1);
keep_around (&z2);
keep_around (&z3);
keep_around (&d1);
keep_around (&f1);
keep_around (&i1);
return 0; /* Break Here. */
}

View File

@ -0,0 +1,62 @@
# Copyright 2019 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/>.
standard_testfile
if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug]} {
return -1
}
if { ![runto_main] } then {
fail "can't run to main"
return 0
}
gdb_breakpoint [gdb_get_line_number "Break Here"]
gdb_continue_to_breakpoint "breakpt" ".* Break Here\\. .*"
gdb_test "p z1" " = 1.5 \\+ 4.5 \\* I"
gdb_test "p z2" " = 2.5 \\+ -5.5 \\* I"
gdb_test "p z3" " = 3.5 \\+ 6.5 \\* I"
gdb_test "ptype z1" " = complex double"
gdb_test "ptype z2" " = complex float"
gdb_test "ptype z3" " = complex long double"
gdb_test "p \$_cimag (z1)" " = 4.5"
gdb_test "ptype \$" " = double"
gdb_test "p \$_cimag (z2)" " = -5.5"
gdb_test "ptype \$" " = float"
gdb_test "p \$_cimag (z3)" " = 6.5"
gdb_test "ptype \$" " = long double"
gdb_test "p \$_creal (z1)" " = 1.5"
gdb_test "ptype \$" " = double"
gdb_test "p \$_creal (z2)" " = 2.5"
gdb_test "ptype \$" " = float"
gdb_test "p \$_creal (z3)" " = 3.5"
gdb_test "ptype \$" " = long double"
gdb_test "p \$_cimag (d1)" "expected a complex number"
gdb_test "p \$_cimag (f1)" "expected a complex number"
gdb_test "p \$_cimag (i1)" "expected a complex number"
gdb_test "p \$_creal (d1)" "expected a complex number"
gdb_test "p \$_creal (f1)" "expected a complex number"
gdb_test "p \$_creal (i1)" "expected a complex number"

View File

@ -601,6 +601,8 @@ set show_conv_list \
{$_probe_arg9 = <error: No frame selected>} \
{$_probe_arg10 = <error: No frame selected>} \
{$_probe_arg11 = <error: No frame selected>} \
{$_cimag = <internal function _cimag>} \
{$_creal = <internal function _creal>} \
{$_isvoid = <internal function _isvoid>} \
{$_gdb_major = 8} \
{$_gdb_minor = 4} \

View File

@ -3933,6 +3933,44 @@ isvoid_internal_fn (struct gdbarch *gdbarch,
return value_from_longest (builtin_type (gdbarch)->builtin_int, ret);
}
/* Implementation of the convenience function $_cimag. Extracts the
real part from a complex number. */
static struct value *
creal_internal_fn (struct gdbarch *gdbarch,
const struct language_defn *language,
void *cookie, int argc, struct value **argv)
{
if (argc != 1)
error (_("You must provide one argument for $_creal."));
value *cval = argv[0];
type *ctype = check_typedef (value_type (cval));
if (TYPE_CODE (ctype) != TYPE_CODE_COMPLEX)
error (_("expected a complex number"));
return value_from_component (cval, TYPE_TARGET_TYPE (ctype), 0);
}
/* Implementation of the convenience function $_cimag. Extracts the
imaginary part from a complex number. */
static struct value *
cimag_internal_fn (struct gdbarch *gdbarch,
const struct language_defn *language,
void *cookie, int argc,
struct value **argv)
{
if (argc != 1)
error (_("You must provide one argument for $_cimag."));
value *cval = argv[0];
type *ctype = check_typedef (value_type (cval));
if (TYPE_CODE (ctype) != TYPE_CODE_COMPLEX)
error (_("expected a complex number"));
return value_from_component (cval, TYPE_TARGET_TYPE (ctype),
TYPE_LENGTH (TYPE_TARGET_TYPE (ctype)));
}
#if GDB_SELF_TEST
namespace selftests
{
@ -4114,6 +4152,20 @@ Usage: $_isvoid (expression)\n\
Return 1 if the expression is void, zero otherwise."),
isvoid_internal_fn, NULL);
add_internal_function ("_creal", _("\
Extract the real part of a complex number.\n\
Usage: $_creal (expression)\n\
Return the real part of a complex number, the type depends on the\n\
type of a complex number."),
creal_internal_fn, NULL);
add_internal_function ("_cimag", _("\
Extract the imaginary part of a complex number.\n\
Usage: $_cimag (expression)\n\
Return the imaginary part of a complex number, the type depends on the\n\
type of a complex number."),
cimag_internal_fn, NULL);
add_setshow_zuinteger_unlimited_cmd ("max-value-size",
class_support, &max_value_size, _("\
Set maximum sized value gdb will load from the inferior."), _("\