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 /**
174 * Return a new operand that is semantically equivalent to <code>this</code>.
175 *
176 * @return a copy of <code>this</code>
177 */
178 public Operand copy() {
179 return new TrapCodeOperand(trapCode);
180 }
181
182 /**
183 * Are two operands semantically equivalent?
184 *
185 * @param op other operand
186 * @return <code>true</code> if <code>this</code> and <code>op</code>
187 * are semantically equivalent or <code>false</code>
188 * if they are not.
189 */
190 public boolean similar(Operand op) {
191 return op instanceof TrapCodeOperand && ((TrapCodeOperand) op).trapCode == trapCode;
192 }
193
194 /**
195 * Returns the string representation of this operand.
196 *
197 * @return a string representation of this operand.
198 */
199 public String toString() {
200 switch (trapCode) {
201 case RuntimeEntrypoints.TRAP_NULL_POINTER:
202 return "<NULL PTR>";
203 case RuntimeEntrypoints.TRAP_ARRAY_BOUNDS:
204 return "<ARRAY BOUNDS>";
205 case RuntimeEntrypoints.TRAP_DIVIDE_BY_ZERO:
206 return "<DIV BY ZERO>";
207 case RuntimeEntrypoints.TRAP_STACK_OVERFLOW:
208 return "<STACK OVERFLOW>";
209 case RuntimeEntrypoints.TRAP_CHECKCAST:
210 return "<CLASSCAST>";
211 case RuntimeEntrypoints.TRAP_MUST_IMPLEMENT:
212 return "<MUST IMPLEMENT>";
213 case RuntimeEntrypoints.TRAP_STORE_CHECK:
214 return "<OBJARRAY STORE CHECK>";
215 case RuntimeEntrypoints.TRAP_REGENERATE:
216 return "<REGENERATE>";
217 default:
218 return "<UNKNOWN TRAP>";
219 }
220 }
221
222 /**
223 * Return the numeric value representing the trap code; this is
224 * used by the assembler (on Intel) when generating code.
225 *
226 * @return Numeric value representing this trap code
227 */
228 public int getTrapCode() {
229 return trapCode;
230 }
231
232 }