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 的交叉编译、调用过程的主要内容,如果未能解决你的问题,请参考以下文章

交叉编译适用于 iOS 的 Jansson C 库

交叉编译和交叉调试环境搭建及使用

为 ARM 交叉编译 opencv 项目并在 go 项目 gocv 中调用

Ubuntu 12.04嵌入式交叉编译环境arm-linux-gcc搭建过程图解

嵌入式杂谈之交叉编译器

交叉编译,为什么需要交叉编译