blob: 65d6412a759beda0f24b0c81284c95c594461405 [file] [log] [blame]
Shih-wei Liaod1fec812012-02-13 09:51:10 -08001/*
2 * Copyright (C) 2012 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 "method_compiler.h"
18
Logan Chienfca7e872011-12-20 20:08:22 +080019#include "backend_types.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080020#include "compiler.h"
21#include "ir_builder.h"
22#include "logging.h"
23#include "object.h"
24#include "object_utils.h"
Logan Chien42e0e152012-01-13 15:42:36 +080025#include "runtime_support_func.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080026#include "stl_util.h"
Logan Chien0b827102011-12-20 19:46:14 +080027#include "stringprintf.h"
28#include "utils_llvm.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080029
30#include <iomanip>
31
32#include <llvm/Analysis/Verifier.h>
Logan Chienc670a8d2011-12-20 21:25:56 +080033#include <llvm/BasicBlock.h>
Shih-wei Liaod1fec812012-02-13 09:51:10 -080034#include <llvm/Function.h>
35
Logan Chien83426162011-12-09 09:29:50 +080036namespace art {
37namespace compiler_llvm {
Shih-wei Liaod1fec812012-02-13 09:51:10 -080038
Logan Chien42e0e152012-01-13 15:42:36 +080039using namespace runtime_support;
40
Shih-wei Liaod1fec812012-02-13 09:51:10 -080041
Logan Chien83426162011-12-09 09:29:50 +080042MethodCompiler::MethodCompiler(InstructionSet insn_set,
43 Compiler* compiler,
44 ClassLinker* class_linker,
45 ClassLoader const* class_loader,
46 DexFile const* dex_file,
47 DexCache* dex_cache,
48 DexFile::CodeItem const* code_item,
Shih-wei Liaod1fec812012-02-13 09:51:10 -080049 uint32_t method_idx,
50 uint32_t access_flags)
51: insn_set_(insn_set),
52 compiler_(compiler), compiler_llvm_(compiler->GetCompilerLLVM()),
53 class_linker_(class_linker), class_loader_(class_loader),
54 dex_file_(dex_file), dex_cache_(dex_cache), code_item_(code_item),
55 method_(dex_cache->GetResolvedMethod(method_idx)),
56 method_helper_(method_), method_idx_(method_idx),
57 access_flags_(access_flags), module_(compiler_llvm_->GetModule()),
58 context_(compiler_llvm_->GetLLVMContext()),
Logan Chienc670a8d2011-12-20 21:25:56 +080059 irb_(*compiler_llvm_->GetIRBuilder()), func_(NULL), retval_reg_(NULL),
Logan Chiend6ececa2011-12-27 16:20:15 +080060 basic_block_reg_alloca_(NULL),
61 basic_block_reg_zero_init_(NULL), basic_block_reg_arg_init_(NULL),
Logan Chienc670a8d2011-12-20 21:25:56 +080062 basic_blocks_(code_item->insns_size_in_code_units_) {
Shih-wei Liaod1fec812012-02-13 09:51:10 -080063}
64
65
66MethodCompiler::~MethodCompiler() {
Logan Chienc670a8d2011-12-20 21:25:56 +080067 STLDeleteElements(&regs_);
Shih-wei Liaod1fec812012-02-13 09:51:10 -080068}
69
70
Logan Chien0b827102011-12-20 19:46:14 +080071void MethodCompiler::CreateFunction() {
72 // LLVM function name
73 std::string func_name(LLVMLongName(method_));
74
75 // Get function type
76 llvm::FunctionType* func_type =
77 GetFunctionType(method_idx_, method_->IsStatic());
78
79 // Create function
80 func_ = llvm::Function::Create(func_type, llvm::Function::ExternalLinkage,
81 func_name, module_);
82
83 // Set argument name
84 llvm::Function::arg_iterator arg_iter(func_->arg_begin());
85 llvm::Function::arg_iterator arg_end(func_->arg_end());
86
87 DCHECK_NE(arg_iter, arg_end);
88 arg_iter->setName("method");
89 ++arg_iter;
90
91 if (!method_->IsStatic()) {
92 DCHECK_NE(arg_iter, arg_end);
93 arg_iter->setName("this");
94 ++arg_iter;
95 }
96
97 for (unsigned i = 0; arg_iter != arg_end; ++i, ++arg_iter) {
98 arg_iter->setName(StringPrintf("a%u", i));
99 }
100}
101
102
103llvm::FunctionType* MethodCompiler::GetFunctionType(uint32_t method_idx,
104 bool is_static) {
105 // Get method signature
106 DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);
107
108 int32_t shorty_size;
109 char const* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
110 CHECK_GE(shorty_size, 1);
111
112 // Get return type
113 llvm::Type* ret_type = irb_.getJType(shorty[0], kAccurate);
114
115 // Get argument type
116 std::vector<llvm::Type*> args_type;
117
118 args_type.push_back(irb_.getJObjectTy()); // method object pointer
119
120 if (!is_static) {
121 args_type.push_back(irb_.getJType('L', kAccurate)); // "this" object pointer
122 }
123
124 for (int32_t i = 1; i < shorty_size; ++i) {
125 args_type.push_back(irb_.getJType(shorty[i], kAccurate));
126 }
127
128 return llvm::FunctionType::get(ret_type, args_type, false);
129}
130
131
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800132void MethodCompiler::EmitPrologue() {
Logan Chienc670a8d2011-12-20 21:25:56 +0800133 // Create basic blocks for prologue
134 basic_block_reg_alloca_ =
135 llvm::BasicBlock::Create(*context_, "prologue.alloca", func_);
136
137 basic_block_reg_zero_init_ =
138 llvm::BasicBlock::Create(*context_, "prologue.zeroinit", func_);
139
Logan Chiend6ececa2011-12-27 16:20:15 +0800140 basic_block_reg_arg_init_ =
141 llvm::BasicBlock::Create(*context_, "prologue.arginit", func_);
142
Logan Chienc670a8d2011-12-20 21:25:56 +0800143 // Create register array
144 for (uint16_t r = 0; r < code_item_->registers_size_; ++r) {
145 regs_.push_back(DalvikReg::CreateLocalVarReg(*this, r));
146 }
147
148 retval_reg_.reset(DalvikReg::CreateRetValReg(*this));
Logan Chiend6ececa2011-12-27 16:20:15 +0800149
150 // Store argument to dalvik register
151 irb_.SetInsertPoint(basic_block_reg_arg_init_);
152 EmitPrologueAssignArgRegister();
153
154 // Branch to start address
155 irb_.CreateBr(GetBasicBlock(0));
Logan Chienc670a8d2011-12-20 21:25:56 +0800156}
157
158
159void MethodCompiler::EmitPrologueLastBranch() {
160 irb_.SetInsertPoint(basic_block_reg_alloca_);
161 irb_.CreateBr(basic_block_reg_zero_init_);
162
163 irb_.SetInsertPoint(basic_block_reg_zero_init_);
Logan Chiend6ececa2011-12-27 16:20:15 +0800164 irb_.CreateBr(basic_block_reg_arg_init_);
165}
166
167
168void MethodCompiler::EmitPrologueAssignArgRegister() {
169 uint16_t arg_reg = code_item_->registers_size_ - code_item_->ins_size_;
170
171 llvm::Function::arg_iterator arg_iter(func_->arg_begin());
172 llvm::Function::arg_iterator arg_end(func_->arg_end());
173
174 char const* shorty = method_helper_.GetShorty();
175 int32_t shorty_size = method_helper_.GetShortyLength();
176 CHECK_LE(1, shorty_size);
177
178 ++arg_iter; // skip method object
179
180 if (!method_->IsStatic()) {
181 EmitStoreDalvikReg(arg_reg, kObject, kAccurate, arg_iter);
182 ++arg_iter;
183 ++arg_reg;
184 }
185
186 for (int32_t i = 1; i < shorty_size; ++i, ++arg_iter) {
187 EmitStoreDalvikReg(arg_reg, shorty[i], kAccurate, arg_iter);
188
189 ++arg_reg;
190 if (shorty[i] == 'J' || shorty[i] == 'D') {
191 // Wide types, such as long and double, are using a pair of registers
192 // to store the value, so we have to increase arg_reg again.
193 ++arg_reg;
194 }
195 }
196
197 DCHECK_EQ(arg_end, arg_iter);
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800198}
199
200
Logan Chien83426162011-12-09 09:29:50 +0800201void MethodCompiler::EmitInstructions() {
Logan Chiend6c239a2011-12-23 15:11:45 +0800202 uint32_t dex_pc = 0;
203 while (dex_pc < code_item_->insns_size_in_code_units_) {
204 Instruction const* insn = Instruction::At(code_item_->insns_ + dex_pc);
205 EmitInstruction(dex_pc, insn);
206 dex_pc += insn->SizeInCodeUnits();
207 }
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800208}
209
210
Logan Chien83426162011-12-09 09:29:50 +0800211void MethodCompiler::EmitInstruction(uint32_t dex_pc,
212 Instruction const* insn) {
Logan Chiend6c239a2011-12-23 15:11:45 +0800213
214 // Set the IRBuilder insertion point
215 irb_.SetInsertPoint(GetBasicBlock(dex_pc));
216
Logan Chien83426162011-12-09 09:29:50 +0800217 // UNIMPLEMENTED(WARNING);
Logan Chiend6c239a2011-12-23 15:11:45 +0800218 irb_.CreateUnreachable();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800219}
220
221
Logan Chien83426162011-12-09 09:29:50 +0800222CompiledMethod *MethodCompiler::Compile() {
Logan Chien0b827102011-12-20 19:46:14 +0800223 // Code generation
224 CreateFunction();
225
226 EmitPrologue();
227 EmitInstructions();
Logan Chienc670a8d2011-12-20 21:25:56 +0800228 EmitPrologueLastBranch();
Logan Chien0b827102011-12-20 19:46:14 +0800229
Logan Chiend6c239a2011-12-23 15:11:45 +0800230 // Verify the generated bitcode
231 llvm::verifyFunction(*func_, llvm::PrintMessageAction);
232
Logan Chien0b827102011-12-20 19:46:14 +0800233 // Delete the inferred register category map (won't be used anymore)
234 method_->ResetInferredRegCategoryMap();
235
236 return new CompiledMethod(insn_set_, func_);
237}
238
239
240llvm::Value* MethodCompiler::EmitLoadMethodObjectAddr() {
241 return func_->arg_begin();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800242}
Logan Chien83426162011-12-09 09:29:50 +0800243
244
Logan Chiend6c239a2011-12-23 15:11:45 +0800245llvm::BasicBlock* MethodCompiler::
246CreateBasicBlockWithDexPC(uint32_t dex_pc, char const* postfix) {
247 std::string name;
248
249 if (postfix) {
250 StringAppendF(&name, "B%u.%s", dex_pc, postfix);
251 } else {
252 StringAppendF(&name, "B%u", dex_pc);
253 }
254
255 return llvm::BasicBlock::Create(*context_, name, func_);
256}
257
258
259llvm::BasicBlock* MethodCompiler::GetBasicBlock(uint32_t dex_pc) {
260 DCHECK(dex_pc < code_item_->insns_size_in_code_units_);
261
262 llvm::BasicBlock* basic_block = basic_blocks_[dex_pc];
263
264 if (!basic_block) {
265 basic_block = CreateBasicBlockWithDexPC(dex_pc);
266 basic_blocks_[dex_pc] = basic_block;
267 }
268
269 return basic_block;
270}
271
272
273llvm::BasicBlock*
274MethodCompiler::GetNextBasicBlock(uint32_t dex_pc) {
275 Instruction const* insn = Instruction::At(code_item_->insns_ + dex_pc);
276 return GetBasicBlock(dex_pc + insn->SizeInCodeUnits());
277}
278
279
Logan Chienc670a8d2011-12-20 21:25:56 +0800280llvm::Value* MethodCompiler::AllocDalvikLocalVarReg(RegCategory cat,
281 uint32_t reg_idx) {
282
283 // Save current IR builder insert point
284 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
285
286 // Alloca
287 llvm::Value* reg_addr = NULL;
288
289 switch (cat) {
290 case kRegCat1nr:
291 irb_.SetInsertPoint(basic_block_reg_alloca_);
292 reg_addr = irb_.CreateAlloca(irb_.getJIntTy(), 0,
293 StringPrintf("r%u", reg_idx));
294
295 irb_.SetInsertPoint(basic_block_reg_zero_init_);
296 irb_.CreateStore(irb_.getJInt(0), reg_addr);
297 break;
298
299 case kRegCat2:
300 irb_.SetInsertPoint(basic_block_reg_alloca_);
301 reg_addr = irb_.CreateAlloca(irb_.getJLongTy(), 0,
302 StringPrintf("w%u", reg_idx));
303
304 irb_.SetInsertPoint(basic_block_reg_zero_init_);
305 irb_.CreateStore(irb_.getJLong(0), reg_addr);
306 break;
307
308 case kRegObject:
309 irb_.SetInsertPoint(basic_block_reg_alloca_);
310 reg_addr = irb_.CreateAlloca(irb_.getJObjectTy(), 0,
311 StringPrintf("p%u", reg_idx));
312
313 irb_.SetInsertPoint(basic_block_reg_zero_init_);
314 irb_.CreateStore(irb_.getJNull(), reg_addr);
315 break;
316
317 default:
318 LOG(FATAL) << "Unknown register category for allocation: " << cat;
319 }
320
321 // Restore IRBuilder insert point
322 irb_.restoreIP(irb_ip_original);
323
324 DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
325 return reg_addr;
326}
327
328
329llvm::Value* MethodCompiler::AllocDalvikRetValReg(RegCategory cat) {
330 // Save current IR builder insert point
331 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
332
333 // Alloca
334 llvm::Value* reg_addr = NULL;
335
336 switch (cat) {
337 case kRegCat1nr:
338 irb_.SetInsertPoint(basic_block_reg_alloca_);
339 reg_addr = irb_.CreateAlloca(irb_.getJIntTy(), 0, "r_res");
340 break;
341
342 case kRegCat2:
343 irb_.SetInsertPoint(basic_block_reg_alloca_);
344 reg_addr = irb_.CreateAlloca(irb_.getJLongTy(), 0, "w_res");
345 break;
346
347 case kRegObject:
348 irb_.SetInsertPoint(basic_block_reg_alloca_);
349 reg_addr = irb_.CreateAlloca(irb_.getJObjectTy(), 0, "p_res");
350 break;
351
352 default:
353 LOG(FATAL) << "Unknown register category for allocation: " << cat;
354 }
355
356 // Restore IRBuilder insert point
357 irb_.restoreIP(irb_ip_original);
358
359 DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
360 return reg_addr;
361}
362
363
Logan Chien83426162011-12-09 09:29:50 +0800364} // namespace compiler_llvm
365} // namespace art