News for hackers. Stuff that matters.
Re:A bug story: data alignment on x86 by speps on Monday November 07, 2016 @08:05AM (#12890688)
In C++11 there is a standard for this : http://en.cppreference.com/w/cpp/language/alignas
Re:A bug story: data alignment on x86 by qb45 on Monday November 07, 2016 @09:08AM (#12891057)
I think it doesn't work in this case because

If the strictest (largest) alignas on a declaration is weaker than the alignment it would have without any alignas specifiers (that is, weaker than its natural alignment or weaker than alignas on another declaration of the same object or type), the program is ill-formed.

Also, using alignas on pointer variable will probably specify alignment of the pointer itself, not the pointed object. I suppose you can create a wrapper class around int with alignas(32) and specify the pointer as pointing to that, but this is going to be nasty given that you can't derive from int and have to write all those operators by hand.

Re:A bug story: data alignment on x86 by d33 on Monday November 07, 2016 @08:25AM (#12890801)
Anybody knows how Rust handles this problem?
Re:A bug story: data alignment on x86 by alkonaut on Monday November 07, 2016 @08:57AM (#12890994)
Not sure if this is what you are asking: Last time I tried alignment in Rust I worked around the lack of explicit alignment support by adding a zero length array of the correct size to the end of the struct. Not sure if alignment support from proper attributes has landed yet.

   [repr(C)]
   struct Something
   {
      pub foo: f32,
      pub _alignment: [EightBytes, 0]
   }
where "EightBytes" is a data type of size 8, to align the whole struct on 8 bytes.
Re:A bug story: data alignment on x86 by steveklabnik on Monday November 07, 2016 @09:34AM (#12891240)
Structs already insert padding to give them alignment:

    struct One {
      foo: u8,
    }
    
    struct Two {
      bar: u16,
    }
    
    struct Three {
      foo: u8,
      bar: u16,
    }
    
    struct Four {
      foo: u16,
      bar: u16,
    }
    
    fn main() {
        assert_eq!(1, std::mem::size_of::<One>());
        assert_eq!(2, std::mem::size_of::<Two>());
        assert_eq!(4, std::mem::size_of::<Three>());
        assert_eq!(4, std::mem::size_of::<Four>());
    }
Re:A bug story: data alignment on x86 by alkonaut on Monday November 07, 2016 @09:43AM (#12891325)
What I needed to do was to place e.g. a N byte struct exactly on an M byte alignment (e.g. 11 byte struct on 32 byte alignment etc).
Re:A bug story: data alignment on x86 by steveklabnik on Monday November 07, 2016 @10:10AM (#12891616)
Ah! Yeah, that's different, and as far as I know your way is the current right way to do it, but I'm not an expert on the subject.
Re:A bug story: data alignment on x86 by Thiez on Monday November 07, 2016 @01:49PM (#12893699)
Well given that Rust leaves struct layout undefined unless #[repr(C)] is specified, std::mem::size_of::<Three> is actually not guaranteed to be 4.
Re:A bug story: data alignment on x86 by steveklabnik on Monday November 07, 2016 @02:01PM (#12893824)
While this is true, it's a weird angle that's not itself super well defined. That is, the definition of repr(packed) implies that the alignment will always be there without it...
Re:A bug story: data alignment on x86 by wyldfire on Monday November 07, 2016 @09:13AM (#12891084)
I doubt you can count on all items being allocated at addresses that are multiples if their size.

It's not optimal but you can always use libc::posix_memalign()

Re:A bug story: data alignment on x86 by alkonaut on Monday November 07, 2016 @02:50PM (#12894350)
The final element of the struct is a zero length array of elements of size N bytes. So that element isn't padding, it has size 0! It's pure hinting. I'm not sure why or how this works under the hood I'm afraid. I used it successfully to call a library with pretty strict alignment requirements (Intel Embree).
Re:A bug story: data alignment on x86 by Thiez on Monday November 07, 2016 @05:37PM (#12895879)
The zero length array still must be aligned correctly. You can create a pointer to it (e.g. by taking &something._alignment[..] to create a slice) and pointers must have correct alignment, so it follows that a zero length array has the same alignment requirements as a longer array. So padding must be inserted in your struct so that the address of the zero-length array is correctly aligned.
Re:A bug story: data alignment on x86 by alkonaut on Tuesday November 08, 2016 @06:29AM (#12899358)
Hmm, I don't understand (sorry). The pointer to the internal array must be aligned. But how does the element size play into the padding. If we take these two examples?

   [repr(C)]
   struct StructA
   {
      pub foo: f32,
      _alignment: [SixteenBytes, 0]
   }

   [repr(C)]
   struct StructB
   {
      pub foo: f32,
      _alignment: [ThirtytwoBytes, 0]
   }
Are both just padded with 16-4 and 32-4 bytes respectively, so they are equivalent to making a padding like this in the first case?

   [repr(C)]
   struct StructAPadded
   {
      pub foo: f32,
      _padding : TwelveBytes;
   }
Re:A bug story: data alignment on x86 by hsivonen on Monday November 07, 2016 @11:48AM (#12892464)
Types in Rust have alignment as in C, and bad stuff may happen if you use unsafe code to violate alignment.

It seems that at present, if you want to generate an unaligned SSE2 load/store, you have to rely on modern memcpy (spelled copy_nonoverlapping in Rust) optimization. See the first reply to https://internals.rust-lang.org/t/unaligned-simd-sse2-in-par...