16bb1caddSDimitry Andric //===-- DiffConsumer.cpp - Difference Consumer ------------------*- C++ -*-===//
26bb1caddSDimitry Andric //
36bb1caddSDimitry Andric //                     The LLVM Compiler Infrastructure
46bb1caddSDimitry Andric //
56bb1caddSDimitry Andric // This file is distributed under the University of Illinois Open Source
66bb1caddSDimitry Andric // License. See LICENSE.TXT for details.
76bb1caddSDimitry Andric //
86bb1caddSDimitry Andric //===----------------------------------------------------------------------===//
96bb1caddSDimitry Andric //
107ae0e2c9SDimitry Andric // This files implements the LLVM difference Consumer
116bb1caddSDimitry Andric //
126bb1caddSDimitry Andric //===----------------------------------------------------------------------===//
136bb1caddSDimitry Andric 
146bb1caddSDimitry Andric #include "DiffConsumer.h"
15139f7f9bSDimitry Andric #include "llvm/IR/Instructions.h"
166bb1caddSDimitry Andric #include "llvm/Support/ErrorHandling.h"
17*7a7e6055SDimitry Andric #include "llvm/Support/Debug.h"
186bb1caddSDimitry Andric 
196bb1caddSDimitry Andric using namespace llvm;
206bb1caddSDimitry Andric 
ComputeNumbering(Function * F,DenseMap<Value *,unsigned> & Numbering)216bb1caddSDimitry Andric static void ComputeNumbering(Function *F, DenseMap<Value*,unsigned> &Numbering){
226bb1caddSDimitry Andric   unsigned IN = 0;
236bb1caddSDimitry Andric 
246bb1caddSDimitry Andric   // Arguments get the first numbers.
256bb1caddSDimitry Andric   for (Function::arg_iterator
266bb1caddSDimitry Andric          AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI)
276bb1caddSDimitry Andric     if (!AI->hasName())
286bb1caddSDimitry Andric       Numbering[&*AI] = IN++;
296bb1caddSDimitry Andric 
306bb1caddSDimitry Andric   // Walk the basic blocks in order.
316bb1caddSDimitry Andric   for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) {
326bb1caddSDimitry Andric     if (!FI->hasName())
336bb1caddSDimitry Andric       Numbering[&*FI] = IN++;
346bb1caddSDimitry Andric 
356bb1caddSDimitry Andric     // Walk the instructions in order.
366bb1caddSDimitry Andric     for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI)
376bb1caddSDimitry Andric       // void instructions don't get numbers.
386bb1caddSDimitry Andric       if (!BI->hasName() && !BI->getType()->isVoidTy())
396bb1caddSDimitry Andric         Numbering[&*BI] = IN++;
406bb1caddSDimitry Andric   }
416bb1caddSDimitry Andric 
426bb1caddSDimitry Andric   assert(!Numbering.empty() && "asked for numbering but numbering was no-op");
436bb1caddSDimitry Andric }
446bb1caddSDimitry Andric 
456bb1caddSDimitry Andric 
anchor()46dff0c46cSDimitry Andric void Consumer::anchor() { }
47dff0c46cSDimitry Andric 
printValue(Value * V,bool isL)486bb1caddSDimitry Andric void DiffConsumer::printValue(Value *V, bool isL) {
496bb1caddSDimitry Andric   if (V->hasName()) {
506bb1caddSDimitry Andric     out << (isa<GlobalValue>(V) ? '@' : '%') << V->getName();
516bb1caddSDimitry Andric     return;
526bb1caddSDimitry Andric   }
536bb1caddSDimitry Andric   if (V->getType()->isVoidTy()) {
546bb1caddSDimitry Andric     if (isa<StoreInst>(V)) {
556bb1caddSDimitry Andric       out << "store to ";
566bb1caddSDimitry Andric       printValue(cast<StoreInst>(V)->getPointerOperand(), isL);
576bb1caddSDimitry Andric     } else if (isa<CallInst>(V)) {
586bb1caddSDimitry Andric       out << "call to ";
596bb1caddSDimitry Andric       printValue(cast<CallInst>(V)->getCalledValue(), isL);
606bb1caddSDimitry Andric     } else if (isa<InvokeInst>(V)) {
616bb1caddSDimitry Andric       out << "invoke to ";
626bb1caddSDimitry Andric       printValue(cast<InvokeInst>(V)->getCalledValue(), isL);
636bb1caddSDimitry Andric     } else {
646bb1caddSDimitry Andric       out << *V;
656bb1caddSDimitry Andric     }
666bb1caddSDimitry Andric     return;
676bb1caddSDimitry Andric   }
68dff0c46cSDimitry Andric   if (isa<Constant>(V)) {
69dff0c46cSDimitry Andric     out << *V;
70dff0c46cSDimitry Andric     return;
71dff0c46cSDimitry Andric   }
726bb1caddSDimitry Andric 
736bb1caddSDimitry Andric   unsigned N = contexts.size();
746bb1caddSDimitry Andric   while (N > 0) {
756bb1caddSDimitry Andric     --N;
766bb1caddSDimitry Andric     DiffContext &ctxt = contexts[N];
776bb1caddSDimitry Andric     if (!ctxt.IsFunction) continue;
786bb1caddSDimitry Andric     if (isL) {
796bb1caddSDimitry Andric       if (ctxt.LNumbering.empty())
806bb1caddSDimitry Andric         ComputeNumbering(cast<Function>(ctxt.L), ctxt.LNumbering);
816bb1caddSDimitry Andric       out << '%' << ctxt.LNumbering[V];
826bb1caddSDimitry Andric       return;
836bb1caddSDimitry Andric     } else {
846bb1caddSDimitry Andric       if (ctxt.RNumbering.empty())
856bb1caddSDimitry Andric         ComputeNumbering(cast<Function>(ctxt.R), ctxt.RNumbering);
866bb1caddSDimitry Andric       out << '%' << ctxt.RNumbering[V];
876bb1caddSDimitry Andric       return;
886bb1caddSDimitry Andric     }
896bb1caddSDimitry Andric   }
906bb1caddSDimitry Andric 
916bb1caddSDimitry Andric   out << "<anonymous>";
926bb1caddSDimitry Andric }
936bb1caddSDimitry Andric 
header()946bb1caddSDimitry Andric void DiffConsumer::header() {
956bb1caddSDimitry Andric   if (contexts.empty()) return;
966bb1caddSDimitry Andric   for (SmallVectorImpl<DiffContext>::iterator
976bb1caddSDimitry Andric          I = contexts.begin(), E = contexts.end(); I != E; ++I) {
986bb1caddSDimitry Andric     if (I->Differences) continue;
996bb1caddSDimitry Andric     if (isa<Function>(I->L)) {
1006bb1caddSDimitry Andric       // Extra newline between functions.
1016bb1caddSDimitry Andric       if (Differences) out << "\n";
1026bb1caddSDimitry Andric 
1036bb1caddSDimitry Andric       Function *L = cast<Function>(I->L);
1046bb1caddSDimitry Andric       Function *R = cast<Function>(I->R);
1056bb1caddSDimitry Andric       if (L->getName() != R->getName())
1066bb1caddSDimitry Andric         out << "in function " << L->getName()
1076bb1caddSDimitry Andric             << " / " << R->getName() << ":\n";
1086bb1caddSDimitry Andric       else
1096bb1caddSDimitry Andric         out << "in function " << L->getName() << ":\n";
1106bb1caddSDimitry Andric     } else if (isa<BasicBlock>(I->L)) {
1116bb1caddSDimitry Andric       BasicBlock *L = cast<BasicBlock>(I->L);
1126bb1caddSDimitry Andric       BasicBlock *R = cast<BasicBlock>(I->R);
1136bb1caddSDimitry Andric       if (L->hasName() && R->hasName() && L->getName() == R->getName())
1146bb1caddSDimitry Andric         out << "  in block %" << L->getName() << ":\n";
1156bb1caddSDimitry Andric       else {
1166bb1caddSDimitry Andric         out << "  in block ";
1176bb1caddSDimitry Andric         printValue(L, true);
1186bb1caddSDimitry Andric         out << " / ";
1196bb1caddSDimitry Andric         printValue(R, false);
1206bb1caddSDimitry Andric         out << ":\n";
1216bb1caddSDimitry Andric       }
1226bb1caddSDimitry Andric     } else if (isa<Instruction>(I->L)) {
1236bb1caddSDimitry Andric       out << "    in instruction ";
1246bb1caddSDimitry Andric       printValue(I->L, true);
1256bb1caddSDimitry Andric       out << " / ";
1266bb1caddSDimitry Andric       printValue(I->R, false);
1276bb1caddSDimitry Andric       out << ":\n";
1286bb1caddSDimitry Andric     }
1296bb1caddSDimitry Andric 
1306bb1caddSDimitry Andric     I->Differences = true;
1316bb1caddSDimitry Andric   }
1326bb1caddSDimitry Andric }
1336bb1caddSDimitry Andric 
indent()1346bb1caddSDimitry Andric void DiffConsumer::indent() {
1356bb1caddSDimitry Andric   unsigned N = Indent;
1366bb1caddSDimitry Andric   while (N--) out << ' ';
1376bb1caddSDimitry Andric }
1386bb1caddSDimitry Andric 
hadDifferences() const1396bb1caddSDimitry Andric bool DiffConsumer::hadDifferences() const {
1406bb1caddSDimitry Andric   return Differences;
1416bb1caddSDimitry Andric }
1426bb1caddSDimitry Andric 
enterContext(Value * L,Value * R)1436bb1caddSDimitry Andric void DiffConsumer::enterContext(Value *L, Value *R) {
1446bb1caddSDimitry Andric   contexts.push_back(DiffContext(L, R));
1456bb1caddSDimitry Andric   Indent += 2;
1466bb1caddSDimitry Andric }
1476bb1caddSDimitry Andric 
exitContext()1486bb1caddSDimitry Andric void DiffConsumer::exitContext() {
1496bb1caddSDimitry Andric   Differences |= contexts.back().Differences;
1506bb1caddSDimitry Andric   contexts.pop_back();
1516bb1caddSDimitry Andric   Indent -= 2;
1526bb1caddSDimitry Andric }
1536bb1caddSDimitry Andric 
log(StringRef text)1546bb1caddSDimitry Andric void DiffConsumer::log(StringRef text) {
1556bb1caddSDimitry Andric   header();
1566bb1caddSDimitry Andric   indent();
1576bb1caddSDimitry Andric   out << text << '\n';
1586bb1caddSDimitry Andric }
1596bb1caddSDimitry Andric 
logf(const LogBuilder & Log)1606bb1caddSDimitry Andric void DiffConsumer::logf(const LogBuilder &Log) {
1616bb1caddSDimitry Andric   header();
1626bb1caddSDimitry Andric   indent();
1636bb1caddSDimitry Andric 
1646bb1caddSDimitry Andric   unsigned arg = 0;
1656bb1caddSDimitry Andric 
1666bb1caddSDimitry Andric   StringRef format = Log.getFormat();
1676bb1caddSDimitry Andric   while (true) {
1686bb1caddSDimitry Andric     size_t percent = format.find('%');
1696bb1caddSDimitry Andric     if (percent == StringRef::npos) {
1706bb1caddSDimitry Andric       out << format;
1716bb1caddSDimitry Andric       break;
1726bb1caddSDimitry Andric     }
1736bb1caddSDimitry Andric     assert(format[percent] == '%');
1746bb1caddSDimitry Andric 
1756bb1caddSDimitry Andric     if (percent > 0) out << format.substr(0, percent);
1766bb1caddSDimitry Andric 
1776bb1caddSDimitry Andric     switch (format[percent+1]) {
1786bb1caddSDimitry Andric     case '%': out << '%'; break;
1796bb1caddSDimitry Andric     case 'l': printValue(Log.getArgument(arg++), true); break;
1806bb1caddSDimitry Andric     case 'r': printValue(Log.getArgument(arg++), false); break;
1816bb1caddSDimitry Andric     default: llvm_unreachable("unknown format character");
1826bb1caddSDimitry Andric     }
1836bb1caddSDimitry Andric 
1846bb1caddSDimitry Andric     format = format.substr(percent+2);
1856bb1caddSDimitry Andric   }
1866bb1caddSDimitry Andric 
1876bb1caddSDimitry Andric   out << '\n';
1886bb1caddSDimitry Andric }
1896bb1caddSDimitry Andric 
logd(const DiffLogBuilder & Log)1906bb1caddSDimitry Andric void DiffConsumer::logd(const DiffLogBuilder &Log) {
1916bb1caddSDimitry Andric   header();
1926bb1caddSDimitry Andric 
1936bb1caddSDimitry Andric   for (unsigned I = 0, E = Log.getNumLines(); I != E; ++I) {
1946bb1caddSDimitry Andric     indent();
1956bb1caddSDimitry Andric     switch (Log.getLineKind(I)) {
1966bb1caddSDimitry Andric     case DC_match:
1976bb1caddSDimitry Andric       out << "  ";
198*7a7e6055SDimitry Andric       Log.getLeft(I)->print(dbgs()); dbgs() << '\n';
1996bb1caddSDimitry Andric       //printValue(Log.getLeft(I), true);
2006bb1caddSDimitry Andric       break;
2016bb1caddSDimitry Andric     case DC_left:
2026bb1caddSDimitry Andric       out << "< ";
203*7a7e6055SDimitry Andric       Log.getLeft(I)->print(dbgs()); dbgs() << '\n';
2046bb1caddSDimitry Andric       //printValue(Log.getLeft(I), true);
2056bb1caddSDimitry Andric       break;
2066bb1caddSDimitry Andric     case DC_right:
2076bb1caddSDimitry Andric       out << "> ";
208*7a7e6055SDimitry Andric       Log.getRight(I)->print(dbgs()); dbgs() << '\n';
2096bb1caddSDimitry Andric       //printValue(Log.getRight(I), false);
2106bb1caddSDimitry Andric       break;
2116bb1caddSDimitry Andric     }
2126bb1caddSDimitry Andric     //out << "\n";
2136bb1caddSDimitry Andric   }
2146bb1caddSDimitry Andric }
215