英文:
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::visitUnreachable 是 UnreachableInst 被转化为 ISD::TRAP 的地方。SelectionDAGLegalize::ConvertNodeToLibcall 是 ISD::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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论