联系我们:010-58426662

llvm之旅第三站 - 认识LLVM IR

2015-04-17 13:29:00

©娜迦 charme版权所有

版权声明:未经许可,请勿转载

认识LLVM IR


前面两篇系列文章,简单的介绍了LLVM以及编译配置过程。到此已经完全可以初步的使用llvm了,如果以研究llvm为目标的话,还远远不够。


一般来说,编译器会将源语言翻译为一种“中间语言(IR)”,之后再由中间语言,利用后端程序和设备翻译为目标平台的汇编语言。不同编译器的中间语言IR是不一样的,IR集中体现了编译器的主要特征——算法,优化方式,汇编流程等等。


LLVM IR主要有三种格式:一种是在内存中的编译中间语言;一种是硬盘上存储的二进制中间语言(以.bc结尾),最后一种是可读的中间格式(以.ll结尾)。这三种中间格式是完全等价的。


下面是一个简单的示例:


编译命令

clang -emit-llvm test.c -S -o test.ll



llvm_ir_struct2.png



简单解释:

1. @代表全局变量,%代表局部变量

2. %a = alloca i32, align 4 栈上分配内存

3. load读出内容 store写入内容

4. i32 i表示32位integer32,即四字节

6. aligin 4 4字节对齐

7. %add = add nsw i32 %0, %1 加法操作


以上只是简单的一个示例,文章里并不展示所有的学习成果,只是介绍学习的途径。

想要深入的了解IR,可以参考 LLVM Language Reference Manual



利用LLVM接口构建IR代码


LLVM提供了很多的API用于操作IR,因此我们可以使用这些接口直接在内存中生成IR,同时直接运行,输出结果。(如果我们想要开发一种新的编程语言,那么我们可以在完成词法语法解析后,很快的利用LLVM 接口生成有效的中间代码,同时能够很快的编译到目标平台上。)



LLVM IR 的基本结构如下: 


llvm_ir_struct.png

模块中包含函数,函数中包含基本块,基本块中包含指令。我们可以使用很简单的代码进行遍历,后续的文章会提及。


LLVM默认实现了C++接口,但同时也提供了C接口,下面我们使用C接口完成一个生成并且运行IR的简单示例。


#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <llvm-c/Core.h>
int main() {
    // 创建一个模块(模块名 module-test 可以任意)
    LLVMModuleRef Module = LLVMModuleCreateWithName("module-test");
    
    // 0. extern int printf(char*, ...)
    LLVMTypeRef PrintfArgsTyList[] = { LLVMPointerType(LLVMInt8Type(), 0) };
    LLVMTypeRef PrintfTy = LLVMFunctionType(
        LLVMInt32Type(),
        PrintfArgsTyList,
        0,
        true // 是否是可变参数
    );
    
    // 添加printf函数到模块中
    LLVMValueRef PrintfFunction = LLVMAddFunction(Module, "printf", PrintfTy);
    
    // 1. void main(void)
    LLVMTypeRef MainFunctionTy = LLVMFunctionType(
        LLVMVoidType(),
        NULL,
        0,
        false
    );
    
    // 添加main函数到模块中
    LLVMValueRef MainFunction = LLVMAddFunction(Module, "main", MainFunctionTy);
    
    // 添加基本块
    LLVMBasicBlockRef BasicBlock = LLVMAppendBasicBlock(MainFunction, 
                                    "entrypoint");
    
    // 创建builder
    LLVMBuilderRef Builder = LLVMCreateBuilder();
    LLVMPositionBuilderAtEnd(Builder, BasicBlock);
    
    // 2. char *format = "Hello, %s.\n", *world = "World"";
    LLVMValueRef Format = LLVMBuildGlobalStringPtr(
        Builder,
        "Hello, %s.\n",
        "format"
    ), World = LLVMBuildGlobalStringPtr(
        Builder,
        "World",
        "world"
    );
    
    // 3. printf("Hello, %s!", world);
    LLVMValueRef PrintfArgs[] = { Format, World };
    LLVMBuildCall(
        Builder,
        PrintfFunction,
        PrintfArgs,
        2,
        "printf"
    );
    
    // 4. return;
    LLVMBuildRetVoid(Builder);
    
    // dump模块
    LLVMDumpModule(Module);
    
    // 释放模块
    LLVMDisposeModule(Module);
    
    return 0;
}



使用如下命令编译:

clang++ -x c llvm_ir.c `llvm-config --cflags --ldflags --libs` -o ./llvm_ir


运行效果: 

1.png



代码中我只做了基本的解释,详细的接口说明,参考 LLVM-C: C interface to LLVM




参考文献:

LLVM-C: C interface to LLVM llvm.org/docs/doxygen/html/group__LLVMC.html

LLVM Language Reference Manual  -llvm.org/docs/LangRef.html



标签: llvm clang

热度  8838 回应  6 收藏  0

  • charme
    @伪装的伤痛 其实你想,如果你要开发一种新的编程语言,在词法 语法解析完成后,你要做什么,肯定是生成中间代码,然后优化,最后编译成目标机器码。但是llvm 的中间代码不仅效率高而且可读性很好。那你可以考虑照搬这个IR过来,怎么搬呢?一定是按照你的语法规则然后利用llvm给你的操作IR的接口,生成等价的IR,生成IR了,要怎么进行优化,然后编译成目标代码呢?llvm不仅仅是虚拟机,它实现了模块化的优化策略和多种后端,所以后面的工作都交给llvm了。总结一下:如果你想开发一种新的编程语言,那么你只需要完成词法和语法解析,然后根据接口生成可用的IR即可了。。很方便了。
    回应 2015-04-20 21:42:33
  • 玩命
    @伪装的伤痛 客气了。。。 个人觉得, 编译原理,算法分析,计算机组成原理, 只有这三门是属于计算机本身的, 而只有编译原理是属于计算机真正唯一的实用科学。其余的东西都和其他学科有关,唯独编译原理其他地方也用不到。
    回应 2015-04-18 19:54:23
  • 伪装的伤痛
    @玩命 原来如此, 不管怎么样,评论之后我还是要支持一下楼主, 本人也是非常喜欢编译原理这个领域, 但只是爱好,也是很久以前, 在学习编程的时代写过解释型的语言,不过跟楼主比起来,望成莫及啊。以后继续关注。 -o-
    回应 2015-04-18 19:10:52
  • 玩命
    @伪装的伤痛 和lua区别还是有的。 llvm是编译器后端,前端词语法分析之后,要生成机器代码。这个过程它首先自己定义了一个虚拟机,先生成自己的字节代码,然后,讲这个代码转化成对应系统结构。 在这个编译过程中。加入了流程控制。。。可以让开发者介入。
    回应 2015-04-18 15:38:46
  • 伪装的伤痛
    我好像看明白了, 意思就是动态编译, 然后把各种函数添加到它的LLVM里面, 然后执行。 跟传统的LUA 思想差不多, 可能作者在LLVM里面加入了一下类似VMP的技术? 但是VMP不是要给定代码片段然后编译,生成中间代码, 放在虚拟机上跑吗?LLVM这种看上去跟LUA差不多, 而且使用相对较复杂。 lua.addfun("funname", fun);
    回应 2015-04-18 12:14:48
  • 玩命
    没看懂~~~ 年龄大了 智商有退化倾向
    回应 2015-04-17 16:21:04
llvm之旅第三站 - 认识LLVM IR

作者信息

  • charme
  • 2015-03-30日入驻

收藏 0

文章 7

进入个人主页

娜迦,守护10亿移动用户安全! 免费体验