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