From 4bdf04654e3bd8ac09882cb49595f6797f2f5d09 Mon Sep 17 00:00:00 2001 From: Evan Haas Date: Mon, 5 Aug 2024 12:54:56 -0700 Subject: [PATCH 1/4] tools: Add tool for checking size and alignment of C types Prints _Static_asserts for the size and alignment of all the basic built-in C types. The output can be run through a compiler for the specified target to verify that Zig's values are the same as those used by a C compiler for the target. --- tools/generate_c_size_and_align_checks.zig | 57 ++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tools/generate_c_size_and_align_checks.zig diff --git a/tools/generate_c_size_and_align_checks.zig b/tools/generate_c_size_and_align_checks.zig new file mode 100644 index 000000000000..ed52da628648 --- /dev/null +++ b/tools/generate_c_size_and_align_checks.zig @@ -0,0 +1,57 @@ +//! Usage: zig run tools/generate_c_size_and_align_checks.zig -- [target_triple] +//! e.g. zig run tools/generate_c_size_and_align_checks.zig -- x86_64-linux-gnu +//! +//! Prints _Static_asserts for the size and alignment of all the basic built-in C +//! types. The output can be run through a compiler for the specified target to +//! verify that Zig's values are the same as those used by a C compiler for the +//! target. + +const std = @import("std"); + +fn c_name(ty: std.Target.CType) []const u8 { + return switch (ty) { + .char => "char", + .short => "short", + .ushort => "unsigned short", + .int => "int", + .uint => "unsigned int", + .long => "long", + .ulong => "unsigned long", + .longlong => "long long", + .ulonglong => "unsigned long long", + .float => "float", + .double => "double", + .longdouble => "long double", + }; +} + +var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){}; + +pub fn main() !void { + const gpa = general_purpose_allocator.allocator(); + defer std.debug.assert(general_purpose_allocator.deinit() == .ok); + + const args = try std.process.argsAlloc(gpa); + defer std.process.argsFree(gpa, args); + + if (args.len != 2) { + std.debug.print("Usage: {s} [target_triple]\n", .{args[0]}); + std.process.exit(1); + } + + const query = try std.Target.Query.parse(.{ .arch_os_abi = args[1] }); + const target = try std.zig.system.resolveTargetQuery(query); + + const stdout = std.io.getStdOut().writer(); + inline for (@typeInfo(std.Target.CType).Enum.fields) |field| { + const c_type: std.Target.CType = @enumFromInt(field.value); + try stdout.print("_Static_assert(sizeof({s}) == {d}, \"\");\n", .{ + c_name(c_type), + target.c_type_byte_size(c_type), + }); + try stdout.print("_Static_assert(_Alignof({s}) == {d}, \"\");\n\n", .{ + c_name(c_type), + target.c_type_alignment(c_type), + }); + } +} From 8daf7673a5d92514407f333de60865ea06fcb274 Mon Sep 17 00:00:00 2001 From: Evan Haas Date: Mon, 5 Aug 2024 13:15:05 -0700 Subject: [PATCH 2/4] test: Add generate_c_size_and_align_checks.zig to standalone build test --- test/standalone/build.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/test/standalone/build.zig b/test/standalone/build.zig index b2575bc83e3e..98b48576adea 100644 --- a/test/standalone/build.zig +++ b/test/standalone/build.zig @@ -34,6 +34,7 @@ pub fn build(b: *std.Build) void { "../../tools/gen_outline_atomics.zig", "../../tools/gen_spirv_spec.zig", "../../tools/gen_stubs.zig", + "../../tools/generate_c_size_and_align_checks.zig", "../../tools/generate_linux_syscalls.zig", "../../tools/process_headers.zig", "../../tools/update-linux-headers.zig", From b2dd0a669a96b874271069bb2ea3dd41dcc2fd48 Mon Sep 17 00:00:00 2001 From: Evan Haas Date: Tue, 6 Aug 2024 07:02:22 -0700 Subject: [PATCH 3/4] generate_c_size_and_align_checks: print failed condition in _Static_assert --- tools/generate_c_size_and_align_checks.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/generate_c_size_and_align_checks.zig b/tools/generate_c_size_and_align_checks.zig index ed52da628648..d0d6bb66d5ca 100644 --- a/tools/generate_c_size_and_align_checks.zig +++ b/tools/generate_c_size_and_align_checks.zig @@ -45,11 +45,11 @@ pub fn main() !void { const stdout = std.io.getStdOut().writer(); inline for (@typeInfo(std.Target.CType).Enum.fields) |field| { const c_type: std.Target.CType = @enumFromInt(field.value); - try stdout.print("_Static_assert(sizeof({s}) == {d}, \"\");\n", .{ + try stdout.print("_Static_assert(sizeof({0s}) == {1d}, \"sizeof({0s}) == {1d}\");\n", .{ c_name(c_type), target.c_type_byte_size(c_type), }); - try stdout.print("_Static_assert(_Alignof({s}) == {d}, \"\");\n\n", .{ + try stdout.print("_Static_assert(_Alignof({0s}) == {1d}, \"_Alignof({0s}) == {1d}\");\n\n", .{ c_name(c_type), target.c_type_alignment(c_type), }); From 679ad36fa069a723aa9094afbd09d1b460232dda Mon Sep 17 00:00:00 2001 From: Evan Haas Date: Tue, 6 Aug 2024 07:06:57 -0700 Subject: [PATCH 4/4] generate_c_size_and_align_checks: add __alignof check --- tools/generate_c_size_and_align_checks.zig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/generate_c_size_and_align_checks.zig b/tools/generate_c_size_and_align_checks.zig index d0d6bb66d5ca..840ef2b6eb88 100644 --- a/tools/generate_c_size_and_align_checks.zig +++ b/tools/generate_c_size_and_align_checks.zig @@ -53,5 +53,9 @@ pub fn main() !void { c_name(c_type), target.c_type_alignment(c_type), }); + try stdout.print("_Static_assert(__alignof({0s}) == {1d}, \"__alignof({0s}) == {1d}\");\n\n", .{ + c_name(c_type), + target.c_type_preferred_alignment(c_type), + }); } }