From 7598a00f34e91375bc8d4f57e8f5ecbc0d1b4d14 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 20 Mar 2021 22:40:08 -0700 Subject: stage2: fix memory management of ZIR code * free Module.Fn ZIR code when destroying the owner Decl * unreachable_safe and unreachable_unsafe are collapsed into one ZIR instruction with a safety flag. * astgen: emit an unreachable instruction for unreachable literals * don't forget to call deinit on ZIR code * astgen: implement some builtin functions --- src/Module.zig | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'src/Module.zig') diff --git a/src/Module.zig b/src/Module.zig index 9830e43d4a..dcf57bb709 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -224,6 +224,10 @@ pub const Decl = struct { const gpa = module.gpa; gpa.free(mem.spanZ(decl.name)); if (decl.typedValueManaged()) |tvm| { + if (tvm.typed_value.val.castTag(.function)) |payload| { + const func = payload.data; + func.deinit(gpa); + } tvm.deinit(gpa); } decl.dependants.deinit(gpa); @@ -334,7 +338,7 @@ pub const EmitH = struct { fwd_decl: std.ArrayListUnmanaged(u8) = .{}, }; -/// Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator. +/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator. /// Extern functions do not have this data structure; they are represented by /// the `Decl` only, with a `Value` tag of `extern_fn`. pub const Fn = struct { @@ -347,6 +351,7 @@ pub const Fn = struct { /// The number of parameters is determined by referring to the type. /// The first N elements of `extra` are indexes into `string_bytes` to /// a null-terminated string. + /// This memory is managed with gpa, must be freed when the function is freed. zir: zir.Code, /// undefined unless analysis state is `success`. body: ir.Body, @@ -370,6 +375,10 @@ pub const Fn = struct { pub fn dump(func: *Fn, mod: Module) void { ir.dumpFn(mod, func); } + + pub fn deinit(func: *Fn, gpa: *Allocator) void { + func.zir.deinit(gpa); + } }; pub const Var = struct { @@ -1502,8 +1511,7 @@ pub const WipZirCode = struct { .ret_node, .ret_tok, .ret_coerce, - .unreachable_unsafe, - .unreachable_safe, + .@"unreachable", .loop, .suspend_block, .suspend_block_one, @@ -1521,6 +1529,7 @@ pub const WipZirCode = struct { pub fn deinit(wzc: *WipZirCode) void { wzc.instructions.deinit(wzc.gpa); wzc.extra.deinit(wzc.gpa); + wzc.string_bytes.deinit(wzc.gpa); } }; @@ -2078,7 +2087,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { var analysis_arena = std.heap.ArenaAllocator.init(mod.gpa); defer analysis_arena.deinit(); - const code: zir.Code = blk: { + var code: zir.Code = blk: { var wip_zir_code: WipZirCode = .{ .decl = decl, .arena = &analysis_arena.allocator, @@ -2102,6 +2111,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { } break :blk code; }; + defer code.deinit(mod.gpa); var sema: Sema = .{ .mod = mod, @@ -2154,17 +2164,17 @@ fn astgenAndSemaFn( var fn_type_scope_arena = std.heap.ArenaAllocator.init(mod.gpa); defer fn_type_scope_arena.deinit(); - var fn_type_wip_zir_exec: WipZirCode = .{ + var fn_type_wip_zir_code: WipZirCode = .{ .decl = decl, .arena = &fn_type_scope_arena.allocator, .gpa = mod.gpa, }; - defer fn_type_wip_zir_exec.deinit(); + defer fn_type_wip_zir_code.deinit(); var fn_type_scope: Scope.GenZir = .{ .force_comptime = true, .parent = &decl.container.base, - .zir_code = &fn_type_wip_zir_exec, + .zir_code = &fn_type_wip_zir_code, }; defer fn_type_scope.instructions.deinit(mod.gpa); @@ -2317,7 +2327,8 @@ fn astgenAndSemaFn( errdefer decl_arena.deinit(); const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); - const fn_type_code = try fn_type_scope.finish(); + var fn_type_code = try fn_type_scope.finish(); + defer fn_type_code.deinit(mod.gpa); if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { fn_type_code.dump(mod.gpa, "fn_type", &fn_type_scope.base, 0) catch {}; } @@ -2621,7 +2632,8 @@ fn astgenAndSemaVarDecl( init_result_loc, var_decl.ast.init_node, ); - const code = try gen_scope.finish(); + var code = try gen_scope.finish(); + defer code.deinit(mod.gpa); if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { code.dump(mod.gpa, "var_init", &gen_scope.base, 0) catch {}; } @@ -2683,7 +2695,8 @@ fn astgenAndSemaVarDecl( defer type_scope.instructions.deinit(mod.gpa); const var_type = try astgen.typeExpr(mod, &type_scope.base, var_decl.ast.type_node); - const code = try type_scope.finish(); + var code = try type_scope.finish(); + defer code.deinit(mod.gpa); if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { code.dump(mod.gpa, "var_type", &type_scope.base, 0) catch {}; } -- cgit v1.2.3