diff options
Diffstat (limited to 'src/Module.zig')
| -rw-r--r-- | src/Module.zig | 155 |
1 files changed, 83 insertions, 72 deletions
diff --git a/src/Module.zig b/src/Module.zig index 5ef0448849..f0810d00a5 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -276,11 +276,16 @@ pub const Decl = struct { pub fn destroy(decl: *Decl, module: *Module) void { const gpa = module.gpa; + log.debug("destroy Decl {s}", .{decl.name}); decl.clearName(gpa); if (decl.has_tv) { if (decl.val.castTag(.function)) |payload| { const func = payload.data; func.deinit(gpa); + } else if (decl.val.getTypeNamespace()) |namespace| { + if (namespace.getDecl() == decl) { + namespace.clearDecls(module); + } } decl.clearValues(gpa); } @@ -303,6 +308,13 @@ pub const Decl = struct { } } + pub fn finalizeNewArena(decl: *Decl, arena: *std.heap.ArenaAllocator) !void { + assert(decl.value_arena == null); + const arena_state = try arena.allocator.create(std.heap.ArenaAllocator.State); + arena_state.* = arena.state; + decl.value_arena = arena_state; + } + /// This name is relative to the containing namespace of the decl. /// The memory is owned by the containing File ZIR. pub fn getName(decl: Decl) ?[:0]const u8 { @@ -719,13 +731,20 @@ pub const Scope = struct { decls: std.StringArrayHashMapUnmanaged(*Decl) = .{}, pub fn deinit(ns: *Namespace, mod: *Module) void { + ns.clearDecls(mod); + ns.* = undefined; + } + + pub fn clearDecls(ns: *Namespace, mod: *Module) void { const gpa = mod.gpa; - for (ns.decls.items()) |entry| { + var decls = ns.decls; + ns.decls = .{}; + + for (decls.items()) |entry| { entry.value.destroy(mod); } - ns.decls.deinit(gpa); - ns.* = undefined; + decls.deinit(gpa); } pub fn removeDecl(ns: *Namespace, child: *Decl) void { @@ -775,14 +794,9 @@ pub const Scope = struct { /// Package that this file is a part of, managed externally. pkg: *Package, /// The namespace of the struct that represents this file. - /// Populated only when status is success. + /// Populated only when status is `success_air`. /// Owned by its owner Decl Value. namespace: *Namespace, - /// All namespaces that this file contains. This is here so that - /// when a file is updated, and new ZIR code is generated, the - /// old and new ZIR code can be compared side by side and references - /// to old ZIR updated to new ZIR, and a changelist generated. - namespace_set: std.AutoArrayHashMapUnmanaged(*Namespace, void) = .{}, pub fn unload(file: *File, gpa: *Allocator) void { file.unloadTree(gpa); @@ -813,6 +827,10 @@ pub const Scope = struct { pub fn deinit(file: *File, mod: *Module) void { const gpa = mod.gpa; + log.debug("deinit File {s}", .{file.sub_file_path}); + if (file.status == .success_air) { + file.namespace.getDecl().destroy(mod); + } gpa.free(file.sub_file_path); file.unload(gpa); file.* = undefined; @@ -866,6 +884,18 @@ pub const Scope = struct { gpa.destroy(file); } + pub fn fullyQualifiedNameZ(file: File, gpa: *Allocator) ![:0]u8 { + // Convert all the slashes into dots and truncate the extension. + const ext = std.fs.path.extension(file.sub_file_path); + const noext = file.sub_file_path[0 .. file.sub_file_path.len - ext.len]; + const duped = try gpa.dupeZ(u8, noext); + for (duped) |*byte| switch (byte.*) { + '/', '\\' => byte.* = '.', + else => continue, + }; + return duped; + } + pub fn dumpSrc(file: *File, src: LazySrcLoc) void { const loc = std.zig.findLineColumn(file.source.bytes, src); std.debug.print("{s}:{d}:{d}\n", .{ file.sub_file_path, loc.line + 1, loc.column + 1 }); @@ -3297,48 +3327,49 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void { assert(file.zir_loaded); const gpa = mod.gpa; - var decl_arena = std.heap.ArenaAllocator.init(gpa); - defer decl_arena.deinit(); - - // We need a Decl to pass to Sema and collect dependencies. But ultimately we - // want to pass them on to the Decl for the struct that represents the file. - var tmp_namespace: Scope.Namespace = .{ - .parent = null, - .file_scope = file, - .ty = Type.initTag(.type), + var new_decl_arena = std.heap.ArenaAllocator.init(gpa); + errdefer new_decl_arena.deinit(); + + const struct_obj = try new_decl_arena.allocator.create(Module.Struct); + const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj); + const struct_val = try Value.Tag.ty.create(&new_decl_arena.allocator, struct_ty); + struct_obj.* = .{ + .owner_decl = undefined, // set below + .fields = .{}, + .node_offset = 0, // it's the struct for the root file + .namespace = .{ + .parent = null, + .ty = struct_ty, + .file_scope = file, + }, }; - var top_decl: Decl = .{ - .name = "", - .namespace = &tmp_namespace, - .generation = mod.generation, - .src_node = 0, // the root AST node for the file - .analysis = .in_progress, - .deletion_flag = false, - .is_pub = true, - .is_exported = false, - .has_linksection = false, - .has_align = false, - .link = undefined, // don't try to codegen this - .fn_link = undefined, // not a function - .zir_decl_index = undefined, + file.namespace = &struct_obj.namespace; + const new_decl = try mod.allocateNewDecl(&struct_obj.namespace, 0); + struct_obj.owner_decl = new_decl; + new_decl.name = try file.fullyQualifiedNameZ(gpa); + new_decl.is_pub = true; + new_decl.is_exported = false; + new_decl.has_align = false; + new_decl.has_linksection = false; + new_decl.zir_decl_index = undefined; + new_decl.ty = struct_ty; + new_decl.val = struct_val; + new_decl.has_tv = true; + new_decl.analysis = .complete; + new_decl.generation = mod.generation; - .has_tv = false, - .ty = undefined, - .val = undefined, - .align_val = undefined, - .linksection_val = undefined, - }; - defer top_decl.dependencies.deinit(gpa); + var sema_arena = std.heap.ArenaAllocator.init(gpa); + defer sema_arena.deinit(); var sema: Sema = .{ .mod = mod, .gpa = gpa, - .arena = &decl_arena.allocator, + .arena = &sema_arena.allocator, .code = file.zir, // TODO use a map because this array is too big - .inst_map = try decl_arena.allocator.alloc(*ir.Inst, file.zir.instructions.len), - .owner_decl = &top_decl, - .namespace = &tmp_namespace, + .inst_map = try sema_arena.allocator.alloc(*ir.Inst, file.zir.instructions.len), + .owner_decl = new_decl, + .namespace = &struct_obj.namespace, .func = null, .owner_func = null, .param_inst_list = &.{}, @@ -3346,7 +3377,7 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void { var block_scope: Scope.Block = .{ .parent = null, .sema = &sema, - .src_decl = &top_decl, + .src_decl = new_decl, .instructions = .{}, .inlining = null, .is_comptime = true, @@ -3355,23 +3386,9 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void { const main_struct_inst = file.zir.extra[@enumToInt(Zir.ExtraIndex.main_struct)] - @intCast(u32, Zir.Inst.Ref.typed_value_map.len); - const air_inst = try sema.zirStructDecl(&block_scope, main_struct_inst, .Auto); - assert(air_inst.ty.zigTypeTag() == .Type); - const val = air_inst.value().?; - const struct_ty = try val.toType(&decl_arena.allocator); - const struct_decl = struct_ty.getOwnerDecl(); - - file.namespace = struct_ty.getNamespace().?; - file.namespace.parent = null; - - // Transfer the dependencies to `owner_decl`. - assert(top_decl.dependants.count() == 0); - for (top_decl.dependencies.items()) |entry| { - const dep = entry.key; - dep.removeDependant(&top_decl); - if (dep == struct_decl) continue; - _ = try mod.declareDeclDependency(struct_decl, dep); - } + try sema.analyzeStructDecl(&block_scope, &new_decl_arena, new_decl, main_struct_inst, .Auto, struct_obj); + try new_decl.finalizeNewArena(&new_decl_arena); + file.status = .success_air; } @@ -4319,23 +4336,17 @@ pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, b } } -pub fn createAnonymousDecl( - mod: *Module, - scope: *Scope, - decl_arena: *std.heap.ArenaAllocator, - typed_value: TypedValue, -) !*Decl { +pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue) !*Decl { const name_index = mod.getNextAnonNameIndex(); const scope_decl = scope.ownerDecl().?; + const namespace = scope_decl.namespace; + try namespace.decls.ensureCapacity(mod.gpa, namespace.decls.count() + 1); const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{ scope_decl.name, name_index }); errdefer mod.gpa.free(name); - const namespace = scope_decl.namespace; const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node); - new_decl.name = name; + namespace.decls.putAssumeCapacityNoClobber(name, new_decl); - const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); - - decl_arena_state.* = decl_arena.state; + new_decl.name = name; new_decl.ty = typed_value.ty; new_decl.val = typed_value.val; new_decl.has_tv = true; |
