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