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