Skip to content

Instantly share code, notes, and snippets.

@kekyo
Last active June 2, 2024 09:13
Show Gist options
  • Save kekyo/bc8e411b846c98d2f2ae7b839ef77fea to your computer and use it in GitHub Desktop.
Save kekyo/bc8e411b846c98d2f2ae7b839ef77fea to your computer and use it in GitHub Desktop.
Extract CIL opcodes and makes relation chibias-cil opcode naming both Reflection.Emit and Cecil.
using System;
using System.Linq;
namespace ConsoleApp1;
class Program
{
static void GenerateReflectionEmit()
{
var emitOpCodes =
typeof(System.Reflection.Emit.OpCodes).GetFields().
Where(field => field is
{
IsPublic: true, IsStatic: true, IsInitOnly: true,
FieldType.FullName: "System.Reflection.Emit.OpCode"
}).
Select(field => (fieldName: field.Name, opCode: (System.Reflection.Emit.OpCode)field.GetValue(null)!)).
Where(entry => entry.opCode.OpCodeType != System.Reflection.Emit.OpCodeType.Nternal).
OrderBy(entry => entry.opCode.Value).
Select(entry => (entry.fieldName, name: entry.opCode.Name!.Replace('_', '.').TrimEnd('.').ToLowerInvariant())).
ToArray();
Console.WriteLine("namespace chibicc.toolchain.Internal;");
Console.WriteLine();
Console.WriteLine("internal static class ReflectionEmitDefinition");
Console.WriteLine("{");
Console.WriteLine(" public static System.Collections.Generic.Dictionary<string, System.Reflection.Emit.OpCode> GetOpCodes() =>");
Console.WriteLine(" new(System.StringComparer.OrdinalIgnoreCase)");
Console.WriteLine(" {");
foreach (var entry in emitOpCodes)
{
Console.WriteLine(
$" {{ \"{entry.name}\", System.Reflection.Emit.OpCodes.{entry.fieldName} }},");
}
Console.WriteLine(" };");
Console.WriteLine("}");
}
static void GenerateCecil()
{
var emitOpCodeBytes =
typeof(System.Reflection.Emit.OpCodes).GetFields().
Where(field => field is
{
IsPublic: true, IsStatic: true, IsInitOnly: true,
FieldType.FullName: "System.Reflection.Emit.OpCode"
}).
Select(field => (fieldName: field.Name, opCode: (System.Reflection.Emit.OpCode)field.GetValue(null)!)).
Where(entry => entry.opCode.OpCodeType != System.Reflection.Emit.OpCodeType.Nternal).
ToDictionary(
entry => entry.opCode.Value,
entry => (entry.fieldName, name: entry.opCode.Name!.Replace('_', '.').TrimEnd('.').ToLowerInvariant()));
var cecilOpCodes = typeof(Mono.Cecil.Cil.OpCodes).GetFields().
Where(field =>
field.IsPublic && field.IsStatic && field.IsInitOnly &&
field.FieldType.FullName == "Mono.Cecil.Cil.OpCode").
Select(field =>
{
var opCode = (Mono.Cecil.Cil.OpCode)field.GetValue(null)!;
if (emitOpCodeBytes.TryGetValue(opCode.Value, out var entry))
{
return (fieldName: field.Name, opCode, name: entry.name);
}
else
{
return (null!, default, null!);
}
}).
Where(entry => entry.name != null && entry.opCode.OpCodeType != Mono.Cecil.Cil.OpCodeType.Nternal).
OrderBy(entry => entry.opCode.Value).
Select(entry => (entry.fieldName, name: entry.name)).
ToArray();
Console.WriteLine("namespace chibild.Internal;");
Console.WriteLine();
Console.WriteLine("internal static class CecilDefinition");
Console.WriteLine("{");
Console.WriteLine(" public static System.Collections.Generic.Dictionary<string, Mono.Cecil.Cil.OpCode> GetOpCodes() =>");
Console.WriteLine(" new(System.StringComparer.OrdinalIgnoreCase)");
Console.WriteLine(" {");
foreach (var entry in cecilOpCodes)
{
Console.WriteLine(
$" {{ \"{entry.name}\", Mono.Cecil.Cil.OpCodes.{entry.fieldName} }},");
}
Console.WriteLine(" };");
Console.WriteLine("}");
}
static void Main(string[] args)
{
GenerateReflectionEmit();
GenerateCecil();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment