| author | |
| committer | |
| log | 8ebfdc14f68521ac129ee7d2c3f4e7250e4e7418 |
| tree | 7a20ca7752b10da7e811a52927b6d1ba0869e893 |
| parent | c66b48194ff83eb5b1774a1428461f5fc94dcd7d |
New ZIR instructions:
* struct_decl_packed
* struct_decl_extern
New TZIR instruction: struct_field_ptr
Introduce `Module.Struct`. It uses `Value` to store default values and
abi alignments.
Implemented Sema.analyzeStructFieldPtr and zirStructDecl.
Some stuff I changed from `@panic("TODO")` to `log.warn("TODO")`.
It's becoming more clear that we need the lazy value mechanism soon;
Type is becoming unruly, and some of these functions have too much logic
given that they don't have any context for memory management or error
reporting.8 files changed, 304 insertions(+), 16 deletions(-)
src/AstGen.zig+9-2| ... | @@ -1322,6 +1322,8 @@ fn blockExprStmts( | ... | @@ -1322,6 +1322,8 @@ fn blockExprStmts( |
| 1322 | .switch_capture_else_ref, | 1322 | .switch_capture_else_ref, |
| 1323 | .struct_init_empty, | 1323 | .struct_init_empty, |
| 1324 | .struct_decl, | 1324 | .struct_decl, |
| 1325 | .struct_decl_packed, | ||
| 1326 | .struct_decl_extern, | ||
| 1325 | .union_decl, | 1327 | .union_decl, |
| 1326 | .enum_decl, | 1328 | .enum_decl, |
| 1327 | .opaque_decl, | 1329 | .opaque_decl, |
| ... | @@ -1789,8 +1791,13 @@ fn containerDecl( | ... | @@ -1789,8 +1791,13 @@ fn containerDecl( |
| 1789 | 1791 | ||
| 1790 | switch (token_tags[container_decl.ast.main_token]) { | 1792 | switch (token_tags[container_decl.ast.main_token]) { |
| 1791 | .keyword_struct => { | 1793 | .keyword_struct => { |
| 1794 | const tag = if (container_decl.layout_token) |t| switch (token_tags[t]) { | ||
| 1795 | .keyword_packed => zir.Inst.Tag.struct_decl_packed, | ||
| 1796 | .keyword_extern => zir.Inst.Tag.struct_decl_extern, | ||
| 1797 | else => unreachable, | ||
| 1798 | } else zir.Inst.Tag.struct_decl; | ||
| 1792 | if (container_decl.ast.members.len == 0) { | 1799 | if (container_decl.ast.members.len == 0) { |
| 1793 | const result = try gz.addPlNode(.struct_decl, node, zir.Inst.StructDecl{ | 1800 | const result = try gz.addPlNode(tag, node, zir.Inst.StructDecl{ |
| 1794 | .fields_len = 0, | 1801 | .fields_len = 0, |
| 1795 | }); | 1802 | }); |
| 1796 | return rvalue(gz, scope, rl, result, node); | 1803 | return rvalue(gz, scope, rl, result, node); |
| ... | @@ -1856,7 +1863,7 @@ fn containerDecl( | ... | @@ -1856,7 +1863,7 @@ fn containerDecl( |
| 1856 | const empty_slot_count = 16 - ((member_index - 1) % 16); | 1863 | const empty_slot_count = 16 - ((member_index - 1) % 16); |
| 1857 | cur_bit_bag >>= @intCast(u5, empty_slot_count * 2); | 1864 | cur_bit_bag >>= @intCast(u5, empty_slot_count * 2); |
| 1858 | 1865 | ||
| 1859 | const result = try gz.addPlNode(.struct_decl, node, zir.Inst.StructDecl{ | 1866 | const result = try gz.addPlNode(tag, node, zir.Inst.StructDecl{ |
| 1860 | .fields_len = @intCast(u32, container_decl.ast.members.len), | 1867 | .fields_len = @intCast(u32, container_decl.ast.members.len), |
| 1861 | }); | 1868 | }); |
| 1862 | try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len + | 1869 | try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len + |
src/Module.zig+41| ... | @@ -356,6 +356,25 @@ pub const ErrorSet = struct { | ... | @@ -356,6 +356,25 @@ pub const ErrorSet = struct { |
| 356 | names_ptr: [*]const []const u8, | 356 | names_ptr: [*]const []const u8, |
| 357 | }; | 357 | }; |
| 358 | 358 | ||
| 359 | /// Represents the data that a struct declaration provides. | ||
| 360 | pub const Struct = struct { | ||
| 361 | owner_decl: *Decl, | ||
| 362 | /// Set of field names in declaration order. | ||
| 363 | fields: std.StringArrayHashMapUnmanaged(Field), | ||
| 364 | /// Represents the declarations inside this struct. | ||
| 365 | container: Scope.Container, | ||
| 366 | |||
| 367 | /// Offset from Decl node index, points to the struct AST node. | ||
| 368 | node_offset: i32, | ||
| 369 | |||
| 370 | pub const Field = struct { | ||
| 371 | ty: Type, | ||
| 372 | abi_align: Value, | ||
| 373 | /// Uses `unreachable_value` to indicate no default. | ||
| 374 | default_val: Value, | ||
| 375 | }; | ||
| 376 | }; | ||
| 377 | |||
| 359 | /// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator. | 378 | /// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator. |
| 360 | /// Extern functions do not have this data structure; they are represented by | 379 | /// Extern functions do not have this data structure; they are represented by |
| 361 | /// the `Decl` only, with a `Value` tag of `extern_fn`. | 380 | /// the `Decl` only, with a `Value` tag of `extern_fn`. |
| ... | @@ -822,6 +841,7 @@ pub const Scope = struct { | ... | @@ -822,6 +841,7 @@ pub const Scope = struct { |
| 822 | try block.instructions.append(block.sema.gpa, &inst.base); | 841 | try block.instructions.append(block.sema.gpa, &inst.base); |
| 823 | return &inst.base; | 842 | return &inst.base; |
| 824 | } | 843 | } |
| 844 | |||
| 825 | pub fn addBr( | 845 | pub fn addBr( |
| 826 | scope_block: *Scope.Block, | 846 | scope_block: *Scope.Block, |
| 827 | src: LazySrcLoc, | 847 | src: LazySrcLoc, |
| ... | @@ -920,6 +940,27 @@ pub const Scope = struct { | ... | @@ -920,6 +940,27 @@ pub const Scope = struct { |
| 920 | try block.instructions.append(block.sema.gpa, &inst.base); | 940 | try block.instructions.append(block.sema.gpa, &inst.base); |
| 921 | return &inst.base; | 941 | return &inst.base; |
| 922 | } | 942 | } |
| 943 | |||
| 944 | pub fn addStructFieldPtr( | ||
| 945 | block: *Scope.Block, | ||
| 946 | src: LazySrcLoc, | ||
| 947 | ty: Type, | ||
| 948 | struct_ptr: *ir.Inst, | ||
| 949 | field_index: u32, | ||
| 950 | ) !*ir.Inst { | ||
| 951 | const inst = try block.sema.arena.create(ir.Inst.StructFieldPtr); | ||
| 952 | inst.* = .{ | ||
| 953 | .base = .{ | ||
| 954 | .tag = .struct_field_ptr, | ||
| 955 | .ty = ty, | ||
| 956 | .src = src, | ||
| 957 | }, | ||
| 958 | .struct_ptr = struct_ptr, | ||
| 959 | .field_index = field_index, | ||
| 960 | }; | ||
| 961 | try block.instructions.append(block.sema.gpa, &inst.base); | ||
| 962 | return &inst.base; | ||
| 963 | } | ||
| 923 | }; | 964 | }; |
| 924 | 965 | ||
| 925 | /// This is a temporary structure; references to it are valid only | 966 | /// This is a temporary structure; references to it are valid only |
src/Sema.zig+118-10| ... | @@ -261,7 +261,9 @@ pub fn analyzeBody( | ... | @@ -261,7 +261,9 @@ pub fn analyzeBody( |
| 261 | .xor => try sema.zirBitwise(block, inst, .xor), | 261 | .xor => try sema.zirBitwise(block, inst, .xor), |
| 262 | .struct_init_empty => try sema.zirStructInitEmpty(block, inst), | 262 | .struct_init_empty => try sema.zirStructInitEmpty(block, inst), |
| 263 | 263 | ||
| 264 | .struct_decl => try sema.zirStructDecl(block, inst), | 264 | .struct_decl => try sema.zirStructDecl(block, inst, .Auto), |
| 265 | .struct_decl_packed => try sema.zirStructDecl(block, inst, .Packed), | ||
| 266 | .struct_decl_extern => try sema.zirStructDecl(block, inst, .Extern), | ||
| 265 | .enum_decl => try sema.zirEnumDecl(block, inst), | 267 | .enum_decl => try sema.zirEnumDecl(block, inst), |
| 266 | .union_decl => try sema.zirUnionDecl(block, inst), | 268 | .union_decl => try sema.zirUnionDecl(block, inst), |
| 267 | .opaque_decl => try sema.zirOpaqueDecl(block, inst), | 269 | .opaque_decl => try sema.zirOpaqueDecl(block, inst), |
| ... | @@ -520,21 +522,98 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In | ... | @@ -520,21 +522,98 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In |
| 520 | return sema.mod.fail(&block.base, sema.src, "TODO implement zirCoerceResultPtr", .{}); | 522 | return sema.mod.fail(&block.base, sema.src, "TODO implement zirCoerceResultPtr", .{}); |
| 521 | } | 523 | } |
| 522 | 524 | ||
| 523 | fn zirStructDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | 525 | fn zirStructDecl( |
| 526 | sema: *Sema, | ||
| 527 | block: *Scope.Block, | ||
| 528 | inst: zir.Inst.Index, | ||
| 529 | layout: std.builtin.TypeInfo.ContainerLayout, | ||
| 530 | ) InnerError!*Inst { | ||
| 524 | const tracy = trace(@src()); | 531 | const tracy = trace(@src()); |
| 525 | defer tracy.end(); | 532 | defer tracy.end(); |
| 526 | 533 | ||
| 534 | const gpa = sema.gpa; | ||
| 527 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 535 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 528 | const src = inst_data.src(); | 536 | const src = inst_data.src(); |
| 529 | const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index); | 537 | const extra = sema.code.extraData(zir.Inst.StructDecl, inst_data.payload_index); |
| 538 | const fields_len = extra.data.fields_len; | ||
| 539 | const bit_bags_count = std.math.divCeil(usize, fields_len, 16) catch unreachable; | ||
| 540 | |||
| 541 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); | ||
| 542 | errdefer new_decl_arena.deinit(); | ||
| 543 | |||
| 544 | var fields_map: std.StringArrayHashMapUnmanaged(Module.Struct.Field) = .{}; | ||
| 545 | try fields_map.ensureCapacity(&new_decl_arena.allocator, fields_len); | ||
| 530 | 546 | ||
| 531 | return sema.mod.fail(&block.base, sema.src, "TODO implement zirStructDecl", .{}); | 547 | { |
| 548 | var field_index: usize = extra.end + bit_bags_count; | ||
| 549 | var bit_bag_index: usize = extra.end; | ||
| 550 | var cur_bit_bag: u32 = undefined; | ||
| 551 | var field_i: u32 = 0; | ||
| 552 | while (field_i < fields_len) : (field_i += 1) { | ||
| 553 | if (field_i % 16 == 0) { | ||
| 554 | cur_bit_bag = sema.code.extra[bit_bag_index]; | ||
| 555 | bit_bag_index += 1; | ||
| 556 | } | ||
| 557 | const has_align = @truncate(u1, cur_bit_bag) != 0; | ||
| 558 | cur_bit_bag >>= 1; | ||
| 559 | const has_default = @truncate(u1, cur_bit_bag) != 0; | ||
| 560 | cur_bit_bag >>= 1; | ||
| 561 | |||
| 562 | const field_name_zir = sema.code.nullTerminatedString(sema.code.extra[field_index]); | ||
| 563 | field_index += 1; | ||
| 564 | const field_type_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]); | ||
| 565 | field_index += 1; | ||
| 566 | |||
| 567 | // This string needs to outlive the ZIR code. | ||
| 568 | const field_name = try new_decl_arena.allocator.dupe(u8, field_name_zir); | ||
| 569 | // TODO: if we need to report an error here, use a source location | ||
| 570 | // that points to this type expression rather than the struct. | ||
| 571 | // But only resolve the source location if we need to emit a compile error. | ||
| 572 | const field_ty = try sema.resolveType(block, src, field_type_ref); | ||
| 573 | |||
| 574 | const gop = fields_map.getOrPutAssumeCapacity(field_name); | ||
| 575 | assert(!gop.found_existing); | ||
| 576 | gop.entry.value = .{ | ||
| 577 | .ty = field_ty, | ||
| 578 | .abi_align = Value.initTag(.abi_align_default), | ||
| 579 | .default_val = Value.initTag(.unreachable_value), | ||
| 580 | }; | ||
| 581 | |||
| 582 | if (has_align) { | ||
| 583 | const align_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]); | ||
| 584 | field_index += 1; | ||
| 585 | // TODO: if we need to report an error here, use a source location | ||
| 586 | // that points to this alignment expression rather than the struct. | ||
| 587 | // But only resolve the source location if we need to emit a compile error. | ||
| 588 | gop.entry.value.abi_align = (try sema.resolveInstConst(block, src, align_ref)).val; | ||
| 589 | } | ||
| 590 | if (has_default) { | ||
| 591 | const default_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]); | ||
| 592 | field_index += 1; | ||
| 593 | // TODO: if we need to report an error here, use a source location | ||
| 594 | // that points to this default value expression rather than the struct. | ||
| 595 | // But only resolve the source location if we need to emit a compile error. | ||
| 596 | gop.entry.value.default_val = (try sema.resolveInstConst(block, src, default_ref)).val; | ||
| 597 | } | ||
| 598 | } | ||
| 599 | } | ||
| 532 | 600 | ||
| 533 | //const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{ | 601 | const struct_obj = try new_decl_arena.allocator.create(Module.Struct); |
| 534 | // .ty = decl_ty, | 602 | const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj); |
| 535 | // .val = decl_val, | 603 | struct_obj.* = .{ |
| 536 | //}); | 604 | .owner_decl = sema.owner_decl, |
| 537 | //return sema.analyzeDeclVal(block, src, new_decl); | 605 | .fields = fields_map, |
| 606 | .node_offset = inst_data.src_node, | ||
| 607 | .container = .{ | ||
| 608 | .ty = struct_ty, | ||
| 609 | .file_scope = block.getFileScope(), | ||
| 610 | }, | ||
| 611 | }; | ||
| 612 | const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{ | ||
| 613 | .ty = Type.initTag(.type), | ||
| 614 | .val = try Value.Tag.ty.create(gpa, struct_ty), | ||
| 615 | }); | ||
| 616 | return sema.analyzeDeclVal(block, src, new_decl); | ||
| 538 | } | 617 | } |
| 539 | 618 | ||
| 540 | fn zirEnumDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | 619 | fn zirEnumDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { |
| ... | @@ -763,7 +842,7 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Ind | ... | @@ -763,7 +842,7 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Ind |
| 763 | const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index); | 842 | const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index); |
| 764 | const instrs = sema.code.extra[extra.end..][0..extra.data.body_len]; | 843 | const instrs = sema.code.extra[extra.end..][0..extra.data.body_len]; |
| 765 | 844 | ||
| 766 | return sema.mod.fail(&block.base, src, "TODO implement zirValidateStructInitPtr", .{}); | 845 | log.warn("TODO implement zirValidateStructInitPtr (compile errors for missing/dupe fields)", .{}); |
| 767 | } | 846 | } |
| 768 | 847 | ||
| 769 | fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void { | 848 | fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void { |
| ... | @@ -4141,11 +4220,40 @@ fn namedFieldPtr( | ... | @@ -4141,11 +4220,40 @@ fn namedFieldPtr( |
| 4141 | else => return sema.mod.fail(&block.base, src, "type '{}' does not support field access", .{child_type}), | 4220 | else => return sema.mod.fail(&block.base, src, "type '{}' does not support field access", .{child_type}), |
| 4142 | } | 4221 | } |
| 4143 | }, | 4222 | }, |
| 4223 | .Struct => return sema.analyzeStructFieldPtr(block, src, object_ptr, field_name, field_name_src, elem_ty), | ||
| 4144 | else => {}, | 4224 | else => {}, |
| 4145 | } | 4225 | } |
| 4146 | return sema.mod.fail(&block.base, src, "type '{}' does not support field access", .{elem_ty}); | 4226 | return sema.mod.fail(&block.base, src, "type '{}' does not support field access", .{elem_ty}); |
| 4147 | } | 4227 | } |
| 4148 | 4228 | ||
| 4229 | fn analyzeStructFieldPtr( | ||
| 4230 | sema: *Sema, | ||
| 4231 | block: *Scope.Block, | ||
| 4232 | src: LazySrcLoc, | ||
| 4233 | struct_ptr: *Inst, | ||
| 4234 | field_name: []const u8, | ||
| 4235 | field_name_src: LazySrcLoc, | ||
| 4236 | elem_ty: Type, | ||
| 4237 | ) InnerError!*Inst { | ||
| 4238 | const mod = sema.mod; | ||
| 4239 | const arena = sema.arena; | ||
| 4240 | assert(elem_ty.zigTypeTag() == .Struct); | ||
| 4241 | |||
| 4242 | const struct_obj = elem_ty.castTag(.@"struct").?.data; | ||
| 4243 | |||
| 4244 | const field_index = struct_obj.fields.getIndex(field_name) orelse { | ||
| 4245 | // TODO note: struct S declared here | ||
| 4246 | return mod.fail(&block.base, field_name_src, "no field named '{s}' in struct '{}'", .{ | ||
| 4247 | field_name, elem_ty, | ||
| 4248 | }); | ||
| 4249 | }; | ||
| 4250 | const field = struct_obj.fields.entries.items[field_index].value; | ||
| 4251 | const ptr_field_ty = try mod.simplePtrType(arena, field.ty, true, .One); | ||
| 4252 | // TODO comptime field access | ||
| 4253 | try sema.requireRuntimeBlock(block, src); | ||
| 4254 | return block.addStructFieldPtr(src, ptr_field_ty, struct_ptr, @intCast(u32, field_index)); | ||
| 4255 | } | ||
| 4256 | |||
| 4149 | fn elemPtr( | 4257 | fn elemPtr( |
| 4150 | sema: *Sema, | 4258 | sema: *Sema, |
| 4151 | block: *Scope.Block, | 4259 | block: *Scope.Block, |
src/codegen.zig+5| ... | @@ -910,6 +910,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -910,6 +910,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 910 | .ret => return self.genRet(inst.castTag(.ret).?), | 910 | .ret => return self.genRet(inst.castTag(.ret).?), |
| 911 | .retvoid => return self.genRetVoid(inst.castTag(.retvoid).?), | 911 | .retvoid => return self.genRetVoid(inst.castTag(.retvoid).?), |
| 912 | .store => return self.genStore(inst.castTag(.store).?), | 912 | .store => return self.genStore(inst.castTag(.store).?), |
| 913 | .struct_field_ptr => return self.genStructFieldPtr(inst.castTag(.struct_field_ptr).?), | ||
| 913 | .sub => return self.genSub(inst.castTag(.sub).?), | 914 | .sub => return self.genSub(inst.castTag(.sub).?), |
| 914 | .subwrap => return self.genSubWrap(inst.castTag(.subwrap).?), | 915 | .subwrap => return self.genSubWrap(inst.castTag(.subwrap).?), |
| 915 | .switchbr => return self.genSwitch(inst.castTag(.switchbr).?), | 916 | .switchbr => return self.genSwitch(inst.castTag(.switchbr).?), |
| ... | @@ -1403,6 +1404,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1403,6 +1404,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1403 | return .none; | 1404 | return .none; |
| 1404 | } | 1405 | } |
| 1405 | 1406 | ||
| 1407 | fn genStructFieldPtr(self: *Self, inst: *ir.Inst.StructFieldPtr) !MCValue { | ||
| 1408 | return self.fail(inst.base.src, "TODO implement codegen struct_field_ptr", .{}); | ||
| 1409 | } | ||
| 1410 | |||
| 1406 | fn genSub(self: *Self, inst: *ir.Inst.BinOp) !MCValue { | 1411 | fn genSub(self: *Self, inst: *ir.Inst.BinOp) !MCValue { |
| 1407 | // No side effects, so if it's unreferenced, do nothing. | 1412 | // No side effects, so if it's unreferenced, do nothing. |
| 1408 | if (inst.base.isUnused()) | 1413 | if (inst.base.isUnused()) |
src/ir.zig+40| ... | @@ -137,6 +137,8 @@ pub const Inst = struct { | ... | @@ -137,6 +137,8 @@ pub const Inst = struct { |
| 137 | wrap_errunion_err, | 137 | wrap_errunion_err, |
| 138 | xor, | 138 | xor, |
| 139 | switchbr, | 139 | switchbr, |
| 140 | /// Given a pointer to a struct and a field index, returns a pointer to the field. | ||
| 141 | struct_field_ptr, | ||
| 140 | 142 | ||
| 141 | pub fn Type(tag: Tag) type { | 143 | pub fn Type(tag: Tag) type { |
| 142 | return switch (tag) { | 144 | return switch (tag) { |
| ... | @@ -204,6 +206,7 @@ pub const Inst = struct { | ... | @@ -204,6 +206,7 @@ pub const Inst = struct { |
| 204 | .constant => Constant, | 206 | .constant => Constant, |
| 205 | .loop => Loop, | 207 | .loop => Loop, |
| 206 | .varptr => VarPtr, | 208 | .varptr => VarPtr, |
| 209 | .struct_field_ptr => StructFieldPtr, | ||
| 207 | .switchbr => SwitchBr, | 210 | .switchbr => SwitchBr, |
| 208 | .dbg_stmt => DbgStmt, | 211 | .dbg_stmt => DbgStmt, |
| 209 | }; | 212 | }; |
| ... | @@ -552,6 +555,27 @@ pub const Inst = struct { | ... | @@ -552,6 +555,27 @@ pub const Inst = struct { |
| 552 | } | 555 | } |
| 553 | }; | 556 | }; |
| 554 | 557 | ||
| 558 | pub const StructFieldPtr = struct { | ||
| 559 | pub const base_tag = Tag.struct_field_ptr; | ||
| 560 | |||
| 561 | base: Inst, | ||
| 562 | struct_ptr: *Inst, | ||
| 563 | field_index: usize, | ||
| 564 | |||
| 565 | pub fn operandCount(self: *const StructFieldPtr) usize { | ||
| 566 | return 1; | ||
| 567 | } | ||
| 568 | pub fn getOperand(self: *const StructFieldPtr, index: usize) ?*Inst { | ||
| 569 | var i = index; | ||
| 570 | |||
| 571 | if (i < 1) | ||
| 572 | return self.struct_ptr; | ||
| 573 | i -= 1; | ||
| 574 | |||
| 575 | return null; | ||
| 576 | } | ||
| 577 | }; | ||
| 578 | |||
| 555 | pub const SwitchBr = struct { | 579 | pub const SwitchBr = struct { |
| 556 | pub const base_tag = Tag.switchbr; | 580 | pub const base_tag = Tag.switchbr; |
| 557 | 581 | ||
| ... | @@ -794,6 +818,10 @@ const DumpTzir = struct { | ... | @@ -794,6 +818,10 @@ const DumpTzir = struct { |
| 794 | try dtz.findConst(arg); | 818 | try dtz.findConst(arg); |
| 795 | } | 819 | } |
| 796 | }, | 820 | }, |
| 821 | .struct_field_ptr => { | ||
| 822 | const struct_field_ptr = inst.castTag(.struct_field_ptr).?; | ||
| 823 | try dtz.findConst(struct_field_ptr.struct_ptr); | ||
| 824 | }, | ||
| 797 | 825 | ||
| 798 | // TODO fill out this debug printing | 826 | // TODO fill out this debug printing |
| 799 | .assembly, | 827 | .assembly, |
| ... | @@ -1067,6 +1095,18 @@ const DumpTzir = struct { | ... | @@ -1067,6 +1095,18 @@ const DumpTzir = struct { |
| 1067 | } | 1095 | } |
| 1068 | }, | 1096 | }, |
| 1069 | 1097 | ||
| 1098 | .struct_field_ptr => { | ||
| 1099 | const struct_field_ptr = inst.castTag(.struct_field_ptr).?; | ||
| 1100 | const kinky = try dtz.writeInst(writer, struct_field_ptr.struct_ptr); | ||
| 1101 | if (kinky != null) { | ||
| 1102 | try writer.print("{d}) // Instruction does not dominate all uses!\n", .{ | ||
| 1103 | struct_field_ptr.field_index, | ||
| 1104 | }); | ||
| 1105 | } else { | ||
| 1106 | try writer.print("{d})\n", .{struct_field_ptr.field_index}); | ||
| 1107 | } | ||
| 1108 | }, | ||
| 1109 | |||
| 1070 | // TODO fill out this debug printing | 1110 | // TODO fill out this debug printing |
| 1071 | .assembly, | 1111 | .assembly, |
| 1072 | .constant, | 1112 | .constant, |
src/type.zig+63-2| ... | @@ -4,6 +4,7 @@ const assert = std.debug.assert; | ... | @@ -4,6 +4,7 @@ const assert = std.debug.assert; |
| 4 | const Allocator = std.mem.Allocator; | 4 | const Allocator = std.mem.Allocator; |
| 5 | const Target = std.Target; | 5 | const Target = std.Target; |
| 6 | const Module = @import("Module.zig"); | 6 | const Module = @import("Module.zig"); |
| 7 | const log = std.log.scoped(.Type); | ||
| 7 | 8 | ||
| 8 | /// This is the raw data, with no bookkeeping, no memory awareness, no de-duplication. | 9 | /// This is the raw data, with no bookkeeping, no memory awareness, no de-duplication. |
| 9 | /// It's important for this type to be small. | 10 | /// It's important for this type to be small. |
| ... | @@ -94,6 +95,7 @@ pub const Type = extern union { | ... | @@ -94,6 +95,7 @@ pub const Type = extern union { |
| 94 | 95 | ||
| 95 | .empty_struct => return .Struct, | 96 | .empty_struct => return .Struct, |
| 96 | .empty_struct_literal => return .Struct, | 97 | .empty_struct_literal => return .Struct, |
| 98 | .@"struct" => return .Struct, | ||
| 97 | 99 | ||
| 98 | .var_args_param => unreachable, // can be any type | 100 | .var_args_param => unreachable, // can be any type |
| 99 | } | 101 | } |
| ... | @@ -611,7 +613,7 @@ pub const Type = extern union { | ... | @@ -611,7 +613,7 @@ pub const Type = extern union { |
| 611 | .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), | 613 | .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), |
| 612 | .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name), | 614 | .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name), |
| 613 | .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope), | 615 | .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope), |
| 614 | 616 | .@"struct" => return self.copyPayloadShallow(allocator, Payload.Struct), | |
| 615 | .@"opaque" => return self.copyPayloadShallow(allocator, Payload.Opaque), | 617 | .@"opaque" => return self.copyPayloadShallow(allocator, Payload.Opaque), |
| 616 | } | 618 | } |
| 617 | } | 619 | } |
| ... | @@ -675,6 +677,7 @@ pub const Type = extern union { | ... | @@ -675,6 +677,7 @@ pub const Type = extern union { |
| 675 | .@"undefined" => return out_stream.writeAll("@Type(.Undefined)"), | 677 | .@"undefined" => return out_stream.writeAll("@Type(.Undefined)"), |
| 676 | 678 | ||
| 677 | .empty_struct, .empty_struct_literal => return out_stream.writeAll("struct {}"), | 679 | .empty_struct, .empty_struct_literal => return out_stream.writeAll("struct {}"), |
| 680 | .@"struct" => return out_stream.writeAll("(struct)"), | ||
| 678 | .anyerror_void_error_union => return out_stream.writeAll("anyerror!void"), | 681 | .anyerror_void_error_union => return out_stream.writeAll("anyerror!void"), |
| 679 | .const_slice_u8 => return out_stream.writeAll("[]const u8"), | 682 | .const_slice_u8 => return out_stream.writeAll("[]const u8"), |
| 680 | .fn_noreturn_no_args => return out_stream.writeAll("fn() noreturn"), | 683 | .fn_noreturn_no_args => return out_stream.writeAll("fn() noreturn"), |
| ... | @@ -940,6 +943,18 @@ pub const Type = extern union { | ... | @@ -940,6 +943,18 @@ pub const Type = extern union { |
| 940 | .error_set, | 943 | .error_set, |
| 941 | .error_set_single, | 944 | .error_set_single, |
| 942 | => true, | 945 | => true, |
| 946 | |||
| 947 | .@"struct" => { | ||
| 948 | // TODO introduce lazy value mechanism | ||
| 949 | const struct_obj = self.castTag(.@"struct").?.data; | ||
| 950 | for (struct_obj.fields.entries.items) |entry| { | ||
| 951 | if (entry.value.ty.hasCodeGenBits()) | ||
| 952 | return true; | ||
| 953 | } else { | ||
| 954 | return false; | ||
| 955 | } | ||
| 956 | }, | ||
| 957 | |||
| 943 | // TODO lazy types | 958 | // TODO lazy types |
| 944 | .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0, | 959 | .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0, |
| 945 | .array_u8 => self.arrayLen() != 0, | 960 | .array_u8 => self.arrayLen() != 0, |
| ... | @@ -1100,6 +1115,10 @@ pub const Type = extern union { | ... | @@ -1100,6 +1115,10 @@ pub const Type = extern union { |
| 1100 | @panic("TODO abiAlignment error union"); | 1115 | @panic("TODO abiAlignment error union"); |
| 1101 | }, | 1116 | }, |
| 1102 | 1117 | ||
| 1118 | .@"struct" => { | ||
| 1119 | @panic("TODO abiAlignment struct"); | ||
| 1120 | }, | ||
| 1121 | |||
| 1103 | .c_void, | 1122 | .c_void, |
| 1104 | .void, | 1123 | .void, |
| 1105 | .type, | 1124 | .type, |
| ... | @@ -1144,6 +1163,10 @@ pub const Type = extern union { | ... | @@ -1144,6 +1163,10 @@ pub const Type = extern union { |
| 1144 | .@"opaque" => unreachable, | 1163 | .@"opaque" => unreachable, |
| 1145 | .var_args_param => unreachable, | 1164 | .var_args_param => unreachable, |
| 1146 | 1165 | ||
| 1166 | .@"struct" => { | ||
| 1167 | @panic("TODO abiSize struct"); | ||
| 1168 | }, | ||
| 1169 | |||
| 1147 | .u8, | 1170 | .u8, |
| 1148 | .i8, | 1171 | .i8, |
| 1149 | .bool, | 1172 | .bool, |
| ... | @@ -1316,6 +1339,7 @@ pub const Type = extern union { | ... | @@ -1316,6 +1339,7 @@ pub const Type = extern union { |
| 1316 | .anyerror_void_error_union, | 1339 | .anyerror_void_error_union, |
| 1317 | .error_set, | 1340 | .error_set, |
| 1318 | .error_set_single, | 1341 | .error_set_single, |
| 1342 | .@"struct", | ||
| 1319 | .empty_struct, | 1343 | .empty_struct, |
| 1320 | .empty_struct_literal, | 1344 | .empty_struct_literal, |
| 1321 | .@"opaque", | 1345 | .@"opaque", |
| ... | @@ -1393,6 +1417,7 @@ pub const Type = extern union { | ... | @@ -1393,6 +1417,7 @@ pub const Type = extern union { |
| 1393 | .empty_struct, | 1417 | .empty_struct, |
| 1394 | .empty_struct_literal, | 1418 | .empty_struct_literal, |
| 1395 | .@"opaque", | 1419 | .@"opaque", |
| 1420 | .@"struct", | ||
| 1396 | .var_args_param, | 1421 | .var_args_param, |
| 1397 | => unreachable, | 1422 | => unreachable, |
| 1398 | 1423 | ||
| ... | @@ -1487,6 +1512,7 @@ pub const Type = extern union { | ... | @@ -1487,6 +1512,7 @@ pub const Type = extern union { |
| 1487 | .empty_struct_literal, | 1512 | .empty_struct_literal, |
| 1488 | .inferred_alloc_const, | 1513 | .inferred_alloc_const, |
| 1489 | .inferred_alloc_mut, | 1514 | .inferred_alloc_mut, |
| 1515 | .@"struct", | ||
| 1490 | .@"opaque", | 1516 | .@"opaque", |
| 1491 | .var_args_param, | 1517 | .var_args_param, |
| 1492 | => false, | 1518 | => false, |
| ... | @@ -1564,6 +1590,7 @@ pub const Type = extern union { | ... | @@ -1564,6 +1590,7 @@ pub const Type = extern union { |
| 1564 | .empty_struct_literal, | 1590 | .empty_struct_literal, |
| 1565 | .inferred_alloc_const, | 1591 | .inferred_alloc_const, |
| 1566 | .inferred_alloc_mut, | 1592 | .inferred_alloc_mut, |
| 1593 | .@"struct", | ||
| 1567 | .@"opaque", | 1594 | .@"opaque", |
| 1568 | .var_args_param, | 1595 | .var_args_param, |
| 1569 | => false, | 1596 | => false, |
| ... | @@ -1650,6 +1677,7 @@ pub const Type = extern union { | ... | @@ -1650,6 +1677,7 @@ pub const Type = extern union { |
| 1650 | .empty_struct_literal, | 1677 | .empty_struct_literal, |
| 1651 | .inferred_alloc_const, | 1678 | .inferred_alloc_const, |
| 1652 | .inferred_alloc_mut, | 1679 | .inferred_alloc_mut, |
| 1680 | .@"struct", | ||
| 1653 | .@"opaque", | 1681 | .@"opaque", |
| 1654 | .var_args_param, | 1682 | .var_args_param, |
| 1655 | => false, | 1683 | => false, |
| ... | @@ -1731,6 +1759,7 @@ pub const Type = extern union { | ... | @@ -1731,6 +1759,7 @@ pub const Type = extern union { |
| 1731 | .empty_struct_literal, | 1759 | .empty_struct_literal, |
| 1732 | .inferred_alloc_const, | 1760 | .inferred_alloc_const, |
| 1733 | .inferred_alloc_mut, | 1761 | .inferred_alloc_mut, |
| 1762 | .@"struct", | ||
| 1734 | .@"opaque", | 1763 | .@"opaque", |
| 1735 | .var_args_param, | 1764 | .var_args_param, |
| 1736 | => false, | 1765 | => false, |
| ... | @@ -1792,7 +1821,11 @@ pub const Type = extern union { | ... | @@ -1792,7 +1821,11 @@ pub const Type = extern union { |
| 1792 | .ErrorUnion => ty = ty.errorUnionChild(), | 1821 | .ErrorUnion => ty = ty.errorUnionChild(), |
| 1793 | 1822 | ||
| 1794 | .Fn => @panic("TODO fn isValidVarType"), | 1823 | .Fn => @panic("TODO fn isValidVarType"), |
| 1795 | .Struct => @panic("TODO struct isValidVarType"), | 1824 | .Struct => { |
| 1825 | // TODO this is not always correct; introduce lazy value mechanism | ||
| 1826 | // and here we need to force a resolve of "type requires comptime". | ||
| 1827 | return true; | ||
| 1828 | }, | ||
| 1796 | .Union => @panic("TODO union isValidVarType"), | 1829 | .Union => @panic("TODO union isValidVarType"), |
| 1797 | }; | 1830 | }; |
| 1798 | } | 1831 | } |
| ... | @@ -1850,6 +1883,7 @@ pub const Type = extern union { | ... | @@ -1850,6 +1883,7 @@ pub const Type = extern union { |
| 1850 | .anyerror_void_error_union => unreachable, | 1883 | .anyerror_void_error_union => unreachable, |
| 1851 | .error_set => unreachable, | 1884 | .error_set => unreachable, |
| 1852 | .error_set_single => unreachable, | 1885 | .error_set_single => unreachable, |
| 1886 | .@"struct" => unreachable, | ||
| 1853 | .empty_struct => unreachable, | 1887 | .empty_struct => unreachable, |
| 1854 | .empty_struct_literal => unreachable, | 1888 | .empty_struct_literal => unreachable, |
| 1855 | .inferred_alloc_const => unreachable, | 1889 | .inferred_alloc_const => unreachable, |
| ... | @@ -1999,6 +2033,7 @@ pub const Type = extern union { | ... | @@ -1999,6 +2033,7 @@ pub const Type = extern union { |
| 1999 | .anyerror_void_error_union, | 2033 | .anyerror_void_error_union, |
| 2000 | .error_set, | 2034 | .error_set, |
| 2001 | .error_set_single, | 2035 | .error_set_single, |
| 2036 | .@"struct", | ||
| 2002 | .empty_struct, | 2037 | .empty_struct, |
| 2003 | .empty_struct_literal, | 2038 | .empty_struct_literal, |
| 2004 | .inferred_alloc_const, | 2039 | .inferred_alloc_const, |
| ... | @@ -2070,6 +2105,7 @@ pub const Type = extern union { | ... | @@ -2070,6 +2105,7 @@ pub const Type = extern union { |
| 2070 | .anyerror_void_error_union, | 2105 | .anyerror_void_error_union, |
| 2071 | .error_set, | 2106 | .error_set, |
| 2072 | .error_set_single, | 2107 | .error_set_single, |
| 2108 | .@"struct", | ||
| 2073 | .empty_struct, | 2109 | .empty_struct, |
| 2074 | .empty_struct_literal, | 2110 | .empty_struct_literal, |
| 2075 | .inferred_alloc_const, | 2111 | .inferred_alloc_const, |
| ... | @@ -2156,6 +2192,7 @@ pub const Type = extern union { | ... | @@ -2156,6 +2192,7 @@ pub const Type = extern union { |
| 2156 | .anyerror_void_error_union, | 2192 | .anyerror_void_error_union, |
| 2157 | .error_set, | 2193 | .error_set, |
| 2158 | .error_set_single, | 2194 | .error_set_single, |
| 2195 | .@"struct", | ||
| 2159 | .empty_struct, | 2196 | .empty_struct, |
| 2160 | .empty_struct_literal, | 2197 | .empty_struct_literal, |
| 2161 | .inferred_alloc_const, | 2198 | .inferred_alloc_const, |
| ... | @@ -2238,6 +2275,7 @@ pub const Type = extern union { | ... | @@ -2238,6 +2275,7 @@ pub const Type = extern union { |
| 2238 | .anyerror_void_error_union, | 2275 | .anyerror_void_error_union, |
| 2239 | .error_set, | 2276 | .error_set, |
| 2240 | .error_set_single, | 2277 | .error_set_single, |
| 2278 | .@"struct", | ||
| 2241 | .empty_struct, | 2279 | .empty_struct, |
| 2242 | .empty_struct_literal, | 2280 | .empty_struct_literal, |
| 2243 | .inferred_alloc_const, | 2281 | .inferred_alloc_const, |
| ... | @@ -2306,6 +2344,7 @@ pub const Type = extern union { | ... | @@ -2306,6 +2344,7 @@ pub const Type = extern union { |
| 2306 | .anyerror_void_error_union, | 2344 | .anyerror_void_error_union, |
| 2307 | .error_set, | 2345 | .error_set, |
| 2308 | .error_set_single, | 2346 | .error_set_single, |
| 2347 | .@"struct", | ||
| 2309 | .empty_struct, | 2348 | .empty_struct, |
| 2310 | .empty_struct_literal, | 2349 | .empty_struct_literal, |
| 2311 | .inferred_alloc_const, | 2350 | .inferred_alloc_const, |
| ... | @@ -2402,6 +2441,7 @@ pub const Type = extern union { | ... | @@ -2402,6 +2441,7 @@ pub const Type = extern union { |
| 2402 | .anyerror_void_error_union, | 2441 | .anyerror_void_error_union, |
| 2403 | .error_set, | 2442 | .error_set, |
| 2404 | .error_set_single, | 2443 | .error_set_single, |
| 2444 | .@"struct", | ||
| 2405 | .empty_struct, | 2445 | .empty_struct, |
| 2406 | .empty_struct_literal, | 2446 | .empty_struct_literal, |
| 2407 | .inferred_alloc_const, | 2447 | .inferred_alloc_const, |
| ... | @@ -2519,6 +2559,7 @@ pub const Type = extern union { | ... | @@ -2519,6 +2559,7 @@ pub const Type = extern union { |
| 2519 | .anyerror_void_error_union, | 2559 | .anyerror_void_error_union, |
| 2520 | .error_set, | 2560 | .error_set, |
| 2521 | .error_set_single, | 2561 | .error_set_single, |
| 2562 | .@"struct", | ||
| 2522 | .empty_struct, | 2563 | .empty_struct, |
| 2523 | .empty_struct_literal, | 2564 | .empty_struct_literal, |
| 2524 | .inferred_alloc_const, | 2565 | .inferred_alloc_const, |
| ... | @@ -2602,6 +2643,7 @@ pub const Type = extern union { | ... | @@ -2602,6 +2643,7 @@ pub const Type = extern union { |
| 2602 | .anyerror_void_error_union, | 2643 | .anyerror_void_error_union, |
| 2603 | .error_set, | 2644 | .error_set, |
| 2604 | .error_set_single, | 2645 | .error_set_single, |
| 2646 | .@"struct", | ||
| 2605 | .empty_struct, | 2647 | .empty_struct, |
| 2606 | .empty_struct_literal, | 2648 | .empty_struct_literal, |
| 2607 | .inferred_alloc_const, | 2649 | .inferred_alloc_const, |
| ... | @@ -2684,6 +2726,7 @@ pub const Type = extern union { | ... | @@ -2684,6 +2726,7 @@ pub const Type = extern union { |
| 2684 | .anyerror_void_error_union, | 2726 | .anyerror_void_error_union, |
| 2685 | .error_set, | 2727 | .error_set, |
| 2686 | .error_set_single, | 2728 | .error_set_single, |
| 2729 | .@"struct", | ||
| 2687 | .empty_struct, | 2730 | .empty_struct, |
| 2688 | .empty_struct_literal, | 2731 | .empty_struct_literal, |
| 2689 | .inferred_alloc_const, | 2732 | .inferred_alloc_const, |
| ... | @@ -2766,6 +2809,7 @@ pub const Type = extern union { | ... | @@ -2766,6 +2809,7 @@ pub const Type = extern union { |
| 2766 | .anyerror_void_error_union, | 2809 | .anyerror_void_error_union, |
| 2767 | .error_set, | 2810 | .error_set, |
| 2768 | .error_set_single, | 2811 | .error_set_single, |
| 2812 | .@"struct", | ||
| 2769 | .empty_struct, | 2813 | .empty_struct, |
| 2770 | .empty_struct_literal, | 2814 | .empty_struct_literal, |
| 2771 | .inferred_alloc_const, | 2815 | .inferred_alloc_const, |
| ... | @@ -2845,6 +2889,7 @@ pub const Type = extern union { | ... | @@ -2845,6 +2889,7 @@ pub const Type = extern union { |
| 2845 | .anyerror_void_error_union, | 2889 | .anyerror_void_error_union, |
| 2846 | .error_set, | 2890 | .error_set, |
| 2847 | .error_set_single, | 2891 | .error_set_single, |
| 2892 | .@"struct", | ||
| 2848 | .empty_struct, | 2893 | .empty_struct, |
| 2849 | .empty_struct_literal, | 2894 | .empty_struct_literal, |
| 2850 | .inferred_alloc_const, | 2895 | .inferred_alloc_const, |
| ... | @@ -2924,6 +2969,7 @@ pub const Type = extern union { | ... | @@ -2924,6 +2969,7 @@ pub const Type = extern union { |
| 2924 | .anyerror_void_error_union, | 2969 | .anyerror_void_error_union, |
| 2925 | .error_set, | 2970 | .error_set, |
| 2926 | .error_set_single, | 2971 | .error_set_single, |
| 2972 | .@"struct", | ||
| 2927 | .empty_struct, | 2973 | .empty_struct, |
| 2928 | .empty_struct_literal, | 2974 | .empty_struct_literal, |
| 2929 | .inferred_alloc_const, | 2975 | .inferred_alloc_const, |
| ... | @@ -3003,6 +3049,7 @@ pub const Type = extern union { | ... | @@ -3003,6 +3049,7 @@ pub const Type = extern union { |
| 3003 | .anyerror_void_error_union, | 3049 | .anyerror_void_error_union, |
| 3004 | .error_set, | 3050 | .error_set, |
| 3005 | .error_set_single, | 3051 | .error_set_single, |
| 3052 | .@"struct", | ||
| 3006 | .empty_struct, | 3053 | .empty_struct, |
| 3007 | .empty_struct_literal, | 3054 | .empty_struct_literal, |
| 3008 | .inferred_alloc_const, | 3055 | .inferred_alloc_const, |
| ... | @@ -3070,6 +3117,11 @@ pub const Type = extern union { | ... | @@ -3070,6 +3117,11 @@ pub const Type = extern union { |
| 3070 | .var_args_param, | 3117 | .var_args_param, |
| 3071 | => return null, | 3118 | => return null, |
| 3072 | 3119 | ||
| 3120 | .@"struct" => { | ||
| 3121 | log.warn("TODO implement Type.onePossibleValue for structs", .{}); | ||
| 3122 | return null; | ||
| 3123 | }, | ||
| 3124 | |||
| 3073 | .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value), | 3125 | .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value), |
| 3074 | .void => return Value.initTag(.void_value), | 3126 | .void => return Value.initTag(.void_value), |
| 3075 | .noreturn => return Value.initTag(.unreachable_value), | 3127 | .noreturn => return Value.initTag(.unreachable_value), |
| ... | @@ -3172,6 +3224,7 @@ pub const Type = extern union { | ... | @@ -3172,6 +3224,7 @@ pub const Type = extern union { |
| 3172 | .anyerror_void_error_union, | 3224 | .anyerror_void_error_union, |
| 3173 | .error_set, | 3225 | .error_set, |
| 3174 | .error_set_single, | 3226 | .error_set_single, |
| 3227 | .@"struct", | ||
| 3175 | .empty_struct, | 3228 | .empty_struct, |
| 3176 | .empty_struct_literal, | 3229 | .empty_struct_literal, |
| 3177 | .inferred_alloc_const, | 3230 | .inferred_alloc_const, |
| ... | @@ -3269,6 +3322,7 @@ pub const Type = extern union { | ... | @@ -3269,6 +3322,7 @@ pub const Type = extern union { |
| 3269 | .empty_struct_literal, | 3322 | .empty_struct_literal, |
| 3270 | => unreachable, | 3323 | => unreachable, |
| 3271 | 3324 | ||
| 3325 | .@"struct" => &self.castTag(.@"struct").?.data.container, | ||
| 3272 | .empty_struct => self.castTag(.empty_struct).?.data, | 3326 | .empty_struct => self.castTag(.empty_struct).?.data, |
| 3273 | .@"opaque" => &self.castTag(.@"opaque").?.data, | 3327 | .@"opaque" => &self.castTag(.@"opaque").?.data, |
| 3274 | }; | 3328 | }; |
| ... | @@ -3421,6 +3475,7 @@ pub const Type = extern union { | ... | @@ -3421,6 +3475,7 @@ pub const Type = extern union { |
| 3421 | error_set_single, | 3475 | error_set_single, |
| 3422 | empty_struct, | 3476 | empty_struct, |
| 3423 | @"opaque", | 3477 | @"opaque", |
| 3478 | @"struct", | ||
| 3424 | 3479 | ||
| 3425 | pub const last_no_payload_tag = Tag.inferred_alloc_const; | 3480 | pub const last_no_payload_tag = Tag.inferred_alloc_const; |
| 3426 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; | 3481 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; |
| ... | @@ -3506,6 +3561,7 @@ pub const Type = extern union { | ... | @@ -3506,6 +3561,7 @@ pub const Type = extern union { |
| 3506 | .error_union => Payload.ErrorUnion, | 3561 | .error_union => Payload.ErrorUnion, |
| 3507 | .error_set_single => Payload.Name, | 3562 | .error_set_single => Payload.Name, |
| 3508 | .@"opaque" => Payload.Opaque, | 3563 | .@"opaque" => Payload.Opaque, |
| 3564 | .@"struct" => Payload.Struct, | ||
| 3509 | .empty_struct => Payload.ContainerScope, | 3565 | .empty_struct => Payload.ContainerScope, |
| 3510 | }; | 3566 | }; |
| 3511 | } | 3567 | } |
| ... | @@ -3638,6 +3694,11 @@ pub const Type = extern union { | ... | @@ -3638,6 +3694,11 @@ pub const Type = extern union { |
| 3638 | base: Payload = .{ .tag = .@"opaque" }, | 3694 | base: Payload = .{ .tag = .@"opaque" }, |
| 3639 | data: Module.Scope.Container, | 3695 | data: Module.Scope.Container, |
| 3640 | }; | 3696 | }; |
| 3697 | |||
| 3698 | pub const Struct = struct { | ||
| 3699 | base: Payload = .{ .tag = .@"struct" }, | ||
| 3700 | data: *Module.Struct, | ||
| 3701 | }; | ||
| 3641 | }; | 3702 | }; |
| 3642 | }; | 3703 | }; |
| 3643 | 3704 |
src/value.zig+18-1| ... | @@ -74,6 +74,7 @@ pub const Value = extern union { | ... | @@ -74,6 +74,7 @@ pub const Value = extern union { |
| 74 | bool_true, | 74 | bool_true, |
| 75 | bool_false, | 75 | bool_false, |
| 76 | 76 | ||
| 77 | abi_align_default, | ||
| 77 | empty_struct_value, | 78 | empty_struct_value, |
| 78 | empty_array, // See last_no_payload_tag below. | 79 | empty_array, // See last_no_payload_tag below. |
| 79 | // After this, the tag requires a payload. | 80 | // After this, the tag requires a payload. |
| ... | @@ -165,6 +166,7 @@ pub const Value = extern union { | ... | @@ -165,6 +166,7 @@ pub const Value = extern union { |
| 165 | .null_value, | 166 | .null_value, |
| 166 | .bool_true, | 167 | .bool_true, |
| 167 | .bool_false, | 168 | .bool_false, |
| 169 | .abi_align_default, | ||
| 168 | => @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"), | 170 | => @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"), |
| 169 | 171 | ||
| 170 | .int_big_positive, | 172 | .int_big_positive, |
| ... | @@ -320,6 +322,7 @@ pub const Value = extern union { | ... | @@ -320,6 +322,7 @@ pub const Value = extern union { |
| 320 | .bool_true, | 322 | .bool_true, |
| 321 | .bool_false, | 323 | .bool_false, |
| 322 | .empty_struct_value, | 324 | .empty_struct_value, |
| 325 | .abi_align_default, | ||
| 323 | => unreachable, | 326 | => unreachable, |
| 324 | 327 | ||
| 325 | .ty => { | 328 | .ty => { |
| ... | @@ -464,8 +467,8 @@ pub const Value = extern union { | ... | @@ -464,8 +467,8 @@ pub const Value = extern union { |
| 464 | .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"), | 467 | .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"), |
| 465 | .const_slice_u8_type => return out_stream.writeAll("[]const u8"), | 468 | .const_slice_u8_type => return out_stream.writeAll("[]const u8"), |
| 466 | .enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"), | 469 | .enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"), |
| 470 | .abi_align_default => return out_stream.writeAll("(default ABI alignment)"), | ||
| 467 | 471 | ||
| 468 | // TODO this should print `NAME{}` | ||
| 469 | .empty_struct_value => return out_stream.writeAll("struct {}{}"), | 472 | .empty_struct_value => return out_stream.writeAll("struct {}{}"), |
| 470 | .null_value => return out_stream.writeAll("null"), | 473 | .null_value => return out_stream.writeAll("null"), |
| 471 | .undef => return out_stream.writeAll("undefined"), | 474 | .undef => return out_stream.writeAll("undefined"), |
| ... | @@ -627,6 +630,7 @@ pub const Value = extern union { | ... | @@ -627,6 +630,7 @@ pub const Value = extern union { |
| 627 | .error_union, | 630 | .error_union, |
| 628 | .empty_struct_value, | 631 | .empty_struct_value, |
| 629 | .inferred_alloc, | 632 | .inferred_alloc, |
| 633 | .abi_align_default, | ||
| 630 | => unreachable, | 634 | => unreachable, |
| 631 | }; | 635 | }; |
| 632 | } | 636 | } |
| ... | @@ -699,6 +703,7 @@ pub const Value = extern union { | ... | @@ -699,6 +703,7 @@ pub const Value = extern union { |
| 699 | .@"error", | 703 | .@"error", |
| 700 | .empty_struct_value, | 704 | .empty_struct_value, |
| 701 | .inferred_alloc, | 705 | .inferred_alloc, |
| 706 | .abi_align_default, | ||
| 702 | => unreachable, | 707 | => unreachable, |
| 703 | 708 | ||
| 704 | .undef => unreachable, | 709 | .undef => unreachable, |
| ... | @@ -786,6 +791,7 @@ pub const Value = extern union { | ... | @@ -786,6 +791,7 @@ pub const Value = extern union { |
| 786 | .error_union, | 791 | .error_union, |
| 787 | .empty_struct_value, | 792 | .empty_struct_value, |
| 788 | .inferred_alloc, | 793 | .inferred_alloc, |
| 794 | .abi_align_default, | ||
| 789 | => unreachable, | 795 | => unreachable, |
| 790 | 796 | ||
| 791 | .undef => unreachable, | 797 | .undef => unreachable, |
| ... | @@ -873,6 +879,7 @@ pub const Value = extern union { | ... | @@ -873,6 +879,7 @@ pub const Value = extern union { |
| 873 | .error_union, | 879 | .error_union, |
| 874 | .empty_struct_value, | 880 | .empty_struct_value, |
| 875 | .inferred_alloc, | 881 | .inferred_alloc, |
| 882 | .abi_align_default, | ||
| 876 | => unreachable, | 883 | => unreachable, |
| 877 | 884 | ||
| 878 | .undef => unreachable, | 885 | .undef => unreachable, |
| ... | @@ -988,6 +995,7 @@ pub const Value = extern union { | ... | @@ -988,6 +995,7 @@ pub const Value = extern union { |
| 988 | .error_union, | 995 | .error_union, |
| 989 | .empty_struct_value, | 996 | .empty_struct_value, |
| 990 | .inferred_alloc, | 997 | .inferred_alloc, |
| 998 | .abi_align_default, | ||
| 991 | => unreachable, | 999 | => unreachable, |
| 992 | 1000 | ||
| 993 | .zero, | 1001 | .zero, |
| ... | @@ -1079,6 +1087,7 @@ pub const Value = extern union { | ... | @@ -1079,6 +1087,7 @@ pub const Value = extern union { |
| 1079 | .error_union, | 1087 | .error_union, |
| 1080 | .empty_struct_value, | 1088 | .empty_struct_value, |
| 1081 | .inferred_alloc, | 1089 | .inferred_alloc, |
| 1090 | .abi_align_default, | ||
| 1082 | => unreachable, | 1091 | => unreachable, |
| 1083 | 1092 | ||
| 1084 | .zero, | 1093 | .zero, |
| ... | @@ -1239,6 +1248,7 @@ pub const Value = extern union { | ... | @@ -1239,6 +1248,7 @@ pub const Value = extern union { |
| 1239 | .error_union, | 1248 | .error_union, |
| 1240 | .empty_struct_value, | 1249 | .empty_struct_value, |
| 1241 | .inferred_alloc, | 1250 | .inferred_alloc, |
| 1251 | .abi_align_default, | ||
| 1242 | => unreachable, | 1252 | => unreachable, |
| 1243 | 1253 | ||
| 1244 | .zero, | 1254 | .zero, |
| ... | @@ -1317,6 +1327,7 @@ pub const Value = extern union { | ... | @@ -1317,6 +1327,7 @@ pub const Value = extern union { |
| 1317 | .error_union, | 1327 | .error_union, |
| 1318 | .empty_struct_value, | 1328 | .empty_struct_value, |
| 1319 | .inferred_alloc, | 1329 | .inferred_alloc, |
| 1330 | .abi_align_default, | ||
| 1320 | => unreachable, | 1331 | => unreachable, |
| 1321 | 1332 | ||
| 1322 | .zero, | 1333 | .zero, |
| ... | @@ -1452,6 +1463,7 @@ pub const Value = extern union { | ... | @@ -1452,6 +1463,7 @@ pub const Value = extern union { |
| 1452 | .const_slice_u8_type, | 1463 | .const_slice_u8_type, |
| 1453 | .enum_literal_type, | 1464 | .enum_literal_type, |
| 1454 | .ty, | 1465 | .ty, |
| 1466 | .abi_align_default, | ||
| 1455 | => { | 1467 | => { |
| 1456 | // Directly return Type.hash, toType can only fail for .int_type. | 1468 | // Directly return Type.hash, toType can only fail for .int_type. |
| 1457 | var allocator = std.heap.FixedBufferAllocator.init(&[_]u8{}); | 1469 | var allocator = std.heap.FixedBufferAllocator.init(&[_]u8{}); |
| ... | @@ -1632,6 +1644,7 @@ pub const Value = extern union { | ... | @@ -1632,6 +1644,7 @@ pub const Value = extern union { |
| 1632 | .error_union, | 1644 | .error_union, |
| 1633 | .empty_struct_value, | 1645 | .empty_struct_value, |
| 1634 | .inferred_alloc, | 1646 | .inferred_alloc, |
| 1647 | .abi_align_default, | ||
| 1635 | => unreachable, | 1648 | => unreachable, |
| 1636 | 1649 | ||
| 1637 | .ref_val => self.castTag(.ref_val).?.data, | 1650 | .ref_val => self.castTag(.ref_val).?.data, |
| ... | @@ -1719,6 +1732,7 @@ pub const Value = extern union { | ... | @@ -1719,6 +1732,7 @@ pub const Value = extern union { |
| 1719 | .error_union, | 1732 | .error_union, |
| 1720 | .empty_struct_value, | 1733 | .empty_struct_value, |
| 1721 | .inferred_alloc, | 1734 | .inferred_alloc, |
| 1735 | .abi_align_default, | ||
| 1722 | => unreachable, | 1736 | => unreachable, |
| 1723 | 1737 | ||
| 1724 | .empty_array => unreachable, // out of bounds array index | 1738 | .empty_array => unreachable, // out of bounds array index |
| ... | @@ -1822,6 +1836,7 @@ pub const Value = extern union { | ... | @@ -1822,6 +1836,7 @@ pub const Value = extern union { |
| 1822 | .@"error", | 1836 | .@"error", |
| 1823 | .error_union, | 1837 | .error_union, |
| 1824 | .empty_struct_value, | 1838 | .empty_struct_value, |
| 1839 | .abi_align_default, | ||
| 1825 | => false, | 1840 | => false, |
| 1826 | 1841 | ||
| 1827 | .undef => unreachable, | 1842 | .undef => unreachable, |
| ... | @@ -1903,6 +1918,7 @@ pub const Value = extern union { | ... | @@ -1903,6 +1918,7 @@ pub const Value = extern union { |
| 1903 | .void_value, | 1918 | .void_value, |
| 1904 | .enum_literal, | 1919 | .enum_literal, |
| 1905 | .empty_struct_value, | 1920 | .empty_struct_value, |
| 1921 | .abi_align_default, | ||
| 1906 | => null, | 1922 | => null, |
| 1907 | 1923 | ||
| 1908 | .error_union => { | 1924 | .error_union => { |
| ... | @@ -2009,6 +2025,7 @@ pub const Value = extern union { | ... | @@ -2009,6 +2025,7 @@ pub const Value = extern union { |
| 2009 | .error_union, | 2025 | .error_union, |
| 2010 | .empty_struct_value, | 2026 | .empty_struct_value, |
| 2011 | .null_value, | 2027 | .null_value, |
| 2028 | .abi_align_default, | ||
| 2012 | => false, | 2029 | => false, |
| 2013 | 2030 | ||
| 2014 | .undef => unreachable, | 2031 | .undef => unreachable, |
src/zir.zig+10-1| ... | @@ -274,6 +274,10 @@ pub const Inst = struct { | ... | @@ -274,6 +274,10 @@ pub const Inst = struct { |
| 274 | /// the field types, defaults, and alignments. | 274 | /// the field types, defaults, and alignments. |
| 275 | /// Uses the `pl_node` union field. Payload is `StructDecl`. | 275 | /// Uses the `pl_node` union field. Payload is `StructDecl`. |
| 276 | struct_decl, | 276 | struct_decl, |
| 277 | /// Same as `struct_decl`, except has the `packed` layout. | ||
| 278 | struct_decl_packed, | ||
| 279 | /// Same as `struct_decl`, except has the `extern` layout. | ||
| 280 | struct_decl_extern, | ||
| 277 | /// A union type definition. Contains references to ZIR instructions for | 281 | /// A union type definition. Contains references to ZIR instructions for |
| 278 | /// the field types and optional type tag expression. | 282 | /// the field types and optional type tag expression. |
| 279 | /// Uses the `pl_node` union field. Payload is `UnionDecl`. | 283 | /// Uses the `pl_node` union field. Payload is `UnionDecl`. |
| ... | @@ -707,6 +711,8 @@ pub const Inst = struct { | ... | @@ -707,6 +711,8 @@ pub const Inst = struct { |
| 707 | .coerce_result_ptr, | 711 | .coerce_result_ptr, |
| 708 | .@"const", | 712 | .@"const", |
| 709 | .struct_decl, | 713 | .struct_decl, |
| 714 | .struct_decl_packed, | ||
| 715 | .struct_decl_extern, | ||
| 710 | .union_decl, | 716 | .union_decl, |
| 711 | .enum_decl, | 717 | .enum_decl, |
| 712 | .opaque_decl, | 718 | .opaque_decl, |
| ... | @@ -1655,7 +1661,10 @@ const Writer = struct { | ... | @@ -1655,7 +1661,10 @@ const Writer = struct { |
| 1655 | .condbr_inline, | 1661 | .condbr_inline, |
| 1656 | => try self.writePlNodeCondBr(stream, inst), | 1662 | => try self.writePlNodeCondBr(stream, inst), |
| 1657 | 1663 | ||
| 1658 | .struct_decl => try self.writeStructDecl(stream, inst), | 1664 | .struct_decl, |
| 1665 | .struct_decl_packed, | ||
| 1666 | .struct_decl_extern, | ||
| 1667 | => try self.writeStructDecl(stream, inst), | ||
| 1659 | 1668 | ||
| 1660 | .switch_block => try self.writePlNodeSwitchBr(stream, inst, .none), | 1669 | .switch_block => try self.writePlNodeSwitchBr(stream, inst, .none), |
| 1661 | .switch_block_else => try self.writePlNodeSwitchBr(stream, inst, .@"else"), | 1670 | .switch_block_else => try self.writePlNodeSwitchBr(stream, inst, .@"else"), |