blob: dc73e753337746835352250e4583abea8140b021 [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
TDYa1278e950c12012-11-02 09:58:19 -070030DalvikReg::DalvikReg(MethodCompiler& method_compiler, const std::string& name, llvm::Value* vreg)
TDYa127e2102142012-05-26 10:27:38 -070031: method_compiler_(&method_compiler), irb_(method_compiler.GetIRBuilder()),
TDYa1278e950c12012-11-02 09:58:19 -070032 reg_name_(name), reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL), vreg_(vreg) {
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;
Logan Chienc670a8d2011-12-20 21:25:56 +0800121 }
122
TDYa127a964d412012-05-20 23:42:19 -0700123 if (jty == kFloat || jty == kDouble) {
124 value = irb_.CreateBitCast(value, irb_.getJType(jty, space));
125 }
126 return value;
Logan Chienc670a8d2011-12-20 21:25:56 +0800127}
128
129
130void DalvikReg::SetValue(JType jty, JTypeSpace space, llvm::Value* value) {
131 DCHECK_NE(jty, kVoid) << "Dalvik register will never be void type";
132
TDYa127a964d412012-05-20 23:42:19 -0700133 if (jty == kFloat || jty == kDouble) {
134 value = irb_.CreateBitCast(value, irb_.getJType(jty, kReg));
135 }
136
Logan Chienc670a8d2011-12-20 21:25:56 +0800137 switch (space) {
138 case kReg:
139 case kField:
TDYa1278e950c12012-11-02 09:58:19 -0700140 break;
Logan Chienc670a8d2011-12-20 21:25:56 +0800141
142 case kAccurate:
143 case kArray:
144 switch (jty) {
145 case kVoid:
TDYa1278e950c12012-11-02 09:58:19 -0700146 LOG(FATAL) << "Dalvik register with void type has no value";
Logan Chienc670a8d2011-12-20 21:25:56 +0800147 break;
148
149 case kBoolean:
150 case kChar:
151 // NOTE: In accurate type space, we have to zero extend boolean from
152 // i1 to i32, and char from i16 to i32. In array type space, we have
153 // to zero extend boolean from i8 to i32, and char from i16 to i32.
TDYa1278e950c12012-11-02 09:58:19 -0700154 value = RegCat1ZExt(value);
Logan Chienc670a8d2011-12-20 21:25:56 +0800155 break;
156
157 case kByte:
158 case kShort:
159 // NOTE: In accurate type space, we have to signed extend byte from
160 // i8 to i32, and short from i16 to i32. In array type space, we have
161 // to sign extend byte from i8 to i32, and short from i16 to i32.
TDYa1278e950c12012-11-02 09:58:19 -0700162 value = RegCat1SExt(value);
Logan Chienc670a8d2011-12-20 21:25:56 +0800163 break;
164
165 case kInt:
166 case kLong:
167 case kFloat:
168 case kDouble:
169 case kObject:
Logan Chienc670a8d2011-12-20 21:25:56 +0800170 break;
TDYa127706e7db2012-05-06 00:05:33 -0700171
172 default:
173 LOG(FATAL) << "Unknown java type: " << jty;
Logan Chienc670a8d2011-12-20 21:25:56 +0800174 }
175 }
TDYa1278e950c12012-11-02 09:58:19 -0700176
177 irb_.CreateStore(value, GetAddr(jty), kTBAARegister);
178 if (vreg_ != NULL) {
179 irb_.CreateStore(value,
180 irb_.CreateBitCast(vreg_, value->getType()->getPointerTo()),
181 kTBAAShadowFrame);
182 }
Logan Chienc670a8d2011-12-20 21:25:56 +0800183}
184
185
TDYa127e2102142012-05-26 10:27:38 -0700186llvm::Value* DalvikReg::GetAddr(JType jty) {
Logan Chienc670a8d2011-12-20 21:25:56 +0800187 switch (GetRegCategoryFromJType(jty)) {
188 case kRegCat1nr:
189 if (reg_32_ == NULL) {
TDYa127e2102142012-05-26 10:27:38 -0700190 reg_32_ = method_compiler_->AllocDalvikReg(kRegCat1nr, reg_name_);
Logan Chienc670a8d2011-12-20 21:25:56 +0800191 }
192 return reg_32_;
193
194 case kRegCat2:
195 if (reg_64_ == NULL) {
TDYa127e2102142012-05-26 10:27:38 -0700196 reg_64_ = method_compiler_->AllocDalvikReg(kRegCat2, reg_name_);
Logan Chienc670a8d2011-12-20 21:25:56 +0800197 }
198 return reg_64_;
199
200 case kRegObject:
201 if (reg_obj_ == NULL) {
TDYa127e2102142012-05-26 10:27:38 -0700202 reg_obj_ = method_compiler_->AllocDalvikReg(kRegObject, reg_name_);
Logan Chienc670a8d2011-12-20 21:25:56 +0800203 }
204 return reg_obj_;
205
206 default:
207 LOG(FATAL) << "Unexpected register category: "
208 << GetRegCategoryFromJType(jty);
209 return NULL;
210 }
211}