Changed OStream templates to functions on raw_ostream, removed the unused "renderWarn...
[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   void RenderMachineFunction::Spacer::print(raw_ostream &os) const {
503     if (!prettyHTML)
504       return;
505     for (unsigned i = 0; i < ns; ++i) {
506       os << " ";
507     }
508   }
509
510   RenderMachineFunction::Spacer RenderMachineFunction::s(unsigned ns) const {
511     return Spacer(ns);
512   }
513
514   raw_ostream& operator<<(raw_ostream &os, const RenderMachineFunction::Spacer &s) {
515     s.print(os);
516     return os;
517   }
518
519   template <typename Iterator>
520   std::string RenderMachineFunction::escapeChars(Iterator sBegin, Iterator sEnd) const {
521     std::string r;
522
523     for (Iterator sItr = sBegin; sItr != sEnd; ++sItr) {
524       char c = *sItr;
525
526       switch (c) {
527         case '<': r.append("&lt;"); break;
528         case '>': r.append("&gt;"); break;
529         case '&': r.append("&amp;"); break;
530         case ' ': r.append("&nbsp;"); break;
531         case '\"': r.append("&quot;"); break;
532         default: r.push_back(c); break;
533       }
534     }
535
536     return r;
537   }
538
539   RenderMachineFunction::LiveState
540   RenderMachineFunction::getLiveStateAt(const LiveInterval *li,
541                                         SlotIndex i) const {
542     const MachineInstr *mi = sis->getInstructionFromIndex(i);
543
544     if (li->liveAt(i)) {
545       if (mi == 0) {
546         if (vrm == 0 || 
547             (vrm->getStackSlot(li->reg) == VirtRegMap::NO_STACK_SLOT)) {
548           return AliveReg;
549         } else {
550           return AliveStack;
551         }
552       } else {
553         if (i.getSlot() == SlotIndex::DEF &&
554             mi->definesRegister(li->reg, tri)) {
555           return Defined;
556         } else if (i.getSlot() == SlotIndex::USE &&
557                    mi->readsRegister(li->reg)) {
558           return Used;
559         } else {
560           if (vrm == 0 || 
561               (vrm->getStackSlot(li->reg) == VirtRegMap::NO_STACK_SLOT)) {
562             return AliveReg;
563           } else {
564             return AliveStack;
565           }
566         }
567       }
568     }
569     return Dead;
570   }
571
572   RenderMachineFunction::PressureState
573   RenderMachineFunction::getPressureStateAt(const TargetRegisterClass *trc,
574                                               SlotIndex i) const {
575     if (trei.getPressureAtSlot(trc, i) == 0) {
576       return Zero;
577     } else if (trei.classOverCapacityAtSlot(trc, i)){
578       return High;
579     }
580     return Low;
581   }
582
583   /// \brief Render a machine instruction.
584   void RenderMachineFunction::renderMachineInstr(raw_ostream &os,
585                                                  const MachineInstr *mi) const {
586     std::string s;
587     raw_string_ostream oss(s);
588     oss << *mi;
589
590     os << escapeChars(oss.str());
591   }
592
593   template <typename T>
594   void RenderMachineFunction::renderVertical(const Spacer &indent,
595                                              raw_ostream &os,
596                                              const T &t) const {
597     if (ro.fancyVerticals()) {
598       os << indent << "<object\n"
599          << indent + s(2) << "class=\"obj\"\n"
600          << indent + s(2) << "type=\"image/svg+xml\"\n"
601          << indent + s(2) << "width=\"14px\"\n"
602          << indent + s(2) << "height=\"55px\"\n"
603          << indent + s(2) << "data=\"data:image/svg+xml,\n"
604          << indent + s(4) << "<svg xmlns='http://www.w3.org/2000/svg'>\n"
605          << indent + s(6) << "<text x='-55' y='10' "
606                              "font-family='Courier' font-size='12' "
607                              "transform='rotate(-90)' "
608                              "text-rendering='optimizeSpeed' "
609                              "fill='#000'>" << t << "</text>\n"
610          << indent + s(4) << "</svg>\">\n"
611          << indent << "</object>\n";
612     } else {
613       std::ostringstream oss;
614       oss << t;
615       std::string tStr(oss.str());
616
617       os << indent;
618       for (std::string::iterator tStrItr = tStr.begin(), tStrEnd = tStr.end();
619            tStrItr != tStrEnd; ++tStrItr) {
620         os << *tStrItr << "<br/>";
621       }
622       os << "\n";
623     }
624   }
625
626   void RenderMachineFunction::insertCSS(const Spacer &indent,
627                                         raw_ostream &os) const {
628     os << indent << "<style type=\"text/css\">\n"
629        << indent + s(2) << "body { font-color: black; }\n"
630        << indent + s(2) << "table.code td { font-family: monospace; "
631                     "border-width: 0px; border-style: solid; "
632                     "border-bottom: 1px solid #dddddd; white-space: nowrap; }\n"
633        << indent + s(2) << "table.code td.p-z { background-color: #000000; }\n"
634        << indent + s(2) << "table.code td.p-l { background-color: #00ff00; }\n"
635        << indent + s(2) << "table.code td.p-h { background-color: #ff0000; }\n"
636        << indent + s(2) << "table.code td.l-n { background-color: #ffffff; }\n"
637        << indent + s(2) << "table.code td.l-d { background-color: #ff0000; }\n"
638        << indent + s(2) << "table.code td.l-u { background-color: #ffff00; }\n"
639        << indent + s(2) << "table.code td.l-r { background-color: #000000; }\n"
640        << indent + s(2) << "table.code td.l-s { background-color: #770000; }\n"
641        << indent + s(2) << "table.code th { border-width: 0px; "
642                     "border-style: solid; }\n"
643        << indent << "</style>\n";
644   }
645
646   void RenderMachineFunction::renderFunctionSummary(
647                                     const Spacer &indent, raw_ostream &os,
648                                     const char * const renderContextStr) const {
649     os << indent << "<h1>Function: " << mf->getFunction()->getName()
650                  << "</h1>\n"
651        << indent << "<h2>Rendering context: " << renderContextStr << "</h2>\n";
652   }
653
654
655   void RenderMachineFunction::renderPressureTableLegend(
656                                                       const Spacer &indent,
657                                                       raw_ostream &os) const {
658     os << indent << "<h2>Rendering Pressure Legend:</h2>\n"
659        << indent << "<table class=\"code\">\n"
660        << indent + s(2) << "<tr>\n"
661        << indent + s(4) << "<th>Pressure</th><th>Description</th>"
662                     "<th>Appearance</th>\n"
663        << indent + s(2) << "</tr>\n"
664        << indent + s(2) << "<tr>\n"
665        << indent + s(4) << "<td>No Pressure</td>"
666                     "<td>No physical registers of this class requested.</td>"
667                     "<td class=\"p-z\">&nbsp;&nbsp;</td>\n"
668        << indent + s(2) << "</tr>\n"
669        << indent + s(2) << "<tr>\n"
670        << indent + s(4) << "<td>Low Pressure</td>"
671                     "<td>Sufficient physical registers to meet demand.</td>"
672                     "<td class=\"p-l\">&nbsp;&nbsp;</td>\n"
673        << indent + s(2) << "</tr>\n"
674        << indent + s(2) << "<tr>\n"
675        << indent + s(4) << "<td>High Pressure</td>"
676                     "<td>Potentially insufficient physical registers to meet demand.</td>"
677                     "<td class=\"p-h\">&nbsp;&nbsp;</td>\n"
678        << indent + s(2) << "</tr>\n"
679        << indent << "</table>\n";
680   }
681
682   template <typename CellType>
683   void RenderMachineFunction::renderCellsWithRLE(
684                    const Spacer &indent, raw_ostream &os,
685                    const std::pair<CellType, unsigned> &rleAccumulator,
686                    const std::map<CellType, std::string> &cellTypeStrs) const {
687
688     if (rleAccumulator.second == 0)
689       return; 
690
691     typename std::map<CellType, std::string>::const_iterator ctsItr =
692       cellTypeStrs.find(rleAccumulator.first);
693
694     assert(ctsItr != cellTypeStrs.end() && "No string for given cell type.");
695
696     os << indent + s(4) << "<td class=\"" << ctsItr->second << "\"";
697     if (rleAccumulator.second > 1)
698       os << " colspan=" << rleAccumulator.second;
699     os << "></td>\n";
700   }
701
702
703   void RenderMachineFunction::renderCodeTablePlusPI(const Spacer &indent,
704                                                     raw_ostream &os) const {
705
706     std::map<LiveState, std::string> lsStrs;
707     lsStrs[Dead] = "l-n";
708     lsStrs[Defined] = "l-d";
709     lsStrs[Used] = "l-u";
710     lsStrs[AliveReg] = "l-r";
711     lsStrs[AliveStack] = "l-s";
712
713     std::map<PressureState, std::string> psStrs;
714     psStrs[Zero] = "p-z";
715     psStrs[Low] = "p-l";
716     psStrs[High] = "p-h";
717
718     // Open the table... 
719
720     os << indent << "<table cellpadding=0 cellspacing=0 class=\"code\">\n"
721        << indent + s(2) << "<tr>\n";
722
723     // Render the header row...
724
725     os << indent + s(4) << "<th>index</th>\n"
726        << indent + s(4) << "<th>instr</th>\n";
727
728     // Render class names if necessary...
729     if (!ro.regClasses().empty()) {
730       for (MFRenderingOptions::RegClassSet::const_iterator
731              rcItr = ro.regClasses().begin(),
732              rcEnd = ro.regClasses().end();
733            rcItr != rcEnd; ++rcItr) {
734         const TargetRegisterClass *trc = *rcItr;
735         os << indent + s(4) << "<th>\n";
736         renderVertical(indent + s(6), os, trc->getName());
737         os << indent + s(4) << "</th>\n";
738       }
739     }
740
741     // FIXME: Is there a nicer way to insert space between columns in HTML?
742     if (!ro.regClasses().empty() && !ro.intervals().empty())
743       os << indent + s(4) << "<th>&nbsp;&nbsp;</th>\n";
744
745     // Render interval numbers if necessary...
746     if (!ro.intervals().empty()) {
747       for (MFRenderingOptions::IntervalSet::const_iterator
748              liItr = ro.intervals().begin(),
749              liEnd = ro.intervals().end();
750            liItr != liEnd; ++liItr) {
751
752         const LiveInterval *li = *liItr;
753         os << indent + s(4) << "<th>\n";
754         renderVertical(indent + s(6), os, li->reg);
755         os << indent + s(4) << "</th>\n";
756       }
757     }
758
759     os << indent + s(2) << "</tr>\n";
760
761     // End header row, start with the data rows...
762
763     MachineInstr *mi = 0;
764
765     // Data rows:
766     for (SlotIndex i = sis->getZeroIndex(); i != sis->getLastIndex();
767          i = i.getNextSlot()) {
768      
769       // Render the slot column. 
770       os << indent + s(2) << "<tr height=6ex>\n";
771       
772       // Render the code column.
773       if (i.getSlot() == SlotIndex::LOAD) {
774         MachineBasicBlock *mbb = sis->getMBBFromIndex(i);
775         mi = sis->getInstructionFromIndex(i);
776
777         if (i == sis->getMBBStartIdx(mbb) || mi != 0 ||
778             ro.renderEmptyIndexes()) {
779           os << indent + s(4) << "<td rowspan=4>" << i << "&nbsp;</td>\n"
780              << indent + s(4) << "<td rowspan=4>\n";
781
782           if (i == sis->getMBBStartIdx(mbb)) {
783             os << indent + s(6) << "BB#" << mbb->getNumber() << ":&nbsp;\n";
784           } else if (mi != 0) {
785             os << indent + s(6) << "&nbsp;&nbsp;";
786             renderMachineInstr(os, mi);
787           } else {
788             // Empty interval - leave blank.
789           }
790           os << indent + s(4) << "</td>\n";
791         } else {
792           i = i.getStoreIndex(); // <- Will be incremented to the next index.
793           continue;
794         }
795       }
796
797       // Render the class columns.
798       if (!ro.regClasses().empty()) {
799         std::pair<PressureState, unsigned> psRLEAccumulator(Zero, 0);
800         for (MFRenderingOptions::RegClassSet::const_iterator
801                rcItr = ro.regClasses().begin(),
802                rcEnd = ro.regClasses().end();
803              rcItr != rcEnd; ++rcItr) {
804           const TargetRegisterClass *trc = *rcItr;
805           PressureState newPressure = getPressureStateAt(trc, i);
806
807           if (newPressure == psRLEAccumulator.first) {
808             ++psRLEAccumulator.second;
809           } else {
810             renderCellsWithRLE(indent + s(4), os, psRLEAccumulator, psStrs);
811             psRLEAccumulator.first = newPressure;
812             psRLEAccumulator.second = 1;
813           }
814         }
815         renderCellsWithRLE(indent + s(4), os, psRLEAccumulator, psStrs);
816       }
817   
818       // FIXME: Is there a nicer way to insert space between columns in HTML?
819       if (!ro.regClasses().empty() && !ro.intervals().empty())
820         os << indent + s(4) << "<td width=2em></td>\n";
821
822       if (!ro.intervals().empty()) {
823         std::pair<LiveState, unsigned> lsRLEAccumulator(Dead, 0);
824         for (MFRenderingOptions::IntervalSet::const_iterator
825                liItr = ro.intervals().begin(),
826                liEnd = ro.intervals().end();
827              liItr != liEnd; ++liItr) {
828           const LiveInterval *li = *liItr;
829           LiveState newLiveness = getLiveStateAt(li, i);
830
831           if (newLiveness == lsRLEAccumulator.first) {
832             ++lsRLEAccumulator.second;
833           } else {
834             renderCellsWithRLE(indent + s(4), os, lsRLEAccumulator, lsStrs);
835             lsRLEAccumulator.first = newLiveness;
836             lsRLEAccumulator.second = 1;
837           }
838         }
839         renderCellsWithRLE(indent + s(4), os, lsRLEAccumulator, lsStrs);
840       }
841       os << indent + s(2) << "</tr>\n";
842     }
843
844     os << indent << "</table>\n";
845
846     if (!ro.regClasses().empty())
847       renderPressureTableLegend(indent, os);
848   }
849
850   void RenderMachineFunction::renderFunctionPage(
851                                     raw_ostream &os,
852                                     const char * const renderContextStr) const {
853     os << "<html>\n"
854        << s(2) << "<head>\n"
855        << s(4) << "<title>" << fqn << "</title>\n";
856
857     insertCSS(s(4), os);
858
859     os << s(2) << "<head>\n"
860        << s(2) << "<body >\n";
861
862     renderFunctionSummary(s(4), os, renderContextStr);
863
864     os << s(4) << "<br/><br/><br/>\n";
865
866     //renderLiveIntervalInfoTable("    ", os);
867
868     os << s(4) << "<br/><br/><br/>\n";
869
870     renderCodeTablePlusPI(s(4), os);
871
872     os << s(2) << "</body>\n"
873        << "</html>\n";
874   }
875
876   void RenderMachineFunction::getAnalysisUsage(AnalysisUsage &au) const {
877     au.addRequired<SlotIndexes>();
878     au.addRequired<LiveIntervals>();
879     au.setPreservesAll();
880     MachineFunctionPass::getAnalysisUsage(au);
881   }
882
883   bool RenderMachineFunction::runOnMachineFunction(MachineFunction &fn) {
884     mf = &fn;
885     mri = &mf->getRegInfo();
886     tri = mf->getTarget().getRegisterInfo();
887     lis = &getAnalysis<LiveIntervals>();
888     sis = &getAnalysis<SlotIndexes>();
889
890     trei.setup(mf, mri, tri, lis);
891     ro.setup(mf, tri, lis);
892
893     fqn = mf->getFunction()->getParent()->getModuleIdentifier() + "." +
894           mf->getFunction()->getName().str();
895
896     return false;
897   }
898
899   void RenderMachineFunction::releaseMemory() {
900     trei.clear();
901     ro.clear();
902   }
903
904   void RenderMachineFunction::renderMachineFunction(
905                                                    const char *renderContextStr,
906                                                    const VirtRegMap *vrm,
907                                                    const char *renderSuffix) {
908     if (!ro.shouldRenderCurrentMachineFunction())
909       return; 
910
911     this->vrm = vrm;
912     trei.reset();
913
914     std::string rpFileName(mf->getFunction()->getName().str() +
915                            (renderSuffix ? renderSuffix : "") +
916                            outputFileSuffix);
917
918     std::string errMsg;
919     raw_fd_ostream outFile(rpFileName.c_str(), errMsg, raw_fd_ostream::F_Binary);
920
921     renderFunctionPage(outFile, renderContextStr);
922
923     ro.resetRenderSpecificOptions();
924   }
925
926   std::string RenderMachineFunction::escapeChars(const std::string &s) const {
927     return escapeChars(s.begin(), s.end());
928   }
929
930 }