From 4c798bb0bd0043459f5b979ab3dfaee9a6f5ac97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Fri, 26 Sep 2025 16:01:43 +0200 Subject: [PATCH 1/6] std.builtin: define VaList as `struct { __ap: *anyopaque }` for Arm per AAPCS --- lib/std/builtin.zig | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index e942f9877f..ca7d9e251a 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -844,6 +844,12 @@ pub const VaListAarch64 = extern struct { __vr_offs: c_int, }; +/// This data structure is used by the Zig language code generation and +/// therefore must be kept in sync with the compiler implementation. +pub const VaListArm = extern struct { + __ap: *anyopaque, +}; + /// This data structure is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. pub const VaListHexagon = extern struct { @@ -899,10 +905,7 @@ pub const VaList = switch (builtin.cpu.arch) { .stage2_llvm => @compileError("disabled due to miscompilations"), }, }, - .arm, .armeb, .thumb, .thumbeb => switch (builtin.os.tag) { - .ios, .macos, .tvos, .watchos, .visionos => *u8, - else => *anyopaque, - }, + .arm, .armeb, .thumb, .thumbeb => VaListArm, .amdgcn => *u8, .avr => *anyopaque, .bpfel, .bpfeb => *anyopaque, From 44c80fc6dcf91a3fb1bfaeb12b27087b2fcd9283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Fri, 26 Sep 2025 16:08:39 +0200 Subject: [PATCH 2/6] std.builtin: sort VaList prongs a bit --- lib/std/builtin.zig | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index ca7d9e251a..a001c52234 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -897,32 +897,45 @@ pub const VaListXtensa = extern struct { /// This data structure is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. pub const VaList = switch (builtin.cpu.arch) { + .amdgcn, + .powerpc64, + .powerpc64le, + .x86, + => *u8, + .avr, + .bpfel, + .bpfeb, + .loongarch32, + .loongarch64, + .mips, + .mipsel, + .mips64, + .mips64el, + .riscv32, + .riscv32be, + .riscv64, + .riscv64be, + .sparc, + .sparc64, + .spirv32, + .spirv64, + .wasm32, + .wasm64, + => *anyopaque, .aarch64, .aarch64_be => switch (builtin.os.tag) { - .windows => *u8, - .ios, .macos, .tvos, .watchos, .visionos => *u8, + .driverkit, .ios, .macos, .tvos, .visionos, .watchos, .windows => *u8, else => switch (builtin.zig_backend) { else => VaListAarch64, .stage2_llvm => @compileError("disabled due to miscompilations"), }, }, .arm, .armeb, .thumb, .thumbeb => VaListArm, - .amdgcn => *u8, - .avr => *anyopaque, - .bpfel, .bpfeb => *anyopaque, .hexagon => if (builtin.target.abi.isMusl()) VaListHexagon else *u8, - .loongarch32, .loongarch64 => *anyopaque, - .mips, .mipsel, .mips64, .mips64el => *anyopaque, - .riscv32, .riscv32be, .riscv64, .riscv64be => *anyopaque, .powerpc, .powerpcle => switch (builtin.os.tag) { .ios, .macos, .tvos, .watchos, .visionos, .aix => *u8, else => VaListPowerPc, }, - .powerpc64, .powerpc64le => *u8, - .sparc, .sparc64 => *anyopaque, - .spirv32, .spirv64 => *anyopaque, .s390x => VaListS390x, - .wasm32, .wasm64 => *anyopaque, - .x86 => *u8, .x86_64 => switch (builtin.os.tag) { .windows => switch (builtin.zig_backend) { else => *u8, From 033d251626822ccc5aae40ad8a02ad885bdcd2e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Fri, 26 Sep 2025 16:10:15 +0200 Subject: [PATCH 3/6] std.builtin: define VaList for arc, csky, lanai, m68k, msp430, nvptx, ve, xcore --- lib/std/builtin.zig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index a001c52234..edd6c27ee7 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -898,15 +898,22 @@ pub const VaListXtensa = extern struct { /// therefore must be kept in sync with the compiler implementation. pub const VaList = switch (builtin.cpu.arch) { .amdgcn, + .msp430, + .nvptx, + .nvptx64, .powerpc64, .powerpc64le, .x86, => *u8, + .arc, .avr, .bpfel, .bpfeb, + .csky, + .lanai, .loongarch32, .loongarch64, + .m68k, .mips, .mipsel, .mips64, @@ -919,8 +926,10 @@ pub const VaList = switch (builtin.cpu.arch) { .sparc64, .spirv32, .spirv64, + .ve, .wasm32, .wasm64, + .xcore, => *anyopaque, .aarch64, .aarch64_be => switch (builtin.os.tag) { .driverkit, .ios, .macos, .tvos, .visionos, .watchos, .windows => *u8, From 6ca52c00d9fcb7af0d50f6cf29be680f323c66a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Fri, 26 Sep 2025 16:14:43 +0200 Subject: [PATCH 4/6] std.builtin: remove dead powerpc-darwin handling for VaList --- lib/std/builtin.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index edd6c27ee7..a3e1ec11c9 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -941,7 +941,7 @@ pub const VaList = switch (builtin.cpu.arch) { .arm, .armeb, .thumb, .thumbeb => VaListArm, .hexagon => if (builtin.target.abi.isMusl()) VaListHexagon else *u8, .powerpc, .powerpcle => switch (builtin.os.tag) { - .ios, .macos, .tvos, .watchos, .visionos, .aix => *u8, + .aix => *u8, else => VaListPowerPc, }, .s390x => VaListS390x, From d16ff4d049d15b63f1dc7ea84b02734eca5d5bd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Fri, 26 Sep 2025 16:19:41 +0200 Subject: [PATCH 5/6] std.builtin: define VaList as `*u8` for uefi --- lib/std/builtin.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index a3e1ec11c9..2504b8fe2f 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -946,7 +946,7 @@ pub const VaList = switch (builtin.cpu.arch) { }, .s390x => VaListS390x, .x86_64 => switch (builtin.os.tag) { - .windows => switch (builtin.zig_backend) { + .uefi, .windows => switch (builtin.zig_backend) { else => *u8, .stage2_llvm => @compileError("disabled due to miscompilations"), }, From e98630aacf816c5fedb7bb504001584bfa425f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Fri, 26 Sep 2025 02:03:58 +0200 Subject: [PATCH 6/6] aro: TypeStore: synchronize __va_list_tag logic with Zig's std.builtin.VaList https://github.com/Vexu/arocc/pull/893 closes #25361 --- lib/compiler/aro/aro/TypeStore.zig | 169 ++++++++++++++++++++++++++--- 1 file changed, 156 insertions(+), 13 deletions(-) diff --git a/lib/compiler/aro/aro/TypeStore.zig b/lib/compiler/aro/aro/TypeStore.zig index 8d18603fbd..655211f35b 100644 --- a/lib/compiler/aro/aro/TypeStore.zig +++ b/lib/compiler/aro/aro/TypeStore.zig @@ -2046,27 +2046,69 @@ fn generateNsConstantStringType(ts: *TypeStore, comp: *Compilation) !QualType { } fn generateVaListType(ts: *TypeStore, comp: *Compilation) !QualType { - const Kind = enum { aarch64_va_list, x86_64_va_list }; + const Kind = enum { + aarch64_va_list, + arm_va_list, + hexagon_va_list, + powerpc_va_list, + s390x_va_list, + x86_64_va_list, + xtensa_va_list, + }; const kind: Kind = switch (comp.target.cpu.arch) { + .amdgcn, + .msp430, + .nvptx, + .nvptx64, + .powerpc64, + .powerpc64le, + .x86, + => return .char_pointer, + .arc, + .avr, + .bpfel, + .bpfeb, + .csky, + .lanai, + .loongarch32, + .loongarch64, + .m68k, + .mips, + .mipsel, + .mips64, + .mips64el, + .riscv32, + .riscv32be, + .riscv64, + .riscv64be, + .sparc, + .sparc64, + .spirv32, + .spirv64, + .ve, + .wasm32, + .wasm64, + .xcore, + => return .void_pointer, .aarch64, .aarch64_be => switch (comp.target.os.tag) { - .windows => return .char_pointer, - .ios, .macos, .tvos, .watchos => return .char_pointer, + .driverkit, .ios, .macos, .tvos, .visionos, .watchos, .windows => return .char_pointer, else => .aarch64_va_list, }, - .arm, .armeb, .thumb, .thumbeb => switch (comp.target.os.tag) { - .ios, .macos, .tvos, .watchos, .visionos => return .char_pointer, - else => return .void_pointer, + .arm, .armeb, .thumb, .thumbeb => .arm_va_list, + .hexagon => if (comp.target.abi.isMusl()) + .hexagon_va_list + else + return .char_pointer, + .powerpc, .powerpcle => switch (comp.target.os.tag) { + .aix => return .char_pointer, + else => .powerpc_va_list, }, - .sparc, .wasm32, .wasm64, .bpfel, .bpfeb, .riscv32, .riscv64, .avr, .spirv32, .spirv64 => return .void_pointer, - .powerpc => switch (comp.target.os.tag) { - .ios, .macos, .tvos, .watchos, .aix => return .char_pointer, - else => return .void, // unknown - }, - .x86, .msp430 => return .char_pointer, + .s390x => .s390x_va_list, .x86_64 => switch (comp.target.os.tag) { - .windows => return .char_pointer, + .uefi, .windows => return .char_pointer, else => .x86_64_va_list, }, + .xtensa => .xtensa_va_list, else => return .void, // unknown }; @@ -2093,6 +2135,87 @@ fn generateVaListType(ts: *TypeStore, comp: *Compilation) !QualType { break :blk qt; }, + .arm_va_list => blk: { + var record: Type.Record = .{ + .name = try comp.internString("__va_list_tag"), + .decl_node = undefined, // TODO + .layout = null, + .fields = &.{}, + }; + const qt = try ts.put(comp.gpa, .{ .@"struct" = record }); + + var fields: [1]Type.Record.Field = .{ + .{ .name = try comp.internString("__ap"), .qt = .void_pointer }, + }; + record.fields = &fields; + record.layout = record_layout.compute(&fields, qt, comp, null) catch unreachable; + try ts.set(comp.gpa, .{ .@"struct" = record }, @intFromEnum(qt._index)); + + break :blk qt; + }, + .hexagon_va_list => blk: { + var record: Type.Record = .{ + .name = try comp.internString("__va_list_tag"), + .decl_node = undefined, // TODO + .layout = null, + .fields = &.{}, + }; + const qt = try ts.put(comp.gpa, .{ .@"struct" = record }); + + var fields: [4]Type.Record.Field = .{ + .{ .name = try comp.internString("__gpr"), .qt = .long }, + .{ .name = try comp.internString("__fpr"), .qt = .long }, + .{ .name = try comp.internString("__overflow_arg_area"), .qt = .void_pointer }, + .{ .name = try comp.internString("__reg_save_area"), .qt = .void_pointer }, + }; + record.fields = &fields; + record.layout = record_layout.compute(&fields, qt, comp, null) catch unreachable; + try ts.set(comp.gpa, .{ .@"struct" = record }, @intFromEnum(qt._index)); + + break :blk qt; + }, + .powerpc_va_list => blk: { + var record: Type.Record = .{ + .name = try comp.internString("__va_list_tag"), + .decl_node = undefined, // TODO + .layout = null, + .fields = &.{}, + }; + const qt = try ts.put(comp.gpa, .{ .@"struct" = record }); + + var fields: [5]Type.Record.Field = .{ + .{ .name = try comp.internString("gpr"), .qt = .uchar }, + .{ .name = try comp.internString("fpr"), .qt = .uchar }, + .{ .name = try comp.internString("reserved"), .qt = .ushort }, + .{ .name = try comp.internString("overflow_arg_area"), .qt = .void_pointer }, + .{ .name = try comp.internString("reg_save_area"), .qt = .void_pointer }, + }; + record.fields = &fields; + record.layout = record_layout.compute(&fields, qt, comp, null) catch unreachable; + try ts.set(comp.gpa, .{ .@"struct" = record }, @intFromEnum(qt._index)); + + break :blk qt; + }, + .s390x_va_list => blk: { + var record: Type.Record = .{ + .name = try comp.internString("__va_list_tag"), + .decl_node = undefined, // TODO + .layout = null, + .fields = &.{}, + }; + const qt = try ts.put(comp.gpa, .{ .@"struct" = record }); + + var fields: [3]Type.Record.Field = .{ + .{ .name = try comp.internString("__current_saved_reg_area_pointer"), .qt = .void_pointer }, + .{ .name = try comp.internString("__saved_reg_area_end_pointer"), .qt = .void_pointer }, + .{ .name = try comp.internString("__overflow_area_pointer"), .qt = .void_pointer }, + }; + record.fields = &fields; + record.layout = record_layout.compute(&fields, qt, comp, null) catch unreachable; + try ts.set(comp.gpa, .{ .@"struct" = record }, @intFromEnum(qt._index)); + + break :blk qt; + }, .x86_64_va_list => blk: { var record: Type.Record = .{ .name = try comp.internString("__va_list_tag"), @@ -2112,6 +2235,26 @@ fn generateVaListType(ts: *TypeStore, comp: *Compilation) !QualType { record.layout = record_layout.compute(&fields, qt, comp, null) catch unreachable; try ts.set(comp.gpa, .{ .@"struct" = record }, @intFromEnum(qt._index)); + break :blk qt; + }, + .xtensa_va_list => blk: { + var record: Type.Record = .{ + .name = try comp.internString("__va_list_tag"), + .decl_node = undefined, // TODO + .layout = null, + .fields = &.{}, + }; + const qt = try ts.put(comp.gpa, .{ .@"struct" = record }); + + var fields: [3]Type.Record.Field = .{ + .{ .name = try comp.internString("__va_stk"), .qt = .int_pointer }, + .{ .name = try comp.internString("__va_reg"), .qt = .int_pointer }, + .{ .name = try comp.internString("__va_ndx"), .qt = .int }, + }; + record.fields = &fields; + record.layout = record_layout.compute(&fields, qt, comp, null) catch unreachable; + try ts.set(comp.gpa, .{ .@"struct" = record }, @intFromEnum(qt._index)); + break :blk qt; }, };