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 }