Skip to content
1 de abril de 2015 / rafaelti

LLVM – Primeiro pass

Objetivo

Criar o primeiro pass no LLVM

Plataforma

C/C++, LLVM e linux

Conhecimento

C/C++, LLVM e linux

Introdução

O pass do LLVM é parte fundamental para o compilador. Com os passes podemos otimizar e transformar os códigos.

Solução

No primeiro exemplo não utilizarei o hello world proposto na página do LLVM, utilizarei um exemplo do Prof. Fernando(sem autorização dele é claro, mas é para um bem maior). Este pass conta a quantidade de opcodes no programa.

Primeiro devemos criar o nosso pass, criei no diretório /llvm/lib/Transforms/CountOP

//CountOp.cpp
define DEBUG_TYPE "opCounter"
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
using namespace llvm;
namespace {
 struct CountOp : public FunctionPass {
	std::map<std::string, int> opCounter;
	static char ID;
	CountOp() : FunctionPass(ID) {}
	virtual bool runOnFunction(Function &F) {
		errs() << "Function " << F.getName() << '\n';
		for (Function::iterator bb = F.begin(), e = F.end(); bb != e; ++bb) {
			for (BasicBlock::iterator i = bb->begin(), e = bb->end(); i != e; ++i) {
				if(opCounter.find(i->getOpcodeName()) == opCounter.end()) {
					opCounter[i->getOpcodeName()] = 1;
				} else {
					opCounter[i->getOpcodeName()] += 1;
				}
			}
		}
		std::map <std::string, int>::iterator i = opCounter.begin();
		std::map <std::string, int>::iterator e = opCounter.end();
		while (i != e) {
			errs() << i->first << ": " << i->second << "\n";
			i++;
		}
		errs() << "\n";
		opCounter.clear();
		return false;
	}
 };
}
char CountOp::ID = 0;
static RegisterPass<CountOp> X("opCounter", "Counts opcodes per functions");

Agora precisamos do nosso makefile

##===- lib/Transforms/Hello/Makefile -----------------------*- Makefile -*-===##
#
#                     The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##

LEVEL = ../../..
LIBRARYNAME = CountOp
LOADABLE_MODULE = 1

include $(LEVEL)/Makefile.common

Ao executar o make será retornado

rafael@ubuntu: /opt/llvm/lib/Transforms/CountOp$ make
llvm[0]: Compiling CountOp.cpp for Release+Asserts build (PIC)
llvm[0]: Linking Release+Asserts Loadable Module CountOp.so

Nosso Pass está pronto.

Segundo passo é o código alvo, ou seja, o código que o pass utilizará para produzir os resultados desejados. Este pode ficar em qualquer lugar.

//teste.c
#include <stdio.h>
int main() {
  int c1 = 17;
  int c2 = 25;
  int c3 = c1 + c2;
  printf("Value = %d\n", c3);
}

Precisamos transformar nosso código em bytecodes com o comando abaixo

clang -c -emit-llvm teste.c -o teste.bc

Agora rodamos o pass obre o bytecode

opt -load CountOp.so -opCounter -disable-output teste.bc

O resultado

Function main
add: 1
alloca: 3
call: 1
load: 3
ret: 1
store: 3
Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: