blob: 0ef21b4800e9664db4208521199dba54544fcd61 [file] [log] [blame]
Dragos Sbirlea0e260a32013-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 <llvm/Support/raw_ostream.h>
18#include "sea.h"
19#include "code_gen.h"
20
21namespace sea_ir {
22
23void CodeGenPrepassVisitor::Visit(PhiInstructionNode* phi) {
24 Region* r = phi->GetRegion();
25 const std::vector<Region*>* predecessors = r->GetPredecessors();
26 DCHECK(NULL != predecessors);
27 DCHECK_GT(predecessors->size(), 0u);
28 llvm::PHINode *llvm_phi = llvm_data_->builder_.CreatePHI(
29 llvm::Type::getInt32Ty(*llvm_data_->context_), predecessors->size(), phi->StringId());
30 llvm_data_->AddValue(phi, llvm_phi);
31}
32
33void CodeGenPassVisitor::Initialize(SeaGraph* graph) {
34 Region* root_region;
35 ordered_regions_.clear();
36 for (std::vector<Region*>::const_iterator cit = graph->GetRegions()->begin();
37 cit != graph->GetRegions()->end(); cit++ ) {
38 if ((*cit)->GetIDominator() == (*cit)) {
39 root_region = *cit;
40 }
41 }
42 ordered_regions_.push_back(root_region);
43 for (unsigned int id = 0; id < ordered_regions_.size(); id++) {
44 Region* current_region = ordered_regions_.at(id);
45 const std::set<Region*>* dominated_regions = current_region->GetIDominatedSet();
46 for (std::set<Region*>::const_iterator cit = dominated_regions->begin();
47 cit != dominated_regions->end(); cit++ ) {
48 ordered_regions_.push_back(*cit);
49 }
50 }
51}
52
53void CodeGenPostpassVisitor::Visit(SeaGraph* graph) {
54 std::vector<SignatureNode*>* parameters = graph->GetParameterNodes();
55 std::cout << "=== SeaGraph ===" << parameters->size() << std::endl;
56}
57void CodeGenVisitor::Visit(SeaGraph* graph) {
58 std::vector<SignatureNode*>* parameters = graph->GetParameterNodes();
59 std::cout << "=== SeaGraph ===" << parameters->size() << std::endl;
60}
61void CodeGenPrepassVisitor::Visit(SeaGraph* graph) {
62 std::vector<SignatureNode*>* parameters = graph->GetParameterNodes();
63 std::cout << "=== SeaGraph ===" << parameters->size() << std::endl;
64 // TODO: Extract correct types from dex for params and return value.
65 DCHECK(parameters != NULL);
66 std::vector<llvm::Type*> parameter_types(parameters->size(),
67 llvm::Type::getInt32Ty(*llvm_data_->context_));
68 // Build llvm function name.
Dragos Sbirleac16c5b42013-07-26 18:08:35 -070069 std::string function_name = art::StringPrintf(
70 "class=%d_method=%d", graph->class_def_idx_, graph->method_idx_);
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070071
72 // Build llvm function type and parameters.
73 llvm::FunctionType *function_type = llvm::FunctionType::get(
74 llvm::Type::getInt32Ty(*llvm_data_->context_),
75 parameter_types, false);
76 llvm_data_->function_ = llvm::Function::Create(function_type,
77 llvm::Function::ExternalLinkage, function_name, &llvm_data_->module_);
78 unsigned param_id = 0;
79 for (llvm::Function::arg_iterator arg_it = llvm_data_->function_->arg_begin();
80 param_id != llvm_data_->function_->arg_size(); ++arg_it, ++param_id) {
81 DCHECK(parameters->size() > param_id) << "Insufficient parameters for function signature";
82 // Build parameter register name for LLVM IR clarity.
Dragos Sbirleadb063062013-07-23 16:29:09 -070083 std::string arg_name = art::StringPrintf("r%d", parameters->at(param_id)->GetResultRegister());
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070084 arg_it->setName(arg_name);
85 SignatureNode* parameter = parameters->at(param_id);
86 llvm_data_->AddValue(parameter, arg_it);
87 }
88
89 std::vector<Region*>* regions = &ordered_regions_;
90 DCHECK_GT(regions->size(), 0u);
91 // Then create all other basic blocks.
92 for (std::vector<Region*>::const_iterator cit = regions->begin(); cit != regions->end(); cit++) {
93 llvm::BasicBlock* new_basic_block = llvm::BasicBlock::Create(*llvm_data_->context_,
94 (*cit)->StringId(), llvm_data_->function_);
95 llvm_data_->AddBlock((*cit), new_basic_block);
96 }
97}
98
99void CodeGenPrepassVisitor::Visit(Region* region) {
100 std::cout << " == Region " << region->StringId() << " ==" << std::endl;
101 llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region));
102}
103void CodeGenPostpassVisitor::Visit(Region* region) {
104 std::cout << " == Region " << region->StringId() << " ==" << std::endl;
105 llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region));
106}
107void CodeGenVisitor::Visit(Region* region) {
108 std::cout << " == Region " << region->StringId() << " ==" << std::endl;
109 llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region));
110}
111
112
113void CodeGenVisitor::Visit(InstructionNode* instruction) {
114 std::string instr = instruction->GetInstruction()->DumpString(NULL);
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700115 DCHECK(0); // This whole function is useful only during development.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700116}
117void CodeGenVisitor::Visit(ConstInstructionNode* instruction) {
118 std::string instr = instruction->GetInstruction()->DumpString(NULL);
119 std::cout << "1.Instruction: " << instr << std::endl;
120 llvm_data_->AddValue(instruction,
121 llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, instruction->GetConstValue())));
122}
123void CodeGenVisitor::Visit(ReturnInstructionNode* instruction) {
124 std::string instr = instruction->GetInstruction()->DumpString(NULL);
125 std::cout << "2.Instruction: " << instr << std::endl;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700126 DCHECK_GT(instruction->GetSSAProducers().size(), 0u);
127 llvm::Value* return_value = llvm_data_->GetValue(instruction->GetSSAProducers().at(0));
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700128 llvm_data_->builder_.CreateRet(return_value);
129}
130void CodeGenVisitor::Visit(IfNeInstructionNode* instruction) {
131 std::string instr = instruction->GetInstruction()->DumpString(NULL);
132 std::cout << "3.Instruction: " << instr << std::endl;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700133 std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700134 DCHECK_GT(ssa_uses.size(), 1u);
135 InstructionNode* use_l = ssa_uses.at(0);
136 llvm::Value* left = llvm_data_->GetValue(use_l);
137
138 InstructionNode* use_r = ssa_uses.at(1);
139 llvm::Value* right = llvm_data_->GetValue(use_r);
140 llvm::Value* ifne = llvm_data_->builder_.CreateICmpNE(left, right, instruction->StringId());
141 DCHECK(instruction->GetRegion() != NULL);
142 std::vector<Region*>* successors = instruction->GetRegion()->GetSuccessors();
143 DCHECK_GT(successors->size(), 0u);
144 llvm::BasicBlock* then_block = llvm_data_->GetBlock(successors->at(0));
145 llvm::BasicBlock* else_block = llvm_data_->GetBlock(successors->at(1));
146
147 llvm_data_->builder_.CreateCondBr(ifne, then_block, else_block);
148}
149
150/*
151void CodeGenVisitor::Visit(AddIntLitInstructionNode* instruction) {
152 std::string instr = instruction->GetInstruction()->DumpString(NULL);
153 std::cout << "4.Instruction: " << instr << std::endl;
154 std::vector<InstructionNode*> ssa_uses = instruction->GetSSAUses();
155 InstructionNode* use_l = ssa_uses.at(0);
156 llvm::Value* left = llvm_data->GetValue(use_l);
157 llvm::Value* right = llvm::ConstantInt::get(*llvm_data->context_,
158 llvm::APInt(32, instruction->GetConstValue()));
159 llvm::Value* result = llvm_data->builder_.CreateAdd(left, right);
160 llvm_data->AddValue(instruction, result);
161}
162*/
163void CodeGenVisitor::Visit(MoveResultInstructionNode* instruction) {
164 std::string instr = instruction->GetInstruction()->DumpString(NULL);
165 std::cout << "5.Instruction: " << instr << std::endl;
166 // TODO: Currently, this "mov" instruction is simulated by "res = return_register + 0".
167 // This is inefficient, but should be optimized out by the coalescing phase of the reg alloc.
168 // The TODO is to either ensure that this happens, or to
169 // remove the move-result instructions completely from the IR
170 // by merging them with the invoke-* instructions,
171 // since their purpose of minimizing the number of opcodes in dex is
172 // not relevant for the IR. (Will need to have different
173 // instruction subclasses for functions and procedures.)
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700174 std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700175 InstructionNode* use_l = ssa_uses.at(0);
176 llvm::Value* left = llvm_data_->GetValue(use_l);
177 llvm::Value* right = llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, 0));
178 llvm::Value* result = llvm_data_->builder_.CreateAdd(left, right);
179 llvm_data_->AddValue(instruction, result);
180}
181void CodeGenVisitor::Visit(InvokeStaticInstructionNode* invoke) {
182 std::string instr = invoke->GetInstruction()->DumpString(NULL);
183 std::cout << "6.Instruction: " << instr << std::endl;
184 // TODO: Build callee llvm function name.
Dragos Sbirlea81f79a62013-07-23 14:31:47 -0700185 std::string function_name = art::StringPrintf("class=%d_method=%d", 0, 1);
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700186 llvm::Function *callee = llvm_data_->module_.getFunction(function_name);
187 // TODO: Add proper checking of the matching between formal and actual signature.
188 DCHECK(NULL != callee);
189 std::vector<llvm::Value*> parameter_values;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700190 std::vector<InstructionNode*> parameter_sources = invoke->GetSSAProducers();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700191 for (std::vector<InstructionNode*>::const_iterator cit = parameter_sources.begin();
192 cit != parameter_sources.end(); ++cit) {
193 llvm::Value* parameter_value = llvm_data_->GetValue((*cit));
194 DCHECK(NULL != parameter_value);
195 parameter_values.push_back(parameter_value);
196 }
197 llvm::Value* return_value = llvm_data_->builder_.CreateCall(callee,
198 parameter_values, invoke->StringId());
199 llvm_data_->AddValue(invoke, return_value);
200}
201void CodeGenVisitor::Visit(AddIntInstructionNode* instruction) {
202 std::string instr = instruction->GetInstruction()->DumpString(NULL);
203 std::cout << "7.Instruction: " << instr << std::endl;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700204 std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700205 DCHECK_GT(ssa_uses.size(), 1u);
206 InstructionNode* use_l = ssa_uses.at(0);
207 InstructionNode* use_r = ssa_uses.at(1);
208 llvm::Value* left = llvm_data_->GetValue(use_l);
209 llvm::Value* right = llvm_data_->GetValue(use_r);
210 llvm::Value* result = llvm_data_->builder_.CreateAdd(left, right);
211 llvm_data_->AddValue(instruction, result);
212}
213void CodeGenVisitor::Visit(GotoInstructionNode* instruction) {
214 std::string instr = instruction->GetInstruction()->DumpString(NULL);
215 std::cout << "8.Instruction: " << instr << std::endl;
216 std::vector<sea_ir::Region*>* targets = instruction->GetRegion()->GetSuccessors();
217 DCHECK_EQ(targets->size(), 1u);
218 llvm::BasicBlock* target_block = llvm_data_->GetBlock(targets->at(0));
219 llvm_data_->builder_.CreateBr(target_block);
220}
221void CodeGenVisitor::Visit(IfEqzInstructionNode* instruction) {
222 std::string instr = instruction->GetInstruction()->DumpString(NULL);
223 std::cout << "9. Instruction: " << instr << "; Id: " <<instruction << std::endl;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700224 std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700225 DCHECK_GT(ssa_uses.size(), 0u);
226 InstructionNode* use_l = ssa_uses.at(0);
227 llvm::Value* left = llvm_data_->GetValue(use_l);
228 llvm::Value* ifeqz = llvm_data_->builder_.CreateICmpEQ(left,
229 llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt::getNullValue(32)),
230 instruction->StringId());
231 DCHECK(instruction->GetRegion() != NULL);
232 std::vector<Region*>* successors = instruction->GetRegion()->GetSuccessors();
233 DCHECK_GT(successors->size(), 0u);
234 llvm::BasicBlock* then_block = llvm_data_->GetBlock(successors->at(0));
235 llvm::BasicBlock* else_block = llvm_data_->GetBlock(successors->at(1));
236 llvm_data_->builder_.CreateCondBr(ifeqz, then_block, else_block);
237}
238
239void CodeGenPostpassVisitor::Visit(PhiInstructionNode* phi) {
240 std::cout << "Phi node for: " << phi->GetRegisterNumber() << std::endl;
241 Region* r = phi->GetRegion();
242 const std::vector<Region*>* predecessors = r->GetPredecessors();
243 DCHECK(NULL != predecessors);
244 DCHECK_GT(predecessors->size(), 0u);
245 // Prepass (CodeGenPrepassVisitor) should create the phi function value.
246 llvm::PHINode* llvm_phi = (llvm::PHINode*) llvm_data_->GetValue(phi);
247 int predecessor_pos = 0;
248 for (std::vector<Region*>::const_iterator cit = predecessors->begin();
249 cit != predecessors->end(); ++cit) {
250 std::vector<InstructionNode*>* defining_instructions = phi->GetSSAUses(predecessor_pos++);
251 DCHECK_EQ(defining_instructions->size(), 1u);
252 InstructionNode* defining_instruction = defining_instructions->at(0);
253 DCHECK(NULL != defining_instruction);
254 Region* incoming_region = *cit;
255 llvm::BasicBlock* incoming_basic_block = llvm_data_->GetBlock(incoming_region);
256 llvm::Value* incoming_value = llvm_data_->GetValue(defining_instruction);
257 llvm_phi->addIncoming(incoming_value, incoming_basic_block);
258 }
259}
260
261void CodeGenVisitor::Visit(SignatureNode* signature) {
262 std::cout << "Signature: ;" << "Id:" << signature->StringId() << std::endl;
Dragos Sbirleac16c5b42013-07-26 18:08:35 -0700263 DCHECK_EQ(signature->GetDefinitions().size(), 1u) <<
264 "Signature nodes must correspond to a single parameter register.";
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700265}
266void CodeGenPrepassVisitor::Visit(SignatureNode* signature) {
267 std::cout << "Signature: ;" << "Id:" << signature->StringId() << std::endl;
Dragos Sbirleac16c5b42013-07-26 18:08:35 -0700268 DCHECK_EQ(signature->GetDefinitions().size(), 1u) <<
269 "Signature nodes must correspond to a single parameter register.";
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700270}
271void CodeGenPostpassVisitor::Visit(SignatureNode* signature) {
272 std::cout << "Signature: ;" << "Id:" << signature->StringId() << std::endl;
Dragos Sbirleac16c5b42013-07-26 18:08:35 -0700273 DCHECK_EQ(signature->GetDefinitions().size(), 1u) <<
274 "Signature nodes must correspond to a single parameter register.";
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700275}
276
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700277} // namespace sea_ir