Commit fb192df4f2

Jacob Young <jacobly0@users.noreply.github.com>
2024-03-30 01:18:09
cbe: fix uncovered bugs
1 parent 7580879
Changed files (4)
lib
src
lib/zig.h
@@ -130,22 +130,18 @@ typedef char bool;
 #define zig_restrict
 #endif
 
-#if __STDC_VERSION__ >= 201112L
-#define zig_align(alignment) _Alignas(alignment)
-#elif zig_has_attribute(aligned)
-#define zig_align(alignment) __attribute__((aligned(alignment)))
+#if zig_has_attribute(aligned)
+#define zig_under_align(alignment) __attribute__((aligned(alignment)))
 #elif _MSC_VER
-#define zig_align(alignment) __declspec(align(alignment))
+#define zig_under_align(alignment) __declspec(align(alignment))
 #else
-#define zig_align zig_align_unavailable
+#define zig_under_align zig_align_unavailable
 #endif
 
-#if zig_has_attribute(aligned)
-#define zig_under_align(alignment) __attribute__((aligned(alignment)))
-#elif _MSC_VER
-#define zig_under_align(alignment) zig_align(alignment)
+#if __STDC_VERSION__ >= 201112L
+#define zig_align(alignment) _Alignas(alignment)
 #else
-#define zig_align zig_align_unavailable
+#define zig_align(alignment) zig_under_align(alignment)
 #endif
 
 #if zig_has_attribute(aligned)
