Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tools: Add tool for checking size and alignment of C types #20951

Merged
merged 4 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions test/standalone/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
61 changes: 61 additions & 0 deletions tools/generate_c_size_and_align_checks.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//! 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({0s}) == {1d}, \"sizeof({0s}) == {1d}\");\n", .{
c_name(c_type),
target.c_type_byte_size(c_type),
});
try stdout.print("_Static_assert(_Alignof({0s}) == {1d}, \"_Alignof({0s}) == {1d}\");\n\n", .{
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),
});
}
}