Home General

Native Disassembly only shows first basic block

I rather like the Native Disassembly feature in LINQPad and use it often to compare implementations. However it seems to be broken I think in the latest version, because only the first basicblock is shown. For example:

ref T ElementAt(T[] array, int offset)
=> ref array[offset];

Above code generates the following. At line L0008 it refers to label L0017 but that code is not visible anymore. (It used to show: int 3)

L0000 sub rsp, 0x28
L0004 cmp r8d, [rdx+8]
L0008 jae short L0017
L000a mov eax, r8d
L000d lea rax, [rdx+rax*4+0x10]
L0012 add rsp, 0x28
L0016 ret

Does anyone know a workaround? (Other than going back to a previous version of LINQPad)

Comments

  • edited February 11

    8.8.6 (latest beta), the same:

    ref T ElementAt<T>(T[] array, int offset)
    => ref array[offset];
    
    L0000   sub rsp, 0x28
    L0004   cmp r8d, [rdx+8]
    L0008   jae short L0017
    L000a   mov eax, r8d
    L000d   lea rax, [rdx+rax*4+0x10]
    L0012   add rsp, 0x28
    L0016   ret
    
  • Can you provide a full repro? I've tried running a fresh install of LINQPad 8.8.6 (Windows Sandbox) with the following script:

    void Main()
    {
    }
    
    ref T ElementAt<T>(T[] array, int offset)
        => ref array[offset];
    

    This is the X64 shown:

    ElementAt<T> (T[], Int32)
    L0000   push    rbp
    L0001   push    rdi
    L0002   sub rsp, 0x28
    L0006   lea rbp, [rsp+0x30]
    L000b   mov [rbp+0x10], rcx
    L000f   mov [rbp+0x18], rdx
    L0013   mov [rbp+0x20], r8d
    L0017   cmp dword ptr [0x7ffbdfdac258], 0
    L001e   je  short L0025
    L0020   call    0x00007ffc3e863390
    L0025   mov rax, [rbp+0x18]
    L0029   mov ecx, [rbp+0x20]
    L002c   cmp ecx, [rax+8]
    L002f   jb  short L0036
    L0031   call    0x00007ffbdeb11728
    L0036   mov edx, ecx
    L0038   lea rax, [rax+rdx*4+0x10]
    L003d   add rsp, 0x28
    L0041   pop rdi
    L0042   pop rbp
    L0043   ret
    
  • edited February 19

    Here is a full example. A clue might be that on my work-pc it works okay if I select .NET 8, but only shows the first basic block when .NET 9 is selected.
    LINQPad version: 8.7.4 (X64)
    Host runtime version: 8.0.12
    Default query runtime version: 9.0.1
    Default query reference assembly version: 9.0.1
    Roslyn Version: 4.12.0-3.24572.7
    FSharp.Compiler.Service version: 43.8.101.0
    NuGet client version: 6.7.1.1

    void Main()
    {
        var myArray = new int[10];
        ref var a = ref ElementAt(myArray, 5);
        a = 5;
        myArray.Dump();
    }
    
    ref T ElementAt<T>(T[] array, int offset)
        => ref array[offset];
    

    This outputs with /o+:

    X64
    Main ()

    L0000   sub rsp, 0x28
    L0004   mov rcx, 0x7ffa29498aa8
    L000e   mov edx, 0xa
    L0013   call    0x00007ffa88fb7a40
    L0018   mov dword ptr [rax+0x24], 5
    L001f   mov rdx, rax
    L0022   mov rcx, 0x7ffa2a02f040
    L002c   call    qword ptr [0x7ffa2a0441f8]
    L0032   nop 
    L0033   add rsp, 0x28
    L0037   ret 
    

    ElementAt (T[], Int32)

    L0000   sub rsp, 0x28
    L0004   cmp r8d, [rdx+8]
    L0008   jae short L0017
    L000a   mov eax, r8d
    L000d   lea rax, [rdx+rax*4+0x10]
    L0012   add rsp, 0x28
    L0016   ret 
    
  • Code generated is the same for .NET 8/9

Sign In or Register to comment.