Merge pull request #17727 from ziglang/elf-memory-deferred

x86_64+elf: do not pass hardcoded memory addresses in prep for build-obj
This commit is contained in:
Jakub Konka 2023-10-28 19:41:07 +02:00 committed by GitHub
commit 13c7aa5fef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 853 additions and 629 deletions

View File

@ -144,8 +144,6 @@ test "tan32" {
}
test "tan64" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
const epsilon = 0.000001;
try expect(math.approxEqAbs(f64, tan(0.0), 0.0, epsilon));

View File

@ -374,8 +374,6 @@ const atomic_rmw_orderings = [_]Ordering{
};
test "Atomic.swap" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
inline for (atomic_rmw_orderings) |ordering| {
var x = Atomic(usize).init(5);
try testing.expectEqual(x.swap(10, ordering), 5);

View File

@ -2513,8 +2513,6 @@ pub fn dumpStackPointerAddr(prefix: []const u8) void {
}
test "manage resources correctly" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.os.tag == .wasi) return error.SkipZigTest;
if (builtin.os.tag == .windows) {

View File

@ -2,7 +2,6 @@ pub const parseFloat = @import("parse_float/parse_float.zig").parseFloat;
pub const ParseFloatError = @import("parse_float/parse_float.zig").ParseFloatError;
const std = @import("std");
const builtin = @import("builtin");
const math = std.math;
const testing = std.testing;
const expect = testing.expect;
@ -14,8 +13,6 @@ const epsilon = 1e-7;
// See https://github.com/tiehuis/parse-number-fxx-test-data for a wider-selection of test-data.
test "fmt.parseFloat" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
inline for ([_]type{ f16, f32, f64, f128 }) |T| {
try testing.expectError(error.InvalidCharacter, parseFloat(T, ""));
try testing.expectError(error.InvalidCharacter, parseFloat(T, " 1"));
@ -72,8 +69,6 @@ test "fmt.parseFloat" {
}
test "fmt.parseFloat nan and inf" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
inline for ([_]type{ f16, f32, f64, f128 }) |T| {
const Z = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
@ -88,7 +83,7 @@ test "fmt.parseFloat #11169" {
}
test "fmt.parseFloat hex.special" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
try testing.expect(math.isNan(try parseFloat(f32, "nAn")));
try testing.expect(math.isPositiveInf(try parseFloat(f32, "iNf")));
@ -96,8 +91,6 @@ test "fmt.parseFloat hex.special" {
try testing.expect(math.isNegativeInf(try parseFloat(f32, "-iNf")));
}
test "fmt.parseFloat hex.zero" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
try testing.expectEqual(@as(f32, 0.0), try parseFloat(f32, "0x0"));
try testing.expectEqual(@as(f32, 0.0), try parseFloat(f32, "-0x0"));
try testing.expectEqual(@as(f32, 0.0), try parseFloat(f32, "0x0p42"));
@ -106,8 +99,6 @@ test "fmt.parseFloat hex.zero" {
}
test "fmt.parseFloat hex.f16" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
try testing.expectEqual(try parseFloat(f16, "0x1p0"), 1.0);
try testing.expectEqual(try parseFloat(f16, "-0x1p-1"), -0.5);
try testing.expectEqual(try parseFloat(f16, "0x10p+10"), 16384.0);
@ -124,8 +115,6 @@ test "fmt.parseFloat hex.f16" {
}
test "fmt.parseFloat hex.f32" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
try testing.expectError(error.InvalidCharacter, parseFloat(f32, "0x"));
try testing.expectEqual(try parseFloat(f32, "0x1p0"), 1.0);
try testing.expectEqual(try parseFloat(f32, "-0x1p-1"), -0.5);

View File

@ -785,8 +785,6 @@ test "max_value_len" {
}
test "parse into vector" {
if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
const T = struct {
vec_i32: @Vector(4, i32),
vec_f32: @Vector(2, f32),

View File

@ -4012,7 +4012,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
.got => .load_memory_ptr_got,
.direct => .load_memory_ptr_direct,
.import => unreachable,
.extern_got => unreachable,
};
const atom_index = switch (self.bin_file.tag) {
.macho => blk: {
@ -5532,7 +5531,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
.got => .load_memory_ptr_got,
.direct => .load_memory_ptr_direct,
.import => unreachable,
.extern_got => unreachable,
};
const atom_index = switch (self.bin_file.tag) {
.macho => blk: {
@ -5654,7 +5652,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
.got => .load_memory_got,
.direct => .load_memory_direct,
.import => .load_memory_import,
.extern_got => unreachable,
};
const atom_index = switch (self.bin_file.tag) {
.macho => blk: {
@ -5852,7 +5849,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
.got => .load_memory_ptr_got,
.direct => .load_memory_ptr_direct,
.import => unreachable,
.extern_got => unreachable,
};
const atom_index = switch (self.bin_file.tag) {
.macho => blk: {
@ -6180,7 +6176,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
.memory => |addr| .{ .memory = addr },
.load_got => |sym_index| .{ .linker_load = .{ .type = .got, .sym_index = sym_index } },
.load_direct => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } },
.load_extern_got, .load_tlv => unreachable, // TODO
.load_symbol, .load_tlv => unreachable, // TODO
},
.fail => |msg| {
self.err_msg = msg;

View File

@ -6135,7 +6135,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
.mcv => |mcv| switch (mcv) {
.none => .none,
.undef => .undef,
.load_got, .load_extern_got, .load_direct, .load_tlv => unreachable, // TODO
.load_got, .load_symbol, .load_direct, .load_tlv => unreachable, // TODO
.immediate => |imm| .{ .immediate = @as(u32, @truncate(imm)) },
.memory => |addr| .{ .memory = addr },
},

View File

@ -2591,7 +2591,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
.mcv => |mcv| switch (mcv) {
.none => .none,
.undef => .undef,
.load_got, .load_extern_got, .load_direct, .load_tlv => unreachable, // TODO
.load_got, .load_symbol, .load_direct, .load_tlv => unreachable, // TODO
.immediate => |imm| .{ .immediate = imm },
.memory => |addr| .{ .memory = addr },
},

View File

@ -4137,7 +4137,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
.mcv => |mcv| switch (mcv) {
.none => .none,
.undef => .undef,
.load_got, .load_extern_got, .load_direct, .load_tlv => unreachable, // TODO
.load_got, .load_symbol, .load_direct, .load_tlv => unreachable, // TODO
.immediate => |imm| .{ .immediate = imm },
.memory => |addr| .{ .memory = addr },
},

File diff suppressed because it is too large Load Diff

View File

@ -78,31 +78,41 @@ pub fn emitMir(emit: *Emit) Error!void {
} else return emit.fail("TODO implement extern reloc for {s}", .{
@tagName(emit.bin_file.tag),
}),
.linker_reloc => |data| if (emit.bin_file.cast(link.File.Elf)) |elf_file| {
const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;
const sym = elf_file.symbol(elf_file.zigModulePtr().symbol(data.sym_index));
if (emit.bin_file.options.pic) {
const r_type: u32 = if (sym.flags.has_zig_got)
link.File.Elf.R_X86_64_ZIG_GOTPCREL
else if (sym.flags.needs_got)
std.elf.R_X86_64_GOTPCREL
else
std.elf.R_X86_64_PC32;
try atom.addReloc(elf_file, .{
.r_offset = end_offset - 4,
.r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
.r_addend = -4,
});
} else {
const r_type: u32 = if (sym.flags.has_zig_got)
link.File.Elf.R_X86_64_ZIG_GOT32
else if (sym.flags.needs_got)
std.elf.R_X86_64_GOT32
else
std.elf.R_X86_64_32;
try atom.addReloc(elf_file, .{
.r_offset = end_offset - 4,
.r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
.r_addend = 0,
});
}
} else unreachable,
.linker_got,
.linker_extern_got,
.linker_direct,
.linker_direct_got,
.linker_import,
.linker_tlv,
=> |symbol| if (emit.bin_file.cast(link.File.Elf)) |elf_file| {
const r_type: u32 = switch (lowered_relocs[0].target) {
.linker_direct_got => link.File.Elf.R_X86_64_ZIG_GOT32,
.linker_got => link.File.Elf.R_X86_64_ZIG_GOTPCREL,
.linker_extern_got => std.elf.R_X86_64_GOTPCREL,
.linker_direct => std.elf.R_X86_64_PC32,
else => unreachable,
};
const r_addend: i64 = switch (lowered_relocs[0].target) {
.linker_direct_got => 0,
.linker_got, .linker_extern_got, .linker_direct => -4,
else => unreachable,
};
const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;
try atom_ptr.addReloc(elf_file, .{
.r_offset = end_offset - 4,
.r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type,
.r_addend = r_addend,
});
=> |symbol| if (emit.bin_file.cast(link.File.Elf)) |_| {
unreachable;
} else if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?;
try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{

View File

@ -1,5 +1,6 @@
//! This file contains the functionality for lowering x86_64 MIR to Instructions
bin_file: *link.File,
allocator: Allocator,
mir: Mir,
cc: std.builtin.CallingConvention,
@ -49,11 +50,10 @@ pub const Reloc = struct {
const Target = union(enum) {
inst: Mir.Inst.Index,
linker_reloc: Mir.Reloc,
linker_extern_fn: Mir.Reloc,
linker_got: Mir.Reloc,
linker_extern_got: Mir.Reloc,
linker_direct: Mir.Reloc,
linker_direct_got: Mir.Reloc,
linker_import: Mir.Reloc,
linker_tlv: Mir.Reloc,
};
@ -408,12 +408,57 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
.m_sib, .m_rip, .rax_moffs, .moffs_rax => inst.data.x.fixes,
.extern_fn_reloc,
.got_reloc,
.extern_got_reloc,
.direct_reloc,
.direct_got_reloc,
.import_reloc,
.tlv_reloc,
=> ._,
.linker_reloc => {
if (lower.bin_file.options.pic) {
assert(inst.data.rx.fixes == ._);
const reg = inst.data.rx.r1;
const extra = lower.mir.extraData(Mir.Reloc, inst.data.rx.payload).data;
_ = lower.reloc(.{ .linker_reloc = extra });
const mnemonic: Mnemonic = switch (inst.tag) {
.mov => .mov,
.lea => .lea,
else => unreachable,
};
try lower.emit(.none, mnemonic, &.{
.{ .reg = reg },
.{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
});
} else {
switch (inst.tag) {
.call => {
_ = lower.reloc(.{ .linker_reloc = inst.data.reloc });
try lower.emit(.none, .call, &.{
.{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = 0 }) },
});
},
.lea => {
assert(inst.data.rx.fixes == ._);
const reg = inst.data.rx.r1;
const extra = lower.mir.extraData(Mir.Reloc, inst.data.rx.payload).data;
try lower.emit(.none, .mov, &.{
.{ .reg = reg },
.{ .imm = lower.reloc(.{ .linker_reloc = extra }) },
});
},
.mov => {
assert(inst.data.rx.fixes == ._);
const reg = inst.data.rx.r1;
const extra = lower.mir.extraData(Mir.Reloc, inst.data.rx.payload).data;
_ = lower.reloc(.{ .linker_reloc = extra });
try lower.emit(.none, .mov, &.{
.{ .reg = reg },
.{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = 0 }) },
});
},
else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
}
}
return;
},
else => return lower.fail("TODO lower .{s}", .{@tagName(inst.ops)}),
};
try lower.emit(switch (fixes) {
@ -545,32 +590,12 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
.extern_fn_reloc => &.{
.{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc }) },
},
.direct_got_reloc => ops: {
switch (inst.tag) {
.call => {
_ = lower.reloc(.{ .linker_direct_got = inst.data.reloc });
break :ops &.{
.{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = 0 }) },
};
},
.mov => {
const reg = inst.data.rx.r1;
const extra = lower.mir.extraData(Mir.Reloc, inst.data.rx.payload).data;
_ = lower.reloc(.{ .linker_direct_got = extra });
break :ops &.{
.{ .reg = reg },
.{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = 0 }) },
};
},
else => unreachable,
}
},
.got_reloc, .extern_got_reloc, .direct_reloc, .import_reloc, .tlv_reloc => ops: {
.linker_reloc => unreachable,
.got_reloc, .direct_reloc, .import_reloc, .tlv_reloc => ops: {
const reg = inst.data.rx.r1;
const extra = lower.mir.extraData(Mir.Reloc, inst.data.rx.payload).data;
_ = lower.reloc(switch (inst.ops) {
.got_reloc => .{ .linker_got = extra },
.extern_got_reloc => .{ .linker_extern_got = extra },
.direct_reloc => .{ .linker_direct = extra },
.import_reloc => .{ .linker_import = extra },
.tlv_reloc => .{ .linker_tlv = extra },
@ -601,6 +626,7 @@ const abi = @import("abi.zig");
const assert = std.debug.assert;
const bits = @import("bits.zig");
const encoder = @import("encoder.zig");
const link = @import("../../link.zig");
const std = @import("std");
const Air = @import("../../Air.zig");

View File

@ -854,9 +854,6 @@ pub const Inst = struct {
/// Linker relocation - GOT indirection.
/// Uses `rx` payload with extra data of type `Reloc`.
got_reloc,
/// Linker relocation - reference to an extern variable via GOT.
/// Uses `rx` payload with extra data of type `Reloc`.
extern_got_reloc,
/// Linker relocation - direct reference.
/// Uses `rx` payload with extra data of type `Reloc`.
direct_reloc,
@ -866,9 +863,9 @@ pub const Inst = struct {
/// Linker relocation - threadlocal variable via GOT indirection.
/// Uses `rx` payload with extra data of type `Reloc`.
tlv_reloc,
/// Linker relocation - non-PIC direct reference to GOT cell.
/// Uses `reloc` payload if tag is `call`, `rx` otherwise.
direct_got_reloc,
/// Linker relocation.
/// Uses `rx` payload with extra data of type `Reloc`.
linker_reloc,
// Pseudo instructions:

View File

@ -791,13 +791,11 @@ fn lowerDeclRef(
/// Helper struct to denote that the value is in memory but requires a linker relocation fixup:
/// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
/// * extern_got - pointer to extern variable referenced via GOT
/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
/// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
pub const LinkerLoad = struct {
type: enum {
got,
extern_got,
direct,
import,
},
@ -827,8 +825,9 @@ pub const GenResult = union(enum) {
load_got: u32,
/// Direct by-address reference to memory location.
memory: u64,
/// Pointer to extern variable via GOT.
load_extern_got: u32,
/// Reference to memory location but deferred until linker allocated the Decl in memory.
/// Traditionally, this corresponds to emitting a relocation in a relocatable object file.
load_symbol: u32,
};
fn mcv(val: MCValue) GenResult {
@ -903,16 +902,14 @@ fn genDeclRef(
mod.intern_pool.stringToSliceUnwrap(ov.lib_name)
else
null;
return GenResult.mcv(.{ .load_extern_got = try elf_file.getGlobalSymbol(name, lib_name) });
const sym_index = try elf_file.getGlobalSymbol(name, lib_name);
elf_file.symbol(elf_file.zigModulePtr().symbol(sym_index)).flags.needs_got = true;
return GenResult.mcv(.{ .load_symbol = sym_index });
}
const sym_index = try elf_file.getOrCreateMetadataForDecl(decl_index);
const sym = elf_file.symbol(sym_index);
_ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
if (bin_file.options.pic) {
return GenResult.mcv(.{ .load_got = sym.esym_index });
} else {
return GenResult.mcv(.{ .memory = sym.zigGotAddress(elf_file) });
}
return GenResult.mcv(.{ .load_symbol = sym.esym_index });
} else if (bin_file.cast(link.File.MachO)) |macho_file| {
const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
@ -948,11 +945,7 @@ fn genUnnamedConst(
};
if (bin_file.cast(link.File.Elf)) |elf_file| {
const local = elf_file.symbol(local_sym_index);
if (bin_file.options.pic) {
return GenResult.mcv(.{ .load_direct = local.esym_index });
} else {
return GenResult.mcv(.{ .memory = local.value });
}
return GenResult.mcv(.{ .load_symbol = local.esym_index });
} else if (bin_file.cast(link.File.MachO)) |_| {
return GenResult.mcv(.{ .load_direct = local_sym_index });
} else if (bin_file.cast(link.File.Coff)) |_| {

View File

@ -3333,7 +3333,8 @@ pub fn updateDecl(
const variable = decl.getOwnedVariable(mod).?;
const name = mod.intern_pool.stringToSlice(decl.name);
const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name);
_ = try self.getGlobalSymbol(name, lib_name);
const esym_index = try self.getGlobalSymbol(name, lib_name);
self.symbol(self.zigModulePtr().symbol(esym_index)).flags.needs_got = true;
return;
}
@ -5955,6 +5956,12 @@ pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32
return lookup_gop.value_ptr.*;
}
pub fn zigModulePtr(self: *Elf) *ZigModule {
assert(self.zig_module_index != null);
const file_ptr = self.file(self.zig_module_index.?).?;
return file_ptr.zig_module;
}
const GetOrCreateComdatGroupOwnerResult = struct {
found_existing: bool,
index: ComdatGroupOwner.Index,

View File

@ -370,6 +370,7 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype
try self.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file);
},
elf.R_X86_64_GOT32,
elf.R_X86_64_GOTPC32,
elf.R_X86_64_GOTPC64,
elf.R_X86_64_GOTPCREL,
@ -879,6 +880,8 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void {
}
},
elf.R_X86_64_GOT32 => try cwriter.writeIntLittle(i32, @as(i32, @intCast(G + GOT + A))),
// Zig custom relocations
Elf.R_X86_64_ZIG_GOT32 => try cwriter.writeIntLittle(u32, @as(u32, @intCast(ZIG_GOT + A))),
Elf.R_X86_64_ZIG_GOTPCREL => try cwriter.writeIntLittle(i32, @as(i32, @intCast(ZIG_GOT + A - P))),

View File

@ -73,10 +73,6 @@ static void assert_or_panic(bool ok) {
#define ZIG_NO_RAW_F16
#endif
#ifdef ZIG_BACKEND_STAGE2_X86_64
#define ZIG_NO_COMPLEX
#endif
#ifdef __i386__
#define ZIG_NO_RAW_F16
#endif
@ -278,7 +274,7 @@ void run_c_tests(void) {
zig_u32(0xfffffffd);
zig_u64(0xfffffffffffffffc);
#if !defined ZIG_NO_I128 && !defined ZIG_BACKEND_STAGE2_X86_64
#ifndef ZIG_NO_I128
{
struct u128 s = {0xfffffffffffffffc};
zig_struct_u128(s);
@ -292,7 +288,7 @@ void run_c_tests(void) {
zig_i32(-3);
zig_i64(-4);
#if !defined ZIG_NO_I128 && !defined ZIG_BACKEND_STAGE2_X86_64
#ifndef ZIG_NO_I128
{
struct i128 s = {-6};
zig_struct_i128(s);
@ -433,7 +429,7 @@ void run_c_tests(void) {
}
#endif
#if !defined __mips__ && !defined ZIG_PPC32 && !defined ZIG_BACKEND_STAGE2_X86_64
#if !defined __mips__ && !defined ZIG_PPC32
{
struct FloatRect r1 = {1, 21, 16, 4};
struct FloatRect r2 = {178, 189, 21, 15};

View File

@ -49,8 +49,6 @@ export fn zig_five_integers(a: i32, b: i32, c: i32, d: i32, e: i32) void {
}
test "C ABI integers" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
c_u8(0xff);
c_u16(0xfffe);
c_u32(0xfffffffd);
@ -187,10 +185,8 @@ const complex_abi_compatible = builtin.cpu.arch != .x86 and !builtin.cpu.arch.is
!builtin.cpu.arch.isARM() and !builtin.cpu.arch.isPPC() and !builtin.cpu.arch.isRISCV();
test "C ABI complex float" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (!complex_abi_compatible) return error.SkipZigTest;
if (builtin.cpu.arch == .x86_64) return error.SkipZigTest; // See https://github.com/ziglang/zig/issues/8465
if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest; // See https://github.com/ziglang/zig/issues/8465
const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };
const b = ComplexFloat{ .real = 11.3, .imag = -1.5 };
@ -201,8 +197,6 @@ test "C ABI complex float" {
}
test "C ABI complex float by component" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (!complex_abi_compatible) return error.SkipZigTest;
const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };
@ -214,8 +208,6 @@ test "C ABI complex float by component" {
}
test "C ABI complex double" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (!complex_abi_compatible) return error.SkipZigTest;
const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };
@ -227,8 +219,6 @@ test "C ABI complex double" {
}
test "C ABI complex double by component" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (!complex_abi_compatible) return error.SkipZigTest;
const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };
@ -240,8 +230,6 @@ test "C ABI complex double by component" {
}
export fn zig_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat {
if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
expect(a.real == 1.25) catch @panic("test failure: zig_cmultf 1");
expect(a.imag == 2.6) catch @panic("test failure: zig_cmultf 2");
expect(b.real == 11.3) catch @panic("test failure: zig_cmultf 3");
@ -251,8 +239,6 @@ export fn zig_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat {
}
export fn zig_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble {
if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
expect(a.real == 1.25) catch @panic("test failure: zig_cmultd 1");
expect(a.imag == 2.6) catch @panic("test failure: zig_cmultd 2");
expect(b.real == 11.3) catch @panic("test failure: zig_cmultd 3");
@ -262,8 +248,6 @@ export fn zig_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble {
}
export fn zig_cmultf_comp(a_r: f32, a_i: f32, b_r: f32, b_i: f32) ComplexFloat {
if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
expect(a_r == 1.25) catch @panic("test failure: zig_cmultf_comp 1");
expect(a_i == 2.6) catch @panic("test failure: zig_cmultf_comp 2");
expect(b_r == 11.3) catch @panic("test failure: zig_cmultf_comp 3");
@ -273,8 +257,6 @@ export fn zig_cmultf_comp(a_r: f32, a_i: f32, b_r: f32, b_i: f32) ComplexFloat {
}
export fn zig_cmultd_comp(a_r: f64, a_i: f64, b_r: f64, b_i: f64) ComplexDouble {
if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
expect(a_r == 1.25) catch @panic("test failure: zig_cmultd_comp 1");
expect(a_i == 2.6) catch @panic("test failure: zig_cmultd_comp 2");
expect(b_r == 11.3) catch @panic("test failure: zig_cmultd_comp 3");
@ -352,8 +334,6 @@ extern fn c_med_struct_mixed(MedStructMixed) void;
extern fn c_ret_med_struct_mixed() MedStructMixed;
test "C ABI medium struct of ints and floats" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.cpu.arch == .x86) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
@ -422,8 +402,6 @@ extern fn c_med_struct_ints(MedStructInts) void;
extern fn c_ret_med_struct_ints() MedStructInts;
test "C ABI medium struct of ints" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.cpu.arch == .x86) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
@ -531,8 +509,6 @@ extern fn c_split_struct_mixed(SplitStructMixed) void;
extern fn c_ret_split_struct_mixed() SplitStructMixed;
test "C ABI split struct of ints and floats" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.cpu.arch == .x86) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
@ -614,8 +590,6 @@ const Vector5 = extern struct {
extern fn c_big_struct_floats(Vector5) void;
test "C ABI structs of floats as parameter" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;
@ -683,8 +657,6 @@ const FloatRect = extern struct {
};
export fn zig_multiple_struct_floats(x: FloatRect, y: FloatRect) void {
if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
expect(x.left == 1) catch @panic("test failure");
expect(x.right == 21) catch @panic("test failure");
expect(x.top == 16) catch @panic("test failure");
@ -696,8 +668,6 @@ export fn zig_multiple_struct_floats(x: FloatRect, y: FloatRect) void {
}
test "C ABI structs of floats as multiple parameters" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
@ -754,8 +724,6 @@ export fn zig_ret_small_struct_ints() SmallStructInts {
}
export fn zig_ret_med_struct_ints() MedStructInts {
if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
return .{
.x = 1,
.y = 2,
@ -764,8 +732,6 @@ export fn zig_ret_med_struct_ints() MedStructInts {
}
export fn zig_ret_med_struct_mixed() MedStructMixed {
if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
return .{
.a = 1234,
.b = 100.0,
@ -774,8 +740,6 @@ export fn zig_ret_med_struct_mixed() MedStructMixed {
}
export fn zig_ret_split_struct_mixed() SplitStructMixed {
if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
return .{
.a = 1234,
.b = 100,
@ -816,8 +780,6 @@ extern fn c_struct_with_array(StructWithArray) void;
extern fn c_ret_struct_with_array() StructWithArray;
test "Struct with array as padding." {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.cpu.arch == .x86) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
@ -889,7 +851,8 @@ extern fn c_medium_vec(MediumVec) void;
extern fn c_ret_medium_vec() MediumVec;
test "medium simd vector" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64 and
!comptime std.Target.x86.featureSetHas(builtin.cpu.features, .avx)) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;
@ -912,7 +875,7 @@ test "big simd vector" {
if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;
if (builtin.cpu.arch == .x86_64 and builtin.os.tag == .macos and builtin.mode != .Debug) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .macos and builtin.mode != .Debug) return error.SkipZigTest;
c_big_vec(.{ 1, 2, 3, 4, 5, 6, 7, 8 });
@ -933,8 +896,6 @@ extern fn c_ptr_size_float_struct(Vector2) void;
extern fn c_ret_ptr_size_float_struct() Vector2;
test "C ABI pointer sized float struct" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.cpu.arch == .x86) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
@ -958,8 +919,6 @@ pub inline fn expectOk(c_err: c_int) !void {
/// Tests for Double + Char struct
const DC = extern struct { v1: f64, v2: u8 };
test "DC: Zig passes to C" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
@ -967,8 +926,6 @@ test "DC: Zig passes to C" {
try expectOk(c_assert_DC(.{ .v1 = -0.25, .v2 = 15 }));
}
test "DC: Zig returns to C" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
@ -977,8 +934,6 @@ test "DC: Zig returns to C" {
try expectOk(c_assert_ret_DC());
}
test "DC: C passes to Zig" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
@ -986,8 +941,6 @@ test "DC: C passes to Zig" {
try expectOk(c_send_DC());
}
test "DC: C returns to Zig" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
@ -1001,8 +954,6 @@ pub extern fn c_assert_ret_DC() c_int;
pub extern fn c_send_DC() c_int;
pub extern fn c_ret_DC() DC;
pub export fn zig_assert_DC(lv: DC) c_int {
if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
var err: c_int = 0;
if (lv.v1 != -0.25) err = 1;
if (lv.v2 != 15) err = 2;
@ -1010,8 +961,6 @@ pub export fn zig_assert_DC(lv: DC) c_int {
return err;
}
pub export fn zig_ret_DC() DC {
if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
return .{ .v1 = -0.25, .v2 = 15 };
}
@ -1019,8 +968,6 @@ pub export fn zig_ret_DC() DC {
const CFF = extern struct { v1: u8, v2: f32, v3: f32 };
test "CFF: Zig passes to C" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
@ -1028,8 +975,6 @@ test "CFF: Zig passes to C" {
try expectOk(c_assert_CFF(.{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }));
}
test "CFF: Zig returns to C" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
@ -1037,8 +982,6 @@ test "CFF: Zig returns to C" {
try expectOk(c_assert_ret_CFF());
}
test "CFF: C passes to Zig" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;
if (builtin.cpu.arch == .aarch64 and builtin.mode != .Debug) return error.SkipZigTest;
@ -1049,8 +992,6 @@ test "CFF: C passes to Zig" {
try expectOk(c_send_CFF());
}
test "CFF: C returns to Zig" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
if (builtin.cpu.arch == .aarch64 and builtin.mode != .Debug) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;
@ -1064,8 +1005,6 @@ pub extern fn c_assert_ret_CFF() c_int;
pub extern fn c_send_CFF() c_int;
pub extern fn c_ret_CFF() CFF;
pub export fn zig_assert_CFF(lv: CFF) c_int {
if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
var err: c_int = 0;
if (lv.v1 != 39) err = 1;
if (lv.v2 != 0.875) err = 2;
@ -1074,8 +1013,6 @@ pub export fn zig_assert_CFF(lv: CFF) c_int {
return err;
}
pub export fn zig_ret_CFF() CFF {
if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
return .{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 };
}
@ -1083,8 +1020,6 @@ pub export fn zig_ret_CFF() CFF {
const PD = extern struct { v1: ?*anyopaque, v2: f64 };
test "PD: Zig passes to C" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
@ -1092,8 +1027,6 @@ test "PD: Zig passes to C" {
try expectOk(c_assert_PD(.{ .v1 = null, .v2 = 0.5 }));
}
test "PD: Zig returns to C" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
@ -1101,8 +1034,6 @@ test "PD: Zig returns to C" {
try expectOk(c_assert_ret_PD());
}
test "PD: C passes to Zig" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
@ -1110,8 +1041,6 @@ test "PD: C passes to Zig" {
try expectOk(c_send_PD());
}
test "PD: C returns to Zig" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
@ -1123,8 +1052,6 @@ pub extern fn c_assert_ret_PD() c_int;
pub extern fn c_send_PD() c_int;
pub extern fn c_ret_PD() PD;
pub export fn zig_c_assert_PD(lv: PD) c_int {
if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
var err: c_int = 0;
if (lv.v1 != null) err = 1;
if (lv.v2 != 0.5) err = 2;
@ -1132,13 +1059,9 @@ pub export fn zig_c_assert_PD(lv: PD) c_int {
return err;
}
pub export fn zig_ret_PD() PD {
if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
return .{ .v1 = null, .v2 = 0.5 };
}
pub export fn zig_assert_PD(lv: PD) c_int {
if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
var err: c_int = 0;
if (lv.v1 != null) err = 1;
if (lv.v2 != 0.5) err = 2;
@ -1228,11 +1151,9 @@ const f80_struct = extern struct {
};
extern fn c_f80_struct(f80_struct) f80_struct;
test "f80 struct" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (!has_f80) return error.SkipZigTest;
if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
if (builtin.mode != .Debug) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_llvm and builtin.mode != .Debug) return error.SkipZigTest;
const a = c_f80_struct(.{ .a = 12.34 });
try expect(@as(f64, @floatCast(a.a)) == 56.78);
@ -1317,8 +1238,6 @@ test "Stdcall ABI big union" {
extern fn c_explict_win64(ByRef) callconv(.Win64) ByRef;
test "explicit SysV calling convention" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.cpu.arch != .x86_64) return error.SkipZigTest;
const res = c_explict_win64(.{ .val = 1, .arr = undefined });