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