AstGen: fix src loc for invalid coercion in breaks

This commit is contained in:
Jacob Young 2023-08-11 23:54:54 -04:00
parent 2b5bd56a67
commit ce7acf1296
3 changed files with 106 additions and 92 deletions

View File

@ -2373,8 +2373,8 @@ fn labeledBlockExpr(
try astgen.appendErrorTok(label_token, "unused block label", .{}); try astgen.appendErrorTok(label_token, "unused block label", .{});
} }
const zir_datas = gz.astgen.instructions.items(.data); const zir_datas = astgen.instructions.items(.data);
const zir_tags = gz.astgen.instructions.items(.tag); const zir_tags = astgen.instructions.items(.tag);
const strat = ri.rl.strategy(&block_scope); const strat = ri.rl.strategy(&block_scope);
switch (strat.tag) { switch (strat.tag) {
.break_void => { .break_void => {
@ -2396,6 +2396,10 @@ fn labeledBlockExpr(
// it as the break operand. // it as the break operand.
// This corresponds to similar code in `setCondBrPayloadElideBlockStorePtr`. // This corresponds to similar code in `setCondBrPayloadElideBlockStorePtr`.
if (block_scope.rl_ty_inst != .none) { if (block_scope.rl_ty_inst != .none) {
try astgen.extra.ensureUnusedCapacity(
astgen.gpa,
@typeInfo(Zir.Inst.As).Struct.fields.len * block_scope.labeled_breaks.items.len,
);
for (block_scope.labeled_breaks.items) |br| { for (block_scope.labeled_breaks.items) |br| {
// We expect the `store_to_block_ptr` to be created between 1-3 instructions // We expect the `store_to_block_ptr` to be created between 1-3 instructions
// prior to the break. // prior to the break.
@ -2404,12 +2408,28 @@ fn labeledBlockExpr(
if (zir_tags[search_index] == .store_to_block_ptr and if (zir_tags[search_index] == .store_to_block_ptr and
zir_datas[search_index].bin.lhs == block_scope.rl_ptr) zir_datas[search_index].bin.lhs == block_scope.rl_ptr)
{ {
const break_data = &zir_datas[br.br].@"break";
const break_src: i32 = @bitCast(astgen.extra.items[
break_data.payload_index +
std.meta.fieldIndex(Zir.Inst.Break, "operand_src_node").?
]);
if (break_src == Zir.Inst.Break.no_src_node) {
zir_tags[search_index] = .as; zir_tags[search_index] = .as;
zir_datas[search_index].bin = .{ zir_datas[search_index].bin = .{
.lhs = block_scope.rl_ty_inst, .lhs = block_scope.rl_ty_inst,
.rhs = zir_datas[br.br].@"break".operand, .rhs = break_data.operand,
}; };
zir_datas[br.br].@"break".operand = indexToRef(search_index); } else {
zir_tags[search_index] = .as_node;
zir_datas[search_index] = .{ .pl_node = .{
.src_node = break_src,
.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.As{
.dest_type = block_scope.rl_ty_inst,
.operand = break_data.operand,
}),
} };
}
break_data.operand = indexToRef(search_index);
break; break;
} }
} else unreachable; } else unreachable;
@ -2530,19 +2550,21 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
// For some instructions, modify the zir data // For some instructions, modify the zir data
// so we can avoid a separate ensure_result_used instruction. // so we can avoid a separate ensure_result_used instruction.
.call, .field_call => { .call, .field_call => {
const extra_index = gz.astgen.instructions.items(.data)[inst].pl_node.payload_index; const break_extra = gz.astgen.instructions.items(.data)[inst].pl_node.payload_index;
const slot = &gz.astgen.extra.items[extra_index]; comptime assert(std.meta.fieldIndex(Zir.Inst.Call, "flags") ==
var flags = @as(Zir.Inst.Call.Flags, @bitCast(slot.*)); std.meta.fieldIndex(Zir.Inst.FieldCall, "flags"));
const flags: *Zir.Inst.Call.Flags = @ptrCast(&gz.astgen.extra.items[
break_extra + std.meta.fieldIndex(Zir.Inst.Call, "flags").?
]);
flags.ensure_result_used = true; flags.ensure_result_used = true;
slot.* = @as(u32, @bitCast(flags));
break :b true; break :b true;
}, },
.builtin_call => { .builtin_call => {
const extra_index = gz.astgen.instructions.items(.data)[inst].pl_node.payload_index; const break_extra = gz.astgen.instructions.items(.data)[inst].pl_node.payload_index;
const slot = &gz.astgen.extra.items[extra_index]; const flags: *Zir.Inst.BuiltinCall.Flags = @ptrCast(&gz.astgen.extra.items[
var flags = @as(Zir.Inst.BuiltinCall.Flags, @bitCast(slot.*)); break_extra + std.meta.fieldIndex(Zir.Inst.BuiltinCall, "flags").?
]);
flags.ensure_result_used = true; flags.ensure_result_used = true;
slot.* = @as(u32, @bitCast(flags));
break :b true; break :b true;
}, },
@ -6106,14 +6128,12 @@ fn setCondBrPayloadElideBlockStorePtr(
const zir_tags = astgen.instructions.items(.tag); const zir_tags = astgen.instructions.items(.tag);
const zir_datas = astgen.instructions.items(.data); const zir_datas = astgen.instructions.items(.data);
const condbr_pl = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{ const condbr_extra = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{
.condition = cond, .condition = cond,
.then_body_len = then_body_len, .then_body_len = then_body_len,
.else_body_len = else_body_len, .else_body_len = else_body_len,
}); });
zir_datas[condbr].pl_node.payload_index = condbr_pl; zir_datas[condbr].pl_node.payload_index = condbr_extra;
const then_body_len_index = condbr_pl + 1;
const else_body_len_index = condbr_pl + 2;
// The break instructions need to have their operands coerced if the // The break instructions need to have their operands coerced if the
// switch's result location is a `ty`. In this case we overwrite the // switch's result location is a `ty`. In this case we overwrite the
@ -6128,7 +6148,9 @@ fn setCondBrPayloadElideBlockStorePtr(
if (then_scope.rl_ty_inst != .none and has_then_break) { if (then_scope.rl_ty_inst != .none and has_then_break) {
then_as_inst = src_inst; then_as_inst = src_inst;
} else { } else {
astgen.extra.items[then_body_len_index] -= 1; astgen.extra.items[
condbr_extra + std.meta.fieldIndex(Zir.Inst.CondBr, "then_body_len").?
] -= 1;
continue; continue;
} }
} }
@ -6144,7 +6166,9 @@ fn setCondBrPayloadElideBlockStorePtr(
if (else_scope.rl_ty_inst != .none and has_else_break) { if (else_scope.rl_ty_inst != .none and has_else_break) {
else_as_inst = src_inst; else_as_inst = src_inst;
} else { } else {
astgen.extra.items[else_body_len_index] -= 1; astgen.extra.items[
condbr_extra + std.meta.fieldIndex(Zir.Inst.CondBr, "else_body_len").?
] -= 1;
continue; continue;
} }
} }
@ -7247,11 +7271,11 @@ fn switchExpr(
assert(!strat.elide_store_to_block_ptr_instructions); assert(!strat.elide_store_to_block_ptr_instructions);
const last_inst = payloads.items[end_index - 1]; const last_inst = payloads.items[end_index - 1];
if (zir_tags[last_inst] == .@"break") { if (zir_tags[last_inst] == .@"break") {
const inst_data = zir_datas[last_inst].@"break"; const break_data = &zir_datas[last_inst].@"break";
const block_inst = astgen.extra.items[inst_data.payload_index]; const block_inst = astgen.extra.items[
if (block_inst == switch_block) { break_data.payload_index + std.meta.fieldIndex(Zir.Inst.Break, "block_inst").?
zir_datas[last_inst].@"break".operand = .void_value; ];
} if (block_inst == switch_block) break_data.operand = .void_value;
} }
}, },
} }
@ -11648,40 +11672,47 @@ const GenZir = struct {
if (align_body.len != 0) { if (align_body.len != 0) {
astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, align_body)); astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, align_body));
astgen.appendBodyWithFixups(align_body); astgen.appendBodyWithFixups(align_body);
const inst_data = zir_datas[align_body[align_body.len - 1]].@"break"; const break_extra = zir_datas[align_body[align_body.len - 1]].@"break".payload_index;
astgen.extra.items[inst_data.payload_index] = new_index; astgen.extra.items[break_extra + std.meta.fieldIndex(Zir.Inst.Break, "block_inst").?] =
new_index;
} else if (args.align_ref != .none) { } else if (args.align_ref != .none) {
astgen.extra.appendAssumeCapacity(@intFromEnum(args.align_ref)); astgen.extra.appendAssumeCapacity(@intFromEnum(args.align_ref));
} }
if (addrspace_body.len != 0) { if (addrspace_body.len != 0) {
astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, addrspace_body)); astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, addrspace_body));
astgen.appendBodyWithFixups(addrspace_body); astgen.appendBodyWithFixups(addrspace_body);
const inst_data = zir_datas[addrspace_body[addrspace_body.len - 1]].@"break"; const break_extra =
astgen.extra.items[inst_data.payload_index] = new_index; zir_datas[addrspace_body[addrspace_body.len - 1]].@"break".payload_index;
astgen.extra.items[break_extra + std.meta.fieldIndex(Zir.Inst.Break, "block_inst").?] =
new_index;
} else if (args.addrspace_ref != .none) { } else if (args.addrspace_ref != .none) {
astgen.extra.appendAssumeCapacity(@intFromEnum(args.addrspace_ref)); astgen.extra.appendAssumeCapacity(@intFromEnum(args.addrspace_ref));
} }
if (section_body.len != 0) { if (section_body.len != 0) {
astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, section_body)); astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, section_body));
astgen.appendBodyWithFixups(section_body); astgen.appendBodyWithFixups(section_body);
const inst_data = zir_datas[section_body[section_body.len - 1]].@"break"; const break_extra =
astgen.extra.items[inst_data.payload_index] = new_index; zir_datas[section_body[section_body.len - 1]].@"break".payload_index;
astgen.extra.items[break_extra + std.meta.fieldIndex(Zir.Inst.Break, "block_inst").?] =
new_index;
} else if (args.section_ref != .none) { } else if (args.section_ref != .none) {
astgen.extra.appendAssumeCapacity(@intFromEnum(args.section_ref)); astgen.extra.appendAssumeCapacity(@intFromEnum(args.section_ref));
} }
if (cc_body.len != 0) { if (cc_body.len != 0) {
astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, cc_body)); astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, cc_body));
astgen.appendBodyWithFixups(cc_body); astgen.appendBodyWithFixups(cc_body);
const inst_data = zir_datas[cc_body[cc_body.len - 1]].@"break"; const break_extra = zir_datas[cc_body[cc_body.len - 1]].@"break".payload_index;
astgen.extra.items[inst_data.payload_index] = new_index; astgen.extra.items[break_extra + std.meta.fieldIndex(Zir.Inst.Break, "block_inst").?] =
new_index;
} else if (args.cc_ref != .none) { } else if (args.cc_ref != .none) {
astgen.extra.appendAssumeCapacity(@intFromEnum(args.cc_ref)); astgen.extra.appendAssumeCapacity(@intFromEnum(args.cc_ref));
} }
if (ret_body.len != 0) { if (ret_body.len != 0) {
astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, ret_body)); astgen.extra.appendAssumeCapacity(countBodyLenAfterFixups(astgen, ret_body));
astgen.appendBodyWithFixups(ret_body); astgen.appendBodyWithFixups(ret_body);
const inst_data = zir_datas[ret_body[ret_body.len - 1]].@"break"; const break_extra = zir_datas[ret_body[ret_body.len - 1]].@"break".payload_index;
astgen.extra.items[inst_data.payload_index] = new_index; astgen.extra.items[break_extra + std.meta.fieldIndex(Zir.Inst.Break, "block_inst").?] =
new_index;
} else if (ret_ref != .none) { } else if (ret_ref != .none) {
astgen.extra.appendAssumeCapacity(@intFromEnum(ret_ref)); astgen.extra.appendAssumeCapacity(@intFromEnum(ret_ref));
} }
@ -11736,8 +11767,9 @@ const GenZir = struct {
if (ret_body.len != 0) { if (ret_body.len != 0) {
astgen.appendBodyWithFixups(ret_body); astgen.appendBodyWithFixups(ret_body);
const inst_data = zir_datas[ret_body[ret_body.len - 1]].@"break"; const break_extra = zir_datas[ret_body[ret_body.len - 1]].@"break".payload_index;
astgen.extra.items[inst_data.payload_index] = new_index; astgen.extra.items[break_extra + std.meta.fieldIndex(Zir.Inst.Break, "block_inst").?] =
new_index;
} else if (ret_ref != .none) { } else if (ret_ref != .none) {
astgen.extra.appendAssumeCapacity(@intFromEnum(ret_ref)); astgen.extra.appendAssumeCapacity(@intFromEnum(ret_ref));
} }
@ -12191,21 +12223,8 @@ const GenZir = struct {
) !Zir.Inst.Index { ) !Zir.Inst.Index {
const gpa = gz.astgen.gpa; const gpa = gz.astgen.gpa;
try gz.instructions.ensureUnusedCapacity(gpa, 1); try gz.instructions.ensureUnusedCapacity(gpa, 1);
try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
const extra: Zir.Inst.Break = .{ const new_index = try gz.makeBreak(tag, block_inst, operand);
.block_inst = block_inst,
.operand_src_node = Zir.Inst.Break.no_src_node,
};
const payload_index = try gz.astgen.addExtra(extra);
const new_index = @as(Zir.Inst.Index, @intCast(gz.astgen.instructions.len));
gz.astgen.instructions.appendAssumeCapacity(.{
.tag = tag,
.data = .{ .@"break" = .{
.operand = operand,
.payload_index = payload_index,
} },
});
gz.instructions.appendAssumeCapacity(new_index); gz.instructions.appendAssumeCapacity(new_index);
return new_index; return new_index;
} }
@ -12216,23 +12235,7 @@ const GenZir = struct {
block_inst: Zir.Inst.Index, block_inst: Zir.Inst.Index,
operand: Zir.Inst.Ref, operand: Zir.Inst.Ref,
) !Zir.Inst.Index { ) !Zir.Inst.Index {
const gpa = gz.astgen.gpa; return gz.makeBreakCommon(tag, block_inst, operand, null);
try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
const extra: Zir.Inst.Break = .{
.block_inst = block_inst,
.operand_src_node = Zir.Inst.Break.no_src_node,
};
const payload_index = try gz.astgen.addExtra(extra);
const new_index = @as(Zir.Inst.Index, @intCast(gz.astgen.instructions.len));
gz.astgen.instructions.appendAssumeCapacity(.{
.tag = tag,
.data = .{ .@"break" = .{
.operand = operand,
.payload_index = payload_index,
} },
});
return new_index;
} }
fn addBreakWithSrcNode( fn addBreakWithSrcNode(
@ -12244,21 +12247,8 @@ const GenZir = struct {
) !Zir.Inst.Index { ) !Zir.Inst.Index {
const gpa = gz.astgen.gpa; const gpa = gz.astgen.gpa;
try gz.instructions.ensureUnusedCapacity(gpa, 1); try gz.instructions.ensureUnusedCapacity(gpa, 1);
try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
const extra: Zir.Inst.Break = .{ const new_index = try gz.makeBreakWithSrcNode(tag, block_inst, operand, operand_src_node);
.block_inst = block_inst,
.operand_src_node = gz.nodeIndexToRelative(operand_src_node),
};
const payload_index = try gz.astgen.addExtra(extra);
const new_index = @as(Zir.Inst.Index, @intCast(gz.astgen.instructions.len));
gz.astgen.instructions.appendAssumeCapacity(.{
.tag = tag,
.data = .{ .@"break" = .{
.operand = operand,
.payload_index = payload_index,
} },
});
gz.instructions.appendAssumeCapacity(new_index); gz.instructions.appendAssumeCapacity(new_index);
return new_index; return new_index;
} }
@ -12269,21 +12259,33 @@ const GenZir = struct {
block_inst: Zir.Inst.Index, block_inst: Zir.Inst.Index,
operand: Zir.Inst.Ref, operand: Zir.Inst.Ref,
operand_src_node: Ast.Node.Index, operand_src_node: Ast.Node.Index,
) !Zir.Inst.Index {
return gz.makeBreakCommon(tag, block_inst, operand, operand_src_node);
}
fn makeBreakCommon(
gz: *GenZir,
tag: Zir.Inst.Tag,
block_inst: Zir.Inst.Index,
operand: Zir.Inst.Ref,
operand_src_node: ?Ast.Node.Index,
) !Zir.Inst.Index { ) !Zir.Inst.Index {
const gpa = gz.astgen.gpa; const gpa = gz.astgen.gpa;
try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1); try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Break).Struct.fields.len);
const extra: Zir.Inst.Break = .{ const new_index: Zir.Inst.Index = @intCast(gz.astgen.instructions.len);
.block_inst = block_inst,
.operand_src_node = gz.nodeIndexToRelative(operand_src_node),
};
const payload_index = try gz.astgen.addExtra(extra);
const new_index = @as(Zir.Inst.Index, @intCast(gz.astgen.instructions.len));
gz.astgen.instructions.appendAssumeCapacity(.{ gz.astgen.instructions.appendAssumeCapacity(.{
.tag = tag, .tag = tag,
.data = .{ .@"break" = .{ .data = .{ .@"break" = .{
.operand = operand, .operand = operand,
.payload_index = payload_index, .payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Break{
.operand_src_node = if (operand_src_node) |src_node|
gz.nodeIndexToRelative(src_node)
else
Zir.Inst.Break.no_src_node,
.block_inst = block_inst,
}),
} }, } },
}); });
return new_index; return new_index;

View File

@ -2347,8 +2347,8 @@ pub const Inst = struct {
pub const Break = struct { pub const Break = struct {
pub const no_src_node = std.math.maxInt(i32); pub const no_src_node = std.math.maxInt(i32);
block_inst: Index,
operand_src_node: i32, operand_src_node: i32,
block_inst: Index,
}; };
/// Trailing: /// Trailing:

View File

@ -0,0 +1,12 @@
export fn invalidBreak() u8 {
const result: u8 = label: {
break :label 256;
};
return result;
}
// error
// backend=stage2
// target=native
//
// :3:22: error: type 'u8' cannot represent integer value '256'