Cesium icon indicating copy to clipboard operation
Cesium copied to clipboard

Struct layout calculation

Open ForNeVeR opened this issue 2 years ago • 2 comments
trafficstars

To statically determine struct layout (for 32b, 64b and wide architecture sets), we'll need to calculate struct layout.

I am planning to make structures have Pack = 4 / 8 and LayoutKind.Explicit for these architectures.

See the documentation on pack.

Look for number 355 in the code when implementing this.

ForNeVeR avatar Dec 04 '22 21:12 ForNeVeR

Hey, This looks interesting, and I want to contribute to this. Can you give me some more details regarding this issue so that I can start working on it asap?

starvader13 avatar Dec 05 '22 04:12 starvader13

Sure thing. This is a good task for new contributors, because it doesn't require deep knowledge of the existing code.

Here's a more detailed explanation.

We support several CPU architectures (or "architecture sets" as we call them right now): 64-bit, 32-bit, and dynamic. (Let's not talk about wide right now since it is not yet implemented, and dynamic is out of scope of this task anyway.)

Each bitness requires separate layout of nearly every C structure, because on different architectures, the pointer size are different.

.NET documentation outlines some basic layout rules, but I'm not sure if this is the full rule set, and even if it is, the wording is very suboptimal, so if you have some domain knowledge in C structure layout, that would be ideal (if not, then you could still try to read the documentation and test on some examples, that would be fine as well).

I want Cesium to support different struct layouts for different architectures, which mean:

  1. Set Pack = 4 or Pack = 8 in StructType.cs based on the target architecture set (already done).
  2. Set an equivalent of [StructLayout(LayoutKind.Explicit)] for all Cesium-generated structure types (see StructType.cs:33)[^1].
  3. For every struct field, calculate the field layout and generate an equivalent of [FieldOffset(x)] in the byte code for said field[^1].
  4. Taking into account these field layots, Cesium should properly calculate static type size as well (see StructType.cs:80–84) – type size is used to allocate arrays of structures.
  5. Ideally, this should be covered by the unit tests:
    • check type sizes for Cesium structs and equivalent C# structs[^2],
    • check field offsets for different struct fields and compare them[^3].

I don't require a contributor to implement everything at once; you can start in small steps and ask for help if/when you feel you need that.

[^1]: I don't know if an setting StructLayout and FieldOffset is straightforward in Mono.Cecil: certain C# attributes may be directly mapped to type metadata flags. This is left for the implementor to research. [^2]: I've just found that that sizeof(T) works in C#, so that should be easy. [^3]: To get a field offset in C#, you may compare a struct pointer with a field pointer, something like this: ```csharp unsafe struct Foo { public int* Padding; public long Field; }

// …
var x = new Foo();
var structPtr = (byte*)&x;
var fieldPtr = (byte*)&x.Field;
var offset = fieldPtr - structPtr;
```

ForNeVeR avatar Dec 05 '22 21:12 ForNeVeR