Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace std.builtin.CallingConvention with a tagged union, eliminating @setAlignStack #21697

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4fe966d
compiler: introduce new `CallingConvention`
mlugg Sep 28, 2024
28aafa6
stage1: update zig1.wasm
mlugg Oct 14, 2024
0f66ec6
std: update for new `CallingConvention`
mlugg Oct 8, 2024
b442da2
compiler: remove @setAlignStack
mlugg Oct 14, 2024
99be949
test: update for `CallingConvention` changes
mlugg Oct 13, 2024
0f5889e
std.zig.render: fix `callconv(.Inline)` -> `inline fn` promotion
mlugg Oct 15, 2024
ca07f24
std.Target: rename `defaultCCallingConvention` and `Cpu.Arch.fromCall…
mlugg Oct 15, 2024
8dabad6
std.builtin.CallingConvention: don't provide bogus `winapi` value
mlugg Oct 15, 2024
0baf775
link: add clarifying comment
mlugg Oct 15, 2024
8339934
std.builtin.CallingConvention: RISC-V `PrivilegeLevel` -> `PrivilegeM…
mlugg Oct 15, 2024
b0b30d0
cbe,translate-c: support more callconvs
mlugg Oct 15, 2024
15d3025
Sema: minor cleanup
mlugg Oct 15, 2024
67c53d3
std.builtin.CallingConvention: include exact architecture tags in com…
mlugg Oct 15, 2024
e92b416
compiler: avoid unreasonable eval branch quotas
mlugg Oct 15, 2024
8152020
std.builtin.CallingConvention: remove deprecated RISC-V privilege mode
mlugg Oct 15, 2024
9f644cb
llvm: fix lowering of avr_interrupt and m68k_interrupt callconvs
mlugg Oct 15, 2024
a73781e
std.Target: correct C callconv on hardfloat ARM
mlugg Oct 15, 2024
0292fe0
link.Dwarf: handle `avr_signal` and `avr_builtin` callconvs
mlugg Oct 15, 2024
42eafbc
llvn: fix incorrect mips64 callconv handling
mlugg Oct 15, 2024
766290a
std: update uses of `.Inline` callconv
mlugg Oct 16, 2024
4994d47
langref: update `enum_export_error.zig` for callconv changes
mlugg Oct 16, 2024
e36d270
Zcu: correct `callconvSupported` for self-hosted aarch64
mlugg Oct 16, 2024
b2dfb69
llvm: fix lowering `arm_aapcs_vfp` functions
mlugg Oct 16, 2024
f819f7a
compiler_rt: remove bogus tests
mlugg Oct 16, 2024
49ddffe
x86_64,riscv64: fix incorrect `incoming_stack_alignment` handling
mlugg Oct 16, 2024
39dd828
x86_64: handle incoming stack alignment
mlugg Oct 17, 2024
b77fe59
Sema: add and improve some callconv compile errors
mlugg Oct 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion doc/langref/enum_export_error.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export fn entry(foo: Foo) void {
_ = foo;
}

// obj=parameter of type 'enum_export_error.Foo' not allowed in function with calling convention 'C'
// obj=parameter of type 'enum_export_error.Foo' not allowed in function with calling convention 'x86_64_sysv'
// target=x86_64-linux
68 changes: 60 additions & 8 deletions lib/compiler/aro_translate_c/ast.zig
Original file line number Diff line number Diff line change
Expand Up @@ -550,12 +550,26 @@ pub const Payload = struct {
is_var_args: bool,
name: ?[]const u8,
linksection_string: ?[]const u8,
explicit_callconv: ?std.builtin.CallingConvention,
explicit_callconv: ?CallingConvention,
params: []Param,
return_type: Node,
body: ?Node,
alignment: ?c_uint,
},

pub const CallingConvention = enum {
c,
x86_64_sysv,
x86_64_win,
x86_stdcall,
x86_fastcall,
x86_thiscall,
x86_vectorcall,
aarch64_vfabi,
arm_aapcs,
arm_aapcs_vfp,
m68k_rtd,
};
};

