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 LLVM difference Consumer
12 //===----------------------------------------------------------------------===//
14 #include "DiffConsumer.h"
15 #include "llvm/IR/Instructions.h"
16 #include "llvm/Support/ErrorHandling.h"
17 #include "llvm/Support/Debug.h"
21 static void ComputeNumbering(Function
*F
, DenseMap
<Value
*,unsigned> &Numbering
){
24 // Arguments get the first numbers.
25 for (Function::arg_iterator
26 AI
= F
->arg_begin(), AE
= F
->arg_end(); AI
!= AE
; ++AI
)
28 Numbering
[&*AI
] = IN
++;
30 // Walk the basic blocks in order.
31 for (Function::iterator FI
= F
->begin(), FE
= F
->end(); FI
!= FE
; ++FI
) {
33 Numbering
[&*FI
] = IN
++;
35 // Walk the instructions in order.
36 for (BasicBlock::iterator BI
= FI
->begin(), BE
= FI
->end(); BI
!= BE
; ++BI
)
37 // void instructions don't get numbers.
38 if (!BI
->hasName() && !BI
->getType()->isVoidTy())
39 Numbering
[&*BI
] = IN
++;
42 assert(!Numbering
.empty() && "asked for numbering but numbering was no-op");
46 void Consumer::anchor() { }
48 void DiffConsumer::printValue(Value
*V
, bool isL
) {
50 out
<< (isa
<GlobalValue
>(V
) ? '@' : '%') << V
->getName();
53 if (V
->getType()->isVoidTy()) {
54 if (isa
<StoreInst
>(V
)) {
56 printValue(cast
<StoreInst
>(V
)->getPointerOperand(), isL
);
57 } else if (isa
<CallInst
>(V
)) {
59 printValue(cast
<CallInst
>(V
)->getCalledValue(), isL
);
60 } else if (isa
<InvokeInst
>(V
)) {
62 printValue(cast
<InvokeInst
>(V
)->getCalledValue(), isL
);
68 if (isa
<Constant
>(V
)) {
73 unsigned N
= contexts
.size();
76 DiffContext
&ctxt
= contexts
[N
];
77 if (!ctxt
.IsFunction
) continue;
79 if (ctxt
.LNumbering
.empty())
80 ComputeNumbering(cast
<Function
>(ctxt
.L
), ctxt
.LNumbering
);
81 out
<< '%' << ctxt
.LNumbering
[V
];
84 if (ctxt
.RNumbering
.empty())
85 ComputeNumbering(cast
<Function
>(ctxt
.R
), ctxt
.RNumbering
);
86 out
<< '%' << ctxt
.RNumbering
[V
];
94 void DiffConsumer::header() {
95 if (contexts
.empty()) return;
96 for (SmallVectorImpl
<DiffContext
>::iterator
97 I
= contexts
.begin(), E
= contexts
.end(); I
!= E
; ++I
) {
98 if (I
->Differences
) continue;
99 if (isa
<Function
>(I
->L
)) {
100 // Extra newline between functions.
101 if (Differences
) out
<< "\n";
103 Function
*L
= cast
<Function
>(I
->L
);
104 Function
*R
= cast
<Function
>(I
->R
);
105 if (L
->getName() != R
->getName())
106 out
<< "in function " << L
->getName()
107 << " / " << R
->getName() << ":\n";
109 out
<< "in function " << L
->getName() << ":\n";
110 } else if (isa
<BasicBlock
>(I
->L
)) {
111 BasicBlock
*L
= cast
<BasicBlock
>(I
->L
);
112 BasicBlock
*R
= cast
<BasicBlock
>(I
->R
);
113 if (L
->hasName() && R
->hasName() && L
->getName() == R
->getName())
114 out
<< " in block %" << L
->getName() << ":\n";
119 printValue(R
, false);
122 } else if (isa
<Instruction
>(I
->L
)) {
123 out
<< " in instruction ";
124 printValue(I
->L
, true);
126 printValue(I
->R
, false);
130 I
->Differences
= true;
134 void DiffConsumer::indent() {
136 while (N
--) out
<< ' ';
139 bool DiffConsumer::hadDifferences() const {
143 void DiffConsumer::enterContext(Value
*L
, Value
*R
) {
144 contexts
.push_back(DiffContext(L
, R
));
148 void DiffConsumer::exitContext() {
149 Differences
|= contexts
.back().Differences
;
154 void DiffConsumer::log(StringRef text
) {
160 void DiffConsumer::logf(const LogBuilder
&Log
) {
166 StringRef format
= Log
.getFormat();
168 size_t percent
= format
.find('%');
169 if (percent
== StringRef::npos
) {
173 assert(format
[percent
] == '%');
175 if (percent
> 0) out
<< format
.substr(0, percent
);
177 switch (format
[percent
+1]) {
178 case '%': out
<< '%'; break;
179 case 'l': printValue(Log
.getArgument(arg
++), true); break;
180 case 'r': printValue(Log
.getArgument(arg
++), false); break;
181 default: llvm_unreachable("unknown format character");
184 format
= format
.substr(percent
+2);
190 void DiffConsumer::logd(const DiffLogBuilder
&Log
) {
193 for (unsigned I
= 0, E
= Log
.getNumLines(); I
!= E
; ++I
) {
195 switch (Log
.getLineKind(I
)) {
198 Log
.getLeft(I
)->print(dbgs()); dbgs() << '\n';
199 //printValue(Log.getLeft(I), true);
203 Log
.getLeft(I
)->print(dbgs()); dbgs() << '\n';
204 //printValue(Log.getLeft(I), true);
208 Log
.getRight(I
)->print(dbgs()); dbgs() << '\n';
209 //printValue(Log.getRight(I), false);