DiffConsumer.cpp 5.5 KB

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