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
var prevFieldSize = previousField.QualifiedType.Type.Desugar().GetWidth(targetInfo) / 8; var prevFieldSize = previousField.QualifiedType.Type.Desugar().GetWidth(targetInfo) / 8;
var unalignedOffset = previousField.Offset + prevFieldSize; var unalignedOffset = previousField.Offset + prevFieldSize;
var alignment = type.GetAlignment(targetInfo) / 8; 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; var alignedOffset = (unalignedOffset + (alignment - 1)) & -alignment;
return (int)alignedOffset; return (int)alignedOffset;
} }

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

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

1
tests/CSharp/CSharp.Tests.cs

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

6
tests/CSharp/CSharp.cpp

@ -1888,3 +1888,9 @@ const unsigned ClassMicrosoftObjectAlignmentOffsets[4]
offsetof(ClassMicrosoftObjectAlignment, i16), offsetof(ClassMicrosoftObjectAlignment, i16),
offsetof(ClassMicrosoftObjectAlignment, boolean), 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
bool boolean; bool boolean;
}; };
struct DLL_API EmbeddedStruct
{
int64_t i64;
};
struct DLL_API StructWithEmbeddedArrayOfStructObjectAlignment
{
bool boolean;
EmbeddedStruct embedded_struct[2];
};
class DLL_API ProtectedConstructorDestructor class DLL_API ProtectedConstructorDestructor
{ {
protected: protected:
@ -1512,6 +1522,7 @@ protected:
DLL_API extern const unsigned ClassCustomTypeAlignmentOffsets[5]; DLL_API extern const unsigned ClassCustomTypeAlignmentOffsets[5];
DLL_API extern const unsigned ClassCustomObjectAlignmentOffsets[2]; DLL_API extern const unsigned ClassCustomObjectAlignmentOffsets[2];
DLL_API extern const unsigned ClassMicrosoftObjectAlignmentOffsets[4]; 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 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); DLL_API const wchar_t* TestCSharpStringWide(const wchar_t* in, CS_OUT const wchar_t** out);

Loading…
Cancel
Save