| author | |
| committer | |
| log | 55e86b724a2ce60b777bd94d1203f243435727b7 |
| tree | cf799707230163746c9642c04a6545fd96a57657 |
| parent | fb4cb430e096d3142eeedb129425b01e80442516 |
5 files changed, 50 insertions(+), 19 deletions(-)
BRANCH_TODO+4| ... | ... | @@ -52,6 +52,10 @@ |
| 52 | 52 | - not sure why this happened, it's stage1 code?? |
| 53 | 53 | - search the behavior test diff for "TODO" |
| 54 | 54 | |
| 55 | * memory efficiency: add another representation for structs which use | |
| 56 | natural alignment for fields and do not have any comptime fields. this | |
| 57 | will save 16 bytes per struct field in the compilation. | |
| 58 | ||
| 55 | 59 | fn getAnonTypeName(mod: *Module, scope: *Scope, base_token: std.zig.ast.TokenIndex) ![]u8 { |
| 56 | 60 | // TODO add namespaces, generic function signatrues |
| 57 | 61 | const tree = scope.tree(); |
src/AstGen.zig+16-11| ... | ... | @@ -3220,7 +3220,9 @@ fn structDeclInner( |
| 3220 | 3220 | var fields_data = ArrayListUnmanaged(u32){}; |
| 3221 | 3221 | defer fields_data.deinit(gpa); |
| 3222 | 3222 | |
| 3223 | // We only need this if there are greater than 16 fields. | |
| 3223 | const bits_per_field = 4; | |
| 3224 | const fields_per_u32 = 32 / bits_per_field; | |
| 3225 | // We only need this if there are greater than fields_per_u32 fields. | |
| 3224 | 3226 | var bit_bag = ArrayListUnmanaged(u32){}; |
| 3225 | 3227 | defer bit_bag.deinit(gpa); |
| 3226 | 3228 | |
| ... | ... | @@ -3307,13 +3309,10 @@ fn structDeclInner( |
| 3307 | 3309 | }, |
| 3308 | 3310 | else => unreachable, |
| 3309 | 3311 | }; |
| 3310 | if (field_index % 16 == 0 and field_index != 0) { | |
| 3312 | if (field_index % fields_per_u32 == 0 and field_index != 0) { | |
| 3311 | 3313 | try bit_bag.append(gpa, cur_bit_bag); |
| 3312 | 3314 | cur_bit_bag = 0; |
| 3313 | 3315 | } |
| 3314 | if (member.comptime_token) |comptime_token| { | |
| 3315 | return astgen.failTok(comptime_token, "TODO implement comptime struct fields", .{}); | |
| 3316 | } | |
| 3317 | 3316 | try fields_data.ensureUnusedCapacity(gpa, 4); |
| 3318 | 3317 | |
| 3319 | 3318 | const field_name = try gz.identAsString(member.ast.name_token); |
| ... | ... | @@ -3324,9 +3323,13 @@ fn structDeclInner( |
| 3324 | 3323 | |
| 3325 | 3324 | const have_align = member.ast.align_expr != 0; |
| 3326 | 3325 | const have_value = member.ast.value_expr != 0; |
| 3327 | cur_bit_bag = (cur_bit_bag >> 2) | | |
| 3328 | (@as(u32, @boolToInt(have_align)) << 30) | | |
| 3329 | (@as(u32, @boolToInt(have_value)) << 31); | |
| 3326 | const is_comptime = member.comptime_token != null; | |
| 3327 | const unused = false; | |
| 3328 | cur_bit_bag = (cur_bit_bag >> bits_per_field) | | |
| 3329 | (@as(u32, @boolToInt(have_align)) << 28) | | |
| 3330 | (@as(u32, @boolToInt(have_value)) << 29) | | |
| 3331 | (@as(u32, @boolToInt(is_comptime)) << 30) | | |
| 3332 | (@as(u32, @boolToInt(unused)) << 31); | |
| 3330 | 3333 | |
| 3331 | 3334 | if (have_align) { |
| 3332 | 3335 | const align_inst = try expr(&block_scope, &block_scope.base, align_rl, member.ast.align_expr); |
| ... | ... | @@ -3335,14 +3338,16 @@ fn structDeclInner( |
| 3335 | 3338 | if (have_value) { |
| 3336 | 3339 | const default_inst = try expr(&block_scope, &block_scope.base, .{ .ty = field_type }, member.ast.value_expr); |
| 3337 | 3340 | fields_data.appendAssumeCapacity(@enumToInt(default_inst)); |
| 3341 | } else if (member.comptime_token) |comptime_token| { | |
| 3342 | return astgen.failTok(comptime_token, "comptime field without default initialization value", .{}); | |
| 3338 | 3343 | } |
| 3339 | 3344 | |
| 3340 | 3345 | field_index += 1; |
| 3341 | 3346 | } |
| 3342 | 3347 | { |
| 3343 | const empty_slot_count = 16 - (field_index % 16); | |
| 3344 | if (empty_slot_count < 16) { | |
| 3345 | cur_bit_bag >>= @intCast(u5, empty_slot_count * 2); | |
| 3348 | const empty_slot_count = fields_per_u32 - (field_index % fields_per_u32); | |
| 3349 | if (empty_slot_count < fields_per_u32) { | |
| 3350 | cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_field); | |
| 3346 | 3351 | } |
| 3347 | 3352 | } |
| 3348 | 3353 | { |
src/Module.zig+1| ... | ... | @@ -471,6 +471,7 @@ pub const Struct = struct { |
| 471 | 471 | abi_align: Value, |
| 472 | 472 | /// Uses `unreachable_value` to indicate no default. |
| 473 | 473 | default_val: Value, |
| 474 | is_comptime: bool, | |
| 474 | 475 | }; |
| 475 | 476 | |
| 476 | 477 | pub fn getFullyQualifiedName(s: *Struct, gpa: *Allocator) ![]u8 { |
src/Sema.zig+11-2| ... | ... | @@ -719,14 +719,16 @@ pub fn zirStructDecl( |
| 719 | 719 | sema.branch_count = struct_sema.branch_count; |
| 720 | 720 | sema.branch_quota = struct_sema.branch_quota; |
| 721 | 721 | } |
| 722 | const bit_bags_count = std.math.divCeil(usize, fields_len, 16) catch unreachable; | |
| 722 | const bits_per_field = 4; | |
| 723 | const fields_per_u32 = 32 / bits_per_field; | |
| 724 | const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; | |
| 723 | 725 | const body_end = extra_index + body.len; |
| 724 | 726 | extra_index += bit_bags_count; |
| 725 | 727 | var bit_bag_index: usize = body_end; |
| 726 | 728 | var cur_bit_bag: u32 = undefined; |
| 727 | 729 | var field_i: u32 = 0; |
| 728 | 730 | while (field_i < fields_len) : (field_i += 1) { |
| 729 | if (field_i % 16 == 0) { | |
| 731 | if (field_i % fields_per_u32 == 0) { | |
| 730 | 732 | cur_bit_bag = sema.code.extra[bit_bag_index]; |
| 731 | 733 | bit_bag_index += 1; |
| 732 | 734 | } |
| ... | ... | @@ -734,6 +736,12 @@ pub fn zirStructDecl( |
| 734 | 736 | cur_bit_bag >>= 1; |
| 735 | 737 | const has_default = @truncate(u1, cur_bit_bag) != 0; |
| 736 | 738 | cur_bit_bag >>= 1; |
| 739 | const is_comptime = @truncate(u1, cur_bit_bag) != 0; | |
| 740 | cur_bit_bag >>= 1; | |
| 741 | const unused = @truncate(u1, cur_bit_bag) != 0; | |
| 742 | cur_bit_bag >>= 1; | |
| 743 | ||
| 744 | _ = unused; | |
| 737 | 745 | |
| 738 | 746 | const field_name_zir = sema.code.nullTerminatedString(sema.code.extra[extra_index]); |
| 739 | 747 | extra_index += 1; |
| ... | ... | @@ -753,6 +761,7 @@ pub fn zirStructDecl( |
| 753 | 761 | .ty = field_ty, |
| 754 | 762 | .abi_align = Value.initTag(.abi_align_default), |
| 755 | 763 | .default_val = Value.initTag(.unreachable_value), |
| 764 | .is_comptime = is_comptime, | |
| 756 | 765 | }; |
| 757 | 766 | |
| 758 | 767 | if (has_align) { |
src/Zir.zig+18-6| ... | ... | @@ -2387,13 +2387,16 @@ pub const Inst = struct { |
| 2387 | 2387 | /// link_section: Ref, // if corresponding bit is set |
| 2388 | 2388 | /// } |
| 2389 | 2389 | /// 2. inst: Index // for every body_len |
| 2390 | /// 3. has_bits: u32 // for every 16 fields | |
| 2391 | /// - sets of 2 bits: | |
| 2392 | /// 0b0X: whether corresponding field has an align expression | |
| 2393 | /// 0bX0: whether corresponding field has a default expression | |
| 2390 | /// 3. flags: u32 // for every 8 fields | |
| 2391 | /// - sets of 4 bits: | |
| 2392 | /// 0b000X: whether corresponding field has an align expression | |
| 2393 | /// 0b00X0: whether corresponding field has a default expression | |
| 2394 | /// 0b0X00: whether corresponding field is comptime | |
| 2395 | /// 0bX000: unused | |
| 2394 | 2396 | /// 4. fields: { // for every fields_len |
| 2395 | 2397 | /// field_name: u32, |
| 2396 | 2398 | /// field_type: Ref, |
| 2399 | /// - if none, means `anytype`. | |
| 2397 | 2400 | /// align: Ref, // if corresponding bit is set |
| 2398 | 2401 | /// default_value: Ref, // if corresponding bit is set |
| 2399 | 2402 | /// } |
| ... | ... | @@ -3394,14 +3397,16 @@ const Writer = struct { |
| 3394 | 3397 | try stream.writeAll("}, {\n"); |
| 3395 | 3398 | } |
| 3396 | 3399 | |
| 3397 | const bit_bags_count = std.math.divCeil(usize, fields_len, 16) catch unreachable; | |
| 3400 | const bits_per_field = 4; | |
| 3401 | const fields_per_u32 = 32 / bits_per_field; | |
| 3402 | const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; | |
| 3398 | 3403 | const body_end = extra_index; |
| 3399 | 3404 | extra_index += bit_bags_count; |
| 3400 | 3405 | var bit_bag_index: usize = body_end; |
| 3401 | 3406 | var cur_bit_bag: u32 = undefined; |
| 3402 | 3407 | var field_i: u32 = 0; |
| 3403 | 3408 | while (field_i < fields_len) : (field_i += 1) { |
| 3404 | if (field_i % 16 == 0) { | |
| 3409 | if (field_i % fields_per_u32 == 0) { | |
| 3405 | 3410 | cur_bit_bag = self.code.extra[bit_bag_index]; |
| 3406 | 3411 | bit_bag_index += 1; |
| 3407 | 3412 | } |
| ... | ... | @@ -3409,6 +3414,12 @@ const Writer = struct { |
| 3409 | 3414 | cur_bit_bag >>= 1; |
| 3410 | 3415 | const has_default = @truncate(u1, cur_bit_bag) != 0; |
| 3411 | 3416 | cur_bit_bag >>= 1; |
| 3417 | const is_comptime = @truncate(u1, cur_bit_bag) != 0; | |
| 3418 | cur_bit_bag >>= 1; | |
| 3419 | const unused = @truncate(u1, cur_bit_bag) != 0; | |
| 3420 | cur_bit_bag >>= 1; | |
| 3421 | ||
| 3422 | _ = unused; | |
| 3412 | 3423 | |
| 3413 | 3424 | const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]); |
| 3414 | 3425 | extra_index += 1; |
| ... | ... | @@ -3416,6 +3427,7 @@ const Writer = struct { |
| 3416 | 3427 | extra_index += 1; |
| 3417 | 3428 | |
| 3418 | 3429 | try stream.writeByteNTimes(' ', self.indent); |
| 3430 | try self.writeFlag(stream, "comptime ", is_comptime); | |
| 3419 | 3431 | try stream.print("{}: ", .{std.zig.fmtId(field_name)}); |
| 3420 | 3432 | try self.writeInstRef(stream, field_type); |
| 3421 | 3433 |