1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package com.sun.org.apache.xalan.internal.xsltc.compiler.util; 22 23 import com.sun.org.apache.bcel.internal.generic.BranchHandle; 24 import com.sun.org.apache.bcel.internal.generic.BranchInstruction; 25 import com.sun.org.apache.bcel.internal.generic.CHECKCAST; 26 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 27 import com.sun.org.apache.bcel.internal.generic.GOTO; 28 import com.sun.org.apache.bcel.internal.generic.IFEQ; 29 import com.sun.org.apache.bcel.internal.generic.IFGE; 30 import com.sun.org.apache.bcel.internal.generic.IFGT; 31 import com.sun.org.apache.bcel.internal.generic.IFLE; 32 import com.sun.org.apache.bcel.internal.generic.IFLT; 33 import com.sun.org.apache.bcel.internal.generic.IF_ICMPGE; 34 import com.sun.org.apache.bcel.internal.generic.IF_ICMPGT; 35 import com.sun.org.apache.bcel.internal.generic.IF_ICMPLE; 36 import com.sun.org.apache.bcel.internal.generic.IF_ICMPLT; 37 import com.sun.org.apache.bcel.internal.generic.ILOAD; 38 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; 39 import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; 40 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; 41 import com.sun.org.apache.bcel.internal.generic.ISTORE; 42 import com.sun.org.apache.bcel.internal.generic.Instruction; 43 import com.sun.org.apache.bcel.internal.generic.InstructionConst; 44 import com.sun.org.apache.bcel.internal.generic.InstructionList; 45 import com.sun.org.apache.bcel.internal.generic.NEW; 46 import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants; 47 import com.sun.org.apache.xalan.internal.xsltc.compiler.FlowList; 48 49 /** 50 * @author Jacek Ambroziak 51 * @author Santiago Pericas-Geertsen 52 */ 53 public final class IntType extends NumberType { 54 protected IntType() {} 55 56 public String toString() { 57 return "int"; 58 } 59 60 public boolean identicalTo(Type other) { 61 return this == other; 62 } 63 64 public String toSignature() { 65 return "I"; 66 } 67 68 public com.sun.org.apache.bcel.internal.generic.Type toJCType() { 69 return com.sun.org.apache.bcel.internal.generic.Type.INT; 70 } 71 72 /** 73 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#distanceTo 74 */ 75 public int distanceTo(Type type) { 76 if (type == this) { 77 return 0; 78 } 79 else if (type == Type.Real) { 80 return 1; 81 } 82 else 83 return Integer.MAX_VALUE; 84 } 85 86 /** 87 * Translates an integer into an object of internal type <code>type</code>. 88 * 89 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 90 */ 91 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 92 final Type type) { 93 if (type == Type.Real) { 94 translateTo(classGen, methodGen, (RealType) type); 95 } 96 else if (type == Type.String) { 97 translateTo(classGen, methodGen, (StringType) type); 98 } 99 else if (type == Type.Boolean) { 100 translateTo(classGen, methodGen, (BooleanType) type); 101 } 102 else if (type == Type.Reference) { 103 translateTo(classGen, methodGen, (ReferenceType) type); 104 } 105 else { 106 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 107 toString(), type.toString()); 108 classGen.getParser().reportError(Constants.FATAL, err); 109 } 110 } 111 112 /** 113 * Expects an integer on the stack and pushes a real. 114 * 115 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 116 */ 117 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 118 RealType type) { 119 methodGen.getInstructionList().append(I2D); 120 } 121 122 /** 123 * Expects an integer on the stack and pushes its string value by calling 124 * <code>Integer.toString(int i)</code>. 125 * 126 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 127 */ 128 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 129 StringType type) { 130 final ConstantPoolGen cpg = classGen.getConstantPool(); 131 final InstructionList il = methodGen.getInstructionList(); 132 il.append(new INVOKESTATIC(cpg.addMethodref(INTEGER_CLASS, 133 "toString", 134 "(I)" + STRING_SIG))); 135 } 136 137 /** 138 * Expects an integer on the stack and pushes a 0 if its value is 0 and 139 * a 1 otherwise. 140 * 141 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 142 */ 143 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 144 BooleanType type) { 145 final InstructionList il = methodGen.getInstructionList(); 146 final BranchHandle falsec = il.append(new IFEQ(null)); 147 il.append(ICONST_1); 148 final BranchHandle truec = il.append(new GOTO(null)); 149 falsec.setTarget(il.append(ICONST_0)); 150 truec.setTarget(il.append(NOP)); 151 } 152 153 /** 154 * Expects an integer on the stack and translates it to a non-synthesized 155 * boolean. It does not push a 0 or a 1 but instead returns branchhandle 156 * list to be appended to the false list. 157 * 158 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateToDesynthesized 159 */ 160 public FlowList translateToDesynthesized(ClassGenerator classGen, 161 MethodGenerator methodGen, 162 BooleanType type) { 163 final InstructionList il = methodGen.getInstructionList(); 164 return new FlowList(il.append(new IFEQ(null))); 165 } 166 167 /** 168 * Expects an integer on the stack and pushes a boxed integer. 169 * Boxed integers are represented by an instance of 170 * <code>java.lang.Integer</code>. 171 * 172 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 173 */ 174 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 175 ReferenceType type) { 176 final ConstantPoolGen cpg = classGen.getConstantPool(); 177 final InstructionList il = methodGen.getInstructionList(); 178 il.append(new NEW(cpg.addClass(INTEGER_CLASS))); 179 il.append(DUP_X1); 180 il.append(SWAP); 181 il.append(new INVOKESPECIAL(cpg.addMethodref(INTEGER_CLASS, 182 "<init>", "(I)V"))); 183 } 184 185 /** 186 * Translates an integer into the Java type denoted by <code>clazz</code>. 187 * Expects an integer on the stack and pushes a number of the appropriate 188 * type after coercion. 189 */ 190 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 191 Class clazz) { 192 final InstructionList il = methodGen.getInstructionList(); 193 if (clazz == Character.TYPE) { 194 il.append(I2C); 195 } 196 else if (clazz == Byte.TYPE) { 197 il.append(I2B); 198 } 199 else if (clazz == Short.TYPE) { 200 il.append(I2S); 201 } 202 else if (clazz == Integer.TYPE) { 203 il.append(NOP); 204 } 205 else if (clazz == Long.TYPE) { 206 il.append(I2L); 207 } 208 else if (clazz == Float.TYPE) { 209 il.append(I2F); 210 } 211 else if (clazz == Double.TYPE) { 212 il.append(I2D); 213 } 214 // Is Double <: clazz? I.e. clazz in { Double, Number, Object } 215 else if (clazz.isAssignableFrom(java.lang.Double.class)) { 216 il.append(I2D); 217 Type.Real.translateTo(classGen, methodGen, Type.Reference); 218 } 219 else { 220 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 221 toString(), clazz.getName()); 222 classGen.getParser().reportError(Constants.FATAL, err); 223 } 224 } 225 226 /** 227 * Translates an object of this type to its boxed representation. 228 */ 229 public void translateBox(ClassGenerator classGen, 230 MethodGenerator methodGen) { 231 translateTo(classGen, methodGen, Type.Reference); 232 } 233 234 /** 235 * Translates an object of this type to its unboxed representation. 236 */ 237 public void translateUnBox(ClassGenerator classGen, 238 MethodGenerator methodGen) { 239 final ConstantPoolGen cpg = classGen.getConstantPool(); 240 final InstructionList il = methodGen.getInstructionList(); 241 il.append(new CHECKCAST(cpg.addClass(INTEGER_CLASS))); 242 final int index = cpg.addMethodref(INTEGER_CLASS, 243 INT_VALUE, 244 INT_VALUE_SIG); 245 il.append(new INVOKEVIRTUAL(index)); 246 } 247 248 public Instruction ADD() { 249 return InstructionConst.IADD; 250 } 251 252 public Instruction SUB() { 253 return InstructionConst.ISUB; 254 } 255 256 public Instruction MUL() { 257 return InstructionConst.IMUL; 258 } 259 260 public Instruction DIV() { 261 return InstructionConst.IDIV; 262 } 263 264 public Instruction REM() { 265 return InstructionConst.IREM; 266 } 267 268 public Instruction NEG() { 269 return InstructionConst.INEG; 270 } 271 272 public Instruction LOAD(int slot) { 273 return new ILOAD(slot); 274 } 275 276 public Instruction STORE(int slot) { 277 return new ISTORE(slot); 278 } 279 280 public BranchInstruction GT(boolean tozero) { 281 return tozero ? (BranchInstruction) new IFGT(null) : 282 (BranchInstruction) new IF_ICMPGT(null); 283 } 284 285 public BranchInstruction GE(boolean tozero) { 286 return tozero ? (BranchInstruction) new IFGE(null) : 287 (BranchInstruction) new IF_ICMPGE(null); 288 } 289 290 public BranchInstruction LT(boolean tozero) { 291 return tozero ? (BranchInstruction) new IFLT(null) : 292 (BranchInstruction) new IF_ICMPLT(null); 293 } 294 295 public BranchInstruction LE(boolean tozero) { 296 return tozero ? (BranchInstruction) new IFLE(null) : 297 (BranchInstruction) new IF_ICMPLE(null); 298 } 299 }