Message ID | CAFOnWk=gVjBMMNrR1m16Wri62ZgUNAS_7q+MJDk_QYxPjECezQ@mail.gmail.com |
---|---|
State | New, archived |
Headers |
Received: (qmail 115795 invoked by alias); 29 Oct 2016 01:02:37 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: <gdb-patches.sourceware.org> List-Unsubscribe: <mailto:gdb-patches-unsubscribe-##L=##H@sourceware.org> List-Subscribe: <mailto:gdb-patches-subscribe@sourceware.org> List-Archive: <http://sourceware.org/ml/gdb-patches/> List-Post: <mailto:gdb-patches@sourceware.org> List-Help: <mailto:gdb-patches-help@sourceware.org>, <http://sourceware.org/ml/#faqs> Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 115785 invoked by uid 89); 29 Oct 2016 01:02:36 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=overlapping, unions X-HELO: mail-wm0-f47.google.com Received: from mail-wm0-f47.google.com (HELO mail-wm0-f47.google.com) (74.125.82.47) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 29 Oct 2016 01:02:34 +0000 Received: by mail-wm0-f47.google.com with SMTP id n67so141799276wme.1 for <gdb-patches@sourceware.org>; Fri, 28 Oct 2016 18:02:34 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:date:message-id:subject:to:cc; bh=GVuVde/COOgvgcY6GkCJTH4xxyYvFpIYRHAwsPXyVI0=; b=RRHJRbN3kvV7mmRnz9No46Eq0AoSXA/JTx6tb54hSsfH0li5oOz52Wauq5zMNDafBC O7fmHhXjsYyj/fLC75TMw7JUY63oDqQbqAP1NsNQkpIAtxyYFb2GFTO44UzYFZ4A/I/r T+h0B+S6Nrmp6VXDLcwuSa4Y97ZfznBOUYasQzw6AkygGqvu3AZxWbB0XZCRyaCxJBFW T3xhrkb0uKq88QGRQIDoK67SmNXP5YCTS5unka4uQWn17aRM5LBl+QDmbic/geIcnN0i 2SII2urlkY66oi/M5tU2WGbs3YSI4aOrdu0NNT0e7FNtV4a0ic7jQfth02jBA7R4pNaf Tkgg== X-Gm-Message-State: ABUngvfp2G27ZXjz1IvHeOGpP+DTLMQ6sieAe+4VAlLqBsUz4cq1ubvKtw3joS66A+XWA4Y/jgvtyGo5hSVqmDKi X-Received: by 10.28.2.68 with SMTP id 65mr973988wmc.5.1477702952457; Fri, 28 Oct 2016 18:02:32 -0700 (PDT) MIME-Version: 1.0 Received: by 10.28.131.21 with HTTP; Fri, 28 Oct 2016 18:02:12 -0700 (PDT) From: Manish Goregaokar <manish@mozilla.com> Date: Fri, 28 Oct 2016 18:02:12 -0700 Message-ID: <CAFOnWk=gVjBMMNrR1m16Wri62ZgUNAS_7q+MJDk_QYxPjECezQ@mail.gmail.com> Subject: [PATCH] Add support for untagged unions To: gdb-patches@sourceware.org Cc: Tom Tromey <tom@tromey.com> Content-Type: text/plain; charset=UTF-8 X-IsSubscribed: yes |
Commit Message
Manish Goregaokar
Oct. 29, 2016, 1:02 a.m. UTC
Rust supports untagged unions (C unions) now (using the same syntax as
structs but with `union` instead of `struct` in the declaration).
These are mainly used for FFI.
No tests because stable Rust doesn't have these yet. Let me know if I
should add them.
From: Manish Goregaokar <manish@mozilla.com>
Subject: [PATCH] Add support for untagged unions
2016-10-28 Manish Goregaokar <manish@mozilla.com>
gdb/ChangeLog:
* rust-lang.c (rust_union_is_untagged): Add function to
check if a union is an untagged unioni
* rust-lang.c (rust_val_print): Handle printing of untagged union values
* rust-lang.c (rust_print_type): Handle printing of untagged union types
* rust-lang.c (rust_evaluate_subexp): Handle evaluating field
access on untagged unions
---
gdb/rust-lang.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 52 insertions(+), 4 deletions(-)
@@ -638,6 +668,7 @@ rust_val_print (struct type *type, const gdb_byte
*valaddr, int embedded_offset,
break;
case TYPE_CODE_STRUCT:
+ struct_val:
{
int i;
int first_field;
@@ -809,6 +840,7 @@ rust_print_type (struct type *type, const char *varstring,
break;
case TYPE_CODE_STRUCT:
+ struct_printer:
{
int is_tuple_struct;
@@ -823,7 +855,12 @@ rust_print_type (struct type *type, const char *varstring,
if (TYPE_N_BASECLASSES (type) > 0)
goto c_printer;
- fputs_filtered ("struct ", stream);
+ /* This code path is also used by unions. */
+ if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
+ fputs_filtered ("struct ", stream);
+ else
+ fputs_filtered ("union ", stream);
+
if (TYPE_TAG_NAME (type) != NULL)
fputs_filtered (TYPE_TAG_NAME (type), stream);
@@ -899,6 +936,13 @@ rust_print_type (struct type *type, const char *varstring,
/* Skip the discriminant field. */
int skip_to = 1;
+ /* Unions and structs have the same syntax in Rust,
+ the only difference is that structs are declared with `struct`
+ and union with `union`. This difference is handled in the struct
+ printer. */
+ if (rust_union_is_untagged (type))
+ goto struct_printer;
+
fputs_filtered ("enum ", stream);
if (TYPE_TAG_NAME (type) != NULL)
{
@@ -1637,7 +1681,10 @@ rust_evaluate_subexp (struct type *expect_type,
struct expression *exp,
lhs = evaluate_subexp (NULL_TYPE, exp, pos, noside);
type = value_type (lhs);
- if (TYPE_CODE (type) == TYPE_CODE_UNION)
+ /* Untagged unions can't have anonymous field access since
+ they can only have named fields. */
+ if (TYPE_CODE (type) == TYPE_CODE_UNION
+ && !rust_union_is_untagged (type))
{
struct cleanup *cleanup;
@@ -1712,8 +1759,8 @@ tuple structs, and tuple-like enum variants"));
lhs = evaluate_subexp (NULL_TYPE, exp, pos, noside);
type = value_type (lhs);
-
- if (TYPE_CODE (type) == TYPE_CODE_UNION)
+ if (TYPE_CODE (type) == TYPE_CODE_UNION
+ && !rust_union_is_untagged (type))
{
int i, start;
struct disr_info disr;
@@ -1762,6 +1809,7 @@ which has only anonymous fields"),
}
else
{
+ /* Field access in structs and untagged unions works like C. */
*pos = pc;
result = evaluate_subexp_standard (expect_type, exp, pos, noside);
}
Comments
Commit message of this and the previous patch should probably say "in Rust" somewhere (will amend before pushing) -Manish On Fri, Oct 28, 2016 at 6:02 PM, Manish Goregaokar <manish@mozilla.com> wrote: > Rust supports untagged unions (C unions) now (using the same syntax as > structs but with `union` instead of `struct` in the declaration). > These are mainly used for FFI. > > No tests because stable Rust doesn't have these yet. Let me know if I > should add them. > > From: Manish Goregaokar <manish@mozilla.com> > Subject: [PATCH] Add support for untagged unions > > 2016-10-28 Manish Goregaokar <manish@mozilla.com> > > gdb/ChangeLog: > * rust-lang.c (rust_union_is_untagged): Add function to > check if a union is an untagged unioni > * rust-lang.c (rust_val_print): Handle printing of untagged union values > * rust-lang.c (rust_print_type): Handle printing of untagged union types > * rust-lang.c (rust_evaluate_subexp): Handle evaluating field > access on untagged unions > --- > gdb/rust-lang.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- > 1 file changed, 52 insertions(+), 4 deletions(-) > > diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c > index 9569584..5376efc 100644 > --- a/gdb/rust-lang.c > +++ b/gdb/rust-lang.c > @@ -93,6 +93,28 @@ struct disr_info > > #define RUST_ENCODED_ENUM_HIDDEN 1 > > +/* Whether or not a TYPE_CODE_UNION value is an untagged union > + as opposed to being a regular Rust enum. */ > +static bool > +rust_union_is_untagged(struct type *type) { > + /* Unions must have at least one field. */ > + if (TYPE_NFIELDS (type) == 0) > + return false; > + /* If the first field is named, but the name has the rust enum prefix, > + it is an enum. */ > + if (strncmp (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX, > + strlen (RUST_ENUM_PREFIX)) == 0) > + return false; > + /* Unions only have named fields. */ > + for (int i = 0; i < TYPE_NFIELDS (type); ++i) > + { > + if (strlen (TYPE_FIELD_NAME (type, i)) == 0) > + return false; > + } > + return true; > + > +} > + > /* Utility function to get discriminant info for a given value. */ > > static struct disr_info > @@ -566,6 +588,14 @@ rust_val_print (struct type *type, const gdb_byte > *valaddr, int embedded_offset, > struct value_print_options opts; > struct cleanup *cleanup; > > + /* 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. */ > + if (rust_union_is_untagged (type)) > + goto struct_val; > + > opts = *options; > opts.deref_ref = 0; > > @@ -638,6 +668,7 @@ rust_val_print (struct type *type, const gdb_byte > *valaddr, int embedded_offset, > break; > > case TYPE_CODE_STRUCT: > + struct_val: > { > int i; > int first_field; > @@ -809,6 +840,7 @@ rust_print_type (struct type *type, const char *varstring, > break; > > case TYPE_CODE_STRUCT: > + struct_printer: > { > int is_tuple_struct; > > @@ -823,7 +855,12 @@ rust_print_type (struct type *type, const char *varstring, > if (TYPE_N_BASECLASSES (type) > 0) > goto c_printer; > > - fputs_filtered ("struct ", stream); > + /* This code path is also used by unions. */ > + if (TYPE_CODE (type) == TYPE_CODE_STRUCT) > + fputs_filtered ("struct ", stream); > + else > + fputs_filtered ("union ", stream); > + > if (TYPE_TAG_NAME (type) != NULL) > fputs_filtered (TYPE_TAG_NAME (type), stream); > > @@ -899,6 +936,13 @@ rust_print_type (struct type *type, const char *varstring, > /* Skip the discriminant field. */ > int skip_to = 1; > > + /* Unions and structs have the same syntax in Rust, > + the only difference is that structs are declared with `struct` > + and union with `union`. This difference is handled in the struct > + printer. */ > + if (rust_union_is_untagged (type)) > + goto struct_printer; > + > fputs_filtered ("enum ", stream); > if (TYPE_TAG_NAME (type) != NULL) > { > @@ -1637,7 +1681,10 @@ rust_evaluate_subexp (struct type *expect_type, > struct expression *exp, > lhs = evaluate_subexp (NULL_TYPE, exp, pos, noside); > > type = value_type (lhs); > - if (TYPE_CODE (type) == TYPE_CODE_UNION) > + /* Untagged unions can't have anonymous field access since > + they can only have named fields. */ > + if (TYPE_CODE (type) == TYPE_CODE_UNION > + && !rust_union_is_untagged (type)) > { > struct cleanup *cleanup; > > @@ -1712,8 +1759,8 @@ tuple structs, and tuple-like enum variants")); > lhs = evaluate_subexp (NULL_TYPE, exp, pos, noside); > > type = value_type (lhs); > - > - if (TYPE_CODE (type) == TYPE_CODE_UNION) > + if (TYPE_CODE (type) == TYPE_CODE_UNION > + && !rust_union_is_untagged (type)) > { > int i, start; > struct disr_info disr; > @@ -1762,6 +1809,7 @@ which has only anonymous fields"), > } > else > { > + /* Field access in structs and untagged unions works like C. */ > *pos = pc; > result = evaluate_subexp_standard (expect_type, exp, pos, noside); > } > -- > 2.10.1
>>>>> "Manish" == Manish Goregaokar <manish@mozilla.com> writes:
Manish> Rust supports untagged unions (C unions) now (using the same
Manish> syntax as structs but with `union` instead of `struct` in the
Manish> declaration). These are mainly used for FFI.
Thank you.
Manish> No tests because stable Rust doesn't have these yet. Let me know
Manish> if I should add them.
I think they're necessary but I want to understand the options.
Is it hard to determine if rustc supports unions?
Is there some flag that must be passed?
I suppose one idea would be to feature test rustc in the test suite,
then change the new tests to be unsupported if this fails. And, if a
flag is needed, pass it -- but go back once the feature hits stable and
remove the flag?
I think the essentials of the patch are fine.
Manish> * rust-lang.c (rust_union_is_untagged): Add function to
Manish> check if a union is an untagged unioni
Manish> * rust-lang.c (rust_val_print): Handle printing of untagged union values
Just the first entry needs the "* FILENAME" bit.
Manish> +/* Whether or not a TYPE_CODE_UNION value is an untagged union
Manish> + as opposed to being a regular Rust enum. */
Manish> +static bool
Manish> +rust_union_is_untagged(struct type *type) {
This has various style issues.
Thanks for using bool.
Manish> + Since the field bit positions overlap in the debuginfo,
Manish> + the code for printing a union is same as that for a struct,
Manish> + the only difference is that the input type will have overlapping
Manish> + fields. */
Manish> + if (rust_union_is_untagged (type))
Manish> + goto struct_val;
I think it'd be better to turn the specific case's body into a helper
function. I'd like to get rid of a lot of these gotos; and I also plan
to remove as many cleanups as possible from the rust code in gdb...
Manish> + /* This code path is also used by unions. */
Manish> + if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
Manish> + fputs_filtered ("struct ", stream);
Manish> + else
Manish> + fputs_filtered ("union ", stream);
Manish> +
Manish> if (TYPE_TAG_NAME (type) != NULL)
Indentation of that addition looks wrong.
Manish> + /* Field access in structs and untagged unions works like C. */
Manish> *pos = pc;
Same here.
Tom
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c index 9569584..5376efc 100644 --- a/gdb/rust-lang.c +++ b/gdb/rust-lang.c @@ -93,6 +93,28 @@ struct disr_info #define RUST_ENCODED_ENUM_HIDDEN 1 +/* Whether or not a TYPE_CODE_UNION value is an untagged union + as opposed to being a regular Rust enum. */ +static bool +rust_union_is_untagged(struct type *type) { + /* Unions must have at least one field. */ + if (TYPE_NFIELDS (type) == 0) + return false; + /* If the first field is named, but the name has the rust enum prefix, + it is an enum. */ + if (strncmp (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX, + strlen (RUST_ENUM_PREFIX)) == 0) + return false; + /* Unions only have named fields. */ + for (int i = 0; i < TYPE_NFIELDS (type); ++i) + { + if (strlen (TYPE_FIELD_NAME (type, i)) == 0) + return false; + } + return true; + +} + /* Utility function to get discriminant info for a given value. */ static struct disr_info @@ -566,6 +588,14 @@ rust_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, struct value_print_options opts; struct cleanup *cleanup; + /* 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. */ + if (rust_union_is_untagged (type)) + goto struct_val; + opts = *options; opts.deref_ref = 0;