1 /*
   2  * Copyright (c) 2017, 2019, 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.bcel.internal.generic;
  22 
  23 import com.sun.org.apache.bcel.internal.Const;
  24 
  25 /**
  26  * Wrapper class for push operations, which are implemented either as BIPUSH,
  27  * LDC or xCONST_n instructions.
  28  *
  29  * @version $Id$
  30  * @LastModified: Jun 2019
  31  */
  32 public final class PUSH implements CompoundInstruction, VariableLengthInstruction {
  33 
  34     private Instruction instruction;
  35 
  36 
  37     /**
  38      * This constructor also applies for values of type short, char, byte
  39      *
  40      * @param cp Constant pool
  41      * @param value to be pushed
  42      */
  43     public PUSH(final ConstantPoolGen cp, final int value) {
  44         if ((value >= -1) && (value <= 5)) {
  45             instruction = InstructionConst.getInstruction(Const.ICONST_0 + value);
  46         } else if (Instruction.isValidByte(value)) {
  47             instruction = new BIPUSH((byte) value);
  48         } else if (Instruction.isValidShort(value)) {
  49             instruction = new SIPUSH((short) value);
  50         } else {
  51             instruction = new LDC(cp.addInteger(value));
  52         }
  53     }
  54 
  55 
  56     /**
  57      * @param cp Constant pool
  58      * @param value to be pushed
  59      */
  60     public PUSH(final ConstantPoolGen cp, final boolean value) {
  61         instruction = InstructionConst.getInstruction(Const.ICONST_0 + (value ? 1 : 0));
  62     }
  63 
  64 
  65     /**
  66      * @param cp Constant pool
  67      * @param value to be pushed
  68      */
  69     public PUSH(final ConstantPoolGen cp, final float value) {
  70         if (value == 0.0) {
  71             instruction = InstructionConst.FCONST_0;
  72         } else if (value == 1.0) {
  73             instruction = InstructionConst.FCONST_1;
  74         } else if (value == 2.0) {
  75             instruction = InstructionConst.FCONST_2;
  76         } else {
  77             instruction = new LDC(cp.addFloat(value));
  78         }
  79     }
  80 
  81 
  82     /**
  83      * @param cp Constant pool
  84      * @param value to be pushed
  85      */
  86     public PUSH(final ConstantPoolGen cp, final long value) {
  87         if (value == 0) {
  88             instruction = InstructionConst.LCONST_0;
  89         } else if (value == 1) {
  90             instruction = InstructionConst.LCONST_1;
  91         } else {
  92             instruction = new LDC2_W(cp.addLong(value));
  93         }
  94     }
  95 
  96 
  97     /**
  98      * @param cp Constant pool
  99      * @param value to be pushed
 100      */
 101     public PUSH(final ConstantPoolGen cp, final double value) {
 102         if (value == 0.0) {
 103             instruction = InstructionConst.DCONST_0;
 104         } else if (value == 1.0) {
 105             instruction = InstructionConst.DCONST_1;
 106         } else {
 107             instruction = new LDC2_W(cp.addDouble(value));
 108         }
 109     }
 110 
 111 
 112     /**
 113      * @param cp Constant pool
 114      * @param value to be pushed
 115      */
 116     public PUSH(final ConstantPoolGen cp, final String value) {
 117         if (value == null) {
 118             instruction = InstructionConst.ACONST_NULL;
 119         } else {
 120             instruction = new LDC(cp.addString(value));
 121         }
 122     }
 123 
 124     /**
 125      *
 126      * @param cp
 127      * @param value
 128      * @since 6.0
 129      */
 130     public PUSH(final ConstantPoolGen cp, final ObjectType value) {
 131         if (value == null) {
 132             instruction = InstructionConst.ACONST_NULL;
 133         } else {
 134             instruction = new LDC(cp.addClass(value));
 135         }
 136     }
 137 
 138     /**
 139      * @param cp Constant pool
 140      * @param value to be pushed
 141      */
 142     public PUSH(final ConstantPoolGen cp, final Number value) {
 143         if ((value instanceof Integer) || (value instanceof Short) || (value instanceof Byte)) {
 144             instruction = new PUSH(cp, value.intValue()).instruction;
 145         } else if (value instanceof Double) {
 146             instruction = new PUSH(cp, value.doubleValue()).instruction;
 147         } else if (value instanceof Float) {
 148             instruction = new PUSH(cp, value.floatValue()).instruction;
 149         } else if (value instanceof Long) {
 150             instruction = new PUSH(cp, value.longValue()).instruction;
 151         } else {
 152             throw new ClassGenException("What's this: " + value);
 153         }
 154     }
 155 
 156 
 157     /**
 158      * creates a push object from a Character value. Warning: Make sure not to attempt to allow
 159      * autoboxing to create this value parameter, as an alternative constructor will be called
 160      *
 161      * @param cp Constant pool
 162      * @param value to be pushed
 163      */
 164     public PUSH(final ConstantPoolGen cp, final Character value) {
 165         this(cp, value.charValue());
 166     }
 167 
 168 
 169     /**
 170      * @param cp Constant pool
 171      * @param value to be pushed
 172      */
 173     public PUSH(final ConstantPoolGen cp, final Boolean value) {
 174         this(cp, value.booleanValue());
 175     }
 176 
 177 
 178     @Override
 179     public final InstructionList getInstructionList() {
 180         return new InstructionList(instruction);
 181     }
 182 
 183 
 184     public final Instruction getInstruction() {
 185         return instruction;
 186     }
 187 
 188 
 189     /**
 190      * @return mnemonic for instruction
 191      */
 192     @Override
 193     public String toString() {
 194         return instruction + " (PUSH)";
 195     }
 196 }