1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  */
18 package org.apache.bcel.generic;
19 
20 import org.apache.bcel.Const;
21 
22 /**
23  * Wrapper class for push operations, which are implemented either as BIPUSH,
24  * LDC or xCONST_n instructions.
25  *
26  * @version $Id$
27  */
28 public final class PUSH implements CompoundInstruction, VariableLengthInstruction, InstructionConstants {
29 
30     private Instruction instruction;
31 
32 
33     /**
34      * This constructor also applies for values of type short, char, byte
35      *
36      * @param cp Constant pool
37      * @param value to be pushed
38      */
PUSH(final ConstantPoolGen cp, final int value)39     public PUSH(final ConstantPoolGen cp, final int value) {
40         if ((value >= -1) && (value <= 5)) {
41             instruction = InstructionConst.getInstruction(Const.ICONST_0 + value);
42         } else if (Instruction.isValidByte(value)) {
43             instruction = new BIPUSH((byte) value);
44         } else if (Instruction.isValidShort(value)) {
45             instruction = new SIPUSH((short) value);
46         } else {
47             instruction = new LDC(cp.addInteger(value));
48         }
49     }
50 
51 
52     /**
53      * @param cp Constant pool
54      * @param value to be pushed
55      */
PUSH(final ConstantPoolGen cp, final boolean value)56     public PUSH(final ConstantPoolGen cp, final boolean value) {
57         instruction = InstructionConst.getInstruction(Const.ICONST_0 + (value ? 1 : 0));
58     }
59 
60 
61     /**
62      * @param cp Constant pool
63      * @param value to be pushed
64      */
PUSH(final ConstantPoolGen cp, final float value)65     public PUSH(final ConstantPoolGen cp, final float value) {
66         if (value == 0.0) {
67             instruction = InstructionConst.FCONST_0;
68         } else if (value == 1.0) {
69             instruction = InstructionConst.FCONST_1;
70         } else if (value == 2.0) {
71             instruction = InstructionConst.FCONST_2;
72         } else {
73             instruction = new LDC(cp.addFloat(value));
74         }
75     }
76 
77 
78     /**
79      * @param cp Constant pool
80      * @param value to be pushed
81      */
PUSH(final ConstantPoolGen cp, final long value)82     public PUSH(final ConstantPoolGen cp, final long value) {
83         if (value == 0) {
84             instruction = InstructionConst.LCONST_0;
85         } else if (value == 1) {
86             instruction = InstructionConst.LCONST_1;
87         } else {
88             instruction = new LDC2_W(cp.addLong(value));
89         }
90     }
91 
92 
93     /**
94      * @param cp Constant pool
95      * @param value to be pushed
96      */
PUSH(final ConstantPoolGen cp, final double value)97     public PUSH(final ConstantPoolGen cp, final double value) {
98         if (value == 0.0) {
99             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      */
PUSH(final ConstantPoolGen cp, final String value)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      */
PUSH(final ConstantPoolGen cp, final ObjectType value)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      */
PUSH(final ConstantPoolGen cp, final Number value)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      */
PUSH(final ConstantPoolGen cp, final Character value)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      */
PUSH(final ConstantPoolGen cp, final Boolean value)169     public PUSH(final ConstantPoolGen cp, final Boolean value) {
170         this(cp, value.booleanValue());
171     }
172 
173 
174     @Override
getInstructionList()175     public final InstructionList getInstructionList() {
176         return new InstructionList(instruction);
177     }
178 
179 
getInstruction()180     public final Instruction getInstruction() {
181         return instruction;
182     }
183 
184 
185     /**
186      * @return mnemonic for instruction
187      */
188     @Override
toString()189     public String toString() {
190         return instruction + " (PUSH)";
191     }
192 }
193