43 template<
typename InstructionProperties>
46 InstructionProperties m_ins_props;
47 std::shared_ptr<InstructionSequence> m_iseq;
48 std::shared_ptr<ControlFlowGraph> m_cfg;
50 std::map<unsigned, std::shared_ptr<InstructionSequence> > m_basic_blocks;
54 std::shared_ptr<InstructionSequence> pred;
68 std::shared_ptr<ControlFlowGraph>
build();
80 std::shared_ptr<InstructionSequence> scan_basic_block(
const WorkItem &item,
const std::string &label);
81 bool ends_in_branch(std::shared_ptr<InstructionSequence> bb);
82 unsigned get_branch_target_index(std::shared_ptr<InstructionSequence> bb);
83 bool falls_through(std::shared_ptr<InstructionSequence> bb);
127 template<
typename InstructionProperties>
129 : m_ins_props(InstructionProperties())
134 template<
typename InstructionProperties>
138 template<
typename InstructionProperties>
140 unsigned num_instructions = m_iseq->get_length();
142 std::shared_ptr<InstructionSequence> entry = m_cfg->create_basic_block(
BASICBLOCK_ENTRY, -1);
143 std::shared_ptr<InstructionSequence> exit = m_cfg->create_basic_block(
BASICBLOCK_EXIT, 2000000);
147 m_basic_blocks[num_instructions] = exit;
149 std::deque<WorkItem> work_list;
150 work_list.push_back({ ins_index: 0, pred: entry, edge_kind: EDGE_FALLTHROUGH });
152 std::shared_ptr<InstructionSequence> last =
nullptr;
153 while (!work_list.empty()) {
154 WorkItem item = work_list.front();
155 work_list.pop_front();
157 assert(item.ins_index <= m_iseq->get_length());
160 if (item.ins_index == m_iseq->get_length()) {
161 m_cfg->create_edge(item.pred, exit, item.edge_kind);
165 std::shared_ptr<InstructionSequence> bb;
167 std::map<unsigned, std::shared_ptr<InstructionSequence> >::iterator i = m_basic_blocks.find(item.ins_index);
168 if (i != m_basic_blocks.end()) {
171 is_new_block =
false;
176 if (item.edge_kind == EDGE_BRANCH && !bb->has_block_label()) {
177 bb->set_block_label(item.label);
183 bb = scan_basic_block(item, item.label);
185 m_basic_blocks[item.ins_index] = bb;
191 assert(item.edge_kind != EDGE_BRANCH || bb->get_block_label() == item.label);
194 m_cfg->create_edge(item.pred, bb, item.edge_kind);
204 if (ends_in_branch(bb)) {
205 unsigned target_index = get_branch_target_index(bb);
210 assert(num_operands > 0);
212 assert(operand.get_kind() == Operand::LABEL);
213 std::string target_label = operand.get_label();
214 work_list.push_back({ ins_index: target_index, pred: bb, edge_kind: EDGE_BRANCH, label: target_label });
220 if (falls_through(bb)) {
221 unsigned target_index = item.ins_index + bb->get_length();
222 assert(target_index <= m_iseq->get_length());
223 if (target_index == num_instructions) {
229 work_list.push_back({ ins_index: target_index, pred: bb, edge_kind: EDGE_FALLTHROUGH });
234 assert(last !=
nullptr);
235 m_cfg->create_edge(last, exit, EDGE_FALLTHROUGH);
240 template<
typename InstructionProperties>
245 return num_operands > 0 && ins->
get_operand(num_operands - 1).get_kind() == Operand::LABEL;
248 template<
typename InstructionProperties>
250 unsigned index = item.ins_index;
252 std::shared_ptr<InstructionSequence> bb = m_cfg->create_basic_block(
BASICBLOCK_INTERIOR,
int(index), label);
258 while (index < m_iseq->get_length()) {
266 if (index >= m_iseq->get_length()) {
271 if (m_ins_props.is_function_call(ins)) {
276 if (is_branch(ins)) {
281 if (m_iseq->has_label(index)) {
288 assert(bb->get_length() > 0);
293 template<
typename InstructionProperties>
295 return !m_ins_props.is_function_call(bb->get_last_instruction()) && is_branch(bb->get_last_instruction());
298 template<
typename InstructionProperties>
300 assert(ends_in_branch(bb));
305 assert(num_operands > 0);
307 assert(label.get_kind() == Operand::LABEL);
310 unsigned target_index = m_iseq->get_index_of_labeled_instruction(label.get_label());
314 template<
typename InstructionProperties>
316 return m_ins_props.falls_through(bb->get_last_instruction());
ControlFlowGraph and associated types.
EdgeKind
Control-flow graph edge kinds.
Definition: cfg.h:48
ControlFlowGraphBuilder< HighLevelInstructionProperties > make_highlevel_cfg_builder(const std::shared_ptr< InstructionSequence > &iseq)
Return a ControlFlowGraphBuilder for building a high-level ControlFlowGraph.
Definition: cfg_builder.h:104
ControlFlowGraphBuilder< LowLevelInstructionProperties > make_lowlevel_cfg_builder(const std::shared_ptr< InstructionSequence > &iseq)
Return a ControlFlowGraphBuilder for building a low-level ControlFlowGraph.
Definition: cfg_builder.h:119
ControlFlowGraphBuilder builds a ControlFlowGraph from an InstructionSequence.
Definition: cfg_builder.h:44
std::shared_ptr< ControlFlowGraph > build()
Build a ControlFlowGraph from the original InstructionSequence.
Definition: cfg_builder.h:139
virtual bool is_branch(Instruction *ins)
Subclasses may override this method to specify which Instructions are branches (i....
Definition: cfg_builder.h:241
ControlFlowGraphBuilder(const std::shared_ptr< InstructionSequence > &iseq)
Constuctor.
Definition: cfg_builder.h:128
ControlFlowGraph: graph of basic blocks connected by control edges.
Definition: cfg.h:86
Instruction object type.
Definition: instruction.h:31
const Operand & get_operand(unsigned index) const
Get the specified Operand.
Definition: instruction.cpp:54
Instruction * duplicate() const
Return an exact duplicate of this Instruction.
Definition: instruction.h:69
unsigned get_num_operands() const
Get the number of operands.
Definition: instruction.cpp:50
HighLevelOpcode enumeration and associated helper functions and the HighLevelInstructionProperties cl...
@ 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
@ BASICBLOCK_EXIT
special "exit" block
Definition: instruction_seq.h:41