feat: error reporting for global reference usage
This commit is contained in:
parent
47351cd6f9
commit
be297047d1
8 changed files with 401 additions and 371 deletions
218
src/AstGen.zig
218
src/AstGen.zig
|
|
@ -392,30 +392,50 @@ const GenIr = struct {
|
|||
});
|
||||
}
|
||||
|
||||
fn addPayloadNode(gi: *GenIr, tag: Ir.Inst.Tag, extra: anytype) !Ir.Inst.Ref {
|
||||
const gpa = gi.astgen.gpa;
|
||||
try gi.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
try gi.astgen.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
fn addPayloadNode(
|
||||
gen: *GenIr,
|
||||
tag: Ir.Inst.Tag,
|
||||
node: *const Ast.Node,
|
||||
extra: anytype,
|
||||
) !Ir.Inst.Ref {
|
||||
const gpa = gen.astgen.gpa;
|
||||
try gen.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
try gen.astgen.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
|
||||
const payload_index = try gi.astgen.addExtra(extra);
|
||||
const new_index: Ir.Inst.Index = @enumFromInt(gi.astgen.instructions.items.len);
|
||||
gi.astgen.instructions.appendAssumeCapacity(.{
|
||||
const extra_index = try gen.astgen.addExtra(extra);
|
||||
const new_index: Ir.Inst.Index = @enumFromInt(gen.astgen.instructions.items.len);
|
||||
gen.astgen.instructions.appendAssumeCapacity(.{
|
||||
.tag = tag,
|
||||
.data = .{ .payload = .{
|
||||
.payload_index = payload_index,
|
||||
.extra_index = extra_index,
|
||||
.src_offset = @intCast(node.loc.start),
|
||||
} },
|
||||
});
|
||||
gi.instructions.appendAssumeCapacity(new_index);
|
||||
gen.instructions.appendAssumeCapacity(new_index);
|
||||
return new_index.toRef();
|
||||
}
|
||||
|
||||
fn addPayloadNodeWithIndex(
|
||||
gen: *GenIr,
|
||||
tag: Ir.Inst.Tag,
|
||||
node: *const Ast.Node,
|
||||
extra_index: u32,
|
||||
) !Ir.Inst.Ref {
|
||||
return gen.add(.{ .tag = tag, .data = .{
|
||||
.payload = .{
|
||||
.extra_index = extra_index,
|
||||
.src_offset = @intCast(node.loc.start),
|
||||
},
|
||||
} });
|
||||
}
|
||||
|
||||
fn makeBlockInst(gi: *GenIr, tag: Ir.Inst.Tag) !Ir.Inst.Index {
|
||||
const inst_index: Ir.Inst.Index = @enumFromInt(gi.astgen.instructions.items.len);
|
||||
const gpa = gi.astgen.gpa;
|
||||
try gi.astgen.instructions.append(gpa, .{
|
||||
.tag = tag,
|
||||
.data = .{
|
||||
.payload = .{ .payload_index = undefined },
|
||||
.payload = undefined,
|
||||
},
|
||||
});
|
||||
return inst_index;
|
||||
|
|
@ -431,11 +451,11 @@ const GenIr = struct {
|
|||
try self.astgen.instructions.append(gpa, .{
|
||||
.tag = .decl_knot,
|
||||
.data = .{
|
||||
.payload = .{ .payload_index = undefined },
|
||||
.payload = undefined,
|
||||
},
|
||||
});
|
||||
const inst_data = &self.astgen.instructions.items[@intFromEnum(new_index)].data;
|
||||
inst_data.payload.payload_index = self.astgen.addExtraAssumeCapacity(
|
||||
inst_data.payload.extra_index = self.astgen.addExtraAssumeCapacity(
|
||||
Ir.Inst.Knot{ .body_len = @intCast(body.len) },
|
||||
);
|
||||
|
||||
|
|
@ -443,75 +463,50 @@ const GenIr = struct {
|
|||
return new_index;
|
||||
}
|
||||
|
||||
fn addVar(self: *GenIr) !Ir.Inst.Index {
|
||||
const gpa = self.astgen.gpa;
|
||||
const new_index: Ir.Inst.Index = @enumFromInt(self.astgen.instructions.items.len);
|
||||
const body = self.instructionsSlice();
|
||||
fn addVar(gen: *GenIr, node: *const Ast.Node) !Ir.Inst.Index {
|
||||
const gpa = gen.astgen.gpa;
|
||||
const body = gen.instructionsSlice();
|
||||
const extra_len = @typeInfo(Ir.Inst.Var).@"struct".fields.len + body.len;
|
||||
try self.astgen.extra.ensureUnusedCapacity(gpa, extra_len);
|
||||
try self.astgen.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
try self.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
try gen.astgen.extra.ensureUnusedCapacity(gpa, extra_len);
|
||||
try gen.astgen.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
|
||||
self.astgen.instructions.appendAssumeCapacity(.{ .tag = .decl_var, .data = .{
|
||||
.payload = .{ .payload_index = self.astgen.addExtraAssumeCapacity(
|
||||
Ir.Inst.Var{ .body_len = @intCast(body.len) },
|
||||
) },
|
||||
} });
|
||||
|
||||
self.astgen.appendBlockBody(body);
|
||||
self.instructions.appendAssumeCapacity(new_index);
|
||||
return new_index;
|
||||
const extra_index = gen.astgen.addExtraAssumeCapacity(Ir.Inst.Var{
|
||||
.body_len = @intCast(body.len),
|
||||
});
|
||||
const new_index = try gen.addPayloadNodeWithIndex(.decl_var, node, extra_index);
|
||||
gen.astgen.appendBlockBody(body);
|
||||
gen.instructions.appendAssumeCapacity(new_index.toIndex().?);
|
||||
return new_index.toIndex().?;
|
||||
}
|
||||
|
||||
fn addCondBr(self: *GenIr, tag: Ir.Inst.Tag) !Ir.Inst.Index {
|
||||
const gpa = self.astgen.gpa;
|
||||
try self.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
try self.astgen.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
fn addCondBr(gen: *GenIr, tag: Ir.Inst.Tag) !Ir.Inst.Index {
|
||||
const gpa = gen.astgen.gpa;
|
||||
try gen.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
try gen.astgen.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
|
||||
const new_index: Ir.Inst.Index = @enumFromInt(self.astgen.instructions.items.len);
|
||||
self.astgen.instructions.appendAssumeCapacity(.{
|
||||
const new_index: Ir.Inst.Index = @enumFromInt(gen.astgen.instructions.items.len);
|
||||
gen.astgen.instructions.appendAssumeCapacity(.{
|
||||
.tag = tag,
|
||||
.data = .{ .payload = .{
|
||||
.payload_index = undefined,
|
||||
} },
|
||||
.data = .{ .payload = undefined },
|
||||
});
|
||||
self.instructions.appendAssumeCapacity(new_index);
|
||||
gen.instructions.appendAssumeCapacity(new_index);
|
||||
return new_index;
|
||||
}
|
||||
|
||||
fn addBreak(
|
||||
self: *GenIr,
|
||||
gen: *GenIr,
|
||||
tag: Ir.Inst.Tag,
|
||||
node: *const Ast.Node,
|
||||
block_inst: Ir.Inst.Index,
|
||||
) !Ir.Inst.Index {
|
||||
const gpa = self.astgen.gpa;
|
||||
try self.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
|
||||
const new_index = try self.makeBreak(tag, block_inst);
|
||||
self.instructions.appendAssumeCapacity(new_index);
|
||||
return new_index;
|
||||
}
|
||||
|
||||
fn makeBreak(
|
||||
self: *GenIr,
|
||||
tag: Ir.Inst.Tag,
|
||||
block_inst: Ir.Inst.Index,
|
||||
) !Ir.Inst.Index {
|
||||
const gpa = self.astgen.gpa;
|
||||
) !Ir.Inst.Ref {
|
||||
const gpa = gen.astgen.gpa;
|
||||
const extra_len = @typeInfo(Ir.Inst.Break).@"struct".fields.len;
|
||||
try self.astgen.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
try self.astgen.extra.ensureUnusedCapacity(gpa, extra_len);
|
||||
try gen.astgen.extra.ensureUnusedCapacity(gpa, extra_len);
|
||||
|
||||
const new_index: Ir.Inst.Index = @enumFromInt(self.astgen.instructions.items.len);
|
||||
self.astgen.instructions.appendAssumeCapacity(.{
|
||||
.tag = tag,
|
||||
.data = .{ .payload = .{
|
||||
.payload_index = self.astgen.addExtraAssumeCapacity(
|
||||
Ir.Inst.Break{ .block_inst = block_inst },
|
||||
),
|
||||
} },
|
||||
});
|
||||
return new_index;
|
||||
const extra_index = gen.astgen.addExtraAssumeCapacity(
|
||||
Ir.Inst.Break{ .block_inst = block_inst },
|
||||
);
|
||||
return gen.addPayloadNodeWithIndex(tag, node, extra_index);
|
||||
}
|
||||
|
||||
fn setBlockBody(self: *GenIr, inst: Ir.Inst.Index) !void {
|
||||
|
|
@ -521,7 +516,7 @@ const GenIr = struct {
|
|||
try self.astgen.extra.ensureUnusedCapacity(gpa, extra_len);
|
||||
|
||||
const inst_data = &self.astgen.instructions.items[@intFromEnum(inst)].data;
|
||||
inst_data.payload.payload_index = self.astgen.addExtraAssumeCapacity(
|
||||
inst_data.payload.extra_index = self.astgen.addExtraAssumeCapacity(
|
||||
Ir.Inst.Block{ .body_len = @intCast(body.len) },
|
||||
);
|
||||
self.astgen.appendBlockBody(body);
|
||||
|
|
@ -599,7 +594,7 @@ fn setDeclaration(
|
|||
}
|
||||
|
||||
const inst_data = &astgen.instructions.items[@intFromEnum(decl_index)].data;
|
||||
inst_data.payload.payload_index = astgen.addExtraAssumeCapacity(
|
||||
inst_data.payload.extra_index = astgen.addExtraAssumeCapacity(
|
||||
Ir.Inst.Declaration{ .name = args.name, .value = args.ref },
|
||||
);
|
||||
|
||||
|
|
@ -630,7 +625,7 @@ fn setCondBrPayload(
|
|||
try astgen.extra.ensureUnusedCapacity(astgen.gpa, extra_len);
|
||||
|
||||
const inst_data = &astgen.instructions.items[@intFromEnum(condbr)].data;
|
||||
inst_data.payload.payload_index = astgen.addExtraAssumeCapacity(
|
||||
inst_data.payload.extra_index = astgen.addExtraAssumeCapacity(
|
||||
Ir.Inst.CondBr{
|
||||
.condition = cond,
|
||||
.then_body_len = @intCast(then_body_len),
|
||||
|
|
@ -856,13 +851,13 @@ fn ifStmt(
|
|||
defer then_block.unstack();
|
||||
|
||||
try blockStmt(&then_block, scope, then_node);
|
||||
_ = try then_block.addBreak(.@"break", block);
|
||||
_ = try then_block.addBreak(.@"break", then_node, block);
|
||||
|
||||
var else_block = parent_block.makeSubBlock();
|
||||
defer else_block.unstack();
|
||||
|
||||
if (then_node == last_prong) {
|
||||
_ = try else_block.addBreak(.@"break", block);
|
||||
_ = try else_block.addBreak(.@"break", then_node, block);
|
||||
} else {
|
||||
const block_node = last_prong.data.bin.rhs.?;
|
||||
try blockStmt(&else_block, scope, block_node);
|
||||
|
|
@ -900,13 +895,13 @@ fn ifChain(
|
|||
var then_block = parent_block.makeSubBlock();
|
||||
defer then_block.unstack();
|
||||
try blockStmt(&then_block, scope, body_node);
|
||||
_ = try then_block.addBreak(.@"break", block_inst);
|
||||
_ = try then_block.addBreak(.@"break", body_node, block_inst);
|
||||
|
||||
var else_block = parent_block.makeSubBlock();
|
||||
defer else_block.unstack();
|
||||
const next_branches = branch_list[1..];
|
||||
_ = try ifChain(parent_block, scope, next_branches);
|
||||
_ = try else_block.addBreak(.@"break", block_inst);
|
||||
_ = try else_block.addBreak(.@"break", body_node, block_inst);
|
||||
try setCondBrPayload(condbr, cond_inst, &then_block, &else_block);
|
||||
return @enumFromInt(0);
|
||||
}
|
||||
|
|
@ -960,7 +955,7 @@ fn switchStmt(
|
|||
var case_block = parent_block.makeSubBlock();
|
||||
defer case_block.unstack();
|
||||
_ = try blockStmt(&case_block, scope, case_stmt.data.bin.rhs.?);
|
||||
_ = try case_block.addBreak(.@"break", switch_br);
|
||||
_ = try case_block.addBreak(.@"break", case_stmt, switch_br);
|
||||
|
||||
const body = case_block.instructionsSlice();
|
||||
const case_extra_len = @typeInfo(Ir.Inst.SwitchBr.Case).@"struct".fields.len + body.len;
|
||||
|
|
@ -982,7 +977,7 @@ fn switchStmt(
|
|||
var case_block = parent_block.makeSubBlock();
|
||||
defer case_block.unstack();
|
||||
_ = try blockStmt(&case_block, scope, else_branch.data.bin.rhs.?);
|
||||
_ = try case_block.addBreak(.@"break", switch_br);
|
||||
_ = try case_block.addBreak(.@"break", else_branch, switch_br);
|
||||
|
||||
const else_body = case_block.instructionsSlice();
|
||||
const extra_len =
|
||||
|
|
@ -990,13 +985,14 @@ fn switchStmt(
|
|||
try astgen.extra.ensureUnusedCapacity(gpa, extra_len);
|
||||
|
||||
astgen.instructions.items[@intFromEnum(switch_br)].data.payload = .{
|
||||
.payload_index = astgen.addExtraAssumeCapacity(
|
||||
.extra_index = astgen.addExtraAssumeCapacity(
|
||||
Ir.Inst.SwitchBr{
|
||||
.operand = cond_inst,
|
||||
.cases_len = @intCast(switch_cases.len),
|
||||
.else_body_len = @intCast(else_body.len),
|
||||
},
|
||||
),
|
||||
.src_offset = @intCast(stmt_node.loc.start),
|
||||
};
|
||||
astgen.extra.appendSliceAssumeCapacity(case_indexes.items[0..]);
|
||||
astgen.appendBlockBody(else_body);
|
||||
|
|
@ -1111,11 +1107,12 @@ fn choiceStmt(
|
|||
try astgen.extra.ensureUnusedCapacity(gpa, extra_len);
|
||||
|
||||
astgen.instructions.items[@intFromEnum(choice_br)].data.payload = .{
|
||||
.payload_index = astgen.addExtraAssumeCapacity(
|
||||
.extra_index = astgen.addExtraAssumeCapacity(
|
||||
Ir.Inst.ChoiceBr{
|
||||
.cases_len = @intCast(choice_branches.len),
|
||||
},
|
||||
),
|
||||
.src_offset = @intCast(stmt_node.loc.start),
|
||||
};
|
||||
astgen.extra.appendSliceAssumeCapacity(case_indexes.items[0..]);
|
||||
}
|
||||
|
|
@ -1132,12 +1129,12 @@ const Callee = union(enum) {
|
|||
fn fieldAccess(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!Ir.Inst.Ref {
|
||||
assert(node.tag == .selector_expr);
|
||||
const data = node.data.bin;
|
||||
|
||||
assert(data.rhs.?.tag == .identifier);
|
||||
const field_str = try gi.astgen.strFromNode(data.rhs.?);
|
||||
const rhs = data.rhs.?;
|
||||
assert(rhs.tag == .identifier);
|
||||
const field_str = try gi.astgen.strFromNode(rhs);
|
||||
const lhs = try expr(gi, scope, data.lhs.?);
|
||||
|
||||
return gi.addPayloadNode(.field_ptr, Ir.Inst.Field{
|
||||
return gi.addPayloadNode(.field_ptr, rhs, Ir.Inst.Field{
|
||||
.lhs = lhs,
|
||||
.field_name_start = field_str.index,
|
||||
});
|
||||
|
|
@ -1205,22 +1202,19 @@ fn callExpr(
|
|||
}
|
||||
switch (callee) {
|
||||
.direct => |callee_obj| {
|
||||
const payload_index = try addExtra(astgen, Ir.Inst.Call{
|
||||
const tag = if (call == .divert) .divert else .call;
|
||||
const extra_index = try addExtra(astgen, Ir.Inst.Call{
|
||||
.callee = callee_obj,
|
||||
.args_len = @intCast(args_count),
|
||||
});
|
||||
if (args_count != 0) {
|
||||
try astgen.extra.appendSlice(gpa, astgen.scratch.items[scratch_top..]);
|
||||
}
|
||||
return gi.add(.{
|
||||
.tag = if (call == .divert) .divert else .call,
|
||||
.data = .{ .payload = .{
|
||||
.payload_index = payload_index,
|
||||
} },
|
||||
});
|
||||
return gi.addPayloadNodeWithIndex(tag, callee_node, extra_index);
|
||||
},
|
||||
.field => |callee_field| {
|
||||
const payload_index = try addExtra(astgen, Ir.Inst.FieldCall{
|
||||
const tag = if (call == .divert) .field_divert else .field_call;
|
||||
const extra_index = try addExtra(astgen, Ir.Inst.FieldCall{
|
||||
.obj_ptr = callee_field.obj_ptr,
|
||||
.field_name_start = callee_field.field_name_start,
|
||||
.args_len = @intCast(args_count),
|
||||
|
|
@ -1228,12 +1222,7 @@ fn callExpr(
|
|||
if (args_count != 0) {
|
||||
try astgen.extra.appendSlice(gpa, astgen.scratch.items[scratch_top..]);
|
||||
}
|
||||
return gi.add(.{
|
||||
.tag = if (call == .divert) .field_divert else .field_call,
|
||||
.data = .{ .payload = .{
|
||||
.payload_index = payload_index,
|
||||
} },
|
||||
});
|
||||
return gi.addPayloadNodeWithIndex(tag, callee_node, extra_index);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -1246,29 +1235,17 @@ fn divertExpr(gi: *GenIr, scope: *Scope, node: *const Ast.Node) !void {
|
|||
const callee = try calleeExpr(gi, scope, lhs);
|
||||
switch (callee) {
|
||||
.direct => |callee_obj| {
|
||||
const payload_index = try addExtra(gi.astgen, Ir.Inst.Call{
|
||||
_ = try gi.addPayloadNode(.divert, lhs, Ir.Inst.Call{
|
||||
.callee = callee_obj,
|
||||
.args_len = @intCast(0),
|
||||
});
|
||||
_ = try gi.add(.{
|
||||
.tag = .divert,
|
||||
.data = .{ .payload = .{
|
||||
.payload_index = payload_index,
|
||||
} },
|
||||
});
|
||||
},
|
||||
.field => |callee_field| {
|
||||
const payload_index = try addExtra(gi.astgen, Ir.Inst.FieldCall{
|
||||
_ = try gi.addPayloadNode(.field_divert, lhs, Ir.Inst.FieldCall{
|
||||
.obj_ptr = callee_field.obj_ptr,
|
||||
.field_name_start = callee_field.field_name_start,
|
||||
.args_len = @intCast(0),
|
||||
});
|
||||
_ = try gi.add(.{
|
||||
.tag = .field_divert,
|
||||
.data = .{ .payload = .{
|
||||
.payload_index = payload_index,
|
||||
} },
|
||||
});
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
@ -1309,17 +1286,14 @@ fn varDecl(gi: *GenIr, scope: *Scope, decl_node: *const Ast.Node) !void {
|
|||
const expr_node = decl_node.data.bin.rhs.?;
|
||||
const decl_inst = try gi.add(.{
|
||||
.tag = .declaration,
|
||||
.data = .{ .payload = .{
|
||||
.payload_index = undefined,
|
||||
} },
|
||||
.data = .{ .payload = undefined },
|
||||
});
|
||||
|
||||
var decl_block = gi.makeSubBlock();
|
||||
defer decl_block.unstack();
|
||||
|
||||
_ = try expr(&decl_block, scope, expr_node);
|
||||
const var_inst = try decl_block.addVar();
|
||||
|
||||
const var_inst = try decl_block.addVar(decl_node);
|
||||
const name_str = try astgen.strFromNode(identifier_node);
|
||||
try setDeclaration(decl_inst.toIndex().?, .{
|
||||
.tag = .variable,
|
||||
|
|
@ -1365,9 +1339,7 @@ fn defaultBlock(
|
|||
const astgen = gi.astgen;
|
||||
const decl_inst = try gi.addAsIndex(.{
|
||||
.tag = .declaration,
|
||||
.data = .{ .payload = .{
|
||||
.payload_index = undefined,
|
||||
} },
|
||||
.data = .{ .payload = undefined },
|
||||
});
|
||||
|
||||
var decl_scope = gi.makeSubBlock();
|
||||
|
|
@ -1400,9 +1372,7 @@ fn stitchDeclInner(
|
|||
const identifier_node = prototype_data.lhs.?;
|
||||
const decl_inst = try gi.addAsIndex(.{
|
||||
.tag = .declaration,
|
||||
.data = .{ .payload = .{
|
||||
.payload_index = undefined,
|
||||
} },
|
||||
.data = .{ .payload = undefined },
|
||||
});
|
||||
|
||||
var decl_block = gi.makeSubBlock();
|
||||
|
|
@ -1440,12 +1410,12 @@ fn stitchDeclInner(
|
|||
|
||||
fn stitchDecl(gi: *GenIr, parent_scope: *Scope, decl_node: *const Ast.Node) InnerError!void {
|
||||
const knot_data = decl_node.data.bin;
|
||||
const prototype_node = knot_data.lhs.?;
|
||||
const body_node = knot_data.rhs.?;
|
||||
const prototype_node = knot_data.lhs;
|
||||
const body_node = knot_data.rhs;
|
||||
var decl_scope = parent_scope.makeChild();
|
||||
defer decl_scope.deinit();
|
||||
|
||||
return stitchDeclInner(gi, &decl_scope, decl_node, prototype_node, body_node);
|
||||
return stitchDeclInner(gi, &decl_scope, decl_node, prototype_node.?, body_node);
|
||||
}
|
||||
|
||||
fn functionDecl(_: *GenIr, _: *Scope, _: *const Ast.Node) InnerError!void {}
|
||||
|
|
@ -1484,7 +1454,7 @@ fn file(gi: *GenIr, scope: *Scope, file_node: *const Ast.Node) InnerError!void {
|
|||
const file_inst = try gi.addAsIndex(.{
|
||||
.tag = .file,
|
||||
.data = .{
|
||||
.payload = .{ .payload_index = undefined },
|
||||
.payload = undefined,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue