master
 1const std = @import("std");
 2const Type = @import("../../Type.zig");
 3const Zcu = @import("../../Zcu.zig");
 4const assert = std.debug.assert;
 5
 6pub const Class = union(enum) {
 7    memory,
 8    byval,
 9    i32_array: u8,
10};
11
12pub const Context = enum { ret, arg };
13
14pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
15    const target = zcu.getTarget();
16    std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
17
18    const max_direct_size = target.ptrBitWidth() * 2;
19    switch (ty.zigTypeTag(zcu)) {
20        .@"struct" => {
21            const bit_size = ty.bitSize(zcu);
22            if (ty.containerLayout(zcu) == .@"packed") {
23                if (bit_size > max_direct_size) return .memory;
24                return .byval;
25            }
26            if (bit_size > max_direct_size) return .memory;
27            // TODO: for bit_size <= 32 using byval is more correct, but that needs inreg argument attribute
28            const count = @as(u8, @intCast(std.mem.alignForward(u64, bit_size, 32) / 32));
29            return .{ .i32_array = count };
30        },
31        .@"union" => {
32            const bit_size = ty.bitSize(zcu);
33            if (ty.containerLayout(zcu) == .@"packed") {
34                if (bit_size > max_direct_size) return .memory;
35                return .byval;
36            }
37            if (bit_size > max_direct_size) return .memory;
38
39            return .byval;
40        },
41        .bool => return .byval,
42        .float => return .byval,
43        .int, .@"enum", .error_set => {
44            return .byval;
45        },
46        .vector => {
47            const elem_type = ty.elemType2(zcu);
48            switch (elem_type.zigTypeTag(zcu)) {
49                .bool, .int => {
50                    const bit_size = ty.bitSize(zcu);
51                    if (ctx == .ret and bit_size > 128) return .memory;
52                    if (bit_size > 512) return .memory;
53                    // TODO: byval vector arguments with non power of 2 size need inreg attribute
54                    return .byval;
55                },
56                .float => return .memory,
57                else => unreachable,
58            }
59        },
60        .optional => {
61            std.debug.assert(ty.isPtrLikeOptional(zcu));
62            return .byval;
63        },
64        .pointer => {
65            std.debug.assert(!ty.isSlice(zcu));
66            return .byval;
67        },
68        .error_union,
69        .frame,
70        .@"anyframe",
71        .noreturn,
72        .void,
73        .type,
74        .comptime_float,
75        .comptime_int,
76        .undefined,
77        .null,
78        .@"fn",
79        .@"opaque",
80        .enum_literal,
81        .array,
82        => unreachable,
83    }
84}