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 * @LastModified: Oct 2017 53 */ 54 public final class IntType extends NumberType { 55 protected IntType() {} 56 57 public String toString() { 58 return "int"; 59 } 60 61 public boolean identicalTo(Type other) { 62 return this == other; 63 } 64 65 public String toSignature() { 66 return "I"; 67 } 68 69 public com.sun.org.apache.bcel.internal.generic.Type toJCType() { 70 return com.sun.org.apache.bcel.internal.generic.Type.INT; 71 } 72 73 /** 74 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#distanceTo 75 */ 76 public int distanceTo(Type type) { 77 if (type == this) { 78 return 0; 79 } 80 else if (type == Type.Real) { 81 return 1; 82 } 83 else 84 return Integer.MAX_VALUE; 85 } 86 87 /** 88 * Translates an integer into an object of internal type <code>type</code>. 89 * 90 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 91 */ 92 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 93 final Type type) { 94 if (type == Type.Real) { 95 translateTo(classGen, methodGen, (RealType) type); 96 } 97 else if (type == Type.String) { 98 translateTo(classGen, methodGen, (StringType) type); 99 } 100 else if (type == Type.Boolean) { 101 translateTo(classGen, methodGen, (BooleanType) type); 102 } 103 else if (type == Type.Reference) { 104 translateTo(classGen, methodGen, (ReferenceType) type); 105 } 106 else { 107 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 108 toString(), type.toString()); 109 classGen.getParser().reportError(Constants.FATAL, err); 110 } 111 } 112 113 /** 114 * Expects an integer on the stack and pushes a real. 115 * 116 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 117 */ 118 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 119 RealType type) { 120 methodGen.getInstructionList().append(I2D); 121 } 122 123 /** 124 * Expects an integer on the stack and pushes its string value by calling 125 * <code>Integer.toString(int i)</code>. 126 * 127 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 128 */ 129 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 130 StringType type) { 131 final ConstantPoolGen cpg = classGen.getConstantPool(); 132 final InstructionList il = methodGen.getInstructionList(); 133 il.append(new INVOKESTATIC(cpg.addMethodref(INTEGER_CLASS, 134 "toString", 135 "(I)" + STRING_SIG))); 136 } 137 138 /** 139 * Expects an integer on the stack and pushes a 0 if its value is 0 and 140 * a 1 otherwise. 141 * 142 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 143 */ 144 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 145 BooleanType type) { 146 final InstructionList il = methodGen.getInstructionList(); 147 final BranchHandle falsec = il.append(new IFEQ(null)); 148 il.append(ICONST_1); 149 final BranchHandle truec = il.append(new GOTO(null)); 150 falsec.setTarget(il.append(ICONST_0)); 151 truec.setTarget(il.append(NOP)); 152 } 153 154 /** 155 * Expects an integer on the stack and translates it to a non-synthesized 156 * boolean. It does not push a 0 or a 1 but instead returns branchhandle 157 * list to be appended to the false list. 158 * 159 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateToDesynthesized 160 */ 161 public FlowList translateToDesynthesized(ClassGenerator classGen, 162 MethodGenerator methodGen, 163 BooleanType type) { 164 final InstructionList il = methodGen.getInstructionList(); 165 return new FlowList(il.append(new IFEQ(null))); 166 } 167 168 /** 169 * Expects an integer on the stack and pushes a boxed integer. 170 * Boxed integers are represented by an instance of 171 * <code>java.lang.Integer</code>. 172 * 173 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 174 */ 175 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 176 ReferenceType type) { 177 final ConstantPoolGen cpg = classGen.getConstantPool(); 178 final InstructionList il = methodGen.getInstructionList(); 179 il.append(new NEW(cpg.addClass(INTEGER_CLASS))); 180 il.append(DUP_X1); 181 il.append(SWAP); 182 il.append(new INVOKESPECIAL(cpg.addMethodref(INTEGER_CLASS, 183 "<init>", "(I)V"))); 184 } 185 186 /** 187 * Translates an integer into the Java type denoted by <code>clazz</code>. 188 * Expects an integer on the stack and pushes a number of the appropriate 189 * type after coercion. 190 */ 191 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 192 Class<?> clazz) { 193 final InstructionList il = methodGen.getInstructionList(); 194 if (clazz == Character.TYPE) { 195 il.append(I2C); 196 } 197 else if (clazz == Byte.TYPE) { 198 il.append(I2B); 199 } 200 else if (clazz == Short.TYPE) { 201 il.append(I2S); 202 } 203 else if (clazz == Integer.TYPE) { 204 il.append(NOP); 205 } 206 else if (clazz == Long.TYPE) { 207 il.append(I2L); 208 } 209 else if (clazz == Float.TYPE) { 210 il.append(I2F); 211 } 212 else if (clazz == Double.TYPE) { 213 il.append(I2D); 214 } 215 // Is Double <: clazz? I.e. clazz in { Double, Number, Object } 216 else if (clazz.isAssignableFrom(java.lang.Double.class)) { 217 il.append(I2D); 218 Type.Real.translateTo(classGen, methodGen, Type.Reference); 219 } 220 else { 221 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 222 toString(), clazz.getName()); 223 classGen.getParser().reportError(Constants.FATAL, err); 224 } 225 } 226 227 /** 228 * Translates an object of this type to its boxed representation. 229 */ 230 public void translateBox(ClassGenerator classGen, 231 MethodGenerator methodGen) { 232 translateTo(classGen, methodGen, Type.Reference); 233 } 234 235 /** 236 * Translates an object of this type to its unboxed representation. 237 */ 238 public void translateUnBox(ClassGenerator classGen, 239 MethodGenerator methodGen) { 240 final ConstantPoolGen cpg = classGen.getConstantPool(); 241 final InstructionList il = methodGen.getInstructionList(); 242 il.append(new CHECKCAST(cpg.addClass(INTEGER_CLASS))); 243 final int index = cpg.addMethodref(INTEGER_CLASS, 244 INT_VALUE, 245 INT_VALUE_SIG); 246 il.append(new INVOKEVIRTUAL(index)); 247 } 248 249 public Instruction ADD() { 250 return InstructionConst.IADD; 251 } 252 253 public Instruction SUB() { 254 return InstructionConst.ISUB; 255 } 256 257 public Instruction MUL() { 258 return InstructionConst.IMUL; 259 } 260 261 public Instruction DIV() { 262 return InstructionConst.IDIV; 263 } 264 265 public Instruction REM() { 266 return InstructionConst.IREM; 267 } 268 269 public Instruction NEG() { 270 return InstructionConst.INEG; 271 } 272 273 public Instruction LOAD(int slot) { 274 return new ILOAD(slot); 275 } 276 277 public Instruction STORE(int slot) { 278 return new ISTORE(slot); 279 } 280 281 public BranchInstruction GT(boolean tozero) { 282 return tozero ? (BranchInstruction) new IFGT(null) : 283 (BranchInstruction) new IF_ICMPGT(null); 284 } 285 286 public BranchInstruction GE(boolean tozero) { 287 return tozero ? (BranchInstruction) new IFGE(null) : 288 (BranchInstruction) new IF_ICMPGE(null); 289 } 290 291 public BranchInstruction LT(boolean tozero) { 292 return tozero ? (BranchInstruction) new IFLT(null) : 293 (BranchInstruction) new IF_ICMPLT(null); 294 } 295 296 public BranchInstruction LE(boolean tozero) { 297 return tozero ? (BranchInstruction) new IFLE(null) : 298 (BranchInstruction) new IF_ICMPLE(null); 299 } 300 }