package com.oracle.graal.pointsto.phases;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.FrameState;
import org.graalvm.compiler.nodes.MergeNode;
import org.graalvm.compiler.nodes.StateSplit;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.UnwindNode;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin;
import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
import org.graalvm.compiler.replacements.IntrinsicGraphBuilder;
public class SubstrateIntrinsicGraphBuilder extends IntrinsicGraphBuilder {
private int bci;
public SubstrateIntrinsicGraphBuilder(OptionValues options, DebugContext debug, CoreProviders providers, Bytecode code) {
super(options, debug, providers, code, -1, AllowAssumptions.NO);
setStateAfter(getGraph().start());
}
@Override
public void setStateAfter(StateSplit sideEffect) {
List<ValueNode> values = new ArrayList<>(Arrays.asList(arguments));
int stackSize = 0;
if (returnValue != null) {
values.add(returnValue);
stackSize++;
if (method.getSignature().getReturnKind().needsTwoSlots()) {
values.add(null);
stackSize++;
}
}
FrameState stateAfter = getGraph().add(new FrameState(null, code, bci, values, arguments.length, stackSize, false, false, null, null));
sideEffect.setStateAfter(stateAfter);
bci++;
}
@Override
protected void setExceptionState(StateSplit exceptionObject) {
List<ValueNode> values = new ArrayList<>(Arrays.asList(arguments));
values.add(exceptionObject.asNode());
int stackSize = 1;
FrameState stateAfter = getGraph().add(new FrameState(null, code, bci, values, arguments.length, stackSize, true, false, null, null));
exceptionObject.setStateAfter(stateAfter);
bci++;
}
@Override
protected void mergeUnwinds() {
List<UnwindNode> unwinds = new ArrayList<>();
for (Node node : getGraph().getNodes()) {
if (node instanceof UnwindNode) {
unwinds.add((UnwindNode) node);
}
}
if (unwinds.size() > 1) {
MergeNode unwindMergeNode = getGraph().add(new MergeNode());
ValueNode exceptionValue = InliningUtil.mergeUnwindExceptions(unwindMergeNode, unwinds);
UnwindNode unwindReplacement = getGraph().add(new UnwindNode(exceptionValue));
unwindMergeNode.setNext(unwindReplacement);
List<ValueNode> values = new ArrayList<>(Arrays.asList(arguments));
values.add(exceptionValue);
int stackSize = 1;
FrameState stateAfter = getGraph().add(new FrameState(null, code, bci, values, arguments.length, stackSize, true, false, null, null));
unwindMergeNode.setStateAfter(stateAfter);
bci++;
}
}
@Override
public int bci() {
return bci;
}
@Override
public boolean canDeferPlugin(GeneratedInvocationPlugin plugin) {
return plugin.isGeneratedFromFoldOrNodeIntrinsic();
}
@Override
public boolean needsExplicitException() {
return true;
}
}