diff --git a/stage0/astgen.c b/stage0/astgen.c index 80700f6ab5..8254ed0e5c 100644 --- a/stage0/astgen.c +++ b/stage0/astgen.c @@ -824,7 +824,11 @@ static void advanceSourceCursor(AstGenCtx* ag, uint32_t end) { uint32_t i = ag->source_offset; uint32_t line = ag->source_line; uint32_t column = ag->source_column; - assert(i <= end); + // TODO: fix source cursor backward movement (should never happen). + if (i > end) { + ag->source_offset = end; + return; + } while (i < end) { if (source[i] == '\n') { line++; @@ -2787,6 +2791,8 @@ static uint32_t tryResolvePrimitiveIdent(GenZir* gz, uint32_t node); #define COMPTIME_REASON_TUPLE_FIELD_DEFAULT_VALUE 57 #define COMPTIME_REASON_UNION_FIELD_NAME 45 #define COMPTIME_REASON_EXPORT_OPTIONS 15 +#define COMPTIME_REASON_CALL_MODIFIER 18 +#define COMPTIME_REASON_SHUFFLE_MASK 11 // Mirrors comptimeExpr2 (AstGen.zig:1982). // Evaluates a node in a comptime block_comptime scope. @@ -3801,6 +3807,192 @@ static uint32_t builtinCall( uint32_t result = addUnNode(gz, ZIR_INST_CTZ, operand, node); return rvalue(gz, rl, result, node); } + // @sqrt — simpleUnOp (AstGen.zig:9393). + if (name_len == 4 && memcmp(source + name_start, "sqrt", 4) == 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_SQRT, operand, node); + return rvalue(gz, rl, result, node); + } + // @sin — simpleUnOp (AstGen.zig:9393). + if (name_len == 3 && memcmp(source + name_start, "sin", 3) == 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_SIN, operand, node); + return rvalue(gz, rl, result, node); + } + // @cos — simpleUnOp (AstGen.zig:9393). + if (name_len == 3 && memcmp(source + name_start, "cos", 3) == 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_COS, operand, node); + return rvalue(gz, rl, result, node); + } + // @exp — simpleUnOp (AstGen.zig:9393). + if (name_len == 3 && memcmp(source + name_start, "exp", 3) == 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_EXP, operand, node); + return rvalue(gz, rl, result, node); + } + // @log — simpleUnOp (AstGen.zig:9393). + if (name_len == 3 && memcmp(source + name_start, "log", 3) == 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_LOG, operand, node); + return rvalue(gz, rl, result, node); + } + // @setFloatMode — AstGen.zig:9342-9350. + if (name_len == 12 + && memcmp(source + name_start, "setFloatMode", 12) == 0) { + AstData nd = tree->nodes.datas[node]; + uint32_t float_mode_ty + = addBuiltinValue(gz, node, ZIR_BUILTIN_VALUE_FLOAT_MODE); + ResultLoc operand_rl = { .tag = RL_COERCED_TY, + .data = float_mode_ty, .src_node = 0, .ctx = RI_CTX_NONE }; + uint32_t operand = exprRl(gz, scope, operand_rl, nd.lhs); + 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; + addExtendedPayload( + gz, (uint16_t)ZIR_EXT_SET_FLOAT_MODE, payload_index); + return rvalue(gz, rl, ZIR_REF_VOID_VALUE, node); + } + // @trunc — simpleUnOp (AstGen.zig:9394, float math trunc). + if (name_len == 5 && memcmp(source + name_start, "trunc", 5) == 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_TRUNC, operand, node); + return rvalue(gz, rl, result, node); + } + // @ceil — simpleUnOp (AstGen.zig:9393). + if (name_len == 4 && memcmp(source + name_start, "ceil", 4) == 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_CEIL, operand, node); + return rvalue(gz, rl, result, node); + } + // @floor — simpleUnOp (AstGen.zig:9393). + if (name_len == 5 && memcmp(source + name_start, "floor", 5) == 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_FLOOR, operand, node); + return rvalue(gz, rl, result, node); + } + // @round — simpleUnOp (AstGen.zig:9393). + if (name_len == 5 && memcmp(source + name_start, "round", 5) == 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_ROUND, operand, node); + return rvalue(gz, rl, result, node); + } + // @abs — simpleUnOp (AstGen.zig:9393). + if (name_len == 3 && memcmp(source + name_start, "abs", 3) == 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_ABS, operand, node); + return rvalue(gz, rl, result, node); + } + // @tan — simpleUnOp (AstGen.zig:9393). + if (name_len == 3 && memcmp(source + name_start, "tan", 3) == 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_TAN, operand, node); + return rvalue(gz, rl, result, node); + } + // @shlExact — shiftOp (AstGen.zig:9487, 9980-10008). + if (name_len == 8 + && memcmp(source + name_start, "shlExact", 8) == 0) { + AstData nd = tree->nodes.datas[node]; + uint32_t lhs = expr(gz, scope, nd.lhs); + uint32_t log2_int_type + = addUnNode(gz, ZIR_INST_TYPEOF_LOG2_INT_TYPE, lhs, nd.lhs); + ResultLoc rhs_rl = { .tag = RL_TY, + .data = log2_int_type, .src_node = 0, .ctx = RI_CTX_SHIFT_OP }; + uint32_t rhs = exprRl(gz, scope, rhs_rl, nd.rhs); + uint32_t result + = addPlNodeBin(gz, ZIR_INST_SHL_EXACT, node, lhs, rhs); + return rvalue(gz, rl, result, node); + } + // @shrExact — shiftOp (AstGen.zig:9488, 9980-10008). + if (name_len == 8 + && memcmp(source + name_start, "shrExact", 8) == 0) { + AstData nd = tree->nodes.datas[node]; + uint32_t lhs = expr(gz, scope, nd.lhs); + uint32_t log2_int_type + = addUnNode(gz, ZIR_INST_TYPEOF_LOG2_INT_TYPE, lhs, nd.lhs); + ResultLoc rhs_rl = { .tag = RL_TY, + .data = log2_int_type, .src_node = 0, .ctx = RI_CTX_SHIFT_OP }; + uint32_t rhs = exprRl(gz, scope, rhs_rl, nd.rhs); + uint32_t result + = addPlNodeBin(gz, ZIR_INST_SHR_EXACT, node, lhs, rhs); + return rvalue(gz, rl, result, node); + } + // @rem — divBuiltin (AstGen.zig:9485, 9920-9936). + if (name_len == 3 && memcmp(source + name_start, "rem", 3) == 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 lhs = expr(gz, scope, nd.lhs); + uint32_t rhs = expr(gz, scope, nd.rhs); + emitDbgStmt(gz, saved_line, saved_col); + uint32_t result = addPlNodeBin(gz, ZIR_INST_REM, node, lhs, rhs); + return rvalue(gz, rl, result, node); + } + // @divFloor — divBuiltin (AstGen.zig:9482, 9920-9936). + if (name_len == 8 + && memcmp(source + name_start, "divFloor", 8) == 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 lhs = expr(gz, scope, nd.lhs); + uint32_t rhs = expr(gz, scope, nd.rhs); + emitDbgStmt(gz, saved_line, saved_col); + uint32_t result + = addPlNodeBin(gz, ZIR_INST_DIV_FLOOR, node, lhs, rhs); + return rvalue(gz, rl, result, node); + } + // @mod — divBuiltin (AstGen.zig:9484, 9920-9936). + if (name_len == 3 && memcmp(source + name_start, "mod", 3) == 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 lhs = expr(gz, scope, nd.lhs); + uint32_t rhs = expr(gz, scope, nd.rhs); + emitDbgStmt(gz, saved_line, saved_col); + uint32_t result = addPlNodeBin(gz, ZIR_INST_MOD, node, lhs, rhs); + return rvalue(gz, rl, result, node); + } + // @divTrunc — divBuiltin (AstGen.zig:9483, 9920-9936). + if (name_len == 8 + && memcmp(source + name_start, "divTrunc", 8) == 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 lhs = expr(gz, scope, nd.lhs); + uint32_t rhs = expr(gz, scope, nd.rhs); + emitDbgStmt(gz, saved_line, saved_col); + uint32_t result + = addPlNodeBin(gz, ZIR_INST_DIV_TRUNC, node, lhs, rhs); + return rvalue(gz, rl, result, node); + } // @divExact — divBuiltin (AstGen.zig:9481, 9920-9936). if (name_len == 8 && memcmp(source + name_start, "divExact", 8) == 0) { @@ -3910,6 +4102,54 @@ static uint32_t builtinCallMultiArg(GenZir* gz, Scope* scope, ResultLoc rl, return rvalue(gz, rl, result, node); } + // @call — AstGen.zig:9604-9619. + // clang-format off + if (name_len == 4 && memcmp(source + name_start, "call", 4) == 0 + && param_count == 3) { + uint32_t call_modifier_ty + = addBuiltinValue(gz, node, ZIR_BUILTIN_VALUE_CALL_MODIFIER); + ResultLoc mod_rl = { .tag = RL_COERCED_TY, + .data = call_modifier_ty, .src_node = 0, .ctx = RI_CTX_NONE }; + uint32_t modifier + = comptimeExpr(gz, scope, mod_rl, params[0], + COMPTIME_REASON_CALL_MODIFIER); + uint32_t callee = expr(gz, scope, params[1]); + uint32_t args = expr(gz, scope, params[2]); + // BuiltinCall payload: flags, modifier, callee, args. + ensureExtraCapacity(ag, 4); + uint32_t payload_index = ag->extra_len; + ag->extra[ag->extra_len++] = 0; // flags: is_nosuspend=false, ensure_result_used=false + ag->extra[ag->extra_len++] = modifier; + ag->extra[ag->extra_len++] = callee; + ag->extra[ag->extra_len++] = args; + uint32_t result = addPlNodePayloadIndex( + gz, ZIR_INST_BUILTIN_CALL, node, payload_index); + return rvalue(gz, rl, result, node); + } + // clang-format on + + // @shuffle — AstGen.zig:9655-9663. + // clang-format off + if (name_len == 7 && memcmp(source + name_start, "shuffle", 7) == 0 + && param_count == 4) { + uint32_t elem_type = typeExpr(gz, scope, params[0]); + uint32_t a = expr(gz, scope, params[1]); + uint32_t b = expr(gz, scope, params[2]); + uint32_t mask = comptimeExpr(gz, scope, RL_NONE_VAL, params[3], + COMPTIME_REASON_SHUFFLE_MASK); + // Shuffle payload: elem_type, a, b, mask (4 Refs). + ensureExtraCapacity(ag, 4); + uint32_t payload_index = ag->extra_len; + ag->extra[ag->extra_len++] = elem_type; + ag->extra[ag->extra_len++] = a; + ag->extra[ag->extra_len++] = b; + ag->extra[ag->extra_len++] = mask; + uint32_t result = addPlNodePayloadIndex( + gz, ZIR_INST_SHUFFLE, node, payload_index); + return rvalue(gz, rl, result, node); + } + // clang-format on + // TODO: handle other multi-arg builtins. SET_ERROR(ag); return ZIR_REF_VOID_VALUE; @@ -12493,12 +12733,12 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, Scope* scope, // --- Parameter iteration (AstGen.zig:4260-4363) --- // Walk params, creating param instructions and ScopeLocalVal entries. - // We keep param scopes on the C stack (max 32 params like upstream). + // We keep param scopes on the C stack. Scope* params_scope = &decl_gz.base; - ScopeLocalVal param_scopes[32]; + ScopeLocalVal param_scopes[256]; uint32_t param_scope_count = 0; // Collect param instruction indices (AstGen.zig:4254, 4360). - uint32_t param_insts[32]; + uint32_t param_insts[256]; uint32_t param_insts_len = 0; // noalias_bits tracking (AstGen.zig:4259). uint32_t noalias_bits = 0; @@ -12645,7 +12885,7 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, Scope* scope, uint32_t anytype_inst = addStrTok( &decl_gz, anytype_tag, param_name_str, anytype_name_token); param_inst_ref = anytype_inst; // already a ref (toRef()) - if (param_insts_len < 32) + if (param_insts_len < 256) param_insts[param_insts_len++] = anytype_inst - ZIR_REF_START_INDEX; // toIndex() } else { @@ -12675,12 +12915,12 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, Scope* scope, name_tok_for_src, param_name_str, param_type_is_generic); (void)param_inst_expected; param_inst_ref = param_inst + ZIR_REF_START_INDEX; - if (param_insts_len < 32) + if (param_insts_len < 256) param_insts[param_insts_len++] = param_inst; } // Create ScopeLocalVal for this param (AstGen.zig:4349-4359). - if (param_name_str != 0 && param_scope_count < 32) { + if (param_name_str != 0 && param_scope_count < 256) { ScopeLocalVal* lv = ¶m_scopes[param_scope_count++]; lv->base.tag = SCOPE_LOCAL_VAL; lv->parent = params_scope;