| /* |
| * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| package org.graalvm.compiler.hotspot.sparc; |
| |
| import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; |
| import static jdk.vm.ci.sparc.SPARC.g5; |
| import static jdk.vm.ci.sparc.SPARC.o7; |
| |
| import org.graalvm.compiler.core.common.LIRKind; |
| import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; |
| import org.graalvm.compiler.core.gen.DebugInfoBuilder; |
| import org.graalvm.compiler.core.sparc.SPARCNodeLIRBuilder; |
| import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules; |
| import org.graalvm.compiler.debug.Debug; |
| import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; |
| import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; |
| import org.graalvm.compiler.hotspot.HotSpotLockStack; |
| import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; |
| import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; |
| import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; |
| import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; |
| import org.graalvm.compiler.lir.LIRFrameState; |
| import org.graalvm.compiler.lir.Variable; |
| import org.graalvm.compiler.lir.gen.LIRGeneratorTool; |
| import org.graalvm.compiler.lir.sparc.SPARCBreakpointOp; |
| import org.graalvm.compiler.lir.sparc.SPARCMove.CompareAndSwapOp; |
| import org.graalvm.compiler.nodes.BreakpointNode; |
| import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; |
| import org.graalvm.compiler.nodes.DirectCallTargetNode; |
| import org.graalvm.compiler.nodes.FullInfopointNode; |
| import org.graalvm.compiler.nodes.IndirectCallTargetNode; |
| import org.graalvm.compiler.nodes.SafepointNode; |
| import org.graalvm.compiler.nodes.StructuredGraph; |
| import org.graalvm.compiler.nodes.ValueNode; |
| import org.graalvm.compiler.nodes.spi.NodeValueMap; |
| |
| import jdk.vm.ci.code.BytecodeFrame; |
| import jdk.vm.ci.code.CallingConvention; |
| import jdk.vm.ci.code.Register; |
| import jdk.vm.ci.code.RegisterValue; |
| import jdk.vm.ci.hotspot.HotSpotCallingConventionType; |
| import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; |
| import jdk.vm.ci.meta.AllocatableValue; |
| import jdk.vm.ci.meta.JavaType; |
| import jdk.vm.ci.meta.Value; |
| import jdk.vm.ci.sparc.SPARCKind; |
| |
| public class SPARCHotSpotNodeLIRBuilder extends SPARCNodeLIRBuilder implements HotSpotNodeLIRBuilder { |
| |
| public SPARCHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen, SPARCNodeMatchRules nodeMatchRules) { |
| super(graph, lirGen, nodeMatchRules); |
| assert gen instanceof SPARCHotSpotLIRGenerator; |
| assert getDebugInfoBuilder() instanceof HotSpotDebugInfoBuilder; |
| ((SPARCHotSpotLIRGenerator) gen).setDebugInfoBuilder(((HotSpotDebugInfoBuilder) getDebugInfoBuilder())); |
| } |
| |
| @Override |
| protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeValueMap nodeValueMap) { |
| HotSpotLockStack lockStack = new HotSpotLockStack(gen.getResult().getFrameMapBuilder(), LIRKind.value(SPARCKind.XWORD)); |
| return new HotSpotDebugInfoBuilder(nodeValueMap, lockStack, (HotSpotLIRGenerator) gen); |
| } |
| |
| private SPARCHotSpotLIRGenerator getGen() { |
| return (SPARCHotSpotLIRGenerator) gen; |
| } |
| |
| @Override |
| public void visitSafepointNode(SafepointNode i) { |
| LIRFrameState info = state(i); |
| append(new SPARCHotSpotSafepointOp(info, getGen().config, gen)); |
| } |
| |
| @Override |
| public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { |
| AllocatableValue address = gen.asAllocatable(operand(x.getAddress())); |
| AllocatableValue cmpValue = gen.asAllocatable(operand(x.expectedValue())); |
| AllocatableValue newValue = gen.asAllocatable(operand(x.newValue())); |
| assert cmpValue.getValueKind().equals(newValue.getValueKind()); |
| |
| Variable result = gen.newVariable(newValue.getValueKind()); |
| append(new CompareAndSwapOp(result, address, cmpValue, newValue)); |
| setResult(x, result); |
| } |
| |
| @Override |
| protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { |
| InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind(); |
| if (invokeKind.isIndirect()) { |
| append(new SPARCHotspotDirectVirtualCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, getGen().config)); |
| } else { |
| assert invokeKind.isDirect(); |
| HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); |
| assert resolvedMethod.isConcrete() : "Cannot make direct call to abstract method."; |
| append(new SPARCHotspotDirectStaticCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, getGen().config)); |
| } |
| } |
| |
| @Override |
| protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { |
| Value metaspaceMethodSrc = operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()); |
| AllocatableValue metaspaceMethod = g5.asValue(metaspaceMethodSrc.getValueKind()); |
| gen.emitMove(metaspaceMethod, metaspaceMethodSrc); |
| |
| Value targetAddressSrc = operand(callTarget.computedAddress()); |
| AllocatableValue targetAddress = o7.asValue(targetAddressSrc.getValueKind()); |
| gen.emitMove(targetAddress, targetAddressSrc); |
| append(new SPARCIndirectCallOp(callTarget.targetMethod(), result, parameters, temps, metaspaceMethod, targetAddress, callState, getGen().config)); |
| } |
| |
| @Override |
| public void emitPatchReturnAddress(ValueNode address) { |
| append(new SPARCHotSpotPatchReturnAddressOp(gen.load(operand(address)))); |
| } |
| |
| @Override |
| public void emitJumpToExceptionHandler(ValueNode address) { |
| append(new SPARCHotSpotJumpToExceptionHandlerOp(gen.load(operand(address)))); |
| } |
| |
| @Override |
| public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { |
| Variable handler = gen.load(operand(handlerInCallerPc)); |
| ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER); |
| CallingConvention linkageCc = linkage.getOutgoingCallingConvention(); |
| assert linkageCc.getArgumentCount() == 2; |
| RegisterValue exceptionFixed = (RegisterValue) linkageCc.getArgument(0); |
| RegisterValue exceptionPcFixed = (RegisterValue) linkageCc.getArgument(1); |
| gen.emitMove(exceptionFixed, operand(exception)); |
| gen.emitMove(exceptionPcFixed, operand(exceptionPc)); |
| Register thread = getGen().getProviders().getRegisters().getThreadRegister(); |
| SPARCHotSpotJumpToExceptionHandlerInCallerOp op = new SPARCHotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, getGen().config.threadIsMethodHandleReturnOffset, |
| thread); |
| append(op); |
| } |
| |
| @Override |
| protected void emitPrologue(StructuredGraph graph) { |
| super.emitPrologue(graph); |
| AllocatableValue var = getGen().getSafepointAddressValue(); |
| append(new SPARCHotSpotSafepointOp.SPARCLoadSafepointPollAddress(var, getGen().config)); |
| getGen().append(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack()); |
| } |
| |
| @Override |
| public void visitFullInfopointNode(FullInfopointNode i) { |
| if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) { |
| Debug.log("Ignoring InfopointNode for AFTER_BCI"); |
| } else { |
| super.visitFullInfopointNode(i); |
| } |
| } |
| |
| @Override |
| public void visitBreakpointNode(BreakpointNode node) { |
| JavaType[] sig = new JavaType[node.arguments().size()]; |
| for (int i = 0; i < sig.length; i++) { |
| sig[i] = node.arguments().get(i).stamp().javaType(gen.getMetaAccess()); |
| } |
| |
| Value[] parameters = visitInvokeArguments(gen.getResult().getFrameMapBuilder().getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.JavaCall, null, sig, gen), |
| node.arguments()); |
| append(new SPARCBreakpointOp(parameters)); |
| } |
| } |