Commit ada83fa557

mlugg <mlugg@mlugg.co.uk>
2023-09-20 22:19:29
compiler: get codegen of behavior tests working on at least one backend
We're hitting false compile errors, but this is progress!
1 parent 0182b72
Changed files (4)
src/codegen/llvm.zig
@@ -2504,6 +2504,7 @@ pub const Object = struct {
                 var it = struct_type.iterateRuntimeOrder(ip);
                 while (it.next()) |field_index| {
                     const field_ty = field_types[field_index].toType();
+                    if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
                     const field_size = field_ty.abiSize(mod);
                     const field_align = mod.structFieldAlignment(
                         struct_type.fieldAlign(ip, field_index),
@@ -3306,6 +3307,7 @@ pub const Object = struct {
                     var it = struct_type.iterateRuntimeOrder(ip);
                     while (it.next()) |field_index| {
                         const field_ty = struct_type.field_types.get(ip)[field_index].toType();
+                        if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
                         const field_align = mod.structFieldAlignment(
                             struct_type.fieldAlign(ip, field_index),
                             field_ty,
@@ -4016,10 +4018,11 @@ pub const Object = struct {
                     var need_unnamed = false;
                     var field_it = struct_type.iterateRuntimeOrder(ip);
                     while (field_it.next()) |field_index| {
-                        const field_ty = struct_type.field_types.get(ip)[field_index];
+                        const field_ty = struct_type.field_types.get(ip)[field_index].toType();
+                        if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
                         const field_align = mod.structFieldAlignment(
                             struct_type.fieldAlign(ip, field_index),
-                            field_ty.toType(),
+                            field_ty,
                             struct_type.layout,
                         );
                         big_align = big_align.max(field_align);
@@ -4045,7 +4048,7 @@ pub const Object = struct {
                             need_unnamed = true;
                         llvm_index += 1;
 
-                        offset += field_ty.toType().abiSize(mod);
+                        offset += field_ty.abiSize(mod);
                     }
                     {
                         const prev_offset = offset;
src/link/Dwarf.zig
@@ -351,25 +351,41 @@ pub const DeclState = struct {
                             break :blk;
                         }
 
-                        for (
-                            struct_type.field_names.get(ip),
-                            struct_type.field_types.get(ip),
-                            struct_type.offsets.get(ip),
-                        ) |field_name_ip, field_ty, field_off| {
-                            if (!field_ty.toType().hasRuntimeBits(mod)) continue;
-                            const field_name = ip.stringToSlice(field_name_ip);
-                            // DW.AT.member
-                            try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2);
-                            dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.struct_member));
-                            // DW.AT.name, DW.FORM.string
-                            dbg_info_buffer.appendSliceAssumeCapacity(field_name);
-                            dbg_info_buffer.appendAssumeCapacity(0);
-                            // DW.AT.type, DW.FORM.ref4
-                            var index = dbg_info_buffer.items.len;
-                            try dbg_info_buffer.resize(index + 4);
-                            try self.addTypeRelocGlobal(atom_index, field_ty.toType(), @intCast(index));
-                            // DW.AT.data_member_location, DW.FORM.udata
-                            try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
+                        if (struct_type.isTuple(ip)) {
+                            for (struct_type.field_types.get(ip), struct_type.offsets.get(ip), 0..) |field_ty, field_off, field_index| {
+                                if (!field_ty.toType().hasRuntimeBits(mod)) continue;
+                                // DW.AT.member
+                                try dbg_info_buffer.append(@intFromEnum(AbbrevKind.struct_member));
+                                // DW.AT.name, DW.FORM.string
+                                try dbg_info_buffer.writer().print("{d}\x00", .{field_index});
+                                // DW.AT.type, DW.FORM.ref4
+                                var index = dbg_info_buffer.items.len;
+                                try dbg_info_buffer.resize(index + 4);
+                                try self.addTypeRelocGlobal(atom_index, field_ty.toType(), @as(u32, @intCast(index)));
+                                // DW.AT.data_member_location, DW.FORM.udata
+                                try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
+                            }
+                        } else {
+                            for (
+                                struct_type.field_names.get(ip),
+                                struct_type.field_types.get(ip),
+                                struct_type.offsets.get(ip),
+                            ) |field_name_ip, field_ty, field_off| {
+                                if (!field_ty.toType().hasRuntimeBits(mod)) continue;
+                                const field_name = ip.stringToSlice(field_name_ip);
+                                // DW.AT.member
+                                try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2);
+                                dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevKind.struct_member));
+                                // DW.AT.name, DW.FORM.string
+                                dbg_info_buffer.appendSliceAssumeCapacity(field_name);
+                                dbg_info_buffer.appendAssumeCapacity(0);
+                                // DW.AT.type, DW.FORM.ref4
+                                var index = dbg_info_buffer.items.len;
+                                try dbg_info_buffer.resize(index + 4);
+                                try self.addTypeRelocGlobal(atom_index, field_ty.toType(), @intCast(index));
+                                // DW.AT.data_member_location, DW.FORM.udata
+                                try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
+                            }
                         }
                     },
                     else => unreachable,
src/InternPool.zig
@@ -527,6 +527,11 @@ pub const Key = union(enum) {
             return false;
         }
 
+        pub fn clearLayoutWip(s: @This(), ip: *InternPool) void {
+            if (s.layout == .Packed) return;
+            s.flagsPtr(ip).layout_wip = false;
+        }
+
         pub fn setFullyResolved(s: @This(), ip: *InternPool) bool {
             if (s.layout == .Packed) return true;
             const flags_ptr = s.flagsPtr(ip);
@@ -612,6 +617,7 @@ pub const Key = union(enum) {
         };
 
         /// Iterates over non-comptime fields in the order they are laid out in memory at runtime.
+        /// May or may not include zero-bit fields.
         /// Asserts the struct is not packed.
         pub fn iterateRuntimeOrder(s: @This(), ip: *InternPool) RuntimeOrderIterator {
             assert(s.layout != .Packed);
src/Sema.zig
@@ -34293,6 +34293,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
         );
         return sema.failWithOwnedErrorMsg(null, msg);
     }
+    defer struct_type.clearLayoutWip(ip);
 
     const aligns = try sema.arena.alloc(Alignment, struct_type.field_types.len);
     const sizes = try sema.arena.alloc(u64, struct_type.field_types.len);
@@ -34300,6 +34301,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
     for (aligns, sizes, 0..) |*field_align, *field_size, i| {
         const field_ty = struct_type.field_types.get(ip)[i].toType();
         if (struct_type.fieldIsComptime(ip, i) or !(try sema.typeHasRuntimeBits(field_ty))) {
+            struct_type.offsets.get(ip)[i] = 0;
             field_size.* = 0;
             field_align.* = .none;
             continue;
@@ -34379,6 +34381,9 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
     var offset: u64 = 0;
     var big_align: Alignment = .@"1";
     while (it.next()) |i| {
+        const field_ty = struct_type.field_types.get(ip)[i].toType();
+        // Type query definitely valid as we performed it earlier
+        if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
         big_align = big_align.max(aligns[i]);
         offsets[i] = @intCast(aligns[i].forward(offset));
         offset = offsets[i] + sizes[i];
@@ -34832,7 +34837,7 @@ fn resolveTypeFieldsStruct(
         );
         return sema.failWithOwnedErrorMsg(null, msg);
     }
-    errdefer struct_type.clearTypesWip(ip);
+    defer struct_type.clearTypesWip(ip);
 
     try semaStructFields(mod, sema.arena, struct_type);
 }