| author | |
| committer | |
| log | 67f5a28257b50e72750f51a03d6ce9ee27ad1439 |
| tree | e2a205ff1e748ded4bfc848e0a841ac5cef3622a |
| parent | 5cacc446c4ff5591b7a9c506952f4eb9ae5efdd1 |
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 | ||
| 6 | 1 | * in SwitchProng resolve, make sure AST tree gets loaded. |
| 7 | 2 | It will be unloaded if using cached ZIR. |
| 8 | 3 |
src/Module.zig+5-9| ... | ... | @@ -2904,14 +2904,13 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void { |
| 2904 | 2904 | .gpa = gpa, |
| 2905 | 2905 | .arena = &sema_arena.allocator, |
| 2906 | 2906 | .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), | |
| 2909 | 2907 | .owner_decl = new_decl, |
| 2910 | 2908 | .namespace = &struct_obj.namespace, |
| 2911 | 2909 | .func = null, |
| 2912 | 2910 | .owner_func = null, |
| 2913 | 2911 | .param_inst_list = &.{}, |
| 2914 | 2912 | }; |
| 2913 | defer sema.deinit(); | |
| 2915 | 2914 | var block_scope: Scope.Block = .{ |
| 2916 | 2915 | .parent = null, |
| 2917 | 2916 | .sema = &sema, |
| ... | ... | @@ -2960,13 +2959,13 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 2960 | 2959 | .gpa = gpa, |
| 2961 | 2960 | .arena = &analysis_arena.allocator, |
| 2962 | 2961 | .code = zir, |
| 2963 | .inst_map = try analysis_arena.allocator.alloc(*ir.Inst, zir.instructions.len), | |
| 2964 | 2962 | .owner_decl = decl, |
| 2965 | 2963 | .namespace = decl.namespace, |
| 2966 | 2964 | .func = null, |
| 2967 | 2965 | .owner_func = null, |
| 2968 | 2966 | .param_inst_list = &.{}, |
| 2969 | 2967 | }; |
| 2968 | defer sema.deinit(); | |
| 2970 | 2969 | |
| 2971 | 2970 | if (decl.isRoot()) { |
| 2972 | 2971 | log.debug("semaDecl root {*} ({s})", .{ decl, decl.name }); |
| ... | ... | @@ -3565,14 +3564,13 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void { |
| 3565 | 3564 | .gpa = mod.gpa, |
| 3566 | 3565 | .arena = &arena.allocator, |
| 3567 | 3566 | .code = zir, |
| 3568 | .inst_map = try mod.gpa.alloc(*ir.Inst, zir.instructions.len), | |
| 3569 | 3567 | .owner_decl = decl, |
| 3570 | 3568 | .namespace = decl.namespace, |
| 3571 | 3569 | .func = func, |
| 3572 | 3570 | .owner_func = func, |
| 3573 | 3571 | .param_inst_list = param_inst_list, |
| 3574 | 3572 | }; |
| 3575 | defer mod.gpa.free(sema.inst_map); | |
| 3573 | defer sema.deinit(); | |
| 3576 | 3574 | |
| 3577 | 3575 | var inner_block: Scope.Block = .{ |
| 3578 | 3576 | .parent = null, |
| ... | ... | @@ -4555,14 +4553,13 @@ pub fn analyzeStructFields(mod: *Module, struct_obj: *Struct) InnerError!void { |
| 4555 | 4553 | .gpa = gpa, |
| 4556 | 4554 | .arena = &decl_arena.allocator, |
| 4557 | 4555 | .code = zir, |
| 4558 | .inst_map = try gpa.alloc(*ir.Inst, zir.instructions.len), | |
| 4559 | 4556 | .owner_decl = struct_obj.owner_decl, |
| 4560 | 4557 | .namespace = &struct_obj.namespace, |
| 4561 | 4558 | .owner_func = null, |
| 4562 | 4559 | .func = null, |
| 4563 | 4560 | .param_inst_list = &.{}, |
| 4564 | 4561 | }; |
| 4565 | defer gpa.free(sema.inst_map); | |
| 4562 | defer sema.deinit(); | |
| 4566 | 4563 | |
| 4567 | 4564 | var block: Scope.Block = .{ |
| 4568 | 4565 | .parent = null, |
| ... | ... | @@ -4712,14 +4709,13 @@ pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) InnerError!void { |
| 4712 | 4709 | .gpa = gpa, |
| 4713 | 4710 | .arena = &decl_arena.allocator, |
| 4714 | 4711 | .code = zir, |
| 4715 | .inst_map = try gpa.alloc(*ir.Inst, zir.instructions.len), | |
| 4716 | 4712 | .owner_decl = union_obj.owner_decl, |
| 4717 | 4713 | .namespace = &union_obj.namespace, |
| 4718 | 4714 | .owner_func = null, |
| 4719 | 4715 | .func = null, |
| 4720 | 4716 | .param_inst_list = &.{}, |
| 4721 | 4717 | }; |
| 4722 | defer gpa.free(sema.inst_map); | |
| 4718 | defer sema.deinit(); | |
| 4723 | 4719 | |
| 4724 | 4720 | var block: Scope.Block = .{ |
| 4725 | 4721 | .parent = null, |
src/Sema.zig+15-7| ... | ... | @@ -12,7 +12,7 @@ gpa: *Allocator, |
| 12 | 12 | arena: *Allocator, |
| 13 | 13 | code: Zir, |
| 14 | 14 | /// Maps ZIR to AIR. |
| 15 | inst_map: []*Inst, | |
| 15 | inst_map: InstMap = .{}, | |
| 16 | 16 | /// When analyzing an inline function call, owner_decl is the Decl of the caller |
| 17 | 17 | /// and `src_decl` of `Scope.Block` is the `Decl` of the callee. |
| 18 | 18 | /// This `Decl` owns the arena memory of this `Sema`. |
| ... | ... | @@ -65,6 +65,13 @@ const LazySrcLoc = Module.LazySrcLoc; |
| 65 | 65 | const RangeSet = @import("RangeSet.zig"); |
| 66 | 66 | const target_util = @import("target.zig"); |
| 67 | 67 | |
| 68 | pub const InstMap = std.AutoHashMapUnmanaged(Zir.Inst.Index, *ir.Inst); | |
| 69 | ||
| 70 | pub fn deinit(sema: *Sema) void { | |
| 71 | sema.inst_map.deinit(sema.gpa); | |
| 72 | sema.* = undefined; | |
| 73 | } | |
| 74 | ||
| 68 | 75 | pub fn analyzeFnBody( |
| 69 | 76 | sema: *Sema, |
| 70 | 77 | block: *Scope.Block, |
| ... | ... | @@ -129,7 +136,7 @@ pub fn analyzeBody( |
| 129 | 136 | ) InnerError!Zir.Inst.Index { |
| 130 | 137 | // No tracy calls here, to avoid interfering with the tail call mechanism. |
| 131 | 138 | |
| 132 | const map = block.sema.inst_map; | |
| 139 | const map = &block.sema.inst_map; | |
| 133 | 140 | const tags = block.sema.code.instructions.items(.tag); |
| 134 | 141 | const datas = block.sema.code.instructions.items(.data); |
| 135 | 142 | |
| ... | ... | @@ -142,7 +149,7 @@ pub fn analyzeBody( |
| 142 | 149 | var i: usize = 0; |
| 143 | 150 | while (true) : (i += 1) { |
| 144 | 151 | const inst = body[i]; |
| 145 | map[inst] = switch (tags[inst]) { | |
| 152 | const air_inst = switch (tags[inst]) { | |
| 146 | 153 | // zig fmt: off |
| 147 | 154 | .arg => try sema.zirArg(block, inst), |
| 148 | 155 | .alloc => try sema.zirAlloc(block, inst), |
| ... | ... | @@ -500,8 +507,9 @@ pub fn analyzeBody( |
| 500 | 507 | } |
| 501 | 508 | }, |
| 502 | 509 | }; |
| 503 | if (map[inst].ty.isNoReturn()) | |
| 510 | if (air_inst.ty.isNoReturn()) | |
| 504 | 511 | return always_noreturn; |
| 512 | try map.putNoClobber(sema.gpa, inst, air_inst); | |
| 505 | 513 | } |
| 506 | 514 | } |
| 507 | 515 | |
| ... | ... | @@ -556,7 +564,7 @@ pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) error{OutOfMemory}!*ir.In |
| 556 | 564 | i -= Zir.Inst.Ref.typed_value_map.len; |
| 557 | 565 | |
| 558 | 566 | // 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)).?; | |
| 560 | 568 | } |
| 561 | 569 | |
| 562 | 570 | fn resolveConstString( |
| ... | ... | @@ -2244,9 +2252,9 @@ fn analyzeCall( |
| 2244 | 2252 | defer sema.code = parent_zir; |
| 2245 | 2253 | |
| 2246 | 2254 | 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 = .{}; | |
| 2248 | 2256 | defer { |
| 2249 | sema.gpa.free(sema.inst_map); | |
| 2257 | sema.inst_map.deinit(sema.gpa); | |
| 2250 | 2258 | sema.inst_map = parent_inst_map; |
| 2251 | 2259 | } |
| 2252 | 2260 |