aboutsummaryrefslogtreecommitdiff
path: root/tools/generate_c_size_and_align_checks.zig
blob: 3663756533ef4bd8595932e6f359267bb2d96b61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//! 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 cName(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(.{}) = .init;

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);
    }

    var threaded: std.Io.Threaded = .init(gpa);
    defer threaded.deinit();
    const io = threaded.io();

    const query = try std.Target.Query.parse(.{ .arch_os_abi = args[1] });
    const target = try std.zig.system.resolveTargetQuery(io, query);

    var buffer: [2000]u8 = undefined;
    var stdout_writer = std.fs.File.stdout().writerStreaming(&buffer);
    const w = &stdout_writer.interface;
    inline for (@typeInfo(std.Target.CType).@"enum".fields) |field| {
        const c_type: std.Target.CType = @enumFromInt(field.value);
        try w.print("_Static_assert(sizeof({0s}) == {1d}, \"sizeof({0s}) == {1d}\");\n", .{
            cName(c_type),
            target.cTypeByteSize(c_type),
        });
        try w.print("_Static_assert(_Alignof({0s}) == {1d}, \"_Alignof({0s}) == {1d}\");\n", .{
            cName(c_type),
            target.cTypeAlignment(c_type),
        });
        try w.print("_Static_assert(__alignof({0s}) == {1d}, \"__alignof({0s}) == {1d}\");\n\n", .{
            cName(c_type),
            target.cTypePreferredAlignment(c_type),
        });
    }
    try w.flush();
}