Where does LLVM translate UnreachableInst into abort function call?

188 Views Asked by At

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

2

There are 2 best solutions below

0
On BEST ANSWER

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.

0
On

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