pub const Param = struct {
Expand Down Expand Up @@ -2812,14 +2826,52 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
const callconv_expr = if (payload.explicit_callconv) |some| blk: {
_ = try c.addToken(.keyword_callconv, "callconv");
_ = try c.addToken(.l_paren, "(");
_ = try c.addToken(.period, ".");
const res = try c.addNode(.{
.tag = .enum_literal,
.main_token = try c.addTokenFmt(.identifier, "{s}", .{@tagName(some)}),
.data = undefined,
});
const cc_node = switch (some) {
.c => cc_node: {
_ = try c.addToken(.period, ".");
break :cc_node try c.addNode(.{
.tag = .enum_literal,
.main_token = try c.addToken(.identifier, "c"),
.data = undefined,
});
},
.x86_64_sysv,
.x86_64_win,
.x86_stdcall,
.x86_fastcall,
.x86_thiscall,
.x86_vectorcall,
.aarch64_vfabi,
.arm_aapcs,
.arm_aapcs_vfp,
.m68k_rtd,
=> cc_node: {
// .{ .foo = .{} }
_ = try c.addToken(.period, ".");
const outer_lbrace = try c.addToken(.l_brace, "{");
_ = try c.addToken(.period, ".");
_ = try c.addToken(.identifier, @tagName(some));
_ = try c.addToken(.equal, "=");
_ = try c.addToken(.period, ".");
const inner_lbrace = try c.addToken(.l_brace, "{");
_ = try c.addToken(.r_brace, "}");
_ = try c.addToken(.r_brace, "}");
break :cc_node try c.addNode(.{
.tag = .struct_init_dot_two,
.main_token = outer_lbrace,
.data = .{
.lhs = try c.addNode(.{
.tag = .struct_init_dot_two,
.main_token = inner_lbrace,
.data = .{ .lhs = 0, .rhs = 0 },
}),
.rhs = 0,
},
});
},
};
_ = try c.addToken(.r_paren, ")");
break :blk res;
break :blk cc_node;
} else 0;

const return_type_expr = try renderNode(c, payload.return_type);
Expand Down
39 changes: 0 additions & 39 deletions lib/compiler_rt/int.zig
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ const is_test = builtin.is_test;
const common = @import("common.zig");
const udivmod = @import("udivmod.zig").udivmod;
const __divti3 = @import("divti3.zig").__divti3;
const arm = @import("arm.zig");

pub const panic = common.panic;

Expand Down Expand Up @@ -102,25 +101,6 @@ test "test_divmoddi4" {
}
}

fn test_one_aeabi_ldivmod(a: i64, b: i64, expected_q: i64, expected_r: i64) !void {
const LdivmodRes = extern struct {
q: i64, // r1:r0
r: i64, // r3:r2
};
const actualIdivmod = @as(*const fn (a: i64, b: i64) callconv(.AAPCS) LdivmodRes, @ptrCast(&arm.__aeabi_ldivmod));
const arm_res = actualIdivmod(a, b);
try testing.expectEqual(expected_q, arm_res.q);
try testing.expectEqual(expected_r, arm_res.r);
}

test "arm.__aeabi_ldivmod" {
if (!builtin.cpu.arch.isARM()) return error.SkipZigTest;

for (cases__divmodsi4) |case| {
try test_one_aeabi_ldivmod(case[0], case[1], case[2], case[3]);
}
}

pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.C) u64 {
return udivmod(u64, a, b, maybe_rem);
}
Expand Down Expand Up @@ -261,25 +241,6 @@ test "test_divmodsi4" {
}
}

fn test_one_aeabi_idivmod(a: i32, b: i32, expected_q: i32, expected_r: i32) !void {
const IdivmodRes = extern struct {
q: i32, // r0
r: i32, // r1
};
const actualIdivmod = @as(*const fn (a: i32, b: i32) callconv(.AAPCS) IdivmodRes, @ptrCast(&arm.__aeabi_idivmod));
const arm_res = actualIdivmod(a, b);
try testing.expectEqual(expected_q, arm_res.q);
try testing.expectEqual(expected_r, arm_res.r);
}

