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