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 }