`Common Language Runtime detected an invalid program` error generating simple dynamic method
09:35 15 Apr 2026

I'm working on a JIT compiler for a MIPS machine emulation. I'm working on getting a nearly hard-coded Shift method, but whenever I try to execute the operation instruction on a value loaded from memory it fails.

This is the code that fails giving the Common Language Runtime detected an invalid program exception message:

    private unsafe bool Shift(ILGenerator il, MipsInstruction inst, OpCode ilOpCode)
    {
        long baseAddress = (long)_cpu.RegisterFile.Regs;
        long regAddress = baseAddress + ((int)inst.RT * sizeof(T));

        // Push Address
        if (IntPtr.Size == 4) il.Emit(OpCodes.Ldc_I4, (int)regAddress);
        else il.Emit(OpCodes.Ldc_I8, regAddress);
        il.Emit(OpCodes.Conv_I);

        // Load the value from memory
        il.Emit(OpCodes.Ldind_U4);

        // Load shift amount
        il.Emit(OpCodes.Ldc_I4, inst.ShiftAmount);

        // Apply shift
        il.Emit(ilOpCode);

        // Pop value (not even trying to store yet)
        il.Emit(OpCodes.Pop);

        return false;
    }

_cpu.RegisterFile.Regs is a T* where T is either a uint or a ulong depending on if the configurated MIPS version is 32 or 64 bit. In my testing I've been using MIPS32R2, so it's a uint.

For additional info, the following two methods do not give the

    private unsafe bool Shift(ILGenerator il, MipsInstruction inst, OpCode ilOpCode)
    {
        il.Emit(OpCodes.Ldc_I4, inst.ShiftAmount);
        il.Emit(OpCodes.Ldc_I4, inst.ShiftAmount);
        il.Emit(ilOpCode);
        il.Emit(OpCodes.Pop);

        return false;
    }
    private unsafe bool Shift(ILGenerator il, MipsInstruction inst, OpCode ilOpCode)
    {
        long baseAddress = (long)_cpu.RegisterFile.Regs;
        long regAddress = baseAddress + ((int)inst.RT * sizeof(T));

        // Push Address
        if (IntPtr.Size == 4) il.Emit(OpCodes.Ldc_I4, (int)regAddress);
        else il.Emit(OpCodes.Ldc_I8, regAddress);
        il.Emit(OpCodes.Conv_I);

        // Load the value from memory
        il.Emit(OpCodes.Ldind_U4);
        il.Emit(OpCodes.Pop);

        return false;
    }

Finally, here is a permalink to a still broken version, which contains the surrounding code: permalink

c# .net clr cil