astgen: implement 20+ builtins, multi-arg dispatch, extended helpers
Add builtins: @sizeOf, @alignOf, @typeInfo (simpleUnOpType pattern), @compileError, @setEvalBranchQuota, @typeName (simpleUnOp pattern), @This (addNodeExtended), @memmove, @FieldType, @reduce, @addWithOverflow/@subWithOverflow/@mulWithOverflow/@shlWithOverflow (overflowArithmetic), @alignCast/@constCast/@volatileCast (ptrCast family), @errSetCast, @Type (reify), @TypeOf (typeof_builtin block), @unionInit (3-arg via builtinCallMultiArg), @intFromPtr, @intFromBool, @floatFromInt, @intFromFloat, @floatCast. Add helper functions: addNodeExtended, addExtendedPayload, addExtendedPayloadSmall. Add is_typeof field to GenZir. Add AST_NODE_BUILTIN_CALL dispatch for 3+ arg builtins. Add COMPTIME_REASON_COMPILE_ERROR_STRING and UNION_FIELD_NAME. Add skipped corpus tests for array_list.zig, multi_array_list.zig, Sema.zig (blocked on identifier resolution across namespace scopes). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
509
stage0/astgen.c
509
stage0/astgen.c
@@ -117,12 +117,8 @@ typedef struct {
|
||||
bool fn_var_args; // AstGen.zig:46
|
||||
} AstGenCtx;
|
||||
|
||||
static void setCompileError(AstGenCtx* ag, const char* where, int line) {
|
||||
(void)where;
|
||||
(void)line;
|
||||
ag->has_compile_errors = true;
|
||||
}
|
||||
#define SET_ERROR(ag) setCompileError(ag, __func__, __LINE__)
|
||||
static void setCompileError(AstGenCtx* ag) { ag->has_compile_errors = true; }
|
||||
#define SET_ERROR(ag) setCompileError(ag)
|
||||
|
||||
// Set fn_block pointer on AstGenCtx. The caller is responsible for saving
|
||||
// and restoring the previous value before the pointed-to GenZir goes out
|
||||
@@ -257,6 +253,7 @@ typedef struct {
|
||||
bool is_comptime;
|
||||
bool is_inline; // true for inline for/while, labeled blocks in comptime
|
||||
bool c_import; // true inside @cImport block
|
||||
bool is_typeof; // true inside @TypeOf scope
|
||||
uint32_t instructions_top; // start index in shared array
|
||||
uint32_t break_block; // UINT32_MAX = none (AstGen.zig:11780)
|
||||
uint32_t continue_block; // UINT32_MAX = none (AstGen.zig:11784)
|
||||
@@ -365,6 +362,7 @@ static GenZir makeSubBlock(GenZir* parent, Scope* scope) {
|
||||
sub.decl_line = parent->decl_line;
|
||||
sub.is_comptime = parent->is_comptime;
|
||||
sub.c_import = parent->c_import;
|
||||
sub.is_typeof = parent->is_typeof;
|
||||
sub.instructions_top = parent->astgen->scratch_inst_len;
|
||||
sub.break_block = UINT32_MAX;
|
||||
sub.continue_block = UINT32_MAX;
|
||||
@@ -595,6 +593,61 @@ static uint32_t addBuiltinValue(
|
||||
return idx + ZIR_REF_START_INDEX;
|
||||
}
|
||||
|
||||
// Mirrors GenZir.addNodeExtended (AstGen.zig:12765-12779).
|
||||
// Creates an extended instruction with operand = node offset.
|
||||
static uint32_t addNodeExtended(
|
||||
GenZir* gz, uint16_t opcode, uint32_t src_node) {
|
||||
AstGenCtx* ag = gz->astgen;
|
||||
ensureInstCapacity(ag, 1);
|
||||
uint32_t idx = ag->inst_len;
|
||||
ag->inst_tags[idx] = ZIR_INST_EXTENDED;
|
||||
ZirInstData data;
|
||||
data.extended.opcode = opcode;
|
||||
data.extended.small = 0;
|
||||
data.extended.operand
|
||||
= (uint32_t)((int32_t)src_node - (int32_t)gz->decl_node_index);
|
||||
ag->inst_datas[idx] = data;
|
||||
ag->inst_len++;
|
||||
gzAppendInstruction(gz, idx);
|
||||
return idx + ZIR_REF_START_INDEX;
|
||||
}
|
||||
|
||||
// Mirrors GenZir.addExtendedPayload (AstGen.zig:12781).
|
||||
// Creates an extended instruction with given payload_index and small=0.
|
||||
static uint32_t addExtendedPayload(
|
||||
GenZir* gz, uint16_t opcode, uint32_t payload_index) {
|
||||
AstGenCtx* ag = gz->astgen;
|
||||
ensureInstCapacity(ag, 1);
|
||||
uint32_t idx = ag->inst_len;
|
||||
ag->inst_tags[idx] = ZIR_INST_EXTENDED;
|
||||
ZirInstData data;
|
||||
data.extended.opcode = opcode;
|
||||
data.extended.small = 0;
|
||||
data.extended.operand = payload_index;
|
||||
ag->inst_datas[idx] = data;
|
||||
ag->inst_len++;
|
||||
gzAppendInstruction(gz, idx);
|
||||
return idx + ZIR_REF_START_INDEX;
|
||||
}
|
||||
|
||||
// Mirrors GenZir.addExtendedPayloadSmall (variant with small field).
|
||||
// Creates an extended instruction with given payload_index and small value.
|
||||
static uint32_t addExtendedPayloadSmall(
|
||||
GenZir* gz, uint16_t opcode, uint16_t small, uint32_t payload_index) {
|
||||
AstGenCtx* ag = gz->astgen;
|
||||
ensureInstCapacity(ag, 1);
|
||||
uint32_t idx = ag->inst_len;
|
||||
ag->inst_tags[idx] = ZIR_INST_EXTENDED;
|
||||
ZirInstData data;
|
||||
data.extended.opcode = opcode;
|
||||
data.extended.small = small;
|
||||
data.extended.operand = payload_index;
|
||||
ag->inst_datas[idx] = data;
|
||||
ag->inst_len++;
|
||||
gzAppendInstruction(gz, idx);
|
||||
return idx + ZIR_REF_START_INDEX;
|
||||
}
|
||||
|
||||
// --- Source cursor (AstGen.zig:13335-13359) ---
|
||||
|
||||
// Mirrors AstGen.advanceSourceCursor (AstGen.zig:13342).
|
||||
@@ -2481,8 +2534,10 @@ static uint32_t tryResolvePrimitiveIdent(GenZir* gz, uint32_t node);
|
||||
#define COMPTIME_REASON_FIELD_NAME 42
|
||||
#define COMPTIME_REASON_COMPTIME_KEYWORD 53
|
||||
#define COMPTIME_REASON_ARRAY_MUL_FACTOR 22
|
||||
#define COMPTIME_REASON_COMPILE_ERROR_STRING 19
|
||||
#define COMPTIME_REASON_SWITCH_ITEM 56
|
||||
#define COMPTIME_REASON_TUPLE_FIELD_DEFAULT_VALUE 57
|
||||
#define COMPTIME_REASON_UNION_FIELD_NAME 45
|
||||
|
||||
// Mirrors comptimeExpr2 (AstGen.zig:1982).
|
||||
// Evaluates a node in a comptime block_comptime scope.
|
||||
@@ -2973,6 +3028,345 @@ static uint32_t builtinCall(
|
||||
gz, ZIR_INST_FIELD_VAL_NAMED, node, lhs, fname);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @sizeOf — simpleUnOpType (AstGen.zig:9381).
|
||||
if (name_len == 6 && memcmp(source + name_start, "sizeOf", 6) == 0) {
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t operand = typeExpr(gz, scope, nd.lhs);
|
||||
uint32_t result = addUnNode(gz, ZIR_INST_SIZE_OF, operand, node);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @alignOf — simpleUnOpType (AstGen.zig:9383).
|
||||
if (name_len == 7 && memcmp(source + name_start, "alignOf", 7) == 0) {
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t operand = typeExpr(gz, scope, nd.lhs);
|
||||
uint32_t result = addUnNode(gz, ZIR_INST_ALIGN_OF, operand, node);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @typeInfo — simpleUnOpType (AstGen.zig:9380).
|
||||
if (name_len == 8 && memcmp(source + name_start, "typeInfo", 8) == 0) {
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t operand = typeExpr(gz, scope, nd.lhs);
|
||||
uint32_t result = addUnNode(gz, ZIR_INST_TYPE_INFO, operand, node);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @compileError — simpleUnOp (AstGen.zig:9386, 9841-9861).
|
||||
if (name_len == 12
|
||||
&& memcmp(source + name_start, "compileError", 12) == 0) {
|
||||
advanceSourceCursorToMainToken(ag, gz, node);
|
||||
AstData nd = tree->nodes.datas[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 = comptimeExpr(gz, scope, operand_rl, nd.lhs,
|
||||
COMPTIME_REASON_COMPILE_ERROR_STRING);
|
||||
uint32_t result
|
||||
= addUnNode(gz, ZIR_INST_COMPILE_ERROR, operand, node);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @setEvalBranchQuota — simpleUnOp (AstGen.zig:9387, 9841-9861).
|
||||
if (name_len == 18
|
||||
&& memcmp(source + name_start, "setEvalBranchQuota", 18) == 0) {
|
||||
advanceSourceCursorToMainToken(ag, gz, node);
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
ResultLoc operand_rl = { .tag = RL_COERCED_TY,
|
||||
.data = ZIR_REF_U32_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_SET_EVAL_BRANCH_QUOTA, operand, node);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @typeName — simpleUnOp (AstGen.zig:9408, 9841-9861).
|
||||
if (name_len == 8 && memcmp(source + name_start, "typeName", 8) == 0) {
|
||||
advanceSourceCursorToMainToken(ag, gz, node);
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t operand = expr(gz, scope, nd.lhs);
|
||||
uint32_t result = addUnNode(gz, ZIR_INST_TYPE_NAME, operand, node);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @This (AstGen.zig:9371).
|
||||
if (name_len == 4 && memcmp(source + name_start, "This", 4) == 0)
|
||||
return rvalue(
|
||||
gz, rl, addNodeExtended(gz, (uint16_t)ZIR_EXT_THIS, node), node);
|
||||
// @memmove (AstGen.zig:9648-9654).
|
||||
if (name_len == 7 && memcmp(source + name_start, "memmove", 7) == 0) {
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t dst = expr(gz, scope, nd.lhs);
|
||||
uint32_t src_op = expr(gz, scope, nd.rhs);
|
||||
addPlNodeBin(gz, ZIR_INST_MEMMOVE, node, dst, src_op);
|
||||
return rvalue(gz, rl, ZIR_REF_VOID_VALUE, node);
|
||||
}
|
||||
// @FieldType (AstGen.zig:9301-9309).
|
||||
if (name_len == 9 && memcmp(source + name_start, "FieldType", 9) == 0) {
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t ty_inst = typeExpr(gz, scope, nd.lhs);
|
||||
ResultLoc name_rl = { .tag = RL_COERCED_TY,
|
||||
.data = ZIR_REF_SLICE_CONST_U8_TYPE, .src_node = 0,
|
||||
.ctx = RI_CTX_NONE };
|
||||
uint32_t name_inst = comptimeExpr(
|
||||
gz, scope, name_rl, nd.rhs, COMPTIME_REASON_FIELD_NAME);
|
||||
uint32_t result = addPlNodeBin(
|
||||
gz, ZIR_INST_FIELD_TYPE_REF, node, ty_inst, name_inst);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @reduce (AstGen.zig:9539-9548).
|
||||
if (name_len == 6 && memcmp(source + name_start, "reduce", 6) == 0) {
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t reduce_op_ty
|
||||
= addBuiltinValue(gz, node, ZIR_BUILTIN_VALUE_REDUCE_OP);
|
||||
ResultLoc op_rl = { .tag = RL_COERCED_TY,
|
||||
.data = reduce_op_ty, .src_node = 0, .ctx = RI_CTX_NONE };
|
||||
uint32_t op = exprRl(gz, scope, op_rl, nd.lhs);
|
||||
uint32_t scalar = expr(gz, scope, nd.rhs);
|
||||
uint32_t result
|
||||
= addPlNodeBin(gz, ZIR_INST_REDUCE, node, op, scalar);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @addWithOverflow — overflowArithmetic (AstGen.zig:9550, 10040-10056).
|
||||
if (name_len == 15
|
||||
&& memcmp(source + name_start, "addWithOverflow", 15) == 0) {
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t lhs = expr(gz, scope, nd.lhs);
|
||||
uint32_t rhs = expr(gz, scope, nd.rhs);
|
||||
ensureExtraCapacity(ag, 3);
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
ag->extra[ag->extra_len++]
|
||||
= (uint32_t)((int32_t)node - (int32_t)gz->decl_node_index);
|
||||
ag->extra[ag->extra_len++] = lhs;
|
||||
ag->extra[ag->extra_len++] = rhs;
|
||||
uint32_t result = addExtendedPayload(
|
||||
gz, (uint16_t)ZIR_EXT_ADD_WITH_OVERFLOW, payload_index);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @subWithOverflow (AstGen.zig:9551, 10040-10056).
|
||||
if (name_len == 15
|
||||
&& memcmp(source + name_start, "subWithOverflow", 15) == 0) {
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t lhs = expr(gz, scope, nd.lhs);
|
||||
uint32_t rhs = expr(gz, scope, nd.rhs);
|
||||
ensureExtraCapacity(ag, 3);
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
ag->extra[ag->extra_len++]
|
||||
= (uint32_t)((int32_t)node - (int32_t)gz->decl_node_index);
|
||||
ag->extra[ag->extra_len++] = lhs;
|
||||
ag->extra[ag->extra_len++] = rhs;
|
||||
uint32_t result = addExtendedPayload(
|
||||
gz, (uint16_t)ZIR_EXT_SUB_WITH_OVERFLOW, payload_index);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @mulWithOverflow (AstGen.zig:9552, 10040-10056).
|
||||
if (name_len == 15
|
||||
&& memcmp(source + name_start, "mulWithOverflow", 15) == 0) {
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t lhs = expr(gz, scope, nd.lhs);
|
||||
uint32_t rhs = expr(gz, scope, nd.rhs);
|
||||
ensureExtraCapacity(ag, 3);
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
ag->extra[ag->extra_len++]
|
||||
= (uint32_t)((int32_t)node - (int32_t)gz->decl_node_index);
|
||||
ag->extra[ag->extra_len++] = lhs;
|
||||
ag->extra[ag->extra_len++] = rhs;
|
||||
uint32_t result = addExtendedPayload(
|
||||
gz, (uint16_t)ZIR_EXT_MUL_WITH_OVERFLOW, payload_index);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @shlWithOverflow (AstGen.zig:9553, 10040-10056).
|
||||
if (name_len == 15
|
||||
&& memcmp(source + name_start, "shlWithOverflow", 15) == 0) {
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t lhs = expr(gz, scope, nd.lhs);
|
||||
uint32_t rhs = expr(gz, scope, nd.rhs);
|
||||
ensureExtraCapacity(ag, 3);
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
ag->extra[ag->extra_len++]
|
||||
= (uint32_t)((int32_t)node - (int32_t)gz->decl_node_index);
|
||||
ag->extra[ag->extra_len++] = lhs;
|
||||
ag->extra[ag->extra_len++] = rhs;
|
||||
uint32_t result = addExtendedPayload(
|
||||
gz, (uint16_t)ZIR_EXT_SHL_WITH_OVERFLOW, payload_index);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @alignCast — ptrCast family (AstGen.zig:9464-9469, 8969-9087).
|
||||
// Simplified: standalone @alignCast uses ptr_cast_full with align_cast flag.
|
||||
if (name_len == 9
|
||||
&& memcmp(source + name_start, "alignCast", 9) == 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 = rlResultTypeForCast(gz, rl, node);
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t operand = expr(gz, scope, nd.lhs);
|
||||
emitDbgStmt(gz, saved_line, saved_col);
|
||||
// align_cast flag = bit 1 (FullPtrCastFlags: ptr_cast=0, align_cast=1)
|
||||
uint16_t flags = 0x02;
|
||||
ensureExtraCapacity(ag, 3);
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
ag->extra[ag->extra_len++]
|
||||
= (uint32_t)((int32_t)node - (int32_t)gz->decl_node_index);
|
||||
ag->extra[ag->extra_len++] = result_type;
|
||||
ag->extra[ag->extra_len++] = operand;
|
||||
uint32_t result = addExtendedPayloadSmall(
|
||||
gz, (uint16_t)ZIR_EXT_PTR_CAST_FULL, flags, payload_index);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @constCast (AstGen.zig:9464-9469, 8969-9087).
|
||||
if (name_len == 9
|
||||
&& memcmp(source + name_start, "constCast", 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];
|
||||
uint32_t operand = expr(gz, scope, nd.lhs);
|
||||
emitDbgStmt(gz, saved_line, saved_col);
|
||||
// const_cast flag = bit 3 (FullPtrCastFlags packed u5)
|
||||
uint16_t flags = 0x08;
|
||||
ensureExtraCapacity(ag, 2);
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
ag->extra[ag->extra_len++]
|
||||
= (uint32_t)((int32_t)node - (int32_t)gz->decl_node_index);
|
||||
ag->extra[ag->extra_len++] = operand;
|
||||
uint32_t result = addExtendedPayloadSmall(
|
||||
gz, (uint16_t)ZIR_EXT_PTR_CAST_NO_DEST, flags, payload_index);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @volatileCast (AstGen.zig:9464-9469, 8969-9087).
|
||||
if (name_len == 12
|
||||
&& memcmp(source + name_start, "volatileCast", 12) == 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];
|
||||
uint32_t operand = expr(gz, scope, nd.lhs);
|
||||
emitDbgStmt(gz, saved_line, saved_col);
|
||||
// volatile_cast flag = bit 4 (FullPtrCastFlags packed u5)
|
||||
uint16_t flags = 0x10;
|
||||
ensureExtraCapacity(ag, 2);
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
ag->extra[ag->extra_len++]
|
||||
= (uint32_t)((int32_t)node - (int32_t)gz->decl_node_index);
|
||||
ag->extra[ag->extra_len++] = operand;
|
||||
uint32_t result = addExtendedPayloadSmall(
|
||||
gz, (uint16_t)ZIR_EXT_PTR_CAST_NO_DEST, flags, payload_index);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @Type (reify) (AstGen.zig:9426-9428, 9747-9781).
|
||||
if (name_len == 4 && memcmp(source + name_start, "Type", 4) == 0) {
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t type_info_ty
|
||||
= addBuiltinValue(gz, node, ZIR_BUILTIN_VALUE_TYPE_INFO);
|
||||
ResultLoc operand_rl = { .tag = RL_COERCED_TY,
|
||||
.data = type_info_ty, .src_node = 0, .ctx = RI_CTX_NONE };
|
||||
uint32_t operand = exprRl(gz, scope, operand_rl, nd.lhs);
|
||||
// Reify payload: absolute node, operand, src_line.
|
||||
ensureExtraCapacity(ag, 3);
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
ag->extra[ag->extra_len++] = node; // absolute node index
|
||||
ag->extra[ag->extra_len++] = operand;
|
||||
ag->extra[ag->extra_len++] = ag->source_line;
|
||||
// name_strat = .anon = 2
|
||||
uint32_t result = addExtendedPayloadSmall(
|
||||
gz, (uint16_t)ZIR_EXT_REIFY, 2, payload_index);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @TypeOf (AstGen.zig:9314, 9089-9147) — single-arg case.
|
||||
if (name_len == 6 && memcmp(source + name_start, "TypeOf", 6) == 0) {
|
||||
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);
|
||||
typeof_scope.is_comptime = false;
|
||||
typeof_scope.is_typeof = true;
|
||||
typeof_scope.c_import = false;
|
||||
uint32_t ty_expr_ref = reachableExpr(
|
||||
&typeof_scope, &typeof_scope.base, RL_NONE_VAL, nd.lhs, node);
|
||||
if (!refIsNoReturn(&typeof_scope, ty_expr_ref)) {
|
||||
addBreak(&typeof_scope, ZIR_INST_BREAK_INLINE,
|
||||
typeof_inst, ty_expr_ref,
|
||||
(int32_t)nd.lhs - (int32_t)gz->decl_node_index);
|
||||
}
|
||||
setBlockBody(ag, &typeof_scope, typeof_inst);
|
||||
// typeof_scope unstacked now, add instruction to gz.
|
||||
gzAppendInstruction(gz, typeof_inst);
|
||||
return rvalue(gz, rl, typeof_inst + ZIR_REF_START_INDEX, node);
|
||||
}
|
||||
// @intFromPtr — simpleUnOp with dbg_stmt (AstGen.zig:9392).
|
||||
if (name_len == 10
|
||||
&& memcmp(source + name_start, "intFromPtr", 10) == 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];
|
||||
uint32_t operand = expr(gz, scope, nd.lhs);
|
||||
emitDbgStmt(gz, saved_line, saved_col);
|
||||
uint32_t result
|
||||
= addUnNode(gz, ZIR_INST_INT_FROM_PTR, operand, node);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @intFromBool — simpleUnOp (AstGen.zig:9389).
|
||||
if (name_len == 11
|
||||
&& memcmp(source + name_start, "intFromBool", 11) == 0) {
|
||||
advanceSourceCursorToMainToken(ag, gz, node);
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t operand = expr(gz, scope, nd.lhs);
|
||||
uint32_t result
|
||||
= addUnNode(gz, ZIR_INST_INT_FROM_BOOL, operand, node);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// @floatFromInt — typeCast (AstGen.zig:9418, 9807-9826).
|
||||
if (name_len == 12
|
||||
&& memcmp(source + name_start, "floatFromInt", 12) == 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 = 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 rvalue(gz, rl, addPlNodeBin(gz, ZIR_INST_FLOAT_FROM_INT,
|
||||
node, result_type, operand), node);
|
||||
}
|
||||
// @intFromFloat — typeCast (AstGen.zig:9419, 9807-9826).
|
||||
if (name_len == 12
|
||||
&& memcmp(source + name_start, "intFromFloat", 12) == 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 = 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 rvalue(gz, rl, addPlNodeBin(gz, ZIR_INST_INT_FROM_FLOAT,
|
||||
node, result_type, operand), node);
|
||||
}
|
||||
// @floatCast — typeCast (AstGen.zig:9420, 9807-9826).
|
||||
if (name_len == 9
|
||||
&& memcmp(source + name_start, "floatCast", 9) == 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 = 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 rvalue(gz, rl, addPlNodeBin(gz, ZIR_INST_FLOAT_CAST,
|
||||
node, result_type, operand), node);
|
||||
}
|
||||
// @errSetCast — extended error_cast (AstGen.zig:9454-9463).
|
||||
if (name_len == 10
|
||||
&& memcmp(source + name_start, "errSetCast", 10) == 0) {
|
||||
emitDbgNode(gz, node);
|
||||
uint32_t result_type = rlResultTypeForCast(gz, rl, node);
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t operand = expr(gz, scope, nd.lhs);
|
||||
ensureExtraCapacity(ag, 3);
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
ag->extra[ag->extra_len++]
|
||||
= (uint32_t)((int32_t)node - (int32_t)gz->decl_node_index);
|
||||
ag->extra[ag->extra_len++] = result_type;
|
||||
ag->extra[ag->extra_len++] = operand;
|
||||
uint32_t result = addExtendedPayload(
|
||||
gz, (uint16_t)ZIR_EXT_ERROR_CAST, payload_index);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
// TODO: handle other builtins.
|
||||
@@ -2980,6 +3374,62 @@ static uint32_t builtinCall(
|
||||
return ZIR_REF_VOID_VALUE;
|
||||
}
|
||||
|
||||
// Mirrors builtinCall for 3+ arg builtins (AST_NODE_BUILTIN_CALL).
|
||||
// params are in extra_data[params_start..params_end].
|
||||
static uint32_t builtinCallMultiArg(GenZir* gz, Scope* scope, ResultLoc rl,
|
||||
uint32_t node, uint32_t params_start, uint32_t params_end) {
|
||||
AstGenCtx* ag = gz->astgen;
|
||||
const Ast* tree = ag->tree;
|
||||
|
||||
uint32_t builtin_token = tree->nodes.main_tokens[node];
|
||||
uint32_t tok_start = tree->tokens.starts[builtin_token];
|
||||
const char* source = tree->source;
|
||||
uint32_t name_start = tok_start + 1;
|
||||
uint32_t name_end = name_start;
|
||||
while (name_end < tree->source_len
|
||||
&& ((source[name_end] >= 'a' && source[name_end] <= 'z')
|
||||
|| (source[name_end] >= 'A' && source[name_end] <= 'Z')
|
||||
|| source[name_end] == '_')) {
|
||||
name_end++;
|
||||
}
|
||||
uint32_t name_len = name_end - name_start;
|
||||
const uint32_t* params = tree->extra_data.arr + params_start;
|
||||
uint32_t param_count = params_end - params_start;
|
||||
|
||||
// @unionInit (AstGen.zig:9315, 8922-8942).
|
||||
if (name_len == 9 && memcmp(source + name_start, "unionInit", 9) == 0
|
||||
&& param_count == 3) {
|
||||
uint32_t union_type = typeExpr(gz, scope, params[0]);
|
||||
ResultLoc name_rl = { .tag = RL_COERCED_TY,
|
||||
.data = ZIR_REF_SLICE_CONST_U8_TYPE,
|
||||
.src_node = 0,
|
||||
.ctx = RI_CTX_NONE };
|
||||
uint32_t field_name_ref = comptimeExpr(
|
||||
gz, scope, name_rl, params[1], COMPTIME_REASON_UNION_FIELD_NAME);
|
||||
// Get field type via field_type_ref.
|
||||
uint32_t field_type = addPlNodeBin(
|
||||
gz, ZIR_INST_FIELD_TYPE_REF, node, union_type, field_name_ref);
|
||||
// Evaluate init value coerced to field type.
|
||||
ResultLoc init_rl = {
|
||||
.tag = RL_TY, .data = field_type, .src_node = 0, .ctx = rl.ctx
|
||||
};
|
||||
uint32_t init = reachableExpr(gz, scope, init_rl, params[2], node);
|
||||
// Emit union_init: payload = union_type, init, field_name_ref.
|
||||
ensureExtraCapacity(ag, 3);
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
ag->extra[ag->extra_len++] = union_type;
|
||||
ag->extra[ag->extra_len++] = init;
|
||||
ag->extra[ag->extra_len++] = field_name_ref;
|
||||
uint32_t result = addPlNodePayloadIndex(
|
||||
gz, ZIR_INST_UNION_INIT, node, payload_index);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
|
||||
// TODO: handle other multi-arg builtins.
|
||||
SET_ERROR(ag);
|
||||
return ZIR_REF_VOID_VALUE;
|
||||
}
|
||||
|
||||
// --- identifier (AstGen.zig:8282) ---
|
||||
// Simplified: handles decl_val resolution for container-level declarations.
|
||||
|
||||
@@ -4538,6 +4988,9 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||
case AST_NODE_BUILTIN_CALL_TWO:
|
||||
case AST_NODE_BUILTIN_CALL_TWO_COMMA:
|
||||
return builtinCall(gz, scope, rl, node);
|
||||
case AST_NODE_BUILTIN_CALL:
|
||||
case AST_NODE_BUILTIN_CALL_COMMA:
|
||||
return builtinCallMultiArg(gz, scope, rl, node, nd.lhs, nd.rhs);
|
||||
case AST_NODE_FIELD_ACCESS:
|
||||
return fieldAccessExpr(gz, scope, rl, node);
|
||||
case AST_NODE_IDENTIFIER:
|
||||
@@ -13249,37 +13702,29 @@ static bool rlExpr(
|
||||
(void)rlExpr(ag, nd.rhs, block, RL_RI_TYPE_ONLY);
|
||||
return false;
|
||||
case AST_NODE_PTR_TYPE: {
|
||||
AstPtrType pt;
|
||||
pt.sentinel = tree->extra_data.arr[nd.lhs];
|
||||
pt.align_node = tree->extra_data.arr[nd.lhs + 1];
|
||||
pt.addrspace_node = tree->extra_data.arr[nd.lhs + 2];
|
||||
const AstPtrType* pt
|
||||
= (const AstPtrType*)(tree->extra_data.arr + nd.lhs);
|
||||
(void)rlExpr(ag, nd.rhs, block, RL_RI_TYPE_ONLY);
|
||||
if (pt.sentinel != 0)
|
||||
(void)rlExpr(ag, pt.sentinel, block, RL_RI_TYPE_ONLY);
|
||||
if (pt.align_node != 0)
|
||||
(void)rlExpr(ag, pt.align_node, block, RL_RI_TYPE_ONLY);
|
||||
if (pt.addrspace_node != 0)
|
||||
(void)rlExpr(ag, pt.addrspace_node, block, RL_RI_TYPE_ONLY);
|
||||
if (pt->sentinel != UINT32_MAX)
|
||||
(void)rlExpr(ag, pt->sentinel, block, RL_RI_TYPE_ONLY);
|
||||
if (pt->align_node != UINT32_MAX)
|
||||
(void)rlExpr(ag, pt->align_node, block, RL_RI_TYPE_ONLY);
|
||||
if (pt->addrspace_node != UINT32_MAX)
|
||||
(void)rlExpr(ag, pt->addrspace_node, block, RL_RI_TYPE_ONLY);
|
||||
return false;
|
||||
}
|
||||
case AST_NODE_PTR_TYPE_BIT_RANGE: {
|
||||
AstPtrTypeBitRange pt;
|
||||
pt.sentinel = tree->extra_data.arr[nd.lhs];
|
||||
pt.align_node = tree->extra_data.arr[nd.lhs + 1];
|
||||
pt.addrspace_node = tree->extra_data.arr[nd.lhs + 2];
|
||||
pt.bit_range_start = tree->extra_data.arr[nd.lhs + 3];
|
||||
pt.bit_range_end = tree->extra_data.arr[nd.lhs + 4];
|
||||
const AstPtrTypeBitRange* pt
|
||||
= (const AstPtrTypeBitRange*)(tree->extra_data.arr + nd.lhs);
|
||||
(void)rlExpr(ag, nd.rhs, block, RL_RI_TYPE_ONLY);
|
||||
if (pt.sentinel != 0)
|
||||
(void)rlExpr(ag, pt.sentinel, block, RL_RI_TYPE_ONLY);
|
||||
if (pt.align_node != 0)
|
||||
(void)rlExpr(ag, pt.align_node, block, RL_RI_TYPE_ONLY);
|
||||
if (pt.addrspace_node != 0)
|
||||
(void)rlExpr(ag, pt.addrspace_node, block, RL_RI_TYPE_ONLY);
|
||||
if (pt.bit_range_start != 0) {
|
||||
(void)rlExpr(ag, pt.bit_range_start, block, RL_RI_TYPE_ONLY);
|
||||
(void)rlExpr(ag, pt.bit_range_end, block, RL_RI_TYPE_ONLY);
|
||||
}
|
||||
if (pt->sentinel != UINT32_MAX)
|
||||
(void)rlExpr(ag, pt->sentinel, block, RL_RI_TYPE_ONLY);
|
||||
// align_node is always present for bit_range.
|
||||
(void)rlExpr(ag, pt->align_node, block, RL_RI_TYPE_ONLY);
|
||||
if (pt->addrspace_node != UINT32_MAX)
|
||||
(void)rlExpr(ag, pt->addrspace_node, block, RL_RI_TYPE_ONLY);
|
||||
(void)rlExpr(ag, pt->bit_range_start, block, RL_RI_TYPE_ONLY);
|
||||
(void)rlExpr(ag, pt->bit_range_end, block, RL_RI_TYPE_ONLY);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user