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