Skip to content

ability to set alignment on struct fields #1512

Closed
@andrewrk

Description

@andrewrk
Member

Just like global variables and local variables support alignment, struct fields should support alignment.

The alignment of a struct should be the alignment of its most aligned member. As Zig iterates over the fields of a struct, it knows the current alignment at that position. When a field requires more alignment, padding bytes are inserted until the desired alignment is achieved. Zig currently does this incorrectly - See #1248

Related is reordering fields for better performance and memory usage (see #168)

You should also be able to set the alignment of fields in packed structs. This does 2 things:

  • acts as assertions - compiler will give an error if the alignment is impossible given that the struct is packed
  • determines the overall alignment of the packed struct - it will be the alignment of the most aligned field. if no field is specified to be aligned, the alignment of the packed struct will be 1.

A packed struct in an array should give a compile error if its size is not byte-aligned, or if its size is not aligned to its own alignment.

Activity

added
proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.
on Sep 13, 2018
added this to the 0.4.0 milestone on Sep 13, 2018
ghost

ghost commented on Sep 18, 2018

@ghost

Here we can see a use case for specifying the alignment of struct fields: https://github.com/facebook/folly/blob/master/folly/ProducerConsumerQueue.h (search for 'alignas').

They specify the alignment to be the minimum offset between two objects to avoid false sharing.

andrewrk

andrewrk commented on Dec 20, 2018

@andrewrk
MemberAuthor

Note this workaround that is now in master branch, and also described in #1845 (comment):

zig/src/analyze.cpp

Lines 2698 to 2707 in 459045a

// TODO If we have no type_entry for the field, we've already failed to
// compile the program correctly. This stage1 compiler needs a deeper
// reworking to make this correct, or we can ignore the problem
// and make sure it is fixed in stage2. This workaround is for when
// there is a false positive of a dependency loop, of alignment depending
// on itself. When this false positive happens we assume a pointer-aligned
// field, which is usually fine but could be incorrectly over-aligned or
// even under-aligned. See https://github.com/ziglang/zig/issues/1512
if (field->type_entry == nullptr) {
this_field_align = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0));

I think we have to solve the underlying issue before this issue can be resolved.

modified the milestones: 0.4.0, 0.5.0 on Mar 20, 2019
andrewrk

andrewrk commented on Mar 27, 2019

@andrewrk
MemberAuthor

One more thing that should be done with this issue, is to make packed structs divide based on ABI size, not store size. So for this example:

const std = @import("std");
const assert = std.debug.assert;

comptime {
    assert(@sizeOf(u24) == 4);
}
const P = packed struct {
    a: u24,
    b: u8,
};

Currently the struct is generated as

%P = type <{ i24, i8 }>

This is problematic because based on @sizeOf(u24) one expects to be able to write the 4th byte without overwriting the next field.

Instead Zig should generate the struct like this:

%P = type <{ i32 }>

and then do the normal bit shifting and masking that happens for bit fields. This will enable packed structs to work effectively when specifying alignment. Otherwise, aligned u24 fields of packed structs would incorrectly be missing a padding byte.

added a commit that references this issue on Mar 29, 2019

4 remaining items

daurnimator

daurnimator commented on Aug 5, 2019

@daurnimator
Contributor

@nrdmn notes that this is required for certain UEFI structures.

EFI_GUID is specified in https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf on page 21 as "128-bit buffer containing a unique identifier value. Unless otherwise specified, aligned on a 64-bit boundary.", with some details in appendix A on page 2201

andrewrk

andrewrk commented on Aug 22, 2019

@andrewrk
MemberAuthor

I'm in the middle of fixing the bugs regarding struct alignment (#2174). Once that's done, the main blocker to this will be updating the grammar, parser, zig fmt, etc. Anyone want to take a crack at that? The syntax/parser updating work can be merged even if the analysis/codegen isn't done yet.

Here's the current syntax proposal:

struct {
    x: i32 align(expression),
}
added
contributor friendlyThis issue is limited in scope and/or knowledge of Zig internals.
on Aug 22, 2019
andrewrk

andrewrk commented on Aug 23, 2019

@andrewrk
MemberAuthor

Thanks @Tetralux for doing the stage1 and stage2 parser/renderer for this in #3114!

andrewrk

andrewrk commented on Aug 27, 2019

@andrewrk
MemberAuthor

Done with the merge of #3115. See #3125 for unions.

Improving the semantics and alignment considerations of packed structs will be a separate issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedThis proposal is planned.contributor friendlyThis issue is limited in scope and/or knowledge of Zig internals.docsproposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @andrewrk@daurnimator

        Issue actions

          ability to set alignment on struct fields · Issue #1512 · ziglang/zig