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 }