1 /* 2 * Copyright (c) 2015, 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 */ 23 package org.graalvm.compiler.hotspot.aarch64; 24 25 import static jdk.vm.ci.aarch64.AArch64.lr; 26 import static jdk.vm.ci.code.ValueUtil.isStackSlot; 27 import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp; 28 import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.inlineCacheRegister; 29 import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.metaspaceMethodRegister; 30 import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; 31 32 import org.graalvm.compiler.core.aarch64.AArch64NodeLIRBuilder; 33 import org.graalvm.compiler.core.aarch64.AArch64NodeMatchRules; 34 import org.graalvm.compiler.core.common.LIRKind; 35 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; 36 import org.graalvm.compiler.core.gen.DebugInfoBuilder; 37 import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; 38 import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; 39 import org.graalvm.compiler.hotspot.HotSpotLockStack; 40 import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; 41 import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; 42 import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; 43 import org.graalvm.compiler.lir.LIRFrameState; 44 import org.graalvm.compiler.lir.Variable; 45 import org.graalvm.compiler.lir.aarch64.AArch64BreakpointOp; 46 import org.graalvm.compiler.lir.gen.LIRGeneratorTool; 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.ParameterNode; 53 import org.graalvm.compiler.nodes.SafepointNode; 54 import org.graalvm.compiler.nodes.StructuredGraph; 55 import org.graalvm.compiler.nodes.ValueNode; 56 import org.graalvm.compiler.nodes.spi.NodeValueMap; 57 58 import jdk.vm.ci.aarch64.AArch64Kind; 59 import jdk.vm.ci.code.BytecodeFrame; 60 import jdk.vm.ci.code.CallingConvention; 61 import jdk.vm.ci.code.Register; 62 import jdk.vm.ci.code.RegisterValue; 63 import jdk.vm.ci.code.StackSlot; 64 import jdk.vm.ci.code.ValueUtil; 65 import jdk.vm.ci.hotspot.HotSpotCallingConventionType; 66 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; 67 import jdk.vm.ci.meta.AllocatableValue; 68 import jdk.vm.ci.meta.JavaType; 69 import jdk.vm.ci.meta.Value; 70 71 /** 72 * LIR generator specialized for AArch64 HotSpot. 73 */ 74 public class AArch64HotSpotNodeLIRBuilder extends AArch64NodeLIRBuilder implements HotSpotNodeLIRBuilder { 75 76 public AArch64HotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen, AArch64NodeMatchRules nodeMatchRules) { 77 super(graph, gen, nodeMatchRules); 78 assert gen instanceof AArch64HotSpotLIRGenerator; 79 assert getDebugInfoBuilder() instanceof HotSpotDebugInfoBuilder; 80 ((AArch64HotSpotLIRGenerator) gen).setDebugInfoBuilder(((HotSpotDebugInfoBuilder) getDebugInfoBuilder())); 81 } 82 83 @Override 84 protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeValueMap nodeValueMap) { 85 HotSpotLockStack lockStack = new HotSpotLockStack(gen.getResult().getFrameMapBuilder(), LIRKind.value(AArch64Kind.QWORD)); 86 return new HotSpotDebugInfoBuilder(nodeValueMap, lockStack, (HotSpotLIRGenerator) gen); 87 } 88 89 private AArch64HotSpotLIRGenerator getGen() { 90 return (AArch64HotSpotLIRGenerator) gen; 91 } 92 93 @Override 94 protected void emitPrologue(StructuredGraph graph) { 95 CallingConvention incomingArguments = gen.getResult().getCallingConvention(); 96 Value[] params = new Value[incomingArguments.getArgumentCount() + 2]; 97 for (int i = 0; i < incomingArguments.getArgumentCount(); i++) { 98 params[i] = incomingArguments.getArgument(i); 99 if (isStackSlot(params[i])) { 100 StackSlot slot = ValueUtil.asStackSlot(params[i]); 101 if (slot.isInCallerFrame() && !gen.getResult().getLIR().hasArgInCallerFrame()) { 102 gen.getResult().getLIR().setHasArgInCallerFrame(); 103 } 104 } 105 } 106 params[params.length - 2] = fp.asValue(LIRKind.value(AArch64Kind.QWORD)); 107 params[params.length - 1] = lr.asValue(LIRKind.value(AArch64Kind.QWORD)); 108 109 gen.emitIncomingValues(params); 110 111 for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { 112 Value paramValue = params[param.index()]; 113 assert paramValue.getValueKind().equals(getLIRGeneratorTool().getLIRKind(param.stamp())) : paramValue.getValueKind() + " != " + param.stamp(); 114 setResult(param, gen.emitMove(paramValue)); 115 } 116 } 117 118 @Override 119 public void visitSafepointNode(SafepointNode i) { 120 LIRFrameState info = state(i); 121 Variable scratch = gen.newVariable(LIRKind.value(getGen().target().arch.getWordKind())); 122 append(new AArch64HotSpotSafepointOp(info, getGen().config, scratch)); 123 } 124 125 @Override 126 protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { 127 InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind(); 128 if (invokeKind.isIndirect()) { 129 append(new AArch64HotSpotDirectVirtualCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, getGen().config)); 130 } else { 131 assert invokeKind.isDirect(); 132 HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); 133 assert resolvedMethod.isConcrete() : "Cannot make direct call to abstract method."; 134 append(new AArch64HotSpotDirectStaticCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, getGen().config)); 135 } 136 } 137 138 @Override 139 protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { 140 Value metaspaceMethodSrc = operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()); 141 Value targetAddressSrc = operand(callTarget.computedAddress()); 142 AllocatableValue metaspaceMethodDst = metaspaceMethodRegister.asValue(metaspaceMethodSrc.getValueKind()); 143 AllocatableValue targetAddressDst = inlineCacheRegister.asValue(targetAddressSrc.getValueKind()); 144 gen.emitMove(metaspaceMethodDst, metaspaceMethodSrc); 145 gen.emitMove(targetAddressDst, targetAddressSrc); 146 append(new AArch64IndirectCallOp(callTarget.targetMethod(), result, parameters, temps, metaspaceMethodDst, targetAddressDst, callState, getGen().config)); 147 } 148 149 @Override 150 public void emitPatchReturnAddress(ValueNode address) { 151 append(new AArch64HotSpotPatchReturnAddressOp(gen.load(operand(address)))); 152 } 153 154 @Override 155 public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { 156 Variable handler = gen.load(operand(handlerInCallerPc)); 157 ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER); 158 CallingConvention outgoingCc = linkage.getOutgoingCallingConvention(); 159 assert outgoingCc.getArgumentCount() == 2; 160 RegisterValue exceptionFixed = (RegisterValue) outgoingCc.getArgument(0); 161 RegisterValue exceptionPcFixed = (RegisterValue) outgoingCc.getArgument(1); 162 gen.emitMove(exceptionFixed, operand(exception)); 163 gen.emitMove(exceptionPcFixed, operand(exceptionPc)); 164 Register thread = getGen().getProviders().getRegisters().getThreadRegister(); 165 AArch64HotSpotJumpToExceptionHandlerInCallerOp op = new AArch64HotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, 166 getGen().config.threadIsMethodHandleReturnOffset, thread, getGen().config); 167 append(op); 168 } 169 170 @Override 171 public void visitFullInfopointNode(FullInfopointNode i) { 172 if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) { 173 i.getDebug().log("Ignoring InfopointNode for AFTER_BCI"); 174 } else { 175 super.visitFullInfopointNode(i); 176 } 177 } 178 179 @Override 180 public void visitBreakpointNode(BreakpointNode node) { 181 JavaType[] sig = new JavaType[node.arguments().size()]; 182 for (int i = 0; i < sig.length; i++) { 183 sig[i] = node.arguments().get(i).stamp().javaType(gen.getMetaAccess()); 184 } 185 186 Value[] parameters = visitInvokeArguments(gen.getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.JavaCall, null, sig, gen), node.arguments()); 187 append(new AArch64BreakpointOp(parameters)); 188 } 189 }