mirror of
https://github.com/ziglang/zig.git
synced 2025-12-18 04:03:14 +00:00
Merge pull request #25430 from jacobly0/x86_64-win
Coff2: create a new linker from scratch
This commit is contained in:
commit
12ed0ff1ef
@ -561,7 +561,6 @@ set(ZIG_STAGE2_SOURCES
|
|||||||
src/libs/libunwind.zig
|
src/libs/libunwind.zig
|
||||||
src/link.zig
|
src/link.zig
|
||||||
src/link/C.zig
|
src/link/C.zig
|
||||||
src/link/Coff.zig
|
|
||||||
src/link/Dwarf.zig
|
src/link/Dwarf.zig
|
||||||
src/link/Elf.zig
|
src/link/Elf.zig
|
||||||
src/link/Elf/Archive.zig
|
src/link/Elf/Archive.zig
|
||||||
|
|||||||
@ -168,7 +168,7 @@ pub fn parseNameOrOrdinal(allocator: Allocator, reader: *std.Io.Reader) !NameOrO
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const CoffOptions = struct {
|
pub const CoffOptions = struct {
|
||||||
target: std.coff.MachineType = .X64,
|
target: std.coff.IMAGE.FILE.MACHINE = .AMD64,
|
||||||
/// If true, zeroes will be written to all timestamp fields
|
/// If true, zeroes will be written to all timestamp fields
|
||||||
reproducible: bool = true,
|
reproducible: bool = true,
|
||||||
/// If true, the MEM_WRITE flag will not be set in the .rsrc section header
|
/// If true, the MEM_WRITE flag will not be set in the .rsrc section header
|
||||||
@ -210,19 +210,19 @@ pub fn writeCoff(allocator: Allocator, writer: *std.Io.Writer, resources: []cons
|
|||||||
const lengths = resource_tree.dataLengths();
|
const lengths = resource_tree.dataLengths();
|
||||||
const byte_size_of_relocation = 10;
|
const byte_size_of_relocation = 10;
|
||||||
const relocations_len: u32 = @intCast(byte_size_of_relocation * resources.len);
|
const relocations_len: u32 = @intCast(byte_size_of_relocation * resources.len);
|
||||||
const pointer_to_rsrc01_data = @sizeOf(std.coff.CoffHeader) + (@sizeOf(std.coff.SectionHeader) * 2);
|
const pointer_to_rsrc01_data = @sizeOf(std.coff.Header) + (@sizeOf(std.coff.SectionHeader) * 2);
|
||||||
const pointer_to_relocations = pointer_to_rsrc01_data + lengths.rsrc01;
|
const pointer_to_relocations = pointer_to_rsrc01_data + lengths.rsrc01;
|
||||||
const pointer_to_rsrc02_data = pointer_to_relocations + relocations_len;
|
const pointer_to_rsrc02_data = pointer_to_relocations + relocations_len;
|
||||||
const pointer_to_symbol_table = pointer_to_rsrc02_data + lengths.rsrc02;
|
const pointer_to_symbol_table = pointer_to_rsrc02_data + lengths.rsrc02;
|
||||||
|
|
||||||
const timestamp: i64 = if (options.reproducible) 0 else std.time.timestamp();
|
const timestamp: i64 = if (options.reproducible) 0 else std.time.timestamp();
|
||||||
const size_of_optional_header = 0;
|
const size_of_optional_header = 0;
|
||||||
const machine_type: std.coff.MachineType = options.target;
|
const machine_type: std.coff.IMAGE.FILE.MACHINE = options.target;
|
||||||
const flags = std.coff.CoffHeaderFlags{
|
const flags = std.coff.Header.Flags{
|
||||||
.@"32BIT_MACHINE" = 1,
|
.@"32BIT_MACHINE" = true,
|
||||||
};
|
};
|
||||||
const number_of_symbols = 5 + @as(u32, @intCast(resources.len)) + @intFromBool(options.define_external_symbol != null);
|
const number_of_symbols = 5 + @as(u32, @intCast(resources.len)) + @intFromBool(options.define_external_symbol != null);
|
||||||
const coff_header = std.coff.CoffHeader{
|
const coff_header = std.coff.Header{
|
||||||
.machine = machine_type,
|
.machine = machine_type,
|
||||||
.number_of_sections = 2,
|
.number_of_sections = 2,
|
||||||
.time_date_stamp = @as(u32, @truncate(@as(u64, @bitCast(timestamp)))),
|
.time_date_stamp = @as(u32, @truncate(@as(u64, @bitCast(timestamp)))),
|
||||||
@ -245,9 +245,9 @@ pub fn writeCoff(allocator: Allocator, writer: *std.Io.Writer, resources: []cons
|
|||||||
.number_of_relocations = @intCast(resources.len),
|
.number_of_relocations = @intCast(resources.len),
|
||||||
.number_of_linenumbers = 0,
|
.number_of_linenumbers = 0,
|
||||||
.flags = .{
|
.flags = .{
|
||||||
.CNT_INITIALIZED_DATA = 1,
|
.CNT_INITIALIZED_DATA = true,
|
||||||
.MEM_WRITE = @intFromBool(!options.read_only),
|
.MEM_WRITE = !options.read_only,
|
||||||
.MEM_READ = 1,
|
.MEM_READ = true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
try writer.writeStruct(rsrc01_header, .little);
|
try writer.writeStruct(rsrc01_header, .little);
|
||||||
@ -263,9 +263,9 @@ pub fn writeCoff(allocator: Allocator, writer: *std.Io.Writer, resources: []cons
|
|||||||
.number_of_relocations = 0,
|
.number_of_relocations = 0,
|
||||||
.number_of_linenumbers = 0,
|
.number_of_linenumbers = 0,
|
||||||
.flags = .{
|
.flags = .{
|
||||||
.CNT_INITIALIZED_DATA = 1,
|
.CNT_INITIALIZED_DATA = true,
|
||||||
.MEM_WRITE = @intFromBool(!options.read_only),
|
.MEM_WRITE = !options.read_only,
|
||||||
.MEM_READ = 1,
|
.MEM_READ = true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
try writer.writeStruct(rsrc02_header, .little);
|
try writer.writeStruct(rsrc02_header, .little);
|
||||||
@ -1005,9 +1005,9 @@ pub const supported_targets = struct {
|
|||||||
x86_64,
|
x86_64,
|
||||||
aarch64,
|
aarch64,
|
||||||
|
|
||||||
pub fn toCoffMachineType(arch: Arch) std.coff.MachineType {
|
pub fn toCoffMachineType(arch: Arch) std.coff.IMAGE.FILE.MACHINE {
|
||||||
return switch (arch) {
|
return switch (arch) {
|
||||||
.x64, .amd64, .x86_64 => .X64,
|
.x64, .amd64, .x86_64 => .AMD64,
|
||||||
.x86, .i386 => .I386,
|
.x86, .i386 => .I386,
|
||||||
.arm, .armnt => .ARMNT,
|
.arm, .armnt => .ARMNT,
|
||||||
.arm64, .aarch64 => .ARM64,
|
.arm64, .aarch64 => .ARM64,
|
||||||
@ -1079,26 +1079,26 @@ pub const supported_targets = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#type-indicators
|
// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#type-indicators
|
||||||
pub fn rvaRelocationTypeIndicator(target: std.coff.MachineType) ?u16 {
|
pub fn rvaRelocationTypeIndicator(target: std.coff.IMAGE.FILE.MACHINE) ?u16 {
|
||||||
return switch (target) {
|
return switch (target) {
|
||||||
.X64 => 0x3, // IMAGE_REL_AMD64_ADDR32NB
|
.AMD64 => @intFromEnum(std.coff.IMAGE.REL.AMD64.ADDR32NB),
|
||||||
.I386 => 0x7, // IMAGE_REL_I386_DIR32NB
|
.I386 => @intFromEnum(std.coff.IMAGE.REL.I386.DIR32NB),
|
||||||
.ARMNT => 0x2, // IMAGE_REL_ARM_ADDR32NB
|
.ARMNT => @intFromEnum(std.coff.IMAGE.REL.ARM.ADDR32NB),
|
||||||
.ARM64, .ARM64EC, .ARM64X => 0x2, // IMAGE_REL_ARM64_ADDR32NB
|
.ARM64, .ARM64EC, .ARM64X => @intFromEnum(std.coff.IMAGE.REL.ARM64.ADDR32NB),
|
||||||
.IA64 => 0x10, // IMAGE_REL_IA64_DIR32NB
|
.IA64 => @intFromEnum(std.coff.IMAGE.REL.IA64.DIR32NB),
|
||||||
.EBC => 0x1, // This is what cvtres.exe writes for this target, unsure where it comes from
|
.EBC => 0x1, // This is what cvtres.exe writes for this target, unsure where it comes from
|
||||||
else => null,
|
else => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isSupported(target: std.coff.MachineType) bool {
|
pub fn isSupported(target: std.coff.IMAGE.FILE.MACHINE) bool {
|
||||||
return rvaRelocationTypeIndicator(target) != null;
|
return rvaRelocationTypeIndicator(target) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
comptime {
|
comptime {
|
||||||
// Enforce two things:
|
// Enforce two things:
|
||||||
// 1. Arch enum field names are all lowercase (necessary for how fromStringIgnoreCase is implemented)
|
// 1. Arch enum field names are all lowercase (necessary for how fromStringIgnoreCase is implemented)
|
||||||
// 2. All enum fields in Arch have an associated RVA relocation type when converted to a coff.MachineType
|
// 2. All enum fields in Arch have an associated RVA relocation type when converted to a coff.IMAGE.FILE.MACHINE
|
||||||
for (@typeInfo(Arch).@"enum".fields) |enum_field| {
|
for (@typeInfo(Arch).@"enum".fields) |enum_field| {
|
||||||
const all_lower = all_lower: for (enum_field.name) |c| {
|
const all_lower = all_lower: for (enum_field.name) |c| {
|
||||||
if (std.ascii.isUpper(c)) break :all_lower false;
|
if (std.ascii.isUpper(c)) break :all_lower false;
|
||||||
|
|||||||
@ -527,7 +527,7 @@ const LazyIncludePaths = struct {
|
|||||||
arena: std.mem.Allocator,
|
arena: std.mem.Allocator,
|
||||||
auto_includes_option: cli.Options.AutoIncludes,
|
auto_includes_option: cli.Options.AutoIncludes,
|
||||||
zig_lib_dir: []const u8,
|
zig_lib_dir: []const u8,
|
||||||
target_machine_type: std.coff.MachineType,
|
target_machine_type: std.coff.IMAGE.FILE.MACHINE,
|
||||||
resolved_include_paths: ?[]const []const u8 = null,
|
resolved_include_paths: ?[]const []const u8 = null,
|
||||||
|
|
||||||
pub fn get(self: *LazyIncludePaths, error_handler: *ErrorHandler) ![]const []const u8 {
|
pub fn get(self: *LazyIncludePaths, error_handler: *ErrorHandler) ![]const []const u8 {
|
||||||
@ -555,11 +555,11 @@ const LazyIncludePaths = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn getIncludePaths(arena: std.mem.Allocator, auto_includes_option: cli.Options.AutoIncludes, zig_lib_dir: []const u8, target_machine_type: std.coff.MachineType) ![]const []const u8 {
|
fn getIncludePaths(arena: std.mem.Allocator, auto_includes_option: cli.Options.AutoIncludes, zig_lib_dir: []const u8, target_machine_type: std.coff.IMAGE.FILE.MACHINE) ![]const []const u8 {
|
||||||
if (auto_includes_option == .none) return &[_][]const u8{};
|
if (auto_includes_option == .none) return &[_][]const u8{};
|
||||||
|
|
||||||
const includes_arch: std.Target.Cpu.Arch = switch (target_machine_type) {
|
const includes_arch: std.Target.Cpu.Arch = switch (target_machine_type) {
|
||||||
.X64 => .x86_64,
|
.AMD64 => .x86_64,
|
||||||
.I386 => .x86,
|
.I386 => .x86,
|
||||||
.ARMNT => .thumb,
|
.ARMNT => .thumb,
|
||||||
.ARM64 => .aarch64,
|
.ARM64 => .aarch64,
|
||||||
|
|||||||
@ -1082,7 +1082,7 @@ pub fn toElfMachine(target: *const Target) std.elf.EM {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toCoffMachine(target: *const Target) std.coff.MachineType {
|
pub fn toCoffMachine(target: *const Target) std.coff.IMAGE.FILE.MACHINE {
|
||||||
return switch (target.cpu.arch) {
|
return switch (target.cpu.arch) {
|
||||||
.arm => .ARM,
|
.arm => .ARM,
|
||||||
.thumb => .ARMNT,
|
.thumb => .ARMNT,
|
||||||
@ -1092,7 +1092,7 @@ pub fn toCoffMachine(target: *const Target) std.coff.MachineType {
|
|||||||
.riscv32 => .RISCV32,
|
.riscv32 => .RISCV32,
|
||||||
.riscv64 => .RISCV64,
|
.riscv64 => .RISCV64,
|
||||||
.x86 => .I386,
|
.x86 => .I386,
|
||||||
.x86_64 => .X64,
|
.x86_64 => .AMD64,
|
||||||
|
|
||||||
.amdgcn,
|
.amdgcn,
|
||||||
.arc,
|
.arc,
|
||||||
|
|||||||
@ -50,7 +50,7 @@ pub fn eqlString(a: []const u8, b: []const u8) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn hashString(s: []const u8) u32 {
|
pub fn hashString(s: []const u8) u32 {
|
||||||
return @as(u32, @truncate(std.hash.Wyhash.hash(0, s)));
|
return @truncate(std.hash.Wyhash.hash(0, s));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated in favor of `ArrayHashMapWithAllocator` (no code changes needed)
|
/// Deprecated in favor of `ArrayHashMapWithAllocator` (no code changes needed)
|
||||||
|
|||||||
1037
lib/std/coff.zig
1037
lib/std/coff.zig
File diff suppressed because it is too large
Load Diff
@ -78,13 +78,15 @@ pub fn defaultQueryPageSize() usize {
|
|||||||
};
|
};
|
||||||
var size = global.cached_result.load(.unordered);
|
var size = global.cached_result.load(.unordered);
|
||||||
if (size > 0) return size;
|
if (size > 0) return size;
|
||||||
size = switch (builtin.os.tag) {
|
size = size: switch (builtin.os.tag) {
|
||||||
.linux => if (builtin.link_libc) @intCast(std.c.sysconf(@intFromEnum(std.c._SC.PAGESIZE))) else std.os.linux.getauxval(std.elf.AT_PAGESZ),
|
.linux => if (builtin.link_libc)
|
||||||
.driverkit, .ios, .macos, .tvos, .visionos, .watchos => blk: {
|
@max(std.c.sysconf(@intFromEnum(std.c._SC.PAGESIZE)), 0)
|
||||||
|
else
|
||||||
|
std.os.linux.getauxval(std.elf.AT_PAGESZ),
|
||||||
|
.driverkit, .ios, .macos, .tvos, .visionos, .watchos => {
|
||||||
const task_port = std.c.mach_task_self();
|
const task_port = std.c.mach_task_self();
|
||||||
// mach_task_self may fail "if there are any resource failures or other errors".
|
// mach_task_self may fail "if there are any resource failures or other errors".
|
||||||
if (task_port == std.c.TASK.NULL)
|
if (task_port == std.c.TASK.NULL) break :size 0;
|
||||||
break :blk 0;
|
|
||||||
var info_count = std.c.TASK.VM.INFO_COUNT;
|
var info_count = std.c.TASK.VM.INFO_COUNT;
|
||||||
var vm_info: std.c.task_vm_info_data_t = undefined;
|
var vm_info: std.c.task_vm_info_data_t = undefined;
|
||||||
vm_info.page_size = 0;
|
vm_info.page_size = 0;
|
||||||
@ -94,21 +96,28 @@ pub fn defaultQueryPageSize() usize {
|
|||||||
@as(std.c.task_info_t, @ptrCast(&vm_info)),
|
@as(std.c.task_info_t, @ptrCast(&vm_info)),
|
||||||
&info_count,
|
&info_count,
|
||||||
);
|
);
|
||||||
assert(vm_info.page_size != 0);
|
break :size @intCast(vm_info.page_size);
|
||||||
break :blk @intCast(vm_info.page_size);
|
|
||||||
},
|
},
|
||||||
.windows => blk: {
|
.windows => {
|
||||||
var info: std.os.windows.SYSTEM_INFO = undefined;
|
var sbi: windows.SYSTEM_BASIC_INFORMATION = undefined;
|
||||||
std.os.windows.kernel32.GetSystemInfo(&info);
|
switch (windows.ntdll.NtQuerySystemInformation(
|
||||||
break :blk info.dwPageSize;
|
.SystemBasicInformation,
|
||||||
|
&sbi,
|
||||||
|
@sizeOf(windows.SYSTEM_BASIC_INFORMATION),
|
||||||
|
null,
|
||||||
|
)) {
|
||||||
|
.SUCCESS => break :size sbi.PageSize,
|
||||||
|
else => break :size 0,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
else => if (builtin.link_libc)
|
else => if (builtin.link_libc)
|
||||||
@intCast(std.c.sysconf(@intFromEnum(std.c._SC.PAGESIZE)))
|
@max(std.c.sysconf(@intFromEnum(std.c._SC.PAGESIZE)), 0)
|
||||||
else if (builtin.os.tag == .freestanding or builtin.os.tag == .other)
|
else if (builtin.os.tag == .freestanding or builtin.os.tag == .other)
|
||||||
@compileError("unsupported target: freestanding/other")
|
@compileError("unsupported target: freestanding/other")
|
||||||
else
|
else
|
||||||
@compileError("pageSize on " ++ @tagName(builtin.cpu.arch) ++ "-" ++ @tagName(builtin.os.tag) ++ " is not supported without linking libc, using the default implementation"),
|
@compileError("pageSize on " ++ @tagName(builtin.cpu.arch) ++ "-" ++ @tagName(builtin.os.tag) ++ " is not supported without linking libc, using the default implementation"),
|
||||||
};
|
};
|
||||||
|
if (size == 0) size = page_size_max;
|
||||||
|
|
||||||
assert(size >= page_size_min);
|
assert(size >= page_size_min);
|
||||||
assert(size <= page_size_max);
|
assert(size <= page_size_max);
|
||||||
|
|||||||
@ -256,8 +256,8 @@ test_filters: []const []const u8,
|
|||||||
|
|
||||||
link_task_wait_group: WaitGroup = .{},
|
link_task_wait_group: WaitGroup = .{},
|
||||||
link_prog_node: std.Progress.Node = .none,
|
link_prog_node: std.Progress.Node = .none,
|
||||||
link_uav_prog_node: std.Progress.Node = .none,
|
link_const_prog_node: std.Progress.Node = .none,
|
||||||
link_lazy_prog_node: std.Progress.Node = .none,
|
link_synth_prog_node: std.Progress.Node = .none,
|
||||||
|
|
||||||
llvm_opt_bisect_limit: c_int,
|
llvm_opt_bisect_limit: c_int,
|
||||||
|
|
||||||
@ -1982,13 +1982,13 @@ pub fn create(gpa: Allocator, arena: Allocator, diag: *CreateDiagnostic, options
|
|||||||
};
|
};
|
||||||
if (have_zcu and (!need_llvm or use_llvm)) {
|
if (have_zcu and (!need_llvm or use_llvm)) {
|
||||||
if (output_mode == .Obj) break :s .zcu;
|
if (output_mode == .Obj) break :s .zcu;
|
||||||
if (options.config.use_new_linker) break :s .zcu;
|
|
||||||
switch (target_util.zigBackend(target, use_llvm)) {
|
switch (target_util.zigBackend(target, use_llvm)) {
|
||||||
else => {},
|
else => {},
|
||||||
.stage2_aarch64, .stage2_x86_64 => if (target.ofmt == .coff) {
|
.stage2_aarch64, .stage2_x86_64 => if (target.ofmt == .coff) {
|
||||||
break :s if (is_exe_or_dyn_lib) .dyn_lib else .zcu;
|
break :s if (is_exe_or_dyn_lib) .dyn_lib else .zcu;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
if (options.config.use_new_linker) break :s .zcu;
|
||||||
}
|
}
|
||||||
if (need_llvm and !build_options.have_llvm) break :s .none; // impossible to build without llvm
|
if (need_llvm and !build_options.have_llvm) break :s .none; // impossible to build without llvm
|
||||||
if (is_exe_or_dyn_lib) break :s .lib;
|
if (is_exe_or_dyn_lib) break :s .lib;
|
||||||
@ -3081,22 +3081,30 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
|
|||||||
comp.link_prog_node = main_progress_node.start("Linking", 0);
|
comp.link_prog_node = main_progress_node.start("Linking", 0);
|
||||||
if (lf.cast(.elf2)) |elf| {
|
if (lf.cast(.elf2)) |elf| {
|
||||||
comp.link_prog_node.increaseEstimatedTotalItems(3);
|
comp.link_prog_node.increaseEstimatedTotalItems(3);
|
||||||
comp.link_uav_prog_node = comp.link_prog_node.start("Constants", 0);
|
comp.link_const_prog_node = comp.link_prog_node.start("Constants", 0);
|
||||||
comp.link_lazy_prog_node = comp.link_prog_node.start("Synthetics", 0);
|
comp.link_synth_prog_node = comp.link_prog_node.start("Synthetics", 0);
|
||||||
elf.mf.update_prog_node = comp.link_prog_node.start("Relocations", elf.mf.updates.items.len);
|
elf.mf.update_prog_node = comp.link_prog_node.start("Relocations", elf.mf.updates.items.len);
|
||||||
|
} else if (lf.cast(.coff2)) |coff| {
|
||||||
|
comp.link_prog_node.increaseEstimatedTotalItems(3);
|
||||||
|
comp.link_const_prog_node = comp.link_prog_node.start("Constants", 0);
|
||||||
|
comp.link_synth_prog_node = comp.link_prog_node.start("Synthetics", 0);
|
||||||
|
coff.mf.update_prog_node = comp.link_prog_node.start("Relocations", coff.mf.updates.items.len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defer {
|
defer {
|
||||||
comp.link_prog_node.end();
|
comp.link_prog_node.end();
|
||||||
comp.link_prog_node = .none;
|
comp.link_prog_node = .none;
|
||||||
comp.link_uav_prog_node.end();
|
comp.link_const_prog_node.end();
|
||||||
comp.link_uav_prog_node = .none;
|
comp.link_const_prog_node = .none;
|
||||||
comp.link_lazy_prog_node.end();
|
comp.link_synth_prog_node.end();
|
||||||
comp.link_lazy_prog_node = .none;
|
comp.link_synth_prog_node = .none;
|
||||||
if (comp.bin_file) |lf| {
|
if (comp.bin_file) |lf| {
|
||||||
if (lf.cast(.elf2)) |elf| {
|
if (lf.cast(.elf2)) |elf| {
|
||||||
elf.mf.update_prog_node.end();
|
elf.mf.update_prog_node.end();
|
||||||
elf.mf.update_prog_node = .none;
|
elf.mf.update_prog_node = .none;
|
||||||
|
} else if (lf.cast(.coff2)) |coff| {
|
||||||
|
coff.mf.update_prog_node.end();
|
||||||
|
coff.mf.update_prog_node = .none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3218,7 +3226,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
|
|||||||
.root_dir = comp.dirs.local_cache,
|
.root_dir = comp.dirs.local_cache,
|
||||||
.sub_path = try fs.path.join(arena, &.{ o_sub_path, comp.emit_bin.? }),
|
.sub_path = try fs.path.join(arena, &.{ o_sub_path, comp.emit_bin.? }),
|
||||||
};
|
};
|
||||||
const result: link.File.OpenError!void = switch (need_writable_dance) {
|
const result: (link.File.OpenError || error{HotSwapUnavailableOnHostOperatingSystem})!void = switch (need_writable_dance) {
|
||||||
.no => {},
|
.no => {},
|
||||||
.lf_only => lf.makeWritable(),
|
.lf_only => lf.makeWritable(),
|
||||||
.lf_and_debug => res: {
|
.lf_and_debug => res: {
|
||||||
|
|||||||
@ -11919,10 +11919,10 @@ pub fn getString(ip: *InternPool, key: []const u8) OptionalNullTerminatedString
|
|||||||
var map_index = hash;
|
var map_index = hash;
|
||||||
while (true) : (map_index += 1) {
|
while (true) : (map_index += 1) {
|
||||||
map_index &= map_mask;
|
map_index &= map_mask;
|
||||||
const entry = map.at(map_index);
|
const entry = &map.entries[map_index];
|
||||||
const index = entry.acquire().unwrap() orelse return null;
|
const index = entry.value.unwrap() orelse return .none;
|
||||||
if (entry.hash != hash) continue;
|
if (entry.hash != hash) continue;
|
||||||
if (index.eqlSlice(key, ip)) return index;
|
if (index.eqlSlice(key, ip)) return index.toOptional();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -978,21 +978,8 @@ pub fn genNavRef(
|
|||||||
},
|
},
|
||||||
.link_once => unreachable,
|
.link_once => unreachable,
|
||||||
}
|
}
|
||||||
} else if (lf.cast(.coff)) |coff_file| {
|
} else if (lf.cast(.coff2)) |coff| {
|
||||||
// TODO audit this
|
return .{ .sym_index = @intFromEnum(try coff.navSymbol(zcu, nav_index)) };
|
||||||
switch (linkage) {
|
|
||||||
.internal => {
|
|
||||||
const atom_index = try coff_file.getOrCreateAtomForNav(nav_index);
|
|
||||||
const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
|
|
||||||
return .{ .sym_index = sym_index };
|
|
||||||
},
|
|
||||||
.strong, .weak => {
|
|
||||||
const global_index = try coff_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
|
|
||||||
try coff_file.need_got_table.put(zcu.gpa, global_index, {}); // needs GOT
|
|
||||||
return .{ .sym_index = global_index };
|
|
||||||
},
|
|
||||||
.link_once => unreachable,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
const msg = try ErrorMsg.create(zcu.gpa, src_loc, "TODO genNavRef for target {}", .{target});
|
const msg = try ErrorMsg.create(zcu.gpa, src_loc, "TODO genNavRef for target {}", .{target});
|
||||||
return .{ .fail = msg };
|
return .{ .fail = msg };
|
||||||
|
|||||||
@ -135,11 +135,6 @@ pub fn emit(
|
|||||||
else if (lf.cast(.macho)) |mf|
|
else if (lf.cast(.macho)) |mf|
|
||||||
mf.getZigObject().?.getOrCreateMetadataForLazySymbol(mf, pt, lazy_reloc.symbol) catch |err|
|
mf.getZigObject().?.getOrCreateMetadataForLazySymbol(mf, pt, lazy_reloc.symbol) catch |err|
|
||||||
return zcu.codegenFail(func.owner_nav, "{s} creating lazy symbol", .{@errorName(err)})
|
return zcu.codegenFail(func.owner_nav, "{s} creating lazy symbol", .{@errorName(err)})
|
||||||
else if (lf.cast(.coff)) |cf|
|
|
||||||
if (cf.getOrCreateAtomForLazySymbol(pt, lazy_reloc.symbol)) |atom|
|
|
||||||
cf.getAtom(atom).getSymbolIndex().?
|
|
||||||
else |err|
|
|
||||||
return zcu.codegenFail(func.owner_nav, "{s} creating lazy symbol", .{@errorName(err)})
|
|
||||||
else
|
else
|
||||||
return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}),
|
return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}),
|
||||||
mir.body[lazy_reloc.reloc.label],
|
mir.body[lazy_reloc.reloc.label],
|
||||||
@ -154,8 +149,6 @@ pub fn emit(
|
|||||||
try ef.getGlobalSymbol(std.mem.span(global_reloc.name), null)
|
try ef.getGlobalSymbol(std.mem.span(global_reloc.name), null)
|
||||||
else if (lf.cast(.macho)) |mf|
|
else if (lf.cast(.macho)) |mf|
|
||||||
try mf.getGlobalSymbol(std.mem.span(global_reloc.name), null)
|
try mf.getGlobalSymbol(std.mem.span(global_reloc.name), null)
|
||||||
else if (lf.cast(.coff)) |cf|
|
|
||||||
try cf.getGlobalSymbol(std.mem.span(global_reloc.name), "compiler_rt")
|
|
||||||
else
|
else
|
||||||
return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}),
|
return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}),
|
||||||
mir.body[global_reloc.reloc.label],
|
mir.body[global_reloc.reloc.label],
|
||||||
|
|||||||
@ -12103,7 +12103,7 @@ fn firstParamSRet(fn_info: InternPool.Key.FuncType, zcu: *Zcu, target: *const st
|
|||||||
return switch (fn_info.cc) {
|
return switch (fn_info.cc) {
|
||||||
.auto => returnTypeByRef(zcu, target, return_type),
|
.auto => returnTypeByRef(zcu, target, return_type),
|
||||||
.x86_64_sysv => firstParamSRetSystemV(return_type, zcu, target),
|
.x86_64_sysv => firstParamSRetSystemV(return_type, zcu, target),
|
||||||
.x86_64_win => x86_64_abi.classifyWindows(return_type, zcu, target) == .memory,
|
.x86_64_win => x86_64_abi.classifyWindows(return_type, zcu, target, .ret) == .memory,
|
||||||
.x86_sysv, .x86_win => isByRef(return_type, zcu),
|
.x86_sysv, .x86_win => isByRef(return_type, zcu),
|
||||||
.x86_stdcall => !isScalar(zcu, return_type),
|
.x86_stdcall => !isScalar(zcu, return_type),
|
||||||
.wasm_mvp => wasm_c_abi.classifyType(return_type, zcu) == .indirect,
|
.wasm_mvp => wasm_c_abi.classifyType(return_type, zcu) == .indirect,
|
||||||
@ -12205,7 +12205,7 @@ fn lowerFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType)
|
|||||||
fn lowerWin64FnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {
|
fn lowerWin64FnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {
|
||||||
const zcu = pt.zcu;
|
const zcu = pt.zcu;
|
||||||
const return_type = Type.fromInterned(fn_info.return_type);
|
const return_type = Type.fromInterned(fn_info.return_type);
|
||||||
switch (x86_64_abi.classifyWindows(return_type, zcu, zcu.getTarget())) {
|
switch (x86_64_abi.classifyWindows(return_type, zcu, zcu.getTarget(), .ret)) {
|
||||||
.integer => {
|
.integer => {
|
||||||
if (isScalar(zcu, return_type)) {
|
if (isScalar(zcu, return_type)) {
|
||||||
return o.lowerType(pt, return_type);
|
return o.lowerType(pt, return_type);
|
||||||
@ -12476,7 +12476,7 @@ const ParamTypeIterator = struct {
|
|||||||
|
|
||||||
fn nextWin64(it: *ParamTypeIterator, ty: Type) ?Lowering {
|
fn nextWin64(it: *ParamTypeIterator, ty: Type) ?Lowering {
|
||||||
const zcu = it.pt.zcu;
|
const zcu = it.pt.zcu;
|
||||||
switch (x86_64_abi.classifyWindows(ty, zcu, zcu.getTarget())) {
|
switch (x86_64_abi.classifyWindows(ty, zcu, zcu.getTarget(), .arg)) {
|
||||||
.integer => {
|
.integer => {
|
||||||
if (isScalar(zcu, ty)) {
|
if (isScalar(zcu, ty)) {
|
||||||
it.zig_index += 1;
|
it.zig_index += 1;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -89,6 +89,7 @@ pub fn emitMir(emit: *Emit) Error!void {
|
|||||||
}
|
}
|
||||||
var reloc_info_buf: [2]RelocInfo = undefined;
|
var reloc_info_buf: [2]RelocInfo = undefined;
|
||||||
var reloc_info_index: usize = 0;
|
var reloc_info_index: usize = 0;
|
||||||
|
const ip = &emit.pt.zcu.intern_pool;
|
||||||
while (lowered_relocs.len > 0 and
|
while (lowered_relocs.len > 0 and
|
||||||
lowered_relocs[0].lowered_inst_index == lowered_index) : ({
|
lowered_relocs[0].lowered_inst_index == lowered_index) : ({
|
||||||
lowered_relocs = lowered_relocs[1..];
|
lowered_relocs = lowered_relocs[1..];
|
||||||
@ -114,7 +115,6 @@ pub fn emitMir(emit: *Emit) Error!void {
|
|||||||
return error.EmitFail;
|
return error.EmitFail;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const ip = &emit.pt.zcu.intern_pool;
|
|
||||||
break :target switch (ip.getNav(nav).status) {
|
break :target switch (ip.getNav(nav).status) {
|
||||||
.unresolved => unreachable,
|
.unresolved => unreachable,
|
||||||
.type_resolved => |type_resolved| .{
|
.type_resolved => |type_resolved| .{
|
||||||
@ -170,11 +170,8 @@ pub fn emitMir(emit: *Emit) Error!void {
|
|||||||
else if (emit.bin_file.cast(.macho)) |macho_file|
|
else if (emit.bin_file.cast(.macho)) |macho_file|
|
||||||
macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, emit.pt, lazy_sym) catch |err|
|
macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, emit.pt, lazy_sym) catch |err|
|
||||||
return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
|
return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
|
||||||
else if (emit.bin_file.cast(.coff)) |coff_file|
|
else if (emit.bin_file.cast(.coff2)) |elf|
|
||||||
if (coff_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym)) |atom|
|
@intFromEnum(try elf.lazySymbol(lazy_sym))
|
||||||
coff_file.getAtom(atom).getSymbolIndex().?
|
|
||||||
else |err|
|
|
||||||
return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
|
|
||||||
else
|
else
|
||||||
return emit.fail("lazy symbols unimplemented for {s}", .{@tagName(emit.bin_file.tag)}),
|
return emit.fail("lazy symbols unimplemented for {s}", .{@tagName(emit.bin_file.tag)}),
|
||||||
.is_extern = false,
|
.is_extern = false,
|
||||||
@ -188,10 +185,13 @@ pub fn emitMir(emit: *Emit) Error!void {
|
|||||||
.type = .FUNC,
|
.type = .FUNC,
|
||||||
})) else if (emit.bin_file.cast(.macho)) |macho_file|
|
})) else if (emit.bin_file.cast(.macho)) |macho_file|
|
||||||
try macho_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null)
|
try macho_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null)
|
||||||
else if (emit.bin_file.cast(.coff)) |coff_file|
|
else if (emit.bin_file.cast(.coff2)) |coff| @intFromEnum(try coff.globalSymbol(
|
||||||
try coff_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, "compiler_rt")
|
extern_func.toSlice(&emit.lower.mir).?,
|
||||||
else
|
switch (comp.compiler_rt_strat) {
|
||||||
return emit.fail("external symbol unimplemented for {s}", .{@tagName(emit.bin_file.tag)}),
|
.none, .lib, .obj, .zcu => null,
|
||||||
|
.dyn_lib => "compiler_rt",
|
||||||
|
},
|
||||||
|
)) else return emit.fail("external symbol unimplemented for {s}", .{@tagName(emit.bin_file.tag)}),
|
||||||
.is_extern = true,
|
.is_extern = true,
|
||||||
.type = .symbol,
|
.type = .symbol,
|
||||||
},
|
},
|
||||||
@ -204,9 +204,7 @@ pub fn emitMir(emit: *Emit) Error!void {
|
|||||||
switch (lowered_inst.encoding.mnemonic) {
|
switch (lowered_inst.encoding.mnemonic) {
|
||||||
.call => {
|
.call => {
|
||||||
reloc.target.type = .branch;
|
reloc.target.type = .branch;
|
||||||
if (emit.bin_file.cast(.coff)) |_| try emit.encodeInst(try .new(.none, .call, &.{
|
try emit.encodeInst(lowered_inst, reloc_info);
|
||||||
.{ .mem = .initRip(.ptr, 0) },
|
|
||||||
}, emit.lower.target), reloc_info) else try emit.encodeInst(lowered_inst, reloc_info);
|
|
||||||
continue :lowered_inst;
|
continue :lowered_inst;
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
@ -283,27 +281,8 @@ pub fn emitMir(emit: *Emit) Error!void {
|
|||||||
}, emit.lower.target), reloc_info),
|
}, emit.lower.target), reloc_info),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
} else if (emit.bin_file.cast(.coff)) |_| {
|
} else if (emit.bin_file.cast(.coff2)) |_| {
|
||||||
if (reloc.target.is_extern) switch (lowered_inst.encoding.mnemonic) {
|
switch (lowered_inst.encoding.mnemonic) {
|
||||||
.lea => try emit.encodeInst(try .new(.none, .mov, &.{
|
|
||||||
lowered_inst.ops[0],
|
|
||||||
.{ .mem = .initRip(.ptr, 0) },
|
|
||||||
}, emit.lower.target), reloc_info),
|
|
||||||
.mov => {
|
|
||||||
const dst_reg = lowered_inst.ops[0].reg.to64();
|
|
||||||
try emit.encodeInst(try .new(.none, .mov, &.{
|
|
||||||
.{ .reg = dst_reg },
|
|
||||||
.{ .mem = .initRip(.ptr, 0) },
|
|
||||||
}, emit.lower.target), reloc_info);
|
|
||||||
try emit.encodeInst(try .new(.none, .mov, &.{
|
|
||||||
lowered_inst.ops[0],
|
|
||||||
.{ .mem = .initSib(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, .{ .base = .{
|
|
||||||
.reg = dst_reg,
|
|
||||||
} }) },
|
|
||||||
}, emit.lower.target), &.{});
|
|
||||||
},
|
|
||||||
else => unreachable,
|
|
||||||
} else switch (lowered_inst.encoding.mnemonic) {
|
|
||||||
.lea => try emit.encodeInst(try .new(.none, .lea, &.{
|
.lea => try emit.encodeInst(try .new(.none, .lea, &.{
|
||||||
lowered_inst.ops[0],
|
lowered_inst.ops[0],
|
||||||
.{ .mem = .initRip(.none, 0) },
|
.{ .mem = .initRip(.none, 0) },
|
||||||
@ -683,7 +662,7 @@ pub fn emitMir(emit: *Emit) Error!void {
|
|||||||
table_reloc.source_offset,
|
table_reloc.source_offset,
|
||||||
@enumFromInt(emit.atom_index),
|
@enumFromInt(emit.atom_index),
|
||||||
@as(i64, table_offset) + table_reloc.target_offset,
|
@as(i64, table_offset) + table_reloc.target_offset,
|
||||||
.{ .x86_64 = .@"32" },
|
.{ .X86_64 = .@"32" },
|
||||||
);
|
);
|
||||||
for (emit.lower.mir.table) |entry| {
|
for (emit.lower.mir.table) |entry| {
|
||||||
try elf.addReloc(
|
try elf.addReloc(
|
||||||
@ -691,7 +670,7 @@ pub fn emitMir(emit: *Emit) Error!void {
|
|||||||
table_offset,
|
table_offset,
|
||||||
@enumFromInt(emit.atom_index),
|
@enumFromInt(emit.atom_index),
|
||||||
emit.code_offset_mapping.items[entry],
|
emit.code_offset_mapping.items[entry],
|
||||||
.{ .x86_64 = .@"64" },
|
.{ .X86_64 = .@"64" },
|
||||||
);
|
);
|
||||||
table_offset += ptr_size;
|
table_offset += ptr_size;
|
||||||
}
|
}
|
||||||
@ -800,23 +779,14 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
|
|||||||
end_offset - 4,
|
end_offset - 4,
|
||||||
@enumFromInt(reloc.target.index),
|
@enumFromInt(reloc.target.index),
|
||||||
reloc.off,
|
reloc.off,
|
||||||
.{ .x86_64 = .@"32" },
|
.{ .X86_64 = .@"32" },
|
||||||
) else if (emit.bin_file.cast(.coff)) |coff_file| {
|
) else if (emit.bin_file.cast(.coff2)) |coff| try coff.addReloc(
|
||||||
const atom_index = coff_file.getAtomIndexForSymbol(
|
@enumFromInt(emit.atom_index),
|
||||||
.{ .sym_index = emit.atom_index, .file = null },
|
end_offset - 4,
|
||||||
).?;
|
@enumFromInt(reloc.target.index),
|
||||||
try coff_file.addRelocation(atom_index, .{
|
reloc.off,
|
||||||
.type = if (reloc.target.is_extern) .got else .direct,
|
.{ .AMD64 = .REL32 },
|
||||||
.target = if (reloc.target.is_extern)
|
) else unreachable,
|
||||||
coff_file.getGlobalByIndex(reloc.target.index)
|
|
||||||
else
|
|
||||||
.{ .sym_index = reloc.target.index, .file = null },
|
|
||||||
.offset = end_offset - 4,
|
|
||||||
.addend = @intCast(reloc.off),
|
|
||||||
.pcrel = true,
|
|
||||||
.length = 2,
|
|
||||||
});
|
|
||||||
} else unreachable,
|
|
||||||
.branch => if (emit.bin_file.cast(.elf)) |elf_file| {
|
.branch => if (emit.bin_file.cast(.elf)) |elf_file| {
|
||||||
const zo = elf_file.zigObjectPtr().?;
|
const zo = elf_file.zigObjectPtr().?;
|
||||||
const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
|
const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
|
||||||
@ -831,7 +801,7 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
|
|||||||
end_offset - 4,
|
end_offset - 4,
|
||||||
@enumFromInt(reloc.target.index),
|
@enumFromInt(reloc.target.index),
|
||||||
reloc.off - 4,
|
reloc.off - 4,
|
||||||
.{ .x86_64 = .PC32 },
|
.{ .X86_64 = .PC32 },
|
||||||
) else if (emit.bin_file.cast(.macho)) |macho_file| {
|
) else if (emit.bin_file.cast(.macho)) |macho_file| {
|
||||||
const zo = macho_file.getZigObject().?;
|
const zo = macho_file.getZigObject().?;
|
||||||
const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
|
const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
|
||||||
@ -848,22 +818,13 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
|
|||||||
.symbolnum = @intCast(reloc.target.index),
|
.symbolnum = @intCast(reloc.target.index),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else if (emit.bin_file.cast(.coff)) |coff_file| {
|
} else if (emit.bin_file.cast(.coff2)) |coff| try coff.addReloc(
|
||||||
const atom_index = coff_file.getAtomIndexForSymbol(
|
@enumFromInt(emit.atom_index),
|
||||||
.{ .sym_index = emit.atom_index, .file = null },
|
end_offset - 4,
|
||||||
).?;
|
@enumFromInt(reloc.target.index),
|
||||||
try coff_file.addRelocation(atom_index, .{
|
reloc.off,
|
||||||
.type = if (reloc.target.is_extern) .import else .got,
|
.{ .AMD64 = .REL32 },
|
||||||
.target = if (reloc.target.is_extern)
|
) else return emit.fail("TODO implement {s} reloc for {s}", .{
|
||||||
coff_file.getGlobalByIndex(reloc.target.index)
|
|
||||||
else
|
|
||||||
.{ .sym_index = reloc.target.index, .file = null },
|
|
||||||
.offset = end_offset - 4,
|
|
||||||
.addend = @intCast(reloc.off),
|
|
||||||
.pcrel = true,
|
|
||||||
.length = 2,
|
|
||||||
});
|
|
||||||
} else return emit.fail("TODO implement {s} reloc for {s}", .{
|
|
||||||
@tagName(reloc.target.type), @tagName(emit.bin_file.tag),
|
@tagName(reloc.target.type), @tagName(emit.bin_file.tag),
|
||||||
}),
|
}),
|
||||||
.tls => if (emit.bin_file.cast(.elf)) |elf_file| {
|
.tls => if (emit.bin_file.cast(.elf)) |elf_file| {
|
||||||
@ -892,7 +853,7 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
|
|||||||
end_offset - 4,
|
end_offset - 4,
|
||||||
@enumFromInt(reloc.target.index),
|
@enumFromInt(reloc.target.index),
|
||||||
reloc.off,
|
reloc.off,
|
||||||
.{ .x86_64 = .TPOFF32 },
|
.{ .X86_64 = .TPOFF32 },
|
||||||
) else if (emit.bin_file.cast(.macho)) |macho_file| {
|
) else if (emit.bin_file.cast(.macho)) |macho_file| {
|
||||||
const zo = macho_file.getZigObject().?;
|
const zo = macho_file.getZigObject().?;
|
||||||
const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
|
const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
|
||||||
|
|||||||
@ -110,7 +110,9 @@ pub const Class = enum {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn classifyWindows(ty: Type, zcu: *Zcu, target: *const std.Target) Class {
|
pub const Context = enum { ret, arg, other };
|
||||||
|
|
||||||
|
pub fn classifyWindows(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Context) Class {
|
||||||
// https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017
|
// https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017
|
||||||
// "There's a strict one-to-one correspondence between a function call's arguments
|
// "There's a strict one-to-one correspondence between a function call's arguments
|
||||||
// and the registers used for those arguments. Any argument that doesn't fit in 8
|
// and the registers used for those arguments. Any argument that doesn't fit in 8
|
||||||
@ -148,8 +150,9 @@ pub fn classifyWindows(ty: Type, zcu: *Zcu, target: *const std.Target) Class {
|
|||||||
},
|
},
|
||||||
|
|
||||||
.float => switch (ty.floatBits(target)) {
|
.float => switch (ty.floatBits(target)) {
|
||||||
16, 32, 64, 128 => .sse,
|
16, 32, 64 => .sse,
|
||||||
80 => .memory,
|
80 => .memory,
|
||||||
|
128 => if (ctx == .arg) .memory else .sse,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
},
|
},
|
||||||
.vector => .sse,
|
.vector => .sse,
|
||||||
@ -166,8 +169,6 @@ pub fn classifyWindows(ty: Type, zcu: *Zcu, target: *const std.Target) Class {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const Context = enum { ret, arg, other };
|
|
||||||
|
|
||||||
/// There are a maximum of 8 possible return slots. Returned values are in
|
/// There are a maximum of 8 possible return slots. Returned values are in
|
||||||
/// the beginning of the array; unused slots are filled with .none.
|
/// the beginning of the array; unused slots are filled with .none.
|
||||||
pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Context) [8]Class {
|
pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Context) [8]Class {
|
||||||
|
|||||||
@ -96,6 +96,7 @@ pub const Env = enum {
|
|||||||
.spirv_backend,
|
.spirv_backend,
|
||||||
.lld_linker,
|
.lld_linker,
|
||||||
.coff_linker,
|
.coff_linker,
|
||||||
|
.coff2_linker,
|
||||||
.elf_linker,
|
.elf_linker,
|
||||||
.elf2_linker,
|
.elf2_linker,
|
||||||
.macho_linker,
|
.macho_linker,
|
||||||
@ -284,6 +285,7 @@ pub const Feature = enum {
|
|||||||
|
|
||||||
lld_linker,
|
lld_linker,
|
||||||
coff_linker,
|
coff_linker,
|
||||||
|
coff2_linker,
|
||||||
elf_linker,
|
elf_linker,
|
||||||
elf2_linker,
|
elf2_linker,
|
||||||
macho_linker,
|
macho_linker,
|
||||||
|
|||||||
84
src/link.zig
84
src/link.zig
@ -574,16 +574,13 @@ pub const File = struct {
|
|||||||
const gpa = comp.gpa;
|
const gpa = comp.gpa;
|
||||||
switch (base.tag) {
|
switch (base.tag) {
|
||||||
.lld => assert(base.file == null),
|
.lld => assert(base.file == null),
|
||||||
.coff, .elf, .macho, .wasm, .goff, .xcoff => {
|
.elf, .macho, .wasm, .goff, .xcoff => {
|
||||||
if (base.file != null) return;
|
if (base.file != null) return;
|
||||||
dev.checkAny(&.{ .coff_linker, .elf_linker, .macho_linker, .plan9_linker, .wasm_linker, .goff_linker, .xcoff_linker });
|
dev.checkAny(&.{ .coff_linker, .elf_linker, .macho_linker, .plan9_linker, .wasm_linker, .goff_linker, .xcoff_linker });
|
||||||
const emit = base.emit;
|
const emit = base.emit;
|
||||||
if (base.child_pid) |pid| {
|
if (base.child_pid) |pid| {
|
||||||
if (builtin.os.tag == .windows) {
|
if (builtin.os.tag == .windows) {
|
||||||
const coff_file = base.cast(.coff).?;
|
return error.HotSwapUnavailableOnHostOperatingSystem;
|
||||||
coff_file.ptraceAttach(pid) catch |err| {
|
|
||||||
log.warn("attaching failed with error: {s}", .{@errorName(err)});
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
// If we try to open the output file in write mode while it is running,
|
// If we try to open the output file in write mode while it is running,
|
||||||
// it will return ETXTBSY. So instead, we copy the file, atomically rename it
|
// it will return ETXTBSY. So instead, we copy the file, atomically rename it
|
||||||
@ -610,27 +607,20 @@ pub const File = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const output_mode = comp.config.output_mode;
|
base.file = try emit.root_dir.handle.openFile(emit.sub_path, .{ .mode = .read_write });
|
||||||
const link_mode = comp.config.link_mode;
|
|
||||||
base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{
|
|
||||||
.truncate = false,
|
|
||||||
.read = true,
|
|
||||||
.mode = determineMode(output_mode, link_mode),
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
.elf2 => {
|
.elf2, .coff2 => if (base.file == null) {
|
||||||
const elf = base.cast(.elf2).?;
|
const mf = if (base.cast(.elf2)) |elf|
|
||||||
if (base.file == null) {
|
&elf.mf
|
||||||
elf.mf.file = try base.emit.root_dir.handle.createFile(base.emit.sub_path, .{
|
else if (base.cast(.coff2)) |coff|
|
||||||
.truncate = false,
|
&coff.mf
|
||||||
.read = true,
|
else
|
||||||
.mode = determineMode(comp.config.output_mode, comp.config.link_mode),
|
unreachable;
|
||||||
|
mf.file = try base.emit.root_dir.handle.openFile(base.emit.sub_path, .{
|
||||||
|
.mode = .read_write,
|
||||||
});
|
});
|
||||||
base.file = elf.mf.file;
|
base.file = mf.file;
|
||||||
try elf.mf.ensureTotalCapacity(
|
try mf.ensureTotalCapacity(@intCast(mf.nodes.items[0].location().resolve(mf)[1]));
|
||||||
@intCast(elf.mf.nodes.items[0].location().resolve(&elf.mf)[1]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
.c, .spirv => dev.checkAny(&.{ .c_linker, .spirv_linker }),
|
.c, .spirv => dev.checkAny(&.{ .c_linker, .spirv_linker }),
|
||||||
.plan9 => unreachable,
|
.plan9 => unreachable,
|
||||||
@ -654,12 +644,9 @@ pub const File = struct {
|
|||||||
pub fn makeExecutable(base: *File) !void {
|
pub fn makeExecutable(base: *File) !void {
|
||||||
dev.check(.make_executable);
|
dev.check(.make_executable);
|
||||||
const comp = base.comp;
|
const comp = base.comp;
|
||||||
const output_mode = comp.config.output_mode;
|
switch (comp.config.output_mode) {
|
||||||
const link_mode = comp.config.link_mode;
|
|
||||||
|
|
||||||
switch (output_mode) {
|
|
||||||
.Obj => return,
|
.Obj => return,
|
||||||
.Lib => switch (link_mode) {
|
.Lib => switch (comp.config.link_mode) {
|
||||||
.static => return,
|
.static => return,
|
||||||
.dynamic => {},
|
.dynamic => {},
|
||||||
},
|
},
|
||||||
@ -681,7 +668,7 @@ pub const File = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.coff, .macho, .wasm, .goff, .xcoff => if (base.file) |f| {
|
.macho, .wasm, .goff, .xcoff => if (base.file) |f| {
|
||||||
dev.checkAny(&.{ .coff_linker, .macho_linker, .plan9_linker, .wasm_linker, .goff_linker, .xcoff_linker });
|
dev.checkAny(&.{ .coff_linker, .macho_linker, .plan9_linker, .wasm_linker, .goff_linker, .xcoff_linker });
|
||||||
f.close();
|
f.close();
|
||||||
base.file = null;
|
base.file = null;
|
||||||
@ -694,23 +681,22 @@ pub const File = struct {
|
|||||||
log.warn("detaching failed with error: {s}", .{@errorName(err)});
|
log.warn("detaching failed with error: {s}", .{@errorName(err)});
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
.windows => {
|
|
||||||
const coff_file = base.cast(.coff).?;
|
|
||||||
coff_file.ptraceDetach(pid);
|
|
||||||
},
|
|
||||||
else => return error.HotSwapUnavailableOnHostOperatingSystem,
|
else => return error.HotSwapUnavailableOnHostOperatingSystem,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.elf2 => {
|
.elf2, .coff2 => if (base.file) |f| {
|
||||||
const elf = base.cast(.elf2).?;
|
const mf = if (base.cast(.elf2)) |elf|
|
||||||
if (base.file) |f| {
|
&elf.mf
|
||||||
elf.mf.unmap();
|
else if (base.cast(.coff2)) |coff|
|
||||||
assert(elf.mf.file.handle == f.handle);
|
&coff.mf
|
||||||
elf.mf.file = undefined;
|
else
|
||||||
|
unreachable;
|
||||||
|
mf.unmap();
|
||||||
|
assert(mf.file.handle == f.handle);
|
||||||
|
mf.file = undefined;
|
||||||
f.close();
|
f.close();
|
||||||
base.file = null;
|
base.file = null;
|
||||||
}
|
|
||||||
},
|
},
|
||||||
.c, .spirv => dev.checkAny(&.{ .c_linker, .spirv_linker }),
|
.c, .spirv => dev.checkAny(&.{ .c_linker, .spirv_linker }),
|
||||||
.plan9 => unreachable,
|
.plan9 => unreachable,
|
||||||
@ -828,7 +814,7 @@ pub const File = struct {
|
|||||||
.spirv => {},
|
.spirv => {},
|
||||||
.goff, .xcoff => {},
|
.goff, .xcoff => {},
|
||||||
.plan9 => unreachable,
|
.plan9 => unreachable,
|
||||||
.elf2 => {},
|
.elf2, .coff2 => {},
|
||||||
inline else => |tag| {
|
inline else => |tag| {
|
||||||
dev.check(tag.devFeature());
|
dev.check(tag.devFeature());
|
||||||
return @as(*tag.Type(), @fieldParentPtr("base", base)).updateLineNumber(pt, ti_id);
|
return @as(*tag.Type(), @fieldParentPtr("base", base)).updateLineNumber(pt, ti_id);
|
||||||
@ -864,7 +850,7 @@ pub const File = struct {
|
|||||||
pub fn idle(base: *File, tid: Zcu.PerThread.Id) !bool {
|
pub fn idle(base: *File, tid: Zcu.PerThread.Id) !bool {
|
||||||
switch (base.tag) {
|
switch (base.tag) {
|
||||||
else => return false,
|
else => return false,
|
||||||
inline .elf2 => |tag| {
|
inline .elf2, .coff2 => |tag| {
|
||||||
dev.check(tag.devFeature());
|
dev.check(tag.devFeature());
|
||||||
return @as(*tag.Type(), @fieldParentPtr("base", base)).idle(tid);
|
return @as(*tag.Type(), @fieldParentPtr("base", base)).idle(tid);
|
||||||
},
|
},
|
||||||
@ -874,7 +860,7 @@ pub const File = struct {
|
|||||||
pub fn updateErrorData(base: *File, pt: Zcu.PerThread) !void {
|
pub fn updateErrorData(base: *File, pt: Zcu.PerThread) !void {
|
||||||
switch (base.tag) {
|
switch (base.tag) {
|
||||||
else => {},
|
else => {},
|
||||||
inline .elf2 => |tag| {
|
inline .elf2, .coff2 => |tag| {
|
||||||
dev.check(tag.devFeature());
|
dev.check(tag.devFeature());
|
||||||
return @as(*tag.Type(), @fieldParentPtr("base", base)).updateErrorData(pt);
|
return @as(*tag.Type(), @fieldParentPtr("base", base)).updateErrorData(pt);
|
||||||
},
|
},
|
||||||
@ -1155,7 +1141,7 @@ pub const File = struct {
|
|||||||
if (base.zcu_object_basename != null) return;
|
if (base.zcu_object_basename != null) return;
|
||||||
|
|
||||||
switch (base.tag) {
|
switch (base.tag) {
|
||||||
inline .elf2, .wasm => |tag| {
|
inline .elf2, .coff2, .wasm => |tag| {
|
||||||
dev.check(tag.devFeature());
|
dev.check(tag.devFeature());
|
||||||
return @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(base.comp.link_prog_node);
|
return @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(base.comp.link_prog_node);
|
||||||
},
|
},
|
||||||
@ -1164,7 +1150,7 @@ pub const File = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const Tag = enum {
|
pub const Tag = enum {
|
||||||
coff,
|
coff2,
|
||||||
elf,
|
elf,
|
||||||
elf2,
|
elf2,
|
||||||
macho,
|
macho,
|
||||||
@ -1178,7 +1164,7 @@ pub const File = struct {
|
|||||||
|
|
||||||
pub fn Type(comptime tag: Tag) type {
|
pub fn Type(comptime tag: Tag) type {
|
||||||
return switch (tag) {
|
return switch (tag) {
|
||||||
.coff => Coff,
|
.coff2 => Coff2,
|
||||||
.elf => Elf,
|
.elf => Elf,
|
||||||
.elf2 => Elf2,
|
.elf2 => Elf2,
|
||||||
.macho => MachO,
|
.macho => MachO,
|
||||||
@ -1194,7 +1180,7 @@ pub const File = struct {
|
|||||||
|
|
||||||
fn fromObjectFormat(ofmt: std.Target.ObjectFormat, use_new_linker: bool) Tag {
|
fn fromObjectFormat(ofmt: std.Target.ObjectFormat, use_new_linker: bool) Tag {
|
||||||
return switch (ofmt) {
|
return switch (ofmt) {
|
||||||
.coff => .coff,
|
.coff => .coff2,
|
||||||
.elf => if (use_new_linker) .elf2 else .elf,
|
.elf => if (use_new_linker) .elf2 else .elf,
|
||||||
.macho => .macho,
|
.macho => .macho,
|
||||||
.wasm => .wasm,
|
.wasm => .wasm,
|
||||||
@ -1279,7 +1265,7 @@ pub const File = struct {
|
|||||||
|
|
||||||
pub const Lld = @import("link/Lld.zig");
|
pub const Lld = @import("link/Lld.zig");
|
||||||
pub const C = @import("link/C.zig");
|
pub const C = @import("link/C.zig");
|
||||||
pub const Coff = @import("link/Coff.zig");
|
pub const Coff2 = @import("link/Coff2.zig");
|
||||||
pub const Elf = @import("link/Elf.zig");
|
pub const Elf = @import("link/Elf.zig");
|
||||||
pub const Elf2 = @import("link/Elf2.zig");
|
pub const Elf2 = @import("link/Elf2.zig");
|
||||||
pub const MachO = @import("link/MachO.zig");
|
pub const MachO = @import("link/MachO.zig");
|
||||||
|
|||||||
3169
src/link/Coff.zig
3169
src/link/Coff.zig
File diff suppressed because it is too large
Load Diff
2193
src/link/Coff2.zig
Normal file
2193
src/link/Coff2.zig
Normal file
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@ lazy: std.EnumArray(link.File.LazySymbol.Kind, struct {
|
|||||||
map: std.AutoArrayHashMapUnmanaged(InternPool.Index, Symbol.Index),
|
map: std.AutoArrayHashMapUnmanaged(InternPool.Index, Symbol.Index),
|
||||||
pending_index: u32,
|
pending_index: u32,
|
||||||
}),
|
}),
|
||||||
pending_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, struct {
|
pending_uavs: std.AutoArrayHashMapUnmanaged(Node.UavMapIndex, struct {
|
||||||
alignment: InternPool.Alignment,
|
alignment: InternPool.Alignment,
|
||||||
src_loc: Zcu.LazySrcLoc,
|
src_loc: Zcu.LazySrcLoc,
|
||||||
}),
|
}),
|
||||||
@ -25,10 +25,65 @@ pub const Node = union(enum) {
|
|||||||
shdr,
|
shdr,
|
||||||
segment: u32,
|
segment: u32,
|
||||||
section: Symbol.Index,
|
section: Symbol.Index,
|
||||||
nav: InternPool.Nav.Index,
|
nav: NavMapIndex,
|
||||||
uav: InternPool.Index,
|
uav: UavMapIndex,
|
||||||
lazy_code: InternPool.Index,
|
lazy_code: LazyMapRef.Index(.code),
|
||||||
lazy_const_data: InternPool.Index,
|
lazy_const_data: LazyMapRef.Index(.const_data),
|
||||||
|
|
||||||
|
pub const NavMapIndex = enum(u32) {
|
||||||
|
_,
|
||||||
|
|
||||||
|
pub fn navIndex(nmi: NavMapIndex, elf: *const Elf) InternPool.Nav.Index {
|
||||||
|
return elf.navs.keys()[@intFromEnum(nmi)];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn symbol(nmi: NavMapIndex, elf: *const Elf) Symbol.Index {
|
||||||
|
return elf.navs.values()[@intFromEnum(nmi)];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const UavMapIndex = enum(u32) {
|
||||||
|
_,
|
||||||
|
|
||||||
|
pub fn uavValue(umi: UavMapIndex, elf: *const Elf) InternPool.Index {
|
||||||
|
return elf.uavs.keys()[@intFromEnum(umi)];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn symbol(umi: UavMapIndex, elf: *const Elf) Symbol.Index {
|
||||||
|
return elf.uavs.values()[@intFromEnum(umi)];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const LazyMapRef = struct {
|
||||||
|
kind: link.File.LazySymbol.Kind,
|
||||||
|
index: u32,
|
||||||
|
|
||||||
|
pub fn Index(comptime kind: link.File.LazySymbol.Kind) type {
|
||||||
|
return enum(u32) {
|
||||||
|
_,
|
||||||
|
|
||||||
|
pub fn ref(lmi: @This()) LazyMapRef {
|
||||||
|
return .{ .kind = kind, .index = @intFromEnum(lmi) };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lazySymbol(lmi: @This(), elf: *const Elf) link.File.LazySymbol {
|
||||||
|
return lmi.ref().lazySymbol(elf);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn symbol(lmi: @This(), elf: *const Elf) Symbol.Index {
|
||||||
|
return lmi.ref().symbol(elf);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lazySymbol(lmr: LazyMapRef, elf: *const Elf) link.File.LazySymbol {
|
||||||
|
return .{ .kind = lmr.kind, .ty = elf.lazy.getPtrConst(lmr.kind).map.keys()[lmr.index] };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn symbol(lmr: LazyMapRef, elf: *const Elf) Symbol.Index {
|
||||||
|
return elf.lazy.getPtrConst(lmr.kind).map.values()[lmr.index];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub const Tag = @typeInfo(Node).@"union".tag_type.?;
|
pub const Tag = @typeInfo(Node).@"union".tag_type.?;
|
||||||
|
|
||||||
@ -43,11 +98,7 @@ pub const Node = union(enum) {
|
|||||||
seg_text,
|
seg_text,
|
||||||
seg_data,
|
seg_data,
|
||||||
};
|
};
|
||||||
var mut_known: std.enums.EnumFieldStruct(
|
var mut_known: std.enums.EnumFieldStruct(Known, MappedFile.Node.Index, null) = undefined;
|
||||||
Known,
|
|
||||||
MappedFile.Node.Index,
|
|
||||||
null,
|
|
||||||
) = undefined;
|
|
||||||
for (@typeInfo(Known).@"enum".fields) |field|
|
for (@typeInfo(Known).@"enum".fields) |field|
|
||||||
@field(mut_known, field.name) = @enumFromInt(field.value);
|
@field(mut_known, field.name) = @enumFromInt(field.value);
|
||||||
break :known mut_known;
|
break :known mut_known;
|
||||||
@ -223,10 +274,10 @@ pub const Reloc = extern struct {
|
|||||||
addend: i64,
|
addend: i64,
|
||||||
|
|
||||||
pub const Type = extern union {
|
pub const Type = extern union {
|
||||||
x86_64: std.elf.R_X86_64,
|
X86_64: std.elf.R_X86_64,
|
||||||
aarch64: std.elf.R_AARCH64,
|
AARCH64: std.elf.R_AARCH64,
|
||||||
riscv: std.elf.R_RISCV,
|
RISCV: std.elf.R_RISCV,
|
||||||
ppc64: std.elf.R_PPC64,
|
PPC64: std.elf.R_PPC64,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Index = enum(u32) {
|
pub const Index = enum(u32) {
|
||||||
@ -239,7 +290,7 @@ pub const Reloc = extern struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn apply(reloc: *const Reloc, elf: *Elf) void {
|
pub fn apply(reloc: *const Reloc, elf: *Elf) void {
|
||||||
const target_endian = elf.endian();
|
const target_endian = elf.targetEndian();
|
||||||
switch (reloc.loc.get(elf).ni) {
|
switch (reloc.loc.get(elf).ni) {
|
||||||
.none => return,
|
.none => return,
|
||||||
else => |ni| if (ni.hasMoved(&elf.mf)) return,
|
else => |ni| if (ni.hasMoved(&elf.mf)) return,
|
||||||
@ -274,7 +325,7 @@ pub const Reloc = extern struct {
|
|||||||
) +% @as(u64, @bitCast(reloc.addend));
|
) +% @as(u64, @bitCast(reloc.addend));
|
||||||
switch (elf.ehdrField(.machine)) {
|
switch (elf.ehdrField(.machine)) {
|
||||||
else => |machine| @panic(@tagName(machine)),
|
else => |machine| @panic(@tagName(machine)),
|
||||||
.X86_64 => switch (reloc.type.x86_64) {
|
.X86_64 => switch (reloc.type.X86_64) {
|
||||||
else => |kind| @panic(@tagName(kind)),
|
else => |kind| @panic(@tagName(kind)),
|
||||||
.@"64" => std.mem.writeInt(
|
.@"64" => std.mem.writeInt(
|
||||||
u64,
|
u64,
|
||||||
@ -394,37 +445,7 @@ fn create(
|
|||||||
},
|
},
|
||||||
.Obj => .REL,
|
.Obj => .REL,
|
||||||
};
|
};
|
||||||
const machine: std.elf.EM = switch (target.cpu.arch) {
|
const machine = target.toElfMachine();
|
||||||
.spirv32, .spirv64, .wasm32, .wasm64 => .NONE,
|
|
||||||
.sparc => .SPARC,
|
|
||||||
.x86 => .@"386",
|
|
||||||
.m68k => .@"68K",
|
|
||||||
.mips, .mipsel, .mips64, .mips64el => .MIPS,
|
|
||||||
.powerpc, .powerpcle => .PPC,
|
|
||||||
.powerpc64, .powerpc64le => .PPC64,
|
|
||||||
.s390x => .S390,
|
|
||||||
.arm, .armeb, .thumb, .thumbeb => .ARM,
|
|
||||||
.hexagon => .SH,
|
|
||||||
.sparc64 => .SPARCV9,
|
|
||||||
.arc => .ARC,
|
|
||||||
.x86_64 => .X86_64,
|
|
||||||
.or1k => .OR1K,
|
|
||||||
.xtensa => .XTENSA,
|
|
||||||
.msp430 => .MSP430,
|
|
||||||
.avr => .AVR,
|
|
||||||
.nvptx, .nvptx64 => .CUDA,
|
|
||||||
.kalimba => .CSR_KALIMBA,
|
|
||||||
.aarch64, .aarch64_be => .AARCH64,
|
|
||||||
.xcore => .XCORE,
|
|
||||||
.amdgcn => .AMDGPU,
|
|
||||||
.riscv32, .riscv32be, .riscv64, .riscv64be => .RISCV,
|
|
||||||
.lanai => .LANAI,
|
|
||||||
.bpfel, .bpfeb => .BPF,
|
|
||||||
.ve => .VE,
|
|
||||||
.csky => .CSKY,
|
|
||||||
.loongarch32, .loongarch64 => .LOONGARCH,
|
|
||||||
.propeller => if (target.cpu.has(.propeller, .p2)) .PROPELLER2 else .PROPELLER,
|
|
||||||
};
|
|
||||||
const maybe_interp = switch (comp.config.output_mode) {
|
const maybe_interp = switch (comp.config.output_mode) {
|
||||||
.Exe, .Lib => switch (comp.config.link_mode) {
|
.Exe, .Lib => switch (comp.config.link_mode) {
|
||||||
.static => null,
|
.static => null,
|
||||||
@ -479,7 +500,7 @@ fn create(
|
|||||||
|
|
||||||
switch (class) {
|
switch (class) {
|
||||||
.NONE, _ => unreachable,
|
.NONE, _ => unreachable,
|
||||||
inline .@"32", .@"64" => |ct_class| try elf.initHeaders(
|
inline else => |ct_class| try elf.initHeaders(
|
||||||
ct_class,
|
ct_class,
|
||||||
data,
|
data,
|
||||||
osabi,
|
osabi,
|
||||||
@ -567,7 +588,7 @@ fn initHeaders(
|
|||||||
.fixed = true,
|
.fixed = true,
|
||||||
}));
|
}));
|
||||||
elf.nodes.appendAssumeCapacity(.ehdr);
|
elf.nodes.appendAssumeCapacity(.ehdr);
|
||||||
|
{
|
||||||
const ehdr: *ElfN.Ehdr = @ptrCast(@alignCast(ehdr_ni.slice(&elf.mf)));
|
const ehdr: *ElfN.Ehdr = @ptrCast(@alignCast(ehdr_ni.slice(&elf.mf)));
|
||||||
const EI = std.elf.EI;
|
const EI = std.elf.EI;
|
||||||
@memcpy(ehdr.ident[0..std.elf.MAGIC.len], std.elf.MAGIC);
|
@memcpy(ehdr.ident[0..std.elf.MAGIC.len], std.elf.MAGIC);
|
||||||
@ -591,6 +612,7 @@ fn initHeaders(
|
|||||||
ehdr.shnum = 1;
|
ehdr.shnum = 1;
|
||||||
ehdr.shstrndx = 0;
|
ehdr.shstrndx = 0;
|
||||||
if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Ehdr, ehdr);
|
if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Ehdr, ehdr);
|
||||||
|
}
|
||||||
|
|
||||||
const phdr_ni = Node.known.phdr;
|
const phdr_ni = Node.known.phdr;
|
||||||
assert(phdr_ni == try elf.mf.addLastChildNode(gpa, seg_rodata_ni, .{
|
assert(phdr_ni == try elf.mf.addLastChildNode(gpa, seg_rodata_ni, .{
|
||||||
@ -750,7 +772,10 @@ fn initHeaders(
|
|||||||
},
|
},
|
||||||
.shndx = std.elf.SHN_UNDEF,
|
.shndx = std.elf.SHN_UNDEF,
|
||||||
};
|
};
|
||||||
|
{
|
||||||
|
const ehdr = @field(elf.ehdrPtr(), @tagName(class));
|
||||||
ehdr.shstrndx = ehdr.shnum;
|
ehdr.shstrndx = ehdr.shnum;
|
||||||
|
}
|
||||||
assert(try elf.addSection(seg_rodata_ni, .{
|
assert(try elf.addSection(seg_rodata_ni, .{
|
||||||
.type = std.elf.SHT_STRTAB,
|
.type = std.elf.SHT_STRTAB,
|
||||||
.addralign = elf.mf.flags.block_size,
|
.addralign = elf.mf.flags.block_size,
|
||||||
@ -821,37 +846,6 @@ fn getNode(elf: *Elf, ni: MappedFile.Node.Index) Node {
|
|||||||
return elf.nodes.get(@intFromEnum(ni));
|
return elf.nodes.get(@intFromEnum(ni));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const EhdrPtr = union(std.elf.CLASS) {
|
|
||||||
NONE: noreturn,
|
|
||||||
@"32": *std.elf.Elf32.Ehdr,
|
|
||||||
@"64": *std.elf.Elf64.Ehdr,
|
|
||||||
};
|
|
||||||
pub fn ehdrPtr(elf: *Elf) EhdrPtr {
|
|
||||||
const slice = Node.known.ehdr.slice(&elf.mf);
|
|
||||||
return switch (elf.identClass()) {
|
|
||||||
.NONE, _ => unreachable,
|
|
||||||
inline .@"32", .@"64" => |class| @unionInit(
|
|
||||||
EhdrPtr,
|
|
||||||
@tagName(class),
|
|
||||||
@ptrCast(@alignCast(slice)),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
pub fn ehdrField(
|
|
||||||
elf: *Elf,
|
|
||||||
comptime field: enum { type, machine },
|
|
||||||
) @FieldType(std.elf.Elf32.Ehdr, @tagName(field)) {
|
|
||||||
const Field = @FieldType(std.elf.Elf32.Ehdr, @tagName(field));
|
|
||||||
comptime assert(@FieldType(std.elf.Elf64.Ehdr, @tagName(field)) == Field);
|
|
||||||
return @enumFromInt(std.mem.toNative(
|
|
||||||
@typeInfo(Field).@"enum".tag_type,
|
|
||||||
@intFromEnum(switch (elf.ehdrPtr()) {
|
|
||||||
inline else => |ehdr| @field(ehdr, @tagName(field)),
|
|
||||||
}),
|
|
||||||
elf.endian(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn identClass(elf: *Elf) std.elf.CLASS {
|
pub fn identClass(elf: *Elf) std.elf.CLASS {
|
||||||
return @enumFromInt(elf.mf.contents[std.elf.EI.CLASS]);
|
return @enumFromInt(elf.mf.contents[std.elf.EI.CLASS]);
|
||||||
}
|
}
|
||||||
@ -866,10 +860,39 @@ fn endianForData(data: std.elf.DATA) std.builtin.Endian {
|
|||||||
.@"2MSB" => .big,
|
.@"2MSB" => .big,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub fn endian(elf: *Elf) std.builtin.Endian {
|
pub fn targetEndian(elf: *Elf) std.builtin.Endian {
|
||||||
return endianForData(elf.identData());
|
return endianForData(elf.identData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const EhdrPtr = union(std.elf.CLASS) {
|
||||||
|
NONE: noreturn,
|
||||||
|
@"32": *std.elf.Elf32.Ehdr,
|
||||||
|
@"64": *std.elf.Elf64.Ehdr,
|
||||||
|
};
|
||||||
|
pub fn ehdrPtr(elf: *Elf) EhdrPtr {
|
||||||
|
const slice = Node.known.ehdr.slice(&elf.mf);
|
||||||
|
return switch (elf.identClass()) {
|
||||||
|
.NONE, _ => unreachable,
|
||||||
|
inline else => |class| @unionInit(
|
||||||
|
EhdrPtr,
|
||||||
|
@tagName(class),
|
||||||
|
@ptrCast(@alignCast(slice)),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
pub fn ehdrField(
|
||||||
|
elf: *Elf,
|
||||||
|
comptime field: enum { type, machine },
|
||||||
|
) @FieldType(std.elf.Elf32.Ehdr, @tagName(field)) {
|
||||||
|
return @enumFromInt(std.mem.toNative(
|
||||||
|
@typeInfo(@FieldType(std.elf.Elf32.Ehdr, @tagName(field))).@"enum".tag_type,
|
||||||
|
@intFromEnum(switch (elf.ehdrPtr()) {
|
||||||
|
inline else => |ehdr| @field(ehdr, @tagName(field)),
|
||||||
|
}),
|
||||||
|
elf.targetEndian(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
fn baseAddrForType(@"type": std.elf.ET) u64 {
|
fn baseAddrForType(@"type": std.elf.ET) u64 {
|
||||||
return switch (@"type") {
|
return switch (@"type") {
|
||||||
else => 0,
|
else => 0,
|
||||||
@ -889,7 +912,7 @@ pub fn phdrSlice(elf: *Elf) PhdrSlice {
|
|||||||
const slice = Node.known.phdr.slice(&elf.mf);
|
const slice = Node.known.phdr.slice(&elf.mf);
|
||||||
return switch (elf.identClass()) {
|
return switch (elf.identClass()) {
|
||||||
.NONE, _ => unreachable,
|
.NONE, _ => unreachable,
|
||||||
inline .@"32", .@"64" => |class| @unionInit(
|
inline else => |class| @unionInit(
|
||||||
PhdrSlice,
|
PhdrSlice,
|
||||||
@tagName(class),
|
@tagName(class),
|
||||||
@ptrCast(@alignCast(slice)),
|
@ptrCast(@alignCast(slice)),
|
||||||
@ -906,7 +929,7 @@ pub fn shdrSlice(elf: *Elf) ShdrSlice {
|
|||||||
const slice = Node.known.shdr.slice(&elf.mf);
|
const slice = Node.known.shdr.slice(&elf.mf);
|
||||||
return switch (elf.identClass()) {
|
return switch (elf.identClass()) {
|
||||||
.NONE, _ => unreachable,
|
.NONE, _ => unreachable,
|
||||||
inline .@"32", .@"64" => |class| @unionInit(
|
inline else => |class| @unionInit(
|
||||||
ShdrSlice,
|
ShdrSlice,
|
||||||
@tagName(class),
|
@tagName(class),
|
||||||
@ptrCast(@alignCast(slice)),
|
@ptrCast(@alignCast(slice)),
|
||||||
@ -923,7 +946,7 @@ pub fn symSlice(elf: *Elf) SymSlice {
|
|||||||
const slice = Symbol.Index.symtab.node(elf).slice(&elf.mf);
|
const slice = Symbol.Index.symtab.node(elf).slice(&elf.mf);
|
||||||
return switch (elf.identClass()) {
|
return switch (elf.identClass()) {
|
||||||
.NONE, _ => unreachable,
|
.NONE, _ => unreachable,
|
||||||
inline .@"32", .@"64" => |class| @unionInit(
|
inline else => |class| @unionInit(
|
||||||
SymSlice,
|
SymSlice,
|
||||||
@tagName(class),
|
@tagName(class),
|
||||||
@ptrCast(@alignCast(slice)),
|
@ptrCast(@alignCast(slice)),
|
||||||
@ -942,7 +965,7 @@ pub fn symPtr(elf: *Elf, si: Symbol.Index) SymPtr {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn addSymbolAssumeCapacity(elf: *Elf) !Symbol.Index {
|
fn addSymbolAssumeCapacity(elf: *Elf) Symbol.Index {
|
||||||
defer elf.symtab.addOneAssumeCapacity().* = .{
|
defer elf.symtab.addOneAssumeCapacity().* = .{
|
||||||
.ni = .none,
|
.ni = .none,
|
||||||
.loc_relocs = .none,
|
.loc_relocs = .none,
|
||||||
@ -953,30 +976,27 @@ fn addSymbolAssumeCapacity(elf: *Elf) !Symbol.Index {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn initSymbolAssumeCapacity(elf: *Elf, opts: Symbol.Index.InitOptions) !Symbol.Index {
|
fn initSymbolAssumeCapacity(elf: *Elf, opts: Symbol.Index.InitOptions) !Symbol.Index {
|
||||||
const si = try elf.addSymbolAssumeCapacity();
|
const si = elf.addSymbolAssumeCapacity();
|
||||||
try si.init(elf, opts);
|
try si.init(elf, opts);
|
||||||
return si;
|
return si;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn globalSymbol(
|
pub fn globalSymbol(elf: *Elf, opts: struct {
|
||||||
elf: *Elf,
|
|
||||||
opts: struct {
|
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
type: std.elf.STT,
|
type: std.elf.STT,
|
||||||
bind: std.elf.STB = .GLOBAL,
|
bind: std.elf.STB = .GLOBAL,
|
||||||
visibility: std.elf.STV = .DEFAULT,
|
visibility: std.elf.STV = .DEFAULT,
|
||||||
},
|
}) !Symbol.Index {
|
||||||
) !Symbol.Index {
|
|
||||||
const gpa = elf.base.comp.gpa;
|
const gpa = elf.base.comp.gpa;
|
||||||
try elf.symtab.ensureUnusedCapacity(gpa, 1);
|
try elf.symtab.ensureUnusedCapacity(gpa, 1);
|
||||||
const sym_gop = try elf.globals.getOrPut(gpa, try elf.string(.strtab, opts.name));
|
const global_gop = try elf.globals.getOrPut(gpa, try elf.string(.strtab, opts.name));
|
||||||
if (!sym_gop.found_existing) sym_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{
|
if (!global_gop.found_existing) global_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{
|
||||||
.name = opts.name,
|
.name = opts.name,
|
||||||
.type = opts.type,
|
.type = opts.type,
|
||||||
.bind = opts.bind,
|
.bind = opts.bind,
|
||||||
.visibility = opts.visibility,
|
.visibility = opts.visibility,
|
||||||
});
|
});
|
||||||
return sym_gop.value_ptr.*;
|
return global_gop.value_ptr.*;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn navType(
|
fn navType(
|
||||||
@ -1008,8 +1028,19 @@ fn navType(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub fn navSymbol(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.Index {
|
fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavMapIndex {
|
||||||
const gpa = zcu.gpa;
|
const gpa = zcu.gpa;
|
||||||
|
const ip = &zcu.intern_pool;
|
||||||
|
const nav = ip.getNav(nav_index);
|
||||||
|
try elf.symtab.ensureUnusedCapacity(gpa, 1);
|
||||||
|
const nav_gop = try elf.navs.getOrPut(gpa, nav_index);
|
||||||
|
if (!nav_gop.found_existing) nav_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{
|
||||||
|
.name = nav.fqn.toSlice(ip),
|
||||||
|
.type = navType(ip, nav.status, elf.base.comp.config.any_non_single_threaded),
|
||||||
|
});
|
||||||
|
return @enumFromInt(nav_gop.index);
|
||||||
|
}
|
||||||
|
pub fn navSymbol(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.Index {
|
||||||
const ip = &zcu.intern_pool;
|
const ip = &zcu.intern_pool;
|
||||||
const nav = ip.getNav(nav_index);
|
const nav = ip.getNav(nav_index);
|
||||||
if (nav.getExtern(ip)) |@"extern"| return elf.globalSymbol(.{
|
if (nav.getExtern(ip)) |@"extern"| return elf.globalSymbol(.{
|
||||||
@ -1027,40 +1058,37 @@ pub fn navSymbol(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.
|
|||||||
.protected => .PROTECTED,
|
.protected => .PROTECTED,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
try elf.symtab.ensureUnusedCapacity(gpa, 1);
|
const nmi = try elf.navMapIndex(zcu, nav_index);
|
||||||
const sym_gop = try elf.navs.getOrPut(gpa, nav_index);
|
return nmi.symbol(elf);
|
||||||
if (!sym_gop.found_existing) {
|
|
||||||
sym_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{
|
|
||||||
.name = nav.fqn.toSlice(ip),
|
|
||||||
.type = navType(ip, nav.status, elf.base.comp.config.any_non_single_threaded),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return sym_gop.value_ptr.*;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uavSymbol(elf: *Elf, uav_val: InternPool.Index) !Symbol.Index {
|
fn uavMapIndex(elf: *Elf, uav_val: InternPool.Index) !Node.UavMapIndex {
|
||||||
const gpa = elf.base.comp.gpa;
|
const gpa = elf.base.comp.gpa;
|
||||||
try elf.symtab.ensureUnusedCapacity(gpa, 1);
|
try elf.symtab.ensureUnusedCapacity(gpa, 1);
|
||||||
const sym_gop = try elf.uavs.getOrPut(gpa, uav_val);
|
const uav_gop = try elf.uavs.getOrPut(gpa, uav_val);
|
||||||
if (!sym_gop.found_existing)
|
if (!uav_gop.found_existing)
|
||||||
sym_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{ .type = .OBJECT });
|
uav_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{ .type = .OBJECT });
|
||||||
return sym_gop.value_ptr.*;
|
return @enumFromInt(uav_gop.index);
|
||||||
|
}
|
||||||
|
pub fn uavSymbol(elf: *Elf, uav_val: InternPool.Index) !Symbol.Index {
|
||||||
|
const umi = try elf.uavMapIndex(uav_val);
|
||||||
|
return umi.symbol(elf);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) !Symbol.Index {
|
pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) !Symbol.Index {
|
||||||
const gpa = elf.base.comp.gpa;
|
const gpa = elf.base.comp.gpa;
|
||||||
try elf.symtab.ensureUnusedCapacity(gpa, 1);
|
try elf.symtab.ensureUnusedCapacity(gpa, 1);
|
||||||
const sym_gop = try elf.lazy.getPtr(lazy.kind).map.getOrPut(gpa, lazy.ty);
|
const lazy_gop = try elf.lazy.getPtr(lazy.kind).map.getOrPut(gpa, lazy.ty);
|
||||||
if (!sym_gop.found_existing) {
|
if (!lazy_gop.found_existing) {
|
||||||
sym_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{
|
lazy_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{
|
||||||
.type = switch (lazy.kind) {
|
.type = switch (lazy.kind) {
|
||||||
.code => .FUNC,
|
.code => .FUNC,
|
||||||
.const_data => .OBJECT,
|
.const_data => .OBJECT,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
elf.base.comp.link_lazy_prog_node.increaseEstimatedTotalItems(1);
|
elf.base.comp.link_synth_prog_node.increaseEstimatedTotalItems(1);
|
||||||
}
|
}
|
||||||
return sym_gop.value_ptr.*;
|
return lazy_gop.value_ptr.*;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getNavVAddr(
|
pub fn getNavVAddr(
|
||||||
@ -1088,7 +1116,7 @@ pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target_si: Symbol.In
|
|||||||
reloc_info.addend,
|
reloc_info.addend,
|
||||||
switch (elf.ehdrField(.machine)) {
|
switch (elf.ehdrField(.machine)) {
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
.X86_64 => .{ .x86_64 = switch (elf.identClass()) {
|
.X86_64 => .{ .X86_64 = switch (elf.identClass()) {
|
||||||
.NONE, _ => unreachable,
|
.NONE, _ => unreachable,
|
||||||
.@"32" => .@"32",
|
.@"32" => .@"32",
|
||||||
.@"64" => .@"64",
|
.@"64" => .@"64",
|
||||||
@ -1107,7 +1135,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
|
|||||||
entsize: std.elf.Word = 0,
|
entsize: std.elf.Word = 0,
|
||||||
}) !Symbol.Index {
|
}) !Symbol.Index {
|
||||||
const gpa = elf.base.comp.gpa;
|
const gpa = elf.base.comp.gpa;
|
||||||
const target_endian = elf.endian();
|
const target_endian = elf.targetEndian();
|
||||||
try elf.nodes.ensureUnusedCapacity(gpa, 1);
|
try elf.nodes.ensureUnusedCapacity(gpa, 1);
|
||||||
try elf.symtab.ensureUnusedCapacity(gpa, 1);
|
try elf.symtab.ensureUnusedCapacity(gpa, 1);
|
||||||
|
|
||||||
@ -1127,7 +1155,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
|
|||||||
.size = opts.size,
|
.size = opts.size,
|
||||||
.moved = true,
|
.moved = true,
|
||||||
});
|
});
|
||||||
const si = try elf.addSymbolAssumeCapacity();
|
const si = elf.addSymbolAssumeCapacity();
|
||||||
elf.nodes.appendAssumeCapacity(.{ .section = si });
|
elf.nodes.appendAssumeCapacity(.{ .section = si });
|
||||||
si.get(elf).ni = ni;
|
si.get(elf).ni = ni;
|
||||||
try si.init(elf, .{
|
try si.init(elf, .{
|
||||||
@ -1160,7 +1188,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
|
|||||||
fn renameSection(elf: *Elf, si: Symbol.Index, name: []const u8) !void {
|
fn renameSection(elf: *Elf, si: Symbol.Index, name: []const u8) !void {
|
||||||
const strtab_entry = try elf.string(.strtab, name);
|
const strtab_entry = try elf.string(.strtab, name);
|
||||||
const shstrtab_entry = try elf.string(.shstrtab, name);
|
const shstrtab_entry = try elf.string(.shstrtab, name);
|
||||||
const target_endian = elf.endian();
|
const target_endian = elf.targetEndian();
|
||||||
switch (elf.shdrSlice()) {
|
switch (elf.shdrSlice()) {
|
||||||
inline else => |shdr, class| {
|
inline else => |shdr, class| {
|
||||||
const sym = @field(elf.symPtr(si), @tagName(class));
|
const sym = @field(elf.symPtr(si), @tagName(class));
|
||||||
@ -1173,7 +1201,7 @@ fn renameSection(elf: *Elf, si: Symbol.Index, name: []const u8) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn linkSections(elf: *Elf, si: Symbol.Index, link_si: Symbol.Index) !void {
|
fn linkSections(elf: *Elf, si: Symbol.Index, link_si: Symbol.Index) !void {
|
||||||
const target_endian = elf.endian();
|
const target_endian = elf.targetEndian();
|
||||||
switch (elf.shdrSlice()) {
|
switch (elf.shdrSlice()) {
|
||||||
inline else => |shdr, class| {
|
inline else => |shdr, class| {
|
||||||
const sym = @field(elf.symPtr(si), @tagName(class));
|
const sym = @field(elf.symPtr(si), @tagName(class));
|
||||||
@ -1184,7 +1212,7 @@ fn linkSections(elf: *Elf, si: Symbol.Index, link_si: Symbol.Index) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn sectionName(elf: *Elf, si: Symbol.Index) [:0]const u8 {
|
fn sectionName(elf: *Elf, si: Symbol.Index) [:0]const u8 {
|
||||||
const target_endian = elf.endian();
|
const target_endian = elf.targetEndian();
|
||||||
const name = Symbol.Index.shstrtab.node(elf).slice(&elf.mf)[name: switch (elf.shdrSlice()) {
|
const name = Symbol.Index.shstrtab.node(elf).slice(&elf.mf)[name: switch (elf.shdrSlice()) {
|
||||||
inline else => |shndx, class| {
|
inline else => |shndx, class| {
|
||||||
const sym = @field(elf.symPtr(si), @tagName(class));
|
const sym = @field(elf.symPtr(si), @tagName(class));
|
||||||
@ -1263,7 +1291,8 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
|
|||||||
};
|
};
|
||||||
if (nav_init == .none or !Type.fromInterned(ip.typeOf(nav_init)).hasRuntimeBits(zcu)) return;
|
if (nav_init == .none or !Type.fromInterned(ip.typeOf(nav_init)).hasRuntimeBits(zcu)) return;
|
||||||
|
|
||||||
const si = try elf.navSymbol(zcu, nav_index);
|
const nmi = try elf.navMapIndex(zcu, nav_index);
|
||||||
|
const si = nmi.symbol(elf);
|
||||||
const ni = ni: {
|
const ni = ni: {
|
||||||
const sym = si.get(elf);
|
const sym = si.get(elf);
|
||||||
switch (sym.ni) {
|
switch (sym.ni) {
|
||||||
@ -1275,7 +1304,7 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
|
|||||||
.alignment = pt.navAlignment(nav_index).toStdMem(),
|
.alignment = pt.navAlignment(nav_index).toStdMem(),
|
||||||
.moved = true,
|
.moved = true,
|
||||||
});
|
});
|
||||||
elf.nodes.appendAssumeCapacity(.{ .nav = nav_index });
|
elf.nodes.appendAssumeCapacity(.{ .nav = nmi });
|
||||||
sym.ni = ni;
|
sym.ni = ni;
|
||||||
switch (elf.symPtr(si)) {
|
switch (elf.symPtr(si)) {
|
||||||
inline else => |sym_ptr, class| sym_ptr.shndx =
|
inline else => |sym_ptr, class| sym_ptr.shndx =
|
||||||
@ -1289,7 +1318,6 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
|
|||||||
break :ni sym.ni;
|
break :ni sym.ni;
|
||||||
};
|
};
|
||||||
|
|
||||||
const size = size: {
|
|
||||||
var nw: MappedFile.Node.Writer = undefined;
|
var nw: MappedFile.Node.Writer = undefined;
|
||||||
ni.writer(&elf.mf, gpa, &nw);
|
ni.writer(&elf.mf, gpa, &nw);
|
||||||
defer nw.deinit();
|
defer nw.deinit();
|
||||||
@ -1304,13 +1332,10 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
|
|||||||
error.WriteFailed => return error.OutOfMemory,
|
error.WriteFailed => return error.OutOfMemory,
|
||||||
else => |e| return e,
|
else => |e| return e,
|
||||||
};
|
};
|
||||||
break :size nw.interface.end;
|
const target_endian = elf.targetEndian();
|
||||||
};
|
|
||||||
|
|
||||||
const target_endian = elf.endian();
|
|
||||||
switch (elf.symPtr(si)) {
|
switch (elf.symPtr(si)) {
|
||||||
inline else => |sym| sym.size =
|
inline else => |sym| sym.size =
|
||||||
std.mem.nativeTo(@TypeOf(sym.size), @intCast(size), target_endian),
|
std.mem.nativeTo(@TypeOf(sym.size), @intCast(nw.interface.end), target_endian),
|
||||||
}
|
}
|
||||||
si.applyLocationRelocs(elf);
|
si.applyLocationRelocs(elf);
|
||||||
}
|
}
|
||||||
@ -1326,7 +1351,7 @@ pub fn lowerUav(
|
|||||||
const gpa = zcu.gpa;
|
const gpa = zcu.gpa;
|
||||||
|
|
||||||
try elf.pending_uavs.ensureUnusedCapacity(gpa, 1);
|
try elf.pending_uavs.ensureUnusedCapacity(gpa, 1);
|
||||||
const si = elf.uavSymbol(uav_val) catch |err| switch (err) {
|
const umi = elf.uavMapIndex(uav_val) catch |err| switch (err) {
|
||||||
error.OutOfMemory => return error.OutOfMemory,
|
error.OutOfMemory => return error.OutOfMemory,
|
||||||
else => |e| return .{ .fail = try Zcu.ErrorMsg.create(
|
else => |e| return .{ .fail = try Zcu.ErrorMsg.create(
|
||||||
gpa,
|
gpa,
|
||||||
@ -1335,11 +1360,12 @@ pub fn lowerUav(
|
|||||||
.{@errorName(e)},
|
.{@errorName(e)},
|
||||||
) },
|
) },
|
||||||
};
|
};
|
||||||
|
const si = umi.symbol(elf);
|
||||||
if (switch (si.get(elf).ni) {
|
if (switch (si.get(elf).ni) {
|
||||||
.none => true,
|
.none => true,
|
||||||
else => |ni| uav_align.toStdMem().order(ni.alignment(&elf.mf)).compare(.gt),
|
else => |ni| uav_align.toStdMem().order(ni.alignment(&elf.mf)).compare(.gt),
|
||||||
}) {
|
}) {
|
||||||
const gop = elf.pending_uavs.getOrPutAssumeCapacity(uav_val);
|
const gop = elf.pending_uavs.getOrPutAssumeCapacity(umi);
|
||||||
if (gop.found_existing) {
|
if (gop.found_existing) {
|
||||||
gop.value_ptr.alignment = gop.value_ptr.alignment.max(uav_align);
|
gop.value_ptr.alignment = gop.value_ptr.alignment.max(uav_align);
|
||||||
} else {
|
} else {
|
||||||
@ -1347,7 +1373,7 @@ pub fn lowerUav(
|
|||||||
.alignment = uav_align,
|
.alignment = uav_align,
|
||||||
.src_loc = src_loc,
|
.src_loc = src_loc,
|
||||||
};
|
};
|
||||||
elf.base.comp.link_uav_prog_node.increaseEstimatedTotalItems(1);
|
elf.base.comp.link_const_prog_node.increaseEstimatedTotalItems(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return .{ .sym_index = @intFromEnum(si) };
|
return .{ .sym_index = @intFromEnum(si) };
|
||||||
@ -1384,7 +1410,8 @@ fn updateFuncInner(
|
|||||||
const func = zcu.funcInfo(func_index);
|
const func = zcu.funcInfo(func_index);
|
||||||
const nav = ip.getNav(func.owner_nav);
|
const nav = ip.getNav(func.owner_nav);
|
||||||
|
|
||||||
const si = try elf.navSymbol(zcu, func.owner_nav);
|
const nmi = try elf.navMapIndex(zcu, func.owner_nav);
|
||||||
|
const si = nmi.symbol(elf);
|
||||||
log.debug("updateFunc({f}) = {d}", .{ nav.fqn.fmt(ip), si });
|
log.debug("updateFunc({f}) = {d}", .{ nav.fqn.fmt(ip), si });
|
||||||
const ni = ni: {
|
const ni = ni: {
|
||||||
const sym = si.get(elf);
|
const sym = si.get(elf);
|
||||||
@ -1406,7 +1433,7 @@ fn updateFuncInner(
|
|||||||
}.toStdMem(),
|
}.toStdMem(),
|
||||||
.moved = true,
|
.moved = true,
|
||||||
});
|
});
|
||||||
elf.nodes.appendAssumeCapacity(.{ .nav = func.owner_nav });
|
elf.nodes.appendAssumeCapacity(.{ .nav = nmi });
|
||||||
sym.ni = ni;
|
sym.ni = ni;
|
||||||
switch (elf.symPtr(si)) {
|
switch (elf.symPtr(si)) {
|
||||||
inline else => |sym_ptr, class| sym_ptr.shndx =
|
inline else => |sym_ptr, class| sym_ptr.shndx =
|
||||||
@ -1420,7 +1447,6 @@ fn updateFuncInner(
|
|||||||
break :ni sym.ni;
|
break :ni sym.ni;
|
||||||
};
|
};
|
||||||
|
|
||||||
const size = size: {
|
|
||||||
var nw: MappedFile.Node.Writer = undefined;
|
var nw: MappedFile.Node.Writer = undefined;
|
||||||
ni.writer(&elf.mf, gpa, &nw);
|
ni.writer(&elf.mf, gpa, &nw);
|
||||||
defer nw.deinit();
|
defer nw.deinit();
|
||||||
@ -1437,20 +1463,19 @@ fn updateFuncInner(
|
|||||||
error.WriteFailed => return nw.err.?,
|
error.WriteFailed => return nw.err.?,
|
||||||
else => |e| return e,
|
else => |e| return e,
|
||||||
};
|
};
|
||||||
break :size nw.interface.end;
|
const target_endian = elf.targetEndian();
|
||||||
};
|
|
||||||
|
|
||||||
const target_endian = elf.endian();
|
|
||||||
switch (elf.symPtr(si)) {
|
switch (elf.symPtr(si)) {
|
||||||
inline else => |sym| sym.size =
|
inline else => |sym| sym.size =
|
||||||
std.mem.nativeTo(@TypeOf(sym.size), @intCast(size), target_endian),
|
std.mem.nativeTo(@TypeOf(sym.size), @intCast(nw.interface.end), target_endian),
|
||||||
}
|
}
|
||||||
si.applyLocationRelocs(elf);
|
si.applyLocationRelocs(elf);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) !void {
|
pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) !void {
|
||||||
const si = elf.lazy.getPtr(.const_data).map.get(.anyerror_type) orelse return;
|
elf.flushLazy(pt, .{
|
||||||
elf.flushLazy(pt, .{ .kind = .const_data, .ty = .anyerror_type }, si) catch |err| switch (err) {
|
.kind = .const_data,
|
||||||
|
.index = @intCast(elf.lazy.getPtr(.const_data).map.getIndex(.anyerror_type) orelse return),
|
||||||
|
}) catch |err| switch (err) {
|
||||||
error.OutOfMemory => return error.OutOfMemory,
|
error.OutOfMemory => return error.OutOfMemory,
|
||||||
error.CodegenFail => return error.LinkFailure,
|
error.CodegenFail => return error.LinkFailure,
|
||||||
else => |e| return elf.base.comp.link_diags.fail("updateErrorData failed {t}", .{e}),
|
else => |e| return elf.base.comp.link_diags.fail("updateErrorData failed {t}", .{e}),
|
||||||
@ -1472,14 +1497,13 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) !bool {
|
|||||||
const comp = elf.base.comp;
|
const comp = elf.base.comp;
|
||||||
task: {
|
task: {
|
||||||
while (elf.pending_uavs.pop()) |pending_uav| {
|
while (elf.pending_uavs.pop()) |pending_uav| {
|
||||||
const sub_prog_node =
|
const sub_prog_node = elf.idleProgNode(
|
||||||
elf.idleProgNode(
|
|
||||||
tid,
|
tid,
|
||||||
comp.link_uav_prog_node,
|
comp.link_const_prog_node,
|
||||||
.{ .uav = pending_uav.key },
|
.{ .uav = pending_uav.key },
|
||||||
);
|
);
|
||||||
defer sub_prog_node.end();
|
defer sub_prog_node.end();
|
||||||
break :task elf.flushUav(
|
elf.flushUav(
|
||||||
.{ .zcu = elf.base.comp.zcu.?, .tid = tid },
|
.{ .zcu = elf.base.comp.zcu.?, .tid = tid },
|
||||||
pending_uav.key,
|
pending_uav.key,
|
||||||
pending_uav.value.alignment,
|
pending_uav.value.alignment,
|
||||||
@ -1491,37 +1515,34 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) !bool {
|
|||||||
.{e},
|
.{e},
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
break :task;
|
||||||
}
|
}
|
||||||
var lazy_it = elf.lazy.iterator();
|
var lazy_it = elf.lazy.iterator();
|
||||||
while (lazy_it.next()) |lazy| for (
|
while (lazy_it.next()) |lazy| if (lazy.value.pending_index < lazy.value.map.count()) {
|
||||||
lazy.value.map.keys()[lazy.value.pending_index..],
|
|
||||||
lazy.value.map.values()[lazy.value.pending_index..],
|
|
||||||
) |ty, si| {
|
|
||||||
lazy.value.pending_index += 1;
|
|
||||||
const pt: Zcu.PerThread = .{ .zcu = elf.base.comp.zcu.?, .tid = tid };
|
const pt: Zcu.PerThread = .{ .zcu = elf.base.comp.zcu.?, .tid = tid };
|
||||||
const kind = switch (lazy.key) {
|
const lmr: Node.LazyMapRef = .{ .kind = lazy.key, .index = lazy.value.pending_index };
|
||||||
|
lazy.value.pending_index += 1;
|
||||||
|
const kind = switch (lmr.kind) {
|
||||||
.code => "code",
|
.code => "code",
|
||||||
.const_data => "data",
|
.const_data => "data",
|
||||||
};
|
};
|
||||||
var name: [std.Progress.Node.max_name_len]u8 = undefined;
|
var name: [std.Progress.Node.max_name_len]u8 = undefined;
|
||||||
const sub_prog_node = comp.link_lazy_prog_node.start(
|
const sub_prog_node = comp.link_synth_prog_node.start(
|
||||||
std.fmt.bufPrint(&name, "lazy {s} for {f}", .{
|
std.fmt.bufPrint(&name, "lazy {s} for {f}", .{
|
||||||
kind,
|
kind,
|
||||||
Type.fromInterned(ty).fmt(pt),
|
Type.fromInterned(lmr.lazySymbol(elf).ty).fmt(pt),
|
||||||
}) catch &name,
|
}) catch &name,
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
defer sub_prog_node.end();
|
defer sub_prog_node.end();
|
||||||
break :task elf.flushLazy(pt, .{
|
elf.flushLazy(pt, lmr) catch |err| switch (err) {
|
||||||
.kind = lazy.key,
|
|
||||||
.ty = ty,
|
|
||||||
}, si) catch |err| switch (err) {
|
|
||||||
error.OutOfMemory => return error.OutOfMemory,
|
error.OutOfMemory => return error.OutOfMemory,
|
||||||
else => |e| return elf.base.comp.link_diags.fail(
|
else => |e| return elf.base.comp.link_diags.fail(
|
||||||
"linker failed to lower lazy {s}: {t}",
|
"linker failed to lower lazy {s}: {t}",
|
||||||
.{ kind, e },
|
.{ kind, e },
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
break :task;
|
||||||
};
|
};
|
||||||
while (elf.mf.updates.pop()) |ni| {
|
while (elf.mf.updates.pop()) |ni| {
|
||||||
const clean_moved = ni.cleanMoved(&elf.mf);
|
const clean_moved = ni.cleanMoved(&elf.mf);
|
||||||
@ -1551,12 +1572,12 @@ fn idleProgNode(
|
|||||||
return prog_node.start(name: switch (node) {
|
return prog_node.start(name: switch (node) {
|
||||||
else => |tag| @tagName(tag),
|
else => |tag| @tagName(tag),
|
||||||
.section => |si| elf.sectionName(si),
|
.section => |si| elf.sectionName(si),
|
||||||
.nav => |nav| {
|
.nav => |nmi| {
|
||||||
const ip = &elf.base.comp.zcu.?.intern_pool;
|
const ip = &elf.base.comp.zcu.?.intern_pool;
|
||||||
break :name ip.getNav(nav).fqn.toSlice(ip);
|
break :name ip.getNav(nmi.navIndex(elf)).fqn.toSlice(ip);
|
||||||
},
|
},
|
||||||
.uav => |uav| std.fmt.bufPrint(&name, "{f}", .{
|
.uav => |umi| std.fmt.bufPrint(&name, "{f}", .{
|
||||||
Value.fromInterned(uav).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
|
Value.fromInterned(umi.uavValue(elf)).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }),
|
||||||
}) catch &name,
|
}) catch &name,
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
@ -1564,14 +1585,15 @@ fn idleProgNode(
|
|||||||
fn flushUav(
|
fn flushUav(
|
||||||
elf: *Elf,
|
elf: *Elf,
|
||||||
pt: Zcu.PerThread,
|
pt: Zcu.PerThread,
|
||||||
uav_val: InternPool.Index,
|
umi: Node.UavMapIndex,
|
||||||
uav_align: InternPool.Alignment,
|
uav_align: InternPool.Alignment,
|
||||||
src_loc: Zcu.LazySrcLoc,
|
src_loc: Zcu.LazySrcLoc,
|
||||||
) !void {
|
) !void {
|
||||||
const zcu = pt.zcu;
|
const zcu = pt.zcu;
|
||||||
const gpa = zcu.gpa;
|
const gpa = zcu.gpa;
|
||||||
|
|
||||||
const si = try elf.uavSymbol(uav_val);
|
const uav_val = umi.uavValue(elf);
|
||||||
|
const si = umi.symbol(elf);
|
||||||
const ni = ni: {
|
const ni = ni: {
|
||||||
const sym = si.get(elf);
|
const sym = si.get(elf);
|
||||||
switch (sym.ni) {
|
switch (sym.ni) {
|
||||||
@ -1581,7 +1603,7 @@ fn flushUav(
|
|||||||
.alignment = uav_align.toStdMem(),
|
.alignment = uav_align.toStdMem(),
|
||||||
.moved = true,
|
.moved = true,
|
||||||
});
|
});
|
||||||
elf.nodes.appendAssumeCapacity(.{ .uav = uav_val });
|
elf.nodes.appendAssumeCapacity(.{ .uav = umi });
|
||||||
sym.ni = ni;
|
sym.ni = ni;
|
||||||
switch (elf.symPtr(si)) {
|
switch (elf.symPtr(si)) {
|
||||||
inline else => |sym_ptr, class| sym_ptr.shndx =
|
inline else => |sym_ptr, class| sym_ptr.shndx =
|
||||||
@ -1598,7 +1620,6 @@ fn flushUav(
|
|||||||
break :ni sym.ni;
|
break :ni sym.ni;
|
||||||
};
|
};
|
||||||
|
|
||||||
const size = size: {
|
|
||||||
var nw: MappedFile.Node.Writer = undefined;
|
var nw: MappedFile.Node.Writer = undefined;
|
||||||
ni.writer(&elf.mf, gpa, &nw);
|
ni.writer(&elf.mf, gpa, &nw);
|
||||||
defer nw.deinit();
|
defer nw.deinit();
|
||||||
@ -1613,21 +1634,20 @@ fn flushUav(
|
|||||||
error.WriteFailed => return error.OutOfMemory,
|
error.WriteFailed => return error.OutOfMemory,
|
||||||
else => |e| return e,
|
else => |e| return e,
|
||||||
};
|
};
|
||||||
break :size nw.interface.end;
|
const target_endian = elf.targetEndian();
|
||||||
};
|
|
||||||
|
|
||||||
const target_endian = elf.endian();
|
|
||||||
switch (elf.symPtr(si)) {
|
switch (elf.symPtr(si)) {
|
||||||
inline else => |sym| sym.size =
|
inline else => |sym| sym.size =
|
||||||
std.mem.nativeTo(@TypeOf(sym.size), @intCast(size), target_endian),
|
std.mem.nativeTo(@TypeOf(sym.size), @intCast(nw.interface.end), target_endian),
|
||||||
}
|
}
|
||||||
si.applyLocationRelocs(elf);
|
si.applyLocationRelocs(elf);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lazy: link.File.LazySymbol, si: Symbol.Index) !void {
|
fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) !void {
|
||||||
const zcu = pt.zcu;
|
const zcu = pt.zcu;
|
||||||
const gpa = zcu.gpa;
|
const gpa = zcu.gpa;
|
||||||
|
|
||||||
|
const lazy = lmr.lazySymbol(elf);
|
||||||
|
const si = lmr.symbol(elf);
|
||||||
const ni = ni: {
|
const ni = ni: {
|
||||||
const sym = si.get(elf);
|
const sym = si.get(elf);
|
||||||
switch (sym.ni) {
|
switch (sym.ni) {
|
||||||
@ -1639,8 +1659,8 @@ fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lazy: link.File.LazySymbol, si: Symbo
|
|||||||
};
|
};
|
||||||
const ni = try elf.mf.addLastChildNode(gpa, sec_si.node(elf), .{ .moved = true });
|
const ni = try elf.mf.addLastChildNode(gpa, sec_si.node(elf), .{ .moved = true });
|
||||||
elf.nodes.appendAssumeCapacity(switch (lazy.kind) {
|
elf.nodes.appendAssumeCapacity(switch (lazy.kind) {
|
||||||
.code => .{ .lazy_code = lazy.ty },
|
.code => .{ .lazy_code = @enumFromInt(lmr.index) },
|
||||||
.const_data => .{ .lazy_const_data = lazy.ty },
|
.const_data => .{ .lazy_const_data = @enumFromInt(lmr.index) },
|
||||||
});
|
});
|
||||||
sym.ni = ni;
|
sym.ni = ni;
|
||||||
switch (elf.symPtr(si)) {
|
switch (elf.symPtr(si)) {
|
||||||
@ -1655,7 +1675,6 @@ fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lazy: link.File.LazySymbol, si: Symbo
|
|||||||
break :ni sym.ni;
|
break :ni sym.ni;
|
||||||
};
|
};
|
||||||
|
|
||||||
const size = size: {
|
|
||||||
var required_alignment: InternPool.Alignment = .none;
|
var required_alignment: InternPool.Alignment = .none;
|
||||||
var nw: MappedFile.Node.Writer = undefined;
|
var nw: MappedFile.Node.Writer = undefined;
|
||||||
ni.writer(&elf.mf, gpa, &nw);
|
ni.writer(&elf.mf, gpa, &nw);
|
||||||
@ -1670,19 +1689,16 @@ fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lazy: link.File.LazySymbol, si: Symbo
|
|||||||
.none,
|
.none,
|
||||||
.{ .atom_index = @intFromEnum(si) },
|
.{ .atom_index = @intFromEnum(si) },
|
||||||
);
|
);
|
||||||
break :size nw.interface.end;
|
const target_endian = elf.targetEndian();
|
||||||
};
|
|
||||||
|
|
||||||
const target_endian = elf.endian();
|
|
||||||
switch (elf.symPtr(si)) {
|
switch (elf.symPtr(si)) {
|
||||||
inline else => |sym| sym.size =
|
inline else => |sym| sym.size =
|
||||||
std.mem.nativeTo(@TypeOf(sym.size), @intCast(size), target_endian),
|
std.mem.nativeTo(@TypeOf(sym.size), @intCast(nw.interface.end), target_endian),
|
||||||
}
|
}
|
||||||
si.applyLocationRelocs(elf);
|
si.applyLocationRelocs(elf);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {
|
fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {
|
||||||
const target_endian = elf.endian();
|
const target_endian = elf.targetEndian();
|
||||||
const file_offset = ni.fileLocation(&elf.mf, false).offset;
|
const file_offset = ni.fileLocation(&elf.mf, false).offset;
|
||||||
const node = elf.getNode(ni);
|
const node = elf.getNode(ni);
|
||||||
switch (node) {
|
switch (node) {
|
||||||
@ -1738,11 +1754,8 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {
|
|||||||
.nav, .uav, .lazy_code, .lazy_const_data => {
|
.nav, .uav, .lazy_code, .lazy_const_data => {
|
||||||
const si = switch (node) {
|
const si = switch (node) {
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
.nav => |nav| elf.navs.get(nav),
|
inline .nav, .uav, .lazy_code, .lazy_const_data => |mi| mi.symbol(elf),
|
||||||
.uav => |uav| elf.uavs.get(uav),
|
};
|
||||||
.lazy_code => |ty| elf.lazy.getPtr(.code).map.get(ty),
|
|
||||||
.lazy_const_data => |ty| elf.lazy.getPtr(.const_data).map.get(ty),
|
|
||||||
}.?;
|
|
||||||
switch (elf.shdrSlice()) {
|
switch (elf.shdrSlice()) {
|
||||||
inline else => |shdr, class| {
|
inline else => |shdr, class| {
|
||||||
const sym = @field(elf.symPtr(si), @tagName(class));
|
const sym = @field(elf.symPtr(si), @tagName(class));
|
||||||
@ -1773,7 +1786,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void {
|
fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void {
|
||||||
const target_endian = elf.endian();
|
const target_endian = elf.targetEndian();
|
||||||
_, const size = ni.location(&elf.mf).resolve(&elf.mf);
|
_, const size = ni.location(&elf.mf).resolve(&elf.mf);
|
||||||
const node = elf.getNode(ni);
|
const node = elf.getNode(ni);
|
||||||
switch (node) {
|
switch (node) {
|
||||||
@ -1957,31 +1970,38 @@ pub fn printNode(
|
|||||||
indent: usize,
|
indent: usize,
|
||||||
) !void {
|
) !void {
|
||||||
const node = elf.getNode(ni);
|
const node = elf.getNode(ni);
|
||||||
const mf_node = &elf.mf.nodes.items[@intFromEnum(ni)];
|
|
||||||
const off, const size = mf_node.location().resolve(&elf.mf);
|
|
||||||
try w.splatByteAll(' ', indent);
|
try w.splatByteAll(' ', indent);
|
||||||
try w.writeAll(@tagName(node));
|
try w.writeAll(@tagName(node));
|
||||||
switch (node) {
|
switch (node) {
|
||||||
else => {},
|
else => {},
|
||||||
.section => |si| try w.print("({s})", .{elf.sectionName(si)}),
|
.section => |si| try w.print("({s})", .{elf.sectionName(si)}),
|
||||||
.nav => |nav_index| {
|
.nav => |nmi| {
|
||||||
const zcu = elf.base.comp.zcu.?;
|
const zcu = elf.base.comp.zcu.?;
|
||||||
const ip = &zcu.intern_pool;
|
const ip = &zcu.intern_pool;
|
||||||
const nav = ip.getNav(nav_index);
|
const nav = ip.getNav(nmi.navIndex(elf));
|
||||||
try w.print("({f}, {f})", .{
|
try w.print("({f}, {f})", .{
|
||||||
Type.fromInterned(nav.typeOf(ip)).fmt(.{ .zcu = zcu, .tid = tid }),
|
Type.fromInterned(nav.typeOf(ip)).fmt(.{ .zcu = zcu, .tid = tid }),
|
||||||
nav.fqn.fmt(ip),
|
nav.fqn.fmt(ip),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.uav => |uav| {
|
.uav => |umi| {
|
||||||
const zcu = elf.base.comp.zcu.?;
|
const zcu = elf.base.comp.zcu.?;
|
||||||
const val: Value = .fromInterned(uav);
|
const val: Value = .fromInterned(umi.uavValue(elf));
|
||||||
try w.print("({f}, {f})", .{
|
try w.print("({f}, {f})", .{
|
||||||
val.typeOf(zcu).fmt(.{ .zcu = zcu, .tid = tid }),
|
val.typeOf(zcu).fmt(.{ .zcu = zcu, .tid = tid }),
|
||||||
val.fmtValue(.{ .zcu = zcu, .tid = tid }),
|
val.fmtValue(.{ .zcu = zcu, .tid = tid }),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
inline .lazy_code, .lazy_const_data => |lmi| try w.print("({f})", .{
|
||||||
|
Type.fromInterned(lmi.lazySymbol(elf).ty).fmt(.{
|
||||||
|
.zcu = elf.base.comp.zcu.?,
|
||||||
|
.tid = tid,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
const mf_node = &elf.mf.nodes.items[@intFromEnum(ni)];
|
||||||
|
const off, const size = mf_node.location().resolve(&elf.mf);
|
||||||
try w.print(" index={d} offset=0x{x} size=0x{x} align=0x{x}{s}{s}{s}{s}\n", .{
|
try w.print(" index={d} offset=0x{x} size=0x{x} align=0x{x}{s}{s}{s}{s}\n", .{
|
||||||
@intFromEnum(ni),
|
@intFromEnum(ni),
|
||||||
off,
|
off,
|
||||||
@ -1992,9 +2012,14 @@ pub fn printNode(
|
|||||||
if (mf_node.flags.resized) " resized" else "",
|
if (mf_node.flags.resized) " resized" else "",
|
||||||
if (mf_node.flags.has_content) " has_content" else "",
|
if (mf_node.flags.has_content) " has_content" else "",
|
||||||
});
|
});
|
||||||
var child_ni = mf_node.first;
|
}
|
||||||
switch (child_ni) {
|
var leaf = true;
|
||||||
.none => {
|
var child_it = ni.children(&elf.mf);
|
||||||
|
while (child_it.next()) |child_ni| {
|
||||||
|
leaf = false;
|
||||||
|
try elf.printNode(tid, w, child_ni, indent + 1);
|
||||||
|
}
|
||||||
|
if (leaf) {
|
||||||
const file_loc = ni.fileLocation(&elf.mf, false);
|
const file_loc = ni.fileLocation(&elf.mf, false);
|
||||||
if (file_loc.size == 0) return;
|
if (file_loc.size == 0) return;
|
||||||
var address = file_loc.offset;
|
var address = file_loc.offset;
|
||||||
@ -2007,15 +2032,12 @@ pub fn printNode(
|
|||||||
);
|
);
|
||||||
while (line_it.next()) |line_bytes| : (address += line_len) {
|
while (line_it.next()) |line_bytes| : (address += line_len) {
|
||||||
try w.splatByteAll(' ', indent + 1);
|
try w.splatByteAll(' ', indent + 1);
|
||||||
try w.print("{x:0>8}", .{address});
|
try w.print("{x:0>8} ", .{address});
|
||||||
for (line_bytes) |byte| try w.print(" {x:0>2}", .{byte});
|
for (line_bytes) |byte| try w.print("{x:0>2} ", .{byte});
|
||||||
|
try w.splatByteAll(' ', 3 * (line_len - line_bytes.len) + 1);
|
||||||
|
for (line_bytes) |byte| try w.writeByte(if (std.ascii.isPrint(byte)) byte else '.');
|
||||||
try w.writeByte('\n');
|
try w.writeByte('\n');
|
||||||
}
|
}
|
||||||
},
|
|
||||||
else => while (child_ni != .none) {
|
|
||||||
try elf.printNode(tid, w, child_ni, indent + 1);
|
|
||||||
child_ni = elf.mf.nodes.items[@intFromEnum(child_ni)].next;
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -34,17 +34,28 @@ pub fn init(file: std.fs.File, gpa: std.mem.Allocator) !MappedFile {
|
|||||||
.writers = .{},
|
.writers = .{},
|
||||||
};
|
};
|
||||||
errdefer mf.deinit(gpa);
|
errdefer mf.deinit(gpa);
|
||||||
const size: u64, const blksize = if (is_windows)
|
const size: u64, const block_size = stat: {
|
||||||
.{ try windows.GetFileSizeEx(file.handle), 1 }
|
if (is_windows) {
|
||||||
else stat: {
|
var sbi: windows.SYSTEM_BASIC_INFORMATION = undefined;
|
||||||
|
break :stat .{
|
||||||
|
try windows.GetFileSizeEx(file.handle),
|
||||||
|
switch (windows.ntdll.NtQuerySystemInformation(
|
||||||
|
.SystemBasicInformation,
|
||||||
|
&sbi,
|
||||||
|
@sizeOf(windows.SYSTEM_BASIC_INFORMATION),
|
||||||
|
null,
|
||||||
|
)) {
|
||||||
|
.SUCCESS => @max(sbi.PageSize, sbi.AllocationGranularity),
|
||||||
|
else => std.heap.page_size_max,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
const stat = try std.posix.fstat(mf.file.handle);
|
const stat = try std.posix.fstat(mf.file.handle);
|
||||||
if (!std.posix.S.ISREG(stat.mode)) return error.PathAlreadyExists;
|
if (!std.posix.S.ISREG(stat.mode)) return error.PathAlreadyExists;
|
||||||
break :stat .{ @bitCast(stat.size), stat.blksize };
|
break :stat .{ @bitCast(stat.size), @max(std.heap.pageSize(), stat.blksize) };
|
||||||
};
|
};
|
||||||
mf.flags = .{
|
mf.flags = .{
|
||||||
.block_size = .fromByteUnits(
|
.block_size = .fromByteUnits(std.math.ceilPowerOfTwoAssert(usize, block_size)),
|
||||||
std.math.ceilPowerOfTwoAssert(usize, @max(std.heap.pageSize(), blksize)),
|
|
||||||
),
|
|
||||||
.copy_file_range_unsupported = false,
|
.copy_file_range_unsupported = false,
|
||||||
.fallocate_insert_range_unsupported = false,
|
.fallocate_insert_range_unsupported = false,
|
||||||
.fallocate_punch_hole_unsupported = false,
|
.fallocate_punch_hole_unsupported = false,
|
||||||
@ -90,9 +101,11 @@ pub const Node = extern struct {
|
|||||||
resized: bool,
|
resized: bool,
|
||||||
/// Whether this node might contain non-zero bytes.
|
/// Whether this node might contain non-zero bytes.
|
||||||
has_content: bool,
|
has_content: bool,
|
||||||
|
/// Whether a moved event on this node bubbles down to children.
|
||||||
|
bubbles_moved: bool,
|
||||||
unused: @Type(.{ .int = .{
|
unused: @Type(.{ .int = .{
|
||||||
.signedness = .unsigned,
|
.signedness = .unsigned,
|
||||||
.bits = 32 - @bitSizeOf(std.mem.Alignment) - 5,
|
.bits = 32 - @bitSizeOf(std.mem.Alignment) - 6,
|
||||||
} }) = 0,
|
} }) = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -136,6 +149,25 @@ pub const Node = extern struct {
|
|||||||
return &mf.nodes.items[@intFromEnum(ni)];
|
return &mf.nodes.items[@intFromEnum(ni)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parent(ni: Node.Index, mf: *const MappedFile) Node.Index {
|
||||||
|
return ni.get(mf).parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const ChildIterator = struct {
|
||||||
|
mf: *const MappedFile,
|
||||||
|
ni: Node.Index,
|
||||||
|
|
||||||
|
pub fn next(it: *ChildIterator) ?Node.Index {
|
||||||
|
const ni = it.ni;
|
||||||
|
if (ni == .none) return null;
|
||||||
|
it.ni = ni.get(it.mf).next;
|
||||||
|
return ni;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pub fn children(ni: Node.Index, mf: *const MappedFile) ChildIterator {
|
||||||
|
return .{ .mf = mf, .ni = ni.get(mf).first };
|
||||||
|
}
|
||||||
|
|
||||||
pub fn childrenMoved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) !void {
|
pub fn childrenMoved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) !void {
|
||||||
var child_ni = ni.get(mf).last;
|
var child_ni = ni.get(mf).last;
|
||||||
while (child_ni != .none) {
|
while (child_ni != .none) {
|
||||||
@ -147,9 +179,10 @@ pub const Node = extern struct {
|
|||||||
pub fn hasMoved(ni: Node.Index, mf: *const MappedFile) bool {
|
pub fn hasMoved(ni: Node.Index, mf: *const MappedFile) bool {
|
||||||
var parent_ni = ni;
|
var parent_ni = ni;
|
||||||
while (parent_ni != Node.Index.root) {
|
while (parent_ni != Node.Index.root) {
|
||||||
const parent = parent_ni.get(mf);
|
const parent_node = parent_ni.get(mf);
|
||||||
if (parent.flags.moved) return true;
|
if (!parent_node.flags.bubbles_moved) break;
|
||||||
parent_ni = parent.parent;
|
if (parent_node.flags.moved) return true;
|
||||||
|
parent_ni = parent_node.parent;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -163,12 +196,7 @@ pub const Node = extern struct {
|
|||||||
return node_moved.*;
|
return node_moved.*;
|
||||||
}
|
}
|
||||||
fn movedAssumeCapacity(ni: Node.Index, mf: *MappedFile) void {
|
fn movedAssumeCapacity(ni: Node.Index, mf: *MappedFile) void {
|
||||||
var parent_ni = ni;
|
if (ni.hasMoved(mf)) return;
|
||||||
while (parent_ni != Node.Index.root) {
|
|
||||||
const parent_node = parent_ni.get(mf);
|
|
||||||
if (parent_node.flags.moved) return;
|
|
||||||
parent_ni = parent_node.parent;
|
|
||||||
}
|
|
||||||
const node = ni.get(mf);
|
const node = ni.get(mf);
|
||||||
node.flags.moved = true;
|
node.flags.moved = true;
|
||||||
if (node.flags.resized) return;
|
if (node.flags.resized) return;
|
||||||
@ -242,10 +270,10 @@ pub const Node = extern struct {
|
|||||||
var offset, const size = ni.location(mf).resolve(mf);
|
var offset, const size = ni.location(mf).resolve(mf);
|
||||||
var parent_ni = ni;
|
var parent_ni = ni;
|
||||||
while (true) {
|
while (true) {
|
||||||
const parent = parent_ni.get(mf);
|
const parent_node = parent_ni.get(mf);
|
||||||
if (set_has_content) parent.flags.has_content = true;
|
if (set_has_content) parent_node.flags.has_content = true;
|
||||||
if (parent_ni == .none) break;
|
if (parent_ni == .none) break;
|
||||||
parent_ni = parent.parent;
|
parent_ni = parent_node.parent;
|
||||||
offset += parent_ni.location(mf).resolve(mf)[0];
|
offset += parent_ni.location(mf).resolve(mf)[0];
|
||||||
}
|
}
|
||||||
return .{ .offset = offset, .size = size };
|
return .{ .offset = offset, .size = size };
|
||||||
@ -449,6 +477,7 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
|
|||||||
.moved = true,
|
.moved = true,
|
||||||
.resized = true,
|
.resized = true,
|
||||||
.has_content = false,
|
.has_content = false,
|
||||||
|
.bubbles_moved = opts.add_node.bubbles_moved,
|
||||||
},
|
},
|
||||||
.location_payload = location_payload,
|
.location_payload = location_payload,
|
||||||
};
|
};
|
||||||
@ -471,6 +500,7 @@ pub const AddNodeOptions = struct {
|
|||||||
fixed: bool = false,
|
fixed: bool = false,
|
||||||
moved: bool = false,
|
moved: bool = false,
|
||||||
resized: bool = false,
|
resized: bool = false,
|
||||||
|
bubbles_moved: bool = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn addOnlyChildNode(
|
pub fn addOnlyChildNode(
|
||||||
|
|||||||
@ -233,7 +233,7 @@ pub fn hasLldSupport(ofmt: std.Target.ObjectFormat) bool {
|
|||||||
|
|
||||||
pub fn hasNewLinkerSupport(ofmt: std.Target.ObjectFormat, backend: std.builtin.CompilerBackend) bool {
|
pub fn hasNewLinkerSupport(ofmt: std.Target.ObjectFormat, backend: std.builtin.CompilerBackend) bool {
|
||||||
return switch (ofmt) {
|
return switch (ofmt) {
|
||||||
.elf => switch (backend) {
|
.elf, .coff => switch (backend) {
|
||||||
.stage2_x86_64 => true,
|
.stage2_x86_64 => true,
|
||||||
else => false,
|
else => false,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1650,7 +1650,6 @@ test "coerce between pointers of compatible differently-named floats" {
|
|||||||
if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows and !builtin.link_libc) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows and !builtin.link_libc) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
|
|
||||||
if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
|
if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
|
||||||
@ -2883,7 +2882,6 @@ test "@intFromFloat vector boundary cases" {
|
|||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
|
||||||
|
|
||||||
const S = struct {
|
const S = struct {
|
||||||
fn case(comptime I: type, unshifted_inputs: [2]f32, expected: [2]I) !void {
|
fn case(comptime I: type, unshifted_inputs: [2]f32, expected: [2]I) !void {
|
||||||
|
|||||||
@ -43,7 +43,6 @@ export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test "export function alias" {
|
test "export function alias" {
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
|
|
||||||
_ = struct {
|
_ = struct {
|
||||||
|
|||||||
@ -16,7 +16,6 @@ export var a_mystery_symbol: i32 = 1234;
|
|||||||
|
|
||||||
test "function extern symbol" {
|
test "function extern symbol" {
|
||||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
|
|
||||||
const a = @extern(*const fn () callconv(.c) i32, .{ .name = "a_mystery_function" });
|
const a = @extern(*const fn () callconv(.c) i32, .{ .name = "a_mystery_function" });
|
||||||
@ -29,7 +28,6 @@ export fn a_mystery_function() i32 {
|
|||||||
|
|
||||||
test "function extern symbol matches extern decl" {
|
test "function extern symbol matches extern decl" {
|
||||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
|
|
||||||
const S = struct {
|
const S = struct {
|
||||||
|
|||||||
@ -158,7 +158,6 @@ test "cmp f80/c_longdouble" {
|
|||||||
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try testCmp(f80);
|
try testCmp(f80);
|
||||||
try comptime testCmp(f80);
|
try comptime testCmp(f80);
|
||||||
@ -283,7 +282,6 @@ test "vector cmp f80/c_longdouble" {
|
|||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try testCmpVector(f80);
|
try testCmpVector(f80);
|
||||||
try comptime testCmpVector(f80);
|
try comptime testCmpVector(f80);
|
||||||
@ -396,7 +394,6 @@ test "@sqrt f80/f128/c_longdouble" {
|
|||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
|
|
||||||
if (builtin.os.tag == .freebsd) {
|
if (builtin.os.tag == .freebsd) {
|
||||||
// TODO https://github.com/ziglang/zig/issues/10875
|
// TODO https://github.com/ziglang/zig/issues/10875
|
||||||
@ -526,7 +523,6 @@ test "@sin f80/f128/c_longdouble" {
|
|||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try testSin(f80);
|
try testSin(f80);
|
||||||
comptime try testSin(f80);
|
comptime try testSin(f80);
|
||||||
@ -596,7 +592,6 @@ test "@cos f80/f128/c_longdouble" {
|
|||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try testCos(f80);
|
try testCos(f80);
|
||||||
try comptime testCos(f80);
|
try comptime testCos(f80);
|
||||||
@ -666,7 +661,6 @@ test "@tan f80/f128/c_longdouble" {
|
|||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try testTan(f80);
|
try testTan(f80);
|
||||||
try comptime testTan(f80);
|
try comptime testTan(f80);
|
||||||
@ -736,7 +730,6 @@ test "@exp f80/f128/c_longdouble" {
|
|||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try testExp(f80);
|
try testExp(f80);
|
||||||
try comptime testExp(f80);
|
try comptime testExp(f80);
|
||||||
@ -810,7 +803,6 @@ test "@exp2 f80/f128/c_longdouble" {
|
|||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try testExp2(f80);
|
try testExp2(f80);
|
||||||
try comptime testExp2(f80);
|
try comptime testExp2(f80);
|
||||||
@ -879,7 +871,6 @@ test "@log f80/f128/c_longdouble" {
|
|||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try testLog(f80);
|
try testLog(f80);
|
||||||
try comptime testLog(f80);
|
try comptime testLog(f80);
|
||||||
@ -946,7 +937,6 @@ test "@log2 f80/f128/c_longdouble" {
|
|||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try testLog2(f80);
|
try testLog2(f80);
|
||||||
try comptime testLog2(f80);
|
try comptime testLog2(f80);
|
||||||
@ -1019,7 +1009,6 @@ test "@log10 f80/f128/c_longdouble" {
|
|||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try testLog10(f80);
|
try testLog10(f80);
|
||||||
try comptime testLog10(f80);
|
try comptime testLog10(f80);
|
||||||
@ -1086,7 +1075,6 @@ test "@abs f80/f128/c_longdouble" {
|
|||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try testFabs(f80);
|
try testFabs(f80);
|
||||||
try comptime testFabs(f80);
|
try comptime testFabs(f80);
|
||||||
@ -1204,7 +1192,6 @@ test "@floor f80/f128/c_longdouble" {
|
|||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
|
|
||||||
@ -1295,7 +1282,6 @@ test "@ceil f80/f128/c_longdouble" {
|
|||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
|
|
||||||
@ -1388,7 +1374,6 @@ test "@trunc f80/f128/c_longdouble" {
|
|||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
|
|
||||||
if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
|
if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
|
||||||
// https://github.com/ziglang/zig/issues/12602
|
// https://github.com/ziglang/zig/issues/12602
|
||||||
@ -1485,7 +1470,6 @@ test "neg f80/f128/c_longdouble" {
|
|||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try testNeg(f80);
|
try testNeg(f80);
|
||||||
try comptime testNeg(f80);
|
try comptime testNeg(f80);
|
||||||
@ -1741,7 +1725,6 @@ test "comptime calls are only memoized when float arguments are bit-for-bit equa
|
|||||||
test "result location forwarded through unary float builtins" {
|
test "result location forwarded through unary float builtins" {
|
||||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,6 @@ test "import c keywords" {
|
|||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
|
|
||||||
try std.testing.expect(int == .c_keyword_variable);
|
try std.testing.expect(int == .c_keyword_variable);
|
||||||
|
|||||||
@ -1416,7 +1416,6 @@ test "remainder division" {
|
|||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
|
||||||
if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
|
|
||||||
@ -1425,6 +1424,8 @@ test "remainder division" {
|
|||||||
return error.SkipZigTest;
|
return error.SkipZigTest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest;
|
||||||
|
|
||||||
try comptime remdiv(f16);
|
try comptime remdiv(f16);
|
||||||
try comptime remdiv(f32);
|
try comptime remdiv(f32);
|
||||||
try comptime remdiv(f64);
|
try comptime remdiv(f64);
|
||||||
@ -1496,9 +1497,10 @@ test "float modulo division using @mod" {
|
|||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
|
|
||||||
|
if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest;
|
||||||
|
|
||||||
try comptime fmod(f16);
|
try comptime fmod(f16);
|
||||||
try comptime fmod(f32);
|
try comptime fmod(f32);
|
||||||
try comptime fmod(f64);
|
try comptime fmod(f64);
|
||||||
@ -1686,7 +1688,6 @@ test "signed zeros are represented properly" {
|
|||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
|
|
||||||
const S = struct {
|
const S = struct {
|
||||||
fn doTheTest() !void {
|
fn doTheTest() !void {
|
||||||
@ -1824,7 +1825,8 @@ test "float divide by zero" {
|
|||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
|
|
||||||
|
if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest;
|
||||||
|
|
||||||
const S = struct {
|
const S = struct {
|
||||||
fn doTheTest(comptime F: type, zero: F, one: F) !void {
|
fn doTheTest(comptime F: type, zero: F, one: F) !void {
|
||||||
|
|||||||
@ -14,7 +14,6 @@ test "call extern function defined with conflicting type" {
|
|||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff) return error.SkipZigTest;
|
|
||||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||||
|
|
||||||
@import("conflicting_externs/a.zig").issue529(null);
|
@import("conflicting_externs/a.zig").issue529(null);
|
||||||
|
|||||||
@ -5172,15 +5172,6 @@ test mulSaturate {
|
|||||||
try test_mul_saturate.testIntVectors();
|
try test_mul_saturate.testIntVectors();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn multiply(comptime Type: type, lhs: Type, rhs: Type) Type {
|
|
||||||
return lhs * rhs;
|
|
||||||
}
|
|
||||||
test multiply {
|
|
||||||
const test_multiply = binary(multiply, .{});
|
|
||||||
try test_multiply.testFloats();
|
|
||||||
try test_multiply.testFloatVectors();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fn divide(comptime Type: type, lhs: Type, rhs: Type) Type {
|
inline fn divide(comptime Type: type, lhs: Type, rhs: Type) Type {
|
||||||
return lhs / rhs;
|
return lhs / rhs;
|
||||||
}
|
}
|
||||||
@ -5264,7 +5255,8 @@ inline fn mod(comptime Type: type, lhs: Type, rhs: Type) Type {
|
|||||||
return @mod(lhs, rhs);
|
return @mod(lhs, rhs);
|
||||||
}
|
}
|
||||||
test mod {
|
test mod {
|
||||||
if (@import("builtin").object_format == .coff) return error.SkipZigTest;
|
const builtin = @import("builtin");
|
||||||
|
if (builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest;
|
||||||
const test_mod = binary(mod, .{});
|
const test_mod = binary(mod, .{});
|
||||||
try test_mod.testInts();
|
try test_mod.testInts();
|
||||||
try test_mod.testIntVectors();
|
try test_mod.testIntVectors();
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
//#target=wasm32-wasi-selfhosted
|
//#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
//#target=wasm32-wasi-selfhosted
|
//#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#update=initial version
|
#update=initial version
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
#update=initial version
|
#update=initial version
|
||||||
#file=main.zig
|
#file=main.zig
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
#update=initial version
|
#update=initial version
|
||||||
#file=main.zig
|
#file=main.zig
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#update=initial version
|
#update=initial version
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#update=initial version
|
#update=initial version
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
//#target=wasm32-wasi-selfhosted
|
//#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
//#target=wasm32-wasi-selfhosted
|
//#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#update=non-inline version
|
#update=non-inline version
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
//#target=wasm32-wasi-selfhosted
|
//#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#target=x86_64-linux-selfhosted
|
#target=x86_64-linux-selfhosted
|
||||||
|
#target=x86_64-windows-selfhosted
|
||||||
#target=x86_64-linux-cbe
|
#target=x86_64-linux-cbe
|
||||||
#target=x86_64-windows-cbe
|
#target=x86_64-windows-cbe
|
||||||
#target=wasm32-wasi-selfhosted
|
#target=wasm32-wasi-selfhosted
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user