基本块定义为以跳转(直接或间接)指令结尾的(非跳转)指令序列。跳转目标地址应该是另一个基本块的开始。考虑我有以下汇编代码:
106ac: ba00000f blt 106f0 <main+0xb8>
106b0: e3099410 movw r9, #37904 ; 0x9410
106b4: e3409001 movt r9, #1
106b8: e79f9009 ldr r9, [pc, r9]
106bc: e3a06000 mov r6, #0
106c0: e1a0a008 mov sl, r8
106c4: e30993fc movw r9, #37884 ; 0x93fc
106c8: e3409001 movt r9, #1
106cc: e79f9009 ldr r9, [pc, r9]
106d0: e5894000 str r4, [r9]
106d4: e7941105 ldr r1, [r4, r5, lsl #2]
106d8: e1a00007 mov r0, r7
106dc: e12fff31 blx r1
106e0: e0806006 add r6, r0, r6
106e4: e25aa001 subs sl, sl, #1
106e8: e287700d add r7, r7, #13
106ec: 1afffff4 bne 106c4 <main+0x8c>
106f0: e30993d0 movw r9, #37840 ; 0x93d0
106f4: e3409001 movt r9, #1
bb1
106a4: ...
106ac: ba00000f blt 106f0 <main+0xb8>
第一个基本块 bb1 有一个目标地址,它是 bb4 的开始。
bb2
106b0: e3099410 movw r9, #37904 ; 0x9410
.... All other instructions
106c4: e30993fc movw r9, #37884 ; 0x93fc
.... All other instructions
106d8: e1a00007 mov r0, r7
106dc: e12fff31 blx r1
第二个基本块 bb2 有一个间接分支,因此目标地址仅在运行时才知道。
bb3
106e0: e0806006 add r6, r0, r6
106e4: e25aa001 subs sl, sl, #1
106e8: e287700d add r7, r7, #13
106ec: 1afffff4 bne 106c4 <main+0x8c>
第三个基本块有一个目标地址,它不是另一个基本块的开始,而是在 bb2 的中间。根据基本块的定义,这是不可能的。但是,在实践中,我在多个地方看到了这种行为(在基本块的中间跳跃)。如何解释这种行为?是否可以强制编译器(LLVM)生成除了基本块开头之外不会跳转到其他任何地方的代码?
bb4
106f0: e30993d0 movw r9, #37840 ; 0x93d0
106f4: e3409001 movt r9, #1
....
Ends with a branch (direct or indirect)
我正在使用工具(SPEDI)生成基本块,使用的编译器是 LLVM(CLANG 前端),目标架构是 ARM V7 Cortex-A9。