diff --git a/stage0/astgen.c b/stage0/astgen.c index fe0c3e296e..c3e09c2a16 100644 --- a/stage0/astgen.c +++ b/stage0/astgen.c @@ -2346,7 +2346,7 @@ static uint32_t forExpr( GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node, bool is_statement); static uint32_t orelseCatchExpr(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node, ZirInstTag cond_op, ZirInstTag unwrap_op, - ZirInstTag unwrap_code_op); + ZirInstTag unwrap_code_op, uint32_t payload_token); static uint32_t arrayInitDotExpr( GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node); static uint32_t switchExpr( @@ -2475,6 +2475,7 @@ static uint32_t tryResolvePrimitiveIdent(GenZir* gz, uint32_t node); #define COMPTIME_REASON_ARRAY_LENGTH 33 #define COMPTIME_REASON_ALIGN 50 #define COMPTIME_REASON_ADDRSPACE 51 +#define COMPTIME_REASON_FIELD_NAME 42 #define COMPTIME_REASON_COMPTIME_KEYWORD 53 #define COMPTIME_REASON_SWITCH_ITEM 56 #define COMPTIME_REASON_TUPLE_FIELD_DEFAULT_VALUE 57 @@ -2923,6 +2924,51 @@ static uint32_t builtinCall( return rvalue(gz, rl, addPlNodeBin(gz, ZIR_INST_MAX, node, a, b), node); } + // @panic — simpleUnOp with dbg_node (AstGen.zig:9429-9432). + if (name_len == 5 && memcmp(source + name_start, "panic", 5) == 0) { + emitDbgNode(gz, node); + AstData nd = tree->nodes.datas[node]; + ResultLoc panic_rl = { .tag = RL_COERCED_TY, + .data = ZIR_REF_SLICE_CONST_U8_TYPE, + .src_node = 0, .ctx = RI_CTX_NONE }; + uint32_t operand = exprRl(gz, scope, panic_rl, nd.lhs); + uint32_t result = addUnNode(gz, ZIR_INST_PANIC, operand, node); + return rvalue(gz, rl, result, node); + } + // @errorName — simpleUnOp with dbg_stmt (AstGen.zig:9391). + if (name_len == 9 && memcmp(source + name_start, "errorName", 9) == 0) { + advanceSourceCursorToMainToken(ag, gz, node); + uint32_t saved_line = ag->source_line - gz->decl_line; + uint32_t saved_col = ag->source_column; + AstData nd = tree->nodes.datas[node]; + ResultLoc err_rl = { .tag = RL_COERCED_TY, + .data = ZIR_REF_ANYERROR_TYPE, + .src_node = 0, .ctx = RI_CTX_NONE }; + uint32_t operand = exprRl(gz, scope, err_rl, nd.lhs); + emitDbgStmt(gz, saved_line, saved_col); + uint32_t result = addUnNode(gz, ZIR_INST_ERROR_NAME, operand, node); + return rvalue(gz, rl, result, node); + } + // @field (AstGen.zig:9288-9300). + if (name_len == 5 && memcmp(source + name_start, "field", 5) == 0) { + AstData nd = tree->nodes.datas[node]; + ResultLoc field_rl = { .tag = RL_COERCED_TY, + .data = ZIR_REF_SLICE_CONST_U8_TYPE, + .src_node = 0, .ctx = RI_CTX_NONE }; + if (RL_IS_REF(rl)) { + uint32_t lhs = exprRl(gz, scope, RL_REF_VAL, nd.lhs); + uint32_t fname = comptimeExpr( + gz, scope, field_rl, nd.rhs, COMPTIME_REASON_FIELD_NAME); + return addPlNodeBin( + gz, ZIR_INST_FIELD_PTR_NAMED, node, lhs, fname); + } + uint32_t lhs = expr(gz, scope, nd.lhs); + uint32_t fname = comptimeExpr( + gz, scope, field_rl, nd.rhs, COMPTIME_REASON_FIELD_NAME); + uint32_t result = addPlNodeBin( + gz, ZIR_INST_FIELD_VAL_NAMED, node, lhs, fname); + return rvalue(gz, rl, result, node); + } // clang-format on // TODO: handle other builtins. @@ -4916,21 +4962,27 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) { if (RL_IS_REF(rl)) { return orelseCatchExpr(gz, scope, rl, node, ZIR_INST_IS_NON_NULL_PTR, ZIR_INST_OPTIONAL_PAYLOAD_UNSAFE_PTR, - (ZirInstTag)0); + (ZirInstTag)0, UINT32_MAX); } else { return orelseCatchExpr(gz, scope, rl, node, ZIR_INST_IS_NON_NULL, - ZIR_INST_OPTIONAL_PAYLOAD_UNSAFE, (ZirInstTag)0); + ZIR_INST_OPTIONAL_PAYLOAD_UNSAFE, (ZirInstTag)0, UINT32_MAX); } // catch (AstGen.zig:1017-1052). - case AST_NODE_CATCH: + case AST_NODE_CATCH: { + uint32_t catch_token = ag->tree->nodes.main_tokens[node]; + uint32_t pt = (ag->tree->tokens.tags[catch_token + 1] == TOKEN_PIPE) + ? catch_token + 2 + : UINT32_MAX; if (RL_IS_REF(rl)) { return orelseCatchExpr(gz, scope, rl, node, ZIR_INST_IS_NON_ERR_PTR, ZIR_INST_ERR_UNION_PAYLOAD_UNSAFE_PTR, - ZIR_INST_ERR_UNION_CODE_PTR); + ZIR_INST_ERR_UNION_CODE_PTR, pt); } else { return orelseCatchExpr(gz, scope, rl, node, ZIR_INST_IS_NON_ERR, - ZIR_INST_ERR_UNION_PAYLOAD_UNSAFE, ZIR_INST_ERR_UNION_CODE); + ZIR_INST_ERR_UNION_PAYLOAD_UNSAFE, ZIR_INST_ERR_UNION_CODE, + pt); } + } // Block expressions (AstGen.zig:984-992). case AST_NODE_BLOCK_TWO: case AST_NODE_BLOCK_TWO_SEMICOLON: @@ -6220,10 +6272,7 @@ static uint32_t forExpr( static uint32_t orelseCatchExpr(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node, ZirInstTag cond_op, ZirInstTag unwrap_op, - ZirInstTag unwrap_code_op) { - // unwrap_code_op used for catch payload capture scope (not yet - // implemented in C, but passed for correctness/future use). - (void)unwrap_code_op; + ZirInstTag unwrap_code_op, uint32_t payload_token) { AstGenCtx* ag = gz->astgen; const Ast* tree = ag->tree; AstData nd = tree->nodes.datas[node]; @@ -6283,10 +6332,33 @@ static uint32_t orelseCatchExpr(GenZir* gz, Scope* scope, ResultLoc rl, if (do_err_trace && nodeMayAppendToErrorTrace(tree, nd.lhs)) addSaveErrRetIndex(&else_scope, ZIR_REF_NONE); + // Error capture scope (AstGen.zig:6102-6123). + ScopeLocalVal err_val_scope; + memset(&err_val_scope, 0, sizeof(err_val_scope)); + Scope* else_sub_scope = &else_scope.base; + if (payload_token != UINT32_MAX) { + if (tokenIsUnderscore(tree, payload_token)) { + // Discard |_| — else_sub_scope stays as &else_scope.base. + } else { + uint32_t err_name = identAsString(ag, payload_token); + uint32_t err_inst + = addUnNode(&else_scope, unwrap_code_op, operand, node); + err_val_scope = (ScopeLocalVal) { + .base = { .tag = SCOPE_LOCAL_VAL }, + .parent = &else_scope.base, + .gen_zir = &else_scope, + .inst = err_inst, + .token_src = payload_token, + .name = err_name, + }; + else_sub_scope = &err_val_scope.base; + } + } + // Use fullBodyExpr (not expr) to inline unlabeled blocks // (AstGen.zig:6125). uint32_t else_result - = fullBodyExpr(&else_scope, &else_scope.base, break_rl, nd.rhs); + = fullBodyExpr(&else_scope, else_sub_scope, break_rl, nd.rhs); if (!endsWithNoReturn(&else_scope)) { // restoreErrRetIndex (AstGen.zig:6128-6129). if (do_err_trace) @@ -8234,10 +8306,10 @@ static void blockExprStmts(GenZir* gz, Scope* scope, const uint32_t* statements, uint32_t stmt_count) { AstGenCtx* ag = gz->astgen; // Stack-allocated scope storage for local variables and defers. - // Max 64 local variable declarations and 64 defers per block. - ScopeLocalVal val_scopes[64]; - ScopeLocalPtr ptr_scopes[64]; - ScopeDefer defer_scopes[64]; + // Max 128 local variable declarations and 128 defers per block. + ScopeLocalVal val_scopes[128]; + ScopeLocalPtr ptr_scopes[128]; + ScopeDefer defer_scopes[128]; uint32_t val_idx = 0; uint32_t ptr_idx = 0; uint32_t defer_idx = 0; @@ -8314,7 +8386,7 @@ static void blockExprStmts(GenZir* gz, Scope* scope, case AST_NODE_SIMPLE_VAR_DECL: case AST_NODE_LOCAL_VAR_DECL: case AST_NODE_ALIGNED_VAR_DECL: - if (val_idx < 64 && ptr_idx < 64) { + if (val_idx < 128 && ptr_idx < 128) { varDecl(gz, cur_scope, stmt, &val_scopes[val_idx], &ptr_scopes[ptr_idx], &cur_scope); // Check which one was used: if scope now points to @@ -8330,7 +8402,7 @@ static void blockExprStmts(GenZir* gz, Scope* scope, // defer/errdefer (AstGen.zig:2580-2581). case AST_NODE_DEFER: case AST_NODE_ERRDEFER: { - if (defer_idx >= 64) { + if (defer_idx >= 128) { SET_ERROR(ag); break; } diff --git a/stage0/astgen_test.zig b/stage0/astgen_test.zig index c6a07fa9d9..6c33fd03b6 100644 --- a/stage0/astgen_test.zig +++ b/stage0/astgen_test.zig @@ -793,6 +793,9 @@ test "astgen: corpus test_all.zig" { } test "astgen: corpus build.zig" { + // TODO: 6 extra instructions — missing switchExprErrUnion optimization + // (catch |err| switch(err) pattern emits SWITCH_BLOCK instead of + // SWITCH_BLOCK_ERR_UNION). if (true) return error.SkipZigTest; const gpa = std.testing.allocator; try corpusCheck(gpa, @embedFile("../build.zig"));