1 /* 2 * Copyright (c) 2014, 2015, 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.graalvm.compiler.core.common.type; 24 25 import static jdk.vm.ci.meta.MetaUtil.getSimpleName; 26 27 import java.util.Arrays; 28 import java.util.Objects; 29 import java.util.function.Function; 30 31 import org.graalvm.compiler.core.common.calc.FloatConvert; 32 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Add; 33 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.And; 34 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Div; 35 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Mul; 36 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.MulHigh; 37 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Or; 38 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Rem; 39 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Sub; 40 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.UMulHigh; 41 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Xor; 42 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow; 43 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp.SignExtend; 44 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp.ZeroExtend; 45 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp.Shl; 46 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp.Shr; 47 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp.UShr; 48 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Abs; 49 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Neg; 50 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Not; 51 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Sqrt; 52 import org.graalvm.util.CollectionsUtil; 53 54 import jdk.vm.ci.meta.Constant; 55 import jdk.vm.ci.meta.JavaKind; 56 57 /** 58 * Information about arithmetic operations. 59 */ 60 public final class ArithmeticOpTable { 61 62 private final UnaryOp<Neg> neg; 63 private final BinaryOp<Add> add; 64 private final BinaryOp<Sub> sub; 65 66 private final BinaryOp<Mul> mul; 67 private final BinaryOp<MulHigh> mulHigh; 68 private final BinaryOp<UMulHigh> umulHigh; 69 private final BinaryOp<Div> div; 70 private final BinaryOp<Rem> rem; 71 72 private final UnaryOp<Not> not; 73 private final BinaryOp<And> and; 74 private final BinaryOp<Or> or; 75 private final BinaryOp<Xor> xor; 76 77 private final ShiftOp<Shl> shl; 78 private final ShiftOp<Shr> shr; 79 private final ShiftOp<UShr> ushr; 80 81 private final UnaryOp<Abs> abs; 82 private final UnaryOp<Sqrt> sqrt; 83 84 private final IntegerConvertOp<ZeroExtend> zeroExtend; 85 private final IntegerConvertOp<SignExtend> signExtend; 86 private final IntegerConvertOp<Narrow> narrow; 87 88 private final FloatConvertOp[] floatConvert; 89 private final int hash; 90 91 public static ArithmeticOpTable forStamp(Stamp s) { 92 if (s instanceof ArithmeticStamp) { 93 return ((ArithmeticStamp) s).getOps(); 94 } else { 95 return EMPTY; 96 } 97 } 98 99 public static final ArithmeticOpTable EMPTY = new ArithmeticOpTable(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); 100 101 public interface ArithmeticOpWrapper { 102 103 <OP> UnaryOp<OP> wrapUnaryOp(UnaryOp<OP> op); 104 105 <OP> BinaryOp<OP> wrapBinaryOp(BinaryOp<OP> op); 106 107 <OP> ShiftOp<OP> wrapShiftOp(ShiftOp<OP> op); 108 109 <OP> IntegerConvertOp<OP> wrapIntegerConvertOp(IntegerConvertOp<OP> op); 110 111 FloatConvertOp wrapFloatConvertOp(FloatConvertOp op); 112 } 113 114 private static <T> T wrapIfNonNull(Function<T, T> wrapper, T obj) { 115 if (obj == null) { 116 return null; 117 } else { 118 return wrapper.apply(obj); 119 } 120 } 121 122 public static ArithmeticOpTable wrap(ArithmeticOpWrapper wrapper, ArithmeticOpTable inner) { 123 UnaryOp<Neg> neg = wrapIfNonNull(wrapper::wrapUnaryOp, inner.getNeg()); 124 BinaryOp<Add> add = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getAdd()); 125 BinaryOp<Sub> sub = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getSub()); 126 127 BinaryOp<Mul> mul = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getMul()); 128 BinaryOp<MulHigh> mulHigh = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getMulHigh()); 129 BinaryOp<UMulHigh> umulHigh = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getUMulHigh()); 130 BinaryOp<Div> div = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getDiv()); 131 BinaryOp<Rem> rem = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getRem()); 132 133 UnaryOp<Not> not = wrapIfNonNull(wrapper::wrapUnaryOp, inner.getNot()); 134 BinaryOp<And> and = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getAnd()); 135 BinaryOp<Or> or = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getOr()); 136 BinaryOp<Xor> xor = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getXor()); 137 138 ShiftOp<Shl> shl = wrapIfNonNull(wrapper::wrapShiftOp, inner.getShl()); 139 ShiftOp<Shr> shr = wrapIfNonNull(wrapper::wrapShiftOp, inner.getShr()); 140 ShiftOp<UShr> ushr = wrapIfNonNull(wrapper::wrapShiftOp, inner.getUShr()); 141 142 UnaryOp<Abs> abs = wrapIfNonNull(wrapper::wrapUnaryOp, inner.getAbs()); 143 UnaryOp<Sqrt> sqrt = wrapIfNonNull(wrapper::wrapUnaryOp, inner.getSqrt()); 144 145 IntegerConvertOp<ZeroExtend> zeroExtend = wrapIfNonNull(wrapper::wrapIntegerConvertOp, inner.getZeroExtend()); 146 IntegerConvertOp<SignExtend> signExtend = wrapIfNonNull(wrapper::wrapIntegerConvertOp, inner.getSignExtend()); 147 IntegerConvertOp<Narrow> narrow = wrapIfNonNull(wrapper::wrapIntegerConvertOp, inner.getNarrow()); 148 149 FloatConvertOp[] floatConvert = CollectionsUtil.filterAndMapToArray(inner.floatConvert, Objects::nonNull, wrapper::wrapFloatConvertOp, FloatConvertOp[]::new); 150 return new ArithmeticOpTable(neg, add, sub, mul, mulHigh, umulHigh, div, rem, not, and, or, xor, shl, shr, ushr, abs, sqrt, zeroExtend, signExtend, narrow, floatConvert); 151 } 152 153 protected ArithmeticOpTable(UnaryOp<Neg> neg, BinaryOp<Add> add, BinaryOp<Sub> sub, BinaryOp<Mul> mul, BinaryOp<MulHigh> mulHigh, BinaryOp<UMulHigh> umulHigh, BinaryOp<Div> div, BinaryOp<Rem> rem, 154 UnaryOp<Not> not, BinaryOp<And> and, BinaryOp<Or> or, BinaryOp<Xor> xor, ShiftOp<Shl> shl, ShiftOp<Shr> shr, ShiftOp<UShr> ushr, UnaryOp<Abs> abs, UnaryOp<Sqrt> sqrt, 155 IntegerConvertOp<ZeroExtend> zeroExtend, IntegerConvertOp<SignExtend> signExtend, IntegerConvertOp<Narrow> narrow, FloatConvertOp... floatConvert) { 156 this.neg = neg; 157 this.add = add; 158 this.sub = sub; 159 this.mul = mul; 160 this.mulHigh = mulHigh; 161 this.umulHigh = umulHigh; 162 this.div = div; 163 this.rem = rem; 164 this.not = not; 165 this.and = and; 166 this.or = or; 167 this.xor = xor; 168 this.shl = shl; 169 this.shr = shr; 170 this.ushr = ushr; 171 this.abs = abs; 172 this.sqrt = sqrt; 173 this.zeroExtend = zeroExtend; 174 this.signExtend = signExtend; 175 this.narrow = narrow; 176 this.floatConvert = new FloatConvertOp[FloatConvert.values().length]; 177 for (FloatConvertOp op : floatConvert) { 178 this.floatConvert[op.getFloatConvert().ordinal()] = op; 179 } 180 181 this.hash = Objects.hash(neg, add, sub, mul, div, rem, not, and, or, xor, shl, shr, ushr, abs, sqrt, zeroExtend, signExtend, narrow); 182 } 183 184 @Override 185 public int hashCode() { 186 return hash; 187 } 188 189 /** 190 * Describes the unary negation operation. 191 */ 192 public UnaryOp<Neg> getNeg() { 193 return neg; 194 } 195 196 /** 197 * Describes the addition operation. 198 */ 199 public BinaryOp<Add> getAdd() { 200 return add; 201 } 202 203 /** 204 * Describes the subtraction operation. 205 */ 206 public BinaryOp<Sub> getSub() { 207 return sub; 208 } 209 210 /** 211 * Describes the multiplication operation. 212 */ 213 public BinaryOp<Mul> getMul() { 214 return mul; 215 } 216 217 /** 218 * Describes a signed operation that multiples the upper 32-bits of two long values. 219 */ 220 public BinaryOp<MulHigh> getMulHigh() { 221 return mulHigh; 222 } 223 224 /** 225 * Describes an unsigned operation that multiples the upper 32-bits of two long values. 226 */ 227 public BinaryOp<UMulHigh> getUMulHigh() { 228 return umulHigh; 229 } 230 231 /** 232 * Describes the division operation. 233 */ 234 public BinaryOp<Div> getDiv() { 235 return div; 236 } 237 238 /** 239 * Describes the remainder operation. 240 */ 241 public BinaryOp<Rem> getRem() { 242 return rem; 243 } 244 245 /** 246 * Describes the bitwise not operation. 247 */ 248 public UnaryOp<Not> getNot() { 249 return not; 250 } 251 252 /** 253 * Describes the bitwise and operation. 254 */ 255 public BinaryOp<And> getAnd() { 256 return and; 257 } 258 259 /** 260 * Describes the bitwise or operation. 261 */ 262 public BinaryOp<Or> getOr() { 263 return or; 264 } 265 266 /** 267 * Describes the bitwise xor operation. 268 */ 269 public BinaryOp<Xor> getXor() { 270 return xor; 271 } 272 273 /** 274 * Describes the shift left operation. 275 */ 276 public ShiftOp<Shl> getShl() { 277 return shl; 278 } 279 280 /** 281 * Describes the signed shift right operation. 282 */ 283 public ShiftOp<Shr> getShr() { 284 return shr; 285 } 286 287 /** 288 * Describes the unsigned shift right operation. 289 */ 290 public ShiftOp<UShr> getUShr() { 291 return ushr; 292 } 293 294 /** 295 * Describes the absolute value operation. 296 */ 297 public UnaryOp<Abs> getAbs() { 298 return abs; 299 } 300 301 /** 302 * Describes the square root operation. 303 */ 304 public UnaryOp<Sqrt> getSqrt() { 305 return sqrt; 306 } 307 308 /** 309 * Describes the zero extend conversion. 310 */ 311 public IntegerConvertOp<ZeroExtend> getZeroExtend() { 312 return zeroExtend; 313 } 314 315 /** 316 * Describes the sign extend conversion. 317 */ 318 public IntegerConvertOp<SignExtend> getSignExtend() { 319 return signExtend; 320 } 321 322 /** 323 * Describes the narrowing conversion. 324 */ 325 public IntegerConvertOp<Narrow> getNarrow() { 326 return narrow; 327 } 328 329 /** 330 * Describes integer/float/double conversions. 331 */ 332 public FloatConvertOp getFloatConvert(FloatConvert op) { 333 return floatConvert[op.ordinal()]; 334 } 335 336 public static String toString(Op... ops) { 337 return CollectionsUtil.mapAndJoin(ops, o -> o == null ? "null" : o.operator + "{" + getSimpleName(o.getClass(), false) + "}", ","); 338 } 339 340 private boolean opsEquals(ArithmeticOpTable that) { 341 // @formatter:off 342 return Objects.equals(neg, that.neg) && 343 Objects.equals(add, that.add) && 344 Objects.equals(sub, that.sub) && 345 Objects.equals(mul, that.mul) && 346 Objects.equals(mulHigh, that.mulHigh) && 347 Objects.equals(umulHigh, that.umulHigh) && 348 Objects.equals(div, that.div) && 349 Objects.equals(rem, that.rem) && 350 Objects.equals(not, that.not) && 351 Objects.equals(and, that.and) && 352 Objects.equals(or, that.or) && 353 Objects.equals(xor, that.xor) && 354 Objects.equals(shl, that.shl) && 355 Objects.equals(shr, that.shr) && 356 Objects.equals(ushr, that.ushr) && 357 Objects.equals(abs, that.abs) && 358 Objects.equals(sqrt, that.sqrt) && 359 Objects.equals(zeroExtend, that.zeroExtend) && 360 Objects.equals(signExtend, that.signExtend) && 361 Objects.equals(narrow, that.narrow); 362 // @formatter:on 363 } 364 365 @Override 366 public boolean equals(Object obj) { 367 if (this == obj) { 368 return true; 369 } 370 if (obj == null) { 371 return false; 372 } 373 if (getClass() != obj.getClass()) { 374 return false; 375 } 376 ArithmeticOpTable that = (ArithmeticOpTable) obj; 377 if (opsEquals(that)) { 378 if (Arrays.equals(this.floatConvert, that.floatConvert)) { 379 return true; 380 } 381 } 382 return false; 383 } 384 385 @Override 386 public String toString() { 387 return getClass().getSimpleName() + "[" + toString(neg, add, sub, mul, mulHigh, umulHigh, div, rem, not, and, or, xor, shl, shr, ushr, abs, sqrt, zeroExtend, signExtend, narrow) + 388 ",floatConvert[" + toString(floatConvert) + "]]"; 389 } 390 391 public abstract static class Op { 392 393 private final String operator; 394 395 protected Op(String operator) { 396 this.operator = operator; 397 } 398 399 @Override 400 public String toString() { 401 return operator; 402 } 403 404 @Override 405 public int hashCode() { 406 return operator.hashCode(); 407 } 408 409 @Override 410 public boolean equals(Object obj) { 411 if (this == obj) { 412 return true; 413 } 414 if (obj == null) { 415 return false; 416 } 417 if (getClass() != obj.getClass()) { 418 return false; 419 } 420 Op that = (Op) obj; 421 if (operator.equals(that.operator)) { 422 return true; 423 } 424 return true; 425 } 426 } 427 428 /** 429 * Describes a unary arithmetic operation. 430 */ 431 public abstract static class UnaryOp<T> extends Op { 432 433 public abstract static class Neg extends UnaryOp<Neg> { 434 435 protected Neg() { 436 super("-"); 437 } 438 } 439 440 public abstract static class Not extends UnaryOp<Not> { 441 442 protected Not() { 443 super("~"); 444 } 445 } 446 447 public abstract static class Abs extends UnaryOp<Abs> { 448 449 protected Abs() { 450 super("ABS"); 451 } 452 } 453 454 public abstract static class Sqrt extends UnaryOp<Sqrt> { 455 456 protected Sqrt() { 457 super("SQRT"); 458 } 459 } 460 461 protected UnaryOp(String operation) { 462 super(operation); 463 } 464 465 /** 466 * Apply the operation to a {@link Constant}. 467 */ 468 public abstract Constant foldConstant(Constant value); 469 470 /** 471 * Apply the operation to a {@link Stamp}. 472 */ 473 public abstract Stamp foldStamp(Stamp stamp); 474 475 public UnaryOp<T> unwrap() { 476 return this; 477 } 478 } 479 480 /** 481 * Describes a binary arithmetic operation. 482 */ 483 public abstract static class BinaryOp<T> extends Op { 484 485 public abstract static class Add extends BinaryOp<Add> { 486 487 protected Add(boolean associative, boolean commutative) { 488 super("+", associative, commutative); 489 } 490 } 491 492 public abstract static class Sub extends BinaryOp<Sub> { 493 494 protected Sub(boolean associative, boolean commutative) { 495 super("-", associative, commutative); 496 } 497 } 498 499 public abstract static class Mul extends BinaryOp<Mul> { 500 501 protected Mul(boolean associative, boolean commutative) { 502 super("*", associative, commutative); 503 } 504 } 505 506 public abstract static class MulHigh extends BinaryOp<MulHigh> { 507 508 protected MulHigh(boolean associative, boolean commutative) { 509 super("*H", associative, commutative); 510 } 511 } 512 513 public abstract static class UMulHigh extends BinaryOp<UMulHigh> { 514 515 protected UMulHigh(boolean associative, boolean commutative) { 516 super("|*H|", associative, commutative); 517 } 518 } 519 520 public abstract static class Div extends BinaryOp<Div> { 521 522 protected Div(boolean associative, boolean commutative) { 523 super("/", associative, commutative); 524 } 525 } 526 527 public abstract static class Rem extends BinaryOp<Rem> { 528 529 protected Rem(boolean associative, boolean commutative) { 530 super("%", associative, commutative); 531 } 532 } 533 534 public abstract static class And extends BinaryOp<And> { 535 536 protected And(boolean associative, boolean commutative) { 537 super("&", associative, commutative); 538 } 539 } 540 541 public abstract static class Or extends BinaryOp<Or> { 542 543 protected Or(boolean associative, boolean commutative) { 544 super("|", associative, commutative); 545 } 546 } 547 548 public abstract static class Xor extends BinaryOp<Xor> { 549 550 protected Xor(boolean associative, boolean commutative) { 551 super("^", associative, commutative); 552 } 553 } 554 555 private final boolean associative; 556 private final boolean commutative; 557 558 protected BinaryOp(String operation, boolean associative, boolean commutative) { 559 super(operation); 560 this.associative = associative; 561 this.commutative = commutative; 562 } 563 564 /** 565 * Apply the operation to two {@linkplain Constant Constants}. 566 */ 567 public abstract Constant foldConstant(Constant a, Constant b); 568 569 /** 570 * Apply the operation to two {@linkplain Stamp Stamps}. 571 */ 572 public abstract Stamp foldStamp(Stamp a, Stamp b); 573 574 /** 575 * Checks whether this operation is associative. An operation is associative when 576 * {@code (a . b) . c == a . (b . c)} for all a, b, c. Note that you still have to be 577 * careful with inverses. For example the integer subtraction operation will report 578 * {@code true} here, since you can still reassociate as long as the correct negations are 579 * inserted. 580 */ 581 public final boolean isAssociative() { 582 return associative; 583 } 584 585 /** 586 * Checks whether this operation is commutative. An operation is commutative when 587 * {@code a . b == b . a} for all a, b. 588 */ 589 public final boolean isCommutative() { 590 return commutative; 591 } 592 593 /** 594 * Check whether a {@link Constant} is a neutral element for this operation. A neutral 595 * element is any element {@code n} where {@code a . n == a} for all a. 596 * 597 * @param n the {@link Constant} that should be tested 598 * @return true iff for all {@code a}: {@code a . n == a} 599 */ 600 public boolean isNeutral(Constant n) { 601 return false; 602 } 603 604 /** 605 * Check whether this operation has a zero {@code z == a . a} for each a. Examples of 606 * operations having such an element are subtraction and exclusive-or. Note that this may be 607 * different from the numbers tested by {@link #isNeutral}. 608 * 609 * @param stamp a {@link Stamp} 610 * @return a unique {@code z} such that {@code z == a . a} for each {@code a} in 611 * {@code stamp} if it exists, otherwise {@code null} 612 */ 613 public Constant getZero(Stamp stamp) { 614 return null; 615 } 616 617 public BinaryOp<T> unwrap() { 618 return this; 619 } 620 621 @Override 622 public int hashCode() { 623 final int prime = 31; 624 int result = super.hashCode(); 625 result = prime * result + (associative ? 1231 : 1237); 626 result = prime * result + (commutative ? 1231 : 1237); 627 return result; 628 } 629 630 @Override 631 public boolean equals(Object obj) { 632 if (this == obj) { 633 return true; 634 } 635 if (!super.equals(obj)) { 636 return false; 637 } 638 if (getClass() != obj.getClass()) { 639 return false; 640 } 641 BinaryOp<?> that = (BinaryOp<?>) obj; 642 if (associative != that.associative) { 643 return false; 644 } 645 if (commutative != that.commutative) { 646 return false; 647 } 648 return true; 649 } 650 651 @Override 652 public String toString() { 653 if (associative) { 654 if (commutative) { 655 return super.toString() + "[AC]"; 656 } else { 657 return super.toString() + "[A]"; 658 } 659 } else if (commutative) { 660 return super.toString() + "[C]"; 661 } 662 return super.toString(); 663 } 664 } 665 666 /** 667 * Describes a shift operation. The right argument of a shift operation always has kind 668 * {@link JavaKind#Int}. 669 */ 670 public abstract static class ShiftOp<OP> extends Op { 671 672 public abstract static class Shl extends ShiftOp<Shl> { 673 674 public Shl() { 675 super("<<"); 676 } 677 } 678 679 public abstract static class Shr extends ShiftOp<Shr> { 680 681 public Shr() { 682 super(">>"); 683 } 684 } 685 686 public abstract static class UShr extends ShiftOp<UShr> { 687 688 public UShr() { 689 super(">>>"); 690 } 691 } 692 693 protected ShiftOp(String operation) { 694 super(operation); 695 } 696 697 /** 698 * Apply the shift to a constant. 699 */ 700 public abstract Constant foldConstant(Constant c, int amount); 701 702 /** 703 * Apply the shift to a stamp. 704 */ 705 public abstract Stamp foldStamp(Stamp s, IntegerStamp amount); 706 707 /** 708 * Get the shift amount mask for a given result stamp. 709 */ 710 public abstract int getShiftAmountMask(Stamp s); 711 } 712 713 public abstract static class FloatConvertOp extends UnaryOp<FloatConvertOp> { 714 715 private final FloatConvert op; 716 717 protected FloatConvertOp(FloatConvert op) { 718 super(op.name()); 719 this.op = op; 720 } 721 722 public FloatConvert getFloatConvert() { 723 return op; 724 } 725 726 @Override 727 public FloatConvertOp unwrap() { 728 return this; 729 } 730 731 @Override 732 public int hashCode() { 733 final int prime = 31; 734 return prime * super.hashCode() + op.hashCode(); 735 } 736 737 @Override 738 public boolean equals(Object obj) { 739 if (this == obj) { 740 return true; 741 } 742 if (!super.equals(obj)) { 743 return false; 744 } 745 if (getClass() != obj.getClass()) { 746 return false; 747 } 748 FloatConvertOp that = (FloatConvertOp) obj; 749 if (op != that.op) { 750 return false; 751 } 752 return true; 753 } 754 } 755 756 public abstract static class IntegerConvertOp<T> extends Op { 757 758 public abstract static class ZeroExtend extends IntegerConvertOp<ZeroExtend> { 759 760 protected ZeroExtend() { 761 super("ZeroExtend"); 762 } 763 } 764 765 public abstract static class SignExtend extends IntegerConvertOp<SignExtend> { 766 767 protected SignExtend() { 768 super("SignExtend"); 769 } 770 } 771 772 public abstract static class Narrow extends IntegerConvertOp<Narrow> { 773 774 protected Narrow() { 775 super("Narrow"); 776 } 777 778 @Override 779 public Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp) { 780 return null; 781 } 782 } 783 784 protected IntegerConvertOp(String op) { 785 super(op); 786 } 787 788 public abstract Constant foldConstant(int inputBits, int resultBits, Constant value); 789 790 public abstract Stamp foldStamp(int inputBits, int resultBits, Stamp stamp); 791 792 public IntegerConvertOp<T> unwrap() { 793 return this; 794 } 795 796 /** 797 * Computes the stamp of the input for the given output stamp. 798 */ 799 public abstract Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp); 800 } 801 }