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    }