Mercurial > hg > CbC > CbC_llvm
comparison tools/clang/lib/Frontend/DependencyGraph.cpp @ 0:95c75e76d11b LLVM3.4
LLVM 3.4
author | Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 12 Dec 2013 13:56:28 +0900 |
parents | |
children | 54457678186b |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:95c75e76d11b |
---|---|
1 //===--- DependencyGraph.cpp - Generate dependency file -------------------===// | |
2 // | |
3 // The LLVM Compiler Infrastructure | |
4 // | |
5 // This file is distributed under the University of Illinois Open Source | |
6 // License. See LICENSE.TXT for details. | |
7 // | |
8 //===----------------------------------------------------------------------===// | |
9 // | |
10 // This code generates a header dependency graph in DOT format, for use | |
11 // with, e.g., GraphViz. | |
12 // | |
13 //===----------------------------------------------------------------------===// | |
14 | |
15 #include "clang/Frontend/Utils.h" | |
16 #include "clang/Basic/FileManager.h" | |
17 #include "clang/Basic/SourceManager.h" | |
18 #include "clang/Frontend/FrontendDiagnostic.h" | |
19 #include "clang/Lex/PPCallbacks.h" | |
20 #include "clang/Lex/Preprocessor.h" | |
21 #include "llvm/ADT/SetVector.h" | |
22 #include "llvm/Support/GraphWriter.h" | |
23 #include "llvm/Support/raw_ostream.h" | |
24 | |
25 using namespace clang; | |
26 namespace DOT = llvm::DOT; | |
27 | |
28 namespace { | |
29 class DependencyGraphCallback : public PPCallbacks { | |
30 const Preprocessor *PP; | |
31 std::string OutputFile; | |
32 std::string SysRoot; | |
33 llvm::SetVector<const FileEntry *> AllFiles; | |
34 typedef llvm::DenseMap<const FileEntry *, | |
35 SmallVector<const FileEntry *, 2> > DependencyMap; | |
36 | |
37 DependencyMap Dependencies; | |
38 | |
39 private: | |
40 raw_ostream &writeNodeReference(raw_ostream &OS, | |
41 const FileEntry *Node); | |
42 void OutputGraphFile(); | |
43 | |
44 public: | |
45 DependencyGraphCallback(const Preprocessor *_PP, StringRef OutputFile, | |
46 StringRef SysRoot) | |
47 : PP(_PP), OutputFile(OutputFile.str()), SysRoot(SysRoot.str()) { } | |
48 | |
49 virtual void InclusionDirective(SourceLocation HashLoc, | |
50 const Token &IncludeTok, | |
51 StringRef FileName, | |
52 bool IsAngled, | |
53 CharSourceRange FilenameRange, | |
54 const FileEntry *File, | |
55 StringRef SearchPath, | |
56 StringRef RelativePath, | |
57 const Module *Imported); | |
58 | |
59 virtual void EndOfMainFile() { | |
60 OutputGraphFile(); | |
61 } | |
62 | |
63 }; | |
64 } | |
65 | |
66 void clang::AttachDependencyGraphGen(Preprocessor &PP, StringRef OutputFile, | |
67 StringRef SysRoot) { | |
68 PP.addPPCallbacks(new DependencyGraphCallback(&PP, OutputFile, SysRoot)); | |
69 } | |
70 | |
71 void DependencyGraphCallback::InclusionDirective(SourceLocation HashLoc, | |
72 const Token &IncludeTok, | |
73 StringRef FileName, | |
74 bool IsAngled, | |
75 CharSourceRange FilenameRange, | |
76 const FileEntry *File, | |
77 StringRef SearchPath, | |
78 StringRef RelativePath, | |
79 const Module *Imported) { | |
80 if (!File) | |
81 return; | |
82 | |
83 SourceManager &SM = PP->getSourceManager(); | |
84 const FileEntry *FromFile | |
85 = SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(HashLoc))); | |
86 if (FromFile == 0) | |
87 return; | |
88 | |
89 Dependencies[FromFile].push_back(File); | |
90 | |
91 AllFiles.insert(File); | |
92 AllFiles.insert(FromFile); | |
93 } | |
94 | |
95 raw_ostream & | |
96 DependencyGraphCallback::writeNodeReference(raw_ostream &OS, | |
97 const FileEntry *Node) { | |
98 OS << "header_" << Node->getUID(); | |
99 return OS; | |
100 } | |
101 | |
102 void DependencyGraphCallback::OutputGraphFile() { | |
103 std::string Err; | |
104 llvm::raw_fd_ostream OS(OutputFile.c_str(), Err); | |
105 if (!Err.empty()) { | |
106 PP->getDiagnostics().Report(diag::err_fe_error_opening) | |
107 << OutputFile << Err; | |
108 return; | |
109 } | |
110 | |
111 OS << "digraph \"dependencies\" {\n"; | |
112 | |
113 // Write the nodes | |
114 for (unsigned I = 0, N = AllFiles.size(); I != N; ++I) { | |
115 // Write the node itself. | |
116 OS.indent(2); | |
117 writeNodeReference(OS, AllFiles[I]); | |
118 OS << " [ shape=\"box\", label=\""; | |
119 StringRef FileName = AllFiles[I]->getName(); | |
120 if (FileName.startswith(SysRoot)) | |
121 FileName = FileName.substr(SysRoot.size()); | |
122 | |
123 OS << DOT::EscapeString(FileName) | |
124 << "\"];\n"; | |
125 } | |
126 | |
127 // Write the edges | |
128 for (DependencyMap::iterator F = Dependencies.begin(), | |
129 FEnd = Dependencies.end(); | |
130 F != FEnd; ++F) { | |
131 for (unsigned I = 0, N = F->second.size(); I != N; ++I) { | |
132 OS.indent(2); | |
133 writeNodeReference(OS, F->first); | |
134 OS << " -> "; | |
135 writeNodeReference(OS, F->second[I]); | |
136 OS << ";\n"; | |
137 } | |
138 } | |
139 OS << "}\n"; | |
140 } | |
141 |