1/*
2 * Copyright (C) 2009 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/*
18 * This file contains register alloction support and is intended to be
19 * included by:
20 *
21 *        Codegen-$(TARGET_ARCH_VARIANT).c
22 *
23 */
24
25#include "compiler/CompilerUtility.h"
26#include "compiler/CompilerIR.h"
27#include "compiler/Dataflow.h"
28#include "compiler/codegen/arm/ArmLIR.h"
29
30/*
31 * Return most flexible allowed register class based on size.
32 * Bug: 2813841
33 * Must use a core register for data types narrower than word (due
34 * to possible unaligned load/store.
35 */
36static inline RegisterClass dvmCompilerRegClassBySize(OpSize size)
37{
38    return (size == kUnsignedHalf ||
39            size == kSignedHalf ||
40            size == kUnsignedByte ||
41            size == kSignedByte ) ? kCoreReg : kAnyReg;
42}
43
44static inline int dvmCompilerS2VReg(CompilationUnit *cUnit, int sReg)
45{
46    assert(sReg != INVALID_SREG);
47    return DECODE_REG(dvmConvertSSARegToDalvik(cUnit, sReg));
48}
49
50/* Reset the tracker to unknown state */
51static inline void dvmCompilerResetNullCheck(CompilationUnit *cUnit)
52{
53    dvmClearAllBits(cUnit->regPool->nullCheckedRegs);
54}
55
56/*
57 * Get the "real" sreg number associated with an sReg slot.  In general,
58 * sReg values passed through codegen are the SSA names created by
59 * dataflow analysis and refer to slot numbers in the cUnit->regLocation
60 * array.  However, renaming is accomplished by simply replacing RegLocation
61 * entries in the cUnit->reglocation[] array.  Therefore, when location
62 * records for operands are first created, we need to ask the locRecord
63 * identified by the dataflow pass what it's new name is.
64 */
65
66static inline int dvmCompilerSRegHi(int lowSreg) {
67    return (lowSreg == INVALID_SREG) ? INVALID_SREG : lowSreg + 1;
68}
69
70
71static inline bool dvmCompilerLiveOut(CompilationUnit *cUnit, int sReg)
72{
73    //TODO: fully implement
74    return true;
75}
76
77static inline int dvmCompilerSSASrc(MIR *mir, int num)
78{
79    assert(mir->ssaRep->numUses > num);
80    return mir->ssaRep->uses[num];
81}
82
83extern RegLocation dvmCompilerEvalLoc(CompilationUnit *cUnit, RegLocation loc,
84                                      int regClass, bool update);
85/* Mark a temp register as dead.  Does not affect allocation state. */
86extern void dvmCompilerClobber(CompilationUnit *cUnit, int reg);
87
88extern RegLocation dvmCompilerUpdateLoc(CompilationUnit *cUnit,
89                                        RegLocation loc);
90
91/* see comments for updateLoc */
92extern RegLocation dvmCompilerUpdateLocWide(CompilationUnit *cUnit,
93                                            RegLocation loc);
94
95/* Clobber all of the temps that might be used by a handler. */
96extern void dvmCompilerClobberHandlerRegs(CompilationUnit *cUnit);
97
98extern void dvmCompilerMarkLive(CompilationUnit *cUnit, int reg, int sReg);
99
100extern void dvmCompilerMarkDirty(CompilationUnit *cUnit, int reg);
101
102extern void dvmCompilerMarkPair(CompilationUnit *cUnit, int lowReg,
103                                int highReg);
104
105extern void dvmCompilerMarkClean(CompilationUnit *cUnit, int reg);
106
107extern void dvmCompilerResetDef(CompilationUnit *cUnit, int reg);
108
109extern void dvmCompilerResetDefLoc(CompilationUnit *cUnit, RegLocation rl);
110
111/* Set up temp & preserved register pools specialized by target */
112extern void dvmCompilerInitPool(RegisterInfo *regs, int *regNums, int num);
113
114/*
115 * Mark the beginning and end LIR of a def sequence.  Note that
116 * on entry start points to the LIR prior to the beginning of the
117 * sequence.
118 */
119extern void dvmCompilerMarkDef(CompilationUnit *cUnit, RegLocation rl,
120                               LIR *start, LIR *finish);
121/*
122 * Mark the beginning and end LIR of a def sequence.  Note that
123 * on entry start points to the LIR prior to the beginning of the
124 * sequence.
125 */
126extern void dvmCompilerMarkDefWide(CompilationUnit *cUnit, RegLocation rl,
127                                   LIR *start, LIR *finish);
128
129extern RegLocation dvmCompilerGetSrcWide(CompilationUnit *cUnit, MIR *mir,
130                                         int low, int high);
131
132extern RegLocation dvmCompilerGetDestWide(CompilationUnit *cUnit, MIR *mir,
133                                          int low, int high);
134// Get the LocRecord associated with an SSA name use.
135extern RegLocation dvmCompilerGetSrc(CompilationUnit *cUnit, MIR *mir, int num);
136
137// Get the LocRecord associated with an SSA name def.
138extern RegLocation dvmCompilerGetDest(CompilationUnit *cUnit, MIR *mir,
139                                      int num);
140
141extern RegLocation dvmCompilerGetReturnWide(CompilationUnit *cUnit);
142
143/* Clobber all regs that might be used by an external C call */
144extern void dvmCompilerClobberCallRegs(CompilationUnit *cUnit);
145
146extern RegisterInfo *dvmCompilerIsTemp(CompilationUnit *cUnit, int reg);
147
148extern void dvmCompilerMarkInUse(CompilationUnit *cUnit, int reg);
149
150extern int dvmCompilerAllocTemp(CompilationUnit *cUnit);
151
152extern int dvmCompilerAllocTempFloat(CompilationUnit *cUnit);
153
154//REDO: too many assumptions.
155extern int dvmCompilerAllocTempDouble(CompilationUnit *cUnit);
156
157extern void dvmCompilerFreeTemp(CompilationUnit *cUnit, int reg);
158
159extern void dvmCompilerResetDefLocWide(CompilationUnit *cUnit, RegLocation rl);
160
161extern void dvmCompilerResetDefTracking(CompilationUnit *cUnit);
162
163/* Kill the corresponding bit in the null-checked register list */
164extern void dvmCompilerKillNullCheckedLoc(CompilationUnit *cUnit,
165                                          RegLocation loc);
166
167//FIXME - this needs to also check the preserved pool.
168extern RegisterInfo *dvmCompilerIsLive(CompilationUnit *cUnit, int reg);
169
170/* To be used when explicitly managing register use */
171extern void dvmCompilerLockAllTemps(CompilationUnit *cUnit);
172
173extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit);
174
175extern RegLocation dvmCompilerGetReturnWideAlt(CompilationUnit *cUnit);
176
177extern RegLocation dvmCompilerGetReturn(CompilationUnit *cUnit);
178
179extern RegLocation dvmCompilerGetReturnAlt(CompilationUnit *cUnit);
180
181/* Clobber any temp associated with an sReg.  Could be in either class */
182extern void dvmCompilerClobberSReg(CompilationUnit *cUnit, int sReg);
183
184/* Return a temp if one is available, -1 otherwise */
185extern int dvmCompilerAllocFreeTemp(CompilationUnit *cUnit);
186
187/*
188 * Similar to dvmCompilerAllocTemp(), but forces the allocation of a specific
189 * register.  No check is made to see if the register was previously
190 * allocated.  Use with caution.
191 */
192extern void dvmCompilerLockTemp(CompilationUnit *cUnit, int reg);
193
194extern RegLocation dvmCompilerWideToNarrow(CompilationUnit *cUnit,
195                                           RegLocation rl);
196
197/*
198 * Free all allocated temps in the temp pools.  Note that this does
199 * not affect the "liveness" of a temp register, which will stay
200 * live until it is either explicitly killed or reallocated.
201 */
202extern void dvmCompilerResetRegPool(CompilationUnit *cUnit);
203
204extern void dvmCompilerClobberAllRegs(CompilationUnit *cUnit);
205
206extern void dvmCompilerResetDefTracking(CompilationUnit *cUnit);
207