Reapply r110396, with fixes to appease the Linux buildbot gods.
[oota-llvm.git] / lib / CodeGen / RenderMachineFunction.cpp
1 //===-- llvm/CodeGen/RenderMachineFunction.cpp - MF->HTML -----s-----------===//
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 #define DEBUG_TYPE "rendermf"
11
12 #include "RenderMachineFunction.h"
13
14 #include "VirtRegMap.h"
15
16 #include "llvm/Function.h"
17 #include "llvm/Module.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/CodeGen/LiveIntervalAnalysis.h"
20 #include "llvm/CodeGen/MachineFunction.h"
21 #include "llvm/CodeGen/MachineInstr.h"
22 #include "llvm/CodeGen/MachineRegisterInfo.h"
23 #include "llvm/Support/CommandLine.h"
24 #include "llvm/Support/Debug.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include "llvm/Target/TargetMachine.h"
27
28 #include <sstream>
29
30 using namespace llvm;
31
32 char RenderMachineFunction::ID = 0;
33 INITIALIZE_PASS(RenderMachineFunction, "rendermf",
34                 "Render machine functions (and related info) to HTML pages",
35                 false, false);
36
37 static cl::opt<std::string>
38 outputFileSuffix("rmf-file-suffix",
39                  cl::desc("Appended to function name to get output file name "
40                           "(default: \".html\")"),
41                  cl::init(".html"), cl::Hidden);
42
43 static cl::opt<std::string>
44 machineFuncsToRender("rmf-funcs",
45                      cl::desc("Coma seperated list of functions to render"
46                               ", or \"*\"."),
47                      cl::init(""), cl::Hidden);
48
49 static cl::opt<std::string>
50 pressureClasses("rmf-classes",
51                 cl::desc("Register classes to render pressure for."),
52                 cl::init(""), cl::Hidden);
53
54 static cl::opt<std::string>
55 showIntervals("rmf-intervals",
56               cl::desc("Live intervals to show alongside code."),
57               cl::init(""), cl::Hidden);
58
59 static cl::opt<bool>
60 showEmptyIndexes("rmf-empty-indexes",
61                  cl::desc("Render indexes not associated with instructions or "
62                           "MBB starts."),
63                  cl::init(false), cl::Hidden);
64
65 static cl::opt<bool>
66 useFancyVerticals("rmf-fancy-verts",
67                   cl::desc("Use SVG for vertical text."),
68                   cl::init(true), cl::Hidden);
69
70 static cl::opt<bool>
71 prettyHTML("rmf-pretty-html",
72            cl::desc("Pretty print HTML. For debugging the renderer only.."),
73            cl::init(false), cl::Hidden);
74
75
76 namespace llvm {
77
78   bool MFRenderingOptions::renderingOptionsProcessed;
79   std::set<std::string> MFRenderingOptions::mfNamesToRender;
80   bool MFRenderingOptions::renderAllMFs = false;
81
82   std::set<std::string> MFRenderingOptions::classNamesToRender;
83   bool MFRenderingOptions::renderAllClasses = false;
84
85   std::set<std::pair<unsigned, unsigned> >
86     MFRenderingOptions::intervalNumsToRender;
87   unsigned MFRenderingOptions::intervalTypesToRender = ExplicitOnly;
88
89   template <typename OutputItr>
90   void MFRenderingOptions::splitComaSeperatedList(const std::string &s,
91                                                          OutputItr outItr) {
92     std::string::const_iterator curPos = s.begin();
93     std::string::const_iterator nextComa = std::find(curPos, s.end(), ',');
94     while (nextComa != s.end()) {
95       std::string elem;
96       std::copy(curPos, nextComa, std::back_inserter(elem));
97       *outItr = elem;
98       ++outItr;
99       curPos = llvm::next(nextComa);
100       nextComa = std::find(curPos, s.end(), ',');
101     }
102
103     if (curPos != s.end()) {
104       std::string elem;
105       std::copy(curPos, s.end(), std::back_inserter(elem));
106       *outItr = elem;
107       ++outItr;
108     }
109   }
110
111   void MFRenderingOptions::processOptions() {
112     if (!renderingOptionsProcessed) {
113       processFuncNames();
114       processRegClassNames();
115       processIntervalNumbers();
116       renderingOptionsProcessed = true;
117     }
118   }
119
120   void MFRenderingOptions::processFuncNames() {
121     if (machineFuncsToRender == "*") {
122       renderAllMFs = true;
123     } else {
124       splitComaSeperatedList(machineFuncsToRender,
125                              std::inserter(mfNamesToRender,
126                                            mfNamesToRender.begin()));
127     }
128   }
129
130   void MFRenderingOptions::processRegClassNames() {
131     if (pressureClasses == "*") {
132       renderAllClasses = true;
133     } else {
134       splitComaSeperatedList(pressureClasses,
135                              std::inserter(classNamesToRender,
136                                            classNamesToRender.begin()));
137     }
138   }
139
140   void MFRenderingOptions::processIntervalNumbers() {
141     std::set<std::string> intervalRanges;
142     splitComaSeperatedList(showIntervals,
143                            std::inserter(intervalRanges,
144                                          intervalRanges.begin()));
145     std::for_each(intervalRanges.begin(), intervalRanges.end(),
146                   processIntervalRange);
147   }
148
149   void MFRenderingOptions::processIntervalRange(
150                                           const std::string &intervalRangeStr) {
151     if (intervalRangeStr == "*") {
152       intervalTypesToRender |= All;
153     } else if (intervalRangeStr == "virt*") {
154       intervalTypesToRender |= VirtPlusExplicit;
155     } else if (intervalRangeStr == "phys*") {
156       intervalTypesToRender |= PhysPlusExplicit;
157     } else {
158       std::istringstream iss(intervalRangeStr);
159       unsigned reg1, reg2;
160       if ((iss >> reg1 >> std::ws)) {
161         if (iss.eof()) {
162           intervalNumsToRender.insert(std::make_pair(reg1, reg1 + 1));
163         } else {
164           char c;
165           iss >> c;
166           if (c == '-' && (iss >> reg2)) {
167             intervalNumsToRender.insert(std::make_pair(reg1, reg2 + 1));
168           } else {
169             dbgs() << "Warning: Invalid interval range \""
170                    << intervalRangeStr << "\" in -rmf-intervals. Skipping.\n";
171           }
172         }
173       } else {
174         dbgs() << "Warning: Invalid interval number \""
175                << intervalRangeStr << "\" in -rmf-intervals. Skipping.\n";
176       }
177     }
178   }
179
180   void MFRenderingOptions::setup(MachineFunction *mf,
181                                  const TargetRegisterInfo *tri,
182                                  LiveIntervals *lis) {
183     this->mf = mf;
184     this->tri = tri;
185     this->lis = lis;
186
187     clear();
188   }
189
190   void MFRenderingOptions::clear() {
191     regClassesTranslatedToCurrentFunction = false;
192     regClassSet.clear();
193
194     intervalsTranslatedToCurrentFunction = false;
195     intervalSet.clear();
196   }
197
198   void MFRenderingOptions::resetRenderSpecificOptions() {
199     intervalSet.clear();
200     intervalsTranslatedToCurrentFunction = false;
201   }
202
203   bool MFRenderingOptions::shouldRenderCurrentMachineFunction() const {
204     processOptions();
205
206     return (renderAllMFs ||
207             mfNamesToRender.find(mf->getFunction()->getName()) !=
208               mfNamesToRender.end());    
209   }
210
211   const MFRenderingOptions::RegClassSet& MFRenderingOptions::regClasses() const{
212     translateRegClassNamesToCurrentFunction();
213     return regClassSet;
214   }
215
216   const MFRenderingOptions::IntervalSet& MFRenderingOptions::intervals() const {
217     translateIntervalNumbersToCurrentFunction();
218     return intervalSet;
219   }
220
221   bool MFRenderingOptions::renderEmptyIndexes() const {
222     return showEmptyIndexes;
223   }
224
225   bool MFRenderingOptions::fancyVerticals() const {
226     return useFancyVerticals;
227   }
228
229   void MFRenderingOptions::translateRegClassNamesToCurrentFunction() const {
230     if (!regClassesTranslatedToCurrentFunction) {
231       processOptions();
232       for (TargetRegisterInfo::regclass_iterator rcItr = tri->regclass_begin(),
233                                                  rcEnd = tri->regclass_end();
234            rcItr != rcEnd; ++rcItr) {
235         const TargetRegisterClass *trc = *rcItr;
236         if (renderAllClasses ||
237             classNamesToRender.find(trc->getName()) !=
238               classNamesToRender.end()) {
239           regClassSet.insert(trc);
240         }
241       }
242       regClassesTranslatedToCurrentFunction = true;
243     }
244   }
245
246   void MFRenderingOptions::translateIntervalNumbersToCurrentFunction() const {
247     if (!intervalsTranslatedToCurrentFunction) {
248       processOptions();
249
250       // If we're not just doing explicit then do a copy over all matching
251       // types.
252       if (intervalTypesToRender != ExplicitOnly) {
253         for (LiveIntervals::iterator liItr = lis->begin(), liEnd = lis->end();
254              liItr != liEnd; ++liItr) {
255
256           if ((TargetRegisterInfo::isPhysicalRegister(liItr->first) &&
257                (intervalTypesToRender & PhysPlusExplicit)) ||
258               (TargetRegisterInfo::isVirtualRegister(liItr->first) &&
259                (intervalTypesToRender & VirtPlusExplicit))) {
260             intervalSet.insert(liItr->second);
261           }
262         }
263       }
264
265       // If we need to process the explicit list...
266       if (intervalTypesToRender != All) {
267         for (std::set<std::pair<unsigned, unsigned> >::const_iterator
268                regRangeItr = intervalNumsToRender.begin(),
269                regRangeEnd = intervalNumsToRender.end();
270              regRangeItr != regRangeEnd; ++regRangeItr) {
271           const std::pair<unsigned, unsigned> &range = *regRangeItr;
272           for (unsigned reg = range.first; reg != range.second; ++reg) {
273             if (lis->hasInterval(reg)) {
274               intervalSet.insert(&lis->getInterval(reg));
275             }
276           }
277         }
278       }
279
280       intervalsTranslatedToCurrentFunction = true;
281     }
282   }
283
284   // ---------- TargetRegisterExtraInformation implementation ----------
285
286   TargetRegisterExtraInfo::TargetRegisterExtraInfo()
287     : mapsPopulated(false) {
288   }
289
290   void TargetRegisterExtraInfo::setup(MachineFunction *mf,
291                                       MachineRegisterInfo *mri,
292                                       const TargetRegisterInfo *tri,
293                                       LiveIntervals *lis) {
294     this->mf = mf;
295     this->mri = mri;
296     this->tri = tri;
297     this->lis = lis;
298   }
299
300   void TargetRegisterExtraInfo::reset() {
301     if (!mapsPopulated) {
302       initWorst();
303       //initBounds();
304       initCapacity();
305       mapsPopulated = true;
306     }
307
308     resetPressureAndLiveStates();
309   }
310
311   void TargetRegisterExtraInfo::clear() {
312     prWorst.clear();
313     vrWorst.clear();
314     capacityMap.clear();
315     pressureMap.clear();
316     //liveStatesMap.clear();
317     mapsPopulated = false;
318   }
319
320   void TargetRegisterExtraInfo::initWorst() {
321     assert(!mapsPopulated && prWorst.empty() && vrWorst.empty() &&
322            "Worst map already initialised?");
323
324     // Start with the physical registers.
325     for (unsigned preg = 1; preg < tri->getNumRegs(); ++preg) {
326       WorstMapLine &pregLine = prWorst[preg];
327
328       for (TargetRegisterInfo::regclass_iterator rcItr = tri->regclass_begin(),
329                                                  rcEnd = tri->regclass_end();
330            rcItr != rcEnd; ++rcItr) {
331         const TargetRegisterClass *trc = *rcItr;
332
333         unsigned numOverlaps = 0;
334         for (TargetRegisterClass::iterator rItr = trc->begin(),
335                                            rEnd = trc->end();
336              rItr != rEnd; ++rItr) {
337           unsigned trcPReg = *rItr;
338           if (tri->regsOverlap(preg, trcPReg))
339             ++numOverlaps;
340         }
341         
342         pregLine[trc] = numOverlaps;
343       }
344     }
345
346     // Now the register classes.
347     for (TargetRegisterInfo::regclass_iterator rc1Itr = tri->regclass_begin(),
348                                                rcEnd = tri->regclass_end();
349          rc1Itr != rcEnd; ++rc1Itr) {
350       const TargetRegisterClass *trc1 = *rc1Itr;
351       WorstMapLine &classLine = vrWorst[trc1];
352
353       for (TargetRegisterInfo::regclass_iterator rc2Itr = tri->regclass_begin();
354            rc2Itr != rcEnd; ++rc2Itr) {
355         const TargetRegisterClass *trc2 = *rc2Itr;
356
357         unsigned worst = 0;
358
359         for (TargetRegisterClass::iterator trc1Itr = trc1->begin(),
360                                            trc1End = trc1->end();
361              trc1Itr != trc1End; ++trc1Itr) {
362           unsigned trc1Reg = *trc1Itr;
363           unsigned trc1RegWorst = 0;
364
365           for (TargetRegisterClass::iterator trc2Itr = trc2->begin(),
366                                              trc2End = trc2->end();
367                trc2Itr != trc2End; ++trc2Itr) {
368             unsigned trc2Reg = *trc2Itr;
369             if (tri->regsOverlap(trc1Reg, trc2Reg))
370               ++trc1RegWorst;
371           }
372           if (trc1RegWorst > worst) {
373             worst = trc1RegWorst;
374           }    
375         }
376
377         if (worst != 0) {
378           classLine[trc2] = worst;
379         }
380       }
381     }
382   }
383
384   unsigned TargetRegisterExtraInfo::getWorst(
385                                         unsigned reg,
386                                         const TargetRegisterClass *trc) const {
387     const WorstMapLine *wml = 0;
388     if (TargetRegisterInfo::isPhysicalRegister(reg)) {
389       PRWorstMap::const_iterator prwItr = prWorst.find(reg);
390       assert(prwItr != prWorst.end() && "Missing prWorst entry.");
391       wml = &prwItr->second;
392     } else {
393       const TargetRegisterClass *regTRC = mri->getRegClass(reg);
394       VRWorstMap::const_iterator vrwItr = vrWorst.find(regTRC);
395       assert(vrwItr != vrWorst.end() && "Missing vrWorst entry.");
396       wml = &vrwItr->second;
397     }
398     
399     WorstMapLine::const_iterator wmlItr = wml->find(trc);
400     if (wmlItr == wml->end())
401       return 0;
402
403     return wmlItr->second;
404   }
405
406   void TargetRegisterExtraInfo::initCapacity() {
407     assert(!mapsPopulated && capacityMap.empty() &&
408            "Capacity map already initialised?");
409
410     for (TargetRegisterInfo::regclass_iterator rcItr = tri->regclass_begin(),
411            rcEnd = tri->regclass_end();
412          rcItr != rcEnd; ++rcItr) {
413       const TargetRegisterClass *trc = *rcItr;
414       unsigned capacity = std::distance(trc->allocation_order_begin(*mf),
415                                         trc->allocation_order_end(*mf));
416
417       if (capacity != 0)
418         capacityMap[trc] = capacity;
419     }
420   }
421
422   unsigned TargetRegisterExtraInfo::getCapacity(
423                                          const TargetRegisterClass *trc) const {
424     CapacityMap::const_iterator cmItr = capacityMap.find(trc);
425     assert(cmItr != capacityMap.end() &&
426            "vreg with unallocable register class");
427     return cmItr->second;
428   }
429
430   void TargetRegisterExtraInfo::resetPressureAndLiveStates() {
431     pressureMap.clear();
432     //liveStatesMap.clear();
433
434     // Iterate over all slots.
435     
436
437     // Iterate over all live intervals.
438     for (LiveIntervals::iterator liItr = lis->begin(),
439            liEnd = lis->end();
440          liItr != liEnd; ++liItr) {
441       LiveInterval *li = liItr->second;
442
443       const TargetRegisterClass *liTRC;
444
445       if (TargetRegisterInfo::isPhysicalRegister(li->reg))
446         continue;
447       
448       liTRC = mri->getRegClass(li->reg);
449      
450
451       // For all ranges in the current interal.
452       for (LiveInterval::iterator lrItr = li->begin(),
453              lrEnd = li->end();
454            lrItr != lrEnd; ++lrItr) {
455         LiveRange *lr = &*lrItr;
456         
457         // For all slots in the current range.
458         for (SlotIndex i = lr->start; i != lr->end; i = i.getNextSlot()) {
459
460           // Record increased pressure at index for all overlapping classes.
461           for (TargetRegisterInfo::regclass_iterator
462                  rcItr = tri->regclass_begin(),
463                  rcEnd = tri->regclass_end();
464                rcItr != rcEnd; ++rcItr) {
465             const TargetRegisterClass *trc = *rcItr;
466
467             if (trc->allocation_order_begin(*mf) ==
468                 trc->allocation_order_end(*mf))
469               continue;
470
471             unsigned worstAtI = getWorst(li->reg, trc);
472
473             if (worstAtI != 0) {
474               pressureMap[i][trc] += worstAtI;
475             }
476           }
477         }
478       }
479     } 
480   }
481
482   unsigned TargetRegisterExtraInfo::getPressureAtSlot(
483                                                  const TargetRegisterClass *trc,
484                                                  SlotIndex i) const {
485     PressureMap::const_iterator pmItr = pressureMap.find(i);
486     if (pmItr == pressureMap.end())
487       return 0;
488     const PressureMapLine &pmLine = pmItr->second;
489     PressureMapLine::const_iterator pmlItr = pmLine.find(trc);
490     if (pmlItr == pmLine.end())
491       return 0;
492     return pmlItr->second;
493   }
494
495   bool TargetRegisterExtraInfo::classOverCapacityAtSlot(
496                                                  const TargetRegisterClass *trc,
497                                                  SlotIndex i) const {
498     return (getPressureAtSlot(trc, i) > getCapacity(trc));
499   }
500
501   // ---------- MachineFunctionRenderer implementation ----------
502
503   void RenderMachineFunction::Spacer::print(raw_ostream &os) const {
504     if (!prettyHTML)
505       return;
506     for (unsigned i = 0; i < ns; ++i) {
507       os << " ";
508     }
509   }
510
511   RenderMachineFunction::Spacer RenderMachineFunction::s(unsigned ns) const {
512     return Spacer(ns);
513   }
514
515   raw_ostream& operator<<(raw_ostream &os, const RenderMachineFunction::Spacer &s) {
516     s.print(os);
517     return os;
518   }
519
520   template <typename Iterator>
521   std::string RenderMachineFunction::escapeChars(Iterator sBegin, Iterator sEnd) const {
522     std::string r;
523
524     for (Iterator sItr = sBegin; sItr != sEnd; ++sItr) {
525       char c = *sItr;
526
527       switch (c) {
528         case '<': r.append("&lt;"); break;
529         case '>': r.append("&gt;"); break;
530         case '&': r.append("&amp;"); break;
531         case ' ': r.append("&nbsp;"); break;
532         case '\"': r.append("&quot;"); break;
533         default: r.push_back(c); break;
534       }
535     }
536
537     return r;
538   }
539
540   RenderMachineFunction::LiveState
541   RenderMachineFunction::getLiveStateAt(const LiveInterval *li,
542                                         SlotIndex i) const {
543     const MachineInstr *mi = sis->getInstructionFromIndex(i);
544
545     if (li->liveAt(i)) {
546       if (mi == 0) {
547         if (vrm == 0 || 
548             (vrm->getStackSlot(li->reg) == VirtRegMap::NO_STACK_SLOT)) {
549           return AliveReg;
550         } else {
551           return AliveStack;
552         }
553       } else {
554         if (i.getSlot() == SlotIndex::DEF &&
555             mi->definesRegister(li->reg, tri)) {
556           return Defined;
557         } else if (i.getSlot() == SlotIndex::USE &&
558                    mi->readsRegister(li->reg)) {
559           return Used;
560         } else {
561           if (vrm == 0 || 
562               (vrm->getStackSlot(li->reg) == VirtRegMap::NO_STACK_SLOT)) {
563             return AliveReg;
564           } else {
565             return AliveStack;
566           }
567         }
568       }
569     }
570     return Dead;
571   }
572
573   RenderMachineFunction::PressureState
574   RenderMachineFunction::getPressureStateAt(const TargetRegisterClass *trc,
575                                               SlotIndex i) const {
576     if (trei.getPressureAtSlot(trc, i) == 0) {
577       return Zero;
578     } else if (trei.classOverCapacityAtSlot(trc, i)){
579       return High;
580     }
581     return Low;
582   }
583
584   /// \brief Render a machine instruction.
585   void RenderMachineFunction::renderMachineInstr(raw_ostream &os,
586                                                  const MachineInstr *mi) const {
587     std::string s;
588     raw_string_ostream oss(s);
589     oss << *mi;
590
591     os << escapeChars(oss.str());
592   }
593
594   template <typename T>
595   void RenderMachineFunction::renderVertical(const Spacer &indent,
596                                              raw_ostream &os,
597                                              const T &t) const {
598     if (ro.fancyVerticals()) {
599       os << indent << "<object\n"
600          << indent + s(2) << "class=\"obj\"\n"
601          << indent + s(2) << "type=\"image/svg+xml\"\n"
602          << indent + s(2) << "width=\"14px\"\n"
603          << indent + s(2) << "height=\"55px\"\n"
604          << indent + s(2) << "data=\"data:image/svg+xml,\n"
605          << indent + s(4) << "<svg xmlns='http://www.w3.org/2000/svg'>\n"
606          << indent + s(6) << "<text x='-55' y='10' "
607                              "font-family='Courier' font-size='12' "
608                              "transform='rotate(-90)' "
609                              "text-rendering='optimizeSpeed' "
610                              "fill='#000'>" << t << "</text>\n"
611          << indent + s(4) << "</svg>\">\n"
612          << indent << "</object>\n";
613     } else {
614       std::ostringstream oss;
615       oss << t;
616       std::string tStr(oss.str());
617
618       os << indent;
619       for (std::string::iterator tStrItr = tStr.begin(), tStrEnd = tStr.end();
620            tStrItr != tStrEnd; ++tStrItr) {
621         os << *tStrItr << "<br/>";
622       }
623       os << "\n";
624     }
625   }
626
627   void RenderMachineFunction::insertCSS(const Spacer &indent,
628                                         raw_ostream &os) const {
629     os << indent << "<style type=\"text/css\">\n"
630        << indent + s(2) << "body { font-color: black; }\n"
631        << indent + s(2) << "table.code td { font-family: monospace; "
632                     "border-width: 0px; border-style: solid; "
633                     "border-bottom: 1px solid #dddddd; white-space: nowrap; }\n"
634        << indent + s(2) << "table.code td.p-z { background-color: #000000; }\n"
635        << indent + s(2) << "table.code td.p-l { background-color: #00ff00; }\n"
636        << indent + s(2) << "table.code td.p-h { background-color: #ff0000; }\n"
637        << indent + s(2) << "table.code td.l-n { background-color: #ffffff; }\n"
638        << indent + s(2) << "table.code td.l-d { background-color: #ff0000; }\n"
639        << indent + s(2) << "table.code td.l-u { background-color: #ffff00; }\n"
640        << indent + s(2) << "table.code td.l-r { background-color: #000000; }\n"
641        << indent + s(2) << "table.code td.l-s { background-color: #770000; }\n"
642        << indent + s(2) << "table.code th { border-width: 0px; "
643                     "border-style: solid; }\n"
644        << indent << "</style>\n";
645   }
646
647   void RenderMachineFunction::renderFunctionSummary(
648                                     const Spacer &indent, raw_ostream &os,
649                                     const char * const renderContextStr) const {
650     os << indent << "<h1>Function: " << mf->getFunction()->getName()
651                  << "</h1>\n"
652        << indent << "<h2>Rendering context: " << renderContextStr << "</h2>\n";
653   }
654
655
656   void RenderMachineFunction::renderPressureTableLegend(
657                                                       const Spacer &indent,
658                                                       raw_ostream &os) const {
659     os << indent << "<h2>Rendering Pressure Legend:</h2>\n"
660        << indent << "<table class=\"code\">\n"
661        << indent + s(2) << "<tr>\n"
662        << indent + s(4) << "<th>Pressure</th><th>Description</th>"
663                     "<th>Appearance</th>\n"
664        << indent + s(2) << "</tr>\n"
665        << indent + s(2) << "<tr>\n"
666        << indent + s(4) << "<td>No Pressure</td>"
667                     "<td>No physical registers of this class requested.</td>"
668                     "<td class=\"p-z\">&nbsp;&nbsp;</td>\n"
669        << indent + s(2) << "</tr>\n"
670        << indent + s(2) << "<tr>\n"
671        << indent + s(4) << "<td>Low Pressure</td>"
672                     "<td>Sufficient physical registers to meet demand.</td>"
673                     "<td class=\"p-l\">&nbsp;&nbsp;</td>\n"
674        << indent + s(2) << "</tr>\n"
675        << indent + s(2) << "<tr>\n"
676        << indent + s(4) << "<td>High Pressure</td>"
677                     "<td>Potentially insufficient physical registers to meet demand.</td>"
678                     "<td class=\"p-h\">&nbsp;&nbsp;</td>\n"
679        << indent + s(2) << "</tr>\n"
680        << indent << "</table>\n";
681   }
682
683   template <typename CellType>
684   void RenderMachineFunction::renderCellsWithRLE(
685                    const Spacer &indent, raw_ostream &os,
686                    const std::pair<CellType, unsigned> &rleAccumulator,
687                    const std::map<CellType, std::string> &cellTypeStrs) const {
688
689     if (rleAccumulator.second == 0)
690       return; 
691
692     typename std::map<CellType, std::string>::const_iterator ctsItr =
693       cellTypeStrs.find(rleAccumulator.first);
694
695     assert(ctsItr != cellTypeStrs.end() && "No string for given cell type.");
696
697     os << indent + s(4) << "<td class=\"" << ctsItr->second << "\"";
698     if (rleAccumulator.second > 1)
699       os << " colspan=" << rleAccumulator.second;
700     os << "></td>\n";
701   }
702
703
704   void RenderMachineFunction::renderCodeTablePlusPI(const Spacer &indent,
705                                                     raw_ostream &os) const {
706
707     std::map<LiveState, std::string> lsStrs;
708     lsStrs[Dead] = "l-n";
709     lsStrs[Defined] = "l-d";
710     lsStrs[Used] = "l-u";
711     lsStrs[AliveReg] = "l-r";
712     lsStrs[AliveStack] = "l-s";
713
714     std::map<PressureState, std::string> psStrs;
715     psStrs[Zero] = "p-z";
716     psStrs[Low] = "p-l";
717     psStrs[High] = "p-h";
718
719     // Open the table... 
720
721     os << indent << "<table cellpadding=0 cellspacing=0 class=\"code\">\n"
722        << indent + s(2) << "<tr>\n";
723
724     // Render the header row...
725
726     os << indent + s(4) << "<th>index</th>\n"
727        << indent + s(4) << "<th>instr</th>\n";
728
729     // Render class names if necessary...
730     if (!ro.regClasses().empty()) {
731       for (MFRenderingOptions::RegClassSet::const_iterator
732              rcItr = ro.regClasses().begin(),
733              rcEnd = ro.regClasses().end();
734            rcItr != rcEnd; ++rcItr) {
735         const TargetRegisterClass *trc = *rcItr;
736         os << indent + s(4) << "<th>\n";
737         renderVertical(indent + s(6), os, trc->getName());
738         os << indent + s(4) << "</th>\n";
739       }
740     }
741
742     // FIXME: Is there a nicer way to insert space between columns in HTML?
743     if (!ro.regClasses().empty() && !ro.intervals().empty())
744       os << indent + s(4) << "<th>&nbsp;&nbsp;</th>\n";
745
746     // Render interval numbers if necessary...
747     if (!ro.intervals().empty()) {
748       for (MFRenderingOptions::IntervalSet::const_iterator
749              liItr = ro.intervals().begin(),
750              liEnd = ro.intervals().end();
751            liItr != liEnd; ++liItr) {
752
753         const LiveInterval *li = *liItr;
754         os << indent + s(4) << "<th>\n";
755         renderVertical(indent + s(6), os, li->reg);
756         os << indent + s(4) << "</th>\n";
757       }
758     }
759
760     os << indent + s(2) << "</tr>\n";
761
762     // End header row, start with the data rows...
763
764     MachineInstr *mi = 0;
765
766     // Data rows:
767     for (SlotIndex i = sis->getZeroIndex(); i != sis->getLastIndex();
768          i = i.getNextSlot()) {
769      
770       // Render the slot column. 
771       os << indent + s(2) << "<tr height=6ex>\n";
772       
773       // Render the code column.
774       if (i.getSlot() == SlotIndex::LOAD) {
775         MachineBasicBlock *mbb = sis->getMBBFromIndex(i);
776         mi = sis->getInstructionFromIndex(i);
777
778         if (i == sis->getMBBStartIdx(mbb) || mi != 0 ||
779             ro.renderEmptyIndexes()) {
780           os << indent + s(4) << "<td rowspan=4>" << i << "&nbsp;</td>\n"
781              << indent + s(4) << "<td rowspan=4>\n";
782
783           if (i == sis->getMBBStartIdx(mbb)) {
784             os << indent + s(6) << "BB#" << mbb->getNumber() << ":&nbsp;\n";
785           } else if (mi != 0) {
786             os << indent + s(6) << "&nbsp;&nbsp;";
787             renderMachineInstr(os, mi);
788           } else {
789             // Empty interval - leave blank.
790           }
791           os << indent + s(4) << "</td>\n";
792         } else {
793           i = i.getStoreIndex(); // <- Will be incremented to the next index.
794           continue;
795         }
796       }
797
798       // Render the class columns.
799       if (!ro.regClasses().empty()) {
800         std::pair<PressureState, unsigned> psRLEAccumulator(Zero, 0);
801         for (MFRenderingOptions::RegClassSet::const_iterator
802                rcItr = ro.regClasses().begin(),
803                rcEnd = ro.regClasses().end();
804              rcItr != rcEnd; ++rcItr) {
805           const TargetRegisterClass *trc = *rcItr;
806           PressureState newPressure = getPressureStateAt(trc, i);
807
808           if (newPressure == psRLEAccumulator.first) {
809             ++psRLEAccumulator.second;
810           } else {
811             renderCellsWithRLE(indent + s(4), os, psRLEAccumulator, psStrs);
812             psRLEAccumulator.first = newPressure;
813             psRLEAccumulator.second = 1;
814           }
815         }
816         renderCellsWithRLE(indent + s(4), os, psRLEAccumulator, psStrs);
817       }
818   
819       // FIXME: Is there a nicer way to insert space between columns in HTML?
820       if (!ro.regClasses().empty() && !ro.intervals().empty())
821         os << indent + s(4) << "<td width=2em></td>\n";
822
823       if (!ro.intervals().empty()) {
824         std::pair<LiveState, unsigned> lsRLEAccumulator(Dead, 0);
825         for (MFRenderingOptions::IntervalSet::const_iterator
826                liItr = ro.intervals().begin(),
827                liEnd = ro.intervals().end();
828              liItr != liEnd; ++liItr) {
829           const LiveInterval *li = *liItr;
830           LiveState newLiveness = getLiveStateAt(li, i);
831
832           if (newLiveness == lsRLEAccumulator.first) {
833             ++lsRLEAccumulator.second;
834           } else {
835             renderCellsWithRLE(indent + s(4), os, lsRLEAccumulator, lsStrs);
836             lsRLEAccumulator.first = newLiveness;
837             lsRLEAccumulator.second = 1;
838           }
839         }
840         renderCellsWithRLE(indent + s(4), os, lsRLEAccumulator, lsStrs);
841       }
842       os << indent + s(2) << "</tr>\n";
843     }
844
845     os << indent << "</table>\n";
846
847     if (!ro.regClasses().empty())
848       renderPressureTableLegend(indent, os);
849   }
850
851   void RenderMachineFunction::renderFunctionPage(
852                                     raw_ostream &os,
853                                     const char * const renderContextStr) const {
854     os << "<html>\n"
855        << s(2) << "<head>\n"
856        << s(4) << "<title>" << fqn << "</title>\n";
857
858     insertCSS(s(4), os);
859
860     os << s(2) << "<head>\n"
861        << s(2) << "<body >\n";
862
863     renderFunctionSummary(s(4), os, renderContextStr);
864
865     os << s(4) << "<br/><br/><br/>\n";
866
867     //renderLiveIntervalInfoTable("    ", os);
868
869     os << s(4) << "<br/><br/><br/>\n";
870
871     renderCodeTablePlusPI(s(4), os);
872
873     os << s(2) << "</body>\n"
874        << "</html>\n";
875   }
876
877   void RenderMachineFunction::getAnalysisUsage(AnalysisUsage &au) const {
878     au.addRequired<SlotIndexes>();
879     au.addRequired<LiveIntervals>();
880     au.setPreservesAll();
881     MachineFunctionPass::getAnalysisUsage(au);
882   }
883
884   bool RenderMachineFunction::runOnMachineFunction(MachineFunction &fn) {
885     mf = &fn;
886     mri = &mf->getRegInfo();
887     tri = mf->getTarget().getRegisterInfo();
888     lis = &getAnalysis<LiveIntervals>();
889     sis = &getAnalysis<SlotIndexes>();
890
891     trei.setup(mf, mri, tri, lis);
892     ro.setup(mf, tri, lis);
893
894     fqn = mf->getFunction()->getParent()->getModuleIdentifier() + "." +
895           mf->getFunction()->getName().str();
896
897     return false;
898   }
899
900   void RenderMachineFunction::releaseMemory() {
901     trei.clear();
902     ro.clear();
903   }
904
905   void RenderMachineFunction::renderMachineFunction(
906                                                    const char *renderContextStr,
907                                                    const VirtRegMap *vrm,
908                                                    const char *renderSuffix) {
909     if (!ro.shouldRenderCurrentMachineFunction())
910       return; 
911
912     this->vrm = vrm;
913     trei.reset();
914
915     std::string rpFileName(mf->getFunction()->getName().str() +
916                            (renderSuffix ? renderSuffix : "") +
917                            outputFileSuffix);
918
919     std::string errMsg;
920     raw_fd_ostream outFile(rpFileName.c_str(), errMsg, raw_fd_ostream::F_Binary);
921
922     renderFunctionPage(outFile, renderContextStr);
923
924     ro.resetRenderSpecificOptions();
925   }
926
927   std::string RenderMachineFunction::escapeChars(const std::string &s) const {
928     return escapeChars(s.begin(), s.end());
929   }
930
931 }