authorgravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-11-01 04:26:18-04:00
committergravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-11-01 05:42:25-04:00
log92d2aa1b48c2171d58eec51552ca30d1cc0fe206
tree0f43d361b20e52d9069e8bae5ee2b3713d4eafc4
parent5760ba949fe3c2ab576e422dd3a74600f0e52d5c

astgen.zig: use scratch buffer for temporary allocations in switchExpr and WipMembers


1 files changed, 50 insertions(+), 40 deletions(-)

src/AstGen.zig+50-40
......@@ -41,6 +41,8 @@ fn_block: ?*GenZir = null,
4141/// Maps string table indexes to the first `@import` ZIR instruction
4242/// that uses this string as the operand.
4343imports: std.AutoArrayHashMapUnmanaged(u32, Ast.TokenIndex) = .{},
44/// Used for temporary storage when building payloads.
45scratch: std.ArrayListUnmanaged(u32) = .{},
4446
4547const InnerError = error{ OutOfMemory, AnalysisFail };
4648
......@@ -198,6 +200,7 @@ pub fn deinit(astgen: *AstGen, gpa: *Allocator) void {
198200 astgen.string_bytes.deinit(gpa);
199201 astgen.compile_errors.deinit(gpa);
200202 astgen.imports.deinit(gpa);
203 astgen.scratch.deinit(gpa);
201204}
202205
203206pub const ResultLoc = union(enum) {
......@@ -2996,7 +2999,8 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.I
29962999}
29973000
29983001const WipMembers = struct {
2999 payload: []u32,
3002 payload: *ArrayListUnmanaged(u32),
3003 payload_top: usize,
30003004 decls_start: u32,
30013005 decls_end: u32,
30023006 field_bits_start: u32,
......@@ -3013,16 +3017,19 @@ const WipMembers = struct {
30133017 /// (4 for src_hash + line + name + value + align + link_section + address_space)
30143018 const max_decl_size = 10;
30153019
3016 pub fn init(gpa: *Allocator, decl_count: u32, field_count: u32, comptime bits_per_field: u32, comptime max_field_size: u32) Allocator.Error!Self {
3017 const decls_start = (decl_count + decls_per_u32 - 1) / decls_per_u32;
3020 pub fn init(gpa: *Allocator, payload: *ArrayListUnmanaged(u32), decl_count: u32, field_count: u32, comptime bits_per_field: u32, comptime max_field_size: u32) Allocator.Error!Self {
3021 const payload_top = @intCast(u32, payload.items.len);
3022 const decls_start = payload_top + (decl_count + decls_per_u32 - 1) / decls_per_u32;
30183023 const field_bits_start = decls_start + decl_count * max_decl_size;
3019 const fields_start = if (bits_per_field > 0) blk: {
3024 const fields_start = field_bits_start + if (bits_per_field > 0) blk: {
30203025 const fields_per_u32 = 32 / bits_per_field;
3021 break :blk field_bits_start + (field_count + fields_per_u32 - 1) / fields_per_u32;
3022 } else field_bits_start;
3023 const capacity = fields_start + field_count * max_field_size;
3026 break :blk (field_count + fields_per_u32 - 1) / fields_per_u32;
3027 } else 0;
3028 const payload_end = fields_start + field_count * max_field_size;
3029 try payload.resize(gpa, payload_end);
30243030 return Self{
3025 .payload = try gpa.alloc(u32, capacity),
3031 .payload = payload,
3032 .payload_top = payload_top,
30263033 .decls_start = decls_start,
30273034 .field_bits_start = field_bits_start,
30283035 .fields_start = fields_start,
......@@ -3032,10 +3039,10 @@ const WipMembers = struct {
30323039 }
30333040
30343041 pub fn nextDecl(self: *Self, is_pub: bool, is_export: bool, has_align: bool, has_section_or_addrspace: bool) void {
3035 const index = self.decl_index / decls_per_u32;
3042 const index = self.payload_top + self.decl_index / decls_per_u32;
30363043 assert(index < self.decls_start);
3037 const bit_bag: u32 = if (self.decl_index % decls_per_u32 == 0) 0 else self.payload[index];
3038 self.payload[index] = (bit_bag >> bits_per_decl) |
3044 const bit_bag: u32 = if (self.decl_index % decls_per_u32 == 0) 0 else self.payload.items[index];
3045 self.payload.items[index] = (bit_bag >> bits_per_decl) |
30393046 (@as(u32, @boolToInt(is_pub)) << 28) |
30403047 (@as(u32, @boolToInt(is_export)) << 29) |
30413048 (@as(u32, @boolToInt(has_align)) << 30) |
......@@ -3047,60 +3054,60 @@ const WipMembers = struct {
30473054 const fields_per_u32 = 32 / bits_per_field;
30483055 const index = self.field_bits_start + self.field_index / fields_per_u32;
30493056 assert(index < self.fields_start);
3050 var bit_bag: u32 = if (self.field_index % fields_per_u32 == 0) 0 else self.payload[index];
3057 var bit_bag: u32 = if (self.field_index % fields_per_u32 == 0) 0 else self.payload.items[index];
30513058 bit_bag >>= bits_per_field;
30523059 comptime var i = 0;
30533060 inline while (i < bits_per_field) : (i += 1) {
30543061 bit_bag |= @as(u32, @boolToInt(bits[i])) << (32 - bits_per_field + i);
30553062 }
3056 self.payload[index] = bit_bag;
3063 self.payload.items[index] = bit_bag;
30573064 self.field_index += 1;
30583065 }
30593066
30603067 pub fn appendToDecl(self: *Self, data: u32) void {
30613068 assert(self.decls_end < self.field_bits_start);
3062 self.payload[self.decls_end] = data;
3069 self.payload.items[self.decls_end] = data;
30633070 self.decls_end += 1;
30643071 }
30653072
30663073 pub fn appendToDeclSlice(self: *Self, data: []const u32) void {
30673074 assert(self.decls_end + data.len <= self.field_bits_start);
3068 mem.copy(u32, self.payload[self.decls_end..], data);
3075 mem.copy(u32, self.payload.items[self.decls_end..], data);
30693076 self.decls_end += @intCast(u32, data.len);
30703077 }
30713078
30723079 pub fn appendToField(self: *Self, data: u32) void {
3073 assert(self.fields_end < self.payload.len);
3074 self.payload[self.fields_end] = data;
3080 assert(self.fields_end < self.payload.items.len);
3081 self.payload.items[self.fields_end] = data;
30753082 self.fields_end += 1;
30763083 }
30773084
30783085 pub fn finishBits(self: *Self, comptime bits_per_field: u32) void {
30793086 const empty_decl_slots = decls_per_u32 - (self.decl_index % decls_per_u32);
30803087 if (self.decl_index > 0 and empty_decl_slots < decls_per_u32) {
3081 const index = self.decl_index / decls_per_u32;
3082 self.payload[index] >>= @intCast(u5, empty_decl_slots * bits_per_decl);
3088 const index = self.payload_top + self.decl_index / decls_per_u32;
3089 self.payload.items[index] >>= @intCast(u5, empty_decl_slots * bits_per_decl);
30833090 }
30843091 if (bits_per_field > 0) {
30853092 const fields_per_u32 = 32 / bits_per_field;
30863093 const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32);
30873094 if (self.field_index > 0 and empty_field_slots < fields_per_u32) {
30883095 const index = self.field_bits_start + self.field_index / fields_per_u32;
3089 self.payload[index] >>= @intCast(u5, empty_field_slots * bits_per_field);
3096 self.payload.items[index] >>= @intCast(u5, empty_field_slots * bits_per_field);
30903097 }
30913098 }
30923099 }
30933100
30943101 pub fn declsSlice(self: *Self) []u32 {
3095 return self.payload[0..self.decls_end];
3102 return self.payload.items[self.payload_top..self.decls_end];
30963103 }
30973104
30983105 pub fn fieldsSlice(self: *Self) []u32 {
3099 return self.payload[self.field_bits_start..self.fields_end];
3106 return self.payload.items[self.field_bits_start..self.fields_end];
31003107 }
31013108
3102 pub fn deinit(self: *Self, gpa: *Allocator) void {
3103 gpa.free(self.payload);
3109 pub fn deinit(self: *Self) void {
3110 self.payload.items.len = self.payload_top;
31043111 }
31053112};
31063113
......@@ -3777,8 +3784,8 @@ fn structDeclInner(
37773784
37783785 const bits_per_field = 4;
37793786 const max_field_size = 4;
3780 var wip_members = try WipMembers.init(gpa, decl_count, field_count, bits_per_field, max_field_size);
3781 defer wip_members.deinit(gpa);
3787 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size);
3788 defer wip_members.deinit();
37823789
37833790 var known_has_bits = false;
37843791 for (container_decl.ast.members) |member_node| {
......@@ -3893,8 +3900,8 @@ fn unionDeclInner(
38933900
38943901 const bits_per_field = 4;
38953902 const max_field_size = 4;
3896 var wip_members = try WipMembers.init(gpa, decl_count, field_count, bits_per_field, max_field_size);
3897 defer wip_members.deinit(gpa);
3903 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size);
3904 defer wip_members.deinit();
38983905
38993906 for (members) |member_node| {
39003907 const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) {
......@@ -4166,8 +4173,8 @@ fn containerDecl(
41664173
41674174 const bits_per_field = 1;
41684175 const max_field_size = 2;
4169 var wip_members = try WipMembers.init(gpa, @intCast(u32, counts.decls), @intCast(u32, counts.total_fields), bits_per_field, max_field_size);
4170 defer wip_members.deinit(gpa);
4176 var wip_members = try WipMembers.init(gpa, &astgen.scratch, @intCast(u32, counts.decls), @intCast(u32, counts.total_fields), bits_per_field, max_field_size);
4177 defer wip_members.deinit();
41714178
41724179 for (container_decl.ast.members) |member_node| {
41734180 if (member_node == counts.nonexhaustive_node)
......@@ -4244,8 +4251,8 @@ fn containerDecl(
42444251
42454252 const decl_count = try astgen.scanDecls(&namespace, container_decl.ast.members);
42464253
4247 var wip_members = try WipMembers.init(gpa, decl_count, 0, 0, 0);
4248 defer wip_members.deinit(gpa);
4254 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, 0, 0, 0);
4255 defer wip_members.deinit();
42494256
42504257 for (container_decl.ast.members) |member_node| {
42514258 _ = try containerMember(gz, &namespace.base, &wip_members, member_node);
......@@ -5579,12 +5586,14 @@ fn switchExpr(
55795586 // This contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti,
55805587 // except the first cases_nodes.len slots are a table that indexes payloads later in the array, with
55815588 // the special case index coming first, then scalar_case_len indexes, then multi_cases_len indexes
5582 var payloads = ArrayListUnmanaged(u32){};
5583 defer payloads.deinit(gpa);
5584 const scalar_case_table: u32 = @boolToInt(special_prong != .none);
5589 const payloads = &astgen.scratch;
5590 const scratch_top = astgen.scratch.items.len;
5591 const case_table_start = scratch_top;
5592 const scalar_case_table = case_table_start + @boolToInt(special_prong != .none);
55855593 const multi_case_table = scalar_case_table + scalar_cases_len;
5586 const case_table_len = multi_case_table + multi_cases_len;
5587 try payloads.resize(gpa, case_table_len);
5594 const case_table_end = multi_case_table + multi_cases_len;
5595 try astgen.scratch.resize(gpa, case_table_end);
5596 defer astgen.scratch.items.len = scratch_top;
55885597
55895598 var block_scope = parent_gz.makeSubBlock(scope);
55905599 block_scope.setBreakResultLoc(rl);
......@@ -5702,7 +5711,7 @@ fn switchExpr(
57025711 payloads.items[header_index + 1] = ranges_len;
57035712 break :blk header_index + 2;
57045713 } else if (case_node == special_node) blk: {
5705 payloads.items[0] = header_index;
5714 payloads.items[case_table_start] = header_index;
57065715 try payloads.resize(gpa, header_index + 1); // body_len
57075716 break :blk header_index;
57085717 } else blk: {
......@@ -5729,7 +5738,7 @@ fn switchExpr(
57295738
57305739 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.SwitchBlock).Struct.fields.len +
57315740 @boolToInt(multi_cases_len != 0) +
5732 payloads.items.len - case_table_len);
5741 payloads.items.len - case_table_end);
57335742
57345743 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.SwitchBlock{
57355744 .operand = cond,
......@@ -5752,9 +5761,10 @@ fn switchExpr(
57525761 zir_datas[switch_block].pl_node.payload_index = payload_index;
57535762
57545763 const strat = rl.strategy(&block_scope);
5755 for (payloads.items[0..case_table_len]) |start_index, table_index| {
5764 for (payloads.items[case_table_start..case_table_end]) |start_index, i| {
57565765 var body_len_index = start_index;
57575766 var end_index = start_index;
5767 const table_index = case_table_start + i;
57585768 if (table_index < scalar_case_table) {
57595769 end_index += 1;
57605770 } else if (table_index < multi_case_table) {