Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LLVM run PassManager (non-legacy)

How do I run a non-legacy PassManager? I have tried doing the following but there is some exception thrown when trying to invalidate the analysis manager in the run function. Is there something else I should do for initialization?

llvm::AnalysisManager<Module> mm;
PassBuilder builder;
auto pm = builder.buildModuleOptimizationPipeline(PassBuilder::OptimizationLevel::O3);
pm.run(module, mm );
like image 300
Moinak Bhattacharyya Avatar asked Jul 31 '17 08:07

Moinak Bhattacharyya


1 Answers

These snippets illustrate how to run and setup to run modern custom function and module pass on some .c/.cpp file... complete with a makefile. This works for LLVM 6 which is pretty recent (march 2018). It does not use the legacy pass manager. HelloWorld.cpp:

#include <llvm/Pass.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Module.h>
#include <llvm/Support/raw_ostream.h>

namespace {

  struct Hello : public llvm::FunctionPass {
    static char ID;
    Hello() : llvm::FunctionPass{ID} {}

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

  struct Hello2 : public llvm::ModulePass {
    static char ID;

    Hello2() : llvm::ModulePass{ID} {}

    bool runOnModule(llvm::Module &M) override {
      llvm::errs() << "Name of the module ", llvm::errs().write_escaped(M.getName()) << "\n";
      for(auto iter = M.getFunctionList().begin(); iter != M.getFunctionList().end(); ++iter) {
    llvm::errs() << "Function name:" << iter->getName() << "\n";
      }
      return false;
    }
  };
}

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

char Hello2::ID = 1;
static llvm::RegisterPass<Hello2> Y("Hello2", 
                    "Hello World2 pass",
                    false,  
                    false
);

Corresponding makefile:

LLVM_VERSION=
LLVM_INCLUDEDIR = `llvm-config-6.0 --includedir`
LLVM_FLAGS = `llvm-config-6.0 --cxxflags --ldflags --system-libs --libs all`
CXX = clang++-6.0
CXXFLAGS = -g -std=c++11 -O3 -I $(LLVM_INCLUDEDIR) -I $(LLVM_INCLUDEDIR)
Hello.so:
    $(CXX) -fPIC $(CXXFLAGS) HelloWorld.cpp $(LLVM_FLAGS) -shared -o Hello.so
Hello: Hello.so

testfile:
    clang++-6.0 -emit-llvm -c test.cpp -o test.bc

runFunctionPassOnTestFile: Hello testfile
    opt-6.0 -load ./Hello.so -Hello < test.bc > /dev/null

runModulePassOnTestfile: Hello testfile
    opt-6.0 -load ./Hello.so -Hello2 < test.bc > /dev/null

clean:
    rm *.o *.so *.out *~
DBG:
@echo LLVM INCLUDE DIRS $(LLVM_INCLUDEDIR) $(test)

A simple file to test everything on, test.cpp:

#include <stdio.h>
#include <stdlib.h>

int a = 4;

int c = 5;

int d = 6;

int e = 7;

int bar() { int *a = (int*) malloc(4); e = 1; return 1;}

int foo() { return 2; }

int barfoo() { return 3; }

int main() {
  printf("Testing testing\n");
  return 0;
}
like image 149
JKRT Avatar answered Oct 31 '22 10:10

JKRT