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
}
Ссылки на документацию
- http://llvm.org - основной сайт
- http://llvm.org/docs/ - вся документация
- http://llvm.org/docs/LangRef.html - документация на внутренний язык llvm
- http://llvm.org/docs/ProgrammersManual.html - документация для программистов, использующих llvm
Домашнее задание
Его нет. Празднуем начало весны.