1 /*
   2  * Copyright (c) 2011, 2016, 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.lir.gen;
  24 
  25 import org.graalvm.compiler.core.common.CompressEncoding;
  26 import org.graalvm.compiler.core.common.LIRKind;
  27 import org.graalvm.compiler.core.common.calc.Condition;
  28 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
  29 import org.graalvm.compiler.core.common.spi.CodeGenProviders;
  30 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
  31 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
  32 import org.graalvm.compiler.core.common.type.Stamp;
  33 import org.graalvm.compiler.debug.GraalError;
  34 import org.graalvm.compiler.graph.NodeSourcePosition;
  35 import org.graalvm.compiler.lir.LIRFrameState;
  36 import org.graalvm.compiler.lir.LIRInstruction;
  37 import org.graalvm.compiler.lir.LabelRef;
  38 import org.graalvm.compiler.lir.SwitchStrategy;
  39 import org.graalvm.compiler.lir.Variable;
  40 
  41 import jdk.vm.ci.code.CodeCacheProvider;
  42 import jdk.vm.ci.code.Register;
  43 import jdk.vm.ci.code.RegisterAttributes;
  44 import jdk.vm.ci.code.TargetDescription;
  45 import jdk.vm.ci.code.ValueKindFactory;
  46 import jdk.vm.ci.meta.AllocatableValue;
  47 import jdk.vm.ci.meta.Constant;
  48 import jdk.vm.ci.meta.JavaConstant;
  49 import jdk.vm.ci.meta.JavaKind;
  50 import jdk.vm.ci.meta.MetaAccessProvider;
  51 import jdk.vm.ci.meta.PlatformKind;
  52 import jdk.vm.ci.meta.Value;
  53 import jdk.vm.ci.meta.ValueKind;
  54 
  55 public interface LIRGeneratorTool extends DiagnosticLIRGeneratorTool, ValueKindFactory<LIRKind> {
  56 
  57     /**
  58      * Factory for creating moves.
  59      */
  60     public interface MoveFactory {
  61 
  62         /**
  63          * Checks whether the supplied constant can be used without loading it into a register for
  64          * most operations, i.e., for commonly used arithmetic, logical, and comparison operations.
  65          *
  66          * @param c The constant to check.
  67          * @return True if the constant can be used directly, false if the constant needs to be in a
  68          *         register.
  69          */
  70         boolean canInlineConstant(Constant c);
  71 
  72         /**
  73          * @param constant The constant that might be moved to a stack slot.
  74          * @return {@code true} if constant to stack moves are supported for this constant.
  75          */
  76         boolean allowConstantToStackMove(Constant constant);
  77 
  78         LIRInstruction createMove(AllocatableValue result, Value input);
  79 
  80         LIRInstruction createStackMove(AllocatableValue result, AllocatableValue input);
  81 
  82         LIRInstruction createLoad(AllocatableValue result, Constant input);
  83 
  84         LIRInstruction createStackLoad(AllocatableValue result, Constant input);
  85     }
  86 
  87     abstract class BlockScope implements AutoCloseable {
  88 
  89         public abstract AbstractBlockBase<?> getCurrentBlock();
  90 
  91         @Override
  92         public abstract void close();
  93 
  94     }
  95 
  96     ArithmeticLIRGeneratorTool getArithmetic();
  97 
  98     CodeGenProviders getProviders();
  99 
 100     TargetDescription target();
 101 
 102     MetaAccessProvider getMetaAccess();
 103 
 104     CodeCacheProvider getCodeCache();
 105 
 106     ForeignCallsProvider getForeignCalls();
 107 
 108     AbstractBlockBase<?> getCurrentBlock();
 109 
 110     LIRGenerationResult getResult();
 111 
 112     boolean hasBlockEnd(AbstractBlockBase<?> block);
 113 
 114     MoveFactory getMoveFactory();
 115 
 116     /**
 117      * Get a special {@link MoveFactory} for spill moves.
 118      *
 119      * The instructions returned by this factory must only depend on the input values. References to
 120      * values that require interaction with register allocation are strictly forbidden.
 121      */
 122     MoveFactory getSpillMoveFactory();
 123 
 124     BlockScope getBlockScope(AbstractBlockBase<?> block);
 125 
 126     Value emitConstant(LIRKind kind, Constant constant);
 127 
 128     Value emitJavaConstant(JavaConstant constant);
 129 
 130     /**
 131      * Some backends need to convert sub-word kinds to a larger kind in
 132      * {@link ArithmeticLIRGeneratorTool#emitLoad} and {@link #emitLoadConstant} because sub-word
 133      * registers can't be accessed. This method converts the {@link LIRKind} of a memory location or
 134      * constant to the {@link LIRKind} that will be used when it is loaded into a register.
 135      */
 136     <K extends ValueKind<K>> K toRegisterKind(K kind);
 137 
 138     AllocatableValue emitLoadConstant(ValueKind<?> kind, Constant constant);
 139 
 140     void emitNullCheck(Value address, LIRFrameState state);
 141 
 142     Variable emitLogicCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue);
 143 
 144     Value emitValueCompareAndSwap(Value address, Value expectedValue, Value newValue);
 145 
 146     /**
 147      * Emit an atomic read-and-add instruction.
 148      *
 149      * @param address address of the value to be read and written
 150      * @param delta the value to be added
 151      */
 152     default Value emitAtomicReadAndAdd(Value address, Value delta) {
 153         throw GraalError.unimplemented();
 154     }
 155 
 156     /**
 157      * Emit an atomic read-and-write instruction.
 158      *
 159      * @param address address of the value to be read and written
 160      * @param newValue the new value to be written
 161      */
 162     default Value emitAtomicReadAndWrite(Value address, Value newValue) {
 163         throw GraalError.unimplemented();
 164     }
 165 
 166     void emitDeoptimize(Value actionAndReason, Value failedSpeculation, LIRFrameState state);
 167 
 168     Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args);
 169 
 170     RegisterAttributes attributes(Register register);
 171 
 172     /**
 173      * Create a new {@link Variable}.
 174      *
 175      * @param kind The type of the value that will be stored in this {@link Variable}. See
 176      *            {@link LIRKind} for documentation on what to pass here. Note that in most cases,
 177      *            simply passing {@link Value#getValueKind()} is wrong.
 178      * @return A new {@link Variable}.
 179      */
 180     Variable newVariable(ValueKind<?> kind);
 181 
 182     Variable emitMove(Value input);
 183 
 184     void emitMove(AllocatableValue dst, Value src);
 185 
 186     void emitMoveConstant(AllocatableValue dst, Constant src);
 187 
 188     Variable emitAddress(AllocatableValue stackslot);
 189 
 190     void emitMembar(int barriers);
 191 
 192     void emitUnwind(Value operand);
 193 
 194     /**
 195      * Called just before register allocation is performed on the LIR owned by this generator.
 196      * Overriding implementations of this method must call the overridden method.
 197      */
 198     void beforeRegisterAllocation();
 199 
 200     void emitIncomingValues(Value[] params);
 201 
 202     /**
 203      * Emits a return instruction. Implementations need to insert a move if the input is not in the
 204      * correct location.
 205      */
 206     void emitReturn(JavaKind javaKind, Value input);
 207 
 208     AllocatableValue asAllocatable(Value value);
 209 
 210     Variable load(Value value);
 211 
 212     Value loadNonConst(Value value);
 213 
 214     /**
 215      * Determines if only oop maps are required for the code generated from the LIR.
 216      */
 217     boolean needOnlyOopMaps();
 218 
 219     /**
 220      * Gets the ABI specific operand used to return a value of a given kind from a method.
 221      *
 222      * @param javaKind the {@link JavaKind} of value being returned
 223      * @param valueKind the backend type of the value being returned
 224      * @return the operand representing the ABI defined location used return a value of kind
 225      *         {@code kind}
 226      */
 227     AllocatableValue resultOperandFor(JavaKind javaKind, ValueKind<?> valueKind);
 228 
 229     <I extends LIRInstruction> I append(I op);
 230 
 231     void setSourcePosition(NodeSourcePosition position);
 232 
 233     void emitJump(LabelRef label);
 234 
 235     void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
 236                     double trueDestinationProbability);
 237 
 238     void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, LIRKind cmpKind, double overflowProbability);
 239 
 240     void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability);
 241 
 242     Variable emitConditionalMove(PlatformKind cmpKind, Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
 243 
 244     Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue);
 245 
 246     void emitStrategySwitch(JavaConstant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value);
 247 
 248     void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget);
 249 
 250     Variable emitByteSwap(Value operand);
 251 
 252     Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length);
 253 
 254     @SuppressWarnings("unused")
 255     default Variable emitStringIndexOf(Value sourcePointer, Value sourceCount, Value targetPointer, Value targetCount, int constantTargetCount) {
 256         throw GraalError.unimplemented();
 257     }
 258 
 259     void emitBlackhole(Value operand);
 260 
 261     LIRKind getLIRKind(Stamp stamp);
 262 
 263     void emitPause();
 264 
 265     void emitPrefetchAllocate(Value address);
 266 
 267     Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull);
 268 
 269     Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull);
 270 
 271 }