astgen: fix builtinCall rvalue, operand coercion, and result type handling
- Move rvalue calls inside builtinCall (all builtins now call rvalue internally, matching upstream) and remove outer rvalue wrap from call site - Add rlResultTypeForCast that errors when no result type is available, used by @bitCast, @intCast, @truncate, @ptrCast, @enumFromInt - Fix @import to compute res_ty from result location instead of hardcoding ZIR_REF_NONE - Fix @embedFile to evaluate operand with coerced_ty=slice_const_u8_type - Fix @cInclude/simpleCBuiltin to check c_import scope and use comptimeExpr with coerced_ty=slice_const_u8_type - Fix @cImport to pass actual block_result to ensure_result_used instead of hardcoded ZIR_REF_VOID_VALUE Not fixed: Issue 14 (ptrCast nested pointer cast collapsing) — upstream routes @ptrCast through a dedicated ptrCast() function that walks nested pointer cast builtins. Currently uses simple typeCast path only. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
132
astgen.c
132
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:
|
||||
|
||||
Reference in New Issue
Block a user