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