Nearly CC
An educational compiler skeleton
cfg_printer.h
Go to the documentation of this file.
1 // Copyright (c) 2021-2023, David H. Hovemeyer <david.hovemeyer@gmail.com>
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the "Software"),
5 // to deal in the Software without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Software, and to permit persons to whom the
8 // Software is furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
17 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
18 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
19 // OTHER DEALINGS IN THE SOFTWARE.
20 
21 #ifndef CFG_PRINTER_H
22 #define CFG_PRINTER_H
23 
24 #include "cfg.h"
25 #include "print_instruction_seq.h"
26 #include "highlevel_formatter.h"
27 #include "lowlevel_formatter.h"
28 
31 
36 public:
42  virtual std::string get_block_begin_annotation(std::shared_ptr<InstructionSequence> bb) const {
43  return "";
44  }
45 
51  virtual std::string get_block_end_annotation(std::shared_ptr<InstructionSequence> bb) const {
52  return "";
53  }
54 };
55 
61 // and basic blocks
62 template<typename Formatter, typename BlockAnnotator = DefaultBlockAnnotator>
64 private:
65  Formatter m_formatter;
66  BlockAnnotator m_annotator;
67  std::shared_ptr<ControlFlowGraph> m_cfg;
68 
69 public:
74  ControlFlowGraphPrinter(const std::shared_ptr<ControlFlowGraph> &cfg,
75  Formatter formatter = Formatter(),
76  BlockAnnotator annotator = BlockAnnotator());
78 
80  void print();
81 };
82 
83 // Convenience functions for instantiating a ControlFlowGraphPrinter
84 // for high-level or low-level code
85 
98 template<typename BlockAnnotator = DefaultBlockAnnotator>
100 make_highlevel_cfg_printer(const std::shared_ptr<ControlFlowGraph> &hl_cfg, BlockAnnotator annotator = BlockAnnotator()) {
102 }
103 
116 template<typename BlockAnnotator = DefaultBlockAnnotator>
118 make_lowlevel_cfg_printer(const std::shared_ptr<ControlFlowGraph> &ll_cfg, BlockAnnotator annotator = BlockAnnotator()) {
120 }
121 
123 // ControlFlowGraphPrinter implementation
125 
126 template<typename Formatter, typename BlockAnnotator>
128  Formatter formatter,
129  BlockAnnotator annotator)
130  : m_formatter(formatter)
131  , m_annotator(annotator)
132  , m_cfg(cfg) {
133 }
134 
135 template<typename Formatter, typename BlockAnnotator>
137 }
138 
139 template<typename Formatter, typename BlockAnnotator>
141  for (auto i = m_cfg->bb_begin(); i != m_cfg->bb_end(); i++) {
142  std::shared_ptr<InstructionSequence> bb = *i;
143 
144  // Print information about the beginning of the basic block
145  std::string begin_str;
146  begin_str += "BASIC BLOCK ";
147  begin_str += std::to_string(bb->get_block_id());
148  BasicBlockKind bb_kind = bb->get_kind();
149  if (bb_kind != BASICBLOCK_INTERIOR)
150  begin_str += (bb_kind == BASICBLOCK_ENTRY ? " [entry]" : " [exit]");
151  if (bb->has_block_label()) {
152  begin_str += " (label ";
153  begin_str += bb->get_block_label();
154  begin_str += ")";
155  }
156  std::string begin_annotation = m_annotator.get_block_begin_annotation(bb);
157  if (!begin_annotation.empty()) {
158  if (begin_str.size() < 37)
159  begin_str += (" " + begin_str.size());
160  begin_str += "/* ";
161  begin_str += begin_annotation;
162  begin_str += " */";
163  }
164  printf("%s\n", begin_str.c_str());
165 
166  // Print the instructions in the basic block
167  PrintInstructionSequence<Formatter, BlockAnnotator> print_ins_seq(m_formatter, m_annotator);
168  print_ins_seq.print(bb);
169 
170  // Print information about the outgoing edges
171  const ControlFlowGraph::EdgeList &outgoing_edges = m_cfg->get_outgoing_edges(bb);
172  for (auto j = outgoing_edges.cbegin(); j != outgoing_edges.cend(); j++) {
173  const Edge *e = *j;
174  assert(e->get_kind() == EDGE_BRANCH || e->get_kind() == EDGE_FALLTHROUGH);
175  printf(" %s EDGE to BASIC BLOCK %u\n", e->get_kind() == EDGE_FALLTHROUGH ? "fall-through" : "branch", e->get_target()->get_block_id());
176  }
177 
178  // If there is an end annotation, print it
179  std::string end_annotation = m_annotator.get_block_end_annotation(bb);
180  if (!end_annotation.empty())
181  printf(" At end of block: /* %s */\n", end_annotation.c_str());
182 
183  printf("\n");
184  }
185 }
186 
187 #endif // CFG_PRINTER_H
ControlFlowGraph and associated types.
ControlFlowGraphPrinter< HighLevelFormatter, BlockAnnotator > make_highlevel_cfg_printer(const std::shared_ptr< ControlFlowGraph > &hl_cfg, BlockAnnotator annotator=BlockAnnotator())
Create a ControlFlowGraphPrinter for printing a high-level ControlFlowGraph.
Definition: cfg_printer.h:100
ControlFlowGraphPrinter< LowLevelFormatter, BlockAnnotator > make_lowlevel_cfg_printer(const std::shared_ptr< ControlFlowGraph > &ll_cfg, BlockAnnotator annotator=BlockAnnotator())
Create a ControlFlowGraphPrinter for printing a low-level ControlFlowGraph.
Definition: cfg_printer.h:118
Print a textual representation of a ControlFlowGraph.
Definition: cfg_printer.h:63
ControlFlowGraphPrinter(const std::shared_ptr< ControlFlowGraph > &cfg, Formatter formatter=Formatter(), BlockAnnotator annotator=BlockAnnotator())
Constructor.
Definition: cfg_printer.h:127
void print()
Print the ControlFlowGraph to the standard output.
Definition: cfg_printer.h:140
std::vector< Edge * > EdgeList
Data type for a vector of edges.
Definition: cfg.h:92
Default annotator for printing a control flow graph.
Definition: cfg_printer.h:35
virtual std::string get_block_begin_annotation(std::shared_ptr< InstructionSequence > bb) const
Get a begin annotation for a basic block.
Definition: cfg_printer.h:42
virtual std::string get_block_end_annotation(std::shared_ptr< InstructionSequence > bb) const
Get an end annotation for a basic block.
Definition: cfg_printer.h:51
Definition: print_instruction_seq.h:28
Control-flow graph edge data type.
Definition: cfg.h:56
EdgeKind get_kind() const
Get the EdgeKind of this Edge.
Definition: cfg.h:71
std::shared_ptr< InstructionSequence > get_target() const
Get the target basic block.
Definition: cfg.h:79
A Formatter turns Operand and Instruction objects into strings, which in turn allows high-level and l...
Definition: formatter.h:30
Implementation of Formatter for high-level code.
Definition: highlevel_formatter.h:27
Implementation of Formatter for low-level code.
Definition: lowlevel_formatter.h:27
Definition: print_instruction_seq.h:43
BasicBlockKind
Kinds of basic blocks.
Definition: instruction_seq.h:39
@ BASICBLOCK_INTERIOR
normal basic block in the "interior" of the CFG
Definition: instruction_seq.h:42
@ BASICBLOCK_ENTRY
special "entry" block
Definition: instruction_seq.h:40