You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让LLVM C-API的LLVMDumpModule导出带值名称的模块?

问题描述

使用Rust结合LLVM及LLVM C-API开发自定义编译器时,调试调用LLVMDumpModule()输出LLVM IR,发现所有自定义值名称(如函数名my_func)被替换为数字编号,导致调试难度陡增。LLVM C++ API的dumpModule可通过参数控制显示值名称,但C-API无直接对应设置。

最小复现代码(Rust + llvm-sys):

extern crate llvm_sys as llvm;
use std::ffi::CString;

fn c_str(s: &str) -> *const i8 {
    CString::new(s).unwrap().as_ptr()
}

fn main() {
    unsafe {
        let ctx = llvm::LLVMContextCreate();
        let mod_ = llvm::LLVMModuleCreateWithNameInContext(c_str("main_ctx"), ctx);
        // 创建i64()类型的函数
        let func_type = llvm::LLVMFunctionType(llvm::LLVMInt64TypeInContext(ctx), std::ptr::null_mut(), 0, 0);
        llvm::LLVMAddFunction(mod_, c_str("my_func"), func_type);
        
        llvm::LLVMDumpModule(mod_);
    }
}

预期输出:

define i64 @my_func()

实际输出:

define i64 @1()
解决方案

LLVM C-API虽未给LLVMDumpModule()提供参数,但可通过以下两种方式实现显示值名称的需求:

方法1:自定义打印选项输出IR

LLVMDumpModule()本质是向标准错误流输出默认配置的IR,我们可以用LLVMPrintModuleToStringWithFlags指定打印标志,手动输出结果:

extern crate llvm_sys as llvm;
use std::ffi::{CString, CStr};
use std::io::{self, Write};

fn c_str(s: &str) -> *const i8 {
    CString::new(s).unwrap().as_ptr()
}

fn main() {
    unsafe {
        let ctx = llvm::LLVMContextCreate();
        let mod_ = llvm::LLVMModuleCreateWithNameInContext(c_str("main_ctx"), ctx);
        let func_type = llvm::LLVMFunctionType(llvm::LLVMInt64TypeInContext(ctx), std::ptr::null_mut(), 0, 0);
        llvm::LLVMAddFunction(mod_, c_str("my_func"), func_type);
        
        // 启用值名称打印标志
        let print_flags = llvm::LLVMPrintNames;
        let ir_str_ptr = llvm::LLVMPrintModuleToStringWithFlags(mod_, print_flags);
        let ir_str = CStr::from_ptr(ir_str_ptr).to_str().unwrap();
        
        // 输出到标准错误流,模拟LLVMDumpModule的行为
        writeln!(io::stderr(), "{ir_str}").unwrap();
        
        // 清理内存
        llvm::LLVMDisposeMessage(ir_str_ptr);
        llvm::LLVMDisposeModule(mod_);
        llvm::LLVMContextDispose(ctx);
    }
}

方法2:全局设置打印标志

如果希望所有LLVMDumpModule()调用都生效,可通过LLVMSetPrintModuleFlags全局配置:

extern crate llvm_sys as llvm;
use std::ffi::CString;

fn c_str(s: &str) -> *const i8 {
    CString::new(s).unwrap().as_ptr()
}

fn main() {
    unsafe {
        // 全局开启值名称打印
        llvm::LLVMSetPrintModuleFlags(llvm::LLVMPrintNames);
        
        let ctx = llvm::LLVMContextCreate();
        let mod_ = llvm::LLVMModuleCreateWithNameInContext(c_str("main_ctx"), ctx);
        let func_type = llvm::LLVMFunctionType(llvm::LLVMInt64TypeInContext(ctx), std::ptr::null_mut(), 0, 0);
        llvm::LLVMAddFunction(mod_, c_str("my_func"), func_type);
        
        // 现在LLVMDumpModule会显示自定义名称
        llvm::LLVMDumpModule(mod_);
        
        llvm::LLVMDisposeModule(mod_);
        llvm::LLVMContextDispose(ctx);
    }
}

关键说明

  • LLVMPrintNames是控制显示值自定义名称的核心标志,开启后IR会保留你设置的名称(如@my_func)。
  • 若需同时显示调试信息,可组合LLVMPrintDebugInfo标志,或直接用LLVMPrintAll开启所有打印选项。
  • 使用LLVMPrintModuleToStringWithFlags返回的字符串必须用LLVMDisposeMessage释放,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Jonas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 11:35:06