diff --git a/astgen.c b/astgen.c index 937570b0fa..63f4cb8aa6 100644 --- a/astgen.c +++ b/astgen.c @@ -1909,6 +1909,16 @@ static uint32_t rlResultType(GenZir* gz, ResultLoc rl, uint32_t node) { } } +// Mirrors ResultLoc.resultTypeForCast (AstGen.zig:356-368). +// Like rlResultType but errors if no result type is available. +static uint32_t rlResultTypeForCast(GenZir* gz, ResultLoc rl, uint32_t node) { + uint32_t ty = rlResultType(gz, rl, node); + if (ty != 0) + return ty; + SET_ERROR(gz->astgen); + return 0; +} + static bool endsWithNoReturn(GenZir* gz); // Mirrors Zir.Inst.Tag.isAlwaysVoid (Zir.zig:1343-1608). @@ -2338,6 +2348,8 @@ static uint32_t reachableExprComptime(GenZir* gz, Scope* scope, ResultLoc rl, static uint32_t tryResolvePrimitiveIdent(GenZir* gz, uint32_t node); // SimpleComptimeReason (std.zig:727) — values used in block_comptime payload. +#define COMPTIME_REASON_C_INCLUDE 9 +#define COMPTIME_REASON_C_UNDEF 10 #define COMPTIME_REASON_TYPE 29 #define COMPTIME_REASON_ARRAY_SENTINEL 30 #define COMPTIME_REASON_POINTER_SENTINEL 31 @@ -2502,7 +2514,8 @@ static uint32_t numberLiteral(GenZir* gz, uint32_t node) { } // Mirrors builtinCall (AstGen.zig:9191), @import case (AstGen.zig:9242). -static uint32_t builtinCallImport(GenZir* gz, Scope* scope, uint32_t node) { +static uint32_t builtinCallImport( + GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) { (void)scope; AstGenCtx* ag = gz->astgen; const Ast* tree = ag->tree; @@ -2517,10 +2530,14 @@ static uint32_t builtinCallImport(GenZir* gz, Scope* scope, uint32_t node) { uint32_t str_index, str_len; strLitAsString(ag, str_lit_token, &str_index, &str_len); + // Compute res_ty from result location (AstGen.zig:9257). + uint32_t res_ty_raw = rlResultType(gz, rl, node); + uint32_t res_ty = (res_ty_raw != 0) ? res_ty_raw : ZIR_REF_NONE; + // Write Import payload to extra (Zir.Inst.Import: res_ty, path). ensureExtraCapacity(ag, 2); uint32_t payload_index = ag->extra_len; - ag->extra[ag->extra_len++] = ZIR_REF_NONE; // res_ty = .none + ag->extra[ag->extra_len++] = res_ty; ag->extra[ag->extra_len++] = str_index; // path // Create .import instruction with pl_tok data. @@ -2532,7 +2549,7 @@ static uint32_t builtinCallImport(GenZir* gz, Scope* scope, uint32_t node) { // Track import (AstGen.zig:9269). addImport(ag, str_index, str_lit_token); - return result_ref; + return rvalue(gz, rl, result_ref, node); } // Mirrors cImport (AstGen.zig:10011). @@ -2548,10 +2565,11 @@ static uint32_t cImportExpr(GenZir* gz, Scope* scope, uint32_t node) { block_scope.c_import = true; // Use fullBodyExpr to inline unlabeled block body (AstGen.zig:10028). - fullBodyExpr(&block_scope, &block_scope.base, RL_NONE_VAL, body_node); + uint32_t block_result = fullBodyExpr( + &block_scope, &block_scope.base, RL_NONE_VAL, body_node); // ensure_result_used on gz (parent), not block_scope (AstGen.zig:10029). - addUnNode(gz, ZIR_INST_ENSURE_RESULT_USED, ZIR_REF_VOID_VALUE, node); + addUnNode(gz, ZIR_INST_ENSURE_RESULT_USED, block_result, node); // break_inline (AstGen.zig:10030-10032). makeBreakInline( @@ -2565,14 +2583,29 @@ static uint32_t cImportExpr(GenZir* gz, Scope* scope, uint32_t node) { } // Mirrors simpleCBuiltin (AstGen.zig:9938). -static uint32_t simpleCBuiltin(GenZir* gz, Scope* scope, uint32_t node, - uint32_t operand_node, uint16_t ext_tag) { +static uint32_t simpleCBuiltin(GenZir* gz, Scope* scope, ResultLoc rl, + uint32_t node, uint32_t operand_node, uint16_t ext_tag) { AstGenCtx* ag = gz->astgen; - // Evaluate operand as comptime string. - uint32_t operand = expr(gz, scope, operand_node); + // Check c_import scope (AstGen.zig:9947). + if (!gz->c_import) { + SET_ERROR(ag); + return ZIR_REF_VOID_VALUE; + } - // Emit extended instruction with UnNode payload (AstGen.zig:9954). + // Evaluate operand as comptimeExpr with coerced_ty=slice_const_u8_type + // (AstGen.zig:9948-9954). + uint32_t comptime_reason = (ext_tag == (uint16_t)ZIR_EXT_C_UNDEF) + ? COMPTIME_REASON_C_UNDEF + : COMPTIME_REASON_C_INCLUDE; + ResultLoc operand_rl = { .tag = RL_COERCED_TY, + .data = ZIR_REF_SLICE_CONST_U8_TYPE, + .src_node = 0, + .ctx = RI_CTX_NONE }; + uint32_t operand + = comptimeExpr(gz, scope, operand_rl, operand_node, comptime_reason); + + // Emit extended instruction with UnNode payload (AstGen.zig:9955). ensureExtraCapacity(ag, 2); uint32_t payload_index = ag->extra_len; ag->extra[ag->extra_len++] @@ -2586,7 +2619,7 @@ static uint32_t simpleCBuiltin(GenZir* gz, Scope* scope, uint32_t node, data.extended.operand = payload_index; addInstruction(gz, ZIR_INST_EXTENDED, data); - return ZIR_REF_VOID_VALUE; + return rvalue(gz, rl, ZIR_REF_VOID_VALUE, node); } // Mirrors builtinCall (AstGen.zig:9191) dispatch. @@ -2613,38 +2646,45 @@ static uint32_t builtinCall( // clang-format off if (name_len == 6 && memcmp(source + name_start, "import", 6) == 0) - return builtinCallImport(gz, scope, node); + return builtinCallImport(gz, scope, rl, node); if (name_len == 7 && memcmp(source + name_start, "cImport", 7) == 0) return cImportExpr(gz, scope, node); if (name_len == 8 && memcmp(source + name_start, "cInclude", 8) == 0) { AstData nd = tree->nodes.datas[node]; - return simpleCBuiltin(gz, scope, node, nd.lhs, (uint16_t)ZIR_EXT_C_INCLUDE); + return simpleCBuiltin(gz, scope, rl, node, nd.lhs, (uint16_t)ZIR_EXT_C_INCLUDE); } // @intCast — typeCast pattern (AstGen.zig:9416, 9807-9826). if (name_len == 7 && memcmp(source + name_start, "intCast", 7) == 0) { advanceSourceCursorToMainToken(ag, gz, node); uint32_t saved_line = ag->source_line - gz->decl_line; uint32_t saved_col = ag->source_column; - uint32_t result_type = rlResultType(gz, rl, node); + uint32_t result_type = rlResultTypeForCast(gz, rl, node); AstData nd = tree->nodes.datas[node]; uint32_t operand = expr(gz, scope, nd.lhs); emitDbgStmt(gz, saved_line, saved_col); - return addPlNodeBin(gz, ZIR_INST_INT_CAST, node, - result_type, operand); + return rvalue(gz, rl, addPlNodeBin(gz, ZIR_INST_INT_CAST, node, + result_type, operand), node); } - // @embedFile (AstGen.zig:9626). + // @embedFile — simpleUnOp with coerced_ty (AstGen.zig:9390). if (name_len == 9 && memcmp(source + name_start, "embedFile", 9) == 0) { + advanceSourceCursorToMainToken(ag, gz, node); AstData nd = tree->nodes.datas[node]; - uint32_t operand = expr(gz, scope, nd.lhs); - return addUnNode(gz, ZIR_INST_EMBED_FILE, operand, node); + ResultLoc operand_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, operand_rl, nd.lhs); + uint32_t result = addUnNode(gz, ZIR_INST_EMBED_FILE, operand, node); + return rvalue(gz, rl, result, node); } - // @intFromEnum (AstGen.zig:9478). + // @intFromEnum — simpleUnOp (AstGen.zig:9388). if (name_len == 11 && memcmp(source + name_start, "intFromEnum", 11) == 0) { + advanceSourceCursorToMainToken(ag, gz, node); AstData nd = tree->nodes.datas[node]; uint32_t operand = expr(gz, scope, nd.lhs); - return addUnNode(gz, ZIR_INST_INT_FROM_ENUM, operand, node); + uint32_t result = addUnNode(gz, ZIR_INST_INT_FROM_ENUM, operand, node); + return rvalue(gz, rl, result, node); } - // @tagName (AstGen.zig:9407) — simpleUnOp with dbg_stmt. + // @tagName — simpleUnOp with dbg_stmt (AstGen.zig:9407). if (name_len == 7 && memcmp(source + name_start, "tagName", 7) == 0) { advanceSourceCursorToMainToken(ag, gz, node); uint32_t saved_line = ag->source_line - gz->decl_line; @@ -2652,7 +2692,8 @@ static uint32_t builtinCall( AstData nd = tree->nodes.datas[node]; uint32_t operand = expr(gz, scope, nd.lhs); emitDbgStmt(gz, saved_line, saved_col); - return addUnNode(gz, ZIR_INST_TAG_NAME, operand, node); + uint32_t result = addUnNode(gz, ZIR_INST_TAG_NAME, operand, node); + return rvalue(gz, rl, result, node); } // @as (AstGen.zig:8909-8920). if (name_len == 2 && memcmp(source + name_start, "as", 2) == 0) { @@ -2668,44 +2709,46 @@ static uint32_t builtinCall( advanceSourceCursorToMainToken(ag, gz, node); uint32_t saved_line = ag->source_line - gz->decl_line; uint32_t saved_col = ag->source_column; - uint32_t result_type = rlResultType(gz, rl, node); + uint32_t result_type = rlResultTypeForCast(gz, rl, node); AstData nd = tree->nodes.datas[node]; uint32_t operand = expr(gz, scope, nd.lhs); emitDbgStmt(gz, saved_line, saved_col); - return addPlNodeBin(gz, ZIR_INST_TRUNCATE, node, - result_type, operand); + return rvalue(gz, rl, addPlNodeBin(gz, ZIR_INST_TRUNCATE, node, + result_type, operand), node); } // @ptrCast — typeCast pattern (AstGen.zig:9056, 9807-9826). + // TODO: Issue 14 — upstream routes through ptrCast() for nested + // pointer cast collapsing. Currently uses simple typeCast path. if (name_len == 7 && memcmp(source + name_start, "ptrCast", 7) == 0) { advanceSourceCursorToMainToken(ag, gz, node); uint32_t saved_line = ag->source_line - gz->decl_line; uint32_t saved_col = ag->source_column; - uint32_t result_type = rlResultType(gz, rl, node); + uint32_t result_type = rlResultTypeForCast(gz, rl, node); AstData nd = tree->nodes.datas[node]; uint32_t operand = expr(gz, scope, nd.lhs); emitDbgStmt(gz, saved_line, saved_col); - return addPlNodeBin(gz, ZIR_INST_PTR_CAST, node, - result_type, operand); + return rvalue(gz, rl, addPlNodeBin(gz, ZIR_INST_PTR_CAST, node, + result_type, operand), node); } // @enumFromInt — typeCast pattern (AstGen.zig:9414, 9807-9826). if (name_len == 11 && memcmp(source + name_start, "enumFromInt", 11) == 0) { advanceSourceCursorToMainToken(ag, gz, node); uint32_t saved_line = ag->source_line - gz->decl_line; uint32_t saved_col = ag->source_column; - uint32_t result_type = rlResultType(gz, rl, node); + uint32_t result_type = rlResultTypeForCast(gz, rl, node); AstData nd = tree->nodes.datas[node]; uint32_t operand = expr(gz, scope, nd.lhs); emitDbgStmt(gz, saved_line, saved_col); - return addPlNodeBin(gz, ZIR_INST_ENUM_FROM_INT, node, - result_type, operand); + return rvalue(gz, rl, addPlNodeBin(gz, ZIR_INST_ENUM_FROM_INT, node, + result_type, operand), node); } // @bitCast (AstGen.zig:8944-8958, dispatched at 9313). if (name_len == 7 && memcmp(source + name_start, "bitCast", 7) == 0) { - uint32_t result_type = rlResultType(gz, rl, node); + uint32_t result_type = rlResultTypeForCast(gz, rl, node); AstData nd = tree->nodes.datas[node]; uint32_t operand = expr(gz, scope, nd.lhs); - return addPlNodeBin(gz, ZIR_INST_BITCAST, node, - result_type, operand); + return rvalue(gz, rl, addPlNodeBin(gz, ZIR_INST_BITCAST, node, + result_type, operand), node); } // @memcpy (AstGen.zig:9631-9637). if (name_len == 6 && memcmp(source + name_start, "memcpy", 6) == 0) { @@ -2713,7 +2756,7 @@ static uint32_t builtinCall( uint32_t dst = expr(gz, scope, nd.lhs); uint32_t src = expr(gz, scope, nd.rhs); addPlNodeBin(gz, ZIR_INST_MEMCPY, node, dst, src); - return ZIR_REF_VOID_VALUE; + return rvalue(gz, rl, ZIR_REF_VOID_VALUE, node); } // @memset (AstGen.zig:9638-9647). if (name_len == 6 && memcmp(source + name_start, "memset", 6) == 0) { @@ -2723,24 +2766,27 @@ static uint32_t builtinCall( uint32_t elem_ty = addUnNode(gz, ZIR_INST_INDEXABLE_PTR_ELEM_TYPE, lhs_ty, nd.lhs); ResultLoc val_rl = { - .tag = RL_COERCED_TY, .data = elem_ty, .src_node = 0}; + .tag = RL_COERCED_TY, .data = elem_ty, .src_node = 0, + .ctx = RI_CTX_NONE }; uint32_t val = exprRl(gz, scope, val_rl, nd.rhs); addPlNodeBin(gz, ZIR_INST_MEMSET, node, lhs, val); - return ZIR_REF_VOID_VALUE; + return rvalue(gz, rl, ZIR_REF_VOID_VALUE, node); } - // @min (AstGen.zig:9155). + // @min (AstGen.zig:9149-9172). if (name_len == 3 && memcmp(source + name_start, "min", 3) == 0) { AstData nd = tree->nodes.datas[node]; uint32_t a = expr(gz, scope, nd.lhs); uint32_t b = expr(gz, scope, nd.rhs); - return addPlNodeBin(gz, ZIR_INST_MIN, node, a, b); + return rvalue(gz, rl, + addPlNodeBin(gz, ZIR_INST_MIN, node, a, b), node); } - // @max (AstGen.zig:9155). + // @max (AstGen.zig:9149-9172). if (name_len == 3 && memcmp(source + name_start, "max", 3) == 0) { AstData nd = tree->nodes.datas[node]; uint32_t a = expr(gz, scope, nd.lhs); uint32_t b = expr(gz, scope, nd.rhs); - return addPlNodeBin(gz, ZIR_INST_MAX, node, a, b); + return rvalue(gz, rl, + addPlNodeBin(gz, ZIR_INST_MAX, node, a, b), node); } // clang-format on @@ -4241,7 +4287,7 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) { return rvalue(gz, rl, numberLiteral(gz, node), node); case AST_NODE_BUILTIN_CALL_TWO: case AST_NODE_BUILTIN_CALL_TWO_COMMA: - return rvalue(gz, rl, builtinCall(gz, scope, rl, node), node); + return builtinCall(gz, scope, rl, node); case AST_NODE_FIELD_ACCESS: return fieldAccessExpr(gz, scope, rl, node); case AST_NODE_IDENTIFIER: