blob: c3263ae95144a6acf35328c332b855ef2b87486e [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
Logan Chienc670a8d2011-12-20 21:25:56 +080026//----------------------------------------------------------------------------
27// Dalvik Register
28//----------------------------------------------------------------------------
29
TDYa127e2102142012-05-26 10:27:38 -070030DalvikReg::DalvikReg(MethodCompiler& method_compiler, const std::string& name)
31: method_compiler_(&method_compiler), irb_(method_compiler.GetIRBuilder()),
32 reg_name_(name), reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL) {
Logan Chienc670a8d2011-12-20 21:25:56 +080033}
34
35
36DalvikReg::~DalvikReg() {
37}
38
39
TDYa12767ae8ff2012-05-02 19:08:02 -070040llvm::Type* DalvikReg::GetRegCategoryEquivSizeTy(IRBuilder& irb, RegCategory reg_cat) {
41 switch (reg_cat) {
42 case kRegCat1nr: return irb.getJIntTy();
43 case kRegCat2: return irb.getJLongTy();
44 case kRegObject: return irb.getJObjectTy();
45 default:
46 LOG(FATAL) << "Unknown register category: " << reg_cat;
47 return NULL;
48 }
49}
50
51
52char DalvikReg::GetRegCategoryNamePrefix(RegCategory reg_cat) {
53 switch (reg_cat) {
54 case kRegCat1nr: return 'r';
55 case kRegCat2: return 'w';
56 case kRegObject: return 'p';
57 default:
58 LOG(FATAL) << "Unknown register category: " << reg_cat;
59 return '\0';
60 }
61}
62
63
Logan Chienc670a8d2011-12-20 21:25:56 +080064inline llvm::Value* DalvikReg::RegCat1SExt(llvm::Value* value) {
65 return irb_.CreateSExt(value, irb_.getJIntTy());
66}
67
68
69inline llvm::Value* DalvikReg::RegCat1ZExt(llvm::Value* value) {
70 return irb_.CreateZExt(value, irb_.getJIntTy());
71}
72
73
74inline llvm::Value* DalvikReg::RegCat1Trunc(llvm::Value* value,
75 llvm::Type* ty) {
76 return irb_.CreateTrunc(value, ty);
77}
78
79
80llvm::Value* DalvikReg::GetValue(JType jty, JTypeSpace space) {
81 DCHECK_NE(jty, kVoid) << "Dalvik register will never be void type";
82
TDYa127a964d412012-05-20 23:42:19 -070083 llvm::Value* value = NULL;
Logan Chienc670a8d2011-12-20 21:25:56 +080084 switch (space) {
85 case kReg:
86 case kField:
TDYa127e2102142012-05-26 10:27:38 -070087 value = irb_.CreateLoad(GetAddr(jty), kTBAARegister);
TDYa127a964d412012-05-20 23:42:19 -070088 break;
Logan Chienc670a8d2011-12-20 21:25:56 +080089
90 case kAccurate:
91 case kArray:
92 switch (jty) {
93 case kVoid:
94 LOG(FATAL) << "Dalvik register with void type has no value";
95 return NULL;
96
97 case kBoolean:
98 case kChar:
99 case kByte:
100 case kShort:
101 // NOTE: In array type space, boolean is truncated from i32 to i8, while
102 // in accurate type space, boolean is truncated from i32 to i1.
103 // For the other cases, array type space is equal to accurate type space.
TDYa127e2102142012-05-26 10:27:38 -0700104 value = RegCat1Trunc(irb_.CreateLoad(GetAddr(jty), kTBAARegister),
TDYa127a964d412012-05-20 23:42:19 -0700105 irb_.getJType(jty, space));
106 break;
Logan Chienc670a8d2011-12-20 21:25:56 +0800107
108 case kInt:
109 case kLong:
110 case kFloat:
111 case kDouble:
112 case kObject:
TDYa127e2102142012-05-26 10:27:38 -0700113 value = irb_.CreateLoad(GetAddr(jty), kTBAARegister);
TDYa127a964d412012-05-20 23:42:19 -0700114 break;
TDYa127706e7db2012-05-06 00:05:33 -0700115
116 default:
117 LOG(FATAL) << "Unknown java type: " << jty;
118 return NULL;
Logan Chienc670a8d2011-12-20 21:25:56 +0800119 }
TDYa127a964d412012-05-20 23:42:19 -0700120 break;
121
122 default:
123 LOG(FATAL) << "Couldn't GetValue of JType " << jty;
124 return NULL;
Logan Chienc670a8d2011-12-20 21:25:56 +0800125 }
126
TDYa127a964d412012-05-20 23:42:19 -0700127 if (jty == kFloat || jty == kDouble) {
128 value = irb_.CreateBitCast(value, irb_.getJType(jty, space));
129 }
130 return value;
Logan Chienc670a8d2011-12-20 21:25:56 +0800131}
132
133
134void DalvikReg::SetValue(JType jty, JTypeSpace space, llvm::Value* value) {
135 DCHECK_NE(jty, kVoid) << "Dalvik register will never be void type";
136
TDYa127a964d412012-05-20 23:42:19 -0700137 if (jty == kFloat || jty == kDouble) {
138 value = irb_.CreateBitCast(value, irb_.getJType(jty, kReg));
139 }
140
Logan Chienc670a8d2011-12-20 21:25:56 +0800141 switch (space) {
142 case kReg:
143 case kField:
TDYa127e2102142012-05-26 10:27:38 -0700144 irb_.CreateStore(value, GetAddr(jty), kTBAARegister);
Logan Chienc670a8d2011-12-20 21:25:56 +0800145 return;
146
147 case kAccurate:
148 case kArray:
149 switch (jty) {
150 case kVoid:
151 break;
152
153 case kBoolean:
154 case kChar:
155 // NOTE: In accurate type space, we have to zero extend boolean from
156 // i1 to i32, and char from i16 to i32. In array type space, we have
157 // to zero extend boolean from i8 to i32, and char from i16 to i32.
TDYa127e2102142012-05-26 10:27:38 -0700158 irb_.CreateStore(RegCat1ZExt(value), GetAddr(jty), kTBAARegister);
Logan Chienc670a8d2011-12-20 21:25:56 +0800159 break;
160
161 case kByte:
162 case kShort:
163 // NOTE: In accurate type space, we have to signed extend byte from
164 // i8 to i32, and short from i16 to i32. In array type space, we have
165 // to sign extend byte from i8 to i32, and short from i16 to i32.
TDYa127e2102142012-05-26 10:27:38 -0700166 irb_.CreateStore(RegCat1SExt(value), GetAddr(jty), kTBAARegister);
Logan Chienc670a8d2011-12-20 21:25:56 +0800167 break;
168
169 case kInt:
170 case kLong:
171 case kFloat:
172 case kDouble:
173 case kObject:
TDYa127e2102142012-05-26 10:27:38 -0700174 irb_.CreateStore(value, GetAddr(jty), kTBAARegister);
Logan Chienc670a8d2011-12-20 21:25:56 +0800175 break;
TDYa127706e7db2012-05-06 00:05:33 -0700176
177 default:
178 LOG(FATAL) << "Unknown java type: " << jty;
Logan Chienc670a8d2011-12-20 21:25:56 +0800179 }
180 }
181}
182
183
TDYa127e2102142012-05-26 10:27:38 -0700184llvm::Value* DalvikReg::GetAddr(JType jty) {
Logan Chienc670a8d2011-12-20 21:25:56 +0800185 switch (GetRegCategoryFromJType(jty)) {
186 case kRegCat1nr:
187 if (reg_32_ == NULL) {
TDYa127e2102142012-05-26 10:27:38 -0700188 reg_32_ = method_compiler_->AllocDalvikReg(kRegCat1nr, reg_name_);
Logan Chienc670a8d2011-12-20 21:25:56 +0800189 }
190 return reg_32_;
191
192 case kRegCat2:
193 if (reg_64_ == NULL) {
TDYa127e2102142012-05-26 10:27:38 -0700194 reg_64_ = method_compiler_->AllocDalvikReg(kRegCat2, reg_name_);
Logan Chienc670a8d2011-12-20 21:25:56 +0800195 }
196 return reg_64_;
197
198 case kRegObject:
199 if (reg_obj_ == NULL) {
TDYa127e2102142012-05-26 10:27:38 -0700200 reg_obj_ = method_compiler_->AllocDalvikReg(kRegObject, reg_name_);
Logan Chienc670a8d2011-12-20 21:25:56 +0800201 }
202 return reg_obj_;
203
204 default:
205 LOG(FATAL) << "Unexpected register category: "
206 << GetRegCategoryFromJType(jty);
207 return NULL;
208 }
209}