lynklody / HelloPass-LLVM

Getting started for LLVM pass writing

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

HelloPass-LLVM

Getting started for LLVM pass writing

Setup

  1. Clone this repo, see the file details below:
  1. For Mac OSX users, uncomment the following line in Pass/Transforms/ValueNumbering/CMakeLists.txt
SET(CMAKE_MODULE_LINKER_FLAGS "-undefined dynamic_lookup")
  1. Move to Pass/build/ directory using cd command on your local system. Next, execute the following command. If it executes successfully, proceed to next step.
cmake -DCMAKE_BUILD_TYPE=Release ../Transforms/ValueNumbering
  1. Next execute make and it will generate *.so files under build directory.
make -j4
  1. Move to test/ directory and generate Test.ll file for Test.c using following command.
clang -Xclang -disable-O0-optnone Test.c -O0 -S -emit-llvm -o Test.ll
  1. Next generate Test.bc file for Test.ll using following command.
opt Test.ll -mem2reg -S -o Test.bc
  1. After generating test.bc, execute following command it execute the LLVM Pass.
opt -load ../Pass/build/libLLVMValueNumberingPass.so  -ValueNumbering < Test.bc > /dev/null

Code Explanation

  1. The implemented Pass extends from FunctionPass class and overrides runOnFunction(Function &F) function.
  2. runOnFunction(Function &F) function gets called the number of times as many number of functions are present in test code. Name of the function is available using following code snippet.
bool runOnFunction(Function &F) override {
	F.getName();
}
  1. We can iterate over basic blocks of the given function as:
bool runOnFunction(Function &F) override {
	for (auto& basic_block : F)
	{
		...
	}
}
  1. Next, we can iterate over the instructions in a basic block (BB). Note: instructions are in LLVM IR.
bool runOnFunction(Function &F) override {
	for (auto& basic_block : F)
	{
		for (auto& inst : basic_block)
		{
			...
		}
	}
}
  1. Once we get an instruction, then we can cast it as User and iterate over operands of that instruction.
auto* ptr = dyn_cast<User>(&inst);
for (auto it = ptr->op_begin(); it != ptr->op_end(); ++it) 
{
...
}
  1. Use Following API to check whether instruction is a binary operation (Assignment)
if (inst.isBinaryOp())
{
	...
}
  1. Use Following APIs to compare and find operator types
if (inst.isBinaryOp())
{
	inst.getOpcodeName(); //prints OpCode by name such as add, mul etc.
	if(inst.getOpcode() == Instruction::Add)
	{
		errs() << "This is Addition"<<"\n";
	}
	if(inst.getOpcode() == Instruction::Mul)
	{
		errs() << "This is Multiplication"<<"\n";
	}
    // See Other classes Instruction::Sub, Instruction::UDiv, Instruction::SDiv
}
  1. Implementation of runOnFunction(Function &F) looks as following in whole.
string func_name = "test";
bool runOnFunction(Function &F) override {
	errs() << "ValueNumbering: ";
	errs() << F.getName() << "\n";
	if (F.getName() != func_name) return false;
	for (auto& basic_block : F)
	{
		for (auto& inst : basic_block)
		{
			errs() << inst << "\n";
			auto* ptr = dyn_cast<User>(&inst);
			for (auto it = ptr->op_begin(); it != ptr->op_end(); ++it) 
			{
				errs() << "\t" << *(*it) << "\n";
			}
		}
	}
	return false;
}

About

Getting started for LLVM pass writing

License:MIT License


Languages

Language:C++ 44.7%Language:LLVM 40.0%Language:CMake 11.3%Language:C 4.0%