blob: ea96b2f59035d5bbe01f7eaef5fc008bcd60fae3 [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 Chien5bcc04e2012-01-30 14:15:12 +080062 basic_blocks_(code_item->insns_size_in_code_units_),
63 basic_block_landing_pads_(code_item->tries_size_, NULL),
64 basic_block_unwind_(NULL), basic_block_unreachable_(NULL) {
Shih-wei Liaod1fec812012-02-13 09:51:10 -080065}
66
67
68MethodCompiler::~MethodCompiler() {
Logan Chienc670a8d2011-12-20 21:25:56 +080069 STLDeleteElements(&regs_);
Shih-wei Liaod1fec812012-02-13 09:51:10 -080070}
71
72
Logan Chien0b827102011-12-20 19:46:14 +080073void MethodCompiler::CreateFunction() {
74 // LLVM function name
75 std::string func_name(LLVMLongName(method_));
76
77 // Get function type
78 llvm::FunctionType* func_type =
79 GetFunctionType(method_idx_, method_->IsStatic());
80
81 // Create function
82 func_ = llvm::Function::Create(func_type, llvm::Function::ExternalLinkage,
83 func_name, module_);
84
85 // Set argument name
86 llvm::Function::arg_iterator arg_iter(func_->arg_begin());
87 llvm::Function::arg_iterator arg_end(func_->arg_end());
88
89 DCHECK_NE(arg_iter, arg_end);
90 arg_iter->setName("method");
91 ++arg_iter;
92
93 if (!method_->IsStatic()) {
94 DCHECK_NE(arg_iter, arg_end);
95 arg_iter->setName("this");
96 ++arg_iter;
97 }
98
99 for (unsigned i = 0; arg_iter != arg_end; ++i, ++arg_iter) {
100 arg_iter->setName(StringPrintf("a%u", i));
101 }
102}
103
104
105llvm::FunctionType* MethodCompiler::GetFunctionType(uint32_t method_idx,
106 bool is_static) {
107 // Get method signature
108 DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);
109
110 int32_t shorty_size;
111 char const* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
112 CHECK_GE(shorty_size, 1);
113
114 // Get return type
115 llvm::Type* ret_type = irb_.getJType(shorty[0], kAccurate);
116
117 // Get argument type
118 std::vector<llvm::Type*> args_type;
119
120 args_type.push_back(irb_.getJObjectTy()); // method object pointer
121
122 if (!is_static) {
123 args_type.push_back(irb_.getJType('L', kAccurate)); // "this" object pointer
124 }
125
126 for (int32_t i = 1; i < shorty_size; ++i) {
127 args_type.push_back(irb_.getJType(shorty[i], kAccurate));
128 }
129
130 return llvm::FunctionType::get(ret_type, args_type, false);
131}
132
133
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800134void MethodCompiler::EmitPrologue() {
Logan Chienc670a8d2011-12-20 21:25:56 +0800135 // Create basic blocks for prologue
136 basic_block_reg_alloca_ =
137 llvm::BasicBlock::Create(*context_, "prologue.alloca", func_);
138
139 basic_block_reg_zero_init_ =
140 llvm::BasicBlock::Create(*context_, "prologue.zeroinit", func_);
141
Logan Chiend6ececa2011-12-27 16:20:15 +0800142 basic_block_reg_arg_init_ =
143 llvm::BasicBlock::Create(*context_, "prologue.arginit", func_);
144
Logan Chienc670a8d2011-12-20 21:25:56 +0800145 // Create register array
146 for (uint16_t r = 0; r < code_item_->registers_size_; ++r) {
147 regs_.push_back(DalvikReg::CreateLocalVarReg(*this, r));
148 }
149
150 retval_reg_.reset(DalvikReg::CreateRetValReg(*this));
Logan Chiend6ececa2011-12-27 16:20:15 +0800151
152 // Store argument to dalvik register
153 irb_.SetInsertPoint(basic_block_reg_arg_init_);
154 EmitPrologueAssignArgRegister();
155
156 // Branch to start address
157 irb_.CreateBr(GetBasicBlock(0));
Logan Chienc670a8d2011-12-20 21:25:56 +0800158}
159
160
161void MethodCompiler::EmitPrologueLastBranch() {
162 irb_.SetInsertPoint(basic_block_reg_alloca_);
163 irb_.CreateBr(basic_block_reg_zero_init_);
164
165 irb_.SetInsertPoint(basic_block_reg_zero_init_);
Logan Chiend6ececa2011-12-27 16:20:15 +0800166 irb_.CreateBr(basic_block_reg_arg_init_);
167}
168
169
170void MethodCompiler::EmitPrologueAssignArgRegister() {
171 uint16_t arg_reg = code_item_->registers_size_ - code_item_->ins_size_;
172
173 llvm::Function::arg_iterator arg_iter(func_->arg_begin());
174 llvm::Function::arg_iterator arg_end(func_->arg_end());
175
176 char const* shorty = method_helper_.GetShorty();
177 int32_t shorty_size = method_helper_.GetShortyLength();
178 CHECK_LE(1, shorty_size);
179
180 ++arg_iter; // skip method object
181
182 if (!method_->IsStatic()) {
183 EmitStoreDalvikReg(arg_reg, kObject, kAccurate, arg_iter);
184 ++arg_iter;
185 ++arg_reg;
186 }
187
188 for (int32_t i = 1; i < shorty_size; ++i, ++arg_iter) {
189 EmitStoreDalvikReg(arg_reg, shorty[i], kAccurate, arg_iter);
190
191 ++arg_reg;
192 if (shorty[i] == 'J' || shorty[i] == 'D') {
193 // Wide types, such as long and double, are using a pair of registers
194 // to store the value, so we have to increase arg_reg again.
195 ++arg_reg;
196 }
197 }
198
199 DCHECK_EQ(arg_end, arg_iter);
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800200}
201
202
Logan Chien83426162011-12-09 09:29:50 +0800203void MethodCompiler::EmitInstructions() {
Logan Chiend6c239a2011-12-23 15:11:45 +0800204 uint32_t dex_pc = 0;
205 while (dex_pc < code_item_->insns_size_in_code_units_) {
206 Instruction const* insn = Instruction::At(code_item_->insns_ + dex_pc);
207 EmitInstruction(dex_pc, insn);
208 dex_pc += insn->SizeInCodeUnits();
209 }
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800210}
211
212
Logan Chien83426162011-12-09 09:29:50 +0800213void MethodCompiler::EmitInstruction(uint32_t dex_pc,
214 Instruction const* insn) {
Logan Chiend6c239a2011-12-23 15:11:45 +0800215
216 // Set the IRBuilder insertion point
217 irb_.SetInsertPoint(GetBasicBlock(dex_pc));
218
Logan Chien83426162011-12-09 09:29:50 +0800219 // UNIMPLEMENTED(WARNING);
Logan Chiend6c239a2011-12-23 15:11:45 +0800220 irb_.CreateUnreachable();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800221}
222
223
Logan Chien83426162011-12-09 09:29:50 +0800224CompiledMethod *MethodCompiler::Compile() {
Logan Chien0b827102011-12-20 19:46:14 +0800225 // Code generation
226 CreateFunction();
227
228 EmitPrologue();
229 EmitInstructions();
Logan Chienc670a8d2011-12-20 21:25:56 +0800230 EmitPrologueLastBranch();
Logan Chien0b827102011-12-20 19:46:14 +0800231
Logan Chiend6c239a2011-12-23 15:11:45 +0800232 // Verify the generated bitcode
233 llvm::verifyFunction(*func_, llvm::PrintMessageAction);
234
Logan Chien0b827102011-12-20 19:46:14 +0800235 // Delete the inferred register category map (won't be used anymore)
236 method_->ResetInferredRegCategoryMap();
237
238 return new CompiledMethod(insn_set_, func_);
239}
240
241
242llvm::Value* MethodCompiler::EmitLoadMethodObjectAddr() {
243 return func_->arg_begin();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800244}
Logan Chien83426162011-12-09 09:29:50 +0800245
246
Logan Chien5bcc04e2012-01-30 14:15:12 +0800247void MethodCompiler::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
248 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
249 irb_.CreateBr(lpad);
250 } else {
251 irb_.CreateBr(GetUnwindBasicBlock());
252 }
253}
254
255
256void MethodCompiler::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
257 llvm::Value* exception_pending =
258 irb_.CreateCall(irb_.GetRuntime(IsExceptionPending));
259
260 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
261
262 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
263 irb_.CreateCondBr(exception_pending, lpad, block_cont);
264 } else {
265 irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont);
266 }
267
268 irb_.SetInsertPoint(block_cont);
269}
270
271
Logan Chien924072f2012-01-30 15:07:24 +0800272void MethodCompiler::EmitGuard_GarbageCollectionSuspend(uint32_t dex_pc) {
273 llvm::Value* runtime_func = irb_.GetRuntime(TestSuspend);
274 irb_.CreateCall(runtime_func);
275
276 EmitGuard_ExceptionLandingPad(dex_pc);
277}
278
279
Logan Chiend6c239a2011-12-23 15:11:45 +0800280llvm::BasicBlock* MethodCompiler::
281CreateBasicBlockWithDexPC(uint32_t dex_pc, char const* postfix) {
282 std::string name;
283
284 if (postfix) {
285 StringAppendF(&name, "B%u.%s", dex_pc, postfix);
286 } else {
287 StringAppendF(&name, "B%u", dex_pc);
288 }
289
290 return llvm::BasicBlock::Create(*context_, name, func_);
291}
292
293
294llvm::BasicBlock* MethodCompiler::GetBasicBlock(uint32_t dex_pc) {
295 DCHECK(dex_pc < code_item_->insns_size_in_code_units_);
296
297 llvm::BasicBlock* basic_block = basic_blocks_[dex_pc];
298
299 if (!basic_block) {
300 basic_block = CreateBasicBlockWithDexPC(dex_pc);
301 basic_blocks_[dex_pc] = basic_block;
302 }
303
304 return basic_block;
305}
306
307
308llvm::BasicBlock*
309MethodCompiler::GetNextBasicBlock(uint32_t dex_pc) {
310 Instruction const* insn = Instruction::At(code_item_->insns_ + dex_pc);
311 return GetBasicBlock(dex_pc + insn->SizeInCodeUnits());
312}
313
314
Logan Chien5bcc04e2012-01-30 14:15:12 +0800315int32_t MethodCompiler::GetTryItemOffset(uint32_t dex_pc) {
316 // TODO: Since we are emitting the dex instructions in ascending order
317 // w.r.t. address, we can cache the lastest try item offset so that we
318 // don't have to do binary search for every query.
319
320 int32_t min = 0;
321 int32_t max = code_item_->tries_size_ - 1;
322
323 while (min <= max) {
324 int32_t mid = min + (max - min) / 2;
325
326 DexFile::TryItem const* ti = DexFile::GetTryItems(*code_item_, mid);
327 uint32_t start = ti->start_addr_;
328 uint32_t end = start + ti->insn_count_;
329
330 if (dex_pc < start) {
331 max = mid - 1;
332 } else if (dex_pc >= end) {
333 min = mid + 1;
334 } else {
335 return mid; // found
336 }
337 }
338
339 return -1; // not found
340}
341
342
343llvm::BasicBlock* MethodCompiler::GetLandingPadBasicBlock(uint32_t dex_pc) {
344 // Find the try item for this address in this method
345 int32_t ti_offset = GetTryItemOffset(dex_pc);
346
347 if (ti_offset == -1) {
348 return NULL; // No landing pad is available for this address.
349 }
350
351 // Check for the existing landing pad basic block
352 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
353 llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
354
355 if (block_lpad) {
356 // We have generated landing pad for this try item already. Return the
357 // same basic block.
358 return block_lpad;
359 }
360
361 // Get try item from code item
362 DexFile::TryItem const* ti = DexFile::GetTryItems(*code_item_, ti_offset);
363
364 // Create landing pad basic block
365 block_lpad = llvm::BasicBlock::Create(*context_,
366 StringPrintf("lpad%d", ti_offset),
367 func_);
368
369 // Change IRBuilder insert point
370 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
371 irb_.SetInsertPoint(block_lpad);
372
373 // Find catch block with matching type
374 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
375
376 // TODO: Maybe passing try item offset will be a better idea? For now,
377 // we are passing dex_pc, so that we can use existing runtime support
378 // function directly. However, in the runtime supporting function we
379 // have to search for try item with binary search which can be
380 // eliminated.
381 llvm::Value* dex_pc_value = irb_.getInt32(ti->start_addr_);
382
383 llvm::Value* catch_handler_index_value =
384 irb_.CreateCall2(irb_.GetRuntime(FindCatchBlock),
385 method_object_addr, dex_pc_value);
386
387 // Switch instruction (Go to unwind basic block by default)
388 llvm::SwitchInst* sw =
389 irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
390
391 // Cases with matched catch block
392 CatchHandlerIterator iter(*code_item_, ti->start_addr_);
393
394 for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
395 sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
396 }
397
398 // Restore the orignal insert point for IRBuilder
399 irb_.restoreIP(irb_ip_original);
400
401 // Cache this landing pad
402 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
403 basic_block_landing_pads_[ti_offset] = block_lpad;
404
405 return block_lpad;
406}
407
408
409llvm::BasicBlock* MethodCompiler::GetUnwindBasicBlock() {
410 // Check the existing unwinding baisc block block
411 if (basic_block_unwind_ != NULL) {
412 return basic_block_unwind_;
413 }
414
415 // Create new basic block for unwinding
416 basic_block_unwind_ =
417 llvm::BasicBlock::Create(*context_, "exception_unwind", func_);
418
419 // Change IRBuilder insert point
420 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
421 irb_.SetInsertPoint(basic_block_unwind_);
422
423 // Emit the code to return default value (zero) for the given return type.
424 char ret_shorty = method_helper_.GetShorty()[0];
425 if (ret_shorty == 'V') {
426 irb_.CreateRetVoid();
427 } else {
428 irb_.CreateRet(irb_.getJZero(ret_shorty));
429 }
430
431 // Restore the orignal insert point for IRBuilder
432 irb_.restoreIP(irb_ip_original);
433
434 return basic_block_unwind_;
435}
436
437
Logan Chienc670a8d2011-12-20 21:25:56 +0800438llvm::Value* MethodCompiler::AllocDalvikLocalVarReg(RegCategory cat,
439 uint32_t reg_idx) {
440
441 // Save current IR builder insert point
442 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
443
444 // Alloca
445 llvm::Value* reg_addr = NULL;
446
447 switch (cat) {
448 case kRegCat1nr:
449 irb_.SetInsertPoint(basic_block_reg_alloca_);
450 reg_addr = irb_.CreateAlloca(irb_.getJIntTy(), 0,
451 StringPrintf("r%u", reg_idx));
452
453 irb_.SetInsertPoint(basic_block_reg_zero_init_);
454 irb_.CreateStore(irb_.getJInt(0), reg_addr);
455 break;
456
457 case kRegCat2:
458 irb_.SetInsertPoint(basic_block_reg_alloca_);
459 reg_addr = irb_.CreateAlloca(irb_.getJLongTy(), 0,
460 StringPrintf("w%u", reg_idx));
461
462 irb_.SetInsertPoint(basic_block_reg_zero_init_);
463 irb_.CreateStore(irb_.getJLong(0), reg_addr);
464 break;
465
466 case kRegObject:
467 irb_.SetInsertPoint(basic_block_reg_alloca_);
468 reg_addr = irb_.CreateAlloca(irb_.getJObjectTy(), 0,
469 StringPrintf("p%u", reg_idx));
470
471 irb_.SetInsertPoint(basic_block_reg_zero_init_);
472 irb_.CreateStore(irb_.getJNull(), reg_addr);
473 break;
474
475 default:
476 LOG(FATAL) << "Unknown register category for allocation: " << cat;
477 }
478
479 // Restore IRBuilder insert point
480 irb_.restoreIP(irb_ip_original);
481
482 DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
483 return reg_addr;
484}
485
486
487llvm::Value* MethodCompiler::AllocDalvikRetValReg(RegCategory cat) {
488 // Save current IR builder insert point
489 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
490
491 // Alloca
492 llvm::Value* reg_addr = NULL;
493
494 switch (cat) {
495 case kRegCat1nr:
496 irb_.SetInsertPoint(basic_block_reg_alloca_);
497 reg_addr = irb_.CreateAlloca(irb_.getJIntTy(), 0, "r_res");
498 break;
499
500 case kRegCat2:
501 irb_.SetInsertPoint(basic_block_reg_alloca_);
502 reg_addr = irb_.CreateAlloca(irb_.getJLongTy(), 0, "w_res");
503 break;
504
505 case kRegObject:
506 irb_.SetInsertPoint(basic_block_reg_alloca_);
507 reg_addr = irb_.CreateAlloca(irb_.getJObjectTy(), 0, "p_res");
508 break;
509
510 default:
511 LOG(FATAL) << "Unknown register category for allocation: " << cat;
512 }
513
514 // Restore IRBuilder insert point
515 irb_.restoreIP(irb_ip_original);
516
517 DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
518 return reg_addr;
519}
520
521
Logan Chien83426162011-12-09 09:29:50 +0800522} // namespace compiler_llvm
523} // namespace art