authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-17 17:39:52-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-17 17:39:52-07:00
log67f5a28257b50e72750f51a03d6ce9ee27ad1439
treee2a205ff1e748ded4bfc848e0a841ac5cef3622a
parent5cacc446c4ff5591b7a9c506952f4eb9ae5efdd1

Sema: use a hash map for ZIR->AIR mapping

Previously, ZIR was per-function so we could simply allocate a slice for all ZIR instructions. However now ZIR is whole-file, so we need a sparse mapping of ZIR to AIR instructions in order to not waste memory.

3 files changed, 20 insertions(+), 21 deletions(-)

BRANCH_TODO-5
......@@ -1,8 +1,3 @@
1 * use a hash map for instructions because the array is too big
2 - no, actually modify the Zir.Inst.Ref strategy so that each decl gets
3 their indexes starting at 0 so that we can use an array to store Sema
4 results rather than a map.
5
61 * in SwitchProng resolve, make sure AST tree gets loaded.
72 It will be unloaded if using cached ZIR.
83
src/Module.zig+5-9
......@@ -2904,14 +2904,13 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {
29042904 .gpa = gpa,
29052905 .arena = &sema_arena.allocator,
29062906 .code = file.zir,
2907 // TODO use a map because this array is too big
2908 .inst_map = try sema_arena.allocator.alloc(*ir.Inst, file.zir.instructions.len),
29092907 .owner_decl = new_decl,
29102908 .namespace = &struct_obj.namespace,
29112909 .func = null,
29122910 .owner_func = null,
29132911 .param_inst_list = &.{},
29142912 };
2913 defer sema.deinit();
29152914 var block_scope: Scope.Block = .{
29162915 .parent = null,
29172916 .sema = &sema,
......@@ -2960,13 +2959,13 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
29602959 .gpa = gpa,
29612960 .arena = &analysis_arena.allocator,
29622961 .code = zir,
2963 .inst_map = try analysis_arena.allocator.alloc(*ir.Inst, zir.instructions.len),
29642962 .owner_decl = decl,
29652963 .namespace = decl.namespace,
29662964 .func = null,
29672965 .owner_func = null,
29682966 .param_inst_list = &.{},
29692967 };
2968 defer sema.deinit();
29702969
29712970 if (decl.isRoot()) {
29722971 log.debug("semaDecl root {*} ({s})", .{ decl, decl.name });
......@@ -3565,14 +3564,13 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {
35653564 .gpa = mod.gpa,
35663565 .arena = &arena.allocator,
35673566 .code = zir,
3568 .inst_map = try mod.gpa.alloc(*ir.Inst, zir.instructions.len),
35693567 .owner_decl = decl,
35703568 .namespace = decl.namespace,
35713569 .func = func,
35723570 .owner_func = func,
35733571 .param_inst_list = param_inst_list,
35743572 };
3575 defer mod.gpa.free(sema.inst_map);
3573 defer sema.deinit();
35763574
35773575 var inner_block: Scope.Block = .{
35783576 .parent = null,
......@@ -4555,14 +4553,13 @@ pub fn analyzeStructFields(mod: *Module, struct_obj: *Struct) InnerError!void {
45554553 .gpa = gpa,
45564554 .arena = &decl_arena.allocator,
45574555 .code = zir,
4558 .inst_map = try gpa.alloc(*ir.Inst, zir.instructions.len),
45594556 .owner_decl = struct_obj.owner_decl,
45604557 .namespace = &struct_obj.namespace,
45614558 .owner_func = null,
45624559 .func = null,
45634560 .param_inst_list = &.{},
45644561 };
4565 defer gpa.free(sema.inst_map);
4562 defer sema.deinit();
45664563
45674564 var block: Scope.Block = .{
45684565 .parent = null,
......@@ -4712,14 +4709,13 @@ pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) InnerError!void {
47124709 .gpa = gpa,
47134710 .arena = &decl_arena.allocator,
47144711 .code = zir,
4715 .inst_map = try gpa.alloc(*ir.Inst, zir.instructions.len),
47164712 .owner_decl = union_obj.owner_decl,
47174713 .namespace = &union_obj.namespace,
47184714 .owner_func = null,
47194715 .func = null,
47204716 .param_inst_list = &.{},
47214717 };
4722 defer gpa.free(sema.inst_map);
4718 defer sema.deinit();
47234719
47244720 var block: Scope.Block = .{
47254721 .parent = null,
src/Sema.zig+15-7
......@@ -12,7 +12,7 @@ gpa: *Allocator,
1212arena: *Allocator,
1313code: Zir,
1414/// Maps ZIR to AIR.
15inst_map: []*Inst,
15inst_map: InstMap = .{},
1616/// When analyzing an inline function call, owner_decl is the Decl of the caller
1717/// and `src_decl` of `Scope.Block` is the `Decl` of the callee.
1818/// This `Decl` owns the arena memory of this `Sema`.
......@@ -65,6 +65,13 @@ const LazySrcLoc = Module.LazySrcLoc;
6565const RangeSet = @import("RangeSet.zig");
6666const target_util = @import("target.zig");
6767
68pub const InstMap = std.AutoHashMapUnmanaged(Zir.Inst.Index, *ir.Inst);
69
70pub fn deinit(sema: *Sema) void {
71 sema.inst_map.deinit(sema.gpa);
72 sema.* = undefined;
73}
74
6875pub fn analyzeFnBody(
6976 sema: *Sema,
7077 block: *Scope.Block,
......@@ -129,7 +136,7 @@ pub fn analyzeBody(
129136) InnerError!Zir.Inst.Index {
130137 // No tracy calls here, to avoid interfering with the tail call mechanism.
131138
132 const map = block.sema.inst_map;
139 const map = &block.sema.inst_map;
133140 const tags = block.sema.code.instructions.items(.tag);
134141 const datas = block.sema.code.instructions.items(.data);
135142
......@@ -142,7 +149,7 @@ pub fn analyzeBody(
142149 var i: usize = 0;
143150 while (true) : (i += 1) {
144151 const inst = body[i];
145 map[inst] = switch (tags[inst]) {
152 const air_inst = switch (tags[inst]) {
146153 // zig fmt: off
147154 .arg => try sema.zirArg(block, inst),
148155 .alloc => try sema.zirAlloc(block, inst),
......@@ -500,8 +507,9 @@ pub fn analyzeBody(
500507 }
501508 },
502509 };
503 if (map[inst].ty.isNoReturn())
510 if (air_inst.ty.isNoReturn())
504511 return always_noreturn;
512 try map.putNoClobber(sema.gpa, inst, air_inst);
505513 }
506514}
507515
......@@ -556,7 +564,7 @@ pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) error{OutOfMemory}!*ir.In
556564 i -= Zir.Inst.Ref.typed_value_map.len;
557565
558566 // Finally, the last section of indexes refers to the map of ZIR=>AIR.
559 return sema.inst_map[i];
567 return sema.inst_map.get(@intCast(u32, i)).?;
560568}
561569
562570fn resolveConstString(
......@@ -2244,9 +2252,9 @@ fn analyzeCall(
22442252 defer sema.code = parent_zir;
22452253
22462254 const parent_inst_map = sema.inst_map;
2247 sema.inst_map = try sema.gpa.alloc(*ir.Inst, sema.code.instructions.len);
2255 sema.inst_map = .{};
22482256 defer {
2249 sema.gpa.free(sema.inst_map);
2257 sema.inst_map.deinit(sema.gpa);
22502258 sema.inst_map = parent_inst_map;
22512259 }
22522260