| //===-- llvm/CodeGen/RenderMachineFunction.h - MF->HTML -*- C++ -*---------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #ifndef LLVM_CODEGEN_RENDERMACHINEFUNCTION_H | 
 | #define LLVM_CODEGEN_RENDERMACHINEFUNCTION_H | 
 |  | 
 | #include "llvm/CodeGen/LiveInterval.h" | 
 | #include "llvm/CodeGen/MachineFunctionPass.h" | 
 | #include "llvm/CodeGen/SlotIndexes.h" | 
 | #include "llvm/Target/TargetRegisterInfo.h" | 
 |  | 
 | #include <algorithm> | 
 | #include <map> | 
 | #include <set> | 
 | #include <string> | 
 |  | 
 | namespace llvm { | 
 |  | 
 |   class LiveInterval; | 
 |   class LiveIntervals; | 
 |   class MachineInstr; | 
 |   class MachineRegisterInfo; | 
 |   class RenderMachineFunction; | 
 |   class TargetRegisterClass; | 
 |   class TargetRegisterInfo; | 
 |   class VirtRegMap; | 
 |   class raw_ostream; | 
 |  | 
 |   /// \brief Helper class to process rendering options. Tries to be as lazy as | 
 |   ///        possible. | 
 |   class MFRenderingOptions { | 
 |   public: | 
 |  | 
 |     struct RegClassComp { | 
 |       bool operator()(const TargetRegisterClass *trc1, | 
 |                       const TargetRegisterClass *trc2) const { | 
 |         std::string trc1Name(trc1->getName()), trc2Name(trc2->getName()); | 
 |         return std::lexicographical_compare(trc1Name.begin(), trc1Name.end(), | 
 |                                             trc2Name.begin(), trc2Name.end()); | 
 |       } | 
 |     }; | 
 |  | 
 |     typedef std::set<const TargetRegisterClass*, RegClassComp> RegClassSet; | 
 |  | 
 |     struct IntervalComp { | 
 |       bool operator()(const LiveInterval *li1, const LiveInterval *li2) const { | 
 |         return li1->reg < li2->reg; | 
 |       } | 
 |     }; | 
 |  | 
 |     typedef std::set<const LiveInterval*, IntervalComp> IntervalSet; | 
 |  | 
 |     /// Initialise the rendering options. | 
 |     void setup(MachineFunction *mf, const TargetRegisterInfo *tri, | 
 |                LiveIntervals *lis, const RenderMachineFunction *rmf); | 
 |  | 
 |     /// Clear translations of options to the current function. | 
 |     void clear(); | 
 |  | 
 |     /// Reset any options computed for this specific rendering. | 
 |     void resetRenderSpecificOptions(); | 
 |  | 
 |     /// Should we render the current function. | 
 |     bool shouldRenderCurrentMachineFunction() const; | 
 |  | 
 |     /// Return the set of register classes to render pressure for. | 
 |     const RegClassSet& regClasses() const; | 
 |  | 
 |     /// Return the set of live intervals to render liveness for. | 
 |     const IntervalSet& intervals() const; | 
 |  | 
 |     /// Render indexes which are not associated with instructions / MBB starts. | 
 |     bool renderEmptyIndexes() const; | 
 |  | 
 |     /// Return whether or not to render using SVG for fancy vertical text. | 
 |     bool fancyVerticals() const; | 
 |  | 
 |   private: | 
 |  | 
 |     static bool renderingOptionsProcessed; | 
 |     static std::set<std::string> mfNamesToRender; | 
 |     static bool renderAllMFs; | 
 |  | 
 |     static std::set<std::string> classNamesToRender; | 
 |     static bool renderAllClasses; | 
 |  | 
 |  | 
 |     static std::set<std::pair<unsigned, unsigned> > intervalNumsToRender; | 
 |     typedef enum { ExplicitOnly     = 0, | 
 |                    AllPhys          = 1, | 
 |                    VirtNoSpills     = 2, | 
 |                    VirtSpills       = 4, | 
 |                    AllVirt          = 6, | 
 |                    All              = 7 } | 
 |       IntervalTypesToRender; | 
 |     static unsigned intervalTypesToRender; | 
 |  | 
 |     template <typename OutputItr> | 
 |     static void splitComaSeperatedList(const std::string &s, OutputItr outItr); | 
 |  | 
 |     static void processOptions(); | 
 |  | 
 |     static void processFuncNames(); | 
 |     static void processRegClassNames(); | 
 |     static void processIntervalNumbers(); | 
 |  | 
 |     static void processIntervalRange(const std::string &intervalRangeStr); | 
 |  | 
 |     MachineFunction *mf; | 
 |     const TargetRegisterInfo *tri; | 
 |     LiveIntervals *lis; | 
 |     const RenderMachineFunction *rmf; | 
 |  | 
 |     mutable bool regClassesTranslatedToCurrentFunction; | 
 |     mutable RegClassSet regClassSet; | 
 |  | 
 |     mutable bool intervalsTranslatedToCurrentFunction; | 
 |     mutable IntervalSet intervalSet; | 
 |  | 
 |     void translateRegClassNamesToCurrentFunction() const; | 
 |  | 
 |     void translateIntervalNumbersToCurrentFunction() const; | 
 |   }; | 
 |  | 
 |   /// \brief Provide extra information about the physical and virtual registers | 
 |   ///        in the function being compiled. | 
 |   class TargetRegisterExtraInfo { | 
 |   public: | 
 |     TargetRegisterExtraInfo(); | 
 |  | 
 |     /// \brief Set up TargetRegisterExtraInfo with pointers to necessary | 
 |     ///        sources of information. | 
 |     void setup(MachineFunction *mf, MachineRegisterInfo *mri, | 
 |                const TargetRegisterInfo *tri, LiveIntervals *lis); | 
 |  | 
 |     /// \brief Recompute tables for changed function. | 
 |     void reset();  | 
 |  | 
 |     /// \brief Free all tables in TargetRegisterExtraInfo. | 
 |     void clear(); | 
 |  | 
 |     /// \brief Maximum number of registers from trc which alias reg. | 
 |     unsigned getWorst(unsigned reg, const TargetRegisterClass *trc) const; | 
 |  | 
 |     /// \brief Returns the number of allocable registers in trc. | 
 |     unsigned getCapacity(const TargetRegisterClass *trc) const; | 
 |  | 
 |     /// \brief Return the number of registers of class trc that may be | 
 |     ///        needed at slot i. | 
 |     unsigned getPressureAtSlot(const TargetRegisterClass *trc, | 
 |                                SlotIndex i) const; | 
 |  | 
 |     /// \brief Return true if the number of registers of type trc that may be | 
 |     ///        needed at slot i is greater than the capacity of trc. | 
 |     bool classOverCapacityAtSlot(const TargetRegisterClass *trc, | 
 |                                  SlotIndex i) const; | 
 |  | 
 |   private: | 
 |  | 
 |     MachineFunction *mf; | 
 |     MachineRegisterInfo *mri; | 
 |     const TargetRegisterInfo *tri; | 
 |     LiveIntervals *lis; | 
 |  | 
 |     typedef std::map<const TargetRegisterClass*, unsigned> WorstMapLine; | 
 |     typedef std::map<const TargetRegisterClass*, WorstMapLine> VRWorstMap; | 
 |     VRWorstMap vrWorst; | 
 |  | 
 |     typedef std::map<unsigned, WorstMapLine> PRWorstMap; | 
 |     PRWorstMap prWorst; | 
 |  | 
 |     typedef std::map<const TargetRegisterClass*, unsigned> CapacityMap; | 
 |     CapacityMap capacityMap; | 
 |  | 
 |     typedef std::map<const TargetRegisterClass*, unsigned> PressureMapLine; | 
 |     typedef std::map<SlotIndex, PressureMapLine> PressureMap; | 
 |     PressureMap pressureMap; | 
 |  | 
 |     bool mapsPopulated; | 
 |  | 
 |     /// \brief Initialise the 'worst' table. | 
 |     void initWorst(); | 
 |   | 
 |     /// \brief Initialise the 'capacity' table. | 
 |     void initCapacity(); | 
 |  | 
 |     /// \brief Initialise/Reset the 'pressure' and live states tables. | 
 |     void resetPressureAndLiveStates(); | 
 |   }; | 
 |  | 
 |   /// \brief Render MachineFunction objects and related information to a HTML | 
 |   ///        page. | 
 |   class RenderMachineFunction : public MachineFunctionPass { | 
 |   public: | 
 |     static char ID; | 
 |  | 
 |     RenderMachineFunction() : MachineFunctionPass(ID) { | 
 |       initializeRenderMachineFunctionPass(*PassRegistry::getPassRegistry()); | 
 |     } | 
 |  | 
 |     virtual void getAnalysisUsage(AnalysisUsage &au) const; | 
 |  | 
 |     virtual bool runOnMachineFunction(MachineFunction &fn); | 
 |  | 
 |     virtual void releaseMemory(); | 
 |  | 
 |     void rememberUseDefs(const LiveInterval *li); | 
 |  | 
 |     void rememberSpills(const LiveInterval *li, | 
 |                         const std::vector<LiveInterval*> &spills); | 
 |  | 
 |     bool isSpill(const LiveInterval *li) const; | 
 |  | 
 |     /// \brief Render this machine function to HTML. | 
 |     ///  | 
 |     /// @param renderContextStr This parameter will be included in the top of | 
 |     ///                         the html file to explain where (in the | 
 |     ///                         codegen pipeline) this function was rendered | 
 |     ///                         from. Set it to something like | 
 |     ///                         "Pre-register-allocation". | 
 |     /// @param vrm              If non-null the VRM will be queried to determine | 
 |     ///                         whether a virtual register was allocated to a | 
 |     ///                         physical register or spilled. | 
 |     /// @param renderFilePrefix This string will be appended to the function | 
 |     ///                         name (before the output file suffix) to enable | 
 |     ///                         multiple renderings from the same function. | 
 |     void renderMachineFunction(const char *renderContextStr, | 
 |                                const VirtRegMap *vrm = 0, | 
 |                                const char *renderSuffix = 0); | 
 |  | 
 |   private: | 
 |     class Spacer; | 
 |     friend raw_ostream& operator<<(raw_ostream &os, const Spacer &s); | 
 |  | 
 |     std::string fqn; | 
 |  | 
 |     MachineFunction *mf; | 
 |     MachineRegisterInfo *mri; | 
 |     const TargetRegisterInfo *tri; | 
 |     LiveIntervals *lis; | 
 |     SlotIndexes *sis; | 
 |     const VirtRegMap *vrm; | 
 |  | 
 |     TargetRegisterExtraInfo trei; | 
 |     MFRenderingOptions ro; | 
 |  | 
 |      | 
 |  | 
 |     // Utilities. | 
 |     typedef enum { Dead, Defined, Used, AliveReg, AliveStack } LiveState; | 
 |     LiveState getLiveStateAt(const LiveInterval *li, SlotIndex i) const; | 
 |  | 
 |     typedef enum { Zero, Low, High } PressureState; | 
 |     PressureState getPressureStateAt(const TargetRegisterClass *trc, | 
 |                                      SlotIndex i) const; | 
 |  | 
 |     typedef std::map<const LiveInterval*, std::set<const LiveInterval*> > | 
 |       SpillIntervals; | 
 |     SpillIntervals spillIntervals; | 
 |  | 
 |     typedef std::map<const LiveInterval*, const LiveInterval*> SpillForMap; | 
 |     SpillForMap spillFor; | 
 |  | 
 |     typedef std::set<SlotIndex> SlotSet; | 
 |     typedef std::map<const LiveInterval*, SlotSet> UseDefs; | 
 |     UseDefs useDefs; | 
 |  | 
 |     // ---------- Rendering methods ---------- | 
 |  | 
 |     /// For inserting spaces when pretty printing. | 
 |     class Spacer { | 
 |     public: | 
 |       explicit Spacer(unsigned numSpaces) : ns(numSpaces) {} | 
 |       Spacer operator+(const Spacer &o) const { return Spacer(ns + o.ns); } | 
 |       void print(raw_ostream &os) const; | 
 |     private: | 
 |       unsigned ns; | 
 |     }; | 
 |  | 
 |     Spacer s(unsigned ns) const; | 
 |  | 
 |     template <typename Iterator> | 
 |     std::string escapeChars(Iterator sBegin, Iterator sEnd) const; | 
 |  | 
 |     /// \brief Render a machine instruction. | 
 |     void renderMachineInstr(raw_ostream &os, | 
 |                             const MachineInstr *mi) const; | 
 |  | 
 |     /// \brief Render vertical text. | 
 |     template <typename T> | 
 |     void renderVertical(const Spacer &indent, | 
 |                         raw_ostream &os, | 
 |                         const T &t) const; | 
 |  | 
 |     /// \brief Insert CSS layout info. | 
 |     void insertCSS(const Spacer &indent, | 
 |                    raw_ostream &os) const; | 
 |  | 
 |     /// \brief Render a brief summary of the function (including rendering | 
 |     ///        context). | 
 |     void renderFunctionSummary(const Spacer &indent, | 
 |                                raw_ostream &os, | 
 |                                const char * const renderContextStr) const; | 
 |  | 
 |     /// \brief Render a legend for the pressure table. | 
 |     void renderPressureTableLegend(const Spacer &indent, | 
 |                                    raw_ostream &os) const; | 
 |  | 
 |     /// \brief Render a consecutive set of HTML cells of the same class using | 
 |     /// the colspan attribute for run-length encoding. | 
 |     template <typename CellType> | 
 |     void renderCellsWithRLE( | 
 |                      const Spacer &indent, raw_ostream &os, | 
 |                      const std::pair<CellType, unsigned> &rleAccumulator, | 
 |                      const std::map<CellType, std::string> &cellTypeStrs) const; | 
 |  | 
 |     /// \brief Render code listing, potentially with register pressure | 
 |     ///        and live intervals shown alongside. | 
 |     void renderCodeTablePlusPI(const Spacer &indent, | 
 |                                raw_ostream &os) const; | 
 |  | 
 |     /// \brief Render the HTML page representing the MachineFunction. | 
 |     void renderFunctionPage(raw_ostream &os, | 
 |                             const char * const renderContextStr) const; | 
 |  | 
 |     std::string escapeChars(const std::string &s) const; | 
 |   }; | 
 | } | 
 |  | 
 | #endif /* LLVM_CODEGEN_RENDERMACHINEFUNCTION_H */ |