From 6fde2fcd519cacdc44871fc1035b05afee072f44 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 8 May 2022 13:05:16 -0700 Subject: [PATCH] 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. --- src/Sema.zig | 9 +++++++++ src/stage1/ir.cpp | 6 ++++++ test/behavior/cast.zig | 20 ++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/src/Sema.zig b/src/Sema.zig index 76edfbf2cd..2e7e5c9293 100644 --- 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 index f7ab5e12fa..ee195680cd 100644 --- 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 index 416c7914e7..231fa25b2d 100644 --- 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); +}