Skip to content

Commit d135ffd

Browse files
jpnoirtritao
authored andcommitted
bug: Repaired broken alignment padding generation for structs with embedded arrays of structs. Added a test for this case.
1 parent af275ed commit d135ffd

File tree

5 files changed

+32
-1
lines changed

5 files changed

+32
-1
lines changed

src/Generator/Extensions/LayoutFieldExtensions.cs

+13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,19 @@ internal static int CalculateOffset(this LayoutField field, LayoutField previous
1212
var prevFieldSize = previousField.QualifiedType.Type.Desugar().GetWidth(targetInfo) / 8;
1313
var unalignedOffset = previousField.Offset + prevFieldSize;
1414
var alignment = type.GetAlignment(targetInfo) / 8;
15+
16+
if (type is ArrayType arrayType && arrayType.Type.Desugar().IsClass())
17+
{
18+
// We have an array of structs. When we generate this field, we'll transform it into an fixed
19+
// array of bytes to which the elements in the embedded struct array can be bound (via their
20+
// accessors). At that point, the .Net subsystem will have no information in the generated
21+
// class on which to base its own alignment calculation. Consequently, we must generate
22+
// padding. Set alignment to indicate one-byte alignment which is consistent with the "fixed
23+
// byte fieldName[]" we'll eventually generate so that the offset we return here mimics what
24+
// will be the case once the struct[] -> byte[] transformation occurs.
25+
alignment = 1;
26+
}
27+
1528
var alignedOffset = (unalignedOffset + (alignment - 1)) & -alignment;
1629
return (int)alignedOffset;
1730
}

src/Generator/Generators/CSharp/CSharpSources.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ private void GenerateClassInternalsFields(Class @class, bool sequentialLayout)
837837
if (sequentialLayout && i > 0)
838838
{
839839
var padding = field.Offset - field.CalculateOffset(fields[i - 1], Context.TargetInfo);
840-
840+
841841
if (padding > 1)
842842
WriteLine($"internal fixed byte {field.Name}Padding[{padding}];");
843843
else if (padding > 0)

tests/CSharp/CSharp.Tests.cs

+1
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,7 @@ public void TestAlignment()
752752
(typeof(ClassCustomTypeAlignment), CSharp.CSharp.ClassCustomTypeAlignmentOffsets),
753753
(typeof(ClassCustomObjectAlignment), CSharp.CSharp.ClassCustomObjectAlignmentOffsets),
754754
(typeof(ClassMicrosoftObjectAlignment), CSharp.CSharp.ClassMicrosoftObjectAlignmentOffsets),
755+
(typeof(StructWithEmbeddedArrayOfStructObjectAlignment), CSharp.CSharp.StructWithEmbeddedArrayOfStructObjectAlignmentOffsets),
755756
})
756757
{
757758
var internalType = type.GetNestedType("__Internal");

tests/CSharp/CSharp.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -1888,3 +1888,9 @@ const unsigned ClassMicrosoftObjectAlignmentOffsets[4]
18881888
offsetof(ClassMicrosoftObjectAlignment, i16),
18891889
offsetof(ClassMicrosoftObjectAlignment, boolean),
18901890
};
1891+
1892+
const unsigned StructWithEmbeddedArrayOfStructObjectAlignmentOffsets[2]
1893+
{
1894+
offsetof(StructWithEmbeddedArrayOfStructObjectAlignment, boolean),
1895+
offsetof(StructWithEmbeddedArrayOfStructObjectAlignment, embedded_struct),
1896+
};

tests/CSharp/CSharp.h

+11
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,16 @@ struct DLL_API ClassMicrosoftObjectAlignment : ClassMicrosoftObjectAlignmentBase
15021502
bool boolean;
15031503
};
15041504

1505+
struct DLL_API EmbeddedStruct
1506+
{
1507+
int64_t i64;
1508+
};
1509+
struct DLL_API StructWithEmbeddedArrayOfStructObjectAlignment
1510+
{
1511+
bool boolean;
1512+
EmbeddedStruct embedded_struct[2];
1513+
};
1514+
15051515
class DLL_API ProtectedConstructorDestructor
15061516
{
15071517
protected:
@@ -1512,6 +1522,7 @@ class DLL_API ProtectedConstructorDestructor
15121522
DLL_API extern const unsigned ClassCustomTypeAlignmentOffsets[5];
15131523
DLL_API extern const unsigned ClassCustomObjectAlignmentOffsets[2];
15141524
DLL_API extern const unsigned ClassMicrosoftObjectAlignmentOffsets[4];
1525+
DLL_API extern const unsigned StructWithEmbeddedArrayOfStructObjectAlignmentOffsets[2];
15151526

15161527
DLL_API const char* TestCSharpString(const char* in, CS_OUT const char** out);
15171528
DLL_API const wchar_t* TestCSharpStringWide(const wchar_t* in, CS_OUT const wchar_t** out);

0 commit comments

Comments
 (0)