sema: add float coercion in calls and param type resolution; enable 12 corpus tests

- 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 <noreply@anthropic.com>
This commit is contained in:
2026-02-22 14:11:33 +00:00
parent a3d35cf4cd
commit ceda322161
2 changed files with 69 additions and 16 deletions

View File

@@ -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) {

View File

@@ -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