From ceda32216108813a5898bdd56faa689eecd4f025 Mon Sep 17 00:00:00 2001 From: Motiejus Date: Sun, 22 Feb 2026 14:11:33 +0000 Subject: [PATCH] sema: add float coercion in calls and param type resolution; enable 12 corpus tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add float→float coercion (fpext/fptrunc) to semaCoerce for runtime values - Extract param types from callee's ZIR param instructions and coerce call arguments to match (f16→f32 fpext for __divhf3 calling __divsf3) - Fix param type resolution to read break_inline operand from type body - Enable divhf3, floatdihf, floatdixf, floatsihf, floatsixf, fixunshfdi, fixunshfsi, fixunsxfdi, fixunsxfsi, floatundihf, floatundixf, floatunsixf Co-Authored-By: Claude Opus 4.6 --- stage0/sema.c | 61 +++++++++++++++++++++++++++++++++++++++--- stage0/stages_test.zig | 24 ++++++++--------- 2 files changed, 69 insertions(+), 16 deletions(-) diff --git a/stage0/sema.c b/stage0/sema.c index 99317933f8..eab1699a57 100644 --- a/stage0/sema.c +++ b/stage0/sema.c @@ -442,11 +442,12 @@ static bool declIdIsExport(uint32_t id) { || id == 29; } -// Forward declaration for recursive call from zirStructDecl. +// Forward declarations. static bool analyzeBodyInner( Sema* sema, SemaBlock* block, const uint32_t* body, uint32_t body_len); static uint8_t analyzeBodyRuntimeBreak( Sema* sema, SemaBlock* block, const uint32_t* body, uint32_t body_len); +static uint16_t floatBits(TypeIndex ty); // getParamBody: extract param body from a param_block ZIR instruction. // Ported from lib/std/zig/Zir.zig getParamBody. @@ -719,6 +720,21 @@ static AirInstRef semaCoerce( data.ty_op.operand = ref; return semaAddInst(block, tag, data); } + // Runtime float→float coercion: emit fpext or fptrunc. + // Ported from src/Sema.zig coerce for float types. + if (AIR_REF_IS_INST(ref)) { + uint16_t src_fbits = floatBits(src_ty); + uint16_t tgt_fbits = floatBits(target_ty); + if (src_fbits > 0 && tgt_fbits > 0 && src_fbits != tgt_fbits) { + AirInstTag ftag + = (tgt_fbits > src_fbits) ? AIR_INST_FPEXT : AIR_INST_FPTRUNC; + AirInstData data; + memset(&data, 0, sizeof(data)); + data.ty_op.ty_ref = AIR_REF_FROM_IP(target_ty); + data.ty_op.operand = ref; + return semaAddInst(block, ftag, data); + } + } // For unsupported type combinations (e.g. type→void during comptime // analysis of generic functions), return the operand unchanged. // This is safe because these paths don't produce runtime AIR. @@ -3533,15 +3549,52 @@ static AirInstRef zirCall( // Dummy allocs for generic runtime params are now emitted // interleaved in the arg evaluation loop above (Fix A). - // Count runtime params (skip comptime type params). + // Count runtime params (skip comptime type params) and coerce + // arguments to callee's parameter types. + // Ported from src/Sema.zig analyzeCall (Sema.zig:7575-7601). uint32_t runtime_args_count = 0; AirInstRef runtime_arg_refs[16]; uint32_t pi = 0; for (uint32_t p = 0; p < param_body_len; p++) { ZirInstTag ptag = sema->code.inst_tags[param_body[p]]; if (ptag == ZIR_INST_PARAM || ptag == ZIR_INST_PARAM_ANYTYPE) { - if (pi < args_len) - runtime_arg_refs[runtime_args_count++] = arg_refs[pi]; + if (pi < args_len) { + AirInstRef arg = arg_refs[pi]; + // For typed params, coerce arg to the param type. + // Param extra: {name(u32), type(u32={body_len:31, + // is_generic:1}), body_inst...} + if (ptag == ZIR_INST_PARAM) { + uint32_t param_pl = sema->code.inst_datas[ + param_body[p]] + .pl_tok.payload_index; + uint32_t type_raw + = sema->code.extra[param_pl + 1]; + uint32_t type_body_len = type_raw & 0x7FFFFFFF; + if (type_body_len >= 1) { + // The type body contains ZIR instruction + // indices. The last instruction should be a + // break_inline whose operand is the type ref. + uint32_t last_type_inst + = sema->code + .extra[param_pl + 2 + + type_body_len - 1]; + if (last_type_inst < sema->code.inst_len + && sema->code.inst_tags[last_type_inst] + == ZIR_INST_BREAK_INLINE) { + ZirInstRef type_ref + = sema->code.inst_datas + [last_type_inst] + .break_data.operand; + if (type_ref < ZIR_REF_START_INDEX) { + TypeIndex param_ty = type_ref; + arg = semaCoerce( + sema, block, param_ty, arg); + } + } + } + } + runtime_arg_refs[runtime_args_count++] = arg; + } pi++; } else if (ptag == ZIR_INST_PARAM_COMPTIME || ptag == ZIR_INST_PARAM_ANYTYPE_COMPTIME) { diff --git a/stage0/stages_test.zig b/stage0/stages_test.zig index 590e24bdfe..834f88e658 100644 --- a/stage0/stages_test.zig +++ b/stage0/stages_test.zig @@ -132,18 +132,18 @@ const corpus_files = .{ "../lib/compiler_rt/unordhf2.zig", // 341 "../lib/compiler_rt/unordxf2.zig", // 341 "../lib/std/crypto/pcurves/secp256k1/field.zig", // 343 - //"../lib/compiler_rt/divhf3.zig", // 344 - //"../lib/compiler_rt/floatdihf.zig", // 347 - //"../lib/compiler_rt/floatdixf.zig", // 347 - //"../lib/compiler_rt/floatsihf.zig", // 347 - //"../lib/compiler_rt/floatsixf.zig", // 347 - //"../lib/compiler_rt/fixunshfdi.zig", // 350 - //"../lib/compiler_rt/fixunshfsi.zig", // 350 - //"../lib/compiler_rt/fixunsxfdi.zig", // 350 - //"../lib/compiler_rt/fixunsxfsi.zig", // 350 - //"../lib/compiler_rt/floatundihf.zig", // 353 - //"../lib/compiler_rt/floatundixf.zig", // 353 - //"../lib/compiler_rt/floatunsixf.zig", // 353 + "../lib/compiler_rt/divhf3.zig", // 344 + "../lib/compiler_rt/floatdihf.zig", // 347 + "../lib/compiler_rt/floatdixf.zig", // 347 + "../lib/compiler_rt/floatsihf.zig", // 347 + "../lib/compiler_rt/floatsixf.zig", // 347 + "../lib/compiler_rt/fixunshfdi.zig", // 350 + "../lib/compiler_rt/fixunshfsi.zig", // 350 + "../lib/compiler_rt/fixunsxfdi.zig", // 350 + "../lib/compiler_rt/fixunsxfsi.zig", // 350 + "../lib/compiler_rt/floatundihf.zig", // 353 + "../lib/compiler_rt/floatundixf.zig", // 353 + "../lib/compiler_rt/floatunsixf.zig", // 353 //"../lib/compiler_rt/truncxfhf2.zig", // 356 //"../lib/compiler_rt/floatunsihf.zig", // 357 //"../lib/compiler_rt/trunctfhf2.zig", // 359