Skip to content
RenderMachineFunction.cpp 33.6 KiB
Newer Older
//===-- llvm/CodeGen/RenderMachineFunction.cpp - MF->HTML -----s-----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "rendermf"

#include "RenderMachineFunction.h"

#include "llvm/Function.h"
#include "llvm/Module.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"

#include <sstream>

using namespace llvm;

char RenderMachineFunction::ID = 0;
INITIALIZE_PASS_BEGIN(RenderMachineFunction, "rendermf",
                "Render machine functions (and related info) to HTML pages",
                false, false)
INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
INITIALIZE_PASS_END(RenderMachineFunction, "rendermf",
                "Render machine functions (and related info) to HTML pages",
                false, false)

static cl::opt<std::string>
outputFileSuffix("rmf-file-suffix",
                 cl::desc("Appended to function name to get output file name "
                          "(default: \".html\")"),
                 cl::init(".html"), cl::Hidden);

static cl::opt<std::string>
machineFuncsToRender("rmf-funcs",
                     cl::desc("Coma seperated list of functions to render"
                              ", or \"*\"."),
                     cl::init(""), cl::Hidden);

static cl::opt<std::string>
pressureClasses("rmf-classes",
                cl::desc("Register classes to render pressure for."),
                cl::init(""), cl::Hidden);

static cl::opt<std::string>
showIntervals("rmf-intervals",
              cl::desc("Live intervals to show alongside code."),
              cl::init(""), cl::Hidden);

static cl::opt<bool>
filterEmpty("rmf-filter-empty-intervals",
            cl::desc("Don't display empty intervals."),
            cl::init(true), cl::Hidden);

static cl::opt<bool>
showEmptyIndexes("rmf-empty-indexes",
                 cl::desc("Render indexes not associated with instructions or "
                          "MBB starts."),
                 cl::init(false), cl::Hidden);

static cl::opt<bool>
useFancyVerticals("rmf-fancy-verts",
                  cl::desc("Use SVG for vertical text."),
                  cl::init(true), cl::Hidden);

static cl::opt<bool>
prettyHTML("rmf-pretty-html",
           cl::desc("Pretty print HTML. For debugging the renderer only.."),
           cl::init(false), cl::Hidden);


namespace llvm {

  bool MFRenderingOptions::renderingOptionsProcessed;
  std::set<std::string> MFRenderingOptions::mfNamesToRender;
  bool MFRenderingOptions::renderAllMFs = false;

  std::set<std::string> MFRenderingOptions::classNamesToRender;
  bool MFRenderingOptions::renderAllClasses = false;

  std::set<std::pair<unsigned, unsigned> >
    MFRenderingOptions::intervalNumsToRender;
  unsigned MFRenderingOptions::intervalTypesToRender = ExplicitOnly;

  template <typename OutputItr>
  void MFRenderingOptions::splitComaSeperatedList(const std::string &s,
                                                         OutputItr outItr) {
    std::string::const_iterator curPos = s.begin();
    std::string::const_iterator nextComa = std::find(curPos, s.end(), ',');
    while (nextComa != s.end()) {
      std::string elem;
      std::copy(curPos, nextComa, std::back_inserter(elem));
      *outItr = elem;
      ++outItr;
      curPos = llvm::next(nextComa);
      nextComa = std::find(curPos, s.end(), ',');
    }

    if (curPos != s.end()) {
      std::string elem;
      std::copy(curPos, s.end(), std::back_inserter(elem));
      *outItr = elem;
      ++outItr;
    }
  }

  void MFRenderingOptions::processOptions() {
    if (!renderingOptionsProcessed) {
      processFuncNames();
      processRegClassNames();
      processIntervalNumbers();
      renderingOptionsProcessed = true;
    }
  }

  void MFRenderingOptions::processFuncNames() {
    if (machineFuncsToRender == "*") {
      renderAllMFs = true;
    } else {
      splitComaSeperatedList(machineFuncsToRender,
                             std::inserter(mfNamesToRender,
                                           mfNamesToRender.begin()));
    }
  }

  void MFRenderingOptions::processRegClassNames() {
    if (pressureClasses == "*") {
      renderAllClasses = true;
    } else {
      splitComaSeperatedList(pressureClasses,
                             std::inserter(classNamesToRender,
                                           classNamesToRender.begin()));
    }
  }

  void MFRenderingOptions::processIntervalNumbers() {
    std::set<std::string> intervalRanges;
    splitComaSeperatedList(showIntervals,
                           std::inserter(intervalRanges,
                                         intervalRanges.begin()));
    std::for_each(intervalRanges.begin(), intervalRanges.end(),
                  processIntervalRange);
  }

  void MFRenderingOptions::processIntervalRange(
                                          const std::string &intervalRangeStr) {
    if (intervalRangeStr == "*") {
      intervalTypesToRender |= All;
    } else if (intervalRangeStr == "virt-nospills*") {
      intervalTypesToRender |= VirtNoSpills;
    } else if (intervalRangeStr == "spills*") {
      intervalTypesToRender |= VirtSpills;
    } else if (intervalRangeStr == "virt*") {
    } else if (intervalRangeStr == "phys*") {
    } else {
      std::istringstream iss(intervalRangeStr);
      unsigned reg1, reg2;
      if ((iss >> reg1 >> std::ws)) {
        if (iss.eof()) {
          intervalNumsToRender.insert(std::make_pair(reg1, reg1 + 1));
        } else {
          char c;
          iss >> c;
          if (c == '-' && (iss >> reg2)) {
            intervalNumsToRender.insert(std::make_pair(reg1, reg2 + 1));
          } else {
            dbgs() << "Warning: Invalid interval range \""
                   << intervalRangeStr << "\" in -rmf-intervals. Skipping.\n";
          }
        }
      } else {
        dbgs() << "Warning: Invalid interval number \""
               << intervalRangeStr << "\" in -rmf-intervals. Skipping.\n";
      }
    }
  }

  void MFRenderingOptions::setup(MachineFunction *mf,
                                 const TargetRegisterInfo *tri,
                                 LiveIntervals *lis,
                                 const RenderMachineFunction *rmf) {
    this->mf = mf;
    this->tri = tri;
    this->lis = lis;
Loading
Loading full blame...