Merge commit '0b12e027a3628e26a765126d9937a2366b638ff3' into zig0-0.15.1

This commit is contained in:
2026-02-14 00:07:36 +02:00
2 changed files with 93 additions and 34 deletions

View File

@@ -1089,6 +1089,54 @@ static void strLitAsString(AstGenCtx* ag, uint32_t str_lit_token,
ag->string_bytes[ag->string_bytes_len++] = val; ag->string_bytes[ag->string_bytes_len++] = val;
break; break;
} }
case 'u': {
// \u{NNNNNN} unicode escape (string_literal.zig:194-231).
// Skip past '{'.
i++;
// Parse hex digits until '}'.
uint32_t codepoint = 0;
while (i + 1 < raw_end) {
i++;
char c = source[i];
if (c >= '0' && c <= '9') {
codepoint = codepoint * 16 + (uint32_t)(c - '0');
} else if (c >= 'a' && c <= 'f') {
codepoint = codepoint * 16 + 10 + (uint32_t)(c - 'a');
} else if (c >= 'A' && c <= 'F') {
codepoint = codepoint * 16 + 10 + (uint32_t)(c - 'A');
} else {
// Must be '}', done.
break;
}
}
// Encode codepoint as UTF-8 (unicode.zig:53-82).
if (codepoint <= 0x7F) {
ag->string_bytes[ag->string_bytes_len++]
= (uint8_t)codepoint;
} else if (codepoint <= 0x7FF) {
ag->string_bytes[ag->string_bytes_len++]
= (uint8_t)(0xC0 | (codepoint >> 6));
ag->string_bytes[ag->string_bytes_len++]
= (uint8_t)(0x80 | (codepoint & 0x3F));
} else if (codepoint <= 0xFFFF) {
ag->string_bytes[ag->string_bytes_len++]
= (uint8_t)(0xE0 | (codepoint >> 12));
ag->string_bytes[ag->string_bytes_len++]
= (uint8_t)(0x80 | ((codepoint >> 6) & 0x3F));
ag->string_bytes[ag->string_bytes_len++]
= (uint8_t)(0x80 | (codepoint & 0x3F));
} else {
ag->string_bytes[ag->string_bytes_len++]
= (uint8_t)(0xF0 | (codepoint >> 18));
ag->string_bytes[ag->string_bytes_len++]
= (uint8_t)(0x80 | ((codepoint >> 12) & 0x3F));
ag->string_bytes[ag->string_bytes_len++]
= (uint8_t)(0x80 | ((codepoint >> 6) & 0x3F));
ag->string_bytes[ag->string_bytes_len++]
= (uint8_t)(0x80 | (codepoint & 0x3F));
}
break;
}
default: default:
ag->string_bytes[ag->string_bytes_len++] = (uint8_t)source[i]; ag->string_bytes[ag->string_bytes_len++] = (uint8_t)source[i];
break; break;
@@ -4251,6 +4299,26 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
char_val = val; char_val = val;
break; break;
} }
case 'u': {
// \u{NNNNNN} unicode escape (string_literal.zig:194-231).
// Skip past '{'.
ci++;
uint32_t codepoint = 0;
while (true) {
ci++;
char c = src[ci];
if (c >= '0' && c <= '9')
codepoint = codepoint * 16 + (uint32_t)(c - '0');
else if (c >= 'a' && c <= 'f')
codepoint = codepoint * 16 + 10 + (uint32_t)(c - 'a');
else if (c >= 'A' && c <= 'F')
codepoint = codepoint * 16 + 10 + (uint32_t)(c - 'A');
else
break; // Must be '}'.
}
char_val = codepoint;
break;
}
default: default:
char_val = (uint8_t)src[ci]; char_val = (uint8_t)src[ci];
break; break;
@@ -4762,7 +4830,7 @@ static uint32_t blockExprExpr(
} }
// Labeled block (AstGen.zig:2466-2536). // Labeled block (AstGen.zig:2466-2536).
bool force_comptime = gz->is_comptime; // Note: upstream blockExpr always passes force_comptime=false.
uint32_t label_token = lbrace - 2; uint32_t label_token = lbrace - 2;
// Compute break result info (AstGen.zig:2484-2492). // Compute break result info (AstGen.zig:2484-2492).
@@ -4771,15 +4839,10 @@ static uint32_t blockExprExpr(
bool need_result_rvalue = (break_ri.tag != rl.tag); bool need_result_rvalue = (break_ri.tag != rl.tag);
// Reserve the block instruction (AstGen.zig:2500-2501). // Reserve the block instruction (AstGen.zig:2500-2501).
ZirInstTag block_tag uint32_t block_inst = makeBlockInst(ag, ZIR_INST_BLOCK, gz, node);
= force_comptime ? ZIR_INST_BLOCK_COMPTIME : ZIR_INST_BLOCK;
uint32_t block_inst = makeBlockInst(ag, block_tag, gz, node);
gzAppendInstruction(gz, block_inst); gzAppendInstruction(gz, block_inst);
GenZir block_scope = makeSubBlock(gz, scope); GenZir block_scope = makeSubBlock(gz, scope);
block_scope.is_inline = force_comptime; // AstGen.zig:2503
if (force_comptime)
block_scope.is_comptime = true;
// Set label on block_scope (AstGen.zig:2504-2508). // Set label on block_scope (AstGen.zig:2504-2508).
block_scope.label_token = label_token; block_scope.label_token = label_token;
block_scope.label_block_inst = block_inst; block_scope.label_block_inst = block_inst;
@@ -4790,29 +4853,19 @@ static uint32_t blockExprExpr(
if (!endsWithNoReturn(&block_scope)) { if (!endsWithNoReturn(&block_scope)) {
// Emit restore_err_ret_index (AstGen.zig:2515). // Emit restore_err_ret_index (AstGen.zig:2515).
if (!force_comptime) { ZirInstData rdata;
ZirInstData rdata; rdata.un_node.operand = block_inst + ZIR_REF_START_INDEX;
rdata.un_node.operand = block_inst + ZIR_REF_START_INDEX; rdata.un_node.src_node = (int32_t)node - (int32_t)gz->decl_node_index;
rdata.un_node.src_node addInstruction(
= (int32_t)node - (int32_t)gz->decl_node_index; gz, ZIR_INST_RESTORE_ERR_RET_INDEX_UNCONDITIONAL, rdata);
addInstruction(
gz, ZIR_INST_RESTORE_ERR_RET_INDEX_UNCONDITIONAL, rdata);
}
// rvalue + break (AstGen.zig:2516-2518). // rvalue + break (AstGen.zig:2516-2518).
uint32_t result = rvalue( uint32_t result = rvalue(
gz, block_scope.break_result_info, ZIR_REF_VOID_VALUE, node); gz, block_scope.break_result_info, ZIR_REF_VOID_VALUE, node);
ZirInstTag break_tag addBreak(&block_scope, ZIR_INST_BREAK, block_inst, result,
= force_comptime ? ZIR_INST_BREAK_INLINE : ZIR_INST_BREAK; AST_NODE_OFFSET_NONE);
addBreak(
&block_scope, break_tag, block_inst, result, AST_NODE_OFFSET_NONE);
} }
if (force_comptime) { setBlockBody(ag, &block_scope, block_inst);
setBlockComptimeBody(
ag, &block_scope, block_inst, COMPTIME_REASON_COMPTIME_KEYWORD);
} else {
setBlockBody(ag, &block_scope, block_inst);
}
// AstGen.zig:2531-2534. // AstGen.zig:2531-2534.
if (need_result_rvalue) if (need_result_rvalue)
@@ -6575,17 +6628,23 @@ static bool addEnsureResult(
uint32_t inst = maybe_unused_result - ZIR_REF_START_INDEX; uint32_t inst = maybe_unused_result - ZIR_REF_START_INDEX;
ZirInstTag tag = ag->inst_tags[inst]; ZirInstTag tag = ag->inst_tags[inst];
switch (tag) { switch (tag) {
// For call/field_call/builtin_call: set ensure_result_used flag // For call/field_call: set ensure_result_used flag
// (bit 3 of flags at offset 0). Flags *must* be at offset 0 in all // (bit 3 of flags at offset 0). Flags *must* be at offset 0
// three structs (AstGen.zig:2658-2665, Zir.zig:3022). // (AstGen.zig:2658-2665, Zir.zig:3022).
case ZIR_INST_CALL: case ZIR_INST_CALL:
case ZIR_INST_FIELD_CALL: case ZIR_INST_FIELD_CALL: {
case ZIR_INST_BUILTIN_CALL: {
uint32_t pi = ag->inst_datas[inst].pl_node.payload_index; uint32_t pi = ag->inst_datas[inst].pl_node.payload_index;
ag->extra[pi] |= (1u << 3); // ensure_result_used ag->extra[pi] |= (1u << 3); // ensure_result_used
elide_check = true; elide_check = true;
break; break;
} }
// For builtin_call: ensure_result_used is at bit 1, not bit 3.
case ZIR_INST_BUILTIN_CALL: {
uint32_t pi = ag->inst_datas[inst].pl_node.payload_index;
ag->extra[pi] |= (1u << 1); // ensure_result_used
elide_check = true;
break;
}
// Always noreturn → elide (AstGen.zig:2909). // Always noreturn → elide (AstGen.zig:2909).
case ZIR_INST_BREAK: case ZIR_INST_BREAK:
case ZIR_INST_BREAK_INLINE: case ZIR_INST_BREAK_INLINE:
@@ -6602,6 +6661,7 @@ static bool addEnsureResult(
case ZIR_INST_TRAP: case ZIR_INST_TRAP:
case ZIR_INST_CHECK_COMPTIME_CONTROL_FLOW: case ZIR_INST_CHECK_COMPTIME_CONTROL_FLOW:
case ZIR_INST_SWITCH_CONTINUE: case ZIR_INST_SWITCH_CONTINUE:
case ZIR_INST_COMPILE_ERROR:
is_noreturn = true; is_noreturn = true;
elide_check = true; elide_check = true;
break; break;
@@ -9577,7 +9637,7 @@ static bool rlExpr(
// defer (AstRlAnnotate.zig:148-151). // defer (AstRlAnnotate.zig:148-151).
case AST_NODE_DEFER: case AST_NODE_DEFER:
(void)rlExpr(ag, nd.rhs, block, RL_RI_NONE); (void)rlExpr(ag, nd.lhs, block, RL_RI_NONE);
return false; return false;
// container_field (AstRlAnnotate.zig:153-167). // container_field (AstRlAnnotate.zig:153-167).

View File

@@ -711,7 +711,7 @@ static AstNodeIndex expectStatement(Parser* p, bool allow_defer_var) {
const AstTokenIndex comptime_token = eatToken(p, TOKEN_KEYWORD_COMPTIME); const AstTokenIndex comptime_token = eatToken(p, TOKEN_KEYWORD_COMPTIME);
if (comptime_token != null_token) { if (comptime_token != null_token) {
// comptime followed by block => comptime block statement // comptime followed by block => comptime block statement
const AstNodeIndex block = parseBlock(p); const AstNodeIndex block = parseBlockExpr(p);
if (block != 0) { if (block != 0) {
return addNode(&p->nodes, return addNode(&p->nodes,
(AstNodeItem) { (AstNodeItem) {
@@ -1728,8 +1728,7 @@ static AstNodeIndex parseTypeExpr(Parser* p) {
const AstNodeIndex condition = expectExpr(p); const AstNodeIndex condition = expectExpr(p);
expectToken(p, TOKEN_R_PAREN); expectToken(p, TOKEN_R_PAREN);
parsePtrPayload(p); parsePtrPayload(p);
const AstNodeIndex cont_expr const AstNodeIndex cont_expr = parseWhileContinueExpr(p);
= eatToken(p, TOKEN_COLON) != null_token ? expectExpr(p) : 0;
const AstNodeIndex body = parseTypeExpr(p); const AstNodeIndex body = parseTypeExpr(p);
if (eatToken(p, TOKEN_KEYWORD_ELSE) != null_token) { if (eatToken(p, TOKEN_KEYWORD_ELSE) != null_token) {
parsePayload(p); parsePayload(p);