blob: e08558fa2d5842c22bf70bd20fb7a55f04b80e09 [file] [log] [blame]
Dragos Sbirlea7467ee02013-06-21 09:20:34 -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#include "compiler/sea_ir/sea.h"
18#include "file_output_stream.h"
19
20
21
22namespace sea_ir {
23
24
25SeaGraph SeaGraph::graph_;
26int SeaNode::current_max_node_id_ = 0;
27
28SeaGraph* SeaGraph::GetCurrentGraph() {
29 return &sea_ir::SeaGraph::graph_;
30}
31
32void SeaGraph::DumpSea(std::string filename) const {
33 std::string result;
34 result += "digraph seaOfNodes {\n";
35 for(std::vector<Region*>::const_iterator cit = regions_.begin(); cit != regions_.end(); cit++) {
36 result += (*cit)->ToDot();
37 }
38 result += "}\n";
39 art::File* file = art::OS::OpenFile(filename.c_str(), true, true);
40 art::FileOutputStream fos(file);
41 fos.WriteFully(result.c_str(), result.size());
42 LOG(INFO) << "Written SEA string to file...";
43}
44
45void SeaGraph::CompileMethod(const art::DexFile::CodeItem* code_item,
46 uint32_t class_def_idx, uint32_t method_idx, const art::DexFile& dex_file) {
47 const uint16_t* code = code_item->insns_;
48 const size_t size_in_code_units = code_item->insns_size_in_code_units_;
49
50 Region* r = NULL;
51 // This maps target instruction pointers to their corresponding region objects.
52 std::map<const uint16_t*, Region*> target_regions;
53 size_t i = 0;
54
55 // Pass 1: Find the start instruction of basic blocks, as targets and flow-though of branches.
56 while (i < size_in_code_units) {
57 const art::Instruction* inst = art::Instruction::At(&code[i]);
58 if (inst->IsBranch()||inst->IsUnconditional()) {
59 int32_t offset = inst->GetTargetOffset();
60 if (target_regions.end() == target_regions.find(&code[i+offset])) {
61 Region* region = GetNewRegion();
62 target_regions.insert(std::pair<const uint16_t*, Region*>(&code[i+offset], region));
63 }
64 if (inst->IsFlowthrough() &&
65 (target_regions.end() == target_regions.find(&code[i+inst->SizeInCodeUnits()]))) {
66 Region* region = GetNewRegion();
67 target_regions.insert(std::pair<const uint16_t*, Region*>(&code[i+inst->SizeInCodeUnits()], region));
68 }
69 }
70 i += inst->SizeInCodeUnits();
71 }
72
73
74 // Pass 2: Assign instructions to region nodes and
75 // assign branches their control flow successors.
76 i = 0;
77 r = GetNewRegion();
78 sea_ir::SeaNode* last_node = NULL;
79 sea_ir::SeaNode* node = NULL;
80 while (i < size_in_code_units) {
81 const art::Instruction* inst = art::Instruction::At(&code[i]); //TODO: find workaround for this
82 last_node = node;
83 node = new sea_ir::SeaNode(inst);
84
85 if (inst->IsBranch() || inst->IsUnconditional()) {
86 int32_t offset = inst->GetTargetOffset();
87 std::map<const uint16_t*, Region*>::iterator it = target_regions.find(&code[i+offset]);
88 DCHECK(it != target_regions.end());
89 node->AddSuccessor(it->second);
90 }
91
92 std::map<const uint16_t*, Region*>::iterator it = target_regions.find(&code[i]);
93 if (target_regions.end() != it) {
94 // Get the already created region because this is a branch target.
95 Region* nextRegion = it->second;
96 if (last_node->GetInstruction()->IsBranch() && last_node->GetInstruction()->IsFlowthrough()) {
97 last_node->AddSuccessor(nextRegion);
98
99 }
100 r = nextRegion;
101 }
102
103 LOG(INFO) << inst->GetDexPc(code) << "*** " << inst->DumpString(&dex_file)
104 << " region:" <<r->StringId() << std::endl;
105 r->AddChild(node);
106 i += inst->SizeInCodeUnits();
107 }
108
109}
110
111
112Region* SeaGraph::GetNewRegion() {
113 Region* new_region = new Region();
114 AddRegion(new_region);
115 return new_region;
116}
117
118void SeaGraph::AddRegion(Region* r) {
119 DCHECK(r) << "Tried to add NULL region to SEA graph.";
120 regions_.push_back(r);
121}
122void Region::AddChild(sea_ir::SeaNode* instruction) {
123 DCHECK(inst) << "Tried to add NULL instruction to region node.";
124 instructions_.push_back(instruction);
125}
126
127SeaNode* Region::GetLastChild() const {
128 if (instructions_.size()>0) {
129 return instructions_.back();
130 }
131 return NULL;
132}
133
134std::string SeaNode::ToDot() const {
135 std::string node = "// Instruction: \n" + StringId() +
136 " [label=\"" + instruction_->DumpString(NULL) + "\"];\n";
137
138 for(std::vector<SeaNode*>::const_iterator cit = successors_.begin();
139 cit != successors_.end(); cit++) {
140 DCHECK(NULL != *cit) << "Null successor found for SeaNode" << StringId() << ".";
141 node += StringId() + " -> " + (*cit)->StringId() + ";\n\n";
142 }
143 return node;
144}
145
146std::string SeaNode::StringId() const {
147 std::stringstream ss;
148 ss << id_;
149 return ss.str();
150}
151
152std::string Region::ToDot() const {
153 std::string result = "// Region: \n" +
154 StringId() + " [label=\"region " + StringId() + "\"];";
155
156 for(std::vector<SeaNode*>::const_iterator cit = instructions_.begin();
157 cit != instructions_.end(); cit++) {
158 result += (*cit)->ToDot();
159 result += StringId() + " -> " + (*cit)->StringId() + ";\n";
160 }
161
162 result += "// End Region.\n";
163 return result;
164}
165
166void SeaNode::AddSuccessor(SeaNode* successor) {
167 DCHECK(successor) << "Tried to add NULL successor to SEA node.";
168 successors_.push_back(successor);
169 return;
170}
171
172} // end namespace