zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 6fde2fcd519cacdc44871fc1035b05afee072f44 (tree)
parent 663b67783e3e140fcaf06747f4aa28b57259023c
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Sun,  8 May 2022 13:05:16 -0700

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.

Diffstat:
Msrc/Sema.zig | 9+++++++++
Msrc/stage1/ir.cpp | 6++++++
Mtest/behavior/cast.zig | 20++++++++++++++++++++
3 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/src/Sema.zig b/src/Sema.zig @@ -18673,6 +18673,15 @@ fn coerceInMemoryAllowed( } } + // Differently-named floats with the same number of bits. + if (dest_ty.zigTypeTag() == .Float and src_ty.zigTypeTag() == .Float) { + const dest_bits = dest_ty.floatBits(target); + const src_bits = src_ty.floatBits(target); + if (dest_bits == src_bits) { + return .ok; + } + } + // Pointers / Pointer-like Optionals var dest_buf: Type.Payload.ElemType = undefined; var src_buf: Type.Payload.ElemType = undefined; diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp @@ -4480,6 +4480,12 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted return result; } + if (wanted_type->id == ZigTypeIdFloat && actual_type->id == ZigTypeIdFloat) { + if (wanted_type->data.floating.bit_count == actual_type->data.floating.bit_count) { + return result; + } + } + if (wanted_type->id == ZigTypeIdVector && actual_type->id == ZigTypeIdVector) { if (actual_type->data.vector.len != wanted_type->data.vector.len) { result.id = ConstCastResultIdVectorLength; diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig @@ -1426,3 +1426,23 @@ test "pointer to empty struct literal to mutable slice" { var x: []i32 = &.{}; try expect(x.len == 0); } + +test "coerce between pointers of compatible differently-named floats" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + const F = switch (@typeInfo(c_longdouble).Float.bits) { + 16 => f16, + 32 => f32, + 64 => f64, + 80 => f80, + 128 => f128, + else => @compileError("unreachable"), + }; + var f1: F = 12.34; + var f2: *c_longdouble = &f1; + f2.* += 1; + try expect(f1 == @as(F, 12.34) + 1); +}