diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2024-09-28 02:10:25 +0100 |
|---|---|---|
| committer | mlugg <mlugg@mlugg.co.uk> | 2024-10-19 19:08:59 +0100 |
| commit | 51706af908e0c6acb822ef36760b7fe31faf62a6 (patch) | |
| tree | d814bcfcfd83ebc5fd50da11f18a9a6427a54859 /src/InternPool.zig | |
| parent | 8573836892ba1b7cd34d377b46258930161256c3 (diff) | |
| download | zig-51706af908e0c6acb822ef36760b7fe31faf62a6.tar.gz zig-51706af908e0c6acb822ef36760b7fe31faf62a6.zip | |
compiler: introduce new `CallingConvention`
This commit begins implementing accepted proposal #21209 by making
`std.builtin.CallingConvention` a tagged union.
The stage1 dance here is a little convoluted. This commit introduces the
new type as `NewCallingConvention`, keeping the old `CallingConvention`
around. The compiler uses `std.builtin.NewCallingConvention`
exclusively, but when fetching the type from `std` when running the
compiler (e.g. with `getBuiltinType`), the name `CallingConvention` is
used. This allows a prior build of Zig to be used to build this commit.
The next commit will update `zig1.wasm`, and then the compiler and
standard library can be updated to completely replace
`CallingConvention` with `NewCallingConvention`.
The second half of #21209 is to remove `@setAlignStack`, which will be
implemented in another commit after updating `zig1.wasm`.
Diffstat (limited to 'src/InternPool.zig')
| -rw-r--r-- | src/InternPool.zig | 105 |
1 files changed, 92 insertions, 13 deletions
diff --git a/src/InternPool.zig b/src/InternPool.zig index 4315855d83..11fee424ec 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -1988,7 +1988,7 @@ pub const Key = union(enum) { /// Tells whether a parameter is noalias. See `paramIsNoalias` helper /// method for accessing this. noalias_bits: u32, - cc: std.builtin.CallingConvention, + cc: std.builtin.NewCallingConvention, is_var_args: bool, is_generic: bool, is_noinline: bool, @@ -2011,10 +2011,10 @@ pub const Key = union(enum) { a.return_type == b.return_type and a.comptime_bits == b.comptime_bits and a.noalias_bits == b.noalias_bits and - a.cc == b.cc and a.is_var_args == b.is_var_args and a.is_generic == b.is_generic and - a.is_noinline == b.is_noinline; + a.is_noinline == b.is_noinline and + std.meta.eql(a.cc, b.cc); } pub fn hash(self: FuncType, hasher: *Hash, ip: *const InternPool) void { @@ -5444,7 +5444,7 @@ pub const Tag = enum(u8) { flags: Flags, pub const Flags = packed struct(u32) { - cc: std.builtin.CallingConvention, + cc: PackedCallingConvention, is_var_args: bool, is_generic: bool, has_comptime_bits: bool, @@ -5453,7 +5453,7 @@ pub const Tag = enum(u8) { cc_is_generic: bool, section_is_generic: bool, addrspace_is_generic: bool, - _: u16 = 0, + _: u6 = 0, }; }; @@ -6912,7 +6912,7 @@ fn extraFuncType(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke .return_type = type_function.data.return_type, .comptime_bits = comptime_bits, .noalias_bits = noalias_bits, - .cc = type_function.data.flags.cc, + .cc = type_function.data.flags.cc.unpack(), .is_var_args = type_function.data.flags.is_var_args, .is_noinline = type_function.data.flags.is_noinline, .cc_is_generic = type_function.data.flags.cc_is_generic, @@ -8526,7 +8526,7 @@ pub const GetFuncTypeKey = struct { comptime_bits: u32 = 0, noalias_bits: u32 = 0, /// `null` means generic. - cc: ?std.builtin.CallingConvention = .Unspecified, + cc: ?std.builtin.NewCallingConvention = .auto, is_var_args: bool = false, is_generic: bool = false, is_noinline: bool = false, @@ -8564,7 +8564,7 @@ pub fn getFuncType( .params_len = params_len, .return_type = key.return_type, .flags = .{ - .cc = key.cc orelse .Unspecified, + .cc = .pack(key.cc orelse .auto), .is_var_args = key.is_var_args, .has_comptime_bits = key.comptime_bits != 0, .has_noalias_bits = key.noalias_bits != 0, @@ -8668,7 +8668,7 @@ pub const GetFuncDeclKey = struct { rbrace_line: u32, lbrace_column: u32, rbrace_column: u32, - cc: ?std.builtin.CallingConvention, + cc: ?std.builtin.NewCallingConvention, is_noinline: bool, }; @@ -8733,7 +8733,7 @@ pub const GetFuncDeclIesKey = struct { comptime_bits: u32, bare_return_type: Index, /// null means generic. - cc: ?std.builtin.CallingConvention, + cc: ?std.builtin.NewCallingConvention, /// null means generic. alignment: ?Alignment, section_is_generic: bool, @@ -8818,7 +8818,7 @@ pub fn getFuncDeclIes( .params_len = params_len, .return_type = error_union_type, .flags = .{ - .cc = key.cc orelse .Unspecified, + .cc = .pack(key.cc orelse .auto), .is_var_args = key.is_var_args, .has_comptime_bits = key.comptime_bits != 0, .has_noalias_bits = key.noalias_bits != 0, @@ -8948,7 +8948,7 @@ pub const GetFuncInstanceKey = struct { comptime_args: []const Index, noalias_bits: u32, bare_return_type: Index, - cc: std.builtin.CallingConvention, + cc: std.builtin.NewCallingConvention, alignment: Alignment, section: OptionalNullTerminatedString, is_noinline: bool, @@ -9110,7 +9110,7 @@ pub fn getFuncInstanceIes( .params_len = params_len, .return_type = error_union_type, .flags = .{ - .cc = arg.cc, + .cc = .pack(arg.cc), .is_var_args = false, .has_comptime_bits = false, .has_noalias_bits = arg.noalias_bits != 0, @@ -12224,3 +12224,82 @@ pub fn getErrorValue( pub fn getErrorValueIfExists(ip: *const InternPool, name: NullTerminatedString) ?Zcu.ErrorInt { return @intFromEnum(ip.global_error_set.getErrorValueIfExists(name) orelse return null); } + +const PackedCallingConvention = packed struct(u18) { + tag: std.builtin.NewCallingConvention.Tag, + /// May be ignored depending on `tag`. + incoming_stack_alignment: Alignment, + /// Interpretation depends on `tag`. + extra: u4, + + fn pack(cc: std.builtin.NewCallingConvention) PackedCallingConvention { + return switch (cc) { + inline else => |pl, tag| switch (@TypeOf(pl)) { + void => .{ + .tag = tag, + .incoming_stack_alignment = .none, // unused + .extra = 0, // unused + }, + std.builtin.NewCallingConvention.CommonOptions => .{ + .tag = tag, + .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0), + .extra = 0, // unused + }, + std.builtin.NewCallingConvention.X86RegparmOptions => .{ + .tag = tag, + .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0), + .extra = pl.register_params, + }, + std.builtin.NewCallingConvention.ArmInterruptOptions => .{ + .tag = tag, + .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0), + .extra = @intFromEnum(pl.type), + }, + std.builtin.NewCallingConvention.MipsInterruptOptions => .{ + .tag = tag, + .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0), + .extra = @intFromEnum(pl.mode), + }, + std.builtin.NewCallingConvention.RiscvInterruptOptions => .{ + .tag = tag, + .incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0), + .extra = @intFromEnum(pl.level), + }, + else => comptime unreachable, + }, + }; + } + + fn unpack(cc: PackedCallingConvention) std.builtin.NewCallingConvention { + @setEvalBranchQuota(400_000); + return switch (cc.tag) { + inline else => |tag| @unionInit( + std.builtin.NewCallingConvention, + @tagName(tag), + switch (std.meta.FieldType(std.builtin.NewCallingConvention, tag)) { + void => {}, + std.builtin.NewCallingConvention.CommonOptions => .{ + .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(), + }, + std.builtin.NewCallingConvention.X86RegparmOptions => .{ + .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(), + .register_params = @intCast(cc.extra), + }, + std.builtin.NewCallingConvention.ArmInterruptOptions => .{ + .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(), + .type = @enumFromInt(cc.extra), + }, + std.builtin.NewCallingConvention.MipsInterruptOptions => .{ + .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(), + .mode = @enumFromInt(cc.extra), + }, + std.builtin.NewCallingConvention.RiscvInterruptOptions => .{ + .incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(), + .level = @enumFromInt(cc.extra), + }, + else => comptime unreachable, + }, + ), + }; + } +}; |
