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 */
013package org.jikesrvm.compilers.opt.ir;
014
015import java.util.HashMap;
016import org.jikesrvm.VM;
017import org.jikesrvm.classloader.TypeReference;
018import org.jikesrvm.compilers.opt.ir.operand.Operand;
019import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
020
021public 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.<p>
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  public void removeRegister(Register reg) {
096    registerListremove(reg);
097  }
098
099  /**
100   * Gets a new address register.
101   *
102   * @return the newly created register object
103   */
104  public Register getAddress() {
105    Register reg = makeNewReg();
106    reg.setAddress();
107    return reg;
108  }
109
110  /**
111   * Gets a new integer register.
112   *
113   * @return the newly created register object
114   */
115  public Register getInteger() {
116    Register reg = makeNewReg();
117    reg.setInteger();
118    return reg;
119  }
120
121  /**
122   * Gets a new float register.
123   *
124   * @return the newly created register object
125   */
126  public Register getFloat() {
127    Register reg = makeNewReg();
128    reg.setFloat();
129    return reg;
130  }
131
132  /**
133   * Gets a new double register.
134   *
135   * @return the newly created register object
136   */
137  public Register getDouble() {
138    Register reg;
139    reg = makeNewReg();
140    reg.setDouble();
141    return reg;
142  }
143
144  /**
145   * Gets a new condition register.
146   *
147   * @return the newly created register object
148   */
149  public Register getCondition() {
150    Register reg = makeNewReg();
151    reg.setCondition();
152    return reg;
153  }
154
155  /**
156   * Gets a new long register.
157   *
158   * @return the newly created register object
159   */
160  public Register getLong() {
161    Register reg;
162    reg = makeNewReg();
163    reg.setLong();
164    return reg;
165  }
166
167  /**
168   * Gets a new validation register.
169   *
170   * @return the newly created register object
171   */
172  public Register getValidation() {
173    Register reg = makeNewReg();
174    reg.setValidation();
175    return reg;
176  }
177
178  /**
179   * Get a new register of the same type as the argument register
180   *
181   * @param template the register to get the type from
182   * @return the newly created register object
183   */
184  public Register getReg(Register template) {
185    switch (template.getType()) {
186      case Register.ADDRESS_TYPE:
187        return getAddress();
188      case Register.INTEGER_TYPE:
189        return getInteger();
190      case Register.FLOAT_TYPE:
191        return getFloat();
192      case Register.DOUBLE_TYPE:
193        return getDouble();
194      case Register.CONDITION_TYPE:
195        return getCondition();
196      case Register.LONG_TYPE:
197        return getLong();
198      case Register.VALIDATION_TYPE:
199        return getValidation();
200    }
201    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
202    return null;
203  }
204
205  /**
206   * Get a new register of the same type as the argument RegisterOperand
207   *
208   * @param template the register operand to get the type from
209   * @return the newly created register object
210   */
211  public Register getReg(RegisterOperand template) {
212    return getReg(template.getRegister());
213  }
214
215  /**
216   * Get a new register of the appropriate type to hold values of 'type'
217   *
218   * @param type the type of values that the register will hold
219   * @return the newly created register object
220   */
221  public Register getReg(TypeReference type) {
222    if (type.isLongType()) {
223      return getLong();
224    } else if (type.isDoubleType()) {
225      return getDouble();
226    } else if (type.isFloatType()) {
227      return getFloat();
228    } else if (type == TypeReference.VALIDATION_TYPE) {
229      return getValidation();
230    } else if (type.isWordLikeType() || type.isReferenceType()) {
231      return getAddress();
232    } else {
233      return getInteger();
234    }
235  }
236
237  /**
238   * MIR: Get the other half of the register pair that is
239   * associated with the argument register.
240   * <p>
241   * Note: this isn't incredibly general, but all architectures we're currently
242   * targeting need at most 2 machine registers to hold Java data values, so
243   * for now don't bother implementing a general mechanism.
244   *
245   * @param reg a register that may already be part of a register pair
246   * @return the register that is the other half of the register pair,
247   *         if the pairing doesn't already exist then it is created.
248   */
249  public Register getSecondReg(Register reg) {
250    Register otherHalf = _regPairs.get(reg);
251    if (otherHalf == null) {
252      otherHalf = getReg(reg);
253      _regPairs.put(reg, otherHalf);
254      if (reg.isLocal()) otherHalf.setLocal();
255      if (reg.isSSA()) otherHalf.setSSA();
256    }
257    return otherHalf;
258  }
259
260  /**
261   * Make a temporary register operand to hold values of the specified type
262   * (a new register is allocated).
263   *
264   * @param type the type of values to be held in the temp register
265   * @return the new temp
266   */
267  public RegisterOperand makeTemp(TypeReference type) {
268    return new RegisterOperand(getReg(type), type);
269  }
270
271  /**
272   * Make a temporary register operand that is similar to the argument.
273   *
274   * @param template the register operand to use as a template.
275   * @return the new temp
276   */
277  public RegisterOperand makeTemp(RegisterOperand template) {
278    RegisterOperand temp = new RegisterOperand(getReg(template), template.getType());
279    temp.addFlags(template.getFlags());
280    return temp;
281  }
282
283  /**
284   * Make a temporary register operand that can hold the values
285   * implied by the passed operand.
286   *
287   * @param op the operand to use as a template.
288   * @return the new temp
289   */
290  public RegisterOperand makeTemp(Operand op) {
291    RegisterOperand result;
292    if (op.isRegister()) {
293      result = makeTemp((RegisterOperand) op);
294    } else {
295      result = makeTemp(op.getType());
296    }
297    return result;
298  }
299
300  /**
301   * Make a temporary to hold an address (allocating a new register).
302   *
303   * @return the newly created temporary
304   */
305  public RegisterOperand makeTempAddress() {
306    return new RegisterOperand(getAddress(), TypeReference.Address);
307  }
308
309  /**
310   * Make a temporary to hold an address (allocating a new register).
311   *
312   * @return the newly created temporary
313   */
314  public RegisterOperand makeTempOffset() {
315    return new RegisterOperand(getAddress(), TypeReference.Offset);
316  }
317
318  /**
319   * Make a temporary to hold an int (allocating a new register).
320   *
321   * @return the newly created temporary
322   */
323  public RegisterOperand makeTempInt() {
324    return new RegisterOperand(getInteger(), TypeReference.Int);
325  }
326
327  /**
328   * Make a temporary to hold a boolean (allocating a new register).
329   *
330   * @return the newly created temporary
331   */
332  public RegisterOperand makeTempBoolean() {
333    return new RegisterOperand(getInteger(), TypeReference.Boolean);
334  }
335
336  /**
337   * Make a temporary to hold a float (allocating a new register).
338   *
339   * @return the newly created temporary
340   */
341  public RegisterOperand makeTempFloat() {
342    return new RegisterOperand(getFloat(), TypeReference.Float);
343  }
344
345  /**
346   * Make a temporary to hold a double (allocating a new register).
347   *
348   * @return the newly created temporary
349   */
350  public RegisterOperand makeTempDouble() {
351    return new RegisterOperand(getDouble(), TypeReference.Double);
352  }
353
354  /**
355   * Make a temporary to hold a long (allocating a new register).
356   *
357   * @return the newly created temporary
358   */
359  public RegisterOperand makeTempLong() {
360    return new RegisterOperand(getLong(), TypeReference.Long);
361  }
362
363  /**
364   * Make a temporary to hold a condition code (allocating a new register).
365   *
366   * @return the newly created temporary
367   */
368  public RegisterOperand makeTempCondition() {
369    Register reg = getCondition();
370    return new RegisterOperand(reg, TypeReference.Int);
371  }
372
373  /**
374   * Make a temporary to hold a guard (validation) (allocating a new register).
375   *
376   * @return the newly created temporary
377   */
378  public RegisterOperand makeTempValidation() {
379    Register reg = getValidation();
380    reg.setValidation();
381    return new RegisterOperand(reg, TypeReference.VALIDATION_TYPE);
382  }
383
384}