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,...@@ -41,6 +41,8 @@ fn_block: ?*GenZir = null,
41/// Maps string table indexes to the first `@import` ZIR instruction41/// Maps string table indexes to the first `@import` ZIR instruction
42/// that uses this string as the operand.42/// that uses this string as the operand.
43imports: std.AutoArrayHashMapUnmanaged(u32, Ast.TokenIndex) = .{},43imports: std.AutoArrayHashMapUnmanaged(u32, Ast.TokenIndex) = .{},
44/// Used for temporary storage when building payloads.
45scratch: std.ArrayListUnmanaged(u32) = .{},
4446
45const InnerError = error{ OutOfMemory, AnalysisFail };47const InnerError = error{ OutOfMemory, AnalysisFail };
4648
...@@ -198,6 +200,7 @@ pub fn deinit(astgen: *AstGen, gpa: *Allocator) void {...@@ -198,6 +200,7 @@ pub fn deinit(astgen: *AstGen, gpa: *Allocator) void {
198 astgen.string_bytes.deinit(gpa);200 astgen.string_bytes.deinit(gpa);
199 astgen.compile_errors.deinit(gpa);201 astgen.compile_errors.deinit(gpa);
200 astgen.imports.deinit(gpa);202 astgen.imports.deinit(gpa);
203 astgen.scratch.deinit(gpa);
201}204}
202205
203pub const ResultLoc = union(enum) {206pub const ResultLoc = union(enum) {
...@@ -2996,7 +2999,8 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.I...@@ -2996,7 +2999,8 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.I
2996}2999}
29973000
2998const WipMembers = struct {3001const WipMembers = struct {
2999 payload: []u32,3002 payload: *ArrayListUnmanaged(u32),
3003 payload_top: usize,
3000 decls_start: u32,3004 decls_start: u32,
3001 decls_end: u32,3005 decls_end: u32,
3002 field_bits_start: u32,3006 field_bits_start: u32,
...@@ -3013,16 +3017,19 @@ const WipMembers = struct {...@@ -3013,16 +3017,19 @@ const WipMembers = struct {
3013 /// (4 for src_hash + line + name + value + align + link_section + address_space)3017 /// (4 for src_hash + line + name + value + align + link_section + address_space)
3014 const max_decl_size = 10;3018 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 {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 {
3017 const decls_start = (decl_count + decls_per_u32 - 1) / decls_per_u32;3021 const payload_top = @intCast(u32, payload.items.len);
3022 const decls_start = payload_top + (decl_count + decls_per_u32 - 1) / decls_per_u32;
3018 const field_bits_start = decls_start + decl_count * max_decl_size;3023 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: {
3020 const fields_per_u32 = 32 / bits_per_field;3025 const fields_per_u32 = 32 / bits_per_field;
3021 break :blk field_bits_start + (field_count + fields_per_u32 - 1) / fields_per_u32;3026 break :blk (field_count + fields_per_u32 - 1) / fields_per_u32;
3022 } else field_bits_start;3027 } else 0;
3023 const capacity = fields_start + field_count * max_field_size;3028 const payload_end = fields_start + field_count * max_field_size;
3029 try payload.resize(gpa, payload_end);
3024 return Self{3030 return Self{
3025 .payload = try gpa.alloc(u32, capacity),3031 .payload = payload,
3032 .payload_top = payload_top,
3026 .decls_start = decls_start,3033 .decls_start = decls_start,
3027 .field_bits_start = field_bits_start,3034 .field_bits_start = field_bits_start,
3028 .fields_start = fields_start,3035 .fields_start = fields_start,
...@@ -3032,10 +3039,10 @@ const WipMembers = struct {...@@ -3032,10 +3039,10 @@ const WipMembers = struct {
3032 }3039 }
30333040
3034 pub fn nextDecl(self: *Self, is_pub: bool, is_export: bool, has_align: bool, has_section_or_addrspace: bool) void {3041 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;
3036 assert(index < self.decls_start);3043 assert(index < self.decls_start);
3037 const bit_bag: u32 = if (self.decl_index % decls_per_u32 == 0) 0 else self.payload[index];3044 const bit_bag: u32 = if (self.decl_index % decls_per_u32 == 0) 0 else self.payload.items[index];
3038 self.payload[index] = (bit_bag >> bits_per_decl) |3045 self.payload.items[index] = (bit_bag >> bits_per_decl) |
3039 (@as(u32, @boolToInt(is_pub)) << 28) |3046 (@as(u32, @boolToInt(is_pub)) << 28) |
3040 (@as(u32, @boolToInt(is_export)) << 29) |3047 (@as(u32, @boolToInt(is_export)) << 29) |
3041 (@as(u32, @boolToInt(has_align)) << 30) |3048 (@as(u32, @boolToInt(has_align)) << 30) |
...@@ -3047,60 +3054,60 @@ const WipMembers = struct {...@@ -3047,60 +3054,60 @@ const WipMembers = struct {
3047 const fields_per_u32 = 32 / bits_per_field;3054 const fields_per_u32 = 32 / bits_per_field;
3048 const index = self.field_bits_start + self.field_index / fields_per_u32;3055 const index = self.field_bits_start + self.field_index / fields_per_u32;
3049 assert(index < self.fields_start);3056 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];
3051 bit_bag >>= bits_per_field;3058 bit_bag >>= bits_per_field;
3052 comptime var i = 0;3059 comptime var i = 0;
3053 inline while (i < bits_per_field) : (i += 1) {3060 inline while (i < bits_per_field) : (i += 1) {
3054 bit_bag |= @as(u32, @boolToInt(bits[i])) << (32 - bits_per_field + i);3061 bit_bag |= @as(u32, @boolToInt(bits[i])) << (32 - bits_per_field + i);
3055 }3062 }
3056 self.payload[index] = bit_bag;3063 self.payload.items[index] = bit_bag;
3057 self.field_index += 1;3064 self.field_index += 1;
3058 }3065 }
30593066
3060 pub fn appendToDecl(self: *Self, data: u32) void {3067 pub fn appendToDecl(self: *Self, data: u32) void {
3061 assert(self.decls_end < self.field_bits_start);3068 assert(self.decls_end < self.field_bits_start);
3062 self.payload[self.decls_end] = data;3069 self.payload.items[self.decls_end] = data;
3063 self.decls_end += 1;3070 self.decls_end += 1;
3064 }3071 }
30653072
3066 pub fn appendToDeclSlice(self: *Self, data: []const u32) void {3073 pub fn appendToDeclSlice(self: *Self, data: []const u32) void {
3067 assert(self.decls_end + data.len <= self.field_bits_start);3074 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);
3069 self.decls_end += @intCast(u32, data.len);3076 self.decls_end += @intCast(u32, data.len);
3070 }3077 }
30713078
3072 pub fn appendToField(self: *Self, data: u32) void {3079 pub fn appendToField(self: *Self, data: u32) void {
3073 assert(self.fields_end < self.payload.len);3080 assert(self.fields_end < self.payload.items.len);
3074 self.payload[self.fields_end] = data;3081 self.payload.items[self.fields_end] = data;
3075 self.fields_end += 1;3082 self.fields_end += 1;
3076 }3083 }
30773084
3078 pub fn finishBits(self: *Self, comptime bits_per_field: u32) void {3085 pub fn finishBits(self: *Self, comptime bits_per_field: u32) void {
3079 const empty_decl_slots = decls_per_u32 - (self.decl_index % decls_per_u32);3086 const empty_decl_slots = decls_per_u32 - (self.decl_index % decls_per_u32);
3080 if (self.decl_index > 0 and empty_decl_slots < decls_per_u32) {3087 if (self.decl_index > 0 and empty_decl_slots < decls_per_u32) {
3081 const index = self.decl_index / decls_per_u32;3088 const index = self.payload_top + self.decl_index / decls_per_u32;
3082 self.payload[index] >>= @intCast(u5, empty_decl_slots * bits_per_decl);3089 self.payload.items[index] >>= @intCast(u5, empty_decl_slots * bits_per_decl);
3083 }3090 }
3084 if (bits_per_field > 0) {3091 if (bits_per_field > 0) {
3085 const fields_per_u32 = 32 / bits_per_field;3092 const fields_per_u32 = 32 / bits_per_field;
3086 const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32);3093 const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32);
3087 if (self.field_index > 0 and empty_field_slots < fields_per_u32) {3094 if (self.field_index > 0 and empty_field_slots < fields_per_u32) {
3088 const index = self.field_bits_start + self.field_index / fields_per_u32;3095 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);
3090 }3097 }
3091 }3098 }
3092 }3099 }
30933100
3094 pub fn declsSlice(self: *Self) []u32 {3101 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];
3096 }3103 }
30973104
3098 pub fn fieldsSlice(self: *Self) []u32 {3105 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];
3100 }3107 }
31013108
3102 pub fn deinit(self: *Self, gpa: *Allocator) void {3109 pub fn deinit(self: *Self) void {
3103 gpa.free(self.payload);3110 self.payload.items.len = self.payload_top;
3104 }3111 }
3105};3112};
31063113
...@@ -3777,8 +3784,8 @@ fn structDeclInner(...@@ -3777,8 +3784,8 @@ fn structDeclInner(
37773784
3778 const bits_per_field = 4;3785 const bits_per_field = 4;
3779 const max_field_size = 4;3786 const max_field_size = 4;
3780 var wip_members = try WipMembers.init(gpa, decl_count, field_count, bits_per_field, max_field_size);3787 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size);
3781 defer wip_members.deinit(gpa);3788 defer wip_members.deinit();
37823789
3783 var known_has_bits = false;3790 var known_has_bits = false;
3784 for (container_decl.ast.members) |member_node| {3791 for (container_decl.ast.members) |member_node| {
...@@ -3893,8 +3900,8 @@ fn unionDeclInner(...@@ -3893,8 +3900,8 @@ fn unionDeclInner(
38933900
3894 const bits_per_field = 4;3901 const bits_per_field = 4;
3895 const max_field_size = 4;3902 const max_field_size = 4;
3896 var wip_members = try WipMembers.init(gpa, decl_count, field_count, bits_per_field, max_field_size);3903 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size);
3897 defer wip_members.deinit(gpa);3904 defer wip_members.deinit();
38983905
3899 for (members) |member_node| {3906 for (members) |member_node| {
3900 const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) {3907 const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) {
...@@ -4166,8 +4173,8 @@ fn containerDecl(...@@ -4166,8 +4173,8 @@ fn containerDecl(
41664173
4167 const bits_per_field = 1;4174 const bits_per_field = 1;
4168 const max_field_size = 2;4175 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);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);
4170 defer wip_members.deinit(gpa);4177 defer wip_members.deinit();
41714178
4172 for (container_decl.ast.members) |member_node| {4179 for (container_decl.ast.members) |member_node| {
4173 if (member_node == counts.nonexhaustive_node)4180 if (member_node == counts.nonexhaustive_node)
...@@ -4244,8 +4251,8 @@ fn containerDecl(...@@ -4244,8 +4251,8 @@ fn containerDecl(
42444251
4245 const decl_count = try astgen.scanDecls(&namespace, container_decl.ast.members);4252 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);4254 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, 0, 0, 0);
4248 defer wip_members.deinit(gpa);4255 defer wip_members.deinit();
42494256
4250 for (container_decl.ast.members) |member_node| {4257 for (container_decl.ast.members) |member_node| {
4251 _ = try containerMember(gz, &namespace.base, &wip_members, member_node);4258 _ = try containerMember(gz, &namespace.base, &wip_members, member_node);
...@@ -5579,12 +5586,14 @@ fn switchExpr(...@@ -5579,12 +5586,14 @@ fn switchExpr(
5579 // This contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti,5586 // This contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti,
5580 // except the first cases_nodes.len slots are a table that indexes payloads later in the array, with5587 // except the first cases_nodes.len slots are a table that indexes payloads later in the array, with
5581 // the special case index coming first, then scalar_case_len indexes, then multi_cases_len indexes5588 // the special case index coming first, then scalar_case_len indexes, then multi_cases_len indexes
5582 var payloads = ArrayListUnmanaged(u32){};5589 const payloads = &astgen.scratch;
5583 defer payloads.deinit(gpa);5590 const scratch_top = astgen.scratch.items.len;
5584 const scalar_case_table: u32 = @boolToInt(special_prong != .none);5591 const case_table_start = scratch_top;
5592 const scalar_case_table = case_table_start + @boolToInt(special_prong != .none);
5585 const multi_case_table = scalar_case_table + scalar_cases_len;5593 const multi_case_table = scalar_case_table + scalar_cases_len;
5586 const case_table_len = multi_case_table + multi_cases_len;5594 const case_table_end = multi_case_table + multi_cases_len;
5587 try payloads.resize(gpa, case_table_len);5595 try astgen.scratch.resize(gpa, case_table_end);
5596 defer astgen.scratch.items.len = scratch_top;
55885597
5589 var block_scope = parent_gz.makeSubBlock(scope);5598 var block_scope = parent_gz.makeSubBlock(scope);
5590 block_scope.setBreakResultLoc(rl);5599 block_scope.setBreakResultLoc(rl);
...@@ -5702,7 +5711,7 @@ fn switchExpr(...@@ -5702,7 +5711,7 @@ fn switchExpr(
5702 payloads.items[header_index + 1] = ranges_len;5711 payloads.items[header_index + 1] = ranges_len;
5703 break :blk header_index + 2;5712 break :blk header_index + 2;
5704 } else if (case_node == special_node) blk: {5713 } else if (case_node == special_node) blk: {
5705 payloads.items[0] = header_index;5714 payloads.items[case_table_start] = header_index;
5706 try payloads.resize(gpa, header_index + 1); // body_len5715 try payloads.resize(gpa, header_index + 1); // body_len
5707 break :blk header_index;5716 break :blk header_index;
5708 } else blk: {5717 } else blk: {
...@@ -5729,7 +5738,7 @@ fn switchExpr(...@@ -5729,7 +5738,7 @@ fn switchExpr(
57295738
5730 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.SwitchBlock).Struct.fields.len +5739 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.SwitchBlock).Struct.fields.len +
5731 @boolToInt(multi_cases_len != 0) +5740 @boolToInt(multi_cases_len != 0) +
5732 payloads.items.len - case_table_len);5741 payloads.items.len - case_table_end);
57335742
5734 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.SwitchBlock{5743 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.SwitchBlock{
5735 .operand = cond,5744 .operand = cond,
...@@ -5752,9 +5761,10 @@ fn switchExpr(...@@ -5752,9 +5761,10 @@ fn switchExpr(
5752 zir_datas[switch_block].pl_node.payload_index = payload_index;5761 zir_datas[switch_block].pl_node.payload_index = payload_index;
57535762
5754 const strat = rl.strategy(&block_scope);5763 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| {
5756 var body_len_index = start_index;5765 var body_len_index = start_index;
5757 var end_index = start_index;5766 var end_index = start_index;
5767 const table_index = case_table_start + i;
5758 if (table_index < scalar_case_table) {5768 if (table_index < scalar_case_table) {
5759 end_index += 1;5769 end_index += 1;
5760 } else if (table_index < multi_case_table) {5770 } else if (table_index < multi_case_table) {