1 /*
2 * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package org.openjdk.asmtools.jdis;
24
25 import org.openjdk.asmtools.jasm.RuntimeConstants;
26 import static org.openjdk.asmtools.jasm.Tables.*;
27 import static org.openjdk.asmtools.jasm.OpcodeTables.*;
28 import org.openjdk.asmtools.jasm.Tables;
29 import java.io.IOException;
30 import java.io.PrintWriter;
31 import java.util.ArrayList;
32
33 /**
34 * instruction attributes
35 */
36 class iAtt {
37
38 /*-------------------------------------------------------- */
39 /* iAtt Fields */
40 private Options options;
41
42 short lnum = 0;
43 boolean referred = false; // from some other instruction
44 ArrayList<CodeData.LocVarData> vars;
45 ArrayList<CodeData.LocVarData> endvars;
46 ArrayList<TrapData> handlers;
47 ArrayList<TrapData> traps;
48 ArrayList<TrapData> endtraps;
49 StackMapData stackMapEntry;
50 CodeData code;
51 ClassData cls;
52 PrintWriter out; // =cls.out;
53 /*-------------------------------------------------------- */
54
55 public iAtt(CodeData code) {
56 this.code = code;
57 this.cls = code.meth.cls;
58 out = cls.out;
59 options = cls.options;
60 }
61
62 void add_var(CodeData.LocVarData var) {
63 if (vars == null) {
64 vars = new ArrayList<>(4);
65 }
66 vars.add(var);
67 }
68
69 void add_endvar(CodeData.LocVarData endvar) {
70 if (endvars == null) {
71 endvars = new ArrayList<>(4);
72 }
73 endvars.add(endvar);
74 }
75
76 void add_trap(TrapData trap) {
77 if (traps == null) {
78 traps = new ArrayList<>(4);
79 }
80 traps.add(trap);
81 }
82
83 void add_endtrap(TrapData endtrap) {
84 if (endtraps == null) {
85 endtraps = new ArrayList<>(4);
86 }
87 endtraps.add(endtrap);
88 }
89
90 void add_handler(TrapData endtrap) {
91 if (handlers == null) {
92 handlers = new ArrayList<>(4);
93 }
94 handlers.add(endtrap);
95 }
96
97 public void printEnds() throws IOException {
98 // prints additional information for instruction:
99 // end of local variable and trap scopes;
100 int len;
101 if ((endvars != null) && (options.contains(Options.PR.VAR))) {
102 len = endvars.size() - 1;
103 out.print("\t\tendvar");
104 for (CodeData.LocVarData line : endvars) {
105 out.print(" " + line.slot);
106 if (len-- > 0) {
107 out.print(",");
108 }
109 }
110 out.println(";");
111 }
112
113 if (endtraps != null) {
114 len = endtraps.size() - 1;
115 out.print("\t\tendtry");
116 for (TrapData line : endtraps) {
117 out.print(" " + line.ident());
118 if (len-- > 0) {
119 out.print(",");
120 }
121 }
122 out.println(";");
123 }
124 }
125
126 public void printBegins()
127 throws IOException {
128 // prints additional information for instruction:
129 // source line number;
130 // start of exception handler;
131 // begin of locvar and trap scopes;
132 boolean eitherOpt = options.contains(Options.PR.LNT) || options.contains(Options.PR.SRC);
133 boolean bothOpt = options.contains(Options.PR.LNT) && options.contains(Options.PR.SRC);
134 int k;
135
136 if ((lnum != 0) && eitherOpt) {
137 if (bothOpt) {
138 out.println("// " + lnum + ": " + cls.getSrcLine(lnum));
139 } else if (options.contains(Options.PR.LNT)) {
140 out.print(lnum);
141 } else if (options.contains(Options.PR.SRC)) {
142 out.println("// " + cls.getSrcLine(lnum));
143 }
144 }
145 out.print("\t");
146 if (handlers != null) {
147 for (TrapData line : handlers) {
148 out.print("\tcatch " + line.ident());
149 out.print(" " + cls.pool.getClassName(line.catch_cpx) + ";\n\t");
150 }
151 }
152 if (traps != null) {
153 int len = traps.size() - 1;
154 out.print("\ttry");
155 for (TrapData line : traps) {
156 out.print(" " + line.ident());
157 if (len-- > 0) {
158 out.print(",");
159 }
160 }
161 out.print(";\n\t");
162 }
163 if ((vars != null) && options.contains(Options.PR.VAR)) {
164 for (CodeData.LocVarData line : vars) {
165 out.println("\tvar " + line.slot + "; // " + cls.pool.getName(line.name_cpx) + ":" + cls.pool.getName(line.sig_cpx));
166 out.print("\t");
167 }
168 }
169 }
170
171 public void printMapList(int[] map) throws IOException {
172 boolean pr_cpx = options.contains(Options.PR.CPX);
173
174 for (int k = 0; k < map.length; k++) {
175 int fullmaptype = map[k];
176 int mt_val = fullmaptype & 0xFF;
177 StackMapType maptype = stackMapType(mt_val, out);
178 int argument = fullmaptype >> 8;
179 switch (maptype) {
180 case ITEM_Object:
181 if (pr_cpx) {
182 out.print(" #" + argument);
183 } else {
184 out.print(" ");
185 cls.pool.PrintConstant(out, argument);
186 }
187 break;
188 case ITEM_NewObject:
189 if (pr_cpx) {
190 out.print(" " + mt_val);
191 } else {
192 out.print(" " + maptype.printval());
193 }
194 out.print(" " + code.meth.lP + argument);
195 break;
196 default:
197 if (pr_cpx) {
198 out.print(" " + mt_val);
199 } else {
200 out.print(" " + maptype.printval());
201 }
202 }
203 out.print((k == (map.length - 1) ? ';' : ','));
204 }
205 }
206
207 public void printStackMap() throws IOException {
208 if (stackMapEntry == null) {
209 return;
210 }
211 boolean printed = false;
212 if (stackMapEntry.stackFrameType != null) {
213 out.print(Opcode.opc_stack_frame_type.parsekey()); // opcNamesTab[opc_stackframetype]);
214 out.print(" " + stackMapEntry.stackFrameType.parsekey() + ';');
215 out.print("\n\t\t");
216 printed = true;
217 }
218 int[] map = stackMapEntry.lockMap;
219 if ((map != null) && (map.length > 0)) {
220 out.print(Opcode.opc_locals_map.parsekey());
221 printMapList(map);
222 out.print("\n\t\t");
223 printed = true;
224 }
225 map = stackMapEntry.stackMap;
226 if ((map != null) && (map.length > 0)) {
227 out.print(Opcode.opc_stack_map.parsekey());
228 printMapList(map);
229 out.print("\n\t\t");
230 printed = true;
231 }
232 if (!printed) {
233 // empty attribute should be printed anyway - it should not
234 // be eliminated after jdis/jasm cycle
235 out.print(Opcode.opc_locals_map.parsekey() + " ;\n\t\t");
236 }
237 }
238 }