我有三个问题:
1)LLVM的IR代码中的Invoke和Call操作有什么区别?
2)为什么在BasicBlocks here中不将Call指令视为终结者操作?
3)Invoke和Call操作是否可以使用汇编级语言生成间接调用?
提前谢谢你,
答案 0 :(得分:9)
1)R \ Invoke是对可以启动异常的函数的调用。如果您意识到,则调用为句柄异常定义一个块,另一个用于继续正常流程。
2)R \ 由于控制流被传输到另一个函数,因此调用指令不被视为终止符指令。在LLVM中,终结符指令必须反映可以被激活的下一个(或多个)基本块。
3)R \ 对不起,我不知道
答案 1 :(得分:1)
关于3),你不清楚是否要问w.r.t.写a)一个自己的后端或b)关于现有的后端。
a)是的,显然/通常你可以生成任何你想要的东西,如果你在你的后端实现它。 b)哪个后端?即ARM的调用已经是一个间接分支(即bl指令),而X86的CALL对X86 HW有副作用(即保存返回地址,也有非功能性副作用,如支持调用堆栈分支预测)因此无法通过间接调用替换,而无需模拟CALL将执行的操作。使用间接分支的AFAIK CALL仿真不是X86的LLVM后端的一部分。
答案 2 :(得分:0)
调用和调用用于调用函数。调用指令是普通的C样式调用,一旦函数返回,程序将从函数调用之后的下一条指令恢复。
invoke可用于处理异常,其方式是当函数未正常返回时,它将从另一个基本块(也称为着陆垫)“恢复”。登陆垫将具有处理异常的信息。
可以使用调用和调用指令AIUI生成间接调用。 llvm langref中有更多详细信息:https://llvm.org/docs/LangRef.html