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.operand;
014    
015    import org.jikesrvm.runtime.RuntimeEntrypoints;
016    
017    /**
018     * Encode the semantic reason for a trap instruction.
019     *
020     * @see Operand
021     */
022    public final class TrapCodeOperand extends Operand {
023    
024      /**
025       * The trap code.
026       */
027      private final byte trapCode;
028    
029      /**
030       * Create a trap code operand
031       * @param why the trap code
032       */
033      private TrapCodeOperand(byte why) {
034        trapCode = why;
035      }
036    
037      /**
038       * Create a trap code operand for a null pointer check
039       * @return the newly created trap code operand
040       */
041      public static TrapCodeOperand NullPtr() {
042        return new TrapCodeOperand((byte) RuntimeEntrypoints.TRAP_NULL_POINTER);
043      }
044    
045      /**
046       * Create a trap code operand for an array bounds check
047       * @return the newly created trap code operand
048       */
049      public static TrapCodeOperand ArrayBounds() {
050        return new TrapCodeOperand((byte) RuntimeEntrypoints.TRAP_ARRAY_BOUNDS);
051      }
052    
053      /**
054       * Create a trap code operand for a divide by zero check
055       * @return the newly created trap code operand
056       */
057      public static TrapCodeOperand DivByZero() {
058        return new TrapCodeOperand((byte) RuntimeEntrypoints.TRAP_DIVIDE_BY_ZERO);
059      }
060    
061      /**
062       * Create a trap code operand for a stack overflow
063       * @return the newly created trap code operand
064       */
065      public static TrapCodeOperand StackOverflow() {
066        return new TrapCodeOperand((byte) RuntimeEntrypoints.TRAP_STACK_OVERFLOW);
067      }
068    
069      /**
070       * Create a trap code operand for a check cast
071       * @return the newly created trap code operand
072       */
073      public static TrapCodeOperand CheckCast() {
074        return new TrapCodeOperand((byte) RuntimeEntrypoints.TRAP_CHECKCAST);
075      }
076    
077      /**
078       * Create a trap code operand for a must implement
079       * @return the newly created trap code operand
080       */
081      public static TrapCodeOperand MustImplement() {
082        return new TrapCodeOperand((byte) RuntimeEntrypoints.TRAP_MUST_IMPLEMENT);
083      }
084    
085      /**
086       * Create a trap code operand for a must implement
087       * @return the newly created trap code operand
088       */
089      public static TrapCodeOperand StoreCheck() {
090        return new TrapCodeOperand((byte) RuntimeEntrypoints.TRAP_STORE_CHECK);
091      }
092    
093      /**
094       * Create a trap code operand for a regeneration trap
095       * @return the newly created trap code operand
096       */
097      public static TrapCodeOperand Regenerate() {
098        return new TrapCodeOperand((byte) RuntimeEntrypoints.TRAP_REGENERATE);
099      }
100    
101      /**
102       * Does the operand represent a null pointer check?
103       * @return <code>true</code> if it does and <code>false</code>
104       *         if it does not
105       */
106      public boolean isNullPtr() {
107        return trapCode == RuntimeEntrypoints.TRAP_NULL_POINTER;
108      }
109    
110      /**
111       * Does the operand represent an array bounds check ?
112       * @return <code>true</code> if it does and <code>false</code>
113       *         if it does not
114       */
115      public boolean isArrayBounds() {
116        return trapCode == RuntimeEntrypoints.TRAP_ARRAY_BOUNDS;
117      }
118    
119      /**
120       * Does the operand represent a divide by zero check?
121       * @return <code>true</code> if it does and <code>false</code>
122       *         if it does not
123       */
124      public boolean isDivByZero() {
125        return trapCode == RuntimeEntrypoints.TRAP_DIVIDE_BY_ZERO;
126      }
127    
128      /**
129       * Does the operand represent a stack overflow check?
130       * @return <code>true</code> if it does and <code>false</code>
131       *         if it does not
132       */
133      public boolean isStackOverflow() {
134        return trapCode == RuntimeEntrypoints.TRAP_STACK_OVERFLOW;
135      }
136    
137      /**
138       * Does the operand represent a check cast?
139       * @return <code>true</code> if it does and <code>false</code>
140       *         if it does not
141       */
142      public boolean isCheckCast() {
143        return trapCode == RuntimeEntrypoints.TRAP_CHECKCAST;
144      }
145    
146      /**
147       * Does the operand represent a must implement trap?
148       * @return <code>true</code> if it does and <code>false</code>
149       *         if it does not
150       */
151      public boolean isDoesImplement() {
152        return trapCode == RuntimeEntrypoints.TRAP_MUST_IMPLEMENT;
153      }
154    
155      /**
156       * Does the operand represent an array store check?
157       * @return <code>true</code> if it does and <code>false</code>
158       *         if it does not
159       */
160      public boolean isStoreCheck() {
161        return trapCode == RuntimeEntrypoints.TRAP_STORE_CHECK;
162      }
163    
164      /**
165       * Does the operand represent a regeneration trap?
166       * @return <code>true</code> if it does and <code>false</code>
167       *         if it does not
168       */
169      public boolean isRegenerate() {
170        return trapCode == RuntimeEntrypoints.TRAP_REGENERATE;
171      }
172    
173      @Override
174      public Operand copy() {
175        return new TrapCodeOperand(trapCode);
176      }
177    
178      @Override
179      public boolean similar(Operand op) {
180        return op instanceof TrapCodeOperand && ((TrapCodeOperand) op).trapCode == trapCode;
181      }
182    
183      /**
184       * Returns the string representation of this operand.
185       *
186       * @return a string representation of this operand.
187       */
188      @Override
189      public String toString() {
190        switch (trapCode) {
191          case RuntimeEntrypoints.TRAP_NULL_POINTER:
192            return "<NULL PTR>";
193          case RuntimeEntrypoints.TRAP_ARRAY_BOUNDS:
194            return "<ARRAY BOUNDS>";
195          case RuntimeEntrypoints.TRAP_DIVIDE_BY_ZERO:
196            return "<DIV BY ZERO>";
197          case RuntimeEntrypoints.TRAP_STACK_OVERFLOW:
198            return "<STACK OVERFLOW>";
199          case RuntimeEntrypoints.TRAP_CHECKCAST:
200            return "<CLASSCAST>";
201          case RuntimeEntrypoints.TRAP_MUST_IMPLEMENT:
202            return "<MUST IMPLEMENT>";
203          case RuntimeEntrypoints.TRAP_STORE_CHECK:
204            return "<OBJARRAY STORE CHECK>";
205          case RuntimeEntrypoints.TRAP_REGENERATE:
206            return "<REGENERATE>";
207          default:
208            return "<UNKNOWN TRAP>";
209        }
210      }
211    
212      /**
213       *  Return the numeric value representing the trap code; this is
214       * used by the assembler (on Intel) when generating code.
215       *
216       * @return Numeric value representing this trap code
217       */
218      public int getTrapCode() {
219        return trapCode;
220      }
221    
222    }