LLVM 在哪里将 UnreachableInst 翻译为 abort 函数调用?

问题描述 投票:0回答:2

我正在搜索 UnreachableInst 在哪里被翻译成 _abort 调用。

下面是故事。

我目前正在尝试让 Rust 可用于 Renesas RL78 目标。 为此,我从 Renesas 的开源工具中获取了 LLVM 源代码,并将其用作 rustc 编译器的后端。

首先,我编写了只有 main 函数的代码。 这段代码编译没有错误,并且就我查看二进制内容而言没有问题。

请注意,这是部分代码,实际代码具有

#![no_main]
等属性和恐慌处理程序等基本组件。

#[no_mangle]
pub unsafe extern "C" fn main() -> ! {
    loop {}
}

但是,如果我像 cortex-m crate 那样编写并使用

#[entry]
proc 宏,则会出现以下错误。

#[rl78_macros::entry]
fn main() -> ! {
    loop {}
}
lld: error: undefined symbol: _abort
          >>> referenced by main.rs:26 (src/main.rs:26)
          >>>               /home/vmuser/Documents/renesas/renesas-program/target/rl78/debug/deps/renesas_program-916d6430e40e98ae.3a31hiwjtkbq95rf.rcgu.o:(_main)

我添加了虚拟中止函数并将

.plt
部分添加到链接器脚本中,因为链接器也需要它。 我重试编译,成功了。

我调查了二进制文件,发现 _abort 调用放在 rust main 调用之后,如下所示。

00000085 _main:
      85: fc 81 00 00                   call !!__ZN15renesas_program11__rl78_main17h608e5bb48d9d4215E
      89: fd 80 00                      call !_abort

我也调查了llvm ir rustc生成的,有unreachable的语句。

define dso_local void @main() unnamed_addr addrspace(2) #0 !dbg !183 {
start:
; call renesas_program::__rl78_main
  call addrspace(2) void @_ZN15renesas_program11__rl78_main17h608e5bb48d9d4215E() #4, !dbg !184
  unreachable, !dbg !184
}

在 rustc 生成的目标文件中,已经插入了 _abort 调用。 这就是为什么,我怀疑 LLVM 将 Unreachable 翻译为 abort 调用,而 Linker 和 Rustc 没有做任何事情。

00000000 _main:
       0: fc 00 00 00                   call !!0x0
       4: fd 00 00                      call !0x0

就像我上面所说的,这个 LLVM 是 Renesas RL78 的 LLVM 10 的定制版本, 所以这个问题可能来自自定义,但我无法从原始和自定义的差异中找到原因。

我知道这是学习llvm内部最好、最好的机会,所以我目前正在学习它。 不过我也想知道问题出在哪里。

请告诉我有什么问题

rust llvm rl78
2个回答
1
投票

可能不会。

每个 LLVM 基本块都必须以终止符指令结束,

unreachable
就是其中之一,并且经常检查并无情地执行该要求。另一方面,A
call
不是终止符。因此,创建 abort() 调用的代码通常会在
call
后面加上
unreachable


0
投票

SelectionDAGBuilder::visitUnreachable
UnreachableInst
变成
ISD::TRAP
的地方。
SelectionDAGLegalize::ConvertNodeToLibcall
ISD::TRAP
降低为 abort() 的地方。

© www.soinside.com 2019 - 2024. All rights reserved.