1 //===-- DiffConsumer.cpp - Difference Consumer ------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This files implements the the LLVM difference Consumer
12 //===----------------------------------------------------------------------===//
14 #include "DiffConsumer.h"
16 #include "llvm/Module.h"
17 #include "llvm/Instructions.h"
18 #include "llvm/Support/ErrorHandling.h"
22 static void ComputeNumbering(Function
*F
, DenseMap
<Value
*,unsigned> &Numbering
){
25 // Arguments get the first numbers.
26 for (Function::arg_iterator
27 AI
= F
->arg_begin(), AE
= F
->arg_end(); AI
!= AE
; ++AI
)
29 Numbering
[&*AI
] = IN
++;
31 // Walk the basic blocks in order.
32 for (Function::iterator FI
= F
->begin(), FE
= F
->end(); FI
!= FE
; ++FI
) {
34 Numbering
[&*FI
] = IN
++;
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
++;
43 assert(!Numbering
.empty() && "asked for numbering but numbering was no-op");
47 void DiffConsumer::printValue(Value
*V
, bool isL
) {
49 out
<< (isa
<GlobalValue
>(V
) ? '@' : '%') << V
->getName();
52 if (V
->getType()->isVoidTy()) {
53 if (isa
<StoreInst
>(V
)) {
55 printValue(cast
<StoreInst
>(V
)->getPointerOperand(), isL
);
56 } else if (isa
<CallInst
>(V
)) {
58 printValue(cast
<CallInst
>(V
)->getCalledValue(), isL
);
59 } else if (isa
<InvokeInst
>(V
)) {
61 printValue(cast
<InvokeInst
>(V
)->getCalledValue(), isL
);
68 unsigned N
= contexts
.size();
71 DiffContext
&ctxt
= contexts
[N
];
72 if (!ctxt
.IsFunction
) continue;
74 if (ctxt
.LNumbering
.empty())
75 ComputeNumbering(cast
<Function
>(ctxt
.L
), ctxt
.LNumbering
);
76 out
<< '%' << ctxt
.LNumbering
[V
];
79 if (ctxt
.RNumbering
.empty())
80 ComputeNumbering(cast
<Function
>(ctxt
.R
), ctxt
.RNumbering
);
81 out
<< '%' << ctxt
.RNumbering
[V
];
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";
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";
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";
114 printValue(R
, false);
117 } else if (isa
<Instruction
>(I
->L
)) {
118 out
<< " in instruction ";
119 printValue(I
->L
, true);
121 printValue(I
->R
, false);
125 I
->Differences
= true;
129 void DiffConsumer::indent() {
131 while (N
--) out
<< ' ';
134 bool DiffConsumer::hadDifferences() const {
138 void DiffConsumer::enterContext(Value
*L
, Value
*R
) {
139 contexts
.push_back(DiffContext(L
, R
));
143 void DiffConsumer::exitContext() {
144 Differences
|= contexts
.back().Differences
;
149 void DiffConsumer::log(StringRef text
) {
155 void DiffConsumer::logf(const LogBuilder
&Log
) {
161 StringRef format
= Log
.getFormat();
163 size_t percent
= format
.find('%');
164 if (percent
== StringRef::npos
) {
168 assert(format
[percent
] == '%');
170 if (percent
> 0) out
<< format
.substr(0, percent
);
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");
179 format
= format
.substr(percent
+2);
185 void DiffConsumer::logd(const DiffLogBuilder
&Log
) {
188 for (unsigned I
= 0, E
= Log
.getNumLines(); I
!= E
; ++I
) {
190 switch (Log
.getLineKind(I
)) {
193 Log
.getLeft(I
)->dump();
194 //printValue(Log.getLeft(I), true);
198 Log
.getLeft(I
)->dump();
199 //printValue(Log.getLeft(I), true);
203 Log
.getRight(I
)->dump();
204 //printValue(Log.getRight(I), false);