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

huangapple go评论84阅读模式
英文:

Where does LLVM translate UnreachableInst into abort function call?

问题

I am searching where is UnreachableInst translated into _abort call.

Below is the story.

I'm currently trying for Rust to be available for Renesas RL78 target. To end this, I got LLVM source code from Open Source Tools for Renesas and used it as a backend for the rustc compiler.

First, I wrote code with only the main function. This code compiled without errors and had no problems as far as I could see in the binary content.

Note that this is a partial code; the actual code has attributes like #![no_main] and essential components like a panic handler.

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

However, if I write and use the #[entry] proc macro like the cortex-m crate has, I get an error below.

#[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)

I added a dummy abort function and added a .plt section to a linker script because the linker requires it too. I retried compilation, and it succeeded.

I investigated the binary and found that the _abort call is placed after the rust main call, as shown below.

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

I also investigated the LLVM IR that rustc generated and found an unreachable statement.

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
}

In the object file rustc generated, the _abort call is already inserted. This is why I suspect that LLVM translates Unreachable into an abort call, and the linker and Rustc do not do anything.

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

As I mentioned above, this LLVM is a custom version of LLVM 10 for Renesas RL78, so this problem may be from the custom version. However, I cannot find the cause from the diff between the original and custom versions.

I know it is the best and a good chance to study LLVM internals, so I am currently learning it now. However, I want to know where the problem is.

Please tell me what is the problem.

英文:

I am searching where is UnreachableInst translated into _abort call.

Below is the story.

I'm currenly trying for Rust to be avaiable for Renesas RL78 target.
To end this, I got a LLVM source code from Open Source Tools for Renesas, and use that as a backend of rustc compiler.

First, I wrote code with only main function.
This code is compiled without errors and no problems as far as I look the binary content.

Note that this is a partial code, actual code has attributes like #![no_main] and essential components like panic handler.

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

However, If I write and use #[entry] proc macro like cortex-m crate has, I got an error below.

#[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)

I add dummy abort function and add .plt section to a linker script because linker requires it too.
I retried compile and it successed.

I investigate the binary and I found that _abort call put after rust main call as I show below.

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

I also investigated llvm ir rustc generated, and there is unreachable statement.

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
}

In the object file rustc generated, _abort call is already inserted.
This is why, I suspect that LLVM translate Unreachable into abort call, and Linker and Rustc do not anything.

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

Like I said above, this LLVM is custom version of LLVM 10 for Renesas RL78,
so this problem may be from a custom, but I cannot find the cause from diff of original and custom one.

I know it is the best and a good chance to study llvm internal, so I currently learn it now.
However, I want to know where is the problem also.

Please tell me what is the problem

答案1

得分: 2

SelectionDAGBuilder::visitUnreachableUnreachableInst 被转化为 ISD::TRAP 的地方。SelectionDAGLegalize::ConvertNodeToLibcallISD::TRAP 被降低为 abort() 的地方。

英文:

SelectionDAGBuilder::visitUnreachable is where UnreachableInst turns into ISD::TRAP. SelectionDAGLegalize::ConvertNodeToLibcall is where ISD::TRAP is lowered as abort().

答案2

得分: 1

可能不会。

每个LLVM基本块都必须以终结指令结尾,unreachable是其中之一,这一要求经常被检查并严格执行。另一方面,call不是终结指令。因此,创建一个调用abort()的代码通常会在该call之后跟随一个unreachable

英文:

It probably doesn't.

Every LLVM basic block has to end with a terminator instruction, unreachable is one of those, and that requirement is checked often and enforced mercilessly. A call, on the other hand, is not a terminator. Because of this, code that creates a call to abort() will typically follow that call with an unreachable.

huangapple
  • 本文由 发表于 2023年7月27日 20:34:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76779797.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定