001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.bcel.generic; 020 021import java.util.Objects; 022 023import org.apache.bcel.Const; 024 025/** 026 * Wrapper class for push operations, which are implemented either as BIPUSH, LDC or xCONST_n instructions. 027 */ 028public final class PUSH implements CompoundInstruction, VariableLengthInstruction, InstructionConstants { 029 030 private final Instruction instruction; 031 032 /** 033 * Pushes an array type constant, for example {@code int[].class}, {@code String[].class}, and so on. 034 * 035 * @param cp generated constant pool. 036 * @param value to push. 037 * @since 6.7.0 038 */ 039 public PUSH(final ConstantPoolGen cp, final ArrayType value) { 040 if (value == null) { 041 instruction = InstructionConst.ACONST_NULL; 042 } else { 043 instruction = new LDC(cp.addArrayClass(value)); 044 } 045 } 046 047 /** 048 * Constructs a PUSH for a boolean value. 049 * 050 * @param cp Constant pool. 051 * @param value to push. 052 */ 053 public PUSH(final ConstantPoolGen cp, final boolean value) { 054 Objects.requireNonNull(cp, "cp"); 055 instruction = InstructionConst.getInstruction(Const.ICONST_0 + (value ? 1 : 0)); 056 } 057 058 /** 059 * Constructs a PUSH for a Boolean value. 060 * 061 * @param cp Constant pool. 062 * @param value to push. 063 */ 064 public PUSH(final ConstantPoolGen cp, final Boolean value) { 065 this(cp, value.booleanValue()); 066 } 067 068 /** 069 * creates a push object from a Character value. Warning: Make sure not to attempt to allow autoboxing to create this 070 * value parameter, as an alternative constructor will be called 071 * 072 * @param cp Constant pool. 073 * @param value to push. 074 */ 075 public PUSH(final ConstantPoolGen cp, final Character value) { 076 this(cp, value.charValue()); 077 } 078 079 /** 080 * Constructs a PUSH for a double value. 081 * 082 * @param cp Constant pool. 083 * @param value to push. 084 */ 085 public PUSH(final ConstantPoolGen cp, final double value) { 086 if (value == 0.0) { 087 instruction = InstructionConst.DCONST_0; 088 } else if (value == 1.0) { 089 instruction = InstructionConst.DCONST_1; 090 } else { 091 instruction = new LDC2_W(cp.addDouble(value)); 092 } 093 } 094 095 /** 096 * Constructs a PUSH for a float value. 097 * 098 * @param cp Constant pool. 099 * @param value to push. 100 */ 101 public PUSH(final ConstantPoolGen cp, final float value) { 102 if (value == 0.0) { 103 instruction = InstructionConst.FCONST_0; 104 } else if (value == 1.0) { 105 instruction = InstructionConst.FCONST_1; 106 } else if (value == 2.0) { 107 instruction = InstructionConst.FCONST_2; 108 } else { 109 instruction = new LDC(cp.addFloat(value)); 110 } 111 } 112 113 /** 114 * This constructor also applies for values of type short, char, byte 115 * 116 * @param cp Constant pool. 117 * @param value to push. 118 */ 119 public PUSH(final ConstantPoolGen cp, final int value) { 120 if (value >= -1 && value <= 5) { 121 instruction = InstructionConst.getInstruction(Const.ICONST_0 + value); 122 } else if (Instruction.isValidByte(value)) { 123 instruction = new BIPUSH((byte) value); 124 } else if (Instruction.isValidShort(value)) { 125 instruction = new SIPUSH((short) value); 126 } else { 127 instruction = new LDC(cp.addInteger(value)); 128 } 129 } 130 131 /** 132 * Constructs a PUSH for a long value. 133 * 134 * @param cp Constant pool. 135 * @param value to push. 136 */ 137 public PUSH(final ConstantPoolGen cp, final long value) { 138 if (value == 0) { 139 instruction = InstructionConst.LCONST_0; 140 } else if (value == 1) { 141 instruction = InstructionConst.LCONST_1; 142 } else { 143 instruction = new LDC2_W(cp.addLong(value)); 144 } 145 } 146 147 /** 148 * Constructs a PUSH for a Number value. 149 * 150 * @param cp Constant pool. 151 * @param value to push. 152 */ 153 public PUSH(final ConstantPoolGen cp, final Number value) { 154 if (value instanceof Integer || value instanceof Short || value instanceof Byte) { 155 instruction = new PUSH(cp, value.intValue()).instruction; 156 } else if (value instanceof Double) { 157 instruction = new PUSH(cp, value.doubleValue()).instruction; 158 } else if (value instanceof Float) { 159 instruction = new PUSH(cp, value.floatValue()).instruction; 160 } else if (value instanceof Long) { 161 instruction = new PUSH(cp, value.longValue()).instruction; 162 } else { 163 throw new ClassGenException("What's this: " + value); 164 } 165 } 166 167 /** 168 * Constructs a PUSH for an ObjectType value. 169 * 170 * @param cp The constant pool. 171 * @param value to push. 172 * @since 6.0 173 */ 174 public PUSH(final ConstantPoolGen cp, final ObjectType value) { 175 if (value == null) { 176 instruction = InstructionConst.ACONST_NULL; 177 } else { 178 instruction = new LDC(cp.addClass(value)); 179 } 180 } 181 182 /** 183 * Constructs a PUSH for a String value. 184 * 185 * @param cp Constant pool. 186 * @param value to push. 187 */ 188 public PUSH(final ConstantPoolGen cp, final String value) { 189 if (value == null) { 190 instruction = InstructionConst.ACONST_NULL; 191 } else { 192 instruction = new LDC(cp.addString(value)); 193 } 194 } 195 196 /** 197 * Gets the instruction. 198 * 199 * @return The instruction. 200 */ 201 public Instruction getInstruction() { 202 return instruction; 203 } 204 205 @Override 206 public InstructionList getInstructionList() { 207 return new InstructionList(instruction); 208 } 209 210 /** 211 * @return mnemonic for instruction. 212 */ 213 @Override 214 public String toString() { 215 return instruction + " (PUSH)"; 216 } 217}