DiffConsumer.cpp revision 231057
1169691Skan//===-- DiffConsumer.cpp - Difference Consumer ------------------*- C++ -*-===// 2169691Skan// 3169691Skan// The LLVM Compiler Infrastructure 4169691Skan// 5169691Skan// This file is distributed under the University of Illinois Open Source 6169691Skan// License. See LICENSE.TXT for details. 7169691Skan// 8169691Skan//===----------------------------------------------------------------------===// 9169691Skan// 10169691Skan// This files implements the the LLVM difference Consumer 11169691Skan// 12169691Skan//===----------------------------------------------------------------------===// 13169691Skan 14169691Skan#include "DiffConsumer.h" 15169691Skan 16169691Skan#include "llvm/Module.h" 17169691Skan#include "llvm/Instructions.h" 18169691Skan#include "llvm/Support/ErrorHandling.h" 19169691Skan 20169691Skanusing namespace llvm; 21169691Skan 22169691Skanstatic void ComputeNumbering(Function *F, DenseMap<Value*,unsigned> &Numbering){ 23169691Skan unsigned IN = 0; 24169691Skan 25169691Skan // Arguments get the first numbers. 26169691Skan for (Function::arg_iterator 27169691Skan AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI) 28169691Skan if (!AI->hasName()) 29169691Skan Numbering[&*AI] = IN++; 30169691Skan 31169691Skan // Walk the basic blocks in order. 32169691Skan for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) { 33169691Skan if (!FI->hasName()) 34169691Skan Numbering[&*FI] = IN++; 35169691Skan 36169691Skan // Walk the instructions in order. 37169691Skan for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) 38169691Skan // void instructions don't get numbers. 39169691Skan if (!BI->hasName() && !BI->getType()->isVoidTy()) 40169691Skan Numbering[&*BI] = IN++; 41169691Skan } 42169691Skan 43169691Skan assert(!Numbering.empty() && "asked for numbering but numbering was no-op"); 44169691Skan} 45169691Skan 46169691Skan 47169691Skanvoid DiffConsumer::printValue(Value *V, bool isL) { 48169691Skan if (V->hasName()) { 49169691Skan out << (isa<GlobalValue>(V) ? '@' : '%') << V->getName(); 50169691Skan return; 51169691Skan } 52169691Skan if (V->getType()->isVoidTy()) { 53169691Skan if (isa<StoreInst>(V)) { 54169691Skan out << "store to "; 55169691Skan printValue(cast<StoreInst>(V)->getPointerOperand(), isL); 56169691Skan } else if (isa<CallInst>(V)) { 57169691Skan out << "call to "; 58169691Skan printValue(cast<CallInst>(V)->getCalledValue(), isL); 59169691Skan } else if (isa<InvokeInst>(V)) { 60169691Skan out << "invoke to "; 61169691Skan printValue(cast<InvokeInst>(V)->getCalledValue(), isL); 62169691Skan } else { 63169691Skan out << *V; 64169691Skan } 65169691Skan return; 66169691Skan } 67169691Skan 68169691Skan unsigned N = contexts.size(); 69169691Skan while (N > 0) { 70169691Skan --N; 71169691Skan DiffContext &ctxt = contexts[N]; 72169691Skan if (!ctxt.IsFunction) continue; 73169691Skan if (isL) { 74169691Skan if (ctxt.LNumbering.empty()) 75169691Skan ComputeNumbering(cast<Function>(ctxt.L), ctxt.LNumbering); 76169691Skan out << '%' << ctxt.LNumbering[V]; 77169691Skan return; 78169691Skan } else { 79169691Skan if (ctxt.RNumbering.empty()) 80169691Skan ComputeNumbering(cast<Function>(ctxt.R), ctxt.RNumbering); 81169691Skan out << '%' << ctxt.RNumbering[V]; 82169691Skan return; 83169691Skan } 84169691Skan } 85169691Skan 86169691Skan out << "<anonymous>"; 87169691Skan} 88169691Skan 89169691Skanvoid DiffConsumer::header() { 90169691Skan if (contexts.empty()) return; 91169691Skan for (SmallVectorImpl<DiffContext>::iterator 92169691Skan I = contexts.begin(), E = contexts.end(); I != E; ++I) { 93169691Skan if (I->Differences) continue; 94169691Skan if (isa<Function>(I->L)) { 95169691Skan // Extra newline between functions. 96169691Skan if (Differences) out << "\n"; 97169691Skan 98169691Skan Function *L = cast<Function>(I->L); 99169691Skan Function *R = cast<Function>(I->R); 100169691Skan if (L->getName() != R->getName()) 101169691Skan out << "in function " << L->getName() 102169691Skan << " / " << R->getName() << ":\n"; 103169691Skan else 104169691Skan out << "in function " << L->getName() << ":\n"; 105169691Skan } else if (isa<BasicBlock>(I->L)) { 106169691Skan BasicBlock *L = cast<BasicBlock>(I->L); 107169691Skan BasicBlock *R = cast<BasicBlock>(I->R); 108169691Skan if (L->hasName() && R->hasName() && L->getName() == R->getName()) 109169691Skan out << " in block %" << L->getName() << ":\n"; 110169691Skan else { 111169691Skan out << " in block "; 112169691Skan printValue(L, true); 113169691Skan out << " / "; 114169691Skan printValue(R, false); 115169691Skan out << ":\n"; 116169691Skan } 117169691Skan } else if (isa<Instruction>(I->L)) { 118169691Skan out << " in instruction "; 119169691Skan printValue(I->L, true); 120169691Skan out << " / "; 121169691Skan printValue(I->R, false); 122169691Skan out << ":\n"; 123169691Skan } 124169691Skan 125169691Skan I->Differences = true; 126169691Skan } 127169691Skan} 128169691Skan 129169691Skanvoid DiffConsumer::indent() { 130169691Skan unsigned N = Indent; 131169691Skan while (N--) out << ' '; 132169691Skan} 133169691Skan 134169691Skanbool DiffConsumer::hadDifferences() const { 135169691Skan return Differences; 136169691Skan} 137169691Skan 138169691Skanvoid DiffConsumer::enterContext(Value *L, Value *R) { 139169691Skan contexts.push_back(DiffContext(L, R)); 140169691Skan Indent += 2; 141169691Skan} 142169691Skan 143169691Skanvoid DiffConsumer::exitContext() { 144169691Skan Differences |= contexts.back().Differences; 145169691Skan contexts.pop_back(); 146169691Skan Indent -= 2; 147169691Skan} 148169691Skan 149169691Skanvoid DiffConsumer::log(StringRef text) { 150169691Skan header(); 151169691Skan indent(); 152169691Skan out << text << '\n'; 153169691Skan} 154169691Skan 155169691Skanvoid DiffConsumer::logf(const LogBuilder &Log) { 156169691Skan header(); 157169691Skan indent(); 158169691Skan 159169691Skan unsigned arg = 0; 160169691Skan 161169691Skan StringRef format = Log.getFormat(); 162169691Skan while (true) { 163169691Skan size_t percent = format.find('%'); 164169691Skan if (percent == StringRef::npos) { 165169691Skan out << format; 166169691Skan break; 167169691Skan } 168169691Skan assert(format[percent] == '%'); 169169691Skan 170169691Skan if (percent > 0) out << format.substr(0, percent); 171169691Skan 172169691Skan switch (format[percent+1]) { 173169691Skan case '%': out << '%'; break; 174169691Skan case 'l': printValue(Log.getArgument(arg++), true); break; 175169691Skan case 'r': printValue(Log.getArgument(arg++), false); break; 176169691Skan default: llvm_unreachable("unknown format character"); 177169691Skan } 178169691Skan 179169691Skan format = format.substr(percent+2); 180169691Skan } 181169691Skan 182169691Skan out << '\n'; 183169691Skan} 184169691Skan 185169691Skanvoid DiffConsumer::logd(const DiffLogBuilder &Log) { 186169691Skan header(); 187169691Skan 188169691Skan for (unsigned I = 0, E = Log.getNumLines(); I != E; ++I) { 189169691Skan indent(); 190169691Skan switch (Log.getLineKind(I)) { 191169691Skan case DC_match: 192169691Skan out << " "; 193169691Skan Log.getLeft(I)->dump(); 194169691Skan //printValue(Log.getLeft(I), true); 195169691Skan break; 196169691Skan case DC_left: 197169691Skan out << "< "; 198169691Skan Log.getLeft(I)->dump(); 199169691Skan //printValue(Log.getLeft(I), true); 200169691Skan break; 201169691Skan case DC_right: 202169691Skan out << "> "; 203169691Skan Log.getRight(I)->dump(); 204169691Skan //printValue(Log.getRight(I), false); 205169691Skan break; 206169691Skan } 207169691Skan //out << "\n"; 208169691Skan } 209169691Skan} 210169691Skan