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