blob: f2c71469e5246b0435f58be4d5af33526a6ded91 [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18#ifndef SEA_IR_H_
19#define SEA_IR_H_
20
21#include <set>
22#include <map>
23
24#include "dex_file.h"
25#include "dex_instruction.h"
26#include "sea_ir/instruction_tools.h"
27
28#define NO_REGISTER (-1)
29
30namespace sea_ir {
31class Region;
32
33class SeaNode {
34 public:
35 explicit SeaNode():id_(GetNewId()), string_id_(), successors_(), predecessors_() {
36 std::stringstream ss;
37 ss << id_;
38 string_id_.append(ss.str());
39 }
40
41 // Adds CFG predecessors and successors to each block.
42 void AddSuccessor(Region* successor);
43 void AddPredecessor(Region* predecesor);
44
45 // Returns the id of the current block as string
46 const std::string& StringId() const {
47 return string_id_;
48 }
49
50 // Appends to @result a dot language formatted string representing the node and
51 // (by convention) outgoing edges, so that the composition of theToDot() of all nodes
52 // builds a complete dot graph, but without prolog ("digraph {") and epilog ("}").
53 virtual void ToDot(std::string& result) const = 0;
54
55 virtual ~SeaNode() {}
56
57 protected:
58 static int GetNewId() {
59 return current_max_node_id_++;
60 }
61
62 const int id_;
63 std::string string_id_;
64 std::vector<sea_ir::Region*> successors_; // CFG successor nodes (regions)
65 std::vector<sea_ir::Region*> predecessors_; // CFG predecessor nodes (instructions/regions)
66
67 private:
68 static int current_max_node_id_;
69};
70
71class InstructionNode: public SeaNode {
72 public:
73 explicit InstructionNode(const art::Instruction* in):SeaNode(), instruction_(in), de_def_(false) {}
74
75 const art::Instruction* GetInstruction() const {
76 DCHECK(NULL != instruction_) << "Tried to access NULL instruction in an InstructionNode.";
77 return instruction_;
78 }
79 // Returns the register that is defined by the current instruction, or NO_REGISTER otherwise.
80 int GetResultRegister() const;
81 void ToDot(std::string& result) const;
82 void MarkAsDEDef();
83
84 private:
85 const art::Instruction* const instruction_;
86 bool de_def_;
87};
88
89
90
91class Region : public SeaNode {
92 public:
93 explicit Region():SeaNode(), reaching_defs_size_(-1) {}
94
95 // Adds @inst as an instruction node child in the current region.
96 void AddChild(sea_ir::InstructionNode* inst);
97
98 // Returns the last instruction node child of the current region.
99 // This child has the CFG successors pointing to the new regions.
100 SeaNode* GetLastChild() const;
101
102 // Appends to @result a dot language formatted string representing the node and
103 // (by convention) outgoing edges, so that the composition of theToDot() of all nodes
104 // builds a complete dot graph (without prolog and epilog though).
105 virtual void ToDot(std::string& result) const;
106
107 // Computes Downward Exposed Definitions for the current node.
108 void ComputeDownExposedDefs();
109 const std::map<int, sea_ir::InstructionNode*>* GetDownExposedDefs() const;
110
111 // Performs one iteration of the reaching definitions algorithm
112 // and returns true if the reaching definitions set changed.
113 bool UpdateReachingDefs();
114
115 // Returns the set of reaching definitions for the current region.
116 std::map<int, std::set<sea_ir::InstructionNode*>* >* GetReachingDefs();
117
118 private:
119 std::vector<sea_ir::InstructionNode*> instructions_;
120 std::map<int, sea_ir::InstructionNode*> de_defs_;
121 std::map<int, std::set<sea_ir::InstructionNode*>* > reaching_defs_;
122 int reaching_defs_size_;
123};
124
125
126
127class SeaGraph {
128 public:
129 static SeaGraph* GetCurrentGraph();
130 void CompileMethod(const art::DexFile::CodeItem* code_item,
131 uint32_t class_def_idx, uint32_t method_idx, const art::DexFile& dex_file);
132
133 // Returns a string representation of the region and its Instruction children
134 void DumpSea(std::string filename) const;
135
136 // Adds a CFG edge from @src node to @dst node.
137 void AddEdge(Region* src, Region* dst) const;
138
139 // Computes Downward Exposed Definitions for all regions in the graph.
140 void ComputeDownExposedDefs();
141
142 // Computes the reaching definitions set following the equations from
143 // Cooper & Torczon, "Engineering a Compiler", second edition, page 491
144 void ComputeReachingDefs();
145
146 /*** Static helper functions follow: ***/
147 static int ParseInstruction(const uint16_t* code_ptr,
148 art::DecodedInstruction* decoded_instruction);
149 static bool IsInstruction(const uint16_t* code_ptr);
150
151 private:
152 // Registers the parameter as a child region of the SeaGraph instance
153 void AddRegion(Region* r);
154 // Returns new region and registers it with the SeaGraph instance
155 Region* GetNewRegion();
156 static SeaGraph graph_;
157 std::vector<Region*> regions_;
158};
159
160
161} // end namespace sea_ir
162#endif