llvmllvm 시작하기


비고

이 섹션에서는 llvm이 무엇인지, 그리고 개발자가 왜 그것을 사용하고 싶어하는지에 대한 개요를 제공합니다.

또한 llvm에있는 큰 주제를 언급하고 관련 주제에 링크해야합니다. llvm에 대한 문서가 새롭기 때문에 이러한 관련 주제의 초기 버전을 만들어야 할 수도 있습니다.

llvm 4.0의 간단한 함수 컴파일

그래서 우리가하려고 할 것은 다음과 같은 함수를 컴파일하는 것입니다.

int sum(int a, int b) {
    return a + b + 2;
}
 

즉석에서. .cpp 예제 전체가 다음과 같습니다.

#include <iostream>

#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Verifier.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/Support/TargetSelect.h"

// Optimizations
#include "llvm/Transforms/Scalar.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"

using namespace llvm;


llvm::Function* createSumFunction(Module* module) {
    /* Builds the following function:
    
    int sum(int a, int b) {
        int sum1 = 1 + 1;
        int sum2 = sum1 + a;
        int result = sum2 + b;
        return result;
    }
    */

    LLVMContext &context = module->getContext();
    IRBuilder<> builder(context);

    // Define function's signature
    std::vector<Type*> Integers(2, builder.getInt32Ty());
    auto *funcType = FunctionType::get(builder.getInt32Ty(), Integers, false);

    // create the function "sum" and bind it to the module with ExternalLinkage,
    // so we can retrieve it later
    auto *fooFunc = Function::Create(
        funcType, Function::ExternalLinkage, "sum", module
    );

    // Define the entry block and fill it with an appropriate code
    auto *entry = BasicBlock::Create(context, "entry", fooFunc);
    builder.SetInsertPoint(entry);

    // Add constant to itself, to visualize constant folding
    Value *constant = ConstantInt::get(builder.getInt32Ty(), 0x1);
    auto *sum1 = builder.CreateAdd(constant, constant, "sum1");

    // Retrieve arguments and proceed with further adding...
    auto args = fooFunc->arg_begin();
    Value *arg1 = &(*args);
    args = std::next(args);
    Value *arg2 = &(*args);
    auto *sum2 = builder.CreateAdd(sum1, arg1, "sum2");
    auto *result = builder.CreateAdd(sum2, arg2, "result");  
    
    // ...and return
    builder.CreateRet(result);

    // Verify at the end
    verifyFunction(*fooFunc);
    return fooFunc;
};

int main(int argc, char* argv[]) {
    // Initilaze native target
    llvm::TargetOptions Opts;
    InitializeNativeTarget();
    InitializeNativeTargetAsmPrinter();

    LLVMContext context;
    auto myModule = make_unique<Module>("My First JIT", context);
    auto* module = myModule.get();

    std::unique_ptr<llvm::RTDyldMemoryManager> MemMgr(new llvm::SectionMemoryManager());

    // Create JIT engine
    llvm::EngineBuilder factory(std::move(myModule));
    factory.setEngineKind(llvm::EngineKind::JIT);
    factory.setTargetOptions(Opts);
    factory.setMCJITMemoryManager(std::move(MemMgr));
    auto executionEngine = std::unique_ptr<llvm::ExecutionEngine>(factory.create());
    module->setDataLayout(executionEngine->getDataLayout());

    // Create optimizations, not necessary, whole block can be ommited.
    // auto fpm = llvm::make_unique<legacy::FunctionPassManager>(module);
    // fpm->add(llvm::createBasicAAWrapperPass());
    // fpm->add(llvm::createPromoteMemoryToRegisterPass());
    // fpm->add(llvm::createInstructionCombiningPass());
    // fpm->add(llvm::createReassociatePass());
    // fpm->add(llvm::createNewGVNPass());
    // fpm->add(llvm::createCFGSimplificationPass());
    // fpm->doInitialization();

    auto* func = createSumFunction(module);  // create function
    executionEngine->finalizeObject();       // compile the module
    module->dump();                          // print the compiled code

    // Get raw pointer
    auto* raw_ptr = executionEngine->getPointerToFunction(func);
    auto* func_ptr = (int(*)(int, int))raw_ptr;

    // Execute
    int arg1 = 5;
    int arg2 = 7;
    int result = func_ptr(arg1, arg2);
    std::cout << arg1 << " + " << arg2 << " + 1 + 1 = " << result << std::endl;

    return 0;
}
 

clang ++ - 4.0 과 함께 다음 플래그를 사용하여 컴파일 할 때 잘 작동합니다.

$ llvm-config-4.0 --cxxflags --libs core
 

설치 또는 설정

항상 LLVM 공식 웹 사이트 를 방문하여 OS에 따라 설치 가이드를 따르는 것이 좋습니다.

posix에서 작업하고 있다면 간단히 공식 LLVM 패키지 저장소 중 하나를 추가해야 합니다 . 예를 들어 Ubuntu Xenial (16.04)에서 작업하는 경우 debdeb-src 항목을 /etc/apt/sources.list 파일에 추가합니다.

$ sudo su
$ echo deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-4.0 main \ >> /etc/apt/sources.list
$ echo deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-4.0 main \ >> /etc/apt/sources.list
 

한 번 설치하면 설치가 간단 해집니다.

$ sudo apt update
$ sudo apt install clang-X
 

여기서 X 는 찾고있는 버전입니다 (4.0은이 글을 쓰는 시점의 현재 버전 임).

clang은 LLVM을 통해 작성된 C / C ++ 컴파일러이며 (실제로는 현재 자체 호스팅 됨) 모든 LLVM 라이브러리와 함께 제공됩니다. 일단 당신이 그것을하면 모든 turorial에 가서 코딩을 시작할 수 있습니다.

원하는 경우 LLVM 라이브러리를 수동으로 설치할 수 있습니다. 이를 위해서는 apt install llvm-Y 해야합니다. 여기서 Y 는 찾고있는 라이브러리입니다. 그러나 clang을 사용하여 프로젝트를 사용하여 LLVM을 컴파일하는 것이 좋습니다.

일단 그렇게하면 llvm-config 도구가 있어야합니다. 올바른 LLVM 프로젝트 컴파일에 필요한 컴파일러 플래그를 얻는 것은 매우 유용합니다. 그래서 그것이 작동 한 첫 번째 테스트는

$ llvm-config-4.0 --cxxflags --libs engine
-I/usr/lib/llvm-4.0/include -std=c++0x -gsplit-dwarf -Wl,-fuse-ld=gold -fPIC -fvisibility-inlines-hidden -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wno-maybe-uninitialized -Wdelete-non-virtual-dtor -Wno-comment -Werror=date-time -std=c++11 -ffunction-sections -fdata-sections -O2 -g -DNDEBUG  -fno-exceptions -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
-lLLVM-4.0
 

다른 플래그 세트를 얻을 수도 있습니다. 걱정하지 마십시오. command not found 실패하지 않는 한 당신은 괜찮을 것입니다.

다음 단계는 실제 LLVM 라이브러리 자체를 테스트하는 것입니다. 그래서 간단한 llvmtest.cpp 파일을 만들 수 있습니다 :

#include <iostream>
#include "llvm/IR/LLVMContext.h"

int main() {
    llvm::LLVMContext context;
    std::cout << &context << std::endl;
    return 0;
};
 

사실 std::cout 사용하여 실제로 context 변수를 사용합니다 (컴파일러가 컴파일 단계에서 제거하지 않도록). 이제 파일을 컴파일하십시오.

$ clang++-4.0 -o llvmtest `llvm-config-4.0 --cxxflags --libs engine` llvmtest.cpp
 

시험해 봐.

$ ./llvmtest
0x7ffd85500970
 

축하해! LLVM을 사용할 준비가되었습니다.