From patchwork Fri Mar 29 22:41:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 32092 Received: (qmail 29440 invoked by alias); 29 Mar 2019 22:41:30 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 29404 invoked by uid 89); 29 Mar 2019 22:41:26 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=65, authentication, UD:gdb.texinfo, UD:texinfo X-HELO: mail-wr1-f66.google.com Received: from mail-wr1-f66.google.com (HELO mail-wr1-f66.google.com) (209.85.221.66) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 29 Mar 2019 22:41:22 +0000 Received: by mail-wr1-f66.google.com with SMTP id y7so4374292wrn.11 for ; Fri, 29 Mar 2019 15:41:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=FjMhNNVvQLKDuIFhBCVurDL6vJDW0zocdvIK3uRxyjs=; b=Nx2Jb8JVSJmq3I2myN6WKlQh+NGaafbuzm9DpZaZXDF5vbNzO1OHg/EMiZluKWII09 /miEi4lrw0xez8UYl0VOg9FHYnZyrP6sfvgrTUFm81LM4xOuYuQc69cAry9RUf7dTX2x DpKpsKgrYcYg5huqno70Ue6AVpyQ6N6Wp3wEGKhIVwKmZFE22D+Oh9MEbjMhOiF2sY51 i3oSxl99a0nuNgXZcNfaZBfj1yCGr7cGJWTSyrk3GQYI6aQctMluwuP0/x0atNjyiX/K 8qDWslIKtsfboGp2Z3iQu2WYFVhig2PTc+yFDo2VzY9ZeaCTiwr+FTVprVUnn46j5/71 h5lA== Return-Path: Received: from localhost (host81-151-161-58.range81-151.btcentralplus.com. [81.151.161.58]) by smtp.gmail.com with ESMTPSA id g3sm2400287wmk.32.2019.03.29.15.41.17 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 29 Mar 2019 15:41:17 -0700 (PDT) Date: Fri, 29 Mar 2019 22:41:16 +0000 From: Andrew Burgess To: Eli Zaretskii Cc: gdb-patches@sourceware.org, Richard.Bunt@arm.com Subject: Re: [PATCH 1/8] gdb: Add $_cimag and $_creal internal functions Message-ID: <20190329224116.GI10887@embecosm.com> References: <854230b716fa6838bd2d8e73f1fd2d342a7a75ed.1552913183.git.andrew.burgess@embecosm.com> <83va0gumjp.fsf@gnu.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <83va0gumjp.fsf@gnu.org> X-Fortune: The revolution will not be televised. X-Editor: GNU Emacs [ http://www.gnu.org/software/emacs ] User-Agent: Mutt/1.9.2 (2017-12-15) X-IsSubscribed: yes * Eli Zaretskii [2019-03-18 19:20:26 +0200]: > > From: Andrew Burgess > > Cc: Richard Bunt , Andrew Burgess > > Date: Mon, 18 Mar 2019 12:52:16 +0000 > > > > 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'. > > The documentation parts are okay, with a couple of comments: > > > +@item $_cimag(@var{value}) > > +@findex $_cimag@r{, convenience function} > > +Return the imaginary part of a complex number @var{value}. > > + > > +The type of the imaginary part depends on the type of the complex > > +number, a @code{float complex} will return an imaginary part of type > > +@code{float}. > > + > > +@item $_creal(@var{value}) > > +@findex $_creal@r{, convenience function} > > +Return the real part of a complex number @var{value}. > > + > > +The type of the real part depends on the type of the complex number, a > > +@code{float complex} will return an real part of type @code{float}. > > There's no need to repeat the sentence about the type being dependent > on the original type; you can say that just once for both. Thanks for your feedback. What I've done is group the @item entries for $_creal and $_cimag together. My thinking is that if a user looks up either of these then the documentation should be complete. If I left the @item entries separate, and removed the sentence as you suggested then I think I'd have to add a cross reference. Hopefully this will be OK. All your other feedback has been addressed. A new version of the patch is below for your consideration. Thanks, Andrew > > Also, the "a @code{float complex} will return ..." part is better > preceded by "e.g.", as this is an example, right? > > And finally, "a real part", not "an real part". > > > +Return the real part of a complex number, the type depends on the\n\ > > +type of a complex number."), > ^ > "the", not "a". > > > +Return the imaginary part of a complex number, the type depends on the\n\ > > +type of a complex number."), > > Likewise. --- 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 = 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. diff --git a/gdb/NEWS b/gdb/NEWS index edcc9c951a0..6d700d1cf32 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -10,6 +10,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. + *** Changes in GDB 8.3 * GDB and GDBserver now support access to additional registers on diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 4c1d5e8294f..6dda71d83c0 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -11390,6 +11390,17 @@ Visiting node of type NODE_INTEGER @end smallexample +@item $_cimag(@var{value}) +@item $_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 diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 658c86264bf..e742931ad53 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -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: diff --git a/gdb/testsuite/gdb.base/complex-parts.c b/gdb/testsuite/gdb.base/complex-parts.c new file mode 100644 index 00000000000..243caee0695 --- /dev/null +++ b/gdb/testsuite/gdb.base/complex-parts.c @@ -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 . */ + +/* 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 + +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. */ +} diff --git a/gdb/testsuite/gdb.base/complex-parts.exp b/gdb/testsuite/gdb.base/complex-parts.exp new file mode 100644 index 00000000000..ce8f4277a8b --- /dev/null +++ b/gdb/testsuite/gdb.base/complex-parts.exp @@ -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 . + +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" diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp index ece1428e617..bdae0d471e7 100644 --- a/gdb/testsuite/gdb.base/default.exp +++ b/gdb/testsuite/gdb.base/default.exp @@ -601,6 +601,8 @@ set show_conv_list \ {$_probe_arg9 = } \ {$_probe_arg10 = } \ {$_probe_arg11 = } \ + {$_cimag = } \ + {$_creal = } \ {$_isvoid = } \ } if ![skip_python_tests] { diff --git a/gdb/value.c b/gdb/value.c index dc297dfe0f9..d011b396986 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -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."), _("\