int CheckForULongOverflow() { switch (this.Kind) { case NumberKind.Real: case NumberKind.Quad: int status; LLVMAPFloatRef apFloat = LLVMExt.APFloatFromAPFloat(APFloat, APFloatSemantics.IEEEquad, out status); var comparisonMax = LLVMExt.APFloatCompare(apFloat, MaxULongValue); var comparisonMin = LLVMExt.APFloatCompare(apFloat, MinULongValue); LLVMExt.APFloatDispose(apFloat); if (comparisonMax == 2) { return(1); } if (comparisonMin == 0) { return(-1); } return(0); default: throw new NotSupportedException(); } }
public Number(ulong number, NumberKind numberKind) { this.Kind = numberKind; if (numberKind.IsInteger()) { var overflows = CheckForOverflow(number, numberKind); if (overflows == 1) { this.State = NumberState.Overflow; } else if (overflows == -1) { this.State = NumberState.Underflow; } if (!HasErrors) { this.Value = LLVM.ConstInt(GetLLVMType(), number, new LLVMBool(0)); } } else { this.APFloat = LLVMExt.APFloatZero(GetAPFloatSemantics(this.Kind)); this.State |= (NumberState)LLVMExt.APFloatFromString(this.APFloat, number.ToString(CultureInfo.InvariantCulture), RoundingMode); } }
public Number(string number, NumberKind numberKind) { if (number == null) { throw new ArgumentNullException(nameof(number)); } this.Kind = numberKind; if (numberKind.IsInteger()) { this.State = CheckIntegerString(number, numberKind); if (!this.HasErrors) { this.Value = LLVM.ConstIntOfString(LLVM.Int128Type(), number, 10); } } else { this.State = CheckFloatString(number); if (!this.HasErrors) { this.APFloat = LLVMExt.APFloatZero(GetAPFloatSemantics(this.Kind)); this.State |= (NumberState)LLVMExt.APFloatFromString(this.APFloat, number, RoundingMode); } } }
static Number() { MaxLongValue = LLVMExt.APFloatZero(APFloatSemantics.IEEEquad); MinLongValue = LLVMExt.APFloatZero(APFloatSemantics.IEEEquad); MaxULongValue = LLVMExt.APFloatZero(APFloatSemantics.IEEEquad); MinULongValue = LLVMExt.APFloatZero(APFloatSemantics.IEEEquad); LLVMExt.APFloatFromString(MaxLongValue, long.MaxValue.ToString(CultureInfo.InvariantCulture), RoundingMode); LLVMExt.APFloatFromString(MinLongValue, long.MinValue.ToString(CultureInfo.InvariantCulture), RoundingMode); LLVMExt.APFloatFromString(MaxULongValue, ulong.MaxValue.ToString(CultureInfo.InvariantCulture), RoundingMode); LLVMExt.APFloatFromString(MinULongValue, ulong.MinValue.ToString(CultureInfo.InvariantCulture), RoundingMode); MaxLongLLVMValue = LLVM.ConstInt(LLVM.Int128Type(), long.MaxValue, new LLVMBool(1)); MinLongLLVMValue = LLVM.ConstInt(LLVM.Int128Type(), unchecked ((ulong)long.MinValue), new LLVMBool(1)); MaxULongLLVMValue = LLVM.ConstInt(LLVM.Int128Type(), ulong.MaxValue, new LLVMBool(0)); }
public Number Duplicate() { var dup = new Number(dummy: string.Empty); dup.State = this.State; dup.Kind = this.Kind; if (this.Value.Pointer.ToInt64() != 0) { dup.Value = Value; } if (this.APFloat.Pointer.ToInt64() != 0) { int status; dup.APFloat = LLVMExt.APFloatFromAPFloat(this.APFloat, GetAPFloatSemantics(this.Kind), out status); } return(dup); }
public NumberComparison CompareTo(Number n) { if (this.HasErrors || n.HasErrors) { return(NumberComparison.Invalid); } var opKind = OperationKind(this.Kind, n.Kind); var op1 = this.Convert(opKind); var op2 = n.Convert(opKind); if (opKind.IsInteger()) { var result = LLVM.ConstICmp(LLVMIntPredicate.LLVMIntEQ, op1.LLVMValue, op2.LLVMValue).ConstIntGetZExtValue(); if (result == 1) { return(NumberComparison.Eq); } else { result = LLVM.ConstICmp(opKind.IsSigned() ? LLVMIntPredicate.LLVMIntSGT : LLVMIntPredicate.LLVMIntUGT, op1.LLVMValue, op2.LLVMValue).ConstIntGetZExtValue(); return(result == 1 ? NumberComparison.Gt : NumberComparison.Ls); } } else { var result = LLVMExt.APFloatCompare(op1.APFloat, op2.APFloat); switch (result) { case 0: return(NumberComparison.Ls); case 1: return(NumberComparison.Eq); case 2: return(NumberComparison.Gt); default: return(NumberComparison.Undef); } } }
public Number Rem(Number n) { var opKind = OperationKind(this.Kind, n.Kind); if (this.HasErrors || n.HasErrors) { return(new Number(this.State | n.State, opKind)); } if (opKind.IsInteger()) { var result = opKind.IsSigned() ? LLVM.ConstSRem(this.Value, n.Value) : LLVM.ConstURem(this.Value, n.Value); var state = CheckForOpOverflow(opKind, result); if (state != NumberState.Ok) { return(new Number(state | this.State | n.State, opKind)); } else { return new Number(dummy: string.Empty) { Value = result, State = this.State | n.State, Kind = opKind } }; } else { var op1 = this.Convert(opKind); var op2 = n.Convert(opKind); if (op1 == this) { op1 = op1.Duplicate(); } op1.State |= (NumberState)LLVMExt.APFloatMod(op1.APFloat, op2.APFloat); return(op1); } }
public Number Neg() { var opKind = OperationKind(this.Kind, NumberKind.UInt8); if (this.HasErrors) { return(new Number(this.State, opKind)); } if (opKind.IsInteger()) { var result = LLVM.ConstNeg(this.Value); var undef = result.IsUndef(); return(new Number(dummy: string.Empty) { Value = result, State = this.State | (undef ? NumberState.Invalid : NumberState.Ok), Kind = opKind }); } else { var dup = this.Duplicate(); var minusOne = new Number(-1.0, this.Kind); var state = (NumberState)LLVMExt.APFloatMult(dup.APFloat, minusOne.APFloat, RoundingMode); var result = dup.APFloat; dup.APFloat = new LLVMAPFloatRef(IntPtr.Zero); return(new Number(dummy: string.Empty) { APFloat = result, State = this.State | state, Kind = opKind }); } }
public Number(double number, NumberKind numberKind) { this.Kind = numberKind; if (numberKind.IsInteger()) { var overflows = CheckForOverflow(number, numberKind); if (overflows == 1) { this.State = NumberState.Overflow; } else if (overflows == -1) { this.State = NumberState.Underflow; } if (!HasErrors) { this.Value = LLVM.ConstReal(LLVM.DoubleType(), number); if (numberKind.IsSigned()) { this.Value = LLVM.ConstFPToSI(this.Value, GetLLVMType()); } else { this.Value = LLVM.ConstFPToUI(this.Value, GetLLVMType()); } } } else { int state; this.APFloat = LLVMExt.APFloatFromDouble(number, GetAPFloatSemantics(this.Kind), out state); this.State |= (NumberState)state; } }
public Number Convert(NumberKind kind) { if (kind == this.Kind) { return(this); } if (this.HasErrors) { return(new Number(this.State, this.Kind)); } if (this.Kind.IsInteger()) { if (this.Kind.IsSigned()) { var n = new Number(this.Int64Value, kind); n.State |= this.State; return(n); } else { var n = new Number(this.UInt64Value, kind); n.State |= this.State; return(n); } } else { if (kind.IsFloat()) { int status; var apFloat = LLVMExt.APFloatFromAPFloat(this.APFloat, GetAPFloatSemantics(kind), out status); return(new Number(dummy: string.Empty) { APFloat = apFloat, State = this.State | (NumberState)status, Kind = kind }); } else { if (this.Kind == NumberKind.Double) { var n = new Number(this.DoubleValue, kind); n.State |= this.State; return(n); } else if (this.Kind == NumberKind.Float) { var n = new Number(this.FloatValue, kind); n.State |= this.State; return(n); } else { if (kind.IsSigned()) { var overflows = CheckForLongOverflow(); if (overflows == 1) { return(new Number(NumberState.Overflow, kind)); } else if (overflows == -1) { return(new Number(NumberState.Underflow, kind)); } else { var longValue = LLVM.ConstFPToSI(LLVMExt.APFloatToValue(APFloat), LLVM.Int64Type()); var longValue2 = LLVM.ConstIntGetSExtValue(longValue); return(new Number(longValue2, kind)); } } else { var overflows = CheckForULongOverflow(); if (overflows == 1) { return(new Number(NumberState.Overflow, kind)); } else if (overflows == -1) { return(new Number(NumberState.Underflow, kind)); } else { var ulongValue = LLVM.ConstFPToUI(LLVMExt.APFloatToValue(APFloat), LLVM.Int64Type()); var ulongValue2 = LLVM.ConstIntGetZExtValue(ulongValue); return(new Number(ulongValue2, kind)); } } } } } }