blob: 379fcb0b68f8eddb1b64eb0e941e5258fd42ef64 [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
32 virtual ~DalvikLocalVarReg();
33
34 private:
35 virtual llvm::Value* GetRawAddr(JType jty, JTypeSpace space);
36
37 private:
38 uint32_t reg_idx_;
39 llvm::Value* reg_32_;
40 llvm::Value* reg_64_;
41 llvm::Value* reg_obj_;
42 };
43
44 class DalvikRetValReg : public DalvikReg {
45 public:
46 DalvikRetValReg(MethodCompiler& method_compiler);
47
48 virtual ~DalvikRetValReg();
49
50 private:
51 virtual llvm::Value* GetRawAddr(JType jty, JTypeSpace space);
52
53 private:
54 llvm::Value* reg_32_;
55 llvm::Value* reg_64_;
56 llvm::Value* reg_obj_;
57 };
58
59} // anonymous namespace
60
61
62//----------------------------------------------------------------------------
63// Dalvik Register
64//----------------------------------------------------------------------------
65
66DalvikReg* DalvikReg::CreateLocalVarReg(MethodCompiler& method_compiler,
67 uint32_t reg_idx) {
68 return new DalvikLocalVarReg(method_compiler, reg_idx);
69}
70
71
72DalvikReg* DalvikReg::CreateRetValReg(MethodCompiler& method_compiler) {
73 return new DalvikRetValReg(method_compiler);
74}
75
76
77DalvikReg::DalvikReg(MethodCompiler& method_compiler)
78: method_compiler_(&method_compiler), irb_(method_compiler.GetIRBuilder()) {
79}
80
81
82DalvikReg::~DalvikReg() {
83}
84
85
86inline llvm::Value* DalvikReg::RegCat1SExt(llvm::Value* value) {
87 return irb_.CreateSExt(value, irb_.getJIntTy());
88}
89
90
91inline llvm::Value* DalvikReg::RegCat1ZExt(llvm::Value* value) {
92 return irb_.CreateZExt(value, irb_.getJIntTy());
93}
94
95
96inline llvm::Value* DalvikReg::RegCat1Trunc(llvm::Value* value,
97 llvm::Type* ty) {
98 return irb_.CreateTrunc(value, ty);
99}
100
101
102llvm::Value* DalvikReg::GetValue(JType jty, JTypeSpace space) {
103 DCHECK_NE(jty, kVoid) << "Dalvik register will never be void type";
104
105 switch (space) {
106 case kReg:
107 case kField:
108 return irb_.CreateLoad(GetAddr(jty, space));
109
110 case kAccurate:
111 case kArray:
112 switch (jty) {
113 case kVoid:
114 LOG(FATAL) << "Dalvik register with void type has no value";
115 return NULL;
116
117 case kBoolean:
118 case kChar:
119 case kByte:
120 case kShort:
121 // NOTE: In array type space, boolean is truncated from i32 to i8, while
122 // in accurate type space, boolean is truncated from i32 to i1.
123 // For the other cases, array type space is equal to accurate type space.
124 return RegCat1Trunc(irb_.CreateLoad(GetAddr(jty, space)),
125 irb_.getJType(jty, space));
126
127 case kInt:
128 case kLong:
129 case kFloat:
130 case kDouble:
131 case kObject:
132 return irb_.CreateLoad(GetAddr(jty, space));
133 }
134 }
135
136 LOG(FATAL) << "Couldn't GetValue of JType " << jty;
137 return NULL;
138}
139
140
141void DalvikReg::SetValue(JType jty, JTypeSpace space, llvm::Value* value) {
142 DCHECK_NE(jty, kVoid) << "Dalvik register will never be void type";
143
144 switch (space) {
145 case kReg:
146 case kField:
147 irb_.CreateStore(value, GetAddr(jty, space));
148 return;
149
150 case kAccurate:
151 case kArray:
152 switch (jty) {
153 case kVoid:
154 break;
155
156 case kBoolean:
157 case kChar:
158 // NOTE: In accurate type space, we have to zero extend boolean from
159 // i1 to i32, and char from i16 to i32. In array type space, we have
160 // to zero extend boolean from i8 to i32, and char from i16 to i32.
161 irb_.CreateStore(RegCat1ZExt(value), GetAddr(jty, space));
162 break;
163
164 case kByte:
165 case kShort:
166 // NOTE: In accurate type space, we have to signed extend byte from
167 // i8 to i32, and short from i16 to i32. In array type space, we have
168 // to sign extend byte from i8 to i32, and short from i16 to i32.
169 irb_.CreateStore(RegCat1SExt(value), GetAddr(jty, space));
170 break;
171
172 case kInt:
173 case kLong:
174 case kFloat:
175 case kDouble:
176 case kObject:
177 irb_.CreateStore(value, GetAddr(jty, space));
178 break;
179 }
180 }
181}
182
183
184llvm::Value* DalvikReg::GetAddr(JType jty, JTypeSpace space) {
185 if (jty == kFloat) {
186 return irb_.CreateBitCast(GetRawAddr(jty, space),
187 irb_.getJFloatTy()->getPointerTo());
188 } else if (jty == kDouble) {
189 return irb_.CreateBitCast(GetRawAddr(jty, space),
190 irb_.getJDoubleTy()->getPointerTo());
191 } else {
192 return GetRawAddr(jty, space);
193 }
194}
195
196
197//----------------------------------------------------------------------------
198// Dalvik Local Variable Register
199//----------------------------------------------------------------------------
200
201DalvikLocalVarReg::DalvikLocalVarReg(MethodCompiler& method_compiler,
202 uint32_t reg_idx)
203: DalvikReg(method_compiler), reg_idx_(reg_idx),
204 reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL) {
205}
206
207
208DalvikLocalVarReg::~DalvikLocalVarReg() {
209}
210
211
212llvm::Value* DalvikLocalVarReg::GetRawAddr(JType jty, JTypeSpace space) {
213 switch (GetRegCategoryFromJType(jty)) {
214 case kRegCat1nr:
215 if (reg_32_ == NULL) {
216 reg_32_ = method_compiler_->AllocDalvikLocalVarReg(kRegCat1nr, reg_idx_);
217 }
218 return reg_32_;
219
220 case kRegCat2:
221 if (reg_64_ == NULL) {
222 reg_64_ = method_compiler_->AllocDalvikLocalVarReg(kRegCat2, reg_idx_);
223 }
224 return reg_64_;
225
226 case kRegObject:
227 if (reg_obj_ == NULL) {
228 reg_obj_ = method_compiler_->AllocDalvikLocalVarReg(kRegObject, reg_idx_);
229 }
230 return reg_obj_;
231
232 default:
233 LOG(FATAL) << "Unexpected register category: "
234 << GetRegCategoryFromJType(jty);
235 return NULL;
236 }
237}
238
239
240//----------------------------------------------------------------------------
241// Dalvik Returned Value Temporary Register
242//----------------------------------------------------------------------------
243
244DalvikRetValReg::DalvikRetValReg(MethodCompiler& method_compiler)
245: DalvikReg(method_compiler), reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL) {
246}
247
248
249DalvikRetValReg::~DalvikRetValReg() {
250}
251
252
253llvm::Value* DalvikRetValReg::GetRawAddr(JType jty, JTypeSpace space) {
254 switch (GetRegCategoryFromJType(jty)) {
255 case kRegCat1nr:
256 if (reg_32_ == NULL) {
257 reg_32_ = method_compiler_->AllocDalvikRetValReg(kRegCat1nr);
258 }
259 return reg_32_;
260
261 case kRegCat2:
262 if (reg_64_ == NULL) {
263 reg_64_ = method_compiler_->AllocDalvikRetValReg(kRegCat2);
264 }
265 return reg_64_;
266
267 case kRegObject:
268 if (reg_obj_ == NULL) {
269 reg_obj_ = method_compiler_->AllocDalvikRetValReg(kRegObject);
270 }
271 return reg_obj_;
272
273 default:
274 LOG(FATAL) << "Unexpected register category: "
275 << GetRegCategoryFromJType(jty);
276 return NULL;
277 }
278}