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 */
018 package org.apache.bcel.generic;
019
020 import org.apache.bcel.Constants;
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 1152072 2011-07-29 01:54:05Z dbrosius $
027 * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
028 */
029 public final class PUSH implements CompoundInstruction, VariableLengthInstruction,
030 InstructionConstants {
031
032 private Instruction instruction;
033
034
035 /**
036 * This constructor also applies for values of type short, char, byte
037 *
038 * @param cp Constant pool
039 * @param value to be pushed
040 */
041 public PUSH(ConstantPoolGen cp, int value) {
042 if ((value >= -1) && (value <= 5)) {
043 instruction = INSTRUCTIONS[Constants.ICONST_0 + value];
044 } else if ((value >= -128) && (value <= 127)) {
045 instruction = new BIPUSH((byte) value);
046 } else if ((value >= -32768) && (value <= 32767)) {
047 instruction = new SIPUSH((short) value);
048 } else {
049 instruction = new LDC(cp.addInteger(value));
050 }
051 }
052
053
054 /**
055 * @param cp Constant pool
056 * @param value to be pushed
057 */
058 public PUSH(ConstantPoolGen cp, boolean value) {
059 instruction = INSTRUCTIONS[Constants.ICONST_0 + (value ? 1 : 0)];
060 }
061
062
063 /**
064 * @param cp Constant pool
065 * @param value to be pushed
066 */
067 public PUSH(ConstantPoolGen cp, float value) {
068 if (value == 0.0) {
069 instruction = FCONST_0;
070 } else if (value == 1.0) {
071 instruction = FCONST_1;
072 } else if (value == 2.0) {
073 instruction = FCONST_2;
074 } else {
075 instruction = new LDC(cp.addFloat(value));
076 }
077 }
078
079
080 /**
081 * @param cp Constant pool
082 * @param value to be pushed
083 */
084 public PUSH(ConstantPoolGen cp, long value) {
085 if (value == 0) {
086 instruction = LCONST_0;
087 } else if (value == 1) {
088 instruction = LCONST_1;
089 } else {
090 instruction = new LDC2_W(cp.addLong(value));
091 }
092 }
093
094
095 /**
096 * @param cp Constant pool
097 * @param value to be pushed
098 */
099 public PUSH(ConstantPoolGen cp, double value) {
100 if (value == 0.0) {
101 instruction = DCONST_0;
102 } else if (value == 1.0) {
103 instruction = DCONST_1;
104 } else {
105 instruction = new LDC2_W(cp.addDouble(value));
106 }
107 }
108
109
110 /**
111 * @param cp Constant pool
112 * @param value to be pushed
113 */
114 public PUSH(ConstantPoolGen cp, String value) {
115 if (value == null) {
116 instruction = ACONST_NULL;
117 } else {
118 instruction = new LDC(cp.addString(value));
119 }
120 }
121
122 /**
123 *
124 * @param cp
125 * @param value
126 */
127 public PUSH(ConstantPoolGen cp, ObjectType value) {
128 if (value == null) {
129 instruction = ACONST_NULL;
130 } else {
131 instruction = new LDC(cp.addClass(value));
132 }
133 }
134
135 /**
136 * @param cp Constant pool
137 * @param value to be pushed
138 */
139 public PUSH(ConstantPoolGen cp, Number value) {
140 if ((value instanceof Integer) || (value instanceof Short) || (value instanceof Byte)) {
141 instruction = new PUSH(cp, value.intValue()).instruction;
142 } else if (value instanceof Double) {
143 instruction = new PUSH(cp, value.doubleValue()).instruction;
144 } else if (value instanceof Float) {
145 instruction = new PUSH(cp, value.floatValue()).instruction;
146 } else if (value instanceof Long) {
147 instruction = new PUSH(cp, value.longValue()).instruction;
148 } else {
149 throw new ClassGenException("What's this: " + value);
150 }
151 }
152
153
154 /**
155 * creates a push object from a Character value. Warning: Make sure not to attempt to allow
156 * autoboxing to create this value parameter, as an alternative constructor will be called
157 *
158 * @param cp Constant pool
159 * @param value to be pushed
160 */
161 public PUSH(ConstantPoolGen cp, Character value) {
162 this(cp, value.charValue());
163 }
164
165
166 /**
167 * @param cp Constant pool
168 * @param value to be pushed
169 */
170 public PUSH(ConstantPoolGen cp, Boolean value) {
171 this(cp, value.booleanValue());
172 }
173
174
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.toString() + " (PUSH)";
191 }
192 }