Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stfld got a wrong operand in a generic type. #954

Open
Gatongone opened this issue Jul 10, 2024 Discussed in #935 · 0 comments
Open

stfld got a wrong operand in a generic type. #954

Gatongone opened this issue Jul 10, 2024 Discussed in #935 · 0 comments

Comments

@Gatongone
Copy link

Discussed in #935

Originally posted by Gatongone March 10, 2024

Background

When I tried to append a stfld to a method body from a TypeDefinition with generic arguments, it got a different instruction with the expected code. Is there any wrong?

See following

stfld !0 Foo`1::list

and

stfld !0 class Foo`1<!0>::list

Sample

using Mono.Cecil;
using Mono.Cecil.Cil;

public class SnippetRunner
{
    public static void Run(string path)
    {
        var mp = new ModuleParameters
        {
            Architecture = TargetArchitecture.AMD64,
            Kind = ModuleKind.Dll,
        };

        using (var assembly = AssemblyDefinition.CreateAssembly(new AssemblyNameDefinition("Foo", Version.Parse("1.0.0.0")), Path.GetFileName(path), mp))
        {
            //Class : Foo
            var cls_Foo_0 = new TypeDefinition("", "Foo`1", TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.NotPublic, assembly.MainModule.TypeSystem.Object);
            assembly.MainModule.Types.Add(cls_Foo_0);
            var gp_T_1 = new Mono.Cecil.GenericParameter("T", cls_Foo_0);
            cls_Foo_0.GenericParameters.Add(gp_T_1);

            //Field: list
            var fld_list_2 = new FieldDefinition("list", FieldAttributes.Private, gp_T_1);
            cls_Foo_0.Fields.Add(fld_list_2);

            //Method : Bar
            var md_Bar_3 = new MethodDefinition("Bar", MethodAttributes.Private | MethodAttributes.HideBySig, assembly.MainModule.TypeSystem.Void);
            cls_Foo_0.Methods.Add(md_Bar_3);
            md_Bar_3.Body.InitLocals = true;
            var il_Bar_4 = md_Bar_3.Body.GetILProcessor();

            //Parameters of 'void Bar(T a) => list = a;'
            var p_a_5 = new ParameterDefinition("a", ParameterAttributes.None, gp_T_1);
            md_Bar_3.Parameters.Add(p_a_5);
            il_Bar_4.Emit(OpCodes.Ldarg_0);
            il_Bar_4.Emit(OpCodes.Ldarg_1);
            il_Bar_4.Emit(OpCodes.Stfld, fld_list_2);
            il_Bar_4.Emit(OpCodes.Ret);

            //** Constructor: Foo() **
            var ctor_Foo_6 = new MethodDefinition(".ctor", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName, assembly.MainModule.TypeSystem.Void);
            cls_Foo_0.Methods.Add(ctor_Foo_6);
            var il_ctor_Foo_7 = ctor_Foo_6.Body.GetILProcessor();
            il_ctor_Foo_7.Emit(OpCodes.Ldarg_0);
            il_ctor_Foo_7.Emit(OpCodes.Call, assembly.MainModule.ImportReference(TypeHelpers.DefaultCtorFor(cls_Foo_0.BaseType)));
            il_ctor_Foo_7.Emit(OpCodes.Ret);

            assembly.Write(path);
        }
    }
}

public class TypeHelpers
{
    public static MethodReference DefaultCtorFor(TypeReference type)
    {
        var resolved = type.Resolve();
        if (resolved == null)
            return null;

        var ctor = resolved.Methods.SingleOrDefault(m => m.IsConstructor && m.Parameters.Count == 0 && !m.IsStatic);
        if (ctor == null)
            return DefaultCtorFor(resolved.BaseType);

        return new MethodReference(".ctor", type.Module.TypeSystem.Void, type) {HasThis = true};
    }
}

Output:

.class private auto ansi beforefieldinit Foo`1<T> extends [mscorlib]System.Object
{
	// Fields
	.field private !T list

	// Methods
	.method private hidebysig instance void Bar (!T a) cil managed 
	{
		// Method begins at RVA 0x2050
		// Header size: 12
		// Code size: 8 (0x8)
		.maxstack 2

		IL_0000: ldarg.0
		IL_0001: ldarg.1
		IL_0002: stfld !0 Foo`1::list
		IL_0007: ret
	} // end of method Foo`1::Bar

	.method public hidebysig specialname rtspecialname instance void .ctor () cil managed {...} 

} // end of class Foo`1

Expected:

.class private auto ansi beforefieldinit Foo`1<T> extends [mscorlib]System.Object
{
	// Fields
	.field private !T list

	// Methods
	.method private hidebysig instance void Bar (!T a) cil managed 
	{
		// Method begins at RVA 0x2050
		// Header size: 12
		// Code size: 8 (0x8)
		.maxstack 2

		IL_0000: ldarg.0
		IL_0001: ldarg.1
		IL_0002: stfld !0 class Foo`1<!0>::list
		IL_0007: ret
	} // end of method Foo`1::Bar

	.method public hidebysig specialname rtspecialname instance void .ctor () cil managed {...} 

} // end of class Foo`1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant