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