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 }