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