test "arm.__aeabi_idivmod" {
if (!builtin.cpu.arch.isARM()) return error.SkipZigTest;

for (cases__divmodsi4) |case| {
try test_one_aeabi_idivmod(case[0], case[1], case[2], case[3]);
}
}

pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.C) u32 {
const d = __udivsi3(a, b);
rem.* = @bitCast(@as(i32, @bitCast(a)) -% (@as(i32, @bitCast(d)) * @as(i32, @bitCast(b))));
Expand Down
229 changes: 229 additions & 0 deletions lib/std/Target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1600,6 +1600,165 @@ pub const Cpu = struct {
else => ".X",
};
}

/// 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 fromCallingConvention(cc: std.builtin.CallingConvention.Tag) []const Arch {
return switch (cc) {
.auto,
.@"async",
.naked,
.@"inline",
=> unreachable,

.x86_64_sysv,
.x86_64_win,
.x86_64_regcall_v3_sysv,
.x86_64_regcall_v4_win,
.x86_64_vectorcall,
.x86_64_interrupt,
=> &.{.x86_64},

.x86_sysv,
.x86_win,
.x86_stdcall,
.x86_fastcall,
.x86_thiscall,
.x86_thiscall_mingw,
.x86_regcall_v3,
.x86_regcall_v4_win,
.x86_vectorcall,
.x86_interrupt,
=> &.{.x86},

.aarch64_aapcs,
.aarch64_aapcs_darwin,
.aarch64_aapcs_win,
.aarch64_vfabi,
.aarch64_vfabi_sve,
=> &.{ .aarch64, .aarch64_be },

.arm_apcs,
.arm_aapcs,
.arm_aapcs_vfp,
.arm_aapcs16_vfp,
.arm_interrupt,
=> &.{ .arm, .armeb, .thumb, .thumbeb },

.mips64_n64,
.mips64_n32,
.mips64_interrupt,
=> &.{ .mips64, .mips64el },

.mips_o32,
.mips_interrupt,
=> &.{ .mips, .mipsel },

.riscv64_lp64,
.riscv64_lp64_v,
.riscv64_interrupt,
=> &.{.riscv64},

.riscv32_ilp32,
.riscv32_ilp32_v,
.riscv32_interrupt,
=> &.{.riscv32},

.sparc64_sysv,
=> &.{.sparc64},

.sparc_sysv,
=> &.{.sparc},

.powerpc64_elf,
.powerpc64_elf_altivec,
.powerpc64_elf_v2,
=> &.{ .powerpc64, .powerpc64le },

.powerpc_sysv,
.powerpc_sysv_altivec,
.powerpc_aix,
.powerpc_aix_altivec,
=> &.{ .powerpc, .powerpcle },

.wasm_watc,
=> &.{ .wasm64, .wasm32 },

.arc_sysv,
=> &.{.arc},

.avr_gnu,
.avr_builtin,
.avr_signal,
.avr_interrupt,
=> &.{.avr},

.bpf_std,
=> &.{ .bpfel, .bpfeb },

.csky_sysv,
.csky_interrupt,
=> &.{.csky},

.hexagon_sysv,
.hexagon_sysv_hvx,
=> &.{.hexagon},

.lanai_sysv,
=> &.{.lanai},

.loongarch64_lp64,
=> &.{.loongarch64},

.loongarch32_ilp32,
=> &.{.loongarch32},

.m68k_sysv,
.m68k_gnu,
.m68k_rtd,
.m68k_interrupt,
=> &.{.m68k},

.msp430_eabi,
=> &.{.msp430},

.propeller1_sysv,
=> &.{.propeller1},

.propeller2_sysv,
=> &.{.propeller2},

.s390x_sysv,
.s390x_sysv_vx,
=> &.{.s390x},

.ve_sysv,
=> &.{.ve},

.xcore_xs1,
.xcore_xs2,
=> &.{.xcore},

.xtensa_call0,
.xtensa_windowed,
=> &.{.xtensa},

.amdgcn_device,
.amdgcn_kernel,
.amdgcn_cs,
=> &.{.amdgcn},

.nvptx_device,
.nvptx_kernel,
=> &.{ .nvptx, .nvptx64 },

.spirv_device,
.spirv_kernel,
.spirv_fragment,
.spirv_vertex,
=> &.{ .spirv, .spirv32, .spirv64 },
};
}
};

