001/*
002 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.hotspot.sparc;
024
025import static com.oracle.graal.hotspot.HotSpotBackend.*;
026import static jdk.internal.jvmci.sparc.SPARC.*;
027
028import com.oracle.graal.compiler.common.spi.*;
029import com.oracle.graal.compiler.gen.*;
030import com.oracle.graal.compiler.sparc.*;
031import com.oracle.graal.hotspot.*;
032import com.oracle.graal.hotspot.nodes.*;
033import com.oracle.graal.lir.*;
034import com.oracle.graal.lir.gen.*;
035import com.oracle.graal.lir.sparc.SPARCMove.*;
036import com.oracle.graal.nodes.*;
037import com.oracle.graal.nodes.CallTargetNode.*;
038import com.oracle.graal.nodes.spi.*;
039
040import jdk.internal.jvmci.code.*;
041
042import com.oracle.graal.debug.*;
043
044import jdk.internal.jvmci.hotspot.*;
045import jdk.internal.jvmci.meta.*;
046
047public class SPARCHotSpotNodeLIRBuilder extends SPARCNodeLIRBuilder implements HotSpotNodeLIRBuilder {
048
049    private HotSpotGraalRuntimeProvider runtime;
050
051    public SPARCHotSpotNodeLIRBuilder(HotSpotGraalRuntimeProvider runtime, StructuredGraph graph, LIRGeneratorTool lirGen) {
052        super(graph, lirGen);
053        this.runtime = runtime;
054        assert gen instanceof SPARCHotSpotLIRGenerator;
055        assert getDebugInfoBuilder() instanceof HotSpotDebugInfoBuilder;
056        ((SPARCHotSpotLIRGenerator) gen).setLockStack(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack());
057    }
058
059    @Override
060    protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeValueMap nodeValueMap) {
061        HotSpotLockStack lockStack = new HotSpotLockStack(gen.getResult().getFrameMapBuilder(), LIRKind.value(Kind.Long));
062        return new HotSpotDebugInfoBuilder(nodeValueMap, lockStack);
063    }
064
065    private SPARCHotSpotLIRGenerator getGen() {
066        return (SPARCHotSpotLIRGenerator) gen;
067    }
068
069    @Override
070    public void visitSafepointNode(SafepointNode i) {
071        LIRFrameState info = state(i);
072        append(new SPARCHotSpotSafepointOp(info, getGen().config, gen));
073    }
074
075    @Override
076    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
077        AllocatableValue address = gen.asAllocatable(operand(x.getAddress()));
078        AllocatableValue cmpValue = gen.asAllocatable(operand(x.expectedValue()));
079        AllocatableValue newValue = gen.asAllocatable(operand(x.newValue()));
080        LIRKind kind = cmpValue.getLIRKind();
081        assert kind.equals(newValue.getLIRKind());
082
083        Variable result = gen.newVariable(newValue.getLIRKind());
084        append(new CompareAndSwapOp(result, address, cmpValue, newValue));
085        setResult(x, result);
086    }
087
088    @Override
089    protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
090        InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind();
091        if (invokeKind.isIndirect()) {
092            append(new SPARCHotspotDirectVirtualCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, runtime.getConfig()));
093        } else {
094            assert invokeKind.isDirect();
095            HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod();
096            assert resolvedMethod.isConcrete() : "Cannot make direct call to abstract method.";
097            append(new SPARCHotspotDirectStaticCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, runtime.getConfig()));
098        }
099    }
100
101    @Override
102    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
103        Value metaspaceMethodSrc = operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod());
104        AllocatableValue metaspaceMethod = g5.asValue(metaspaceMethodSrc.getLIRKind());
105        gen.emitMove(metaspaceMethod, metaspaceMethodSrc);
106
107        Value targetAddressSrc = operand(callTarget.computedAddress());
108        AllocatableValue targetAddress = o7.asValue(targetAddressSrc.getLIRKind());
109        gen.emitMove(targetAddress, targetAddressSrc);
110        append(new SPARCIndirectCallOp(callTarget.targetMethod(), result, parameters, temps, metaspaceMethod, targetAddress, callState, runtime.getConfig()));
111    }
112
113    @Override
114    public void emitPatchReturnAddress(ValueNode address) {
115        append(new SPARCHotSpotPatchReturnAddressOp(gen.load(operand(address))));
116    }
117
118    public void emitJumpToExceptionHandler(ValueNode address) {
119        append(new SPARCHotSpotJumpToExceptionHandlerOp(gen.load(operand(address))));
120    }
121
122    @Override
123    public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
124        Variable handler = gen.load(operand(handlerInCallerPc));
125        ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER);
126        CallingConvention linkageCc = linkage.getOutgoingCallingConvention();
127        assert linkageCc.getArgumentCount() == 2;
128        RegisterValue exceptionFixed = (RegisterValue) linkageCc.getArgument(0);
129        RegisterValue exceptionPcFixed = (RegisterValue) linkageCc.getArgument(1);
130        gen.emitMove(exceptionFixed, operand(exception));
131        gen.emitMove(exceptionPcFixed, operand(exceptionPc));
132        Register thread = getGen().getProviders().getRegisters().getThreadRegister();
133        SPARCHotSpotJumpToExceptionHandlerInCallerOp op = new SPARCHotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, getGen().config.threadIsMethodHandleReturnOffset,
134                        thread);
135        append(op);
136    }
137
138    @Override
139    protected void emitPrologue(StructuredGraph graph) {
140        super.emitPrologue(graph);
141        AllocatableValue var = getGen().getSafepointAddressValue();
142        append(new SPARCHotSpotSafepointOp.SPARCLoadSafepointPollAddress(var, getGen().config));
143        getGen().append(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack());
144    }
145
146    @Override
147    public void visitFullInfopointNode(FullInfopointNode i) {
148        if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) {
149            Debug.log("Ignoring InfopointNode for AFTER_BCI");
150        } else {
151            super.visitFullInfopointNode(i);
152        }
153    }
154}