diff --git a/lib/zig.h b/lib/zig.h index f2ae283baf..ec7508670d 100644 --- a/lib/zig.h +++ b/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))) -#elif _MSC_VER -#define zig_align(alignment) __declspec(align(alignment)) -#else -#define zig_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) +#define zig_under_align(alignment) __declspec(align(alignment)) #else -#define zig_align zig_align_unavailable +#define zig_under_align zig_align_unavailable +#endif + +#if __STDC_VERSION__ >= 201112L +#define zig_align(alignment) _Alignas(alignment) +#else +#define zig_align(alignment) zig_under_align(alignment) #endif #if zig_has_attribute(aligned) diff --git a/src/Sema.zig b/src/Sema.zig index 6061dbfea4..3c999e507e 100644 --- a/src/Sema.zig +++ b/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); diff --git a/src/codegen/c.zig b/src/codegen/c.zig index cec7cdcd99..883f3f7c77 100644 --- a/src/codegen/c.zig +++ b/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; diff --git a/src/codegen/c/Type.zig b/src/codegen/c/Type.zig index 16fb7d708a..1c460acc6b 100644 --- a/src/codegen/c/Type.zig +++ b/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, };