blob: 3d87a434cc70ec8855f4abbe3a19e38ed639d545 [file] [log] [blame]
Logan Chienc670a8d2011-12-20 21:25:56 +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 "dalvik_reg.h"
18
19#include "ir_builder.h"
20#include "method_compiler.h"
21
22using namespace art;
23using namespace art::compiler_llvm;
24
25
26namespace {
27
28 class DalvikLocalVarReg : public DalvikReg {
29 public:
30 DalvikLocalVarReg(MethodCompiler& method_compiler, uint32_t reg_idx);
31
TDYa1277f5b9be2012-04-29 01:31:49 -070032 virtual void SetValue(JType jty, JTypeSpace space, llvm::Value* value);
33
Logan Chienc670a8d2011-12-20 21:25:56 +080034 virtual ~DalvikLocalVarReg();
35
36 private:
37 virtual llvm::Value* GetRawAddr(JType jty, JTypeSpace space);
38
39 private:
40 uint32_t reg_idx_;
41 llvm::Value* reg_32_;
42 llvm::Value* reg_64_;
43 llvm::Value* reg_obj_;
TDYa1277f5b9be2012-04-29 01:31:49 -070044 llvm::Value* reg_shadow_frame_;
Logan Chienc670a8d2011-12-20 21:25:56 +080045 };
46
47 class DalvikRetValReg : public DalvikReg {
48 public:
49 DalvikRetValReg(MethodCompiler& method_compiler);
50
51 virtual ~DalvikRetValReg();
52
53 private:
54 virtual llvm::Value* GetRawAddr(JType jty, JTypeSpace space);
55
56 private:
57 llvm::Value* reg_32_;
58 llvm::Value* reg_64_;
59 llvm::Value* reg_obj_;
60 };
61
62} // anonymous namespace
63
64
65//----------------------------------------------------------------------------
66// Dalvik Register
67//----------------------------------------------------------------------------
68
69DalvikReg* DalvikReg::CreateLocalVarReg(MethodCompiler& method_compiler,
70 uint32_t reg_idx) {
71 return new DalvikLocalVarReg(method_compiler, reg_idx);
72}
73
74
75DalvikReg* DalvikReg::CreateRetValReg(MethodCompiler& method_compiler) {
76 return new DalvikRetValReg(method_compiler);
77}
78
79
80DalvikReg::DalvikReg(MethodCompiler& method_compiler)
81: method_compiler_(&method_compiler), irb_(method_compiler.GetIRBuilder()) {
82}
83
84
85DalvikReg::~DalvikReg() {
86}
87
88
TDYa12767ae8ff2012-05-02 19:08:02 -070089llvm::Type* DalvikReg::GetRegCategoryEquivSizeTy(IRBuilder& irb, RegCategory reg_cat) {
90 switch (reg_cat) {
91 case kRegCat1nr: return irb.getJIntTy();
92 case kRegCat2: return irb.getJLongTy();
93 case kRegObject: return irb.getJObjectTy();
94 default:
95 LOG(FATAL) << "Unknown register category: " << reg_cat;
96 return NULL;
97 }
98}
99
100
101char DalvikReg::GetRegCategoryNamePrefix(RegCategory reg_cat) {
102 switch (reg_cat) {
103 case kRegCat1nr: return 'r';
104 case kRegCat2: return 'w';
105 case kRegObject: return 'p';
106 default:
107 LOG(FATAL) << "Unknown register category: " << reg_cat;
108 return '\0';
109 }
110}
111
112
Logan Chienc670a8d2011-12-20 21:25:56 +0800113inline llvm::Value* DalvikReg::RegCat1SExt(llvm::Value* value) {
114 return irb_.CreateSExt(value, irb_.getJIntTy());
115}
116
117
118inline llvm::Value* DalvikReg::RegCat1ZExt(llvm::Value* value) {
119 return irb_.CreateZExt(value, irb_.getJIntTy());
120}
121
122
123inline llvm::Value* DalvikReg::RegCat1Trunc(llvm::Value* value,
124 llvm::Type* ty) {
125 return irb_.CreateTrunc(value, ty);
126}
127
128
129llvm::Value* DalvikReg::GetValue(JType jty, JTypeSpace space) {
130 DCHECK_NE(jty, kVoid) << "Dalvik register will never be void type";
131
132 switch (space) {
133 case kReg:
134 case kField:
TDYa127aba61122012-05-04 18:28:36 -0700135 return irb_.CreateLoad(GetAddr(jty, space), kTBAARegister);
Logan Chienc670a8d2011-12-20 21:25:56 +0800136
137 case kAccurate:
138 case kArray:
139 switch (jty) {
140 case kVoid:
141 LOG(FATAL) << "Dalvik register with void type has no value";
142 return NULL;
143
144 case kBoolean:
145 case kChar:
146 case kByte:
147 case kShort:
148 // NOTE: In array type space, boolean is truncated from i32 to i8, while
149 // in accurate type space, boolean is truncated from i32 to i1.
150 // For the other cases, array type space is equal to accurate type space.
TDYa127aba61122012-05-04 18:28:36 -0700151 return RegCat1Trunc(irb_.CreateLoad(GetAddr(jty, space), kTBAARegister),
Logan Chienc670a8d2011-12-20 21:25:56 +0800152 irb_.getJType(jty, space));
153
154 case kInt:
155 case kLong:
156 case kFloat:
157 case kDouble:
158 case kObject:
TDYa127aba61122012-05-04 18:28:36 -0700159 return irb_.CreateLoad(GetAddr(jty, space), kTBAARegister);
Logan Chienc670a8d2011-12-20 21:25:56 +0800160 }
161 }
162
163 LOG(FATAL) << "Couldn't GetValue of JType " << jty;
164 return NULL;
165}
166
167
168void DalvikReg::SetValue(JType jty, JTypeSpace space, llvm::Value* value) {
169 DCHECK_NE(jty, kVoid) << "Dalvik register will never be void type";
170
171 switch (space) {
172 case kReg:
173 case kField:
TDYa127aba61122012-05-04 18:28:36 -0700174 irb_.CreateStore(value, GetAddr(jty, space), kTBAARegister);
Logan Chienc670a8d2011-12-20 21:25:56 +0800175 return;
176
177 case kAccurate:
178 case kArray:
179 switch (jty) {
180 case kVoid:
181 break;
182
183 case kBoolean:
184 case kChar:
185 // NOTE: In accurate type space, we have to zero extend boolean from
186 // i1 to i32, and char from i16 to i32. In array type space, we have
187 // to zero extend boolean from i8 to i32, and char from i16 to i32.
TDYa127aba61122012-05-04 18:28:36 -0700188 irb_.CreateStore(RegCat1ZExt(value), GetAddr(jty, space), kTBAARegister);
Logan Chienc670a8d2011-12-20 21:25:56 +0800189 break;
190
191 case kByte:
192 case kShort:
193 // NOTE: In accurate type space, we have to signed extend byte from
194 // i8 to i32, and short from i16 to i32. In array type space, we have
195 // to sign extend byte from i8 to i32, and short from i16 to i32.
TDYa127aba61122012-05-04 18:28:36 -0700196 irb_.CreateStore(RegCat1SExt(value), GetAddr(jty, space), kTBAARegister);
Logan Chienc670a8d2011-12-20 21:25:56 +0800197 break;
198
199 case kInt:
200 case kLong:
201 case kFloat:
202 case kDouble:
203 case kObject:
TDYa127aba61122012-05-04 18:28:36 -0700204 irb_.CreateStore(value, GetAddr(jty, space), kTBAARegister);
Logan Chienc670a8d2011-12-20 21:25:56 +0800205 break;
206 }
207 }
208}
209
210
211llvm::Value* DalvikReg::GetAddr(JType jty, JTypeSpace space) {
212 if (jty == kFloat) {
213 return irb_.CreateBitCast(GetRawAddr(jty, space),
214 irb_.getJFloatTy()->getPointerTo());
215 } else if (jty == kDouble) {
216 return irb_.CreateBitCast(GetRawAddr(jty, space),
217 irb_.getJDoubleTy()->getPointerTo());
218 } else {
219 return GetRawAddr(jty, space);
220 }
221}
222
223
224//----------------------------------------------------------------------------
225// Dalvik Local Variable Register
226//----------------------------------------------------------------------------
227
228DalvikLocalVarReg::DalvikLocalVarReg(MethodCompiler& method_compiler,
229 uint32_t reg_idx)
230: DalvikReg(method_compiler), reg_idx_(reg_idx),
TDYa1277f5b9be2012-04-29 01:31:49 -0700231 reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL), reg_shadow_frame_(NULL) {
Logan Chienc670a8d2011-12-20 21:25:56 +0800232}
233
234
235DalvikLocalVarReg::~DalvikLocalVarReg() {
236}
237
238
TDYa1277f5b9be2012-04-29 01:31:49 -0700239void DalvikLocalVarReg::SetValue(JType jty, JTypeSpace space, llvm::Value* value) {
240 DalvikReg::SetValue(jty, space, value);
241
242 if (jty == kObject) {
243 DCHECK_NE(reg_shadow_frame_, static_cast<llvm::Value*>(NULL))
244 << "Didn't allocate shadow frame entry.";
TDYa127aba61122012-05-04 18:28:36 -0700245 irb_.CreateStore(value, reg_shadow_frame_, kTBAARuntimeInfo);
TDYa1277f5b9be2012-04-29 01:31:49 -0700246 }
247}
248
249
Logan Chienc670a8d2011-12-20 21:25:56 +0800250llvm::Value* DalvikLocalVarReg::GetRawAddr(JType jty, JTypeSpace space) {
251 switch (GetRegCategoryFromJType(jty)) {
252 case kRegCat1nr:
253 if (reg_32_ == NULL) {
254 reg_32_ = method_compiler_->AllocDalvikLocalVarReg(kRegCat1nr, reg_idx_);
255 }
256 return reg_32_;
257
258 case kRegCat2:
259 if (reg_64_ == NULL) {
260 reg_64_ = method_compiler_->AllocDalvikLocalVarReg(kRegCat2, reg_idx_);
261 }
262 return reg_64_;
263
264 case kRegObject:
265 if (reg_obj_ == NULL) {
266 reg_obj_ = method_compiler_->AllocDalvikLocalVarReg(kRegObject, reg_idx_);
TDYa1277f5b9be2012-04-29 01:31:49 -0700267 reg_shadow_frame_ = method_compiler_->AllocShadowFrameEntry(reg_idx_);
Logan Chienc670a8d2011-12-20 21:25:56 +0800268 }
269 return reg_obj_;
270
271 default:
272 LOG(FATAL) << "Unexpected register category: "
273 << GetRegCategoryFromJType(jty);
274 return NULL;
275 }
276}
277
278
279//----------------------------------------------------------------------------
280// Dalvik Returned Value Temporary Register
281//----------------------------------------------------------------------------
282
283DalvikRetValReg::DalvikRetValReg(MethodCompiler& method_compiler)
284: DalvikReg(method_compiler), reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL) {
285}
286
287
288DalvikRetValReg::~DalvikRetValReg() {
289}
290
291
292llvm::Value* DalvikRetValReg::GetRawAddr(JType jty, JTypeSpace space) {
293 switch (GetRegCategoryFromJType(jty)) {
294 case kRegCat1nr:
295 if (reg_32_ == NULL) {
296 reg_32_ = method_compiler_->AllocDalvikRetValReg(kRegCat1nr);
297 }
298 return reg_32_;
299
300 case kRegCat2:
301 if (reg_64_ == NULL) {
302 reg_64_ = method_compiler_->AllocDalvikRetValReg(kRegCat2);
303 }
304 return reg_64_;
305
306 case kRegObject:
307 if (reg_obj_ == NULL) {
308 reg_obj_ = method_compiler_->AllocDalvikRetValReg(kRegObject);
309 }
310 return reg_obj_;
311
312 default:
313 LOG(FATAL) << "Unexpected register category: "
314 << GetRegCategoryFromJType(jty);
315 return NULL;
316 }
317}