zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit fb9ba5e4b315e76c3ff1d01ebd56c651e13c314d (tree)
parent 5cc281e7232b9f1bc5f4d732e4a37fb5df02f780
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Sat, 25 Apr 2026 05:19:18 +0200

Merge pull request 'llvm: fix `multiple_llvm_types` handling and aarch64 return types' (#32028) from aarch64-c-abi into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/32028
Reviewed-by: Andrew Kelley <andrew@ziglang.org>

Diffstat:
Mbuild.zig | 20++++++++++----------
Msrc/InternPool.zig | 6++++++
Msrc/codegen/llvm.zig | 25+++++++++++++++----------
Msrc/codegen/llvm/FuncGen.zig | 101+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mtest/c_abi/cfuncs.c | 16++++------------
Mtest/c_abi/main.zig | 6------
Mtest/tests.zig | 44++++++++++++++++++++------------------------
7 files changed, 107 insertions(+), 111 deletions(-)

diff --git a/build.zig b/build.zig @@ -416,7 +416,7 @@ pub fn build(b: *std.Build) !void { chosen_opt_modes_buf[chosen_mode_index] = builtin.OptimizeMode.ReleaseSmall; chosen_mode_index += 1; } - const optimization_modes = chosen_opt_modes_buf[0..chosen_mode_index]; + const optimize_modes = chosen_opt_modes_buf[0..chosen_mode_index]; const test_only: ?tests.ModuleTestOptions.TestOnly = if (no_matrix) .default @@ -476,7 +476,7 @@ pub fn build(b: *std.Build) !void { .root_src = "test/behavior.zig", .name = "behavior", .desc = "Run the behavior tests", - .optimize_modes = optimization_modes, + .optimize_modes = optimize_modes, .include_paths = &.{}, .sanitize_thread = sanitize_thread, .skip_single_threaded = skip_single_threaded, @@ -502,7 +502,7 @@ pub fn build(b: *std.Build) !void { .root_src = "lib/compiler_rt.zig", .name = "compiler-rt", .desc = "Run the compiler_rt tests", - .optimize_modes = optimization_modes, + .optimize_modes = optimize_modes, .include_paths = &.{}, .sanitize_thread = sanitize_thread, .skip_single_threaded = true, @@ -529,7 +529,7 @@ pub fn build(b: *std.Build) !void { .root_src = "lib/std/std.zig", .name = "std", .desc = "Run the standard library tests", - .optimize_modes = optimization_modes, + .optimize_modes = optimize_modes, .include_paths = &.{}, .sanitize_thread = sanitize_thread, .skip_single_threaded = skip_single_threaded, @@ -555,7 +555,7 @@ pub fn build(b: *std.Build) !void { .root_src = "test/c.zig", .name = "libc", .desc = "Run the libc API tests", - .optimize_modes = optimization_modes, + .optimize_modes = optimize_modes, .include_paths = &.{}, .sanitize_thread = sanitize_thread, .skip_single_threaded = true, @@ -599,13 +599,14 @@ pub fn build(b: *std.Build) !void { test_step.dependOn(tests.addStandaloneTests( b, - optimization_modes, + optimize_modes, enable_macos_sdk, enable_ios_sdk, enable_symlinks_windows, )); test_step.dependOn(tests.addCAbiTests(b, .{ .test_target_filters = test_target_filters, + .optimize_modes = optimize_modes, .skip_non_native = skip_non_native, .skip_wasm = skip_wasm, .skip_freebsd = skip_freebsd, @@ -615,19 +616,18 @@ pub fn build(b: *std.Build) !void { .skip_darwin = skip_darwin, .skip_linux = skip_linux, .skip_llvm = skip_llvm, - .skip_release = skip_release, .max_rss = 3_300_000_000, })); test_step.dependOn(tests.addLinkTests(b, enable_macos_sdk, enable_ios_sdk, enable_symlinks_windows)); test_step.dependOn(tests.addStackTraceTests(b, test_filters, skip_non_native)); - test_step.dependOn(tests.addErrorTraceTests(b, test_filters, optimization_modes, skip_non_native)); + test_step.dependOn(tests.addErrorTraceTests(b, test_filters, optimize_modes, skip_non_native)); test_step.dependOn(tests.addCliTests(b)); if (tests.addDebuggerTests(b, .{ .test_filters = test_filters, .test_target_filters = test_target_filters, .gdb = b.option([]const u8, "gdb", "path to gdb binary"), .lldb = b.option([]const u8, "lldb", "path to lldb binary"), - .optimize_modes = optimization_modes, + .optimize_modes = optimize_modes, .skip_single_threaded = skip_single_threaded, .skip_libc = skip_libc, })) |test_debugger_step| test_step.dependOn(test_debugger_step); @@ -663,7 +663,7 @@ pub fn build(b: *std.Build) !void { if (!skip_test_incremental) test_step.dependOn(test_incremental_step); if (tests.addLibcTestNszTests(b, .{ - .optimize_modes = optimization_modes, + .optimize_modes = optimize_modes, .test_filters = test_filters, .test_target_filters = test_target_filters, .skip_wasm = skip_wasm, diff --git a/src/InternPool.zig b/src/InternPool.zig @@ -5888,6 +5888,12 @@ pub const Alignment = enum(u6) { return @enumFromInt(@min(@intFromEnum(lhs), @intFromEnum(rhs))); } + /// Given a base address known to be aligned to `a`, + /// computes the known alignment of base address plus `off`. + pub fn offset(a: Alignment, off: u64) Alignment { + return .fromLog2Units(@min(a.toLog2Units(), @ctz(off))); + } + /// Align an address forwards to this alignment. pub fn forward(a: Alignment, addr: u64) u64 { assert(a != .none); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig @@ -1358,24 +1358,22 @@ pub const Object = struct { }, .multiple_llvm_types => { assert(!it.byval_attr); - const field_types = it.types_buffer[0..it.types_len]; const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); const param_llvm_ty = try o.lowerType(param_ty); - const param_alignment = param_ty.abiAlignment(zcu).toLlvm(); - const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, param_alignment, target); - const llvm_ty = try o.builder.structType(.normal, field_types); - const llvm_args_start = it.llvm_index - field_types.len; - for (0..field_types.len, llvm_args_start..) |field_i, llvm_arg_index| { + const param_alignment = param_ty.abiAlignment(zcu); + const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8); + const arg_ptr = try buildAllocaInner(&wip, llvm_ty, param_alignment.toLlvm(), target); + const llvm_args_start = it.llvm_index - it.types_len; + for (llvm_args_start.., it.offsets_buffer[0..it.types_len]) |llvm_arg_index, offset| { const param = wip.arg(@intCast(llvm_arg_index)); - const field_ptr = try wip.gepStruct(llvm_ty, arg_ptr, field_i, ""); - const alignment = Type.ptrAbiAlignment(target).toLlvm(); - _ = try wip.store(.normal, param, field_ptr, alignment); + const part_ptr = try o.ptraddConst(&wip, arg_ptr, offset); + _ = try wip.store(.normal, param, part_ptr, param_alignment.offset(offset).toLlvm()); } if (isByRef(param_ty, zcu)) { args.appendAssumeCapacity(arg_ptr); } else { - args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, arg_ptr, param_alignment, "")); + args.appendAssumeCapacity(try wip.load(.normal, param_llvm_ty, arg_ptr, param_alignment.toLlvm(), "")); } }, .float_array => { @@ -4362,6 +4360,13 @@ pub const Object = struct { toLlvmAddressSpace(.generic, o.zcu.getTarget()), ); } + + pub fn ptraddConst(o: *Object, wip: *Builder.WipFunction, ptr: Builder.Value, offset: u64) Allocator.Error!Builder.Value { + if (offset == 0) return ptr; + const llvm_usize_ty = try o.lowerType(.usize); + const offset_val = try o.builder.intValue(llvm_usize_ty, offset); + return wip.gep(.inbounds, .i8, ptr, &.{offset_val}, ""); + } }; const CallingConventionInfo = struct { diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig @@ -709,22 +709,25 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif .multiple_llvm_types => { const arg = args[it.zig_index - 1]; const param_ty = self.typeOf(arg); - const llvm_types = it.types_buffer[0..it.types_len]; const llvm_arg = try self.resolveInst(arg); const is_by_ref = isByRef(param_ty, zcu); - const arg_ptr = if (is_by_ref) llvm_arg else ptr: { - const alignment = param_ty.abiAlignment(zcu).toLlvm(); - const ptr = try self.buildAlloca(llvm_arg.typeOfWip(&self.wip), alignment); - _ = try self.wip.store(.normal, llvm_arg, ptr, alignment); - break :ptr ptr; - }; + const param_alignment = param_ty.abiAlignment(zcu); + const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8); + const arg_ptr = try self.buildAlloca(llvm_ty, param_alignment.toLlvm()); + if (is_by_ref) _ = try self.wip.callMemCpy( + arg_ptr, + param_alignment.toLlvm(), + llvm_arg, + param_alignment.toLlvm(), + try o.builder.intValue(try o.lowerType(.usize), param_ty.abiSize(zcu)), + .normal, + self.disable_intrinsics, + ) else _ = try self.wip.store(.normal, llvm_arg, arg_ptr, param_alignment.toLlvm()); - const llvm_ty = try o.builder.structType(.normal, llvm_types); try llvm_args.ensureUnusedCapacity(it.types_len); - for (llvm_types, 0..) |field_ty, i| { - const alignment: Builder.Alignment = .fromByteUnits(@divExact(target.ptrBitWidth(), 8)); - const field_ptr = try self.wip.gepStruct(llvm_ty, arg_ptr, i, ""); - const loaded = try self.wip.load(.normal, field_ty, field_ptr, alignment, ""); + for (it.types_buffer[0..it.types_len], it.offsets_buffer[0..it.types_len]) |field_ty, offset| { + const field_ptr = try self.ptraddConst(arg_ptr, offset); + const loaded = try self.wip.load(.normal, field_ty, field_ptr, param_alignment.offset(offset).toLlvm(), ""); llvm_args.appendAssumeCapacity(loaded); } }, @@ -2269,10 +2272,7 @@ fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build const struct_ptr_align = struct_ty.abiAlignment(zcu); const field_ptr = try self.ptraddConst(struct_llvm_val, offset); - const field_ptr_align: InternPool.Alignment = switch (offset) { - 0 => struct_ptr_align, - else => struct_ptr_align.minStrict(.fromLog2Units(@ctz(offset))), - }; + const field_ptr_align = struct_ptr_align.offset(offset); if (isByRef(field_ty, zcu)) { return self.loadByRef(field_ptr, field_ty, field_ptr_align.toLlvm(), .normal); @@ -3120,11 +3120,7 @@ fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) Allocator.Er const field_ty = struct_ty.fieldType(field_index, zcu); const field_offset = struct_ty.structFieldOffset(field_index, zcu); - const field_align = switch (field_offset) { - 0 => struct_ty.abiAlignment(zcu), - else => struct_ty.abiAlignment(zcu).minStrict(.fromLog2Units(@ctz(field_offset))), - }; - + const field_align = struct_ty.abiAlignment(zcu).offset(field_offset); const field_ptr = try self.ptraddConst(self.err_ret_trace, field_offset); return self.load(field_ptr, field_ty, field_align.toLlvm(), .normal); } @@ -5279,10 +5275,7 @@ fn airSetUnionTag(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder. return .none; } const tag_field_ptr = try self.ptraddConst(union_ptr, layout.tagOffset()); - const tag_ptr_align: InternPool.Alignment = switch (layout.tagOffset()) { - 0 => union_ptr_align, - else => |off| .minStrict(union_ptr_align, .fromLog2Units(@ctz(off))), - }; + const tag_ptr_align = union_ptr_align.offset(layout.tagOffset()); _ = try self.wip.store(access_kind, new_tag, tag_field_ptr, tag_ptr_align.toLlvm()); return .none; } @@ -5922,10 +5915,7 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde if (!field_ty.hasRuntimeBits(zcu)) continue; const offset = result_ty.structFieldOffset(field_index, zcu); const field_ptr = try self.ptraddConst(alloca_inst, offset); - const field_ptr_align: InternPool.Alignment = switch (offset) { - 0 => struct_align, - else => struct_align.minStrict(.fromLog2Units(@ctz(offset))), - }; + const field_ptr_align = struct_align.offset(offset); const llvm_field_val = try self.resolveInst(elem); @@ -6581,6 +6571,7 @@ const ParamTypeIterator = struct { llvm_index: u32, types_len: u32, types_buffer: [8]Builder.Type, + offsets_buffer: [9]u64, byval_attr: bool, const Lowering = union(enum) { @@ -6672,7 +6663,12 @@ const ParamTypeIterator = struct { .memory => return .byref_mut, .float_array => |len| return Lowering{ .float_array = len }, .byval => return .byval, - .integer => return .abi_sized_int, + .integer => { + it.types_len = 1; + it.types_buffer[0..1].* = .{.i64}; + it.offsets_buffer[0..2].* = .{ 0, 8 }; + return .multiple_llvm_types; + }, .double_integer => return Lowering{ .i64_array = 2 }, } }, @@ -6711,12 +6707,17 @@ const ParamTypeIterator = struct { .double_integer => return Lowering{ .i64_array = 2 }, .fields => { it.types_len = 0; + var offset: u64 = 0; for (0..ty.structFieldCount(zcu)) |field_index| { const field_ty = ty.fieldType(field_index, zcu); if (!field_ty.hasRuntimeBits(zcu)) continue; + offset = field_ty.abiAlignment(zcu).forward(offset); it.types_buffer[it.types_len] = try it.object.lowerType(field_ty); + it.offsets_buffer[it.types_len] = offset; it.types_len += 1; + offset += field_ty.abiSize(zcu); } + it.offsets_buffer[it.types_len] = offset; it.llvm_index += it.types_len - 1; return .multiple_llvm_types; }, @@ -6729,9 +6730,8 @@ const ParamTypeIterator = struct { it.llvm_index += 1; return .byval; } else { - var types_buffer: [8]Builder.Type = undefined; - types_buffer[0] = try it.object.lowerType(scalar_ty); - it.types_buffer = types_buffer; + it.types_buffer[0..1].* = .{try it.object.lowerType(scalar_ty)}; + it.offsets_buffer[0..2].* = .{ 0, scalar_ty.abiSize(zcu) }; it.types_len = 1; it.llvm_index += 1; it.zig_index += 1; @@ -6804,31 +6804,36 @@ const ParamTypeIterator = struct { return .byval; } var types_index: u32 = 0; - var types_buffer: [8]Builder.Type = undefined; + var offset: u64 = 0; for (classes) |class| { switch (class) { .integer => { - types_buffer[types_index] = .i64; + it.types_buffer[types_index] = .i64; + it.offsets_buffer[types_index] = offset; types_index += 1; }, .sse => { - types_buffer[types_index] = .double; + it.types_buffer[types_index] = .double; + it.offsets_buffer[types_index] = offset; types_index += 1; }, .sseup => { - if (types_buffer[types_index - 1] == .double) { - types_buffer[types_index - 1] = .fp128; + if (it.types_buffer[types_index - 1] == .double) { + it.types_buffer[types_index - 1] = .fp128; } else { - types_buffer[types_index] = .double; + it.types_buffer[types_index] = .double; + it.offsets_buffer[types_index] = offset; types_index += 1; } }, .float => { - types_buffer[types_index] = .float; + it.types_buffer[types_index] = .float; + it.offsets_buffer[types_index] = offset; types_index += 1; }, .float_combine => { - types_buffer[types_index] = try it.object.builder.vectorType(.normal, 2, .float); + it.types_buffer[types_index] = try it.object.builder.vectorType(.normal, 2, .float); + it.offsets_buffer[types_index] = offset; types_index += 1; }, .x87 => { @@ -6845,6 +6850,7 @@ const ParamTypeIterator = struct { @panic("TODO"); }, } + offset += 8; } const first_non_integer = std.mem.indexOfNone(x86_64_abi.Class, &classes, &.{.integer}); if (first_non_integer == null or classes[first_non_integer.?] == .none) { @@ -6865,15 +6871,15 @@ const ParamTypeIterator = struct { const size = ty.abiSize(zcu); assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index); if (size % 8 > 0) { - types_buffer[types_index - 1] = + it.types_buffer[types_index - 1] = try it.object.builder.intType(@intCast(size % 8 * 8)); } }, else => {}, } } + it.offsets_buffer[types_index] = offset; it.types_len = types_index; - it.types_buffer = types_buffer; it.llvm_index += types_index; it.zig_index += 1; return .multiple_llvm_types; @@ -6887,6 +6893,7 @@ pub fn iterateParamTypes(object: *Object, fn_info: InternPool.Key.FuncType) Para .llvm_index = 0, .types_len = 0, .types_buffer = undefined, + .offsets_buffer = undefined, .byval_attr = false, }; } @@ -6965,7 +6972,7 @@ pub fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Erro .memory => return .void, .float_array => return o.lowerType(return_type), .byval => return o.lowerType(return_type), - .integer => return o.builder.intType(@intCast(return_type.bitSize(zcu))), + .integer => return .i64, .double_integer => return o.builder.arrayType(2, .i64), }, .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) { @@ -7285,11 +7292,7 @@ fn getAtomicAbiType(fg: *const FuncGen, ty: Type, is_rmw_xchg: bool) Allocator.E } fn ptraddConst(fg: *FuncGen, ptr: Builder.Value, offset: u64) Allocator.Error!Builder.Value { - if (offset == 0) return ptr; - const o = fg.object; - const llvm_usize_ty = try o.lowerType(.usize); - const offset_val = try o.builder.intValue(llvm_usize_ty, offset); - return fg.wip.gep(.inbounds, .i8, ptr, &.{offset_val}, ""); + return fg.object.ptraddConst(&fg.wip, ptr, offset); } fn ptraddScaled(fg: *FuncGen, ptr: Builder.Value, index: Builder.Value, scale: u64) Allocator.Error!Builder.Value { if (scale == 0) return ptr; diff --git a/test/c_abi/cfuncs.c b/test/c_abi/cfuncs.c @@ -2802,7 +2802,6 @@ void run_c_tests(void) { } #endif -#if !defined(__AARCH_BIG_ENDIAN) #if !defined(__mips64) #if !defined(ZIG_PPC32) #if !defined(__s390x__) @@ -2814,9 +2813,7 @@ void run_c_tests(void) { #endif #endif #endif -#endif -#if !defined(__AARCH_BIG_ENDIAN) #if !defined(__mips64) #if !defined(ZIG_PPC32) #if !defined(__s390x__) @@ -2828,9 +2825,7 @@ void run_c_tests(void) { #endif #endif #endif -#endif -#if !defined(__AARCH_BIG_ENDIAN) #if !defined(__mips64) #if !defined(ZIG_PPC32) #if !defined(__s390x__) @@ -2842,7 +2837,6 @@ void run_c_tests(void) { #endif #endif #endif -#endif #if !defined(ZIG_PPC32) #if !defined(ZIG_RISCV32) @@ -2872,7 +2866,6 @@ void run_c_tests(void) { zig_struct_u64_u64_8(0, 1, 2, 3, 4, 5, 6, 7, (struct Struct_u64_u64){ .a = 19, .b = 20 }, 9); } -#if !defined(ZIG_RISCV64) #if !defined(__mips64__) { struct Struct_f32 s = zig_ret_struct_f32(); @@ -2908,7 +2901,6 @@ void run_c_tests(void) { } #endif #endif -#endif #if !defined(__powerpc__) && !defined(__loongarch__) && !defined(__mips64__) { @@ -2933,8 +2925,8 @@ void run_c_tests(void) { #endif #endif -#if !defined __i386__ && !defined __arm__ && !defined(__AARCH_BIG_ENDIAN) && \ - !defined __powerpc__ && !defined ZIG_RISCV64 && !defined(__loongarch__) && \ +#if !defined __i386__ && !defined __arm__ && \ + !defined __powerpc__ && !defined(__loongarch__) && \ !defined(__mips64__) && !defined(__hexagon__) && !defined(__s390x__) { struct SmallStructInts s = {1, 2, 3, 4}; @@ -2942,8 +2934,8 @@ void run_c_tests(void) { } #endif -#if !defined __arm__ && !defined(__AARCH_BIG_ENDIAN) && \ - !defined __powerpc__ && !defined ZIG_RISCV64 && !defined(__loongarch__) && \ +#if !defined __arm__ && \ + !defined __powerpc__ && !defined(__loongarch__) && \ !defined(__mips64__) && !defined(__hexagon__) && !defined(__s390x__) { struct MedStructInts s = {1, 2, 3}; diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig @@ -287,7 +287,6 @@ extern fn c_ret_struct_u8() Struct_u8; extern fn c_struct_u8(Struct_u8, usize) void; test "C ABI struct u8" { - if (builtin.cpu.arch == .aarch64_be) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch == .s390x) return error.SkipZigTest; @@ -315,7 +314,6 @@ extern fn c_ret_struct_u16() Struct_u16; extern fn c_struct_u16(Struct_u16, usize) void; test "C ABI struct u16" { - if (builtin.cpu.arch == .aarch64_be) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch == .s390x) return error.SkipZigTest; @@ -343,7 +341,6 @@ extern fn c_ret_struct_u32() Struct_u32; extern fn c_struct_u32(Struct_u32, usize) void; test "C ABI struct u32" { - if (builtin.cpu.arch == .aarch64_be) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch == .s390x) return error.SkipZigTest; @@ -770,7 +767,6 @@ test "C ABI small struct of ints" { if (builtin.cpu.arch == .x86) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .aarch64_be) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .s390x) return error.SkipZigTest; @@ -5613,7 +5609,6 @@ extern fn c_ret_ptr_size_float_struct() Vector2; test "C ABI pointer sized float struct" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; - if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest; if (builtin.cpu.arch == .s390x) return error.SkipZigTest; @@ -5978,7 +5973,6 @@ extern fn stdcall_coord2(Coord2, Coord2, Coord2) callconv(stdcall_callconv) Coor test "Stdcall ABI structs" { if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; - if (builtin.cpu.arch == .aarch64_be) return error.SkipZigTest; if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .s390x) return error.SkipZigTest; diff --git a/test/tests.zig b/test/tests.zig @@ -2749,6 +2749,7 @@ pub fn wouldUseLlvm(use_llvm: ?bool, query: std.Target.Query, optimize_mode: Opt const CAbiTestOptions = struct { test_target_filters: []const []const u8, + optimize_modes: []const OptimizeMode, skip_non_native: bool, skip_wasm: bool, skip_freebsd: bool, @@ -2758,43 +2759,38 @@ const CAbiTestOptions = struct { skip_darwin: bool, skip_linux: bool, skip_llvm: bool, - skip_release: bool, max_rss: usize = 0, }; pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step { const step = b.step("test-c-abi", "Run the C ABI tests"); - const optimize_modes: [3]OptimizeMode = .{ .Debug, .ReleaseSafe, .ReleaseFast }; + for (c_abi_targets) |c_abi_target| { + if (options.skip_non_native and !c_abi_target.target.isNative()) continue; - for (optimize_modes) |optimize_mode| { - if (optimize_mode != .Debug and options.skip_release) continue; + if (options.skip_wasm and c_abi_target.target.cpu_arch != null and c_abi_target.target.cpu_arch.?.isWasm()) continue; - for (c_abi_targets) |c_abi_target| { - if (options.skip_non_native and !c_abi_target.target.isNative()) continue; + if (options.skip_freebsd and c_abi_target.target.os_tag == .freebsd) continue; + if (options.skip_netbsd and c_abi_target.target.os_tag == .netbsd) continue; + if (options.skip_openbsd and c_abi_target.target.os_tag == .openbsd) continue; + if (options.skip_windows and c_abi_target.target.os_tag == .windows) continue; + if (options.skip_darwin and c_abi_target.target.os_tag != null and c_abi_target.target.os_tag.?.isDarwin()) continue; + if (options.skip_linux and c_abi_target.target.os_tag == .linux) continue; - if (options.skip_wasm and c_abi_target.target.cpu_arch != null and c_abi_target.target.cpu_arch.?.isWasm()) continue; + const resolved_target = b.resolveTargetQuery(c_abi_target.target); + const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM"); + const target = &resolved_target.result; - if (options.skip_freebsd and c_abi_target.target.os_tag == .freebsd) continue; - if (options.skip_netbsd and c_abi_target.target.os_tag == .netbsd) continue; - if (options.skip_openbsd and c_abi_target.target.os_tag == .openbsd) continue; - if (options.skip_windows and c_abi_target.target.os_tag == .windows) continue; - if (options.skip_darwin and c_abi_target.target.os_tag != null and c_abi_target.target.os_tag.?.isDarwin()) continue; - if (options.skip_linux and c_abi_target.target.os_tag == .linux) continue; + if (options.test_target_filters.len > 0) { + for (options.test_target_filters) |filter| { + if (std.mem.indexOf(u8, triple_txt, filter) != null) break; + } else continue; + } - const would_use_llvm = wouldUseLlvm(c_abi_target.use_llvm, c_abi_target.target, .Debug); + for (options.optimize_modes) |optimize_mode| { + const would_use_llvm = wouldUseLlvm(c_abi_target.use_llvm, c_abi_target.target, optimize_mode); if (options.skip_llvm and would_use_llvm) continue; - const resolved_target = b.resolveTargetQuery(c_abi_target.target); - const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM"); - const target = &resolved_target.result; - - if (options.test_target_filters.len > 0) { - for (options.test_target_filters) |filter| { - if (std.mem.indexOf(u8, triple_txt, filter) != null) break; - } else continue; - } - const test_mod = b.createModule(.{ .root_source_file = b.path("test/c_abi/main.zig"), .target = resolved_target,