1 /*
   2  * Copyright (c) 2012, 2019, 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.hotspot.amd64;
  26 
  27 import static jdk.vm.ci.common.InitTimer.timer;
  28 
  29 import java.util.ArrayList;
  30 import java.util.List;
  31 
  32 import org.graalvm.compiler.bytecode.BytecodeProvider;
  33 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
  34 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
  35 import org.graalvm.compiler.hotspot.HotSpotBackend;
  36 import org.graalvm.compiler.hotspot.HotSpotBackendFactory;
  37 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
  38 import org.graalvm.compiler.hotspot.HotSpotReplacementsImpl;
  39 import org.graalvm.compiler.hotspot.meta.AddressLoweringHotSpotSuitesProvider;
  40 import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
  41 import org.graalvm.compiler.hotspot.meta.HotSpotGCProvider;
  42 import org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider;
  43 import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins;
  44 import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider;
  45 import org.graalvm.compiler.hotspot.meta.HotSpotLoweringProvider;
  46 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
  47 import org.graalvm.compiler.hotspot.meta.HotSpotRegisters;
  48 import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
  49 import org.graalvm.compiler.hotspot.meta.HotSpotSnippetReflectionProvider;
  50 import org.graalvm.compiler.hotspot.meta.HotSpotStampProvider;
  51 import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider;
  52 import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
  53 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
  54 import org.graalvm.compiler.nodes.spi.Replacements;
  55 import org.graalvm.compiler.options.OptionValues;
  56 import org.graalvm.compiler.phases.common.AddressLoweringPhase;
  57 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
  58 import org.graalvm.compiler.phases.util.Providers;
  59 import org.graalvm.compiler.replacements.amd64.AMD64GraphBuilderPlugins;
  60 import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
  61 import org.graalvm.compiler.serviceprovider.ServiceProvider;
  62 import org.graalvm.compiler.word.WordTypes;
  63 
  64 import jdk.vm.ci.amd64.AMD64;
  65 import jdk.vm.ci.code.Architecture;
  66 import jdk.vm.ci.code.Register;
  67 import jdk.vm.ci.code.RegisterConfig;
  68 import jdk.vm.ci.code.TargetDescription;
  69 import jdk.vm.ci.common.InitTimer;
  70 import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
  71 import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
  72 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
  73 import jdk.vm.ci.hotspot.HotSpotMetaAccessProvider;
  74 import jdk.vm.ci.meta.Value;
  75 import jdk.vm.ci.runtime.JVMCIBackend;
  76 
  77 @ServiceProvider(HotSpotBackendFactory.class)
  78 public class AMD64HotSpotBackendFactory extends HotSpotBackendFactory {
  79 
  80     @Override
  81     public String getName() {
  82         return "community";
  83     }
  84 
  85     @Override
  86     public Class<? extends Architecture> getArchitecture() {
  87         return AMD64.class;
  88     }
  89 
  90     @Override
  91     @SuppressWarnings("try")
  92     public HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRuntime, CompilerConfiguration compilerConfiguration, HotSpotJVMCIRuntime jvmciRuntime, HotSpotBackend host) {
  93         assert host == null;
  94 
  95         OptionValues options = graalRuntime.getOptions();
  96         JVMCIBackend jvmci = jvmciRuntime.getHostJVMCIBackend();
  97         GraalHotSpotVMConfig config = graalRuntime.getVMConfig();
  98         HotSpotProviders providers;
  99         HotSpotRegistersProvider registers;
 100         HotSpotCodeCacheProvider codeCache = (HotSpotCodeCacheProvider) jvmci.getCodeCache();
 101         TargetDescription target = codeCache.getTarget();
 102         HotSpotHostForeignCallsProvider foreignCalls;
 103         Value[] nativeABICallerSaveRegisters;
 104         HotSpotMetaAccessProvider metaAccess = (HotSpotMetaAccessProvider) jvmci.getMetaAccess();
 105         HotSpotConstantReflectionProvider constantReflection = (HotSpotConstantReflectionProvider) jvmci.getConstantReflection();
 106         ConstantFieldProvider constantFieldProvider = new HotSpotGraalConstantFieldProvider(config, metaAccess);
 107         HotSpotLoweringProvider lowerer;
 108         HotSpotStampProvider stampProvider;
 109         HotSpotGCProvider gc;
 110         HotSpotSnippetReflectionProvider snippetReflection;
 111         HotSpotReplacementsImpl replacements;
 112         HotSpotSuitesProvider suites;
 113         HotSpotWordTypes wordTypes;
 114         Plugins plugins;
 115         BytecodeProvider bytecodeProvider;
 116         try (InitTimer t = timer("create providers")) {
 117             try (InitTimer rt = timer("create HotSpotRegisters provider")) {
 118                 registers = createRegisters();
 119             }
 120             try (InitTimer rt = timer("create NativeABICallerSaveRegisters")) {
 121                 nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(config, codeCache.getRegisterConfig());
 122             }
 123             try (InitTimer rt = timer("create WordTypes")) {
 124                 wordTypes = createWordTypes(metaAccess, target);
 125             }
 126             try (InitTimer rt = timer("create ForeignCalls provider")) {
 127                 foreignCalls = createForeignCalls(jvmciRuntime, graalRuntime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters);
 128             }
 129             try (InitTimer rt = timer("create Lowerer provider")) {
 130                 lowerer = createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, target);
 131             }
 132             try (InitTimer rt = timer("create stamp provider")) {
 133                 stampProvider = createStampProvider();
 134             }
 135             try (InitTimer rt = timer("create GC provider")) {
 136                 gc = createGCProvider(config);
 137             }
 138 
 139             Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, gc);
 140 
 141             try (InitTimer rt = timer("create SnippetReflection provider")) {
 142                 snippetReflection = createSnippetReflection(graalRuntime, constantReflection, wordTypes);
 143             }
 144             try (InitTimer rt = timer("create Bytecode provider")) {
 145                 bytecodeProvider = createBytecodeProvider(metaAccess, snippetReflection);
 146             }
 147             try (InitTimer rt = timer("create Replacements provider")) {
 148                 replacements = createReplacements(target, p, snippetReflection, bytecodeProvider);
 149             }
 150             try (InitTimer rt = timer("create GraphBuilderPhase plugins")) {
 151                 plugins = createGraphBuilderPlugins(graalRuntime, compilerConfiguration, config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes,
 152                                 options);
 153                 replacements.setGraphBuilderPlugins(plugins);
 154             }
 155             try (InitTimer rt = timer("create Suites provider")) {
 156                 suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, registers, replacements, options);
 157             }
 158             providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers,
 159                             snippetReflection, wordTypes, plugins, gc);
 160             replacements.setProviders(providers);
 161         }
 162         try (InitTimer rt = timer("instantiate backend")) {
 163             return createBackend(config, graalRuntime, providers);
 164         }
 165     }
 166 
 167     protected Plugins createGraphBuilderPlugins(HotSpotGraalRuntimeProvider graalRuntime,
 168                     CompilerConfiguration compilerConfiguration,
 169                     GraalHotSpotVMConfig config,
 170                     TargetDescription target,
 171                     HotSpotConstantReflectionProvider constantReflection,
 172                     HotSpotHostForeignCallsProvider foreignCalls,
 173                     HotSpotMetaAccessProvider metaAccess,
 174                     HotSpotSnippetReflectionProvider snippetReflection,
 175                     HotSpotReplacementsImpl replacements,
 176                     HotSpotWordTypes wordTypes,
 177                     OptionValues options) {
 178         Plugins plugins = HotSpotGraphBuilderPlugins.create(
 179                         graalRuntime,
 180                         compilerConfiguration,
 181                         config,
 182                         wordTypes,
 183                         metaAccess,
 184                         constantReflection,
 185                         snippetReflection,
 186                         foreignCalls,
 187                         replacements,
 188                         options);
 189         AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false, JavaVersionUtil.JAVA_SPEC >= 9, config.useFMAIntrinsics);
 190         return plugins;
 191     }
 192 
 193     protected AMD64HotSpotBackend createBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
 194         return new AMD64HotSpotBackend(config, runtime, providers);
 195     }
 196 
 197     protected HotSpotRegistersProvider createRegisters() {
 198         return new HotSpotRegisters(AMD64.r15, AMD64.r12, AMD64.rsp);
 199     }
 200 
 201     protected AMD64HotSpotForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess,
 202                     HotSpotCodeCacheProvider codeCache, WordTypes wordTypes, Value[] nativeABICallerSaveRegisters) {
 203         return new AMD64HotSpotForeignCallsProvider(jvmciRuntime, runtime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters);
 204     }
 205 
 206     /**
 207      * @param replacements
 208      */
 209     protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins,
 210                     HotSpotRegistersProvider registers, Replacements replacements, OptionValues options) {
 211         return new AddressLoweringHotSpotSuitesProvider(new AMD64HotSpotSuitesCreator(compilerConfiguration, plugins), config, runtime,
 212                         new AddressLoweringPhase(new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister(), options)));
 213     }
 214 
 215     protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls,
 216                     HotSpotRegistersProvider registers, HotSpotConstantReflectionProvider constantReflection, TargetDescription target) {
 217         return new AMD64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, constantReflection, target);
 218     }
 219 
 220     protected Value[] createNativeABICallerSaveRegisters(GraalHotSpotVMConfig config, RegisterConfig regConfig) {
 221         List<Register> callerSave = new ArrayList<>(regConfig.getAllocatableRegisters().asList());
 222         if (config.windowsOs) {
 223             // http://msdn.microsoft.com/en-us/library/9z1stfyw.aspx
 224             callerSave.remove(AMD64.rdi);
 225             callerSave.remove(AMD64.rsi);
 226             callerSave.remove(AMD64.rbx);
 227             callerSave.remove(AMD64.rbp);
 228             callerSave.remove(AMD64.rsp);
 229             callerSave.remove(AMD64.r12);
 230             callerSave.remove(AMD64.r13);
 231             callerSave.remove(AMD64.r14);
 232             callerSave.remove(AMD64.r15);
 233             callerSave.remove(AMD64.xmm6);
 234             callerSave.remove(AMD64.xmm7);
 235             callerSave.remove(AMD64.xmm8);
 236             callerSave.remove(AMD64.xmm9);
 237             callerSave.remove(AMD64.xmm10);
 238             callerSave.remove(AMD64.xmm11);
 239             callerSave.remove(AMD64.xmm12);
 240             callerSave.remove(AMD64.xmm13);
 241             callerSave.remove(AMD64.xmm14);
 242             callerSave.remove(AMD64.xmm15);
 243         } else {
 244             /*
 245              * System V Application Binary Interface, AMD64 Architecture Processor Supplement
 246              *
 247              * Draft Version 0.96
 248              *
 249              * http://www.uclibc.org/docs/psABI-x86_64.pdf
 250              *
 251              * 3.2.1
 252              *
 253              * ...
 254              *
 255              * This subsection discusses usage of each register. Registers %rbp, %rbx and %r12
 256              * through %r15 "belong" to the calling function and the called function is required to
 257              * preserve their values. In other words, a called function must preserve these
 258              * registers' values for its caller. Remaining registers "belong" to the called
 259              * function. If a calling function wants to preserve such a register value across a
 260              * function call, it must save the value in its local stack frame.
 261              */
 262             callerSave.remove(AMD64.rbp);
 263             callerSave.remove(AMD64.rbx);
 264             callerSave.remove(AMD64.r12);
 265             callerSave.remove(AMD64.r13);
 266             callerSave.remove(AMD64.r14);
 267             callerSave.remove(AMD64.r15);
 268         }
 269         Value[] nativeABICallerSaveRegisters = new Value[callerSave.size()];
 270         for (int i = 0; i < callerSave.size(); i++) {
 271             nativeABICallerSaveRegisters[i] = callerSave.get(i).asValue();
 272         }
 273         return nativeABICallerSaveRegisters;
 274     }
 275 
 276     @Override
 277     public String toString() {
 278         return "AMD64";
 279     }
 280 }