Wide arch `CPtr<T>` conversion doesn't work
- Dominant language
- C#
- Stars
- 451
- Forks
- 49
- Avg merge
- 13h 59m
- Merged PRs (30d)
- 6
Description
Imagine this C program, compiled into the **wide** architecture:
```c
typedef struct Greeting {
char* message;
} Greeting;
int len(Greeting* greeting) {
int count = 0;
char* p = greeting->message;
while (p[count] != '\0') {
++count;
}
return count;
}
```
It gets compiled into this:
```cil
.class public abstract sealed auto ansi
CesiumLib.Global
extends [mscorlib]System.Object
{
.method public static int32
len(
valuetype CesiumLib.Greeting* greeting
) cil managed
{
.maxstack 3
.locals (
[0] int32 num,
[1] unsigned int8* message
)
// [14 5 - 14 16]
IL_0000: ldc.i4.0
IL_0001: stloc.0 // num
// [15 5 - 15 46]
IL_0002: ldarg.0 // greeting
IL_0003: ldfld valuetype [Cesium.Runtime]Cesium.Runtime.CPtr`1 CesiumLib.Greeting::message
IL_0008: stloc.1 // message
// start of loop, entry point: IL_0009
IL_0009: nop
// [16 5 - 16 41]
IL_000a: ldloc.1 // message
IL_000b: ldc.i4.1
IL_000c: ldloc.0 // num
IL_000d: mul
IL_000e: add
IL_000f: ldind.i1
IL_0010: conv.i4
IL_0011: ldc.i4.s 0 // 0x00
IL_0013: ceq
IL_0015: ldc.i4.0
IL_0016: ceq
IL_0018: brfalse IL_0026
// [17 7 - 17 12]
IL_001d: ldloc.0 // num
IL_001e: ldc.i4.1
IL_001f: add
IL_0020: stloc.0 // num
IL_0021: br IL_0009
// end of loop
IL_0026: nop
// [18 5 - 18 16]
IL_0027: ldloc.0 // num
IL_0028: ret
} // end of method Global::len
} // end of class CesiumLib.Global
```
Or, in terms of C#, something like this:
```csharp
[StructLayout(LayoutKind.Explicit, Pack = 8)]
public struct Greeting
{
[FieldOffset(0)]
public CPtr message;
}
class Global
{
public static unsafe int len(Greeting* greeting)
{
int num = 0;
byte* message = (byte*) greeting->message;
while (message[1 * num] != (byte) 0)
++num;
return num;
}
}
```
The line `(byte*) greeting->message;` is problematic: there's actually no cast operator emitted, because it doesn't exists.
`Cesium.CodeGen.Ir.Types.InteropType.EmitConversion` supports conversion **into** an interop type (`CPtr` is an "interop type" by our definition) — while there's no code in the compiler to convert stuff _back_ from an interop type. We should support this eventually.
See `TODO[#973]` for the relevant test (discovered by #972).
Contributor guide
Assessment
This issue has not been assessed yet.