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