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
Closed

There is no syntax for struct alignment #325

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

Comments

@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
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
Copy link

zwarich commented Sep 26, 2014

@edef1c I updated it for you.

@huonw
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
Copy link
Member

aturon commented Sep 26, 2014

See also rust-lang/rust#4578

@edef1c
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
Copy link

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

@pythonesque
Copy link
Contributor

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
Copy link
Member

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
Copy link

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
Copy link
Member

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
Copy link

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

@eddyb
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
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
Copy link
Member

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

@scottmcm
Copy link
Member

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

@eddyb eddyb closed this as completed 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
Labels
None yet
Projects
None yet
Development

No branches or pull requests