LLVM将UnreachableInst转为_abort调用的位置及RL78 Rust编译问题
RL78平台Rust适配:Unreachable转_abort的问题定位
转换逻辑的具体位置
LLVM 10里把UnreachableInst转成_abort调用的逻辑,基本都在RL78目标后端的代码里:
- 优先看
llvm/lib/Target/RL78/RL78ISelLowering.cpp,找LowerOperation函数里对ISD::UNREACHABLE的处理分支——后端通常会在这里把不可达节点替换成平台相关的异常调用 - 其次检查
RL78InstrInfo.cpp或RL78CodeGenPrepare.cpp,有些后端会在代码生成准备阶段做这类替换 - 另外,通用CodeGen的
SelectionDAGBuilder会把LLVM IR里的llvm.unreachable转成ISD::UNREACHABLE节点,要是后端没做特殊处理,LLVM可能触发默认逻辑,但瑞萨定制版肯定是针对性加了转_abort的代码
问题根源
- 定制LLVM的隐式修改:瑞萨的LLVM 10定制版大概率是为了适配RL78的异常流程,把不可达指令强制替换成
call _abort,但没在工具链里默认提供这个函数的实现,也没在文档里提这茬 - Rust过程宏的隐性依赖:
#[entry]这类宏生成的代码会带Rust标准库的隐式分支(比如panic处理里的不可达路径),这些分支在优化后被保留,触发了后端的转换逻辑 - 链接脚本的缺失:RL78的默认链接脚本可能没定义
.plt段,也没给_abort加弱符号实现,导致链接时找不到符号
排查验证步骤
- 用
llvm-dis导出rustc生成的LLVM IR,对比优化前后的版本,确认unreachable是在哪个优化阶段被替换成call _abort的 - 直接搜瑞萨定制LLVM的代码diff,关键词用
UNREACHABLE或abort,重点看RL78目标后端的代码变更 - 检查工具链的启动文件(比如
crt0.s),看有没有默认的_abort弱定义,没有的话就得手动加个dummy实现
内容的提问来源于stack exchange,提问作者Mizunashi
相关产品推荐
相关产品推荐

