1/*
2 * Copyright (c) 2011, 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 */
23package org.graalvm.compiler.hotspot.nodes;
24
25import static org.graalvm.compiler.nodeinfo.InputType.Memory;
26import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN;
27import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN;
28
29import java.util.Arrays;
30
31import org.graalvm.compiler.core.common.LocationIdentity;
32import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
33import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
34import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
35import org.graalvm.compiler.core.common.type.StampFactory;
36import org.graalvm.compiler.graph.NodeClass;
37import org.graalvm.compiler.graph.NodeInputList;
38import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil;
39import org.graalvm.compiler.nodeinfo.NodeInfo;
40import org.graalvm.compiler.nodeinfo.Verbosity;
41import org.graalvm.compiler.nodes.FixedWithNextNode;
42import org.graalvm.compiler.nodes.ValueNode;
43import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
44import org.graalvm.compiler.nodes.spi.LIRLowerable;
45import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
46
47import jdk.vm.ci.meta.JavaKind;
48import jdk.vm.ci.meta.Value;
49
50/**
51 * Node for a {@linkplain ForeignCallDescriptor foreign} call from within a stub.
52 */
53@NodeInfo(nameTemplate = "StubForeignCall#{p#descriptor/s}", allowedUsageTypes = Memory, cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN)
54public final class StubForeignCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi {
55
56    public static final NodeClass<StubForeignCallNode> TYPE = NodeClass.create(StubForeignCallNode.class);
57    @Input NodeInputList<ValueNode> arguments;
58    protected final ForeignCallsProvider foreignCalls;
59
60    protected final ForeignCallDescriptor descriptor;
61
62    public StubForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) {
63        super(TYPE, StampFactory.forKind(JavaKind.fromJavaClass(descriptor.getResultType())));
64        this.arguments = new NodeInputList<>(this, arguments);
65        this.descriptor = descriptor;
66        this.foreignCalls = foreignCalls;
67    }
68
69    public ForeignCallDescriptor getDescriptor() {
70        return descriptor;
71    }
72
73    @Override
74    public LocationIdentity[] getLocationIdentities() {
75        LocationIdentity[] killedLocations = foreignCalls.getKilledLocations(descriptor);
76        killedLocations = Arrays.copyOf(killedLocations, killedLocations.length + 1);
77        killedLocations[killedLocations.length - 1] = HotSpotReplacementsUtil.PENDING_EXCEPTION_LOCATION;
78        return killedLocations;
79    }
80
81    protected Value[] operands(NodeLIRBuilderTool gen) {
82        Value[] operands = new Value[arguments.size()];
83        for (int i = 0; i < operands.length; i++) {
84            operands[i] = gen.operand(arguments.get(i));
85        }
86        return operands;
87    }
88
89    @Override
90    public void generate(NodeLIRBuilderTool gen) {
91        assert graph().start() instanceof StubStartNode;
92        ForeignCallLinkage linkage = foreignCalls.lookupForeignCall(descriptor);
93        Value[] operands = operands(gen);
94        Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, null, operands);
95        if (result != null) {
96            gen.setResult(this, result);
97        }
98    }
99
100    @Override
101    public String toString(Verbosity verbosity) {
102        if (verbosity == Verbosity.Name) {
103            return super.toString(verbosity) + "#" + descriptor;
104        }
105        return super.toString(verbosity);
106    }
107}
108