-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Closed
Description
The code:
public static OneParameter<ulong, Item> GenerateILGetRankIL()
{
DynamicMethod dynamicMethod = new(
"getRank",
typeof(ulong),
new[] { typeof(Item) }
);
ILGenerator il = dynamicMethod.GetILGenerator();
Label[] labels = new Label[8];
for (int i = 0; i < labels.Length; i++) labels[i] = il.DefineLabel();
// ulong num = 0uL;
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Conv_I8);
il.Emit(OpCodes.Stloc_0);
// if (item == null)
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Brtrue_S, labels[0]);
// return num;
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);
// ulong num2 = 9223372036854775808uL;
il.MarkLabel(labels[0]);
il.Emit(OpCodes.Ldc_I8, -9223372036854775808);
il.Emit(OpCodes.Stloc_1);
// int num3 = 64;
il.Emit(OpCodes.Ldc_I4_S, 64);
il.Emit(OpCodes.Stloc_2);
// if (item.IsUnique)
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Callvirt, Item__GetUnique, null);
il.Emit(OpCodes.Brfalse_S, labels[1]);
// num |= num2;
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Or);
il.Emit(OpCodes.Stloc_0);
// num2 >>= 1;
il.MarkLabel(labels[1]);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Shr_Un);
il.Emit(OpCodes.Stloc_1);
// num3--;
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Sub);
il.Emit(OpCodes.Stloc_2);
// num |= num2 >> (int)(6 - item.Rarity);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldc_I4_6);
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Callvirt, Item__GetRarity, null);
il.Emit(OpCodes.Sub);
il.Emit(OpCodes.Ldc_I4_S, 63);
il.Emit(OpCodes.And);
il.Emit(OpCodes.Shr_Un);
il.Emit(OpCodes.Or);
il.Emit(OpCodes.Stloc_0);
// num2 >>= 6;
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldc_I4_6);
il.Emit(OpCodes.Shr_Un);
il.Emit(OpCodes.Stloc_1);
// num3 -= 6;
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Ldc_I4_6);
il.Emit(OpCodes.Sub);
il.Emit(OpCodes.Stloc_2);
// num |= num2 >> 5 - item.Tier.Id;
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldc_I4_5);
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Callvirt, Item__GetTier, null);
il.Emit(OpCodes.Stloc_3);
il.Emit(OpCodes.Ldloca_S, 3);
il.EmitCall(OpCodes.Callvirt, TierId__GetId, null);
il.Emit(OpCodes.Sub);
il.Emit(OpCodes.Ldc_I4_S, 63);
il.Emit(OpCodes.And);
il.Emit(OpCodes.Shr_Un);
il.Emit(OpCodes.Or);
il.Emit(OpCodes.Stloc_0);
// num2 >>= 5;
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldc_I4_5);
il.Emit(OpCodes.Shr_Un);
il.Emit(OpCodes.Stloc_1);
// num3 -= 5;
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Ldc_I4_5);
il.Emit(OpCodes.Sub);
il.Emit(OpCodes.Stloc_2);
// num |= num2 >> (int)item.Type;
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Callvirt, Item__GetType, null);
il.Emit(OpCodes.Ldc_I4_S, 63);
il.Emit(OpCodes.And);
il.Emit(OpCodes.Shr_Un);
il.Emit(OpCodes.Or);
// num2 >>= 11;
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldc_I4_S, 11);
il.Emit(OpCodes.Shr_Un);
il.Emit(OpCodes.Stloc_1);
// num3 -= 11;
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Ldc_I4_S, 11);
il.Emit(OpCodes.Sub);
il.Emit(OpCodes.Stloc_2);
// num3 -= 26;
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Ldc_I4_S, 26);
il.Emit(OpCodes.Sub);
il.Emit(OpCodes.Stloc_2);
// string subtypeCode = item.SubtypeCode;
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Callvirt, Item__GetSubtypeCode, null);
il.Emit(OpCodes.Stloc_S, 4);
// (no C# code)
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Stloc_S, 5);
// foreach (int num4 in subtypeCode)
// {
// int num5 = num4;
// if (num5 < 65)
// {
// continue;
// }
// if (num4 > 65 + num3)
// {
// if (num5 > 96 && num5 < 123)
// {
// num ^= num2 >> num4 - 97 + num3;
// }
// }
// else
// {
// num ^= num2 >> num4 - 65;
// }
// }
il.Emit(OpCodes.Br_S, labels[7]);
MelonLogger.Msg($"MarkLabel 2 {il.ILOffset}");
il.MarkLabel(labels[2]);
MelonLogger.Msg($"MarkLabel 2 {il.ILOffset}");
il.Emit(OpCodes.Ldloc_S, 4);
il.Emit(OpCodes.Ldloc_S, 5);
il.EmitCall(OpCodes.Callvirt,String__GetChars, null);
il.Emit(OpCodes.Stloc_S, 6);
// int num5 = num4;
il.Emit(OpCodes.Ldloc_S, 6);
il.Emit(OpCodes.Stloc_S, 7);
// if (num5 < 65)
il.Emit(OpCodes.Ldloc_S, 7);
il.Emit(OpCodes.Ldc_I4_S, 65);
il.Emit(OpCodes.Bge_S, labels[4]);
// if (num5 > 96 && num5 < 123)
il.Emit(OpCodes.Br_S, labels[6]);
// loop start (head: IL_00b0)
il.MarkLabel(labels[3]);
il.Emit(OpCodes.Ldloc_S, 7);
il.Emit(OpCodes.Ldc_I4_S, 96);
il.Emit(OpCodes.Ble_S, labels[6]);
il.Emit(OpCodes.Ldloc_S, 7);
il.Emit(OpCodes.Ldc_I4_S, 123);
MelonLogger.Msg($"Blt_S {il.ILOffset}");
il.Emit(OpCodes.Blt_S, labels[5]);
MelonLogger.Msg($"Blt_S {il.ILOffset}");
// if (num4 > 65 + num3)
il.Emit(OpCodes.Br_S, labels[6]);
il.MarkLabel(labels[4]);
il.Emit(OpCodes.Ldloc_S, 6);
il.Emit(OpCodes.Ldc_I4_S, 65);
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Bgt_S, labels[3]);
// end loop
// num ^= num2 >> num4 - 65;
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldloc_S, 6);
il.Emit(OpCodes.Ldc_I4_S, 65);
il.Emit(OpCodes.Sub);
il.Emit(OpCodes.Ldc_I4_S, 63);
il.Emit(OpCodes.And);
il.Emit(OpCodes.Shr_Un);
il.Emit(OpCodes.Xor);
il.Emit(OpCodes.Stloc_0);
// num ^= num2 >> num4 - 97 + num3;
il.Emit(OpCodes.Br_S, labels[6]);
MelonLogger.Msg($"MarkLabel 5 {il.ILOffset}");
il.MarkLabel(labels[5]);
MelonLogger.Msg($"MarkLabel 5 {il.ILOffset}");
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldloc_S, 6);
il.Emit(OpCodes.Ldc_I4_S, 97);
il.Emit(OpCodes.Sub);
il.Emit(OpCodes.Ldloc_2);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Ldc_I4_S, 63);
il.Emit(OpCodes.And);
il.Emit(OpCodes.Shr_Un);
il.Emit(OpCodes.Xor);
il.Emit(OpCodes.Stloc_0);
// (no C# code)
il.MarkLabel(labels[6]);
il.Emit(OpCodes.Ldloc_S, 5);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Stloc_S, 5);
// return num;
il.MarkLabel(labels[7]);
il.Emit(OpCodes.Ldloc_S, 5);
il.Emit(OpCodes.Ldloc_S, 4);
il.EmitCall(OpCodes.Callvirt, String__GetLength, null);
MelonLogger.Msg($"Blt_S {il.ILOffset}");
il.Emit(OpCodes.Blt_S, labels[2]);
MelonLogger.Msg($"Blt_S {il.ILOffset}");
// end loop
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);
OneParameter<ulong, Item> del =
(OneParameter<ulong, Item>)dynamicMethod.CreateDelegate(typeof(OneParameter<ulong, Item>));
return del;
// OneParameter<ulong, Item> getRankIL =
// (OneParameter<ulong, Item>)dynamicMethod.CreateDelegate(typeof(OneParameter<ulong, Item>));
// return del;
}
The console log:
[14:05:20.761] [MoreQOD] MarkLabel 2 169
[14:05:20.763] [MoreQOD] MarkLabel 2 169
[14:05:20.764] [MoreQOD] Blt_S 235
[14:05:20.764] [MoreQOD] Blt_S 237
[14:05:20.765] [MoreQOD] MarkLabel 5 277
[14:05:20.766] [MoreQOD] MarkLabel 5 277
[14:05:20.767] [MoreQOD] Blt_S 328
[14:05:20.768] [MoreQOD] Blt_S 330
[14:05:20.770] [MoreQOD] [ERROR] System.InvalidProgramException: Invalid IL code in (wrapper dynamic-method) object:getRank (Death.Items.Item): IL_0148: blt.s IL_01a9
at (wrapper managed-to-native) System.Delegate.CreateDelegate_internal(System.Type,object,System.Reflection.MethodInfo,bool)
at System.Delegate.CreateDelegate (System.Type type, System.Object firstArgument, System.Reflection.MethodInfo method, System.Boolean throwOnBindFailure, System.Boolean allowClosed) [0x002f0] in <9aad1b3a47484d63ba2b3985692d80e9>:0
at System.Delegate.CreateDelegate (System.Type type, System.Object firstArgument, System.Reflection.MethodInfo method) [0x00000] in <9aad1b3a47484d63ba2b3985692d80e9>:0
at System.Reflection.Emit.DynamicMethod.CreateDelegate (System.Type delegateType) [0x00029] in <9aad1b3a47484d63ba2b3985692d80e9>:0
at MQOD.Sort.GenerateILGetRankIL () [0x00957] in <1efc024047cc4f579f5b6f749046551d>:0
at MQOD.SortShop.sortShop () [0x00028] in <1efc024047cc4f579f5b6f749046551d>:0
at MQOD.MQOD.OnLateUpdate () [0x0037a] in <1efc024047cc4f579f5b6f749046551d>:0
at MelonLoader.MelonEvent+<>c.<Invoke>b__1_0 (MelonLoader.LemonAction x) [0x00000] in <6425afb6ac6a429aaf770255d2f7de57>:0
at MelonLoader.MelonEventBase`1[T].Invoke (System.Action`1[T] delegateInvoker) [0x00018] in <6425afb6ac6a429aaf770255d2f7de57>:0
I have tracked the issue down to that last call of Blt_S, because we can see from the error that the offending code happens at offset IL_0148 which corresponds to 328 in decimal in the log:
...
il.Emit(OpCodes.Blt_S, labels[2]);
...
The generated IL uses the address IL_01a9 for labels[2] but from my logging I can see that MarkLabel(labels[2]) happens at ILOffset '169' decimal or 'A9' in hex. So IL_01a9 is off by exactly 100 in hex or 256 in decimal. So the generated IL should be "IL_0148: blt.s IL_00a9" and not "IL_0148: blt.s IL_01a9", right?
Metadata
Metadata
Assignees
Labels
No labels