1 /*
2 * Copyright (c) 1996, 2014, 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.jasm;
24
25 import java.io.IOException;
26 import java.util.ArrayList;
27
28 /**
29 *
30 */
31 class SwitchTable {
32
33 Argument deflabel = null;
34 ArrayList<Argument> labels = new ArrayList<>();
35 ArrayList<Integer> keys = new ArrayList<>();
36
37 // for tableswitch:
38 Argument[] resLabels;
39 int high, low;
40
41 int pc, pad;
42 Environment env;
43
44 SwitchTable(Environment env) {
45 this.env = env;
46 }
47
48 void addEntry(int key, Argument label) {
49 keys.add(key);
50 labels.add(label);
51 }
52
53 // for lookupswitch:
54 int calcLookupSwitch(int pc) {
55 this.pc = pc;
56 pad = ((3 - pc) & 0x3);
57 int len = 1 + pad + (keys.size() + 1) * 8;
58 if (deflabel == null) {
59 deflabel = new Argument(pc + len);
60 }
61 return len;
62 }
63
64 void writeLookupSwitch(CheckedDataOutputStream out) throws IOException {
65 env.traceln(" writeLookupSwitch: pc=" + pc + " pad=" + pad + " deflabel=" + deflabel.arg);
66 int k;
67 for (k = 0; k < pad; k++) {
68 out.writeByte(0);
69 }
70 out.writeInt(deflabel.arg - pc);
71 out.writeInt(keys.size());
72 for (k = 0; k < keys.size(); k++) {
73 out.writeInt(keys.get(k));
74 out.writeInt((labels.get(k)).arg - pc);
75 }
76 }
77
78 int recalcTableSwitch(int pc) {
79 int k;
80 int numpairs = keys.size();
81 int high1 = Integer.MIN_VALUE, low1 = Integer.MAX_VALUE;
82 int numslots = 0;
83 if (numpairs > 0) {
84 for (k = 0; k < numpairs; k++) {
85 int key = keys.get(k);
86 if (key > high1) {
87 high1 = key;
88 }
89 if (key < low1) {
90 low1 = key;
91 }
92 }
93 numslots = high1 - low1 + 1;
94 }
95 // if (numslots>2000) env.error("long.switchtable", "2000");
96 env.traceln(" recalcTableSwitch: low=" + low1 + " high=" + high1);
97 this.pc = pc;
98 pad = ((3 - pc) & 0x3);
99 int len = 1 + pad + (numslots + 3) * 4;
100 if (deflabel == null) {
101 deflabel = new Argument(pc + len);
102 }
103 Argument[] resLabels1 = new Argument[numslots];
104 for (k = 0; k < numslots; k++) {
105 resLabels1[k] = deflabel;
106 }
107 for (k = 0; k < numpairs; k++) {
108 env.traceln(" keys.data[" + k + "]=" + keys.get(k));
109 resLabels1[keys.get(k) - low1] = labels.get(k);
110 }
111 this.resLabels = resLabels1;
112 this.labels = null;
113 this.keys = null;
114 this.high = high1;
115 this.low = low1;
116 return len;
117 }
118
119 void writeTableSwitch(CheckedDataOutputStream out) throws IOException {
120 int k;
121 for (k = 0; k < pad; k++) {
122 out.writeByte(0);
123 }
124 out.writeInt(deflabel.arg - pc);
125 out.writeInt(low);
126 out.writeInt(high);
127 for (k = 0; k < resLabels.length; k++) {
128 out.writeInt(resLabels[k].arg - pc);
129 }
130 }
131 }