1 /* 2 * Copyright (c) 2013, 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 24 package com.oracle.graal.compiler.hsail; 25 26 import static com.oracle.graal.api.code.ValueUtil.*; 27 import static com.oracle.graal.lir.hsail.HSAILArithmetic.*; 28 import static com.oracle.graal.lir.hsail.HSAILBitManipulationOp.IntrinsicOpcode.*; 29 import static com.oracle.graal.lir.hsail.HSAILCompare.*; 30 31 import com.oracle.graal.api.code.*; 32 import com.oracle.graal.api.meta.*; 33 import com.oracle.graal.asm.*; 34 import com.oracle.graal.compiler.gen.*; 35 import com.oracle.graal.compiler.target.*; 36 import com.oracle.graal.debug.*; 37 import com.oracle.graal.graph.*; 38 import com.oracle.graal.lir.*; 39 import com.oracle.graal.lir.StandardOp.JumpOp; 40 import com.oracle.graal.lir.hsail.*; 41 import com.oracle.graal.lir.hsail.HSAILArithmetic.Op1Stack; 42 import com.oracle.graal.lir.hsail.HSAILArithmetic.Op2Reg; 43 import com.oracle.graal.lir.hsail.HSAILArithmetic.Op2Stack; 44 import com.oracle.graal.lir.hsail.HSAILArithmetic.ShiftOp; 45 import com.oracle.graal.lir.hsail.HSAILControlFlow.CompareBranchOp; 46 import com.oracle.graal.lir.hsail.HSAILControlFlow.CondMoveOp; 47 import com.oracle.graal.lir.hsail.HSAILControlFlow.FloatCompareBranchOp; 48 import com.oracle.graal.lir.hsail.HSAILControlFlow.FloatCondMoveOp; 49 import com.oracle.graal.lir.hsail.HSAILControlFlow.ReturnOp; 50 import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCallNoOp0; 51 import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCallNoOp1; 52 import com.oracle.graal.lir.hsail.HSAILMove.LeaOp; 53 import com.oracle.graal.lir.hsail.HSAILMove.LoadOp; 54 import com.oracle.graal.lir.hsail.HSAILMove.MoveFromRegOp; 55 import com.oracle.graal.lir.hsail.HSAILMove.MoveToRegOp; 56 import com.oracle.graal.lir.hsail.HSAILMove.StoreOp; 57 import com.oracle.graal.lir.hsail.HSAILMove.LoadCompressedPointer; 58 import com.oracle.graal.lir.hsail.HSAILMove.StoreCompressedPointer; 59 import com.oracle.graal.nodes.*; 60 import com.oracle.graal.nodes.calc.*; 61 import com.oracle.graal.nodes.java.*; 62 import com.oracle.graal.hotspot.*; 63 import com.oracle.graal.hotspot.meta.*; 64 65 /** 66 * This class implements the HSAIL specific portion of the LIR generator. 67 */ 68 public class HSAILLIRGenerator extends LIRGenerator { 69 70 private HotSpotRuntime runtime() { 71 return (HotSpotRuntime) runtime; 72 } 73 74 public static class HSAILSpillMoveFactory implements LIR.SpillMoveFactory { 75 76 @Override 77 public LIRInstruction createMove(AllocatableValue dst, Value src) { 78 if (src instanceof HSAILAddressValue) { 79 return new LeaOp(dst, (HSAILAddressValue) src); 80 } else if (isRegister(src) || isStackSlot(dst)) { 81 return new MoveFromRegOp(dst, src); 82 } else { 83 return new MoveToRegOp(dst, src); 84 } 85 } 86 } 87 88 public HSAILLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, CallingConvention cc, LIR lir) { 89 super(graph, runtime, target, frameMap, cc, lir); 90 lir.spillMoveFactory = new HSAILSpillMoveFactory(); 91 } 92 93 @Override 94 protected void emitNode(ValueNode node) { 95 if (node instanceof LIRGenLowerable) { 96 ((LIRGenLowerable) node).generate(this); 97 } else { 98 super.emitNode(node); 99 } 100 } 101 102 @Override 103 public boolean canStoreConstant(Constant c) { 104 // Operand b must be in the .reg state space. 105 return false; 106 } 107 108 @Override 109 public boolean canInlineConstant(Constant c) { 110 switch (c.getKind()) { 111 case Long: 112 return NumUtil.isInt(c.asLong()) && !runtime.needsDataPatch(c); 113 case Object: 114 return c.isNull(); 115 default: 116 return true; 117 } 118 } 119 120 @Override 121 public Variable emitMove(Value input) { 122 Variable result = newVariable(input.getKind()); 123 emitMove(result, input); 124 return result; 125 } 126 127 @Override 128 public void emitMove(AllocatableValue dst, Value src) { 129 if (isRegister(src) || isStackSlot(dst)) { 130 append(new MoveFromRegOp(dst, src)); 131 } else { 132 append(new MoveToRegOp(dst, src)); 133 } 134 } 135 136 protected HSAILAddressValue asAddressValue(Value address) { 137 if (address instanceof HSAILAddressValue) { 138 return (HSAILAddressValue) address; 139 } else { 140 return emitAddress(address, 0, Value.ILLEGAL, 0); 141 } 142 } 143 144 public HSAILAddressValue emitAddress(Value base, long displacement, Value index, int scale) { 145 AllocatableValue baseRegister; 146 long finalDisp = displacement; 147 148 if (isConstant(base)) { 149 if (asConstant(base).isNull()) { 150 baseRegister = Value.ILLEGAL; 151 } else if (asConstant(base).getKind() != Kind.Object) { 152 finalDisp += asConstant(base).asLong(); 153 baseRegister = Value.ILLEGAL; 154 } else { 155 baseRegister = load(base); 156 } 157 } else if (base == Value.ILLEGAL) { 158 baseRegister = Value.ILLEGAL; 159 } else { 160 baseRegister = asAllocatable(base); 161 } 162 if (index != Value.ILLEGAL) { 163 if (isConstant(index)) { 164 finalDisp += asConstant(index).asLong() * scale; 165 } else { 166 Value indexRegister; 167 Value convertedIndex; 168 convertedIndex = this.emitConvert(ConvertNode.Op.I2L, index); 169 if (scale != 1) { 170 indexRegister = emitUMul(convertedIndex, Constant.forInt(scale)); 171 } else { 172 indexRegister = convertedIndex; 173 } 174 if (baseRegister == Value.ILLEGAL) { 175 baseRegister = asAllocatable(indexRegister); 176 } else { 177 baseRegister = emitAdd(baseRegister, indexRegister); 178 } 179 } 180 } 181 return new HSAILAddressValue(target().wordKind, baseRegister, finalDisp); 182 } 183 184 private HSAILAddressValue asAddress(Value address) { 185 if (address instanceof HSAILAddressValue) { 186 return (HSAILAddressValue) address; 187 } else { 188 return emitAddress(address, 0, Value.ILLEGAL, 0); 189 } 190 } 191 192 private static boolean isCompressCandidate(DeoptimizingNode access) { 193 return access != null && ((HeapAccess) access).compress(); 194 } 195 196 @Override 197 public Variable emitLoad(Kind kind, Value address, DeoptimizingNode access) { 198 HSAILAddressValue loadAddress = asAddressValue(address); 199 Variable result = newVariable(kind); 200 LIRFrameState state = access != null ? state(access) : null; 201 assert access == null || access instanceof HeapAccess; 202 if (runtime().config.useCompressedOops && isCompressCandidate(access)) { 203 Variable scratch = newVariable(Kind.Long); 204 append(new LoadCompressedPointer(kind, result, scratch, loadAddress, state, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment)); 205 } else { 206 append(new LoadOp(kind, result, loadAddress, state)); 207 } 208 return result; 209 } 210 211 @Override 212 public void emitStore(Kind kind, Value address, Value inputVal, DeoptimizingNode access) { 213 HSAILAddressValue storeAddress = asAddressValue(address); 214 LIRFrameState state = access != null ? state(access) : null; 215 Variable input = load(inputVal); 216 if (runtime().config.useCompressedOops && isCompressCandidate(access)) { 217 Variable scratch = newVariable(Kind.Long); 218 append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment)); 219 } else { 220 append(new StoreOp(kind, storeAddress, input, state)); 221 } 222 } 223 224 @Override 225 public Variable emitAddress(StackSlot address) { 226 throw new InternalError("NYI"); 227 } 228 229 @Override 230 public void emitJump(LabelRef label) { 231 append(new JumpOp(label)); 232 } 233 234 private static HSAILCompare mapKindToCompareOp(Kind kind) { 235 switch (kind) { 236 case Int: 237 return ICMP; 238 case Long: 239 return LCMP; 240 case Float: 241 return FCMP; 242 case Double: 243 return DCMP; 244 case Object: 245 return ACMP; 246 default: 247 throw GraalInternalError.shouldNotReachHere("" + kind); 248 } 249 } 250 251 @Override 252 public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) { 253 // We don't have top worry about mirroring the condition on HSAIL. 254 Condition finalCondition = cond; 255 Variable result = newVariable(left.getKind()); 256 Kind kind = left.getKind().getStackKind(); 257 switch (kind) { 258 case Int: 259 case Long: 260 case Object: 261 append(new CompareBranchOp(mapKindToCompareOp(kind), finalCondition, left, right, result, result, label)); 262 break; 263 case Float: 264 case Double: 265 append(new FloatCompareBranchOp(mapKindToCompareOp(kind), finalCondition, left, right, result, result, label, unorderedIsTrue)); 266 break; 267 default: 268 throw GraalInternalError.shouldNotReachHere("" + left.getKind()); 269 } 270 } 271 272 @Override 273 public void emitOverflowCheckBranch(LabelRef label, boolean negated) { 274 throw new InternalError("NYI"); 275 } 276 277 @Override 278 public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) { 279 throw new InternalError("NYI"); 280 } 281 282 @Override 283 public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { 284 Condition finalCondition = cond; 285 Variable result = newVariable(trueValue.getKind()); 286 Kind kind = left.getKind().getStackKind(); 287 switch (kind) { 288 case Int: 289 case Long: 290 case Object: 291 append(new CondMoveOp(mapKindToCompareOp(kind), load(left), load(right), result, finalCondition, load(trueValue), load(falseValue))); 292 break; 293 case Float: 294 case Double: 295 append(new FloatCondMoveOp(mapKindToCompareOp(kind), load(left), load(right), result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue))); 296 break; 297 default: 298 throw GraalInternalError.shouldNotReachHere("missing: " + left.getKind()); 299 } 300 return result; 301 } 302 303 @Override 304 public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) { 305 throw new InternalError("NYI"); 306 } 307 308 @Override 309 public Variable emitNegate(Value input) { 310 Variable result = newVariable(input.getKind()); 311 switch (input.getKind()) { 312 case Int: 313 append(new Op1Stack(INEG, result, input)); 314 break; 315 default: 316 throw GraalInternalError.shouldNotReachHere(); 317 } 318 return result; 319 320 } 321 322 public Variable emitTestAddressAdd(Value a, Value b) { 323 Variable result = newVariable(a.getKind()); 324 switch (a.getKind()) { 325 case Int: 326 append(new Op2Stack(IADD, result, a, loadNonConst(b))); 327 break; 328 case Long: 329 append(new Op2Stack(LADD, result, a, loadNonConst(b))); 330 break; 331 case Float: 332 append(new Op2Stack(FADD, result, a, loadNonConst(b))); 333 break; 334 case Double: 335 append(new Op2Stack(DADD, result, a, loadNonConst(b))); 336 break; 337 case Object: 338 throw GraalInternalError.shouldNotReachHere(); 339 default: 340 throw GraalInternalError.shouldNotReachHere(); 341 } 342 343 return result; 344 } 345 346 @Override 347 public Variable emitAdd(Value a, Value b) { 348 Variable result = newVariable(a.getKind()); 349 switch (a.getKind()) { 350 case Int: 351 append(new Op2Stack(IADD, result, a, loadNonConst(b))); 352 break; 353 case Long: 354 append(new Op2Stack(LADD, result, a, loadNonConst(b))); 355 break; 356 case Float: 357 append(new Op2Stack(FADD, result, a, loadNonConst(b))); 358 break; 359 case Double: 360 append(new Op2Stack(DADD, result, a, loadNonConst(b))); 361 break; 362 case Object: 363 append(new Op2Stack(OADD, result, a, loadNonConst(b))); 364 break; 365 default: 366 throw GraalInternalError.shouldNotReachHere(); 367 } 368 return result; 369 } 370 371 @Override 372 public Variable emitSub(Value a, Value b) { 373 Variable result = newVariable(a.getKind()); 374 switch (a.getKind()) { 375 case Int: 376 append(new Op2Stack(ISUB, result, a, loadNonConst(b))); 377 break; 378 case Float: 379 append(new Op2Stack(FSUB, result, a, loadNonConst(b))); 380 break; 381 case Long: 382 append(new Op2Stack(LSUB, result, a, loadNonConst(b))); 383 break; 384 case Double: 385 append(new Op2Stack(DSUB, result, a, loadNonConst(b))); 386 break; 387 default: 388 throw GraalInternalError.shouldNotReachHere(); 389 } 390 return result; 391 } 392 393 @Override 394 public Variable emitMul(Value a, Value b) { 395 Variable result = newVariable(a.getKind()); 396 switch (a.getKind()) { 397 case Int: 398 append(new Op2Reg(IMUL, result, a, loadNonConst(b))); 399 break; 400 case Long: 401 append(new Op2Reg(LMUL, result, a, loadNonConst(b))); 402 break; 403 case Float: 404 append(new Op2Reg(FMUL, result, a, loadNonConst(b))); 405 break; 406 case Double: 407 append(new Op2Reg(DMUL, result, a, loadNonConst(b))); 408 break; 409 default: 410 throw GraalInternalError.shouldNotReachHere(); 411 } 412 return result; 413 } 414 415 public Variable emitUMul(Value a, Value b) { 416 Variable result = newVariable(a.getKind()); 417 switch (a.getKind()) { 418 case Int: 419 append(new Op2Reg(LUMUL, result, a, loadNonConst(b))); 420 break; 421 case Long: 422 append(new Op2Reg(LUMUL, result, a, loadNonConst(b))); 423 break; 424 default: 425 throw GraalInternalError.shouldNotReachHere(); 426 } 427 return result; 428 } 429 430 @Override 431 protected boolean peephole(ValueNode valueNode) { 432 // No peephole optimizations for now. 433 return false; 434 } 435 436 @Override 437 public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) { 438 Variable result = newVariable(a.getKind()); 439 switch (a.getKind()) { 440 case Int: 441 append(new Op2Stack(IDIV, result, a, loadNonConst(b))); 442 break; 443 case Long: 444 append(new Op2Stack(LDIV, result, a, loadNonConst(b))); 445 break; 446 case Float: 447 append(new Op2Stack(FDIV, result, a, loadNonConst(b))); 448 break; 449 case Double: 450 append(new Op2Stack(DDIV, result, a, loadNonConst(b))); 451 break; 452 default: 453 throw GraalInternalError.shouldNotReachHere(); 454 } 455 return result; 456 457 } 458 459 @Override 460 public Value emitRem(Value a, Value b, DeoptimizingNode deopting) { 461 Variable result = newVariable(a.getKind()); 462 switch (a.getKind()) { 463 case Int: 464 append(new Op2Stack(IREM, result, a, loadNonConst(b))); 465 break; 466 case Long: 467 append(new Op2Stack(LREM, result, a, loadNonConst(b))); 468 break; 469 case Float: 470 append(new Op2Stack(FREM, result, a, loadNonConst(b))); 471 break; 472 case Double: 473 append(new Op2Stack(DREM, result, a, loadNonConst(b))); 474 break; 475 default: 476 throw GraalInternalError.shouldNotReachHere(); 477 } 478 return result; 479 } 480 481 @Override 482 public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) { 483 throw new InternalError("NYI"); 484 } 485 486 @Override 487 public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) { 488 throw new InternalError("NYI"); 489 } 490 491 @Override 492 public Variable emitAnd(Value a, Value b) { 493 Variable result = newVariable(a.getKind()); 494 switch (a.getKind()) { 495 case Int: 496 append(new Op2Stack(IAND, result, a, loadNonConst(b))); 497 break; 498 case Long: 499 append(new Op2Stack(LAND, result, a, loadNonConst(b))); 500 break; 501 default: 502 throw GraalInternalError.shouldNotReachHere(); 503 } 504 return result; 505 } 506 507 @Override 508 public Variable emitOr(Value a, Value b) { 509 throw new InternalError("NYI"); 510 } 511 512 @Override 513 public Variable emitXor(Value a, Value b) { 514 throw new InternalError("NYI"); 515 } 516 517 @Override 518 public Variable emitShl(Value a, Value b) { 519 Variable result = newVariable(a.getKind()); 520 switch (a.getKind()) { 521 case Int: 522 append(new ShiftOp(ISHL, result, a, b)); 523 break; 524 case Long: 525 append(new ShiftOp(LSHL, result, a, b)); 526 break; 527 default: 528 GraalInternalError.shouldNotReachHere(); 529 } 530 return result; 531 } 532 533 @Override 534 public Variable emitShr(Value a, Value b) { 535 throw new InternalError("NYI"); 536 } 537 538 @Override 539 public Variable emitUShr(Value a, Value b) { 540 Variable result = newVariable(a.getKind()); 541 switch (a.getKind()) { 542 case Int: 543 append(new ShiftOp(IUSHR, result, a, b)); 544 break; 545 case Long: 546 append(new ShiftOp(LUSHR, result, a, b)); 547 break; 548 default: 549 GraalInternalError.shouldNotReachHere(); 550 } 551 return result; 552 } 553 554 @Override 555 public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) { 556 Variable input = load(inputVal); 557 Variable result = newVariable(opcode.to); 558 switch (opcode) { 559 case I2F: 560 append(new Op1Stack(I2F, result, input)); 561 break; 562 case I2L: 563 append(new Op1Stack(I2L, result, input)); 564 break; 565 case I2D: 566 append(new Op1Stack(I2D, result, input)); 567 break; 568 case D2I: 569 append(new Op1Stack(D2I, result, input)); 570 break; 571 case L2I: 572 append(new Op1Stack(L2I, result, input)); 573 break; 574 case F2D: 575 append(new Op1Stack(F2D, result, input)); 576 break; 577 case D2F: 578 append(new Op1Stack(D2F, result, input)); 579 break; 580 default: 581 throw GraalInternalError.shouldNotReachHere(); 582 } 583 return result; 584 } 585 586 @Override 587 public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) { 588 append(new ReturnOp(Value.ILLEGAL)); 589 } 590 591 @Override 592 public void emitMembar(int barriers) { 593 throw new InternalError("NYI"); 594 } 595 596 @Override 597 protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { 598 throw new InternalError("NYI"); 599 } 600 601 @Override 602 protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { 603 throw new InternalError("NYI"); 604 } 605 606 @Override 607 protected void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { 608 String callName = linkage.getDescriptor().getName(); 609 if (callName.equals("createOutOfBoundsException") || callName.equals("createNullPointerException")) { 610 // hack Alert !! 611 switch (arguments.length) { 612 case 0: 613 append(new ForeignCallNoOp0(callName, result)); 614 break; 615 case 1: 616 append(new ForeignCallNoOp1(callName, result, arguments[0])); 617 break; 618 default: 619 throw new InternalError("NYI emitForeignCall"); 620 } 621 622 } else { 623 throw new InternalError("NYI emitForeignCall"); 624 } 625 } 626 627 @Override 628 public void emitBitCount(Variable result, Value value) { 629 if (value.getKind().getStackKind() == Kind.Int) { 630 append(new HSAILBitManipulationOp(IPOPCNT, result, value)); 631 } else { 632 append(new HSAILBitManipulationOp(LPOPCNT, result, value)); 633 } 634 } 635 636 @Override 637 public void emitBitScanForward(Variable result, Value value) { 638 throw new InternalError("NYI"); 639 } 640 641 @Override 642 public void emitBitScanReverse(Variable result, Value value) { 643 throw new InternalError("NYI"); 644 } 645 646 @Override 647 public void emitMathAbs(Variable result, Variable input) { 648 throw new InternalError("NYI"); 649 } 650 651 @Override 652 public void emitMathSqrt(Variable result, Variable input) { 653 append(new Op1Stack(SQRT, result, input)); 654 } 655 656 @Override 657 public void emitMathLog(Variable result, Variable input, boolean base10) { 658 throw new InternalError("NYI"); 659 } 660 661 @Override 662 public void emitMathCos(Variable result, Variable input) { 663 throw new InternalError("NYI"); 664 } 665 666 @Override 667 public void emitMathSin(Variable result, Variable input) { 668 throw new InternalError("NYI"); 669 } 670 671 @Override 672 public void emitMathTan(Variable result, Variable input) { 673 throw new InternalError("NYI"); 674 } 675 676 @Override 677 public void emitByteSwap(Variable result, Value input) { 678 throw new InternalError("NYI"); 679 } 680 681 @Override 682 protected void emitReturn(Value input) { 683 append(new ReturnOp(input)); 684 } 685 686 @Override 687 protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) { 688 throw new InternalError("NYI"); 689 } 690 691 @Override 692 protected void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key) { 693 throw new InternalError("NYI"); 694 } 695 696 @Override 697 protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) { 698 throw new InternalError("NYI"); 699 } 700 701 @Override 702 public void visitCompareAndSwap(CompareAndSwapNode node) { 703 throw new InternalError("NYI"); 704 } 705 706 @Override 707 public void visitBreakpointNode(BreakpointNode node) { 708 throw new InternalError("NYI"); 709 } 710 711 @Override 712 public void visitSafepointNode(SafepointNode i) { 713 Debug.log("visitSafePointNode unimplemented"); 714 } 715 716 @Override 717 public void emitUnwind(Value operand) { 718 throw new InternalError("NYI"); 719 } 720 721 @Override 722 public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { 723 assert v.kind() == Kind.Object; 724 Variable obj = newVariable(Kind.Object); 725 emitMove(obj, operand(v)); 726 append(new HSAILMove.NullCheckOp(obj, state(deopting))); 727 } 728 729 @Override 730 public void visitInfopointNode(InfopointNode i) { 731 throw new InternalError("NYI"); 732 } 733 }