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 }