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