pub const Model = struct {
Expand Down Expand Up @@ -2864,6 +3023,76 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 {
);
}

pub fn cCallingConvention(target: Target) ?std.builtin.CallingConvention {
return switch (target.cpu.arch) {
.x86_64 => switch (target.os.tag) {
.windows, .uefi => .{ .x86_64_win = .{} },
else => .{ .x86_64_sysv = .{} },
},
.x86 => switch (target.os.tag) {
.windows, .uefi => .{ .x86_win = .{} },
else => .{ .x86_sysv = .{} },
},
.aarch64, .aarch64_be => if (target.os.tag.isDarwin()) cc: {
break :cc .{ .aarch64_aapcs_darwin = .{} };
} else switch (target.os.tag) {
.windows => .{ .aarch64_aapcs_win = .{} },
else => .{ .aarch64_aapcs = .{} },
},
.arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
.netbsd => .{ .arm_apcs = .{} },
else => switch (target.abi.floatAbi()) {
.soft => .{ .arm_aapcs = .{} },
.hard => .{ .arm_aapcs_vfp = .{} },
},
},
.mips64, .mips64el => switch (target.abi) {
.gnuabin32 => .{ .mips64_n32 = .{} },
else => .{ .mips64_n64 = .{} },
},
.mips, .mipsel => .{ .mips_o32 = .{} },
.riscv64 => .{ .riscv64_lp64 = .{} },
.riscv32 => .{ .riscv32_ilp32 = .{} },
.sparc64 => .{ .sparc64_sysv = .{} },
.sparc => .{ .sparc_sysv = .{} },
.powerpc64 => if (target.isMusl())
alexrp marked this conversation as resolved.
Show resolved Hide resolved
.{ .powerpc64_elf_v2 = .{} }
else
.{ .powerpc64_elf = .{} },
.powerpc64le => .{ .powerpc64_elf_v2 = .{} },
.powerpc, .powerpcle => switch (target.os.tag) {
.aix => .{ .powerpc_aix = .{} },
else => .{ .powerpc_sysv = .{} },
},
.wasm32 => .{ .wasm_watc = .{} },
.wasm64 => .{ .wasm_watc = .{} },
.arc => .{ .arc_sysv = .{} },
.avr => .avr_gnu,
.bpfel, .bpfeb => .{ .bpf_std = .{} },
.csky => .{ .csky_sysv = .{} },
.hexagon => .{ .hexagon_sysv = .{} },
.kalimba => null,
.lanai => .{ .lanai_sysv = .{} },
.loongarch64 => .{ .loongarch64_lp64 = .{} },
.loongarch32 => .{ .loongarch32_ilp32 = .{} },
.m68k => if (target.abi.isGnu() or target.abi.isMusl())
.{ .m68k_gnu = .{} }
else
.{ .m68k_sysv = .{} },
.msp430 => .{ .msp430_eabi = .{} },
.propeller1 => .{ .propeller1_sysv = .{} },
.propeller2 => .{ .propeller2_sysv = .{} },
.s390x => .{ .s390x_sysv = .{} },
.spu_2 => null,
.ve => .{ .ve_sysv = .{} },
.xcore => .{ .xcore_xs1 = .{} },
.xtensa => .{ .xtensa_call0 = .{} },
.amdgcn => .{ .amdgcn_device = .{} },
.nvptx, .nvptx64 => .nvptx_device,
.spirv, .spirv32, .spirv64 => .spirv_device,
};
}

pub fn osArchName(target: std.Target) [:0]const u8 {
return target.os.tag.archName(target.cpu.arch);
}
Expand Down
Loading
Loading