1 /*
   2  * Copyright (c) 2011, 2019, 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 
  25 package org.graalvm.compiler.lir.gen;
  26 
  27 import java.util.BitSet;
  28 import java.util.List;
  29 
  30 import org.graalvm.compiler.core.common.CompressEncoding;
  31 import org.graalvm.compiler.core.common.LIRKind;
  32 import org.graalvm.compiler.core.common.calc.Condition;
  33 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
  34 import org.graalvm.compiler.core.common.spi.CodeGenProviders;
  35 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
  36 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
  37 import org.graalvm.compiler.core.common.type.Stamp;
  38 import org.graalvm.compiler.debug.GraalError;
  39 import org.graalvm.compiler.graph.NodeSourcePosition;
  40 import org.graalvm.compiler.lir.LIRFrameState;
  41 import org.graalvm.compiler.lir.LIRInstruction;
  42 import org.graalvm.compiler.lir.LabelRef;
  43 import org.graalvm.compiler.lir.SwitchStrategy;
  44 import org.graalvm.compiler.lir.Variable;
  45 import org.graalvm.compiler.lir.VirtualStackSlot;
  46 
  47 import jdk.vm.ci.code.CodeCacheProvider;
  48 import jdk.vm.ci.code.Register;
  49 import jdk.vm.ci.code.RegisterAttributes;
  50 import jdk.vm.ci.code.RegisterConfig;
  51 import jdk.vm.ci.code.StackSlot;
  52 import jdk.vm.ci.code.TargetDescription;
  53 import jdk.vm.ci.code.ValueKindFactory;
  54 import jdk.vm.ci.meta.AllocatableValue;
  55 import jdk.vm.ci.meta.Constant;
  56 import jdk.vm.ci.meta.JavaConstant;
  57 import jdk.vm.ci.meta.JavaKind;
  58 import jdk.vm.ci.meta.MetaAccessProvider;
  59 import jdk.vm.ci.meta.PlatformKind;
  60 import jdk.vm.ci.meta.Value;
  61 import jdk.vm.ci.meta.ValueKind;
  62 
  63 public interface LIRGeneratorTool extends DiagnosticLIRGeneratorTool, ValueKindFactory<LIRKind> {
  64 
  65     /**
  66      * Factory for creating moves.
  67      */
  68     interface MoveFactory {
  69 
  70         /**
  71          * Checks whether the supplied constant can be used without loading it into a register for
  72          * most operations, i.e., for commonly used arithmetic, logical, and comparison operations.
  73          *
  74          * @param c The constant to check.
  75          * @return True if the constant can be used directly, false if the constant needs to be in a
  76          *         register.
  77          */
  78         boolean canInlineConstant(Constant c);
  79 
  80         /**
  81          * @param constant The constant that might be moved to a stack slot.
  82          * @return {@code true} if constant to stack moves are supported for this constant.
  83          */
  84         boolean allowConstantToStackMove(Constant constant);
  85 
  86         LIRInstruction createMove(AllocatableValue result, Value input);
  87 
  88         LIRInstruction createStackMove(AllocatableValue result, AllocatableValue input);
  89 
  90         LIRInstruction createLoad(AllocatableValue result, Constant input);
  91 
  92         LIRInstruction createStackLoad(AllocatableValue result, Constant input);
  93     }
  94 
  95     abstract class BlockScope implements AutoCloseable {
  96 
  97         public abstract AbstractBlockBase<?> getCurrentBlock();
  98 
  99         @Override
 100         public abstract void close();
 101 
 102     }
 103 
 104     ArithmeticLIRGeneratorTool getArithmetic();
 105 
 106     CodeGenProviders getProviders();
 107 
 108     TargetDescription target();
 109 
 110     MetaAccessProvider getMetaAccess();
 111 
 112     CodeCacheProvider getCodeCache();
 113 
 114     ForeignCallsProvider getForeignCalls();
 115 
 116     AbstractBlockBase<?> getCurrentBlock();
 117 
 118     LIRGenerationResult getResult();
 119 
 120     RegisterConfig getRegisterConfig();
 121 
 122     boolean hasBlockEnd(AbstractBlockBase<?> block);
 123 
 124     MoveFactory getMoveFactory();
 125 
 126     /**
 127      * Get a special {@link MoveFactory} for spill moves.
 128      *
 129      * The instructions returned by this factory must only depend on the input values. References to
 130      * values that require interaction with register allocation are strictly forbidden.
 131      */
 132     MoveFactory getSpillMoveFactory();
 133 
 134     BlockScope getBlockScope(AbstractBlockBase<?> block);
 135 
 136     Value emitConstant(LIRKind kind, Constant constant);
 137 
 138     Value emitJavaConstant(JavaConstant constant);
 139 
 140     /**
 141      * Some backends need to convert sub-word kinds to a larger kind in
 142      * {@link ArithmeticLIRGeneratorTool#emitLoad} and {@link #emitLoadConstant} because sub-word
 143      * registers can't be accessed. This method converts the {@link LIRKind} of a memory location or
 144      * constant to the {@link LIRKind} that will be used when it is loaded into a register.
 145      */
 146     <K extends ValueKind<K>> K toRegisterKind(K kind);
 147 
 148     AllocatableValue emitLoadConstant(ValueKind<?> kind, Constant constant);
 149 
 150     void emitNullCheck(Value address, LIRFrameState state);
 151 
 152     Variable emitLogicCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue);
 153 
 154     Value emitValueCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue);
 155 
 156     /**
 157      * Emit an atomic read-and-add instruction.
 158      *
 159      * @param address address of the value to be read and written
 160      * @param valueKind the access kind for the value to be written
 161      * @param delta the value to be added
 162      */
 163     default Value emitAtomicReadAndAdd(Value address, ValueKind<?> valueKind, Value delta) {
 164         throw GraalError.unimplemented();
 165     }
 166 
 167     /**
 168      * Emit an atomic read-and-write instruction.
 169      *
 170      * @param address address of the value to be read and written
 171      * @param valueKind the access kind for the value to be written
 172      * @param newValue the new value to be written
 173      */
 174     default Value emitAtomicReadAndWrite(Value address, ValueKind<?> valueKind, Value newValue) {
 175         throw GraalError.unimplemented();
 176     }
 177 
 178     void emitDeoptimize(Value actionAndReason, Value failedSpeculation, LIRFrameState state);
 179 
 180     Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args);
 181 
 182     RegisterAttributes attributes(Register register);
 183 
 184     /**
 185      * Create a new {@link Variable}.
 186      *
 187      * @param kind The type of the value that will be stored in this {@link Variable}. See
 188      *            {@link LIRKind} for documentation on what to pass here. Note that in most cases,
 189      *            simply passing {@link Value#getValueKind()} is wrong.
 190      * @return A new {@link Variable}.
 191      */
 192     Variable newVariable(ValueKind<?> kind);
 193 
 194     Variable emitMove(Value input);
 195 
 196     void emitMove(AllocatableValue dst, Value src);
 197 
 198     void emitMoveConstant(AllocatableValue dst, Constant src);
 199 
 200     Variable emitAddress(AllocatableValue stackslot);
 201 
 202     void emitMembar(int barriers);
 203 
 204     void emitUnwind(Value operand);
 205 
 206     /**
 207      * Called just before register allocation is performed on the LIR owned by this generator.
 208      * Overriding implementations of this method must call the overridden method.
 209      */
 210     void beforeRegisterAllocation();
 211 
 212     void emitIncomingValues(Value[] params);
 213 
 214     /**
 215      * Emits a return instruction. Implementations need to insert a move if the input is not in the
 216      * correct location.
 217      */
 218     void emitReturn(JavaKind javaKind, Value input);
 219 
 220     AllocatableValue asAllocatable(Value value);
 221 
 222     Variable load(Value value);
 223 
 224     Value loadNonConst(Value value);
 225 
 226     /**
 227      * Determines if only oop maps are required for the code generated from the LIR.
 228      */
 229     boolean needOnlyOopMaps();
 230 
 231     /**
 232      * Gets the ABI specific operand used to return a value of a given kind from a method.
 233      *
 234      * @param javaKind the {@link JavaKind} of value being returned
 235      * @param valueKind the backend type of the value being returned
 236      * @return the operand representing the ABI defined location used return a value of kind
 237      *         {@code kind}
 238      */
 239     AllocatableValue resultOperandFor(JavaKind javaKind, ValueKind<?> valueKind);
 240 
 241     <I extends LIRInstruction> I append(I op);
 242 
 243     void setSourcePosition(NodeSourcePosition position);
 244 
 245     void emitJump(LabelRef label);
 246 
 247     void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
 248                     double trueDestinationProbability);
 249 
 250     void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, LIRKind cmpKind, double overflowProbability);
 251 
 252     void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability);
 253 
 254     Variable emitConditionalMove(PlatformKind cmpKind, Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
 255 
 256     Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue);
 257 
 258     void emitStrategySwitch(JavaConstant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value);
 259 
 260     void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget);
 261 
 262     Variable emitByteSwap(Value operand);
 263 
 264     @SuppressWarnings("unused")
 265     default Variable emitArrayCompareTo(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length1, Value length2) {
 266         throw GraalError.unimplemented("String.compareTo substitution is not implemented on this architecture");
 267     }
 268 
 269     Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length, int constantLength, boolean directPointers);
 270 
 271     @SuppressWarnings("unused")
 272     default ForeignCallLinkage lookupArrayEqualsStub(JavaKind kind, int constantLength) {
 273         return null;
 274     }
 275 
 276     @SuppressWarnings("unused")
 277     default Variable emitArrayEquals(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length, int constantLength, boolean directPointers) {
 278         throw GraalError.unimplemented("Array.equals with different types substitution is not implemented on this architecture");
 279     }
 280 
 281     @SuppressWarnings("unused")
 282     default Variable emitArrayIndexOf(JavaKind kind, boolean findTwoConsecutive, Value sourcePointer, Value sourceCount, Value... searchValues) {
 283         throw GraalError.unimplemented("String.indexOf substitution is not implemented on this architecture");
 284     }
 285 
 286     /*
 287      * The routines emitStringLatin1Inflate/3 and emitStringUTF16Compress/3 models a simplified
 288      * version of
 289      *
 290      * emitStringLatin1Inflate(Value src, Value src_ndx, Value dst, Value dst_ndx, Value len) and
 291      * emitStringUTF16Compress(Value src, Value src_ndx, Value dst, Value dst_ndx, Value len)
 292      *
 293      * respectively, where we have hoisted the offset address computations in a method replacement
 294      * snippet.
 295      */
 296     @SuppressWarnings("unused")
 297     default void emitStringLatin1Inflate(Value src, Value dst, Value len) {
 298         throw GraalError.unimplemented("StringLatin1.inflate substitution is not implemented on this architecture");
 299     }
 300 
 301     @SuppressWarnings("unused")
 302     default Variable emitStringUTF16Compress(Value src, Value dst, Value len) {
 303         throw GraalError.unimplemented("StringUTF16.compress substitution is not implemented on this architecture");
 304     }
 305 
 306     void emitBlackhole(Value operand);
 307 
 308     LIRKind getLIRKind(Stamp stamp);
 309 
 310     void emitPause();
 311 
 312     void emitPrefetchAllocate(Value address);
 313 
 314     Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull);
 315 
 316     Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull);
 317 
 318     default void emitConvertNullToZero(AllocatableValue result, Value input) {
 319         emitMove(result, input);
 320     }
 321 
 322     default void emitConvertZeroToNull(AllocatableValue result, Value input) {
 323         emitMove(result, input);
 324     }
 325 
 326     /**
 327      * Emits an instruction that prevents speculative execution from proceeding: no instruction
 328      * after this fence will execute until all previous instructions have retired.
 329      */
 330     void emitSpeculationFence();
 331 
 332     default VirtualStackSlot allocateStackSlots(int slots, BitSet objects, List<VirtualStackSlot> outObjectStackSlots) {
 333         return getResult().getFrameMapBuilder().allocateStackSlots(slots, objects, outObjectStackSlots);
 334     }
 335 
 336     default Value emitReadCallerStackPointer(Stamp wordStamp) {
 337         /*
 338          * We do not know the frame size yet. So we load the address of the first spill slot
 339          * relative to the beginning of the frame, which is equivalent to the stack pointer of the
 340          * caller.
 341          */
 342         return emitAddress(StackSlot.get(getLIRKind(wordStamp), 0, true));
 343     }
 344 
 345     default Value emitReadReturnAddress(Stamp wordStamp, int returnAddressSize) {
 346         return emitMove(StackSlot.get(getLIRKind(wordStamp), -returnAddressSize, true));
 347     }
 348 }