Move the support for using .init_array from ARM to the generic
[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 Consumer::anchor() { }
48
49 void DiffConsumer::printValue(Value *V, bool isL) {
50   if (V->hasName()) {
51     out << (isa<GlobalValue>(V) ? '@' : '%') << V->getName();
52     return;
53   }
54   if (V->getType()->isVoidTy()) {
55     if (isa<StoreInst>(V)) {
56       out << "store to ";
57       printValue(cast<StoreInst>(V)->getPointerOperand(), isL);
58     } else if (isa<CallInst>(V)) {
59       out << "call to ";
60       printValue(cast<CallInst>(V)->getCalledValue(), isL);
61     } else if (isa<InvokeInst>(V)) {
62       out << "invoke to ";
63       printValue(cast<InvokeInst>(V)->getCalledValue(), isL);
64     } else {
65       out << *V;
66     }
67     return;
68   }
69   if (isa<Constant>(V)) {
70     out << *V;
71     return;
72   }
73
74   unsigned N = contexts.size();
75   while (N > 0) {
76     --N;
77     DiffContext &ctxt = contexts[N];
78     if (!ctxt.IsFunction) continue;
79     if (isL) {
80       if (ctxt.LNumbering.empty())
81         ComputeNumbering(cast<Function>(ctxt.L), ctxt.LNumbering);
82       out << '%' << ctxt.LNumbering[V];
83       return;
84     } else {
85       if (ctxt.RNumbering.empty())
86         ComputeNumbering(cast<Function>(ctxt.R), ctxt.RNumbering);
87       out << '%' << ctxt.RNumbering[V];
88       return;
89     }
90   }
91
92   out << "<anonymous>";
93 }
94
95 void DiffConsumer::header() {
96   if (contexts.empty()) return;
97   for (SmallVectorImpl<DiffContext>::iterator
98          I = contexts.begin(), E = contexts.end(); I != E; ++I) {
99     if (I->Differences) continue;
100     if (isa<Function>(I->L)) {
101       // Extra newline between functions.
102       if (Differences) out << "\n";
103
104       Function *L = cast<Function>(I->L);
105       Function *R = cast<Function>(I->R);
106       if (L->getName() != R->getName())
107         out << "in function " << L->getName()
108             << " / " << R->getName() << ":\n";
109       else
110         out << "in function " << L->getName() << ":\n";
111     } else if (isa<BasicBlock>(I->L)) {
112       BasicBlock *L = cast<BasicBlock>(I->L);
113       BasicBlock *R = cast<BasicBlock>(I->R);
114       if (L->hasName() && R->hasName() && L->getName() == R->getName())
115         out << "  in block %" << L->getName() << ":\n";
116       else {
117         out << "  in block ";
118         printValue(L, true);
119         out << " / ";
120         printValue(R, false);
121         out << ":\n";
122       }
123     } else if (isa<Instruction>(I->L)) {
124       out << "    in instruction ";
125       printValue(I->L, true);
126       out << " / ";
127       printValue(I->R, false);
128       out << ":\n";
129     }
130
131     I->Differences = true;
132   }
133 }
134
135 void DiffConsumer::indent() {
136   unsigned N = Indent;
137   while (N--) out << ' ';
138 }
139
140 bool DiffConsumer::hadDifferences() const {
141   return Differences;
142 }
143
144 void DiffConsumer::enterContext(Value *L, Value *R) {
145   contexts.push_back(DiffContext(L, R));
146   Indent += 2;
147 }
148
149 void DiffConsumer::exitContext() {
150   Differences |= contexts.back().Differences;
151   contexts.pop_back();
152   Indent -= 2;
153 }
154
155 void DiffConsumer::log(StringRef text) {
156   header();
157   indent();
158   out << text << '\n';
159 }
160
161 void DiffConsumer::logf(const LogBuilder &Log) {
162   header();
163   indent();
164
165   unsigned arg = 0;
166
167   StringRef format = Log.getFormat();
168   while (true) {
169     size_t percent = format.find('%');
170     if (percent == StringRef::npos) {
171       out << format;
172       break;
173     }
174     assert(format[percent] == '%');
175
176     if (percent > 0) out << format.substr(0, percent);
177
178     switch (format[percent+1]) {
179     case '%': out << '%'; break;
180     case 'l': printValue(Log.getArgument(arg++), true); break;
181     case 'r': printValue(Log.getArgument(arg++), false); break;
182     default: llvm_unreachable("unknown format character");
183     }
184
185     format = format.substr(percent+2);
186   }
187
188   out << '\n';
189 }
190
191 void DiffConsumer::logd(const DiffLogBuilder &Log) {
192   header();
193
194   for (unsigned I = 0, E = Log.getNumLines(); I != E; ++I) {
195     indent();
196     switch (Log.getLineKind(I)) {
197     case DC_match:
198       out << "  ";
199       Log.getLeft(I)->dump();
200       //printValue(Log.getLeft(I), true);
201       break;
202     case DC_left:
203       out << "< ";
204       Log.getLeft(I)->dump();
205       //printValue(Log.getLeft(I), true);
206       break;
207     case DC_right:
208       out << "> ";
209       Log.getRight(I)->dump();
210       //printValue(Log.getRight(I), false);
211       break;
212     }
213     //out << "\n";
214   }
215 }