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