LLVM IR和C/C++函数相互调用时的注意事项

本文介绍了在LLVM 3.6中从C/C++调用LLVM IR函数及从LLVM IR调用C/C++函数的方法。主要包括通过ExecutionEngine接口调用、使用DynamicLibrary::AddSymbol注册函数和自定义内存分配器等技术细节。
以下叙述,主要针对LLVM 3.6。

一、从C/C++调用LLVM IR函数
主要有两种办法。
1、通过llvm::ExecutionEngine::runFunction()调用。
    存在的问题:可以直接调用llvm::Function,但目前LLVM项目没有实现参数传递,只提供了接口,因此我们只能调用无参函数
2、通过llvm::ExecutionEngine::getPointerToFunction()即时编译为本机代码,并获得一个指向C函数的void *指针。然后,可以将其转换为合适的C/C++函数指针,进行调用。
    存在的问题:LLVM指令被编译为ELF格式,而不是COFF格式,导致在Windows平台加载时错误" Incompatible object format "。
    为解决这一问题,需要在系统三元组(Triple)后加“-elf”。参见: http://comments.gmane.org/gmane.comp.compilers.llvm.devel/82330
二、从LLVM IR调用 C/C++函数
    主要有三种办法。
   1、将被调用函数声明为动态链接导出函数,LLVM自动在执行时解析并调用。  
    这是官方“标准”的做法。
    存在的问题:windows平台可执行文件中的函数一般不会被导出,不能通过这一机制解析。
    解决办法是,通过llvm::sys::DynamicLibrary::AddSymbol()显示注册函数。LLVM在查找外部函数时,首先查找通过AddSymbol注册的函数,然后才通过系统调用查找可执行文件或动态链接库中的符号。
    2、通过llvm::ExecutionEngine::addGlobalMapping()将被调用的C/C++函数指针注册为LLVM中的全局变量。
    这样做的好处是,被调用函数不需要声明为动态链接库的导出函数,只要知道函数指针就可以。
    存在的问题:MCJIT对addGlobalMapping的支持不完善,实际运行时会报错。参见: http://llvm.1065342.n5.nabble.com/Weird-problems-on-calling-an-external-function-from-MCJIT-on-Windows-mingw-td67478.html
    解决办法同1,通过AddSymbol()来实现。
    3、通过自定义的内存分配器来直接解析函数。
    原理同addGlobalMapping类似,这一方法我没有验证,有空可以试验一下。
C++ Rust 在生成 LLVM IR 的主要区别主要体现在语言特性、编译器设计哲学、以及中间表示的生成方式上。 ### 语言特性与编译流程 C++ 是一种静态类型语言,其编译过程通常直接由前端(如 Clang)将 C++ 代码转换为 LLVM IR,然后由 LLVM 完成优化代码生成。Clang 是 LLVM 项目的一部分,因此 C++LLVM 的集成非常紧密,编译器可以较为直接地将 C++ 的语法结构映射到 LLVM IR 中的控制流数据流表示 [^4]。 Rust 则采用了不同的路径。Rust 编译器 rustc 的前端并不直接生成 LLVM IR,而是先将源代码转换为 Rust 特有的中间表示(如 HIR、MIR),然后通过一个独立的后端将 MIR 转换为 LLVM IR。这种设计使得 Rust 能够在 MIR 阶段进行语言特有的优化类型检查,再利用 LLVM 的优化能力进行进一步的低级优化 [^2]。 ### 内存管理与安全性 Rust 的核心特性之一是其所有权系统,这在 C++ 中是不存在的。在生成 LLVM IR ,Rust 编译器必须确保生成的代码符合所有权借用规则,这通常意味着在 IR 中会包含额外的元信息或插入运行检查(尽管大多数检查在编译已完成)。相比之下,C++ 的内存管理完全由开发者负责,因此其 LLVM IR 更加直接地反映源代码中的内存操作 [^2]。 ### 优化与代码生成 由于 LLVM 的优化器已经非常成熟,C++ Rust 都可以利用其进行高级优化,如过程间分析、向量化等。然而,Rust 的编译器在优化方面承担了更多语言层面的责任,例如确保安全性零成本抽象。这使得 Rust 在生成 LLVM IR 前的优化阶段更加复杂,而 C++ 的优化更多依赖 LLVM 自身的优化通道 [^2]。 ### 示例:函数定义 在 LLVM IR 中,C++ Rust 生成的函数定义在结构上是相似的,但命名调用约定可能有所不同。以下是一个简单的函数定义示例: ```llvm define i32 @add(i32 %a, i32 %b) { entry: %tmp = add i32 %a, %b ret i32 %tmp } ``` 对于 C++ 来说,这个函数可能直接对应于源代码中的一个函数;而对于 Rust 来说,这个函数可能是在 MIR 转换为 LLVM IR 的过程中生成的,且可能包含更多的元信息以支持 Rust 的语言特性 [^4]。 ### 总结 C++ Rust 在生成 LLVM IR 的主要区别体现在以下几个方面: - **编译器架构**:C++ 通过 Clang 直接生成 LLVM IR,而 Rust 通过 rustc 的 MIR 阶段间接生成。 - **语言特性支持**:Rust 的所有权系统安全性机制在 LLVM IR 中需要额外的处理,而 C++ 更加直接。 - **优化阶段**:Rust 在 MIR 阶段进行语言特有的优化,而 C++ 更多依赖 LLVM 的通用优化通道 [^2]。 这些差异使得两种语言在生成 LLVM IR 各有侧重,同也反映了它们在设计哲学上的不同。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值