]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-diff/DiffConsumer.cpp
Fix a memory leak in if_delgroups() introduced in r334118.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / llvm-diff / DiffConsumer.cpp
1 //===-- DiffConsumer.cpp - Difference Consumer ------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This files implements the LLVM difference Consumer
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "DiffConsumer.h"
14 #include "llvm/IR/Instructions.h"
15 #include "llvm/Support/Debug.h"
16 #include "llvm/Support/ErrorHandling.h"
17
18 using namespace llvm;
19
20 static void ComputeNumbering(Function *F, DenseMap<Value*,unsigned> &Numbering){
21   unsigned IN = 0;
22
23   // Arguments get the first numbers.
24   for (Function::arg_iterator
25          AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI)
26     if (!AI->hasName())
27       Numbering[&*AI] = IN++;
28
29   // Walk the basic blocks in order.
30   for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) {
31     if (!FI->hasName())
32       Numbering[&*FI] = IN++;
33
34     // Walk the instructions in order.
35     for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI)
36       // void instructions don't get numbers.
37       if (!BI->hasName() && !BI->getType()->isVoidTy())
38         Numbering[&*BI] = IN++;
39   }
40
41   assert(!Numbering.empty() && "asked for numbering but numbering was no-op");
42 }
43
44
45 void Consumer::anchor() { }
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   if (isa<Constant>(V)) {
68     out << *V;
69     return;
70   }
71
72   unsigned N = contexts.size();
73   while (N > 0) {
74     --N;
75     DiffContext &ctxt = contexts[N];
76     if (!ctxt.IsFunction) continue;
77     if (isL) {
78       if (ctxt.LNumbering.empty())
79         ComputeNumbering(cast<Function>(ctxt.L), ctxt.LNumbering);
80       out << '%' << ctxt.LNumbering[V];
81       return;
82     } else {
83       if (ctxt.RNumbering.empty())
84         ComputeNumbering(cast<Function>(ctxt.R), ctxt.RNumbering);
85       out << '%' << ctxt.RNumbering[V];
86       return;
87     }
88   }
89
90   out << "<anonymous>";
91 }
92
93 void DiffConsumer::header() {
94   if (contexts.empty()) return;
95   for (SmallVectorImpl<DiffContext>::iterator
96          I = contexts.begin(), E = contexts.end(); I != E; ++I) {
97     if (I->Differences) continue;
98     if (isa<Function>(I->L)) {
99       // Extra newline between functions.
100       if (Differences) out << "\n";
101
102       Function *L = cast<Function>(I->L);
103       Function *R = cast<Function>(I->R);
104       if (L->getName() != R->getName())
105         out << "in function " << L->getName()
106             << " / " << R->getName() << ":\n";
107       else
108         out << "in function " << L->getName() << ":\n";
109     } else if (isa<BasicBlock>(I->L)) {
110       BasicBlock *L = cast<BasicBlock>(I->L);
111       BasicBlock *R = cast<BasicBlock>(I->R);
112       if (L->hasName() && R->hasName() && L->getName() == R->getName())
113         out << "  in block %" << L->getName() << ":\n";
114       else {
115         out << "  in block ";
116         printValue(L, true);
117         out << " / ";
118         printValue(R, false);
119         out << ":\n";
120       }
121     } else if (isa<Instruction>(I->L)) {
122       out << "    in instruction ";
123       printValue(I->L, true);
124       out << " / ";
125       printValue(I->R, false);
126       out << ":\n";
127     }
128
129     I->Differences = true;
130   }
131 }
132
133 void DiffConsumer::indent() {
134   unsigned N = Indent;
135   while (N--) out << ' ';
136 }
137
138 bool DiffConsumer::hadDifferences() const {
139   return Differences;
140 }
141
142 void DiffConsumer::enterContext(Value *L, Value *R) {
143   contexts.push_back(DiffContext(L, R));
144   Indent += 2;
145 }
146
147 void DiffConsumer::exitContext() {
148   Differences |= contexts.back().Differences;
149   contexts.pop_back();
150   Indent -= 2;
151 }
152
153 void DiffConsumer::log(StringRef text) {
154   header();
155   indent();
156   out << text << '\n';
157 }
158
159 void DiffConsumer::logf(const LogBuilder &Log) {
160   header();
161   indent();
162
163   unsigned arg = 0;
164
165   StringRef format = Log.getFormat();
166   while (true) {
167     size_t percent = format.find('%');
168     if (percent == StringRef::npos) {
169       out << format;
170       break;
171     }
172     assert(format[percent] == '%');
173
174     if (percent > 0) out << format.substr(0, percent);
175
176     switch (format[percent+1]) {
177     case '%': out << '%'; break;
178     case 'l': printValue(Log.getArgument(arg++), true); break;
179     case 'r': printValue(Log.getArgument(arg++), false); break;
180     default: llvm_unreachable("unknown format character");
181     }
182
183     format = format.substr(percent+2);
184   }
185
186   out << '\n';
187 }
188
189 void DiffConsumer::logd(const DiffLogBuilder &Log) {
190   header();
191
192   for (unsigned I = 0, E = Log.getNumLines(); I != E; ++I) {
193     indent();
194     switch (Log.getLineKind(I)) {
195     case DC_match:
196       out << "  ";
197       Log.getLeft(I)->print(dbgs()); dbgs() << '\n';
198       //printValue(Log.getLeft(I), true);
199       break;
200     case DC_left:
201       out << "< ";
202       Log.getLeft(I)->print(dbgs()); dbgs() << '\n';
203       //printValue(Log.getLeft(I), true);
204       break;
205     case DC_right:
206       out << "> ";
207       Log.getRight(I)->print(dbgs()); dbgs() << '\n';
208       //printValue(Log.getRight(I), false);
209       break;
210     }
211     //out << "\n";
212   }
213 }