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.ptx;
  25 
  26 import static com.oracle.graal.api.code.ValueUtil.*;
  27 import static com.oracle.graal.lir.ptx.PTXArithmetic.*;
  28 import static com.oracle.graal.lir.ptx.PTXBitManipulationOp.IntrinsicOpcode.*;
  29 import static com.oracle.graal.lir.ptx.PTXCompare.*;
  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.graph.*;
  37 import com.oracle.graal.lir.*;
  38 import com.oracle.graal.lir.StandardOp.JumpOp;
  39 import com.oracle.graal.lir.ptx.*;
  40 import com.oracle.graal.lir.ptx.PTXArithmetic.Op1Stack;
  41 import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Reg;
  42 import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Stack;
  43 import com.oracle.graal.lir.ptx.PTXArithmetic.ShiftOp;
  44 import com.oracle.graal.lir.ptx.PTXCompare.CompareOp;
  45 import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp;
  46 import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp;
  47 import com.oracle.graal.lir.ptx.PTXMove.LoadOp;
  48 import com.oracle.graal.lir.ptx.PTXMove.MoveFromRegOp;
  49 import com.oracle.graal.lir.ptx.PTXMove.MoveToRegOp;
  50 import com.oracle.graal.lir.ptx.PTXMove.StoreOp;
  51 import com.oracle.graal.nodes.*;
  52 import com.oracle.graal.nodes.calc.*;
  53 import com.oracle.graal.nodes.java.*;
  54 
  55 /**
  56  * This class implements the PTX specific portion of the LIR generator.
  57  */
  58 public class PTXLIRGenerator extends LIRGenerator {
  59 
  60     public static class PTXSpillMoveFactory implements LIR.SpillMoveFactory {
  61 
  62         @Override
  63         public LIRInstruction createMove(Value result, Value input) {
  64             throw new InternalError("NYI");
  65         }
  66     }
  67 
  68     public PTXLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
  69         super(graph, runtime, target, frameMap, method, lir);
  70         lir.spillMoveFactory = new PTXSpillMoveFactory();
  71     }
  72 
  73     @Override
  74     protected void emitNode(ValueNode node) {
  75         if (node instanceof LIRGenLowerable) {
  76             ((LIRGenLowerable) node).generate(this);
  77         } else {
  78             super.emitNode(node);
  79         }
  80     }
  81 
  82     @Override
  83     public boolean canStoreConstant(Constant c) {
  84         // Operand b must be in the .reg state space.
  85         return false;
  86     }
  87 
  88     @Override
  89     public boolean canInlineConstant(Constant c) {
  90         switch (c.getKind()) {
  91             case Long:
  92                 return NumUtil.isInt(c.asLong()) && !runtime.needsDataPatch(c);
  93             case Object:
  94                 return c.isNull();
  95             default:
  96                 return true;
  97         }
  98     }
  99 
 100     @Override
 101     public Variable emitMove(Value input) {
 102         Variable result = newVariable(input.getKind());
 103         emitMove(result, input);
 104         return result;
 105     }
 106 
 107     @Override
 108     public void emitMove(Value dst, Value src) {
 109         if (isRegister(src) || isStackSlot(dst)) {
 110             append(new MoveFromRegOp(dst, src));
 111         } else {
 112             append(new MoveToRegOp(dst, src));
 113         }
 114     }
 115 
 116     private PTXAddressValue prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) {
 117         AllocatableValue baseRegister;
 118         long finalDisp = displacement;
 119         if (isConstant(base)) {
 120             if (asConstant(base).isNull()) {
 121                 baseRegister = AllocatableValue.UNUSED;
 122             } else if (asConstant(base).getKind() != Kind.Object) {
 123                 finalDisp += asConstant(base).asLong();
 124                 baseRegister = AllocatableValue.UNUSED;
 125             } else {
 126                 baseRegister = load(base);
 127             }
 128         } else if (base == Value.ILLEGAL) {
 129             baseRegister = AllocatableValue.UNUSED;
 130         } else {
 131             baseRegister = asAllocatable(base);
 132         }
 133 
 134         if (index != Value.ILLEGAL) {
 135             if (isConstant(index)) {
 136                 finalDisp += asConstant(index).asLong() * scale;
 137             } else {
 138                 Value indexRegister;
 139                 if (scale != 1) {
 140                     indexRegister = emitMul(index, Constant.forInt(scale));
 141                 } else {
 142                     indexRegister = index;
 143                 }
 144 
 145                 if (baseRegister == AllocatableValue.UNUSED) {
 146                     baseRegister = asAllocatable(indexRegister);
 147                 } else {
 148                     baseRegister = emitAdd(baseRegister, indexRegister);
 149                 }
 150             }
 151         }
 152 
 153         return new PTXAddressValue(kind, baseRegister, finalDisp);
 154     }
 155 
 156     @Override
 157     public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) {
 158         PTXAddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale);
 159         Variable result = newVariable(loadAddress.getKind());
 160         append(new LoadOp(result, loadAddress, canTrap ? state() : null));
 161         return result;
 162     }
 163 
 164     @Override
 165     public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, boolean canTrap) {
 166         PTXAddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale);
 167         Variable input = load(inputVal);
 168         append(new StoreOp(storeAddress, input, canTrap ? state() : null));
 169     }
 170 
 171     @Override
 172     public Variable emitLea(Value base, int displacement, Value index, int scale) {
 173         throw new InternalError("NYI");
 174     }
 175 
 176     @Override
 177     public Variable emitLea(StackSlot address) {
 178         throw new InternalError("NYI");
 179     }
 180 
 181     @Override
 182     public void emitJump(LabelRef label) {
 183         append(new JumpOp(label));
 184     }
 185 
 186     @Override
 187     public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) {
 188         switch (left.getKind().getStackKind()) {
 189             case Int:
 190                 append(new CompareOp(ICMP, cond, left, right));
 191                 append(new BranchOp(cond, label));
 192                 break;
 193             case Object:
 194                 append(new CompareOp(ACMP, cond, left, right));
 195                 append(new BranchOp(cond, label));
 196                 break;
 197             default:
 198                 throw GraalInternalError.shouldNotReachHere("" + left.getKind());
 199         }
 200     }
 201 
 202     @Override
 203     public void emitOverflowCheckBranch(LabelRef label, boolean negated) {
 204         throw new InternalError("NYI");
 205     }
 206 
 207     @Override
 208     public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) {
 209         throw new InternalError("NYI");
 210     }
 211 
 212     @Override
 213     public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
 214         throw new InternalError("NYI");
 215     }
 216 
 217     @Override
 218     public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) {
 219         throw new InternalError("NYI");
 220     }
 221 
 222     @Override
 223     public Variable emitNegate(Value input) {
 224         Variable result = newVariable(input.getKind());
 225         switch (input.getKind()) {
 226             case Int:
 227                 append(new Op1Stack(INEG, result, input));
 228                 break;
 229             default:
 230                 throw GraalInternalError.shouldNotReachHere();
 231         }
 232         return result;
 233     }
 234 
 235     @Override
 236     public Variable emitAdd(Value a, Value b) {
 237         Variable result = newVariable(a.getKind());
 238         switch (a.getKind()) {
 239             case Int:
 240                 append(new Op2Stack(IADD, result, a, loadNonConst(b)));
 241                 break;
 242             default:
 243                 throw GraalInternalError.shouldNotReachHere();
 244         }
 245         return result;
 246     }
 247 
 248     @Override
 249     public Variable emitSub(Value a, Value b) {
 250         Variable result = newVariable(a.getKind());
 251         switch (a.getKind()) {
 252             case Int:
 253                 append(new Op2Stack(ISUB, result, a, loadNonConst(b)));
 254                 break;
 255             default:
 256                 throw GraalInternalError.shouldNotReachHere();
 257         }
 258         return result;
 259     }
 260 
 261     @Override
 262     public Variable emitMul(Value a, Value b) {
 263         Variable result = newVariable(a.getKind());
 264         switch (a.getKind()) {
 265             case Int:
 266                 append(new Op2Reg(IMUL, result, a, loadNonConst(b)));
 267                 break;
 268             default:
 269                 throw GraalInternalError.shouldNotReachHere();
 270         }
 271         return result;
 272     }
 273 
 274     @Override
 275     protected boolean peephole(ValueNode valueNode) {
 276         // No peephole optimizations for now
 277         return false;
 278     }
 279 
 280     @Override
 281     public Value emitDiv(Value a, Value b) {
 282         throw new InternalError("NYI");
 283     }
 284 
 285     @Override
 286     public Value emitRem(Value a, Value b) {
 287         throw new InternalError("NYI");
 288     }
 289 
 290     @Override
 291     public Variable emitUDiv(Value a, Value b) {
 292         throw new InternalError("NYI");
 293     }
 294 
 295     @Override
 296     public Variable emitURem(Value a, Value b) {
 297         throw new InternalError("NYI");
 298     }
 299 
 300     @Override
 301     public Variable emitAnd(Value a, Value b) {
 302         Variable result = newVariable(a.getKind());
 303         switch (a.getKind()) {
 304             case Int:
 305                 append(new Op2Stack(IAND, result, a, loadNonConst(b)));
 306                 break;
 307             default:
 308                 throw GraalInternalError.shouldNotReachHere();
 309         }
 310         return result;
 311     }
 312 
 313     @Override
 314     public Variable emitOr(Value a, Value b) {
 315         throw new InternalError("NYI");
 316     }
 317 
 318     @Override
 319     public Variable emitXor(Value a, Value b) {
 320         throw new InternalError("NYI");
 321     }
 322 
 323     @Override
 324     public Variable emitShl(Value a, Value b) {
 325         throw new InternalError("NYI");
 326     }
 327 
 328     @Override
 329     public Variable emitShr(Value a, Value b) {
 330         throw new InternalError("NYI");
 331     }
 332 
 333     @Override
 334     public Variable emitUShr(Value a, Value b) {
 335         Variable result = newVariable(a.getKind());
 336         switch (a.getKind()) {
 337             case Int:
 338                 append(new ShiftOp(IUSHR, result, a, b));
 339                 break;
 340             default:
 341                 GraalInternalError.shouldNotReachHere();
 342         }
 343         return result;
 344     }
 345 
 346     @Override
 347     public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) {
 348         throw new InternalError("NYI");
 349     }
 350 
 351     @Override
 352     public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
 353         append(new ReturnOp(Value.ILLEGAL));
 354     }
 355 
 356     @Override
 357     public void emitMembar(int barriers) {
 358         throw new InternalError("NYI");
 359     }
 360 
 361     @Override
 362     protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
 363         throw new InternalError("NYI");
 364     }
 365 
 366     @Override
 367     protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
 368         throw new InternalError("NYI");
 369     }
 370 
 371     @Override
 372     protected void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
 373         throw new InternalError("NYI");
 374     }
 375 
 376     @Override
 377     public void emitBitCount(Variable result, Value value) {
 378         if (value.getKind().getStackKind() == Kind.Int) {
 379             append(new PTXBitManipulationOp(IPOPCNT, result, value));
 380         } else {
 381             append(new PTXBitManipulationOp(LPOPCNT, result, value));
 382         }
 383     }
 384 
 385     @Override
 386     public void emitBitScanForward(Variable result, Value value) {
 387         throw new InternalError("NYI");
 388     }
 389 
 390     @Override
 391     public void emitBitScanReverse(Variable result, Value value) {
 392         throw new InternalError("NYI");
 393     }
 394 
 395     @Override
 396     public void emitMathAbs(Variable result, Variable input) {
 397         throw new InternalError("NYI");
 398     }
 399 
 400     @Override
 401     public void emitMathSqrt(Variable result, Variable input) {
 402         throw new InternalError("NYI");
 403     }
 404 
 405     @Override
 406     public void emitMathLog(Variable result, Variable input, boolean base10) {
 407         throw new InternalError("NYI");
 408     }
 409 
 410     @Override
 411     public void emitMathCos(Variable result, Variable input) {
 412         throw new InternalError("NYI");
 413     }
 414 
 415     @Override
 416     public void emitMathSin(Variable result, Variable input) {
 417         throw new InternalError("NYI");
 418     }
 419 
 420     @Override
 421     public void emitMathTan(Variable result, Variable input) {
 422         throw new InternalError("NYI");
 423     }
 424 
 425     @Override
 426     public void emitByteSwap(Variable result, Value input) {
 427         throw new InternalError("NYI");
 428     }
 429 
 430     @Override
 431     protected void emitReturn(Value input) {
 432         append(new ReturnOp(input));
 433     }
 434 
 435     @Override
 436     protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
 437         throw new InternalError("NYI");
 438     }
 439 
 440     @Override
 441     protected void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key) {
 442         throw new InternalError("NYI");
 443     }
 444 
 445     @Override
 446     protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
 447         throw new InternalError("NYI");
 448     }
 449 
 450     @Override
 451     public void visitCompareAndSwap(CompareAndSwapNode node) {
 452         throw new InternalError("NYI");
 453     }
 454 
 455     @Override
 456     public void visitBreakpointNode(BreakpointNode node) {
 457         throw new InternalError("NYI");
 458     }
 459 
 460     @Override
 461     public void visitSafepointNode(SafepointNode i) {
 462         throw new InternalError("NYI");
 463     }
 464 
 465     @Override
 466     public void emitUnwind(Value operand) {
 467         // TODO Auto-generated method stub
 468 
 469     }
 470 
 471     @Override
 472     public void emitNullCheck(ValueNode v) {
 473         throw new InternalError("NYI");
 474     }
 475 }