Description
There is a problem with union type: it has no padding. And it's important to have one.
Example:
typedef union {
uint16_t f0;
signed f1 : 11;
unsigned f2 : 2;
signed f3 : 5;
} U;
static U g0 = {65534};
static U g1[2] = {{65534}, {65534}};
static uint16_t *g2 = &g1[1].f0;
This is how the original LLVM IR looks like:
@g0 = global %union.U { i16 -2, [2 x i8] zeroinitializer }
@g1 = global [2 x %union.U] [%union.U { i16 -2, [2 x i8] zeroinitializer }, %union.U0 { i16 -2, [2 x i8] zeroinitializer }]
@g2 = global ptr getelementptr (i8, ptr @g1, i64 4)
As one can see, there is an extra padding for the union type: [2 x i8] zeroinitializer
, and g0
size is 4 bytes in total. And for g2
offset is computes as 4 - since it points to the second element of g1
.
LLVM IR after CIR doesn't have these padding bytes neither it has union
keyword (I wonder when we lost it but it's not a problem right now).
@g0 = global { i16 } { i16 -2 }
@g1 = global [2 x { i16 }] [{ i16 } { i16 -2 }, { i16 } { i16 -2 }]
@g2 = global ptr getelementptr inbounds ([2 x { i16 }], ptr @g1, i32 0, i32 2)
g0
has size of 2 bytes, so as g1
element size as well.
The problem is in the g2
initialization: unfortunately the offset is computed from APValue
methods here and is equal to 4 as in the OG, no CIR is involved.
Thus, the offset of the second element of g1
is computed as 4, and element size is 2 -> we got wrong indices for the GlobalViewAttr
from the very beginning: @g2 = #cir.global_view<@g1, [2 : i32]> : !cir.ptr<!u16i>
!
The g0
size is 2 because for unions we compute size as a size of the largest member and nothing else.
According to the comments we chose to track all union members and deffer padding computation to the lowering. But looks like that was not happened.
So the question is - what do you think, how to fix it properly?
I see the following ways:
- Make a separate type for unions. In this case we can still track all the members and have padding bytes as a separate field
- Add a notion about trailing padding into the struct type - as a parameter, e.g. index of the field.
- Try to add padding in the lowering like it was planned, e.g. in the type conversion. I'm not sure that's a good way though.
Any other thoughts, ideas?