package com.oracle.truffle.llvm.runtime.nodes.control;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.instrumentation.GenerateWrapper;
import com.oracle.truffle.api.instrumentation.ProbeNode;
import com.oracle.truffle.api.profiles.ValueProfile;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMControlFlowNode;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode;
import com.oracle.truffle.llvm.runtime.nodes.control.LLVMSwitchNodeFactory.LLVMSwitchNodeImplNodeGen;
import com.oracle.truffle.llvm.runtime.nodes.op.LLVMCompareNode.LLVMEqNode;
import com.oracle.truffle.llvm.runtime.nodes.op.LLVMCompareNodeFactory.LLVMEqNodeGen;
@GenerateWrapper
public abstract class LLVMSwitchNode extends LLVMControlFlowNode {
public static LLVMSwitchNode create(int[] successors, LLVMStatementNode[] phiNodes, LLVMExpressionNode cond, LLVMExpressionNode[] cases) {
return LLVMSwitchNodeImplNodeGen.create(successors, phiNodes, cases, cond);
}
@Override
public WrapperNode createWrapper(ProbeNode probe) {
return new LLVMSwitchNodeWrapper(this, probe);
}
public abstract Object executeCondition(VirtualFrame frame);
public abstract boolean checkCase(VirtualFrame frame, int i, Object value);
@NodeChild(value = "cond", type = LLVMExpressionNode.class)
public abstract static class LLVMSwitchNodeImpl extends LLVMSwitchNode {
@Children private final LLVMStatementNode[] phiNodes;
@Children protected final LLVMExpressionNode[] cases;
@Children protected final LLVMEqNode[] caseEquals;
@CompilationFinal(dimensions = 1) private final int[] successors;
private final ValueProfile conditionValueClass = ValueProfile.createClassProfile();
public LLVMSwitchNodeImpl(int[] successors, LLVMStatementNode[] phiNodes, LLVMExpressionNode[] cases) {
assert successors.length == cases.length + 1 : "the last entry of the successors array must be the default case";
this.successors = successors;
this.phiNodes = phiNodes;
this.cases = cases;
this.caseEquals = new LLVMEqNode[cases.length];
for (int i = 0; i < caseEquals.length; i++) {
caseEquals[i] = LLVMEqNodeGen.create(null, null);
}
}
@Specialization
public Object doCondition(Object cond) {
return conditionValueClass.profile(cond);
}
@Override
public int[] getSuccessors() {
return successors;
}
@Override
public int getSuccessorCount() {
return successors.length;
}
@Override
public LLVMStatementNode getPhiNode(int successorIndex) {
return phiNodes[successorIndex];
}
@Override
public boolean checkCase(VirtualFrame frame, int i, Object value) {
return caseEquals[i].executeWithTarget(cases[i].executeGeneric(frame), value);
}
}
}