blob: aa95e77f6dda37036ca237ace5216cf0a727e1ab [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
2 * Copyright (C) 2011 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
Andreas Gampe0b9203e2015-01-22 20:39:27 -080017#include "mir_to_lir-inl.h"
18
Brian Carlstrom7940e442013-07-12 13:46:57 -070019#include "dex/compiler_ir.h"
Andreas Gampe0b9203e2015-01-22 20:39:27 -080020#include "dex/mir_graph.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070021#include "invoke_type.h"
22
23namespace art {
24
25/* This file contains target-independent codegen and support. */
26
27/*
28 * Load an immediate value into a fixed or temp register. Target
29 * register is clobbered, and marked in_use.
30 */
buzbee2700f7e2014-03-07 09:46:20 -080031LIR* Mir2Lir::LoadConstant(RegStorage r_dest, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070032 if (IsTemp(r_dest)) {
33 Clobber(r_dest);
34 MarkInUse(r_dest);
35 }
36 return LoadConstantNoClobber(r_dest, value);
37}
38
39/*
Brian Carlstrom7940e442013-07-12 13:46:57 -070040 * Load a Dalvik register into a physical register. Take care when
41 * using this routine, as it doesn't perform any bookkeeping regarding
42 * register liveness. That is the responsibility of the caller.
43 */
buzbee2700f7e2014-03-07 09:46:20 -080044void Mir2Lir::LoadValueDirect(RegLocation rl_src, RegStorage r_dest) {
Mathieu Chartiere401d142015-04-22 13:56:20 -070045 rl_src = rl_src.wide ? UpdateLocWide(rl_src) : UpdateLoc(rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -070046 if (rl_src.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -080047 OpRegCopy(r_dest, rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -070048 } else if (IsInexpensiveConstant(rl_src)) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -070049 // On 64-bit targets, will sign extend. Make sure constant reference is always null.
buzbee695d13a2014-04-19 13:32:20 -070050 DCHECK(!rl_src.ref || (mir_graph_->ConstantValue(rl_src) == 0));
Brian Carlstrom7940e442013-07-12 13:46:57 -070051 LoadConstantNoClobber(r_dest, mir_graph_->ConstantValue(rl_src));
52 } else {
53 DCHECK((rl_src.location == kLocDalvikFrame) ||
54 (rl_src.location == kLocCompilerTemp));
Vladimir Marko8dea81c2014-06-06 14:50:36 +010055 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Mathieu Chartiere401d142015-04-22 13:56:20 -070056 OpSize op_size;
buzbee695d13a2014-04-19 13:32:20 -070057 if (rl_src.ref) {
Mathieu Chartiere401d142015-04-22 13:56:20 -070058 op_size = kReference;
59 } else if (rl_src.wide) {
60 op_size = k64;
buzbee695d13a2014-04-19 13:32:20 -070061 } else {
Mathieu Chartiere401d142015-04-22 13:56:20 -070062 op_size = k32;
buzbee695d13a2014-04-19 13:32:20 -070063 }
Mathieu Chartiere401d142015-04-22 13:56:20 -070064 LoadBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_src.s_reg_low), r_dest, op_size, kNotVolatile);
Brian Carlstrom7940e442013-07-12 13:46:57 -070065 }
66}
67
68/*
69 * Similar to LoadValueDirect, but clobbers and allocates the target
70 * register. Should be used when loading to a fixed register (for example,
71 * loading arguments to an out of line call.
72 */
buzbee2700f7e2014-03-07 09:46:20 -080073void Mir2Lir::LoadValueDirectFixed(RegLocation rl_src, RegStorage r_dest) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070074 Clobber(r_dest);
75 MarkInUse(r_dest);
76 LoadValueDirect(rl_src, r_dest);
77}
78
79/*
80 * Load a Dalvik register pair into a physical register[s]. Take care when
81 * using this routine, as it doesn't perform any bookkeeping regarding
82 * register liveness. That is the responsibility of the caller.
83 */
buzbee2700f7e2014-03-07 09:46:20 -080084void Mir2Lir::LoadValueDirectWide(RegLocation rl_src, RegStorage r_dest) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070085 rl_src = UpdateLocWide(rl_src);
86 if (rl_src.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -080087 OpRegCopyWide(r_dest, rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -070088 } else if (IsInexpensiveConstant(rl_src)) {
buzbee2700f7e2014-03-07 09:46:20 -080089 LoadConstantWide(r_dest, mir_graph_->ConstantValueWide(rl_src));
Brian Carlstrom7940e442013-07-12 13:46:57 -070090 } else {
91 DCHECK((rl_src.location == kLocDalvikFrame) ||
92 (rl_src.location == kLocCompilerTemp));
Vladimir Marko8dea81c2014-06-06 14:50:36 +010093 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Chao-ying Fua77ee512014-07-01 17:43:41 -070094 LoadBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_src.s_reg_low), r_dest, k64, kNotVolatile);
Brian Carlstrom7940e442013-07-12 13:46:57 -070095 }
96}
97
98/*
99 * Similar to LoadValueDirect, but clobbers and allocates the target
100 * registers. Should be used when loading to a fixed registers (for example,
101 * loading arguments to an out of line call.
102 */
buzbee2700f7e2014-03-07 09:46:20 -0800103void Mir2Lir::LoadValueDirectWideFixed(RegLocation rl_src, RegStorage r_dest) {
104 Clobber(r_dest);
105 MarkInUse(r_dest);
106 LoadValueDirectWide(rl_src, r_dest);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700107}
108
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700109RegLocation Mir2Lir::LoadValue(RegLocation rl_src, RegisterClass op_kind) {
buzbeea0cd2d72014-06-01 09:33:49 -0700110 DCHECK(!rl_src.ref || op_kind == kRefReg);
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100111 rl_src = UpdateLoc(rl_src);
112 if (rl_src.location == kLocPhysReg) {
113 if (!RegClassMatches(op_kind, rl_src.reg)) {
114 // Wrong register class, realloc, copy and transfer ownership.
115 RegStorage new_reg = AllocTypedTemp(rl_src.fp, op_kind);
116 OpRegCopy(new_reg, rl_src.reg);
Serguei Katkov02c637e2014-10-29 13:48:02 +0600117 // Clobber the old regs and free it.
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100118 Clobber(rl_src.reg);
Serguei Katkov02c637e2014-10-29 13:48:02 +0600119 FreeTemp(rl_src.reg);
buzbee082833c2014-05-17 23:16:26 -0700120 // ...and mark the new one live.
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100121 rl_src.reg = new_reg;
buzbee082833c2014-05-17 23:16:26 -0700122 MarkLive(rl_src);
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100123 }
124 return rl_src;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700125 }
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100126
127 DCHECK_NE(rl_src.s_reg_low, INVALID_SREG);
128 rl_src.reg = AllocTypedTemp(rl_src.fp, op_kind);
129 LoadValueDirect(rl_src, rl_src.reg);
130 rl_src.location = kLocPhysReg;
131 MarkLive(rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700132 return rl_src;
133}
134
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700135void Mir2Lir::StoreValue(RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700136 /*
137 * Sanity checking - should never try to store to the same
138 * ssa name during the compilation of a single instruction
139 * without an intervening ClobberSReg().
140 */
141 if (kIsDebugBuild) {
142 DCHECK((live_sreg_ == INVALID_SREG) ||
143 (rl_dest.s_reg_low != live_sreg_));
144 live_sreg_ = rl_dest.s_reg_low;
145 }
146 LIR* def_start;
147 LIR* def_end;
148 DCHECK(!rl_dest.wide);
149 DCHECK(!rl_src.wide);
150 rl_src = UpdateLoc(rl_src);
151 rl_dest = UpdateLoc(rl_dest);
152 if (rl_src.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -0800153 if (IsLive(rl_src.reg) ||
154 IsPromoted(rl_src.reg) ||
Brian Carlstrom7940e442013-07-12 13:46:57 -0700155 (rl_dest.location == kLocPhysReg)) {
156 // Src is live/promoted or Dest has assigned reg.
Andreas Gampe4b537a82014-06-30 22:24:53 -0700157 rl_dest = EvalLoc(rl_dest, rl_dest.ref || rl_src.ref ? kRefReg : kAnyReg, false);
buzbee2700f7e2014-03-07 09:46:20 -0800158 OpRegCopy(rl_dest.reg, rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700159 } else {
160 // Just re-assign the registers. Dest gets Src's regs
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000161 rl_dest.reg = rl_src.reg;
buzbee2700f7e2014-03-07 09:46:20 -0800162 Clobber(rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700163 }
164 } else {
165 // Load Src either into promoted Dest or temps allocated for Dest
Andreas Gampe4b537a82014-06-30 22:24:53 -0700166 rl_dest = EvalLoc(rl_dest, rl_dest.ref ? kRefReg : kAnyReg, false);
buzbee2700f7e2014-03-07 09:46:20 -0800167 LoadValueDirect(rl_src, rl_dest.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700168 }
169
170 // Dest is now live and dirty (until/if we flush it to home location)
buzbee091cc402014-03-31 10:14:40 -0700171 MarkLive(rl_dest);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700172 MarkDirty(rl_dest);
173
174
175 ResetDefLoc(rl_dest);
buzbee091cc402014-03-31 10:14:40 -0700176 if (IsDirty(rl_dest.reg) && LiveOut(rl_dest.s_reg_low)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700177 def_start = last_lir_insn_;
Ian Rogerse98297b2014-06-22 07:47:53 +0000178 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Andreas Gampe2073e752014-06-23 15:39:00 +0000179 if (rl_dest.ref) {
Chao-ying Fua77ee512014-07-01 17:43:41 -0700180 StoreRefDisp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg, kNotVolatile);
Andreas Gampe2073e752014-06-23 15:39:00 +0000181 } else {
Chao-ying Fua77ee512014-07-01 17:43:41 -0700182 Store32Disp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg);
Andreas Gampe2073e752014-06-23 15:39:00 +0000183 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700184 MarkClean(rl_dest);
185 def_end = last_lir_insn_;
186 if (!rl_dest.ref) {
187 // Exclude references from store elimination
188 MarkDef(rl_dest, def_start, def_end);
189 }
190 }
191}
192
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700193RegLocation Mir2Lir::LoadValueWide(RegLocation rl_src, RegisterClass op_kind) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700194 DCHECK(rl_src.wide);
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100195 rl_src = UpdateLocWide(rl_src);
196 if (rl_src.location == kLocPhysReg) {
197 if (!RegClassMatches(op_kind, rl_src.reg)) {
198 // Wrong register class, realloc, copy and transfer ownership.
199 RegStorage new_regs = AllocTypedTempWide(rl_src.fp, op_kind);
200 OpRegCopyWide(new_regs, rl_src.reg);
Serguei Katkov02c637e2014-10-29 13:48:02 +0600201 // Clobber the old regs and free it.
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100202 Clobber(rl_src.reg);
Serguei Katkov02c637e2014-10-29 13:48:02 +0600203 FreeTemp(rl_src.reg);
buzbee082833c2014-05-17 23:16:26 -0700204 // ...and mark the new ones live.
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100205 rl_src.reg = new_regs;
buzbee082833c2014-05-17 23:16:26 -0700206 MarkLive(rl_src);
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100207 }
208 return rl_src;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700209 }
Vladimir Marko0dc242d2014-05-12 16:22:14 +0100210
211 DCHECK_NE(rl_src.s_reg_low, INVALID_SREG);
212 DCHECK_NE(GetSRegHi(rl_src.s_reg_low), INVALID_SREG);
213 rl_src.reg = AllocTypedTempWide(rl_src.fp, op_kind);
214 LoadValueDirectWide(rl_src, rl_src.reg);
215 rl_src.location = kLocPhysReg;
216 MarkLive(rl_src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700217 return rl_src;
218}
219
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700220void Mir2Lir::StoreValueWide(RegLocation rl_dest, RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700221 /*
222 * Sanity checking - should never try to store to the same
223 * ssa name during the compilation of a single instruction
224 * without an intervening ClobberSReg().
225 */
226 if (kIsDebugBuild) {
227 DCHECK((live_sreg_ == INVALID_SREG) ||
228 (rl_dest.s_reg_low != live_sreg_));
229 live_sreg_ = rl_dest.s_reg_low;
230 }
231 LIR* def_start;
232 LIR* def_end;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700233 DCHECK(rl_dest.wide);
234 DCHECK(rl_src.wide);
Alexei Zavjalovc17ebe82014-02-26 10:38:23 +0700235 rl_src = UpdateLocWide(rl_src);
236 rl_dest = UpdateLocWide(rl_dest);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700237 if (rl_src.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -0800238 if (IsLive(rl_src.reg) ||
239 IsPromoted(rl_src.reg) ||
Brian Carlstrom7940e442013-07-12 13:46:57 -0700240 (rl_dest.location == kLocPhysReg)) {
buzbee30adc732014-05-09 15:10:18 -0700241 /*
242 * If src reg[s] are tied to the original Dalvik vreg via liveness or promotion, we
243 * can't repurpose them. Similarly, if the dest reg[s] are tied to Dalvik vregs via
244 * promotion, we can't just re-assign. In these cases, we have to copy.
245 */
Brian Carlstrom7940e442013-07-12 13:46:57 -0700246 rl_dest = EvalLoc(rl_dest, kAnyReg, false);
buzbee2700f7e2014-03-07 09:46:20 -0800247 OpRegCopyWide(rl_dest.reg, rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700248 } else {
249 // Just re-assign the registers. Dest gets Src's regs
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000250 rl_dest.reg = rl_src.reg;
buzbee2700f7e2014-03-07 09:46:20 -0800251 Clobber(rl_src.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700252 }
253 } else {
254 // Load Src either into promoted Dest or temps allocated for Dest
255 rl_dest = EvalLoc(rl_dest, kAnyReg, false);
buzbee2700f7e2014-03-07 09:46:20 -0800256 LoadValueDirectWide(rl_src, rl_dest.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700257 }
258
259 // Dest is now live and dirty (until/if we flush it to home location)
buzbee091cc402014-03-31 10:14:40 -0700260 MarkLive(rl_dest);
261 MarkWide(rl_dest.reg);
262 MarkDirty(rl_dest);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700263
264 ResetDefLocWide(rl_dest);
buzbee091cc402014-03-31 10:14:40 -0700265 if (IsDirty(rl_dest.reg) && (LiveOut(rl_dest.s_reg_low) ||
266 LiveOut(GetSRegHi(rl_dest.s_reg_low)))) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700267 def_start = last_lir_insn_;
268 DCHECK_EQ((mir_graph_->SRegToVReg(rl_dest.s_reg_low)+1),
269 mir_graph_->SRegToVReg(GetSRegHi(rl_dest.s_reg_low)));
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100270 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Chao-ying Fua77ee512014-07-01 17:43:41 -0700271 StoreBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg, k64, kNotVolatile);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700272 MarkClean(rl_dest);
273 def_end = last_lir_insn_;
274 MarkDefWide(rl_dest, def_start, def_end);
275 }
276}
277
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800278void Mir2Lir::StoreFinalValue(RegLocation rl_dest, RegLocation rl_src) {
279 DCHECK_EQ(rl_src.location, kLocPhysReg);
280
281 if (rl_dest.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -0800282 OpRegCopy(rl_dest.reg, rl_src.reg);
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800283 } else {
284 // Just re-assign the register. Dest gets Src's reg.
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800285 rl_dest.location = kLocPhysReg;
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000286 rl_dest.reg = rl_src.reg;
buzbee2700f7e2014-03-07 09:46:20 -0800287 Clobber(rl_src.reg);
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800288 }
289
290 // Dest is now live and dirty (until/if we flush it to home location)
buzbee091cc402014-03-31 10:14:40 -0700291 MarkLive(rl_dest);
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800292 MarkDirty(rl_dest);
293
294
295 ResetDefLoc(rl_dest);
buzbee091cc402014-03-31 10:14:40 -0700296 if (IsDirty(rl_dest.reg) && LiveOut(rl_dest.s_reg_low)) {
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800297 LIR *def_start = last_lir_insn_;
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100298 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Chao-ying Fua77ee512014-07-01 17:43:41 -0700299 Store32Disp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg);
Mark Mendellfeb2b4e2014-01-28 12:59:49 -0800300 MarkClean(rl_dest);
301 LIR *def_end = last_lir_insn_;
302 if (!rl_dest.ref) {
303 // Exclude references from store elimination
304 MarkDef(rl_dest, def_start, def_end);
305 }
306 }
307}
308
Mark Mendelle02d48f2014-01-15 11:19:23 -0800309void Mir2Lir::StoreFinalValueWide(RegLocation rl_dest, RegLocation rl_src) {
Mark Mendelle02d48f2014-01-15 11:19:23 -0800310 DCHECK(rl_dest.wide);
311 DCHECK(rl_src.wide);
312 DCHECK_EQ(rl_src.location, kLocPhysReg);
313
314 if (rl_dest.location == kLocPhysReg) {
buzbee2700f7e2014-03-07 09:46:20 -0800315 OpRegCopyWide(rl_dest.reg, rl_src.reg);
Mark Mendelle02d48f2014-01-15 11:19:23 -0800316 } else {
317 // Just re-assign the registers. Dest gets Src's regs.
Mark Mendelle02d48f2014-01-15 11:19:23 -0800318 rl_dest.location = kLocPhysReg;
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000319 rl_dest.reg = rl_src.reg;
buzbee091cc402014-03-31 10:14:40 -0700320 Clobber(rl_src.reg);
Mark Mendelle02d48f2014-01-15 11:19:23 -0800321 }
322
323 // Dest is now live and dirty (until/if we flush it to home location).
buzbee091cc402014-03-31 10:14:40 -0700324 MarkLive(rl_dest);
325 MarkWide(rl_dest.reg);
326 MarkDirty(rl_dest);
Mark Mendelle02d48f2014-01-15 11:19:23 -0800327
328 ResetDefLocWide(rl_dest);
buzbee091cc402014-03-31 10:14:40 -0700329 if (IsDirty(rl_dest.reg) && (LiveOut(rl_dest.s_reg_low) ||
330 LiveOut(GetSRegHi(rl_dest.s_reg_low)))) {
Mark Mendelle02d48f2014-01-15 11:19:23 -0800331 LIR *def_start = last_lir_insn_;
332 DCHECK_EQ((mir_graph_->SRegToVReg(rl_dest.s_reg_low)+1),
333 mir_graph_->SRegToVReg(GetSRegHi(rl_dest.s_reg_low)));
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100334 ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
Chao-ying Fua77ee512014-07-01 17:43:41 -0700335 StoreBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_dest.s_reg_low), rl_dest.reg, k64, kNotVolatile);
Mark Mendelle02d48f2014-01-15 11:19:23 -0800336 MarkClean(rl_dest);
337 LIR *def_end = last_lir_insn_;
338 MarkDefWide(rl_dest, def_start, def_end);
339 }
340}
341
Brian Carlstrom7940e442013-07-12 13:46:57 -0700342/* Utilities to load the current Method* */
buzbee2700f7e2014-03-07 09:46:20 -0800343void Mir2Lir::LoadCurrMethodDirect(RegStorage r_tgt) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700344 if (GetCompilationUnit()->target64) {
345 LoadValueDirectWideFixed(mir_graph_->GetMethodLoc(), r_tgt);
346 } else {
347 LoadValueDirectFixed(mir_graph_->GetMethodLoc(), r_tgt);
348 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700349}
350
Vladimir Marko20f85592015-03-19 10:07:02 +0000351RegStorage Mir2Lir::LoadCurrMethodWithHint(RegStorage r_hint) {
352 // If the method is promoted to a register, return that register, otherwise load it to r_hint.
353 // (Replacement for LoadCurrMethod() usually used when LockCallTemps() is in effect.)
354 DCHECK(r_hint.Valid());
355 RegLocation rl_method = mir_graph_->GetMethodLoc();
356 if (rl_method.location == kLocPhysReg) {
357 DCHECK(!IsTemp(rl_method.reg));
358 return rl_method.reg;
359 } else {
360 LoadCurrMethodDirect(r_hint);
361 return r_hint;
362 }
363}
364
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700365RegLocation Mir2Lir::LoadCurrMethod() {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700366 return GetCompilationUnit()->target64 ?
367 LoadValueWide(mir_graph_->GetMethodLoc(), kCoreReg) :
368 LoadValue(mir_graph_->GetMethodLoc(), kRefReg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700369}
370
Mark Mendelle02d48f2014-01-15 11:19:23 -0800371RegLocation Mir2Lir::ForceTemp(RegLocation loc) {
372 DCHECK(!loc.wide);
373 DCHECK(loc.location == kLocPhysReg);
buzbee091cc402014-03-31 10:14:40 -0700374 DCHECK(!loc.reg.IsFloat());
buzbee2700f7e2014-03-07 09:46:20 -0800375 if (IsTemp(loc.reg)) {
376 Clobber(loc.reg);
Mark Mendelle02d48f2014-01-15 11:19:23 -0800377 } else {
buzbee2700f7e2014-03-07 09:46:20 -0800378 RegStorage temp_low = AllocTemp();
379 OpRegCopy(temp_low, loc.reg);
380 loc.reg = temp_low;
Mark Mendelle02d48f2014-01-15 11:19:23 -0800381 }
382
383 // Ensure that this doesn't represent the original SR any more.
384 loc.s_reg_low = INVALID_SREG;
385 return loc;
386}
387
388RegLocation Mir2Lir::ForceTempWide(RegLocation loc) {
389 DCHECK(loc.wide);
390 DCHECK(loc.location == kLocPhysReg);
buzbee091cc402014-03-31 10:14:40 -0700391 DCHECK(!loc.reg.IsFloat());
Chao-ying Fue0ccdc02014-06-06 17:32:37 -0700392
393 if (!loc.reg.IsPair()) {
394 if (IsTemp(loc.reg)) {
395 Clobber(loc.reg);
396 } else {
397 RegStorage temp = AllocTempWide();
398 OpRegCopy(temp, loc.reg);
399 loc.reg = temp;
400 }
Mark Mendelle02d48f2014-01-15 11:19:23 -0800401 } else {
Chao-ying Fue0ccdc02014-06-06 17:32:37 -0700402 if (IsTemp(loc.reg.GetLow())) {
403 Clobber(loc.reg.GetLow());
404 } else {
405 RegStorage temp_low = AllocTemp();
406 OpRegCopy(temp_low, loc.reg.GetLow());
407 loc.reg.SetLowReg(temp_low.GetReg());
408 }
409 if (IsTemp(loc.reg.GetHigh())) {
410 Clobber(loc.reg.GetHigh());
411 } else {
412 RegStorage temp_high = AllocTemp();
413 OpRegCopy(temp_high, loc.reg.GetHigh());
414 loc.reg.SetHighReg(temp_high.GetReg());
415 }
Mark Mendelle02d48f2014-01-15 11:19:23 -0800416 }
417
418 // Ensure that this doesn't represent the original SR any more.
419 loc.s_reg_low = INVALID_SREG;
420 return loc;
421}
422
Brian Carlstrom7940e442013-07-12 13:46:57 -0700423} // namespace art