1/*
2 * Copyright (c) 2013, 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.hotspot.sparc;
24
25import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER;
26import static jdk.vm.ci.sparc.SPARC.g5;
27import static jdk.vm.ci.sparc.SPARC.o7;
28
29import org.graalvm.compiler.core.common.LIRKind;
30import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
31import org.graalvm.compiler.core.gen.DebugInfoBuilder;
32import org.graalvm.compiler.core.sparc.SPARCNodeLIRBuilder;
33import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules;
34import org.graalvm.compiler.debug.Debug;
35import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder;
36import org.graalvm.compiler.hotspot.HotSpotLIRGenerator;
37import org.graalvm.compiler.hotspot.HotSpotLockStack;
38import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder;
39import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode;
40import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode;
41import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode;
42import org.graalvm.compiler.lir.LIRFrameState;
43import org.graalvm.compiler.lir.Variable;
44import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
45import org.graalvm.compiler.lir.sparc.SPARCBreakpointOp;
46import org.graalvm.compiler.lir.sparc.SPARCMove.CompareAndSwapOp;
47import org.graalvm.compiler.nodes.BreakpointNode;
48import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
49import org.graalvm.compiler.nodes.DirectCallTargetNode;
50import org.graalvm.compiler.nodes.FullInfopointNode;
51import org.graalvm.compiler.nodes.IndirectCallTargetNode;
52import org.graalvm.compiler.nodes.SafepointNode;
53import org.graalvm.compiler.nodes.StructuredGraph;
54import org.graalvm.compiler.nodes.ValueNode;
55import org.graalvm.compiler.nodes.spi.NodeValueMap;
56
57import jdk.vm.ci.code.BytecodeFrame;
58import jdk.vm.ci.code.CallingConvention;
59import jdk.vm.ci.code.Register;
60import jdk.vm.ci.code.RegisterValue;
61import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
62import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
63import jdk.vm.ci.meta.AllocatableValue;
64import jdk.vm.ci.meta.JavaType;
65import jdk.vm.ci.meta.Value;
66import jdk.vm.ci.sparc.SPARCKind;
67
68public class SPARCHotSpotNodeLIRBuilder extends SPARCNodeLIRBuilder implements HotSpotNodeLIRBuilder {
69
70    public SPARCHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen, SPARCNodeMatchRules nodeMatchRules) {
71        super(graph, lirGen, nodeMatchRules);
72        assert gen instanceof SPARCHotSpotLIRGenerator;
73        assert getDebugInfoBuilder() instanceof HotSpotDebugInfoBuilder;
74        ((SPARCHotSpotLIRGenerator) gen).setDebugInfoBuilder(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()));
75    }
76
77    @Override
78    protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeValueMap nodeValueMap) {
79        HotSpotLockStack lockStack = new HotSpotLockStack(gen.getResult().getFrameMapBuilder(), LIRKind.value(SPARCKind.XWORD));
80        return new HotSpotDebugInfoBuilder(nodeValueMap, lockStack, (HotSpotLIRGenerator) gen);
81    }
82
83    private SPARCHotSpotLIRGenerator getGen() {
84        return (SPARCHotSpotLIRGenerator) gen;
85    }
86
87    @Override
88    public void visitSafepointNode(SafepointNode i) {
89        LIRFrameState info = state(i);
90        append(new SPARCHotSpotSafepointOp(info, getGen().config, gen));
91    }
92
93    @Override
94    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
95        AllocatableValue address = gen.asAllocatable(operand(x.getAddress()));
96        AllocatableValue cmpValue = gen.asAllocatable(operand(x.expectedValue()));
97        AllocatableValue newValue = gen.asAllocatable(operand(x.newValue()));
98        assert cmpValue.getValueKind().equals(newValue.getValueKind());
99
100        Variable result = gen.newVariable(newValue.getValueKind());
101        append(new CompareAndSwapOp(result, address, cmpValue, newValue));
102        setResult(x, result);
103    }
104
105    @Override
106    protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
107        InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind();
108        if (invokeKind.isIndirect()) {
109            append(new SPARCHotspotDirectVirtualCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, getGen().config));
110        } else {
111            assert invokeKind.isDirect();
112            HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod();
113            assert resolvedMethod.isConcrete() : "Cannot make direct call to abstract method.";
114            append(new SPARCHotspotDirectStaticCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, getGen().config));
115        }
116    }
117
118    @Override
119    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
120        Value metaspaceMethodSrc = operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod());
121        AllocatableValue metaspaceMethod = g5.asValue(metaspaceMethodSrc.getValueKind());
122        gen.emitMove(metaspaceMethod, metaspaceMethodSrc);
123
124        Value targetAddressSrc = operand(callTarget.computedAddress());
125        AllocatableValue targetAddress = o7.asValue(targetAddressSrc.getValueKind());
126        gen.emitMove(targetAddress, targetAddressSrc);
127        append(new SPARCIndirectCallOp(callTarget.targetMethod(), result, parameters, temps, metaspaceMethod, targetAddress, callState, getGen().config));
128    }
129
130    @Override
131    public void emitPatchReturnAddress(ValueNode address) {
132        append(new SPARCHotSpotPatchReturnAddressOp(gen.load(operand(address))));
133    }
134
135    @Override
136    public void emitJumpToExceptionHandler(ValueNode address) {
137        append(new SPARCHotSpotJumpToExceptionHandlerOp(gen.load(operand(address))));
138    }
139
140    @Override
141    public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
142        Variable handler = gen.load(operand(handlerInCallerPc));
143        ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER);
144        CallingConvention linkageCc = linkage.getOutgoingCallingConvention();
145        assert linkageCc.getArgumentCount() == 2;
146        RegisterValue exceptionFixed = (RegisterValue) linkageCc.getArgument(0);
147        RegisterValue exceptionPcFixed = (RegisterValue) linkageCc.getArgument(1);
148        gen.emitMove(exceptionFixed, operand(exception));
149        gen.emitMove(exceptionPcFixed, operand(exceptionPc));
150        Register thread = getGen().getProviders().getRegisters().getThreadRegister();
151        SPARCHotSpotJumpToExceptionHandlerInCallerOp op = new SPARCHotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, getGen().config.threadIsMethodHandleReturnOffset,
152                        thread);
153        append(op);
154    }
155
156    @Override
157    protected void emitPrologue(StructuredGraph graph) {
158        super.emitPrologue(graph);
159        AllocatableValue var = getGen().getSafepointAddressValue();
160        append(new SPARCHotSpotSafepointOp.SPARCLoadSafepointPollAddress(var, getGen().config));
161        getGen().append(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack());
162    }
163
164    @Override
165    public void visitFullInfopointNode(FullInfopointNode i) {
166        if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) {
167            Debug.log("Ignoring InfopointNode for AFTER_BCI");
168        } else {
169            super.visitFullInfopointNode(i);
170        }
171    }
172
173    @Override
174    public void visitBreakpointNode(BreakpointNode node) {
175        JavaType[] sig = new JavaType[node.arguments().size()];
176        for (int i = 0; i < sig.length; i++) {
177            sig[i] = node.arguments().get(i).stamp().javaType(gen.getMetaAccess());
178        }
179
180        Value[] parameters = visitInvokeArguments(gen.getResult().getFrameMapBuilder().getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.JavaCall, null, sig, gen),
181                        node.arguments());
182        append(new SPARCBreakpointOp(parameters));
183    }
184}
185