1/*
2 * Copyright (c) 2015, 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 */
23package org.graalvm.compiler.replacements.sparc;
24
25import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.COS;
26import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.EXP;
27import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG;
28import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10;
29import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN;
30import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN;
31
32import org.graalvm.compiler.bytecode.BytecodeProvider;
33import org.graalvm.compiler.nodes.ValueNode;
34import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
35import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
36import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
37import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
38import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
39import org.graalvm.compiler.replacements.IntegerSubstitutions;
40import org.graalvm.compiler.replacements.LongSubstitutions;
41import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode;
42import org.graalvm.compiler.replacements.nodes.BitCountNode;
43import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
44import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
45
46import jdk.vm.ci.meta.JavaKind;
47import jdk.vm.ci.meta.ResolvedJavaMethod;
48
49public class SPARCGraphBuilderPlugins {
50
51    public static void register(Plugins plugins, BytecodeProvider bytecodeProvider) {
52        InvocationPlugins invocationPlugins = plugins.getInvocationPlugins();
53        invocationPlugins.defer(new Runnable() {
54            @Override
55            public void run() {
56                registerIntegerLongPlugins(invocationPlugins, IntegerSubstitutions.class, JavaKind.Int, bytecodeProvider);
57                registerIntegerLongPlugins(invocationPlugins, LongSubstitutions.class, JavaKind.Long, bytecodeProvider);
58                registerMathPlugins(invocationPlugins);
59            }
60        });
61    }
62
63    private static void registerIntegerLongPlugins(InvocationPlugins plugins, Class<?> substituteDeclaringClass, JavaKind kind, BytecodeProvider bytecodeProvider) {
64        Class<?> declaringClass = kind.toBoxedJavaClass();
65        Class<?> type = kind.toJavaClass();
66        Registration r = new Registration(plugins, declaringClass, bytecodeProvider);
67        r.registerMethodSubstitution(substituteDeclaringClass, "numberOfLeadingZeros", type);
68        r.registerMethodSubstitution(substituteDeclaringClass, "numberOfTrailingZeros", type);
69
70        r.register1("bitCount", type, new InvocationPlugin() {
71            @Override
72            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
73                b.push(JavaKind.Int, b.append(new BitCountNode(value).canonical(null)));
74                return true;
75            }
76        });
77    }
78
79    private static void registerMathPlugins(InvocationPlugins plugins) {
80        Registration r = new Registration(plugins, Math.class);
81        registerUnaryMath(r, "sin", SIN);
82        registerUnaryMath(r, "cos", COS);
83        registerUnaryMath(r, "tan", TAN);
84        registerUnaryMath(r, "exp", EXP);
85        registerUnaryMath(r, "log", LOG);
86        registerUnaryMath(r, "log10", LOG10);
87        r.register2("pow", Double.TYPE, Double.TYPE, new InvocationPlugin() {
88            @Override
89            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
90                b.push(JavaKind.Double, b.append(BinaryMathIntrinsicNode.create(x, y, BinaryMathIntrinsicNode.BinaryOperation.POW)));
91                return true;
92            }
93        });
94    }
95
96    private static void registerUnaryMath(Registration r, String name, UnaryOperation operation) {
97        r.register1(name, Double.TYPE, new InvocationPlugin() {
98            @Override
99            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
100                b.push(JavaKind.Double, b.append(UnaryMathIntrinsicNode.create(value, operation)));
101                return true;
102            }
103        });
104    }
105}
106