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