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 }