请注意,我已阅读the questions并阅读blog posts,我也引用了the ABI。
我完全不理解的是它与LLVM的EH内在函数的交互方式。 LLVM EH页面给出了一个非常模糊的概述 - 不完全是“实施X,Y,Z”的清单。
LLVM EH页面直接引用Itanium ABI。这意味着LLVM只支持Itanium ABI异常。但我已经知道Clang支持ARM并且正在开发对Microsoft ABI的支持。那么LLVM对Itanium ABI的EH实现究竟有多具体呢?
当引用Itanium ABI定义的_Unwind内容时,是否必须由后端提供,或者我是否必须为自己实现?
我还注意到Clang生成的LLVM IR没有显示任何特定于语言的表,任何异常帧,异常表或类似的东西。在这种情况下,LLVM如何知道如何生成特定于语言的数据?
简而言之,您究竟是如何从LSDA,EH情境和_Unwind_RaiseException
到landingpad
和resume
的?
编辑:仅供参考,我将在Windows上JITting生成的代码。
答案 0 :(得分:4)
如今Itanium C ++ ABI实际上是标准的C ++ ABI,用于其他许多方面 平台。 Itanium C ++ ABI支持零成本异常处理技术, 这是今天最普遍的技术。
要支持异常处理,必须更改函数的语义
呼叫。现在调用分叉执行流程。当一个分支被采取
一切都很好,第二个分支是在例外情况下采取的。
在LLVM IR中,有invoke
指令来调用可能抛出的函数。
当采取第二个分支时,可以执行几种操作:
很明显,必须生成一些额外的代码才能执行这些操作。
这就是我们获得landingpad
指令的原因。这是第一次
invoke
结束异常后要执行的指令。
但主要魔法是在运行时执行的。抛出异常后, 语言不可知的运行时展开堆栈,对于它找到语言的每一帧 特定数据区域(LSDA)并调用语言特定的个性例程。该 个性例程检查程序计数器,LSDA和当前异常。它 如果违反任何抛出规范,则确定是否需要进行任何清理 或者如果此框架可以捕获异常。
您可能知道,所有这些数据(个性例程,捕获类型,抛出规范,清理操作)已在landingpad
中指定
指令,因此不应将其他数据传递给后端来生成
目标文件中与异常相关的部分。
答案 1 :(得分:4)
简短的回答是,LLVM有效地硬编码支持它想要支持的每个EH ABI-- ARM,Itanium,SEH等。所以虽然landingpad
的东西在理论上可能有点抽象,但它是真的不是抽象的,而且非常紧密耦合,因为你需要做的另外一半的东西必须由你需要明确做的Itanium ABI EH支持库来完成。
LLVM几乎生成所有EH实现细节,但您还必须在运行时链接到Itanium EH支持库。除此之外,IR实际上就是它所展示的 - 代表程序员不需要额外的努力。
如果您想使用非Itanium,我认为事情变得更加棘手。