comparison graal/Compiler/src/com/sun/c1x/util/Util.java @ 2507:9ec15d6914ca

Pull over of compiler from maxine repository.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 27 Apr 2011 11:43:22 +0200
parents
children
comparison
equal deleted inserted replaced
2506:4a3bf8a5bf41 2507:9ec15d6914ca
1 /*
2 * Copyright (c) 2009, 2011, 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 com.sun.c1x.util;
24
25 import java.util.*;
26
27 import com.sun.c1x.*;
28 import com.sun.c1x.debug.*;
29 import com.sun.c1x.ir.*;
30 import com.sun.cri.ci.*;
31 import com.sun.cri.ri.*;
32
33 /**
34 * The {@code Util} class contains a motley collection of utility methods used throughout the compiler.
35 *
36 * @author Ben L. Titzer
37 * @author Doug Simon
38 */
39 public class Util {
40
41 public static final int PRINTING_LINE_WIDTH = 40;
42 public static final char SECTION_CHARACTER = '*';
43 public static final char SUB_SECTION_CHARACTER = '=';
44 public static final char SEPERATOR_CHARACTER = '-';
45
46 public static RuntimeException unimplemented() {
47 throw new InternalError("unimplemented");
48 }
49
50 public static RuntimeException unimplemented(String msg) {
51 throw new InternalError("unimplemented:" + msg);
52 }
53
54 public static RuntimeException shouldNotReachHere() {
55 throw new InternalError("should not reach here");
56 }
57
58 public static RuntimeException shouldNotReachHere(String msg) {
59 throw new InternalError("Should not reach here: " + msg);
60 }
61
62 public static <T> boolean replaceInList(T a, T b, List<T> list) {
63 final int max = list.size();
64 for (int i = 0; i < max; i++) {
65 if (list.get(i) == a) {
66 list.set(i, b);
67 return true;
68 }
69 }
70 return false;
71 }
72
73 public static <T> boolean replaceAllInList(T a, T b, List<T> list) {
74 final int max = list.size();
75 for (int i = 0; i < max; i++) {
76 if (list.get(i) == a) {
77 list.set(i, b);
78 }
79 }
80 return false;
81 }
82
83 /**
84 * Statically cast an object to an arbitrary Object type. Dynamically checked.
85 */
86 @SuppressWarnings("unchecked")
87 public static <T> T uncheckedCast(Class<T> type, Object object) {
88 return (T) object;
89 }
90
91 /**
92 * Statically cast an object to an arbitrary Object type. Dynamically checked.
93 */
94 @SuppressWarnings("unchecked")
95 public static <T> T uncheckedCast(Object object) {
96 return (T) object;
97 }
98
99 /**
100 * Utility method to combine a base hash with the identity hash of one or more objects.
101 *
102 * @param hash the base hash
103 * @param x the object to add to the hash
104 * @return the combined hash
105 */
106 public static int hash1(int hash, Object x) {
107 // always set at least one bit in case the hash wraps to zero
108 return 0x10000000 | (hash + 7 * System.identityHashCode(x));
109 }
110
111 /**
112 * Utility method to combine a base hash with the identity hash of one or more objects.
113 *
114 * @param hash the base hash
115 * @param x the first object to add to the hash
116 * @param y the second object to add to the hash
117 * @return the combined hash
118 */
119 public static int hash2(int hash, Object x, Object y) {
120 // always set at least one bit in case the hash wraps to zero
121 return 0x20000000 | (hash + 7 * System.identityHashCode(x) + 11 * System.identityHashCode(y));
122 }
123
124 /**
125 * Utility method to combine a base hash with the identity hash of one or more objects.
126 *
127 * @param hash the base hash
128 * @param x the first object to add to the hash
129 * @param y the second object to add to the hash
130 * @param z the third object to add to the hash
131 * @return the combined hash
132 */
133 public static int hash3(int hash, Object x, Object y, Object z) {
134 // always set at least one bit in case the hash wraps to zero
135 return 0x30000000 | (hash + 7 * System.identityHashCode(x) + 11 * System.identityHashCode(y) + 13 * System.identityHashCode(z));
136 }
137
138 /**
139 * Utility method to combine a base hash with the identity hash of one or more objects.
140 *
141 * @param hash the base hash
142 * @param x the first object to add to the hash
143 * @param y the second object to add to the hash
144 * @param z the third object to add to the hash
145 * @param w the fourth object to add to the hash
146 * @return the combined hash
147 */
148 public static int hash4(int hash, Object x, Object y, Object z, Object w) {
149 // always set at least one bit in case the hash wraps to zero
150 return 0x40000000 | (hash + 7 * System.identityHashCode(x) + 11 * System.identityHashCode(y) + 13 * System.identityHashCode(z) + 17 * System.identityHashCode(w));
151 }
152
153 static {
154 assert CiUtil.log2(2) == 1;
155 assert CiUtil.log2(4) == 2;
156 assert CiUtil.log2(8) == 3;
157 assert CiUtil.log2(16) == 4;
158 assert CiUtil.log2(32) == 5;
159 assert CiUtil.log2(0x40000000) == 30;
160
161 assert CiUtil.log2(2L) == 1;
162 assert CiUtil.log2(4L) == 2;
163 assert CiUtil.log2(8L) == 3;
164 assert CiUtil.log2(16L) == 4;
165 assert CiUtil.log2(32L) == 5;
166 assert CiUtil.log2(0x4000000000000000L) == 62;
167
168 assert !CiUtil.isPowerOf2(3);
169 assert !CiUtil.isPowerOf2(5);
170 assert !CiUtil.isPowerOf2(7);
171 assert !CiUtil.isPowerOf2(-1);
172
173 assert CiUtil.isPowerOf2(2);
174 assert CiUtil.isPowerOf2(4);
175 assert CiUtil.isPowerOf2(8);
176 assert CiUtil.isPowerOf2(16);
177 assert CiUtil.isPowerOf2(32);
178 assert CiUtil.isPowerOf2(64);
179 }
180
181 /**
182 * Sets the element at a given position of a list and ensures that this position exists. If the list is current
183 * shorter than the position, intermediate positions are filled with a given value.
184 *
185 * @param list the list to put the element into
186 * @param pos the position at which to insert the element
187 * @param x the element that should be inserted
188 * @param filler the filler element that is used for the intermediate positions in case the list is shorter than pos
189 */
190 public static <T> void atPutGrow(List<T> list, int pos, T x, T filler) {
191 if (list.size() < pos + 1) {
192 while (list.size() < pos + 1) {
193 list.add(filler);
194 }
195 assert list.size() == pos + 1;
196 }
197
198 assert list.size() >= pos + 1;
199 list.set(pos, x);
200 }
201
202 public static void breakpoint() {
203 // do nothing.
204 }
205
206 public static void guarantee(boolean b, String string) {
207 if (!b) {
208 throw new CiBailout(string);
209 }
210 }
211
212 public static void warning(String string) {
213 TTY.println("WARNING: " + string);
214 }
215
216 public static int safeToInt(long l) {
217 assert (int) l == l;
218 return (int) l;
219 }
220
221 public static int roundUp(int number, int mod) {
222 return ((number + mod - 1) / mod) * mod;
223 }
224
225 public static void truncate(List<?> list, int length) {
226 while (list.size() > length) {
227 list.remove(list.size() - 1);
228 }
229 }
230
231 public static void printSection(String name, char sectionCharacter) {
232
233 String header = " " + name + " ";
234 int remainingCharacters = PRINTING_LINE_WIDTH - header.length();
235 int leftPart = remainingCharacters / 2;
236 int rightPart = remainingCharacters - leftPart;
237 for (int i = 0; i < leftPart; i++) {
238 TTY.print(sectionCharacter);
239 }
240
241 TTY.print(header);
242
243 for (int i = 0; i < rightPart; i++) {
244 TTY.print(sectionCharacter);
245 }
246
247 TTY.println();
248 }
249
250 /**
251 * Prints entries in a byte array as space separated hex values to {@link TTY}.
252 *
253 * @param address an address at which the bytes are located. This is used to print an address prefix per line of output.
254 * @param array the array containing all the bytes to print
255 * @param bytesPerLine the number of values to print per line of output
256 */
257 public static void printBytes(long address, byte[] array, int bytesPerLine) {
258 printBytes(address, array, 0, array.length, bytesPerLine);
259 }
260
261 /**
262 * Prints entries in a byte array as space separated hex values to {@link TTY}.
263 *
264 * @param address an address at which the bytes are located. This is used to print an address prefix per line of output.
265 * @param array the array containing the bytes to print
266 * @param offset the offset in {@code array} of the values to print
267 * @param length the number of values from {@code array} print
268 * @param bytesPerLine the number of values to print per line of output
269 */
270 public static void printBytes(long address, byte[] array, int offset, int length, int bytesPerLine) {
271 assert bytesPerLine > 0;
272 boolean newLine = true;
273 for (int i = 0; i < length; i++) {
274 if (newLine) {
275 TTY.print("%08x: ", address + i);
276 newLine = false;
277 }
278 TTY.print("%02x ", array[i]);
279 if (i % bytesPerLine == bytesPerLine - 1) {
280 TTY.println();
281 newLine = true;
282 }
283 }
284
285 if (length % bytesPerLine != bytesPerLine) {
286 TTY.println();
287 }
288 }
289
290 public static CiKind[] signatureToKinds(RiSignature signature, CiKind receiverKind) {
291 int args = signature.argumentCount(false);
292 CiKind[] result;
293 int i = 0;
294 if (receiverKind != null) {
295 result = new CiKind[args + 1];
296 result[0] = receiverKind;
297 i = 1;
298 } else {
299 result = new CiKind[args];
300 }
301 for (int j = 0; j < args; j++) {
302 result[i + j] = signature.argumentKindAt(j);
303 }
304 return result;
305 }
306
307 public static <T> T nonFatalUnimplemented(T val) {
308 if (C1XOptions.FatalUnimplemented) {
309 throw new Error("unimplemented");
310 }
311 return val;
312 }
313
314 public static void nonFatalUnimplemented() {
315 if (C1XOptions.FatalUnimplemented) {
316 throw new Error("unimplemented");
317 }
318 }
319
320 public static boolean isShiftCount(int x) {
321 return 0 <= x && x < 32;
322 }
323
324 /**
325 * Determines if a given {@code int} value is the range of unsigned byte values.
326 */
327 public static boolean isUByte(int x) {
328 return (x & 0xff) == x;
329 }
330
331 /**
332 * Determines if a given {@code int} value is the range of signed byte values.
333 */
334 public static boolean isByte(int x) {
335 return (byte) x == x;
336 }
337
338 /**
339 * Determines if a given {@code long} value is the range of unsigned byte values.
340 */
341 public static boolean isUByte(long x) {
342 return (x & 0xffL) == x;
343 }
344
345 /**
346 * Determines if a given {@code long} value is the range of signed byte values.
347 */
348 public static boolean isByte(long l) {
349 return (byte) l == l;
350 }
351
352 /**
353 * Determines if a given {@code long} value is the range of unsigned int values.
354 */
355 public static boolean isUInt(long x) {
356 return (x & 0xffffffffL) == x;
357 }
358
359 /**
360 * Determines if a given {@code long} value is the range of signed int values.
361 */
362 public static boolean isInt(long l) {
363 return (int) l == l;
364 }
365 /**
366 * Determines if a given {@code int} value is the range of signed short values.
367 */
368 public static boolean isShort(int x) {
369 return (short) x == x;
370 }
371
372 public static boolean is32bit(long x) {
373 return -0x80000000L <= x && x < 0x80000000L;
374 }
375
376 public static short safeToShort(int v) {
377 assert isShort(v);
378 return (short) v;
379 }
380
381 /**
382 * Determines if the kinds of two given IR nodes are equal at the {@linkplain #archKind(CiKind) architecture}
383 * level in the context of the {@linkplain C1XCompilation#compilation()} compilation.
384 */
385 public static boolean archKindsEqual(Value i, Value other) {
386 return archKindsEqual(i.kind, other.kind);
387 }
388
389 /**
390 * Determines if two given kinds are equal at the {@linkplain #archKind(CiKind) architecture} level
391 * in the context of the {@linkplain C1XCompilation#compilation()} compilation.
392 */
393 public static boolean archKindsEqual(CiKind k1, CiKind k2) {
394 C1XCompilation compilation = C1XCompilation.compilation();
395 assert compilation != null : "missing compilation context";
396 return compilation.archKindsEqual(k1, k2);
397 }
398
399 /**
400 * Translates a given kind to a {@linkplain C1XCompilation#archKind(CiKind) canonical architecture}
401 * kind in the context of the {@linkplain C1XCompilation#compilation() current} compilation.
402 */
403 public static CiKind archKind(CiKind kind) {
404 C1XCompilation compilation = C1XCompilation.compilation();
405 assert compilation != null : "missing compilation context";
406 return compilation.archKind(kind);
407 }
408
409
410 /**
411 * Checks that two instructions are equivalent, optionally comparing constants.
412 * @param x the first instruction
413 * @param y the second instruction
414 * @param compareConstants {@code true} if equivalent constants should be considered equivalent
415 * @return {@code true} if the instructions are equivalent; {@code false} otherwise
416 */
417 public static boolean equivalent(Instruction x, Instruction y, boolean compareConstants) {
418 if (x == y) {
419 return true;
420 }
421 if (compareConstants && x != null && y != null) {
422 if (x.isConstant() && x.asConstant().equivalent(y.asConstant())) {
423 return true;
424 }
425 }
426 return false;
427 }
428
429 /**
430 * Converts a given instruction to a value string. The representation of an instruction as
431 * a value is formed by concatenating the {@linkplain com.sun.cri.ci.CiKind#typeChar character} denoting its
432 * {@linkplain Value#kind kind} and its {@linkplain Value#id()}. For example, {@code "i13"}.
433 *
434 * @param value the instruction to convert to a value string. If {@code value == null}, then "-" is returned.
435 * @return the instruction representation as a string
436 */
437 public static String valueString(Value value) {
438 return value == null ? "-" : "" + value.kind.typeChar + value.id();
439 }
440 }