LLVM构建IR代码

发布于 2019-05-29  85 次阅读


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


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

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

代码中我只做了基本的解释,详细的接口说明,参考 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