Skip to content

Assertion failure when a struct contains a struct which contains bit fields spanning [17, 25) or [33, 57) bits. #4646

@just-harry

Description

@just-harry

A quick test case:

In a C file, define BitFlags like:

typedef struct BitFlags {
  unsigned int _00 : 1;
  unsigned int _01 : 1;
  unsigned int _02 : 1;
  unsigned int _03 : 1;
  unsigned int _04 : 1;
  unsigned int _05 : 1;
  unsigned int _06 : 1;
  unsigned int _07 : 1;
  unsigned int _08 : 1;
  unsigned int _09 : 1;
  unsigned int _10 : 1;
  unsigned int _11 : 1;
  unsigned int _12 : 1;
  unsigned int _13 : 1;
  unsigned int _14 : 1;
  unsigned int _15 : 1;
  unsigned int _16 : 1;
} BitFlags;

or like:

typedef struct BitFlags {
  unsigned long long _00 : 1;
  unsigned long long _01 : 1;
  unsigned long long _02 : 1;
  unsigned long long _03 : 1;
  unsigned long long _04 : 1;
  unsigned long long _05 : 1;
  unsigned long long _06 : 1;
  unsigned long long _07 : 1;
  unsigned long long _08 : 1;
  unsigned long long _09 : 1;
  unsigned long long _10 : 1;
  unsigned long long _11 : 1;
  unsigned long long _12 : 1;
  unsigned long long _13 : 1;
  unsigned long long _14 : 1;
  unsigned long long _15 : 1;
  unsigned long long _16 : 1;
  unsigned long long _17 : 1;
  unsigned long long _18 : 1;
  unsigned long long _19 : 1;
  unsigned long long _20 : 1;
  unsigned long long _21 : 1;
  unsigned long long _22 : 1;
  unsigned long long _23 : 1;
  unsigned long long _24 : 1;
  unsigned long long _25 : 1;
  unsigned long long _26 : 1;
  unsigned long long _27 : 1;
  unsigned long long _28 : 1;
  unsigned long long _29 : 1;
  unsigned long long _30 : 1;
  unsigned long long _31 : 1;
  unsigned long long _32 : 1;
} BitFlags;

then define a struct which contains BitFlags, e.g.

typedef struct Foo {
  BitFlags flags;
} Foo;

The following failure will occur upon compilation:

Assertion failed: fieldSize <= af.size, file D:\a\ldc\ldc\ir\irtypeaggr.cpp, line 219

As far as I can tell, this is the cause:
Within the context of a call to IrTypeStruct::get for the BitFlags struct, in AggrTypeBuilder::addAggregate when the bitfield-grouping's group.sizeInBytes (and thus the actual field's size) is 3, 5, 6, or 7 the LLVM type for that bitfield-grouping ends up being i24, i40, i48, or i56.

Then, because sd->structsize is 4 or 8, AggrTypeBuilder::addTailPadding ends up adding some bytes of padding after the bitfield's non-power-of-two-sized integer.

But as i24 has same ABI alignment as i32, and i40, i48, i56 the same as i64, they have their own implicit padding from LLVM's data-layout, so the tail-padding added by LDC ends up making the BitFlags struct bigger than it should be.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions