Impala中 LLVM 的交叉编译、调用过程
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Impala中 LLVM 的交叉编译、调用过程相关的知识,希望对你有一定的参考价值。
参考技术A[TOC]
Impala 使用的 LLVM JIT,首先通过 Clang 将源码编译成了 LLVM IR 文件,然后通过脚本将 IR 文件装成可加载的二进制文件,BE 进程在运行过程中,通过 LLVM 的加载接口,把二进制文件加载进来使用。
待编译的文件通过codegen/ impala-ir.cpp 指定
impala-ir.cpp 文件主要的作用就是把需要产生 LLVM IR 的文件包含进来。
确定了哪些文件需要产生 LLVM IR 之后,就开始生成 IR 的二进制文件了。大致流程如下:
这个阶段生成最初始的bc文件,使用的是 CLang 的编译工具。命令可见codegen/CMakeFiles.txt
生成的结果是 impala-sse-tmp.bc 文件。
使用LLVM 优化工具,对原始的 bc 文件进行优化。命令可见codegen/CMakeFiles.txt
生成的结果就是impala-sse.bc。
这一步使用的是Impala 自定义的一个脚本 file2array.sh ,将优化后的 bc 文件转换为可加载的二进制c 文件。命令可见codegen/CMakeFiles.txt。
生成的结果是impala-sse-ir.cc。这个文件内部就是用一个数组存放二进制的值。
be 进程就是通过读取 impala_sse_llvm_ir 数组,把 LLVM IR加载到进程中。
file2array.sh 脚本其实就是使用 xxd -i < impala-sse-ir.cc 命令把bc 文件内容转成 c 语言的二进制形式。
LlvmCodeGen 类通过 CreateImpalaCodegen 接口实例化 codegen 对象。 CreateImpalaCodegen 最终会调用 CreateFromMemory ,在 CreateFromMemory 中就是将上文中生成的 impala_sse_llvm_ir 数组通过 LLVM 接口加载进来。
完成加载后,就可以通过 GetFunction 获取指定的 IR 函数了。
所有的函数名及描述,定义在 impala-ir-names.h 和 impala-ir-functions.h ,这两个文件是有对应关系的,都是通过gen_ir_descriptions.py生成。
impala-ir-names.h 定义了数组 FN_MAPPINGS ,存储函数名和枚举值的映射关系,如下:
impala-ir-functions.h定义了所有函数的枚举值,如下:
通过 GetFunction 获取函数的时候,因为有了 FN_MAPPINGS 存储的映射关系,可以通过传入枚举值或者字符串符号查找函数。
在 InitializeLlvm 方法中会使用 FN_MAPPINGS ,对加载的 llvm 函数进行校验。
Tips-LLVM 粗略编译过程
LLVM 编译过程
- 替换宏,将代码补全
- 词法、语法分析,生成AST(抽象语法树),方便代码静态检查
- AST生成IR(中间状态代码),和平台无关
- IR生成不同平台机器码,iOS就是Mach-O
以上是关于Impala中 LLVM 的交叉编译、调用过程的主要内容,如果未能解决你的问题,请参考以下文章
为 ARM 交叉编译 opencv 项目并在 go 项目 gocv 中调用