LLVM(3)编写Pass

2023-10-13 10:29:01 浏览数 (1)

总结

LLVM Pass简单总结:对IR进行遍历、优化的逻辑,例如:

代码语言:javascript复制
opt --help
	...
	...
	Optimizations available (use '-passes=' for the new pass manager)
		...
		...
        --loop-deletion         - Delete dead loops
        --memcpyopt             - MemCpy Optimization
        --print-callgraph       - Print a call graph
        ...
        ...

opt提供了很多pass,例如检测代码中的死循环、对代码中的memcpy优化、遍历全部函数分析调用关系等等。

上述都是pass可实现的功能,llvm工程中给出了一个实例:

hello pass实例

LLVM version 16.0.6

库中位置:llvm/lib/Transforms/Hello/Hello.cpp

代码语言:javascript复制
//===- Hello.cpp - Example code from "Writing an LLVM Pass" ---------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements two versions of the LLVM "Hello World" pass described
// in docs/WritingAnLLVMPass.html
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

#define DEBUG_TYPE "hello"

STATISTIC(HelloCounter, "Counts number of functions greeted");

namespace {
  // Hello - The first implementation, without getAnalysisUsage.
  struct Hello : public FunctionPass {
    static char ID; // Pass identification, replacement for typeid
    Hello() : FunctionPass(ID) {}

    bool runOnFunction(Function &F) override {
        HelloCounter;
      errs() << "Hello: ";
      errs().write_escaped(F.getName()) << 'n';
      return false;
    }
  };
}

char Hello::ID = 0;
static RegisterPass<Hello> X("hello", "Hello World Pass");

namespace {
  // Hello2 - The second implementation with getAnalysisUsage implemented.
  struct Hello2 : public FunctionPass {
    static char ID; // Pass identification, replacement for typeid
    Hello2() : FunctionPass(ID) {}

    bool runOnFunction(Function &F) override {
        HelloCounter;
      errs() << "Hello: ";
      errs().write_escaped(F.getName()) << 'n';
      return false;
    }

    // We don't modify the program, so we preserve all analyses.
    void getAnalysisUsage(AnalysisUsage &AU) const override {
      AU.setPreservesAll();
    }
  };
}

char Hello2::ID = 0;
static RegisterPass<Hello2>
Y("hello2", "Hello World Pass (with getAnalysisUsage implemented)");

这个pass会跟着工程编译,无需自己编译了。

生成的so位置:pathto/llvm-project/build/lib/LLVMHello.so

如何使用pass?

pass需要分析IR,先生成一个IR:

t3.cpp

代码语言:javascript复制
int g_var = 0;

int factorial(int val);

int factorial(int val)
{
	g_var = 1;
	if (val <= 2)
		return 1;

	return factorial(val - 1)   factorial(val - 2);
}

int factorial_iter(int val)
{
	int temp = 1;
	for (int i = 2; i <= val;   i)
		temp *= i;
	return temp;
}

int main(int argc, char **argv)
{
	return factorial(2) * 7 == 42;
}

生成IR

$ clang -O0 -emit-llvm t3.cpp -c -o t3.bc

用pass分析t3.bc

代码语言:javascript复制
$ opt  -load pathto/llvm-project/build/lib/LLVMHello.so -enable-new-pm=0 -hello t3.bc
Hello: _Z9factoriali
Hello: _Z14factorial_iteri
Hello: main

0 人点赞