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}