views:

28

answers:

1

Hi, 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.

+2  A: 

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 to

  1. newobj
  2. stloc to a temporary variable
  3. ldloca to get the address of the value type stored in the temporary variable
  4. call

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();.

Tim Robinson
Humm nice tip, I'm getting [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.this must be related with what the constructor is returning...
Ivo Leitão
See my edit... :)
Tim Robinson
I will try that tnks a lot. I will update as answer after
Ivo Leitão