From 607f7093cdf5aeac48d032e7ddd0dc95a2de1e50 Mon Sep 17 00:00:00 2001 From: Motiejus Date: Sat, 7 Mar 2026 09:39:58 +0000 Subject: [PATCH] sema: add runtime path to zirOptionalPayload Previously, zirOptionalPayload only handled comptime optional unwrapping. Runtime optional values (AIR instructions) returned void instead of emitting proper AIR code. Add runtime path: if operand is a runtime AIR instruction with optional type, get the payload child type and emit AIR_INST_OPTIONAL_PAYLOAD with ty_op layout. Also add AIR_INST_OPTIONAL_PAYLOAD to semaTypeOf ty_op group. Ported from Sema.zig zirOptionalPayload runtime path. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- stage0/sema.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/stage0/sema.c b/stage0/sema.c index d136583383..23a73f89b5 100644 --- a/stage0/sema.c +++ b/stage0/sema.c @@ -592,6 +592,7 @@ static TypeIndex semaTypeOf(Sema* sema, AirInstRef ref) { case AIR_INST_INTCAST: case AIR_INST_TRUNC: case AIR_INST_LOAD: + case AIR_INST_OPTIONAL_PAYLOAD: case AIR_INST_NOT: case AIR_INST_FPTRUNC: case AIR_INST_FPEXT: @@ -11595,15 +11596,27 @@ static AirInstRef zirCoercePtrElemTy(Sema* sema, uint32_t inst) { return resolveInst(sema, val_ref); } -// zirOptionalPayload: extract value payload from a comptime optional. +// zirOptionalPayload: extract value payload from an optional. // Ported from src/Sema.zig zirOptionalPayload. -// For comptime: resolves operand, gets optional child type, extracts payload. -static AirInstRef zirOptionalPayload(Sema* sema, uint32_t inst) { +// Comptime: resolves operand, gets optional child type, extracts payload. +// Runtime: emits AIR_INST_OPTIONAL_PAYLOAD with the payload type. +static AirInstRef zirOptionalPayload( + Sema* sema, SemaBlock* block, uint32_t inst) { ZirInstRef operand_ref = sema->code.inst_datas[inst].un_node.operand; AirInstRef operand = resolveInst(sema, operand_ref); - if (!AIR_REF_IS_IP(operand)) - return AIR_REF_FROM_IP(IP_INDEX_VOID_VALUE); + if (!AIR_REF_IS_IP(operand)) { + // Runtime optional: get child type and emit optional_payload. + TypeIndex opt_ty = semaTypeOf(sema, operand); + TypeIndex child_ty = IP_INDEX_VOID_TYPE; + if (sema->ip->items[opt_ty].tag == IP_KEY_OPT_TYPE) + child_ty = sema->ip->items[opt_ty].data.opt_type; + AirInstData data; + memset(&data, 0, sizeof(data)); + data.ty_op.ty_ref = AIR_REF_FROM_IP(child_ty); + data.ty_op.operand = operand; + return semaAddInst(block, AIR_INST_OPTIONAL_PAYLOAD, data); + } InternPoolIndex operand_ip = AIR_REF_TO_IP(operand); InternPoolIndex operand_ty = ipTypeOf(sema->ip, operand_ip); @@ -12401,7 +12414,8 @@ bool analyzeBodyInner( // Ported from src/Sema.zig zirOptionalPayload. case ZIR_INST_OPTIONAL_PAYLOAD_SAFE: case ZIR_INST_OPTIONAL_PAYLOAD_UNSAFE: - instMapPut(&sema->inst_map, inst, zirOptionalPayload(sema, inst)); + instMapPut( + &sema->inst_map, inst, zirOptionalPayload(sema, block, inst)); i++; continue;