[cfe-dev] Alignment of bitfield structs

Bradley Smith bradley.smith at arm.com
Mon Apr 20 06:57:27 PDT 2015


Hi,

I'm trying to fix what appears to be incorrect codegen to do with alignment
of bitfield structs, but have hit a wall as to how to approach this. With
the following testcase:

extern struct T {
  int b0 : 8;
  int b1 : 24;
  int b2 : 1;
} g;

int foo() {
  return g.b1;
}

before optimization, Clang produces the following (for ARM, but I believe
this is just as valid elsewhere):

%struct.T = type { i40 }

@g = external global %struct.T

define arm_aapcscc i32 @foo() #0 {
entry:
  %bf.load = load i64, i64* bitcast (%struct.T* @g to i64*), align 4
   ...

This in itself seems correct, Clang has combined the bitfields into an i40
but also noted an alignment of 4 to preserve the ABI alignment on the
bitfield. The record layout being as below, which again, seems correct.

Layout: <CGRecordLayout
  LLVMType:%struct.T = type { i40 }
  IsZeroInitializable:1
  BitFields:[
    <CGBitFieldInfo Offset:0 Size:8 IsSigned:1 StorageSize:64
StorageAlignment:4>
    <CGBitFieldInfo Offset:8 Size:24 IsSigned:1 StorageSize:64
StorageAlignment:4>
    <CGBitFieldInfo Offset:32 Size:1 IsSigned:1 StorageSize:64
StorageAlignment:4>
]>

However, when this IR goes down to LLVM there is no context of the bitfields
left so LLVM just sees an i64 load from an i40. InstCombine sees this and
blindly (but correctly I believe, based on the information it has) converts
this load to the ABI alignment of i64, which is now incorrect.

>From what I can tell there are only 2 ways to fix this, either have clang
not combine the bitfield into an i40, or somehow pass the bitfield layout
down to LLVM. Neither of these seem particularly easy to do, what are others
thoughts on this, have I missed something? Thanks.

Regards,
Bradley Smith






More information about the cfe-dev mailing list