Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions src/CppAst.Tests/TestStructs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,5 +310,46 @@ struct HelloWorld
}
);
}

[Test]
public void TestBitOffsets()
{
ParseAssert(@"
struct NormalFields
{
int a;
short b;
float c;
};

struct Bitfields
{
int a : 1;
int b : 2;
int c : 3;
};
",
compilation =>
{
Assert.False(compilation.HasErrors);

void Test(int classIndex, int fieldIndex, int expectedOffset, int expectedBitOffset)
{
var cppStruct = compilation.Classes[classIndex];
var field = cppStruct.Fields[fieldIndex];
Assert.AreEqual(expectedOffset, field.Offset);
Assert.AreEqual(expectedBitOffset, field.BitOffset);
}

Test(0, 0, 0, 0);
Test(0, 1, 4, 32);
Test(0, 2, 8, 64);

Test(1, 0, 0, 0);
Test(1, 1, 0, 1);
Test(1, 2, 0, 3);
}
);
}
}
}
11 changes: 8 additions & 3 deletions src/CppAst/CppField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,16 @@ public CppField(CppType type, string name)
/// Gets or sets the number of bits for this bit field. Only valid if <see cref="IsBitField"/> is <c>true</c>.
/// </summary>
public int BitFieldWidth { get; set; }


/// <summary>
/// Gets the offset of the field in bytes.
/// </summary>
public long Offset => BitOffset / 8;

/// <summary>
/// Gets or sets the offset of the field in bytes.
/// Gets or sets the offset of the field in bits.
/// </summary>
public long Offset { get; set; }
public long BitOffset { get; set; }

/// <inheritdoc />
public override string ToString()
Expand Down
13 changes: 7 additions & 6 deletions src/CppAst/CppModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -531,13 +531,14 @@ private CXChildVisitResult VisitMember(CXCursor cursor, CXCursor parent, void* d
// Might not be always correct (with alignment rules),
// but not sure how to recover the offset without recalculating the entire offsets
// BF: disregard the above comment? as we are now aligning using the anonymous struct's AlignOf...
var offset = 0L;
var bitOffset = 0L;
var cppClassContainer = containerContext.Container as CppClass;
if (cppClassContainer is object && cppClassContainer.Fields.Count > 0)
{
var lastField = cppClassContainer.Fields[cppClassContainer.Fields.Count - 1];
offset = (int)lastField.Offset + lastField.Type.SizeOf;
var offset = lastField.Offset + lastField.Type.SizeOf;
offset = Align(offset, cppClass.AlignOf);
bitOffset = offset * 8;

static long Align(long offset, long alignment)
{
Expand All @@ -551,7 +552,7 @@ static long Align(long offset, long alignment)
Visibility = containerContext.CurrentVisibility,
StorageQualifier = GetStorageQualifier(cursor),
IsAnonymous = true,
Offset = offset,
BitOffset = bitOffset,
};
ParseAttributes(cursor, cppField, true);
containerContext.DeclarationContainer.Fields.Add(cppField);
Expand Down Expand Up @@ -1154,7 +1155,7 @@ private CppField VisitFieldOrVariable(CppContainerContext containerContext, CXCu
cppField = previousField;
cppField.Name = fieldName;
cppField.Type = type;
cppField.Offset = cursor.OffsetOfField / 8;
cppField.BitOffset = cursor.OffsetOfField;
}
else
{
Expand All @@ -1164,7 +1165,7 @@ private CppField VisitFieldOrVariable(CppContainerContext containerContext, CXCu
StorageQualifier = GetStorageQualifier(cursor),
IsBitField = cursor.IsBitField,
BitFieldWidth = cursor.FieldDeclBitWidth,
Offset = cursor.OffsetOfField / 8,
BitOffset = cursor.OffsetOfField,
};
containerContext.DeclarationContainer.Fields.Add(cppField);
ParseAttributes(cursor, cppField, true);
Expand All @@ -1188,7 +1189,7 @@ private void AddAnonymousTypeWithField(CppContainerContext containerContext, CXC
Visibility = GetVisibility(cursor.CXXAccessSpecifier),
StorageQualifier = GetStorageQualifier(cursor),
IsAnonymous = true,
Offset = cursor.OffsetOfField / 8,
BitOffset = cursor.OffsetOfField,
};
containerContext.DeclarationContainer.Fields.Add(cppField);
ParseAttributes(cursor, cppField, true);
Expand Down
Loading