001/*
002 * Copyright (c) 2012, 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.amd64;
024
025import static com.oracle.graal.hotspot.HotSpotBackend.*;
026import static jdk.internal.jvmci.amd64.AMD64.*;
027import static jdk.internal.jvmci.code.ValueUtil.*;
028
029import com.oracle.graal.compiler.amd64.*;
030import com.oracle.graal.compiler.common.spi.*;
031import com.oracle.graal.compiler.gen.*;
032import com.oracle.graal.hotspot.*;
033import com.oracle.graal.hotspot.nodes.*;
034import com.oracle.graal.lir.*;
035import com.oracle.graal.lir.amd64.AMD64Move.*;
036import com.oracle.graal.lir.gen.*;
037import com.oracle.graal.nodes.*;
038import com.oracle.graal.nodes.CallTargetNode.*;
039import com.oracle.graal.nodes.spi.*;
040
041import jdk.internal.jvmci.amd64.*;
042import jdk.internal.jvmci.code.*;
043
044import com.oracle.graal.debug.*;
045
046import jdk.internal.jvmci.hotspot.*;
047import jdk.internal.jvmci.meta.*;
048
049/**
050 * LIR generator specialized for AMD64 HotSpot.
051 */
052public class AMD64HotSpotNodeLIRBuilder extends AMD64NodeLIRBuilder implements HotSpotNodeLIRBuilder {
053
054    private final HotSpotGraalRuntimeProvider runtime;
055
056    public AMD64HotSpotNodeLIRBuilder(HotSpotGraalRuntimeProvider runtime, StructuredGraph graph, LIRGeneratorTool gen) {
057        super(graph, gen);
058        this.runtime = runtime;
059        assert gen instanceof AMD64HotSpotLIRGenerator;
060        assert getDebugInfoBuilder() instanceof HotSpotDebugInfoBuilder;
061        ((AMD64HotSpotLIRGenerator) gen).setLockStack(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack());
062    }
063
064    private AMD64HotSpotLIRGenerator getGen() {
065        return (AMD64HotSpotLIRGenerator) gen;
066    }
067
068    @Override
069    protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeValueMap nodeValueMap) {
070        HotSpotLockStack lockStack = new HotSpotLockStack(gen.getResult().getFrameMapBuilder(), LIRKind.value(Kind.Long));
071        return new HotSpotDebugInfoBuilder(nodeValueMap, lockStack);
072    }
073
074    @Override
075    protected void emitPrologue(StructuredGraph graph) {
076
077        CallingConvention incomingArguments = gen.getCallingConvention();
078
079        Value[] params = new Value[incomingArguments.getArgumentCount() + 1];
080        for (int i = 0; i < params.length - 1; i++) {
081            params[i] = LIRGenerator.toStackKind(incomingArguments.getArgument(i));
082            if (isStackSlot(params[i])) {
083                StackSlot slot = ValueUtil.asStackSlot(params[i]);
084                if (slot.isInCallerFrame() && !gen.getResult().getLIR().hasArgInCallerFrame()) {
085                    gen.getResult().getLIR().setHasArgInCallerFrame();
086                }
087            }
088        }
089        params[params.length - 1] = rbp.asValue(LIRKind.value(Kind.Long));
090
091        gen.emitIncomingValues(params);
092
093        getGen().emitSaveRbp();
094
095        getGen().append(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack());
096
097        for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) {
098            Value paramValue = params[param.index()];
099            assert paramValue.getLIRKind().equals(getLIRGeneratorTool().getLIRKind(param.stamp()));
100            setResult(param, gen.emitMove(paramValue));
101        }
102    }
103
104    @Override
105    public void visitSafepointNode(SafepointNode i) {
106        LIRFrameState info = state(i);
107        append(new AMD64HotSpotSafepointOp(info, getGen().config, this));
108    }
109
110    @Override
111    protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
112        InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind();
113        if (invokeKind.isIndirect()) {
114            append(new AMD64HotspotDirectVirtualCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, runtime.getConfig()));
115        } else {
116            assert invokeKind.isDirect();
117            HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod();
118            assert resolvedMethod.isConcrete() : "Cannot make direct call to abstract method.";
119            append(new AMD64HotSpotDirectStaticCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, runtime.getConfig()));
120        }
121    }
122
123    @Override
124    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
125        if (callTarget instanceof HotSpotIndirectCallTargetNode) {
126            Value metaspaceMethodSrc = operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod());
127            Value targetAddressSrc = operand(callTarget.computedAddress());
128            AllocatableValue metaspaceMethodDst = AMD64.rbx.asValue(metaspaceMethodSrc.getLIRKind());
129            AllocatableValue targetAddressDst = AMD64.rax.asValue(targetAddressSrc.getLIRKind());
130            gen.emitMove(metaspaceMethodDst, metaspaceMethodSrc);
131            gen.emitMove(targetAddressDst, targetAddressSrc);
132            append(new AMD64IndirectCallOp(callTarget.targetMethod(), result, parameters, temps, metaspaceMethodDst, targetAddressDst, callState, runtime.getConfig()));
133        } else {
134            super.emitIndirectCall(callTarget, result, parameters, temps, callState);
135        }
136    }
137
138    @Override
139    public void emitPatchReturnAddress(ValueNode address) {
140        append(new AMD64HotSpotPatchReturnAddressOp(gen.load(operand(address))));
141    }
142
143    @Override
144    public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
145        Variable handler = gen.load(operand(handlerInCallerPc));
146        ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER);
147        CallingConvention outgoingCc = linkage.getOutgoingCallingConvention();
148        assert outgoingCc.getArgumentCount() == 2;
149        RegisterValue exceptionFixed = (RegisterValue) outgoingCc.getArgument(0);
150        RegisterValue exceptionPcFixed = (RegisterValue) outgoingCc.getArgument(1);
151        gen.emitMove(exceptionFixed, operand(exception));
152        gen.emitMove(exceptionPcFixed, operand(exceptionPc));
153        Register thread = getGen().getProviders().getRegisters().getThreadRegister();
154        AMD64HotSpotJumpToExceptionHandlerInCallerOp op = new AMD64HotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, getGen().config.threadIsMethodHandleReturnOffset,
155                        thread, getGen().getSaveRbp().getRbpRescueSlot());
156        append(op);
157    }
158
159    @Override
160    public void visitFullInfopointNode(FullInfopointNode i) {
161        if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) {
162            Debug.log("Ignoring InfopointNode for AFTER_BCI");
163        } else {
164            super.visitFullInfopointNode(i);
165        }
166    }
167
168    @Override
169    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
170        Value expected = gen.loadNonConst(operand(x.expectedValue()));
171        Variable newVal = gen.load(operand(x.newValue()));
172        assert expected.getLIRKind().equals(newVal.getLIRKind());
173
174        RegisterValue raxLocal = AMD64.rax.asValue(expected.getLIRKind());
175        gen.emitMove(raxLocal, expected);
176        append(new CompareAndSwapOp(expected.getKind(), raxLocal, getGen().asAddressValue(operand(x.getAddress())), raxLocal, newVal));
177
178        setResult(x, gen.emitMove(raxLocal));
179    }
180}