blob: 8833a5ccff6e7f576d110d868ae554fcd238df2b [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#ifndef ART_SRC_COMPILER_LLVM_METHOD_COMPILER_H_
18#define ART_SRC_COMPILER_LLVM_METHOD_COMPILER_H_
19
Logan Chienfca7e872011-12-20 20:08:22 +080020#include "backend_types.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080021#include "constants.h"
Logan Chienc670a8d2011-12-20 21:25:56 +080022#include "dalvik_reg.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080023#include "dex_file.h"
24#include "dex_instruction.h"
25#include "object_utils.h"
26
27#include <llvm/Support/IRBuilder.h>
28
29#include <vector>
30
31#include <stdint.h>
32
33
34namespace art {
35 class ClassLinker;
36 class ClassLoader;
37 class CompiledMethod;
38 class Compiler;
39 class DexCache;
40}
41
42
43namespace llvm {
44 class AllocaInst;
45 class BasicBlock;
46 class Function;
47 class FunctionType;
48 class LLVMContext;
49 class Module;
50 class Type;
51}
52
53
54namespace art {
55namespace compiler_llvm {
56
57class CompilerLLVM;
58class IRBuilder;
59
60class MethodCompiler {
61 private:
Logan Chien83426162011-12-09 09:29:50 +080062 InstructionSet insn_set_;
63 Compiler* compiler_;
64 compiler_llvm::CompilerLLVM* compiler_llvm_;
Shih-wei Liaod1fec812012-02-13 09:51:10 -080065
Logan Chien83426162011-12-09 09:29:50 +080066 ClassLinker* class_linker_;
67 ClassLoader const* class_loader_;
Shih-wei Liaod1fec812012-02-13 09:51:10 -080068
Logan Chien83426162011-12-09 09:29:50 +080069 DexFile const* dex_file_;
70 DexCache* dex_cache_;
71 DexFile::CodeItem const* code_item_;
Shih-wei Liaod1fec812012-02-13 09:51:10 -080072
Logan Chien83426162011-12-09 09:29:50 +080073 Method* method_;
74 MethodHelper method_helper_;
Shih-wei Liaod1fec812012-02-13 09:51:10 -080075
76 uint32_t method_idx_;
77 uint32_t access_flags_;
78
79 llvm::Module* module_;
80 llvm::LLVMContext* context_;
81 IRBuilder& irb_;
82 llvm::Function* func_;
83
Logan Chienc670a8d2011-12-20 21:25:56 +080084 std::vector<DalvikReg*> regs_;
85 UniquePtr<DalvikReg> retval_reg_;
Logan Chiend6c239a2011-12-23 15:11:45 +080086
Logan Chienc670a8d2011-12-20 21:25:56 +080087 llvm::BasicBlock* basic_block_reg_alloca_;
88 llvm::BasicBlock* basic_block_reg_zero_init_;
Logan Chiend6ececa2011-12-27 16:20:15 +080089 llvm::BasicBlock* basic_block_reg_arg_init_;
Logan Chiend6c239a2011-12-23 15:11:45 +080090 std::vector<llvm::BasicBlock*> basic_blocks_;
91
Logan Chien5bcc04e2012-01-30 14:15:12 +080092 std::vector<llvm::BasicBlock*> basic_block_landing_pads_;
93 llvm::BasicBlock* basic_block_unwind_;
94 llvm::BasicBlock* basic_block_unreachable_;
95
Logan Chiend6c239a2011-12-23 15:11:45 +080096
Shih-wei Liaod1fec812012-02-13 09:51:10 -080097 public:
Logan Chien83426162011-12-09 09:29:50 +080098 MethodCompiler(InstructionSet insn_set,
99 Compiler* compiler,
100 ClassLinker* class_linker,
101 ClassLoader const* class_loader,
102 DexFile const* dex_file,
103 DexCache* dex_cache,
104 DexFile::CodeItem const* code_item,
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800105 uint32_t method_idx,
106 uint32_t access_flags);
107
108 ~MethodCompiler();
109
Logan Chien83426162011-12-09 09:29:50 +0800110 CompiledMethod* Compile();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800111
Logan Chienc670a8d2011-12-20 21:25:56 +0800112
113 // Code generation helper function
114
115 IRBuilder& GetIRBuilder() const {
116 return irb_;
117 }
118
119
120 // Register helper function
121
122 llvm::Value* AllocDalvikLocalVarReg(RegCategory cat, uint32_t reg_idx);
123
124 llvm::Value* AllocDalvikRetValReg(RegCategory cat);
125
126
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800127 private:
128 void CreateFunction();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800129 void EmitPrologue();
Logan Chienc670a8d2011-12-20 21:25:56 +0800130 void EmitPrologueLastBranch();
Logan Chiend6ececa2011-12-27 16:20:15 +0800131 void EmitPrologueAssignArgRegister();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800132 void EmitInstructions();
Logan Chien83426162011-12-09 09:29:50 +0800133 void EmitInstruction(uint32_t dex_pc, Instruction const* insn);
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800134
Logan Chien70f94b42011-12-27 17:49:11 +0800135 enum CondBranchKind {
136 kCondBranch_EQ,
137 kCondBranch_NE,
138 kCondBranch_LT,
139 kCondBranch_GE,
140 kCondBranch_GT,
141 kCondBranch_LE,
142 };
143
144 enum IntArithmKind {
145 kIntArithm_Add,
146 kIntArithm_Sub,
147 kIntArithm_Mul,
148 kIntArithm_Div,
149 kIntArithm_Rem,
150 kIntArithm_And,
151 kIntArithm_Or,
152 kIntArithm_Xor,
153 kIntArithm_Shl,
154 kIntArithm_Shr,
155 kIntArithm_UShr,
156 };
157
158 enum FPArithmKind {
159 kFPArithm_Add,
160 kFPArithm_Sub,
161 kFPArithm_Mul,
162 kFPArithm_Div,
163 kFPArithm_Rem,
164 };
165
166#define GEN_INSN_ARGS uint32_t dex_pc, Instruction const* insn
167
168 // NOP, PAYLOAD (unreachable) instructions
169 void EmitInsn_Nop(GEN_INSN_ARGS);
170
171 // MOVE, MOVE_RESULT instructions
172 void EmitInsn_Move(GEN_INSN_ARGS, JType jty);
173 void EmitInsn_MoveResult(GEN_INSN_ARGS, JType jty);
174
175 // MOVE_EXCEPTION, THROW instructions
176 void EmitInsn_MoveException(GEN_INSN_ARGS);
177 void EmitInsn_ThrowException(GEN_INSN_ARGS);
178
179 // RETURN instructions
180 void EmitInsn_ReturnVoid(GEN_INSN_ARGS);
181 void EmitInsn_Return(GEN_INSN_ARGS);
182
183 // CONST, CONST_CLASS, CONST_STRING instructions
184 void EmitInsn_LoadConstant(GEN_INSN_ARGS, JType imm_jty);
185 void EmitInsn_LoadConstantString(GEN_INSN_ARGS);
186 void EmitInsn_LoadConstantClass(GEN_INSN_ARGS);
187
188 // MONITOR_ENTER, MONITOR_EXIT instructions
189 void EmitInsn_MonitorEnter(GEN_INSN_ARGS);
190 void EmitInsn_MonitorExit(GEN_INSN_ARGS);
191
192 // CHECK_CAST, INSTANCE_OF instructions
193 void EmitInsn_CheckCast(GEN_INSN_ARGS);
194 void EmitInsn_InstanceOf(GEN_INSN_ARGS);
195
196 // NEW_INSTANCE instructions
197 void EmitInsn_NewInstance(GEN_INSN_ARGS);
198
199 // ARRAY_LEN, NEW_ARRAY, FILLED_NEW_ARRAY, FILL_ARRAY_DATA instructions
200 void EmitInsn_ArrayLength(GEN_INSN_ARGS);
201 void EmitInsn_NewArray(GEN_INSN_ARGS);
202 void EmitInsn_FilledNewArray(GEN_INSN_ARGS, bool is_range);
203 void EmitInsn_FillArrayData(GEN_INSN_ARGS);
204
205 // GOTO, IF_TEST, IF_TESTZ instructions
206 void EmitInsn_UnconditionalBranch(GEN_INSN_ARGS);
207 void EmitInsn_BinaryConditionalBranch(GEN_INSN_ARGS, CondBranchKind cond);
208 void EmitInsn_UnaryConditionalBranch(GEN_INSN_ARGS, CondBranchKind cond);
209
210 // PACKED_SWITCH, SPARSE_SWITCH instrutions
211 void EmitInsn_PackedSwitch(GEN_INSN_ARGS);
212 void EmitInsn_SparseSwitch(GEN_INSN_ARGS);
213
214 // CMPX_FLOAT, CMPX_DOUBLE, CMP_LONG instructions
215 void EmitInsn_FPCompare(GEN_INSN_ARGS, JType fp_jty, bool gt_bias);
216 void EmitInsn_LongCompare(GEN_INSN_ARGS);
217
218 // AGET, APUT instrutions
219 void EmitInsn_AGet(GEN_INSN_ARGS, JType elem_jty);
220 void EmitInsn_APut(GEN_INSN_ARGS, JType elem_jty);
221
222 // IGET, IPUT instructions
223 void EmitInsn_IGet(GEN_INSN_ARGS, JType field_jty);
224 void EmitInsn_IPut(GEN_INSN_ARGS, JType field_jty);
225
226 // SGET, SPUT instructions
227 void EmitInsn_SGet(GEN_INSN_ARGS, JType field_jty);
228 void EmitInsn_SPut(GEN_INSN_ARGS, JType field_jty);
229
230 // INVOKE instructions
231 void EmitInsn_InvokeVirtual(GEN_INSN_ARGS, bool is_range);
232 void EmitInsn_InvokeSuper(GEN_INSN_ARGS, bool is_range);
233 void EmitInsn_InvokeDirect(GEN_INSN_ARGS, bool is_range);
234 void EmitInsn_InvokeStatic(GEN_INSN_ARGS, bool is_range);
235 void EmitInsn_InvokeInterface(GEN_INSN_ARGS, bool is_range);
236
237 // Unary instructions
238 void EmitInsn_Neg(GEN_INSN_ARGS, JType op_jty);
239 void EmitInsn_Not(GEN_INSN_ARGS, JType op_jty);
240 void EmitInsn_SExt(GEN_INSN_ARGS);
241 void EmitInsn_Trunc(GEN_INSN_ARGS);
242 void EmitInsn_TruncAndSExt(GEN_INSN_ARGS, unsigned N);
243 void EmitInsn_TruncAndZExt(GEN_INSN_ARGS, unsigned N);
244
245 void EmitInsn_FNeg(GEN_INSN_ARGS, JType op_jty);
246 void EmitInsn_IntToFP(GEN_INSN_ARGS, JType src_jty, JType dest_jty);
247 void EmitInsn_FPToInt(GEN_INSN_ARGS, JType src_jty, JType dest_jty);
248 void EmitInsn_FExt(GEN_INSN_ARGS);
249 void EmitInsn_FTrunc(GEN_INSN_ARGS);
250
251 // Integer binary arithmetic instructions
252 void EmitInsn_IntArithm(GEN_INSN_ARGS, IntArithmKind arithm,
253 JType op_jty, bool is_2addr);
254
255 void EmitInsn_IntArithmImmediate(GEN_INSN_ARGS, IntArithmKind arithm);
256
257 void EmitInsn_RSubImmediate(GEN_INSN_ARGS);
258
259
260 // Floating-point binary arithmetic instructions
261 void EmitInsn_FPArithm(GEN_INSN_ARGS, FPArithmKind arithm,
262 JType op_jty, bool is_2addr);
263
264#undef GEN_INSN_ARGS
265
Logan Chien0b827102011-12-20 19:46:14 +0800266
267 // Code generation helper function
268
269 llvm::Value* EmitLoadMethodObjectAddr();
270
271 llvm::FunctionType* GetFunctionType(uint32_t method_idx, bool is_static);
272
Logan Chien5bcc04e2012-01-30 14:15:12 +0800273 void EmitGuard_ExceptionLandingPad(uint32_t dex_pc);
274
275 void EmitBranchExceptionLandingPad(uint32_t dex_pc);
276
Logan Chien70f94b42011-12-27 17:49:11 +0800277 void EmitGuard_GarbageCollectionSuspend(uint32_t dex_pc);
Logan Chien924072f2012-01-30 15:07:24 +0800278
Logan Chien2c37e8e2011-12-27 17:58:46 +0800279 llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
280 llvm::Value* cmp_lt);
281
Logan Chiena78e3c82011-12-27 17:59:35 +0800282 llvm::Value* EmitConditionResult(llvm::Value* lhs,
283 llvm::Value* rhs,
284 CondBranchKind cond);
285
286 RegCategory GetInferredRegCategory(uint32_t dex_pc, uint16_t reg);
287
Logan Chiend6c239a2011-12-23 15:11:45 +0800288
289 // Basic block helper functions
290 llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);
291
292 llvm::BasicBlock* GetNextBasicBlock(uint32_t dex_pc);
293
294 llvm::BasicBlock* CreateBasicBlockWithDexPC(uint32_t dex_pc,
295 char const* postfix = NULL);
296
Logan Chien5bcc04e2012-01-30 14:15:12 +0800297 int32_t GetTryItemOffset(uint32_t dex_pc);
298
299 llvm::BasicBlock* GetLandingPadBasicBlock(uint32_t dex_pc);
300
301 llvm::BasicBlock* GetUnwindBasicBlock();
302
Logan Chienc670a8d2011-12-20 21:25:56 +0800303
304 // Register helper function
305
306 llvm::Value* EmitLoadDalvikReg(uint32_t reg_idx, JType jty,
307 JTypeSpace space) {
308 return regs_[reg_idx]->GetValue(jty, space);
309 }
310
311 llvm::Value* EmitLoadDalvikReg(uint32_t reg_idx, char shorty,
312 JTypeSpace space) {
313 return EmitLoadDalvikReg(reg_idx, GetJTypeFromShorty(shorty), space);
314 }
315
316 void EmitStoreDalvikReg(uint32_t reg_idx, JType jty,
317 JTypeSpace space, llvm::Value* new_value) {
318 regs_[reg_idx]->SetValue(jty, space, new_value);
319 }
320
321 void EmitStoreDalvikReg(uint32_t reg_idx, char shorty,
322 JTypeSpace space, llvm::Value* new_value) {
323 EmitStoreDalvikReg(reg_idx, GetJTypeFromShorty(shorty), space, new_value);
324 }
325
326 llvm::Value* EmitLoadDalvikRetValReg(JType jty, JTypeSpace space) {
327 return retval_reg_->GetValue(jty, space);
328 }
329
330 llvm::Value* EmitLoadDalvikRetValReg(char shorty, JTypeSpace space) {
331 return EmitLoadDalvikRetValReg(GetJTypeFromShorty(shorty), space);
332 }
333
334 void EmitStoreDalvikRetValReg(JType jty, JTypeSpace space,
335 llvm::Value* new_value) {
336 retval_reg_->SetValue(jty, space, new_value);
337 }
338
339 void EmitStoreDalvikRetValReg(char shorty, JTypeSpace space,
340 llvm::Value* new_value) {
341 EmitStoreDalvikRetValReg(GetJTypeFromShorty(shorty), space, new_value);
342 }
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800343};
344
345
346} // namespace compiler_llvm
347} // namespace art
348
349#endif // ART_SRC_COMPILER_LLVM_METHOD_COMPILER_H_