Skip to content

Tags with more than one variant are always 4 byte aligned #792

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
pcwalton opened this issue Aug 1, 2011 · 2 comments
Closed

Tags with more than one variant are always 4 byte aligned #792

pcwalton opened this issue Aug 1, 2011 · 2 comments

Comments

@pcwalton
Copy link
Contributor

pcwalton commented Aug 1, 2011

Because of this code:

fn T_tag(&type_names tn, uint size) -> TypeRef {
    auto s = "tag_" + uint::to_str(size, 10u);
    if (tn.name_has_type(s)) { ret tn.get_type(s); }
    auto t = T_struct(~[T_int(), T_array(T_i8(), size)]);
    tn.associate(s, t);
    ret t;
}

Tags always end up 4 byte aligned when they have more than one variant, even when that's wrong.

@nikomatsakis
Copy link
Contributor

This problem is more urgent as we support more architectures.

In general, I think tags should be laid out as follows (this is fairly close to what the current code does):

  • No data: just like an enum.

  • Only one variant: just like that variant's data

  • Multiple variants with data:

    struct Tag {
        unsigned variant_id;
        union { variant_1, variant_2, variant_3 } data;
    }
    

    where variant_N stands in for the translation of the data types.

The tricky case of course is with generic types. For something like

tag option<T> { none; some(val: T); }

where is the data located? That depends on the type of T and its corresponding alignment restrictions. I am not clear on how the current dynamic shape-walking code (GEP-tuple-like, Shape.h, and friends) handles this kind of dynamic alignment. I could see an argument for using a pessimistic alignment (i.e., maximally align the data in tags always), but that seems to waste a lot of space, since the maximal reasonable alignment is probably 16 bytes (vector data), and you only NEED 4 bytes (for the variant ID).

For reference, the current behavior is:

  • No data: unsigned long variant_id
  • Only one variant: use a char[X] array where X is the size of the variant
  • Multiple variants: struct Tag { unsigned long variant_id; char[X] data; } where X is the size of the largest variant

@nikomatsakis
Copy link
Contributor

Subsumed by #1645

keeperofdakeys pushed a commit to keeperofdakeys/rust that referenced this issue Dec 12, 2017
Add IP_BINDANY for FreeBSD

Adds the IP_BINDANY constant for FreeBSD. Thanks!
coastalwhite pushed a commit to coastalwhite/rust that referenced this issue Aug 5, 2023
celinval pushed a commit to celinval/rust-dev that referenced this issue Jun 4, 2024
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants