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