2016-04-27 09:38:08 +08:00
|
|
|
|
/* Rust language support routines for GDB, the GNU debugger.
|
|
|
|
|
|
2020-01-01 14:20:01 +08:00
|
|
|
|
Copyright (C) 2016-2020 Free Software Foundation, Inc.
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
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/>. */
|
|
|
|
|
|
|
|
|
|
#include "defs.h"
|
|
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
|
|
#include "block.h"
|
|
|
|
|
#include "c-lang.h"
|
|
|
|
|
#include "charset.h"
|
|
|
|
|
#include "cp-support.h"
|
2016-05-27 05:04:07 +08:00
|
|
|
|
#include "demangle.h"
|
2016-04-27 09:38:08 +08:00
|
|
|
|
#include "gdbarch.h"
|
|
|
|
|
#include "infcall.h"
|
|
|
|
|
#include "objfiles.h"
|
Handle dereferencing Rust trait objects
In Rust, virtual tables work a bit differently than they do in C++. In
C++, as you know, they are connected to a particular class hierarchy.
Rust, instead, can generate a virtual table for potentially any type --
in fact, one such virtual table for each trait (a trait is similar to an
abstract class or to a Java interface) that a type implements.
Objects that are referenced via a trait can't currently be inspected by
gdb. This patch implements the Rust equivalent of "set print object".
gdb relies heavily on the C++ ABI to decode virtual tables; primarily to
make "set print object" work; but also "info vtbl". However, Rust does
not currently have a specified ABI, so this approach seems unwise to
emulate.
Instead, I've changed the Rust compiler to emit some DWARF that
describes trait objects (previously their internal structure was
opaque), vtables (currently just a size -- but I hope to expand this in
the future), and the concrete type for which a vtable was emitted.
The concrete type is expressed as a DW_AT_containing_type on the
vtable's type. This is a small extension to DWARF.
This patch adds a new entry to quick_symbol_functions to return the
symtab that holds a data address. Previously there was no way in gdb to
look up a full (only minimal) non-text symbol by address. The psymbol
implementation of this method works by lazily filling in a map that is
added to the objfile. This avoids slowing down psymbol reading for a
feature that is likely to not be used too frequently.
I did not update .gdb_index. My thinking here is that the DWARF 5
indices will obsolete .gdb_index soon-ish, meaning that adding a new
feature to them is probably wasted work. If necessary I can update the
DWARF 5 index code when it lands in gdb.
Regression tested on x86-64 Fedora 25.
2017-11-17 Tom Tromey <tom@tromey.com>
* symtab.h (struct symbol) <is_rust_vtable>: New member.
(struct rust_vtable_symbol): New.
(find_symbol_at_address): Declare.
* symtab.c (find_symbol_at_address): New function.
* symfile.h (struct quick_symbol_functions)
<find_compunit_symtab_by_address>: New member.
* symfile-debug.c (debug_qf_find_compunit_symtab_by_address): New
function.
(debug_sym_quick_functions): Link to
debug_qf_find_compunit_symtab_by_address.
* rust-lang.c (rust_get_trait_object_pointer): New function.
(rust_evaluate_subexp) <case UNOP_IND>: New case. Call
rust_get_trait_object_pointer.
* psymtab.c (psym_relocate): Clear psymbol_map.
(psym_fill_psymbol_map, psym_find_compunit_symtab_by_address): New
functions.
(psym_functions): Link to psym_find_compunit_symtab_by_address.
* objfiles.h (struct objfile) <psymbol_map>: New member.
* dwarf2read.c (dwarf2_gdb_index_functions): Update.
(process_die) <DW_TAG_variable>: New case. Call read_variable.
(rust_containing_type, read_variable): New functions.
2017-11-17 Tom Tromey <tom@tromey.com>
* gdb.rust/traits.rs: New file.
* gdb.rust/traits.exp: New file.
2017-07-06 20:44:38 +08:00
|
|
|
|
#include "psymtab.h"
|
2016-04-27 09:38:08 +08:00
|
|
|
|
#include "rust-lang.h"
|
2018-06-09 03:18:25 +08:00
|
|
|
|
#include "typeprint.h"
|
2016-04-27 09:38:08 +08:00
|
|
|
|
#include "valprint.h"
|
|
|
|
|
#include "varobj.h"
|
2018-06-09 03:18:25 +08:00
|
|
|
|
#include <algorithm>
|
2016-09-22 23:51:20 +08:00
|
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
Introduce metadata style
This introduces a new "metadata" style and changes many places in gdb
to use it. The idea here is to let the user distinguish gdb output
from output that (conceptually at least) comes directly from the
inferior. The newly-styled category includes text that gdb
traditionally surrounds in "<...>", like "<unavailable>".
I only added a single test for this. In many cases this output is
difficult to test. Also, while developing this errors in the
implementation of the new printf formats showed up as regressions.
gdb/ChangeLog
2019-10-01 Tom Tromey <tom@tromey.com>
* p-lang.c (pascal_printstr): Use metadata style.
* value.c (show_convenience): Use metadata style.
* valprint.c (valprint_check_validity, val_print_optimized_out)
(val_print_not_saved, val_print_unavailable)
(val_print_invalid_address, generic_val_print, val_print)
(value_check_printable, val_print_array_elements): Use metadata
style.
* ui-out.h (class ui_out) <field_fmt>: New overload.
<do_field_fmt>: Add style parameter.
* ui-out.c (ui_out::field_fmt): New overload.
* typeprint.c (type_print_unknown_return_type)
(val_print_not_allocated, val_print_not_associated): Use metadata
style.
* tui/tui-out.h (class tui_ui_out) <do_field_fmt>: Add style
parameter.
* tui/tui-out.c (tui_ui_out::do_field_fmt): Update.
* tracepoint.c (tvariables_info_1): Use metadata style.
* stack.c (print_frame_arg, print_frame_info, print_frame)
(info_frame_command_core): Use metadata style.
* skip.c (info_skip_command): Use metadata style.
* rust-lang.c (rust_print_enum): Use metadata style.
* python/py-prettyprint.c (print_stack_unless_memory_error): Use
metadata style.
* python/py-framefilter.c (py_print_single_arg): Use metadata
style.
* printcmd.c (do_one_display, print_variable_and_value): Use
metadata style.
* p-valprint.c (pascal_val_print)
(pascal_object_print_value_fields): Use metadata style.
* p-typeprint.c (pascal_type_print_base): Use metadata style.
* mi/mi-out.h (class mi_ui_out) <do_field_fmt>: Add style
parameter.
* mi/mi-out.c (mi_ui_out::do_field_fmt): Update.
* m2-valprint.c (m2_print_long_set): Use metadata style.
* m2-typeprint.c (m2_print_type): Use metadata style.
* infcmd.c (print_return_value_1): Use metadata style.
* gnu-v3-abi.c (print_one_vtable): Use metadata style.
* f-valprint.c (info_common_command_for_block): Use metadata
style.
* f-typeprint.c (f_type_print_base): Use metadata style.
* expprint.c (print_subexp_standard): Use metadata style.
* cp-valprint.c (cp_print_value_fields): Use metadata style.
* cli/cli-style.h (class cli_style_option): Add constructor.
(metadata_style): Declare.
* cli/cli-style.c (metadata_style): New global.
(_initialize_cli_style): Register metadata style.
* cli-out.h (class cli_ui_out) <do_field_fmt>: Add style
parameter.
* cli-out.c (cli_ui_out::do_field_fmt): Update.
* c-typeprint.c (c_type_print_base_struct_union)
(c_type_print_base_1): Use metadata style.
* breakpoint.c (watchpoint_value_print)
(print_one_breakpoint_location): Use metadata style.
* break-catch-syscall.c (print_one_catch_syscall): Use metadata
style.
* break-catch-sig.c (signal_catchpoint_print_one): Use metadata
style.
* ada-valprint.c (val_print_packed_array_elements, printstr)
(print_field_values, ada_val_print_ref, ada_val_print): Use
metadata style.
* ada-typeprint.c (print_array_type, ada_print_type): Use metadata
style.
* ada-tasks.c (print_ada_task_info, info_task): Use metadata
style.
* ada-lang.c (user_select_syms): Use metadata style.
gdb/testsuite/ChangeLog
2019-10-01 Tom Tromey <tom@tromey.com>
* lib/gdb-utils.exp (style): Handle "metadata" argument.
* gdb.base/style.exp: Add metadata style test.
2019-04-03 10:00:18 +08:00
|
|
|
|
#include "cli/cli-style.h"
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
/* See rust-lang.h. */
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
const char *
|
|
|
|
|
rust_last_path_segment (const char *path)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
|
|
|
|
const char *result = strrchr (path, ':');
|
|
|
|
|
|
|
|
|
|
if (result == NULL)
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
return path;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
return result + 1;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-03 11:58:12 +08:00
|
|
|
|
/* See rust-lang.h. */
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2017-02-03 11:58:12 +08:00
|
|
|
|
std::string
|
2016-04-27 09:38:08 +08:00
|
|
|
|
rust_crate_for_block (const struct block *block)
|
|
|
|
|
{
|
|
|
|
|
const char *scope = block_scope (block);
|
|
|
|
|
|
|
|
|
|
if (scope[0] == '\0')
|
2017-02-03 11:58:12 +08:00
|
|
|
|
return std::string ();
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2017-02-03 11:58:12 +08:00
|
|
|
|
return std::string (scope, cp_find_first_component (scope));
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
/* Return true if TYPE, which must be a struct type, represents a Rust
|
|
|
|
|
enum. */
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2016-10-29 09:00:43 +08:00
|
|
|
|
static bool
|
2020-04-25 03:40:31 +08:00
|
|
|
|
rust_enum_p (struct type *type)
|
2016-10-29 09:00:43 +08:00
|
|
|
|
{
|
2020-04-25 03:40:31 +08:00
|
|
|
|
/* is_dynamic_type will return true if any field has a dynamic
|
|
|
|
|
attribute -- but we only want to check the top level. */
|
|
|
|
|
return TYPE_HAS_VARIANT_PARTS (type);
|
2016-10-29 09:00:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-25 03:40:31 +08:00
|
|
|
|
/* Return true if TYPE, which must be an already-resolved enum type,
|
|
|
|
|
has no variants. */
|
2018-09-12 05:28:04 +08:00
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
rust_empty_enum_p (const struct type *type)
|
|
|
|
|
{
|
2020-05-23 04:55:15 +08:00
|
|
|
|
return type->num_fields () == 0;
|
2018-09-12 05:28:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-25 03:40:31 +08:00
|
|
|
|
/* Given an already-resolved enum type and contents, find which
|
|
|
|
|
variant is active. */
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2020-04-25 03:40:31 +08:00
|
|
|
|
static int
|
|
|
|
|
rust_enum_variant (struct type *type)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
2020-04-25 03:40:31 +08:00
|
|
|
|
/* The active variant is simply the first non-artificial field. */
|
2020-05-23 04:55:15 +08:00
|
|
|
|
for (int i = 0; i < type->num_fields (); ++i)
|
2020-04-25 03:40:31 +08:00
|
|
|
|
if (!TYPE_FIELD_ARTIFICIAL (type, i))
|
|
|
|
|
return i;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2020-04-25 03:40:31 +08:00
|
|
|
|
/* Perhaps we could get here by trying to print an Ada variant
|
|
|
|
|
record in Rust mode. Unlikely, but an error is safer than an
|
|
|
|
|
assert. */
|
|
|
|
|
error (_("Could not find active enum variant"));
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* See rust-lang.h. */
|
|
|
|
|
|
2017-02-03 12:21:19 +08:00
|
|
|
|
bool
|
2016-04-27 09:38:08 +08:00
|
|
|
|
rust_tuple_type_p (struct type *type)
|
|
|
|
|
{
|
|
|
|
|
/* The current implementation is a bit of a hack, but there's
|
|
|
|
|
nothing else in the debuginfo to distinguish a tuple from a
|
|
|
|
|
struct. */
|
2020-05-15 01:46:38 +08:00
|
|
|
|
return (type->code () == TYPE_CODE_STRUCT
|
2020-05-17 00:16:06 +08:00
|
|
|
|
&& type->name () != NULL
|
|
|
|
|
&& type->name ()[0] == '(');
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return true if all non-static fields of a structlike type are in a
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
sequence like __0, __1, __2. */
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2017-02-03 12:21:19 +08:00
|
|
|
|
static bool
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
rust_underscore_fields (struct type *type)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
|
|
|
|
int i, field_number;
|
|
|
|
|
|
|
|
|
|
field_number = 0;
|
|
|
|
|
|
2020-05-15 01:46:38 +08:00
|
|
|
|
if (type->code () != TYPE_CODE_STRUCT)
|
2017-02-03 12:21:19 +08:00
|
|
|
|
return false;
|
2020-05-23 04:55:15 +08:00
|
|
|
|
for (i = 0; i < type->num_fields (); ++i)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
2020-05-24 05:39:54 +08:00
|
|
|
|
if (!field_is_static (&type->field (i)))
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
char buf[20];
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
xsnprintf (buf, sizeof (buf), "__%d", field_number);
|
|
|
|
|
if (strcmp (buf, TYPE_FIELD_NAME (type, i)) != 0)
|
|
|
|
|
return false;
|
|
|
|
|
field_number++;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-02-03 12:21:19 +08:00
|
|
|
|
return true;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* See rust-lang.h. */
|
|
|
|
|
|
2017-02-03 12:21:19 +08:00
|
|
|
|
bool
|
2016-04-27 09:38:08 +08:00
|
|
|
|
rust_tuple_struct_type_p (struct type *type)
|
|
|
|
|
{
|
2016-07-12 05:02:10 +08:00
|
|
|
|
/* This is just an approximation until DWARF can represent Rust more
|
|
|
|
|
precisely. We exclude zero-length structs because they may not
|
|
|
|
|
be tuple structs, and there's no way to tell. */
|
2020-05-23 04:55:15 +08:00
|
|
|
|
return type->num_fields () > 0 && rust_underscore_fields (type);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return true if TYPE is a slice type, otherwise false. */
|
|
|
|
|
|
2017-02-03 12:21:19 +08:00
|
|
|
|
static bool
|
2016-04-27 09:38:08 +08:00
|
|
|
|
rust_slice_type_p (struct type *type)
|
|
|
|
|
{
|
2020-05-15 01:46:38 +08:00
|
|
|
|
return (type->code () == TYPE_CODE_STRUCT
|
2020-05-17 00:16:06 +08:00
|
|
|
|
&& type->name () != NULL
|
|
|
|
|
&& (strncmp (type->name (), "&[", 2) == 0
|
|
|
|
|
|| strcmp (type->name (), "&str") == 0));
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return true if TYPE is a range type, otherwise false. */
|
|
|
|
|
|
2017-02-03 12:21:19 +08:00
|
|
|
|
static bool
|
2016-04-27 09:38:08 +08:00
|
|
|
|
rust_range_type_p (struct type *type)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
2020-05-15 01:46:38 +08:00
|
|
|
|
if (type->code () != TYPE_CODE_STRUCT
|
2020-05-23 04:55:15 +08:00
|
|
|
|
|| type->num_fields () > 2
|
2020-05-17 00:16:06 +08:00
|
|
|
|
|| type->name () == NULL
|
|
|
|
|
|| strstr (type->name (), "::Range") == NULL)
|
2017-02-03 12:21:19 +08:00
|
|
|
|
return false;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2020-05-23 04:55:15 +08:00
|
|
|
|
if (type->num_fields () == 0)
|
2017-02-03 12:21:19 +08:00
|
|
|
|
return true;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
if (strcmp (TYPE_FIELD_NAME (type, 0), "start") == 0)
|
|
|
|
|
{
|
2020-05-23 04:55:15 +08:00
|
|
|
|
if (type->num_fields () == 1)
|
2017-02-03 12:21:19 +08:00
|
|
|
|
return true;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
i = 1;
|
|
|
|
|
}
|
2020-05-23 04:55:15 +08:00
|
|
|
|
else if (type->num_fields () == 2)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
|
|
|
|
/* First field had to be "start". */
|
2017-02-03 12:21:19 +08:00
|
|
|
|
return false;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return strcmp (TYPE_FIELD_NAME (type, i), "end") == 0;
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-30 04:14:07 +08:00
|
|
|
|
/* Return true if TYPE is an inclusive range type, otherwise false.
|
|
|
|
|
This is only valid for types which are already known to be range
|
|
|
|
|
types. */
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
rust_inclusive_range_type_p (struct type *type)
|
|
|
|
|
{
|
2020-05-17 00:16:06 +08:00
|
|
|
|
return (strstr (type->name (), "::RangeInclusive") != NULL
|
|
|
|
|
|| strstr (type->name (), "::RangeToInclusive") != NULL);
|
2018-03-30 04:14:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-27 09:38:08 +08:00
|
|
|
|
/* Return true if TYPE seems to be the type "u8", otherwise false. */
|
|
|
|
|
|
2017-02-03 12:21:19 +08:00
|
|
|
|
static bool
|
2016-04-27 09:38:08 +08:00
|
|
|
|
rust_u8_type_p (struct type *type)
|
|
|
|
|
{
|
2020-05-15 01:46:38 +08:00
|
|
|
|
return (type->code () == TYPE_CODE_INT
|
2020-09-14 23:07:57 +08:00
|
|
|
|
&& type->is_unsigned ()
|
2016-04-27 09:38:08 +08:00
|
|
|
|
&& TYPE_LENGTH (type) == 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return true if TYPE is a Rust character type. */
|
|
|
|
|
|
2017-02-03 12:21:19 +08:00
|
|
|
|
static bool
|
2016-04-27 09:38:08 +08:00
|
|
|
|
rust_chartype_p (struct type *type)
|
|
|
|
|
{
|
2020-05-15 01:46:38 +08:00
|
|
|
|
return (type->code () == TYPE_CODE_CHAR
|
2016-04-27 09:38:08 +08:00
|
|
|
|
&& TYPE_LENGTH (type) == 4
|
2020-09-14 23:07:57 +08:00
|
|
|
|
&& type->is_unsigned ());
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
Handle dereferencing Rust trait objects
In Rust, virtual tables work a bit differently than they do in C++. In
C++, as you know, they are connected to a particular class hierarchy.
Rust, instead, can generate a virtual table for potentially any type --
in fact, one such virtual table for each trait (a trait is similar to an
abstract class or to a Java interface) that a type implements.
Objects that are referenced via a trait can't currently be inspected by
gdb. This patch implements the Rust equivalent of "set print object".
gdb relies heavily on the C++ ABI to decode virtual tables; primarily to
make "set print object" work; but also "info vtbl". However, Rust does
not currently have a specified ABI, so this approach seems unwise to
emulate.
Instead, I've changed the Rust compiler to emit some DWARF that
describes trait objects (previously their internal structure was
opaque), vtables (currently just a size -- but I hope to expand this in
the future), and the concrete type for which a vtable was emitted.
The concrete type is expressed as a DW_AT_containing_type on the
vtable's type. This is a small extension to DWARF.
This patch adds a new entry to quick_symbol_functions to return the
symtab that holds a data address. Previously there was no way in gdb to
look up a full (only minimal) non-text symbol by address. The psymbol
implementation of this method works by lazily filling in a map that is
added to the objfile. This avoids slowing down psymbol reading for a
feature that is likely to not be used too frequently.
I did not update .gdb_index. My thinking here is that the DWARF 5
indices will obsolete .gdb_index soon-ish, meaning that adding a new
feature to them is probably wasted work. If necessary I can update the
DWARF 5 index code when it lands in gdb.
Regression tested on x86-64 Fedora 25.
2017-11-17 Tom Tromey <tom@tromey.com>
* symtab.h (struct symbol) <is_rust_vtable>: New member.
(struct rust_vtable_symbol): New.
(find_symbol_at_address): Declare.
* symtab.c (find_symbol_at_address): New function.
* symfile.h (struct quick_symbol_functions)
<find_compunit_symtab_by_address>: New member.
* symfile-debug.c (debug_qf_find_compunit_symtab_by_address): New
function.
(debug_sym_quick_functions): Link to
debug_qf_find_compunit_symtab_by_address.
* rust-lang.c (rust_get_trait_object_pointer): New function.
(rust_evaluate_subexp) <case UNOP_IND>: New case. Call
rust_get_trait_object_pointer.
* psymtab.c (psym_relocate): Clear psymbol_map.
(psym_fill_psymbol_map, psym_find_compunit_symtab_by_address): New
functions.
(psym_functions): Link to psym_find_compunit_symtab_by_address.
* objfiles.h (struct objfile) <psymbol_map>: New member.
* dwarf2read.c (dwarf2_gdb_index_functions): Update.
(process_die) <DW_TAG_variable>: New case. Call read_variable.
(rust_containing_type, read_variable): New functions.
2017-11-17 Tom Tromey <tom@tromey.com>
* gdb.rust/traits.rs: New file.
* gdb.rust/traits.exp: New file.
2017-07-06 20:44:38 +08:00
|
|
|
|
/* If VALUE represents a trait object pointer, return the underlying
|
|
|
|
|
pointer with the correct (i.e., runtime) type. Otherwise, return
|
|
|
|
|
NULL. */
|
|
|
|
|
|
|
|
|
|
static struct value *
|
|
|
|
|
rust_get_trait_object_pointer (struct value *value)
|
|
|
|
|
{
|
|
|
|
|
struct type *type = check_typedef (value_type (value));
|
|
|
|
|
|
2020-05-23 04:55:15 +08:00
|
|
|
|
if (type->code () != TYPE_CODE_STRUCT || type->num_fields () != 2)
|
Handle dereferencing Rust trait objects
In Rust, virtual tables work a bit differently than they do in C++. In
C++, as you know, they are connected to a particular class hierarchy.
Rust, instead, can generate a virtual table for potentially any type --
in fact, one such virtual table for each trait (a trait is similar to an
abstract class or to a Java interface) that a type implements.
Objects that are referenced via a trait can't currently be inspected by
gdb. This patch implements the Rust equivalent of "set print object".
gdb relies heavily on the C++ ABI to decode virtual tables; primarily to
make "set print object" work; but also "info vtbl". However, Rust does
not currently have a specified ABI, so this approach seems unwise to
emulate.
Instead, I've changed the Rust compiler to emit some DWARF that
describes trait objects (previously their internal structure was
opaque), vtables (currently just a size -- but I hope to expand this in
the future), and the concrete type for which a vtable was emitted.
The concrete type is expressed as a DW_AT_containing_type on the
vtable's type. This is a small extension to DWARF.
This patch adds a new entry to quick_symbol_functions to return the
symtab that holds a data address. Previously there was no way in gdb to
look up a full (only minimal) non-text symbol by address. The psymbol
implementation of this method works by lazily filling in a map that is
added to the objfile. This avoids slowing down psymbol reading for a
feature that is likely to not be used too frequently.
I did not update .gdb_index. My thinking here is that the DWARF 5
indices will obsolete .gdb_index soon-ish, meaning that adding a new
feature to them is probably wasted work. If necessary I can update the
DWARF 5 index code when it lands in gdb.
Regression tested on x86-64 Fedora 25.
2017-11-17 Tom Tromey <tom@tromey.com>
* symtab.h (struct symbol) <is_rust_vtable>: New member.
(struct rust_vtable_symbol): New.
(find_symbol_at_address): Declare.
* symtab.c (find_symbol_at_address): New function.
* symfile.h (struct quick_symbol_functions)
<find_compunit_symtab_by_address>: New member.
* symfile-debug.c (debug_qf_find_compunit_symtab_by_address): New
function.
(debug_sym_quick_functions): Link to
debug_qf_find_compunit_symtab_by_address.
* rust-lang.c (rust_get_trait_object_pointer): New function.
(rust_evaluate_subexp) <case UNOP_IND>: New case. Call
rust_get_trait_object_pointer.
* psymtab.c (psym_relocate): Clear psymbol_map.
(psym_fill_psymbol_map, psym_find_compunit_symtab_by_address): New
functions.
(psym_functions): Link to psym_find_compunit_symtab_by_address.
* objfiles.h (struct objfile) <psymbol_map>: New member.
* dwarf2read.c (dwarf2_gdb_index_functions): Update.
(process_die) <DW_TAG_variable>: New case. Call read_variable.
(rust_containing_type, read_variable): New functions.
2017-11-17 Tom Tromey <tom@tromey.com>
* gdb.rust/traits.rs: New file.
* gdb.rust/traits.exp: New file.
2017-07-06 20:44:38 +08:00
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
/* Try to be a bit resilient if the ABI changes. */
|
|
|
|
|
int vtable_field = 0;
|
|
|
|
|
for (int i = 0; i < 2; ++i)
|
|
|
|
|
{
|
|
|
|
|
if (strcmp (TYPE_FIELD_NAME (type, i), "vtable") == 0)
|
|
|
|
|
vtable_field = i;
|
|
|
|
|
else if (strcmp (TYPE_FIELD_NAME (type, i), "pointer") != 0)
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CORE_ADDR vtable = value_as_address (value_field (value, vtable_field));
|
|
|
|
|
struct symbol *symbol = find_symbol_at_address (vtable);
|
2017-11-18 03:05:58 +08:00
|
|
|
|
if (symbol == NULL || symbol->subclass != SYMBOL_RUST_VTABLE)
|
Handle dereferencing Rust trait objects
In Rust, virtual tables work a bit differently than they do in C++. In
C++, as you know, they are connected to a particular class hierarchy.
Rust, instead, can generate a virtual table for potentially any type --
in fact, one such virtual table for each trait (a trait is similar to an
abstract class or to a Java interface) that a type implements.
Objects that are referenced via a trait can't currently be inspected by
gdb. This patch implements the Rust equivalent of "set print object".
gdb relies heavily on the C++ ABI to decode virtual tables; primarily to
make "set print object" work; but also "info vtbl". However, Rust does
not currently have a specified ABI, so this approach seems unwise to
emulate.
Instead, I've changed the Rust compiler to emit some DWARF that
describes trait objects (previously their internal structure was
opaque), vtables (currently just a size -- but I hope to expand this in
the future), and the concrete type for which a vtable was emitted.
The concrete type is expressed as a DW_AT_containing_type on the
vtable's type. This is a small extension to DWARF.
This patch adds a new entry to quick_symbol_functions to return the
symtab that holds a data address. Previously there was no way in gdb to
look up a full (only minimal) non-text symbol by address. The psymbol
implementation of this method works by lazily filling in a map that is
added to the objfile. This avoids slowing down psymbol reading for a
feature that is likely to not be used too frequently.
I did not update .gdb_index. My thinking here is that the DWARF 5
indices will obsolete .gdb_index soon-ish, meaning that adding a new
feature to them is probably wasted work. If necessary I can update the
DWARF 5 index code when it lands in gdb.
Regression tested on x86-64 Fedora 25.
2017-11-17 Tom Tromey <tom@tromey.com>
* symtab.h (struct symbol) <is_rust_vtable>: New member.
(struct rust_vtable_symbol): New.
(find_symbol_at_address): Declare.
* symtab.c (find_symbol_at_address): New function.
* symfile.h (struct quick_symbol_functions)
<find_compunit_symtab_by_address>: New member.
* symfile-debug.c (debug_qf_find_compunit_symtab_by_address): New
function.
(debug_sym_quick_functions): Link to
debug_qf_find_compunit_symtab_by_address.
* rust-lang.c (rust_get_trait_object_pointer): New function.
(rust_evaluate_subexp) <case UNOP_IND>: New case. Call
rust_get_trait_object_pointer.
* psymtab.c (psym_relocate): Clear psymbol_map.
(psym_fill_psymbol_map, psym_find_compunit_symtab_by_address): New
functions.
(psym_functions): Link to psym_find_compunit_symtab_by_address.
* objfiles.h (struct objfile) <psymbol_map>: New member.
* dwarf2read.c (dwarf2_gdb_index_functions): Update.
(process_die) <DW_TAG_variable>: New case. Call read_variable.
(rust_containing_type, read_variable): New functions.
2017-11-17 Tom Tromey <tom@tromey.com>
* gdb.rust/traits.rs: New file.
* gdb.rust/traits.exp: New file.
2017-07-06 20:44:38 +08:00
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
struct rust_vtable_symbol *vtable_sym
|
|
|
|
|
= static_cast<struct rust_vtable_symbol *> (symbol);
|
|
|
|
|
struct type *pointer_type = lookup_pointer_type (vtable_sym->concrete_type);
|
|
|
|
|
return value_cast (pointer_type, value_field (value, 1 - vtable_field));
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
|
2020-06-03 23:44:05 +08:00
|
|
|
|
/* language_defn::printstr implementation for Rust. */
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
rust_printstr (struct ui_file *stream, struct type *type,
|
|
|
|
|
const gdb_byte *string, unsigned int length,
|
|
|
|
|
const char *user_encoding, int force_ellipses,
|
|
|
|
|
const struct value_print_options *options)
|
|
|
|
|
{
|
|
|
|
|
/* Rust always uses UTF-8, but let the caller override this if need
|
|
|
|
|
be. */
|
|
|
|
|
const char *encoding = user_encoding;
|
|
|
|
|
if (user_encoding == NULL || !*user_encoding)
|
|
|
|
|
{
|
|
|
|
|
/* In Rust strings, characters are "u8". */
|
|
|
|
|
if (rust_u8_type_p (type))
|
|
|
|
|
encoding = "UTF-8";
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* This is probably some C string, so let's let C deal with
|
|
|
|
|
it. */
|
|
|
|
|
c_printstr (stream, type, string, length, user_encoding,
|
|
|
|
|
force_ellipses, options);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This is not ideal as it doesn't use our character printer. */
|
|
|
|
|
generic_printstr (stream, type, string, length, encoding, force_ellipses,
|
|
|
|
|
'"', 0, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-03-14 07:39:52 +08:00
|
|
|
|
static void rust_value_print_inner (struct value *val, struct ui_file *stream,
|
|
|
|
|
int recurse,
|
|
|
|
|
const struct value_print_options *options);
|
|
|
|
|
|
2017-10-03 03:55:42 +08:00
|
|
|
|
/* Helper function to print a string slice. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
rust_val_print_str (struct ui_file *stream, struct value *val,
|
|
|
|
|
const struct value_print_options *options)
|
|
|
|
|
{
|
|
|
|
|
struct value *base = value_struct_elt (&val, NULL, "data_ptr", NULL,
|
|
|
|
|
"slice");
|
|
|
|
|
struct value *len = value_struct_elt (&val, NULL, "length", NULL, "slice");
|
|
|
|
|
|
|
|
|
|
val_print_string (TYPE_TARGET_TYPE (value_type (base)), "UTF-8",
|
|
|
|
|
value_as_address (base), value_as_long (len), stream,
|
|
|
|
|
options);
|
|
|
|
|
}
|
|
|
|
|
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
/* rust_val_print helper for structs and untagged unions. */
|
2016-10-29 09:00:43 +08:00
|
|
|
|
|
|
|
|
|
static void
|
2020-03-14 07:39:52 +08:00
|
|
|
|
val_print_struct (struct value *val, struct ui_file *stream, int recurse,
|
2016-11-08 19:32:53 +08:00
|
|
|
|
const struct value_print_options *options)
|
2016-10-29 09:00:43 +08:00
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
int first_field;
|
2020-03-14 07:39:52 +08:00
|
|
|
|
struct type *type = check_typedef (value_type (val));
|
2017-10-03 03:55:42 +08:00
|
|
|
|
|
2020-05-17 00:16:06 +08:00
|
|
|
|
if (rust_slice_type_p (type) && strcmp (type->name (), "&str") == 0)
|
2017-10-03 03:55:42 +08:00
|
|
|
|
{
|
2019-05-02 07:40:01 +08:00
|
|
|
|
/* If what we are printing here is actually a string within a
|
|
|
|
|
structure then VAL will be the original parent value, while TYPE
|
|
|
|
|
will be the type of the structure representing the string we want
|
|
|
|
|
to print.
|
|
|
|
|
However, RUST_VAL_PRINT_STR looks up the fields of the string
|
|
|
|
|
inside VAL, assuming that VAL is the string.
|
|
|
|
|
So, recreate VAL as a value representing just the string. */
|
2020-03-14 07:39:52 +08:00
|
|
|
|
val = value_at_lazy (type, value_address (val));
|
2017-10-03 03:55:42 +08:00
|
|
|
|
rust_val_print_str (stream, val, options);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-03 12:21:19 +08:00
|
|
|
|
bool is_tuple = rust_tuple_type_p (type);
|
|
|
|
|
bool is_tuple_struct = !is_tuple && rust_tuple_struct_type_p (type);
|
2016-10-29 09:00:43 +08:00
|
|
|
|
struct value_print_options opts;
|
|
|
|
|
|
|
|
|
|
if (!is_tuple)
|
|
|
|
|
{
|
2020-05-17 00:16:06 +08:00
|
|
|
|
if (type->name () != NULL)
|
|
|
|
|
fprintf_filtered (stream, "%s", type->name ());
|
2016-10-29 09:00:43 +08:00
|
|
|
|
|
2020-05-23 04:55:15 +08:00
|
|
|
|
if (type->num_fields () == 0)
|
2016-10-29 09:00:43 +08:00
|
|
|
|
return;
|
|
|
|
|
|
2020-05-17 00:16:06 +08:00
|
|
|
|
if (type->name () != NULL)
|
2016-10-29 09:00:43 +08:00
|
|
|
|
fputs_filtered (" ", stream);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_tuple || is_tuple_struct)
|
|
|
|
|
fputs_filtered ("(", stream);
|
|
|
|
|
else
|
|
|
|
|
fputs_filtered ("{", stream);
|
|
|
|
|
|
|
|
|
|
opts = *options;
|
|
|
|
|
opts.deref_ref = 0;
|
|
|
|
|
|
|
|
|
|
first_field = 1;
|
2020-05-23 04:55:15 +08:00
|
|
|
|
for (i = 0; i < type->num_fields (); ++i)
|
2016-10-29 09:00:43 +08:00
|
|
|
|
{
|
2020-05-24 05:39:54 +08:00
|
|
|
|
if (field_is_static (&type->field (i)))
|
2016-10-29 09:00:43 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!first_field)
|
|
|
|
|
fputs_filtered (",", stream);
|
|
|
|
|
|
|
|
|
|
if (options->prettyformat)
|
|
|
|
|
{
|
2017-02-03 12:01:11 +08:00
|
|
|
|
fputs_filtered ("\n", stream);
|
|
|
|
|
print_spaces_filtered (2 + 2 * recurse, stream);
|
2016-10-29 09:00:43 +08:00
|
|
|
|
}
|
|
|
|
|
else if (!first_field)
|
|
|
|
|
fputs_filtered (" ", stream);
|
|
|
|
|
|
|
|
|
|
first_field = 0;
|
|
|
|
|
|
|
|
|
|
if (!is_tuple && !is_tuple_struct)
|
|
|
|
|
{
|
2020-02-23 01:02:42 +08:00
|
|
|
|
fputs_styled (TYPE_FIELD_NAME (type, i),
|
|
|
|
|
variable_name_style.style (), stream);
|
2017-02-03 12:01:11 +08:00
|
|
|
|
fputs_filtered (": ", stream);
|
2016-10-29 09:00:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-14 07:39:52 +08:00
|
|
|
|
rust_value_print_inner (value_field (val, i), stream, recurse + 1,
|
|
|
|
|
&opts);
|
2016-10-29 09:00:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options->prettyformat)
|
|
|
|
|
{
|
|
|
|
|
fputs_filtered ("\n", stream);
|
|
|
|
|
print_spaces_filtered (2 * recurse, stream);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_tuple || is_tuple_struct)
|
|
|
|
|
fputs_filtered (")", stream);
|
|
|
|
|
else
|
|
|
|
|
fputs_filtered ("}", stream);
|
|
|
|
|
}
|
|
|
|
|
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
/* rust_val_print helper for discriminated unions (Rust enums). */
|
|
|
|
|
|
|
|
|
|
static void
|
2020-03-14 07:39:52 +08:00
|
|
|
|
rust_print_enum (struct value *val, struct ui_file *stream, int recurse,
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
const struct value_print_options *options)
|
|
|
|
|
{
|
|
|
|
|
struct value_print_options opts = *options;
|
2020-03-14 07:39:52 +08:00
|
|
|
|
struct type *type = check_typedef (value_type (val));
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
|
|
|
|
|
opts.deref_ref = 0;
|
|
|
|
|
|
2020-04-25 03:40:31 +08:00
|
|
|
|
gdb_assert (rust_enum_p (type));
|
|
|
|
|
gdb::array_view<const gdb_byte> view (value_contents_for_printing (val),
|
|
|
|
|
TYPE_LENGTH (value_type (val)));
|
|
|
|
|
type = resolve_dynamic_type (type, view, value_address (val));
|
|
|
|
|
|
2018-09-12 05:28:04 +08:00
|
|
|
|
if (rust_empty_enum_p (type))
|
|
|
|
|
{
|
|
|
|
|
/* Print the enum type name here to be more clear. */
|
Introduce metadata style
This introduces a new "metadata" style and changes many places in gdb
to use it. The idea here is to let the user distinguish gdb output
from output that (conceptually at least) comes directly from the
inferior. The newly-styled category includes text that gdb
traditionally surrounds in "<...>", like "<unavailable>".
I only added a single test for this. In many cases this output is
difficult to test. Also, while developing this errors in the
implementation of the new printf formats showed up as regressions.
gdb/ChangeLog
2019-10-01 Tom Tromey <tom@tromey.com>
* p-lang.c (pascal_printstr): Use metadata style.
* value.c (show_convenience): Use metadata style.
* valprint.c (valprint_check_validity, val_print_optimized_out)
(val_print_not_saved, val_print_unavailable)
(val_print_invalid_address, generic_val_print, val_print)
(value_check_printable, val_print_array_elements): Use metadata
style.
* ui-out.h (class ui_out) <field_fmt>: New overload.
<do_field_fmt>: Add style parameter.
* ui-out.c (ui_out::field_fmt): New overload.
* typeprint.c (type_print_unknown_return_type)
(val_print_not_allocated, val_print_not_associated): Use metadata
style.
* tui/tui-out.h (class tui_ui_out) <do_field_fmt>: Add style
parameter.
* tui/tui-out.c (tui_ui_out::do_field_fmt): Update.
* tracepoint.c (tvariables_info_1): Use metadata style.
* stack.c (print_frame_arg, print_frame_info, print_frame)
(info_frame_command_core): Use metadata style.
* skip.c (info_skip_command): Use metadata style.
* rust-lang.c (rust_print_enum): Use metadata style.
* python/py-prettyprint.c (print_stack_unless_memory_error): Use
metadata style.
* python/py-framefilter.c (py_print_single_arg): Use metadata
style.
* printcmd.c (do_one_display, print_variable_and_value): Use
metadata style.
* p-valprint.c (pascal_val_print)
(pascal_object_print_value_fields): Use metadata style.
* p-typeprint.c (pascal_type_print_base): Use metadata style.
* mi/mi-out.h (class mi_ui_out) <do_field_fmt>: Add style
parameter.
* mi/mi-out.c (mi_ui_out::do_field_fmt): Update.
* m2-valprint.c (m2_print_long_set): Use metadata style.
* m2-typeprint.c (m2_print_type): Use metadata style.
* infcmd.c (print_return_value_1): Use metadata style.
* gnu-v3-abi.c (print_one_vtable): Use metadata style.
* f-valprint.c (info_common_command_for_block): Use metadata
style.
* f-typeprint.c (f_type_print_base): Use metadata style.
* expprint.c (print_subexp_standard): Use metadata style.
* cp-valprint.c (cp_print_value_fields): Use metadata style.
* cli/cli-style.h (class cli_style_option): Add constructor.
(metadata_style): Declare.
* cli/cli-style.c (metadata_style): New global.
(_initialize_cli_style): Register metadata style.
* cli-out.h (class cli_ui_out) <do_field_fmt>: Add style
parameter.
* cli-out.c (cli_ui_out::do_field_fmt): Update.
* c-typeprint.c (c_type_print_base_struct_union)
(c_type_print_base_1): Use metadata style.
* breakpoint.c (watchpoint_value_print)
(print_one_breakpoint_location): Use metadata style.
* break-catch-syscall.c (print_one_catch_syscall): Use metadata
style.
* break-catch-sig.c (signal_catchpoint_print_one): Use metadata
style.
* ada-valprint.c (val_print_packed_array_elements, printstr)
(print_field_values, ada_val_print_ref, ada_val_print): Use
metadata style.
* ada-typeprint.c (print_array_type, ada_print_type): Use metadata
style.
* ada-tasks.c (print_ada_task_info, info_task): Use metadata
style.
* ada-lang.c (user_select_syms): Use metadata style.
gdb/testsuite/ChangeLog
2019-10-01 Tom Tromey <tom@tromey.com>
* lib/gdb-utils.exp (style): Handle "metadata" argument.
* gdb.base/style.exp: Add metadata style test.
2019-04-03 10:00:18 +08:00
|
|
|
|
fprintf_filtered (stream, _("%s {%p[<No data fields>%p]}"),
|
2020-05-17 00:16:06 +08:00
|
|
|
|
type->name (),
|
Introduce metadata style
This introduces a new "metadata" style and changes many places in gdb
to use it. The idea here is to let the user distinguish gdb output
from output that (conceptually at least) comes directly from the
inferior. The newly-styled category includes text that gdb
traditionally surrounds in "<...>", like "<unavailable>".
I only added a single test for this. In many cases this output is
difficult to test. Also, while developing this errors in the
implementation of the new printf formats showed up as regressions.
gdb/ChangeLog
2019-10-01 Tom Tromey <tom@tromey.com>
* p-lang.c (pascal_printstr): Use metadata style.
* value.c (show_convenience): Use metadata style.
* valprint.c (valprint_check_validity, val_print_optimized_out)
(val_print_not_saved, val_print_unavailable)
(val_print_invalid_address, generic_val_print, val_print)
(value_check_printable, val_print_array_elements): Use metadata
style.
* ui-out.h (class ui_out) <field_fmt>: New overload.
<do_field_fmt>: Add style parameter.
* ui-out.c (ui_out::field_fmt): New overload.
* typeprint.c (type_print_unknown_return_type)
(val_print_not_allocated, val_print_not_associated): Use metadata
style.
* tui/tui-out.h (class tui_ui_out) <do_field_fmt>: Add style
parameter.
* tui/tui-out.c (tui_ui_out::do_field_fmt): Update.
* tracepoint.c (tvariables_info_1): Use metadata style.
* stack.c (print_frame_arg, print_frame_info, print_frame)
(info_frame_command_core): Use metadata style.
* skip.c (info_skip_command): Use metadata style.
* rust-lang.c (rust_print_enum): Use metadata style.
* python/py-prettyprint.c (print_stack_unless_memory_error): Use
metadata style.
* python/py-framefilter.c (py_print_single_arg): Use metadata
style.
* printcmd.c (do_one_display, print_variable_and_value): Use
metadata style.
* p-valprint.c (pascal_val_print)
(pascal_object_print_value_fields): Use metadata style.
* p-typeprint.c (pascal_type_print_base): Use metadata style.
* mi/mi-out.h (class mi_ui_out) <do_field_fmt>: Add style
parameter.
* mi/mi-out.c (mi_ui_out::do_field_fmt): Update.
* m2-valprint.c (m2_print_long_set): Use metadata style.
* m2-typeprint.c (m2_print_type): Use metadata style.
* infcmd.c (print_return_value_1): Use metadata style.
* gnu-v3-abi.c (print_one_vtable): Use metadata style.
* f-valprint.c (info_common_command_for_block): Use metadata
style.
* f-typeprint.c (f_type_print_base): Use metadata style.
* expprint.c (print_subexp_standard): Use metadata style.
* cp-valprint.c (cp_print_value_fields): Use metadata style.
* cli/cli-style.h (class cli_style_option): Add constructor.
(metadata_style): Declare.
* cli/cli-style.c (metadata_style): New global.
(_initialize_cli_style): Register metadata style.
* cli-out.h (class cli_ui_out) <do_field_fmt>: Add style
parameter.
* cli-out.c (cli_ui_out::do_field_fmt): Update.
* c-typeprint.c (c_type_print_base_struct_union)
(c_type_print_base_1): Use metadata style.
* breakpoint.c (watchpoint_value_print)
(print_one_breakpoint_location): Use metadata style.
* break-catch-syscall.c (print_one_catch_syscall): Use metadata
style.
* break-catch-sig.c (signal_catchpoint_print_one): Use metadata
style.
* ada-valprint.c (val_print_packed_array_elements, printstr)
(print_field_values, ada_val_print_ref, ada_val_print): Use
metadata style.
* ada-typeprint.c (print_array_type, ada_print_type): Use metadata
style.
* ada-tasks.c (print_ada_task_info, info_task): Use metadata
style.
* ada-lang.c (user_select_syms): Use metadata style.
gdb/testsuite/ChangeLog
2019-10-01 Tom Tromey <tom@tromey.com>
* lib/gdb-utils.exp (style): Handle "metadata" argument.
* gdb.base/style.exp: Add metadata style test.
2019-04-03 10:00:18 +08:00
|
|
|
|
metadata_style.style ().ptr (), nullptr);
|
2018-09-12 05:28:04 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-25 03:40:31 +08:00
|
|
|
|
int variant_fieldno = rust_enum_variant (type);
|
|
|
|
|
val = value_field (val, variant_fieldno);
|
2020-06-09 03:26:20 +08:00
|
|
|
|
struct type *variant_type = type->field (variant_fieldno).type ();
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
|
2020-05-23 04:55:15 +08:00
|
|
|
|
int nfields = variant_type->num_fields ();
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
|
|
|
|
|
bool is_tuple = rust_tuple_struct_type_p (variant_type);
|
|
|
|
|
|
2020-05-17 00:16:06 +08:00
|
|
|
|
fprintf_filtered (stream, "%s", variant_type->name ());
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
if (nfields == 0)
|
|
|
|
|
{
|
|
|
|
|
/* In case of a nullary variant like 'None', just output
|
|
|
|
|
the name. */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* In case of a non-nullary variant, we output 'Foo(x,y,z)'. */
|
|
|
|
|
if (is_tuple)
|
|
|
|
|
fprintf_filtered (stream, "(");
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* struct variant. */
|
|
|
|
|
fprintf_filtered (stream, "{");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool first_field = true;
|
2020-05-23 04:55:15 +08:00
|
|
|
|
for (int j = 0; j < variant_type->num_fields (); j++)
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
{
|
|
|
|
|
if (!first_field)
|
|
|
|
|
fputs_filtered (", ", stream);
|
|
|
|
|
first_field = false;
|
|
|
|
|
|
|
|
|
|
if (!is_tuple)
|
2020-02-23 01:02:42 +08:00
|
|
|
|
fprintf_filtered (stream, "%ps: ",
|
|
|
|
|
styled_string (variable_name_style.style (),
|
|
|
|
|
TYPE_FIELD_NAME (variant_type, j)));
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
|
2020-03-14 07:39:52 +08:00
|
|
|
|
rust_value_print_inner (value_field (val, j), stream, recurse + 1,
|
|
|
|
|
&opts);
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_tuple)
|
|
|
|
|
fputs_filtered (")", stream);
|
|
|
|
|
else
|
|
|
|
|
fputs_filtered ("}", stream);
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-27 09:38:08 +08:00
|
|
|
|
static const struct generic_val_print_decorations rust_decorations =
|
|
|
|
|
{
|
|
|
|
|
/* Complex isn't used in Rust, but we provide C-ish values just in
|
|
|
|
|
case. */
|
|
|
|
|
"",
|
|
|
|
|
" + ",
|
|
|
|
|
" * I",
|
|
|
|
|
"true",
|
|
|
|
|
"false",
|
2016-06-27 23:46:59 +08:00
|
|
|
|
"()",
|
2016-04-27 09:38:08 +08:00
|
|
|
|
"[",
|
|
|
|
|
"]"
|
|
|
|
|
};
|
|
|
|
|
|
2020-03-14 07:39:52 +08:00
|
|
|
|
/* la_value_print_inner implementation for Rust. */
|
|
|
|
|
static void
|
|
|
|
|
rust_value_print_inner (struct value *val, struct ui_file *stream,
|
|
|
|
|
int recurse,
|
|
|
|
|
const struct value_print_options *options)
|
|
|
|
|
{
|
|
|
|
|
struct value_print_options opts = *options;
|
|
|
|
|
opts.deref_ref = 1;
|
|
|
|
|
|
|
|
|
|
if (opts.prettyformat == Val_prettyformat_default)
|
|
|
|
|
opts.prettyformat = (opts.prettyformat_structs
|
|
|
|
|
? Val_prettyformat : Val_no_prettyformat);
|
|
|
|
|
|
|
|
|
|
struct type *type = check_typedef (value_type (val));
|
2020-05-15 01:46:38 +08:00
|
|
|
|
switch (type->code ())
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
|
|
|
|
case TYPE_CODE_PTR:
|
|
|
|
|
{
|
|
|
|
|
LONGEST low_bound, high_bound;
|
|
|
|
|
|
2020-05-15 01:46:38 +08:00
|
|
|
|
if (TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_ARRAY
|
2016-04-27 09:38:08 +08:00
|
|
|
|
&& rust_u8_type_p (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type)))
|
|
|
|
|
&& get_array_bounds (TYPE_TARGET_TYPE (type), &low_bound,
|
2020-03-14 07:39:52 +08:00
|
|
|
|
&high_bound))
|
|
|
|
|
{
|
|
|
|
|
/* We have a pointer to a byte string, so just print
|
|
|
|
|
that. */
|
|
|
|
|
struct type *elttype = check_typedef (TYPE_TARGET_TYPE (type));
|
|
|
|
|
CORE_ADDR addr = value_as_address (val);
|
|
|
|
|
struct gdbarch *arch = get_type_arch (type);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2020-03-14 07:39:52 +08:00
|
|
|
|
if (opts.addressprint)
|
|
|
|
|
{
|
|
|
|
|
fputs_filtered (paddress (arch, addr), stream);
|
|
|
|
|
fputs_filtered (" ", stream);
|
|
|
|
|
}
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2020-03-14 07:39:52 +08:00
|
|
|
|
fputs_filtered ("b", stream);
|
|
|
|
|
val_print_string (TYPE_TARGET_TYPE (elttype), "ASCII", addr,
|
|
|
|
|
high_bound - low_bound + 1, stream,
|
|
|
|
|
&opts);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
2020-03-14 07:39:52 +08:00
|
|
|
|
goto generic_print;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
case TYPE_CODE_INT:
|
|
|
|
|
/* Recognize the unit type. */
|
2020-09-14 23:07:57 +08:00
|
|
|
|
if (type->is_unsigned () && TYPE_LENGTH (type) == 0
|
2020-05-17 00:16:06 +08:00
|
|
|
|
&& type->name () != NULL && strcmp (type->name (), "()") == 0)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
|
|
|
|
fputs_filtered ("()", stream);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
goto generic_print;
|
|
|
|
|
|
|
|
|
|
case TYPE_CODE_STRING:
|
|
|
|
|
{
|
|
|
|
|
LONGEST low_bound, high_bound;
|
|
|
|
|
|
|
|
|
|
if (!get_array_bounds (type, &low_bound, &high_bound))
|
|
|
|
|
error (_("Could not determine the array bounds"));
|
|
|
|
|
|
|
|
|
|
/* If we see a plain TYPE_CODE_STRING, then we're printing a
|
|
|
|
|
byte string, hence the choice of "ASCII" as the
|
|
|
|
|
encoding. */
|
|
|
|
|
fputs_filtered ("b", stream);
|
|
|
|
|
rust_printstr (stream, TYPE_TARGET_TYPE (type),
|
2020-03-14 07:39:52 +08:00
|
|
|
|
value_contents_for_printing (val),
|
|
|
|
|
high_bound - low_bound + 1, "ASCII", 0, &opts);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TYPE_CODE_ARRAY:
|
|
|
|
|
{
|
|
|
|
|
LONGEST low_bound, high_bound;
|
|
|
|
|
|
|
|
|
|
if (get_array_bounds (type, &low_bound, &high_bound)
|
|
|
|
|
&& high_bound - low_bound + 1 == 0)
|
|
|
|
|
fputs_filtered ("[]", stream);
|
|
|
|
|
else
|
|
|
|
|
goto generic_print;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TYPE_CODE_UNION:
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
/* Untagged unions are printed as if they are structs. Since
|
|
|
|
|
the field bit positions overlap in the debuginfo, the code
|
|
|
|
|
for printing a union is same as that for a struct, the only
|
|
|
|
|
difference is that the input type will have overlapping
|
|
|
|
|
fields. */
|
2020-03-14 07:39:52 +08:00
|
|
|
|
val_print_struct (val, stream, recurse, &opts);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TYPE_CODE_STRUCT:
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
if (rust_enum_p (type))
|
2020-03-14 07:39:52 +08:00
|
|
|
|
rust_print_enum (val, stream, recurse, &opts);
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
else
|
2020-03-14 07:39:52 +08:00
|
|
|
|
val_print_struct (val, stream, recurse, &opts);
|
2016-10-29 09:00:43 +08:00
|
|
|
|
break;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2016-10-29 09:00:43 +08:00
|
|
|
|
default:
|
|
|
|
|
generic_print:
|
|
|
|
|
/* Nothing special yet. */
|
2020-03-14 07:39:52 +08:00
|
|
|
|
generic_value_print (val, stream, recurse, &opts, &rust_decorations);
|
2016-10-29 09:00:43 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2016-10-29 09:00:43 +08:00
|
|
|
|
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2016-10-29 09:00:43 +08:00
|
|
|
|
static void
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
rust_internal_print_type (struct type *type, const char *varstring,
|
|
|
|
|
struct ui_file *stream, int show, int level,
|
|
|
|
|
const struct type_print_options *flags,
|
2018-06-09 03:18:25 +08:00
|
|
|
|
bool for_rust_enum, print_offset_data *podata);
|
2016-10-29 09:00:43 +08:00
|
|
|
|
|
|
|
|
|
/* Print a struct or union typedef. */
|
|
|
|
|
static void
|
|
|
|
|
rust_print_struct_def (struct type *type, const char *varstring,
|
2017-02-03 12:01:11 +08:00
|
|
|
|
struct ui_file *stream, int show, int level,
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
const struct type_print_options *flags,
|
2018-06-09 03:18:25 +08:00
|
|
|
|
bool for_rust_enum, print_offset_data *podata)
|
2016-10-29 09:00:43 +08:00
|
|
|
|
{
|
2017-02-03 12:01:11 +08:00
|
|
|
|
/* Print a tuple type simply. */
|
|
|
|
|
if (rust_tuple_type_p (type))
|
|
|
|
|
{
|
2020-05-17 00:16:06 +08:00
|
|
|
|
fputs_filtered (type->name (), stream);
|
2017-02-03 12:01:11 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2017-02-03 12:01:11 +08:00
|
|
|
|
/* If we see a base class, delegate to C. */
|
|
|
|
|
if (TYPE_N_BASECLASSES (type) > 0)
|
|
|
|
|
c_print_type (type, varstring, stream, show, level, flags);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2018-06-09 03:18:25 +08:00
|
|
|
|
if (flags->print_offsets)
|
|
|
|
|
{
|
|
|
|
|
/* Temporarily bump the level so that the output lines up
|
|
|
|
|
correctly. */
|
|
|
|
|
level += 2;
|
|
|
|
|
}
|
|
|
|
|
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
/* Compute properties of TYPE here because, in the enum case, the
|
|
|
|
|
rest of the code ends up looking only at the variant part. */
|
2020-05-17 00:16:06 +08:00
|
|
|
|
const char *tagname = type->name ();
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
bool is_tuple_struct = rust_tuple_struct_type_p (type);
|
|
|
|
|
bool is_tuple = rust_tuple_type_p (type);
|
|
|
|
|
bool is_enum = rust_enum_p (type);
|
2016-10-29 09:00:43 +08:00
|
|
|
|
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
if (for_rust_enum)
|
|
|
|
|
{
|
|
|
|
|
/* Already printing an outer enum, so nothing to print here. */
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* This code path is also used by unions and enums. */
|
|
|
|
|
if (is_enum)
|
|
|
|
|
{
|
|
|
|
|
fputs_filtered ("enum ", stream);
|
2020-05-07 23:32:25 +08:00
|
|
|
|
dynamic_prop *prop = type->dyn_prop (DYN_PROP_VARIANT_PARTS);
|
gdb: add accessors to struct dynamic_prop
Add setters, to ensure that the kind and value of the property are
always kept in sync (a caller can't forget one or the other). Add
getters, such that we can assert that when a caller accesses a data bit
of the property, the property is indeed of the corresponding kind.
Note that because of the way `struct dynamic_prop` is allocated
currently, we can't make the `m_kind` and `m_data` fields private. That
would make the type non-default-constructible, and we would have to call
the constructor when allocating them. However, I still prefixed them
with `m_` to indicate that they should not be accessed from outside the
class (and also to be able to use the name `kind` for the method).
gdb/ChangeLog:
* gdbtypes.h (struct dynamic_prop) <kind, set_undefined,
const_val, set_const_val, baton, set_locexpr, set_loclist,
set_addr_offset, variant_parts, set_variant_parts,
original_type, set_original_type>: New methods.
<kind>: Rename to...
<m_kind>: ... this. Update all users to use the new methods
instead.
<data>: Rename to...
<m_data>: ... this. Update all users to use the new methods
instead.
Change-Id: Ib72a8eb440dfeb1a5421d0933334230d7f2478f9
2020-07-13 10:58:51 +08:00
|
|
|
|
if (prop != nullptr && prop->kind () == PROP_TYPE)
|
|
|
|
|
type = prop->original_type ();
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
}
|
2020-05-15 01:46:38 +08:00
|
|
|
|
else if (type->code () == TYPE_CODE_STRUCT)
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
fputs_filtered ("struct ", stream);
|
|
|
|
|
else
|
|
|
|
|
fputs_filtered ("union ", stream);
|
2016-10-29 09:00:43 +08:00
|
|
|
|
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
if (tagname != NULL)
|
|
|
|
|
fputs_filtered (tagname, stream);
|
|
|
|
|
}
|
2016-10-29 09:00:43 +08:00
|
|
|
|
|
2020-05-23 04:55:15 +08:00
|
|
|
|
if (type->num_fields () == 0 && !is_tuple)
|
2017-02-03 12:01:11 +08:00
|
|
|
|
return;
|
2018-06-09 03:18:25 +08:00
|
|
|
|
if (for_rust_enum && !flags->print_offsets)
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
fputs_filtered (is_tuple_struct ? "(" : "{", stream);
|
|
|
|
|
else
|
|
|
|
|
fputs_filtered (is_tuple_struct ? " (\n" : " {\n", stream);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2018-06-09 03:18:25 +08:00
|
|
|
|
/* When printing offsets, we rearrange the fields into storage
|
|
|
|
|
order. This lets us show holes more clearly. We work using
|
|
|
|
|
field indices here because it simplifies calls to
|
|
|
|
|
print_offset_data::update below. */
|
|
|
|
|
std::vector<int> fields;
|
2020-05-23 04:55:15 +08:00
|
|
|
|
for (int i = 0; i < type->num_fields (); ++i)
|
2017-02-03 12:01:11 +08:00
|
|
|
|
{
|
2020-05-24 05:39:54 +08:00
|
|
|
|
if (field_is_static (&type->field (i)))
|
2017-02-03 12:01:11 +08:00
|
|
|
|
continue;
|
2020-04-25 03:40:31 +08:00
|
|
|
|
if (is_enum && TYPE_FIELD_ARTIFICIAL (type, i))
|
2018-06-09 03:18:25 +08:00
|
|
|
|
continue;
|
|
|
|
|
fields.push_back (i);
|
|
|
|
|
}
|
|
|
|
|
if (flags->print_offsets)
|
|
|
|
|
std::sort (fields.begin (), fields.end (),
|
|
|
|
|
[&] (int a, int b)
|
|
|
|
|
{
|
|
|
|
|
return (TYPE_FIELD_BITPOS (type, a)
|
|
|
|
|
< TYPE_FIELD_BITPOS (type, b));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
for (int i : fields)
|
|
|
|
|
{
|
|
|
|
|
QUIT;
|
|
|
|
|
|
2020-05-24 05:39:54 +08:00
|
|
|
|
gdb_assert (!field_is_static (&type->field (i)));
|
2020-04-25 03:40:31 +08:00
|
|
|
|
gdb_assert (! (is_enum && TYPE_FIELD_ARTIFICIAL (type, i)));
|
2018-06-09 03:18:25 +08:00
|
|
|
|
|
|
|
|
|
if (flags->print_offsets)
|
|
|
|
|
podata->update (type, i, stream);
|
2017-02-03 12:01:11 +08:00
|
|
|
|
|
|
|
|
|
/* We'd like to print "pub" here as needed, but rustc
|
|
|
|
|
doesn't emit the debuginfo, and our types don't have
|
|
|
|
|
cplus_struct_type attached. */
|
|
|
|
|
|
|
|
|
|
/* For a tuple struct we print the type but nothing
|
|
|
|
|
else. */
|
2018-06-09 03:18:25 +08:00
|
|
|
|
if (!for_rust_enum || flags->print_offsets)
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
print_spaces_filtered (level + 2, stream);
|
|
|
|
|
if (is_enum)
|
2020-02-23 01:02:42 +08:00
|
|
|
|
fputs_styled (TYPE_FIELD_NAME (type, i), variable_name_style.style (),
|
|
|
|
|
stream);
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
else if (!is_tuple_struct)
|
2020-02-23 01:02:42 +08:00
|
|
|
|
fprintf_filtered (stream, "%ps: ",
|
|
|
|
|
styled_string (variable_name_style.style (),
|
|
|
|
|
TYPE_FIELD_NAME (type, i)));
|
2017-02-03 12:01:11 +08:00
|
|
|
|
|
2020-06-09 03:26:20 +08:00
|
|
|
|
rust_internal_print_type (type->field (i).type (), NULL,
|
2018-03-30 02:08:32 +08:00
|
|
|
|
stream, (is_enum ? show : show - 1),
|
2018-06-09 03:18:25 +08:00
|
|
|
|
level + 2, flags, is_enum, podata);
|
|
|
|
|
if (!for_rust_enum || flags->print_offsets)
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
fputs_filtered (",\n", stream);
|
2018-06-09 03:18:25 +08:00
|
|
|
|
/* Note that this check of "I" is ok because we only sorted the
|
|
|
|
|
fields by offset when print_offsets was set, so we won't take
|
|
|
|
|
this branch in that case. */
|
2020-05-23 04:55:15 +08:00
|
|
|
|
else if (i + 1 < type->num_fields ())
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
fputs_filtered (", ", stream);
|
2017-02-03 12:01:11 +08:00
|
|
|
|
}
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2018-06-09 03:18:25 +08:00
|
|
|
|
if (flags->print_offsets)
|
|
|
|
|
{
|
|
|
|
|
/* Undo the temporary level increase we did above. */
|
|
|
|
|
level -= 2;
|
|
|
|
|
podata->finish (type, level, stream);
|
|
|
|
|
print_spaces_filtered (print_offset_data::indentation, stream);
|
|
|
|
|
if (level == 0)
|
|
|
|
|
print_spaces_filtered (2, stream);
|
|
|
|
|
}
|
|
|
|
|
if (!for_rust_enum || flags->print_offsets)
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
print_spaces_filtered (level, stream);
|
|
|
|
|
fputs_filtered (is_tuple_struct ? ")" : "}", stream);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* la_print_type implementation for Rust. */
|
|
|
|
|
|
|
|
|
|
static void
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
rust_internal_print_type (struct type *type, const char *varstring,
|
|
|
|
|
struct ui_file *stream, int show, int level,
|
|
|
|
|
const struct type_print_options *flags,
|
2018-06-09 03:18:25 +08:00
|
|
|
|
bool for_rust_enum, print_offset_data *podata)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
|
|
|
|
QUIT;
|
|
|
|
|
if (show <= 0
|
2020-05-17 00:16:06 +08:00
|
|
|
|
&& type->name () != NULL)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
2016-06-27 23:46:59 +08:00
|
|
|
|
/* Rust calls the unit type "void" in its debuginfo,
|
|
|
|
|
but we don't want to print it as that. */
|
2020-05-15 01:46:38 +08:00
|
|
|
|
if (type->code () == TYPE_CODE_VOID)
|
2016-06-27 23:46:59 +08:00
|
|
|
|
fputs_filtered ("()", stream);
|
|
|
|
|
else
|
2020-05-17 00:16:06 +08:00
|
|
|
|
fputs_filtered (type->name (), stream);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type = check_typedef (type);
|
2020-05-15 01:46:38 +08:00
|
|
|
|
switch (type->code ())
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
2016-06-27 23:46:59 +08:00
|
|
|
|
case TYPE_CODE_VOID:
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
/* If we have an enum, we've already printed the type's
|
|
|
|
|
unqualified name, and there is nothing else to print
|
|
|
|
|
here. */
|
|
|
|
|
if (!for_rust_enum)
|
|
|
|
|
fputs_filtered ("()", stream);
|
2016-06-27 23:46:59 +08:00
|
|
|
|
break;
|
|
|
|
|
|
2016-04-27 09:38:08 +08:00
|
|
|
|
case TYPE_CODE_FUNC:
|
|
|
|
|
/* Delegate varargs to the C printer. */
|
2020-09-14 23:08:02 +08:00
|
|
|
|
if (type->has_varargs ())
|
2016-04-27 09:38:08 +08:00
|
|
|
|
goto c_printer;
|
|
|
|
|
|
|
|
|
|
fputs_filtered ("fn ", stream);
|
|
|
|
|
if (varstring != NULL)
|
|
|
|
|
fputs_filtered (varstring, stream);
|
|
|
|
|
fputs_filtered ("(", stream);
|
2020-05-23 04:55:15 +08:00
|
|
|
|
for (int i = 0; i < type->num_fields (); ++i)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
|
|
|
|
QUIT;
|
|
|
|
|
if (i > 0)
|
|
|
|
|
fputs_filtered (", ", stream);
|
2020-06-09 03:26:20 +08:00
|
|
|
|
rust_internal_print_type (type->field (i).type (), "", stream,
|
2018-06-09 03:18:25 +08:00
|
|
|
|
-1, 0, flags, false, podata);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
2016-06-27 23:46:59 +08:00
|
|
|
|
fputs_filtered (")", stream);
|
|
|
|
|
/* If it returns unit, we can omit the return type. */
|
2020-05-15 01:46:38 +08:00
|
|
|
|
if (TYPE_TARGET_TYPE (type)->code () != TYPE_CODE_VOID)
|
2016-06-27 23:46:59 +08:00
|
|
|
|
{
|
|
|
|
|
fputs_filtered (" -> ", stream);
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
rust_internal_print_type (TYPE_TARGET_TYPE (type), "", stream,
|
2018-06-09 03:18:25 +08:00
|
|
|
|
-1, 0, flags, false, podata);
|
2016-06-27 23:46:59 +08:00
|
|
|
|
}
|
2016-04-27 09:38:08 +08:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TYPE_CODE_ARRAY:
|
|
|
|
|
{
|
|
|
|
|
LONGEST low_bound, high_bound;
|
|
|
|
|
|
|
|
|
|
fputs_filtered ("[", stream);
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
rust_internal_print_type (TYPE_TARGET_TYPE (type), NULL,
|
2018-06-09 03:18:25 +08:00
|
|
|
|
stream, show - 1, level, flags, false,
|
|
|
|
|
podata);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2020-07-13 11:05:08 +08:00
|
|
|
|
if (type->bounds ()->high.kind () == PROP_LOCEXPR
|
|
|
|
|
|| type->bounds ()->high.kind () == PROP_LOCLIST)
|
2017-05-22 07:00:10 +08:00
|
|
|
|
fprintf_filtered (stream, "; variable length");
|
2016-04-27 09:38:08 +08:00
|
|
|
|
else if (get_array_bounds (type, &low_bound, &high_bound))
|
2017-05-22 07:00:10 +08:00
|
|
|
|
fprintf_filtered (stream, "; %s",
|
2016-04-27 09:38:08 +08:00
|
|
|
|
plongest (high_bound - low_bound + 1));
|
|
|
|
|
fputs_filtered ("]", stream);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
case TYPE_CODE_UNION:
|
2016-04-27 09:38:08 +08:00
|
|
|
|
case TYPE_CODE_STRUCT:
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
rust_print_struct_def (type, varstring, stream, show, level, flags,
|
2018-06-09 03:18:25 +08:00
|
|
|
|
for_rust_enum, podata);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TYPE_CODE_ENUM:
|
|
|
|
|
{
|
2018-04-22 06:16:27 +08:00
|
|
|
|
int len = 0;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
fputs_filtered ("enum ", stream);
|
2020-05-17 00:16:06 +08:00
|
|
|
|
if (type->name () != NULL)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
2020-05-17 00:16:06 +08:00
|
|
|
|
fputs_filtered (type->name (), stream);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
fputs_filtered (" ", stream);
|
2020-05-17 00:16:06 +08:00
|
|
|
|
len = strlen (type->name ());
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
fputs_filtered ("{\n", stream);
|
|
|
|
|
|
2020-05-23 04:55:15 +08:00
|
|
|
|
for (int i = 0; i < type->num_fields (); ++i)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
|
|
|
|
const char *name = TYPE_FIELD_NAME (type, i);
|
|
|
|
|
|
|
|
|
|
QUIT;
|
|
|
|
|
|
|
|
|
|
if (len > 0
|
2020-05-17 00:16:06 +08:00
|
|
|
|
&& strncmp (name, type->name (), len) == 0
|
2016-04-27 09:38:08 +08:00
|
|
|
|
&& name[len] == ':'
|
|
|
|
|
&& name[len + 1] == ':')
|
|
|
|
|
name += len + 2;
|
2020-02-23 01:02:42 +08:00
|
|
|
|
fprintfi_filtered (level + 2, stream, "%ps,\n",
|
|
|
|
|
styled_string (variable_name_style.style (),
|
|
|
|
|
name));
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fputs_filtered ("}", stream);
|
|
|
|
|
}
|
2018-11-17 06:30:35 +08:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TYPE_CODE_PTR:
|
|
|
|
|
{
|
2020-05-17 00:16:06 +08:00
|
|
|
|
if (type->name () != nullptr)
|
|
|
|
|
fputs_filtered (type->name (), stream);
|
2018-11-17 06:30:35 +08:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* We currently can't distinguish between pointers and
|
|
|
|
|
references. */
|
|
|
|
|
fputs_filtered ("*mut ", stream);
|
|
|
|
|
type_print (TYPE_TARGET_TYPE (type), "", stream, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-27 09:38:08 +08:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
c_printer:
|
|
|
|
|
c_print_type (type, varstring, stream, show, level, flags);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Like arch_composite_type, but uses TYPE to decide how to allocate
|
|
|
|
|
-- either on an obstack or on a gdbarch. */
|
|
|
|
|
|
|
|
|
|
static struct type *
|
|
|
|
|
rust_composite_type (struct type *original,
|
|
|
|
|
const char *name,
|
|
|
|
|
const char *field1, struct type *type1,
|
|
|
|
|
const char *field2, struct type *type2)
|
|
|
|
|
{
|
|
|
|
|
struct type *result = alloc_type_copy (original);
|
|
|
|
|
int i, nfields, bitpos;
|
|
|
|
|
|
|
|
|
|
nfields = 0;
|
|
|
|
|
if (field1 != NULL)
|
|
|
|
|
++nfields;
|
|
|
|
|
if (field2 != NULL)
|
|
|
|
|
++nfields;
|
|
|
|
|
|
2020-05-15 01:45:40 +08:00
|
|
|
|
result->set_code (TYPE_CODE_STRUCT);
|
2020-05-17 00:15:54 +08:00
|
|
|
|
result->set_name (name);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2020-05-23 04:55:14 +08:00
|
|
|
|
result->set_num_fields (nfields);
|
2020-05-23 04:55:16 +08:00
|
|
|
|
result->set_fields
|
|
|
|
|
((struct field *) TYPE_ZALLOC (result, nfields * sizeof (struct field)));
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
bitpos = 0;
|
|
|
|
|
if (field1 != NULL)
|
|
|
|
|
{
|
2020-05-24 05:39:54 +08:00
|
|
|
|
struct field *field = &result->field (i);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
SET_FIELD_BITPOS (*field, bitpos);
|
|
|
|
|
bitpos += TYPE_LENGTH (type1) * TARGET_CHAR_BIT;
|
|
|
|
|
|
|
|
|
|
FIELD_NAME (*field) = field1;
|
2020-06-09 03:26:04 +08:00
|
|
|
|
field->set_type (type1);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
if (field2 != NULL)
|
|
|
|
|
{
|
2020-05-24 05:39:54 +08:00
|
|
|
|
struct field *field = &result->field (i);
|
2018-04-24 03:23:02 +08:00
|
|
|
|
unsigned align = type_align (type2);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
if (align != 0)
|
|
|
|
|
{
|
|
|
|
|
int delta;
|
|
|
|
|
|
|
|
|
|
align *= TARGET_CHAR_BIT;
|
|
|
|
|
delta = bitpos % align;
|
|
|
|
|
if (delta != 0)
|
|
|
|
|
bitpos += align - delta;
|
|
|
|
|
}
|
|
|
|
|
SET_FIELD_BITPOS (*field, bitpos);
|
|
|
|
|
|
|
|
|
|
FIELD_NAME (*field) = field2;
|
2020-06-09 03:26:04 +08:00
|
|
|
|
field->set_type (type2);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (i > 0)
|
|
|
|
|
TYPE_LENGTH (result)
|
|
|
|
|
= (TYPE_FIELD_BITPOS (result, i - 1) / TARGET_CHAR_BIT +
|
2020-06-09 03:26:20 +08:00
|
|
|
|
TYPE_LENGTH (result->field (i - 1).type ()));
|
2016-04-27 09:38:08 +08:00
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* See rust-lang.h. */
|
|
|
|
|
|
|
|
|
|
struct type *
|
|
|
|
|
rust_slice_type (const char *name, struct type *elt_type,
|
|
|
|
|
struct type *usize_type)
|
|
|
|
|
{
|
|
|
|
|
struct type *type;
|
|
|
|
|
|
|
|
|
|
elt_type = lookup_pointer_type (elt_type);
|
|
|
|
|
type = rust_composite_type (elt_type, name,
|
|
|
|
|
"data_ptr", elt_type,
|
|
|
|
|
"length", usize_type);
|
|
|
|
|
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum rust_primitive_types
|
|
|
|
|
{
|
|
|
|
|
rust_primitive_bool,
|
|
|
|
|
rust_primitive_char,
|
|
|
|
|
rust_primitive_i8,
|
|
|
|
|
rust_primitive_u8,
|
|
|
|
|
rust_primitive_i16,
|
|
|
|
|
rust_primitive_u16,
|
|
|
|
|
rust_primitive_i32,
|
|
|
|
|
rust_primitive_u32,
|
|
|
|
|
rust_primitive_i64,
|
|
|
|
|
rust_primitive_u64,
|
|
|
|
|
rust_primitive_isize,
|
|
|
|
|
rust_primitive_usize,
|
|
|
|
|
rust_primitive_f32,
|
|
|
|
|
rust_primitive_f64,
|
|
|
|
|
rust_primitive_unit,
|
|
|
|
|
rust_primitive_str,
|
|
|
|
|
nr_rust_primitive_types
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* A helper for rust_evaluate_subexp that handles OP_FUNCALL. */
|
|
|
|
|
|
|
|
|
|
static struct value *
|
|
|
|
|
rust_evaluate_funcall (struct expression *exp, int *pos, enum noside noside)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
int num_args = exp->elts[*pos + 1].longconst;
|
|
|
|
|
const char *method;
|
|
|
|
|
struct value *function, *result, *arg0;
|
|
|
|
|
struct type *type, *fn_type;
|
|
|
|
|
const struct block *block;
|
|
|
|
|
struct block_symbol sym;
|
|
|
|
|
|
|
|
|
|
/* For an ordinary function call we can simply defer to the
|
|
|
|
|
generic implementation. */
|
|
|
|
|
if (exp->elts[*pos + 3].opcode != STRUCTOP_STRUCT)
|
|
|
|
|
return evaluate_subexp_standard (NULL, exp, pos, noside);
|
|
|
|
|
|
|
|
|
|
/* Skip over the OP_FUNCALL and the STRUCTOP_STRUCT. */
|
|
|
|
|
*pos += 4;
|
|
|
|
|
method = &exp->elts[*pos + 1].string;
|
|
|
|
|
*pos += 3 + BYTES_TO_EXP_ELEM (exp->elts[*pos].longconst + 1);
|
|
|
|
|
|
|
|
|
|
/* Evaluate the argument to STRUCTOP_STRUCT, then find its
|
|
|
|
|
type in order to look up the method. */
|
2020-08-31 22:44:33 +08:00
|
|
|
|
arg0 = evaluate_subexp (nullptr, exp, pos, noside);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
if (noside == EVAL_SKIP)
|
|
|
|
|
{
|
|
|
|
|
for (i = 0; i < num_args; ++i)
|
2020-08-31 22:44:33 +08:00
|
|
|
|
evaluate_subexp (nullptr, exp, pos, noside);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
return arg0;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-22 23:51:20 +08:00
|
|
|
|
std::vector<struct value *> args (num_args + 1);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
args[0] = arg0;
|
|
|
|
|
|
|
|
|
|
/* We don't yet implement real Deref semantics. */
|
2020-05-15 01:46:38 +08:00
|
|
|
|
while (value_type (args[0])->code () == TYPE_CODE_PTR)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
args[0] = value_ind (args[0]);
|
|
|
|
|
|
|
|
|
|
type = value_type (args[0]);
|
2020-05-15 01:46:38 +08:00
|
|
|
|
if ((type->code () != TYPE_CODE_STRUCT
|
|
|
|
|
&& type->code () != TYPE_CODE_UNION
|
|
|
|
|
&& type->code () != TYPE_CODE_ENUM)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|| rust_tuple_type_p (type))
|
|
|
|
|
error (_("Method calls only supported on struct or enum types"));
|
2020-05-17 00:16:06 +08:00
|
|
|
|
if (type->name () == NULL)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
error (_("Method call on nameless type"));
|
|
|
|
|
|
2020-05-17 00:16:06 +08:00
|
|
|
|
std::string name = std::string (type->name ()) + "::" + method;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
block = get_selected_block (0);
|
2016-09-22 23:51:20 +08:00
|
|
|
|
sym = lookup_symbol (name.c_str (), block, VAR_DOMAIN, NULL);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
if (sym.symbol == NULL)
|
2016-09-22 23:51:20 +08:00
|
|
|
|
error (_("Could not find function named '%s'"), name.c_str ());
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
fn_type = SYMBOL_TYPE (sym.symbol);
|
2020-05-23 04:55:15 +08:00
|
|
|
|
if (fn_type->num_fields () == 0)
|
2016-09-22 23:51:20 +08:00
|
|
|
|
error (_("Function '%s' takes no arguments"), name.c_str ());
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2020-06-09 03:26:20 +08:00
|
|
|
|
if (fn_type->field (0).type ()->code () == TYPE_CODE_PTR)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
args[0] = value_addr (args[0]);
|
|
|
|
|
|
|
|
|
|
function = address_of_variable (sym.symbol, block);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < num_args; ++i)
|
2020-08-31 22:44:33 +08:00
|
|
|
|
args[i + 1] = evaluate_subexp (nullptr, exp, pos, noside);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
if (noside == EVAL_AVOID_SIDE_EFFECTS)
|
|
|
|
|
result = value_zero (TYPE_TARGET_TYPE (fn_type), not_lval);
|
|
|
|
|
else
|
Use gdb:array_view in call_function_by_hand & friends
This replaces a few uses of pointer+length with gdb::array_view, in
call_function_by_hand and related code.
Unfortunately, due to -Wnarrowing, there are places where we can't
brace-initialize an gdb::array_view without an ugly-ish cast. To
avoid the cast, this patch introduces a gdb::make_array_view function.
Unit tests included.
This patch in isolation may not look so interesting, due to
gdb::make_array_view uses, but I think it's still worth it. Some of
the gdb::make_array_view calls disappear down the series, and others
could be eliminated with more (non-trivial) gdb::array_view
detangling/conversion (e.g. code around eval_call). See this as a "we
have to start somewhere" patch.
gdb/ChangeLog:
2018-11-21 Pedro Alves <palves@redhat.com>
* ada-lang.c (ada_evaluate_subexp): Adjust to pass an array_view.
* common/array-view.h (make_array_view): New.
* compile/compile-object-run.c (compile_object_run): Adjust to
pass an array_view.
* elfread.c (elf_gnu_ifunc_resolve_addr): Adjust.
* eval.c (eval_call): Adjust to pass an array_view.
(evaluate_subexp_standard): Adjust to pass an array_view.
* gcore.c (call_target_sbrk): Adjust to pass an array_view.
* guile/scm-value.c (gdbscm_value_call): Likewise.
* infcall.c (push_dummy_code): Replace pointer + size parameters
with an array_view parameter.
(call_function_by_hand, call_function_by_hand_dummy): Likewise and
adjust.
* infcall.h: Include "common/array-view.h".
(call_function_by_hand, call_function_by_hand_dummy): Replace
pointer + size parameters with an array_view parameter.
* linux-fork.c (inferior_call_waitpid): Adjust to use array_view.
* linux-tdep.c (linux_infcall_mmap): Likewise.
* objc-lang.c (lookup_objc_class, lookup_child_selector)
(value_nsstring, print_object_command): Likewise.
* python/py-value.c (valpy_call): Likewise.
* rust-lang.c (rust_evaluate_funcall): Likewise.
* spu-tdep.c (flush_ea_cache): Likewise.
* valarith.c (value_x_binop, value_x_unop): Likewise.
* valops.c (value_allocate_space_in_inferior): Likewise.
* unittests/array-view-selftests.c (run_tests): Add
gdb::make_array_view test.
2018-11-21 19:55:11 +08:00
|
|
|
|
result = call_function_by_hand (function, NULL, args);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-28 00:28:56 +08:00
|
|
|
|
/* A helper for rust_evaluate_subexp that handles OP_RANGE. */
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
static struct value *
|
|
|
|
|
rust_range (struct expression *exp, int *pos, enum noside noside)
|
|
|
|
|
{
|
2016-04-28 00:28:56 +08:00
|
|
|
|
enum range_type kind;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
struct value *low = NULL, *high = NULL;
|
|
|
|
|
struct value *addrval, *result;
|
|
|
|
|
CORE_ADDR addr;
|
|
|
|
|
struct type *range_type;
|
|
|
|
|
struct type *index_type;
|
|
|
|
|
struct type *temp_type;
|
|
|
|
|
const char *name;
|
|
|
|
|
|
2016-04-28 00:28:56 +08:00
|
|
|
|
kind = (enum range_type) longest_to_int (exp->elts[*pos + 1].longconst);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
*pos += 3;
|
|
|
|
|
|
2018-03-30 04:14:07 +08:00
|
|
|
|
if (kind == HIGH_BOUND_DEFAULT || kind == NONE_BOUND_DEFAULT
|
|
|
|
|
|| kind == NONE_BOUND_DEFAULT_EXCLUSIVE)
|
2020-08-31 22:44:33 +08:00
|
|
|
|
low = evaluate_subexp (nullptr, exp, pos, noside);
|
2018-03-30 04:14:07 +08:00
|
|
|
|
if (kind == LOW_BOUND_DEFAULT || kind == LOW_BOUND_DEFAULT_EXCLUSIVE
|
|
|
|
|
|| kind == NONE_BOUND_DEFAULT || kind == NONE_BOUND_DEFAULT_EXCLUSIVE)
|
2020-08-31 22:44:33 +08:00
|
|
|
|
high = evaluate_subexp (nullptr, exp, pos, noside);
|
2018-03-30 04:14:07 +08:00
|
|
|
|
bool inclusive = (kind == NONE_BOUND_DEFAULT || kind == LOW_BOUND_DEFAULT);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
if (noside == EVAL_SKIP)
|
|
|
|
|
return value_from_longest (builtin_type (exp->gdbarch)->builtin_int, 1);
|
|
|
|
|
|
|
|
|
|
if (low == NULL)
|
|
|
|
|
{
|
|
|
|
|
if (high == NULL)
|
|
|
|
|
{
|
|
|
|
|
index_type = NULL;
|
|
|
|
|
name = "std::ops::RangeFull";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
index_type = value_type (high);
|
2018-03-30 04:14:07 +08:00
|
|
|
|
name = (inclusive
|
|
|
|
|
? "std::ops::RangeToInclusive" : "std::ops::RangeTo");
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (high == NULL)
|
|
|
|
|
{
|
|
|
|
|
index_type = value_type (low);
|
|
|
|
|
name = "std::ops::RangeFrom";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!types_equal (value_type (low), value_type (high)))
|
|
|
|
|
error (_("Range expression with different types"));
|
|
|
|
|
index_type = value_type (low);
|
2018-03-30 04:14:07 +08:00
|
|
|
|
name = inclusive ? "std::ops::RangeInclusive" : "std::ops::Range";
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we don't have an index type, just allocate this on the
|
|
|
|
|
arch. Here any type will do. */
|
|
|
|
|
temp_type = (index_type == NULL
|
|
|
|
|
? language_bool_type (exp->language_defn, exp->gdbarch)
|
|
|
|
|
: index_type);
|
|
|
|
|
/* It would be nicer to cache the range type. */
|
|
|
|
|
range_type = rust_composite_type (temp_type, name,
|
|
|
|
|
low == NULL ? NULL : "start", index_type,
|
|
|
|
|
high == NULL ? NULL : "end", index_type);
|
|
|
|
|
|
|
|
|
|
if (noside == EVAL_AVOID_SIDE_EFFECTS)
|
|
|
|
|
return value_zero (range_type, lval_memory);
|
|
|
|
|
|
|
|
|
|
addrval = value_allocate_space_in_inferior (TYPE_LENGTH (range_type));
|
|
|
|
|
addr = value_as_long (addrval);
|
|
|
|
|
result = value_at_lazy (range_type, addr);
|
|
|
|
|
|
|
|
|
|
if (low != NULL)
|
|
|
|
|
{
|
|
|
|
|
struct value *start = value_struct_elt (&result, NULL, "start", NULL,
|
|
|
|
|
"range");
|
|
|
|
|
|
|
|
|
|
value_assign (start, low);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (high != NULL)
|
|
|
|
|
{
|
|
|
|
|
struct value *end = value_struct_elt (&result, NULL, "end", NULL,
|
|
|
|
|
"range");
|
|
|
|
|
|
|
|
|
|
value_assign (end, high);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = value_at_lazy (range_type, addr);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* A helper function to compute the range and kind given a range
|
|
|
|
|
value. TYPE is the type of the range value. RANGE is the range
|
|
|
|
|
value. LOW, HIGH, and KIND are out parameters. The LOW and HIGH
|
|
|
|
|
parameters might be filled in, or might not be, depending on the
|
|
|
|
|
kind of range this is. KIND will always be set to the appropriate
|
|
|
|
|
value describing the kind of range, and this can be used to
|
|
|
|
|
determine whether LOW or HIGH are valid. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
rust_compute_range (struct type *type, struct value *range,
|
|
|
|
|
LONGEST *low, LONGEST *high,
|
2016-04-28 00:28:56 +08:00
|
|
|
|
enum range_type *kind)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
*low = 0;
|
|
|
|
|
*high = 0;
|
|
|
|
|
*kind = BOTH_BOUND_DEFAULT;
|
|
|
|
|
|
2020-05-23 04:55:15 +08:00
|
|
|
|
if (type->num_fields () == 0)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
if (strcmp (TYPE_FIELD_NAME (type, 0), "start") == 0)
|
|
|
|
|
{
|
|
|
|
|
*kind = HIGH_BOUND_DEFAULT;
|
|
|
|
|
*low = value_as_long (value_field (range, 0));
|
|
|
|
|
++i;
|
|
|
|
|
}
|
2020-05-23 04:55:15 +08:00
|
|
|
|
if (type->num_fields () > i
|
2016-04-27 09:38:08 +08:00
|
|
|
|
&& strcmp (TYPE_FIELD_NAME (type, i), "end") == 0)
|
|
|
|
|
{
|
|
|
|
|
*kind = (*kind == BOTH_BOUND_DEFAULT
|
|
|
|
|
? LOW_BOUND_DEFAULT : NONE_BOUND_DEFAULT);
|
|
|
|
|
*high = value_as_long (value_field (range, i));
|
2018-03-30 04:14:07 +08:00
|
|
|
|
|
|
|
|
|
if (rust_inclusive_range_type_p (type))
|
|
|
|
|
++*high;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* A helper for rust_evaluate_subexp that handles BINOP_SUBSCRIPT. */
|
|
|
|
|
|
|
|
|
|
static struct value *
|
|
|
|
|
rust_subscript (struct expression *exp, int *pos, enum noside noside,
|
|
|
|
|
int for_addr)
|
|
|
|
|
{
|
|
|
|
|
struct value *lhs, *rhs, *result;
|
|
|
|
|
struct type *rhstype;
|
2016-05-19 00:48:41 +08:00
|
|
|
|
LONGEST low, high_bound;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
/* Initialized to appease the compiler. */
|
2016-04-28 00:28:56 +08:00
|
|
|
|
enum range_type kind = BOTH_BOUND_DEFAULT;
|
2016-05-19 00:48:41 +08:00
|
|
|
|
LONGEST high = 0;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
int want_slice = 0;
|
|
|
|
|
|
|
|
|
|
++*pos;
|
2020-08-31 22:44:33 +08:00
|
|
|
|
lhs = evaluate_subexp (nullptr, exp, pos, noside);
|
|
|
|
|
rhs = evaluate_subexp (nullptr, exp, pos, noside);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
if (noside == EVAL_SKIP)
|
|
|
|
|
return lhs;
|
|
|
|
|
|
|
|
|
|
rhstype = check_typedef (value_type (rhs));
|
|
|
|
|
if (rust_range_type_p (rhstype))
|
|
|
|
|
{
|
|
|
|
|
if (!for_addr)
|
|
|
|
|
error (_("Can't take slice of array without '&'"));
|
|
|
|
|
rust_compute_range (rhstype, rhs, &low, &high, &kind);
|
|
|
|
|
want_slice = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
low = value_as_long (rhs);
|
|
|
|
|
|
2017-10-03 03:47:15 +08:00
|
|
|
|
struct type *type = check_typedef (value_type (lhs));
|
2016-04-27 09:38:08 +08:00
|
|
|
|
if (noside == EVAL_AVOID_SIDE_EFFECTS)
|
|
|
|
|
{
|
2017-10-03 03:47:15 +08:00
|
|
|
|
struct type *base_type = nullptr;
|
2020-05-15 01:46:38 +08:00
|
|
|
|
if (type->code () == TYPE_CODE_ARRAY)
|
2017-10-03 03:47:15 +08:00
|
|
|
|
base_type = TYPE_TARGET_TYPE (type);
|
|
|
|
|
else if (rust_slice_type_p (type))
|
|
|
|
|
{
|
2020-05-23 04:55:15 +08:00
|
|
|
|
for (int i = 0; i < type->num_fields (); ++i)
|
2017-10-03 03:47:15 +08:00
|
|
|
|
{
|
|
|
|
|
if (strcmp (TYPE_FIELD_NAME (type, i), "data_ptr") == 0)
|
|
|
|
|
{
|
2020-06-09 03:26:20 +08:00
|
|
|
|
base_type = TYPE_TARGET_TYPE (type->field (i).type ());
|
2017-10-03 03:47:15 +08:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (base_type == nullptr)
|
|
|
|
|
error (_("Could not find 'data_ptr' in slice type"));
|
|
|
|
|
}
|
2020-05-15 01:46:38 +08:00
|
|
|
|
else if (type->code () == TYPE_CODE_PTR)
|
2017-10-03 03:47:15 +08:00
|
|
|
|
base_type = TYPE_TARGET_TYPE (type);
|
|
|
|
|
else
|
|
|
|
|
error (_("Cannot subscript non-array type"));
|
|
|
|
|
|
|
|
|
|
struct type *new_type;
|
|
|
|
|
if (want_slice)
|
|
|
|
|
{
|
|
|
|
|
if (rust_slice_type_p (type))
|
|
|
|
|
new_type = type;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
struct type *usize
|
|
|
|
|
= language_lookup_primitive_type (exp->language_defn,
|
|
|
|
|
exp->gdbarch,
|
|
|
|
|
"usize");
|
|
|
|
|
new_type = rust_slice_type ("&[*gdb*]", base_type, usize);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
new_type = base_type;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2017-10-03 03:47:15 +08:00
|
|
|
|
return value_zero (new_type, VALUE_LVAL (lhs));
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
LONGEST low_bound;
|
|
|
|
|
struct value *base;
|
|
|
|
|
|
2020-05-15 01:46:38 +08:00
|
|
|
|
if (type->code () == TYPE_CODE_ARRAY)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
|
|
|
|
base = lhs;
|
|
|
|
|
if (!get_array_bounds (type, &low_bound, &high_bound))
|
|
|
|
|
error (_("Can't compute array bounds"));
|
|
|
|
|
if (low_bound != 0)
|
|
|
|
|
error (_("Found array with non-zero lower bound"));
|
|
|
|
|
++high_bound;
|
|
|
|
|
}
|
|
|
|
|
else if (rust_slice_type_p (type))
|
|
|
|
|
{
|
|
|
|
|
struct value *len;
|
|
|
|
|
|
|
|
|
|
base = value_struct_elt (&lhs, NULL, "data_ptr", NULL, "slice");
|
|
|
|
|
len = value_struct_elt (&lhs, NULL, "length", NULL, "slice");
|
|
|
|
|
low_bound = 0;
|
|
|
|
|
high_bound = value_as_long (len);
|
|
|
|
|
}
|
2020-05-15 01:46:38 +08:00
|
|
|
|
else if (type->code () == TYPE_CODE_PTR)
|
2016-07-06 13:25:10 +08:00
|
|
|
|
{
|
|
|
|
|
base = lhs;
|
|
|
|
|
low_bound = 0;
|
|
|
|
|
high_bound = LONGEST_MAX;
|
|
|
|
|
}
|
2016-04-27 09:38:08 +08:00
|
|
|
|
else
|
|
|
|
|
error (_("Cannot subscript non-array type"));
|
|
|
|
|
|
|
|
|
|
if (want_slice
|
|
|
|
|
&& (kind == BOTH_BOUND_DEFAULT || kind == LOW_BOUND_DEFAULT))
|
|
|
|
|
low = low_bound;
|
|
|
|
|
if (low < 0)
|
|
|
|
|
error (_("Index less than zero"));
|
|
|
|
|
if (low > high_bound)
|
|
|
|
|
error (_("Index greater than length"));
|
|
|
|
|
|
|
|
|
|
result = value_subscript (base, low);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (for_addr)
|
|
|
|
|
{
|
|
|
|
|
if (want_slice)
|
|
|
|
|
{
|
|
|
|
|
struct type *usize, *slice;
|
|
|
|
|
CORE_ADDR addr;
|
|
|
|
|
struct value *addrval, *tem;
|
|
|
|
|
|
|
|
|
|
if (kind == BOTH_BOUND_DEFAULT || kind == HIGH_BOUND_DEFAULT)
|
|
|
|
|
high = high_bound;
|
|
|
|
|
if (high < 0)
|
|
|
|
|
error (_("High index less than zero"));
|
|
|
|
|
if (low > high)
|
|
|
|
|
error (_("Low index greater than high index"));
|
|
|
|
|
if (high > high_bound)
|
|
|
|
|
error (_("High index greater than length"));
|
|
|
|
|
|
|
|
|
|
usize = language_lookup_primitive_type (exp->language_defn,
|
|
|
|
|
exp->gdbarch,
|
|
|
|
|
"usize");
|
2017-10-03 03:55:42 +08:00
|
|
|
|
const char *new_name = ((type != nullptr
|
|
|
|
|
&& rust_slice_type_p (type))
|
2020-05-17 00:16:06 +08:00
|
|
|
|
? type->name () : "&[*gdb*]");
|
2017-10-03 03:55:42 +08:00
|
|
|
|
|
|
|
|
|
slice = rust_slice_type (new_name, value_type (result), usize);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
addrval = value_allocate_space_in_inferior (TYPE_LENGTH (slice));
|
|
|
|
|
addr = value_as_long (addrval);
|
|
|
|
|
tem = value_at_lazy (slice, addr);
|
|
|
|
|
|
|
|
|
|
value_assign (value_field (tem, 0), value_addr (result));
|
|
|
|
|
value_assign (value_field (tem, 1),
|
|
|
|
|
value_from_longest (usize, high - low));
|
|
|
|
|
|
|
|
|
|
result = value_at_lazy (slice, addr);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
result = value_addr (result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* evaluate_exp implementation for Rust. */
|
|
|
|
|
|
|
|
|
|
static struct value *
|
|
|
|
|
rust_evaluate_subexp (struct type *expect_type, struct expression *exp,
|
|
|
|
|
int *pos, enum noside noside)
|
|
|
|
|
{
|
|
|
|
|
struct value *result;
|
|
|
|
|
|
|
|
|
|
switch (exp->elts[*pos].opcode)
|
|
|
|
|
{
|
Handle dereferencing Rust trait objects
In Rust, virtual tables work a bit differently than they do in C++. In
C++, as you know, they are connected to a particular class hierarchy.
Rust, instead, can generate a virtual table for potentially any type --
in fact, one such virtual table for each trait (a trait is similar to an
abstract class or to a Java interface) that a type implements.
Objects that are referenced via a trait can't currently be inspected by
gdb. This patch implements the Rust equivalent of "set print object".
gdb relies heavily on the C++ ABI to decode virtual tables; primarily to
make "set print object" work; but also "info vtbl". However, Rust does
not currently have a specified ABI, so this approach seems unwise to
emulate.
Instead, I've changed the Rust compiler to emit some DWARF that
describes trait objects (previously their internal structure was
opaque), vtables (currently just a size -- but I hope to expand this in
the future), and the concrete type for which a vtable was emitted.
The concrete type is expressed as a DW_AT_containing_type on the
vtable's type. This is a small extension to DWARF.
This patch adds a new entry to quick_symbol_functions to return the
symtab that holds a data address. Previously there was no way in gdb to
look up a full (only minimal) non-text symbol by address. The psymbol
implementation of this method works by lazily filling in a map that is
added to the objfile. This avoids slowing down psymbol reading for a
feature that is likely to not be used too frequently.
I did not update .gdb_index. My thinking here is that the DWARF 5
indices will obsolete .gdb_index soon-ish, meaning that adding a new
feature to them is probably wasted work. If necessary I can update the
DWARF 5 index code when it lands in gdb.
Regression tested on x86-64 Fedora 25.
2017-11-17 Tom Tromey <tom@tromey.com>
* symtab.h (struct symbol) <is_rust_vtable>: New member.
(struct rust_vtable_symbol): New.
(find_symbol_at_address): Declare.
* symtab.c (find_symbol_at_address): New function.
* symfile.h (struct quick_symbol_functions)
<find_compunit_symtab_by_address>: New member.
* symfile-debug.c (debug_qf_find_compunit_symtab_by_address): New
function.
(debug_sym_quick_functions): Link to
debug_qf_find_compunit_symtab_by_address.
* rust-lang.c (rust_get_trait_object_pointer): New function.
(rust_evaluate_subexp) <case UNOP_IND>: New case. Call
rust_get_trait_object_pointer.
* psymtab.c (psym_relocate): Clear psymbol_map.
(psym_fill_psymbol_map, psym_find_compunit_symtab_by_address): New
functions.
(psym_functions): Link to psym_find_compunit_symtab_by_address.
* objfiles.h (struct objfile) <psymbol_map>: New member.
* dwarf2read.c (dwarf2_gdb_index_functions): Update.
(process_die) <DW_TAG_variable>: New case. Call read_variable.
(rust_containing_type, read_variable): New functions.
2017-11-17 Tom Tromey <tom@tromey.com>
* gdb.rust/traits.rs: New file.
* gdb.rust/traits.exp: New file.
2017-07-06 20:44:38 +08:00
|
|
|
|
case UNOP_IND:
|
|
|
|
|
{
|
|
|
|
|
if (noside != EVAL_NORMAL)
|
|
|
|
|
result = evaluate_subexp_standard (expect_type, exp, pos, noside);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
++*pos;
|
|
|
|
|
struct value *value = evaluate_subexp (expect_type, exp, pos,
|
|
|
|
|
noside);
|
|
|
|
|
|
|
|
|
|
struct value *trait_ptr = rust_get_trait_object_pointer (value);
|
|
|
|
|
if (trait_ptr != NULL)
|
|
|
|
|
value = trait_ptr;
|
|
|
|
|
|
|
|
|
|
result = value_ind (value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2016-04-27 09:38:08 +08:00
|
|
|
|
case UNOP_COMPLEMENT:
|
|
|
|
|
{
|
|
|
|
|
struct value *value;
|
|
|
|
|
|
|
|
|
|
++*pos;
|
2020-08-31 22:44:33 +08:00
|
|
|
|
value = evaluate_subexp (nullptr, exp, pos, noside);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
if (noside == EVAL_SKIP)
|
|
|
|
|
{
|
|
|
|
|
/* Preserving the type is enough. */
|
|
|
|
|
return value;
|
|
|
|
|
}
|
2020-05-15 01:46:38 +08:00
|
|
|
|
if (value_type (value)->code () == TYPE_CODE_BOOL)
|
2016-04-27 09:38:08 +08:00
|
|
|
|
result = value_from_longest (value_type (value),
|
|
|
|
|
value_logical_not (value));
|
|
|
|
|
else
|
|
|
|
|
result = value_complement (value);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BINOP_SUBSCRIPT:
|
|
|
|
|
result = rust_subscript (exp, pos, noside, 0);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OP_FUNCALL:
|
|
|
|
|
result = rust_evaluate_funcall (exp, pos, noside);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OP_AGGREGATE:
|
|
|
|
|
{
|
|
|
|
|
int pc = (*pos)++;
|
|
|
|
|
struct type *type = exp->elts[pc + 1].type;
|
|
|
|
|
int arglen = longest_to_int (exp->elts[pc + 2].longconst);
|
|
|
|
|
int i;
|
|
|
|
|
CORE_ADDR addr = 0;
|
|
|
|
|
struct value *addrval = NULL;
|
|
|
|
|
|
|
|
|
|
*pos += 3;
|
|
|
|
|
|
|
|
|
|
if (noside == EVAL_NORMAL)
|
|
|
|
|
{
|
|
|
|
|
addrval = value_allocate_space_in_inferior (TYPE_LENGTH (type));
|
|
|
|
|
addr = value_as_long (addrval);
|
|
|
|
|
result = value_at_lazy (type, addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (arglen > 0 && exp->elts[*pos].opcode == OP_OTHERS)
|
|
|
|
|
{
|
|
|
|
|
struct value *init;
|
|
|
|
|
|
|
|
|
|
++*pos;
|
|
|
|
|
init = rust_evaluate_subexp (NULL, exp, pos, noside);
|
|
|
|
|
if (noside == EVAL_NORMAL)
|
|
|
|
|
{
|
|
|
|
|
/* This isn't quite right but will do for the time
|
|
|
|
|
being, seeing that we can't implement the Copy
|
|
|
|
|
trait anyway. */
|
|
|
|
|
value_assign (result, init);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
--arglen;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gdb_assert (arglen % 2 == 0);
|
|
|
|
|
for (i = 0; i < arglen; i += 2)
|
|
|
|
|
{
|
|
|
|
|
int len;
|
|
|
|
|
const char *fieldname;
|
|
|
|
|
struct value *value, *field;
|
|
|
|
|
|
|
|
|
|
gdb_assert (exp->elts[*pos].opcode == OP_NAME);
|
|
|
|
|
++*pos;
|
|
|
|
|
len = longest_to_int (exp->elts[*pos].longconst);
|
|
|
|
|
++*pos;
|
|
|
|
|
fieldname = &exp->elts[*pos].string;
|
|
|
|
|
*pos += 2 + BYTES_TO_EXP_ELEM (len + 1);
|
|
|
|
|
|
|
|
|
|
value = rust_evaluate_subexp (NULL, exp, pos, noside);
|
|
|
|
|
if (noside == EVAL_NORMAL)
|
|
|
|
|
{
|
|
|
|
|
field = value_struct_elt (&result, NULL, fieldname, NULL,
|
|
|
|
|
"structure");
|
|
|
|
|
value_assign (field, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (noside == EVAL_SKIP)
|
|
|
|
|
return value_from_longest (builtin_type (exp->gdbarch)->builtin_int,
|
|
|
|
|
1);
|
|
|
|
|
else if (noside == EVAL_AVOID_SIDE_EFFECTS)
|
|
|
|
|
result = allocate_value (type);
|
|
|
|
|
else
|
|
|
|
|
result = value_at_lazy (type, addr);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OP_RUST_ARRAY:
|
|
|
|
|
{
|
Simple unused variable removals
This patch holds all the straightforward unused variable deletions.
gdb/ChangeLog
2018-07-22 Tom Tromey <tom@tromey.com>
* guile/scm-value.c (gdbscm_value_call): Remove unused variables.
* guile/scm-math.c (vlscm_unop_gdbthrow, vlscm_binop_gdbthrow)
(vlscm_convert_typed_value_from_scheme): Remove unused variable.
* buildsym-legacy.c (get_macro_table): Remove unused variable.
* stack.c (frame_apply_level_command): Remove unused variable.
* tic6x-tdep.c (tic6x_push_dummy_call): Remove unused variable.
* sparc64-tdep.c (adi_examine_command): Remove unused variable.
* rs6000-lynx178-tdep.c (rs6000_lynx178_push_dummy_call): Remove
unused variable.
* nios2-tdep.c (nios2_push_dummy_call): Remove unused variable.
* mep-tdep.c (mep_push_dummy_call): Remove unused variable.
* ada-lang.c (ada_lookup_symbol_list_worker): Remove unused
variable.
* amd64-tdep.c (amd64_supply_xsave): Remove unused variable.
* arm-tdep.c (arm_record_data_proc_misc_ld_str): Remove unused
variable.
* breakpoint.c (check_no_tracepoint_commands, update_watchpoint):
Remove unused variable.
* cli/cli-script.c (recurse_read_control_structure): Remove unused
variable.
* common/tdesc.c (print_xml_feature::visit): Remove unused
variable.
* compile/compile-object-load.c (store_regs): Remove unused
variables.
* complaints.c (clear_complaints): Remove unused variable.
* corelow.c (core_target_open): Remove unused variable.
* fbsd-tdep.c (fbsd_core_info_proc_status): Remove unused
variable.
* guile/scm-frame.c (gdbscm_frame_read_var): Remove unused
variable.
* guile/scm-symtab.c (stscm_print_sal_smob): Remove unused
variable.
* guile/scm-type.c (gdbscm_field_baseclass_p): Remove unused
variable.
* guile/scm-utils.c (gdbscm_parse_function_args): Remove unused
variable.
* hppa-tdep.c (hppa_stub_frame_unwind_cache): Remove unused
variable.
* ia64-tdep.c (examine_prologue): Remove unused variable.
* infcall.c (run_inferior_call): Remove unused variable.
* inferior.c (exit_inferior): Remove unused variable.
* infrun.c (infrun_thread_ptid_changed): Remove unused variable.
* linespec.c (decode_line_2): Remove unused variable.
* linux-nat.c (super_close): Remove.
* linux-tdep.c (linux_info_proc): Remove unused variable.
* mi/mi-main.c (mi_execute_command): Remove unused variable.
* microblaze-linux-tdep.c (microblaze_linux_sigtramp_cache):
Remove unused variable.
* parse.c (find_minsym_type_and_address): Remove unused variable.
* printcmd.c (info_symbol_command, printf_floating): Remove unused
variable.
* python/py-breakpoint.c (bppy_set_commands): Remove unused
variable.
* python/py-unwind.c (unwind_infopy_dealloc): Remove unused
variables.
* record-btrace.c (record_btrace_target::store_registers): Remove
unused variable.
(cmd_show_record_btrace_cpu): Remove unused variable.
* riscv-tdep.c (riscv_register_reggroup_p)
(riscv_push_dummy_call, riscv_return_value): Remove unused
variable.
* rust-exp.y (literal): Remove unused variable.
* rust-lang.c (rust_evaluate_subexp) <OP_RUST_ARARAY>: Remove
unused variable.
<STRUCTOP_ANONYMOUS>: Likewise.
* s390-linux-tdep.c (s390_linux_init_abi_31)
(s390_linux_init_abi_64): Remove unused variable.
* ser-ming2.c (ser_windows_read_prim, pipe_select_thread)
(file_select_thread, net_windows_open, _initialize_ser_windows):
Remove unused variables.
* symtab.c (find_pc_sect_line): Remove unused variable.
* target-memory.c (compute_garbled_blocks): Remove unused
variable.
(target_write_memory_blocks): Remove unused variable.
* target.c (target_stack::unpush): Remove unused variables.
* tracepoint.c (start_tracing, all_tracepoint_actions)
(merge_uploaded_trace_state_variables)
(print_one_static_tracepoint_marker): Remove unused variable.
* unittests/basic_string_view/element_access/char/1.cc (test01):
Remove unused variable.
* windows-nat.c (windows_continue, windows_add_all_dlls)
(do_initial_windows_stuff, windows_nat_target::create_inferior):
Remove unused variables.
2018-07-09 02:15:04 +08:00
|
|
|
|
(*pos)++;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
int copies;
|
|
|
|
|
struct value *elt;
|
|
|
|
|
struct value *ncopies;
|
|
|
|
|
|
|
|
|
|
elt = rust_evaluate_subexp (NULL, exp, pos, noside);
|
|
|
|
|
ncopies = rust_evaluate_subexp (NULL, exp, pos, noside);
|
|
|
|
|
copies = value_as_long (ncopies);
|
|
|
|
|
if (copies < 0)
|
|
|
|
|
error (_("Array with negative number of elements"));
|
|
|
|
|
|
|
|
|
|
if (noside == EVAL_NORMAL)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
2016-09-22 23:51:20 +08:00
|
|
|
|
std::vector<struct value *> eltvec (copies);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
for (i = 0; i < copies; ++i)
|
|
|
|
|
eltvec[i] = elt;
|
2016-09-22 23:51:20 +08:00
|
|
|
|
result = value_array (0, copies - 1, eltvec.data ());
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
struct type *arraytype
|
|
|
|
|
= lookup_array_range_type (value_type (elt), 0, copies - 1);
|
|
|
|
|
result = allocate_value (arraytype);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case STRUCTOP_ANONYMOUS:
|
|
|
|
|
{
|
|
|
|
|
/* Anonymous field access, i.e. foo.1. */
|
|
|
|
|
struct value *lhs;
|
|
|
|
|
int pc, field_number, nfields;
|
Simple unused variable removals
This patch holds all the straightforward unused variable deletions.
gdb/ChangeLog
2018-07-22 Tom Tromey <tom@tromey.com>
* guile/scm-value.c (gdbscm_value_call): Remove unused variables.
* guile/scm-math.c (vlscm_unop_gdbthrow, vlscm_binop_gdbthrow)
(vlscm_convert_typed_value_from_scheme): Remove unused variable.
* buildsym-legacy.c (get_macro_table): Remove unused variable.
* stack.c (frame_apply_level_command): Remove unused variable.
* tic6x-tdep.c (tic6x_push_dummy_call): Remove unused variable.
* sparc64-tdep.c (adi_examine_command): Remove unused variable.
* rs6000-lynx178-tdep.c (rs6000_lynx178_push_dummy_call): Remove
unused variable.
* nios2-tdep.c (nios2_push_dummy_call): Remove unused variable.
* mep-tdep.c (mep_push_dummy_call): Remove unused variable.
* ada-lang.c (ada_lookup_symbol_list_worker): Remove unused
variable.
* amd64-tdep.c (amd64_supply_xsave): Remove unused variable.
* arm-tdep.c (arm_record_data_proc_misc_ld_str): Remove unused
variable.
* breakpoint.c (check_no_tracepoint_commands, update_watchpoint):
Remove unused variable.
* cli/cli-script.c (recurse_read_control_structure): Remove unused
variable.
* common/tdesc.c (print_xml_feature::visit): Remove unused
variable.
* compile/compile-object-load.c (store_regs): Remove unused
variables.
* complaints.c (clear_complaints): Remove unused variable.
* corelow.c (core_target_open): Remove unused variable.
* fbsd-tdep.c (fbsd_core_info_proc_status): Remove unused
variable.
* guile/scm-frame.c (gdbscm_frame_read_var): Remove unused
variable.
* guile/scm-symtab.c (stscm_print_sal_smob): Remove unused
variable.
* guile/scm-type.c (gdbscm_field_baseclass_p): Remove unused
variable.
* guile/scm-utils.c (gdbscm_parse_function_args): Remove unused
variable.
* hppa-tdep.c (hppa_stub_frame_unwind_cache): Remove unused
variable.
* ia64-tdep.c (examine_prologue): Remove unused variable.
* infcall.c (run_inferior_call): Remove unused variable.
* inferior.c (exit_inferior): Remove unused variable.
* infrun.c (infrun_thread_ptid_changed): Remove unused variable.
* linespec.c (decode_line_2): Remove unused variable.
* linux-nat.c (super_close): Remove.
* linux-tdep.c (linux_info_proc): Remove unused variable.
* mi/mi-main.c (mi_execute_command): Remove unused variable.
* microblaze-linux-tdep.c (microblaze_linux_sigtramp_cache):
Remove unused variable.
* parse.c (find_minsym_type_and_address): Remove unused variable.
* printcmd.c (info_symbol_command, printf_floating): Remove unused
variable.
* python/py-breakpoint.c (bppy_set_commands): Remove unused
variable.
* python/py-unwind.c (unwind_infopy_dealloc): Remove unused
variables.
* record-btrace.c (record_btrace_target::store_registers): Remove
unused variable.
(cmd_show_record_btrace_cpu): Remove unused variable.
* riscv-tdep.c (riscv_register_reggroup_p)
(riscv_push_dummy_call, riscv_return_value): Remove unused
variable.
* rust-exp.y (literal): Remove unused variable.
* rust-lang.c (rust_evaluate_subexp) <OP_RUST_ARARAY>: Remove
unused variable.
<STRUCTOP_ANONYMOUS>: Likewise.
* s390-linux-tdep.c (s390_linux_init_abi_31)
(s390_linux_init_abi_64): Remove unused variable.
* ser-ming2.c (ser_windows_read_prim, pipe_select_thread)
(file_select_thread, net_windows_open, _initialize_ser_windows):
Remove unused variables.
* symtab.c (find_pc_sect_line): Remove unused variable.
* target-memory.c (compute_garbled_blocks): Remove unused
variable.
(target_write_memory_blocks): Remove unused variable.
* target.c (target_stack::unpush): Remove unused variables.
* tracepoint.c (start_tracing, all_tracepoint_actions)
(merge_uploaded_trace_state_variables)
(print_one_static_tracepoint_marker): Remove unused variable.
* unittests/basic_string_view/element_access/char/1.cc (test01):
Remove unused variable.
* windows-nat.c (windows_continue, windows_add_all_dlls)
(do_initial_windows_stuff, windows_nat_target::create_inferior):
Remove unused variables.
2018-07-09 02:15:04 +08:00
|
|
|
|
struct type *type;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
pc = (*pos)++;
|
|
|
|
|
field_number = longest_to_int (exp->elts[pc + 1].longconst);
|
|
|
|
|
(*pos) += 2;
|
2020-08-31 22:44:33 +08:00
|
|
|
|
lhs = evaluate_subexp (nullptr, exp, pos, noside);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2020-08-31 22:44:33 +08:00
|
|
|
|
type = value_type (lhs);
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
|
2020-05-15 01:46:38 +08:00
|
|
|
|
if (type->code () == TYPE_CODE_STRUCT)
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
{
|
|
|
|
|
struct type *outer_type = NULL;
|
|
|
|
|
|
|
|
|
|
if (rust_enum_p (type))
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
2020-04-25 03:40:31 +08:00
|
|
|
|
gdb::array_view<const gdb_byte> view (value_contents (lhs),
|
|
|
|
|
TYPE_LENGTH (type));
|
|
|
|
|
type = resolve_dynamic_type (type, view, value_address (lhs));
|
|
|
|
|
|
2018-09-12 05:28:04 +08:00
|
|
|
|
if (rust_empty_enum_p (type))
|
|
|
|
|
error (_("Cannot access field %d of empty enum %s"),
|
2020-05-17 00:16:06 +08:00
|
|
|
|
field_number, type->name ());
|
2018-09-12 05:28:04 +08:00
|
|
|
|
|
2020-04-25 03:40:31 +08:00
|
|
|
|
int fieldno = rust_enum_variant (type);
|
|
|
|
|
lhs = value_primitive_field (lhs, 0, fieldno, type);
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
outer_type = type;
|
|
|
|
|
type = value_type (lhs);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Tuples and tuple structs */
|
2020-05-23 04:55:15 +08:00
|
|
|
|
nfields = type->num_fields ();
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
if (field_number >= nfields || field_number < 0)
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
{
|
|
|
|
|
if (outer_type != NULL)
|
|
|
|
|
error(_("Cannot access field %d of variant %s::%s, "
|
|
|
|
|
"there are only %d fields"),
|
2020-05-17 00:16:06 +08:00
|
|
|
|
field_number, outer_type->name (),
|
|
|
|
|
rust_last_path_segment (type->name ()),
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
nfields);
|
|
|
|
|
else
|
|
|
|
|
error(_("Cannot access field %d of %s, "
|
|
|
|
|
"there are only %d fields"),
|
2020-05-17 00:16:06 +08:00
|
|
|
|
field_number, type->name (), nfields);
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
}
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
/* Tuples are tuple structs too. */
|
|
|
|
|
if (!rust_tuple_struct_type_p (type))
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
{
|
|
|
|
|
if (outer_type != NULL)
|
|
|
|
|
error(_("Variant %s::%s is not a tuple variant"),
|
2020-05-17 00:16:06 +08:00
|
|
|
|
outer_type->name (),
|
|
|
|
|
rust_last_path_segment (type->name ()));
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
else
|
|
|
|
|
error(_("Attempting to access anonymous field %d "
|
|
|
|
|
"of %s, which is not a tuple, tuple struct, or "
|
|
|
|
|
"tuple-like variant"),
|
2020-05-17 00:16:06 +08:00
|
|
|
|
field_number, type->name ());
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
}
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
result = value_primitive_field (lhs, 0, field_number, type);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
error(_("Anonymous field access is only allowed on tuples, \
|
|
|
|
|
tuple structs, and tuple-like enum variants"));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case STRUCTOP_STRUCT:
|
|
|
|
|
{
|
2017-05-12 12:22:36 +08:00
|
|
|
|
struct value *lhs;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
struct type *type;
|
|
|
|
|
int tem, pc;
|
|
|
|
|
|
|
|
|
|
pc = (*pos)++;
|
|
|
|
|
tem = longest_to_int (exp->elts[pc + 1].longconst);
|
|
|
|
|
(*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
|
2020-08-31 22:44:33 +08:00
|
|
|
|
lhs = evaluate_subexp (nullptr, exp, pos, noside);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
2017-05-12 12:22:36 +08:00
|
|
|
|
const char *field_name = &exp->elts[pc + 2].string;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
type = value_type (lhs);
|
2020-05-15 01:46:38 +08:00
|
|
|
|
if (type->code () == TYPE_CODE_STRUCT && rust_enum_p (type))
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
2020-04-25 03:40:31 +08:00
|
|
|
|
gdb::array_view<const gdb_byte> view (value_contents (lhs),
|
|
|
|
|
TYPE_LENGTH (type));
|
|
|
|
|
type = resolve_dynamic_type (type, view, value_address (lhs));
|
|
|
|
|
|
2018-09-12 05:28:04 +08:00
|
|
|
|
if (rust_empty_enum_p (type))
|
|
|
|
|
error (_("Cannot access field %s of empty enum %s"),
|
2020-05-17 00:16:06 +08:00
|
|
|
|
field_name, type->name ());
|
2018-09-12 05:28:04 +08:00
|
|
|
|
|
2020-04-25 03:40:31 +08:00
|
|
|
|
int fieldno = rust_enum_variant (type);
|
|
|
|
|
lhs = value_primitive_field (lhs, 0, fieldno, type);
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
|
|
|
|
|
struct type *outer_type = type;
|
|
|
|
|
type = value_type (lhs);
|
|
|
|
|
if (rust_tuple_type_p (type) || rust_tuple_struct_type_p (type))
|
2018-09-14 00:56:34 +08:00
|
|
|
|
error (_("Attempting to access named field %s of tuple "
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
"variant %s::%s, which has only anonymous fields"),
|
2020-05-17 00:16:06 +08:00
|
|
|
|
field_name, outer_type->name (),
|
|
|
|
|
rust_last_path_segment (type->name ()));
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
|
2019-04-04 06:02:42 +08:00
|
|
|
|
try
|
2016-04-27 09:38:08 +08:00
|
|
|
|
{
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
result = value_struct_elt (&lhs, NULL, field_name,
|
|
|
|
|
NULL, "structure");
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
2019-04-04 05:59:07 +08:00
|
|
|
|
catch (const gdb_exception_error &except)
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
{
|
|
|
|
|
error (_("Could not find field %s of struct variant %s::%s"),
|
2020-05-17 00:16:06 +08:00
|
|
|
|
field_name, outer_type->name (),
|
|
|
|
|
rust_last_path_segment (type->name ()));
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
}
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
Convert Rust to use discriminated unions
A Rust enum is, essentially, a discriminated union. Currently the
Rust language support handles Rust enums locally, in rust-lang.c.
However, because I am changing the Rust compiler to use
DW_TAG_variant* to represent enums, it seemed better to have a single
internal representation for Rust enums in gdb.
This patch implements this idea by moving the current Rust enum
handling code to dwarf2read. This allows the simplification of some
parts of rust-lang.c as well.
2018-02-26 Tom Tromey <tom@tromey.com>
* rust-lang.h (rust_last_path_segment): Declare.
* rust-lang.c (rust_last_path_segment): Now public. Change
contract.
(struct disr_info): Remove.
(RUST_ENUM_PREFIX, RUST_ENCODED_ENUM_REAL)
(RUST_ENCODED_ENUM_HIDDEN, rust_union_is_untagged)
(rust_get_disr_info, rust_tuple_variant_type_p): Remove.
(rust_enum_p, rust_enum_variant): New function.
(rust_underscore_fields): Remove "offset" parameter.
(rust_print_enum): New function.
(rust_val_print) <TYPE_CODE_UNION>: Remove enum code.
<TYPE_CODE_STRUCT>: Call rust_print_enum when appropriate.
(rust_print_struct_def): Add "for_rust_enum" parameter. Handle
enums.
(rust_internal_print_type): New function, from rust_print_type.
Remove enum code.
(rust_print_type): Call rust_internal_print_type.
(rust_evaluate_subexp) <STRUCTOP_ANONYMOUS, STRUCTOP_STRUCT>:
Update enum handling.
* dwarf2read.c (struct dwarf2_cu) <rust_unions>: New field.
(rust_fully_qualify, alloc_discriminant_info, quirk_rust_enum)
(rust_union_quirks): New functions.
(process_full_comp_unit, process_full_type_unit): Call
rust_union_quirks.
(process_structure_scope): Update rust_unions if necessary.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.rust/simple.exp: Accept more possible results in enum test.
2018-02-10 04:31:51 +08:00
|
|
|
|
result = value_struct_elt (&lhs, NULL, field_name, NULL, "structure");
|
|
|
|
|
if (noside == EVAL_AVOID_SIDE_EFFECTS)
|
|
|
|
|
result = value_zero (value_type (result), VALUE_LVAL (result));
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2016-04-28 00:28:56 +08:00
|
|
|
|
case OP_RANGE:
|
2016-04-27 09:38:08 +08:00
|
|
|
|
result = rust_range (exp, pos, noside);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case UNOP_ADDR:
|
|
|
|
|
/* We might have &array[range], in which case we need to make a
|
|
|
|
|
slice. */
|
|
|
|
|
if (exp->elts[*pos + 1].opcode == BINOP_SUBSCRIPT)
|
|
|
|
|
{
|
|
|
|
|
++*pos;
|
|
|
|
|
result = rust_subscript (exp, pos, noside, 1);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* Fall through. */
|
|
|
|
|
default:
|
|
|
|
|
result = evaluate_subexp_standard (expect_type, exp, pos, noside);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* operator_length implementation for Rust. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
rust_operator_length (const struct expression *exp, int pc, int *oplenp,
|
|
|
|
|
int *argsp)
|
|
|
|
|
{
|
|
|
|
|
int oplen = 1;
|
|
|
|
|
int args = 0;
|
|
|
|
|
|
|
|
|
|
switch (exp->elts[pc - 1].opcode)
|
|
|
|
|
{
|
|
|
|
|
case OP_AGGREGATE:
|
|
|
|
|
/* We handle aggregate as a type and argument count. The first
|
|
|
|
|
argument might be OP_OTHERS. After that the arguments
|
|
|
|
|
alternate: first an OP_NAME, then an expression. */
|
|
|
|
|
oplen = 4;
|
|
|
|
|
args = longest_to_int (exp->elts[pc - 2].longconst);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OP_OTHERS:
|
|
|
|
|
oplen = 1;
|
|
|
|
|
args = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case STRUCTOP_ANONYMOUS:
|
|
|
|
|
oplen = 3;
|
|
|
|
|
args = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OP_RUST_ARRAY:
|
|
|
|
|
oplen = 1;
|
|
|
|
|
args = 2;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
operator_length_standard (exp, pc, oplenp, argsp);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*oplenp = oplen;
|
|
|
|
|
*argsp = args;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* op_name implementation for Rust. */
|
|
|
|
|
|
-Wwrite-strings: The Rest
This is the remainder boring constification that all looks more of less
borderline obvious IMO.
gdb/ChangeLog:
2017-04-05 Pedro Alves <palves@redhat.com>
* ada-exp.y (yyerror): Constify.
* ada-lang.c (bound_name, get_selections)
(ada_variant_discrim_type)
(ada_variant_discrim_name, ada_value_struct_elt)
(ada_lookup_struct_elt_type, is_unchecked_variant)
(ada_which_variant_applies, standard_exc, ada_get_next_arg)
(catch_ada_exception_command_split)
(catch_ada_assert_command_split, catch_assert_command)
(ada_op_name): Constify.
* ada-lang.h (ada_yyerror, get_selections)
(ada_variant_discrim_name, ada_value_struct_elt): Constify.
* arc-tdep.c (arc_print_frame_cache): Constify.
* arm-tdep.c (arm_skip_stub): Constify.
* ax-gdb.c (gen_binop, gen_struct_ref_recursive, gen_struct_ref)
(gen_aggregate_elt_ref): Constify.
* bcache.c (print_bcache_statistics): Constify.
* bcache.h (print_bcache_statistics): Constify.
* break-catch-throw.c (catch_exception_command_1):
* breakpoint.c (struct ep_type_description::description):
Constify.
(add_solib_catchpoint): Constify.
(catch_fork_command_1): Add cast.
(add_catch_command): Constify.
* breakpoint.h (add_catch_command, add_solib_catchpoint):
Constify.
* bsd-uthread.c (bsd_uthread_state): Constify.
* buildsym.c (patch_subfile_names): Constify.
* buildsym.h (next_symbol_text_func, patch_subfile_names):
Constify.
* c-exp.y (yyerror): Constify.
(token::oper): Constify.
* c-lang.h (c_yyerror, cp_print_class_member): Constify.
* c-varobj.c (cplus_describe_child): Constify.
* charset.c (find_charset_names): Add cast.
(find_charset_names): Constify array and add const_cast.
* cli/cli-cmds.c (complete_command, cd_command): Constify.
(edit_command): Constify.
* cli/cli-decode.c (lookup_cmd): Constify.
* cli/cli-dump.c (dump_memory_command, dump_value_command):
Constify.
(struct dump_context): Constify.
(add_dump_command, restore_command): Constify.
* cli/cli-script.c (get_command_line): Constify.
* cli/cli-script.h (get_command_line): Constify.
* cli/cli-utils.c (check_for_argument): Constify.
* cli/cli-utils.h (check_for_argument): Constify.
* coff-pe-read.c (struct read_pe_section_data): Constify.
* command.h (lookup_cmd): Constify.
* common/print-utils.c (decimal2str): Constify.
* completer.c (gdb_print_filename): Constify.
* corefile.c (set_gnutarget): Constify.
* cp-name-parser.y (yyerror): Constify.
* cp-valprint.c (cp_print_class_member): Constify.
* cris-tdep.c (cris_register_name, crisv32_register_name):
Constify.
* d-exp.y (yyerror): Constify.
(struct token::oper): Constify.
* d-lang.h (d_yyerror): Constify.
* dbxread.c (struct header_file_location::name): Constify.
(add_old_header_file, add_new_header_file, last_function_name)
(dbx_next_symbol_text, add_bincl_to_list)
(find_corresponding_bincl_psymtab, set_namestring)
(find_stab_function_addr, read_dbx_symtab, start_psymtab)
(dbx_end_psymtab, read_ofile_symtab, process_one_symbol):
* defs.h (command_line_input, print_address_symbolic)
(deprecated_readline_begin_hook): Constify.
* dwarf2read.c (anonymous_struct_prefix, dwarf_bool_name):
Constify.
* event-top.c (handle_line_of_input): Constify and add cast.
* exceptions.c (catch_errors): Constify.
* exceptions.h (catch_errors): Constify.
* expprint.c (print_subexp_standard, op_string, op_name)
(op_name_standard, dump_raw_expression, dump_raw_expression):
* expression.h (op_name, op_string, dump_raw_expression):
Constify.
* f-exp.y (yyerror): Constify.
(struct token::oper): Constify.
(struct f77_boolean_val::name): Constify.
* f-lang.c (f_word_break_characters): Constify.
* f-lang.h (f_yyerror): Constify.
* fork-child.c (fork_inferior): Add cast.
* frv-tdep.c (struct gdbarch_tdep::register_names): Constify.
(new_variant): Constify.
* gdbarch.sh (pstring_ptr, pstring_list): Constify.
* gdbarch.c: Regenerate.
* gdbcore.h (set_gnutarget): Constify.
* go-exp.y (yyerror): Constify.
(token::oper): Constify.
* go-lang.h (go_yyerror): Constify.
* go32-nat.c (go32_sysinfo): Constify.
* guile/scm-breakpoint.c (gdbscm_breakpoint_expression): Constify.
* guile/scm-cmd.c (cmdscm_function): Constify.
* guile/scm-param.c (pascm_param_value): Constify.
* h8300-tdep.c (h8300_register_name, h8300s_register_name)
(h8300sx_register_name): Constify.
* hppa-tdep.c (hppa32_register_name, hppa64_register_name):
Constify.
* ia64-tdep.c (ia64_register_names): Constify.
* infcmd.c (construct_inferior_arguments): Constify.
(path_command, attach_post_wait): Constify.
* language.c (show_range_command, show_case_command)
(unk_lang_error): Constify.
* language.h (language_defn::la_error)
(language_defn::la_name_of_this): Constify.
* linespec.c (decode_line_2): Constify.
* linux-thread-db.c (thread_db_err_str): Constify.
* lm32-tdep.c (lm32_register_name): Constify.
* m2-exp.y (yyerror): Constify.
* m2-lang.h (m2_yyerror): Constify.
* m32r-tdep.c (m32r_register_names): Constify and make static.
* m68hc11-tdep.c (m68hc11_register_names): Constify.
* m88k-tdep.c (m88k_register_name): Constify.
* macroexp.c (appendmem): Constify.
* mdebugread.c (fdr_name, add_data_symbol, parse_type)
(upgrade_type, parse_external, parse_partial_symbols)
(mdebug_next_symbol_text, cross_ref, mylookup_symbol, new_psymtab)
(new_symbol): Constify.
* memattr.c (mem_info_command): Constify.
* mep-tdep.c (register_name_from_keyword): Constify.
* mi/mi-cmd-env.c (mi_cmd_env_path, _initialize_mi_cmd_env):
Constify.
* mi/mi-cmd-stack.c (list_args_or_locals): Constify.
* mi/mi-cmd-var.c (mi_cmd_var_show_attributes): Constify.
* mi/mi-main.c (captured_mi_execute_command): Constify and add
cast.
(mi_execute_async_cli_command): Constify.
* mips-tdep.c (mips_register_name): Constify.
* mn10300-tdep.c (register_name, mn10300_generic_register_name)
(am33_register_name, am33_2_register_name)
* moxie-tdep.c (moxie_register_names): Constify.
* nat/linux-osdata.c (osdata_type): Constify fields.
* nto-tdep.c (nto_parse_redirection): Constify.
* objc-lang.c (lookup_struct_typedef, lookup_objc_class)
(lookup_child_selector): Constify.
(objc_methcall::name): Constify.
* objc-lang.h (lookup_objc_class, lookup_child_selector)
(lookup_struct_typedef): Constify.
* objfiles.c (pc_in_section): Constify.
* objfiles.h (pc_in_section): Constify.
* p-exp.y (struct token::oper): Constify.
(yyerror): Constify.
* p-lang.h (pascal_yyerror): Constify.
* parser-defs.h (op_name_standard): Constify.
(op_print::string): Constify.
(exp_descriptor::op_name): Constify.
* printcmd.c (print_address_symbolic): Constify.
* psymtab.c (print_partial_symbols): Constify.
* python/py-breakpoint.c (stop_func): Constify.
(bppy_get_expression): Constify.
* python/py-cmd.c (cmdpy_completer::name): Constify.
(cmdpy_function): Constify.
* python/py-event.c (evpy_add_attribute)
(gdbpy_initialize_event_generic): Constify.
* python/py-event.h (evpy_add_attribute)
(gdbpy_initialize_event_generic): Constify.
* python/py-evts.c (add_new_registry): Constify.
* python/py-finishbreakpoint.c (outofscope_func): Constify.
* python/py-framefilter.c (get_py_iter_from_func): Constify.
* python/py-inferior.c (get_buffer): Add cast.
* python/py-param.c (parm_constant::name): Constify.
* python/py-unwind.c (fprint_frame_id): Constify.
* python/python.c (gdbpy_parameter_value): Constify.
* remote-fileio.c (remote_fio_func_map): Make 'name' const.
* remote.c (memory_packet_config::name): Constify.
(show_packet_config_cmd, remote_write_bytes)
(remote_buffer_add_string):
* reverse.c (exec_reverse_once): Constify.
* rs6000-tdep.c (variant::name, variant::description): Constify.
* rust-exp.y (rustyyerror): Constify.
* rust-lang.c (rust_op_name): Constify.
* rust-lang.h (rustyyerror): Constify.
* serial.h (serial_ops::name): Constify.
* sh-tdep.c (sh_sh_register_name, sh_sh3_register_name)
(sh_sh3e_register_name, sh_sh2e_register_name)
(sh_sh2a_register_name, sh_sh2a_nofpu_register_name)
(sh_sh_dsp_register_name, sh_sh3_dsp_register_name)
(sh_sh4_register_name, sh_sh4_nofpu_register_name)
(sh_sh4al_dsp_register_name): Constify.
* sh64-tdep.c (sh64_register_name): Constify.
* solib-darwin.c (lookup_symbol_from_bfd): Constify.
* spu-tdep.c (spu_register_name, info_spu_dma_cmdlist): Constify.
* stabsread.c (patch_block_stabs, read_type_number)
(ref_map::stabs, ref_add, process_reference)
(symbol_reference_defined, define_symbol, define_symbol)
(error_type, read_type, read_member_functions, read_cpp_abbrev)
(read_one_struct_field, read_struct_fields, read_baseclasses)
(read_tilde_fields, read_struct_type, read_array_type)
(read_enum_type, read_sun_builtin_type, read_sun_floating_type)
(read_huge_number, read_range_type, read_args, common_block_start)
(find_name_end): Constify.
* stabsread.h (common_block_start, define_symbol)
(process_one_symbol, symbol_reference_defined, ref_add):
* symfile.c (get_section_index, add_symbol_file_command):
* symfile.h (get_section_index): Constify.
* target-descriptions.c (tdesc_type::name): Constify.
(tdesc_free_type): Add cast.
* target.c (find_default_run_target):
(add_deprecated_target_alias, find_default_run_target)
(target_announce_detach): Constify.
(do_option): Constify.
* target.h (add_deprecated_target_alias): Constify.
* thread.c (print_thread_info_1): Constify.
* top.c (deprecated_readline_begin_hook, command_line_input):
Constify.
(init_main): Add casts.
* top.h (handle_line_of_input): Constify.
* tracefile-tfile.c (tfile_write_uploaded_tsv): Constify.
* tracepoint.c (tvariables_info_1, trace_status_mi): Constify.
(tfind_command): Rename to ...
(tfind_command_1): ... this and constify.
(tfind_command): New function.
(tfind_end_command, tfind_start_command): Adjust.
(encode_source_string): Constify.
* tracepoint.h (encode_source_string): Constify.
* tui/tui-data.c (tui_partial_win_by_name): Constify.
* tui/tui-data.h (tui_partial_win_by_name): Constify.
* tui/tui-source.c (tui_set_source_content_nil): Constify.
* tui/tui-source.h (tui_set_source_content_nil): Constify.
* tui/tui-win.c (parse_scrolling_args): Constify.
* tui/tui-windata.c (tui_erase_data_content): Constify.
* tui/tui-windata.h (tui_erase_data_content): Constify.
* tui/tui-winsource.c (tui_erase_source_content): Constify.
* tui/tui.c (tui_enable): Add cast.
* utils.c (defaulted_query): Constify.
(init_page_info): Add cast.
(puts_debug, subset_compare): Constify.
* utils.h (subset_compare): Constify.
* varobj.c (varobj_format_string): Constify.
* varobj.h (varobj_format_string): Constify.
* vax-tdep.c (vax_register_name): Constify.
* windows-nat.c (windows_detach): Constify.
* xcoffread.c (process_linenos, xcoff_next_symbol_text): Constify.
* xml-support.c (gdb_xml_end_element): Constify.
* xml-tdesc.c (tdesc_start_reg): Constify.
* xstormy16-tdep.c (xstormy16_register_name): Constify.
* xtensa-tdep.c (xtensa_find_register_by_name): Constify.
* xtensa-tdep.h (xtensa_register_t::name): Constify.
gdb/gdbserver/ChangeLog:
2017-04-05 Pedro Alves <palves@redhat.com>
* gdbreplay.c (sync_error): Constify.
* linux-x86-low.c (push_opcode): Constify.
2017-04-06 02:21:37 +08:00
|
|
|
|
static const char *
|
2016-04-27 09:38:08 +08:00
|
|
|
|
rust_op_name (enum exp_opcode opcode)
|
|
|
|
|
{
|
|
|
|
|
switch (opcode)
|
|
|
|
|
{
|
|
|
|
|
case OP_AGGREGATE:
|
|
|
|
|
return "OP_AGGREGATE";
|
|
|
|
|
case OP_OTHERS:
|
|
|
|
|
return "OP_OTHERS";
|
|
|
|
|
default:
|
|
|
|
|
return op_name_standard (opcode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* dump_subexp_body implementation for Rust. */
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
rust_dump_subexp_body (struct expression *exp, struct ui_file *stream,
|
|
|
|
|
int elt)
|
|
|
|
|
{
|
|
|
|
|
switch (exp->elts[elt].opcode)
|
|
|
|
|
{
|
|
|
|
|
case OP_AGGREGATE:
|
|
|
|
|
{
|
|
|
|
|
int length = longest_to_int (exp->elts[elt + 2].longconst);
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
fprintf_filtered (stream, "Type @");
|
|
|
|
|
gdb_print_host_address (exp->elts[elt + 1].type, stream);
|
|
|
|
|
fprintf_filtered (stream, " (");
|
|
|
|
|
type_print (exp->elts[elt + 1].type, NULL, stream, 0);
|
|
|
|
|
fprintf_filtered (stream, "), length %d", length);
|
|
|
|
|
|
|
|
|
|
elt += 4;
|
|
|
|
|
for (i = 0; i < length; ++i)
|
|
|
|
|
elt = dump_subexp (exp, stream, elt);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OP_STRING:
|
|
|
|
|
case OP_NAME:
|
|
|
|
|
{
|
|
|
|
|
LONGEST len = exp->elts[elt + 1].longconst;
|
|
|
|
|
|
|
|
|
|
fprintf_filtered (stream, "%s: %s",
|
|
|
|
|
(exp->elts[elt].opcode == OP_STRING
|
|
|
|
|
? "string" : "name"),
|
|
|
|
|
&exp->elts[elt + 2].string);
|
|
|
|
|
elt += 4 + BYTES_TO_EXP_ELEM (len + 1);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OP_OTHERS:
|
|
|
|
|
elt = dump_subexp (exp, stream, elt + 1);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case STRUCTOP_ANONYMOUS:
|
|
|
|
|
{
|
|
|
|
|
int field_number;
|
|
|
|
|
|
2017-05-12 09:50:47 +08:00
|
|
|
|
field_number = longest_to_int (exp->elts[elt + 1].longconst);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
fprintf_filtered (stream, "Field number: %d", field_number);
|
2017-05-12 09:50:47 +08:00
|
|
|
|
elt = dump_subexp (exp, stream, elt + 3);
|
2016-04-27 09:38:08 +08:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OP_RUST_ARRAY:
|
2017-05-12 09:50:47 +08:00
|
|
|
|
++elt;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
elt = dump_subexp_body_standard (exp, stream, elt);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return elt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* print_subexp implementation for Rust. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
rust_print_subexp (struct expression *exp, int *pos, struct ui_file *stream,
|
|
|
|
|
enum precedence prec)
|
|
|
|
|
{
|
|
|
|
|
switch (exp->elts[*pos].opcode)
|
|
|
|
|
{
|
|
|
|
|
case OP_AGGREGATE:
|
|
|
|
|
{
|
|
|
|
|
int length = longest_to_int (exp->elts[*pos + 2].longconst);
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
type_print (exp->elts[*pos + 1].type, "", stream, 0);
|
|
|
|
|
fputs_filtered (" { ", stream);
|
|
|
|
|
|
|
|
|
|
*pos += 4;
|
|
|
|
|
for (i = 0; i < length; ++i)
|
|
|
|
|
{
|
|
|
|
|
rust_print_subexp (exp, pos, stream, prec);
|
|
|
|
|
fputs_filtered (", ", stream);
|
|
|
|
|
}
|
|
|
|
|
fputs_filtered (" }", stream);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OP_NAME:
|
|
|
|
|
{
|
|
|
|
|
LONGEST len = exp->elts[*pos + 1].longconst;
|
|
|
|
|
|
|
|
|
|
fputs_filtered (&exp->elts[*pos + 2].string, stream);
|
|
|
|
|
*pos += 4 + BYTES_TO_EXP_ELEM (len + 1);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OP_OTHERS:
|
|
|
|
|
{
|
|
|
|
|
fputs_filtered ("<<others>> (", stream);
|
|
|
|
|
++*pos;
|
|
|
|
|
rust_print_subexp (exp, pos, stream, prec);
|
|
|
|
|
fputs_filtered (")", stream);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case STRUCTOP_ANONYMOUS:
|
|
|
|
|
{
|
|
|
|
|
int tem = longest_to_int (exp->elts[*pos + 1].longconst);
|
|
|
|
|
|
|
|
|
|
(*pos) += 3;
|
|
|
|
|
print_subexp (exp, pos, stream, PREC_SUFFIX);
|
|
|
|
|
fprintf_filtered (stream, ".%d", tem);
|
|
|
|
|
}
|
2017-05-12 09:44:43 +08:00
|
|
|
|
break;
|
2016-04-27 09:38:08 +08:00
|
|
|
|
|
|
|
|
|
case OP_RUST_ARRAY:
|
|
|
|
|
++*pos;
|
|
|
|
|
fprintf_filtered (stream, "[");
|
|
|
|
|
rust_print_subexp (exp, pos, stream, prec);
|
|
|
|
|
fprintf_filtered (stream, "; ");
|
|
|
|
|
rust_print_subexp (exp, pos, stream, prec);
|
|
|
|
|
fprintf_filtered (stream, "]");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
print_subexp_standard (exp, pos, stream, prec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* operator_check implementation for Rust. */
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
rust_operator_check (struct expression *exp, int pos,
|
|
|
|
|
int (*objfile_func) (struct objfile *objfile,
|
|
|
|
|
void *data),
|
|
|
|
|
void *data)
|
|
|
|
|
{
|
|
|
|
|
switch (exp->elts[pos].opcode)
|
|
|
|
|
{
|
|
|
|
|
case OP_AGGREGATE:
|
|
|
|
|
{
|
|
|
|
|
struct type *type = exp->elts[pos + 1].type;
|
|
|
|
|
struct objfile *objfile = TYPE_OBJFILE (type);
|
|
|
|
|
|
|
|
|
|
if (objfile != NULL && (*objfile_func) (objfile, data))
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OP_OTHERS:
|
|
|
|
|
case OP_NAME:
|
|
|
|
|
case OP_RUST_ARRAY:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return operator_check_standard (exp, pos, objfile_func, data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const struct exp_descriptor exp_descriptor_rust =
|
|
|
|
|
{
|
|
|
|
|
rust_print_subexp,
|
|
|
|
|
rust_operator_length,
|
|
|
|
|
rust_operator_check,
|
|
|
|
|
rust_op_name,
|
|
|
|
|
rust_dump_subexp_body,
|
|
|
|
|
rust_evaluate_subexp
|
|
|
|
|
};
|
|
|
|
|
|
gdb: Represent all languages as sub-classes of language_defn
This commit converts all languages to sub-classes of a language_defn
base class.
The motivation for this change is to make it easier to add new methods
onto languages without having to update all of the individual language
structures. In the future it might be possible to move more things,
like expression parsing, into the language class(es) for better
encapsulation, however I have no plans to tackle this in the short
term.
This commit sets up a strategy for transitioning from the current
language system, where each language is an instance of the
language_defn structure, to the class hierarchy system.
The plan is to rename the existing language_defn into language_data,
and make this a base class for the new language_defn class, something
like this:
struct language_data
{
... old language_defn fields here ...
};
struct language_defn : public language_data
{
language_defn (const language_data d)
: language_data (d)
{ .... }
};
Then each existing language, for example ada_language_defn can be
converted into an instance of language_data, and passed into the
constructor of a new language class, something like this:
language_data ada_language_data =
{
... old ada_language_defn values here ...
};
struct ada_language : public language_defn
{
ada_language (ada_language_data)
{ .... }
};
What this means is that immediately after the conversion nothing much
changes. Every language is now its own class, but all the old
language fields still exist and can be accessed in the same way.
In later commits I will convert function pointers from the old
language_defn structure into real class methods on language_defn, with
overrides on sub-classes where needed.
At this point I imagine that those fields of the old language_defn
structure that contained only data will probably remain as data fields
within the new language_data base structure, it is only the methods
that I plan to change initially.
I tweaked how we manage the list of languages a bit, each language is
now registered as it is created, and this resulted in a small number
of changes in language.c.
Most of the changes in the *-lang.c files are identical.
There should be no user visible changes after this commit.
gdb/ChangeLog:
* gdb/ada-lang.c (ada_language_defn): Convert to...
(ada_language_data): ...this.
(class ada_language): New class.
(ada_language_defn): New static global.
* gdb/c-lang.c (c_language_defn): Convert to...
(c_language_data): ...this.
(class c_language): New class.
(c_language_defn): New static global.
(cplus_language_defn): Convert to...
(cplus_language_data): ...this.
(class cplus_language): New class.
(cplus_language_defn): New static global.
(asm_language_defn): Convert to...
(asm_language_data): ...this.
(class asm_language): New class.
(asm_language_defn): New static global.
(minimal_language_defn): Convert to...
(minimal_language_data): ...this.
(class minimal_language): New class.
(minimal_language_defn): New static global.
* gdb/d-lang.c (d_language_defn): Convert to...
(d_language_data): ...this.
(class d_language): New class.
(d_language_defn): New static global.
* gdb/f-lang.c (f_language_defn): Convert to...
(f_language_data): ...this.
(class f_language): New class.
(f_language_defn): New static global.
* gdb/go-lang.c (go_language_defn): Convert to...
(go_language_data): ...this.
(class go_language): New class.
(go_language_defn): New static global.
* gdb/language.c (unknown_language_defn): Remove declaration.
(current_language): Initialize to nullptr, real initialization is
moved to _initialize_language.
(languages): Delete global.
(language_defn::languages): Define.
(set_language_command): Use language_defn::languages.
(set_language): Likewise.
(range_error): Likewise.
(language_enum): Likewise.
(language_def): Likewise.
(add_set_language_command): Use language_def::languages for the
language list, and language_def to lookup language pointers.
(skip_language_trampoline): Use language_defn::languages.
(unknown_language_defn): Convert to...
(unknown_language_data): ...this.
(class unknown_language): New class.
(unknown_language_defn): New static global.
(auto_language_defn): Convert to...
(auto_language_data): ...this.
(class auto_language): New class.
(auto_language_defn): New static global.
(language_gdbarch_post_init): Use language_defn::languages.
(_initialize_language): Initialize current_language.
* gdb/language.h (struct language_defn): Rename to...
(struct language_data): ...this.
(struct language_defn): New.
(auto_language_defn): Delete.
(unknown_language_defn): Delete.
(minimal_language_defn): Delete.
(ada_language_defn): Delete.
(asm_language_defn): Delete.
(c_language_defn): Delete.
(cplus_language_defn): Delete.
(d_language_defn): Delete.
(f_language_defn): Delete.
(go_language_defn): Delete.
(m2_language_defn): Delete.
(objc_language_defn): Delete.
(opencl_language_defn): Delete.
(pascal_language_defn): Delete.
(rust_language_defn): Delete.
* gdb/m2-lang.c (m2_language_defn): Convert to...
(m2_language_data): ...this.
(class m2_language): New class.
(m2_language_defn): New static global.
* gdb/objc-lang.c (objc_language_defn): Convert to...
(objc_language_data): ...this.
(class objc_language): New class.
(objc_language_defn): New static global.
* gdb/opencl-lang.c (opencl_language_defn): Convert to...
(opencl_language_data): ...this.
(class opencl_language): New class.
(opencl_language_defn): New static global.
* gdb/p-lang.c (pascal_language_defn): Convert to...
(pascal_language_data): ...this.
(class pascal_language): New class.
(pascal_language_defn): New static global.
* gdb/rust-exp.y (rust_lex_tests): Use language_def to find
language pointer, update comment format.
* gdb/rust-lang.c (rust_language_defn): Convert to...
(rust_language_data): ...this.
(class rust_language): New class.
(rust_language_defn): New static global.
2020-05-01 19:16:58 +08:00
|
|
|
|
/* Class representing the Rust language. */
|
|
|
|
|
|
|
|
|
|
class rust_language : public language_defn
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
rust_language ()
|
2020-08-05 00:13:40 +08:00
|
|
|
|
: language_defn (language_rust)
|
gdb: Represent all languages as sub-classes of language_defn
This commit converts all languages to sub-classes of a language_defn
base class.
The motivation for this change is to make it easier to add new methods
onto languages without having to update all of the individual language
structures. In the future it might be possible to move more things,
like expression parsing, into the language class(es) for better
encapsulation, however I have no plans to tackle this in the short
term.
This commit sets up a strategy for transitioning from the current
language system, where each language is an instance of the
language_defn structure, to the class hierarchy system.
The plan is to rename the existing language_defn into language_data,
and make this a base class for the new language_defn class, something
like this:
struct language_data
{
... old language_defn fields here ...
};
struct language_defn : public language_data
{
language_defn (const language_data d)
: language_data (d)
{ .... }
};
Then each existing language, for example ada_language_defn can be
converted into an instance of language_data, and passed into the
constructor of a new language class, something like this:
language_data ada_language_data =
{
... old ada_language_defn values here ...
};
struct ada_language : public language_defn
{
ada_language (ada_language_data)
{ .... }
};
What this means is that immediately after the conversion nothing much
changes. Every language is now its own class, but all the old
language fields still exist and can be accessed in the same way.
In later commits I will convert function pointers from the old
language_defn structure into real class methods on language_defn, with
overrides on sub-classes where needed.
At this point I imagine that those fields of the old language_defn
structure that contained only data will probably remain as data fields
within the new language_data base structure, it is only the methods
that I plan to change initially.
I tweaked how we manage the list of languages a bit, each language is
now registered as it is created, and this resulted in a small number
of changes in language.c.
Most of the changes in the *-lang.c files are identical.
There should be no user visible changes after this commit.
gdb/ChangeLog:
* gdb/ada-lang.c (ada_language_defn): Convert to...
(ada_language_data): ...this.
(class ada_language): New class.
(ada_language_defn): New static global.
* gdb/c-lang.c (c_language_defn): Convert to...
(c_language_data): ...this.
(class c_language): New class.
(c_language_defn): New static global.
(cplus_language_defn): Convert to...
(cplus_language_data): ...this.
(class cplus_language): New class.
(cplus_language_defn): New static global.
(asm_language_defn): Convert to...
(asm_language_data): ...this.
(class asm_language): New class.
(asm_language_defn): New static global.
(minimal_language_defn): Convert to...
(minimal_language_data): ...this.
(class minimal_language): New class.
(minimal_language_defn): New static global.
* gdb/d-lang.c (d_language_defn): Convert to...
(d_language_data): ...this.
(class d_language): New class.
(d_language_defn): New static global.
* gdb/f-lang.c (f_language_defn): Convert to...
(f_language_data): ...this.
(class f_language): New class.
(f_language_defn): New static global.
* gdb/go-lang.c (go_language_defn): Convert to...
(go_language_data): ...this.
(class go_language): New class.
(go_language_defn): New static global.
* gdb/language.c (unknown_language_defn): Remove declaration.
(current_language): Initialize to nullptr, real initialization is
moved to _initialize_language.
(languages): Delete global.
(language_defn::languages): Define.
(set_language_command): Use language_defn::languages.
(set_language): Likewise.
(range_error): Likewise.
(language_enum): Likewise.
(language_def): Likewise.
(add_set_language_command): Use language_def::languages for the
language list, and language_def to lookup language pointers.
(skip_language_trampoline): Use language_defn::languages.
(unknown_language_defn): Convert to...
(unknown_language_data): ...this.
(class unknown_language): New class.
(unknown_language_defn): New static global.
(auto_language_defn): Convert to...
(auto_language_data): ...this.
(class auto_language): New class.
(auto_language_defn): New static global.
(language_gdbarch_post_init): Use language_defn::languages.
(_initialize_language): Initialize current_language.
* gdb/language.h (struct language_defn): Rename to...
(struct language_data): ...this.
(struct language_defn): New.
(auto_language_defn): Delete.
(unknown_language_defn): Delete.
(minimal_language_defn): Delete.
(ada_language_defn): Delete.
(asm_language_defn): Delete.
(c_language_defn): Delete.
(cplus_language_defn): Delete.
(d_language_defn): Delete.
(f_language_defn): Delete.
(go_language_defn): Delete.
(m2_language_defn): Delete.
(objc_language_defn): Delete.
(opencl_language_defn): Delete.
(pascal_language_defn): Delete.
(rust_language_defn): Delete.
* gdb/m2-lang.c (m2_language_defn): Convert to...
(m2_language_data): ...this.
(class m2_language): New class.
(m2_language_defn): New static global.
* gdb/objc-lang.c (objc_language_defn): Convert to...
(objc_language_data): ...this.
(class objc_language): New class.
(objc_language_defn): New static global.
* gdb/opencl-lang.c (opencl_language_defn): Convert to...
(opencl_language_data): ...this.
(class opencl_language): New class.
(opencl_language_defn): New static global.
* gdb/p-lang.c (pascal_language_defn): Convert to...
(pascal_language_data): ...this.
(class pascal_language): New class.
(pascal_language_defn): New static global.
* gdb/rust-exp.y (rust_lex_tests): Use language_def to find
language pointer, update comment format.
* gdb/rust-lang.c (rust_language_defn): Convert to...
(rust_language_data): ...this.
(class rust_language): New class.
(rust_language_defn): New static global.
2020-05-01 19:16:58 +08:00
|
|
|
|
{ /* Nothing. */ }
|
gdb: Convert language la_language_arch_info field to a method
This commit changes the language_data::la_language_arch_info function
pointer member variable into a member function of language_defn.
There should be no user visible changes after this commit.
gdb/ChangeLog:
* ada-lang.c (ada_language_arch_info): Delete function, move
implementation to...
(ada_language::language_arch_info): ...here, a new member
function.
(ada_language_data): Delete la_language_arch_info.
* c-lang.c (c_language_data): Likewise.
(c_language::language_arch_info): New member function.
(cplus_language_arch_info): Delete function, move
implementation to...
(cplus_language::language_arch_info): ...here, a new member
function.
(cplus_language_data): Delete la_language_arch_info.
(asm_language_data): Likewise.
(asm_language::language_arch_info): New member function.
(minimal_language_data): Delete la_language_arch_info.
(minimal_language::language_arch_info): New member function.
* d-lang.c (d_language_arch_info): Delete function, move
implementation to...
(d_language::language_arch_info): ...here, a new member
function.
(d_language_data): Delete la_language_arch_info.
* f-lang.c (f_language_arch_info): Delete function, move
implementation to...
(f_language::language_arch_info): ...here, a new member
function.
(f_language_data): Delete la_language_arch_info.
* go-lang.c (go_language_arch_info): Delete function, move
implementation to...
(go_language::language_arch_info): ...here, a new member
function.
(go_language_data): Delete la_language_arch_info.
* language.c (unknown_language_data): Likewise.
(unknown_language::language_arch_info): New member function.
(auto_language_data): Delete la_language_arch_info.
(auto_language::language_arch_info): New member function.
(language_gdbarch_post_init): Update call to
la_language_arch_info.
* language.h (language_data): Delete la_language_arch_info
function pointer.
(language_defn::language_arch_info): New function.
* m2-lang.c (m2_language_arch_info): Delete function, move
implementation to...
(m2_language::language_arch_info): ...here, a new member
function.
(m2_language_data): Delete la_language_arch_info.
* objc-lang.c (objc_language_arch_info): Delete function, move
implementation to...
(objc_language::language_arch_info): ...here, a new member
function.
(objc_language_data): Delete la_language_arch_info.
* opencl-lang.c (opencl_language_arch_info): Delete function, move
implementation to...
(opencl_language::language_arch_info): ...here, a new member
function.
(opencl_language_data): Delete la_language_arch_info.
* p-lang.c (pascal_language_arch_info): Delete function, move
implementation to...
(pascal_language::language_arch_info): ...here, a new member
function.
(pascal_language_data): Delete la_language_arch_info.
* rust-lang.c (rust_language_arch_info): Delete function, move
implementation to...
(rust_language::language_arch_info): ...here, a new member
function.
(rust_language_data): Delete la_language_arch_info.
2020-05-02 04:51:15 +08:00
|
|
|
|
|
gdb: Convert la_name and la_natural_name to methods
Convert the two language_data member variables la_name and
la_natural_name to virtual methods in language_defn struct called name
and natural_name respectively.
The virtual methods in the language_defn base class are pure virtual,
as every language must implement these, and as every language has a
unique name there's no sensible default here.
Given that every language must implement these methods I did wonder
about making this data passed into the base class constructor, but in
the end I went with the virtual method approach. I'm open to changing
this approach if people prefer the constructor approach.
During updating the calls to language_defn::name I found in
add_set_language_command a place where we took la_name and then
capitalised the first letter to create a language name that could be
used in the documentation string. I replaced this with a use of
natural_name instead as this seemed a better choice, in most cases
this will make no difference, as for most languages the natural_name
is just the name with the first character in upper case, but for some
languages, for example 'Open-CL' and 'Objective-C' this is not the
case.
In the case of asm_language the name is 'asm', while the natural_name
was previously 'assembly'. I changed the natural name to 'Assembly',
this makes the documentation string case above cleaner, however, this
will change the MI output for -var-info-expression, where the 'lang'
field will change from 'assembly' to 'Assembly'. It is possible this
could be a breaking change if a front-end is relying on the existing
name.
gdb/ChangeLog:
* ada-lang.c (ada_language_data): Remove la_name and
la_natural_name initializers.
(ada_language::name): New member function.
(ada_language::natural_name): New member function.
* c-lang.c (c_language_data): Remove la_name and
la_natural_name initializers.
(c_language::name): New member function.
(c_language::natural_name): New member function.
(cplus_language_data): Remove la_name and
la_natural_name initializers.
(cplus_language::name): New member function.
(cplus_language::natural_name): New member function.
(asm_language_data): Remove la_name and
la_natural_name initializers.
(asm_language::name): New member function.
(asm_language::natural_name): New member function.
(minimal_language_data): Remove la_name and
la_natural_name initializers.
(minimal_language::name): New member function.
(minimal_language::natural_name): New member function.
* compile/compile.c (compile_to_object): Update call to
lanugage_defn::name.
* d-lang.c (d_language_data): Remove la_name and
la_natural_name initializers.
(d_language::name): New member function.
(d_language::natural_name): New member function.
* expprint.c (print_subexp_standard): Update call to
language_defn::name.
(dump_raw_expression): Likewise
(dump_prefix_expression): Likewise.
* f-lang.c (f_language_data): Remove la_name and
la_natural_name initializers.
(f_language::name): New member function.
(f_language::natural_name): New member function.
* go-lang.c (go_language_data): Remove la_name and
la_natural_name initializers.
(go_language::name): New member function.
(go_language::natural_name): New member function.
* language.c (show_language_command): Update call to
language_defn::name.
(set_language_command): Likewise.
(language_enum): Likewise.
(language_str): Likewise.
(add_set_language_command): Likewise, use
language_defn::natural_name in the doc string.
(unknown_language_data): Remove la_name and
la_natural_name initializers.
(unknown_language::name): New member function.
(unknown_language::natural_name): New member function.
(auto_language_data): Remove la_name and
la_natural_name initializers.
(auto_language::name): New member function.
(auto_language::natural_name): New member function.
(language_lookup_primitive_type_as_symbol): Update call to
language_defn::name.
* language.h (language_data): Remove la_name and la_natural_name
member variables.
(language_defn::name): New member function.
(language_defn::natural_name): New member function.
* m2-lang.c (m2_language_data): Remove la_name and
la_natural_name initializers.
(m2_language::name): New member function.
(m2_language::natural_name): New member function.
* mi/mi-cmd-var.c (mi_cmd_var_info_expression): Update call to
language_defn::natural_name.
* objc-lang.c (objc_language_data): Remove la_name and
la_natural_name initializers.
(objc_language::name): New member function.
(objc_language::natural_name): New member function.
* opencl-lang.c (opencl_language_data): Remove la_name and
la_natural_name initializers.
(opencl_language::name): New member function.
(opencl_language::natural_name): New member function.
* p-lang.c (pascal_language_data): Remove la_name and
la_natural_name initializers.
(pascal_language::name): New member function.
(pascal_language::natural_name): New member function.
* rust-lang.c (rust_language_data): Remove la_name and
la_natural_name initializers.
(rust_language::name): New member function.
(rust_language::natural_name): New member function.
* symtab.c (lookup_language_this): Update call to
language_defn::name.
2020-06-24 03:07:09 +08:00
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
|
|
|
|
const char *name () const override
|
|
|
|
|
{ return "rust"; }
|
|
|
|
|
|
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
|
|
|
|
const char *natural_name () const override
|
|
|
|
|
{ return "Rust"; }
|
|
|
|
|
|
gdb: Convert la_filename_extensions to a method
Convert language_data::la_filename_extensions member variable to a
virtual method language_defn::filename_extensions.
The new method returns a vector of filename extensions, which means
that where previously we needed a NULL marker on the end of the list,
we can now discard this.
All of the old arrays that contained the extensions now become static
data within each languages filename_extensions method.
I've updated the single use of the filename_extensions method to make
use of this method returning a vector. And, just in case anyone
accidentally adds a NULL marked into a languages extensions list, I've
added a new assert in add_filename_language (symtab.c) to catch this.
gdb/ChangeLog:
* ada-lang.c (ada_extensions): Delete, moved into
ada_language::filename_extensions.
(ada_language_data): Remove la_filename_extensions initializer.
(ada_language::filename_extensions): New member function.
* c-lang.c (c_extensions): Delete, moved into
c_language::filename_extensions.
(c_language_data): Remove la_filename_extensions initializer.
(c_language::filename_extensions): New member function.
(cplus_extensions): Delete, moved into
cplus_language::filename_extensions.
(cplus_language_data): Remove la_filename_extensions initializer.
(cplus_language::filename_extensions): New member function.
(asm_extensions): Delete, moved into
asm_language::filename_extensions.
(asm_language_data): Remove la_filename_extensions initializer.
(asm_language::filename_extensions): New member function.
(minimal_language_data): Remove la_filename_extensions
initializer.
* d-lang.c (d_extensions): Delete, moved into
d_language::filename_extensions.
(d_language_data): Remove la_filename_extensions initializer.
(d_language::filename_extensions): New member function.
* f-lang.c (f_extensions): Delete, moved into
f_language::filename_extensions.
(f_language_data): Remove la_filename_extensions initializer.
(f_language::filename_extensions): New member function.
* go-lang.c (go_language_data): Remove la_filename_extensions
initializer.
* language.c (add_set_language_command): Update now that
filename_extensions returns a vector.
(unknown_language_data): Remove la_filename_extensions
initializer.
(auto_language_data): Likewise.
* language.h (language_data): Remove la_filename_extensions field.
(language_defn::filename_extensions): New member function.
* m2-lang.c (m2_language_data): Remove la_filename_extensions
initializer.
* objc-lang.c (objc_extensions): Delete, moved into
objc_language::filename_extensions.
(objc_language_data): Remove la_filename_extensions initializer.
(objc_language::filename_extensions): New member function.
* opencl-lang.c (opencl_language_data): Remove
la_filename_extensions initializer.
* p-lang.c (pascal_extensions): Delete, moved into
pascal_language::filename_extensions.
(pascal_language_data): Remove la_filename_extensions initializer.
(pascal_language::filename_extensions): New member function.
* rust-lang.c (rust_extensions): Delete, moved into
rust_language::filename_extensions.
(rust_language_data): Remove la_filename_extensions initializer.
(rust_language::filename_extensions): New member function.
* symfile.c (add_filename_language): Add new assert.
2020-07-04 01:46:16 +08:00
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
|
|
|
|
const std::vector<const char *> &filename_extensions () const override
|
|
|
|
|
{
|
|
|
|
|
static const std::vector<const char *> extensions = { ".rs" };
|
|
|
|
|
return extensions;
|
|
|
|
|
}
|
|
|
|
|
|
gdb: Convert language la_language_arch_info field to a method
This commit changes the language_data::la_language_arch_info function
pointer member variable into a member function of language_defn.
There should be no user visible changes after this commit.
gdb/ChangeLog:
* ada-lang.c (ada_language_arch_info): Delete function, move
implementation to...
(ada_language::language_arch_info): ...here, a new member
function.
(ada_language_data): Delete la_language_arch_info.
* c-lang.c (c_language_data): Likewise.
(c_language::language_arch_info): New member function.
(cplus_language_arch_info): Delete function, move
implementation to...
(cplus_language::language_arch_info): ...here, a new member
function.
(cplus_language_data): Delete la_language_arch_info.
(asm_language_data): Likewise.
(asm_language::language_arch_info): New member function.
(minimal_language_data): Delete la_language_arch_info.
(minimal_language::language_arch_info): New member function.
* d-lang.c (d_language_arch_info): Delete function, move
implementation to...
(d_language::language_arch_info): ...here, a new member
function.
(d_language_data): Delete la_language_arch_info.
* f-lang.c (f_language_arch_info): Delete function, move
implementation to...
(f_language::language_arch_info): ...here, a new member
function.
(f_language_data): Delete la_language_arch_info.
* go-lang.c (go_language_arch_info): Delete function, move
implementation to...
(go_language::language_arch_info): ...here, a new member
function.
(go_language_data): Delete la_language_arch_info.
* language.c (unknown_language_data): Likewise.
(unknown_language::language_arch_info): New member function.
(auto_language_data): Delete la_language_arch_info.
(auto_language::language_arch_info): New member function.
(language_gdbarch_post_init): Update call to
la_language_arch_info.
* language.h (language_data): Delete la_language_arch_info
function pointer.
(language_defn::language_arch_info): New function.
* m2-lang.c (m2_language_arch_info): Delete function, move
implementation to...
(m2_language::language_arch_info): ...here, a new member
function.
(m2_language_data): Delete la_language_arch_info.
* objc-lang.c (objc_language_arch_info): Delete function, move
implementation to...
(objc_language::language_arch_info): ...here, a new member
function.
(objc_language_data): Delete la_language_arch_info.
* opencl-lang.c (opencl_language_arch_info): Delete function, move
implementation to...
(opencl_language::language_arch_info): ...here, a new member
function.
(opencl_language_data): Delete la_language_arch_info.
* p-lang.c (pascal_language_arch_info): Delete function, move
implementation to...
(pascal_language::language_arch_info): ...here, a new member
function.
(pascal_language_data): Delete la_language_arch_info.
* rust-lang.c (rust_language_arch_info): Delete function, move
implementation to...
(rust_language::language_arch_info): ...here, a new member
function.
(rust_language_data): Delete la_language_arch_info.
2020-05-02 04:51:15 +08:00
|
|
|
|
/* See language.h. */
|
|
|
|
|
void language_arch_info (struct gdbarch *gdbarch,
|
|
|
|
|
struct language_arch_info *lai) const override
|
|
|
|
|
{
|
|
|
|
|
const struct builtin_type *builtin = builtin_type (gdbarch);
|
|
|
|
|
|
|
|
|
|
struct type **types
|
|
|
|
|
= GDBARCH_OBSTACK_CALLOC (gdbarch, nr_rust_primitive_types + 1,
|
|
|
|
|
struct type *);
|
|
|
|
|
|
|
|
|
|
types[rust_primitive_bool] = arch_boolean_type (gdbarch, 8, 1, "bool");
|
|
|
|
|
types[rust_primitive_char] = arch_character_type (gdbarch, 32, 1, "char");
|
|
|
|
|
types[rust_primitive_i8] = arch_integer_type (gdbarch, 8, 0, "i8");
|
|
|
|
|
types[rust_primitive_u8] = arch_integer_type (gdbarch, 8, 1, "u8");
|
|
|
|
|
types[rust_primitive_i16] = arch_integer_type (gdbarch, 16, 0, "i16");
|
|
|
|
|
types[rust_primitive_u16] = arch_integer_type (gdbarch, 16, 1, "u16");
|
|
|
|
|
types[rust_primitive_i32] = arch_integer_type (gdbarch, 32, 0, "i32");
|
|
|
|
|
types[rust_primitive_u32] = arch_integer_type (gdbarch, 32, 1, "u32");
|
|
|
|
|
types[rust_primitive_i64] = arch_integer_type (gdbarch, 64, 0, "i64");
|
|
|
|
|
types[rust_primitive_u64] = arch_integer_type (gdbarch, 64, 1, "u64");
|
|
|
|
|
|
|
|
|
|
unsigned int length = 8 * TYPE_LENGTH (builtin->builtin_data_ptr);
|
|
|
|
|
types[rust_primitive_isize] = arch_integer_type (gdbarch, length, 0, "isize");
|
|
|
|
|
types[rust_primitive_usize] = arch_integer_type (gdbarch, length, 1, "usize");
|
|
|
|
|
|
|
|
|
|
types[rust_primitive_f32] = arch_float_type (gdbarch, 32, "f32",
|
|
|
|
|
floatformats_ieee_single);
|
|
|
|
|
types[rust_primitive_f64] = arch_float_type (gdbarch, 64, "f64",
|
|
|
|
|
floatformats_ieee_double);
|
|
|
|
|
|
|
|
|
|
types[rust_primitive_unit] = arch_integer_type (gdbarch, 0, 1, "()");
|
|
|
|
|
|
|
|
|
|
struct type *tem = make_cv_type (1, 0, types[rust_primitive_u8], NULL);
|
|
|
|
|
types[rust_primitive_str] = rust_slice_type ("&str", tem,
|
|
|
|
|
types[rust_primitive_usize]);
|
|
|
|
|
|
|
|
|
|
lai->primitive_type_vector = types;
|
|
|
|
|
lai->bool_type_default = types[rust_primitive_bool];
|
|
|
|
|
lai->string_char_type = types[rust_primitive_u8];
|
|
|
|
|
}
|
gdb: Convert language la_sniff_from_mangled_name field to a method
This commit changes the language_data::la_sniff_from_mangled_name
function pointer member variable into a member function of
language_defn.
Previously the la_sniff_from_mangled_name pointer was NULL for some
languages, however, all uses of this function pointer were through the
function language_sniff_from_mangled_name which provided a default
implementation.
This default implementation now becomes the implementation in the base
class language_defn, which is then overridden as required in various
language sub-classes.
There should be no user visible changes after this commit.
gdb/ChangeLog:
* ada-lang.c (ada_sniff_from_mangled_name): Delete function,
implementation moves to...
(ada_language::sniff_from_mangled_name): ...here. Update return
type.
(ada_language_data): Delete la_sniff_from_mangled_name
initializer.
* c-lang.c (c_language_data): Likewise.
(cplus_language_data): Likewise.
(cplus_language::sniff_from_mangled_name): New member function,
implementation taken from gdb_sniff_from_mangled_name.
(asm_language_data): Delete la_sniff_from_mangled_name
initializer.
(minimal_language_data): Likewise.
* cp-support.c (gdb_sniff_from_mangled_name): Delete,
implementation moves to cplus_language::sniff_from_mangled_name.
* cp-support.h (gdb_sniff_from_mangled_name): Delete declaration.
* d-lang.c (d_sniff_from_mangled_name): Delete, implementation
moves to...
(d_language::sniff_from_mangled_name): ...here.
(d_language_data): Delete la_sniff_from_mangled_name initializer.
* f-lang.c (f_language_data): Likewise.
* go-lang.c (go_sniff_from_mangled_name): Delete, implementation
moves to...
(go_language::sniff_from_mangled_name): ...here.
(go_language_data): Delete la_sniff_from_mangled_name initializer.
* language.c (language_sniff_from_mangled_name): Delete.
(unknown_language_data): Delete la_sniff_from_mangled_name
initializer.
(auto_language_data): Likewise.
* language.h (language_data): Delete la_sniff_from_mangled_name
field.
(language_defn::sniff_from_mangled_name): New function.
(language_sniff_from_mangled_name): Delete declaration.
* m2-lang.c (m2_language_data): Delete la_sniff_from_mangled_name
field.
* objc-lang.c (objc_sniff_from_mangled_name): Delete,
implementation moves to...
(objc_language::sniff_from_mangled_name): ...here.
(objc_language_data): Delete la_sniff_from_mangled_name initializer.
* opencl-lang.c (opencl_language_data): Likewise.
* p-lang.c (pascal_language_data): Likewise.
* rust-lang.c (rust_sniff_from_mangled_name): Delete,
implementation moves to...
(rust_language::sniff_from_mangled_name): ...here.
(rust_language_data): Delete la_sniff_from_mangled_name
initializer.
* symtab.c (symbol_find_demangled_name): Call
sniff_from_mangled_name member function.
2020-05-14 01:04:30 +08:00
|
|
|
|
|
|
|
|
|
/* See language.h. */
|
|
|
|
|
bool sniff_from_mangled_name (const char *mangled,
|
|
|
|
|
char **demangled) const override
|
|
|
|
|
{
|
|
|
|
|
*demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
|
|
|
|
|
return *demangled != NULL;
|
|
|
|
|
}
|
2020-05-15 01:41:39 +08:00
|
|
|
|
|
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
2020-05-15 02:03:45 +08:00
|
|
|
|
char *demangle (const char *mangled, int options) const override
|
|
|
|
|
{
|
|
|
|
|
return gdb_demangle (mangled, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
2020-05-15 01:41:39 +08:00
|
|
|
|
void print_type (struct type *type, const char *varstring,
|
|
|
|
|
struct ui_file *stream, int show, int level,
|
|
|
|
|
const struct type_print_options *flags) const override
|
|
|
|
|
{
|
|
|
|
|
print_offset_data podata;
|
|
|
|
|
rust_internal_print_type (type, varstring, stream, show, level,
|
|
|
|
|
flags, false, &podata);
|
|
|
|
|
}
|
2020-06-01 22:06:43 +08:00
|
|
|
|
|
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
|
|
|
|
gdb::unique_xmalloc_ptr<char> watch_location_expression
|
|
|
|
|
(struct type *type, CORE_ADDR addr) const override
|
|
|
|
|
{
|
|
|
|
|
type = check_typedef (TYPE_TARGET_TYPE (check_typedef (type)));
|
|
|
|
|
std::string name = type_to_string (type);
|
|
|
|
|
return gdb::unique_xmalloc_ptr<char>
|
|
|
|
|
(xstrprintf ("*(%s as *mut %s)", core_addr_to_string (addr),
|
|
|
|
|
name.c_str ()));
|
|
|
|
|
}
|
2020-06-01 22:36:30 +08:00
|
|
|
|
|
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
|
|
|
|
void value_print_inner
|
|
|
|
|
(struct value *val, struct ui_file *stream, int recurse,
|
|
|
|
|
const struct value_print_options *options) const override
|
|
|
|
|
{
|
|
|
|
|
return rust_value_print_inner (val, stream, recurse, options);
|
|
|
|
|
}
|
2020-06-02 05:17:59 +08:00
|
|
|
|
|
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
|
|
|
|
struct block_symbol lookup_symbol_nonlocal
|
|
|
|
|
(const char *name, const struct block *block,
|
|
|
|
|
const domain_enum domain) const override
|
|
|
|
|
{
|
|
|
|
|
struct block_symbol result = {};
|
|
|
|
|
|
|
|
|
|
if (symbol_lookup_debug)
|
|
|
|
|
{
|
|
|
|
|
fprintf_unfiltered (gdb_stdlog,
|
|
|
|
|
"rust_lookup_symbol_non_local"
|
|
|
|
|
" (%s, %s (scope %s), %s)\n",
|
|
|
|
|
name, host_address_to_string (block),
|
|
|
|
|
block_scope (block), domain_name (domain));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Look up bare names in the block's scope. */
|
|
|
|
|
std::string scopedname;
|
|
|
|
|
if (name[cp_find_first_component (name)] == '\0')
|
|
|
|
|
{
|
|
|
|
|
const char *scope = block_scope (block);
|
|
|
|
|
|
|
|
|
|
if (scope[0] != '\0')
|
|
|
|
|
{
|
|
|
|
|
scopedname = std::string (scope) + "::" + name;
|
|
|
|
|
name = scopedname.c_str ();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
name = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (name != NULL)
|
|
|
|
|
{
|
|
|
|
|
result = lookup_symbol_in_static_block (name, block, domain);
|
|
|
|
|
if (result.symbol == NULL)
|
|
|
|
|
result = lookup_global_symbol (name, block, domain);
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2020-06-02 21:48:04 +08:00
|
|
|
|
|
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
|
|
|
|
int parser (struct parser_state *ps) const override
|
|
|
|
|
{
|
|
|
|
|
return rust_parse (ps);
|
|
|
|
|
}
|
2020-06-03 04:54:49 +08:00
|
|
|
|
|
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
|
|
|
|
void emitchar (int ch, struct type *chtype,
|
|
|
|
|
struct ui_file *stream, int quoter) const override
|
|
|
|
|
{
|
|
|
|
|
if (!rust_chartype_p (chtype))
|
|
|
|
|
generic_emit_char (ch, chtype, stream, quoter,
|
|
|
|
|
target_charset (get_type_arch (chtype)));
|
|
|
|
|
else if (ch == '\\' || ch == quoter)
|
|
|
|
|
fprintf_filtered (stream, "\\%c", ch);
|
|
|
|
|
else if (ch == '\n')
|
|
|
|
|
fputs_filtered ("\\n", stream);
|
|
|
|
|
else if (ch == '\r')
|
|
|
|
|
fputs_filtered ("\\r", stream);
|
|
|
|
|
else if (ch == '\t')
|
|
|
|
|
fputs_filtered ("\\t", stream);
|
|
|
|
|
else if (ch == '\0')
|
|
|
|
|
fputs_filtered ("\\0", stream);
|
|
|
|
|
else if (ch >= 32 && ch <= 127 && isprint (ch))
|
|
|
|
|
fputc_filtered (ch, stream);
|
|
|
|
|
else if (ch <= 255)
|
|
|
|
|
fprintf_filtered (stream, "\\x%02x", ch);
|
|
|
|
|
else
|
|
|
|
|
fprintf_filtered (stream, "\\u{%06x}", ch);
|
|
|
|
|
}
|
2020-06-03 22:54:19 +08:00
|
|
|
|
|
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
|
|
|
|
void printchar (int ch, struct type *chtype,
|
|
|
|
|
struct ui_file *stream) const override
|
|
|
|
|
{
|
|
|
|
|
fputs_filtered ("'", stream);
|
|
|
|
|
LA_EMIT_CHAR (ch, chtype, stream, '\'');
|
|
|
|
|
fputs_filtered ("'", stream);
|
|
|
|
|
}
|
2020-06-03 23:44:05 +08:00
|
|
|
|
|
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
|
|
|
|
void printstr (struct ui_file *stream, struct type *elttype,
|
|
|
|
|
const gdb_byte *string, unsigned int length,
|
|
|
|
|
const char *encoding, int force_ellipses,
|
|
|
|
|
const struct value_print_options *options) const override
|
|
|
|
|
{
|
|
|
|
|
rust_printstr (stream, elttype, string, length, encoding,
|
|
|
|
|
force_ellipses, options);
|
|
|
|
|
}
|
2020-06-19 04:38:50 +08:00
|
|
|
|
|
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
|
|
|
|
void print_typedef (struct type *type, struct symbol *new_symbol,
|
|
|
|
|
struct ui_file *stream) const override
|
|
|
|
|
{
|
|
|
|
|
type = check_typedef (type);
|
|
|
|
|
fprintf_filtered (stream, "type %s = ", new_symbol->print_name ());
|
|
|
|
|
type_print (type, "", stream, 0);
|
|
|
|
|
fprintf_filtered (stream, ";");
|
|
|
|
|
}
|
gdb: Convert language la_is_string_type_p field to a method
This commit changes the language_data::la_is_string_type_p function
pointer member variable into a member function of language_defn.
There should be no user visible changes after this commit.
gdb/ChangeLog:
* ada-lang.c (ada_language_data): Delete la_is_string_type_p
initializer.
(ada_language::is_string_type_p): New member function.
* c-lang.c (c_language_data): Delete la_is_string_type_p
initializer.
(cplus_language_data): Likewise.
(asm_language_data): Likewise.
(minimal_language_data): Likewise.
* d-lang.c (d_language_data): Likewise.
* f-lang.c (f_is_string_type_p): Delete function, implementation
moved to f_language::is_string_type_p.
(f_language_data): Delete la_is_string_type_p initializer.
(f_language::is_string_type_p): New member function,
implementation from f_is_string_type_p.
* go-lang.c (go_is_string_type_p): Delete function, implementation
moved to go_language::is_string_type_p.
(go_language_data): Delete la_is_string_type_p initializer.
(go_language::is_string_type_p): New member function,
implementation from go_is_string_type_p.
* language.c (language_defn::is_string_type_p): Define new member
function.
(default_is_string_type_p): Make static, add comment copied from
header file.
(unknown_language_data): Delete la_is_string_type_p initializer.
(unknown_language::is_string_type_p): New member function.
(auto_language_data): Delete la_is_string_type_p initializer.
(auto_language::is_string_type_p): New member function.
* language.h (language_data): Delete la_is_string_type_p field.
(language_defn::is_string_type_p): Declare new function.
(default_is_string_type_p): Delete desclaration, move comment to
definition.
* m2-lang.c (m2_is_string_type_p): Delete function, implementation
moved to m2_language::is_string_type_p.
(m2_language_data): Delete la_is_string_type_p initializer.
(m2_language::is_string_type_p): New member function,
implementation from m2_is_string_type_p.
* objc-lang.c (objc_language_data): Delete la_is_string_type_p
initializer.
* opencl-lang.c (opencl_language_data): Likewise.
* p-lang.c (pascal_is_string_type_p): Delete function,
implementation moved to pascal_language::is_string_type_p.
(pascal_language_data): Delete la_is_string_type_p initializer.
(pascal_language::is_string_type_p): New member function,
implementation from pascal_is_string_type_p.
* rust-lang.c (rust_is_string_type_p): Delete function,
implementation moved to rust_language::is_string_type_p.
(rust_language_data): Delete la_is_string_type_p initializer.
(rust_language::is_string_type_p): New member function,
implementation from rust_is_string_type_p.
* valprint.c (val_print_scalar_or_string_type_p): Update call to
is_string_type_p.
2020-06-19 05:01:33 +08:00
|
|
|
|
|
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
|
|
|
|
bool is_string_type_p (struct type *type) const override
|
|
|
|
|
{
|
|
|
|
|
LONGEST low_bound, high_bound;
|
|
|
|
|
|
|
|
|
|
type = check_typedef (type);
|
|
|
|
|
return ((type->code () == TYPE_CODE_STRING)
|
|
|
|
|
|| (type->code () == TYPE_CODE_PTR
|
|
|
|
|
&& (TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_ARRAY
|
|
|
|
|
&& rust_u8_type_p (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type)))
|
|
|
|
|
&& get_array_bounds (TYPE_TARGET_TYPE (type), &low_bound,
|
|
|
|
|
&high_bound)))
|
|
|
|
|
|| (type->code () == TYPE_CODE_STRUCT
|
|
|
|
|
&& !rust_enum_p (type)
|
|
|
|
|
&& rust_slice_type_p (type)
|
|
|
|
|
&& strcmp (type->name (), "&str") == 0));
|
|
|
|
|
}
|
2020-07-12 17:15:32 +08:00
|
|
|
|
|
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
|
|
|
|
bool range_checking_on_by_default () const override
|
|
|
|
|
{ return true; }
|
2020-08-04 23:31:56 +08:00
|
|
|
|
|
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
|
|
|
|
const struct exp_descriptor *expression_ops () const override
|
|
|
|
|
{ return &exp_descriptor_rust; }
|
2020-08-05 00:07:59 +08:00
|
|
|
|
|
|
|
|
|
/* See language.h. */
|
|
|
|
|
|
|
|
|
|
const struct op_print *opcode_print_table () const override
|
|
|
|
|
{ return c_op_print_tab; }
|
gdb: Represent all languages as sub-classes of language_defn
This commit converts all languages to sub-classes of a language_defn
base class.
The motivation for this change is to make it easier to add new methods
onto languages without having to update all of the individual language
structures. In the future it might be possible to move more things,
like expression parsing, into the language class(es) for better
encapsulation, however I have no plans to tackle this in the short
term.
This commit sets up a strategy for transitioning from the current
language system, where each language is an instance of the
language_defn structure, to the class hierarchy system.
The plan is to rename the existing language_defn into language_data,
and make this a base class for the new language_defn class, something
like this:
struct language_data
{
... old language_defn fields here ...
};
struct language_defn : public language_data
{
language_defn (const language_data d)
: language_data (d)
{ .... }
};
Then each existing language, for example ada_language_defn can be
converted into an instance of language_data, and passed into the
constructor of a new language class, something like this:
language_data ada_language_data =
{
... old ada_language_defn values here ...
};
struct ada_language : public language_defn
{
ada_language (ada_language_data)
{ .... }
};
What this means is that immediately after the conversion nothing much
changes. Every language is now its own class, but all the old
language fields still exist and can be accessed in the same way.
In later commits I will convert function pointers from the old
language_defn structure into real class methods on language_defn, with
overrides on sub-classes where needed.
At this point I imagine that those fields of the old language_defn
structure that contained only data will probably remain as data fields
within the new language_data base structure, it is only the methods
that I plan to change initially.
I tweaked how we manage the list of languages a bit, each language is
now registered as it is created, and this resulted in a small number
of changes in language.c.
Most of the changes in the *-lang.c files are identical.
There should be no user visible changes after this commit.
gdb/ChangeLog:
* gdb/ada-lang.c (ada_language_defn): Convert to...
(ada_language_data): ...this.
(class ada_language): New class.
(ada_language_defn): New static global.
* gdb/c-lang.c (c_language_defn): Convert to...
(c_language_data): ...this.
(class c_language): New class.
(c_language_defn): New static global.
(cplus_language_defn): Convert to...
(cplus_language_data): ...this.
(class cplus_language): New class.
(cplus_language_defn): New static global.
(asm_language_defn): Convert to...
(asm_language_data): ...this.
(class asm_language): New class.
(asm_language_defn): New static global.
(minimal_language_defn): Convert to...
(minimal_language_data): ...this.
(class minimal_language): New class.
(minimal_language_defn): New static global.
* gdb/d-lang.c (d_language_defn): Convert to...
(d_language_data): ...this.
(class d_language): New class.
(d_language_defn): New static global.
* gdb/f-lang.c (f_language_defn): Convert to...
(f_language_data): ...this.
(class f_language): New class.
(f_language_defn): New static global.
* gdb/go-lang.c (go_language_defn): Convert to...
(go_language_data): ...this.
(class go_language): New class.
(go_language_defn): New static global.
* gdb/language.c (unknown_language_defn): Remove declaration.
(current_language): Initialize to nullptr, real initialization is
moved to _initialize_language.
(languages): Delete global.
(language_defn::languages): Define.
(set_language_command): Use language_defn::languages.
(set_language): Likewise.
(range_error): Likewise.
(language_enum): Likewise.
(language_def): Likewise.
(add_set_language_command): Use language_def::languages for the
language list, and language_def to lookup language pointers.
(skip_language_trampoline): Use language_defn::languages.
(unknown_language_defn): Convert to...
(unknown_language_data): ...this.
(class unknown_language): New class.
(unknown_language_defn): New static global.
(auto_language_defn): Convert to...
(auto_language_data): ...this.
(class auto_language): New class.
(auto_language_defn): New static global.
(language_gdbarch_post_init): Use language_defn::languages.
(_initialize_language): Initialize current_language.
* gdb/language.h (struct language_defn): Rename to...
(struct language_data): ...this.
(struct language_defn): New.
(auto_language_defn): Delete.
(unknown_language_defn): Delete.
(minimal_language_defn): Delete.
(ada_language_defn): Delete.
(asm_language_defn): Delete.
(c_language_defn): Delete.
(cplus_language_defn): Delete.
(d_language_defn): Delete.
(f_language_defn): Delete.
(go_language_defn): Delete.
(m2_language_defn): Delete.
(objc_language_defn): Delete.
(opencl_language_defn): Delete.
(pascal_language_defn): Delete.
(rust_language_defn): Delete.
* gdb/m2-lang.c (m2_language_defn): Convert to...
(m2_language_data): ...this.
(class m2_language): New class.
(m2_language_defn): New static global.
* gdb/objc-lang.c (objc_language_defn): Convert to...
(objc_language_data): ...this.
(class objc_language): New class.
(objc_language_defn): New static global.
* gdb/opencl-lang.c (opencl_language_defn): Convert to...
(opencl_language_data): ...this.
(class opencl_language): New class.
(opencl_language_defn): New static global.
* gdb/p-lang.c (pascal_language_defn): Convert to...
(pascal_language_data): ...this.
(class pascal_language): New class.
(pascal_language_defn): New static global.
* gdb/rust-exp.y (rust_lex_tests): Use language_def to find
language pointer, update comment format.
* gdb/rust-lang.c (rust_language_defn): Convert to...
(rust_language_data): ...this.
(class rust_language): New class.
(rust_language_defn): New static global.
2020-05-01 19:16:58 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Single instance of the Rust language class. */
|
|
|
|
|
|
|
|
|
|
static rust_language rust_language_defn;
|