前言
IR技术应用在各个编程语言当中,它属于JIT的核心部分,确实有点点麻烦。但部分基本明了。本篇通过.Net8里面的边界检查的小例子了解下。前情提要,看这一篇之前建议看看前一篇:点击此处,以便于理解。
概括
1.前奏
先上C#代码:
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool Test(int[] array)
{
for (int i = 0; i < 0x12345; i++)
{
if (array[i] == 42)
{
return true;
}
}
return false;
}
Test函数经过Roslyn编译成IL代码之后,会被JIT导入及操作变成IR。
BBnum BBid ref try hnd preds weight lp [IL range] [jump] [EH region] [flags]
-----------------------------------------------------------------------------------------------------------------------------------------
BB01 [0007] 1 1 [???..???)-> BB04 ( cond ) internal
BB02 [0001] 2 BB01,BB03 4 0 [004..00B)-> BB05 ( cond ) i Loop idxlen bwd bwd-target align
BB03 [0003] 1 BB02 4 0 [00D..019)-> BB02 ( cond ) i bwd
BB04 [0005] 2 BB01,BB03 0.50 [019..01B) (return) i
BB05 [0002] 1 BB02 0.50 [00B..00D) (return) i
-----------------------------------------------------------------------------------------------------------------------------------------
可以看到IL被分割成了五个BB(basic block).注意表格的BBnum和jump列。BB01的BBnum就是BB01,它的jump是BB04。为啥是BB04?因为BB01的IR表示的是如果(i>=0x12345),则跳转到BB04,也就是BB01的正常逻辑。下面看下这个五个BB.
------------ BB01 [???..???) -> BB04 (cond), preds={} succs={BB02,BB04}
***** BB01
STMT00006 ( 0x011[E-] ... ??? )
( 7, 9) [000038] ----------- * JTRUE void
( 5, 7) [000039] J------N--- \--* GE int
( 3, 2) [000040] ----------- +--* LCL_VAR int V01 loc0
( 1, 4) [000041] ----------- \--* CNS_INT int 0x12345
------------ BB02 [004..00B) -> BB05 (cond), preds={BB01,BB03} succs={BB03,BB05}
***** BB02
STMT00002 ( 0x004[E-] ... 0x009 )
[000013] ---XG+----- * JTRUE void
[000012] N--XG+-N-U- \--* EQ int
[000034] ---XG+----- +--* COMMA int
[000026] ---X-+----- | +--* BOUNDS_CHECK_Rng void
[000008] -----+----- | | +--* LCL_VAR int V01 loc0
[000025] ---X-+----- | | \--* ARR_LENGTH int
[000007] -----+----- | | \--* LCL_VAR ref V00 arg0
[000035] n---G+----- | \--* IND int
[000033] -----+----- | \--* ARR_ADDR byref int[]
[000032] -----+----- | \--* ADD byref
[000023] -----+----- | +--* LCL_VAR ref V00 arg0
[000031] -----+----- | \--* ADD long
[000029] -----+----- | +--* LSH long
[000027] -----+---U- | | +--* CAST long <- uint
[000024] -----+----- | | | \--* LCL_VAR int V01 loc0
[000028