Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Proposal: Allow aligned zero-size pointers #6954

Closed
SpexGuy opened this issue Nov 2, 2020 · 3 comments
Closed

Proposal: Allow aligned zero-size pointers #6954

SpexGuy opened this issue Nov 2, 2020 · 3 comments
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@SpexGuy
Copy link
Contributor

SpexGuy commented Nov 2, 2020

Zero-sized pointers are really inconsistent about alignment.

// compiles
[]void, []align(0) void, []align(4) void, []align(@alignOf(void)) void
comptime { const x = @alignOf(void); }

// doesn't compile
var x: u29 = @alignOf(void);
var y: u29 = @typeInfo([]void).Pointer.alignment;
[]align(@compileError("")) void

fn slice(comptime ment: u29) type { return []align(ment) void; }
slice(@alignOf(void));

// crashes compiler
_ = ([]align(2) void == []align(4) void);

I see two ways to resolve this:

  • never allow alignment on zero-sized types
  • define default alignment on zero-sized types and allow it always

Never allowing alignment causes a lot of special cases for zero sized types. So I think we should standardize alignment. In all places, we have the invariant that @alignOf(T) <= @sizeOf(T). This means the only valid alignment for zero-sized types is 0. Which kind of makes sense, you could argue that they are bit packed. Defining the alignment this way isn't perfect but definitely cuts down on the number of special cases with zero-sized types.

@daurnimator
Copy link
Contributor

daurnimator commented Nov 3, 2020

Alignment of types can be user defined; it's our definition of @sizeOf which is a bit weird: it's defined as the size the type takes in an array. i.e. max(ceil(@bitSizeOf(T)/8), @alignOf(T)).

You can create a small object with large alignment with e.g.

const Foo = struct {
   x: u32 align(4096),
};
pub fn main() !void {
  const f = Foo{.x=2};
  std.debug.print("align={}, size={}, {}\n", .{@alignOf(Foo), @sizeOf(Foo), f});
}

You'll see

align=4096, size=4096, Foo{ .x = 2 }

See also #4016

@daurnimator daurnimator added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Nov 3, 2020
@marler8997
Copy link
Contributor

marler8997 commented Nov 3, 2020

I suggest the invariant @alignOf(T) >= 1. By forbidding @alignOf from being 0, you're able to use the alignment in more mathematical expressions without having a special case for 0. Using this invariant, the alignment of all 0 sized types would be 1. I think this makes things simple.

@SpexGuy
Copy link
Contributor Author

SpexGuy commented Nov 25, 2020

In #6706 it was decided that pointers to zero-sized types should actually be pointers, so I'm closing this issue. However I think there's a case to be made that the abi alignment of zero sized types should be 1 instead of 0, so I've opened #7221 to continue that discussion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

4 participants