1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * https://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.bcel.generic;
20
21 import java.io.DataOutputStream;
22 import java.io.IOException;
23
24 import org.apache.bcel.Const;
25 import org.apache.bcel.util.ByteSequence;
26
27 /**
28 * RET - Return from subroutine
29 *
30 * <pre>
31 * Stack: ... -> ...
32 * </pre>
33 */
34 public class RET extends Instruction implements IndexedInstruction, TypedInstruction {
35
36 private boolean wide;
37 private int index; // index to local variable containg the return address
38
39 /**
40 * Default constructor needed for Instruction.readInstruction. Not to be used otherwise.
41 */
42 RET() {
43 }
44
45 /**
46 * Constructs a RET instruction.
47 *
48 * @param index index of local variable containing the return address.
49 */
50 public RET(final int index) {
51 super(Const.RET, (short) 2);
52 setIndex(index); // May set wide as side effect
53 }
54
55 /**
56 * Call corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call
57 * methods according to the class hierarchy in descending order, that is, the most specific visitXXX() call comes last.
58 *
59 * @param v Visitor object.
60 */
61 @Override
62 public void accept(final Visitor v) {
63 v.visitRET(this);
64 }
65
66 /**
67 * Dumps instruction as byte code to stream out.
68 *
69 * @param out Output stream.
70 */
71 @Override
72 public void dump(final DataOutputStream out) throws IOException {
73 if (wide) {
74 out.writeByte(Const.WIDE);
75 }
76 out.writeByte(super.getOpcode());
77 if (wide) {
78 out.writeShort(index);
79 } else {
80 out.writeByte(index);
81 }
82 }
83
84 /**
85 * @return index of local variable containg the return address.
86 */
87 @Override
88 public final int getIndex() {
89 return index;
90 }
91
92 /**
93 * @return return address type.
94 */
95 @Override
96 public Type getType(final ConstantPoolGen cp) {
97 return ReturnaddressType.NO_TARGET;
98 }
99
100 /**
101 * Reads needed data (for example index) from file.
102 */
103 @Override
104 protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException {
105 this.wide = wide;
106 if (wide) {
107 index = bytes.readUnsignedShort();
108 super.setLength(4);
109 } else {
110 index = bytes.readUnsignedByte();
111 super.setLength(2);
112 }
113 }
114
115 /**
116 * Sets index of local variable containg the return address
117 *
118 * @param index index of local variable containg the return address.
119 * @throws ClassGenException Thrown if index is out of bounds.
120 */
121 @Override
122 public final void setIndex(final int index) {
123 if (!isNonNegativeUShort(index)) {
124 throw new ClassGenException("Illegal value: " + index);
125 }
126 this.index = index;
127 setWide();
128 }
129
130 private void setWide() {
131 wide = index > Const.MAX_BYTE;
132 if (wide) {
133 super.setLength(4); // Including the wide byte
134 } else {
135 super.setLength(2);
136 }
137 }
138
139 /**
140 * @return mnemonic for instruction.
141 */
142 @Override
143 public String toString(final boolean verbose) {
144 return super.toString(verbose) + " " + index;
145 }
146 }