1 /* 2 * Copyright (c) 2009, 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.core.target; 24 25 import java.util.Set; 26 27 import org.graalvm.compiler.asm.Assembler; 28 import org.graalvm.compiler.code.CompilationResult; 29 import org.graalvm.compiler.core.common.CompilationIdentifier; 30 import org.graalvm.compiler.core.common.LIRKind; 31 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; 32 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; 33 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; 34 import org.graalvm.compiler.debug.Debug; 35 import org.graalvm.compiler.debug.Debug.Scope; 36 import org.graalvm.compiler.lir.LIR; 37 import org.graalvm.compiler.lir.asm.CompilationResultBuilder; 38 import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; 39 import org.graalvm.compiler.lir.framemap.FrameMap; 40 import org.graalvm.compiler.lir.framemap.FrameMapBuilder; 41 import org.graalvm.compiler.lir.gen.LIRGenerationResult; 42 import org.graalvm.compiler.lir.gen.LIRGeneratorTool; 43 import org.graalvm.compiler.nodes.StructuredGraph; 44 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 45 import org.graalvm.compiler.phases.tiers.SuitesProvider; 46 import org.graalvm.compiler.phases.tiers.TargetProvider; 47 import org.graalvm.compiler.phases.util.Providers; 48 49 import jdk.vm.ci.code.BailoutException; 50 import jdk.vm.ci.code.CodeCacheProvider; 51 import jdk.vm.ci.code.CompilationRequest; 52 import jdk.vm.ci.code.CompiledCode; 53 import jdk.vm.ci.code.InstalledCode; 54 import jdk.vm.ci.code.Register; 55 import jdk.vm.ci.code.RegisterConfig; 56 import jdk.vm.ci.code.TargetDescription; 57 import jdk.vm.ci.code.ValueKindFactory; 58 import jdk.vm.ci.meta.ConstantReflectionProvider; 59 import jdk.vm.ci.meta.JavaKind; 60 import jdk.vm.ci.meta.MetaAccessProvider; 61 import jdk.vm.ci.meta.ResolvedJavaMethod; 62 import jdk.vm.ci.meta.SpeculationLog; 63 64 /** 65 * Represents a compiler backend for Graal. 66 */ 67 public abstract class Backend implements TargetProvider, ValueKindFactory<LIRKind> { 68 69 private final Providers providers; 70 71 public static final ForeignCallDescriptor ARITHMETIC_FREM = new ForeignCallDescriptor("arithmeticFrem", float.class, float.class, float.class); 72 public static final ForeignCallDescriptor ARITHMETIC_DREM = new ForeignCallDescriptor("arithmeticDrem", double.class, double.class, double.class); 73 74 protected Backend(Providers providers) { 75 this.providers = providers; 76 } 77 78 public Providers getProviders() { 79 return providers; 80 } 81 82 public CodeCacheProvider getCodeCache() { 83 return providers.getCodeCache(); 84 } 85 86 public MetaAccessProvider getMetaAccess() { 87 return providers.getMetaAccess(); 88 } 89 90 public ConstantReflectionProvider getConstantReflection() { 91 return providers.getConstantReflection(); 92 } 93 94 public ForeignCallsProvider getForeignCalls() { 95 return providers.getForeignCalls(); 96 } 97 98 public abstract SuitesProvider getSuites(); 99 100 @Override 101 public TargetDescription getTarget() { 102 return providers.getCodeCache().getTarget(); 103 } 104 105 @Override 106 public LIRKind getValueKind(JavaKind javaKind) { 107 return LIRKind.fromJavaKind(getTarget().arch, javaKind); 108 } 109 110 /** 111 * The given registerConfig is optional, in case null is passed the default RegisterConfig from 112 * the CodeCacheProvider will be used. 113 */ 114 public abstract FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig); 115 116 public abstract RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig); 117 118 public abstract FrameMap newFrameMap(RegisterConfig registerConfig); 119 120 public abstract LIRGeneratorTool newLIRGenerator(LIRGenerationResult lirGenRes); 121 122 public abstract LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph, 123 Object stub); 124 125 public abstract NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen); 126 127 /** 128 * Creates the assembler used to emit the machine code. 129 */ 130 protected abstract Assembler createAssembler(FrameMap frameMap); 131 132 /** 133 * Creates the object used to fill in the details of a given compilation result. 134 */ 135 public abstract CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenResult, FrameMap frameMap, CompilationResult compilationResult, 136 CompilationResultBuilderFactory factory); 137 138 /** 139 * Turns a Graal {@link CompilationResult} into a {@link CompiledCode} object that can be passed 140 * to the VM for code installation. 141 */ 142 protected abstract CompiledCode createCompiledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult); 143 144 /** 145 * @see #createInstalledCode(ResolvedJavaMethod, CompilationRequest, CompilationResult, 146 * SpeculationLog, InstalledCode, boolean) 147 */ 148 public InstalledCode createInstalledCode(ResolvedJavaMethod method, CompilationResult compilationResult, 149 SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault) { 150 return createInstalledCode(method, null, compilationResult, speculationLog, predefinedInstalledCode, isDefault); 151 } 152 153 /** 154 * Installs code based on a given compilation result. 155 * 156 * @param method the method compiled to produce {@code compiledCode} or {@code null} if the 157 * input to {@code compResult} was not a {@link ResolvedJavaMethod} 158 * @param compilationRequest the compilation request or {@code null} 159 * @param compilationResult the code to be compiled 160 * @param predefinedInstalledCode a pre-allocated {@link InstalledCode} object to use as a 161 * reference to the installed code. If {@code null}, a new {@link InstalledCode} 162 * object will be created. 163 * @param speculationLog the speculation log to be used 164 * @param isDefault specifies if the installed code should be made the default implementation of 165 * {@code compRequest.getMethod()}. The default implementation for a method is the 166 * code executed for standard calls to the method. This argument is ignored if 167 * {@code compRequest == null}. 168 * @return a reference to the compiled and ready-to-run installed code 169 * @throws BailoutException if the code installation failed 170 */ 171 @SuppressWarnings("try") 172 public InstalledCode createInstalledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult, 173 SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault) { 174 try (Scope s2 = Debug.scope("CodeInstall", getProviders().getCodeCache(), compilationResult)) { 175 CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult); 176 return getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, speculationLog, isDefault); 177 } catch (Throwable e) { 178 throw Debug.handle(e); 179 } 180 } 181 182 /** 183 * Installs code based on a given compilation result. 184 * 185 * @param method the method compiled to produce {@code compiledCode} or {@code null} if the 186 * input to {@code compResult} was not a {@link ResolvedJavaMethod} 187 * @param compilationRequest the request or {@code null} 188 * @param compilationResult the code to be compiled 189 * @return a reference to the compiled and ready-to-run installed code 190 * @throws BailoutException if the code installation failed 191 */ 192 public InstalledCode addInstalledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult) { 193 return createInstalledCode(method, compilationRequest, compilationResult, null, null, false); 194 } 195 196 /** 197 * Installs code based on a given compilation result and sets it as the default code to be used 198 * when {@code method} is invoked. 199 * 200 * @param method the method compiled to produce {@code compiledCode} or {@code null} if the 201 * input to {@code compResult} was not a {@link ResolvedJavaMethod} 202 * @param compilationResult the code to be compiled 203 * @return a reference to the compiled and ready-to-run installed code 204 * @throws BailoutException if the code installation failed 205 */ 206 public InstalledCode createDefaultInstalledCode(ResolvedJavaMethod method, CompilationResult compilationResult) { 207 return createInstalledCode(method, compilationResult, null, null, true); 208 } 209 210 /** 211 * Emits the code for a given graph. 212 * 213 * @param installedCodeOwner the method the compiled code will be associated with once 214 * installed. This argument can be null. 215 */ 216 public abstract void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner); 217 218 /** 219 * Translates a set of registers from the callee's perspective to the caller's perspective. This 220 * is needed for architectures where input/output registers are renamed during a call (e.g. 221 * register windows on SPARC). Registers which are not visible by the caller are removed. 222 */ 223 public abstract Set<Register> translateToCallerRegisters(Set<Register> calleeRegisters); 224 225 /** 226 * Gets the compilation id for a given {@link ResolvedJavaMethod}. Returns 227 * {@code CompilationIdentifier#INVALID_COMPILATION_ID} in case there is no such id. 228 * 229 * @param resolvedJavaMethod 230 */ 231 public CompilationIdentifier getCompilationIdentifier(ResolvedJavaMethod resolvedJavaMethod) { 232 return CompilationIdentifier.INVALID_COMPILATION_ID; 233 } 234 }