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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
const std = @import("std");
const Type = @import("../../Type.zig");
const Zcu = @import("../../Zcu.zig");
const assert = std.debug.assert;
pub const Class = union(enum) {
memory,
byval,
i32_array: u8,
};
pub const Context = enum { ret, arg };
pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
const target = zcu.getTarget();
std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
const max_direct_size = target.ptrBitWidth() * 2;
switch (ty.zigTypeTag(zcu)) {
.@"struct" => {
const bit_size = ty.bitSize(zcu);
if (ty.containerLayout(zcu) == .@"packed") {
if (bit_size > max_direct_size) return .memory;
return .byval;
}
if (bit_size > max_direct_size) return .memory;
// TODO: for bit_size <= 32 using byval is more correct, but that needs inreg argument attribute
const count = @as(u8, @intCast(std.mem.alignForward(u64, bit_size, 32) / 32));
return .{ .i32_array = count };
},
.@"union" => {
const bit_size = ty.bitSize(zcu);
if (ty.containerLayout(zcu) == .@"packed") {
if (bit_size > max_direct_size) return .memory;
return .byval;
}
if (bit_size > max_direct_size) return .memory;
return .byval;
},
.bool => return .byval,
.float => return .byval,
.int, .@"enum", .error_set => {
return .byval;
},
.vector => {
const elem_type = ty.elemType2(zcu);
switch (elem_type.zigTypeTag(zcu)) {
.bool, .int => {
const bit_size = ty.bitSize(zcu);
if (ctx == .ret and bit_size > 128) return .memory;
if (bit_size > 512) return .memory;
// TODO: byval vector arguments with non power of 2 size need inreg attribute
return .byval;
},
.float => return .memory,
else => unreachable,
}
},
.optional => {
std.debug.assert(ty.isPtrLikeOptional(zcu));
return .byval;
},
.pointer => {
std.debug.assert(!ty.isSlice(zcu));
return .byval;
},
.error_union,
.frame,
.@"anyframe",
.noreturn,
.void,
.type,
.comptime_float,
.comptime_int,
.undefined,
.null,
.@"fn",
.@"opaque",
.enum_literal,
.array,
=> unreachable,
}
}
|