xref: /aosp_15_r20/external/llvm/tools/llvm-diff/DiffConsumer.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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