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