001 /*
002 * This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 * This file is licensed to You under the Common Public License (CPL);
005 * You may not use this file except in compliance with the License. You
006 * may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/cpl1.0.php
009 *
010 * See the COPYRIGHT.txt file distributed with this work for information
011 * regarding copyright ownership.
012 */
013 package org.jikesrvm.compilers.opt.ir;
014
015 import java.util.HashMap;
016 import org.jikesrvm.VM;
017 import org.jikesrvm.classloader.TypeReference;
018 import org.jikesrvm.compilers.opt.ir.operand.Operand;
019 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
020
021 public abstract class AbstractRegisterPool {
022
023 /* inlined behavior of DoublyLinkedList */
024 private Register start, end;
025
026 /**
027 * Return the first symbolic register in this pool.
028 */
029 public Register getFirstSymbolicRegister() {
030 return start;
031 }
032
033 private void registerListappend(Register reg) {
034 if (start == null) {
035 start = end = reg;
036 } else {
037 end.append(reg);
038 end = reg;
039 }
040 }
041
042 private void registerListremove(Register e) {
043 if (e == start) {
044 if (e == end) {
045 start = end = null;
046 } else {
047 Register next = e.next;
048 start = next;
049 next.prev = null;
050 }
051 } else if (e == end) {
052 Register prev = e.prev;
053 end = prev;
054 prev.next = null;
055 } else {
056 e.remove();
057 }
058 }
059 /* end of inlined behavior */
060
061 /**
062 * All registers are assigned unique numbers; currentNum is the counter
063 * containing the next available register number.
064 */
065 protected int currentNum;
066
067 private Register makeNewReg() {
068 Register reg = new Register(currentNum);
069 currentNum++;
070 registerListappend(reg);
071 return reg;
072 }
073
074 /**
075 * Release a now unused register.
076 * NOTE: It is the CALLERS responsibility to ensure that the register is no
077 * longer used!!!!
078 * @param r the register to release
079 */
080 public void release(RegisterOperand r) {
081 Register reg = r.getRegister();
082 if (reg.number == currentNum - 1) {
083 currentNum--;
084 registerListremove(end);
085 }
086 }
087
088 /**
089 * Remove register from register pool.
090 */
091 public void removeRegister(Register reg) {
092 registerListremove(reg);
093 }
094
095 /**
096 * Gets a new address register.
097 *
098 * @return the newly created register object
099 */
100 public Register getAddress() {
101 Register reg = makeNewReg();
102 reg.setAddress();
103 return reg;
104 }
105
106 /**
107 * Gets a new integer register.
108 *
109 * @return the newly created register object
110 */
111 public Register getInteger() {
112 Register reg = makeNewReg();
113 reg.setInteger();
114 return reg;
115 }
116
117 /**
118 * Gets a new float register.
119 *
120 * @return the newly created register object
121 */
122 public Register getFloat() {
123 Register reg = makeNewReg();
124 reg.setFloat();
125 return reg;
126 }
127
128 /**
129 * Gets a new double register.
130 *
131 * @return the newly created register object
132 */
133 public Register getDouble() {
134 Register reg;
135 reg = makeNewReg();
136 reg.setDouble();
137 return reg;
138 }
139
140 /**
141 * Gets a new condition register.
142 *
143 * @return the newly created register object
144 */
145 public Register getCondition() {
146 Register reg = makeNewReg();
147 reg.setCondition();
148 return reg;
149 }
150
151 /**
152 * Gets a new long register.
153 *
154 * @return the newly created register object
155 */
156 public Register getLong() {
157 Register reg;
158 reg = makeNewReg();
159 reg.setLong();
160 return reg;
161 }
162
163 /**
164 * Gets a new validation register.
165 *
166 * @return the newly created register object
167 */
168 public Register getValidation() {
169 Register reg = makeNewReg();
170 reg.setValidation();
171 return reg;
172 }
173
174 /**
175 * Get a new register of the same type as the argument register
176 *
177 * @param template the register to get the type from
178 * @return the newly created register object
179 */
180 public Register getReg(Register template) {
181 switch (template.getType()) {
182 case Register.ADDRESS_TYPE:
183 return getAddress();
184 case Register.INTEGER_TYPE:
185 return getInteger();
186 case Register.FLOAT_TYPE:
187 return getFloat();
188 case Register.DOUBLE_TYPE:
189 return getDouble();
190 case Register.CONDITION_TYPE:
191 return getCondition();
192 case Register.LONG_TYPE:
193 return getLong();
194 case Register.VALIDATION_TYPE:
195 return getValidation();
196 }
197 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
198 return null;
199 }
200
201 /**
202 * Get a new register of the same type as the argument RegisterOperand
203 *
204 * @param template the register operand to get the type from
205 * @return the newly created register object
206 */
207 public Register getReg(RegisterOperand template) {
208 return getReg(template.getRegister());
209 }
210
211 /**
212 * Get a new register of the appropriate type to hold values of 'type'
213 *
214 * @param type the type of values that the register will hold
215 * @return the newly created register object
216 */
217 public Register getReg(TypeReference type) {
218 if (type.isLongType()) {
219 return getLong();
220 } else if (type.isDoubleType()) {
221 return getDouble();
222 } else if (type.isFloatType()) {
223 return getFloat();
224 } else if (type == TypeReference.VALIDATION_TYPE) {
225 return getValidation();
226 } else if (type.isWordType() || type.isReferenceType()) {
227 return getAddress();
228 } else {
229 return getInteger();
230 }
231 }
232
233 private final HashMap<Register, Register> _regPairs = new HashMap<Register, Register>();
234
235 /**
236 * MIR: Get the other half of the register pair that is
237 * associated with the argument register.
238 * Note: this isn't incredibly general, but all architectures we're currently
239 * targeting need at most 2 machine registers to hold Java data values, so
240 * for now don't bother implementing a general mechanism.
241 *
242 * @param reg a register that may already be part of a register pair
243 * @return the register that is the other half of the register pair,
244 * if the pairing doesn't already exist then it is created.
245 */
246 public Register getSecondReg(Register reg) {
247 Register otherHalf = _regPairs.get(reg);
248 if (otherHalf == null) {
249 otherHalf = getReg(reg);
250 _regPairs.put(reg, otherHalf);
251 if (reg.isLocal()) otherHalf.setLocal();
252 if (reg.isSSA()) otherHalf.setSSA();
253 }
254 return otherHalf;
255 }
256
257 /**
258 * Make a temporary register operand to hold values of the specified type
259 * (a new register is allocated).
260 *
261 * @param type the type of values to be held in the temp register
262 * @return the new temp
263 */
264 public RegisterOperand makeTemp(TypeReference type) {
265 return new RegisterOperand(getReg(type), type);
266 }
267
268 /**
269 * Make a temporary register operand that is similar to the argument.
270 *
271 * @param template the register operand to use as a template.
272 * @return the new temp
273 */
274 public RegisterOperand makeTemp(RegisterOperand template) {
275 RegisterOperand temp = new RegisterOperand(getReg(template), template.getType());
276 temp.addFlags(template.getFlags());
277 return temp;
278 }
279
280 /**
281 * Make a temporary register operand that can hold the values
282 * implied by the passed operand.
283 *
284 * @param op the operand to use as a template.
285 * @return the new temp
286 */
287 public RegisterOperand makeTemp(Operand op) {
288 RegisterOperand result;
289 if (op.isRegister()) {
290 result = makeTemp((RegisterOperand) op);
291 } else {
292 result = makeTemp(op.getType());
293 }
294 return result;
295 }
296
297 /**
298 * Make a temporary to hold an address (allocating a new register).
299 *
300 * @return the newly created temporary
301 */
302 public RegisterOperand makeTempAddress() {
303 return new RegisterOperand(getAddress(), TypeReference.Address);
304 }
305
306 /**
307 * Make a temporary to hold an address (allocating a new register).
308 *
309 * @return the newly created temporary
310 */
311 public RegisterOperand makeTempOffset() {
312 return new RegisterOperand(getAddress(), TypeReference.Offset);
313 }
314
315 /**
316 * Make a temporary to hold an int (allocating a new register).
317 *
318 * @return the newly created temporary
319 */
320 public RegisterOperand makeTempInt() {
321 return new RegisterOperand(getInteger(), TypeReference.Int);
322 }
323
324 /**
325 * Make a temporary to hold a boolean (allocating a new register).
326 *
327 * @return the newly created temporary
328 */
329 public RegisterOperand makeTempBoolean() {
330 return new RegisterOperand(getInteger(), TypeReference.Boolean);
331 }
332
333 /**
334 * Make a temporary to hold a float (allocating a new register).
335 *
336 * @return the newly created temporary
337 */
338 public RegisterOperand makeTempFloat() {
339 return new RegisterOperand(getFloat(), TypeReference.Float);
340 }
341
342 /**
343 * Make a temporary to hold a double (allocating a new register).
344 *
345 * @return the newly created temporary
346 */
347 public RegisterOperand makeTempDouble() {
348 return new RegisterOperand(getDouble(), TypeReference.Double);
349 }
350
351 /**
352 * Make a temporary to hold a long (allocating a new register).
353 *
354 * @return the newly created temporary
355 */
356 public RegisterOperand makeTempLong() {
357 return new RegisterOperand(getLong(), TypeReference.Long);
358 }
359
360 /**
361 * Make a temporary to hold a condition code (allocating a new register).
362 *
363 * @return the newly created temporary
364 */
365 public RegisterOperand makeTempCondition() {
366 Register reg = getCondition();
367 return new RegisterOperand(reg, TypeReference.Int);
368 }
369
370 /**
371 * Make a temporary to hold a guard (validation) (allocating a new register).
372 *
373 * @return the newly created temporary
374 */
375 public RegisterOperand makeTempValidation() {
376 Register reg = getValidation();
377 reg.setValidation();
378 return new RegisterOperand(reg, TypeReference.VALIDATION_TYPE);
379 }
380
381 }