Browse Source

bug: Repaired broken alignment padding generation for structs with embedded arrays of structs. Added a test for this case.

pull/1612/head
Joe Hull 4 years ago committed by João Matos
parent
commit
d135ffdb86
  1. 13
      src/Generator/Extensions/LayoutFieldExtensions.cs
  2. 2
      src/Generator/Generators/CSharp/CSharpSources.cs
  3. 1
      tests/CSharp/CSharp.Tests.cs
  4. 6
      tests/CSharp/CSharp.cpp
  5. 11
      tests/CSharp/CSharp.h

13
src/Generator/Extensions/LayoutFieldExtensions.cs

@ -12,6 +12,19 @@ namespace CppSharp.Extensions @@ -12,6 +12,19 @@ namespace CppSharp.Extensions
var prevFieldSize = previousField.QualifiedType.Type.Desugar().GetWidth(targetInfo) / 8;
var unalignedOffset = previousField.Offset + prevFieldSize;
var alignment = type.GetAlignment(targetInfo) / 8;
if (type is ArrayType arrayType && arrayType.Type.Desugar().IsClass())
{
// We have an array of structs. When we generate this field, we'll transform it into an fixed
// array of bytes to which the elements in the embedded struct array can be bound (via their
// accessors). At that point, the .Net subsystem will have no information in the generated
// class on which to base its own alignment calculation. Consequently, we must generate
// padding. Set alignment to indicate one-byte alignment which is consistent with the "fixed
// byte fieldName[]" we'll eventually generate so that the offset we return here mimics what
// will be the case once the struct[] -> byte[] transformation occurs.
alignment = 1;
}
var alignedOffset = (unalignedOffset + (alignment - 1)) & -alignment;
return (int)alignedOffset;
}

2
src/Generator/Generators/CSharp/CSharpSources.cs

@ -837,7 +837,7 @@ namespace CppSharp.Generators.CSharp @@ -837,7 +837,7 @@ namespace CppSharp.Generators.CSharp
if (sequentialLayout && i > 0)
{
var padding = field.Offset - field.CalculateOffset(fields[i - 1], Context.TargetInfo);
if (padding > 1)
WriteLine($"internal fixed byte {field.Name}Padding[{padding}];");
else if (padding > 0)

1
tests/CSharp/CSharp.Tests.cs

@ -752,6 +752,7 @@ public unsafe class CSharpTests @@ -752,6 +752,7 @@ public unsafe class CSharpTests
(typeof(ClassCustomTypeAlignment), CSharp.CSharp.ClassCustomTypeAlignmentOffsets),
(typeof(ClassCustomObjectAlignment), CSharp.CSharp.ClassCustomObjectAlignmentOffsets),
(typeof(ClassMicrosoftObjectAlignment), CSharp.CSharp.ClassMicrosoftObjectAlignmentOffsets),
(typeof(StructWithEmbeddedArrayOfStructObjectAlignment), CSharp.CSharp.StructWithEmbeddedArrayOfStructObjectAlignmentOffsets),
})
{
var internalType = type.GetNestedType("__Internal");

6
tests/CSharp/CSharp.cpp

@ -1888,3 +1888,9 @@ const unsigned ClassMicrosoftObjectAlignmentOffsets[4] @@ -1888,3 +1888,9 @@ const unsigned ClassMicrosoftObjectAlignmentOffsets[4]
offsetof(ClassMicrosoftObjectAlignment, i16),
offsetof(ClassMicrosoftObjectAlignment, boolean),
};
const unsigned StructWithEmbeddedArrayOfStructObjectAlignmentOffsets[2]
{
offsetof(StructWithEmbeddedArrayOfStructObjectAlignment, boolean),
offsetof(StructWithEmbeddedArrayOfStructObjectAlignment, embedded_struct),
};

11
tests/CSharp/CSharp.h

@ -1502,6 +1502,16 @@ struct DLL_API ClassMicrosoftObjectAlignment : ClassMicrosoftObjectAlignmentBase @@ -1502,6 +1502,16 @@ struct DLL_API ClassMicrosoftObjectAlignment : ClassMicrosoftObjectAlignmentBase
bool boolean;
};
struct DLL_API EmbeddedStruct
{
int64_t i64;
};
struct DLL_API StructWithEmbeddedArrayOfStructObjectAlignment
{
bool boolean;
EmbeddedStruct embedded_struct[2];
};
class DLL_API ProtectedConstructorDestructor
{
protected:
@ -1512,6 +1522,7 @@ protected: @@ -1512,6 +1522,7 @@ protected:
DLL_API extern const unsigned ClassCustomTypeAlignmentOffsets[5];
DLL_API extern const unsigned ClassCustomObjectAlignmentOffsets[2];
DLL_API extern const unsigned ClassMicrosoftObjectAlignmentOffsets[4];
DLL_API extern const unsigned StructWithEmbeddedArrayOfStructObjectAlignmentOffsets[2];
DLL_API const char* TestCSharpString(const char* in, CS_OUT const char** out);
DLL_API const wchar_t* TestCSharpStringWide(const wchar_t* in, CS_OUT const wchar_t** out);

Loading…
Cancel
Save