package com.oracle.truffle.llvm.runtime.nodes.func;
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.StandardTags;
import com.oracle.truffle.api.instrumentation.Tag;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode;
import com.oracle.truffle.llvm.runtime.types.FunctionType;
@NodeChild(value = "dispatchTarget", type = LLVMExpressionNode.class)
public abstract class LLVMCallNode extends LLVMExpressionNode {
public static final int USER_ARGUMENT_OFFSET = 1;
@Children private final LLVMExpressionNode[] argumentNodes;
@Children private final LLVMPrepareArgumentNode[] prepareArgumentNodes;
@Child private LLVMDispatchNode dispatchNode;
private final boolean isSourceCall;
public static LLVMCallNode create(FunctionType functionType, LLVMExpressionNode functionNode, LLVMExpressionNode[] argumentNodes, boolean isSourceCall) {
return LLVMCallNodeGen.create(functionType, argumentNodes, isSourceCall, LLVMLookupDispatchTargetNode.createOptimized(functionNode));
}
LLVMCallNode(FunctionType functionType, LLVMExpressionNode[] argumentNodes, boolean isSourceCall) {
this.argumentNodes = argumentNodes;
this.prepareArgumentNodes = createPrepareArgumentNodes(argumentNodes);
this.dispatchNode = LLVMDispatchNodeGen.create(functionType);
this.isSourceCall = isSourceCall;
}
@ExplodeLoop
@Specialization
Object doCall(VirtualFrame frame, Object function) {
Object[] argValues = new Object[argumentNodes.length];
for (int i = 0; i < argumentNodes.length; i++) {
argValues[i] = prepareArgumentNodes[i].executeWithTarget(argumentNodes[i].executeGeneric(frame));
}
return dispatchNode.executeDispatch(function, argValues);
}
private static LLVMPrepareArgumentNode[] createPrepareArgumentNodes(LLVMExpressionNode[] argumentNodes) {
LLVMPrepareArgumentNode[] nodes = new LLVMPrepareArgumentNode[argumentNodes.length];
for (int i = 0; i < nodes.length; i++) {
nodes[i] = LLVMPrepareArgumentNodeGen.create();
}
return nodes;
}
@Override
public boolean hasTag(Class<? extends Tag> tag) {
if (tag == StandardTags.CallTag.class) {
return isSourceCall && getSourceLocation() != null;
} else {
return super.hasTag(tag);
}
}
}