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