]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===-- DiffConsumer.cpp - Difference Consumer ------------------*- C++ -*-===// |
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 files implements the LLVM difference Consumer | |
11 | // | |
12 | //===----------------------------------------------------------------------===// | |
13 | ||
14 | #include "DiffConsumer.h" | |
970d7e83 LB |
15 | #include "llvm/IR/Instructions.h" |
16 | #include "llvm/IR/Module.h" | |
223e47cc LB |
17 | #include "llvm/Support/ErrorHandling.h" |
18 | ||
19 | using namespace llvm; | |
20 | ||
21 | static void ComputeNumbering(Function *F, DenseMap<Value*,unsigned> &Numbering){ | |
22 | unsigned IN = 0; | |
23 | ||
24 | // Arguments get the first numbers. | |
25 | for (Function::arg_iterator | |
26 | AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI) | |
27 | if (!AI->hasName()) | |
28 | Numbering[&*AI] = IN++; | |
29 | ||
30 | // Walk the basic blocks in order. | |
31 | for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) { | |
32 | if (!FI->hasName()) | |
33 | Numbering[&*FI] = IN++; | |
34 | ||
35 | // Walk the instructions in order. | |
36 | for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) | |
37 | // void instructions don't get numbers. | |
38 | if (!BI->hasName() && !BI->getType()->isVoidTy()) | |
39 | Numbering[&*BI] = IN++; | |
40 | } | |
41 | ||
42 | assert(!Numbering.empty() && "asked for numbering but numbering was no-op"); | |
43 | } | |
44 | ||
45 | ||
46 | void Consumer::anchor() { } | |
47 | ||
48 | void DiffConsumer::printValue(Value *V, bool isL) { | |
49 | if (V->hasName()) { | |
50 | out << (isa<GlobalValue>(V) ? '@' : '%') << V->getName(); | |
51 | return; | |
52 | } | |
53 | if (V->getType()->isVoidTy()) { | |
54 | if (isa<StoreInst>(V)) { | |
55 | out << "store to "; | |
56 | printValue(cast<StoreInst>(V)->getPointerOperand(), isL); | |
57 | } else if (isa<CallInst>(V)) { | |
58 | out << "call to "; | |
59 | printValue(cast<CallInst>(V)->getCalledValue(), isL); | |
60 | } else if (isa<InvokeInst>(V)) { | |
61 | out << "invoke to "; | |
62 | printValue(cast<InvokeInst>(V)->getCalledValue(), isL); | |
63 | } else { | |
64 | out << *V; | |
65 | } | |
66 | return; | |
67 | } | |
68 | if (isa<Constant>(V)) { | |
69 | out << *V; | |
70 | return; | |
71 | } | |
72 | ||
73 | unsigned N = contexts.size(); | |
74 | while (N > 0) { | |
75 | --N; | |
76 | DiffContext &ctxt = contexts[N]; | |
77 | if (!ctxt.IsFunction) continue; | |
78 | if (isL) { | |
79 | if (ctxt.LNumbering.empty()) | |
80 | ComputeNumbering(cast<Function>(ctxt.L), ctxt.LNumbering); | |
81 | out << '%' << ctxt.LNumbering[V]; | |
82 | return; | |
83 | } else { | |
84 | if (ctxt.RNumbering.empty()) | |
85 | ComputeNumbering(cast<Function>(ctxt.R), ctxt.RNumbering); | |
86 | out << '%' << ctxt.RNumbering[V]; | |
87 | return; | |
88 | } | |
89 | } | |
90 | ||
91 | out << "<anonymous>"; | |
92 | } | |
93 | ||
94 | void DiffConsumer::header() { | |
95 | if (contexts.empty()) return; | |
96 | for (SmallVectorImpl<DiffContext>::iterator | |
97 | I = contexts.begin(), E = contexts.end(); I != E; ++I) { | |
98 | if (I->Differences) continue; | |
99 | if (isa<Function>(I->L)) { | |
100 | // Extra newline between functions. | |
101 | if (Differences) out << "\n"; | |
102 | ||
103 | Function *L = cast<Function>(I->L); | |
104 | Function *R = cast<Function>(I->R); | |
105 | if (L->getName() != R->getName()) | |
106 | out << "in function " << L->getName() | |
107 | << " / " << R->getName() << ":\n"; | |
108 | else | |
109 | out << "in function " << L->getName() << ":\n"; | |
110 | } else if (isa<BasicBlock>(I->L)) { | |
111 | BasicBlock *L = cast<BasicBlock>(I->L); | |
112 | BasicBlock *R = cast<BasicBlock>(I->R); | |
113 | if (L->hasName() && R->hasName() && L->getName() == R->getName()) | |
114 | out << " in block %" << L->getName() << ":\n"; | |
115 | else { | |
116 | out << " in block "; | |
117 | printValue(L, true); | |
118 | out << " / "; | |
119 | printValue(R, false); | |
120 | out << ":\n"; | |
121 | } | |
122 | } else if (isa<Instruction>(I->L)) { | |
123 | out << " in instruction "; | |
124 | printValue(I->L, true); | |
125 | out << " / "; | |
126 | printValue(I->R, false); | |
127 | out << ":\n"; | |
128 | } | |
129 | ||
130 | I->Differences = true; | |
131 | } | |
132 | } | |
133 | ||
134 | void DiffConsumer::indent() { | |
135 | unsigned N = Indent; | |
136 | while (N--) out << ' '; | |
137 | } | |
138 | ||
139 | bool DiffConsumer::hadDifferences() const { | |
140 | return Differences; | |
141 | } | |
142 | ||
143 | void DiffConsumer::enterContext(Value *L, Value *R) { | |
144 | contexts.push_back(DiffContext(L, R)); | |
145 | Indent += 2; | |
146 | } | |
147 | ||
148 | void DiffConsumer::exitContext() { | |
149 | Differences |= contexts.back().Differences; | |
150 | contexts.pop_back(); | |
151 | Indent -= 2; | |
152 | } | |
153 | ||
154 | void DiffConsumer::log(StringRef text) { | |
155 | header(); | |
156 | indent(); | |
157 | out << text << '\n'; | |
158 | } | |
159 | ||
160 | void DiffConsumer::logf(const LogBuilder &Log) { | |
161 | header(); | |
162 | indent(); | |
163 | ||
164 | unsigned arg = 0; | |
165 | ||
166 | StringRef format = Log.getFormat(); | |
167 | while (true) { | |
168 | size_t percent = format.find('%'); | |
169 | if (percent == StringRef::npos) { | |
170 | out << format; | |
171 | break; | |
172 | } | |
173 | assert(format[percent] == '%'); | |
174 | ||
175 | if (percent > 0) out << format.substr(0, percent); | |
176 | ||
177 | switch (format[percent+1]) { | |
178 | case '%': out << '%'; break; | |
179 | case 'l': printValue(Log.getArgument(arg++), true); break; | |
180 | case 'r': printValue(Log.getArgument(arg++), false); break; | |
181 | default: llvm_unreachable("unknown format character"); | |
182 | } | |
183 | ||
184 | format = format.substr(percent+2); | |
185 | } | |
186 | ||
187 | out << '\n'; | |
188 | } | |
189 | ||
190 | void DiffConsumer::logd(const DiffLogBuilder &Log) { | |
191 | header(); | |
192 | ||
193 | for (unsigned I = 0, E = Log.getNumLines(); I != E; ++I) { | |
194 | indent(); | |
195 | switch (Log.getLineKind(I)) { | |
196 | case DC_match: | |
197 | out << " "; | |
198 | Log.getLeft(I)->dump(); | |
199 | //printValue(Log.getLeft(I), true); | |
200 | break; | |
201 | case DC_left: | |
202 | out << "< "; | |
203 | Log.getLeft(I)->dump(); | |
204 | //printValue(Log.getLeft(I), true); | |
205 | break; | |
206 | case DC_right: | |
207 | out << "> "; | |
208 | Log.getRight(I)->dump(); | |
209 | //printValue(Log.getRight(I), false); | |
210 | break; | |
211 | } | |
212 | //out << "\n"; | |
213 | } | |
214 | } |