我的LLVM学习笔记——编写LLVM demo

一、安装LLVM

 

二、使用CLion创建demo工程

main.cpp代码如下:


#include "llvm/IR/Verifier.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/Interpreter.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
//#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/IR/ValueSymbolTable.h"

using namespace llvm;

void register_printf(llvm::Module *module) {
    std::vector printf_arg_types;
    printf_arg_types.push_back(llvm::Type::getInt8PtrTy(module->getContext()));

    llvm::FunctionType* printf_type =
            llvm::FunctionType::get(
                    llvm::Type::getInt32Ty(module->getContext()), printf_arg_types, true);

    llvm::Function *func = llvm::Function::Create(
            printf_type, llvm::Function::ExternalLinkage,
            llvm::Twine("printf"),
            module
    );
    func->setCallingConv(llvm::CallingConv::C);
}


int main(){
    InitializeNativeTarget();
    LLVMContext Context;
    Module* M = new Module("main", Context);

    register_printf(M);

    // 校验问题, 这个函数需要一个输出流来打印错误信息
    if (verifyModule(*M, &errs())) {
        errs() << "构建LLVM字节码出错!\n";
        exit(1);
    }

    // 输出llvm字节码
    outs() << "LLVM module:\n\n" << *M;
    outs() << "\n\n";
    outs().flush();

    // 输出二进制BitCode到.bc文件
    std::error_code ErrInfo;
    raw_ostream *out = new raw_fd_ostream("a.bc", ErrInfo, sys::fs::F_None);
//    WriteBitcodeToFile(M, *out);
    out->flush(); delete out;

    // 关闭LLVM释放内存
    llvm_shutdown();
    return 0;
}

 

CMakeLists.txt代码如下:


cmake_minimum_required(VERSION 3.14)
project(TestLLVM)

set(CMAKE_CXX_STANDARD 11)
## 定义需要的库
set(LLVM_LINK_COMPONENTS
        all
        )

# 使用llvm
find_package(LLVM REQUIRED CONFIG)

set(SOURCE_FILES main.cpp)

#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")


# 添加头文件路径
message(STATUS "include path: ${LLVM_INCLUDE_DIRS}")
include_directories(${LLVM_INCLUDE_DIRS})


#add_definitions(${LLVM_DEFINITIONS})
#message(STATUS "LLVM_DEFINITIONS: ${LLVM_DEFINITIONS}")


add_executable(TestLLVM ${SOURCE_FILES})

# 寻找对应的库
llvm_map_components_to_libnames(llvm_libs ${LLVM_LINK_COMPONENTS})

# 将库与目标代码一起链接
target_link_libraries(TestLLVM ${llvm_libs})

 

三、关键点记录

1,set(CMAKE_CXX_STANDARD 11)

通过在cmake文件中添加该属性,可以设置采用c++ 11进行编译。另外还可以采用第二种方式,如下:

add_compile_options(-std=c++11)

add_compile_options是针对所有类型编译器的,在编译c代码时可能会有问题,所以还可以采用第三种方式,如下

add_definitions(${LLVM_DEFINITIONS} -std=c++11)

更多cmake命令可以参考:https://cmake.org/cmake/help/v3.1/manual/cmake-commands.7.html

 

2,llvm_map_components_to_libnames

它会将需要的库与目标代码进行连接,在上面的例子中,我们设置的属性为all,所有库都被链接。可以通过命令行执行llvm-config --components 命令来查看所有的components,按照自己需要进行链接

 

 

 

你可能感兴趣的:(LLVM)