blob: 8d79c415459a73dc76f5cc13ae72f6e583aef716 [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>
Dragos Sbirlea90af14d2013-08-15 17:50:16 -070018
19#include "base/logging.h"
20#include "utils.h"
21
Dragos Sbirleabfaf44f2013-08-06 15:41:44 -070022#include "sea_ir/ir/sea.h"
23#include "sea_ir/code_gen/code_gen.h"
Dragos Sbirlea90af14d2013-08-15 17:50:16 -070024#include "sea_ir/types/type_inference.h"
25#include "sea_ir/types/types.h"
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070026
27namespace sea_ir {
28
29void CodeGenPrepassVisitor::Visit(PhiInstructionNode* phi) {
30 Region* r = phi->GetRegion();
31 const std::vector<Region*>* predecessors = r->GetPredecessors();
32 DCHECK(NULL != predecessors);
33 DCHECK_GT(predecessors->size(), 0u);
34 llvm::PHINode *llvm_phi = llvm_data_->builder_.CreatePHI(
35 llvm::Type::getInt32Ty(*llvm_data_->context_), predecessors->size(), phi->StringId());
36 llvm_data_->AddValue(phi, llvm_phi);
37}
38
39void CodeGenPassVisitor::Initialize(SeaGraph* graph) {
40 Region* root_region;
41 ordered_regions_.clear();
42 for (std::vector<Region*>::const_iterator cit = graph->GetRegions()->begin();
43 cit != graph->GetRegions()->end(); cit++ ) {
44 if ((*cit)->GetIDominator() == (*cit)) {
45 root_region = *cit;
46 }
47 }
48 ordered_regions_.push_back(root_region);
49 for (unsigned int id = 0; id < ordered_regions_.size(); id++) {
50 Region* current_region = ordered_regions_.at(id);
51 const std::set<Region*>* dominated_regions = current_region->GetIDominatedSet();
52 for (std::set<Region*>::const_iterator cit = dominated_regions->begin();
53 cit != dominated_regions->end(); cit++ ) {
54 ordered_regions_.push_back(*cit);
55 }
56 }
57}
58
Dragos Sbirlea90af14d2013-08-15 17:50:16 -070059void CodeGenPostpassVisitor::Visit(SeaGraph* graph) { }
60void CodeGenVisitor::Visit(SeaGraph* graph) { }
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070061void CodeGenPrepassVisitor::Visit(SeaGraph* graph) {
62 std::vector<SignatureNode*>* parameters = graph->GetParameterNodes();
Dragos Sbirlea90af14d2013-08-15 17:50:16 -070063 // TODO: It may be better to extract correct types from dex
64 // instead than from type inference.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070065 DCHECK(parameters != NULL);
Dragos Sbirlea90af14d2013-08-15 17:50:16 -070066 std::vector<llvm::Type*> parameter_types;
67 for (std::vector<SignatureNode*>::const_iterator param_iterator = parameters->begin();
68 param_iterator!= parameters->end(); param_iterator++) {
69 const Type* param_type = graph->ti_->type_data_.FindTypeOf((*param_iterator)->Id());
70 DCHECK(param_type->Equals(graph->ti_->type_cache_->Integer()))
71 << "Code generation for types other than integer not implemented.";
72 parameter_types.push_back(llvm::Type::getInt32Ty(*llvm_data_->context_));
73 }
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070074
Dragos Sbirlea90af14d2013-08-15 17:50:16 -070075 // TODO: Get correct function return type.
76 const Type* return_type = graph->ti_->type_data_.FindTypeOf(-1);
77 DCHECK(return_type->Equals(graph->ti_->type_cache_->Integer()))
78 << "Code generation for types other than integer not implemented.";
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070079 llvm::FunctionType *function_type = llvm::FunctionType::get(
80 llvm::Type::getInt32Ty(*llvm_data_->context_),
81 parameter_types, false);
Dragos Sbirlea90af14d2013-08-15 17:50:16 -070082
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070083 llvm_data_->function_ = llvm::Function::Create(function_type,
Dragos Sbirlea90af14d2013-08-15 17:50:16 -070084 llvm::Function::ExternalLinkage, function_name_, &llvm_data_->module_);
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070085 unsigned param_id = 0;
86 for (llvm::Function::arg_iterator arg_it = llvm_data_->function_->arg_begin();
87 param_id != llvm_data_->function_->arg_size(); ++arg_it, ++param_id) {
Dragos Sbirlea90af14d2013-08-15 17:50:16 -070088 // TODO: The "+1" is because of the Method parameter on position 0.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070089 DCHECK(parameters->size() > param_id) << "Insufficient parameters for function signature";
90 // Build parameter register name for LLVM IR clarity.
Dragos Sbirleadb063062013-07-23 16:29:09 -070091 std::string arg_name = art::StringPrintf("r%d", parameters->at(param_id)->GetResultRegister());
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070092 arg_it->setName(arg_name);
93 SignatureNode* parameter = parameters->at(param_id);
94 llvm_data_->AddValue(parameter, arg_it);
95 }
96
97 std::vector<Region*>* regions = &ordered_regions_;
98 DCHECK_GT(regions->size(), 0u);
99 // Then create all other basic blocks.
100 for (std::vector<Region*>::const_iterator cit = regions->begin(); cit != regions->end(); cit++) {
101 llvm::BasicBlock* new_basic_block = llvm::BasicBlock::Create(*llvm_data_->context_,
102 (*cit)->StringId(), llvm_data_->function_);
103 llvm_data_->AddBlock((*cit), new_basic_block);
104 }
105}
106
107void CodeGenPrepassVisitor::Visit(Region* region) {
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700108 llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region));
109}
110void CodeGenPostpassVisitor::Visit(Region* region) {
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700111 llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region));
112}
113void CodeGenVisitor::Visit(Region* region) {
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700114 llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region));
115}
116
117
118void CodeGenVisitor::Visit(InstructionNode* instruction) {
119 std::string instr = instruction->GetInstruction()->DumpString(NULL);
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700120 DCHECK(0); // This whole function is useful only during development.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700121}
Dragos Sbirlea6547fa92013-08-05 18:33:30 -0700122
123void CodeGenVisitor::Visit(UnnamedConstInstructionNode* instruction) {
124 std::string instr = instruction->GetInstruction()->DumpString(NULL);
125 std::cout << "1.Instruction: " << instr << std::endl;
126 llvm_data_->AddValue(instruction,
127 llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, instruction->GetConstValue())));
128}
129
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700130void CodeGenVisitor::Visit(ConstInstructionNode* instruction) {
131 std::string instr = instruction->GetInstruction()->DumpString(NULL);
132 std::cout << "1.Instruction: " << instr << std::endl;
133 llvm_data_->AddValue(instruction,
134 llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, instruction->GetConstValue())));
135}
136void CodeGenVisitor::Visit(ReturnInstructionNode* instruction) {
137 std::string instr = instruction->GetInstruction()->DumpString(NULL);
138 std::cout << "2.Instruction: " << instr << std::endl;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700139 DCHECK_GT(instruction->GetSSAProducers().size(), 0u);
140 llvm::Value* return_value = llvm_data_->GetValue(instruction->GetSSAProducers().at(0));
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700141 llvm_data_->builder_.CreateRet(return_value);
142}
143void CodeGenVisitor::Visit(IfNeInstructionNode* instruction) {
144 std::string instr = instruction->GetInstruction()->DumpString(NULL);
145 std::cout << "3.Instruction: " << instr << std::endl;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700146 std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700147 DCHECK_GT(ssa_uses.size(), 1u);
148 InstructionNode* use_l = ssa_uses.at(0);
149 llvm::Value* left = llvm_data_->GetValue(use_l);
150
151 InstructionNode* use_r = ssa_uses.at(1);
152 llvm::Value* right = llvm_data_->GetValue(use_r);
153 llvm::Value* ifne = llvm_data_->builder_.CreateICmpNE(left, right, instruction->StringId());
154 DCHECK(instruction->GetRegion() != NULL);
155 std::vector<Region*>* successors = instruction->GetRegion()->GetSuccessors();
156 DCHECK_GT(successors->size(), 0u);
157 llvm::BasicBlock* then_block = llvm_data_->GetBlock(successors->at(0));
158 llvm::BasicBlock* else_block = llvm_data_->GetBlock(successors->at(1));
159
160 llvm_data_->builder_.CreateCondBr(ifne, then_block, else_block);
161}
162
163/*
164void CodeGenVisitor::Visit(AddIntLitInstructionNode* instruction) {
165 std::string instr = instruction->GetInstruction()->DumpString(NULL);
166 std::cout << "4.Instruction: " << instr << std::endl;
167 std::vector<InstructionNode*> ssa_uses = instruction->GetSSAUses();
168 InstructionNode* use_l = ssa_uses.at(0);
169 llvm::Value* left = llvm_data->GetValue(use_l);
170 llvm::Value* right = llvm::ConstantInt::get(*llvm_data->context_,
171 llvm::APInt(32, instruction->GetConstValue()));
172 llvm::Value* result = llvm_data->builder_.CreateAdd(left, right);
173 llvm_data->AddValue(instruction, result);
174}
175*/
176void CodeGenVisitor::Visit(MoveResultInstructionNode* instruction) {
177 std::string instr = instruction->GetInstruction()->DumpString(NULL);
178 std::cout << "5.Instruction: " << instr << std::endl;
179 // TODO: Currently, this "mov" instruction is simulated by "res = return_register + 0".
180 // This is inefficient, but should be optimized out by the coalescing phase of the reg alloc.
181 // The TODO is to either ensure that this happens, or to
182 // remove the move-result instructions completely from the IR
183 // by merging them with the invoke-* instructions,
184 // since their purpose of minimizing the number of opcodes in dex is
185 // not relevant for the IR. (Will need to have different
186 // instruction subclasses for functions and procedures.)
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700187 std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700188 InstructionNode* use_l = ssa_uses.at(0);
189 llvm::Value* left = llvm_data_->GetValue(use_l);
190 llvm::Value* right = llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, 0));
191 llvm::Value* result = llvm_data_->builder_.CreateAdd(left, right);
192 llvm_data_->AddValue(instruction, result);
193}
194void CodeGenVisitor::Visit(InvokeStaticInstructionNode* invoke) {
195 std::string instr = invoke->GetInstruction()->DumpString(NULL);
196 std::cout << "6.Instruction: " << instr << std::endl;
Dragos Sbirlea90af14d2013-08-15 17:50:16 -0700197 // TODO: Build callee LLVM function name.
198 std::string symbol = "dex_";
199 symbol += art::MangleForJni(PrettyMethod(invoke->GetCalledMethodIndex(), dex_file_));
200 std::string function_name = "dex_int_00020Main_fibonacci_00028int_00029";
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700201 llvm::Function *callee = llvm_data_->module_.getFunction(function_name);
202 // TODO: Add proper checking of the matching between formal and actual signature.
203 DCHECK(NULL != callee);
204 std::vector<llvm::Value*> parameter_values;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700205 std::vector<InstructionNode*> parameter_sources = invoke->GetSSAProducers();
Dragos Sbirlea90af14d2013-08-15 17:50:16 -0700206 // TODO: Replace first parameter with Method argument instead of 0.
207 parameter_values.push_back(llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, 0)));
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700208 for (std::vector<InstructionNode*>::const_iterator cit = parameter_sources.begin();
209 cit != parameter_sources.end(); ++cit) {
210 llvm::Value* parameter_value = llvm_data_->GetValue((*cit));
211 DCHECK(NULL != parameter_value);
212 parameter_values.push_back(parameter_value);
213 }
214 llvm::Value* return_value = llvm_data_->builder_.CreateCall(callee,
215 parameter_values, invoke->StringId());
216 llvm_data_->AddValue(invoke, return_value);
217}
218void CodeGenVisitor::Visit(AddIntInstructionNode* instruction) {
219 std::string instr = instruction->GetInstruction()->DumpString(NULL);
220 std::cout << "7.Instruction: " << instr << std::endl;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700221 std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700222 DCHECK_GT(ssa_uses.size(), 1u);
223 InstructionNode* use_l = ssa_uses.at(0);
224 InstructionNode* use_r = ssa_uses.at(1);
225 llvm::Value* left = llvm_data_->GetValue(use_l);
226 llvm::Value* right = llvm_data_->GetValue(use_r);
227 llvm::Value* result = llvm_data_->builder_.CreateAdd(left, right);
228 llvm_data_->AddValue(instruction, result);
229}
230void CodeGenVisitor::Visit(GotoInstructionNode* instruction) {
231 std::string instr = instruction->GetInstruction()->DumpString(NULL);
232 std::cout << "8.Instruction: " << instr << std::endl;
233 std::vector<sea_ir::Region*>* targets = instruction->GetRegion()->GetSuccessors();
234 DCHECK_EQ(targets->size(), 1u);
235 llvm::BasicBlock* target_block = llvm_data_->GetBlock(targets->at(0));
236 llvm_data_->builder_.CreateBr(target_block);
237}
238void CodeGenVisitor::Visit(IfEqzInstructionNode* instruction) {
239 std::string instr = instruction->GetInstruction()->DumpString(NULL);
240 std::cout << "9. Instruction: " << instr << "; Id: " <<instruction << std::endl;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700241 std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700242 DCHECK_GT(ssa_uses.size(), 0u);
243 InstructionNode* use_l = ssa_uses.at(0);
244 llvm::Value* left = llvm_data_->GetValue(use_l);
245 llvm::Value* ifeqz = llvm_data_->builder_.CreateICmpEQ(left,
246 llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt::getNullValue(32)),
247 instruction->StringId());
248 DCHECK(instruction->GetRegion() != NULL);
249 std::vector<Region*>* successors = instruction->GetRegion()->GetSuccessors();
250 DCHECK_GT(successors->size(), 0u);
251 llvm::BasicBlock* then_block = llvm_data_->GetBlock(successors->at(0));
252 llvm::BasicBlock* else_block = llvm_data_->GetBlock(successors->at(1));
253 llvm_data_->builder_.CreateCondBr(ifeqz, then_block, else_block);
254}
255
256void CodeGenPostpassVisitor::Visit(PhiInstructionNode* phi) {
Dragos Sbirlea90af14d2013-08-15 17:50:16 -0700257 std::cout << "10. Instruction: Phi(" << phi->GetRegisterNumber() << ")" << std::endl;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700258 Region* r = phi->GetRegion();
259 const std::vector<Region*>* predecessors = r->GetPredecessors();
260 DCHECK(NULL != predecessors);
261 DCHECK_GT(predecessors->size(), 0u);
262 // Prepass (CodeGenPrepassVisitor) should create the phi function value.
263 llvm::PHINode* llvm_phi = (llvm::PHINode*) llvm_data_->GetValue(phi);
264 int predecessor_pos = 0;
265 for (std::vector<Region*>::const_iterator cit = predecessors->begin();
266 cit != predecessors->end(); ++cit) {
267 std::vector<InstructionNode*>* defining_instructions = phi->GetSSAUses(predecessor_pos++);
268 DCHECK_EQ(defining_instructions->size(), 1u);
269 InstructionNode* defining_instruction = defining_instructions->at(0);
270 DCHECK(NULL != defining_instruction);
271 Region* incoming_region = *cit;
272 llvm::BasicBlock* incoming_basic_block = llvm_data_->GetBlock(incoming_region);
273 llvm::Value* incoming_value = llvm_data_->GetValue(defining_instruction);
274 llvm_phi->addIncoming(incoming_value, incoming_basic_block);
275 }
276}
277
278void CodeGenVisitor::Visit(SignatureNode* signature) {
Dragos Sbirleac16c5b42013-07-26 18:08:35 -0700279 DCHECK_EQ(signature->GetDefinitions().size(), 1u) <<
280 "Signature nodes must correspond to a single parameter register.";
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700281}
282void CodeGenPrepassVisitor::Visit(SignatureNode* signature) {
Dragos Sbirleac16c5b42013-07-26 18:08:35 -0700283 DCHECK_EQ(signature->GetDefinitions().size(), 1u) <<
284 "Signature nodes must correspond to a single parameter register.";
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700285}
286void CodeGenPostpassVisitor::Visit(SignatureNode* signature) {
Dragos Sbirleac16c5b42013-07-26 18:08:35 -0700287 DCHECK_EQ(signature->GetDefinitions().size(), 1u) <<
288 "Signature nodes must correspond to a single parameter register.";
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700289}
290
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700291} // namespace sea_ir