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 }