diff --git a/stage0/astgen.c b/stage0/astgen.c index 32efc99c20..27f9af76ec 100644 --- a/stage0/astgen.c +++ b/stage0/astgen.c @@ -3605,7 +3605,7 @@ static uint32_t builtinCall( AstData nd = tree->nodes.datas[node]; uint32_t typeof_inst = makeBlockInst(ag, ZIR_INST_TYPEOF_BUILTIN, gz, node); - GenZir typeof_scope = makeSubBlock(gz, &gz->base); + GenZir typeof_scope = makeSubBlock(gz, scope); typeof_scope.is_comptime = false; typeof_scope.is_typeof = true; typeof_scope.c_import = false; @@ -4293,6 +4293,63 @@ static uint32_t builtinCallMultiArg(GenZir* gz, Scope* scope, ResultLoc rl, gz, ZIR_INST_SHUFFLE, node, payload_index); return rvalue(gz, rl, result, node); } + // @TypeOf multi-arg (AstGen.zig:9120-9146). + if (name_len == 6 && memcmp(source + name_start, "TypeOf", 6) == 0) { + // Reserve extra space: 3 (TypeOfPeer payload) + param_count (refs). + uint32_t payload_size = 3; // src_node, body_len, body_index + ensureExtraCapacity(ag, payload_size + param_count); + uint32_t payload_index = ag->extra_len; + ag->extra_len += payload_size + param_count; + uint32_t args_index = payload_index + payload_size; + + // Create the extended instruction (AstGen.zig:9124). + uint32_t typeof_inst = ag->inst_len; + ensureInstCapacity(ag, 1); + ag->inst_tags[typeof_inst] = ZIR_INST_EXTENDED; + ZirInstData tdata; + memset(&tdata, 0, sizeof(tdata)); + tdata.extended.opcode = (uint16_t)ZIR_EXT_TYPEOF_PEER; + tdata.extended.small = (uint16_t)param_count; + tdata.extended.operand = payload_index; + ag->inst_datas[typeof_inst] = tdata; + ag->inst_len++; + gzAppendInstruction(gz, typeof_inst); + + // Create sub-block scope (AstGen.zig:9126-9128). + GenZir typeof_scope = makeSubBlock(gz, scope); + typeof_scope.is_comptime = false; + + // Evaluate each arg (AstGen.zig:9129-9132). + for (uint32_t i = 0; i < param_count; i++) { + uint32_t param_ref = reachableExpr( + &typeof_scope, &typeof_scope.base, RL_NONE_VAL, + params[i], node); + ag->extra[args_index + i] = param_ref; + } + + // Add break_inline (AstGen.zig:9133). + addBreak(&typeof_scope, ZIR_INST_BREAK_INLINE, + typeof_inst, ZIR_REF_VOID_VALUE, + (int32_t)node - (int32_t)gz->decl_node_index); + + // Get body and fill in payload (AstGen.zig:9135-9141). + uint32_t raw_len = gzInstructionsLen(&typeof_scope); + const uint32_t* body = gzInstructionsSlice(&typeof_scope); + uint32_t body_len = countBodyLenAfterFixups(ag, body, raw_len); + + ag->extra[payload_index + 0] + = (uint32_t)((int32_t)node - (int32_t)gz->decl_node_index); + ag->extra[payload_index + 1] = body_len; + ag->extra[payload_index + 2] = ag->extra_len; + + // Append body with fixups (AstGen.zig:9142-9143). + ensureExtraCapacity(ag, body_len); + for (uint32_t j = 0; j < raw_len; j++) + appendPossiblyRefdBodyInst(ag, body[j]); + + gzUnstack(&typeof_scope); + return rvalue(gz, rl, typeof_inst + ZIR_REF_START_INDEX, node); + } // clang-format on // TODO: handle other multi-arg builtins.