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 }