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 be pushed. 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 * @param cp Constant pool 049 * @param value to be pushed 050 */ 051 public PUSH(final ConstantPoolGen cp, final boolean value) { 052 Objects.requireNonNull(cp, "cp"); 053 instruction = InstructionConst.getInstruction(Const.ICONST_0 + (value ? 1 : 0)); 054 } 055 056 /** 057 * @param cp Constant pool 058 * @param value to be pushed 059 */ 060 public PUSH(final ConstantPoolGen cp, final Boolean value) { 061 this(cp, value.booleanValue()); 062 } 063 064 /** 065 * creates a push object from a Character value. Warning: Make sure not to attempt to allow autoboxing to create this 066 * value parameter, as an alternative constructor will be called 067 * 068 * @param cp Constant pool 069 * @param value to be pushed 070 */ 071 public PUSH(final ConstantPoolGen cp, final Character value) { 072 this(cp, value.charValue()); 073 } 074 075 /** 076 * @param cp Constant pool 077 * @param value to be pushed 078 */ 079 public PUSH(final ConstantPoolGen cp, final double value) { 080 if (value == 0.0) { 081 instruction = InstructionConst.DCONST_0; 082 } else if (value == 1.0) { 083 instruction = InstructionConst.DCONST_1; 084 } else { 085 instruction = new LDC2_W(cp.addDouble(value)); 086 } 087 } 088 089 /** 090 * @param cp Constant pool 091 * @param value to be pushed 092 */ 093 public PUSH(final ConstantPoolGen cp, final float value) { 094 if (value == 0.0) { 095 instruction = InstructionConst.FCONST_0; 096 } else if (value == 1.0) { 097 instruction = InstructionConst.FCONST_1; 098 } else if (value == 2.0) { 099 instruction = InstructionConst.FCONST_2; 100 } else { 101 instruction = new LDC(cp.addFloat(value)); 102 } 103 } 104 105 /** 106 * This constructor also applies for values of type short, char, byte 107 * 108 * @param cp Constant pool 109 * @param value to be pushed 110 */ 111 public PUSH(final ConstantPoolGen cp, final int value) { 112 if (value >= -1 && value <= 5) { 113 instruction = InstructionConst.getInstruction(Const.ICONST_0 + value); 114 } else if (Instruction.isValidByte(value)) { 115 instruction = new BIPUSH((byte) value); 116 } else if (Instruction.isValidShort(value)) { 117 instruction = new SIPUSH((short) value); 118 } else { 119 instruction = new LDC(cp.addInteger(value)); 120 } 121 } 122 123 /** 124 * @param cp Constant pool 125 * @param value to be pushed 126 */ 127 public PUSH(final ConstantPoolGen cp, final long value) { 128 if (value == 0) { 129 instruction = InstructionConst.LCONST_0; 130 } else if (value == 1) { 131 instruction = InstructionConst.LCONST_1; 132 } else { 133 instruction = new LDC2_W(cp.addLong(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 * @param cp 158 * @param value 159 * @since 6.0 160 */ 161 public PUSH(final ConstantPoolGen cp, final ObjectType value) { 162 if (value == null) { 163 instruction = InstructionConst.ACONST_NULL; 164 } else { 165 instruction = new LDC(cp.addClass(value)); 166 } 167 } 168 169 /** 170 * @param cp Constant pool 171 * @param value to be pushed 172 */ 173 public PUSH(final ConstantPoolGen cp, final String value) { 174 if (value == null) { 175 instruction = InstructionConst.ACONST_NULL; 176 } else { 177 instruction = new LDC(cp.addString(value)); 178 } 179 } 180 181 public Instruction getInstruction() { 182 return instruction; 183 } 184 185 @Override 186 public InstructionList getInstructionList() { 187 return new InstructionList(instruction); 188 } 189 190 /** 191 * @return mnemonic for instruction 192 */ 193 @Override 194 public String toString() { 195 return instruction + " (PUSH)"; 196 } 197}