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    }