1 //===-- DiffConsumer.cpp - Difference Consumer ------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This files implements the the LLVM difference Consumer 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "DiffConsumer.h" 15 16 #include "llvm/Module.h" 17 #include "llvm/Instructions.h" 18 #include "llvm/Support/ErrorHandling.h" 19 20 using namespace llvm; 21 22 static void ComputeNumbering(Function *F, DenseMap<Value*,unsigned> &Numbering){ 23 unsigned IN = 0; 24 25 // Arguments get the first numbers. 26 for (Function::arg_iterator 27 AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI) 28 if (!AI->hasName()) 29 Numbering[&*AI] = IN++; 30 31 // Walk the basic blocks in order. 32 for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) { 33 if (!FI->hasName()) 34 Numbering[&*FI] = IN++; 35 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++; 41 } 42 43 assert(!Numbering.empty() && "asked for numbering but numbering was no-op"); 44 } 45 46 47 void Consumer::anchor() { } 48 49 void DiffConsumer::printValue(Value *V, bool isL) { 50 if (V->hasName()) { 51 out << (isa<GlobalValue>(V) ? '@' : '%') << V->getName(); 52 return; 53 } 54 if (V->getType()->isVoidTy()) { 55 if (isa<StoreInst>(V)) { 56 out << "store to "; 57 printValue(cast<StoreInst>(V)->getPointerOperand(), isL); 58 } else if (isa<CallInst>(V)) { 59 out << "call to "; 60 printValue(cast<CallInst>(V)->getCalledValue(), isL); 61 } else if (isa<InvokeInst>(V)) { 62 out << "invoke to "; 63 printValue(cast<InvokeInst>(V)->getCalledValue(), isL); 64 } else { 65 out << *V; 66 } 67 return; 68 } 69 if (isa<Constant>(V)) { 70 out << *V; 71 return; 72 } 73 74 unsigned N = contexts.size(); 75 while (N > 0) { 76 --N; 77 DiffContext &ctxt = contexts[N]; 78 if (!ctxt.IsFunction) continue; 79 if (isL) { 80 if (ctxt.LNumbering.empty()) 81 ComputeNumbering(cast<Function>(ctxt.L), ctxt.LNumbering); 82 out << '%' << ctxt.LNumbering[V]; 83 return; 84 } else { 85 if (ctxt.RNumbering.empty()) 86 ComputeNumbering(cast<Function>(ctxt.R), ctxt.RNumbering); 87 out << '%' << ctxt.RNumbering[V]; 88 return; 89 } 90 } 91 92 out << "<anonymous>"; 93 } 94 95 void DiffConsumer::header() { 96 if (contexts.empty()) return; 97 for (SmallVectorImpl<DiffContext>::iterator 98 I = contexts.begin(), E = contexts.end(); I != E; ++I) { 99 if (I->Differences) continue; 100 if (isa<Function>(I->L)) { 101 // Extra newline between functions. 102 if (Differences) out << "\n"; 103 104 Function *L = cast<Function>(I->L); 105 Function *R = cast<Function>(I->R); 106 if (L->getName() != R->getName()) 107 out << "in function " << L->getName() 108 << " / " << R->getName() << ":\n"; 109 else 110 out << "in function " << L->getName() << ":\n"; 111 } else if (isa<BasicBlock>(I->L)) { 112 BasicBlock *L = cast<BasicBlock>(I->L); 113 BasicBlock *R = cast<BasicBlock>(I->R); 114 if (L->hasName() && R->hasName() && L->getName() == R->getName()) 115 out << " in block %" << L->getName() << ":\n"; 116 else { 117 out << " in block "; 118 printValue(L, true); 119 out << " / "; 120 printValue(R, false); 121 out << ":\n"; 122 } 123 } else if (isa<Instruction>(I->L)) { 124 out << " in instruction "; 125 printValue(I->L, true); 126 out << " / "; 127 printValue(I->R, false); 128 out << ":\n"; 129 } 130 131 I->Differences = true; 132 } 133 } 134 135 void DiffConsumer::indent() { 136 unsigned N = Indent; 137 while (N--) out << ' '; 138 } 139 140 bool DiffConsumer::hadDifferences() const { 141 return Differences; 142 } 143 144 void DiffConsumer::enterContext(Value *L, Value *R) { 145 contexts.push_back(DiffContext(L, R)); 146 Indent += 2; 147 } 148 149 void DiffConsumer::exitContext() { 150 Differences |= contexts.back().Differences; 151 contexts.pop_back(); 152 Indent -= 2; 153 } 154 155 void DiffConsumer::log(StringRef text) { 156 header(); 157 indent(); 158 out << text << '\n'; 159 } 160 161 void DiffConsumer::logf(const LogBuilder &Log) { 162 header(); 163 indent(); 164 165 unsigned arg = 0; 166 167 StringRef format = Log.getFormat(); 168 while (true) { 169 size_t percent = format.find('%'); 170 if (percent == StringRef::npos) { 171 out << format; 172 break; 173 } 174 assert(format[percent] == '%'); 175 176 if (percent > 0) out << format.substr(0, percent); 177 178 switch (format[percent+1]) { 179 case '%': out << '%'; break; 180 case 'l': printValue(Log.getArgument(arg++), true); break; 181 case 'r': printValue(Log.getArgument(arg++), false); break; 182 default: llvm_unreachable("unknown format character"); 183 } 184 185 format = format.substr(percent+2); 186 } 187 188 out << '\n'; 189 } 190 191 void DiffConsumer::logd(const DiffLogBuilder &Log) { 192 header(); 193 194 for (unsigned I = 0, E = Log.getNumLines(); I != E; ++I) { 195 indent(); 196 switch (Log.getLineKind(I)) { 197 case DC_match: 198 out << " "; 199 Log.getLeft(I)->dump(); 200 //printValue(Log.getLeft(I), true); 201 break; 202 case DC_left: 203 out << "< "; 204 Log.getLeft(I)->dump(); 205 //printValue(Log.getLeft(I), true); 206 break; 207 case DC_right: 208 out << "> "; 209 Log.getRight(I)->dump(); 210 //printValue(Log.getRight(I), false); 211 break; 212 } 213 //out << "\n"; 214 } 215 } 216