blob: 31e3c07db64c907f7f6c03f7c4850f3d30d566c7 [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),
57 basic_block_reg_alloca_(NULL), basic_block_reg_zero_init_(NULL),
58 basic_blocks_(code_item->insns_size_in_code_units_) {
Shih-wei Liaod1fec812012-02-13 09:51:10 -080059}
60
61
62MethodCompiler::~MethodCompiler() {
Logan Chienc670a8d2011-12-20 21:25:56 +080063 STLDeleteElements(&regs_);
Shih-wei Liaod1fec812012-02-13 09:51:10 -080064}
65
66
Logan Chien0b827102011-12-20 19:46:14 +080067void MethodCompiler::CreateFunction() {
68 // LLVM function name
69 std::string func_name(LLVMLongName(method_));
70
71 // Get function type
72 llvm::FunctionType* func_type =
73 GetFunctionType(method_idx_, method_->IsStatic());
74
75 // Create function
76 func_ = llvm::Function::Create(func_type, llvm::Function::ExternalLinkage,
77 func_name, module_);
78
79 // Set argument name
80 llvm::Function::arg_iterator arg_iter(func_->arg_begin());
81 llvm::Function::arg_iterator arg_end(func_->arg_end());
82
83 DCHECK_NE(arg_iter, arg_end);
84 arg_iter->setName("method");
85 ++arg_iter;
86
87 if (!method_->IsStatic()) {
88 DCHECK_NE(arg_iter, arg_end);
89 arg_iter->setName("this");
90 ++arg_iter;
91 }
92
93 for (unsigned i = 0; arg_iter != arg_end; ++i, ++arg_iter) {
94 arg_iter->setName(StringPrintf("a%u", i));
95 }
96}
97
98
99llvm::FunctionType* MethodCompiler::GetFunctionType(uint32_t method_idx,
100 bool is_static) {
101 // Get method signature
102 DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);
103
104 int32_t shorty_size;
105 char const* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
106 CHECK_GE(shorty_size, 1);
107
108 // Get return type
109 llvm::Type* ret_type = irb_.getJType(shorty[0], kAccurate);
110
111 // Get argument type
112 std::vector<llvm::Type*> args_type;
113
114 args_type.push_back(irb_.getJObjectTy()); // method object pointer
115
116 if (!is_static) {
117 args_type.push_back(irb_.getJType('L', kAccurate)); // "this" object pointer
118 }
119
120 for (int32_t i = 1; i < shorty_size; ++i) {
121 args_type.push_back(irb_.getJType(shorty[i], kAccurate));
122 }
123
124 return llvm::FunctionType::get(ret_type, args_type, false);
125}
126
127
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800128void MethodCompiler::EmitPrologue() {
Logan Chienc670a8d2011-12-20 21:25:56 +0800129 // Create basic blocks for prologue
130 basic_block_reg_alloca_ =
131 llvm::BasicBlock::Create(*context_, "prologue.alloca", func_);
132
133 basic_block_reg_zero_init_ =
134 llvm::BasicBlock::Create(*context_, "prologue.zeroinit", func_);
135
136 // Create register array
137 for (uint16_t r = 0; r < code_item_->registers_size_; ++r) {
138 regs_.push_back(DalvikReg::CreateLocalVarReg(*this, r));
139 }
140
141 retval_reg_.reset(DalvikReg::CreateRetValReg(*this));
142}
143
144
145void MethodCompiler::EmitPrologueLastBranch() {
146 irb_.SetInsertPoint(basic_block_reg_alloca_);
147 irb_.CreateBr(basic_block_reg_zero_init_);
148
149 irb_.SetInsertPoint(basic_block_reg_zero_init_);
150 irb_.CreateBr(GetBasicBlock(0));
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800151}
152
153
Logan Chien83426162011-12-09 09:29:50 +0800154void MethodCompiler::EmitInstructions() {
Logan Chiend6c239a2011-12-23 15:11:45 +0800155 uint32_t dex_pc = 0;
156 while (dex_pc < code_item_->insns_size_in_code_units_) {
157 Instruction const* insn = Instruction::At(code_item_->insns_ + dex_pc);
158 EmitInstruction(dex_pc, insn);
159 dex_pc += insn->SizeInCodeUnits();
160 }
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800161}
162
163
Logan Chien83426162011-12-09 09:29:50 +0800164void MethodCompiler::EmitInstruction(uint32_t dex_pc,
165 Instruction const* insn) {
Logan Chiend6c239a2011-12-23 15:11:45 +0800166
167 // Set the IRBuilder insertion point
168 irb_.SetInsertPoint(GetBasicBlock(dex_pc));
169
Logan Chien83426162011-12-09 09:29:50 +0800170 // UNIMPLEMENTED(WARNING);
Logan Chiend6c239a2011-12-23 15:11:45 +0800171 irb_.CreateUnreachable();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800172}
173
174
Logan Chien83426162011-12-09 09:29:50 +0800175CompiledMethod *MethodCompiler::Compile() {
Logan Chien0b827102011-12-20 19:46:14 +0800176 // Code generation
177 CreateFunction();
178
179 EmitPrologue();
180 EmitInstructions();
Logan Chienc670a8d2011-12-20 21:25:56 +0800181 EmitPrologueLastBranch();
Logan Chien0b827102011-12-20 19:46:14 +0800182
Logan Chiend6c239a2011-12-23 15:11:45 +0800183 // Verify the generated bitcode
184 llvm::verifyFunction(*func_, llvm::PrintMessageAction);
185
Logan Chien0b827102011-12-20 19:46:14 +0800186 // Delete the inferred register category map (won't be used anymore)
187 method_->ResetInferredRegCategoryMap();
188
189 return new CompiledMethod(insn_set_, func_);
190}
191
192
193llvm::Value* MethodCompiler::EmitLoadMethodObjectAddr() {
194 return func_->arg_begin();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800195}
Logan Chien83426162011-12-09 09:29:50 +0800196
197
Logan Chiend6c239a2011-12-23 15:11:45 +0800198llvm::BasicBlock* MethodCompiler::
199CreateBasicBlockWithDexPC(uint32_t dex_pc, char const* postfix) {
200 std::string name;
201
202 if (postfix) {
203 StringAppendF(&name, "B%u.%s", dex_pc, postfix);
204 } else {
205 StringAppendF(&name, "B%u", dex_pc);
206 }
207
208 return llvm::BasicBlock::Create(*context_, name, func_);
209}
210
211
212llvm::BasicBlock* MethodCompiler::GetBasicBlock(uint32_t dex_pc) {
213 DCHECK(dex_pc < code_item_->insns_size_in_code_units_);
214
215 llvm::BasicBlock* basic_block = basic_blocks_[dex_pc];
216
217 if (!basic_block) {
218 basic_block = CreateBasicBlockWithDexPC(dex_pc);
219 basic_blocks_[dex_pc] = basic_block;
220 }
221
222 return basic_block;
223}
224
225
226llvm::BasicBlock*
227MethodCompiler::GetNextBasicBlock(uint32_t dex_pc) {
228 Instruction const* insn = Instruction::At(code_item_->insns_ + dex_pc);
229 return GetBasicBlock(dex_pc + insn->SizeInCodeUnits());
230}
231
232
Logan Chienc670a8d2011-12-20 21:25:56 +0800233llvm::Value* MethodCompiler::AllocDalvikLocalVarReg(RegCategory cat,
234 uint32_t reg_idx) {
235
236 // Save current IR builder insert point
237 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
238
239 // Alloca
240 llvm::Value* reg_addr = NULL;
241
242 switch (cat) {
243 case kRegCat1nr:
244 irb_.SetInsertPoint(basic_block_reg_alloca_);
245 reg_addr = irb_.CreateAlloca(irb_.getJIntTy(), 0,
246 StringPrintf("r%u", reg_idx));
247
248 irb_.SetInsertPoint(basic_block_reg_zero_init_);
249 irb_.CreateStore(irb_.getJInt(0), reg_addr);
250 break;
251
252 case kRegCat2:
253 irb_.SetInsertPoint(basic_block_reg_alloca_);
254 reg_addr = irb_.CreateAlloca(irb_.getJLongTy(), 0,
255 StringPrintf("w%u", reg_idx));
256
257 irb_.SetInsertPoint(basic_block_reg_zero_init_);
258 irb_.CreateStore(irb_.getJLong(0), reg_addr);
259 break;
260
261 case kRegObject:
262 irb_.SetInsertPoint(basic_block_reg_alloca_);
263 reg_addr = irb_.CreateAlloca(irb_.getJObjectTy(), 0,
264 StringPrintf("p%u", reg_idx));
265
266 irb_.SetInsertPoint(basic_block_reg_zero_init_);
267 irb_.CreateStore(irb_.getJNull(), reg_addr);
268 break;
269
270 default:
271 LOG(FATAL) << "Unknown register category for allocation: " << cat;
272 }
273
274 // Restore IRBuilder insert point
275 irb_.restoreIP(irb_ip_original);
276
277 DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
278 return reg_addr;
279}
280
281
282llvm::Value* MethodCompiler::AllocDalvikRetValReg(RegCategory cat) {
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, "r_res");
293 break;
294
295 case kRegCat2:
296 irb_.SetInsertPoint(basic_block_reg_alloca_);
297 reg_addr = irb_.CreateAlloca(irb_.getJLongTy(), 0, "w_res");
298 break;
299
300 case kRegObject:
301 irb_.SetInsertPoint(basic_block_reg_alloca_);
302 reg_addr = irb_.CreateAlloca(irb_.getJObjectTy(), 0, "p_res");
303 break;
304
305 default:
306 LOG(FATAL) << "Unknown register category for allocation: " << cat;
307 }
308
309 // Restore IRBuilder insert point
310 irb_.restoreIP(irb_ip_original);
311
312 DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
313 return reg_addr;
314}
315
316
Logan Chien83426162011-12-09 09:29:50 +0800317} // namespace compiler_llvm
318} // namespace art