blob: ba2bb3f87156526bb53d5b2e0e488dfe4b86c219 [file] [log] [blame]
Ted Kremenek97f75312007-08-21 21:42:03 +00001//===--- CFG.cpp - Classes for representing and building CFGs----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Ted Kremenek and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the CFG and CFGBuilder classes for representing and
11// building Control-Flow Graphs (CFGs) from ASTs.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/AST/CFG.h"
16#include "clang/AST/Expr.h"
Ted Kremenek95e854d2007-08-21 22:06:14 +000017#include "clang/AST/StmtVisitor.h"
Ted Kremenek97f75312007-08-21 21:42:03 +000018#include <iostream>
19#include <iomanip>
20#include <algorithm>
21using namespace clang;
22
23namespace {
24
25 // SaveAndRestore - A utility class that uses RIIA to save and restore
26 // the value of a variable.
27 template<typename T>
28 struct SaveAndRestore {
29 SaveAndRestore(T& x) : X(x), old_value(x) {}
30 ~SaveAndRestore() { X = old_value; }
31
32 T& X;
33 T old_value;
34 };
35}
36
37/// CFGBuilder - This class is implements CFG construction from an AST.
38/// The builder is stateful: an instance of the builder should be used to only
39/// construct a single CFG.
40///
41/// Example usage:
42///
43/// CFGBuilder builder;
44/// CFG* cfg = builder.BuildAST(stmt1);
45///
Ted Kremenek95e854d2007-08-21 22:06:14 +000046/// CFG construction is done via a recursive walk of an AST.
47/// We actually parse the AST in reverse order so that the successor
48/// of a basic block is constructed prior to its predecessor. This
49/// allows us to nicely capture implicit fall-throughs without extra
50/// basic blocks.
51///
52class CFGBuilder : public StmtVisitor<CFGBuilder,CFGBlock*> {
Ted Kremenek97f75312007-08-21 21:42:03 +000053 CFG* cfg;
54 CFGBlock* Block;
55 CFGBlock* Exit;
56 CFGBlock* Succ;
57 unsigned NumBlocks;
58
59public:
60 explicit CFGBuilder() : cfg(NULL), Block(NULL), Exit(NULL), Succ(NULL),
61 NumBlocks(0) {
62 // Create an empty CFG.
63 cfg = new CFG();
64 }
65
66 ~CFGBuilder() { delete cfg; }
67
68 /// buildCFG - Constructs a CFG from an AST (a Stmt*). The AST can
69 /// represent an arbitrary statement. Examples include a single expression
70 /// or a function body (compound statement). The ownership of the returned
71 /// CFG is transferred to the caller. If CFG construction fails, this method
72 /// returns NULL.
73 CFG* buildCFG(Stmt* Statement) {
74 if (!Statement) return NULL;
75
76 assert (cfg && "CFGBuilder should only be used to construct one CFG");
77
78 // Create the exit block.
79 Block = createBlock();
80 Exit = Block;
81
82 // Visit the statements and create the CFG.
Ted Kremenek95e854d2007-08-21 22:06:14 +000083 if (CFGBlock* B = Visit(Statement)) {
Ted Kremenek97f75312007-08-21 21:42:03 +000084 // Reverse the statements in the last constructed block. Statements
85 // are inserted into the blocks in reverse order.
86 B->reverseStmts();
87 // NULL out cfg so that repeated calls
88 CFG* t = cfg;
89 cfg = NULL;
90 return t;
91 }
92 else {
93 // Error occured while building CFG: Delete the partially constructed CFG.
94 delete cfg;
95 cfg = NULL;
96 return NULL;
97 }
98 }
Ted Kremenek95e854d2007-08-21 22:06:14 +000099
Ted Kremenek97f75312007-08-21 21:42:03 +0000100 // createBlock - Used to lazily create blocks that are connected
101 // to the current (global) succcessor.
102 CFGBlock* createBlock( bool add_successor = true ) {
103 CFGBlock* B = cfg->createBlock(NumBlocks++);
104 if (add_successor && Succ) B->addSuccessor(Succ);
105 return B;
106 }
Ted Kremenek97f75312007-08-21 21:42:03 +0000107
Ted Kremenek95e854d2007-08-21 22:06:14 +0000108 /// Here we handle statements with no branching control flow.
109 CFGBlock* VisitStmt(Stmt* Statement) {
110 // We cannot assume that we are in the middle of a basic block, since
111 // the CFG might only be constructed for this single statement. If
112 // we have no current basic block, just create one lazily.
113 if (!Block) Block = createBlock();
114
115 // Simply add the statement to the current block. We actually
116 // insert statements in reverse order; this order is reversed later
117 // when processing the containing element in the AST.
118 Block->appendStmt(Statement);
Ted Kremenek97f75312007-08-21 21:42:03 +0000119
120 return Block;
121 }
122
Ted Kremenek95e854d2007-08-21 22:06:14 +0000123 CFGBlock* VisitCompoundStmt(CompoundStmt* C) {
124 // The value returned from this function is the last created CFGBlock
125 // that represents the "entry" point for the translated AST node.
126 for (CompoundStmt::reverse_body_iterator I = C->body_rbegin(),
127 E = C->body_rend(); I != E; ++I )
128 // Add the statement to the current block.
129 if (!Visit(*I)) return NULL;
130
131 return Block;
132 }
133
134 CFGBlock* VisitIfStmt(IfStmt* I) {
135
136 // We may see an if statement in the middle of a basic block, or
137 // it may be the first statement we are processing. In either case,
138 // we create a new basic block. First, we create the blocks for
139 // the then...else statements, and then we create the block containing
140 // the if statement. If we were in the middle of a block, we
141 // stop processing that block and reverse its statements. That block
142 // is then the implicit successor for the "then" and "else" clauses.
143
144 // The block we were proccessing is now finished. Make it the
145 // successor block.
146 if (Block) {
147 Succ = Block;
148 Block->reverseStmts();
149 }
150
151 // Process the false branch. NULL out Block so that the recursive
152 // call to Visit will create a new basic block.
153 // Null out Block so that all successor
154 CFGBlock* ElseBlock = Succ;
155
156 if (Stmt* Else = I->getElse()) {
157 SaveAndRestore<CFGBlock*> sv(Succ);
158
159 // NULL out Block so that the recursive call to Visit will
160 // create a new basic block.
161 Block = NULL;
162 ElseBlock = Visit(Else);
163 if (!ElseBlock) return NULL;
164 ElseBlock->reverseStmts();
165 }
166
167 // Process the true branch. NULL out Block so that the recursive
168 // call to Visit will create a new basic block.
169 // Null out Block so that all successor
170 CFGBlock* ThenBlock;
171 {
172 Stmt* Then = I->getThen();
173 assert (Then);
174 SaveAndRestore<CFGBlock*> sv(Succ);
175 Block = NULL;
176 ThenBlock = Visit(Then);
177 if (!ThenBlock) return NULL;
178 ThenBlock->reverseStmts();
179 }
180
181 // Now create a new block containing the if statement.
182 Block = createBlock(false);
183
184 // Add the condition as the last statement in the new block.
185 Block->appendStmt(I->getCond());
186
187 // Set the terminator of the new block to the If statement.
188 Block->setTerminator(I);
189
190 // Now add the successors.
191 Block->addSuccessor(ThenBlock);
192 Block->addSuccessor(ElseBlock);
193
194 return Block;
195 }
196
197 CFGBlock* VisitReturnStmt(ReturnStmt* R) {
198 // If we were in the middle of a block we stop processing that block
199 // and reverse its statements.
200 //
201 // NOTE: If a "return" appears in the middle of a block, this means
202 // that the code afterwards is DEAD (unreachable). We still
203 // keep a basic block for that code; a simple "mark-and-sweep"
204 // from the entry block will be able to report such dead
205 // blocks.
206 if (Block) Block->reverseStmts();
207
208 // Create the new block.
209 Block = createBlock(false);
210
211 // The Exit block is the only successor.
212 Block->addSuccessor(Exit);
213
214 // Add the return expression to the block.
215 Block->appendStmt(R);
216
217 // Add the return statement itself to the block.
218 if (R->getRetValue()) Block->appendStmt(R->getRetValue());
219
220 return Block;
221 }
Ted Kremenek97f75312007-08-21 21:42:03 +0000222};
223
224// BuildCFG - A helper function that builds CFGs from ASTS.
Ted Kremenek95e854d2007-08-21 22:06:14 +0000225CFG* CFG::BuildCFG(Stmt* Statement) {
Ted Kremenek97f75312007-08-21 21:42:03 +0000226 CFGBuilder Builder;
227 return Builder.buildCFG(Statement);
228}
229
230// reverseStmts - A method that reverses the order of the statements within
231// a CFGBlock.
232void CFGBlock::reverseStmts() { std::reverse(Stmts.begin(),Stmts.end()); }
233
234// dump - A simple pretty printer of a CFG that outputs to stderr.
235void CFG::dump() { print(std::cerr); }
236
237// print - A simple pretty printer of a CFG that outputs to an ostream.
238void CFG::print(std::ostream& OS) {
239 // Iterate through the CFGBlocks and print them one by one. Specially
240 // designate the Entry and Exit blocks.
241 for (iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
242 OS << "\n [ B" << I->getBlockID();
243 if (&(*I) == getExit()) OS << " (EXIT) ]\n";
244 else if (&(*I) == getEntry()) OS << " (ENTRY) ]\n";
245 else OS << " ]\n";
246 I->print(OS);
247 }
248 OS << "\n";
249}
250
251// dump - A simply pretty printer of a CFGBlock that outputs to stderr.
252void CFGBlock::dump() { print(std::cerr); }
253
254// print - A simple pretty printer of a CFGBlock that outputs to an ostream.
255// Generally this will only be called from CFG::print.
256void CFGBlock::print(std::ostream& OS) {
257
258 // Iterate through the statements in the block and print them.
259 OS << " ------------------------\n";
260 unsigned j = 1;
261 for (iterator I = Stmts.begin(), E = Stmts.end() ; I != E ; ++I, ++j ) {
262 OS << " " << std::setw(3) << j << ": ";
263 (*I)->printPretty(OS);
264 if (isa<Expr>(*I)) OS << '\n';
265 }
266 OS << " ------------------------\n";
267
268 // Print the predecessors of this block.
269 OS << " Predecessors (" << pred_size() << "):";
270 unsigned i = 0;
271 for (pred_iterator I = pred_begin(), E = pred_end(); I != E; ++I, ++i ) {
272 if (i == 8 || (i-8) == 0) {
273 OS << "\n ";
274 }
275 OS << " B" << (*I)->getBlockID();
276 }
277
278 // Print the terminator of this block.
279 OS << "\n Terminator: ";
280 if (ControlFlowStmt) {
281 switch (ControlFlowStmt->getStmtClass()) {
282 case Stmt::IfStmtClass: {
283 IfStmt* I = cast<IfStmt>(ControlFlowStmt);
284 OS << "if ";
285 I->getCond()->printPretty(std::cerr);
286 OS << "\n";
287 break;
288 }
289
290 case Stmt::ReturnStmtClass: {
291 ReturnStmt* R = cast<ReturnStmt>(ControlFlowStmt);
292 R->printPretty(std::cerr);
293 break;
294 }
295
296 default:
297 assert(false && "terminator print not fully implemented");
298 }
299 }
300 else OS << "<NULL>\n";
301
302 // Print the successors of this block.
303 OS << " Successors (" << succ_size() << "):";
304 i = 0;
305 for (succ_iterator I = succ_begin(), E = succ_end(); I != E; ++I, ++i ) {
306 if (i == 8 || (i-8) % 10 == 0) {
307 OS << "\n ";
308 }
309 OS << " B" << (*I)->getBlockID();
310 }
311 OS << '\n';
312}