package com.oracle.truffle.llvm.runtime.nodes.op;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.llvm.runtime.LLVMIVarBit;
import com.oracle.truffle.llvm.runtime.UnaryOperation;
import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode;
@NodeChild("operandNode")
public abstract class LLVMUnaryNode extends LLVMExpressionNode {
public abstract Object executeWithTarget(Object operand);
private abstract static class LLVMUnaryOp {
abstract boolean doBoolean(boolean operand);
abstract byte doByte(byte operand);
abstract short doShort(short operand);
abstract int doInt(int operand);
abstract long doLong(long operand);
abstract LLVMIVarBit doVarBit(LLVMIVarBit operand);
}
private abstract static class LLVMFPUnaryOp extends LLVMUnaryOp {
abstract float doFloat(float operand);
abstract double doDouble(double operand);
abstract LLVM80BitFloat doFP80(LLVM80BitFloat operand);
}
final LLVMUnaryOp op;
protected LLVMUnaryNode(UnaryOperation op) {
switch (op) {
case NEG:
this.op = NEG;
break;
default:
throw new AssertionError(op.name());
}
}
public abstract static class LLVMFloatingUnaryNode extends LLVMUnaryNode {
LLVMFloatingUnaryNode(UnaryOperation op) {
super(op);
assert this.op instanceof LLVMFPUnaryOp;
}
LLVMFPUnaryOp fpOp() {
return (LLVMFPUnaryOp) op;
}
}
public abstract static class LLVMFloatUnaryNode extends LLVMFloatingUnaryNode {
LLVMFloatUnaryNode(UnaryOperation op) {
super(op);
}
@Specialization
float doFloat(float operand) {
return fpOp().doFloat(operand);
}
}
public abstract static class LLVMDoubleUnaryNode extends LLVMFloatingUnaryNode {
LLVMDoubleUnaryNode(UnaryOperation op) {
super(op);
}
@Specialization
double doDouble(double operand) {
return fpOp().doDouble(operand);
}
}
public abstract static class LLVMFP80UnaryNode extends LLVMFloatingUnaryNode {
LLVMFP80UnaryNode(UnaryOperation op) {
super(op);
}
@Specialization
LLVM80BitFloat do80BitFloat(LLVM80BitFloat operand) {
return fpOp().doFP80(operand);
}
}
private static final LLVMFPUnaryOp NEG = new LLVMFPUnaryOp() {
@Override
float doFloat(float operand) {
return -operand;
}
@Override
double doDouble(double operand) {
return -operand;
}
@Override
LLVM80BitFloat doFP80(LLVM80BitFloat operand) {
return operand.negate();
}
@Override
boolean doBoolean(boolean operand) {
return !operand;
}
@Override
byte doByte(byte operand) {
return (byte) -operand;
}
@Override
short doShort(short operand) {
return (short) -operand;
}
@Override
int doInt(int operand) {
return -operand;
}
@Override
long doLong(long operand) {
return -operand;
}
@Override
LLVMIVarBit doVarBit(LLVMIVarBit operand) {
return LLVMIVarBit.fromInt(operand.getBitSize(), 0).sub(operand);
}
};
}