authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-08 13:05:16-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-08 13:05:16-07:00
log6fde2fcd519cacdc44871fc1035b05afee072f44
tree05f4d03603480acda6b87d01e6d325621675da7c
parent663b67783e3e140fcaf06747f4aa28b57259023c

allow in-memory coercion of differently-named floats with same bits

For example, this allows passing a `*c_longdouble` where a `*f80` is expected, provided that `c_longdouble` maps to `f80` for this target.

3 files changed, 35 insertions(+), 0 deletions(-)

src/Sema.zig+9
...@@ -18673,6 +18673,15 @@ fn coerceInMemoryAllowed(...@@ -18673,6 +18673,15 @@ fn coerceInMemoryAllowed(
18673 }18673 }
18674 }18674 }
1867518675
18676 // Differently-named floats with the same number of bits.
18677 if (dest_ty.zigTypeTag() == .Float and src_ty.zigTypeTag() == .Float) {
18678 const dest_bits = dest_ty.floatBits(target);
18679 const src_bits = src_ty.floatBits(target);
18680 if (dest_bits == src_bits) {
18681 return .ok;
18682 }
18683 }
18684
18676 // Pointers / Pointer-like Optionals18685 // Pointers / Pointer-like Optionals
18677 var dest_buf: Type.Payload.ElemType = undefined;18686 var dest_buf: Type.Payload.ElemType = undefined;
18678 var src_buf: Type.Payload.ElemType = undefined;18687 var src_buf: Type.Payload.ElemType = undefined;
src/stage1/ir.cpp+6
...@@ -4480,6 +4480,12 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -4480,6 +4480,12 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
4480 return result;4480 return result;
4481 }4481 }
44824482
4483 if (wanted_type->id == ZigTypeIdFloat && actual_type->id == ZigTypeIdFloat) {
4484 if (wanted_type->data.floating.bit_count == actual_type->data.floating.bit_count) {
4485 return result;
4486 }
4487 }
4488
4483 if (wanted_type->id == ZigTypeIdVector && actual_type->id == ZigTypeIdVector) {4489 if (wanted_type->id == ZigTypeIdVector && actual_type->id == ZigTypeIdVector) {
4484 if (actual_type->data.vector.len != wanted_type->data.vector.len) {4490 if (actual_type->data.vector.len != wanted_type->data.vector.len) {
4485 result.id = ConstCastResultIdVectorLength;4491 result.id = ConstCastResultIdVectorLength;
test/behavior/cast.zig+20
...@@ -1426,3 +1426,23 @@ test "pointer to empty struct literal to mutable slice" {...@@ -1426,3 +1426,23 @@ test "pointer to empty struct literal to mutable slice" {
1426 var x: []i32 = &.{};1426 var x: []i32 = &.{};
1427 try expect(x.len == 0);1427 try expect(x.len == 0);
1428}1428}
1429
1430test "coerce between pointers of compatible differently-named floats" {
1431 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1432 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1433 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1434 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1435
1436 const F = switch (@typeInfo(c_longdouble).Float.bits) {
1437 16 => f16,
1438 32 => f32,
1439 64 => f64,
1440 80 => f80,
1441 128 => f128,
1442 else => @compileError("unreachable"),
1443 };
1444 var f1: F = 12.34;
1445 var f2: *c_longdouble = &f1;
1446 f2.* += 1;
1447 try expect(f1 == @as(F, 12.34) + 1);
1448}