├── .gitignore ├── README.md ├── example.png ├── pdg.cpp └── pdg.so /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LLVM-Program-Dependency-Graph-Generator 2 | 3 | ** Please make sure you have LLVM installed ** 4 | 5 | A pass that can generate PDG(in *.dot) for LLVM. 6 | 7 | As LLVM dosen't provide ways to generate Program Dependency Graph(PDG), and I need to use them in one of my project. 8 | I wrote this simple generation pass that can help generate PDG for a *.bc file. 9 | 10 | You can feel free to use it if you needed with simple insturctions like 11 | 12 | `"opt -load ./pdg.so -pdg < "filename" > /dev/null"` 13 | 14 | and it will generate a *.dot format output for each functions in the *.bc file 15 | like 16 | 17 |
18 | digraph add{
19 |
20 | "a" -> " %1 = getelementptr inbounds %struct.Node, %struct.Node* %a, i64 0, i32 0";
21 | "a" [ color = red ]
22 | " %1 = getelementptr inbounds %struct.Node, %struct.Node* %a, i64 0, i32 0" -> " %2 = load volatile %struct.Node*, %struct.Node** %1, align 8, !tbaa !2";
23 | "b" -> " %3 = getelementptr inbounds %struct.Node, %struct.Node* %b, i64 0, i32 0";
24 | "b" [ color = red ]
25 | " %2 = load volatile %struct.Node*, %struct.Node** %1, align 8, !tbaa !2" -> " store volatile %struct.Node* %2, %struct.Node** %3, align 8, !tbaa !2";
26 | " %3 = getelementptr inbounds %struct.Node, %struct.Node* %b, i64 0, i32 0" -> " store volatile %struct.Node* %2, %struct.Node** %3, align 8, !tbaa !2";
27 | "b" -> " %4 = getelementptr inbounds %struct.Node, %struct.Node* %b, i64 0, i32 1";
28 | "b" [ color = red ]
29 | "a" -> " store volatile %struct.Node* %a, %struct.Node** %4, align 8, !tbaa !8";
30 | "a" [ color = red ]
31 | " %4 = getelementptr inbounds %struct.Node, %struct.Node* %b, i64 0, i32 1" -> " store volatile %struct.Node* %a, %struct.Node** %4, align 8, !tbaa !8";
32 | " %1 = getelementptr inbounds %struct.Node, %struct.Node* %a, i64 0, i32 0" -> " %5 = load volatile %struct.Node*, %struct.Node** %1, align 8, !tbaa !2";
33 | " %5 = load volatile %struct.Node*, %struct.Node** %1, align 8, !tbaa !2" -> " %6 = getelementptr inbounds %struct.Node, %struct.Node* %5, i64 0, i32 1";
34 | "b" -> " store volatile %struct.Node* %b, %struct.Node** %6, align 8, !tbaa !8";
35 | "b" [ color = red ]
36 | " %6 = getelementptr inbounds %struct.Node, %struct.Node* %5, i64 0, i32 1" -> " store volatile %struct.Node* %b, %struct.Node** %6, align 8, !tbaa !8";
37 | "b" -> " store volatile %struct.Node* %b, %struct.Node** %1, align 8, !tbaa !2";
38 | "b" [ color = red ]
39 | " %1 = getelementptr inbounds %struct.Node, %struct.Node* %a, i64 0, i32 0" -> " store volatile %struct.Node* %b, %struct.Node** %1, align 8, !tbaa !2";
40 |
41 | }
42 |
43 |
44 | and picture like below can be genertated by using *.dot drawer.( "dot" command under *.unix with graphviz)
45 | 
46 |
47 |
48 |
--------------------------------------------------------------------------------
/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DengMinghua/LLVM-Program-Dependency-Graph-Generator/faf85d4d4b0ff1df2d09cf066b8b8cbbab9ffda2/example.png
--------------------------------------------------------------------------------
/pdg.cpp:
--------------------------------------------------------------------------------
1 | #include "llvm/ADT/Statistic.h"
2 | #include "llvm/IR/Function.h"
3 | #include "llvm/Pass.h"
4 | #include "llvm/Support/raw_ostream.h"
5 | using namespace llvm;
6 |
7 | #define DEBUG_TYPE "hello"
8 |
9 | namespace {
10 | struct Hello :public FunctionPass {
11 | static char ID;
12 | Hello():FunctionPass(ID){}
13 | virtual bool runOnFunction(Function &F) override {
14 | errs()<< "digraph "+F.getName() + "{\n";
15 | errs() << "\n";
16 | for(auto block = F.getBasicBlockList().begin();block != F.getBasicBlockList().end();block++)
17 | {
18 | for (auto inst = block->begin(); inst != block->end(); inst++)
19 | {
20 | for(Use &U:inst->operands())
21 | {
22 | Value *v = U.get();
23 | if(dyn_cast