From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id 8HCeGdiY718DTQAAWB0awg (envelope-from ) for ; Fri, 01 Jan 2021 16:49:12 -0500 Received: by simark.ca (Postfix, from userid 112) id 565D21F0AA; Fri, 1 Jan 2021 16:49:10 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: * X-Spam-Status: No, score=1.6 required=5.0 tests=DKIM_SIGNED,MAILING_LIST_MULTI, RCVD_IN_BL_SPAMCOP_NET,RDNS_NONE,T_DKIM_INVALID,URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.2 Received: from sourceware.org (unknown [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 308EE1F071 for ; Fri, 1 Jan 2021 16:49:06 -0500 (EST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 93C9A3896C29; Fri, 1 Jan 2021 21:48:41 +0000 (GMT) Received: from gateway22.websitewelcome.com (gateway22.websitewelcome.com [192.185.46.187]) by sourceware.org (Postfix) with ESMTPS id B65F23896C17 for ; Fri, 1 Jan 2021 21:48:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org B65F23896C17 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=tromey.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=tom@tromey.com Received: from cm16.websitewelcome.com (cm16.websitewelcome.com [100.42.49.19]) by gateway22.websitewelcome.com (Postfix) with ESMTP id 587F9377D for ; Fri, 1 Jan 2021 15:48:34 -0600 (CST) Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with SMTP id vSHikXB2lHPnUvSHikgzlm; Fri, 01 Jan 2021 15:48:34 -0600 X-Authority-Reason: nr=8 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tromey.com; s=default; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=M5EIqXSnFMZIMA4Qp8BnhsfAn+bpPqMV04u7DixcdYA=; b=F9IGcaXP52WzNDzSg8LqAlZxr9 lfGprJhSetxSjFxHpsZ6kJTtzpCRT4W+YJHaMdTJdPdkFdmuIww5lN7OSJpWWBnlVxXBsrmeg9853 eYSHKSEfVLiY5IU5jQe3f3GGM; Received: from 97-122-81-39.hlrn.qwest.net ([97.122.81.39]:60414 helo=localhost.localdomain) by box5379.bluehost.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1kvSHi-0029lU-5i for gdb-patches@sourceware.org; Fri, 01 Jan 2021 14:48:34 -0700 From: Tom Tromey To: gdb-patches@sourceware.org Subject: [PATCH 141/203] Introduce array_operation Date: Fri, 1 Jan 2021 14:46:21 -0700 Message-Id: <20210101214723.1784144-142-tom@tromey.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210101214723.1784144-1-tom@tromey.com> References: <20210101214723.1784144-1-tom@tromey.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - box5379.bluehost.com X-AntiAbuse: Original Domain - sourceware.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - tromey.com X-BWhitelist: no X-Source-IP: 97.122.81.39 X-Source-L: No X-Exim-ID: 1kvSHi-0029lU-5i X-Source: X-Source-Args: X-Source-Dir: X-Source-Sender: 97-122-81-39.hlrn.qwest.net (localhost.localdomain) [97.122.81.39]:60414 X-Source-Auth: tom+tromey.com X-Email-Count: 142 X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTM3OS5ibHVlaG9zdC5jb20= X-Local-Domain: yes 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: , Errors-To: gdb-patches-bounces@sourceware.org Sender: "Gdb-patches" This adds class array_operation, which implements OP_ARRAY. gdb/ChangeLog 2021-01-01 Tom Tromey * expop.h (class array_operation): New. * eval.c (array_operation::evaluate_struct_tuple) (array_operation::evaluate): New methods. --- gdb/ChangeLog | 6 ++ gdb/eval.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/expop.h | 22 ++++++ 3 files changed, 228 insertions(+) diff --git a/gdb/eval.c b/gdb/eval.c index 62b3f219ca4..2589e35ae30 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -2547,6 +2547,206 @@ adl_func_operation::evaluate (struct type *expect_type, } +/* This function evaluates brace-initializers (in C/C++) for + structure types. */ + +struct value * +array_operation::evaluate_struct_tuple (struct value *struct_val, + struct expression *exp, + enum noside noside, int nargs) +{ + const std::vector &in_args = std::get<2> (m_storage); + struct type *struct_type = check_typedef (value_type (struct_val)); + struct type *field_type; + int fieldno = -1; + + int idx = 0; + while (--nargs >= 0) + { + struct value *val = NULL; + int bitpos, bitsize; + bfd_byte *addr; + + fieldno++; + /* Skip static fields. */ + while (fieldno < struct_type->num_fields () + && field_is_static (&struct_type->field (fieldno))) + fieldno++; + if (fieldno >= struct_type->num_fields ()) + error (_("too many initializers")); + field_type = struct_type->field (fieldno).type (); + if (field_type->code () == TYPE_CODE_UNION + && TYPE_FIELD_NAME (struct_type, fieldno)[0] == '0') + error (_("don't know which variant you want to set")); + + /* Here, struct_type is the type of the inner struct, + while substruct_type is the type of the inner struct. + These are the same for normal structures, but a variant struct + contains anonymous union fields that contain substruct fields. + The value fieldno is the index of the top-level (normal or + anonymous union) field in struct_field, while the value + subfieldno is the index of the actual real (named inner) field + in substruct_type. */ + + field_type = struct_type->field (fieldno).type (); + if (val == 0) + val = in_args[idx++]->evaluate (field_type, exp, noside); + + /* Now actually set the field in struct_val. */ + + /* Assign val to field fieldno. */ + if (value_type (val) != field_type) + val = value_cast (field_type, val); + + bitsize = TYPE_FIELD_BITSIZE (struct_type, fieldno); + bitpos = TYPE_FIELD_BITPOS (struct_type, fieldno); + addr = value_contents_writeable (struct_val) + bitpos / 8; + if (bitsize) + modify_field (struct_type, addr, + value_as_long (val), bitpos % 8, bitsize); + else + memcpy (addr, value_contents (val), + TYPE_LENGTH (value_type (val))); + + } + return struct_val; +} + +value * +array_operation::evaluate (struct type *expect_type, + struct expression *exp, + enum noside noside) +{ + int tem; + int tem2 = std::get<0> (m_storage); + int tem3 = std::get<1> (m_storage); + const std::vector &in_args = std::get<2> (m_storage); + int nargs = tem3 - tem2 + 1; + struct type *type = expect_type ? check_typedef (expect_type) : nullptr; + + if (expect_type != nullptr && noside != EVAL_SKIP + && type->code () == TYPE_CODE_STRUCT) + { + struct value *rec = allocate_value (expect_type); + + memset (value_contents_raw (rec), '\0', TYPE_LENGTH (type)); + return evaluate_struct_tuple (rec, exp, noside, nargs); + } + + if (expect_type != nullptr && noside != EVAL_SKIP + && type->code () == TYPE_CODE_ARRAY) + { + struct type *range_type = type->index_type (); + struct type *element_type = TYPE_TARGET_TYPE (type); + struct value *array = allocate_value (expect_type); + int element_size = TYPE_LENGTH (check_typedef (element_type)); + LONGEST low_bound, high_bound, index; + + if (!get_discrete_bounds (range_type, &low_bound, &high_bound)) + { + low_bound = 0; + high_bound = (TYPE_LENGTH (type) / element_size) - 1; + } + index = low_bound; + memset (value_contents_raw (array), 0, TYPE_LENGTH (expect_type)); + for (tem = nargs; --nargs >= 0;) + { + struct value *element; + + element = in_args[index - low_bound]->evaluate (element_type, + exp, noside); + if (value_type (element) != element_type) + element = value_cast (element_type, element); + if (index > high_bound) + /* To avoid memory corruption. */ + error (_("Too many array elements")); + memcpy (value_contents_raw (array) + + (index - low_bound) * element_size, + value_contents (element), + element_size); + index++; + } + return array; + } + + if (expect_type != nullptr && noside != EVAL_SKIP + && type->code () == TYPE_CODE_SET) + { + struct value *set = allocate_value (expect_type); + gdb_byte *valaddr = value_contents_raw (set); + struct type *element_type = type->index_type (); + struct type *check_type = element_type; + LONGEST low_bound, high_bound; + + /* Get targettype of elementtype. */ + while (check_type->code () == TYPE_CODE_RANGE + || check_type->code () == TYPE_CODE_TYPEDEF) + check_type = TYPE_TARGET_TYPE (check_type); + + if (!get_discrete_bounds (element_type, &low_bound, &high_bound)) + error (_("(power)set type with unknown size")); + memset (valaddr, '\0', TYPE_LENGTH (type)); + int idx = 0; + for (tem = 0; tem < nargs; tem++) + { + LONGEST range_low, range_high; + struct type *range_low_type, *range_high_type; + struct value *elem_val; + + elem_val = in_args[idx++]->evaluate (element_type, exp, noside); + range_low_type = range_high_type = value_type (elem_val); + range_low = range_high = value_as_long (elem_val); + + /* Check types of elements to avoid mixture of elements from + different types. Also check if type of element is "compatible" + with element type of powerset. */ + if (range_low_type->code () == TYPE_CODE_RANGE) + range_low_type = TYPE_TARGET_TYPE (range_low_type); + if (range_high_type->code () == TYPE_CODE_RANGE) + range_high_type = TYPE_TARGET_TYPE (range_high_type); + if ((range_low_type->code () != range_high_type->code ()) + || (range_low_type->code () == TYPE_CODE_ENUM + && (range_low_type != range_high_type))) + /* different element modes. */ + error (_("POWERSET tuple elements of different mode")); + if ((check_type->code () != range_low_type->code ()) + || (check_type->code () == TYPE_CODE_ENUM + && range_low_type != check_type)) + error (_("incompatible POWERSET tuple elements")); + if (range_low > range_high) + { + warning (_("empty POWERSET tuple range")); + continue; + } + if (range_low < low_bound || range_high > high_bound) + error (_("POWERSET tuple element out of range")); + range_low -= low_bound; + range_high -= low_bound; + for (; range_low <= range_high; range_low++) + { + int bit_index = (unsigned) range_low % TARGET_CHAR_BIT; + + if (gdbarch_byte_order (exp->gdbarch) == BFD_ENDIAN_BIG) + bit_index = TARGET_CHAR_BIT - 1 - bit_index; + valaddr[(unsigned) range_low / TARGET_CHAR_BIT] + |= 1 << bit_index; + } + } + return set; + } + + value **argvec = XALLOCAVEC (struct value *, nargs); + for (tem = 0; tem < nargs; tem++) + { + /* Ensure that array expressions are coerced into pointer + objects. */ + argvec[tem] = in_args[tem]->evaluate_with_coercion (exp, noside); + } + if (noside == EVAL_SKIP) + return eval_skip_value (exp); + return value_array (tem2, tem3, argvec); +} + } struct value * diff --git a/gdb/expop.h b/gdb/expop.h index a8aa0f43acc..08e40345e76 100644 --- a/gdb/expop.h +++ b/gdb/expop.h @@ -2046,6 +2046,28 @@ class adl_func_operation { return OP_ADL_FUNC; } }; +/* The OP_ARRAY operation. */ +class array_operation + : public tuple_holding_operation> +{ +public: + + using tuple_holding_operation::tuple_holding_operation; + + value *evaluate (struct type *expect_type, + struct expression *exp, + enum noside noside) override; + + enum exp_opcode opcode () const override + { return OP_ARRAY; } + +private: + + struct value *evaluate_struct_tuple (struct value *struct_val, + struct expression *exp, + enum noside noside, int nargs); +}; + } /* namespace expr */ #endif /* EXPOP_H */ -- 2.26.2