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 */ 23 package org.graalvm.compiler.hotspot.sparc; 24 25 import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; 26 import static jdk.vm.ci.sparc.SPARC.g5; 27 import static jdk.vm.ci.sparc.SPARC.o7; 28 29 import org.graalvm.compiler.core.common.LIRKind; 30 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; 31 import org.graalvm.compiler.core.gen.DebugInfoBuilder; 32 import org.graalvm.compiler.core.sparc.SPARCNodeLIRBuilder; 33 import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules; 34 import org.graalvm.compiler.debug.Debug; 35 import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; 36 import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; 37 import org.graalvm.compiler.hotspot.HotSpotLockStack; 38 import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; 39 import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; 40 import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; 41 import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; 42 import org.graalvm.compiler.lir.LIRFrameState; 43 import org.graalvm.compiler.lir.Variable; 44 import org.graalvm.compiler.lir.gen.LIRGeneratorTool; 45 import org.graalvm.compiler.lir.sparc.SPARCBreakpointOp; 46 import org.graalvm.compiler.lir.sparc.SPARCMove.CompareAndSwapOp; 47 import org.graalvm.compiler.nodes.BreakpointNode; 48 import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; 49 import org.graalvm.compiler.nodes.DirectCallTargetNode; 50 import org.graalvm.compiler.nodes.FullInfopointNode; 51 import org.graalvm.compiler.nodes.IndirectCallTargetNode; 52 import org.graalvm.compiler.nodes.SafepointNode; 53 import org.graalvm.compiler.nodes.StructuredGraph; 54 import org.graalvm.compiler.nodes.ValueNode; 55 import org.graalvm.compiler.nodes.spi.NodeValueMap; 56 57 import jdk.vm.ci.code.BytecodeFrame; 58 import jdk.vm.ci.code.CallingConvention; 59 import jdk.vm.ci.code.Register; 60 import jdk.vm.ci.code.RegisterValue; 61 import jdk.vm.ci.hotspot.HotSpotCallingConventionType; 62 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; 63 import jdk.vm.ci.meta.AllocatableValue; 64 import jdk.vm.ci.meta.JavaType; 65 import jdk.vm.ci.meta.Value; 66 import jdk.vm.ci.sparc.SPARCKind; 67 68 public 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 }