| ... | @@ -2961,7 +2961,8 @@ pub const Value = extern union { | ... | @@ -2961,7 +2961,8 @@ pub const Value = extern union { |
| 2961 | } | 2961 | } |
| 2962 | | 2962 | |
| 2963 | pub const OverflowArithmeticResult = struct { | 2963 | pub const OverflowArithmeticResult = struct { |
| 2964 | overflowed: bool, | 2964 | /// TODO: Rename to `overflow_bit` and make of type `u1`. |
| | 2965 | overflowed: Value, |
| 2965 | wrapped_result: Value, | 2966 | wrapped_result: Value, |
| 2966 | }; | 2967 | }; |
| 2967 | | 2968 | |
| ... | @@ -2971,6 +2972,29 @@ pub const Value = extern union { | ... | @@ -2971,6 +2972,29 @@ pub const Value = extern union { |
| 2971 | ty: Type, | 2972 | ty: Type, |
| 2972 | arena: Allocator, | 2973 | arena: Allocator, |
| 2973 | target: Target, | 2974 | target: Target, |
| | 2975 | ) !OverflowArithmeticResult { |
| | 2976 | if (ty.zigTypeTag() == .Vector) { |
| | 2977 | const overflowed_data = try arena.alloc(Value, ty.vectorLen()); |
| | 2978 | const result_data = try arena.alloc(Value, ty.vectorLen()); |
| | 2979 | for (result_data) |*scalar, i| { |
| | 2980 | const of_math_result = try intAddWithOverflowScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target); |
| | 2981 | overflowed_data[i] = of_math_result.overflowed; |
| | 2982 | scalar.* = of_math_result.wrapped_result; |
| | 2983 | } |
| | 2984 | return OverflowArithmeticResult{ |
| | 2985 | .overflowed = try Value.Tag.aggregate.create(arena, overflowed_data), |
| | 2986 | .wrapped_result = try Value.Tag.aggregate.create(arena, result_data), |
| | 2987 | }; |
| | 2988 | } |
| | 2989 | return intAddWithOverflowScalar(lhs, rhs, ty, arena, target); |
| | 2990 | } |
| | 2991 | |
| | 2992 | pub fn intAddWithOverflowScalar( |
| | 2993 | lhs: Value, |
| | 2994 | rhs: Value, |
| | 2995 | ty: Type, |
| | 2996 | arena: Allocator, |
| | 2997 | target: Target, |
| 2974 | ) !OverflowArithmeticResult { | 2998 | ) !OverflowArithmeticResult { |
| 2975 | const info = ty.intInfo(target); | 2999 | const info = ty.intInfo(target); |
| 2976 | | 3000 | |
| ... | @@ -2986,7 +3010,7 @@ pub const Value = extern union { | ... | @@ -2986,7 +3010,7 @@ pub const Value = extern union { |
| 2986 | const overflowed = result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); | 3010 | const overflowed = result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); |
| 2987 | const result = try fromBigInt(arena, result_bigint.toConst()); | 3011 | const result = try fromBigInt(arena, result_bigint.toConst()); |
| 2988 | return OverflowArithmeticResult{ | 3012 | return OverflowArithmeticResult{ |
| 2989 | .overflowed = overflowed, | 3013 | .overflowed = makeBool(overflowed), |
| 2990 | .wrapped_result = result, | 3014 | .wrapped_result = result, |
| 2991 | }; | 3015 | }; |
| 2992 | } | 3016 | } |
| ... | @@ -3097,6 +3121,29 @@ pub const Value = extern union { | ... | @@ -3097,6 +3121,29 @@ pub const Value = extern union { |
| 3097 | ty: Type, | 3121 | ty: Type, |
| 3098 | arena: Allocator, | 3122 | arena: Allocator, |
| 3099 | target: Target, | 3123 | target: Target, |
| | 3124 | ) !OverflowArithmeticResult { |
| | 3125 | if (ty.zigTypeTag() == .Vector) { |
| | 3126 | const overflowed_data = try arena.alloc(Value, ty.vectorLen()); |
| | 3127 | const result_data = try arena.alloc(Value, ty.vectorLen()); |
| | 3128 | for (result_data) |*scalar, i| { |
| | 3129 | const of_math_result = try intSubWithOverflowScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target); |
| | 3130 | overflowed_data[i] = of_math_result.overflowed; |
| | 3131 | scalar.* = of_math_result.wrapped_result; |
| | 3132 | } |
| | 3133 | return OverflowArithmeticResult{ |
| | 3134 | .overflowed = try Value.Tag.aggregate.create(arena, overflowed_data), |
| | 3135 | .wrapped_result = try Value.Tag.aggregate.create(arena, result_data), |
| | 3136 | }; |
| | 3137 | } |
| | 3138 | return intSubWithOverflowScalar(lhs, rhs, ty, arena, target); |
| | 3139 | } |
| | 3140 | |
| | 3141 | pub fn intSubWithOverflowScalar( |
| | 3142 | lhs: Value, |
| | 3143 | rhs: Value, |
| | 3144 | ty: Type, |
| | 3145 | arena: Allocator, |
| | 3146 | target: Target, |
| 3100 | ) !OverflowArithmeticResult { | 3147 | ) !OverflowArithmeticResult { |
| 3101 | const info = ty.intInfo(target); | 3148 | const info = ty.intInfo(target); |
| 3102 | | 3149 | |
| ... | @@ -3112,7 +3159,7 @@ pub const Value = extern union { | ... | @@ -3112,7 +3159,7 @@ pub const Value = extern union { |
| 3112 | const overflowed = result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); | 3159 | const overflowed = result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); |
| 3113 | const wrapped_result = try fromBigInt(arena, result_bigint.toConst()); | 3160 | const wrapped_result = try fromBigInt(arena, result_bigint.toConst()); |
| 3114 | return OverflowArithmeticResult{ | 3161 | return OverflowArithmeticResult{ |
| 3115 | .overflowed = overflowed, | 3162 | .overflowed = makeBool(overflowed), |
| 3116 | .wrapped_result = wrapped_result, | 3163 | .wrapped_result = wrapped_result, |
| 3117 | }; | 3164 | }; |
| 3118 | } | 3165 | } |
| ... | @@ -3207,6 +3254,29 @@ pub const Value = extern union { | ... | @@ -3207,6 +3254,29 @@ pub const Value = extern union { |
| 3207 | ty: Type, | 3254 | ty: Type, |
| 3208 | arena: Allocator, | 3255 | arena: Allocator, |
| 3209 | target: Target, | 3256 | target: Target, |
| | 3257 | ) !OverflowArithmeticResult { |
| | 3258 | if (ty.zigTypeTag() == .Vector) { |
| | 3259 | const overflowed_data = try arena.alloc(Value, ty.vectorLen()); |
| | 3260 | const result_data = try arena.alloc(Value, ty.vectorLen()); |
| | 3261 | for (result_data) |*scalar, i| { |
| | 3262 | const of_math_result = try intMulWithOverflowScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), arena, target); |
| | 3263 | overflowed_data[i] = of_math_result.overflowed; |
| | 3264 | scalar.* = of_math_result.wrapped_result; |
| | 3265 | } |
| | 3266 | return OverflowArithmeticResult{ |
| | 3267 | .overflowed = try Value.Tag.aggregate.create(arena, overflowed_data), |
| | 3268 | .wrapped_result = try Value.Tag.aggregate.create(arena, result_data), |
| | 3269 | }; |
| | 3270 | } |
| | 3271 | return intMulWithOverflowScalar(lhs, rhs, ty, arena, target); |
| | 3272 | } |
| | 3273 | |
| | 3274 | pub fn intMulWithOverflowScalar( |
| | 3275 | lhs: Value, |
| | 3276 | rhs: Value, |
| | 3277 | ty: Type, |
| | 3278 | arena: Allocator, |
| | 3279 | target: Target, |
| 3210 | ) !OverflowArithmeticResult { | 3280 | ) !OverflowArithmeticResult { |
| 3211 | const info = ty.intInfo(target); | 3281 | const info = ty.intInfo(target); |
| 3212 | | 3282 | |
| ... | @@ -3231,7 +3301,7 @@ pub const Value = extern union { | ... | @@ -3231,7 +3301,7 @@ pub const Value = extern union { |
| 3231 | } | 3301 | } |
| 3232 | | 3302 | |
| 3233 | return OverflowArithmeticResult{ | 3303 | return OverflowArithmeticResult{ |
| 3234 | .overflowed = overflowed, | 3304 | .overflowed = makeBool(overflowed), |
| 3235 | .wrapped_result = try fromBigInt(arena, result_bigint.toConst()), | 3305 | .wrapped_result = try fromBigInt(arena, result_bigint.toConst()), |
| 3236 | }; | 3306 | }; |
| 3237 | } | 3307 | } |
| ... | @@ -3921,6 +3991,29 @@ pub const Value = extern union { | ... | @@ -3921,6 +3991,29 @@ pub const Value = extern union { |
| 3921 | ty: Type, | 3991 | ty: Type, |
| 3922 | allocator: Allocator, | 3992 | allocator: Allocator, |
| 3923 | target: Target, | 3993 | target: Target, |
| | 3994 | ) !OverflowArithmeticResult { |
| | 3995 | if (ty.zigTypeTag() == .Vector) { |
| | 3996 | const overflowed_data = try allocator.alloc(Value, ty.vectorLen()); |
| | 3997 | const result_data = try allocator.alloc(Value, ty.vectorLen()); |
| | 3998 | for (result_data) |*scalar, i| { |
| | 3999 | const of_math_result = try shlWithOverflowScalar(lhs.indexVectorlike(i), rhs.indexVectorlike(i), ty.scalarType(), allocator, target); |
| | 4000 | overflowed_data[i] = of_math_result.overflowed; |
| | 4001 | scalar.* = of_math_result.wrapped_result; |
| | 4002 | } |
| | 4003 | return OverflowArithmeticResult{ |
| | 4004 | .overflowed = try Value.Tag.aggregate.create(allocator, overflowed_data), |
| | 4005 | .wrapped_result = try Value.Tag.aggregate.create(allocator, result_data), |
| | 4006 | }; |
| | 4007 | } |
| | 4008 | return shlWithOverflowScalar(lhs, rhs, ty, allocator, target); |
| | 4009 | } |
| | 4010 | |
| | 4011 | pub fn shlWithOverflowScalar( |
| | 4012 | lhs: Value, |
| | 4013 | rhs: Value, |
| | 4014 | ty: Type, |
| | 4015 | allocator: Allocator, |
| | 4016 | target: Target, |
| 3924 | ) !OverflowArithmeticResult { | 4017 | ) !OverflowArithmeticResult { |
| 3925 | const info = ty.intInfo(target); | 4018 | const info = ty.intInfo(target); |
| 3926 | var lhs_space: Value.BigIntSpace = undefined; | 4019 | var lhs_space: Value.BigIntSpace = undefined; |
| ... | @@ -3941,7 +4034,7 @@ pub const Value = extern union { | ... | @@ -3941,7 +4034,7 @@ pub const Value = extern union { |
| 3941 | result_bigint.truncate(result_bigint.toConst(), info.signedness, info.bits); | 4034 | result_bigint.truncate(result_bigint.toConst(), info.signedness, info.bits); |
| 3942 | } | 4035 | } |
| 3943 | return OverflowArithmeticResult{ | 4036 | return OverflowArithmeticResult{ |
| 3944 | .overflowed = overflowed, | 4037 | .overflowed = makeBool(overflowed), |
| 3945 | .wrapped_result = try fromBigInt(allocator, result_bigint.toConst()), | 4038 | .wrapped_result = try fromBigInt(allocator, result_bigint.toConst()), |
| 3946 | }; | 4039 | }; |
| 3947 | } | 4040 | } |