diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-09-21 15:08:32 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-09-21 15:23:29 -0700 |
| commit | 5913140b6bf96e168a0167906a78e2d4aac5bd9d (patch) | |
| tree | 95eba3e1ac8628e4fbba4ea8a1c222cd04555771 /src/Module.zig | |
| parent | affd8f8b59d9d803f98178ec32ab9e2f6b0b30d2 (diff) | |
| download | zig-5913140b6bf96e168a0167906a78e2d4aac5bd9d.tar.gz zig-5913140b6bf96e168a0167906a78e2d4aac5bd9d.zip | |
stage2: free Sema's arena after generating machine code
Previously, linker backends or machine code backends were able to hold
on to references to inside Sema's temporary arena. However there can
be large objects stored there that we want to free after machine code is
generated.
The primary change in this commit is to use a temporary arena for Sema
of function bodies that gets freed after machine code backend finishes
handling `updateFunc` (at the same time that Air and Liveness get freed).
The other changes in this commit are fixing issues that fell out from
the primary change.
* The C linker backend is rewritten to handle updateDecl and updateFunc
separately. Also, all Decl updates get access to typedefs and
fwd_decls, not only functions.
* The C linker backend is updated to the new API that does not depend
on allocateDeclIndexes and does not have to handle garbage collected
decls.
* The C linker backend uses an arena for Type/Value objects that
`typedefs` references. These can be garbage collected every so often
after flush(), however that garbage collection code is not
implemented at this time. It will be pretty simple, just allocate a
new arena, copy all the Type objects to it, update the keys of the
hash map, free the old arena.
* Sema: fix a handful of instances of not copying Type/Value objects
from the temporary arena into the appropriate Decl arena.
* Type: fix some function types not reporting hasCodeGenBits()
correctly.
Diffstat (limited to 'src/Module.zig')
| -rw-r--r-- | src/Module.zig | 32 |
1 files changed, 15 insertions, 17 deletions
diff --git a/src/Module.zig b/src/Module.zig index fd275b507f..88817efc26 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -610,7 +610,7 @@ pub const Decl = struct { /// If the Decl has a value and it is a function, return it, /// otherwise null. - pub fn getFunction(decl: *Decl) ?*Fn { + pub fn getFunction(decl: *const Decl) ?*Fn { if (!decl.owns_tv) return null; const func = (decl.val.castTag(.function) orelse return null).data; assert(func.owner_decl == decl); @@ -3789,7 +3789,7 @@ pub fn clearDecl( .elf => .{ .elf = link.File.Elf.TextBlock.empty }, .macho => .{ .macho = link.File.MachO.TextBlock.empty }, .plan9 => .{ .plan9 = link.File.Plan9.DeclBlock.empty }, - .c => .{ .c = link.File.C.DeclBlock.empty }, + .c => .{ .c = {} }, .wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty }, .spirv => .{ .spirv = {} }, }; @@ -3798,7 +3798,7 @@ pub fn clearDecl( .elf => .{ .elf = link.File.Elf.SrcFn.empty }, .macho => .{ .macho = link.File.MachO.SrcFn.empty }, .plan9 => .{ .plan9 = {} }, - .c => .{ .c = link.File.C.FnBlock.empty }, + .c => .{ .c = {} }, .wasm => .{ .wasm = link.File.Wasm.FnData.empty }, .spirv => .{ .spirv = .{} }, }; @@ -3828,10 +3828,13 @@ pub fn deleteUnusedDecl(mod: *Module, decl: *Decl) void { // about the Decl in the first place. // Until then, we did call `allocateDeclIndexes` on this anonymous Decl and so we // must call `freeDecl` in the linker backend now. - if (decl.has_tv) { - if (decl.ty.hasCodeGenBits()) { - mod.comp.bin_file.freeDecl(decl); - } + switch (mod.comp.bin_file.tag) { + .c => {}, // this linker backend has already migrated to the new API + else => if (decl.has_tv) { + if (decl.ty.hasCodeGenBits()) { + mod.comp.bin_file.freeDecl(decl); + } + }, } const dependants = decl.dependants.keys(); @@ -3893,22 +3896,16 @@ fn deleteDeclExports(mod: *Module, decl: *Decl) void { mod.gpa.free(kv.value); } -pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air { +pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn, arena: *Allocator) SemaError!Air { const tracy = trace(@src()); defer tracy.end(); const gpa = mod.gpa; - // Use the Decl's arena for function memory. - var arena = decl.value_arena.?.promote(gpa); - defer decl.value_arena.?.* = arena.state; - - const fn_ty = decl.ty; - var sema: Sema = .{ .mod = mod, .gpa = gpa, - .arena = &arena.allocator, + .arena = arena, .code = decl.namespace.file_scope.zir, .owner_decl = decl, .namespace = decl.namespace, @@ -3942,6 +3939,7 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air { // This could be a generic function instantiation, however, in which case we need to // map the comptime parameters to constant values and only emit arg AIR instructions // for the runtime ones. + const fn_ty = decl.ty; const runtime_params_len = @intCast(u32, fn_ty.fnParamLen()); try inner_block.instructions.ensureTotalCapacity(gpa, runtime_params_len); try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len * 2); // * 2 for the `addType` @@ -4072,7 +4070,7 @@ pub fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: Ast. .elf => .{ .elf = link.File.Elf.TextBlock.empty }, .macho => .{ .macho = link.File.MachO.TextBlock.empty }, .plan9 => .{ .plan9 = link.File.Plan9.DeclBlock.empty }, - .c => .{ .c = link.File.C.DeclBlock.empty }, + .c => .{ .c = {} }, .wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty }, .spirv => .{ .spirv = {} }, }, @@ -4081,7 +4079,7 @@ pub fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: Ast. .elf => .{ .elf = link.File.Elf.SrcFn.empty }, .macho => .{ .macho = link.File.MachO.SrcFn.empty }, .plan9 => .{ .plan9 = {} }, - .c => .{ .c = link.File.C.FnBlock.empty }, + .c => .{ .c = {} }, .wasm => .{ .wasm = link.File.Wasm.FnData.empty }, .spirv => .{ .spirv = .{} }, }, |
