LLVM 使用手册

作者: AirChen | 来源:发表于2020-02-10 13:16 被阅读0次

    简介

    LLVM 是一个发展中的前言编辑器技术框架,它易于扩展并设计成多个库的形式,可以为编译器开发者提供流畅的体验,并能使编译器开发所涉及的学习过程变得非常流畅。

    LLVM 架构特性

    1. C++ 语言实现
    2. 前端与后端分离,支持多种前端和后端,使用中间代码 IR 进行衔接
    LLVM 架构组成
    1. 第一个 Release 版本发布于 2003 年,代码开源
    2. 提供了很多工具用于编译和优化代码
    LLVM 工具集
    1. 与 GCC 相比,编译出的程序运行效率更高

    Tools 使用

    LLVM 的一些优化和绘图都针对 bitcode 文件,这里介绍与之相关的工具使用

    从 源文件 生成 bitcode 文件

    clang -c -emit-llvm const.c -o const.bc
    

    clang 是 LLVM 的前端编译工具,可以用它来生成目标文件,这个指令将 .c 代码生成 .bc 文件.

    warning:
    使用这个命令的时候会自动带有 -O0 级别的优化(新版本中),可以禁止它,参考

    clang -c -emit-llvm -Xclang -disable-O0-optnone const.c -o const.bc    
    

    llvm tools 提供了产生 cfg callgraph 等图片参数的工具(opt),注意,不会自己生成图片,还需要工具(如:graphviz MacOS下安装 brew install graphviz)
    cfg 图

    opt –view-cfg const.bc
    

    call 图

    opt -view-callgraph file.bc
    

    中间代码优化
    用 opt ,还可以调用 LLVM 提供的优化器对 bitcode 文件进行代码优化

    opt -mem2reg const.bc -o const.reg.bc
    

    -constprop 临时变量
    -early-cse 消除公共部分
    运行 help ,可以查看 LLVM 提供的优化器

    opt -help
    

    -load 可以加载自定义的优化器(或其他分析器),如

    opt -load LLVMCountOp.dylib -opCounter file.bc -o file.oc.bc
    opt -load LLVMCountOp.dylib -help
    

    -opCounter LLVMCountOp.dylib 里面 Pass 的注册标记

    如果仅仅分析代码,可以用 -disable-output 禁用输出

    opt -load LLVMCountOp.dylib -opCounter -disable-output -time-passes file.bc
    

    -time-passes pass 运行时间

    bitcode 文件生产 .ll ,中间代码 IR 文件

    llvm-dis const.bc  
    

    可以对 .ll 进行即时运行(JIT)

    lli const.ll   
    

    bitcode 文件生成可执行文件

    clang const.ll
    ./a.out
    

    bitcode 文件生成目标平台机器码

    llc -march=x86 ex0.reg.bc -o ex0.reg.x86
    

    使用官方二进制库

    LLVM 官网提供了各个版本的下载,有二进制文件和源码,使用二进制文件中包含了可以直接运行在目标平台的 Tools 和 LLVM 的基础功能静态库。
    直接使用二进制静态库,可以开发出我们自己的编译工具,Tools 里有 llvm-config 提供了补充 LLVM 各个依赖参数功能,可以方便编写 MakeFile 文件,编译工程。
    仓库下 JIT 提供了一个编译工具的工程,依赖的 LLVM 版本是 3.4 。提供了一个通用的 MakeFile 模板。

    LLVM_CONFIG ?= ../bin_3.4/bin/llvm-config
    
    ifndef VERBOSE
    QUIET := @
    endif
    
    SRC_DIR ?= $(PWD)
    
    LLVM_LDFLAGS := $(shell $(LLVM_CONFIG) --ldflags)
    COMMON_FLAGS = -Wall -Wextra
    LLVM_CXXFLAGS += $(COMMON_FLAGS) $(shell $(LLVM_CONFIG) --cxxflags)
    LLVM_CPPFLAGS += $(shell $(LLVM_CONFIG) --cppflags) -I$(SRC_DIR)
    LLVM_LIBS = $(shell $(LLVM_CONFIG) --libs jit interpreter nativecodegen)
    
    objects = Driver.o Expr.o Lexer.o Parser.o
    name = driver
    
    default: $(name)
    
    $(name) : $(objects)
            @echo Linking $@
            $(QUIET)$(CXX) -o $@ $(LLVM_CXXFLAGS) $(LLVM_LDFLAGS) $^ $(LLVM_LIBS)
    
    %.o : %.cpp
            @echo Compiling $*.cpp
            $(QUIET)$(CXX) -c $< $(LLVM_CPPFLAGS) -o $@
    
    clean::
            $(QUIET)rm -f $(name) $(objects)
    

    系统下配置好 clang 环境,然后设置好 LLVM_CONFIG 目录,即可运行 make 命令,进行编译。

    使用官方源码

    借助于官网提供的源代码也能开发出高效工具,这里以 Pass 的开发为例。
    从官网找到一个版本(如:3.4)的代码后,下载到本地,代码工程由 cmake 工具组织,可以在工程下创建目录llvm_xcode,然后进入目录执行

    cmake -G Xcode ../llvm 
    

    就能生成支持 Xcode 的项目,用 Xcode IDE 可以打开工程(还支持其他IDE工具,详情参考官网)。
    在源码工程下我们可以找到一个实例工程 Hello ,这是一个 Pass 工程,在 llvm/lib/Transforms 目录下(不是 llvm_xcode 下的 lib)。我们使用目录工具进入该文件下,模仿Hello工程的配置,新建自己的工程,修改 Transforms 目录下的 CMakeList.txt Makefile 和 子目录下的文件。然后回到 llvm_xcode 目录下,再执行一遍 cmake 指令。
    Xcode IDE 可以对工程代码进行编辑,编译完成后,可以对目标 Target 进行编译。会生成以动态链接库,放在工程下验证, 仓库 Passes 下提供了编译好的库,可以直接使用。

    常见错误:

    Error opening 'LLVMCountOp.dylib': dlopen(LLVMCountOp.dylib, 9): Symbol not found: __ZN4llvm12FunctionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
      Referenced from: LLVMCountOp.dylib
      Expected in: flat namespace
    

    加载的 Pass 和 opt 版本不对,或者 Release Debug 不一致

    参考

    Makefile 调用 llvm-config

    llvm-config 官文

    Makefile 官文

    课件官网

    相关文章

      网友评论

        本文标题:LLVM 使用手册

        本文链接:https://www.haomeiwen.com/subject/prjaxhtx.html