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}