本篇看下.NET9下面的C#源码到机器码的全过程运行模型--顶级技术展示。CLR/JIT干预了全过程。
简单的例子:
static void Main(string[] args)
{
Console.WriteLine("Call Main");
}
以上C#源码的IL如下:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 )
// 代码大小 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "Call Main"
IL_0006: call void [System.Console]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
} // end of method Program::Main
导入到JIT的IL二进制机器码
IL to import:
IL_0000 00 nop
IL_0001 72 01 00 00 70 ldstr 0x70000001
IL_0006 28 0e 00 00 0a call 0xA00000E
IL_000b 00 nop
IL_000c 2a ret
IL在JIT的中间表象IR:
fgMorphTree BB02, STMT00001 (before)
[000001] ----------- * NO_OP void
fgMorphTree BB02, STMT00002 (before)
[000003] --C-G------ * CALL void System.Console:WriteLine(System.String)
[000002] ----------- arg0 \--* CNS_STR ref <string constant>
Initializing arg info for 3.CALL:
Args for call [000003] CALL after AddFinalArgsAndDetermineABIInfo:
CallArg[[000002].CNS_STR ref (By value), 1 reg: rdi, byteAlignment=8]
Morphing args for 3.CALL:
Sorting the arguments:
Deferred argument ('rdi'):
[000014] H----+----- * CNS_INT(h) ref 'Call Main'
Moved to late list
Register placement order: rdi
Args for [000003].CALL after fgMorphArgs:
CallArg[[000014].CNS_INT ref (By value), 1 reg: rdi, byteAlignment=8, isLate, processed]
OutgoingArgsStackSize is 0
fgMorphTree BB02, STMT00002 (after)
[000003] --CXG+----- * CALL void System.Console:WriteLine(System.String)
[000014] H----+----- arg0 in rdi \--* CNS_INT(h) ref 'Call Main'
fgMorphTree BB02, STMT00003 (before)
[000004] ----------- * NO_OP void
fgMorphTree BB02, STMT00004 (before)
[000005] ----------- * RETURN void
中间表象最后生成的Machine(机器码)如下:
IN0009: 000000 push rbp
IN000a: 000001 sub rsp, 16
IN000b: 000005 lea rbp, [rsp+0x10]
IN000c: 00000A mov gword ptr [V00 rbp-0x08], rdi
G_M27759_IG02: ; offs=0x00000E, size=0x0009, bbWeight=1, PerfScore 4.00, gcrefRegs=0000 {}, byrefRegs=0000 {}, BB02 [0003], byref, isz
IN0001: 00000E cmp dword ptr [(reloc 0x7fff79253d38)], 0
IN0002: 000015 je SHORT G_M27759_IG04
G_M27759_IG03: ; offs=0x000017, size=0x0005, bbWeight=0.50, PerfScore 0.50, gcrefRegs=0000 {}, byrefRegs=0000 {}, BB03 [0004], byref
IN0003: 000017 call CORINFO_HELP_DBG_IS_JUST_MY_CODE
G_M27759_IG04: ; offs=0x00001C, size=0x0013, bbWeight=1, PerfScore 4.00, gcrefRegs=0000 {}, byrefRegs=0000 {}, BB05 [0001], byref
IN0004: 00001C nop
IN0005: 00001D mov rdi, 0x7FFFE6BFF818 ; 'Call Main'
IN0006: 000027 call [System.Console:WriteLine(System.String)]
IN0007: 00002D nop
IN0008: 00002E nop
G_M27759_IG05: ; offs=0x00002F, size=0x0006, bbWeight=1, PerfScore 1.75, epilog, nogc, extend
IN000d: 00002F add rsp, 16
IN000e: 000033 pop rbp
IN000f: 000034 ret
以上就是一个最简单的Hello World在CLR/JIT的作用下一步步变成机器码的全过程。