From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id CNOeK/2Y718XTQAAWB0awg (envelope-from ) for ; Fri, 01 Jan 2021 16:49:49 -0500 Received: by simark.ca (Postfix, from userid 112) id A8AAC1F0D2; Fri, 1 Jan 2021 16:49:49 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIM_SIGNED, MAILING_LIST_MULTI,T_DKIM_INVALID,URIBL_BLOCKED autolearn=unavailable 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 4BB431F0B7 for ; Fri, 1 Jan 2021 16:49:33 -0500 (EST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 40C2D3939C02; Fri, 1 Jan 2021 21:48:59 +0000 (GMT) Received: from gateway33.websitewelcome.com (gateway33.websitewelcome.com [192.185.146.130]) by sourceware.org (Postfix) with ESMTPS id 9F8863938C26 for ; Fri, 1 Jan 2021 21:48:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 9F8863938C26 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 cm11.websitewelcome.com (cm11.websitewelcome.com [100.42.49.5]) by gateway33.websitewelcome.com (Postfix) with ESMTP id 4256B55261EB for ; Fri, 1 Jan 2021 15:48:54 -0600 (CST) Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with SMTP id vSI2ka1tznPrxvSI2kleLF; Fri, 01 Jan 2021 15:48:54 -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=G4uqT49bz65976H2XPygWf0WNSj9DTK5v0Fzp9aXhbE=; b=ADPNlgj4gwO07i6rbzPrqlCJhS M23ZxJY32z4xViDUtD+fN6kQ2gNfSjz0qng69MWZ8EcOxu9YF4UfdZcvHsZ6mKqQllZyCOMkKIqJj wML44I6+io8jSRS/whrMfNTQQ; Received: from 97-122-81-39.hlrn.qwest.net ([97.122.81.39]:60424 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 1kvSI2-0029vv-0S for gdb-patches@sourceware.org; Fri, 01 Jan 2021 14:48:54 -0700 From: Tom Tromey To: gdb-patches@sourceware.org Subject: [PATCH 177/203] Convert rust-exp.y to use operations Date: Fri, 1 Jan 2021 14:46:57 -0700 Message-Id: <20210101214723.1784144-178-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: 1kvSI2-0029vv-0S X-Source: X-Source-Args: X-Source-Dir: X-Source-Sender: 97-122-81-39.hlrn.qwest.net (localhost.localdomain) [97.122.81.39]:60424 X-Source-Auth: tom+tromey.com X-Email-Count: 178 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 converts the Rust parser to generate operations rather than exp_elements. The Rust parser already made its own AST, that it then lowered to GDB expressions. Ironically, this made conversion trickier, rather than simpler, than the other parsers, primarily due to the way that binary operations were lowered. Perhaps in the future, converting the Rust parser to directly create operations while parsing would be worthwhile. gdb/ChangeLog 2021-01-01 Tom Tromey * rust-exp.y: Create operations. (rust_parser::convert_params_to_expression): Change return type. (binop_maker_ftype): New typedef. (maker_map): New global. (rust_parser::convert_ast_to_expression): Change return type. (rust_language::parser): Update. (_initialize_rust_exp): Initialize maker_map. --- gdb/ChangeLog | 10 ++ gdb/rust-exp.y | 324 +++++++++++++++++++++++++++---------------------- 2 files changed, 190 insertions(+), 144 deletions(-) diff --git a/gdb/rust-exp.y b/gdb/rust-exp.y index a6583a6129a..9a5bdd7a836 100644 --- a/gdb/rust-exp.y +++ b/gdb/rust-exp.y @@ -41,6 +41,8 @@ #include "gdbsupport/selftest.h" #include "value.h" #include "gdbarch.h" +#include "rust-exp.h" +#include #define GDB_YY_REMAP_PREFIX rust #include "yy-remap.h" @@ -246,11 +248,11 @@ struct rust_parser std::vector convert_params_to_types (rust_op_vector *params); struct type *convert_ast_to_type (const struct rust_op *operation); const char *convert_name (const struct rust_op *operation); - void convert_params_to_expression (rust_op_vector *params, - const struct rust_op *top); - void convert_ast_to_expression (const struct rust_op *operation, - const struct rust_op *top, - bool want_type = false); + std::vector convert_params_to_expression + (rust_op_vector *params, const struct rust_op *top); + expr::operation_up convert_ast_to_expression (const struct rust_op *opn, + const struct rust_op *top, + bool want_type = false); struct rust_op *ast_basic_type (enum type_code typecode); const struct rust_op *ast_operation (enum exp_opcode opcode, @@ -2183,14 +2185,25 @@ rust_parser::convert_name (const struct rust_op *operation) /* A helper function that converts a vec of rust_ops to a gdb expression. */ -void +std::vector rust_parser::convert_params_to_expression (rust_op_vector *params, const struct rust_op *top) { + std::vector result; for (const rust_op *elem : *params) - convert_ast_to_expression (elem, top); + result.push_back (convert_ast_to_expression (elem, top)); + result.shrink_to_fit (); + return result; } +typedef expr::operation_up binop_maker_ftype (expr::operation_up &&, + expr::operation_up &&); + +/* Map from an expression opcode to a function that will create an + instance of the appropriate operation subclass. Only binary + operations are handled this way. */ +static std::unordered_map maker_map; + /* Lower a rust_op to a gdb expression. STATE is the parser state. OPERATION is the operation to lower. TOP is a pointer to the top-most operation; it is used to handle the special case where the @@ -2200,62 +2213,87 @@ rust_parser::convert_params_to_expression (rust_op_vector *params, erroring). If WANT_TYPE is set, then the similar TOP handling is not done. */ -void +expr::operation_up rust_parser::convert_ast_to_expression (const struct rust_op *operation, const struct rust_op *top, bool want_type) { + using namespace expr; + switch (operation->opcode) { case OP_LONG: - write_exp_elt_opcode (pstate, OP_LONG); - write_exp_elt_type (pstate, operation->left.typed_val_int.type); - write_exp_elt_longcst (pstate, operation->left.typed_val_int.val); - write_exp_elt_opcode (pstate, OP_LONG); - break; + return operation_up + (new long_const_operation (operation->left.typed_val_int.type, + operation->left.typed_val_int.val)); case OP_FLOAT: - write_exp_elt_opcode (pstate, OP_FLOAT); - write_exp_elt_type (pstate, operation->left.typed_val_float.type); - write_exp_elt_floatcst (pstate, operation->left.typed_val_float.val); - write_exp_elt_opcode (pstate, OP_FLOAT); - break; + { + float_data data; + memcpy (data.data (), operation->left.typed_val_float.val, + sizeof (operation->left.typed_val_float.val)); + return operation_up + (new float_const_operation (operation->left.typed_val_float.type, + data)); + } case STRUCTOP_STRUCT: { - convert_ast_to_expression (operation->left.op, top); - + operation_up lhs = convert_ast_to_expression (operation->left.op, top); + auto result = new rust_structop (std::move (lhs), + operation->right.sval.ptr); if (operation->completing) - pstate->mark_struct_expression (); - write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); - write_exp_string (pstate, operation->right.sval); - write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); + pstate->mark_struct_expression (result); + return operation_up (result); } - break; case STRUCTOP_ANONYMOUS: { - convert_ast_to_expression (operation->left.op, top); + operation_up lhs = convert_ast_to_expression (operation->left.op, top); - write_exp_elt_opcode (pstate, STRUCTOP_ANONYMOUS); - write_exp_elt_longcst (pstate, operation->right.typed_val_int.val); - write_exp_elt_opcode (pstate, STRUCTOP_ANONYMOUS); + return operation_up + (new rust_struct_anon (operation->right.typed_val_int.val, + std::move (lhs))); } - break; case UNOP_SIZEOF: - convert_ast_to_expression (operation->left.op, top, true); - write_exp_elt_opcode (pstate, UNOP_SIZEOF); - break; + { + operation_up lhs = convert_ast_to_expression (operation->left.op, top, + true); + return operation_up + (new unop_sizeof_operation (std::move (lhs))); + } case UNOP_PLUS: + { + operation_up lhs = convert_ast_to_expression (operation->left.op, top); + return operation_up + (new unary_plus_operation (std::move (lhs))); + } case UNOP_NEG: + { + operation_up lhs = convert_ast_to_expression (operation->left.op, top); + return operation_up + (new unary_neg_operation (std::move (lhs))); + } case UNOP_COMPLEMENT: + { + operation_up lhs = convert_ast_to_expression (operation->left.op, top); + return operation_up + (new rust_unop_compl_operation (std::move (lhs))); + } case UNOP_IND: + { + operation_up lhs = convert_ast_to_expression (operation->left.op, top); + return operation_up + (new rust_unop_ind_operation (std::move (lhs))); + } case UNOP_ADDR: - convert_ast_to_expression (operation->left.op, top); - write_exp_elt_opcode (pstate, operation->opcode); - break; + { + operation_up lhs = convert_ast_to_expression (operation->left.op, top); + return operation_up + (new rust_unop_addr_operation (std::move (lhs))); + } case BINOP_SUBSCRIPT: case BINOP_MUL: @@ -2279,45 +2317,45 @@ rust_parser::convert_ast_to_expression (const struct rust_op *operation, case BINOP_RSH: case BINOP_ASSIGN: case OP_RUST_ARRAY: - convert_ast_to_expression (operation->left.op, top); - convert_ast_to_expression (operation->right.op, top); - if (operation->compound_assignment) - { - write_exp_elt_opcode (pstate, BINOP_ASSIGN_MODIFY); - write_exp_elt_opcode (pstate, operation->opcode); - write_exp_elt_opcode (pstate, BINOP_ASSIGN_MODIFY); - } - else - write_exp_elt_opcode (pstate, operation->opcode); - - if (operation->compound_assignment - || operation->opcode == BINOP_ASSIGN) - { - struct type *type; - - type = language_lookup_primitive_type (pstate->language (), - pstate->gdbarch (), - "()"); + { + operation_up lhs = convert_ast_to_expression (operation->left.op, top); + operation_up rhs = convert_ast_to_expression (operation->right.op, + top); + operation_up result; + if (operation->compound_assignment) + result = (operation_up + (new assign_modify_operation (operation->opcode, + std::move (lhs), + std::move (rhs)))); + else + { + auto iter = maker_map.find (operation->opcode); + gdb_assert (iter != maker_map.end ()); + result = iter->second (std::move (lhs), std::move (rhs)); + } - write_exp_elt_opcode (pstate, OP_LONG); - write_exp_elt_type (pstate, type); - write_exp_elt_longcst (pstate, 0); - write_exp_elt_opcode (pstate, OP_LONG); + if (operation->compound_assignment + || operation->opcode == BINOP_ASSIGN) + { + struct type *type + = language_lookup_primitive_type (pstate->language (), + pstate->gdbarch (), + "()"); + + operation_up nil (new long_const_operation (type, 0)); + result.reset (new comma_operation (std::move (result), + std::move (nil))); + } - write_exp_elt_opcode (pstate, BINOP_COMMA); - } - break; + return result; + } case UNOP_CAST: { struct type *type = convert_ast_to_type (operation->right.op); - - convert_ast_to_expression (operation->left.op, top); - write_exp_elt_opcode (pstate, UNOP_CAST); - write_exp_elt_type (pstate, type); - write_exp_elt_opcode (pstate, UNOP_CAST); + operation_up lhs = convert_ast_to_expression (operation->left.op, top); + return operation_up (new unop_cast_operation (std::move (lhs), type)); } - break; case OP_FUNCALL: { @@ -2339,42 +2377,39 @@ rust_parser::convert_ast_to_expression (const struct rust_op *operation, if (!rust_tuple_struct_type_p (type)) error (_("Type %s is not a tuple struct"), varname); + std::vector> args + (params->size ()); for (int i = 0; i < params->size (); ++i) { char *cell = get_print_cell (); + operation_up op + = convert_ast_to_expression ((*params)[i], top); xsnprintf (cell, PRINT_CELL_SIZE, "__%d", i); - write_exp_elt_opcode (pstate, OP_NAME); - write_exp_string (pstate, make_stoken (cell)); - write_exp_elt_opcode (pstate, OP_NAME); - - convert_ast_to_expression ((*params)[i], top); + args[i] = { cell, std::move (op) }; } - write_exp_elt_opcode (pstate, OP_AGGREGATE); - write_exp_elt_type (pstate, type); - write_exp_elt_longcst (pstate, 2 * params->size ()); - write_exp_elt_opcode (pstate, OP_AGGREGATE); - break; + return make_operation + (type, operation_up (), std::move (args)); } } } - convert_ast_to_expression (operation->left.op, top); - convert_params_to_expression (operation->right.params, top); - write_exp_elt_opcode (pstate, OP_FUNCALL); - write_exp_elt_longcst (pstate, operation->right.params->size ()); - write_exp_elt_longcst (pstate, OP_FUNCALL); + operation_up callee = convert_ast_to_expression (operation->left.op, + top); + std::vector args + = convert_params_to_expression (operation->right.params, top); + return make_operation (std::move (callee), + std::move (args)); } - break; case OP_ARRAY: - gdb_assert (operation->left.op == NULL); - convert_params_to_expression (operation->right.params, top); - write_exp_elt_opcode (pstate, OP_ARRAY); - write_exp_elt_longcst (pstate, 0); - write_exp_elt_longcst (pstate, operation->right.params->size () - 1); - write_exp_elt_longcst (pstate, OP_ARRAY); - break; + { + gdb_assert (operation->left.op == NULL); + std::vector subexps + = convert_params_to_expression (operation->right.params, top); + return make_operation + (0, operation->right.params->size () - 1, std::move (subexps)); + } case OP_VAR_VALUE: { @@ -2383,20 +2418,16 @@ rust_parser::convert_ast_to_expression (const struct rust_op *operation, if (operation->left.sval.ptr[0] == '$') { - write_dollar_variable (pstate, operation->left.sval); - break; + pstate->push_dollar (operation->left.sval); + return pstate->pop (); } varname = convert_name (operation); sym = lookup_symbol (varname, pstate->expression_context_block, VAR_DOMAIN); + operation_up result; if (sym.symbol != NULL && SYMBOL_CLASS (sym.symbol) != LOC_TYPEDEF) - { - write_exp_elt_opcode (pstate, OP_VAR_VALUE); - write_exp_elt_block (pstate, sym.block); - write_exp_elt_sym (pstate, sym.symbol); - write_exp_elt_opcode (pstate, OP_VAR_VALUE); - } + result.reset (new var_value_operation (sym.symbol, sym.block)); else { struct type *type = NULL; @@ -2417,52 +2448,35 @@ rust_parser::convert_ast_to_expression (const struct rust_op *operation, && type->num_fields () == 0) { /* A unit-like struct. */ - write_exp_elt_opcode (pstate, OP_AGGREGATE); - write_exp_elt_type (pstate, type); - write_exp_elt_longcst (pstate, 0); - write_exp_elt_opcode (pstate, OP_AGGREGATE); + result.reset (new rust_aggregate_operation (type, {}, {})); } else if (want_type || operation == top) - { - write_exp_elt_opcode (pstate, OP_TYPE); - write_exp_elt_type (pstate, type); - write_exp_elt_opcode (pstate, OP_TYPE); - } + result.reset (new type_operation (type)); else error (_("Found type '%s', which can't be " "evaluated in this context"), varname); } + + return result; } - break; case OP_AGGREGATE: { - int length; rust_set_vector *fields = operation->right.field_inits; struct type *type; const char *name; - length = 0; + operation_up others; + std::vector> field_v; for (const set_field &init : *fields) { - if (init.name.ptr != NULL) - { - write_exp_elt_opcode (pstate, OP_NAME); - write_exp_string (pstate, init.name); - write_exp_elt_opcode (pstate, OP_NAME); - ++length; - } - - convert_ast_to_expression (init.init, top); - ++length; + operation_up expr = convert_ast_to_expression (init.init, top); if (init.name.ptr == NULL) - { - /* This is handled differently from Ada in our - evaluator. */ - write_exp_elt_opcode (pstate, OP_OTHERS); - } + others = std::move (expr); + else + field_v.emplace_back (init.name.ptr, std::move (expr)); } name = convert_name (operation->left.op); @@ -2475,34 +2489,29 @@ rust_parser::convert_ast_to_expression (const struct rust_op *operation, || rust_tuple_struct_type_p (type)) error (_("Struct expression applied to non-struct type")); - write_exp_elt_opcode (pstate, OP_AGGREGATE); - write_exp_elt_type (pstate, type); - write_exp_elt_longcst (pstate, length); - write_exp_elt_opcode (pstate, OP_AGGREGATE); + return operation_up + (new rust_aggregate_operation (type, std::move (others), + std::move (field_v))); } - break; case OP_STRING: - { - write_exp_elt_opcode (pstate, OP_STRING); - write_exp_string (pstate, operation->left.sval); - write_exp_elt_opcode (pstate, OP_STRING); - } - break; + return (operation_up + (new string_operation (::copy_name (operation->left.sval)))); case OP_RANGE: { enum range_flag kind = (RANGE_HIGH_BOUND_DEFAULT | RANGE_LOW_BOUND_DEFAULT); + operation_up lhs, rhs; if (operation->left.op != NULL) { - convert_ast_to_expression (operation->left.op, top); + lhs = convert_ast_to_expression (operation->left.op, top); kind &= ~RANGE_LOW_BOUND_DEFAULT; } if (operation->right.op != NULL) { - convert_ast_to_expression (operation->right.op, top); + rhs = convert_ast_to_expression (operation->right.op, top); if (kind == (RANGE_HIGH_BOUND_DEFAULT | RANGE_LOW_BOUND_DEFAULT)) { kind = RANGE_LOW_BOUND_DEFAULT; @@ -2524,11 +2533,10 @@ rust_parser::convert_ast_to_expression (const struct rust_op *operation, gdb_assert (!operation->inclusive); } - write_exp_elt_opcode (pstate, OP_RANGE); - write_exp_elt_longcst (pstate, kind); - write_exp_elt_opcode (pstate, OP_RANGE); + return operation_up (new rust_range_operation (kind, + std::move (lhs), + std::move (rhs))); } - break; default: gdb_assert_not_reached ("unhandled opcode in convert_ast_to_expression"); @@ -2551,7 +2559,11 @@ rust_language::parser (struct parser_state *state) const result = rustyyparse (&parser); if (!result || (state->parse_completion && parser.rust_ast != NULL)) - parser.convert_ast_to_expression (parser.rust_ast, parser.rust_ast); + { + expr::operation_up op + = parser.convert_ast_to_expression (parser.rust_ast, parser.rust_ast); + state->set_operation (std::move (op)); + } return result; } @@ -2840,6 +2852,30 @@ _initialize_rust_exp () error. */ gdb_assert (code == 0); + using namespace expr; + maker_map[BINOP_SUBSCRIPT] = make_operation; + maker_map[BINOP_MUL] = make_operation; + maker_map[BINOP_REPEAT] = make_operation; + maker_map[BINOP_DIV] = make_operation; + maker_map[BINOP_REM] = make_operation; + maker_map[BINOP_LESS] = make_operation; + maker_map[BINOP_GTR] = make_operation; + maker_map[BINOP_BITWISE_AND] = make_operation; + maker_map[BINOP_BITWISE_IOR] = make_operation; + maker_map[BINOP_BITWISE_XOR] = make_operation; + maker_map[BINOP_ADD] = make_operation; + maker_map[BINOP_SUB] = make_operation; + maker_map[BINOP_LOGICAL_OR] = make_operation; + maker_map[BINOP_LOGICAL_AND] = make_operation; + maker_map[BINOP_EQUAL] = make_operation; + maker_map[BINOP_NOTEQUAL] = make_operation; + maker_map[BINOP_LEQ] = make_operation; + maker_map[BINOP_GEQ] = make_operation; + maker_map[BINOP_LSH] = make_operation; + maker_map[BINOP_RSH] = make_operation; + maker_map[BINOP_ASSIGN] = make_operation; + maker_map[OP_RUST_ARRAY] = make_operation; + #if GDB_SELF_TEST selftests::register_test ("rust-lex", rust_lex_tests); #endif -- 2.26.2