From d7b0cb19093fbff3040a56891bd9630178956712 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 6 Sep 2026 00:41:00 +0200 Subject: [PATCH] Invent a syntax for `ldtoken`. Still not valid C# code, but at least it's now possible to see which member is referenced. --- .../Ugly/NoArrayInitializers.Expected.cs | 3 +- .../CSharp/ExpressionBuilder.cs | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoArrayInitializers.Expected.cs b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoArrayInitializers.Expected.cs index 0ed732c8a..ff0f1f8d8 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoArrayInitializers.Expected.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoArrayInitializers.Expected.cs @@ -1,4 +1,3 @@ -using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -19,7 +18,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly public int[] LiteralArray() { int[] array = new int[3]; - RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); + RuntimeHelpers.InitializeArray(array, __ldtoken(_003CPrivateImplementationDetails_003E._4636993D3E1DA4E9D6B8F87B79E8F7C6D018580D52661950EABC3845C5897A4D)); return array; } diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 600ca0b84..7a7c911d2 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -5153,6 +5153,35 @@ namespace ICSharpCode.Decompiler.CSharp .WithILInstruction(inst); } + protected internal override TranslatedExpression VisitLdMemberToken(LdMemberToken inst, TranslationContext context) + { + // fields: __ldtoken(DeclaringType.Member) + // methods: __ldtoken(DeclaringType.Member(parameter-types)) + var classType = astBuilder.ConvertType(inst.Member.DeclaringType); + var mre = new MemberReferenceExpression( + new TypeReferenceExpression(classType), + inst.Member.Name + ); + Expression memberExpr = mre.WithRR(new MemberResolveResult(null, inst.Member)); + if (inst.Member is IMethod method) + { + foreach (var t in method.TypeArguments) + { + mre.TypeArguments.Add(astBuilder.ConvertType(t)); + } + var inv = new InvocationExpression(memberExpr); + foreach (var param in method.Parameters) + { + inv.Arguments.Add(new TypeReferenceExpression(astBuilder.ConvertType(param.Type))); + } + memberExpr = inv; + } + var tokenType = inst.Member is IField ? KnownTypeCode.RuntimeFieldHandle : KnownTypeCode.RuntimeMethodHandle; + return new InvocationExpression(new IdentifierExpression("__ldtoken"), memberExpr) + .WithRR(new ResolveResult(compilation.FindType(tokenType))) + .WithILInstruction(inst); + } + protected internal override TranslatedExpression VisitCallIndirect(CallIndirect inst, TranslationContext context) { if (inst.IsInstance)