Struct alignment implementation questions


#1

I’m attempting to implement the #[repr(align)] RFC which is jumping in the deep end slightly with my level of knowledge about Rust compiler internals. I managed to get parsing an align repr and setting alignment of the struct such that mem::align_of returns the right thing for my aligned type. However mem::size_of is not returning the aligned size and I’m not totally sure what the correct way to do this is.

If I create this aligned type in C++:

struct alignas(16) Align16 {
        int i;
};

The IR type generated from Clang is:

%struct.Align16 = type { i32, [12 x i8] }

My similarly aligned type in Rust is missing the [12 xi8]. I wasn’t sure if I’d need to add padding or if LLVM would pad the layout to the alignment, but it seems that it’s something that needs to be handled on the Rust side of things. Does that sound correct, the way to get the type sized correctly would be to add padding bytes to the struct layout? If so, where would be the place to do this in the code? I figure someone here might be able to point me in the right direction :slight_smile:


#2

I think the compiler will take care of it. Probably all you need to do is to check the repr(align) attribute at all places where a ty::Layout is created, error if the attribute alignment is smaller than the alignment required by the type, and overwrite the alignment, if the attribute alignment is bigger than the required one.

Afaik, anything breaking due to this can probably be considered a bug.


#3

Hmm, I was hoping that would be the case, but it didn’t seem to work. Possibly I’m not adding alignment everywhere I need to. At the moment I check for repr align in librustc::ty::layout::Struct::new and set alignment on the returned Struct there, the alignment did appear to be picked up but it didn’t seem to result in a correctly sized type. I also tried setting Struct::min_size to the alignment value, although I wasn’t sure where that was used, and indeed it didn’t seem to change the size. The change I’ve made so far is https://github.com/bitshifter/rust/commit/19007861eff40a326f951e6b6159f9a2d7e8b0e3 plus a unit test in the next commit.


#4

Added setting min_size back since that sets the Layout stride correctly, but still doesn’t result in a correct LLVM type. One thing I’m trying to work out is where in the code the corresponding LLVM type is created from the Rust layout type. That might help work out what’s going on.