I'm building a compiler with reflection.emit in my spare time, and i've come to a problem that i'm not understanding.
A little context, I've a runtime with a couple of types and one of them is Float2, a simpler vector struct with two float values (X and Y). I've made a couple of properties that allow me to swizzle the values (a la hlsl). For example if i have a new Float2(1.0f, 2.0f), if i make something like (new Float2(1.0f, 2.0f)).YX i'm going to get a Float2(2.0f, 1.0f) I'm using this type in my language and currently testing this case (minor details of the language omitted):
float2 a = float2(1.0, 2.0).yx;
return a;
I'm transforming float2(1.0, 2.0) in a new call and accessing the property YX of my Float2 type in .yx.
The problem is I'm getting a "System.AccessViolationException : Attempted to read or write protected memory. This is often an indication that other memory is corrupt.". I don't understand why because if I make something like this:
float2 a = float2(1.0, 2.0);
return a;
Everything goes well.
The IL code that i'm generating is the following (I think the problem occurs in "L_0014: stloc.0", I don't know why it happens though) :
.method public virtual final instance valuetype
[Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2 Main() cil managed
{
.maxstack 3
.locals init (
[0] valuetype [Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2 num)
L_0000: ldc.r4 1
L_0005: ldc.r4 2
L_000a: newobj instance void [Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2::.ctor(float32, float32)
L_000f: call instance valuetype [Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2 [Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2::get_XY()
L_0014: stloc.0
L_0015: ldloc.0
L_0016: ret
}
Result of peverify:
[IL]: Error: [offset 0x0000000F] [found value 'Bifrost.Psl.Compiler.Runtime.Float2'][expected address of value 'Bifrost.Psl.Compiler.Runtime.Float2'] Unexpected type on the stack.
The IL looks OK, although I don't know what your
Float2
looks like.I found the best way to debug this is to save the assembly to disk, then run peverify. Any code that generates an
AccessViolationException
will cause an error in peverify.Edit: The
newobj
doc on MSDN talks about pushing an object reference onto the stack, which I took to be a pointer to a value type. If you're getting this error from peverify then I think you need tonewobj
stloc
to a temporary variableldloca
to get the address of the value type stored in the temporary variablecall
Now that I think about it, this is what the C# compiler does if you do a direct call on a value type like
4.ToString();
.