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