Skip to content

Commit

Permalink
std: update for new CallingConvention
Browse files Browse the repository at this point in the history
The old `CallingConvention` type is replaced with the new
`NewCallingConvention`. References to `NewCallingConvention` in the
compiler are updated accordingly. In addition, a few parts of the
standard library are updated to use the new type correctly.
  • Loading branch information
mlugg committed Oct 19, 2024
1 parent 36405b9 commit bc797a9
Show file tree
Hide file tree
Showing 19 changed files with 109 additions and 160 deletions.
4 changes: 2 additions & 2 deletions lib/std/Target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1612,7 +1612,7 @@ pub const Cpu = struct {

/// Returns the array of `Arch` to which a specific `std.builtin.CallingConvention` applies.
/// Asserts that `cc` is not `.auto`, `.@"async"`, `.naked`, or `.@"inline"`.
pub fn fromCallconv(cc: std.builtin.NewCallingConvention) []const Arch {
pub fn fromCallconv(cc: std.builtin.CallingConvention) []const Arch {
return switch (cc) {
.auto,
.@"async",
Expand Down Expand Up @@ -3032,7 +3032,7 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 {
);
}

pub fn defaultCCallingConvention(target: Target) ?std.builtin.NewCallingConvention {
pub fn defaultCCallingConvention(target: Target) ?std.builtin.CallingConvention {
return switch (target.cpu.arch) {
.x86_64 => switch (target.os.tag) {
.windows, .uefi => .{ .x86_64_win = .{} },
Expand Down
107 changes: 31 additions & 76 deletions lib/std/builtin.zig
Original file line number Diff line number Diff line change
Expand Up @@ -160,134 +160,82 @@ pub const OptimizeMode = enum {
/// Deprecated; use OptimizeMode.
pub const Mode = OptimizeMode;

/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const CallingConvention = enum(u8) {
/// This is the default Zig calling convention used when not using `export` on `fn`
/// and no other calling convention is specified.
Unspecified,
/// Matches the C ABI for the target.
/// This is the default calling convention when using `export` on `fn`
/// and no other calling convention is specified.
C,
/// This makes a function not have any function prologue or epilogue,
/// making the function itself uncallable in regular Zig code.
/// This can be useful when integrating with assembly.
Naked,
/// Functions with this calling convention are called asynchronously,
/// as if called as `async function()`.
Async,
/// Functions with this calling convention are inlined at all call sites.
Inline,
/// x86-only.
Interrupt,
Signal,
/// x86-only.
Stdcall,
/// x86-only.
Fastcall,
/// x86-only.
Vectorcall,
/// x86-only.
Thiscall,
/// ARM Procedure Call Standard (obsolete)
/// ARM-only.
APCS,
/// ARM Architecture Procedure Call Standard (current standard)
/// ARM-only.
AAPCS,
/// ARM Architecture Procedure Call Standard Vector Floating-Point
/// ARM-only.
AAPCSVFP,
/// x86-64-only.
SysV,
/// x86-64-only.
Win64,
/// AMD GPU, NVPTX, or SPIR-V kernel
Kernel,
// Vulkan-only
Fragment,
Vertex,
};

/// The calling convention of a function defines how arguments and return values are passed, as well
/// as any other requirements which callers and callees must respect, such as register preservation
/// and stack alignment.
///
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
///
/// TODO: this will be renamed `CallingConvention` after an initial zig1.wasm update.
pub const NewCallingConvention = union(enum(u8)) {
pub const Tag = @typeInfo(NewCallingConvention).@"union".tag_type.?;
pub const CallingConvention = union(enum(u8)) {
pub const Tag = @typeInfo(CallingConvention).@"union".tag_type.?;

/// This is an alias for the default C calling convention for this target.
/// Functions marked as `extern` or `export` are given this calling convention by default.
pub const c = builtin.target.defaultCCallingConvention().?;

pub const winapi: NewCallingConvention = switch (builtin.target.arch) {
pub const winapi: CallingConvention = switch (builtin.target.arch) {
.x86_64 => .{ .x86_64_win = .{} },
.x86 => .{ .x86_stdcall = .{} },
.aarch64, .aarch64_be => .{ .aarch64_aapcs_win = .{} },
.arm, .armeb, .thumb, .thumbeb => .{ .arm_aapcs_vfp = .{} },
else => unreachable,
};

pub const kernel: NewCallingConvention = switch (builtin.target.cpu.arch) {
pub const kernel: CallingConvention = switch (builtin.target.cpu.arch) {
.amdgcn => .amdgcn_kernel,
.nvptx, .nvptx64 => .nvptx_kernel,
.spirv, .spirv32, .spirv64 => .spirv_kernel,
else => unreachable,
};

/// Deprecated; use `.auto`.
pub const Unspecified: NewCallingConvention = .auto;
pub const Unspecified: CallingConvention = .auto;
/// Deprecated; use `.c`.
pub const C: NewCallingConvention = .c;
pub const C: CallingConvention = .c;
/// Deprecated; use `.naked`.
pub const Naked: NewCallingConvention = .naked;
pub const Naked: CallingConvention = .naked;
/// Deprecated; use `.@"async"`.
pub const Async: NewCallingConvention = .@"async";
pub const Async: CallingConvention = .@"async";
/// Deprecated; use `.@"inline"`.
pub const Inline: NewCallingConvention = .@"inline";
pub const Inline: CallingConvention = .@"inline";
/// Deprecated; use `.x86_64_interrupt`, `.x86_interrupt`, or `.avr_interrupt`.
pub const Interrupt: NewCallingConvention = switch (builtin.target.cpu.arch) {
pub const Interrupt: CallingConvention = switch (builtin.target.cpu.arch) {
.x86_64 => .{ .x86_64_interrupt = .{} },
.x86 => .{ .x86_interrupt = .{} },
.avr => .avr_interrupt,
else => unreachable,
};
/// Deprecated; use `.avr_signal`.
pub const Signal: NewCallingConvention = .avr_signal;
pub const Signal: CallingConvention = .avr_signal;
/// Deprecated; use `.x86_stdcall`.
pub const Stdcall: NewCallingConvention = .{ .x86_stdcall = .{} };
pub const Stdcall: CallingConvention = .{ .x86_stdcall = .{} };
/// Deprecated; use `.x86_fastcall`.
pub const Fastcall: NewCallingConvention = .{ .x86_fastcall = .{} };
pub const Fastcall: CallingConvention = .{ .x86_fastcall = .{} };
/// Deprecated; use `.x86_64_vectorcall`, `.x86_vectorcall`, or `aarch64_vfabi`.
pub const Vectorcall: NewCallingConvention = switch (builtin.target.cpu.arch) {
pub const Vectorcall: CallingConvention = switch (builtin.target.cpu.arch) {
.x86_64 => .{ .x86_64_vectorcall = .{} },
.x86 => .{ .x86_vectorcall = .{} },
.aarch64, .aarch64_be => .{ .aarch64_vfabi = .{} },
else => unreachable,
};
/// Deprecated; use `.x86_thiscall`.
pub const Thiscall: NewCallingConvention = .{ .x86_thiscall = .{} };
pub const Thiscall: CallingConvention = .{ .x86_thiscall = .{} };
/// Deprecated; use `.arm_apcs`.
pub const APCS: NewCallingConvention = .{ .arm_apcs = .{} };
pub const APCS: CallingConvention = .{ .arm_apcs = .{} };
/// Deprecated; use `.arm_aapcs`.
pub const AAPCS: NewCallingConvention = .{ .arm_aapcs = .{} };
pub const AAPCS: CallingConvention = .{ .arm_aapcs = .{} };
/// Deprecated; use `.arm_aapcs_vfp`.
pub const AAPCSVFP: NewCallingConvention = .{ .arm_aapcs_vfp = .{} };
pub const AAPCSVFP: CallingConvention = .{ .arm_aapcs_vfp = .{} };
/// Deprecated; use `.x86_64_sysv`.
pub const SysV: NewCallingConvention = .{ .x86_64_sysv = .{} };
pub const SysV: CallingConvention = .{ .x86_64_sysv = .{} };
/// Deprecated; use `.x86_64_win`.
pub const Win64: NewCallingConvention = .{ .x86_64_win = .{} };
pub const Win64: CallingConvention = .{ .x86_64_win = .{} };
/// Deprecated; use `.kernel`.
pub const Kernel: NewCallingConvention = .kernel;
pub const Kernel: CallingConvention = .kernel;
/// Deprecated; use `.spirv_fragment`.
pub const Fragment: NewCallingConvention = .spirv_fragment;
pub const Fragment: CallingConvention = .spirv_fragment;
/// Deprecated; use `.spirv_vertex`.
pub const Vertex: NewCallingConvention = .spirv_vertex;
pub const Vertex: CallingConvention = .spirv_vertex;

/// The default Zig calling convention when neither `export` nor `inline` is specified.
/// This calling convention makes no guarantees about stack alignment, registers, etc.
Expand Down Expand Up @@ -535,9 +483,16 @@ pub const NewCallingConvention = union(enum(u8)) {
/// Asserts that `cc` is not `.auto`, `.@"async"`, `.naked`, or `.@"inline"`.
pub const archs = std.Target.Cpu.Arch.fromCallconv;

pub fn eql(a: NewCallingConvention, b: NewCallingConvention) bool {
pub fn eql(a: CallingConvention, b: CallingConvention) bool {
return std.meta.eql(a, b);
}

pub fn withStackAlign(cc: CallingConvention, incoming_stack_alignment: u64) CallingConvention {
const tag: CallingConvention.Tag = cc;
var result = cc;
@field(result, tag).incoming_stack_alignment = incoming_stack_alignment;
return result;
}
};

/// This data structure is used by the Zig language code generation and
Expand Down
6 changes: 3 additions & 3 deletions lib/std/crypto/25519/field.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ const NonCanonicalError = crypto.errors.NonCanonicalError;
const NotSquareError = crypto.errors.NotSquareError;

// Inline conditionally, when it can result in large code generation.
const bloaty_inline = switch (builtin.mode) {
.ReleaseSafe, .ReleaseFast => .Inline,
.Debug, .ReleaseSmall => .Unspecified,
const bloaty_inline: std.builtin.CallingConvention = switch (builtin.mode) {
.ReleaseSafe, .ReleaseFast => .@"inline",
.Debug, .ReleaseSmall => .auto,
};

pub const Fe = struct {
Expand Down
5 changes: 1 addition & 4 deletions lib/std/os/windows.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2824,10 +2824,7 @@ pub const STD_OUTPUT_HANDLE = maxInt(DWORD) - 11 + 1;
/// The standard error device. Initially, this is the active console screen buffer, CONOUT$.
pub const STD_ERROR_HANDLE = maxInt(DWORD) - 12 + 1;

pub const WINAPI: std.builtin.CallingConvention = if (native_arch == .x86)
.Stdcall
else
.C;
pub const WINAPI: std.builtin.CallingConvention = .winapi;

pub const BOOL = c_int;
pub const BOOLEAN = BYTE;
Expand Down
11 changes: 4 additions & 7 deletions lib/std/start.zig
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ comptime {
if (builtin.link_libc and @hasDecl(root, "main")) {
if (native_arch.isWasm()) {
@export(&mainWithoutEnv, .{ .name = "main" });
} else if (@typeInfo(@TypeOf(root.main)).@"fn".calling_convention != .C) {
} else if (!@typeInfo(@TypeOf(root.main)).@"fn".calling_convention.eql(.c)) {
@export(&main, .{ .name = "main" });
}
} else if (native_os == .windows) {
Expand Down Expand Up @@ -102,12 +102,11 @@ fn main2() callconv(.C) c_int {
return 0;
}

fn _start2() callconv(.C) noreturn {
fn _start2() callconv(.withStackAlign(.c, 1)) noreturn {
callMain2();
}

fn callMain2() noreturn {
@setAlignStack(16);
root.main();
exit2(0);
}
Expand Down Expand Up @@ -428,8 +427,7 @@ fn _start() callconv(.Naked) noreturn {
);
}

fn WinStartup() callconv(std.os.windows.WINAPI) noreturn {
@setAlignStack(16);
fn WinStartup() callconv(.withStackAlign(.winapi, 1)) noreturn {
if (!builtin.single_threaded and !builtin.link_libc) {
_ = @import("os/windows/tls.zig");
}
Expand All @@ -439,8 +437,7 @@ fn WinStartup() callconv(std.os.windows.WINAPI) noreturn {
std.os.windows.ntdll.RtlExitUserProcess(callMain());
}

fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {
@setAlignStack(16);
fn wWinMainCRTStartup() callconv(.withStackAlign(.winapi, 1)) noreturn {
if (!builtin.single_threaded and !builtin.link_libc) {
_ = @import("os/windows/tls.zig");
}
Expand Down
40 changes: 20 additions & 20 deletions src/InternPool.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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.NewCallingConvention,
cc: std.builtin.CallingConvention,
is_var_args: bool,
is_generic: bool,
is_noinline: bool,
Expand Down Expand Up @@ -8526,7 +8526,7 @@ pub const GetFuncTypeKey = struct {
comptime_bits: u32 = 0,
noalias_bits: u32 = 0,
/// `null` means generic.
cc: ?std.builtin.NewCallingConvention = .auto,
cc: ?std.builtin.CallingConvention = .auto,
is_var_args: bool = false,
is_generic: bool = false,
is_noinline: bool = false,
Expand Down Expand Up @@ -8668,7 +8668,7 @@ pub const GetFuncDeclKey = struct {
rbrace_line: u32,
lbrace_column: u32,
rbrace_column: u32,
cc: ?std.builtin.NewCallingConvention,
cc: ?std.builtin.CallingConvention,
is_noinline: bool,
};

Expand Down Expand Up @@ -8733,7 +8733,7 @@ pub const GetFuncDeclIesKey = struct {
comptime_bits: u32,
bare_return_type: Index,
/// null means generic.
cc: ?std.builtin.NewCallingConvention,
cc: ?std.builtin.CallingConvention,
/// null means generic.
alignment: ?Alignment,
section_is_generic: bool,
Expand Down Expand Up @@ -8948,7 +8948,7 @@ pub const GetFuncInstanceKey = struct {
comptime_args: []const Index,
noalias_bits: u32,
bare_return_type: Index,
cc: std.builtin.NewCallingConvention,
cc: std.builtin.CallingConvention,
alignment: Alignment,
section: OptionalNullTerminatedString,
is_noinline: bool,
Expand Down Expand Up @@ -12226,41 +12226,41 @@ pub fn getErrorValueIfExists(ip: *const InternPool, name: NullTerminatedString)
}

const PackedCallingConvention = packed struct(u18) {
tag: std.builtin.NewCallingConvention.Tag,
tag: std.builtin.CallingConvention.Tag,
/// May be ignored depending on `tag`.
incoming_stack_alignment: Alignment,
/// Interpretation depends on `tag`.
extra: u4,

fn pack(cc: std.builtin.NewCallingConvention) PackedCallingConvention {
fn pack(cc: std.builtin.CallingConvention) 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 => .{
std.builtin.CallingConvention.CommonOptions => .{
.tag = tag,
.incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0),
.extra = 0, // unused
},
std.builtin.NewCallingConvention.X86RegparmOptions => .{
std.builtin.CallingConvention.X86RegparmOptions => .{
.tag = tag,
.incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0),
.extra = pl.register_params,
},
std.builtin.NewCallingConvention.ArmInterruptOptions => .{
std.builtin.CallingConvention.ArmInterruptOptions => .{
.tag = tag,
.incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0),
.extra = @intFromEnum(pl.type),
},
std.builtin.NewCallingConvention.MipsInterruptOptions => .{
std.builtin.CallingConvention.MipsInterruptOptions => .{
.tag = tag,
.incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0),
.extra = @intFromEnum(pl.mode),
},
std.builtin.NewCallingConvention.RiscvInterruptOptions => .{
std.builtin.CallingConvention.RiscvInterruptOptions => .{
.tag = tag,
.incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0),
.extra = @intFromEnum(pl.level),
Expand All @@ -12270,30 +12270,30 @@ const PackedCallingConvention = packed struct(u18) {
};
}

fn unpack(cc: PackedCallingConvention) std.builtin.NewCallingConvention {
fn unpack(cc: PackedCallingConvention) std.builtin.CallingConvention {
@setEvalBranchQuota(400_000);
return switch (cc.tag) {
inline else => |tag| @unionInit(
std.builtin.NewCallingConvention,
std.builtin.CallingConvention,
@tagName(tag),
switch (std.meta.FieldType(std.builtin.NewCallingConvention, tag)) {
switch (std.meta.FieldType(std.builtin.CallingConvention, tag)) {
void => {},
std.builtin.NewCallingConvention.CommonOptions => .{
std.builtin.CallingConvention.CommonOptions => .{
.incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(),
},
std.builtin.NewCallingConvention.X86RegparmOptions => .{
std.builtin.CallingConvention.X86RegparmOptions => .{
.incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(),
.register_params = @intCast(cc.extra),
},
std.builtin.NewCallingConvention.ArmInterruptOptions => .{
std.builtin.CallingConvention.ArmInterruptOptions => .{
.incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(),
.type = @enumFromInt(cc.extra),
},
std.builtin.NewCallingConvention.MipsInterruptOptions => .{
std.builtin.CallingConvention.MipsInterruptOptions => .{
.incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(),
.mode = @enumFromInt(cc.extra),
},
std.builtin.NewCallingConvention.RiscvInterruptOptions => .{
std.builtin.CallingConvention.RiscvInterruptOptions => .{
.incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(),
.level = @enumFromInt(cc.extra),
},
Expand Down
Loading

0 comments on commit bc797a9

Please sign in to comment.