authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-07-21 21:43:40+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-07-21 22:34:14+03:00
logdd8929738876544d9b83c55df6e2ee3a491298ca
treed8321b267087c50ff959ad9d75ecb2dc2f5db10d
parentc29c79b17aa4b8ce5fe35ae1fd4f06201ab059ba
signaturelock-open Commit is signed but in an unrecognized format.

stage2: actually implement float casting


2 files changed, 62 insertions(+), 9 deletions(-)

src-self-hosted/Module.zig+10-1
...@@ -3437,7 +3437,16 @@ fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst {...@@ -3437,7 +3437,16 @@ fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst {
3437 }3437 }
3438 } else if (dst_zig_tag == .ComptimeFloat or dst_zig_tag == .Float) {3438 } else if (dst_zig_tag == .ComptimeFloat or dst_zig_tag == .Float) {
3439 if (src_zig_tag == .Float or src_zig_tag == .ComptimeFloat) {3439 if (src_zig_tag == .Float or src_zig_tag == .ComptimeFloat) {
3440 return self.fail(scope, inst.src, "TODO float cast", .{});3440 const res = val.floatCast(scope.arena(), dest_type, self.target()) catch |err| switch (err) {
3441 error.Overflow => return self.fail(
3442 scope,
3443 inst.src,
3444 "cast of value {} to type '{}' loses information",
3445 .{ val, dest_type },
3446 ),
3447 error.OutOfMemory => return error.OutOfMemory,
3448 };
3449 return self.constInst(scope, inst.src, .{ .ty = dest_type, .val = res });
3441 } else if (src_zig_tag == .Int or src_zig_tag == .ComptimeInt) {3450 } else if (src_zig_tag == .Int or src_zig_tag == .ComptimeInt) {
3442 return self.fail(scope, inst.src, "TODO int to float", .{});3451 return self.fail(scope, inst.src, "TODO int to float", .{});
3443 }3452 }
src-self-hosted/value.zig+52-8
...@@ -563,15 +563,15 @@ pub const Value = extern union {...@@ -563,15 +563,15 @@ pub const Value = extern union {
563 }563 }
564564
565 /// Asserts that the value is a float or an integer.565 /// Asserts that the value is a float or an integer.
566 pub fn toF128(self: Value) f128 {566 pub fn toFloat(self: Value, comptime T: type) T {
567 return switch (self.tag()) {567 return switch (self.tag()) {
568 .float_16 => @panic("TODO soft float"),568 .float_16 => @panic("TODO soft float"),
569 .float_32 => self.cast(Payload.Float_32).?.val,569 .float_32 => @floatCast(T, self.cast(Payload.Float_32).?.val),
570 .float_64 => self.cast(Payload.Float_64).?.val,570 .float_64 => @floatCast(T, self.cast(Payload.Float_64).?.val),
571 .float_128 => self.cast(Payload.Float_128).?.val,571 .float_128 => @floatCast(T, self.cast(Payload.Float_128).?.val),
572572
573 .zero, .the_one_possible_value => 0,573 .zero, .the_one_possible_value => 0,
574 .int_u64 => @intToFloat(f128, self.cast(Payload.Int_u64).?.int),574 .int_u64 => @intToFloat(T, self.cast(Payload.Int_u64).?.int),
575 // .int_i64 => @intToFloat(f128, self.cast(Payload.Int_i64).?.int),575 // .int_i64 => @intToFloat(f128, self.cast(Payload.Int_i64).?.int),
576 .int_i64 => @panic("TODO lld: error: undefined symbol: __floatditf"),576 .int_i64 => @panic("TODO lld: error: undefined symbol: __floatditf"),
577577
...@@ -773,6 +773,50 @@ pub const Value = extern union {...@@ -773,6 +773,50 @@ pub const Value = extern union {
773 }773 }
774 }774 }
775775
776 /// Converts an integer or a float to a float.
777 /// Returns `error.Overflow` if the value does not fit in the new type.
778 pub fn floatCast(self: Value, allocator: *Allocator, ty: Type, target: Target) !Value {
779 const dest_bit_count = switch (ty.tag()) {
780 .comptime_float => 128,
781 else => ty.floatBits(target),
782 };
783 switch (dest_bit_count) {
784 16, 32, 64, 128 => {},
785 else => std.debug.panic("TODO float cast bit count {}\n", .{dest_bit_count}),
786 }
787 if (ty.isInt()) {
788 @panic("TODO int to float");
789 }
790
791 switch (dest_bit_count) {
792 16 => {
793 @panic("TODO soft float");
794 // var res_payload = Value.Payload.Float_16{.val = self.toFloat(f16)};
795 // if (!self.eql(Value.initPayload(&res_payload.base)))
796 // return error.Overflow;
797 // return Value.initPayload(&res_payload.base).copy(allocator);
798 },
799 32 => {
800 var res_payload = Value.Payload.Float_32{.val = self.toFloat(f32)};
801 if (!self.eql(Value.initPayload(&res_payload.base)))
802 return error.Overflow;
803 return Value.initPayload(&res_payload.base).copy(allocator);
804 },
805 64 => {
806 var res_payload = Value.Payload.Float_64{.val = self.toFloat(f64)};
807 if (!self.eql(Value.initPayload(&res_payload.base)))
808 return error.Overflow;
809 return Value.initPayload(&res_payload.base).copy(allocator);
810 },
811 128 => {
812 const float_payload = try allocator.create(Value.Payload.Float_128);
813 float_payload.* = .{ .val = self.toFloat(f128) };
814 return Value.initPayload(&float_payload.base);
815 },
816 else => unreachable,
817 }
818 }
819
776 /// Asserts the value is a float820 /// Asserts the value is a float
777 pub fn floatHasFraction(self: Value) bool {821 pub fn floatHasFraction(self: Value) bool {
778 return switch (self.tag()) {822 return switch (self.tag()) {
...@@ -919,7 +963,7 @@ pub const Value = extern union {...@@ -919,7 +963,7 @@ pub const Value = extern union {
919 /// Asserts the value is comparable.963 /// Asserts the value is comparable.
920 pub fn order(lhs: Value, rhs: Value) std.math.Order {964 pub fn order(lhs: Value, rhs: Value) std.math.Order {
921 const lhs_tag = lhs.tag();965 const lhs_tag = lhs.tag();
922 const rhs_tag = lhs.tag();966 const rhs_tag = rhs.tag();
923 const lhs_is_zero = lhs_tag == .zero or lhs_tag == .the_one_possible_value;967 const lhs_is_zero = lhs_tag == .zero or lhs_tag == .the_one_possible_value;
924 const rhs_is_zero = rhs_tag == .zero or rhs_tag == .the_one_possible_value;968 const rhs_is_zero = rhs_tag == .zero or rhs_tag == .the_one_possible_value;
925 if (lhs_is_zero) return rhs.orderAgainstZero().invert();969 if (lhs_is_zero) return rhs.orderAgainstZero().invert();
...@@ -939,8 +983,8 @@ pub const Value = extern union {...@@ -939,8 +983,8 @@ pub const Value = extern union {
939 }983 }
940 }984 }
941 if (lhs_float or rhs_float) {985 if (lhs_float or rhs_float) {
942 const lhs_f128 = lhs.toF128();986 const lhs_f128 = lhs.toFloat(f128);
943 const rhs_f128 = rhs.toF128();987 const rhs_f128 = rhs.toFloat(f128);
944 return std.math.order(lhs_f128, rhs_f128);988 return std.math.order(lhs_f128, rhs_f128);
945 }989 }
946990