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