blob: ca1eba5b02f39f3b9222f83dcb7749bbd377577f [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 Chiend6c239a2011-12-23 15:11:45 +0800272llvm::BasicBlock* MethodCompiler::
273CreateBasicBlockWithDexPC(uint32_t dex_pc, char const* postfix) {
274 std::string name;
275
276 if (postfix) {
277 StringAppendF(&name, "B%u.%s", dex_pc, postfix);
278 } else {
279 StringAppendF(&name, "B%u", dex_pc);
280 }
281
282 return llvm::BasicBlock::Create(*context_, name, func_);
283}
284
285
286llvm::BasicBlock* MethodCompiler::GetBasicBlock(uint32_t dex_pc) {
287 DCHECK(dex_pc < code_item_->insns_size_in_code_units_);
288
289 llvm::BasicBlock* basic_block = basic_blocks_[dex_pc];
290
291 if (!basic_block) {
292 basic_block = CreateBasicBlockWithDexPC(dex_pc);
293 basic_blocks_[dex_pc] = basic_block;
294 }
295
296 return basic_block;
297}
298
299
300llvm::BasicBlock*
301MethodCompiler::GetNextBasicBlock(uint32_t dex_pc) {
302 Instruction const* insn = Instruction::At(code_item_->insns_ + dex_pc);
303 return GetBasicBlock(dex_pc + insn->SizeInCodeUnits());
304}
305
306
Logan Chien5bcc04e2012-01-30 14:15:12 +0800307int32_t MethodCompiler::GetTryItemOffset(uint32_t dex_pc) {
308 // TODO: Since we are emitting the dex instructions in ascending order
309 // w.r.t. address, we can cache the lastest try item offset so that we
310 // don't have to do binary search for every query.
311
312 int32_t min = 0;
313 int32_t max = code_item_->tries_size_ - 1;
314
315 while (min <= max) {
316 int32_t mid = min + (max - min) / 2;
317
318 DexFile::TryItem const* ti = DexFile::GetTryItems(*code_item_, mid);
319 uint32_t start = ti->start_addr_;
320 uint32_t end = start + ti->insn_count_;
321
322 if (dex_pc < start) {
323 max = mid - 1;
324 } else if (dex_pc >= end) {
325 min = mid + 1;
326 } else {
327 return mid; // found
328 }
329 }
330
331 return -1; // not found
332}
333
334
335llvm::BasicBlock* MethodCompiler::GetLandingPadBasicBlock(uint32_t dex_pc) {
336 // Find the try item for this address in this method
337 int32_t ti_offset = GetTryItemOffset(dex_pc);
338
339 if (ti_offset == -1) {
340 return NULL; // No landing pad is available for this address.
341 }
342
343 // Check for the existing landing pad basic block
344 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
345 llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
346
347 if (block_lpad) {
348 // We have generated landing pad for this try item already. Return the
349 // same basic block.
350 return block_lpad;
351 }
352
353 // Get try item from code item
354 DexFile::TryItem const* ti = DexFile::GetTryItems(*code_item_, ti_offset);
355
356 // Create landing pad basic block
357 block_lpad = llvm::BasicBlock::Create(*context_,
358 StringPrintf("lpad%d", ti_offset),
359 func_);
360
361 // Change IRBuilder insert point
362 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
363 irb_.SetInsertPoint(block_lpad);
364
365 // Find catch block with matching type
366 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
367
368 // TODO: Maybe passing try item offset will be a better idea? For now,
369 // we are passing dex_pc, so that we can use existing runtime support
370 // function directly. However, in the runtime supporting function we
371 // have to search for try item with binary search which can be
372 // eliminated.
373 llvm::Value* dex_pc_value = irb_.getInt32(ti->start_addr_);
374
375 llvm::Value* catch_handler_index_value =
376 irb_.CreateCall2(irb_.GetRuntime(FindCatchBlock),
377 method_object_addr, dex_pc_value);
378
379 // Switch instruction (Go to unwind basic block by default)
380 llvm::SwitchInst* sw =
381 irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
382
383 // Cases with matched catch block
384 CatchHandlerIterator iter(*code_item_, ti->start_addr_);
385
386 for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
387 sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
388 }
389
390 // Restore the orignal insert point for IRBuilder
391 irb_.restoreIP(irb_ip_original);
392
393 // Cache this landing pad
394 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
395 basic_block_landing_pads_[ti_offset] = block_lpad;
396
397 return block_lpad;
398}
399
400
401llvm::BasicBlock* MethodCompiler::GetUnwindBasicBlock() {
402 // Check the existing unwinding baisc block block
403 if (basic_block_unwind_ != NULL) {
404 return basic_block_unwind_;
405 }
406
407 // Create new basic block for unwinding
408 basic_block_unwind_ =
409 llvm::BasicBlock::Create(*context_, "exception_unwind", func_);
410
411 // Change IRBuilder insert point
412 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
413 irb_.SetInsertPoint(basic_block_unwind_);
414
415 // Emit the code to return default value (zero) for the given return type.
416 char ret_shorty = method_helper_.GetShorty()[0];
417 if (ret_shorty == 'V') {
418 irb_.CreateRetVoid();
419 } else {
420 irb_.CreateRet(irb_.getJZero(ret_shorty));
421 }
422
423 // Restore the orignal insert point for IRBuilder
424 irb_.restoreIP(irb_ip_original);
425
426 return basic_block_unwind_;
427}
428
429
Logan Chienc670a8d2011-12-20 21:25:56 +0800430llvm::Value* MethodCompiler::AllocDalvikLocalVarReg(RegCategory cat,
431 uint32_t reg_idx) {
432
433 // Save current IR builder insert point
434 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
435
436 // Alloca
437 llvm::Value* reg_addr = NULL;
438
439 switch (cat) {
440 case kRegCat1nr:
441 irb_.SetInsertPoint(basic_block_reg_alloca_);
442 reg_addr = irb_.CreateAlloca(irb_.getJIntTy(), 0,
443 StringPrintf("r%u", reg_idx));
444
445 irb_.SetInsertPoint(basic_block_reg_zero_init_);
446 irb_.CreateStore(irb_.getJInt(0), reg_addr);
447 break;
448
449 case kRegCat2:
450 irb_.SetInsertPoint(basic_block_reg_alloca_);
451 reg_addr = irb_.CreateAlloca(irb_.getJLongTy(), 0,
452 StringPrintf("w%u", reg_idx));
453
454 irb_.SetInsertPoint(basic_block_reg_zero_init_);
455 irb_.CreateStore(irb_.getJLong(0), reg_addr);
456 break;
457
458 case kRegObject:
459 irb_.SetInsertPoint(basic_block_reg_alloca_);
460 reg_addr = irb_.CreateAlloca(irb_.getJObjectTy(), 0,
461 StringPrintf("p%u", reg_idx));
462
463 irb_.SetInsertPoint(basic_block_reg_zero_init_);
464 irb_.CreateStore(irb_.getJNull(), reg_addr);
465 break;
466
467 default:
468 LOG(FATAL) << "Unknown register category for allocation: " << cat;
469 }
470
471 // Restore IRBuilder insert point
472 irb_.restoreIP(irb_ip_original);
473
474 DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
475 return reg_addr;
476}
477
478
479llvm::Value* MethodCompiler::AllocDalvikRetValReg(RegCategory cat) {
480 // Save current IR builder insert point
481 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
482
483 // Alloca
484 llvm::Value* reg_addr = NULL;
485
486 switch (cat) {
487 case kRegCat1nr:
488 irb_.SetInsertPoint(basic_block_reg_alloca_);
489 reg_addr = irb_.CreateAlloca(irb_.getJIntTy(), 0, "r_res");
490 break;
491
492 case kRegCat2:
493 irb_.SetInsertPoint(basic_block_reg_alloca_);
494 reg_addr = irb_.CreateAlloca(irb_.getJLongTy(), 0, "w_res");
495 break;
496
497 case kRegObject:
498 irb_.SetInsertPoint(basic_block_reg_alloca_);
499 reg_addr = irb_.CreateAlloca(irb_.getJObjectTy(), 0, "p_res");
500 break;
501
502 default:
503 LOG(FATAL) << "Unknown register category for allocation: " << cat;
504 }
505
506 // Restore IRBuilder insert point
507 irb_.restoreIP(irb_ip_original);
508
509 DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
510 return reg_addr;
511}
512
513
Logan Chien83426162011-12-09 09:29:50 +0800514} // namespace compiler_llvm
515} // namespace art