1 /*
2  * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
3  * Copyright (c) 2018, Red Hat Inc. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.
9  *
10  * This code is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * version 2 for more details (a copy is included in the LICENSE file that
14  * accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License version
17  * 2 along with this work; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21  * or visit www.oracle.com if you need additional information or have any
22  * questions.
23  */
24 
25 
26 package org.graalvm.compiler.hotspot.aarch64;
27 
28 import static jdk.vm.ci.aarch64.AArch64.sp;
29 import static jdk.vm.ci.common.InitTimer.timer;
30 
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.List;
34 
35 import org.graalvm.compiler.bytecode.BytecodeProvider;
36 import org.graalvm.compiler.core.aarch64.AArch64AddressLoweringByUse;
37 import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool;
38 import org.graalvm.compiler.core.aarch64.AArch64SuitesCreator;
39 import org.graalvm.compiler.core.common.spi.MetaAccessExtensionProvider;
40 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
41 import org.graalvm.compiler.hotspot.HotSpotBackend;
42 import org.graalvm.compiler.hotspot.HotSpotBackendFactory;
43 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
44 import org.graalvm.compiler.hotspot.HotSpotReplacementsImpl;
45 import org.graalvm.compiler.hotspot.meta.AddressLoweringHotSpotSuitesProvider;
46 import org.graalvm.compiler.hotspot.meta.HotSpotConstantFieldProvider;
47 import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
48 import org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider;
49 import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins;
50 import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider;
51 import org.graalvm.compiler.hotspot.meta.HotSpotLoweringProvider;
52 import org.graalvm.compiler.hotspot.meta.HotSpotMetaAccessExtensionProvider;
53 import org.graalvm.compiler.hotspot.meta.HotSpotPlatformConfigurationProvider;
54 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
55 import org.graalvm.compiler.hotspot.meta.HotSpotRegisters;
56 import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
57 import org.graalvm.compiler.hotspot.meta.HotSpotSnippetReflectionProvider;
58 import org.graalvm.compiler.hotspot.meta.HotSpotStampProvider;
59 import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider;
60 import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
61 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
62 import org.graalvm.compiler.nodes.spi.PlatformConfigurationProvider;
63 import org.graalvm.compiler.nodes.spi.Replacements;
64 import org.graalvm.compiler.options.OptionValues;
65 import org.graalvm.compiler.phases.Phase;
66 import org.graalvm.compiler.phases.common.AddressLoweringByUsePhase;
67 import org.graalvm.compiler.phases.schedule.SchedulePhase;
68 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
69 import org.graalvm.compiler.replacements.aarch64.AArch64GraphBuilderPlugins;
70 import org.graalvm.compiler.serviceprovider.ServiceProvider;
71 import org.graalvm.compiler.word.WordTypes;
72 
73 import jdk.vm.ci.aarch64.AArch64;
74 import jdk.vm.ci.code.Architecture;
75 import jdk.vm.ci.code.Register;
76 import jdk.vm.ci.code.RegisterConfig;
77 import jdk.vm.ci.code.TargetDescription;
78 import jdk.vm.ci.common.InitTimer;
79 import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
80 import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
81 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
82 import jdk.vm.ci.hotspot.HotSpotMetaAccessProvider;
83 import jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig;
84 import jdk.vm.ci.meta.Value;
85 import jdk.vm.ci.runtime.JVMCIBackend;
86 
87 @ServiceProvider(HotSpotBackendFactory.class)
88 public class AArch64HotSpotBackendFactory extends HotSpotBackendFactory {
89 
90     @Override
getName()91     public String getName() {
92         return "community";
93     }
94 
95     @Override
getArchitecture()96     public Class<? extends Architecture> getArchitecture() {
97         return AArch64.class;
98     }
99 
100     @Override
101     @SuppressWarnings("try")
createBackend(HotSpotGraalRuntimeProvider graalRuntime, CompilerConfiguration compilerConfiguration, HotSpotJVMCIRuntime jvmciRuntime, HotSpotBackend host)102     public HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRuntime, CompilerConfiguration compilerConfiguration, HotSpotJVMCIRuntime jvmciRuntime, HotSpotBackend host) {
103         assert host == null;
104 
105         OptionValues options = graalRuntime.getOptions();
106         JVMCIBackend jvmci = jvmciRuntime.getHostJVMCIBackend();
107         GraalHotSpotVMConfig config = graalRuntime.getVMConfig();
108         HotSpotProviders providers;
109         HotSpotRegistersProvider registers;
110         HotSpotCodeCacheProvider codeCache = (HotSpotCodeCacheProvider) jvmci.getCodeCache();
111         TargetDescription target = codeCache.getTarget();
112         HotSpotHostForeignCallsProvider foreignCalls;
113         Value[] nativeABICallerSaveRegisters;
114         HotSpotMetaAccessProvider metaAccess = (HotSpotMetaAccessProvider) jvmci.getMetaAccess();
115         HotSpotConstantReflectionProvider constantReflection = (HotSpotConstantReflectionProvider) jvmci.getConstantReflection();
116         HotSpotConstantFieldProvider constantFieldProvider = new HotSpotGraalConstantFieldProvider(config, metaAccess);
117         HotSpotLoweringProvider lowerer;
118         HotSpotStampProvider stampProvider;
119         HotSpotPlatformConfigurationProvider platformConfigurationProvider;
120         HotSpotMetaAccessExtensionProvider metaAccessExtensionProvider;
121         HotSpotSnippetReflectionProvider snippetReflection;
122         HotSpotReplacementsImpl replacements;
123         HotSpotSuitesProvider suites;
124         HotSpotWordTypes wordTypes;
125         Plugins plugins;
126         BytecodeProvider bytecodeProvider;
127         try (InitTimer t = timer("create providers")) {
128             try (InitTimer rt = timer("create HotSpotRegisters provider")) {
129                 registers = createRegisters();
130             }
131             try (InitTimer rt = timer("create NativeABICallerSaveRegisters")) {
132                 nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(config, codeCache.getRegisterConfig());
133             }
134             try (InitTimer rt = timer("create WordTypes")) {
135                 wordTypes = createWordTypes(metaAccess, target);
136             }
137             try (InitTimer rt = timer("create ForeignCalls provider")) {
138                 foreignCalls = createForeignCalls(jvmciRuntime, graalRuntime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters);
139             }
140             try (InitTimer rt = timer("create stamp provider")) {
141                 stampProvider = createStampProvider();
142             }
143             try (InitTimer rt = timer("create platform configuration provider")) {
144                 platformConfigurationProvider = createConfigInfoProvider(config, metaAccess);
145             }
146             try (InitTimer rt = timer("create MetaAccessExtensionProvider")) {
147                 metaAccessExtensionProvider = createMetaAccessExtensionProvider();
148             }
149             try (InitTimer rt = timer("create Lowerer provider")) {
150                 lowerer = createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, platformConfigurationProvider, metaAccessExtensionProvider, target);
151             }
152 
153             HotSpotProviders p = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, platformConfigurationProvider,
154                             metaAccessExtensionProvider);
155 
156             try (InitTimer rt = timer("create SnippetReflection provider")) {
157                 snippetReflection = createSnippetReflection(graalRuntime, constantReflection, wordTypes);
158             }
159             try (InitTimer rt = timer("create Bytecode provider")) {
160                 bytecodeProvider = createBytecodeProvider(metaAccess, snippetReflection);
161             }
162             try (InitTimer rt = timer("create Replacements provider")) {
163                 replacements = createReplacements(target, p, snippetReflection, bytecodeProvider);
164             }
165             try (InitTimer rt = timer("create GraphBuilderPhase plugins")) {
166                 plugins = createGraphBuilderPlugins(graalRuntime, compilerConfiguration, config, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes,
167                                 graalRuntime.getOptions(), target);
168                 replacements.setGraphBuilderPlugins(plugins);
169             }
170             try (InitTimer rt = timer("create Suites provider")) {
171                 suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, replacements);
172             }
173             providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers,
174                             snippetReflection, wordTypes, plugins, platformConfigurationProvider, metaAccessExtensionProvider, config);
175             replacements.setProviders(providers);
176             replacements.maybeInitializeEncoder(options);
177         }
178         try (InitTimer rt = timer("instantiate backend")) {
179             return createBackend(config, graalRuntime, providers);
180         }
181     }
182 
createGraphBuilderPlugins(HotSpotGraalRuntimeProvider graalRuntime, CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, OptionValues options, TargetDescription target)183     protected Plugins createGraphBuilderPlugins(HotSpotGraalRuntimeProvider graalRuntime,
184                     CompilerConfiguration compilerConfiguration,
185                     GraalHotSpotVMConfig config,
186                     HotSpotConstantReflectionProvider constantReflection,
187                     HotSpotHostForeignCallsProvider foreignCalls,
188                     HotSpotMetaAccessProvider metaAccess,
189                     HotSpotSnippetReflectionProvider snippetReflection,
190                     HotSpotReplacementsImpl replacements,
191                     HotSpotWordTypes wordTypes,
192                     OptionValues options,
193                     TargetDescription target) {
194         Plugins plugins = HotSpotGraphBuilderPlugins.create(graalRuntime,
195                         compilerConfiguration,
196                         config,
197                         wordTypes,
198                         metaAccess,
199                         constantReflection,
200                         snippetReflection,
201                         foreignCalls,
202                         replacements,
203                         options,
204                         target);
205         AArch64GraphBuilderPlugins.register(plugins, replacements, false, //
206                         /* registerForeignCallMath */true, /* emitJDK9StringSubstitutions */true, config.useFMAIntrinsics);
207         return plugins;
208     }
209 
createBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers)210     protected AArch64HotSpotBackend createBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
211         return new AArch64HotSpotBackend(config, runtime, providers);
212     }
213 
createRegisters()214     protected HotSpotRegistersProvider createRegisters() {
215         return new HotSpotRegisters(AArch64HotSpotRegisterConfig.threadRegister, AArch64HotSpotRegisterConfig.heapBaseRegister, sp);
216     }
217 
createForeignCalls(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, WordTypes wordTypes, Value[] nativeABICallerSaveRegisters)218     protected HotSpotHostForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess,
219                     HotSpotCodeCacheProvider codeCache, WordTypes wordTypes, Value[] nativeABICallerSaveRegisters) {
220         return new AArch64HotSpotForeignCallsProvider(jvmciRuntime, runtime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters);
221     }
222 
createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins, @SuppressWarnings(R) Replacements replacements)223     protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins,
224                     @SuppressWarnings("unused") Replacements replacements) {
225         AArch64SuitesCreator suitesCreator = new AArch64SuitesCreator(compilerConfiguration, plugins, Arrays.asList(SchedulePhase.class));
226         Phase addressLoweringPhase = new AddressLoweringByUsePhase(new AArch64AddressLoweringByUse(new AArch64LIRKindTool()));
227         return new AddressLoweringHotSpotSuitesProvider(suitesCreator, config, runtime, addressLoweringPhase);
228     }
229 
createLowerer(HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, HotSpotConstantReflectionProvider constantReflection, PlatformConfigurationProvider platformConfig, MetaAccessExtensionProvider metaAccessExtensionProvider, TargetDescription target)230     protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls,
231                     HotSpotRegistersProvider registers, HotSpotConstantReflectionProvider constantReflection, PlatformConfigurationProvider platformConfig,
232                     MetaAccessExtensionProvider metaAccessExtensionProvider,
233                     TargetDescription target) {
234         return new AArch64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, constantReflection, platformConfig, metaAccessExtensionProvider, target);
235     }
236 
createNativeABICallerSaveRegisters(@uppressWarningsR) GraalHotSpotVMConfig config, RegisterConfig regConfig)237     protected static Value[] createNativeABICallerSaveRegisters(@SuppressWarnings("unused") GraalHotSpotVMConfig config, RegisterConfig regConfig) {
238         List<Register> callerSave = new ArrayList<>(regConfig.getAllocatableRegisters().asList());
239         callerSave.remove(AArch64.r19);
240         callerSave.remove(AArch64.r20);
241         callerSave.remove(AArch64.r21);
242         callerSave.remove(AArch64.r22);
243         callerSave.remove(AArch64.r23);
244         callerSave.remove(AArch64.r24);
245         callerSave.remove(AArch64.r25);
246         callerSave.remove(AArch64.r26);
247         callerSave.remove(AArch64.r27);
248         callerSave.remove(AArch64.r28);
249         Value[] nativeABICallerSaveRegisters = new Value[callerSave.size()];
250         for (int i = 0; i < callerSave.size(); i++) {
251             nativeABICallerSaveRegisters[i] = callerSave.get(i).asValue();
252         }
253         return nativeABICallerSaveRegisters;
254     }
255 
256     @Override
toString()257     public String toString() {
258         return "AArch64";
259     }
260 }
261