From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id aG3QLFPldF91dgAAWB0awg (envelope-from ) for ; Wed, 30 Sep 2020 16:06:43 -0400 Received: by simark.ca (Postfix, from userid 112) id B24E71E99A; Wed, 30 Sep 2020 16:06:43 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=MAILING_LIST_MULTI, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id F2E341E590 for ; Wed, 30 Sep 2020 16:06:39 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4A9543986036; Wed, 30 Sep 2020 20:06:39 +0000 (GMT) Received: from rock.gnat.com (rock.gnat.com [205.232.38.15]) by sourceware.org (Postfix) with ESMTP id D11893971C49 for ; Wed, 30 Sep 2020 20:06:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org D11893971C49 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=adacore.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tromey@adacore.com Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id A70981174A2; Wed, 30 Sep 2020 16:06:05 -0400 (EDT) X-Virus-Scanned: Debian amavisd-new at gnat.com Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id LiQMk5wgSm+p; Wed, 30 Sep 2020 16:06:05 -0400 (EDT) Received: from murgatroyd.Home (97-118-100-18.hlrn.qwest.net [97.118.100.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by rock.gnat.com (Postfix) with ESMTPSA id 6188B116F1D; Wed, 30 Sep 2020 16:06:05 -0400 (EDT) From: Tom Tromey To: gdb-patches@sourceware.org Subject: [PATCH 2/9] Fix decoding of multi-dimensional constrained packed arrays Date: Wed, 30 Sep 2020 14:05:53 -0600 Message-Id: <20200930200600.1207702-3-tromey@adacore.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200930200600.1207702-1-tromey@adacore.com> References: <20200930200600.1207702-1-tromey@adacore.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Tom Tromey Errors-To: gdb-patches-bounces@sourceware.org Sender: "Gdb-patches" Printing a multi-dimensional constrained packed array in Ada would not show the correct values. The bug here is that, when decoding the type of such an array, only the innermost dimension's element bitsize would be correct. For outer dimensions, the bitsize must account for the size of each sub-array, but this was not done. This patch fixes the problem by arranging to compute these sizes after decoding the array type. I've included a bit more test case than is strictly necessary -- the current test here was derived from an internal test, and this patch brings the two into sync. 2020-09-30 Tom Tromey * ada-lang.c (recursively_update_array_bitsize): New function. (decode_constrained_packed_array_type): Call it. gdb/testsuite/ChangeLog 2020-09-30 Tom Tromey * gdb.ada/enum_idx_packed.exp: Add tests. * gdb.ada/enum_idx_packed/foo.adb: Add variables. * gdb.ada/enum_idx_packed/pck.adb: Add functions. * gdb.ada/enum_idx_packed/pck.ads: Add types, function declarations. --- gdb/ChangeLog | 5 ++ gdb/ada-lang.c | 41 ++++++++++++++++ gdb/testsuite/ChangeLog | 8 ++++ gdb/testsuite/gdb.ada/enum_idx_packed.exp | 48 +++++++++++++++++++ gdb/testsuite/gdb.ada/enum_idx_packed/foo.adb | 12 ++++- gdb/testsuite/gdb.ada/enum_idx_packed/pck.adb | 40 ++++++++++++++++ gdb/testsuite/gdb.ada/enum_idx_packed/pck.ads | 24 ++++++++++ 7 files changed, 176 insertions(+), 2 deletions(-) diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index b4b7e838114..624e4ad702b 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -2157,6 +2157,35 @@ decode_constrained_packed_array_type (struct type *type) return constrained_packed_array_type (shadow_type, &bits); } +/* Helper function for decode_constrained_packed_array. Set the field + bitsize on a series of packed arrays. Returns the number of + elements in TYPE. */ + +static LONGEST +recursively_update_array_bitsize (struct type *type) +{ + gdb_assert (type->code () == TYPE_CODE_ARRAY); + + LONGEST low, high; + if (get_discrete_bounds (type->index_type (), &low, &high) < 0 + || low > high) + return 0; + LONGEST our_len = high - low + 1; + + struct type *elt_type = TYPE_TARGET_TYPE (type); + if (elt_type->code () == TYPE_CODE_ARRAY) + { + LONGEST elt_len = recursively_update_array_bitsize (elt_type); + LONGEST elt_bitsize = elt_len * TYPE_FIELD_BITSIZE (elt_type, 0); + TYPE_FIELD_BITSIZE (type, 0) = elt_bitsize; + + TYPE_LENGTH (type) = ((our_len * elt_bitsize + HOST_CHAR_BIT - 1) + / HOST_CHAR_BIT); + } + + return our_len; +} + /* Given that ARR is a struct value *indicating a GNAT constrained packed array, returns a simple array that denotes that array. Its type is a standard GDB array type except that the BITSIZEs of the array @@ -2186,6 +2215,18 @@ decode_constrained_packed_array (struct value *arr) return NULL; } + /* Decoding the packed array type could not correctly set the field + bitsizes for any dimension except the innermost, because the + bounds may be variable and were not passed to that function. So, + we further resolve the array bounds here and then update the + sizes. */ + const gdb_byte *valaddr = value_contents_for_printing (arr); + CORE_ADDR address = value_address (arr); + gdb::array_view view + = gdb::make_array_view (valaddr, TYPE_LENGTH (type)); + type = resolve_dynamic_type (type, view, address); + recursively_update_array_bitsize (type); + if (type_byte_order (value_type (arr)) == BFD_ENDIAN_BIG && ada_is_modular_type (value_type (arr))) { diff --git a/gdb/testsuite/gdb.ada/enum_idx_packed.exp b/gdb/testsuite/gdb.ada/enum_idx_packed.exp index bfa091ec9a6..480de71b7c4 100644 --- a/gdb/testsuite/gdb.ada/enum_idx_packed.exp +++ b/gdb/testsuite/gdb.ada/enum_idx_packed.exp @@ -28,7 +28,55 @@ clean_restart ${testfile} set bp_location [gdb_get_line_number "STOP" ${testdir}/foo.adb] runto "foo.adb:$bp_location" +gdb_test "ptype full" \ + "type = array \\(black \\.\\. white\\) of boolean " + gdb_test "print full" " = \\(false, true, false, true, false\\)" gdb_test "print full'first" " = black" +gdb_test "ptype primary" \ + "type = array \\(red \\.\\. blue\\) of boolean " + +gdb_test "print primary" " = \\(red => false, true, false\\)" + +gdb_test "print primary'first" " = red" + +gdb_test "ptype cold" \ + "type = array \\(green \\.\\. blue\\) of boolean " + +gdb_test "print cold" " = \\(green => false, true\\)" + +gdb_test "print cold'first" " = green" + +# Note the bounds values are still not correctly displayed. So we get +# the enum equivalent of "1 .. 0" (empty range) as the array ranges. +# Accept that for now. +gdb_test "ptype small" \ + "array \\(red \\.\\. green\\) of boolean " + +gdb_test "print small" " = \\(red => false, true\\)" + +gdb_test "print small'first" " = red" + +gdb_test "ptype multi" \ + "array \\(red \\.\\. green, low .. medium\\) of boolean " + +gdb_test "print multi" \ + " = \\(red => \\(low => true, false\\), \\(low => true, false\\)\\)" + +gdb_test "print multi'first" " = red" + +set base "\\(true, false, true, false, true, false, true, false, true, false\\)" +set matrix "\\(" +foreach x {1 2 3 4 5 6 7} { + if {$x > 1} { + append matrix ", " + } + append matrix $base +} +append matrix "\\)" + +gdb_test "print multi_multi" " = \\($matrix, $matrix\\)" +gdb_test "print multi_multi(1,3)" " = $base" +gdb_test "print multi_multi(2)" " = $matrix" diff --git a/gdb/testsuite/gdb.ada/enum_idx_packed/foo.adb b/gdb/testsuite/gdb.ada/enum_idx_packed/foo.adb index 6f142a18b00..e9f30747167 100644 --- a/gdb/testsuite/gdb.ada/enum_idx_packed/foo.adb +++ b/gdb/testsuite/gdb.ada/enum_idx_packed/foo.adb @@ -17,8 +17,16 @@ with Pck; use Pck; procedure Foo is Full : Full_Table := (False, True, False, True, False); + Primary : Primary_Table := (False, True, False); + Cold : Cold_Table := (False, True); + Small : Small_Table := New_Small_Table (Low => Red, High => Green); + Multi : Multi_Table := New_Multi_Table (Red, Green, Low, Medium); + Multi_Multi : Multi_Multi_Table := New_Multi_Multi_Table (1, 2, 1, 7, 1, 10); begin Do_Nothing (Full'Address); -- STOP + Do_Nothing (Primary'Address); + Do_Nothing (Cold'Address); + Do_Nothing (Small'Address); + Do_Nothing (Multi'Address); + Do_Nothing (Multi_Multi'Address); end Foo; - - diff --git a/gdb/testsuite/gdb.ada/enum_idx_packed/pck.adb b/gdb/testsuite/gdb.ada/enum_idx_packed/pck.adb index 5b18de9952b..a4e04747526 100644 --- a/gdb/testsuite/gdb.ada/enum_idx_packed/pck.adb +++ b/gdb/testsuite/gdb.ada/enum_idx_packed/pck.adb @@ -14,6 +14,46 @@ -- along with this program. If not, see . package body Pck is + + function New_Small_Table (Low: Color; High: Color) return Small_Table is + Result : Small_Table (Low .. High); + begin + for J in Low .. High loop + Result (J) := (J = Black or J = Green or J = White); + end loop; + return Result; + end New_Small_Table; + + function New_Multi_Table (Low, High: Color; LS, HS: Strength) + return Multi_Table is + Result : Multi_Table (Low .. High, LS .. HS); + Next : Boolean := True; + begin + for J in Low .. High loop + for K in LS .. HS loop + Result (J, K) := Next; + Next := not Next; + end loop; + end loop; + return Result; + end New_Multi_Table; + + function New_Multi_Multi_Table (L1, H1, L2, H2, L3, H3: Positive) + return Multi_Multi_Table is + Result : Multi_Multi_Table (L1 .. H1, L2 .. H2, L3 .. H3); + Next : Boolean := True; + begin + for J in L1 .. H1 loop + for K in L2 .. H2 loop + for L in L3 .. H3 loop + Result (J, K, L) := Next; + Next := not Next; + end loop; + end loop; + end loop; + return Result; + end New_Multi_Multi_Table; + procedure Do_Nothing (A : System.Address) is begin null; diff --git a/gdb/testsuite/gdb.ada/enum_idx_packed/pck.ads b/gdb/testsuite/gdb.ada/enum_idx_packed/pck.ads index c8f5b00d5c0..fdfd8bbc4c6 100644 --- a/gdb/testsuite/gdb.ada/enum_idx_packed/pck.ads +++ b/gdb/testsuite/gdb.ada/enum_idx_packed/pck.ads @@ -16,8 +16,32 @@ with System; package Pck is type Color is (Black, Red, Green, Blue, White); + type Strength is (None, Low, Medium, High); + type Full_Table is array (Color) of Boolean; pragma Pack (Full_Table); + subtype Primary_Color is Color range Red .. Blue; + type Primary_Table is array (Primary_Color) of Boolean; + pragma Pack (Primary_Table); + + type Cold_Color is new Color range Green .. Blue; + type Cold_Table is array (Cold_Color) of Boolean; + pragma Pack (Cold_Table); + + type Small_Table is array (Color range <>) of Boolean; + pragma Pack (Small_Table); + function New_Small_Table (Low: Color; High: Color) return Small_Table; + + type Multi_Table is array (Color range <>, Strength range <>) of Boolean; + pragma Pack (Multi_Table); + function New_Multi_Table (Low, High: Color; LS, HS: Strength) + return Multi_Table; + + type Multi_Multi_Table is array (Positive range <>, Positive range <>, Positive range <>) of Boolean; + pragma Pack (Multi_Multi_Table); + function New_Multi_Multi_Table (L1, H1, L2, H2, L3, H3: Positive) + return Multi_Multi_Table; + procedure Do_Nothing (A : System.Address); end Pck; -- 2.26.2