src/codegen/c/Type.zig
@@ -734,6 +734,8 @@ pub const Info = union(enum) {
     aggregate: Aggregate,
     function: Function,
 
+    const Tag = @typeInfo(Info).Union.tag_type.?;
+
     pub const Pointer = struct {
         elem_ctype: CType,
         @"const": bool = false,
@@ -761,7 +763,7 @@ pub const Info = union(enum) {
         len: u64,
     };
 
-    pub const Tag = enum { @"enum", @"struct", @"union" };
+    pub const AggregateTag = enum { @"enum", @"struct", @"union" };
 
     pub const Field = struct {
         name: String,
@@ -820,7 +822,7 @@ pub const Info = union(enum) {
     };
 
     pub const FwdDecl = struct {
-        tag: Tag,
+        tag: AggregateTag,
         name: union(enum) {
             anon: Field.Slice,
             owner_decl: DeclIndex,
@@ -828,7 +830,7 @@ pub const Info = union(enum) {
     };
 
     pub const Aggregate = struct {
-        tag: Tag,
+        tag: AggregateTag,
         @"packed": bool = false,
         name: union(enum) {
             anon: struct {
@@ -853,9 +855,8 @@ pub const Info = union(enum) {
         rhs_pool: *const Pool,
         pool_adapter: anytype,
     ) bool {
-        const InfoTag = @typeInfo(Info).Union.tag_type.?;
         const rhs_info = rhs_ctype.info(rhs_pool);
-        if (@as(InfoTag, lhs_info) != @as(InfoTag, rhs_info)) return false;
+        if (@as(Info.Tag, lhs_info) != @as(Info.Tag, rhs_info)) return false;
         return switch (lhs_info) {
             .basic => |lhs_basic_info| lhs_basic_info == rhs_info.basic,
             .pointer => |lhs_pointer_info| lhs_pointer_info.@"const" == rhs_info.pointer.@"const" and
@@ -1012,7 +1013,7 @@ pub const Pool = struct {
         pool: *Pool,
         allocator: std.mem.Allocator,
         fwd_decl_info: struct {
-            tag: Info.Tag,
+            tag: Info.AggregateTag,
             name: union(enum) {
                 anon: []const Info.Field,
                 owner_decl: DeclIndex,
@@ -1070,7 +1071,7 @@ pub const Pool = struct {
         pool: *Pool,
         allocator: std.mem.Allocator,
         aggregate_info: struct {
-            tag: Info.Tag,
+            tag: Info.AggregateTag,
             @"packed": bool = false,
             name: union(enum) {
                 anon: struct {
@@ -1175,7 +1176,7 @@ pub const Pool = struct {
     pub fn fromFields(
         pool: *Pool,
         allocator: std.mem.Allocator,
-        tag: Info.Tag,
+        tag: Info.AggregateTag,
         fields: []Info.Field,
         kind: Kind,
     ) !CType {
@@ -1390,8 +1391,8 @@ pub const Pool = struct {
             else => |ip_index| switch (ip.indexToKey(ip_index)) {
                 .int_type => |int_info| return pool.fromIntInfo(allocator, int_info, mod, kind),
                 .ptr_type => |ptr_info| switch (ptr_info.flags.size) {
-                    .One, .Many, .C => return pool.getPointer(allocator, .{
-                        .elem_ctype = elem_ctype: {
+                    .One, .Many, .C => {
+                        const elem_ctype = elem_ctype: {
                             if (ptr_info.packed_offset.host_size > 0 and
                                 ptr_info.flags.vector_index == .none)
                                 break :elem_ctype try pool.fromIntInfo(allocator, .{
@@ -1412,13 +1413,31 @@ pub const Pool = struct {
                                     .abi = Type.fromInterned(ptr_info.child).abiAlignment(zcu),
                                 }),
                             };
-                            if (elem.alignas.abiOrder().compare(.gte))
-                                break :elem_ctype elem.ctype;
-                            break :elem_ctype try pool.getAligned(allocator, elem);
-                        },
-                        .@"const" = ptr_info.flags.is_const,
-                        .@"volatile" = ptr_info.flags.is_volatile,
-                    }),
+                            break :elem_ctype if (elem.alignas.abiOrder().compare(.gte))
+                                elem.ctype
+                            else
+                                try pool.getAligned(allocator, elem);
+                        };
+                        const elem_tag: Info.Tag = switch (elem_ctype.info(pool)) {
+                            .aligned => |aligned_info| aligned_info.ctype.info(pool),
+                            else => |elem_tag| elem_tag,
+                        };
+                        return pool.getPointer(allocator, .{
+                            .elem_ctype = elem_ctype,
+                            .@"const" = switch (elem_tag) {
+                                .basic,
+                                .pointer,
+                                .aligned,
+                                .array,
+                                .vector,
+                                .fwd_decl,
+                                .aggregate,
+                                => ptr_info.flags.is_const,
+                                .function => false,
+                            },
+                            .@"volatile" = ptr_info.flags.is_volatile,
+                        });
+                    },
                     .Slice => {
                         const target = &mod.resolved_target.result;
                         var fields = [_]Info.Field{
@@ -1589,7 +1608,7 @@ pub const Pool = struct {
                                 loaded_struct.field_types.len * @typeInfo(Field).Struct.fields.len,
                             );
                             var hasher = Hasher.init;
-                            var tag: Tag = .aggregate_struct;
+                            var tag: Pool.Tag = .aggregate_struct;
                             var field_it = loaded_struct.iterateRuntimeOrder(ip);
                             while (field_it.next()) |field_index| {
                                 const field_type = Type.fromInterned(
@@ -1729,7 +1748,7 @@ pub const Pool = struct {
                                 loaded_union.field_types.len * @typeInfo(Field).Struct.fields.len,
                             );
                             var hasher = Hasher.init;
-                            var tag: Tag = .aggregate_union;
+                            var tag: Pool.Tag = .aggregate_union;
                             var payload_align: Alignment = .@"1";
                             for (0..loaded_union.field_types.len) |field_index| {
                                 const field_type = Type.fromInterned(
@@ -2093,7 +2112,7 @@ pub const Pool = struct {
             inline for (@typeInfo(Extra).Struct.fields) |field| {
                 const value = @field(extra, field.name);
                 hasher.update(switch (field.type) {
-                    Tag, String, CType => unreachable,
+                    Pool.Tag, String, CType => unreachable,
                     CType.Index => (CType{ .index = value }).hash(pool),
                     String.Index => (String{ .index = value }).slice(pool),
                     else => value,
@@ -2102,7 +2121,7 @@ pub const Pool = struct {
         }
         fn update(hasher: *Hasher, data: anytype) void {
             switch (@TypeOf(data)) {
-                Tag => @compileError("pass tag to final"),
+                Pool.Tag => @compileError("pass tag to final"),
                 CType, CType.Index => @compileError("hash ctype.hash(pool) instead"),
                 String, String.Index => @compileError("hash string.slice(pool) instead"),
                 u32, DeclIndex, Aligned.Flags => hasher.impl.update(std.mem.asBytes(&data)),
@@ -2111,7 +2130,7 @@ pub const Pool = struct {
             }
         }
 
-        fn final(hasher: Hasher, tag: Tag) Map.Hash {
+        fn final(hasher: Hasher, tag: Pool.Tag) Map.Hash {
             var impl = hasher.impl;
             impl.update(std.mem.asBytes(&tag));
             return @truncate(impl.final());
@@ -2122,11 +2141,11 @@ pub const Pool = struct {
         pool: *Pool,
         allocator: std.mem.Allocator,
         hasher: Hasher,
-        tag: Tag,
+        tag: Pool.Tag,
         data: u32,
     ) !CType {
         try pool.ensureUnusedCapacity(allocator, 1);
-        const Key = struct { hash: Map.Hash, tag: Tag, data: u32 };
+        const Key = struct { hash: Map.Hash, tag: Pool.Tag, data: u32 };
         const CTypeAdapter = struct {
             pool: *const Pool,
             pub fn hash(_: @This(), key: Key) Map.Hash {
@@ -2148,7 +2167,7 @@ pub const Pool = struct {
     fn tagExtra(
         pool: *Pool,
         allocator: std.mem.Allocator,
-        tag: Tag,
+        tag: Pool.Tag,
         comptime Extra: type,
         extra: Extra,
     ) !CType {
@@ -2166,7 +2185,7 @@ pub const Pool = struct {
         pool: *Pool,
         allocator: std.mem.Allocator,
         hasher: Hasher,
-        tag: Tag,
+        tag: Pool.Tag,
         extra_index: ExtraIndex,
     ) !CType {
         try pool.ensureUnusedCapacity(allocator, 1);
@@ -2176,10 +2195,10 @@ pub const Pool = struct {
     fn tagTrailingExtraAssumeCapacity(
         pool: *Pool,
         hasher: Hasher,
-        tag: Tag,
+        tag: Pool.Tag,
         extra_index: ExtraIndex,
     ) CType {
-        const Key = struct { hash: Map.Hash, tag: Tag, extra: []const u32 };
+        const Key = struct { hash: Map.Hash, tag: Pool.Tag, extra: []const u32 };
         const CTypeAdapter = struct {
             pool: *const Pool,
             pub fn hash(_: @This(), key: Key) Map.Hash {
@@ -2239,7 +2258,7 @@ pub const Pool = struct {
     }
 
     const Item = struct {
-        tag: Tag,
+        tag: Pool.Tag,
         data: u32,
     };
 
src/codegen/c.zig
@@ -2475,14 +2475,20 @@ pub fn genTypeDecl(
         .basic, .pointer, .array, .vector, .function => {},
         .aligned => |aligned_info| {
             if (!found_existing) {
-                try writer.writeAll("typedef ");
-                try writer.print("{}", .{
-                    try renderTypePrefix(pass, global_ctype_pool, zcu, writer, aligned_info.ctype, .suffix, .{}),
-                });
-                try renderAlignedTypeName(writer, global_ctype);
-                try renderTypeSuffix(pass, global_ctype_pool, zcu, writer, aligned_info.ctype, .suffix, .{});
                 std.debug.assert(aligned_info.alignas.abiOrder().compare(.lt));
-                try writer.print(" zig_under_align({d});\n", .{aligned_info.alignas.toByteUnits()});
+                try writer.print("typedef zig_under_align({d}) ", .{aligned_info.alignas.toByteUnits()});
+                try writer.print("{}", .{try renderTypePrefix(
+                    .flush,
+                    global_ctype_pool,
+                    zcu,
+                    writer,
+                    aligned_info.ctype,
+                    .suffix,
+                    .{},
+                )});
+                try renderAlignedTypeName(writer, global_ctype);
+                try renderTypeSuffix(.flush, global_ctype_pool, zcu, writer, aligned_info.ctype, .suffix, .{});
+                try writer.writeAll(";\n");
             }
             switch (pass) {
                 .decl, .anon => {
@@ -5032,15 +5038,18 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
     const result = result: {
         const writer = f.object.writer();
         const inst_ty = f.typeOfIndex(inst);
-        const local = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) local: {
-            const local = try f.allocLocal(inst, inst_ty);
+        const inst_local = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) local: {
+            const inst_local = try f.allocLocalValue(.{
+                .ctype = try f.ctypeFromType(inst_ty, .complete),
+                .alignas = CType.AlignAs.fromAbiAlignment(inst_ty.abiAlignment(zcu)),
+            });
             if (f.wantSafety()) {
-                try f.writeCValue(writer, local, .Other);
+                try f.writeCValue(writer, inst_local, .Other);
                 try writer.writeAll(" = ");
                 try f.writeCValue(writer, .{ .undef = inst_ty }, .Other);
                 try writer.writeAll(";\n");
             }
-            break :local local;
+            break :local inst_local;
         } else .none;
 
         const locals_begin = @as(LocalIndex, @intCast(f.locals.items.len));
@@ -5063,9 +5072,12 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
             if (is_reg) {
                 const output_ty = if (output == .none) inst_ty else f.typeOf(output).childType(zcu);
                 try writer.writeAll("register ");
-                const local_value = try f.allocLocal(inst, output_ty);
-                try f.allocs.put(gpa, local_value.new_local, false);
-                try f.object.dg.renderTypeAndName(writer, output_ty, local_value, .{}, .none, .complete);
+                const output_local = try f.allocLocalValue(.{
+                    .ctype = try f.ctypeFromType(output_ty, .complete),
+                    .alignas = CType.AlignAs.fromAbiAlignment(output_ty.abiAlignment(zcu)),
+                });
+                try f.allocs.put(gpa, output_local.new_local, false);
+                try f.object.dg.renderTypeAndName(writer, output_ty, output_local, .{}, .none, .complete);
                 try writer.writeAll(" __asm(\"");
                 try writer.writeAll(constraint["={".len .. constraint.len - "}".len]);
                 try writer.writeAll("\")");
@@ -5095,9 +5107,12 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
             if (asmInputNeedsLocal(f, constraint, input_val)) {
                 const input_ty = f.typeOf(input);
                 if (is_reg) try writer.writeAll("register ");
-                const local_value = try f.allocLocal(inst, input_ty);
-                try f.allocs.put(gpa, local_value.new_local, false);
-                try f.object.dg.renderTypeAndName(writer, input_ty, local_value, Const, .none, .complete);
+                const input_local = try f.allocLocalValue(.{
+                    .ctype = try f.ctypeFromType(input_ty, .complete),
+                    .alignas = CType.AlignAs.fromAbiAlignment(input_ty.abiAlignment(zcu)),
+                });
+                try f.allocs.put(gpa, input_local.new_local, false);
+                try f.object.dg.renderTypeAndName(writer, input_ty, input_local, Const, .none, .complete);
                 if (is_reg) {
                     try writer.writeAll(" __asm(\"");
                     try writer.writeAll(constraint["{".len .. constraint.len - "}".len]);
@@ -5190,7 +5205,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
                 try f.writeCValue(writer, .{ .local = locals_index }, .Other);
                 locals_index += 1;
             } else if (output == .none) {
-                try f.writeCValue(writer, local, .FunctionArgument);
+                try f.writeCValue(writer, inst_local, .FunctionArgument);
             } else {
                 try f.writeCValueDeref(writer, try f.resolveInst(output));
             }
@@ -5246,7 +5261,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
             const is_reg = constraint[1] == '{';
             if (is_reg) {
                 try f.writeCValueDeref(writer, if (output == .none)
-                    .{ .local_ref = local.new_local }
+                    .{ .local_ref = inst_local.new_local }
                 else
                     try f.resolveInst(output));
                 try writer.writeAll(" = ");
@@ -5256,7 +5271,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
             }
         }
 
-        break :result if (f.liveness.isUnused(inst)) .none else local;
+        break :result if (f.liveness.isUnused(inst)) .none else inst_local;
     };
 
     var bt = iterateBigTomb(f, inst);
@@ -6690,25 +6705,15 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
     try writeSliceOrPtr(f, writer, src_ptr, src_ty);
     try writer.writeAll(", ");
     switch (dest_ty.ptrSize(zcu)) {
-        .Slice => {
-            const elem_ty = dest_ty.childType(zcu);
-            const elem_abi_size = elem_ty.abiSize(zcu);
-            try f.writeCValueMember(writer, dest_ptr, .{ .identifier = "len" });
-            if (elem_abi_size > 1) {
-                try writer.print(" * {d});\n", .{elem_abi_size});
-            } else {
-                try writer.writeAll(");\n");
-            }
-        },
-        .One => {
-            const array_ty = dest_ty.childType(zcu);
-            const elem_ty = array_ty.childType(zcu);
-            const elem_abi_size = elem_ty.abiSize(zcu);
-            const len = array_ty.arrayLen(zcu) * elem_abi_size;
-            try writer.print("{d});\n", .{len});
-        },
+        .One => try writer.print("{}", .{
+            try f.fmtIntLiteral(try zcu.intValue(Type.usize, dest_ty.childType(zcu).arrayLen(zcu))),
+        }),
         .Many, .C => unreachable,
+        .Slice => try f.writeCValueMember(writer, dest_ptr, .{ .identifier = "len" }),
     }
+    try writer.writeAll(" * sizeof(");
+    try f.renderType(writer, dest_ty.elemType2(zcu));
+    try writer.writeAll("));\n");
 
     try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
     return .none;
src/Sema.zig
@@ -36125,7 +36125,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
         // alignment is greater.
         var size: u64 = 0;
         var padding: u32 = 0;
-        if (tag_align.compare(.gte, max_align)) {
+        if (tag_align.order(max_align).compare(.gte)) {
             // {Tag, Payload}
             size += tag_size;
             size = max_align.forward(size);
@@ -36136,7 +36136,10 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
         } else {
             // {Payload, Tag}
             size += max_size;
-            size = tag_align.forward(size);
+            size = switch (mod.getTarget().ofmt) {
+                .c => max_align,
+                else => tag_align,
+            }.forward(size);
             size += tag_size;
             const prev_size = size;
             size = max_align.forward(size);