Skip to content

Instantly share code, notes, and snippets.

@lambdageek
Created February 6, 2020 20:49
Show Gist options
  • Save lambdageek/1d0b334fd736b4d3040604d5e645b5af to your computer and use it in GitHub Desktop.
Save lambdageek/1d0b334fd736b4d3040604d5e645b5af to your computer and use it in GitHub Desktop.
// compiled with:
// csc /target:library /unsafe /O foo.cs
using System;
using System.Runtime.InteropServices;
public struct S {
public int a;
public int b;
}
public unsafe class P {
[DllImport ("Bar")]
static extern void Bar (int *x, int *y);
public static void Plop (S[] x, bool b)
{
if (b) {
fixed (S* p = x)
{
Bar (&p->a, &p->b);
}
Plop (x, !b);
} else
Plop (x, !b);
}
}
// method line 2
.method public static hidebysig
default void Plop (valuetype S[] x, bool b) cil managed
{
// Method begins at RVA 0x2050
// Code size 70 (0x46)
.maxstack 3
.locals init (
valuetype S* V_0,
valuetype S[] pinned V_1)
IL_0000: ldarg.1
IL_0001: brfalse.s IL_003b
IL_0003: ldarg.0
IL_0004: dup
IL_0005: stloc.1
IL_0006: brfalse.s IL_000d
IL_0008: ldloc.1
IL_0009: ldlen
IL_000a: conv.i4
IL_000b: brtrue.s IL_0012
IL_000d: ldc.i4.0
IL_000e: conv.u
IL_000f: stloc.0
IL_0010: br.s IL_001b
IL_0012: ldloc.1
IL_0013: ldc.i4.0
IL_0014: ldelema S
IL_0019: conv.u
IL_001a: stloc.0
IL_001b: ldloc.0
IL_001c: ldflda int32 S::a
IL_0021: conv.u
IL_0022: ldloc.0
IL_0023: ldflda int32 S::b
IL_0028: conv.u
IL_0029: call void class P::Bar(int32*, int32*)
IL_002e: ldnull
IL_002f: stloc.1 // <- zeroes out the fixed pointer
IL_0030: ldarg.0
IL_0031: ldarg.1
IL_0032: ldc.i4.0
IL_0033: ceq
IL_0035: call void class P::Plop(valuetype S[], bool)
IL_003a: ret
IL_003b: ldarg.0
IL_003c: ldarg.1
IL_003d: ldc.i4.0
IL_003e: ceq
IL_0040: call void class P::Plop(valuetype S[], bool)
IL_0045: ret
} // end of method P::Plop
Var R16 live at enter, add range to R16: [1c0001, 200001)
Var R17 live at enter, add range to R17: [1c0001, 200001)
Var R19 live at enter, add range to R19: [1c0001, 200001)
LIVENESS BLOCK BB9:
180013: br [B1]
180012: il_seq_point il: 0x3a
180011: il_seq_point il: 0x3a, nonempty-stack
180010: voidcall [void P:Plop (S[],bool)] [%rdi <- R49] [%rsi <- R50] clobbers: c
18000f: move R50 <- R48
18000e: move R49 <- R16
last use of R16 set to 18000e
18000d: int_ceq R48 <-
18000c: icompare_imm R17 [0]
last use of R17 set to 18000c
18000b: il_seq_point il: 0x30
18000a: i8const R19 <- [0]
dead def of R19, eliminated // store to fixed pointer eliminated!
180009: il_seq_point il: 0x2e
180008: il_seq_point il: 0x2e, nonempty-stack
180007: voidcall [void P:Bar (int*,int*)] [%rdi <- R42] [%rsi <- R43] clobbers: c
180006: move R43 <- R41
180005: move R42 <- R18
last use of R18 set to 180005
180004: long_add_imm R41 <- R18 [4] clobbers: 1
180003: il_seq_point il: 0x1b
// I believe R19 is the fixed pointer
LIVENESS:
BLOCK BB0 (BB3, ):
1 aotconst R57 <-
1 gc_safe_point R57 clobbers: c
GEN BB0: {}
KILL BB0: {}
BLOCK BB3 (BB4, BB5, ):
1 i8const R18 <- [0]
KILL: R18(2)
1 i8const R19 <- [0]
KILL: R19(3)
1 il_seq_point il: 0x0
1 icompare_imm R17 [0]
GEN: R17(1)
1 int_beq [B4B5]
GEN BB3: {1}
KILL BB3: {2, 3}
BLOCK BB4 (BB1, ):
1 il_seq_point il: 0x3b
1 icompare_imm R17 [0]
GEN: R17(1)
1 int_ceq R54 <-
1 move R55 <- R16
GEN: R16(0)
1 move R56 <- R54
1 voidcall [void P:Plop (S[],bool)] [%rdi <- R55] [%rsi <- R56] clobbers: c
1 il_seq_point il: 0x45, nonempty-stack
1 il_seq_point il: 0x45
GEN BB4: {0, 1}
KILL BB4: {}
BLOCK BB1 ():
GEN BB1: {}
KILL BB1: {}
BLOCK BB5 (BB6, BB7, ):
1 il_seq_point il: 0x3
1 move R19 <- R16
GEN: R16(0)
KILL: R19(3)
1 lcompare_imm R16
GEN: R16(0)
1 long_beq [B6B7]
GEN BB5: {0}
KILL BB5: {3}
BLOCK BB6 (BB9, ):
1 il_seq_point il: 0xd
1 iconst R28 <- [0]
1 zext_i4 R18 <- R28
KILL: R18(2)
1 il_seq_point il: 0x10
1 br [B9]
GEN BB6: {}
KILL BB6: {2}
BLOCK BB9 (BB1, ):
1 il_seq_point il: 0x1b
1 long_add_imm R41 <- R18 [4] clobbers: 1
GEN: R18(2)
1 move R42 <- R18
GEN: R18(2)
1 move R43 <- R41
1 voidcall [void P:Bar (int*,int*)] [%rdi <- R42] [%rsi <- R43] clobbers: c
1 il_seq_point il: 0x2e, nonempty-stack
1 il_seq_point il: 0x2e
1 i8const R19 <- [0]
KILL: R19(3)
1 il_seq_point il: 0x30
1 icompare_imm R17 [0]
GEN: R17(1)
1 int_ceq R48 <-
1 move R49 <- R16
GEN: R16(0)
1 move R50 <- R48
1 voidcall [void P:Plop (S[],bool)] [%rdi <- R49] [%rsi <- R50] clobbers: c
1 il_seq_point il: 0x3a, nonempty-stack
1 il_seq_point il: 0x3a
1 br [B1]
GEN BB9: {0, 1, 2}
KILL BB9: {3}
BLOCK BB7 (BB8, BB6, ):
1 il_seq_point il: 0x8
1 not_null R19
GEN: R19(3)
1 loadi4_membase R26 <- [R19 + 0x18]
GEN: R19(3)
1 not_null R19
GEN: R19(3)
1 icompare_imm R26 [0]
1 int_bne_un [B8B6]
GEN BB7: {3}
KILL BB7: {}
BLOCK BB8 (BB9, ):
1 il_seq_point il: 0x12
1 not_null R19
GEN: R19(3)
1 amd64_icompare_membase_imm [R19 + 0x18]
GEN: R19(3)
1 cond_exc_le_un IndexOutOfRangeException
1 long_add_imm R18 <- R19 [32] clobbers: 1
GEN: R19(3)
KILL: R18(2)
GEN BB8: {3}
KILL BB8: {2}
Now that the store is eliminated, there's nothing left:
LOCAL REGALLOC BLOCK 9:
1 il_seq_point il: 0x1b
2 amd64_lea_membase R41 <- %r13
3 move R42 <- %r13
4 move R43 <- R41
5 voidcall [void P:Bar (int*,int*)] [%rdi <- R42] [%rsi <- R43] clobbers: c
6 il_seq_point il: 0x2e, nonempty-stack
7 il_seq_point il: 0x2e
8 il_seq_point il: 0x30
9 loadu1_membase R59 <- [%rsp + 0x10]
10 x86_test_null R59
11 int_ceq R48 <-
12 move R49 <- %r14
13 move R50 <- R48
14 voidcall [void P:Plop (S[],bool)] [%rdi <- R49] [%rsi <- R50] clobbers: c
15 il_seq_point il: 0x3a, nonempty-stack
16 il_seq_point il: 0x3a
17 br [B1]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment