CC S02E04

April 3, 2013, 8:06 p.m.

Clang, LLVM tools

Рассмотрим исходник.

#include <stdio.h>

int main() {
    printf("hello");
    return 0;
}

Вот что мы можем с ним сделать:

.PHONY: byte-code interpret assembler code-generator native compile run

help:
    @echo "tagets: byte-code interpret assembler code-generator native compile run help"

compile:
    clang hello.c -o hello

byte-code:
    clang -O0 -emit-llvm hello.c -c -o hello.bc

assembler:
    llvm-dis-mp-3.2 < hello.bc | less

code-generator:
    llc-mp-3.2 -disable-cfi hello.bc -o hello.s

native:
    gcc hello.s -o hello.native

run:
    ./hello

interpret:
    lli-mp-3.2 hello.bc

Кодогенерация

one

Научимся генерировать код для функции

double one()
{
    return 1.0;
}

При помощи llvm это делается следующим образом:

#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/IRBuilder.h"
#include <vector>

int main(int argc, const char* argv[])
{
    using namespace llvm;

    IRBuilder<> builder(getGlobalContext());
    Module* theModule = new Module("module.1", getGlobalContext());

    std::vector<Type*> noParams;
    FunctionType* functionType = 
        FunctionType::get(Type::getDoubleTy(getGlobalContext()), noParams, false);
    Function* function = 
        Function::Create(functionType, Function::ExternalLinkage, "one", theModule);

    BasicBlock* bb = BasicBlock::Create(getGlobalContext(), "entry", function);
    builder.SetInsertPoint(bb);
    Value* d = ConstantFP::get(getGlobalContext(), APFloat(1.0)); 
    builder.CreateRet(d);

    verifyFunction(*function);

    theModule->dump();

    return 0;
}

И собирается так:

.PHONY: build

build:
     g++ -o one `llvm-config-mp-3.2 --cppflags --ldflags --libs core` one.cpp

Если запустить получившийся исполняемый файл, то на экран выведется

; ModuleID = 'module.1'

define double @one() {
entry:
  ret double 1.000000e+00
}

inc

Теперь рассмотрим более интересную функцию:

double inc(double x)
{
    return x + 1.0;
}

Код генерируем так:

#include "llvm/DerivedTypes.h"
#include "llvm/BasicBlock.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/IRBuilder.h"
#include <string>
#include <vector>
#include <iostream>

int main(int argc, const char* argv[])
{
    using namespace llvm;

    IRBuilder<> builder(getGlobalContext());
    Module* module = new Module("module.1", getGlobalContext());

    std::vector<Type*> doubles(1, Type::getDoubleTy(getGlobalContext()));
    FunctionType* functionType = 
        FunctionType::get(Type::getDoubleTy(getGlobalContext()), doubles, false);
    Function* function = 
        Function::Create(functionType, Function::ExternalLinkage, "inc", module);
    function->arg_begin()->setName("x");

    BasicBlock* bb = BasicBlock::Create(getGlobalContext(), "entry", function);
    builder.SetInsertPoint(bb);
    Value* d = ConstantFP::get(getGlobalContext(), APFloat(1.0)); 
    Value* inc = builder.CreateFAdd(function->arg_begin(), d, "addtmp");
    builder.CreateRet(inc);

    verifyFunction(*function);

    verifyModule(*module);

    module->dump();

    return 0;
}

Makefile:

.PHONY: build

build:
     g++ -o inc `llvm-config-mp-3.2 --cppflags --ldflags --libs core` inc.cpp

Результат запуска ./inc:

; ModuleID = 'module.1'

define double @inc(double %x) {
entry:
  %addtmp = fadd double %x, 1.000000e+00
  ret double %addtmp
}

Ссылки на документацию

Домашнее задание

Его нет. Празднуем начало весны.

comments powered by Disqus