Skip to content

Commit 9963313

Browse files
committed
Generate boolean fields in generic structs as a custom struct.
1 parent 35d2507 commit 9963313

File tree

3 files changed

+81
-3
lines changed

3 files changed

+81
-3
lines changed

Il2CppInterop.Generator/Passes/Pass21GenerateValueTypeFields.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
using System;
2-
using System.Linq;
31
using Il2CppInterop.Generator.Contexts;
42
using Il2CppInterop.Generator.Extensions;
53
using Il2CppInterop.Generator.Utils;
@@ -67,7 +65,16 @@ public static void DoPass(RewriteGlobalContext context)
6765

6866
// Special case: bools in Il2Cpp are bytes
6967
if (newField.FieldType.FullName == "System.Boolean")
70-
newField.MarshalInfo = new MarshalInfo(NativeType.U1);
68+
{
69+
if (typeContext.ComputedTypeSpecifics == TypeRewriteContext.TypeSpecifics.GenericBlittableStruct)
70+
{
71+
newField.FieldType = assemblyContext.Imports.NativeBoolean;
72+
}
73+
else
74+
{
75+
newField.MarshalInfo = new MarshalInfo(NativeType.U1);
76+
}
77+
}
7178

7279
newType.Fields.Add(newField);
7380
}

Il2CppInterop.Generator/Utils/RuntimeAssemblyReferences.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ public RuntimeAssemblyReferences(ModuleDefinition module, RewriteGlobalContext g
8787
public TypeReference DelegateSupport { get; private set; }
8888
public TypeReference Il2CppException { get; private set; }
8989

90+
public TypeReference NativeBoolean { get; private set; }
91+
9092
private TypeReference ResolveType(string typeName)
9193
{
9294
return allTypes[typeName];
@@ -142,12 +144,16 @@ private void InitTypeRefs()
142144

143145
Il2CppException = new TypeReference("Il2CppInterop.Runtime", "Il2CppException", Module, assemblyRef);
144146

147+
NativeBoolean = new TypeReference("Il2CppInterop.Runtime", "NativeBoolean", Module, assemblyRef);
148+
NativeBoolean.IsValueType = true;
149+
145150
allTypes["Il2CppInterop.Runtime.InteropTypes.Il2CppObjectBase"] = Il2CppObjectBase;
146151
allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStringArray"] = Il2CppStringArray;
147152
allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppReferenceArray<T>"] = Il2CppReferenceArray;
148153
allTypes["Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStructArray<T>"] = Il2CppStructArray;
149154
allTypes["Il2CppInterop.Runtime.Il2CppException"] = Il2CppException;
150155
allTypes["Il2CppInterop.Runtime.IL2CPP"] = Il2Cpp;
156+
allTypes["Il2CppInterop.Runtime.NativeBoolean"] = NativeBoolean;
151157
}
152158

153159
private void InitMethodRefs()
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using System;
2+
using System.Runtime.CompilerServices;
3+
using System.Runtime.InteropServices;
4+
5+
namespace Il2CppInterop.Runtime
6+
{
7+
[StructLayout(LayoutKind.Sequential)]
8+
public readonly struct NativeBoolean : IComparable, IComparable<bool>, IEquatable<bool>, IComparable<NativeBoolean>, IEquatable<NativeBoolean>
9+
{
10+
private readonly byte Value;
11+
12+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
13+
public static implicit operator bool(NativeBoolean b)
14+
=> Unsafe.As<NativeBoolean, bool>(ref b);
15+
16+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
17+
public static implicit operator NativeBoolean(bool b)
18+
=> Unsafe.As<bool, NativeBoolean>(ref b);
19+
20+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
21+
public override int GetHashCode()
22+
=> Unsafe.As<byte, bool>(ref Unsafe.AsRef(in Value)).GetHashCode();
23+
24+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
25+
public override string ToString()
26+
=> Unsafe.As<byte, bool>(ref Unsafe.AsRef(in Value)).ToString();
27+
28+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
29+
public string ToString(IFormatProvider? provider)
30+
=> Unsafe.As<byte, bool>(ref Unsafe.AsRef(in Value)).ToString(provider);
31+
32+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
33+
public bool TryFormat(Span<char> destination, out int charsWritten)
34+
=> Unsafe.As<byte, bool>(ref Unsafe.AsRef(in Value)).TryFormat(destination, out charsWritten);
35+
36+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
37+
public override bool Equals(object? obj)
38+
=> obj switch
39+
{
40+
bool boolean => this == boolean,
41+
NativeBoolean nativeBool => this == nativeBool,
42+
_ => false
43+
};
44+
45+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
46+
public bool Equals(bool other)
47+
=> this == other;
48+
49+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
50+
public bool Equals(NativeBoolean other)
51+
=> this == other;
52+
53+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
54+
public int CompareTo(object? obj)
55+
=> Unsafe.As<byte, bool>(ref Unsafe.AsRef(in Value)).CompareTo(obj);
56+
57+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
58+
public int CompareTo(bool value)
59+
=> Unsafe.As<byte, bool>(ref Unsafe.AsRef(in Value)).CompareTo(value);
60+
61+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
62+
public int CompareTo(NativeBoolean value)
63+
=> CompareTo(Unsafe.As<NativeBoolean, bool>(ref value));
64+
}
65+
}

0 commit comments

Comments
 (0)