LLVM异常处理实现

时间:2013-11-17 04:21:39

标签: llvm

请注意,我已阅读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_RaiseExceptionlandingpadresume的?

编辑:仅供参考,我将在Windows上JITting生成的代码。

2 个答案:

答案 0 :(得分:4)

如今Itanium C ++ ABI实际上是标准的C ++ ABI,用于其他许多方面 平台。 Itanium C ++ ABI支持零成本异常处理技术, 这是今天最普遍的技术。

要支持异常处理,必须更改函数的语义 呼叫。现在调用分叉执行流程。当一个分支被采取 一切都很好,第二个分支是在例外情况下采取的。 在LLVM IR中,有invoke指令来调用可能抛出的函数。

当采取第二个分支时,可以执行几种操作:

  • 调用析构函数(清理
  • 继续堆叠展开(简历
  • 强制执行投放规范(过滤器
  • 恢复正常控制流程( catch )。

很明显,必须生成一些额外的代码才能执行这些操作。 这就是我们获得landingpad指令的原因。这是第一次 invoke结束异常后要执行的指令。

但主要魔法是在运行时执行的。抛出异常后, 语言不可知的运行时展开堆栈,对于它找到语言的每一帧 特定数据区域(LSDA)并调用语言特定的个性例程。该 个性例程检查程序计数器,LSDA和当前异常。它 如果违反任何抛出规范,则确定是否需要进行任何清理 或者如果此框架可以捕获异常。

您可能知道,所有这些数据(个性例程,捕获类型,抛出规范,清理操作)已在landingpad中指定 指令,因此不应将其他数据传递给后端来生成 目标文件中与异常相关的部分。

答案 1 :(得分:4)

简短的回答是,LLVM有效地硬编码支持它想要支持的每个EH ABI-- ARM,Itanium,SEH等。所以虽然landingpad的东西在理论上可能有点抽象,但它是真的不是抽象的,而且非常紧密耦合,因为你需要做的另外一半的东西必须由你需要明确做的Itanium ABI EH支持库来完成。

LLVM几乎生成所有EH实现细节,但您还必须在运行时链接到Itanium EH支持库。除此之外,IR实际上就是它所展示的 - 代表程序员不需要额外的努力。

如果您想使用非Itanium,我认为事情变得更加棘手。