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.operand;
014
015import org.jikesrvm.runtime.RuntimeEntrypoints;
016
017/**
018 * Encode the semantic reason for a trap instruction.
019 *
020 * @see Operand
021 */
022public 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}