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