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

There is no syntax for struct alignment #325

Closed
rust-highfive opened this Issue Sep 26, 2014 · 15 comments

Comments

Projects
None yet
@rust-highfive
Copy link

rust-highfive commented Sep 26, 2014

Issue by edef1c
Thursday Sep 25, 2014 at 18:20 GMT

For earlier discussion, see rust-lang/rust#17537

This issue was labelled with: in the Rust repository


Currently, a C struct definition including an alignment hint (ALIGN(64)) cannot be translated to Rust.
Our inability to translate this makes some C ABIs impossible to adhere to, causing crashes and undefined behaviour.
The only way to hack around this is to prepend your struct with a zero-length array of a SIMD type.
We should have some kind of syntax for this. Perhaps #[align(64)]?
@eddyb proposed #[repr(align(64))], but I fear that complicates the repr attribute a bit much.

@edef1c

This comment has been minimized.

Copy link

edef1c commented Sep 26, 2014

welp, I can't edit this one.

- The only way to hack around this is to build a same-sized type out of SIMD types and transmute it when necessary.
+ The only way to hack around this is to prepend your struct with a zero-length array of a SIMD type.
@zwarich

This comment has been minimized.

Copy link
Contributor

zwarich commented Sep 26, 2014

@edef1c I updated it for you.

@huonw

This comment has been minimized.

Copy link
Member

huonw commented Sep 26, 2014

@edef1c it's information added to each load/store/manipulation, it's not an inherent property of the LLVM "type", e.g.

struct Foo {
    int x;
} __attribute__((__aligned__(1024)));

struct Foo f(struct Foo x) {
    struct Foo y;
    return x;
}

compiles to (clang -S -emit-llvm):

; ModuleID = 'alignment.c'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"

%struct.Foo = type { i32, [1020 x i8] }

; Function Attrs: nounwind uwtable
define void @f(%struct.Foo* noalias sret %agg.result, %struct.Foo* byval align 1024 %x) #0 {
  %y = alloca %struct.Foo, align 1024
  %1 = bitcast %struct.Foo* %agg.result to i8*
  %2 = bitcast %struct.Foo* %x to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* %2, i64 1024, i32 1024, i1 false)
  ret void
}

; Function Attrs: nounwind
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) #1

attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind }
@aturon

This comment has been minimized.

Copy link
Member

aturon commented Sep 26, 2014

@edef1c

This comment has been minimized.

Copy link

edef1c commented Sep 27, 2014

@huonw Yep, I discovered that — though Clang seems to get it horribly wrong for my struct (an array of internal align(64) structs has padding /next/ to it — gcc gets it right though)

@thestinger

This comment has been minimized.

Copy link

thestinger commented Sep 27, 2014

The information added to the loads / stores / parameters is just an optimization.

@pythonesque

This comment has been minimized.

Copy link
Contributor

pythonesque commented Oct 17, 2014

Idly, it would be convenient for some usecases if the checks done for transmute (statically verifying that its two type parameters have the same alignment and size) would be useful in some cases for custom allocators (both would be independently useful, actually--in the case I'm thinking of I would only care about alignment). Then instead of requiring the allocator to track the different size class / aligment pools at runtime, you could explicitly allocate a pool with the class you needed and safely verify it at compile time. It would also allow transmute to be used on types with type parameters as long as they could be bounded to have the same size and alignment. I guess such a type would require associated constants in order to be representable, though. Right now there's no way to provide an interface like this without requiring the client to use unsafe code to transmute his or her type.

Looking up, it seems like this has more to do with the closed issue (rust-lang/rust#4578) than this one.

@retep998

This comment has been minimized.

Copy link
Member

retep998 commented Oct 24, 2015

I'd like to mention that in some cases the workaround of using a simd type doesn't work. For example in Windows API where some types will have packing specified to be 2, which is greater than what I'd get with #[repr(packed)] but less than the default, so there's simply no way to specify that alignment correctly in Rust right now. I'm really not a huge fan of how much Rust seems to be deliberately ignoring the needs of people trying to do FFI. We've had several stable versions of Rust already, maybe we can start looking into actually adding things like this.

@Rufflewind

This comment has been minimized.

Copy link

Rufflewind commented Apr 24, 2017

It would also be nice to have something similar to C++’s std::aligned_storage<T>. This can be useful for e.g. intentionally bypassing lifetime or trait bounds (see: #1918), or preventing drop or clone from being run, etc.

@Mark-Simulacrum

This comment has been minimized.

Copy link
Member

Mark-Simulacrum commented Apr 24, 2017

Does #1358 not fulfill the needs of this? Or is there something more (besides that RFC) that needs to be implemented in order to close this issue?

@Rufflewind

This comment has been minimized.

Copy link

Rufflewind commented May 31, 2017

@Mark-Simulacrum I don't believe it's possible to write #[repr(align = alignof(T))] for a type parameter T.

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented May 31, 2017

You could always do that with [T; 0], though. This feature is about custom alignments (not from types).

@Rufflewind

This comment has been minimized.

Copy link

Rufflewind commented May 31, 2017

@eddyb Had no idea that was possible. Thanks!

Edit: Still need a way to declare an array of u8 of size T, but that's out of the scope of this issue.

@retep998

This comment has been minimized.

Copy link
Member

retep998 commented May 31, 2017

@Mark-Simulacrum I believe #1358 did solve the issue. Still waiting for the feature to stabilize, but it does at least exist.

@scottmcm

This comment has been minimized.

Copy link
Member

scottmcm commented Jan 19, 2018

With #1358 merged, I'm going to close this to reduce issue volume. Comment if you disagree!

@eddyb eddyb closed this Jan 19, 2018

wycats pushed a commit to wycats/rust-rfcs that referenced this issue Mar 5, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.