authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-28 19:41:07+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-10-28 19:41:07+02:00
log13c7aa5fefef9b1338951cf0d01c04345201d996
tree4fd2509ed8a88870a02b655cc29dec77ec0a9f6c
parentd817a3c5173a4f9e41c5872e58733287c9686018
parent12b5c8156a2ce9c2ef1e5e71a19e86d4876fd457
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

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

x86_64+elf: do not pass hardcoded memory addresses in prep for build-obj

18 files changed, 853 insertions(+), 629 deletions(-)

lib/compiler_rt/tan.zig-2
...@@ -144,8 +144,6 @@ test "tan32" {...@@ -144,8 +144,6 @@ test "tan32" {
144}144}
145145
146test "tan64" {146test "tan64" {
147 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
148
149 const epsilon = 0.000001;147 const epsilon = 0.000001;
150148
151 try expect(math.approxEqAbs(f64, tan(0.0), 0.0, epsilon));149 try expect(math.approxEqAbs(f64, tan(0.0), 0.0, epsilon));
lib/std/atomic/Atomic.zig-2
...@@ -374,8 +374,6 @@ const atomic_rmw_orderings = [_]Ordering{...@@ -374,8 +374,6 @@ const atomic_rmw_orderings = [_]Ordering{
374};374};
375375
376test "Atomic.swap" {376test "Atomic.swap" {
377 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
378
379 inline for (atomic_rmw_orderings) |ordering| {377 inline for (atomic_rmw_orderings) |ordering| {
380 var x = Atomic(usize).init(5);378 var x = Atomic(usize).init(5);
381 try testing.expectEqual(x.swap(10, ordering), 5);379 try testing.expectEqual(x.swap(10, ordering), 5);
lib/std/debug.zig-2
...@@ -2513,8 +2513,6 @@ pub fn dumpStackPointerAddr(prefix: []const u8) void {...@@ -2513,8 +2513,6 @@ pub fn dumpStackPointerAddr(prefix: []const u8) void {
2513}2513}
25142514
2515test "manage resources correctly" {2515test "manage resources correctly" {
2516 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2517
2518 if (builtin.os.tag == .wasi) return error.SkipZigTest;2516 if (builtin.os.tag == .wasi) return error.SkipZigTest;
25192517
2520 if (builtin.os.tag == .windows) {2518 if (builtin.os.tag == .windows) {
lib/std/fmt/parse_float.zig+1-12
...@@ -2,7 +2,6 @@ pub const parseFloat = @import("parse_float/parse_float.zig").parseFloat;...@@ -2,7 +2,6 @@ pub const parseFloat = @import("parse_float/parse_float.zig").parseFloat;
2pub const ParseFloatError = @import("parse_float/parse_float.zig").ParseFloatError;2pub const ParseFloatError = @import("parse_float/parse_float.zig").ParseFloatError;
33
4const std = @import("std");4const std = @import("std");
5const builtin = @import("builtin");
6const math = std.math;5const math = std.math;
7const testing = std.testing;6const testing = std.testing;
8const expect = testing.expect;7const expect = testing.expect;
...@@ -14,8 +13,6 @@ const epsilon = 1e-7;...@@ -14,8 +13,6 @@ const epsilon = 1e-7;
14// See https://github.com/tiehuis/parse-number-fxx-test-data for a wider-selection of test-data.13// See https://github.com/tiehuis/parse-number-fxx-test-data for a wider-selection of test-data.
1514
16test "fmt.parseFloat" {15test "fmt.parseFloat" {
17 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
18
19 inline for ([_]type{ f16, f32, f64, f128 }) |T| {16 inline for ([_]type{ f16, f32, f64, f128 }) |T| {
20 try testing.expectError(error.InvalidCharacter, parseFloat(T, ""));17 try testing.expectError(error.InvalidCharacter, parseFloat(T, ""));
21 try testing.expectError(error.InvalidCharacter, parseFloat(T, " 1"));18 try testing.expectError(error.InvalidCharacter, parseFloat(T, " 1"));
...@@ -72,8 +69,6 @@ test "fmt.parseFloat" {...@@ -72,8 +69,6 @@ test "fmt.parseFloat" {
72}69}
7370
74test "fmt.parseFloat nan and inf" {71test "fmt.parseFloat nan and inf" {
75 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
76
77 inline for ([_]type{ f16, f32, f64, f128 }) |T| {72 inline for ([_]type{ f16, f32, f64, f128 }) |T| {
78 const Z = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);73 const Z = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
7974
...@@ -88,7 +83,7 @@ test "fmt.parseFloat #11169" {...@@ -88,7 +83,7 @@ test "fmt.parseFloat #11169" {
88}83}
8984
90test "fmt.parseFloat hex.special" {85test "fmt.parseFloat hex.special" {
91 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;86 if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
9287
93 try testing.expect(math.isNan(try parseFloat(f32, "nAn")));88 try testing.expect(math.isNan(try parseFloat(f32, "nAn")));
94 try testing.expect(math.isPositiveInf(try parseFloat(f32, "iNf")));89 try testing.expect(math.isPositiveInf(try parseFloat(f32, "iNf")));
...@@ -96,8 +91,6 @@ test "fmt.parseFloat hex.special" {...@@ -96,8 +91,6 @@ test "fmt.parseFloat hex.special" {
96 try testing.expect(math.isNegativeInf(try parseFloat(f32, "-iNf")));91 try testing.expect(math.isNegativeInf(try parseFloat(f32, "-iNf")));
97}92}
98test "fmt.parseFloat hex.zero" {93test "fmt.parseFloat hex.zero" {
99 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
100
101 try testing.expectEqual(@as(f32, 0.0), try parseFloat(f32, "0x0"));94 try testing.expectEqual(@as(f32, 0.0), try parseFloat(f32, "0x0"));
102 try testing.expectEqual(@as(f32, 0.0), try parseFloat(f32, "-0x0"));95 try testing.expectEqual(@as(f32, 0.0), try parseFloat(f32, "-0x0"));
103 try testing.expectEqual(@as(f32, 0.0), try parseFloat(f32, "0x0p42"));96 try testing.expectEqual(@as(f32, 0.0), try parseFloat(f32, "0x0p42"));
...@@ -106,8 +99,6 @@ test "fmt.parseFloat hex.zero" {...@@ -106,8 +99,6 @@ test "fmt.parseFloat hex.zero" {
106}99}
107100
108test "fmt.parseFloat hex.f16" {101test "fmt.parseFloat hex.f16" {
109 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
110
111 try testing.expectEqual(try parseFloat(f16, "0x1p0"), 1.0);102 try testing.expectEqual(try parseFloat(f16, "0x1p0"), 1.0);
112 try testing.expectEqual(try parseFloat(f16, "-0x1p-1"), -0.5);103 try testing.expectEqual(try parseFloat(f16, "-0x1p-1"), -0.5);
113 try testing.expectEqual(try parseFloat(f16, "0x10p+10"), 16384.0);104 try testing.expectEqual(try parseFloat(f16, "0x10p+10"), 16384.0);
...@@ -124,8 +115,6 @@ test "fmt.parseFloat hex.f16" {...@@ -124,8 +115,6 @@ test "fmt.parseFloat hex.f16" {
124}115}
125116
126test "fmt.parseFloat hex.f32" {117test "fmt.parseFloat hex.f32" {
127 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
128
129 try testing.expectError(error.InvalidCharacter, parseFloat(f32, "0x"));118 try testing.expectError(error.InvalidCharacter, parseFloat(f32, "0x"));
130 try testing.expectEqual(try parseFloat(f32, "0x1p0"), 1.0);119 try testing.expectEqual(try parseFloat(f32, "0x1p0"), 1.0);
131 try testing.expectEqual(try parseFloat(f32, "-0x1p-1"), -0.5);120 try testing.expectEqual(try parseFloat(f32, "-0x1p-1"), -0.5);
lib/std/json/static_test.zig-2
...@@ -785,8 +785,6 @@ test "max_value_len" {...@@ -785,8 +785,6 @@ test "max_value_len" {
785}785}
786786
787test "parse into vector" {787test "parse into vector" {
788 if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
789
790 const T = struct {788 const T = struct {
791 vec_i32: @Vector(4, i32),789 vec_i32: @Vector(4, i32),
792 vec_f32: @Vector(2, f32),790 vec_f32: @Vector(2, f32),
src/arch/aarch64/CodeGen.zig+1-5
...@@ -4012,7 +4012,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -4012,7 +4012,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
4012 .got => .load_memory_ptr_got,4012 .got => .load_memory_ptr_got,
4013 .direct => .load_memory_ptr_direct,4013 .direct => .load_memory_ptr_direct,
4014 .import => unreachable,4014 .import => unreachable,
4015 .extern_got => unreachable,
4016 };4015 };
4017 const atom_index = switch (self.bin_file.tag) {4016 const atom_index = switch (self.bin_file.tag) {
4018 .macho => blk: {4017 .macho => blk: {
...@@ -5532,7 +5531,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5532,7 +5531,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5532 .got => .load_memory_ptr_got,5531 .got => .load_memory_ptr_got,
5533 .direct => .load_memory_ptr_direct,5532 .direct => .load_memory_ptr_direct,
5534 .import => unreachable,5533 .import => unreachable,
5535 .extern_got => unreachable,
5536 };5534 };
5537 const atom_index = switch (self.bin_file.tag) {5535 const atom_index = switch (self.bin_file.tag) {
5538 .macho => blk: {5536 .macho => blk: {
...@@ -5654,7 +5652,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -5654,7 +5652,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5654 .got => .load_memory_got,5652 .got => .load_memory_got,
5655 .direct => .load_memory_direct,5653 .direct => .load_memory_direct,
5656 .import => .load_memory_import,5654 .import => .load_memory_import,
5657 .extern_got => unreachable,
5658 };5655 };
5659 const atom_index = switch (self.bin_file.tag) {5656 const atom_index = switch (self.bin_file.tag) {
5660 .macho => blk: {5657 .macho => blk: {
...@@ -5852,7 +5849,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -5852,7 +5849,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5852 .got => .load_memory_ptr_got,5849 .got => .load_memory_ptr_got,
5853 .direct => .load_memory_ptr_direct,5850 .direct => .load_memory_ptr_direct,
5854 .import => unreachable,5851 .import => unreachable,
5855 .extern_got => unreachable,
5856 };5852 };
5857 const atom_index = switch (self.bin_file.tag) {5853 const atom_index = switch (self.bin_file.tag) {
5858 .macho => blk: {5854 .macho => blk: {
...@@ -6180,7 +6176,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -6180,7 +6176,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6180 .memory => |addr| .{ .memory = addr },6176 .memory => |addr| .{ .memory = addr },
6181 .load_got => |sym_index| .{ .linker_load = .{ .type = .got, .sym_index = sym_index } },6177 .load_got => |sym_index| .{ .linker_load = .{ .type = .got, .sym_index = sym_index } },
6182 .load_direct => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } },6178 .load_direct => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } },
6183 .load_extern_got, .load_tlv => unreachable, // TODO6179 .load_symbol, .load_tlv => unreachable, // TODO
6184 },6180 },
6185 .fail => |msg| {6181 .fail => |msg| {
6186 self.err_msg = msg;6182 self.err_msg = msg;
src/arch/arm/CodeGen.zig+1-1
...@@ -6135,7 +6135,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -6135,7 +6135,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6135 .mcv => |mcv| switch (mcv) {6135 .mcv => |mcv| switch (mcv) {
6136 .none => .none,6136 .none => .none,
6137 .undef => .undef,6137 .undef => .undef,
6138 .load_got, .load_extern_got, .load_direct, .load_tlv => unreachable, // TODO6138 .load_got, .load_symbol, .load_direct, .load_tlv => unreachable, // TODO
6139 .immediate => |imm| .{ .immediate = @as(u32, @truncate(imm)) },6139 .immediate => |imm| .{ .immediate = @as(u32, @truncate(imm)) },
6140 .memory => |addr| .{ .memory = addr },6140 .memory => |addr| .{ .memory = addr },
6141 },6141 },
src/arch/riscv64/CodeGen.zig+1-1
...@@ -2591,7 +2591,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -2591,7 +2591,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
2591 .mcv => |mcv| switch (mcv) {2591 .mcv => |mcv| switch (mcv) {
2592 .none => .none,2592 .none => .none,
2593 .undef => .undef,2593 .undef => .undef,
2594 .load_got, .load_extern_got, .load_direct, .load_tlv => unreachable, // TODO2594 .load_got, .load_symbol, .load_direct, .load_tlv => unreachable, // TODO
2595 .immediate => |imm| .{ .immediate = imm },2595 .immediate => |imm| .{ .immediate = imm },
2596 .memory => |addr| .{ .memory = addr },2596 .memory => |addr| .{ .memory = addr },
2597 },2597 },
src/arch/sparc64/CodeGen.zig+1-1
...@@ -4137,7 +4137,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -4137,7 +4137,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
4137 .mcv => |mcv| switch (mcv) {4137 .mcv => |mcv| switch (mcv) {
4138 .none => .none,4138 .none => .none,
4139 .undef => .undef,4139 .undef => .undef,
4140 .load_got, .load_extern_got, .load_direct, .load_tlv => unreachable, // TODO4140 .load_got, .load_symbol, .load_direct, .load_tlv => unreachable, // TODO
4141 .immediate => |imm| .{ .immediate = imm },4141 .immediate => |imm| .{ .immediate = imm },
4142 .memory => |addr| .{ .memory = addr },4142 .memory => |addr| .{ .memory = addr },
4143 },4143 },
src/arch/x86_64/CodeGen.zig+735-439
...@@ -193,6 +193,11 @@ pub const MCValue = union(enum) {...@@ -193,6 +193,11 @@ pub const MCValue = union(enum) {
193 /// The value is in memory at a hard-coded address.193 /// The value is in memory at a hard-coded address.
194 /// If the type is a pointer, it means the pointer address is stored at this memory location.194 /// If the type is a pointer, it means the pointer address is stored at this memory location.
195 memory: u64,195 memory: u64,
196 /// The value is in memory at an address not-yet-allocated by the linker.
197 /// This traditionally corresponds to a relocation emitted in a relocatable object file.
198 load_symbol: u32,
199 /// The address of the memory location not-yet-allocated by the linker.
200 lea_symbol: u32,
196 /// The value is in memory at a constant offset from the address in a register.201 /// The value is in memory at a constant offset from the address in a register.
197 indirect: RegisterOffset,202 indirect: RegisterOffset,
198 /// The value is in memory.203 /// The value is in memory.
...@@ -207,12 +212,6 @@ pub const MCValue = union(enum) {...@@ -207,12 +212,6 @@ pub const MCValue = union(enum) {
207 /// The value is a pointer to a value referenced indirectly via GOT.212 /// The value is a pointer to a value referenced indirectly via GOT.
208 /// Payload is a symbol index.213 /// Payload is a symbol index.
209 lea_got: u32,214 lea_got: u32,
210 /// The value is an extern variable referenced via GOT.
211 /// Payload is a symbol index.
212 load_extern_got: u32,
213 /// The value is a pointer to an extern variable referenced via GOT.
214 /// Payload is a symbol index.
215 lea_extern_got: u32,
216 /// The value is a threadlocal variable.215 /// The value is a threadlocal variable.
217 /// Payload is a symbol index.216 /// Payload is a symbol index.
218 load_tlv: u32,217 load_tlv: u32,
...@@ -299,9 +298,9 @@ pub const MCValue = union(enum) {...@@ -299,9 +298,9 @@ pub const MCValue = union(enum) {
299 .register_pair,298 .register_pair,
300 .register_offset,299 .register_offset,
301 .register_overflow,300 .register_overflow,
301 .lea_symbol,
302 .lea_direct,302 .lea_direct,
303 .lea_got,303 .lea_got,
304 .lea_extern_got,
305 .lea_tlv,304 .lea_tlv,
306 .lea_frame,305 .lea_frame,
307 .reserved_frame,306 .reserved_frame,
...@@ -315,8 +314,8 @@ pub const MCValue = union(enum) {...@@ -315,8 +314,8 @@ pub const MCValue = union(enum) {
315 .load_direct => |sym_index| .{ .lea_direct = sym_index },314 .load_direct => |sym_index| .{ .lea_direct = sym_index },
316 .load_got => |sym_index| .{ .lea_got = sym_index },315 .load_got => |sym_index| .{ .lea_got = sym_index },
317 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },316 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
318 .load_extern_got => |sym_index| .{ .lea_extern_got = sym_index },
319 .load_frame => |frame_addr| .{ .lea_frame = frame_addr },317 .load_frame => |frame_addr| .{ .lea_frame = frame_addr },
318 .load_symbol => |sym_index| .{ .lea_symbol = sym_index },
320 };319 };
321 }320 }
322321
...@@ -333,9 +332,9 @@ pub const MCValue = union(enum) {...@@ -333,9 +332,9 @@ pub const MCValue = union(enum) {
333 .indirect,332 .indirect,
334 .load_direct,333 .load_direct,
335 .load_got,334 .load_got,
336 .load_extern_got,
337 .load_tlv,335 .load_tlv,
338 .load_frame,336 .load_frame,
337 .load_symbol,
339 .reserved_frame,338 .reserved_frame,
340 .air_ref,339 .air_ref,
341 => unreachable, // not dereferenceable340 => unreachable, // not dereferenceable
...@@ -344,9 +343,9 @@ pub const MCValue = union(enum) {...@@ -344,9 +343,9 @@ pub const MCValue = union(enum) {
344 .register_offset => |reg_off| .{ .indirect = reg_off },343 .register_offset => |reg_off| .{ .indirect = reg_off },
345 .lea_direct => |sym_index| .{ .load_direct = sym_index },344 .lea_direct => |sym_index| .{ .load_direct = sym_index },
346 .lea_got => |sym_index| .{ .load_got = sym_index },345 .lea_got => |sym_index| .{ .load_got = sym_index },
347 .lea_extern_got => |sym_index| .{ .load_extern_got = sym_index },
348 .lea_tlv => |sym_index| .{ .load_tlv = sym_index },346 .lea_tlv => |sym_index| .{ .load_tlv = sym_index },
349 .lea_frame => |frame_addr| .{ .load_frame = frame_addr },347 .lea_frame => |frame_addr| .{ .load_frame = frame_addr },
348 .lea_symbol => |sym_index| .{ .load_symbol = sym_index },
350 };349 };
351 }350 }
352351
...@@ -368,11 +367,11 @@ pub const MCValue = union(enum) {...@@ -368,11 +367,11 @@ pub const MCValue = union(enum) {
368 .lea_direct,367 .lea_direct,
369 .load_got,368 .load_got,
370 .lea_got,369 .lea_got,
371 .load_extern_got,
372 .lea_extern_got,
373 .load_tlv,370 .load_tlv,
374 .lea_tlv,371 .lea_tlv,
375 .load_frame,372 .load_frame,
373 .load_symbol,
374 .lea_symbol,
376 => switch (off) {375 => switch (off) {
377 0 => mcv,376 0 => mcv,
378 else => unreachable, // not offsettable377 else => unreachable, // not offsettable
...@@ -404,13 +403,13 @@ pub const MCValue = union(enum) {...@@ -404,13 +403,13 @@ pub const MCValue = union(enum) {
404 .lea_direct,403 .lea_direct,
405 .load_got,404 .load_got,
406 .lea_got,405 .lea_got,
407 .load_extern_got,
408 .lea_extern_got,
409 .load_tlv,406 .load_tlv,
410 .lea_tlv,407 .lea_tlv,
411 .lea_frame,408 .lea_frame,
412 .reserved_frame,409 .reserved_frame,
413 .air_ref,410 .air_ref,
411 .load_symbol,
412 .lea_symbol,
414 => unreachable,413 => unreachable,
415 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|414 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
416 Memory.sib(ptr_size, .{ .base = .{ .reg = .ds }, .disp = small_addr })415 Memory.sib(ptr_size, .{ .base = .{ .reg = .ds }, .disp = small_addr })
...@@ -448,14 +447,14 @@ pub const MCValue = union(enum) {...@@ -448,14 +447,14 @@ pub const MCValue = union(enum) {
448 .lea_direct => |pl| try writer.print("direct:{d}", .{pl}),447 .lea_direct => |pl| try writer.print("direct:{d}", .{pl}),
449 .load_got => |pl| try writer.print("[got:{d}]", .{pl}),448 .load_got => |pl| try writer.print("[got:{d}]", .{pl}),
450 .lea_got => |pl| try writer.print("got:{d}", .{pl}),449 .lea_got => |pl| try writer.print("got:{d}", .{pl}),
451 .load_extern_got => |pl| try writer.print("[extern_got:{d}]", .{pl}),
452 .lea_extern_got => |pl| try writer.print("extern_got:{d}", .{pl}),
453 .load_tlv => |pl| try writer.print("[tlv:{d}]", .{pl}),450 .load_tlv => |pl| try writer.print("[tlv:{d}]", .{pl}),
454 .lea_tlv => |pl| try writer.print("tlv:{d}", .{pl}),451 .lea_tlv => |pl| try writer.print("tlv:{d}", .{pl}),
455 .load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }),452 .load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }),
456 .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }),453 .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }),
457 .reserved_frame => |pl| try writer.print("(dead:{})", .{pl}),454 .reserved_frame => |pl| try writer.print("(dead:{})", .{pl}),
458 .air_ref => |pl| try writer.print("(air:0x{x})", .{@intFromEnum(pl)}),455 .air_ref => |pl| try writer.print("(air:0x{x})", .{@intFromEnum(pl)}),
456 .load_symbol => |pl| try writer.print("[symbol:{d}]", .{pl}),
457 .lea_symbol => |pl| try writer.print("symbol:{d}", .{pl}),
459 }458 }
460 }459 }
461};460};
...@@ -477,12 +476,12 @@ const InstTracking = struct {...@@ -477,12 +476,12 @@ const InstTracking = struct {
477 .lea_direct,476 .lea_direct,
478 .load_got,477 .load_got,
479 .lea_got,478 .lea_got,
480 .load_extern_got,
481 .lea_extern_got,
482 .load_tlv,479 .load_tlv,
483 .lea_tlv,480 .lea_tlv,
484 .load_frame,481 .load_frame,
485 .lea_frame,482 .lea_frame,
483 .load_symbol,
484 .lea_symbol,
486 => result,485 => result,
487 .dead,486 .dead,
488 .reserved_frame,487 .reserved_frame,
...@@ -538,12 +537,12 @@ const InstTracking = struct {...@@ -538,12 +537,12 @@ const InstTracking = struct {
538 .lea_direct,537 .lea_direct,
539 .load_got,538 .load_got,
540 .lea_got,539 .lea_got,
541 .load_extern_got,
542 .lea_extern_got,
543 .load_tlv,540 .load_tlv,
544 .lea_tlv,541 .lea_tlv,
545 .load_frame,542 .load_frame,
546 .lea_frame,543 .lea_frame,
544 .load_symbol,
545 .lea_symbol,
547 => self.long,546 => self.long,
548 .dead,547 .dead,
549 .eflags,548 .eflags,
...@@ -575,11 +574,11 @@ const InstTracking = struct {...@@ -575,11 +574,11 @@ const InstTracking = struct {
575 .lea_direct,574 .lea_direct,
576 .load_got,575 .load_got,
577 .lea_got,576 .lea_got,
578 .load_extern_got,
579 .lea_extern_got,
580 .load_tlv,577 .load_tlv,
581 .lea_tlv,578 .lea_tlv,
582 .lea_frame,579 .lea_frame,
580 .load_symbol,
581 .lea_symbol,
583 => assert(std.meta.eql(self.long, target.long)),582 => assert(std.meta.eql(self.long, target.long)),
584 .load_frame,583 .load_frame,
585 .reserved_frame,584 .reserved_frame,
...@@ -883,6 +882,7 @@ pub fn generate(...@@ -883,6 +882,7 @@ pub fn generate(
883882
884 var emit = Emit{883 var emit = Emit{
885 .lower = .{884 .lower = .{
885 .bin_file = bin_file,
886 .allocator = bin_file.allocator,886 .allocator = bin_file.allocator,
887 .mir = mir,887 .mir = mir,
888 .cc = cc,888 .cc = cc,
...@@ -970,6 +970,7 @@ pub fn generateLazy(...@@ -970,6 +970,7 @@ pub fn generateLazy(
970970
971 var emit = Emit{971 var emit = Emit{
972 .lower = .{972 .lower = .{
973 .bin_file = bin_file,
973 .allocator = bin_file.allocator,974 .allocator = bin_file.allocator,
974 .mir = mir,975 .mir = mir,
975 .cc = abi.resolveCallingConvention(.Unspecified, function.target.*),976 .cc = abi.resolveCallingConvention(.Unspecified, function.target.*),
...@@ -1060,6 +1061,7 @@ fn formatWipMir(...@@ -1060,6 +1061,7 @@ fn formatWipMir(
1060 writer: anytype,1061 writer: anytype,
1061) @TypeOf(writer).Error!void {1062) @TypeOf(writer).Error!void {
1062 var lower = Lower{1063 var lower = Lower{
1064 .bin_file = data.self.bin_file,
1063 .allocator = data.self.gpa,1065 .allocator = data.self.gpa,
1064 .mir = .{1066 .mir = .{
1065 .instructions = data.self.mir_instructions.slice(),1067 .instructions = data.self.mir_instructions.slice(),
...@@ -3261,25 +3263,51 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -3261,25 +3263,51 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
3261 defer self.register_manager.unlockReg(tmp_lock);3263 defer self.register_manager.unlockReg(tmp_lock);
32623264
3263 const lhs_mcv = try self.resolveInst(bin_op.lhs);3265 const lhs_mcv = try self.resolveInst(bin_op.lhs);
3264 if (lhs_mcv.isMemory()) try self.asmRegisterMemory(3266 const mat_lhs_mcv = switch (lhs_mcv) {
3267 .load_symbol => mat_lhs_mcv: {
3268 // TODO clean this up!
3269 const addr_reg = try self.copyToTmpRegister(Type.usize, lhs_mcv.address());
3270 break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
3271 },
3272 else => lhs_mcv,
3273 };
3274 const mat_lhs_lock = switch (mat_lhs_mcv) {
3275 .indirect => |reg_off| self.register_manager.lockReg(reg_off.reg),
3276 else => null,
3277 };
3278 defer if (mat_lhs_lock) |lock| self.register_manager.unlockReg(lock);
3279 if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory(
3265 .{ ._, .mov },3280 .{ ._, .mov },
3266 tmp_reg,3281 tmp_reg,
3267 lhs_mcv.address().offset(8).deref().mem(.qword),3282 mat_lhs_mcv.address().offset(8).deref().mem(.qword),
3268 ) else try self.asmRegisterRegister(3283 ) else try self.asmRegisterRegister(
3269 .{ ._, .mov },3284 .{ ._, .mov },
3270 tmp_reg,3285 tmp_reg,
3271 lhs_mcv.register_pair[1],3286 mat_lhs_mcv.register_pair[1],
3272 );3287 );
32733288
3274 const rhs_mcv = try self.resolveInst(bin_op.rhs);3289 const rhs_mcv = try self.resolveInst(bin_op.rhs);
3275 if (rhs_mcv.isMemory()) try self.asmRegisterMemory(3290 const mat_rhs_mcv = switch (rhs_mcv) {
3291 .load_symbol => mat_rhs_mcv: {
3292 // TODO clean this up!
3293 const addr_reg = try self.copyToTmpRegister(Type.usize, rhs_mcv.address());
3294 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
3295 },
3296 else => rhs_mcv,
3297 };
3298 const mat_rhs_lock = switch (mat_rhs_mcv) {
3299 .indirect => |reg_off| self.register_manager.lockReg(reg_off.reg),
3300 else => null,
3301 };
3302 defer if (mat_rhs_lock) |lock| self.register_manager.unlockReg(lock);
3303 if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory(
3276 .{ ._, .xor },3304 .{ ._, .xor },
3277 tmp_reg,3305 tmp_reg,
3278 rhs_mcv.address().offset(8).deref().mem(.qword),3306 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
3279 ) else try self.asmRegisterRegister(3307 ) else try self.asmRegisterRegister(
3280 .{ ._, .xor },3308 .{ ._, .xor },
3281 tmp_reg,3309 tmp_reg,
3282 rhs_mcv.register_pair[1],3310 mat_rhs_mcv.register_pair[1],
3283 );3311 );
3284 const reloc = try self.asmJccReloc(.ns, undefined);3312 const reloc = try self.asmJccReloc(.ns, undefined);
32853313
...@@ -3353,20 +3381,37 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -3353,20 +3381,37 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
3353 defer for (tmp_locks) |lock| self.register_manager.unlockReg(lock);3381 defer for (tmp_locks) |lock| self.register_manager.unlockReg(lock);
33543382
3355 const rhs_mcv = try self.resolveInst(bin_op.rhs);3383 const rhs_mcv = try self.resolveInst(bin_op.rhs);
3384 const mat_rhs_mcv = switch (rhs_mcv) {
3385 .load_symbol => mat_rhs_mcv: {
3386 // TODO clean this up!
3387 const addr_reg = try self.copyToTmpRegister(Type.usize, rhs_mcv.address());
3388 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
3389 },
3390 else => rhs_mcv,
3391 };
3392 const mat_rhs_lock = switch (mat_rhs_mcv) {
3393 .indirect => |reg_off| self.register_manager.lockReg(reg_off.reg),
3394 else => null,
3395 };
3396 defer if (mat_rhs_lock) |lock| self.register_manager.unlockReg(lock);
33563397
3357 for (tmp_regs, dst_regs) |tmp_reg, dst_reg|3398 for (tmp_regs, dst_regs) |tmp_reg, dst_reg|
3358 try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, dst_reg);3399 try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, dst_reg);
3359 if (rhs_mcv.isMemory()) {3400 if (mat_rhs_mcv.isMemory()) {
3360 try self.asmRegisterMemory(.{ ._, .add }, tmp_regs[0], rhs_mcv.mem(.qword));3401 try self.asmRegisterMemory(
3402 .{ ._, .add },
3403 tmp_regs[0],
3404 mat_rhs_mcv.mem(.qword),
3405 );
3361 try self.asmRegisterMemory(3406 try self.asmRegisterMemory(
3362 .{ ._, .adc },3407 .{ ._, .adc },
3363 tmp_regs[1],3408 tmp_regs[1],
3364 rhs_mcv.address().offset(8).deref().mem(.qword),3409 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
3365 );3410 );
3366 } else for (3411 } else for (
3367 [_]Mir.Inst.Tag{ .add, .adc },3412 [_]Mir.Inst.Tag{ .add, .adc },
3368 tmp_regs,3413 tmp_regs,
3369 rhs_mcv.register_pair,3414 mat_rhs_mcv.register_pair,
3370 ) |op, tmp_reg, rhs_reg|3415 ) |op, tmp_reg, rhs_reg|
3371 try self.asmRegisterRegister(.{ ._, op }, tmp_reg, rhs_reg);3416 try self.asmRegisterRegister(.{ ._, op }, tmp_reg, rhs_reg);
3372 try self.asmRegisterRegister(.{ ._, .@"test" }, dst_regs[1], dst_regs[1]);3417 try self.asmRegisterRegister(.{ ._, .@"test" }, dst_regs[1], dst_regs[1]);
...@@ -3871,39 +3916,65 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -3871,39 +3916,65 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
38713916
3872 const lhs_mcv = try self.resolveInst(bin_op.lhs);3917 const lhs_mcv = try self.resolveInst(bin_op.lhs);
3873 const rhs_mcv = try self.resolveInst(bin_op.rhs);3918 const rhs_mcv = try self.resolveInst(bin_op.rhs);
3919 const mat_lhs_mcv = switch (lhs_mcv) {
3920 .load_symbol => mat_lhs_mcv: {
3921 // TODO clean this up!
3922 const addr_reg = try self.copyToTmpRegister(Type.usize, lhs_mcv.address());
3923 break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
3924 },
3925 else => lhs_mcv,
3926 };
3927 const mat_lhs_lock = switch (mat_lhs_mcv) {
3928 .indirect => |reg_off| self.register_manager.lockReg(reg_off.reg),
3929 else => null,
3930 };
3931 defer if (mat_lhs_lock) |lock| self.register_manager.unlockReg(lock);
3932 const mat_rhs_mcv = switch (rhs_mcv) {
3933 .load_symbol => mat_rhs_mcv: {
3934 // TODO clean this up!
3935 const addr_reg = try self.copyToTmpRegister(Type.usize, rhs_mcv.address());
3936 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
3937 },
3938 else => rhs_mcv,
3939 };
3940 const mat_rhs_lock = switch (mat_rhs_mcv) {
3941 .indirect => |reg_off| self.register_manager.lockReg(reg_off.reg),
3942 else => null,
3943 };
3944 defer if (mat_rhs_lock) |lock| self.register_manager.unlockReg(lock);
38743945
3875 if (lhs_mcv.isMemory())3946 if (mat_lhs_mcv.isMemory())
3876 try self.asmRegisterMemory(.{ ._, .mov }, .rax, lhs_mcv.mem(.qword))3947 try self.asmRegisterMemory(.{ ._, .mov }, .rax, mat_lhs_mcv.mem(.qword))
3877 else3948 else
3878 try self.asmRegisterRegister(.{ ._, .mov }, .rax, lhs_mcv.register_pair[0]);3949 try self.asmRegisterRegister(.{ ._, .mov }, .rax, mat_lhs_mcv.register_pair[0]);
3879 if (rhs_mcv.isMemory()) try self.asmRegisterMemory(3950 if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory(
3880 .{ ._, .mov },3951 .{ ._, .mov },
3881 tmp_regs[0],3952 tmp_regs[0],
3882 rhs_mcv.address().offset(8).deref().mem(.qword),3953 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
3883 ) else try self.asmRegisterRegister(3954 ) else try self.asmRegisterRegister(
3884 .{ ._, .mov },3955 .{ ._, .mov },
3885 tmp_regs[0],3956 tmp_regs[0],
3886 rhs_mcv.register_pair[1],3957 mat_rhs_mcv.register_pair[1],
3887 );3958 );
3888 try self.asmRegisterRegister(.{ ._, .@"test" }, tmp_regs[0], tmp_regs[0]);3959 try self.asmRegisterRegister(.{ ._, .@"test" }, tmp_regs[0], tmp_regs[0]);
3889 try self.asmSetccRegister(.nz, tmp_regs[1].to8());3960 try self.asmSetccRegister(.nz, tmp_regs[1].to8());
3890 try self.asmRegisterRegister(.{ .i_, .mul }, tmp_regs[0], .rax);3961 try self.asmRegisterRegister(.{ .i_, .mul }, tmp_regs[0], .rax);
3891 try self.asmSetccRegister(.o, tmp_regs[2].to8());3962 try self.asmSetccRegister(.o, tmp_regs[2].to8());
3892 if (rhs_mcv.isMemory())3963 if (mat_rhs_mcv.isMemory())
3893 try self.asmMemory(.{ ._, .mul }, rhs_mcv.mem(.qword))3964 try self.asmMemory(.{ ._, .mul }, mat_rhs_mcv.mem(.qword))
3894 else3965 else
3895 try self.asmRegister(.{ ._, .mul }, rhs_mcv.register_pair[0]);3966 try self.asmRegister(.{ ._, .mul }, mat_rhs_mcv.register_pair[0]);
3896 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_regs[0]);3967 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_regs[0]);
3897 try self.asmSetccRegister(.c, tmp_regs[3].to8());3968 try self.asmSetccRegister(.c, tmp_regs[3].to8());
3898 try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[2].to8(), tmp_regs[3].to8());3969 try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[2].to8(), tmp_regs[3].to8());
3899 if (lhs_mcv.isMemory()) try self.asmRegisterMemory(3970 if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory(
3900 .{ ._, .mov },3971 .{ ._, .mov },
3901 tmp_regs[0],3972 tmp_regs[0],
3902 lhs_mcv.address().offset(8).deref().mem(.qword),3973 mat_lhs_mcv.address().offset(8).deref().mem(.qword),
3903 ) else try self.asmRegisterRegister(3974 ) else try self.asmRegisterRegister(
3904 .{ ._, .mov },3975 .{ ._, .mov },
3905 tmp_regs[0],3976 tmp_regs[0],
3906 lhs_mcv.register_pair[1],3977 mat_lhs_mcv.register_pair[1],
3907 );3978 );
3908 try self.asmRegisterRegister(.{ ._, .@"test" }, tmp_regs[0], tmp_regs[0]);3979 try self.asmRegisterRegister(.{ ._, .@"test" }, tmp_regs[0], tmp_regs[0]);
3909 try self.asmSetccRegister(.nz, tmp_regs[3].to8());3980 try self.asmSetccRegister(.nz, tmp_regs[3].to8());
...@@ -3913,13 +3984,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -3913,13 +3984,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3913 tmp_regs[3].to8(),3984 tmp_regs[3].to8(),
3914 );3985 );
3915 try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[1].to8(), tmp_regs[2].to8());3986 try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[1].to8(), tmp_regs[2].to8());
3916 if (rhs_mcv.isMemory())3987 if (mat_rhs_mcv.isMemory())
3917 try self.asmRegisterMemory(.{ .i_, .mul }, tmp_regs[0], rhs_mcv.mem(.qword))3988 try self.asmRegisterMemory(.{ .i_, .mul }, tmp_regs[0], mat_rhs_mcv.mem(.qword))
3918 else3989 else
3919 try self.asmRegisterRegister(3990 try self.asmRegisterRegister(
3920 .{ .i_, .mul },3991 .{ .i_, .mul },
3921 tmp_regs[0],3992 tmp_regs[0],
3922 rhs_mcv.register_pair[0],3993 mat_rhs_mcv.register_pair[0],
3923 );3994 );
3924 try self.asmSetccRegister(.o, tmp_regs[2].to8());3995 try self.asmSetccRegister(.o, tmp_regs[2].to8());
3925 try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[1].to8(), tmp_regs[2].to8());3996 try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[1].to8(), tmp_regs[2].to8());
...@@ -4729,12 +4800,12 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -4729,12 +4800,12 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
4729 Memory.sib(.qword, .{ .base = .{ .frame = frame_addr.index }, .disp = frame_addr.off }),4800 Memory.sib(.qword, .{ .base = .{ .frame = frame_addr.index }, .disp = frame_addr.off }),
4730 ),4801 ),
4731 .memory,4802 .memory,
4803 .load_symbol,
4732 .load_direct,4804 .load_direct,
4733 .load_got,4805 .load_got,
4734 .load_extern_got,
4735 .load_tlv,4806 .load_tlv,
4736 => try self.genSetReg(addr_reg, Type.usize, array.address()),4807 => try self.genSetReg(addr_reg, Type.usize, array.address()),
4737 .lea_direct, .lea_tlv => unreachable,4808 .lea_symbol, .lea_direct, .lea_tlv => unreachable,
4738 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),4809 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
4739 }4810 }
47404811
...@@ -6327,17 +6398,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro...@@ -6327,17 +6398,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro
6327 .immediate,6398 .immediate,
6328 .register,6399 .register,
6329 .register_offset,6400 .register_offset,
6401 .lea_symbol,
6330 .lea_direct,6402 .lea_direct,
6331 .lea_got,6403 .lea_got,
6332 .lea_extern_got,
6333 .lea_tlv,6404 .lea_tlv,
6334 .lea_frame,6405 .lea_frame,
6335 => try self.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()),6406 => try self.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()),
6336 .memory,6407 .memory,
6337 .indirect,6408 .indirect,
6409 .load_symbol,
6338 .load_direct,6410 .load_direct,
6339 .load_got,6411 .load_got,
6340 .load_extern_got,
6341 .load_tlv,6412 .load_tlv,
6342 .load_frame,6413 .load_frame,
6343 => {6414 => {
...@@ -6476,17 +6547,17 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr...@@ -6476,17 +6547,17 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr
6476 .immediate,6547 .immediate,
6477 .register,6548 .register,
6478 .register_offset,6549 .register_offset,
6550 .lea_symbol,
6479 .lea_direct,6551 .lea_direct,
6480 .lea_got,6552 .lea_got,
6481 .lea_extern_got,
6482 .lea_tlv,6553 .lea_tlv,
6483 .lea_frame,6554 .lea_frame,
6484 => try self.genCopy(src_ty, ptr_mcv.deref(), src_mcv),6555 => try self.genCopy(src_ty, ptr_mcv.deref(), src_mcv),
6485 .memory,6556 .memory,
6486 .indirect,6557 .indirect,
6558 .load_symbol,
6487 .load_direct,6559 .load_direct,
6488 .load_got,6560 .load_got,
6489 .load_extern_got,
6490 .load_tlv,6561 .load_tlv,
6491 .load_frame,6562 .load_frame,
6492 => {6563 => {
...@@ -6587,12 +6658,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -6587,12 +6658,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
6587 const src_reg_lock = self.register_manager.lockRegAssumeUnused(src_reg);6658 const src_reg_lock = self.register_manager.lockRegAssumeUnused(src_reg);
6588 defer self.register_manager.unlockReg(src_reg_lock);6659 defer self.register_manager.unlockReg(src_reg_lock);
65896660
6590 const dst_reg = if (field_rc.supersetOf(container_rc) and6661 const src_in_field_rc =
6591 self.reuseOperand(inst, operand, 0, src_mcv))6662 field_rc.isSet(RegisterManager.indexOfRegIntoTracked(src_reg).?);
6663 const dst_reg = if (src_in_field_rc and self.reuseOperand(inst, operand, 0, src_mcv))
6592 src_reg6664 src_reg
6665 else if (field_off == 0)
6666 (try self.copyToRegisterWithInstTracking(inst, field_ty, src_mcv)).register
6593 else6667 else
6594 try self.copyToTmpRegister(Type.usize, .{ .register = src_reg });6668 try self.copyToTmpRegister(Type.usize, .{ .register = src_reg });
6595 const dst_mcv = MCValue{ .register = dst_reg };6669 const dst_mcv: MCValue = .{ .register = dst_reg };
6596 const dst_lock = self.register_manager.lockReg(dst_reg);6670 const dst_lock = self.register_manager.lockReg(dst_reg);
6597 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);6671 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
65986672
...@@ -6602,9 +6676,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -6602,9 +6676,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
6602 dst_mcv,6676 dst_mcv,
6603 .{ .immediate = field_off },6677 .{ .immediate = field_off },
6604 );6678 );
6605 if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg);6679 if (abi.RegisterClass.gp.isSet(RegisterManager.indexOfRegIntoTracked(dst_reg).?) and
6680 container_ty.abiSize(mod) * 8 > field_ty.bitSize(mod))
6681 try self.truncateRegister(field_ty, dst_reg);
66066682
6607 break :result if (field_rc.supersetOf(abi.RegisterClass.gp))6683 break :result if (field_off == 0 or field_rc.supersetOf(abi.RegisterClass.gp))
6608 dst_mcv6684 dst_mcv
6609 else6685 else
6610 try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv);6686 try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv);
...@@ -6908,15 +6984,15 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MC...@@ -6908,15 +6984,15 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MC
6908 .register_overflow,6984 .register_overflow,
6909 .lea_direct,6985 .lea_direct,
6910 .lea_got,6986 .lea_got,
6911 .lea_extern_got,
6912 .lea_tlv,6987 .lea_tlv,
6913 .lea_frame,6988 .lea_frame,
6914 .reserved_frame,6989 .reserved_frame,
6915 .air_ref,6990 .air_ref,
6991 .lea_symbol,
6916 => unreachable, // unmodifiable destination6992 => unreachable, // unmodifiable destination
6917 .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)),6993 .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)),
6918 .register_pair => unreachable, // unimplemented6994 .register_pair => unreachable, // unimplemented
6919 .memory, .load_got, .load_extern_got, .load_direct, .load_tlv => {6995 .memory, .load_symbol, .load_got, .load_direct, .load_tlv => {
6920 const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);6996 const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
6921 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);6997 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
6922 defer self.register_manager.unlockReg(addr_reg_lock);6998 defer self.register_manager.unlockReg(addr_reg_lock);
...@@ -7352,34 +7428,61 @@ fn genMulDivBinOp(...@@ -7352,34 +7428,61 @@ fn genMulDivBinOp(
7352 const reg_locks = self.register_manager.lockRegsAssumeUnused(2, .{ .rax, .rdx });7428 const reg_locks = self.register_manager.lockRegsAssumeUnused(2, .{ .rax, .rdx });
7353 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);7429 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
73547430
7431 const mat_lhs_mcv = switch (lhs_mcv) {
7432 .load_symbol => mat_lhs_mcv: {
7433 // TODO clean this up!
7434 const addr_reg = try self.copyToTmpRegister(Type.usize, lhs_mcv.address());
7435 break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
7436 },
7437 else => lhs_mcv,
7438 };
7439 const mat_lhs_lock = switch (mat_lhs_mcv) {
7440 .indirect => |reg_off| self.register_manager.lockReg(reg_off.reg),
7441 else => null,
7442 };
7443 defer if (mat_lhs_lock) |lock| self.register_manager.unlockReg(lock);
7444 const mat_rhs_mcv = switch (rhs_mcv) {
7445 .load_symbol => mat_rhs_mcv: {
7446 // TODO clean this up!
7447 const addr_reg = try self.copyToTmpRegister(Type.usize, rhs_mcv.address());
7448 break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } };
7449 },
7450 else => rhs_mcv,
7451 };
7452 const mat_rhs_lock = switch (mat_rhs_mcv) {
7453 .indirect => |reg_off| self.register_manager.lockReg(reg_off.reg),
7454 else => null,
7455 };
7456 defer if (mat_rhs_lock) |lock| self.register_manager.unlockReg(lock);
7457
7355 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);7458 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
7356 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);7459 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7357 defer self.register_manager.unlockReg(tmp_lock);7460 defer self.register_manager.unlockReg(tmp_lock);
73587461
7359 if (lhs_mcv.isMemory())7462 if (mat_lhs_mcv.isMemory())
7360 try self.asmRegisterMemory(.{ ._, .mov }, .rax, lhs_mcv.mem(.qword))7463 try self.asmRegisterMemory(.{ ._, .mov }, .rax, mat_lhs_mcv.mem(.qword))
7361 else7464 else
7362 try self.asmRegisterRegister(.{ ._, .mov }, .rax, lhs_mcv.register_pair[0]);7465 try self.asmRegisterRegister(.{ ._, .mov }, .rax, mat_lhs_mcv.register_pair[0]);
7363 if (rhs_mcv.isMemory()) try self.asmRegisterMemory(7466 if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory(
7364 .{ ._, .mov },7467 .{ ._, .mov },
7365 tmp_reg,7468 tmp_reg,
7366 rhs_mcv.address().offset(8).deref().mem(.qword),7469 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
7367 ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, rhs_mcv.register_pair[1]);7470 ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, mat_rhs_mcv.register_pair[1]);
7368 try self.asmRegisterRegister(.{ .i_, .mul }, tmp_reg, .rax);7471 try self.asmRegisterRegister(.{ .i_, .mul }, tmp_reg, .rax);
7369 if (rhs_mcv.isMemory())7472 if (mat_rhs_mcv.isMemory())
7370 try self.asmMemory(.{ ._, .mul }, rhs_mcv.mem(.qword))7473 try self.asmMemory(.{ ._, .mul }, mat_rhs_mcv.mem(.qword))
7371 else7474 else
7372 try self.asmRegister(.{ ._, .mul }, rhs_mcv.register_pair[0]);7475 try self.asmRegister(.{ ._, .mul }, mat_rhs_mcv.register_pair[0]);
7373 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_reg);7476 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_reg);
7374 if (lhs_mcv.isMemory()) try self.asmRegisterMemory(7477 if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory(
7375 .{ ._, .mov },7478 .{ ._, .mov },
7376 tmp_reg,7479 tmp_reg,
7377 lhs_mcv.address().offset(8).deref().mem(.qword),7480 mat_lhs_mcv.address().offset(8).deref().mem(.qword),
7378 ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, lhs_mcv.register_pair[1]);7481 ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, mat_lhs_mcv.register_pair[1]);
7379 if (rhs_mcv.isMemory())7482 if (mat_rhs_mcv.isMemory())
7380 try self.asmRegisterMemory(.{ .i_, .mul }, tmp_reg, rhs_mcv.mem(.qword))7483 try self.asmRegisterMemory(.{ .i_, .mul }, tmp_reg, mat_rhs_mcv.mem(.qword))
7381 else7484 else
7382 try self.asmRegisterRegister(.{ .i_, .mul }, tmp_reg, rhs_mcv.register_pair[0]);7485 try self.asmRegisterRegister(.{ .i_, .mul }, tmp_reg, mat_rhs_mcv.register_pair[0]);
7383 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_reg);7486 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_reg);
7384 return .{ .register_pair = .{ .rax, .rdx } };7487 return .{ .register_pair = .{ .rax, .rdx } };
7385 }7488 }
...@@ -7968,12 +8071,12 @@ fn genBinOp(...@@ -7968,12 +8071,12 @@ fn genBinOp(
7968 .immediate,8071 .immediate,
7969 .eflags,8072 .eflags,
7970 .register_offset,8073 .register_offset,
8074 .load_symbol,
8075 .lea_symbol,
7971 .load_direct,8076 .load_direct,
7972 .lea_direct,8077 .lea_direct,
7973 .load_got,8078 .load_got,
7974 .lea_got,8079 .lea_got,
7975 .load_extern_got,
7976 .lea_extern_got,
7977 .load_tlv,8080 .load_tlv,
7978 .lea_tlv,8081 .lea_tlv,
7979 .lea_frame,8082 .lea_frame,
...@@ -8026,12 +8129,12 @@ fn genBinOp(...@@ -8026,12 +8129,12 @@ fn genBinOp(
8026 .register_pair,8129 .register_pair,
8027 .register_offset,8130 .register_offset,
8028 .register_overflow,8131 .register_overflow,
8132 .load_symbol,
8133 .lea_symbol,
8029 .load_direct,8134 .load_direct,
8030 .lea_direct,8135 .lea_direct,
8031 .load_got,8136 .load_got,
8032 .lea_got,8137 .lea_got,
8033 .load_extern_got,
8034 .lea_extern_got,
8035 .load_tlv,8138 .load_tlv,
8036 .lea_tlv,8139 .lea_tlv,
8037 .lea_frame,8140 .lea_frame,
...@@ -9159,9 +9262,9 @@ fn genBinOpMir(...@@ -9159,9 +9262,9 @@ fn genBinOpMir(
9159 .register_overflow,9262 .register_overflow,
9160 .lea_direct,9263 .lea_direct,
9161 .lea_got,9264 .lea_got,
9162 .lea_extern_got,
9163 .lea_tlv,9265 .lea_tlv,
9164 .lea_frame,9266 .lea_frame,
9267 .lea_symbol,
9165 .reserved_frame,9268 .reserved_frame,
9166 .air_ref,9269 .air_ref,
9167 => unreachable, // unmodifiable destination9270 => unreachable, // unmodifiable destination
...@@ -9244,12 +9347,12 @@ fn genBinOpMir(...@@ -9244,12 +9347,12 @@ fn genBinOpMir(
9244 .register_offset,9347 .register_offset,
9245 .memory,9348 .memory,
9246 .indirect,9349 .indirect,
9350 .load_symbol,
9351 .lea_symbol,
9247 .load_direct,9352 .load_direct,
9248 .lea_direct,9353 .lea_direct,
9249 .load_got,9354 .load_got,
9250 .lea_got,9355 .lea_got,
9251 .load_extern_got,
9252 .lea_extern_got,
9253 .load_tlv,9356 .load_tlv,
9254 .lea_tlv,9357 .lea_tlv,
9255 .load_frame,9358 .load_frame,
...@@ -9280,9 +9383,9 @@ fn genBinOpMir(...@@ -9280,9 +9383,9 @@ fn genBinOpMir(
9280 switch (src_mcv) {9383 switch (src_mcv) {
9281 .eflags,9384 .eflags,
9282 .register_offset,9385 .register_offset,
9386 .lea_symbol,
9283 .lea_direct,9387 .lea_direct,
9284 .lea_got,9388 .lea_got,
9285 .lea_extern_got,
9286 .lea_tlv,9389 .lea_tlv,
9287 .lea_frame,9390 .lea_frame,
9288 => {9391 => {
...@@ -9296,9 +9399,9 @@ fn genBinOpMir(...@@ -9296,9 +9399,9 @@ fn genBinOpMir(
9296 );9399 );
9297 },9400 },
9298 .memory,9401 .memory,
9402 .load_symbol,
9299 .load_direct,9403 .load_direct,
9300 .load_got,9404 .load_got,
9301 .load_extern_got,
9302 .load_tlv,9405 .load_tlv,
9303 => {9406 => {
9304 const ptr_ty = try mod.singleConstPtrType(ty);9407 const ptr_ty = try mod.singleConstPtrType(ty);
...@@ -9319,13 +9422,13 @@ fn genBinOpMir(...@@ -9319,13 +9422,13 @@ fn genBinOpMir(
9319 }9422 }
9320 }9423 }
9321 },9424 },
9322 .memory, .indirect, .load_got, .load_extern_got, .load_direct, .load_tlv, .load_frame => {9425 .memory, .indirect, .load_symbol, .load_got, .load_direct, .load_tlv, .load_frame => {
9323 const OpInfo = ?struct { addr_reg: Register, addr_lock: RegisterLock };9426 const OpInfo = ?struct { addr_reg: Register, addr_lock: RegisterLock };
9324 const limb_abi_size: u32 = @min(abi_size, 8);9427 const limb_abi_size: u32 = @min(abi_size, 8);
93259428
9326 const dst_info: OpInfo = switch (dst_mcv) {9429 const dst_info: OpInfo = switch (dst_mcv) {
9327 else => unreachable,9430 else => unreachable,
9328 .memory, .load_got, .load_extern_got, .load_direct, .load_tlv => dst: {9431 .memory, .load_symbol, .load_got, .load_direct, .load_tlv => dst: {
9329 const dst_addr_reg =9432 const dst_addr_reg =
9330 (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64();9433 (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64();
9331 const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);9434 const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);
...@@ -9359,17 +9462,17 @@ fn genBinOpMir(...@@ -9359,17 +9462,17 @@ fn genBinOpMir(
9359 .indirect,9462 .indirect,
9360 .lea_direct,9463 .lea_direct,
9361 .lea_got,9464 .lea_got,
9362 .lea_extern_got,
9363 .lea_tlv,9465 .lea_tlv,
9364 .load_frame,9466 .load_frame,
9365 .lea_frame,9467 .lea_frame,
9468 .lea_symbol,
9366 => null,9469 => null,
9367 .memory, .load_got, .load_extern_got, .load_direct, .load_tlv => src: {9470 .memory, .load_symbol, .load_got, .load_direct, .load_tlv => src: {
9368 switch (resolved_src_mcv) {9471 switch (resolved_src_mcv) {
9369 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr))) != null and9472 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr))) != null and
9370 math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null)9473 math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null)
9371 break :src null,9474 break :src null,
9372 .load_got, .load_extern_got, .load_direct, .load_tlv => {},9475 .load_symbol, .load_got, .load_direct, .load_tlv => {},
9373 else => unreachable,9476 else => unreachable,
9374 }9477 }
93759478
...@@ -9411,8 +9514,8 @@ fn genBinOpMir(...@@ -9411,8 +9514,8 @@ fn genBinOpMir(
9411 Memory.PtrSize.fromSize(limb_abi_size),9514 Memory.PtrSize.fromSize(limb_abi_size),
9412 switch (dst_mcv) {9515 switch (dst_mcv) {
9413 .memory,9516 .memory,
9517 .load_symbol,
9414 .load_got,9518 .load_got,
9415 .load_extern_got,
9416 .load_direct,9519 .load_direct,
9417 .load_tlv,9520 .load_tlv,
9418 => .{ .base = .{ .reg = dst_info.?.addr_reg }, .disp = off },9521 => .{ .base = .{ .reg = dst_info.?.addr_reg }, .disp = off },
...@@ -9493,12 +9596,12 @@ fn genBinOpMir(...@@ -9493,12 +9596,12 @@ fn genBinOpMir(
9493 .eflags,9596 .eflags,
9494 .memory,9597 .memory,
9495 .indirect,9598 .indirect,
9599 .load_symbol,
9600 .lea_symbol,
9496 .load_direct,9601 .load_direct,
9497 .lea_direct,9602 .lea_direct,
9498 .load_got,9603 .load_got,
9499 .lea_got,9604 .lea_got,
9500 .load_extern_got,
9501 .lea_extern_got,
9502 .load_tlv,9605 .load_tlv,
9503 .lea_tlv,9606 .lea_tlv,
9504 .load_frame,9607 .load_frame,
...@@ -9512,9 +9615,9 @@ fn genBinOpMir(...@@ -9512,9 +9615,9 @@ fn genBinOpMir(
9512 },9615 },
9513 .eflags,9616 .eflags,
9514 .register_offset,9617 .register_offset,
9618 .lea_symbol,
9515 .lea_direct,9619 .lea_direct,
9516 .lea_got,9620 .lea_got,
9517 .lea_extern_got,
9518 .lea_tlv,9621 .lea_tlv,
9519 .lea_frame,9622 .lea_frame,
9520 => switch (limb_i) {9623 => switch (limb_i) {
...@@ -9563,9 +9666,9 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -9563,9 +9666,9 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
9563 .eflags,9666 .eflags,
9564 .register_offset,9667 .register_offset,
9565 .register_overflow,9668 .register_overflow,
9669 .lea_symbol,
9566 .lea_direct,9670 .lea_direct,
9567 .lea_got,9671 .lea_got,
9568 .lea_extern_got,
9569 .lea_tlv,9672 .lea_tlv,
9570 .lea_frame,9673 .lea_frame,
9571 .reserved_frame,9674 .reserved_frame,
...@@ -9610,12 +9713,12 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -9610,12 +9713,12 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
9610 },9713 },
9611 .register_offset,9714 .register_offset,
9612 .eflags,9715 .eflags,
9716 .load_symbol,
9717 .lea_symbol,
9613 .load_direct,9718 .load_direct,
9614 .lea_direct,9719 .lea_direct,
9615 .load_got,9720 .load_got,
9616 .lea_got,9721 .lea_got,
9617 .load_extern_got,
9618 .lea_extern_got,
9619 .load_tlv,9722 .load_tlv,
9620 .lea_tlv,9723 .lea_tlv,
9621 .lea_frame,9724 .lea_frame,
...@@ -9654,7 +9757,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -9654,7 +9757,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
9654 }9757 }
9655 },9758 },
9656 .register_pair => unreachable, // unimplemented9759 .register_pair => unreachable, // unimplemented
9657 .memory, .indirect, .load_direct, .load_got, .load_extern_got, .load_tlv, .load_frame => {9760 .memory, .indirect, .load_symbol, .load_direct, .load_got, .load_tlv, .load_frame => {
9658 const tmp_reg = try self.copyToTmpRegister(dst_ty, dst_mcv);9761 const tmp_reg = try self.copyToTmpRegister(dst_ty, dst_mcv);
9659 const tmp_mcv = MCValue{ .register = tmp_reg };9762 const tmp_mcv = MCValue{ .register = tmp_reg };
9660 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);9763 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
...@@ -9674,17 +9777,25 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -9674,17 +9777,25 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
9674 self.arg_index = arg_index + 1;9777 self.arg_index = arg_index + 1;
96759778
9676 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {9779 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {
9677 const dst_mcv = self.args[arg_index];9780 const arg_ty = self.typeOfIndex(inst);
9678 switch (dst_mcv) {9781 const src_mcv = self.args[arg_index];
9679 .register, .register_pair, .load_frame => for (dst_mcv.getRegs()) |reg|9782 const dst_mcv = switch (src_mcv) {
9680 self.register_manager.getRegAssumeFree(reg, inst),9783 .register, .register_pair, .load_frame => dst: {
9681 else => return self.fail("TODO implement arg for {}", .{dst_mcv}),9784 for (src_mcv.getRegs()) |reg| self.register_manager.getRegAssumeFree(reg, inst);
9682 }9785 break :dst src_mcv;
9786 },
9787 .indirect => |reg_off| dst: {
9788 self.register_manager.getRegAssumeFree(reg_off.reg, inst);
9789 const dst_mcv = try self.allocRegOrMem(inst, false);
9790 try self.genCopy(arg_ty, dst_mcv, src_mcv);
9791 break :dst dst_mcv;
9792 },
9793 else => return self.fail("TODO implement arg for {}", .{src_mcv}),
9794 };
96839795
9684 const ty = self.typeOfIndex(inst);
9685 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;9796 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
9686 const name = mod.getParamName(self.owner.func_index, src_index);9797 const name = mod.getParamName(self.owner.func_index, src_index);
9687 try self.genArgDbgInfo(ty, name, dst_mcv);9798 try self.genArgDbgInfo(arg_ty, name, src_mcv);
96889799
9689 break :result dst_mcv;9800 break :result dst_mcv;
9690 };9801 };
...@@ -9746,8 +9857,8 @@ fn genVarDbgInfo(...@@ -9746,8 +9857,8 @@ fn genVarDbgInfo(
9746 // .offset = -off,9857 // .offset = -off,
9747 //} },9858 //} },
9748 .memory => |address| .{ .memory = address },9859 .memory => |address| .{ .memory = address },
9860 .load_symbol => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } }, // TODO
9749 .load_got => |sym_index| .{ .linker_load = .{ .type = .got, .sym_index = sym_index } },9861 .load_got => |sym_index| .{ .linker_load = .{ .type = .got, .sym_index = sym_index } },
9750 .load_extern_got => |sym_index| .{ .linker_load = .{ .type = .extern_got, .sym_index = sym_index } },
9751 .load_direct => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } },9862 .load_direct => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } },
9752 .immediate => |x| .{ .immediate = x },9863 .immediate => |x| .{ .immediate = x },
9753 .undef => .undef,9864 .undef => .undef,
...@@ -9863,7 +9974,8 @@ fn genCall(self: *Self, info: union(enum) {...@@ -9863,7 +9974,8 @@ fn genCall(self: *Self, info: union(enum) {
98639974
9864 const ExpectedContents = extern struct {9975 const ExpectedContents = extern struct {
9865 var_args: [16][@sizeOf(Type)]u8 align(@alignOf(Type)),9976 var_args: [16][@sizeOf(Type)]u8 align(@alignOf(Type)),
9866 arg_regs: [16][@sizeOf(?RegisterLock)]u8 align(@alignOf(?RegisterLock)),9977 frame_indices: [16]FrameIndex,
9978 reg_locks: [16][@sizeOf(?RegisterLock)]u8 align(@alignOf(?RegisterLock)),
9867 };9979 };
9868 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =9980 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
9869 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);9981 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
...@@ -9873,10 +9985,13 @@ fn genCall(self: *Self, info: union(enum) {...@@ -9873,10 +9985,13 @@ fn genCall(self: *Self, info: union(enum) {
9873 defer allocator.free(var_args);9985 defer allocator.free(var_args);
9874 for (var_args, arg_types[fn_info.param_types.len..]) |*var_arg, arg_ty| var_arg.* = arg_ty;9986 for (var_args, arg_types[fn_info.param_types.len..]) |*var_arg, arg_ty| var_arg.* = arg_ty;
98759987
9876 var arg_locks = std.ArrayList(?RegisterLock).init(allocator);9988 const frame_indices = try allocator.alloc(FrameIndex, args.len);
9877 defer arg_locks.deinit();9989 defer allocator.free(frame_indices);
9878 try arg_locks.ensureTotalCapacity(16);9990
9879 defer for (arg_locks.items) |arg_lock| if (arg_lock) |lock| self.register_manager.unlockReg(lock);9991 var reg_locks = std.ArrayList(?RegisterLock).init(allocator);
9992 defer reg_locks.deinit();
9993 try reg_locks.ensureTotalCapacity(16);
9994 defer for (reg_locks.items) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock);
98809995
9881 var call_info = try self.resolveCallingConventionValues(fn_info, var_args, .call_frame);9996 var call_info = try self.resolveCallingConventionValues(fn_info, var_args, .call_frame);
9882 defer call_info.deinit(self);9997 defer call_info.deinit(self);
...@@ -9908,44 +10023,69 @@ fn genCall(self: *Self, info: union(enum) {...@@ -9908,44 +10023,69 @@ fn genCall(self: *Self, info: union(enum) {
9908 .indirect => |reg_off| try self.spillRegisters(&.{reg_off.reg}),10023 .indirect => |reg_off| try self.spillRegisters(&.{reg_off.reg}),
9909 else => unreachable,10024 else => unreachable,
9910 }10025 }
9911 for (call_info.args, arg_types, args) |dst_arg, arg_ty, src_arg| switch (dst_arg) {10026 for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, *frame_index|
9912 .none => {},10027 switch (dst_arg) {
9913 .register => |reg| {10028 .none => {},
9914 try self.spillRegisters(&.{reg});10029 .register => |reg| {
9915 try arg_locks.append(self.register_manager.lockReg(reg));10030 try self.spillRegisters(&.{reg});
9916 },10031 try reg_locks.append(self.register_manager.lockReg(reg));
9917 .register_pair => |regs| {10032 },
9918 try self.spillRegisters(&regs);10033 .register_pair => |regs| {
9919 try arg_locks.appendSlice(&self.register_manager.lockRegs(2, regs));10034 try self.spillRegisters(&regs);
9920 },10035 try reg_locks.appendSlice(&self.register_manager.lockRegs(2, regs));
9921 .load_frame => {10036 },
9922 try self.genCopy(arg_ty, dst_arg, src_arg);10037 .indirect => |reg_off| {
9923 try self.freeValue(src_arg);10038 frame_index.* = try self.allocFrameIndex(FrameAlloc.initType(arg_ty, mod));
9924 },10039 try self.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg);
9925 else => unreachable,10040 try self.spillRegisters(&.{reg_off.reg});
9926 };10041 try reg_locks.append(self.register_manager.lockReg(reg_off.reg));
10042 },
10043 .load_frame => {
10044 try self.genCopy(arg_ty, dst_arg, src_arg);
10045 try self.freeValue(src_arg);
10046 },
10047 else => unreachable,
10048 };
992710049
9928 // now we are free to set register arguments10050 // now we are free to set register arguments
9929 const ret_lock = switch (call_info.return_value.long) {10051 switch (call_info.return_value.long) {
9930 .none, .unreach => null,10052 .none, .unreach => {},
9931 .indirect => |reg_off| lock: {10053 .indirect => |reg_off| {
9932 const ret_ty = fn_info.return_type.toType();10054 const ret_ty = fn_info.return_type.toType();
9933 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, mod));10055 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, mod));
9934 try self.genSetReg(reg_off.reg, Type.usize, .{10056 try self.genSetReg(reg_off.reg, Type.usize, .{
9935 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },10057 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
9936 });10058 });
9937 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };10059 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };
9938 break :lock self.register_manager.lockRegAssumeUnused(reg_off.reg);10060 try reg_locks.append(self.register_manager.lockReg(reg_off.reg));
9939 },10061 },
9940 else => unreachable,10062 else => unreachable,
9941 };10063 }
9942 defer if (ret_lock) |lock| self.register_manager.unlockReg(lock);
994310064
9944 for (call_info.args, arg_types, args) |dst_arg, arg_ty, src_arg| switch (dst_arg) {10065 for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, frame_index|
9945 .none, .load_frame => {},10066 switch (dst_arg) {
9946 .register, .register_pair => try self.genCopy(arg_ty, dst_arg, src_arg),10067 .none, .load_frame => {},
9947 else => unreachable,10068 .register => |dst_reg| switch (fn_info.cc) {
9948 };10069 else => try self.genSetReg(
10070 registerAlias(dst_reg, @intCast(arg_ty.abiSize(mod))),
10071 arg_ty,
10072 src_arg,
10073 ),
10074 .C, .SysV, .Win64 => {
10075 const promoted_ty = self.promoteInt(arg_ty);
10076 const promoted_abi_size: u32 = @intCast(promoted_ty.abiSize(mod));
10077 const dst_alias = registerAlias(dst_reg, promoted_abi_size);
10078 try self.genSetReg(dst_alias, promoted_ty, src_arg);
10079 if (promoted_ty.toIntern() != arg_ty.toIntern())
10080 try self.truncateRegister(arg_ty, dst_alias);
10081 },
10082 },
10083 .register_pair => try self.genCopy(arg_ty, dst_arg, src_arg),
10084 .indirect => |reg_off| try self.genSetReg(reg_off.reg, Type.usize, .{
10085 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
10086 }),
10087 else => unreachable,
10088 };
994910089
9950 if (fn_info.is_var_args)10090 if (fn_info.is_var_args)
9951 try self.asmRegisterImmediate(.{ ._, .mov }, .al, Immediate.u(call_info.fp_count));10091 try self.asmRegisterImmediate(.{ ._, .mov }, .al, Immediate.u(call_info.fp_count));
...@@ -9969,12 +10109,12 @@ fn genCall(self: *Self, info: union(enum) {...@@ -9969,12 +10109,12 @@ fn genCall(self: *Self, info: union(enum) {
9969 const sym = elf_file.symbol(sym_index);10109 const sym = elf_file.symbol(sym_index);
9970 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);10110 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
9971 if (self.bin_file.options.pic) {10111 if (self.bin_file.options.pic) {
9972 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym.esym_index });10112 try self.genSetReg(.rax, Type.usize, .{ .load_symbol = sym.esym_index });
9973 try self.asmRegister(.{ ._, .call }, .rax);10113 try self.asmRegister(.{ ._, .call }, .rax);
9974 } else {10114 } else {
9975 _ = try self.addInst(.{10115 _ = try self.addInst(.{
9976 .tag = .call,10116 .tag = .call,
9977 .ops = .direct_got_reloc,10117 .ops = .linker_reloc,
9978 .data = .{ .reloc = .{10118 .data = .{ .reloc = .{
9979 .atom_index = try self.owner.getSymbolIndex(self),10119 .atom_index = try self.owner.getSymbolIndex(self),
9980 .sym_index = sym.esym_index,10120 .sym_index = sym.esym_index,
...@@ -10054,7 +10194,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -10054,7 +10194,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
10054 const ptr_ty = self.typeOf(un_op);10194 const ptr_ty = self.typeOf(un_op);
10055 switch (self.ret_mcv.short) {10195 switch (self.ret_mcv.short) {
10056 .none => {},10196 .none => {},
10057 .register => try self.load(self.ret_mcv.short, ptr_ty, ptr),10197 .register, .register_pair => try self.load(self.ret_mcv.short, ptr_ty, ptr),
10058 .indirect => |reg_off| try self.genSetReg(reg_off.reg, ptr_ty, ptr),10198 .indirect => |reg_off| try self.genSetReg(reg_off.reg, ptr_ty, ptr),
10059 else => unreachable,10199 else => unreachable,
10060 }10200 }
...@@ -10115,20 +10255,28 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -10115,20 +10255,28 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
10115 try self.spillEflagsIfOccupied();10255 try self.spillEflagsIfOccupied();
1011610256
10117 const lhs_mcv = try self.resolveInst(bin_op.lhs);10257 const lhs_mcv = try self.resolveInst(bin_op.lhs);
10118 const lhs_lock = switch (lhs_mcv) {10258 const lhs_locks: [2]?RegisterLock = switch (lhs_mcv) {
10119 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),10259 .register => |lhs_reg| .{ self.register_manager.lockRegAssumeUnused(lhs_reg), null },
10120 .register_offset => |ro| self.register_manager.lockRegAssumeUnused(ro.reg),10260 .register_pair => |lhs_regs| locks: {
10121 else => null,10261 const locks = self.register_manager.lockRegsAssumeUnused(2, lhs_regs);
10262 break :locks .{ locks[0], locks[1] };
10263 },
10264 .register_offset => |lhs_ro| .{
10265 self.register_manager.lockRegAssumeUnused(lhs_ro.reg),
10266 null,
10267 },
10268 else => .{null} ** 2,
10122 };10269 };
10123 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);10270 defer for (lhs_locks) |lhs_lock| if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
1012410271
10125 const rhs_mcv = try self.resolveInst(bin_op.rhs);10272 const rhs_mcv = try self.resolveInst(bin_op.rhs);
10126 const rhs_lock = switch (rhs_mcv) {10273 const rhs_locks: [2]?RegisterLock = switch (rhs_mcv) {
10127 .register => |reg| self.register_manager.lockReg(reg),10274 .register => |rhs_reg| .{ self.register_manager.lockReg(rhs_reg), null },
10128 .register_offset => |ro| self.register_manager.lockReg(ro.reg),10275 .register_pair => |rhs_regs| self.register_manager.lockRegs(2, rhs_regs),
10129 else => null,10276 .register_offset => |rhs_ro| .{ self.register_manager.lockReg(rhs_ro.reg), null },
10277 else => .{null} ** 2,
10130 };10278 };
10131 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);10279 defer for (rhs_locks) |rhs_lock| if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
1013210280
10133 switch (ty.zigTypeTag(mod)) {10281 switch (ty.zigTypeTag(mod)) {
10134 else => {10282 else => {
...@@ -10159,7 +10307,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -10159,7 +10307,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
10159 if (dst_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;10307 if (dst_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
10160 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);10308 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
1016110309
10162 const src_mcv = if (flipped) lhs_mcv else rhs_mcv;10310 const src_mcv = try self.resolveInst(if (flipped) bin_op.lhs else bin_op.rhs);
10163 const src_lock =10311 const src_lock =
10164 if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;10312 if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
10165 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);10313 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
...@@ -10191,14 +10339,14 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -10191,14 +10339,14 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
10191 .indirect,10339 .indirect,
10192 .lea_direct,10340 .lea_direct,
10193 .lea_got,10341 .lea_got,
10194 .lea_extern_got,
10195 .lea_tlv,10342 .lea_tlv,
10196 .lea_frame,10343 .lea_frame,
10344 .lea_symbol,
10197 .reserved_frame,10345 .reserved_frame,
10198 .air_ref,10346 .air_ref,
10199 => unreachable,10347 => unreachable,
10200 .register_pair, .load_frame => null,10348 .register_pair, .load_frame => null,
10201 .memory, .load_got, .load_extern_got, .load_direct, .load_tlv => dst: {10349 .memory, .load_symbol, .load_got, .load_direct, .load_tlv => dst: {
10202 switch (resolved_dst_mcv) {10350 switch (resolved_dst_mcv) {
10203 .memory => |addr| if (math.cast(10351 .memory => |addr| if (math.cast(
10204 i32,10352 i32,
...@@ -10207,7 +10355,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -10207,7 +10355,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
10207 i32,10355 i32,
10208 @as(i64, @bitCast(addr)) + abi_size - 8,10356 @as(i64, @bitCast(addr)) + abi_size - 8,
10209 ) != null) break :dst null,10357 ) != null) break :dst null,
10210 .load_got, .load_extern_got, .load_direct, .load_tlv => {},10358 .load_symbol, .load_got, .load_direct, .load_tlv => {},
10211 else => unreachable,10359 else => unreachable,
10212 }10360 }
1021310361
...@@ -10248,16 +10396,16 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -10248,16 +10396,16 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
10248 .register_offset,10396 .register_offset,
10249 .register_overflow,10397 .register_overflow,
10250 .indirect,10398 .indirect,
10399 .lea_symbol,
10251 .lea_direct,10400 .lea_direct,
10252 .lea_got,10401 .lea_got,
10253 .lea_extern_got,
10254 .lea_tlv,10402 .lea_tlv,
10255 .lea_frame,10403 .lea_frame,
10256 .reserved_frame,10404 .reserved_frame,
10257 .air_ref,10405 .air_ref,
10258 => unreachable,10406 => unreachable,
10259 .register_pair, .load_frame => null,10407 .register_pair, .load_frame => null,
10260 .memory, .load_got, .load_extern_got, .load_direct, .load_tlv => src: {10408 .memory, .load_symbol, .load_got, .load_direct, .load_tlv => src: {
10261 switch (resolved_src_mcv) {10409 switch (resolved_src_mcv) {
10262 .memory => |addr| if (math.cast(10410 .memory => |addr| if (math.cast(
10263 i32,10411 i32,
...@@ -10266,7 +10414,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -10266,7 +10414,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
10266 i32,10414 i32,
10267 @as(i64, @bitCast(addr)) + abi_size - 8,10415 @as(i64, @bitCast(addr)) + abi_size - 8,
10268 ) != null) break :src null,10416 ) != null) break :src null,
10269 .load_got, .load_extern_got, .load_direct, .load_tlv => {},10417 .load_symbol, .load_got, .load_direct, .load_tlv => {},
10270 else => unreachable,10418 else => unreachable,
10271 }10419 }
1027210420
...@@ -10350,13 +10498,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -10350,13 +10498,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
10350 },10498 },
10351 );10499 );
1035210500
10353 if (limb_i > 0) try self.asmRegisterRegister(10501 if (limb_i > 0)
10354 .{ ._, .@"or" },10502 try self.asmRegisterRegister(.{ ._, .@"or" }, acc_reg, tmp_reg);
10355 acc_reg,
10356 tmp_reg,
10357 );
10358 }10503 }
10359 try self.asmRegisterRegister(.{ ._, .@"test" }, acc_reg, acc_reg);10504 assert(limbs_len >= 2); // use flags from or
10360 break :result_op flipped_op;10505 break :result_op flipped_op;
10361 },10506 },
10362 };10507 };
...@@ -10692,9 +10837,9 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -10692,9 +10837,9 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
10692 .register_overflow,10837 .register_overflow,
10693 .lea_direct,10838 .lea_direct,
10694 .lea_got,10839 .lea_got,
10695 .lea_extern_got,
10696 .lea_tlv,10840 .lea_tlv,
10697 .lea_frame,10841 .lea_frame,
10842 .lea_symbol,
10698 .reserved_frame,10843 .reserved_frame,
10699 .air_ref,10844 .air_ref,
10700 => unreachable,10845 => unreachable,
...@@ -10718,8 +10863,8 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -10718,8 +10863,8 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
10718 },10863 },
1071910864
10720 .memory,10865 .memory,
10866 .load_symbol,
10721 .load_got,10867 .load_got,
10722 .load_extern_got,
10723 .load_direct,10868 .load_direct,
10724 .load_tlv,10869 .load_tlv,
10725 => {10870 => {
...@@ -11316,7 +11461,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -11316,7 +11461,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
11316 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|11461 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
11317 break :arg input_mcv,11462 break :arg input_mcv,
11318 .indirect, .load_frame => break :arg input_mcv,11463 .indirect, .load_frame => break :arg input_mcv,
11319 .load_direct, .load_got, .load_extern_got, .load_tlv => {},11464 .load_symbol, .load_direct, .load_got, .load_tlv => {},
11320 else => {11465 else => {
11321 const temp_mcv = try self.allocTempRegOrMem(ty, false);11466 const temp_mcv = try self.allocTempRegOrMem(ty, false);
11322 try self.genCopy(ty, temp_mcv, input_mcv);11467 try self.genCopy(ty, temp_mcv, input_mcv);
...@@ -11578,6 +11723,10 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -11578,6 +11723,10 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
11578 .{ .reg = try self.copyToTmpRegister(Type.usize, .{ .lea_got = sym_index }) }11723 .{ .reg = try self.copyToTmpRegister(Type.usize, .{ .lea_got = sym_index }) }
11579 else11724 else
11580 return self.fail("invalid modifier: '{s}'", .{modifier}),11725 return self.fail("invalid modifier: '{s}'", .{modifier}),
11726 .load_symbol => |sym_index| if (mem.eql(u8, modifier, "P"))
11727 .{ .reg = try self.copyToTmpRegister(Type.usize, .{ .load_symbol = sym_index }) }
11728 else
11729 return self.fail("invalid modifier: '{s}'", .{modifier}),
11581 else => return self.fail("invalid constraint: '{s}'", .{op_str}),11730 else => return self.fail("invalid constraint: '{s}'", .{op_str}),
11582 };11731 };
11583 } else if (mem.startsWith(u8, op_str, "$")) {11732 } else if (mem.startsWith(u8, op_str, "$")) {
...@@ -11798,6 +11947,7 @@ const MoveStrategy = union(enum) {...@@ -11798,6 +11947,7 @@ const MoveStrategy = union(enum) {
11798 .move => |tag| try self.asmRegisterMemory(tag, dst_reg, src_mem),11947 .move => |tag| try self.asmRegisterMemory(tag, dst_reg, src_mem),
11799 .x87_load_store => {11948 .x87_load_store => {
11800 try self.asmMemory(.{ .f_, .ld }, src_mem);11949 try self.asmMemory(.{ .f_, .ld }, src_mem);
11950 assert(dst_reg != .st7);
11801 try self.asmRegister(.{ .f_p, .st }, @enumFromInt(@intFromEnum(dst_reg) + 1));11951 try self.asmRegister(.{ .f_p, .st }, @enumFromInt(@intFromEnum(dst_reg) + 1));
11802 },11952 },
11803 .insert_extract => |ie| try self.asmRegisterMemoryImmediate(11953 .insert_extract => |ie| try self.asmRegisterMemoryImmediate(
...@@ -11831,188 +11981,284 @@ const MoveStrategy = union(enum) {...@@ -11831,188 +11981,284 @@ const MoveStrategy = union(enum) {
11831 }11981 }
11832 }11982 }
11833};11983};
11834fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {11984fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !MoveStrategy {
11835 const mod = self.bin_file.options.module.?;11985 const mod = self.bin_file.options.module.?;
11836 switch (ty.zigTypeTag(mod)) {11986 switch (class) {
11837 else => return .{ .move = .{ ._, .mov } },11987 .general_purpose, .segment => return .{ .move = .{ ._, .mov } },
11838 .Float => switch (ty.floatBits(self.target.*)) {11988 .x87 => return .x87_load_store,
11839 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{11989 .mmx => {},
11840 .insert = .{ .vp_w, .insr },11990 .sse => {
11841 .extract = .{ .vp_w, .extr },11991 switch (ty.zigTypeTag(mod)) {
11842 } } else .{ .insert_extract = .{11992 else => {
11843 .insert = .{ .p_w, .insr },11993 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none);
11844 .extract = .{ .p_w, .extr },11994 assert(std.mem.indexOfNone(abi.Class, classes, &.{
11845 } },11995 .integer, .sse, .float, .float_combine,
11846 32 => return .{ .move = if (self.hasFeature(.avx)) .{ .v_ss, .mov } else .{ ._ss, .mov } },11996 }) == null);
11847 64 => return .{ .move = if (self.hasFeature(.avx)) .{ .v_sd, .mov } else .{ ._sd, .mov } },11997 const abi_size = ty.abiSize(mod);
11848 80 => return .x87_load_store,11998 if (abi_size < 4 or
11849 128 => return .{ .move = if (self.hasFeature(.avx))11999 std.mem.indexOfScalar(abi.Class, classes, .integer) != null) switch (abi_size) {
11850 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }12000 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{
11851 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },12001 .insert = .{ .vp_b, .insr },
11852 else => {},12002 .extract = .{ .vp_b, .extr },
11853 },12003 } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{
11854 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {12004 .insert = .{ .p_b, .insr },
11855 .Bool => return .{ .move = .{ ._, .mov } },12005 .extract = .{ .p_b, .extr },
11856 .Int => switch (ty.childType(mod).intInfo(mod).bits) {12006 } },
11857 8 => switch (ty.vectorLen(mod)) {12007 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
11858 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{12008 .insert = .{ .vp_w, .insr },
11859 .insert = .{ .vp_b, .insr },12009 .extract = .{ .vp_w, .extr },
11860 .extract = .{ .vp_b, .extr },12010 } } else .{ .insert_extract = .{
11861 } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{12011 .insert = .{ .p_w, .insr },
11862 .insert = .{ .p_b, .insr },12012 .extract = .{ .p_w, .extr },
11863 .extract = .{ .p_b, .extr },12013 } },
11864 } },12014 3...4 => return .{ .move = if (self.hasFeature(.avx))
11865 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{12015 .{ .v_d, .mov }
11866 .insert = .{ .vp_w, .insr },12016 else
11867 .extract = .{ .vp_w, .extr },12017 .{ ._d, .mov } },
11868 } } else .{ .insert_extract = .{12018 5...8 => return .{ .move = if (self.hasFeature(.avx))
11869 .insert = .{ .p_w, .insr },12019 .{ .v_q, .mov }
11870 .extract = .{ .p_w, .extr },12020 else
11871 } },12021 .{ ._q, .mov } },
11872 3...4 => return .{ .move = if (self.hasFeature(.avx))12022 9...16 => return .{ .move = if (self.hasFeature(.avx))
11873 .{ .v_d, .mov }12023 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11874 else12024 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11875 .{ ._d, .mov } },12025 17...32 => if (self.hasFeature(.avx))
11876 5...8 => return .{ .move = if (self.hasFeature(.avx))12026 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
11877 .{ .v_q, .mov }12027 else => {},
11878 else12028 } else switch (abi_size) {
11879 .{ ._q, .mov } },12029 4 => return .{ .move = if (self.hasFeature(.avx))
11880 9...16 => return .{ .move = if (self.hasFeature(.avx))12030 .{ .v_ss, .mov }
11881 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }12031 else
11882 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },12032 .{ ._ss, .mov } },
11883 17...32 => if (self.hasFeature(.avx))12033 5...8 => return .{ .move = if (self.hasFeature(.avx))
11884 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },12034 .{ .v_sd, .mov }
11885 else => {},12035 else
11886 },12036 .{ ._sd, .mov } },
11887 16 => switch (ty.vectorLen(mod)) {12037 9...16 => return .{ .move = if (self.hasFeature(.avx))
11888 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{12038 if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu }
11889 .insert = .{ .vp_w, .insr },12039 else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } },
11890 .extract = .{ .vp_w, .extr },12040 17...32 => if (self.hasFeature(.avx)) return .{ .move = if (aligned)
11891 } } else .{ .insert_extract = .{12041 .{ .v_pd, .mova }
11892 .insert = .{ .p_w, .insr },12042 else
11893 .extract = .{ .p_w, .extr },12043 .{ .v_pd, .movu } },
11894 } },12044 else => {},
11895 2 => return .{ .move = if (self.hasFeature(.avx))12045 }
11896 .{ .v_d, .mov }
11897 else
11898 .{ ._d, .mov } },
11899 3...4 => return .{ .move = if (self.hasFeature(.avx))
11900 .{ .v_q, .mov }
11901 else
11902 .{ ._q, .mov } },
11903 5...8 => return .{ .move = if (self.hasFeature(.avx))
11904 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11905 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11906 9...16 => if (self.hasFeature(.avx))
11907 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
11908 else => {},
11909 },
11910 32 => switch (ty.vectorLen(mod)) {
11911 1 => return .{ .move = if (self.hasFeature(.avx))
11912 .{ .v_d, .mov }
11913 else
11914 .{ ._d, .mov } },
11915 2 => return .{ .move = if (self.hasFeature(.avx))
11916 .{ .v_q, .mov }
11917 else
11918 .{ ._q, .mov } },
11919 3...4 => return .{ .move = if (self.hasFeature(.avx))
11920 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11921 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11922 5...8 => if (self.hasFeature(.avx))
11923 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
11924 else => {},
11925 },
11926 64 => switch (ty.vectorLen(mod)) {
11927 1 => return .{ .move = if (self.hasFeature(.avx))
11928 .{ .v_q, .mov }
11929 else
11930 .{ ._q, .mov } },
11931 2 => return .{ .move = if (self.hasFeature(.avx))
11932 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11933 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11934 3...4 => if (self.hasFeature(.avx))
11935 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
11936 else => {},
11937 },
11938 128 => switch (ty.vectorLen(mod)) {
11939 1 => return .{ .move = if (self.hasFeature(.avx))
11940 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11941 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11942 2 => if (self.hasFeature(.avx))
11943 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
11944 else => {},
11945 },
11946 256 => switch (ty.vectorLen(mod)) {
11947 1 => if (self.hasFeature(.avx))
11948 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
11949 else => {},
11950 },12046 },
11951 else => {},12047 .Float => switch (ty.floatBits(self.target.*)) {
11952 },12048 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
11953 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
11954 16 => switch (ty.vectorLen(mod)) {
11955 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
11956 .insert = .{ .vp_w, .insr },12049 .insert = .{ .vp_w, .insr },
11957 .extract = .{ .vp_w, .extr },12050 .extract = .{ .vp_w, .extr },
11958 } } else .{ .insert_extract = .{12051 } } else .{ .insert_extract = .{
11959 .insert = .{ .p_w, .insr },12052 .insert = .{ .p_w, .insr },
11960 .extract = .{ .p_w, .extr },12053 .extract = .{ .p_w, .extr },
11961 } },12054 } },
11962 2 => return .{ .move = if (self.hasFeature(.avx))12055 32 => return .{ .move = if (self.hasFeature(.avx))
11963 .{ .v_d, .mov }
11964 else
11965 .{ ._d, .mov } },
11966 3...4 => return .{ .move = if (self.hasFeature(.avx))
11967 .{ .v_q, .mov }
11968 else
11969 .{ ._q, .mov } },
11970 5...8 => return .{ .move = if (self.hasFeature(.avx))
11971 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11972 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11973 9...16 => if (self.hasFeature(.avx))
11974 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
11975 else => {},
11976 },
11977 32 => switch (ty.vectorLen(mod)) {
11978 1 => return .{ .move = if (self.hasFeature(.avx))
11979 .{ .v_ss, .mov }12056 .{ .v_ss, .mov }
11980 else12057 else
11981 .{ ._ss, .mov } },12058 .{ ._ss, .mov } },
11982 2 => return .{ .move = if (self.hasFeature(.avx))12059 64 => return .{ .move = if (self.hasFeature(.avx))
11983 .{ .v_sd, .mov }
11984 else
11985 .{ ._sd, .mov } },
11986 3...4 => return .{ .move = if (self.hasFeature(.avx))
11987 if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu }
11988 else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu } },
11989 5...8 => if (self.hasFeature(.avx))
11990 return .{ .move = if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu } },
11991 else => {},
11992 },
11993 64 => switch (ty.vectorLen(mod)) {
11994 1 => return .{ .move = if (self.hasFeature(.avx))
11995 .{ .v_sd, .mov }12060 .{ .v_sd, .mov }
11996 else12061 else
11997 .{ ._sd, .mov } },12062 .{ ._sd, .mov } },
11998 2 => return .{ .move = if (self.hasFeature(.avx))12063 128 => return .{ .move = if (self.hasFeature(.avx))
11999 if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu }
12000 else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } },
12001 3...4 => if (self.hasFeature(.avx))
12002 return .{ .move = if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu } },
12003 else => {},
12004 },
12005 128 => switch (ty.vectorLen(mod)) {
12006 1 => return .{ .move = if (self.hasFeature(.avx))
12007 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }12064 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12008 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },12065 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12009 2 => if (self.hasFeature(.avx))
12010 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
12011 else => {},12066 else => {},
12012 },12067 },
12013 else => {},12068 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
12014 },12069 .Bool => return .{ .move = .{ ._, .mov } },
12015 else => {},12070 .Int => switch (ty.childType(mod).intInfo(mod).bits) {
12071 8 => switch (ty.vectorLen(mod)) {
12072 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{
12073 .insert = .{ .vp_b, .insr },
12074 .extract = .{ .vp_b, .extr },
12075 } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{
12076 .insert = .{ .p_b, .insr },
12077 .extract = .{ .p_b, .extr },
12078 } },
12079 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12080 .insert = .{ .vp_w, .insr },
12081 .extract = .{ .vp_w, .extr },
12082 } } else .{ .insert_extract = .{
12083 .insert = .{ .p_w, .insr },
12084 .extract = .{ .p_w, .extr },
12085 } },
12086 3...4 => return .{ .move = if (self.hasFeature(.avx))
12087 .{ .v_d, .mov }
12088 else
12089 .{ ._d, .mov } },
12090 5...8 => return .{ .move = if (self.hasFeature(.avx))
12091 .{ .v_q, .mov }
12092 else
12093 .{ ._q, .mov } },
12094 9...16 => return .{ .move = if (self.hasFeature(.avx))
12095 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12096 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12097 17...32 => if (self.hasFeature(.avx))
12098 return .{ .move = if (aligned)
12099 .{ .v_, .movdqa }
12100 else
12101 .{ .v_, .movdqu } },
12102 else => {},
12103 },
12104 16 => switch (ty.vectorLen(mod)) {
12105 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12106 .insert = .{ .vp_w, .insr },
12107 .extract = .{ .vp_w, .extr },
12108 } } else .{ .insert_extract = .{
12109 .insert = .{ .p_w, .insr },
12110 .extract = .{ .p_w, .extr },
12111 } },
12112 2 => return .{ .move = if (self.hasFeature(.avx))
12113 .{ .v_d, .mov }
12114 else
12115 .{ ._d, .mov } },
12116 3...4 => return .{ .move = if (self.hasFeature(.avx))
12117 .{ .v_q, .mov }
12118 else
12119 .{ ._q, .mov } },
12120 5...8 => return .{ .move = if (self.hasFeature(.avx))
12121 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12122 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12123 9...16 => if (self.hasFeature(.avx))
12124 return .{ .move = if (aligned)
12125 .{ .v_, .movdqa }
12126 else
12127 .{ .v_, .movdqu } },
12128 else => {},
12129 },
12130 32 => switch (ty.vectorLen(mod)) {
12131 1 => return .{ .move = if (self.hasFeature(.avx))
12132 .{ .v_d, .mov }
12133 else
12134 .{ ._d, .mov } },
12135 2 => return .{ .move = if (self.hasFeature(.avx))
12136 .{ .v_q, .mov }
12137 else
12138 .{ ._q, .mov } },
12139 3...4 => return .{ .move = if (self.hasFeature(.avx))
12140 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12141 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12142 5...8 => if (self.hasFeature(.avx))
12143 return .{ .move = if (aligned)
12144 .{ .v_, .movdqa }
12145 else
12146 .{ .v_, .movdqu } },
12147 else => {},
12148 },
12149 64 => switch (ty.vectorLen(mod)) {
12150 1 => return .{ .move = if (self.hasFeature(.avx))
12151 .{ .v_q, .mov }
12152 else
12153 .{ ._q, .mov } },
12154 2 => return .{ .move = if (self.hasFeature(.avx))
12155 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12156 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12157 3...4 => if (self.hasFeature(.avx))
12158 return .{ .move = if (aligned)
12159 .{ .v_, .movdqa }
12160 else
12161 .{ .v_, .movdqu } },
12162 else => {},
12163 },
12164 128 => switch (ty.vectorLen(mod)) {
12165 1 => return .{ .move = if (self.hasFeature(.avx))
12166 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12167 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12168 2 => if (self.hasFeature(.avx))
12169 return .{ .move = if (aligned)
12170 .{ .v_, .movdqa }
12171 else
12172 .{ .v_, .movdqu } },
12173 else => {},
12174 },
12175 256 => switch (ty.vectorLen(mod)) {
12176 1 => if (self.hasFeature(.avx))
12177 return .{ .move = if (aligned)
12178 .{ .v_, .movdqa }
12179 else
12180 .{ .v_, .movdqu } },
12181 else => {},
12182 },
12183 else => {},
12184 },
12185 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
12186 16 => switch (ty.vectorLen(mod)) {
12187 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12188 .insert = .{ .vp_w, .insr },
12189 .extract = .{ .vp_w, .extr },
12190 } } else .{ .insert_extract = .{
12191 .insert = .{ .p_w, .insr },
12192 .extract = .{ .p_w, .extr },
12193 } },
12194 2 => return .{ .move = if (self.hasFeature(.avx))
12195 .{ .v_d, .mov }
12196 else
12197 .{ ._d, .mov } },
12198 3...4 => return .{ .move = if (self.hasFeature(.avx))
12199 .{ .v_q, .mov }
12200 else
12201 .{ ._q, .mov } },
12202 5...8 => return .{ .move = if (self.hasFeature(.avx))
12203 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12204 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12205 9...16 => if (self.hasFeature(.avx))
12206 return .{ .move = if (aligned)
12207 .{ .v_, .movdqa }
12208 else
12209 .{ .v_, .movdqu } },
12210 else => {},
12211 },
12212 32 => switch (ty.vectorLen(mod)) {
12213 1 => return .{ .move = if (self.hasFeature(.avx))
12214 .{ .v_ss, .mov }
12215 else
12216 .{ ._ss, .mov } },
12217 2 => return .{ .move = if (self.hasFeature(.avx))
12218 .{ .v_sd, .mov }
12219 else
12220 .{ ._sd, .mov } },
12221 3...4 => return .{ .move = if (self.hasFeature(.avx))
12222 if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu }
12223 else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu } },
12224 5...8 => if (self.hasFeature(.avx))
12225 return .{ .move = if (aligned)
12226 .{ .v_ps, .mova }
12227 else
12228 .{ .v_ps, .movu } },
12229 else => {},
12230 },
12231 64 => switch (ty.vectorLen(mod)) {
12232 1 => return .{ .move = if (self.hasFeature(.avx))
12233 .{ .v_sd, .mov }
12234 else
12235 .{ ._sd, .mov } },
12236 2 => return .{ .move = if (self.hasFeature(.avx))
12237 if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu }
12238 else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } },
12239 3...4 => if (self.hasFeature(.avx))
12240 return .{ .move = if (aligned)
12241 .{ .v_pd, .mova }
12242 else
12243 .{ .v_pd, .movu } },
12244 else => {},
12245 },
12246 128 => switch (ty.vectorLen(mod)) {
12247 1 => return .{ .move = if (self.hasFeature(.avx))
12248 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12249 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12250 2 => if (self.hasFeature(.avx))
12251 return .{ .move = if (aligned)
12252 .{ .v_, .movdqa }
12253 else
12254 .{ .v_, .movdqu } },
12255 else => {},
12256 },
12257 else => {},
12258 },
12259 else => {},
12260 },
12261 }
12016 },12262 },
12017 }12263 }
12018 return self.fail("TODO moveStrategy for {}", .{ty.fmt(mod)});12264 return self.fail("TODO moveStrategy for {}", .{ty.fmt(mod)});
...@@ -12034,9 +12280,9 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError...@@ -12034,9 +12280,9 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError
12034 .register_overflow,12280 .register_overflow,
12035 .lea_direct,12281 .lea_direct,
12036 .lea_got,12282 .lea_got,
12037 .lea_extern_got,
12038 .lea_tlv,12283 .lea_tlv,
12039 .lea_frame,12284 .lea_frame,
12285 .lea_symbol,
12040 .reserved_frame,12286 .reserved_frame,
12041 .air_ref,12287 .air_ref,
12042 => unreachable, // unmodifiable destination12288 => unreachable, // unmodifiable destination
...@@ -12060,37 +12306,58 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError...@@ -12060,37 +12306,58 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError
12060 } },12306 } },
12061 }),12307 }),
12062 .register_pair => |dst_regs| {12308 .register_pair => |dst_regs| {
12063 switch (src_mcv) {12309 const src_info: ?struct { addr_reg: Register, addr_lock: RegisterLock } = switch (src_mcv) {
12310 .register_pair, .memory, .indirect, .load_frame => null,
12311 .load_symbol, .load_direct, .load_got, .load_tlv => src: {
12312 const src_addr_reg =
12313 (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64();
12314 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);
12315 errdefer self.register_manager.unlockReg(src_addr_lock);
12316
12317 try self.genSetReg(src_addr_reg, Type.usize, src_mcv.address());
12318 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };
12319 },
12064 .air_ref => |src_ref| return self.genCopy(ty, dst_mcv, try self.resolveInst(src_ref)),12320 .air_ref => |src_ref| return self.genCopy(ty, dst_mcv, try self.resolveInst(src_ref)),
12065 else => {},12321 else => return self.fail("TODO implement genCopy for {s} of {}", .{
12066 }12322 @tagName(src_mcv), ty.fmt(mod),
12323 }),
12324 };
12325 defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock);
12326
12067 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none);12327 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none);
12068 for (dst_regs, classes, 0..) |dst_reg, class, dst_reg_i| {12328 for (dst_regs, classes, 0..) |dst_reg, class, dst_reg_i| {
12069 const class_ty = switch (class) {12329 const class_ty = switch (class) {
12070 .integer => Type.usize,12330 .integer => Type.usize,
12071 .sse => Type.f64,12331 .sse, .float, .float_combine => Type.f64,
12072 else => unreachable,12332 else => unreachable,
12073 };12333 };
12334 const off: i32 = @intCast(dst_reg_i * 8);
12074 switch (src_mcv) {12335 switch (src_mcv) {
12075 .register_pair => |src_regs| try self.genSetReg(12336 .register_pair => |src_regs| try self.genSetReg(
12076 dst_reg,12337 dst_reg,
12077 class_ty,12338 class_ty,
12078 .{ .register = src_regs[dst_reg_i] },12339 .{ .register = src_regs[dst_reg_i] },
12079 ),12340 ),
12080 else => try self.genSetReg(12341 .memory, .indirect, .load_frame => try self.genSetReg(
12342 dst_reg,
12343 class_ty,
12344 src_mcv.address().offset(off).deref(),
12345 ),
12346 .load_symbol, .load_direct, .load_got, .load_tlv => try self.genSetReg(
12081 dst_reg,12347 dst_reg,
12082 class_ty,12348 class_ty,
12083 src_mcv.address().offset(@intCast(dst_reg_i * 8)).deref(),12349 .{ .indirect = .{ .reg = src_info.?.addr_reg, .off = off } },
12084 ),12350 ),
12351 else => unreachable,
12085 }12352 }
12086 }12353 }
12087 },12354 },
12088 .indirect => |reg_off| try self.genSetMem(.{ .reg = reg_off.reg }, reg_off.off, ty, src_mcv),12355 .indirect => |reg_off| try self.genSetMem(.{ .reg = reg_off.reg }, reg_off.off, ty, src_mcv),
12089 .memory, .load_direct, .load_got, .load_extern_got, .load_tlv => {12356 .memory, .load_symbol, .load_direct, .load_got, .load_tlv => {
12090 switch (dst_mcv) {12357 switch (dst_mcv) {
12091 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|12358 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
12092 return self.genSetMem(.{ .reg = .ds }, small_addr, ty, src_mcv),12359 return self.genSetMem(.{ .reg = .ds }, small_addr, ty, src_mcv),
12093 .load_direct, .load_got, .load_extern_got, .load_tlv => {},12360 .load_symbol, .load_direct, .load_got, .load_tlv => {},
12094 else => unreachable,12361 else => unreachable,
12095 }12362 }
1209612363
...@@ -12157,6 +12424,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -12157,6 +12424,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
12157 registerAlias(dst_reg, abi_size),12424 registerAlias(dst_reg, abi_size),
12158 src_reg,12425 src_reg,
12159 ),12426 ),
12427 .x87, .mmx => unreachable,
12160 .sse => try self.asmRegisterRegister(12428 .sse => try self.asmRegisterRegister(
12161 switch (abi_size) {12429 switch (abi_size) {
12162 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },12430 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },
...@@ -12166,17 +12434,30 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -12166,17 +12434,30 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
12166 registerAlias(dst_reg, @max(abi_size, 4)),12434 registerAlias(dst_reg, @max(abi_size, 4)),
12167 src_reg.to128(),12435 src_reg.to128(),
12168 ),12436 ),
12169 .x87, .mmx => unreachable,
12170 },12437 },
12171 .segment => try self.asmRegisterRegister(12438 .segment => try self.asmRegisterRegister(
12172 .{ ._, .mov },12439 .{ ._, .mov },
12173 dst_reg,12440 dst_reg,
12174 switch (src_reg.class()) {12441 switch (src_reg.class()) {
12175 .general_purpose, .segment => registerAlias(src_reg, abi_size),12442 .general_purpose, .segment => registerAlias(src_reg, abi_size),
12176 .sse => try self.copyToTmpRegister(ty, src_mcv),
12177 .x87, .mmx => unreachable,12443 .x87, .mmx => unreachable,
12444 .sse => try self.copyToTmpRegister(ty, src_mcv),
12178 },12445 },
12179 ),12446 ),
12447 .x87 => switch (src_reg.class()) {
12448 .general_purpose, .segment => unreachable,
12449 .x87 => switch (src_reg) {
12450 .st0 => try self.asmRegister(.{ .f_, .st }, dst_reg),
12451 .st1, .st2, .st3, .st4, .st5, .st6 => {
12452 try self.asmRegister(.{ .f_, .ld }, src_reg);
12453 assert(dst_reg != .st7);
12454 try self.asmRegister(.{ .f_p, .st }, @enumFromInt(@intFromEnum(dst_reg) + 1));
12455 },
12456 else => unreachable,
12457 },
12458 .mmx, .sse => unreachable,
12459 },
12460 .mmx => unreachable,
12180 .sse => switch (src_reg.class()) {12461 .sse => switch (src_reg.class()) {
12181 .general_purpose => try self.asmRegisterRegister(12462 .general_purpose => try self.asmRegisterRegister(
12182 switch (abi_size) {12463 switch (abi_size) {
...@@ -12192,6 +12473,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -12192,6 +12473,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
12192 ty,12473 ty,
12193 .{ .register = try self.copyToTmpRegister(ty, src_mcv) },12474 .{ .register = try self.copyToTmpRegister(ty, src_mcv) },
12194 ),12475 ),
12476 .x87, .mmx => unreachable,
12195 .sse => try self.asmRegisterRegister(12477 .sse => try self.asmRegisterRegister(
12196 @as(?Mir.Inst.FixedTag, switch (ty.scalarType(mod).zigTypeTag(mod)) {12478 @as(?Mir.Inst.FixedTag, switch (ty.scalarType(mod).zigTypeTag(mod)) {
12197 else => switch (abi_size) {12479 else => switch (abi_size) {
...@@ -12217,9 +12499,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -12217,9 +12499,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
12217 registerAlias(dst_reg, abi_size),12499 registerAlias(dst_reg, abi_size),
12218 registerAlias(src_reg, abi_size),12500 registerAlias(src_reg, abi_size),
12219 ),12501 ),
12220 .x87, .mmx => unreachable,
12221 },12502 },
12222 .x87, .mmx => unreachable,
12223 },12503 },
12224 .register_pair => |src_regs| try self.genSetReg(dst_reg, ty, .{ .register = src_regs[0] }),12504 .register_pair => |src_regs| try self.genSetReg(dst_reg, ty, .{ .register = src_regs[0] }),
12225 .register_offset,12505 .register_offset,
...@@ -12231,9 +12511,10 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -12231,9 +12511,10 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
12231 0 => return self.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }),12511 0 => return self.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }),
12232 else => .{ .move = .{ ._, .lea } },12512 else => .{ .move = .{ ._, .lea } },
12233 },12513 },
12234 .indirect => try self.moveStrategy(ty, false),12514 .indirect => try self.moveStrategy(ty, dst_reg.class(), false),
12235 .load_frame => |frame_addr| try self.moveStrategy(12515 .load_frame => |frame_addr| try self.moveStrategy(
12236 ty,12516 ty,
12517 dst_reg.class(),
12237 self.getFrameAddrAlignment(frame_addr).compare(.gte, ty.abiAlignment(mod)),12518 self.getFrameAddrAlignment(frame_addr).compare(.gte, ty.abiAlignment(mod)),
12238 ),12519 ),
12239 .lea_frame => .{ .move = .{ ._, .lea } },12520 .lea_frame => .{ .move = .{ ._, .lea } },
...@@ -12252,18 +12533,19 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -12252,18 +12533,19 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
12252 else => unreachable,12533 else => unreachable,
12253 },12534 },
12254 )),12535 )),
12255 .memory, .load_direct, .load_got, .load_extern_got, .load_tlv => {12536 .memory, .load_symbol, .load_direct, .load_got, .load_tlv => {
12256 switch (src_mcv) {12537 switch (src_mcv) {
12257 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|12538 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
12258 return (try self.moveStrategy(12539 return (try self.moveStrategy(
12259 ty,12540 ty,
12541 dst_reg.class(),
12260 ty.abiAlignment(mod).check(@as(u32, @bitCast(small_addr))),12542 ty.abiAlignment(mod).check(@as(u32, @bitCast(small_addr))),
12261 )).read(self, registerAlias(dst_reg, abi_size), Memory.sib(12543 )).read(self, registerAlias(dst_reg, abi_size), Memory.sib(
12262 self.memPtrSize(ty),12544 self.memPtrSize(ty),
12263 .{ .base = .{ .reg = .ds }, .disp = small_addr },12545 .{ .base = .{ .reg = .ds }, .disp = small_addr },
12264 )),12546 )),
12265 .load_direct => |sym_index| switch (ty.zigTypeTag(mod)) {12547 .load_direct => |sym_index| switch (dst_reg.class()) {
12266 else => {12548 .general_purpose => {
12267 const atom_index = try self.owner.getSymbolIndex(self);12549 const atom_index = try self.owner.getSymbolIndex(self);
12268 _ = try self.addInst(.{12550 _ = try self.addInst(.{
12269 .tag = .mov,12551 .tag = .mov,
...@@ -12278,9 +12560,10 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -12278,9 +12560,10 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
12278 });12560 });
12279 return;12561 return;
12280 },12562 },
12281 .Float, .Vector => {},12563 .segment, .mmx => unreachable,
12564 .x87, .sse => {},
12282 },12565 },
12283 .load_got, .load_extern_got, .load_tlv => {},12566 .load_symbol, .load_got, .load_tlv => {},
12284 else => unreachable,12567 else => unreachable,
12285 }12568 }
1228612569
...@@ -12288,34 +12571,47 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -12288,34 +12571,47 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
12288 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);12571 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
12289 defer self.register_manager.unlockReg(addr_lock);12572 defer self.register_manager.unlockReg(addr_lock);
1229012573
12291 try (try self.moveStrategy(ty, false)).read(12574 try (try self.moveStrategy(ty, dst_reg.class(), false)).read(
12292 self,12575 self,
12293 registerAlias(dst_reg, abi_size),12576 registerAlias(dst_reg, abi_size),
12294 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .{ .reg = addr_reg } }),12577 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .{ .reg = addr_reg } }),
12295 );12578 );
12296 },12579 },
12297 .lea_direct, .lea_got, .lea_extern_got => |sym_index| {12580 .lea_symbol, .lea_direct, .lea_got => |sym_index| {
12298 const atom_index = try self.owner.getSymbolIndex(self);12581 const atom_index = try self.owner.getSymbolIndex(self);
12299 _ = try self.addInst(.{12582 if (self.bin_file.cast(link.File.Elf)) |_| {
12300 .tag = switch (src_mcv) {12583 _ = try self.addInst(.{
12301 .lea_direct => .lea,12584 .tag = .lea,
12302 .lea_got, .lea_extern_got => .mov,12585 .ops = .linker_reloc,
12303 else => unreachable,12586 .data = .{ .rx = .{
12304 },12587 .r1 = dst_reg.to64(),
12305 .ops = switch (src_mcv) {12588 .payload = try self.addExtra(Mir.Reloc{
12306 .lea_direct => .direct_reloc,12589 .atom_index = atom_index,
12307 .lea_got => .got_reloc,12590 .sym_index = sym_index,
12308 .lea_extern_got => .extern_got_reloc,12591 }),
12309 else => unreachable,12592 } },
12310 },12593 });
12311 .data = .{ .rx = .{12594 } else {
12312 .r1 = dst_reg.to64(),12595 _ = try self.addInst(.{
12313 .payload = try self.addExtra(Mir.Reloc{12596 .tag = switch (src_mcv) {
12314 .atom_index = atom_index,12597 .lea_direct => .lea,
12315 .sym_index = sym_index,12598 .lea_got => .mov,
12316 }),12599 else => unreachable,
12317 } },12600 },
12318 });12601 .ops = switch (src_mcv) {
12602 .lea_direct => .direct_reloc,
12603 .lea_got => .got_reloc,
12604 else => unreachable,
12605 },
12606 .data = .{ .rx = .{
12607 .r1 = dst_reg.to64(),
12608 .payload = try self.addExtra(Mir.Reloc{
12609 .atom_index = atom_index,
12610 .sym_index = sym_index,
12611 }),
12612 } },
12613 });
12614 }
12319 },12615 },
12320 .lea_tlv => |sym_index| {12616 .lea_tlv => |sym_index| {
12321 const atom_index = try self.owner.getSymbolIndex(self);12617 const atom_index = try self.owner.getSymbolIndex(self);
...@@ -12393,7 +12689,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal...@@ -12393,7 +12689,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
12393 },12689 },
12394 },12690 },
12395 .eflags => |cc| try self.asmSetccMemory(cc, Memory.sib(.byte, .{ .base = base, .disp = disp })),12691 .eflags => |cc| try self.asmSetccMemory(cc, Memory.sib(.byte, .{ .base = base, .disp = disp })),
12396 .register => |src_reg| try (try self.moveStrategy(ty, switch (base) {12692 .register => |src_reg| try (try self.moveStrategy(ty, src_reg.class(), switch (base) {
12397 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),12693 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12398 .reg => |reg| switch (reg) {12694 .reg => |reg| switch (reg) {
12399 .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),12695 .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
...@@ -12408,17 +12704,21 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal...@@ -12408,17 +12704,21 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
12408 registerAlias(src_reg, abi_size),12704 registerAlias(src_reg, abi_size),
12409 ),12705 ),
12410 .register_pair => |src_regs| for (src_regs, 0..) |src_reg, src_reg_i| {12706 .register_pair => |src_regs| for (src_regs, 0..) |src_reg, src_reg_i| {
12411 const part_size = @min(abi_size - src_reg_i * 8, 8);12707 const part_size: u16 = @min(abi_size - src_reg_i * 8, 8);
12412 try (try self.moveStrategy(ty, switch (base) {12708 try (try self.moveStrategy(
12413 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),12709 try mod.intType(.unsigned, part_size * 8),
12414 .reg => |reg| switch (reg) {12710 src_reg.class(),
12415 .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),12711 switch (base) {
12416 else => false,12712 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12713 .reg => |reg| switch (reg) {
12714 .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12715 else => false,
12716 },
12717 .frame => |frame_index| self.getFrameAddrAlignment(
12718 .{ .index = frame_index, .off = disp },
12719 ).compare(.gte, ty.abiAlignment(mod)),
12417 },12720 },
12418 .frame => |frame_index| self.getFrameAddrAlignment(12721 )).write(self, Memory.sib(
12419 .{ .index = frame_index, .off = disp },
12420 ).compare(.gte, ty.abiAlignment(mod)),
12421 })).write(self, Memory.sib(
12422 Memory.PtrSize.fromSize(part_size),12722 Memory.PtrSize.fromSize(part_size),
12423 .{ .base = base, .disp = disp + @as(i32, @intCast(src_reg_i * 8)) },12723 .{ .base = base, .disp = disp + @as(i32, @intCast(src_reg_i * 8)) },
12424 ), registerAlias(src_reg, part_size));12724 ), registerAlias(src_reg, part_size));
...@@ -12460,12 +12760,12 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal...@@ -12460,12 +12760,12 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
12460 .lea_direct,12760 .lea_direct,
12461 .load_got,12761 .load_got,
12462 .lea_got,12762 .lea_got,
12463 .load_extern_got,
12464 .lea_extern_got,
12465 .load_tlv,12763 .load_tlv,
12466 .lea_tlv,12764 .lea_tlv,
12467 .load_frame,12765 .load_frame,
12468 .lea_frame,12766 .lea_frame,
12767 .load_symbol,
12768 .lea_symbol,
12469 => switch (abi_size) {12769 => switch (abi_size) {
12470 0 => {},12770 0 => {},
12471 1, 2, 4, 8 => {12771 1, 2, 4, 8 => {
...@@ -12482,9 +12782,9 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal...@@ -12482,9 +12782,9 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
12482}12782}
1248312783
12484fn genInlineMemcpy(self: *Self, dst_ptr: MCValue, src_ptr: MCValue, len: MCValue) InnerError!void {12784fn genInlineMemcpy(self: *Self, dst_ptr: MCValue, src_ptr: MCValue, len: MCValue) InnerError!void {
12485 try self.spillRegisters(&.{ .rdi, .rsi, .rcx });12785 try self.spillRegisters(&.{ .rsi, .rdi, .rcx });
12486 try self.genSetReg(.rdi, Type.usize, dst_ptr);
12487 try self.genSetReg(.rsi, Type.usize, src_ptr);12786 try self.genSetReg(.rsi, Type.usize, src_ptr);
12787 try self.genSetReg(.rdi, Type.usize, dst_ptr);
12488 try self.genSetReg(.rcx, Type.usize, len);12788 try self.genSetReg(.rcx, Type.usize, len);
12489 try self.asmOpOnly(.{ .@"rep _sb", .mov });12789 try self.asmOpOnly(.{ .@"rep _sb", .mov });
12490}12790}
...@@ -12556,8 +12856,8 @@ fn genLazySymbolRef(...@@ -12556,8 +12856,8 @@ fn genLazySymbolRef(
1255612856
12557 if (self.bin_file.options.pic) {12857 if (self.bin_file.options.pic) {
12558 switch (tag) {12858 switch (tag) {
12559 .lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym.esym_index }),12859 .lea, .call => try self.genSetReg(reg, Type.usize, .{ .load_symbol = sym.esym_index }),
12560 .mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym.esym_index }),12860 .mov => try self.genSetReg(reg, Type.usize, .{ .load_symbol = sym.esym_index }),
12561 else => unreachable,12861 else => unreachable,
12562 }12862 }
12563 switch (tag) {12863 switch (tag) {
...@@ -12573,7 +12873,7 @@ fn genLazySymbolRef(...@@ -12573,7 +12873,7 @@ fn genLazySymbolRef(
12573 switch (tag) {12873 switch (tag) {
12574 .lea, .mov => _ = try self.addInst(.{12874 .lea, .mov => _ = try self.addInst(.{
12575 .tag = .mov,12875 .tag = .mov,
12576 .ops = .direct_got_reloc,12876 .ops = .linker_reloc,
12577 .data = .{ .rx = .{12877 .data = .{ .rx = .{
12578 .r1 = reg.to64(),12878 .r1 = reg.to64(),
12579 .payload = try self.addExtra(reloc),12879 .payload = try self.addExtra(reloc),
...@@ -12581,20 +12881,11 @@ fn genLazySymbolRef(...@@ -12581,20 +12881,11 @@ fn genLazySymbolRef(
12581 }),12881 }),
12582 .call => _ = try self.addInst(.{12882 .call => _ = try self.addInst(.{
12583 .tag = .call,12883 .tag = .call,
12584 .ops = .direct_got_reloc,12884 .ops = .linker_reloc,
12585 .data = .{ .reloc = reloc },12885 .data = .{ .reloc = reloc },
12586 }),12886 }),
12587 else => unreachable,12887 else => unreachable,
12588 }12888 }
12589 switch (tag) {
12590 .lea, .call => {},
12591 .mov => try self.asmRegisterMemory(
12592 .{ ._, tag },
12593 reg.to64(),
12594 Memory.sib(.qword, .{ .base = .{ .reg = reg.to64() } }),
12595 ),
12596 else => unreachable,
12597 }
12598 }12889 }
12599 } else if (self.bin_file.cast(link.File.Plan9)) |p9_file| {12890 } else if (self.bin_file.cast(link.File.Plan9)) |p9_file| {
12600 const atom_index = p9_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|12891 const atom_index = p9_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
...@@ -14481,10 +14772,11 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {...@@ -14481,10 +14772,11 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
14481 } else mcv: {14772 } else mcv: {
14482 const ip_index = Air.refToInterned(ref).?;14773 const ip_index = Air.refToInterned(ref).?;
14483 const gop = try self.const_tracking.getOrPut(self.gpa, ip_index);14774 const gop = try self.const_tracking.getOrPut(self.gpa, ip_index);
14484 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(try self.genTypedValue(.{14775 const mcv = try self.genTypedValue(.{
14485 .ty = ty,14776 .ty = ty,
14486 .val = ip_index.toValue(),14777 .val = ip_index.toValue(),
14487 }));14778 });
14779 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(mcv);
14488 break :mcv gop.value_ptr.short;14780 break :mcv gop.value_ptr.short;
14489 };14781 };
1449014782
...@@ -14531,9 +14823,9 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -14531,9 +14823,9 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
14531 .undef => .undef,14823 .undef => .undef,
14532 .immediate => |imm| .{ .immediate = imm },14824 .immediate => |imm| .{ .immediate = imm },
14533 .memory => |addr| .{ .memory = addr },14825 .memory => |addr| .{ .memory = addr },
14826 .load_symbol => |sym_index| .{ .load_symbol = sym_index },
14534 .load_direct => |sym_index| .{ .load_direct = sym_index },14827 .load_direct => |sym_index| .{ .load_direct = sym_index },
14535 .load_got => |sym_index| .{ .lea_got = sym_index },14828 .load_got => |sym_index| .{ .lea_got = sym_index },
14536 .load_extern_got => |sym_index| .{ .lea_extern_got = sym_index },
14537 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },14829 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
14538 },14830 },
14539 .fail => |msg| {14831 .fail => |msg| {
...@@ -14730,16 +15022,22 @@ fn resolveCallingConventionValues(...@@ -14730,16 +15022,22 @@ fn resolveCallingConventionValues(
14730 arg_mcv_i += 1;15022 arg_mcv_i += 1;
14731 },15023 },
14732 .sseup => assert(arg_mcv[arg_mcv_i - 1].register.class() == .sse),15024 .sseup => assert(arg_mcv[arg_mcv_i - 1].register.class() == .sse),
14733 .x87, .x87up, .complex_x87, .memory => break,15025 .x87, .x87up, .complex_x87, .memory, .win_i128 => switch (resolved_cc) {
14734 .none => unreachable,15026 .SysV => switch (class) {
14735 .win_i128 => {15027 .x87, .x87up, .complex_x87, .memory => break,
14736 const param_int_reg =15028 else => unreachable,
14737 abi.getCAbiIntParamRegs(resolved_cc)[param_int_reg_i].to64();15029 },
14738 param_int_reg_i += 1;15030 .Win64 => if (ty.abiSize(mod) > 8) {
1473915031 const param_int_reg =
14740 arg_mcv[arg_mcv_i] = .{ .indirect = .{ .reg = param_int_reg } };15032 abi.getCAbiIntParamRegs(resolved_cc)[param_int_reg_i].to64();
14741 arg_mcv_i += 1;15033 param_int_reg_i += 1;
15034
15035 arg_mcv[arg_mcv_i] = .{ .indirect = .{ .reg = param_int_reg } };
15036 arg_mcv_i += 1;
15037 } else break,
15038 else => unreachable,
14742 },15039 },
15040 .none => unreachable,
14743 } else {15041 } else {
14744 arg.* = switch (arg_mcv_i) {15042 arg.* = switch (arg_mcv_i) {
14745 else => unreachable,15043 else => unreachable,
...@@ -15017,34 +15315,32 @@ fn floatLibcAbiSuffix(ty: Type) []const u8 {...@@ -15017,34 +15315,32 @@ fn floatLibcAbiSuffix(ty: Type) []const u8 {
15017 };15315 };
15018}15316}
1501915317
15020fn promoteVarArg(self: *Self, ty: Type) Type {15318fn promoteInt(self: *Self, ty: Type) Type {
15021 const mod = self.bin_file.options.module.?;15319 const mod = self.bin_file.options.module.?;
15022 switch (ty.zigTypeTag(mod)) {15320 const int_info: InternPool.Key.IntType = switch (ty.toIntern()) {
15023 .Bool => return Type.c_int,15321 .bool_type => .{ .signedness = .unsigned, .bits = 1 },
15024 else => {15322 else => if (ty.isAbiInt(mod)) ty.intInfo(mod) else return ty,
15025 const int_info = ty.intInfo(mod);15323 };
15026 for ([_]Type{15324 for ([_]Type{
15027 Type.c_int, Type.c_uint,15325 Type.c_int, Type.c_uint,
15028 Type.c_long, Type.c_ulong,15326 Type.c_long, Type.c_ulong,
15029 Type.c_longlong, Type.c_ulonglong,15327 Type.c_longlong, Type.c_ulonglong,
15030 }) |promote_ty| {15328 }) |promote_ty| {
15031 const promote_info = promote_ty.intInfo(mod);15329 const promote_info = promote_ty.intInfo(mod);
15032 if (int_info.signedness == .signed and promote_info.signedness == .unsigned) continue;15330 if (int_info.signedness == .signed and promote_info.signedness == .unsigned) continue;
15033 if (int_info.bits + @intFromBool(int_info.signedness == .unsigned and15331 if (int_info.bits + @intFromBool(int_info.signedness == .unsigned and
15034 promote_info.signedness == .signed) <= promote_info.bits) return promote_ty;15332 promote_info.signedness == .signed) <= promote_info.bits) return promote_ty;
15035 }15333 }
15036 unreachable;15334 return ty;
15037 },15335}
15038 .Float => switch (ty.floatBits(self.target.*)) {15336
15039 32, 64 => return Type.f64,15337fn promoteVarArg(self: *Self, ty: Type) Type {
15040 else => |float_bits| {15338 if (!ty.isRuntimeFloat()) return self.promoteInt(ty);
15041 assert(float_bits == self.target.c_type_bit_size(.longdouble));15339 switch (ty.floatBits(self.target.*)) {
15042 return Type.c_longdouble;15340 32, 64 => return Type.f64,
15043 },15341 else => |float_bits| {
15044 },15342 assert(float_bits == self.target.c_type_bit_size(.longdouble));
15045 .Pointer => {15343 return Type.c_longdouble;
15046 assert(!ty.isSlice(mod));
15047 return ty;
15048 },15344 },
15049 }15345 }
15050}15346}
src/arch/x86_64/Emit.zig+31-21
...@@ -78,31 +78,41 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -78,31 +78,41 @@ pub fn emitMir(emit: *Emit) Error!void {
78 } else return emit.fail("TODO implement extern reloc for {s}", .{78 } else return emit.fail("TODO implement extern reloc for {s}", .{
79 @tagName(emit.bin_file.tag),79 @tagName(emit.bin_file.tag),
80 }),80 }),
81 .linker_reloc => |data| if (emit.bin_file.cast(link.File.Elf)) |elf_file| {
82 const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;
83 const sym = elf_file.symbol(elf_file.zigModulePtr().symbol(data.sym_index));
84 if (emit.bin_file.options.pic) {
85 const r_type: u32 = if (sym.flags.has_zig_got)
86 link.File.Elf.R_X86_64_ZIG_GOTPCREL
87 else if (sym.flags.needs_got)
88 std.elf.R_X86_64_GOTPCREL
89 else
90 std.elf.R_X86_64_PC32;
91 try atom.addReloc(elf_file, .{
92 .r_offset = end_offset - 4,
93 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
94 .r_addend = -4,
95 });
96 } else {
97 const r_type: u32 = if (sym.flags.has_zig_got)
98 link.File.Elf.R_X86_64_ZIG_GOT32
99 else if (sym.flags.needs_got)
100 std.elf.R_X86_64_GOT32
101 else
102 std.elf.R_X86_64_32;
103 try atom.addReloc(elf_file, .{
104 .r_offset = end_offset - 4,
105 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
106 .r_addend = 0,
107 });
108 }
109 } else unreachable,
81 .linker_got,110 .linker_got,
82 .linker_extern_got,
83 .linker_direct,111 .linker_direct,
84 .linker_direct_got,
85 .linker_import,112 .linker_import,
86 .linker_tlv,113 .linker_tlv,
87 => |symbol| if (emit.bin_file.cast(link.File.Elf)) |elf_file| {114 => |symbol| if (emit.bin_file.cast(link.File.Elf)) |_| {
88 const r_type: u32 = switch (lowered_relocs[0].target) {115 unreachable;
89 .linker_direct_got => link.File.Elf.R_X86_64_ZIG_GOT32,
90 .linker_got => link.File.Elf.R_X86_64_ZIG_GOTPCREL,
91 .linker_extern_got => std.elf.R_X86_64_GOTPCREL,
92 .linker_direct => std.elf.R_X86_64_PC32,
93 else => unreachable,
94 };
95 const r_addend: i64 = switch (lowered_relocs[0].target) {
96 .linker_direct_got => 0,
97 .linker_got, .linker_extern_got, .linker_direct => -4,
98 else => unreachable,
99 };
100 const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;
101 try atom_ptr.addReloc(elf_file, .{
102 .r_offset = end_offset - 4,
103 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type,
104 .r_addend = r_addend,
105 });
106 } else if (emit.bin_file.cast(link.File.MachO)) |macho_file| {116 } else if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
107 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?;117 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?;
108 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{118 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
src/arch/x86_64/Lower.zig+52-26
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1//! This file contains the functionality for lowering x86_64 MIR to Instructions1//! This file contains the functionality for lowering x86_64 MIR to Instructions
22
3bin_file: *link.File,
3allocator: Allocator,4allocator: Allocator,
4mir: Mir,5mir: Mir,
5cc: std.builtin.CallingConvention,6cc: std.builtin.CallingConvention,
...@@ -49,11 +50,10 @@ pub const Reloc = struct {...@@ -49,11 +50,10 @@ pub const Reloc = struct {
4950
50 const Target = union(enum) {51 const Target = union(enum) {
51 inst: Mir.Inst.Index,52 inst: Mir.Inst.Index,
53 linker_reloc: Mir.Reloc,
52 linker_extern_fn: Mir.Reloc,54 linker_extern_fn: Mir.Reloc,
53 linker_got: Mir.Reloc,55 linker_got: Mir.Reloc,
54 linker_extern_got: Mir.Reloc,
55 linker_direct: Mir.Reloc,56 linker_direct: Mir.Reloc,
56 linker_direct_got: Mir.Reloc,
57 linker_import: Mir.Reloc,57 linker_import: Mir.Reloc,
58 linker_tlv: Mir.Reloc,58 linker_tlv: Mir.Reloc,
59 };59 };
...@@ -408,12 +408,57 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {...@@ -408,12 +408,57 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
408 .m_sib, .m_rip, .rax_moffs, .moffs_rax => inst.data.x.fixes,408 .m_sib, .m_rip, .rax_moffs, .moffs_rax => inst.data.x.fixes,
409 .extern_fn_reloc,409 .extern_fn_reloc,
410 .got_reloc,410 .got_reloc,
411 .extern_got_reloc,
412 .direct_reloc,411 .direct_reloc,
413 .direct_got_reloc,
414 .import_reloc,412 .import_reloc,
415 .tlv_reloc,413 .tlv_reloc,
416 => ._,414 => ._,
415 .linker_reloc => {
416 if (lower.bin_file.options.pic) {
417 assert(inst.data.rx.fixes == ._);
418 const reg = inst.data.rx.r1;
419 const extra = lower.mir.extraData(Mir.Reloc, inst.data.rx.payload).data;
420 _ = lower.reloc(.{ .linker_reloc = extra });
421 const mnemonic: Mnemonic = switch (inst.tag) {
422 .mov => .mov,
423 .lea => .lea,
424 else => unreachable,
425 };
426 try lower.emit(.none, mnemonic, &.{
427 .{ .reg = reg },
428 .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
429 });
430 } else {
431 switch (inst.tag) {
432 .call => {
433 _ = lower.reloc(.{ .linker_reloc = inst.data.reloc });
434 try lower.emit(.none, .call, &.{
435 .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = 0 }) },
436 });
437 },
438 .lea => {
439 assert(inst.data.rx.fixes == ._);
440 const reg = inst.data.rx.r1;
441 const extra = lower.mir.extraData(Mir.Reloc, inst.data.rx.payload).data;
442 try lower.emit(.none, .mov, &.{
443 .{ .reg = reg },
444 .{ .imm = lower.reloc(.{ .linker_reloc = extra }) },
445 });
446 },
447 .mov => {
448 assert(inst.data.rx.fixes == ._);
449 const reg = inst.data.rx.r1;
450 const extra = lower.mir.extraData(Mir.Reloc, inst.data.rx.payload).data;
451 _ = lower.reloc(.{ .linker_reloc = extra });
452 try lower.emit(.none, .mov, &.{
453 .{ .reg = reg },
454 .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = 0 }) },
455 });
456 },
457 else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
458 }
459 }
460 return;
461 },
417 else => return lower.fail("TODO lower .{s}", .{@tagName(inst.ops)}),462 else => return lower.fail("TODO lower .{s}", .{@tagName(inst.ops)}),
418 };463 };
419 try lower.emit(switch (fixes) {464 try lower.emit(switch (fixes) {
...@@ -545,32 +590,12 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {...@@ -545,32 +590,12 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
545 .extern_fn_reloc => &.{590 .extern_fn_reloc => &.{
546 .{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc }) },591 .{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc }) },
547 },592 },
548 .direct_got_reloc => ops: {593 .linker_reloc => unreachable,
549 switch (inst.tag) {594 .got_reloc, .direct_reloc, .import_reloc, .tlv_reloc => ops: {
550 .call => {
551 _ = lower.reloc(.{ .linker_direct_got = inst.data.reloc });
552 break :ops &.{
553 .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = 0 }) },
554 };
555 },
556 .mov => {
557 const reg = inst.data.rx.r1;
558 const extra = lower.mir.extraData(Mir.Reloc, inst.data.rx.payload).data;
559 _ = lower.reloc(.{ .linker_direct_got = extra });
560 break :ops &.{
561 .{ .reg = reg },
562 .{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = 0 }) },
563 };
564 },
565 else => unreachable,
566 }
567 },
568 .got_reloc, .extern_got_reloc, .direct_reloc, .import_reloc, .tlv_reloc => ops: {
569 const reg = inst.data.rx.r1;595 const reg = inst.data.rx.r1;
570 const extra = lower.mir.extraData(Mir.Reloc, inst.data.rx.payload).data;596 const extra = lower.mir.extraData(Mir.Reloc, inst.data.rx.payload).data;
571 _ = lower.reloc(switch (inst.ops) {597 _ = lower.reloc(switch (inst.ops) {
572 .got_reloc => .{ .linker_got = extra },598 .got_reloc => .{ .linker_got = extra },
573 .extern_got_reloc => .{ .linker_extern_got = extra },
574 .direct_reloc => .{ .linker_direct = extra },599 .direct_reloc => .{ .linker_direct = extra },
575 .import_reloc => .{ .linker_import = extra },600 .import_reloc => .{ .linker_import = extra },
576 .tlv_reloc => .{ .linker_tlv = extra },601 .tlv_reloc => .{ .linker_tlv = extra },
...@@ -601,6 +626,7 @@ const abi = @import("abi.zig");...@@ -601,6 +626,7 @@ const abi = @import("abi.zig");
601const assert = std.debug.assert;626const assert = std.debug.assert;
602const bits = @import("bits.zig");627const bits = @import("bits.zig");
603const encoder = @import("encoder.zig");628const encoder = @import("encoder.zig");
629const link = @import("../../link.zig");
604const std = @import("std");630const std = @import("std");
605631
606const Air = @import("../../Air.zig");632const Air = @import("../../Air.zig");
src/arch/x86_64/Mir.zig+3-6
...@@ -854,9 +854,6 @@ pub const Inst = struct {...@@ -854,9 +854,6 @@ pub const Inst = struct {
854 /// Linker relocation - GOT indirection.854 /// Linker relocation - GOT indirection.
855 /// Uses `rx` payload with extra data of type `Reloc`.855 /// Uses `rx` payload with extra data of type `Reloc`.
856 got_reloc,856 got_reloc,
857 /// Linker relocation - reference to an extern variable via GOT.
858 /// Uses `rx` payload with extra data of type `Reloc`.
859 extern_got_reloc,
860 /// Linker relocation - direct reference.857 /// Linker relocation - direct reference.
861 /// Uses `rx` payload with extra data of type `Reloc`.858 /// Uses `rx` payload with extra data of type `Reloc`.
862 direct_reloc,859 direct_reloc,
...@@ -866,9 +863,9 @@ pub const Inst = struct {...@@ -866,9 +863,9 @@ pub const Inst = struct {
866 /// Linker relocation - threadlocal variable via GOT indirection.863 /// Linker relocation - threadlocal variable via GOT indirection.
867 /// Uses `rx` payload with extra data of type `Reloc`.864 /// Uses `rx` payload with extra data of type `Reloc`.
868 tlv_reloc,865 tlv_reloc,
869 /// Linker relocation - non-PIC direct reference to GOT cell.866 /// Linker relocation.
870 /// Uses `reloc` payload if tag is `call`, `rx` otherwise.867 /// Uses `rx` payload with extra data of type `Reloc`.
871 direct_got_reloc,868 linker_reloc,
872869
873 // Pseudo instructions:870 // Pseudo instructions:
874871
src/codegen.zig+8-15
...@@ -791,13 +791,11 @@ fn lowerDeclRef(...@@ -791,13 +791,11 @@ fn lowerDeclRef(
791791
792/// Helper struct to denote that the value is in memory but requires a linker relocation fixup:792/// Helper struct to denote that the value is in memory but requires a linker relocation fixup:
793/// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)793/// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
794/// * extern_got - pointer to extern variable referenced via GOT
795/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)794/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
796/// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)795/// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
797pub const LinkerLoad = struct {796pub const LinkerLoad = struct {
798 type: enum {797 type: enum {
799 got,798 got,
800 extern_got,
801 direct,799 direct,
802 import,800 import,
803 },801 },
...@@ -827,8 +825,9 @@ pub const GenResult = union(enum) {...@@ -827,8 +825,9 @@ pub const GenResult = union(enum) {
827 load_got: u32,825 load_got: u32,
828 /// Direct by-address reference to memory location.826 /// Direct by-address reference to memory location.
829 memory: u64,827 memory: u64,
830 /// Pointer to extern variable via GOT.828 /// Reference to memory location but deferred until linker allocated the Decl in memory.
831 load_extern_got: u32,829 /// Traditionally, this corresponds to emitting a relocation in a relocatable object file.
830 load_symbol: u32,
832 };831 };
833832
834 fn mcv(val: MCValue) GenResult {833 fn mcv(val: MCValue) GenResult {
...@@ -903,16 +902,14 @@ fn genDeclRef(...@@ -903,16 +902,14 @@ fn genDeclRef(
903 mod.intern_pool.stringToSliceUnwrap(ov.lib_name)902 mod.intern_pool.stringToSliceUnwrap(ov.lib_name)
904 else903 else
905 null;904 null;
906 return GenResult.mcv(.{ .load_extern_got = try elf_file.getGlobalSymbol(name, lib_name) });905 const sym_index = try elf_file.getGlobalSymbol(name, lib_name);
906 elf_file.symbol(elf_file.zigModulePtr().symbol(sym_index)).flags.needs_got = true;
907 return GenResult.mcv(.{ .load_symbol = sym_index });
907 }908 }
908 const sym_index = try elf_file.getOrCreateMetadataForDecl(decl_index);909 const sym_index = try elf_file.getOrCreateMetadataForDecl(decl_index);
909 const sym = elf_file.symbol(sym_index);910 const sym = elf_file.symbol(sym_index);
910 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);911 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
911 if (bin_file.options.pic) {912 return GenResult.mcv(.{ .load_symbol = sym.esym_index });
912 return GenResult.mcv(.{ .load_got = sym.esym_index });
913 } else {
914 return GenResult.mcv(.{ .memory = sym.zigGotAddress(elf_file) });
915 }
916 } else if (bin_file.cast(link.File.MachO)) |macho_file| {913 } else if (bin_file.cast(link.File.MachO)) |macho_file| {
917 const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);914 const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
918 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;915 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
...@@ -948,11 +945,7 @@ fn genUnnamedConst(...@@ -948,11 +945,7 @@ fn genUnnamedConst(
948 };945 };
949 if (bin_file.cast(link.File.Elf)) |elf_file| {946 if (bin_file.cast(link.File.Elf)) |elf_file| {
950 const local = elf_file.symbol(local_sym_index);947 const local = elf_file.symbol(local_sym_index);
951 if (bin_file.options.pic) {948 return GenResult.mcv(.{ .load_symbol = local.esym_index });
952 return GenResult.mcv(.{ .load_direct = local.esym_index });
953 } else {
954 return GenResult.mcv(.{ .memory = local.value });
955 }
956 } else if (bin_file.cast(link.File.MachO)) |_| {949 } else if (bin_file.cast(link.File.MachO)) |_| {
957 return GenResult.mcv(.{ .load_direct = local_sym_index });950 return GenResult.mcv(.{ .load_direct = local_sym_index });
958 } else if (bin_file.cast(link.File.Coff)) |_| {951 } else if (bin_file.cast(link.File.Coff)) |_| {
src/link/Elf.zig+8-1
...@@ -3333,7 +3333,8 @@ pub fn updateDecl(...@@ -3333,7 +3333,8 @@ pub fn updateDecl(
3333 const variable = decl.getOwnedVariable(mod).?;3333 const variable = decl.getOwnedVariable(mod).?;
3334 const name = mod.intern_pool.stringToSlice(decl.name);3334 const name = mod.intern_pool.stringToSlice(decl.name);
3335 const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name);3335 const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name);
3336 _ = try self.getGlobalSymbol(name, lib_name);3336 const esym_index = try self.getGlobalSymbol(name, lib_name);
3337 self.symbol(self.zigModulePtr().symbol(esym_index)).flags.needs_got = true;
3337 return;3338 return;
3338 }3339 }
33393340
...@@ -5955,6 +5956,12 @@ pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32...@@ -5955,6 +5956,12 @@ pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32
5955 return lookup_gop.value_ptr.*;5956 return lookup_gop.value_ptr.*;
5956}5957}
59575958
5959pub fn zigModulePtr(self: *Elf) *ZigModule {
5960 assert(self.zig_module_index != null);
5961 const file_ptr = self.file(self.zig_module_index.?).?;
5962 return file_ptr.zig_module;
5963}
5964
5958const GetOrCreateComdatGroupOwnerResult = struct {5965const GetOrCreateComdatGroupOwnerResult = struct {
5959 found_existing: bool,5966 found_existing: bool,
5960 index: ComdatGroupOwner.Index,5967 index: ComdatGroupOwner.Index,
src/link/Elf/Atom.zig+3
...@@ -370,6 +370,7 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype...@@ -370,6 +370,7 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype
370 try self.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file);370 try self.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file);
371 },371 },
372372
373 elf.R_X86_64_GOT32,
373 elf.R_X86_64_GOTPC32,374 elf.R_X86_64_GOTPC32,
374 elf.R_X86_64_GOTPC64,375 elf.R_X86_64_GOTPC64,
375 elf.R_X86_64_GOTPCREL,376 elf.R_X86_64_GOTPCREL,
...@@ -879,6 +880,8 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void {...@@ -879,6 +880,8 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void {
879 }880 }
880 },881 },
881882
883 elf.R_X86_64_GOT32 => try cwriter.writeIntLittle(i32, @as(i32, @intCast(G + GOT + A))),
884
882 // Zig custom relocations885 // Zig custom relocations
883 Elf.R_X86_64_ZIG_GOT32 => try cwriter.writeIntLittle(u32, @as(u32, @intCast(ZIG_GOT + A))),886 Elf.R_X86_64_ZIG_GOT32 => try cwriter.writeIntLittle(u32, @as(u32, @intCast(ZIG_GOT + A))),
884 Elf.R_X86_64_ZIG_GOTPCREL => try cwriter.writeIntLittle(i32, @as(i32, @intCast(ZIG_GOT + A - P))),887 Elf.R_X86_64_ZIG_GOTPCREL => try cwriter.writeIntLittle(i32, @as(i32, @intCast(ZIG_GOT + A - P))),
test/c_abi/cfuncs.c+3-7
...@@ -73,10 +73,6 @@ static void assert_or_panic(bool ok) {...@@ -73,10 +73,6 @@ static void assert_or_panic(bool ok) {
73#define ZIG_NO_RAW_F1673#define ZIG_NO_RAW_F16
74#endif74#endif
7575
76#ifdef ZIG_BACKEND_STAGE2_X86_64
77#define ZIG_NO_COMPLEX
78#endif
79
80#ifdef __i386__76#ifdef __i386__
81#define ZIG_NO_RAW_F1677#define ZIG_NO_RAW_F16
82#endif78#endif
...@@ -278,7 +274,7 @@ void run_c_tests(void) {...@@ -278,7 +274,7 @@ void run_c_tests(void) {
278 zig_u32(0xfffffffd);274 zig_u32(0xfffffffd);
279 zig_u64(0xfffffffffffffffc);275 zig_u64(0xfffffffffffffffc);
280276
281#if !defined ZIG_NO_I128 && !defined ZIG_BACKEND_STAGE2_X86_64277#ifndef ZIG_NO_I128
282 {278 {
283 struct u128 s = {0xfffffffffffffffc};279 struct u128 s = {0xfffffffffffffffc};
284 zig_struct_u128(s);280 zig_struct_u128(s);
...@@ -292,7 +288,7 @@ void run_c_tests(void) {...@@ -292,7 +288,7 @@ void run_c_tests(void) {
292 zig_i32(-3);288 zig_i32(-3);
293 zig_i64(-4);289 zig_i64(-4);
294290
295#if !defined ZIG_NO_I128 && !defined ZIG_BACKEND_STAGE2_X86_64291#ifndef ZIG_NO_I128
296 {292 {
297 struct i128 s = {-6};293 struct i128 s = {-6};
298 zig_struct_i128(s);294 zig_struct_i128(s);
...@@ -433,7 +429,7 @@ void run_c_tests(void) {...@@ -433,7 +429,7 @@ void run_c_tests(void) {
433 }429 }
434#endif430#endif
435431
436#if !defined __mips__ && !defined ZIG_PPC32 && !defined ZIG_BACKEND_STAGE2_X86_64432#if !defined __mips__ && !defined ZIG_PPC32
437 {433 {
438 struct FloatRect r1 = {1, 21, 16, 4};434 struct FloatRect r1 = {1, 21, 16, 4};
439 struct FloatRect r2 = {178, 189, 21, 15};435 struct FloatRect r2 = {178, 189, 21, 15};
test/c_abi/main.zig+5-86
...@@ -49,8 +49,6 @@ export fn zig_five_integers(a: i32, b: i32, c: i32, d: i32, e: i32) void {...@@ -49,8 +49,6 @@ export fn zig_five_integers(a: i32, b: i32, c: i32, d: i32, e: i32) void {
49}49}
5050
51test "C ABI integers" {51test "C ABI integers" {
52 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
53
54 c_u8(0xff);52 c_u8(0xff);
55 c_u16(0xfffe);53 c_u16(0xfffe);
56 c_u32(0xfffffffd);54 c_u32(0xfffffffd);
...@@ -187,10 +185,8 @@ const complex_abi_compatible = builtin.cpu.arch != .x86 and !builtin.cpu.arch.is...@@ -187,10 +185,8 @@ const complex_abi_compatible = builtin.cpu.arch != .x86 and !builtin.cpu.arch.is
187 !builtin.cpu.arch.isARM() and !builtin.cpu.arch.isPPC() and !builtin.cpu.arch.isRISCV();185 !builtin.cpu.arch.isARM() and !builtin.cpu.arch.isPPC() and !builtin.cpu.arch.isRISCV();
188186
189test "C ABI complex float" {187test "C ABI complex float" {
190 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
191
192 if (!complex_abi_compatible) return error.SkipZigTest;188 if (!complex_abi_compatible) return error.SkipZigTest;
193 if (builtin.cpu.arch == .x86_64) return error.SkipZigTest; // See https://github.com/ziglang/zig/issues/8465189 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest; // See https://github.com/ziglang/zig/issues/8465
194190
195 const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };191 const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };
196 const b = ComplexFloat{ .real = 11.3, .imag = -1.5 };192 const b = ComplexFloat{ .real = 11.3, .imag = -1.5 };
...@@ -201,8 +197,6 @@ test "C ABI complex float" {...@@ -201,8 +197,6 @@ test "C ABI complex float" {
201}197}
202198
203test "C ABI complex float by component" {199test "C ABI complex float by component" {
204 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
205
206 if (!complex_abi_compatible) return error.SkipZigTest;200 if (!complex_abi_compatible) return error.SkipZigTest;
207201
208 const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };202 const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };
...@@ -214,8 +208,6 @@ test "C ABI complex float by component" {...@@ -214,8 +208,6 @@ test "C ABI complex float by component" {
214}208}
215209
216test "C ABI complex double" {210test "C ABI complex double" {
217 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
218
219 if (!complex_abi_compatible) return error.SkipZigTest;211 if (!complex_abi_compatible) return error.SkipZigTest;
220212
221 const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };213 const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };
...@@ -227,8 +219,6 @@ test "C ABI complex double" {...@@ -227,8 +219,6 @@ test "C ABI complex double" {
227}219}
228220
229test "C ABI complex double by component" {221test "C ABI complex double by component" {
230 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
231
232 if (!complex_abi_compatible) return error.SkipZigTest;222 if (!complex_abi_compatible) return error.SkipZigTest;
233223
234 const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };224 const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };
...@@ -240,8 +230,6 @@ test "C ABI complex double by component" {...@@ -240,8 +230,6 @@ test "C ABI complex double by component" {
240}230}
241231
242export fn zig_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat {232export fn zig_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat {
243 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
244
245 expect(a.real == 1.25) catch @panic("test failure: zig_cmultf 1");233 expect(a.real == 1.25) catch @panic("test failure: zig_cmultf 1");
246 expect(a.imag == 2.6) catch @panic("test failure: zig_cmultf 2");234 expect(a.imag == 2.6) catch @panic("test failure: zig_cmultf 2");
247 expect(b.real == 11.3) catch @panic("test failure: zig_cmultf 3");235 expect(b.real == 11.3) catch @panic("test failure: zig_cmultf 3");
...@@ -251,8 +239,6 @@ export fn zig_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat {...@@ -251,8 +239,6 @@ export fn zig_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat {
251}239}
252240
253export fn zig_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble {241export fn zig_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble {
254 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
255
256 expect(a.real == 1.25) catch @panic("test failure: zig_cmultd 1");242 expect(a.real == 1.25) catch @panic("test failure: zig_cmultd 1");
257 expect(a.imag == 2.6) catch @panic("test failure: zig_cmultd 2");243 expect(a.imag == 2.6) catch @panic("test failure: zig_cmultd 2");
258 expect(b.real == 11.3) catch @panic("test failure: zig_cmultd 3");244 expect(b.real == 11.3) catch @panic("test failure: zig_cmultd 3");
...@@ -262,8 +248,6 @@ export fn zig_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble {...@@ -262,8 +248,6 @@ export fn zig_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble {
262}248}
263249
264export fn zig_cmultf_comp(a_r: f32, a_i: f32, b_r: f32, b_i: f32) ComplexFloat {250export fn zig_cmultf_comp(a_r: f32, a_i: f32, b_r: f32, b_i: f32) ComplexFloat {
265 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
266
267 expect(a_r == 1.25) catch @panic("test failure: zig_cmultf_comp 1");251 expect(a_r == 1.25) catch @panic("test failure: zig_cmultf_comp 1");
268 expect(a_i == 2.6) catch @panic("test failure: zig_cmultf_comp 2");252 expect(a_i == 2.6) catch @panic("test failure: zig_cmultf_comp 2");
269 expect(b_r == 11.3) catch @panic("test failure: zig_cmultf_comp 3");253 expect(b_r == 11.3) catch @panic("test failure: zig_cmultf_comp 3");
...@@ -273,8 +257,6 @@ export fn zig_cmultf_comp(a_r: f32, a_i: f32, b_r: f32, b_i: f32) ComplexFloat {...@@ -273,8 +257,6 @@ export fn zig_cmultf_comp(a_r: f32, a_i: f32, b_r: f32, b_i: f32) ComplexFloat {
273}257}
274258
275export fn zig_cmultd_comp(a_r: f64, a_i: f64, b_r: f64, b_i: f64) ComplexDouble {259export fn zig_cmultd_comp(a_r: f64, a_i: f64, b_r: f64, b_i: f64) ComplexDouble {
276 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
277
278 expect(a_r == 1.25) catch @panic("test failure: zig_cmultd_comp 1");260 expect(a_r == 1.25) catch @panic("test failure: zig_cmultd_comp 1");
279 expect(a_i == 2.6) catch @panic("test failure: zig_cmultd_comp 2");261 expect(a_i == 2.6) catch @panic("test failure: zig_cmultd_comp 2");
280 expect(b_r == 11.3) catch @panic("test failure: zig_cmultd_comp 3");262 expect(b_r == 11.3) catch @panic("test failure: zig_cmultd_comp 3");
...@@ -352,8 +334,6 @@ extern fn c_med_struct_mixed(MedStructMixed) void;...@@ -352,8 +334,6 @@ extern fn c_med_struct_mixed(MedStructMixed) void;
352extern fn c_ret_med_struct_mixed() MedStructMixed;334extern fn c_ret_med_struct_mixed() MedStructMixed;
353335
354test "C ABI medium struct of ints and floats" {336test "C ABI medium struct of ints and floats" {
355 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
356
357 if (builtin.cpu.arch == .x86) return error.SkipZigTest;337 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
358 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;338 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
359 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;339 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
...@@ -422,8 +402,6 @@ extern fn c_med_struct_ints(MedStructInts) void;...@@ -422,8 +402,6 @@ extern fn c_med_struct_ints(MedStructInts) void;
422extern fn c_ret_med_struct_ints() MedStructInts;402extern fn c_ret_med_struct_ints() MedStructInts;
423403
424test "C ABI medium struct of ints" {404test "C ABI medium struct of ints" {
425 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
426
427 if (builtin.cpu.arch == .x86) return error.SkipZigTest;405 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
428 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;406 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
429 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;407 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
...@@ -531,8 +509,6 @@ extern fn c_split_struct_mixed(SplitStructMixed) void;...@@ -531,8 +509,6 @@ extern fn c_split_struct_mixed(SplitStructMixed) void;
531extern fn c_ret_split_struct_mixed() SplitStructMixed;509extern fn c_ret_split_struct_mixed() SplitStructMixed;
532510
533test "C ABI split struct of ints and floats" {511test "C ABI split struct of ints and floats" {
534 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
535
536 if (builtin.cpu.arch == .x86) return error.SkipZigTest;512 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
537 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;513 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
538 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;514 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
...@@ -614,8 +590,6 @@ const Vector5 = extern struct {...@@ -614,8 +590,6 @@ const Vector5 = extern struct {
614extern fn c_big_struct_floats(Vector5) void;590extern fn c_big_struct_floats(Vector5) void;
615591
616test "C ABI structs of floats as parameter" {592test "C ABI structs of floats as parameter" {
617 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
618
619 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;593 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
620 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;594 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
621 if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;595 if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;
...@@ -683,8 +657,6 @@ const FloatRect = extern struct {...@@ -683,8 +657,6 @@ const FloatRect = extern struct {
683};657};
684658
685export fn zig_multiple_struct_floats(x: FloatRect, y: FloatRect) void {659export fn zig_multiple_struct_floats(x: FloatRect, y: FloatRect) void {
686 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
687
688 expect(x.left == 1) catch @panic("test failure");660 expect(x.left == 1) catch @panic("test failure");
689 expect(x.right == 21) catch @panic("test failure");661 expect(x.right == 21) catch @panic("test failure");
690 expect(x.top == 16) catch @panic("test failure");662 expect(x.top == 16) catch @panic("test failure");
...@@ -696,8 +668,6 @@ export fn zig_multiple_struct_floats(x: FloatRect, y: FloatRect) void {...@@ -696,8 +668,6 @@ export fn zig_multiple_struct_floats(x: FloatRect, y: FloatRect) void {
696}668}
697669
698test "C ABI structs of floats as multiple parameters" {670test "C ABI structs of floats as multiple parameters" {
699 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
700
701 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;671 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
702 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;672 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
703673
...@@ -754,8 +724,6 @@ export fn zig_ret_small_struct_ints() SmallStructInts {...@@ -754,8 +724,6 @@ export fn zig_ret_small_struct_ints() SmallStructInts {
754}724}
755725
756export fn zig_ret_med_struct_ints() MedStructInts {726export fn zig_ret_med_struct_ints() MedStructInts {
757 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
758
759 return .{727 return .{
760 .x = 1,728 .x = 1,
761 .y = 2,729 .y = 2,
...@@ -764,8 +732,6 @@ export fn zig_ret_med_struct_ints() MedStructInts {...@@ -764,8 +732,6 @@ export fn zig_ret_med_struct_ints() MedStructInts {
764}732}
765733
766export fn zig_ret_med_struct_mixed() MedStructMixed {734export fn zig_ret_med_struct_mixed() MedStructMixed {
767 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
768
769 return .{735 return .{
770 .a = 1234,736 .a = 1234,
771 .b = 100.0,737 .b = 100.0,
...@@ -774,8 +740,6 @@ export fn zig_ret_med_struct_mixed() MedStructMixed {...@@ -774,8 +740,6 @@ export fn zig_ret_med_struct_mixed() MedStructMixed {
774}740}
775741
776export fn zig_ret_split_struct_mixed() SplitStructMixed {742export fn zig_ret_split_struct_mixed() SplitStructMixed {
777 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
778
779 return .{743 return .{
780 .a = 1234,744 .a = 1234,
781 .b = 100,745 .b = 100,
...@@ -816,8 +780,6 @@ extern fn c_struct_with_array(StructWithArray) void;...@@ -816,8 +780,6 @@ extern fn c_struct_with_array(StructWithArray) void;
816extern fn c_ret_struct_with_array() StructWithArray;780extern fn c_ret_struct_with_array() StructWithArray;
817781
818test "Struct with array as padding." {782test "Struct with array as padding." {
819 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
820
821 if (builtin.cpu.arch == .x86) return error.SkipZigTest;783 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
822 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;784 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
823 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;785 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
...@@ -889,7 +851,8 @@ extern fn c_medium_vec(MediumVec) void;...@@ -889,7 +851,8 @@ extern fn c_medium_vec(MediumVec) void;
889extern fn c_ret_medium_vec() MediumVec;851extern fn c_ret_medium_vec() MediumVec;
890852
891test "medium simd vector" {853test "medium simd vector" {
892 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;854 if (builtin.zig_backend == .stage2_x86_64 and
855 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .avx)) return error.SkipZigTest;
893856
894 if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;857 if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;
895858
...@@ -912,7 +875,7 @@ test "big simd vector" {...@@ -912,7 +875,7 @@ test "big simd vector" {
912875
913 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;876 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
914 if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;877 if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;
915 if (builtin.cpu.arch == .x86_64 and builtin.os.tag == .macos and builtin.mode != .Debug) return error.SkipZigTest;878 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .macos and builtin.mode != .Debug) return error.SkipZigTest;
916879
917 c_big_vec(.{ 1, 2, 3, 4, 5, 6, 7, 8 });880 c_big_vec(.{ 1, 2, 3, 4, 5, 6, 7, 8 });
918881
...@@ -933,8 +896,6 @@ extern fn c_ptr_size_float_struct(Vector2) void;...@@ -933,8 +896,6 @@ extern fn c_ptr_size_float_struct(Vector2) void;
933extern fn c_ret_ptr_size_float_struct() Vector2;896extern fn c_ret_ptr_size_float_struct() Vector2;
934897
935test "C ABI pointer sized float struct" {898test "C ABI pointer sized float struct" {
936 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
937
938 if (builtin.cpu.arch == .x86) return error.SkipZigTest;899 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
939 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;900 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
940 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;901 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
...@@ -958,8 +919,6 @@ pub inline fn expectOk(c_err: c_int) !void {...@@ -958,8 +919,6 @@ pub inline fn expectOk(c_err: c_int) !void {
958/// Tests for Double + Char struct919/// Tests for Double + Char struct
959const DC = extern struct { v1: f64, v2: u8 };920const DC = extern struct { v1: f64, v2: u8 };
960test "DC: Zig passes to C" {921test "DC: Zig passes to C" {
961 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
962
963 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;922 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
964 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;923 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
965 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;924 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
...@@ -967,8 +926,6 @@ test "DC: Zig passes to C" {...@@ -967,8 +926,6 @@ test "DC: Zig passes to C" {
967 try expectOk(c_assert_DC(.{ .v1 = -0.25, .v2 = 15 }));926 try expectOk(c_assert_DC(.{ .v1 = -0.25, .v2 = 15 }));
968}927}
969test "DC: Zig returns to C" {928test "DC: Zig returns to C" {
970 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
971
972 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;929 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
973 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;930 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
974 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;931 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
...@@ -977,8 +934,6 @@ test "DC: Zig returns to C" {...@@ -977,8 +934,6 @@ test "DC: Zig returns to C" {
977 try expectOk(c_assert_ret_DC());934 try expectOk(c_assert_ret_DC());
978}935}
979test "DC: C passes to Zig" {936test "DC: C passes to Zig" {
980 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
981
982 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;937 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
983 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;938 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
984 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;939 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
...@@ -986,8 +941,6 @@ test "DC: C passes to Zig" {...@@ -986,8 +941,6 @@ test "DC: C passes to Zig" {
986 try expectOk(c_send_DC());941 try expectOk(c_send_DC());
987}942}
988test "DC: C returns to Zig" {943test "DC: C returns to Zig" {
989 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
990
991 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;944 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
992 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;945 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
993 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;946 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
...@@ -1001,8 +954,6 @@ pub extern fn c_assert_ret_DC() c_int;...@@ -1001,8 +954,6 @@ pub extern fn c_assert_ret_DC() c_int;
1001pub extern fn c_send_DC() c_int;954pub extern fn c_send_DC() c_int;
1002pub extern fn c_ret_DC() DC;955pub extern fn c_ret_DC() DC;
1003pub export fn zig_assert_DC(lv: DC) c_int {956pub export fn zig_assert_DC(lv: DC) c_int {
1004 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1005
1006 var err: c_int = 0;957 var err: c_int = 0;
1007 if (lv.v1 != -0.25) err = 1;958 if (lv.v1 != -0.25) err = 1;
1008 if (lv.v2 != 15) err = 2;959 if (lv.v2 != 15) err = 2;
...@@ -1010,8 +961,6 @@ pub export fn zig_assert_DC(lv: DC) c_int {...@@ -1010,8 +961,6 @@ pub export fn zig_assert_DC(lv: DC) c_int {
1010 return err;961 return err;
1011}962}
1012pub export fn zig_ret_DC() DC {963pub export fn zig_ret_DC() DC {
1013 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1014
1015 return .{ .v1 = -0.25, .v2 = 15 };964 return .{ .v1 = -0.25, .v2 = 15 };
1016}965}
1017966
...@@ -1019,8 +968,6 @@ pub export fn zig_ret_DC() DC {...@@ -1019,8 +968,6 @@ pub export fn zig_ret_DC() DC {
1019const CFF = extern struct { v1: u8, v2: f32, v3: f32 };968const CFF = extern struct { v1: u8, v2: f32, v3: f32 };
1020969
1021test "CFF: Zig passes to C" {970test "CFF: Zig passes to C" {
1022 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1023
1024 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;971 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
1025 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;972 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1026 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;973 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
...@@ -1028,8 +975,6 @@ test "CFF: Zig passes to C" {...@@ -1028,8 +975,6 @@ test "CFF: Zig passes to C" {
1028 try expectOk(c_assert_CFF(.{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }));975 try expectOk(c_assert_CFF(.{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }));
1029}976}
1030test "CFF: Zig returns to C" {977test "CFF: Zig returns to C" {
1031 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1032
1033 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;978 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
1034 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;979 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1035 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;980 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
...@@ -1037,8 +982,6 @@ test "CFF: Zig returns to C" {...@@ -1037,8 +982,6 @@ test "CFF: Zig returns to C" {
1037 try expectOk(c_assert_ret_CFF());982 try expectOk(c_assert_ret_CFF());
1038}983}
1039test "CFF: C passes to Zig" {984test "CFF: C passes to Zig" {
1040 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1041
1042 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;985 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
1043 if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;986 if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;
1044 if (builtin.cpu.arch == .aarch64 and builtin.mode != .Debug) return error.SkipZigTest;987 if (builtin.cpu.arch == .aarch64 and builtin.mode != .Debug) return error.SkipZigTest;
...@@ -1049,8 +992,6 @@ test "CFF: C passes to Zig" {...@@ -1049,8 +992,6 @@ test "CFF: C passes to Zig" {
1049 try expectOk(c_send_CFF());992 try expectOk(c_send_CFF());
1050}993}
1051test "CFF: C returns to Zig" {994test "CFF: C returns to Zig" {
1052 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1053
1054 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;995 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
1055 if (builtin.cpu.arch == .aarch64 and builtin.mode != .Debug) return error.SkipZigTest;996 if (builtin.cpu.arch == .aarch64 and builtin.mode != .Debug) return error.SkipZigTest;
1056 if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;997 if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;
...@@ -1064,8 +1005,6 @@ pub extern fn c_assert_ret_CFF() c_int;...@@ -1064,8 +1005,6 @@ pub extern fn c_assert_ret_CFF() c_int;
1064pub extern fn c_send_CFF() c_int;1005pub extern fn c_send_CFF() c_int;
1065pub extern fn c_ret_CFF() CFF;1006pub extern fn c_ret_CFF() CFF;
1066pub export fn zig_assert_CFF(lv: CFF) c_int {1007pub export fn zig_assert_CFF(lv: CFF) c_int {
1067 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1068
1069 var err: c_int = 0;1008 var err: c_int = 0;
1070 if (lv.v1 != 39) err = 1;1009 if (lv.v1 != 39) err = 1;
1071 if (lv.v2 != 0.875) err = 2;1010 if (lv.v2 != 0.875) err = 2;
...@@ -1074,8 +1013,6 @@ pub export fn zig_assert_CFF(lv: CFF) c_int {...@@ -1074,8 +1013,6 @@ pub export fn zig_assert_CFF(lv: CFF) c_int {
1074 return err;1013 return err;
1075}1014}
1076pub export fn zig_ret_CFF() CFF {1015pub export fn zig_ret_CFF() CFF {
1077 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1078
1079 return .{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 };1016 return .{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 };
1080}1017}
10811018
...@@ -1083,8 +1020,6 @@ pub export fn zig_ret_CFF() CFF {...@@ -1083,8 +1020,6 @@ pub export fn zig_ret_CFF() CFF {
1083const PD = extern struct { v1: ?*anyopaque, v2: f64 };1020const PD = extern struct { v1: ?*anyopaque, v2: f64 };
10841021
1085test "PD: Zig passes to C" {1022test "PD: Zig passes to C" {
1086 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1087
1088 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;1023 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
1089 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;1024 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1090 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;1025 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
...@@ -1092,8 +1027,6 @@ test "PD: Zig passes to C" {...@@ -1092,8 +1027,6 @@ test "PD: Zig passes to C" {
1092 try expectOk(c_assert_PD(.{ .v1 = null, .v2 = 0.5 }));1027 try expectOk(c_assert_PD(.{ .v1 = null, .v2 = 0.5 }));
1093}1028}
1094test "PD: Zig returns to C" {1029test "PD: Zig returns to C" {
1095 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1096
1097 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;1030 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
1098 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;1031 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
1099 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;1032 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
...@@ -1101,8 +1034,6 @@ test "PD: Zig returns to C" {...@@ -1101,8 +1034,6 @@ test "PD: Zig returns to C" {
1101 try expectOk(c_assert_ret_PD());1034 try expectOk(c_assert_ret_PD());
1102}1035}
1103test "PD: C passes to Zig" {1036test "PD: C passes to Zig" {
1104 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1105
1106 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;1037 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
1107 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;1038 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1108 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;1039 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
...@@ -1110,8 +1041,6 @@ test "PD: C passes to Zig" {...@@ -1110,8 +1041,6 @@ test "PD: C passes to Zig" {
1110 try expectOk(c_send_PD());1041 try expectOk(c_send_PD());
1111}1042}
1112test "PD: C returns to Zig" {1043test "PD: C returns to Zig" {
1113 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1114
1115 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;1044 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
1116 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;1045 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
1117 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;1046 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
...@@ -1123,8 +1052,6 @@ pub extern fn c_assert_ret_PD() c_int;...@@ -1123,8 +1052,6 @@ pub extern fn c_assert_ret_PD() c_int;
1123pub extern fn c_send_PD() c_int;1052pub extern fn c_send_PD() c_int;
1124pub extern fn c_ret_PD() PD;1053pub extern fn c_ret_PD() PD;
1125pub export fn zig_c_assert_PD(lv: PD) c_int {1054pub export fn zig_c_assert_PD(lv: PD) c_int {
1126 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1127
1128 var err: c_int = 0;1055 var err: c_int = 0;
1129 if (lv.v1 != null) err = 1;1056 if (lv.v1 != null) err = 1;
1130 if (lv.v2 != 0.5) err = 2;1057 if (lv.v2 != 0.5) err = 2;
...@@ -1132,13 +1059,9 @@ pub export fn zig_c_assert_PD(lv: PD) c_int {...@@ -1132,13 +1059,9 @@ pub export fn zig_c_assert_PD(lv: PD) c_int {
1132 return err;1059 return err;
1133}1060}
1134pub export fn zig_ret_PD() PD {1061pub export fn zig_ret_PD() PD {
1135 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1136
1137 return .{ .v1 = null, .v2 = 0.5 };1062 return .{ .v1 = null, .v2 = 0.5 };
1138}1063}
1139pub export fn zig_assert_PD(lv: PD) c_int {1064pub export fn zig_assert_PD(lv: PD) c_int {
1140 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1141
1142 var err: c_int = 0;1065 var err: c_int = 0;
1143 if (lv.v1 != null) err = 1;1066 if (lv.v1 != null) err = 1;
1144 if (lv.v2 != 0.5) err = 2;1067 if (lv.v2 != 0.5) err = 2;
...@@ -1228,11 +1151,9 @@ const f80_struct = extern struct {...@@ -1228,11 +1151,9 @@ const f80_struct = extern struct {
1228};1151};
1229extern fn c_f80_struct(f80_struct) f80_struct;1152extern fn c_f80_struct(f80_struct) f80_struct;
1230test "f80 struct" {1153test "f80 struct" {
1231 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1232
1233 if (!has_f80) return error.SkipZigTest;1154 if (!has_f80) return error.SkipZigTest;
1234 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;1155 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
1235 if (builtin.mode != .Debug) return error.SkipZigTest;1156 if (builtin.zig_backend == .stage2_llvm and builtin.mode != .Debug) return error.SkipZigTest;
12361157
1237 const a = c_f80_struct(.{ .a = 12.34 });1158 const a = c_f80_struct(.{ .a = 12.34 });
1238 try expect(@as(f64, @floatCast(a.a)) == 56.78);1159 try expect(@as(f64, @floatCast(a.a)) == 56.78);
...@@ -1317,8 +1238,6 @@ test "Stdcall ABI big union" {...@@ -1317,8 +1238,6 @@ test "Stdcall ABI big union" {
13171238
1318extern fn c_explict_win64(ByRef) callconv(.Win64) ByRef;1239extern fn c_explict_win64(ByRef) callconv(.Win64) ByRef;
1319test "explicit SysV calling convention" {1240test "explicit SysV calling convention" {
1320 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1321
1322 if (builtin.cpu.arch != .x86_64) return error.SkipZigTest;1241 if (builtin.cpu.arch != .x86_64) return error.SkipZigTest;
13231242
1324 const res = c_explict_win64(.{ .val = 1, .arr = undefined });1243 const res = c_explict_win64(.{ .val = 1, .arr = undefined });