more astgen
This commit is contained in:
140
astgen.c
140
astgen.c
@@ -737,13 +737,13 @@ static uint32_t makeBlockInst(
|
||||
}
|
||||
|
||||
// Mirrors appendPossiblyRefdBodyInst (AstGen.zig:13675-13683).
|
||||
// Prepends ref_table entry before body_inst in extra.
|
||||
// Appends body_inst first, then recursively appends ref_table entry.
|
||||
static void appendPossiblyRefdBodyInst(AstGenCtx* ag, uint32_t body_inst) {
|
||||
ag->extra[ag->extra_len++] = body_inst;
|
||||
uint32_t ref_inst;
|
||||
if (refTableFetchRemove(ag, body_inst, &ref_inst)) {
|
||||
appendPossiblyRefdBodyInst(ag, ref_inst);
|
||||
}
|
||||
ag->extra[ag->extra_len++] = body_inst;
|
||||
}
|
||||
|
||||
// Mirrors countBodyLenAfterFixups (AstGen.zig:13686-13710).
|
||||
@@ -1145,14 +1145,21 @@ static inline ResultLoc rlBr(ResultLoc rl) {
|
||||
// from parent RL. Converts coerced_ty → ty, discard → discard, else passes
|
||||
// through. For ptr/inferred_ptr, converts to ty/none respectively.
|
||||
static ResultLoc breakResultInfo(
|
||||
GenZir* gz, ResultLoc parent_rl, uint32_t node) {
|
||||
GenZir* gz, ResultLoc parent_rl, uint32_t node, bool need_rl) {
|
||||
// First: compute block_ri (AstGen.zig:7639-7646).
|
||||
// When need_rl is true, forward the rl as-is (don't convert ptr→ty).
|
||||
ResultLoc block_ri;
|
||||
if (need_rl) {
|
||||
block_ri = parent_rl;
|
||||
} else {
|
||||
switch (parent_rl.tag) {
|
||||
case RL_PTR: {
|
||||
uint32_t ptr_ty = addUnNode(gz, ZIR_INST_TYPEOF, parent_rl.data, node);
|
||||
uint32_t ty = addUnNode(gz, ZIR_INST_ELEM_TYPE, ptr_ty, node);
|
||||
block_ri = (ResultLoc) { .tag = RL_TY, .data = ty, .src_node = 0 };
|
||||
uint32_t ptr_ty
|
||||
= addUnNode(gz, ZIR_INST_TYPEOF, parent_rl.data, node);
|
||||
uint32_t ty
|
||||
= addUnNode(gz, ZIR_INST_ELEM_TYPE, ptr_ty, node);
|
||||
block_ri
|
||||
= (ResultLoc) { .tag = RL_TY, .data = ty, .src_node = 0 };
|
||||
break;
|
||||
}
|
||||
case RL_INFERRED_PTR:
|
||||
@@ -1162,6 +1169,7 @@ static ResultLoc breakResultInfo(
|
||||
block_ri = parent_rl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Then: setBreakResultInfo (AstGen.zig:11910-11925).
|
||||
switch (block_ri.tag) {
|
||||
case RL_COERCED_TY:
|
||||
@@ -1407,7 +1415,7 @@ static uint32_t ifExpr(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node);
|
||||
static uint32_t forExpr(
|
||||
GenZir* gz, Scope* scope, uint32_t node, bool is_statement);
|
||||
static uint32_t orelseCatchExpr(
|
||||
GenZir* gz, Scope* scope, uint32_t node, bool is_catch);
|
||||
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node, bool is_catch);
|
||||
static uint32_t arrayInitDotExpr(
|
||||
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node);
|
||||
static uint32_t switchExpr(
|
||||
@@ -1449,18 +1457,48 @@ static bool endsWithNoReturn(GenZir* gz) {
|
||||
case ZIR_INST_UNREACHABLE:
|
||||
case ZIR_INST_REPEAT:
|
||||
case ZIR_INST_REPEAT_INLINE:
|
||||
case ZIR_INST_PANIC:
|
||||
case ZIR_INST_TRAP:
|
||||
case ZIR_INST_CHECK_COMPTIME_CONTROL_FLOW:
|
||||
case ZIR_INST_SWITCH_CONTINUE:
|
||||
case ZIR_INST_SWITCH_BLOCK:
|
||||
case ZIR_INST_SWITCH_BLOCK_REF:
|
||||
case ZIR_INST_SWITCH_BLOCK_ERR_UNION:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Mirrors GenZir.refIsNoReturn (AstGen.zig:11885).
|
||||
static bool refIsNoReturn(GenZir* gz, uint32_t inst_ref) {
|
||||
if (inst_ref == ZIR_REF_UNREACHABLE_VALUE)
|
||||
return true;
|
||||
if (inst_ref >= ZIR_REF_START_INDEX) {
|
||||
uint32_t inst_index = inst_ref - ZIR_REF_START_INDEX;
|
||||
ZirInstTag tag = gz->astgen->inst_tags[inst_index];
|
||||
switch (tag) {
|
||||
case ZIR_INST_BREAK:
|
||||
case ZIR_INST_BREAK_INLINE:
|
||||
case ZIR_INST_CONDBR:
|
||||
case ZIR_INST_CONDBR_INLINE:
|
||||
case ZIR_INST_COMPILE_ERROR:
|
||||
case ZIR_INST_RET_NODE:
|
||||
case ZIR_INST_RET_LOAD:
|
||||
case ZIR_INST_RET_IMPLICIT:
|
||||
case ZIR_INST_RET_ERR_VALUE:
|
||||
case ZIR_INST_UNREACHABLE:
|
||||
case ZIR_INST_REPEAT:
|
||||
case ZIR_INST_REPEAT_INLINE:
|
||||
case ZIR_INST_PANIC:
|
||||
case ZIR_INST_TRAP:
|
||||
case ZIR_INST_CHECK_COMPTIME_CONTROL_FLOW:
|
||||
case ZIR_INST_SWITCH_CONTINUE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint32_t tryResolvePrimitiveIdent(GenZir* gz, uint32_t node);
|
||||
|
||||
// SimpleComptimeReason (std.zig:727) — values used in block_comptime payload.
|
||||
@@ -1802,15 +1840,11 @@ static uint32_t builtinCall(
|
||||
return addPlNodeBin(gz, ZIR_INST_ENUM_FROM_INT, node,
|
||||
result_type, operand);
|
||||
}
|
||||
// @bitCast — typeCast pattern (AstGen.zig:9416, 9807-9826).
|
||||
// @bitCast (AstGen.zig:8944-8958, dispatched at 9313).
|
||||
if (name_len == 7 && memcmp(source + name_start, "bitCast", 7) == 0) {
|
||||
advanceSourceCursorToMainToken(ag, 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);
|
||||
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_BITCAST, node,
|
||||
result_type, operand);
|
||||
}
|
||||
@@ -2254,7 +2288,23 @@ static uint32_t simpleBinOp(
|
||||
AstGenCtx* ag = gz->astgen;
|
||||
AstData nd = ag->tree->nodes.datas[node];
|
||||
uint32_t lhs = exprRl(gz, scope, RL_NONE_VAL, nd.lhs);
|
||||
// For arithmetic ops, advance cursor before RHS (AstGen.zig:6245-6256).
|
||||
uint32_t saved_line = 0, saved_col = 0;
|
||||
bool need_dbg = false;
|
||||
if (op_tag == ZIR_INST_ADD || op_tag == ZIR_INST_SUB
|
||||
|| op_tag == ZIR_INST_MUL || op_tag == ZIR_INST_DIV
|
||||
|| op_tag == ZIR_INST_MOD_REM) {
|
||||
if (!gz->is_comptime) {
|
||||
advanceSourceCursorToMainToken(ag, node);
|
||||
}
|
||||
saved_line = ag->source_line - gz->decl_line;
|
||||
saved_col = ag->source_column;
|
||||
need_dbg = true;
|
||||
}
|
||||
uint32_t rhs = exprRl(gz, scope, RL_NONE_VAL, nd.rhs);
|
||||
if (need_dbg) {
|
||||
emitDbgStmt(gz, saved_line, saved_col);
|
||||
}
|
||||
return addPlNodeBin(gz, op_tag, node, lhs, rhs);
|
||||
}
|
||||
|
||||
@@ -3203,10 +3253,10 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||
}
|
||||
// orelse (AstGen.zig:6031-6142).
|
||||
case AST_NODE_ORELSE:
|
||||
return rvalue(gz, rl, orelseCatchExpr(gz, scope, node, false), node);
|
||||
return orelseCatchExpr(gz, scope, rl, node, false);
|
||||
// catch (AstGen.zig:6031-6142).
|
||||
case AST_NODE_CATCH:
|
||||
return rvalue(gz, rl, orelseCatchExpr(gz, scope, node, true), node);
|
||||
return orelseCatchExpr(gz, scope, rl, node, true);
|
||||
// Block expressions (AstGen.zig:984-992).
|
||||
case AST_NODE_BLOCK_TWO:
|
||||
case AST_NODE_BLOCK_TWO_SEMICOLON:
|
||||
@@ -3577,7 +3627,8 @@ static uint32_t blockExprExpr(
|
||||
uint32_t label_token = lbrace - 2;
|
||||
|
||||
// Compute break result info (AstGen.zig:2484-2492).
|
||||
ResultLoc break_ri = breakResultInfo(gz, rl, node);
|
||||
bool need_rl = nodesNeedRlContains(ag, node);
|
||||
ResultLoc break_ri = breakResultInfo(gz, rl, node, need_rl);
|
||||
bool need_result_rvalue = (break_ri.tag != rl.tag);
|
||||
|
||||
// Reserve the block instruction (AstGen.zig:2500-2501).
|
||||
@@ -3786,7 +3837,8 @@ static uint32_t arrayInitDotExpr(
|
||||
static uint32_t ifExpr(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||
AstGenCtx* ag = gz->astgen;
|
||||
const Ast* tree = ag->tree;
|
||||
ResultLoc break_rl = breakResultInfo(gz, rl, node);
|
||||
bool need_rl = nodesNeedRlContains(ag, node);
|
||||
ResultLoc break_rl = breakResultInfo(gz, rl, node, need_rl);
|
||||
AstNodeTag tag = tree->nodes.tags[node];
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
|
||||
@@ -3944,6 +3996,10 @@ static uint32_t ifExpr(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||
// Wire up condbr (AstGen.zig:6491).
|
||||
setCondBrPayload(ag, condbr, bool_bit, &then_scope, &else_scope);
|
||||
|
||||
// AstGen.zig:6493-6497.
|
||||
bool need_result_rvalue = (break_rl.tag != rl.tag);
|
||||
if (need_result_rvalue)
|
||||
return rvalue(gz, rl, block_inst + ZIR_REF_START_INDEX, node);
|
||||
return block_inst + ZIR_REF_START_INDEX;
|
||||
}
|
||||
|
||||
@@ -4232,13 +4288,18 @@ static uint32_t forExpr(
|
||||
// Handles `lhs orelse rhs` and `lhs catch rhs`.
|
||||
|
||||
static uint32_t orelseCatchExpr(
|
||||
GenZir* gz, Scope* scope, uint32_t node, bool is_catch) {
|
||||
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node, bool is_catch) {
|
||||
AstGenCtx* ag = gz->astgen;
|
||||
const Ast* tree = ag->tree;
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
|
||||
bool do_err_trace = is_catch && ag->fn_ret_ty != 0;
|
||||
|
||||
// breakResultInfo (AstGen.zig:6046-6058).
|
||||
bool need_rl = nodesNeedRlContains(ag, node);
|
||||
ResultLoc break_rl = breakResultInfo(gz, rl, node, need_rl);
|
||||
bool need_result_rvalue = (break_rl.tag != rl.tag);
|
||||
|
||||
// Create block_scope (AstGen.zig:6062-6063).
|
||||
GenZir block_scope = makeSubBlock(gz, scope);
|
||||
|
||||
@@ -4274,14 +4335,23 @@ static uint32_t orelseCatchExpr(
|
||||
if (do_err_trace && nodeMayAppendToErrorTrace(tree, nd.lhs))
|
||||
addSaveErrRetIndex(&else_scope, ZIR_REF_NONE);
|
||||
|
||||
uint32_t else_result = expr(&else_scope, &else_scope.base, nd.rhs);
|
||||
// Use fullBodyExpr (not expr) to inline unlabeled blocks (AstGen.zig:6125).
|
||||
uint32_t else_result
|
||||
= fullBodyExpr(&else_scope, &else_scope.base, break_rl, nd.rhs);
|
||||
if (!endsWithNoReturn(&else_scope)) {
|
||||
// restoreErrRetIndex (AstGen.zig:6128-6129).
|
||||
if (do_err_trace)
|
||||
restoreErrRetIndex(
|
||||
&else_scope, block_inst, break_rl, nd.rhs, else_result);
|
||||
addBreak(&else_scope, ZIR_INST_BREAK, block_inst, else_result,
|
||||
(int32_t)nd.rhs - (int32_t)gz->decl_node_index);
|
||||
}
|
||||
|
||||
setCondBrPayload(ag, condbr, condition, &then_scope, &else_scope);
|
||||
|
||||
// AstGen.zig:6137-6141.
|
||||
if (need_result_rvalue)
|
||||
return rvalue(gz, rl, block_inst + ZIR_REF_START_INDEX, node);
|
||||
return block_inst + ZIR_REF_START_INDEX;
|
||||
}
|
||||
|
||||
@@ -4417,7 +4487,8 @@ static uint32_t switchExpr(
|
||||
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||
AstGenCtx* ag = gz->astgen;
|
||||
const Ast* tree = ag->tree;
|
||||
ResultLoc break_rl = breakResultInfo(gz, rl, node);
|
||||
bool need_rl = nodesNeedRlContains(ag, node);
|
||||
ResultLoc break_rl = breakResultInfo(gz, rl, node, need_rl);
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
|
||||
// AST_NODE_SWITCH: lhs = condition node, rhs = extra index for SubRange.
|
||||
@@ -4599,7 +4670,7 @@ static uint32_t switchExpr(
|
||||
// Use fullBodyExpr to process body inline (AstGen.zig:8009).
|
||||
uint32_t result
|
||||
= fullBodyExpr(&case_scope, &case_scope.base, break_rl, body_node);
|
||||
if (!endsWithNoReturn(&case_scope)) {
|
||||
if (!refIsNoReturn(gz, result)) {
|
||||
addBreak(&case_scope, ZIR_INST_BREAK, switch_inst, result,
|
||||
(int32_t)body_node - (int32_t)gz->decl_node_index);
|
||||
}
|
||||
@@ -4669,6 +4740,10 @@ static uint32_t switchExpr(
|
||||
ag->inst_datas[switch_inst].pl_node.payload_index = payload_index;
|
||||
gzAppendInstruction(gz, switch_inst);
|
||||
|
||||
// AstGen.zig:8112-8115.
|
||||
bool need_result_rvalue = (break_rl.tag != rl.tag);
|
||||
if (need_result_rvalue)
|
||||
return rvalue(gz, rl, switch_inst + ZIR_REF_START_INDEX, node);
|
||||
return switch_inst + ZIR_REF_START_INDEX;
|
||||
}
|
||||
|
||||
@@ -4770,12 +4845,14 @@ static void assignStmt(GenZir* gz, Scope* scope, uint32_t infix_node) {
|
||||
}
|
||||
}
|
||||
|
||||
// Non-discard assignment: evaluate LHS as lvalue, store RHS.
|
||||
// Non-discard assignment: evaluate LHS as lvalue, pass ptr rl to RHS.
|
||||
// (AstGen.zig:3448-3452).
|
||||
{
|
||||
uint32_t lhs_ptr = exprRl(gz, scope, RL_REF_VAL, lhs);
|
||||
uint32_t rhs_val = expr(gz, scope, rhs);
|
||||
addPlNodeBin(gz, ZIR_INST_STORE_NODE, infix_node, lhs_ptr, rhs_val);
|
||||
ResultLoc ptr_rl = {
|
||||
.tag = RL_PTR, .data = lhs_ptr, .src_node = infix_node
|
||||
};
|
||||
(void)exprRl(gz, scope, ptr_rl, rhs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6519,9 +6596,11 @@ static void testDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
||||
fn_block.instructions_top = ag->scratch_inst_len;
|
||||
fn_block.break_block = UINT32_MAX;
|
||||
|
||||
// Set fn_block for retExpr (AstGen.zig:4849-4852).
|
||||
// Set fn_block and fn_ret_ty for the body (AstGen.zig:4849-4853).
|
||||
void* prev_fn_block = ag->fn_block;
|
||||
uint32_t prev_fn_ret_ty = ag->fn_ret_ty;
|
||||
ag->fn_block = &fn_block;
|
||||
ag->fn_ret_ty = ZIR_REF_ANYERROR_VOID_ERROR_UNION_TYPE;
|
||||
|
||||
// Compute lbrace source location (AstGen.zig:4860-4862).
|
||||
advanceSourceCursorToNode(ag, body_node);
|
||||
@@ -6529,16 +6608,19 @@ static void testDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
||||
uint32_t lbrace_column = ag->source_column;
|
||||
|
||||
// Process test body (AstGen.zig:4864).
|
||||
fullBodyExpr(&fn_block, &fn_block.base, RL_NONE_VAL, body_node);
|
||||
uint32_t block_result
|
||||
= fullBodyExpr(&fn_block, &fn_block.base, RL_NONE_VAL, body_node);
|
||||
|
||||
ag->fn_block = prev_fn_block;
|
||||
ag->fn_ret_ty = prev_fn_ret_ty;
|
||||
|
||||
// If we hit unimplemented features, bail out.
|
||||
if (ag->has_compile_errors)
|
||||
return;
|
||||
|
||||
// Add restore_err_ret_index + ret_implicit (AstGen.zig:4865-4871).
|
||||
if (!endsWithNoReturn(&fn_block)) {
|
||||
if (gzInstructionsLen(&fn_block) == 0
|
||||
|| !refIsNoReturn(&fn_block, block_result)) {
|
||||
ZirInstData rdata;
|
||||
rdata.un_node.operand = ZIR_REF_NONE; // .none for .ret
|
||||
rdata.un_node.src_node
|
||||
|
||||
121
astgen_test.zig
121
astgen_test.zig
@@ -607,12 +607,20 @@ fn expectEqualData(
|
||||
|
||||
/// Silent ZIR comparison: returns true if ZIR matches, false otherwise.
|
||||
/// Unlike expectEqualZir, does not print diagnostics or return errors.
|
||||
fn zirMatches(gpa: Allocator, ref: Zir, got: c.Zir) bool {
|
||||
fn zirMatches(_: Allocator, ref: Zir, got: c.Zir) bool {
|
||||
const ref_len: u32 = @intCast(ref.instructions.len);
|
||||
if (ref_len != got.inst_len) {
|
||||
std.debug.print(" inst_len: ref={d} got={d}\n", .{ ref_len, got.inst_len });
|
||||
}
|
||||
|
||||
{
|
||||
const elen: u32 = @intCast(ref.extra.len);
|
||||
const slen: u32 = @intCast(ref.string_bytes.len);
|
||||
std.debug.print(" inst_len: ref={d} got={d}\n", .{ ref_len, got.inst_len });
|
||||
std.debug.print(" extra_len: ref={d} got={d} diff={d}\n", .{ elen, got.extra_len, @as(i64, elen) - @as(i64, got.extra_len) });
|
||||
std.debug.print(" string_bytes_len: ref={d} got={d} diff={d}\n", .{ slen, got.string_bytes_len, @as(i64, slen) - @as(i64, got.string_bytes_len) });
|
||||
}
|
||||
|
||||
const ref_tags = ref.instructions.items(.tag);
|
||||
const ref_datas = ref.instructions.items(.data);
|
||||
const min_len = @min(ref_len, got.inst_len);
|
||||
@@ -626,8 +634,8 @@ fn zirMatches(gpa: Allocator, ref: Zir, got: c.Zir) bool {
|
||||
}
|
||||
}
|
||||
if (first_tag_mismatch) |ftm| {
|
||||
const start = if (ftm > 5) ftm - 5 else 0;
|
||||
const end = @min(ftm + 10, min_len);
|
||||
const start = if (ftm > 15) ftm - 15 else 0;
|
||||
const end = @min(ftm + 30, min_len);
|
||||
std.debug.print(" first tag mismatch at inst[{d}]:\n", .{ftm});
|
||||
for (start..end) |i| {
|
||||
const ref_tag: u8 = @intFromEnum(ref_tags[i]);
|
||||
@@ -640,44 +648,85 @@ fn zirMatches(gpa: Allocator, ref: Zir, got: c.Zir) bool {
|
||||
std.debug.print(" {c} [{d}] ref_tag={d} got_tag={d}\n", .{ marker, i, ref_tag, got_tag });
|
||||
}
|
||||
}
|
||||
// Tag histogram: count each tag in ref vs got and show diffs.
|
||||
var ref_hist: [256]i32 = undefined;
|
||||
var got_hist: [256]i32 = undefined;
|
||||
for (&ref_hist) |*h| h.* = 0;
|
||||
for (&got_hist) |*h| h.* = 0;
|
||||
for (0..ref_len) |j| {
|
||||
ref_hist[@intFromEnum(ref_tags[j])] += 1;
|
||||
}
|
||||
for (0..got.inst_len) |j| {
|
||||
got_hist[@as(u8, @intCast(got.inst_tags[j]))] += 1;
|
||||
}
|
||||
std.debug.print(" tag histogram diff (ref-got):\n", .{});
|
||||
for (0..256) |t| {
|
||||
const diff = ref_hist[t] - got_hist[t];
|
||||
if (diff != 0) {
|
||||
std.debug.print(" tag {d}: ref={d} got={d} diff={d}\n", .{ t, ref_hist[t], got_hist[t], diff });
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
for (0..min_len) |i| {
|
||||
if (!dataMatches(ref_tags[i], ref_datas[i], got.inst_datas[i])) {
|
||||
std.debug.print(" inst_datas[{d}] mismatch (tag={d})\n", .{ i, @as(u8, @intFromEnum(ref_tags[i])) });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Skip inst_datas comparison for now (extra indices shift).
|
||||
// Go straight to extra/string_bytes.
|
||||
if (ref_len != got.inst_len) return false;
|
||||
|
||||
const ref_extra_len: u32 = @intCast(ref.extra.len);
|
||||
if (ref_extra_len != got.extra_len) {
|
||||
std.debug.print(" extra_len: ref={d} got={d}\n", .{ ref_extra_len, got.extra_len });
|
||||
return false;
|
||||
}
|
||||
|
||||
const skip = buildHashSkipMask(gpa, ref) catch return false;
|
||||
defer gpa.free(skip);
|
||||
|
||||
for (0..ref_extra_len) |i| {
|
||||
if (skip[i]) continue;
|
||||
if (ref.extra[i] != got.extra[i]) {
|
||||
std.debug.print(" extra[{d}]: ref=0x{x:0>8} got=0x{x:0>8}\n", .{ i, ref.extra[i], got.extra[i] });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const ref_sb_len: u32 = @intCast(ref.string_bytes.len);
|
||||
if (ref_sb_len != got.string_bytes_len) {
|
||||
std.debug.print(" string_bytes_len: ref={d} got={d}\n", .{ ref_sb_len, got.string_bytes_len });
|
||||
return false;
|
||||
}
|
||||
for (0..ref_sb_len) |i| {
|
||||
// Compare string_bytes first (smaller diff).
|
||||
const ref_sb_len2: u32 = @intCast(ref.string_bytes.len);
|
||||
const sb_min = @min(ref_sb_len2, got.string_bytes_len);
|
||||
for (0..sb_min) |i| {
|
||||
if (ref.string_bytes[i] != got.string_bytes[i]) {
|
||||
std.debug.print(" string_bytes[{d}]: ref=0x{x:0>2} got=0x{x:0>2}\n", .{ i, ref.string_bytes[i], got.string_bytes[i] });
|
||||
// Print surrounding context.
|
||||
const ctx_start = if (i > 30) i - 30 else 0;
|
||||
std.debug.print(" string_bytes[{d}] first diff (ref=0x{x:0>2} got=0x{x:0>2})\n", .{ i, ref.string_bytes[i], got.string_bytes[i] });
|
||||
std.debug.print(" ref context: \"", .{});
|
||||
for (ctx_start..@min(i + 30, sb_min)) |j| {
|
||||
const ch = ref.string_bytes[j];
|
||||
if (ch >= 0x20 and ch < 0x7f) {
|
||||
std.debug.print("{c}", .{ch});
|
||||
} else {
|
||||
std.debug.print("\\x{x:0>2}", .{ch});
|
||||
}
|
||||
}
|
||||
std.debug.print("\"\n", .{});
|
||||
std.debug.print(" got context: \"", .{});
|
||||
for (ctx_start..@min(i + 30, sb_min)) |j| {
|
||||
const ch = got.string_bytes[j];
|
||||
if (ch >= 0x20 and ch < 0x7f) {
|
||||
std.debug.print("{c}", .{ch});
|
||||
} else {
|
||||
std.debug.print("\\x{x:0>2}", .{ch});
|
||||
}
|
||||
}
|
||||
std.debug.print("\"\n", .{});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (ref_sb_len2 != got.string_bytes_len) {
|
||||
std.debug.print(" string_bytes_len mismatch: ref={d} got={d} (content matched up to {d})\n", .{ ref_sb_len2, got.string_bytes_len, sb_min });
|
||||
// Print what ref has at the end.
|
||||
if (ref_sb_len2 > got.string_bytes_len) {
|
||||
const extra_start = got.string_bytes_len;
|
||||
std.debug.print(" ref extra at [{d}]: \"", .{extra_start});
|
||||
for (extra_start..@min(extra_start + 60, ref_sb_len2)) |j| {
|
||||
const ch = ref.string_bytes[j];
|
||||
if (ch >= 0x20 and ch < 0x7f) {
|
||||
std.debug.print("{c}", .{ch});
|
||||
} else {
|
||||
std.debug.print("\\x{x:0>2}", .{ch});
|
||||
}
|
||||
}
|
||||
std.debug.print("\"\n", .{});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const ref_extra_len2: u32 = @intCast(ref.extra.len);
|
||||
if (ref_extra_len2 != got.extra_len) {
|
||||
std.debug.print(" extra_len mismatch: ref={d} got={d}\n", .{ ref_extra_len2, got.extra_len });
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -803,7 +852,11 @@ test "astgen: corpus" {
|
||||
if (true) return error.SkipZigTest;
|
||||
const gpa = std.testing.allocator;
|
||||
|
||||
var any_fail = false;
|
||||
inline for (corpus_files) |entry| {
|
||||
try corpusCheck(gpa, entry[0], entry[1]);
|
||||
corpusCheck(gpa, entry[0], entry[1]) catch {
|
||||
any_fail = true;
|
||||
};
|
||||
}
|
||||
if (any_fail) return error.ZirMismatch;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user