blob: 6f7e908831a28acde169735be86c352b9c2e9b1e [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);
TDYa127706e7db2012-05-06 00:05:33 -0700160
161 default:
162 LOG(FATAL) << "Unknown java type: " << jty;
163 return NULL;
Logan Chienc670a8d2011-12-20 21:25:56 +0800164 }
165 }
166
167 LOG(FATAL) << "Couldn't GetValue of JType " << jty;
168 return NULL;
169}
170
171
172void DalvikReg::SetValue(JType jty, JTypeSpace space, llvm::Value* value) {
173 DCHECK_NE(jty, kVoid) << "Dalvik register will never be void type";
174
175 switch (space) {
176 case kReg:
177 case kField:
TDYa127aba61122012-05-04 18:28:36 -0700178 irb_.CreateStore(value, GetAddr(jty, space), kTBAARegister);
Logan Chienc670a8d2011-12-20 21:25:56 +0800179 return;
180
181 case kAccurate:
182 case kArray:
183 switch (jty) {
184 case kVoid:
185 break;
186
187 case kBoolean:
188 case kChar:
189 // NOTE: In accurate type space, we have to zero extend boolean from
190 // i1 to i32, and char from i16 to i32. In array type space, we have
191 // to zero extend boolean from i8 to i32, and char from i16 to i32.
TDYa127aba61122012-05-04 18:28:36 -0700192 irb_.CreateStore(RegCat1ZExt(value), GetAddr(jty, space), kTBAARegister);
Logan Chienc670a8d2011-12-20 21:25:56 +0800193 break;
194
195 case kByte:
196 case kShort:
197 // NOTE: In accurate type space, we have to signed extend byte from
198 // i8 to i32, and short from i16 to i32. In array type space, we have
199 // to sign extend byte from i8 to i32, and short from i16 to i32.
TDYa127aba61122012-05-04 18:28:36 -0700200 irb_.CreateStore(RegCat1SExt(value), GetAddr(jty, space), kTBAARegister);
Logan Chienc670a8d2011-12-20 21:25:56 +0800201 break;
202
203 case kInt:
204 case kLong:
205 case kFloat:
206 case kDouble:
207 case kObject:
TDYa127aba61122012-05-04 18:28:36 -0700208 irb_.CreateStore(value, GetAddr(jty, space), kTBAARegister);
Logan Chienc670a8d2011-12-20 21:25:56 +0800209 break;
TDYa127706e7db2012-05-06 00:05:33 -0700210
211 default:
212 LOG(FATAL) << "Unknown java type: " << jty;
Logan Chienc670a8d2011-12-20 21:25:56 +0800213 }
214 }
215}
216
217
218llvm::Value* DalvikReg::GetAddr(JType jty, JTypeSpace space) {
219 if (jty == kFloat) {
220 return irb_.CreateBitCast(GetRawAddr(jty, space),
221 irb_.getJFloatTy()->getPointerTo());
222 } else if (jty == kDouble) {
223 return irb_.CreateBitCast(GetRawAddr(jty, space),
224 irb_.getJDoubleTy()->getPointerTo());
225 } else {
226 return GetRawAddr(jty, space);
227 }
228}
229
230
231//----------------------------------------------------------------------------
232// Dalvik Local Variable Register
233//----------------------------------------------------------------------------
234
235DalvikLocalVarReg::DalvikLocalVarReg(MethodCompiler& method_compiler,
236 uint32_t reg_idx)
237: DalvikReg(method_compiler), reg_idx_(reg_idx),
TDYa1277f5b9be2012-04-29 01:31:49 -0700238 reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL), reg_shadow_frame_(NULL) {
Logan Chienc670a8d2011-12-20 21:25:56 +0800239}
240
241
242DalvikLocalVarReg::~DalvikLocalVarReg() {
243}
244
245
TDYa1277f5b9be2012-04-29 01:31:49 -0700246void DalvikLocalVarReg::SetValue(JType jty, JTypeSpace space, llvm::Value* value) {
247 DalvikReg::SetValue(jty, space, value);
248
249 if (jty == kObject) {
250 DCHECK_NE(reg_shadow_frame_, static_cast<llvm::Value*>(NULL))
251 << "Didn't allocate shadow frame entry.";
TDYa127aba61122012-05-04 18:28:36 -0700252 irb_.CreateStore(value, reg_shadow_frame_, kTBAARuntimeInfo);
TDYa1277f5b9be2012-04-29 01:31:49 -0700253 }
254}
255
256
Logan Chienc670a8d2011-12-20 21:25:56 +0800257llvm::Value* DalvikLocalVarReg::GetRawAddr(JType jty, JTypeSpace space) {
258 switch (GetRegCategoryFromJType(jty)) {
259 case kRegCat1nr:
260 if (reg_32_ == NULL) {
261 reg_32_ = method_compiler_->AllocDalvikLocalVarReg(kRegCat1nr, reg_idx_);
262 }
263 return reg_32_;
264
265 case kRegCat2:
266 if (reg_64_ == NULL) {
267 reg_64_ = method_compiler_->AllocDalvikLocalVarReg(kRegCat2, reg_idx_);
268 }
269 return reg_64_;
270
271 case kRegObject:
272 if (reg_obj_ == NULL) {
273 reg_obj_ = method_compiler_->AllocDalvikLocalVarReg(kRegObject, reg_idx_);
TDYa1277f5b9be2012-04-29 01:31:49 -0700274 reg_shadow_frame_ = method_compiler_->AllocShadowFrameEntry(reg_idx_);
Logan Chienc670a8d2011-12-20 21:25:56 +0800275 }
276 return reg_obj_;
277
278 default:
279 LOG(FATAL) << "Unexpected register category: "
280 << GetRegCategoryFromJType(jty);
281 return NULL;
282 }
283}
284
285
286//----------------------------------------------------------------------------
287// Dalvik Returned Value Temporary Register
288//----------------------------------------------------------------------------
289
290DalvikRetValReg::DalvikRetValReg(MethodCompiler& method_compiler)
291: DalvikReg(method_compiler), reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL) {
292}
293
294
295DalvikRetValReg::~DalvikRetValReg() {
296}
297
298
299llvm::Value* DalvikRetValReg::GetRawAddr(JType jty, JTypeSpace space) {
300 switch (GetRegCategoryFromJType(jty)) {
301 case kRegCat1nr:
302 if (reg_32_ == NULL) {
303 reg_32_ = method_compiler_->AllocDalvikRetValReg(kRegCat1nr);
304 }
305 return reg_32_;
306
307 case kRegCat2:
308 if (reg_64_ == NULL) {
309 reg_64_ = method_compiler_->AllocDalvikRetValReg(kRegCat2);
310 }
311 return reg_64_;
312
313 case kRegObject:
314 if (reg_obj_ == NULL) {
315 reg_obj_ = method_compiler_->AllocDalvikRetValReg(kRegObject);
316 }
317 return reg_obj_;
318
319 default:
320 LOG(FATAL) << "Unexpected register category: "
321 << GetRegCategoryFromJType(jty);
322 return NULL;
323 }
324}