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" {
144144}
145145
146146test "tan64" {
147 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
148
149147 const epsilon = 0.000001;
150148
151149 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{
374374};
375375
376376test "Atomic.swap" {
377 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
378
379377 inline for (atomic_rmw_orderings) |ordering| {
380378 var x = Atomic(usize).init(5);
381379 try testing.expectEqual(x.swap(10, ordering), 5);
lib/std/debug.zig-2
......@@ -2513,8 +2513,6 @@ pub fn dumpStackPointerAddr(prefix: []const u8) void {
25132513}
25142514
25152515test "manage resources correctly" {
2516 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2517
25182516 if (builtin.os.tag == .wasi) return error.SkipZigTest;
25192517
25202518 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;
22pub const ParseFloatError = @import("parse_float/parse_float.zig").ParseFloatError;
33
44const std = @import("std");
5const builtin = @import("builtin");
65const math = std.math;
76const testing = std.testing;
87const expect = testing.expect;
......@@ -14,8 +13,6 @@ const epsilon = 1e-7;
1413// See https://github.com/tiehuis/parse-number-fxx-test-data for a wider-selection of test-data.
1514
1615test "fmt.parseFloat" {
17 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
18
1916 inline for ([_]type{ f16, f32, f64, f128 }) |T| {
2017 try testing.expectError(error.InvalidCharacter, parseFloat(T, ""));
2118 try testing.expectError(error.InvalidCharacter, parseFloat(T, " 1"));
......@@ -72,8 +69,6 @@ test "fmt.parseFloat" {
7269}
7370
7471test "fmt.parseFloat nan and inf" {
75 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
76
7772 inline for ([_]type{ f16, f32, f64, f128 }) |T| {
7873 const Z = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
7974
......@@ -88,7 +83,7 @@ test "fmt.parseFloat #11169" {
8883}
8984
9085test "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
9388 try testing.expect(math.isNan(try parseFloat(f32, "nAn")));
9489 try testing.expect(math.isPositiveInf(try parseFloat(f32, "iNf")));
......@@ -96,8 +91,6 @@ test "fmt.parseFloat hex.special" {
9691 try testing.expect(math.isNegativeInf(try parseFloat(f32, "-iNf")));
9792}
9893test "fmt.parseFloat hex.zero" {
99 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
100
10194 try testing.expectEqual(@as(f32, 0.0), try parseFloat(f32, "0x0"));
10295 try testing.expectEqual(@as(f32, 0.0), try parseFloat(f32, "-0x0"));
10396 try testing.expectEqual(@as(f32, 0.0), try parseFloat(f32, "0x0p42"));
......@@ -106,8 +99,6 @@ test "fmt.parseFloat hex.zero" {
10699}
107100
108101test "fmt.parseFloat hex.f16" {
109 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
110
111102 try testing.expectEqual(try parseFloat(f16, "0x1p0"), 1.0);
112103 try testing.expectEqual(try parseFloat(f16, "-0x1p-1"), -0.5);
113104 try testing.expectEqual(try parseFloat(f16, "0x10p+10"), 16384.0);
......@@ -124,8 +115,6 @@ test "fmt.parseFloat hex.f16" {
124115}
125116
126117test "fmt.parseFloat hex.f32" {
127 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
128
129118 try testing.expectError(error.InvalidCharacter, parseFloat(f32, "0x"));
130119 try testing.expectEqual(try parseFloat(f32, "0x1p0"), 1.0);
131120 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" {
785785}
786786
787787test "parse into vector" {
788 if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
789
790788 const T = struct {
791789 vec_i32: @Vector(4, i32),
792790 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
40124012 .got => .load_memory_ptr_got,
40134013 .direct => .load_memory_ptr_direct,
40144014 .import => unreachable,
4015 .extern_got => unreachable,
40164015 };
40174016 const atom_index = switch (self.bin_file.tag) {
40184017 .macho => blk: {
......@@ -5532,7 +5531,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
55325531 .got => .load_memory_ptr_got,
55335532 .direct => .load_memory_ptr_direct,
55345533 .import => unreachable,
5535 .extern_got => unreachable,
55365534 };
55375535 const atom_index = switch (self.bin_file.tag) {
55385536 .macho => blk: {
......@@ -5654,7 +5652,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
56545652 .got => .load_memory_got,
56555653 .direct => .load_memory_direct,
56565654 .import => .load_memory_import,
5657 .extern_got => unreachable,
56585655 };
56595656 const atom_index = switch (self.bin_file.tag) {
56605657 .macho => blk: {
......@@ -5852,7 +5849,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
58525849 .got => .load_memory_ptr_got,
58535850 .direct => .load_memory_ptr_direct,
58545851 .import => unreachable,
5855 .extern_got => unreachable,
58565852 };
58575853 const atom_index = switch (self.bin_file.tag) {
58585854 .macho => blk: {
......@@ -6180,7 +6176,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
61806176 .memory => |addr| .{ .memory = addr },
61816177 .load_got => |sym_index| .{ .linker_load = .{ .type = .got, .sym_index = sym_index } },
61826178 .load_direct => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } },
6183 .load_extern_got, .load_tlv => unreachable, // TODO
6179 .load_symbol, .load_tlv => unreachable, // TODO
61846180 },
61856181 .fail => |msg| {
61866182 self.err_msg = msg;
src/arch/arm/CodeGen.zig+1-1
......@@ -6135,7 +6135,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
61356135 .mcv => |mcv| switch (mcv) {
61366136 .none => .none,
61376137 .undef => .undef,
6138 .load_got, .load_extern_got, .load_direct, .load_tlv => unreachable, // TODO
6138 .load_got, .load_symbol, .load_direct, .load_tlv => unreachable, // TODO
61396139 .immediate => |imm| .{ .immediate = @as(u32, @truncate(imm)) },
61406140 .memory => |addr| .{ .memory = addr },
61416141 },
src/arch/riscv64/CodeGen.zig+1-1
......@@ -2591,7 +2591,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
25912591 .mcv => |mcv| switch (mcv) {
25922592 .none => .none,
25932593 .undef => .undef,
2594 .load_got, .load_extern_got, .load_direct, .load_tlv => unreachable, // TODO
2594 .load_got, .load_symbol, .load_direct, .load_tlv => unreachable, // TODO
25952595 .immediate => |imm| .{ .immediate = imm },
25962596 .memory => |addr| .{ .memory = addr },
25972597 },
src/arch/sparc64/CodeGen.zig+1-1
......@@ -4137,7 +4137,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
41374137 .mcv => |mcv| switch (mcv) {
41384138 .none => .none,
41394139 .undef => .undef,
4140 .load_got, .load_extern_got, .load_direct, .load_tlv => unreachable, // TODO
4140 .load_got, .load_symbol, .load_direct, .load_tlv => unreachable, // TODO
41414141 .immediate => |imm| .{ .immediate = imm },
41424142 .memory => |addr| .{ .memory = addr },
41434143 },
src/arch/x86_64/CodeGen.zig+735-439
......@@ -193,6 +193,11 @@ pub const MCValue = union(enum) {
193193 /// The value is in memory at a hard-coded address.
194194 /// If the type is a pointer, it means the pointer address is stored at this memory location.
195195 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,
196201 /// The value is in memory at a constant offset from the address in a register.
197202 indirect: RegisterOffset,
198203 /// The value is in memory.
......@@ -207,12 +212,6 @@ pub const MCValue = union(enum) {
207212 /// The value is a pointer to a value referenced indirectly via GOT.
208213 /// Payload is a symbol index.
209214 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,
216215 /// The value is a threadlocal variable.
217216 /// Payload is a symbol index.
218217 load_tlv: u32,
......@@ -299,9 +298,9 @@ pub const MCValue = union(enum) {
299298 .register_pair,
300299 .register_offset,
301300 .register_overflow,
301 .lea_symbol,
302302 .lea_direct,
303303 .lea_got,
304 .lea_extern_got,
305304 .lea_tlv,
306305 .lea_frame,
307306 .reserved_frame,
......@@ -315,8 +314,8 @@ pub const MCValue = union(enum) {
315314 .load_direct => |sym_index| .{ .lea_direct = sym_index },
316315 .load_got => |sym_index| .{ .lea_got = sym_index },
317316 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
318 .load_extern_got => |sym_index| .{ .lea_extern_got = sym_index },
319317 .load_frame => |frame_addr| .{ .lea_frame = frame_addr },
318 .load_symbol => |sym_index| .{ .lea_symbol = sym_index },
320319 };
321320 }
322321
......@@ -333,9 +332,9 @@ pub const MCValue = union(enum) {
333332 .indirect,
334333 .load_direct,
335334 .load_got,
336 .load_extern_got,
337335 .load_tlv,
338336 .load_frame,
337 .load_symbol,
339338 .reserved_frame,
340339 .air_ref,
341340 => unreachable, // not dereferenceable
......@@ -344,9 +343,9 @@ pub const MCValue = union(enum) {
344343 .register_offset => |reg_off| .{ .indirect = reg_off },
345344 .lea_direct => |sym_index| .{ .load_direct = sym_index },
346345 .lea_got => |sym_index| .{ .load_got = sym_index },
347 .lea_extern_got => |sym_index| .{ .load_extern_got = sym_index },
348346 .lea_tlv => |sym_index| .{ .load_tlv = sym_index },
349347 .lea_frame => |frame_addr| .{ .load_frame = frame_addr },
348 .lea_symbol => |sym_index| .{ .load_symbol = sym_index },
350349 };
351350 }
352351
......@@ -368,11 +367,11 @@ pub const MCValue = union(enum) {
368367 .lea_direct,
369368 .load_got,
370369 .lea_got,
371 .load_extern_got,
372 .lea_extern_got,
373370 .load_tlv,
374371 .lea_tlv,
375372 .load_frame,
373 .load_symbol,
374 .lea_symbol,
376375 => switch (off) {
377376 0 => mcv,
378377 else => unreachable, // not offsettable
......@@ -404,13 +403,13 @@ pub const MCValue = union(enum) {
404403 .lea_direct,
405404 .load_got,
406405 .lea_got,
407 .load_extern_got,
408 .lea_extern_got,
409406 .load_tlv,
410407 .lea_tlv,
411408 .lea_frame,
412409 .reserved_frame,
413410 .air_ref,
411 .load_symbol,
412 .lea_symbol,
414413 => unreachable,
415414 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
416415 Memory.sib(ptr_size, .{ .base = .{ .reg = .ds }, .disp = small_addr })
......@@ -448,14 +447,14 @@ pub const MCValue = union(enum) {
448447 .lea_direct => |pl| try writer.print("direct:{d}", .{pl}),
449448 .load_got => |pl| try writer.print("[got:{d}]", .{pl}),
450449 .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}),
453450 .load_tlv => |pl| try writer.print("[tlv:{d}]", .{pl}),
454451 .lea_tlv => |pl| try writer.print("tlv:{d}", .{pl}),
455452 .load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }),
456453 .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }),
457454 .reserved_frame => |pl| try writer.print("(dead:{})", .{pl}),
458455 .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}),
459458 }
460459 }
461460};
......@@ -477,12 +476,12 @@ const InstTracking = struct {
477476 .lea_direct,
478477 .load_got,
479478 .lea_got,
480 .load_extern_got,
481 .lea_extern_got,
482479 .load_tlv,
483480 .lea_tlv,
484481 .load_frame,
485482 .lea_frame,
483 .load_symbol,
484 .lea_symbol,
486485 => result,
487486 .dead,
488487 .reserved_frame,
......@@ -538,12 +537,12 @@ const InstTracking = struct {
538537 .lea_direct,
539538 .load_got,
540539 .lea_got,
541 .load_extern_got,
542 .lea_extern_got,
543540 .load_tlv,
544541 .lea_tlv,
545542 .load_frame,
546543 .lea_frame,
544 .load_symbol,
545 .lea_symbol,
547546 => self.long,
548547 .dead,
549548 .eflags,
......@@ -575,11 +574,11 @@ const InstTracking = struct {
575574 .lea_direct,
576575 .load_got,
577576 .lea_got,
578 .load_extern_got,
579 .lea_extern_got,
580577 .load_tlv,
581578 .lea_tlv,
582579 .lea_frame,
580 .load_symbol,
581 .lea_symbol,
583582 => assert(std.meta.eql(self.long, target.long)),
584583 .load_frame,
585584 .reserved_frame,
......@@ -883,6 +882,7 @@ pub fn generate(
883882
884883 var emit = Emit{
885884 .lower = .{
885 .bin_file = bin_file,
886886 .allocator = bin_file.allocator,
887887 .mir = mir,
888888 .cc = cc,
......@@ -970,6 +970,7 @@ pub fn generateLazy(
970970
971971 var emit = Emit{
972972 .lower = .{
973 .bin_file = bin_file,
973974 .allocator = bin_file.allocator,
974975 .mir = mir,
975976 .cc = abi.resolveCallingConvention(.Unspecified, function.target.*),
......@@ -1060,6 +1061,7 @@ fn formatWipMir(
10601061 writer: anytype,
10611062) @TypeOf(writer).Error!void {
10621063 var lower = Lower{
1064 .bin_file = data.self.bin_file,
10631065 .allocator = data.self.gpa,
10641066 .mir = .{
10651067 .instructions = data.self.mir_instructions.slice(),
......@@ -3261,25 +3263,51 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
32613263 defer self.register_manager.unlockReg(tmp_lock);
32623264
32633265 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(
32653280 .{ ._, .mov },
32663281 tmp_reg,
3267 lhs_mcv.address().offset(8).deref().mem(.qword),
3282 mat_lhs_mcv.address().offset(8).deref().mem(.qword),
32683283 ) else try self.asmRegisterRegister(
32693284 .{ ._, .mov },
32703285 tmp_reg,
3271 lhs_mcv.register_pair[1],
3286 mat_lhs_mcv.register_pair[1],
32723287 );
32733288
32743289 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(
32763304 .{ ._, .xor },
32773305 tmp_reg,
3278 rhs_mcv.address().offset(8).deref().mem(.qword),
3306 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
32793307 ) else try self.asmRegisterRegister(
32803308 .{ ._, .xor },
32813309 tmp_reg,
3282 rhs_mcv.register_pair[1],
3310 mat_rhs_mcv.register_pair[1],
32833311 );
32843312 const reloc = try self.asmJccReloc(.ns, undefined);
32853313
......@@ -3353,20 +3381,37 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
33533381 defer for (tmp_locks) |lock| self.register_manager.unlockReg(lock);
33543382
33553383 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
33573398 for (tmp_regs, dst_regs) |tmp_reg, dst_reg|
33583399 try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, dst_reg);
3359 if (rhs_mcv.isMemory()) {
3360 try self.asmRegisterMemory(.{ ._, .add }, tmp_regs[0], rhs_mcv.mem(.qword));
3400 if (mat_rhs_mcv.isMemory()) {
3401 try self.asmRegisterMemory(
3402 .{ ._, .add },
3403 tmp_regs[0],
3404 mat_rhs_mcv.mem(.qword),
3405 );
33613406 try self.asmRegisterMemory(
33623407 .{ ._, .adc },
33633408 tmp_regs[1],
3364 rhs_mcv.address().offset(8).deref().mem(.qword),
3409 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
33653410 );
33663411 } else for (
33673412 [_]Mir.Inst.Tag{ .add, .adc },
33683413 tmp_regs,
3369 rhs_mcv.register_pair,
3414 mat_rhs_mcv.register_pair,
33703415 ) |op, tmp_reg, rhs_reg|
33713416 try self.asmRegisterRegister(.{ ._, op }, tmp_reg, rhs_reg);
33723417 try self.asmRegisterRegister(.{ ._, .@"test" }, dst_regs[1], dst_regs[1]);
......@@ -3871,39 +3916,65 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
38713916
38723917 const lhs_mcv = try self.resolveInst(bin_op.lhs);
38733918 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())
3876 try self.asmRegisterMemory(.{ ._, .mov }, .rax, lhs_mcv.mem(.qword))
3946 if (mat_lhs_mcv.isMemory())
3947 try self.asmRegisterMemory(.{ ._, .mov }, .rax, mat_lhs_mcv.mem(.qword))
38773948 else
3878 try self.asmRegisterRegister(.{ ._, .mov }, .rax, lhs_mcv.register_pair[0]);
3879 if (rhs_mcv.isMemory()) try self.asmRegisterMemory(
3949 try self.asmRegisterRegister(.{ ._, .mov }, .rax, mat_lhs_mcv.register_pair[0]);
3950 if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory(
38803951 .{ ._, .mov },
38813952 tmp_regs[0],
3882 rhs_mcv.address().offset(8).deref().mem(.qword),
3953 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
38833954 ) else try self.asmRegisterRegister(
38843955 .{ ._, .mov },
38853956 tmp_regs[0],
3886 rhs_mcv.register_pair[1],
3957 mat_rhs_mcv.register_pair[1],
38873958 );
38883959 try self.asmRegisterRegister(.{ ._, .@"test" }, tmp_regs[0], tmp_regs[0]);
38893960 try self.asmSetccRegister(.nz, tmp_regs[1].to8());
38903961 try self.asmRegisterRegister(.{ .i_, .mul }, tmp_regs[0], .rax);
38913962 try self.asmSetccRegister(.o, tmp_regs[2].to8());
3892 if (rhs_mcv.isMemory())
3893 try self.asmMemory(.{ ._, .mul }, rhs_mcv.mem(.qword))
3963 if (mat_rhs_mcv.isMemory())
3964 try self.asmMemory(.{ ._, .mul }, mat_rhs_mcv.mem(.qword))
38943965 else
3895 try self.asmRegister(.{ ._, .mul }, rhs_mcv.register_pair[0]);
3966 try self.asmRegister(.{ ._, .mul }, mat_rhs_mcv.register_pair[0]);
38963967 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_regs[0]);
38973968 try self.asmSetccRegister(.c, tmp_regs[3].to8());
38983969 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(
39003971 .{ ._, .mov },
39013972 tmp_regs[0],
3902 lhs_mcv.address().offset(8).deref().mem(.qword),
3973 mat_lhs_mcv.address().offset(8).deref().mem(.qword),
39033974 ) else try self.asmRegisterRegister(
39043975 .{ ._, .mov },
39053976 tmp_regs[0],
3906 lhs_mcv.register_pair[1],
3977 mat_lhs_mcv.register_pair[1],
39073978 );
39083979 try self.asmRegisterRegister(.{ ._, .@"test" }, tmp_regs[0], tmp_regs[0]);
39093980 try self.asmSetccRegister(.nz, tmp_regs[3].to8());
......@@ -3913,13 +3984,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
39133984 tmp_regs[3].to8(),
39143985 );
39153986 try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[1].to8(), tmp_regs[2].to8());
3916 if (rhs_mcv.isMemory())
3917 try self.asmRegisterMemory(.{ .i_, .mul }, tmp_regs[0], rhs_mcv.mem(.qword))
3987 if (mat_rhs_mcv.isMemory())
3988 try self.asmRegisterMemory(.{ .i_, .mul }, tmp_regs[0], mat_rhs_mcv.mem(.qword))
39183989 else
39193990 try self.asmRegisterRegister(
39203991 .{ .i_, .mul },
39213992 tmp_regs[0],
3922 rhs_mcv.register_pair[0],
3993 mat_rhs_mcv.register_pair[0],
39233994 );
39243995 try self.asmSetccRegister(.o, tmp_regs[2].to8());
39253996 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 {
47294800 Memory.sib(.qword, .{ .base = .{ .frame = frame_addr.index }, .disp = frame_addr.off }),
47304801 ),
47314802 .memory,
4803 .load_symbol,
47324804 .load_direct,
47334805 .load_got,
4734 .load_extern_got,
47354806 .load_tlv,
47364807 => try self.genSetReg(addr_reg, Type.usize, array.address()),
4737 .lea_direct, .lea_tlv => unreachable,
4808 .lea_symbol, .lea_direct, .lea_tlv => unreachable,
47384809 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
47394810 }
47404811
......@@ -6327,17 +6398,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro
63276398 .immediate,
63286399 .register,
63296400 .register_offset,
6401 .lea_symbol,
63306402 .lea_direct,
63316403 .lea_got,
6332 .lea_extern_got,
63336404 .lea_tlv,
63346405 .lea_frame,
63356406 => try self.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()),
63366407 .memory,
63376408 .indirect,
6409 .load_symbol,
63386410 .load_direct,
63396411 .load_got,
6340 .load_extern_got,
63416412 .load_tlv,
63426413 .load_frame,
63436414 => {
......@@ -6476,17 +6547,17 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr
64766547 .immediate,
64776548 .register,
64786549 .register_offset,
6550 .lea_symbol,
64796551 .lea_direct,
64806552 .lea_got,
6481 .lea_extern_got,
64826553 .lea_tlv,
64836554 .lea_frame,
64846555 => try self.genCopy(src_ty, ptr_mcv.deref(), src_mcv),
64856556 .memory,
64866557 .indirect,
6558 .load_symbol,
64876559 .load_direct,
64886560 .load_got,
6489 .load_extern_got,
64906561 .load_tlv,
64916562 .load_frame,
64926563 => {
......@@ -6587,12 +6658,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
65876658 const src_reg_lock = self.register_manager.lockRegAssumeUnused(src_reg);
65886659 defer self.register_manager.unlockReg(src_reg_lock);
65896660
6590 const dst_reg = if (field_rc.supersetOf(container_rc) and
6591 self.reuseOperand(inst, operand, 0, src_mcv))
6661 const src_in_field_rc =
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))
65926664 src_reg
6665 else if (field_off == 0)
6666 (try self.copyToRegisterWithInstTracking(inst, field_ty, src_mcv)).register
65936667 else
65946668 try self.copyToTmpRegister(Type.usize, .{ .register = src_reg });
6595 const dst_mcv = MCValue{ .register = dst_reg };
6669 const dst_mcv: MCValue = .{ .register = dst_reg };
65966670 const dst_lock = self.register_manager.lockReg(dst_reg);
65976671 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
65986672
......@@ -6602,9 +6676,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
66026676 dst_mcv,
66036677 .{ .immediate = field_off },
66046678 );
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))
66086684 dst_mcv
66096685 else
66106686 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
69086984 .register_overflow,
69096985 .lea_direct,
69106986 .lea_got,
6911 .lea_extern_got,
69126987 .lea_tlv,
69136988 .lea_frame,
69146989 .reserved_frame,
69156990 .air_ref,
6991 .lea_symbol,
69166992 => unreachable, // unmodifiable destination
69176993 .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)),
69186994 .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 => {
69206996 const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
69216997 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
69226998 defer self.register_manager.unlockReg(addr_reg_lock);
......@@ -7352,34 +7428,61 @@ fn genMulDivBinOp(
73527428 const reg_locks = self.register_manager.lockRegsAssumeUnused(2, .{ .rax, .rdx });
73537429 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
73557458 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
73567459 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
73577460 defer self.register_manager.unlockReg(tmp_lock);
73587461
7359 if (lhs_mcv.isMemory())
7360 try self.asmRegisterMemory(.{ ._, .mov }, .rax, lhs_mcv.mem(.qword))
7462 if (mat_lhs_mcv.isMemory())
7463 try self.asmRegisterMemory(.{ ._, .mov }, .rax, mat_lhs_mcv.mem(.qword))
73617464 else
7362 try self.asmRegisterRegister(.{ ._, .mov }, .rax, lhs_mcv.register_pair[0]);
7363 if (rhs_mcv.isMemory()) try self.asmRegisterMemory(
7465 try self.asmRegisterRegister(.{ ._, .mov }, .rax, mat_lhs_mcv.register_pair[0]);
7466 if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory(
73647467 .{ ._, .mov },
73657468 tmp_reg,
7366 rhs_mcv.address().offset(8).deref().mem(.qword),
7367 ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, rhs_mcv.register_pair[1]);
7469 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
7470 ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, mat_rhs_mcv.register_pair[1]);
73687471 try self.asmRegisterRegister(.{ .i_, .mul }, tmp_reg, .rax);
7369 if (rhs_mcv.isMemory())
7370 try self.asmMemory(.{ ._, .mul }, rhs_mcv.mem(.qword))
7472 if (mat_rhs_mcv.isMemory())
7473 try self.asmMemory(.{ ._, .mul }, mat_rhs_mcv.mem(.qword))
73717474 else
7372 try self.asmRegister(.{ ._, .mul }, rhs_mcv.register_pair[0]);
7475 try self.asmRegister(.{ ._, .mul }, mat_rhs_mcv.register_pair[0]);
73737476 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_reg);
7374 if (lhs_mcv.isMemory()) try self.asmRegisterMemory(
7477 if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory(
73757478 .{ ._, .mov },
73767479 tmp_reg,
7377 lhs_mcv.address().offset(8).deref().mem(.qword),
7378 ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, lhs_mcv.register_pair[1]);
7379 if (rhs_mcv.isMemory())
7380 try self.asmRegisterMemory(.{ .i_, .mul }, tmp_reg, rhs_mcv.mem(.qword))
7480 mat_lhs_mcv.address().offset(8).deref().mem(.qword),
7481 ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, mat_lhs_mcv.register_pair[1]);
7482 if (mat_rhs_mcv.isMemory())
7483 try self.asmRegisterMemory(.{ .i_, .mul }, tmp_reg, mat_rhs_mcv.mem(.qword))
73817484 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]);
73837486 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_reg);
73847487 return .{ .register_pair = .{ .rax, .rdx } };
73857488 }
......@@ -7968,12 +8071,12 @@ fn genBinOp(
79688071 .immediate,
79698072 .eflags,
79708073 .register_offset,
8074 .load_symbol,
8075 .lea_symbol,
79718076 .load_direct,
79728077 .lea_direct,
79738078 .load_got,
79748079 .lea_got,
7975 .load_extern_got,
7976 .lea_extern_got,
79778080 .load_tlv,
79788081 .lea_tlv,
79798082 .lea_frame,
......@@ -8026,12 +8129,12 @@ fn genBinOp(
80268129 .register_pair,
80278130 .register_offset,
80288131 .register_overflow,
8132 .load_symbol,
8133 .lea_symbol,
80298134 .load_direct,
80308135 .lea_direct,
80318136 .load_got,
80328137 .lea_got,
8033 .load_extern_got,
8034 .lea_extern_got,
80358138 .load_tlv,
80368139 .lea_tlv,
80378140 .lea_frame,
......@@ -9159,9 +9262,9 @@ fn genBinOpMir(
91599262 .register_overflow,
91609263 .lea_direct,
91619264 .lea_got,
9162 .lea_extern_got,
91639265 .lea_tlv,
91649266 .lea_frame,
9267 .lea_symbol,
91659268 .reserved_frame,
91669269 .air_ref,
91679270 => unreachable, // unmodifiable destination
......@@ -9244,12 +9347,12 @@ fn genBinOpMir(
92449347 .register_offset,
92459348 .memory,
92469349 .indirect,
9350 .load_symbol,
9351 .lea_symbol,
92479352 .load_direct,
92489353 .lea_direct,
92499354 .load_got,
92509355 .lea_got,
9251 .load_extern_got,
9252 .lea_extern_got,
92539356 .load_tlv,
92549357 .lea_tlv,
92559358 .load_frame,
......@@ -9280,9 +9383,9 @@ fn genBinOpMir(
92809383 switch (src_mcv) {
92819384 .eflags,
92829385 .register_offset,
9386 .lea_symbol,
92839387 .lea_direct,
92849388 .lea_got,
9285 .lea_extern_got,
92869389 .lea_tlv,
92879390 .lea_frame,
92889391 => {
......@@ -9296,9 +9399,9 @@ fn genBinOpMir(
92969399 );
92979400 },
92989401 .memory,
9402 .load_symbol,
92999403 .load_direct,
93009404 .load_got,
9301 .load_extern_got,
93029405 .load_tlv,
93039406 => {
93049407 const ptr_ty = try mod.singleConstPtrType(ty);
......@@ -9319,13 +9422,13 @@ fn genBinOpMir(
93199422 }
93209423 }
93219424 },
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 => {
93239426 const OpInfo = ?struct { addr_reg: Register, addr_lock: RegisterLock };
93249427 const limb_abi_size: u32 = @min(abi_size, 8);
93259428
93269429 const dst_info: OpInfo = switch (dst_mcv) {
93279430 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: {
93299432 const dst_addr_reg =
93309433 (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64();
93319434 const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);
......@@ -9359,17 +9462,17 @@ fn genBinOpMir(
93599462 .indirect,
93609463 .lea_direct,
93619464 .lea_got,
9362 .lea_extern_got,
93639465 .lea_tlv,
93649466 .load_frame,
93659467 .lea_frame,
9468 .lea_symbol,
93669469 => null,
9367 .memory, .load_got, .load_extern_got, .load_direct, .load_tlv => src: {
9470 .memory, .load_symbol, .load_got, .load_direct, .load_tlv => src: {
93689471 switch (resolved_src_mcv) {
93699472 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr))) != null and
93709473 math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null)
93719474 break :src null,
9372 .load_got, .load_extern_got, .load_direct, .load_tlv => {},
9475 .load_symbol, .load_got, .load_direct, .load_tlv => {},
93739476 else => unreachable,
93749477 }
93759478
......@@ -9411,8 +9514,8 @@ fn genBinOpMir(
94119514 Memory.PtrSize.fromSize(limb_abi_size),
94129515 switch (dst_mcv) {
94139516 .memory,
9517 .load_symbol,
94149518 .load_got,
9415 .load_extern_got,
94169519 .load_direct,
94179520 .load_tlv,
94189521 => .{ .base = .{ .reg = dst_info.?.addr_reg }, .disp = off },
......@@ -9493,12 +9596,12 @@ fn genBinOpMir(
94939596 .eflags,
94949597 .memory,
94959598 .indirect,
9599 .load_symbol,
9600 .lea_symbol,
94969601 .load_direct,
94979602 .lea_direct,
94989603 .load_got,
94999604 .lea_got,
9500 .load_extern_got,
9501 .lea_extern_got,
95029605 .load_tlv,
95039606 .lea_tlv,
95049607 .load_frame,
......@@ -9512,9 +9615,9 @@ fn genBinOpMir(
95129615 },
95139616 .eflags,
95149617 .register_offset,
9618 .lea_symbol,
95159619 .lea_direct,
95169620 .lea_got,
9517 .lea_extern_got,
95189621 .lea_tlv,
95199622 .lea_frame,
95209623 => switch (limb_i) {
......@@ -9563,9 +9666,9 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
95639666 .eflags,
95649667 .register_offset,
95659668 .register_overflow,
9669 .lea_symbol,
95669670 .lea_direct,
95679671 .lea_got,
9568 .lea_extern_got,
95699672 .lea_tlv,
95709673 .lea_frame,
95719674 .reserved_frame,
......@@ -9610,12 +9713,12 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
96109713 },
96119714 .register_offset,
96129715 .eflags,
9716 .load_symbol,
9717 .lea_symbol,
96139718 .load_direct,
96149719 .lea_direct,
96159720 .load_got,
96169721 .lea_got,
9617 .load_extern_got,
9618 .lea_extern_got,
96199722 .load_tlv,
96209723 .lea_tlv,
96219724 .lea_frame,
......@@ -9654,7 +9757,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
96549757 }
96559758 },
96569759 .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 => {
96589761 const tmp_reg = try self.copyToTmpRegister(dst_ty, dst_mcv);
96599762 const tmp_mcv = MCValue{ .register = tmp_reg };
96609763 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
......@@ -9674,17 +9777,25 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
96749777 self.arg_index = arg_index + 1;
96759778
96769779 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {
9677 const dst_mcv = self.args[arg_index];
9678 switch (dst_mcv) {
9679 .register, .register_pair, .load_frame => for (dst_mcv.getRegs()) |reg|
9680 self.register_manager.getRegAssumeFree(reg, inst),
9681 else => return self.fail("TODO implement arg for {}", .{dst_mcv}),
9682 }
9780 const arg_ty = self.typeOfIndex(inst);
9781 const src_mcv = self.args[arg_index];
9782 const dst_mcv = switch (src_mcv) {
9783 .register, .register_pair, .load_frame => dst: {
9784 for (src_mcv.getRegs()) |reg| self.register_manager.getRegAssumeFree(reg, inst);
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);
96859796 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
96869797 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
96899800 break :result dst_mcv;
96909801 };
......@@ -9746,8 +9857,8 @@ fn genVarDbgInfo(
97469857 // .offset = -off,
97479858 //} },
97489859 .memory => |address| .{ .memory = address },
9860 .load_symbol => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } }, // TODO
97499861 .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 } },
97519862 .load_direct => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } },
97529863 .immediate => |x| .{ .immediate = x },
97539864 .undef => .undef,
......@@ -9863,7 +9974,8 @@ fn genCall(self: *Self, info: union(enum) {
98639974
98649975 const ExpectedContents = extern struct {
98659976 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)),
98679979 };
98689980 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
98699981 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
......@@ -9873,10 +9985,13 @@ fn genCall(self: *Self, info: union(enum) {
98739985 defer allocator.free(var_args);
98749986 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);
9877 defer arg_locks.deinit();
9878 try arg_locks.ensureTotalCapacity(16);
9879 defer for (arg_locks.items) |arg_lock| if (arg_lock) |lock| self.register_manager.unlockReg(lock);
9988 const frame_indices = try allocator.alloc(FrameIndex, args.len);
9989 defer allocator.free(frame_indices);
9990
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
98819996 var call_info = try self.resolveCallingConventionValues(fn_info, var_args, .call_frame);
98829997 defer call_info.deinit(self);
......@@ -9908,44 +10023,69 @@ fn genCall(self: *Self, info: union(enum) {
990810023 .indirect => |reg_off| try self.spillRegisters(&.{reg_off.reg}),
990910024 else => unreachable,
991010025 }
9911 for (call_info.args, arg_types, args) |dst_arg, arg_ty, src_arg| switch (dst_arg) {
9912 .none => {},
9913 .register => |reg| {
9914 try self.spillRegisters(&.{reg});
9915 try arg_locks.append(self.register_manager.lockReg(reg));
9916 },
9917 .register_pair => |regs| {
9918 try self.spillRegisters(&regs);
9919 try arg_locks.appendSlice(&self.register_manager.lockRegs(2, regs));
9920 },
9921 .load_frame => {
9922 try self.genCopy(arg_ty, dst_arg, src_arg);
9923 try self.freeValue(src_arg);
9924 },
9925 else => unreachable,
9926 };
10026 for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, *frame_index|
10027 switch (dst_arg) {
10028 .none => {},
10029 .register => |reg| {
10030 try self.spillRegisters(&.{reg});
10031 try reg_locks.append(self.register_manager.lockReg(reg));
10032 },
10033 .register_pair => |regs| {
10034 try self.spillRegisters(&regs);
10035 try reg_locks.appendSlice(&self.register_manager.lockRegs(2, regs));
10036 },
10037 .indirect => |reg_off| {
10038 frame_index.* = try self.allocFrameIndex(FrameAlloc.initType(arg_ty, mod));
10039 try self.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg);
10040 try self.spillRegisters(&.{reg_off.reg});
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
992810050 // now we are free to set register arguments
9929 const ret_lock = switch (call_info.return_value.long) {
9930 .none, .unreach => null,
9931 .indirect => |reg_off| lock: {
10051 switch (call_info.return_value.long) {
10052 .none, .unreach => {},
10053 .indirect => |reg_off| {
993210054 const ret_ty = fn_info.return_type.toType();
993310055 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, mod));
993410056 try self.genSetReg(reg_off.reg, Type.usize, .{
993510057 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
993610058 });
993710059 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));
993910061 },
994010062 else => unreachable,
9941 };
9942 defer if (ret_lock) |lock| self.register_manager.unlockReg(lock);
10063 }
994310064
9944 for (call_info.args, arg_types, args) |dst_arg, arg_ty, src_arg| switch (dst_arg) {
9945 .none, .load_frame => {},
9946 .register, .register_pair => try self.genCopy(arg_ty, dst_arg, src_arg),
9947 else => unreachable,
9948 };
10065 for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, frame_index|
10066 switch (dst_arg) {
10067 .none, .load_frame => {},
10068 .register => |dst_reg| switch (fn_info.cc) {
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
995010090 if (fn_info.is_var_args)
995110091 try self.asmRegisterImmediate(.{ ._, .mov }, .al, Immediate.u(call_info.fp_count));
......@@ -9969,12 +10109,12 @@ fn genCall(self: *Self, info: union(enum) {
996910109 const sym = elf_file.symbol(sym_index);
997010110 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
997110111 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 });
997310113 try self.asmRegister(.{ ._, .call }, .rax);
997410114 } else {
997510115 _ = try self.addInst(.{
997610116 .tag = .call,
9977 .ops = .direct_got_reloc,
10117 .ops = .linker_reloc,
997810118 .data = .{ .reloc = .{
997910119 .atom_index = try self.owner.getSymbolIndex(self),
998010120 .sym_index = sym.esym_index,
......@@ -10054,7 +10194,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
1005410194 const ptr_ty = self.typeOf(un_op);
1005510195 switch (self.ret_mcv.short) {
1005610196 .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),
1005810198 .indirect => |reg_off| try self.genSetReg(reg_off.reg, ptr_ty, ptr),
1005910199 else => unreachable,
1006010200 }
......@@ -10115,20 +10255,28 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1011510255 try self.spillEflagsIfOccupied();
1011610256
1011710257 const lhs_mcv = try self.resolveInst(bin_op.lhs);
10118 const lhs_lock = switch (lhs_mcv) {
10119 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
10120 .register_offset => |ro| self.register_manager.lockRegAssumeUnused(ro.reg),
10121 else => null,
10258 const lhs_locks: [2]?RegisterLock = switch (lhs_mcv) {
10259 .register => |lhs_reg| .{ self.register_manager.lockRegAssumeUnused(lhs_reg), null },
10260 .register_pair => |lhs_regs| locks: {
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,
1012210269 };
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
1012510272 const rhs_mcv = try self.resolveInst(bin_op.rhs);
10126 const rhs_lock = switch (rhs_mcv) {
10127 .register => |reg| self.register_manager.lockReg(reg),
10128 .register_offset => |ro| self.register_manager.lockReg(ro.reg),
10129 else => null,
10273 const rhs_locks: [2]?RegisterLock = switch (rhs_mcv) {
10274 .register => |rhs_reg| .{ self.register_manager.lockReg(rhs_reg), null },
10275 .register_pair => |rhs_regs| self.register_manager.lockRegs(2, rhs_regs),
10276 .register_offset => |rhs_ro| .{ self.register_manager.lockReg(rhs_ro.reg), null },
10277 else => .{null} ** 2,
1013010278 };
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
1013310281 switch (ty.zigTypeTag(mod)) {
1013410282 else => {
......@@ -10159,7 +10307,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1015910307 if (dst_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
1016010308 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);
1016310311 const src_lock =
1016410312 if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
1016510313 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 {
1019110339 .indirect,
1019210340 .lea_direct,
1019310341 .lea_got,
10194 .lea_extern_got,
1019510342 .lea_tlv,
1019610343 .lea_frame,
10344 .lea_symbol,
1019710345 .reserved_frame,
1019810346 .air_ref,
1019910347 => unreachable,
1020010348 .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: {
1020210350 switch (resolved_dst_mcv) {
1020310351 .memory => |addr| if (math.cast(
1020410352 i32,
......@@ -10207,7 +10355,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1020710355 i32,
1020810356 @as(i64, @bitCast(addr)) + abi_size - 8,
1020910357 ) != null) break :dst null,
10210 .load_got, .load_extern_got, .load_direct, .load_tlv => {},
10358 .load_symbol, .load_got, .load_direct, .load_tlv => {},
1021110359 else => unreachable,
1021210360 }
1021310361
......@@ -10248,16 +10396,16 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1024810396 .register_offset,
1024910397 .register_overflow,
1025010398 .indirect,
10399 .lea_symbol,
1025110400 .lea_direct,
1025210401 .lea_got,
10253 .lea_extern_got,
1025410402 .lea_tlv,
1025510403 .lea_frame,
1025610404 .reserved_frame,
1025710405 .air_ref,
1025810406 => unreachable,
1025910407 .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: {
1026110409 switch (resolved_src_mcv) {
1026210410 .memory => |addr| if (math.cast(
1026310411 i32,
......@@ -10266,7 +10414,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1026610414 i32,
1026710415 @as(i64, @bitCast(addr)) + abi_size - 8,
1026810416 ) != null) break :src null,
10269 .load_got, .load_extern_got, .load_direct, .load_tlv => {},
10417 .load_symbol, .load_got, .load_direct, .load_tlv => {},
1027010418 else => unreachable,
1027110419 }
1027210420
......@@ -10350,13 +10498,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1035010498 },
1035110499 );
1035210500
10353 if (limb_i > 0) try self.asmRegisterRegister(
10354 .{ ._, .@"or" },
10355 acc_reg,
10356 tmp_reg,
10357 );
10501 if (limb_i > 0)
10502 try self.asmRegisterRegister(.{ ._, .@"or" }, acc_reg, tmp_reg);
1035810503 }
10359 try self.asmRegisterRegister(.{ ._, .@"test" }, acc_reg, acc_reg);
10504 assert(limbs_len >= 2); // use flags from or
1036010505 break :result_op flipped_op;
1036110506 },
1036210507 };
......@@ -10692,9 +10837,9 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
1069210837 .register_overflow,
1069310838 .lea_direct,
1069410839 .lea_got,
10695 .lea_extern_got,
1069610840 .lea_tlv,
1069710841 .lea_frame,
10842 .lea_symbol,
1069810843 .reserved_frame,
1069910844 .air_ref,
1070010845 => unreachable,
......@@ -10718,8 +10863,8 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
1071810863 },
1071910864
1072010865 .memory,
10866 .load_symbol,
1072110867 .load_got,
10722 .load_extern_got,
1072310868 .load_direct,
1072410869 .load_tlv,
1072510870 => {
......@@ -11316,7 +11461,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1131611461 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
1131711462 break :arg input_mcv,
1131811463 .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 => {},
1132011465 else => {
1132111466 const temp_mcv = try self.allocTempRegOrMem(ty, false);
1132211467 try self.genCopy(ty, temp_mcv, input_mcv);
......@@ -11578,6 +11723,10 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1157811723 .{ .reg = try self.copyToTmpRegister(Type.usize, .{ .lea_got = sym_index }) }
1157911724 else
1158011725 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}),
1158111730 else => return self.fail("invalid constraint: '{s}'", .{op_str}),
1158211731 };
1158311732 } else if (mem.startsWith(u8, op_str, "$")) {
......@@ -11798,6 +11947,7 @@ const MoveStrategy = union(enum) {
1179811947 .move => |tag| try self.asmRegisterMemory(tag, dst_reg, src_mem),
1179911948 .x87_load_store => {
1180011949 try self.asmMemory(.{ .f_, .ld }, src_mem);
11950 assert(dst_reg != .st7);
1180111951 try self.asmRegister(.{ .f_p, .st }, @enumFromInt(@intFromEnum(dst_reg) + 1));
1180211952 },
1180311953 .insert_extract => |ie| try self.asmRegisterMemoryImmediate(
......@@ -11831,188 +11981,284 @@ const MoveStrategy = union(enum) {
1183111981 }
1183211982 }
1183311983};
11834fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
11984fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !MoveStrategy {
1183511985 const mod = self.bin_file.options.module.?;
11836 switch (ty.zigTypeTag(mod)) {
11837 else => return .{ .move = .{ ._, .mov } },
11838 .Float => switch (ty.floatBits(self.target.*)) {
11839 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
11840 .insert = .{ .vp_w, .insr },
11841 .extract = .{ .vp_w, .extr },
11842 } } else .{ .insert_extract = .{
11843 .insert = .{ .p_w, .insr },
11844 .extract = .{ .p_w, .extr },
11845 } },
11846 32 => return .{ .move = if (self.hasFeature(.avx)) .{ .v_ss, .mov } else .{ ._ss, .mov } },
11847 64 => return .{ .move = if (self.hasFeature(.avx)) .{ .v_sd, .mov } else .{ ._sd, .mov } },
11848 80 => return .x87_load_store,
11849 128 => return .{ .move = if (self.hasFeature(.avx))
11850 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11851 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11852 else => {},
11853 },
11854 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
11855 .Bool => return .{ .move = .{ ._, .mov } },
11856 .Int => switch (ty.childType(mod).intInfo(mod).bits) {
11857 8 => switch (ty.vectorLen(mod)) {
11858 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{
11859 .insert = .{ .vp_b, .insr },
11860 .extract = .{ .vp_b, .extr },
11861 } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{
11862 .insert = .{ .p_b, .insr },
11863 .extract = .{ .p_b, .extr },
11864 } },
11865 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
11866 .insert = .{ .vp_w, .insr },
11867 .extract = .{ .vp_w, .extr },
11868 } } else .{ .insert_extract = .{
11869 .insert = .{ .p_w, .insr },
11870 .extract = .{ .p_w, .extr },
11871 } },
11872 3...4 => return .{ .move = if (self.hasFeature(.avx))
11873 .{ .v_d, .mov }
11874 else
11875 .{ ._d, .mov } },
11876 5...8 => return .{ .move = if (self.hasFeature(.avx))
11877 .{ .v_q, .mov }
11878 else
11879 .{ ._q, .mov } },
11880 9...16 => return .{ .move = if (self.hasFeature(.avx))
11881 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11882 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11883 17...32 => if (self.hasFeature(.avx))
11884 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
11885 else => {},
11886 },
11887 16 => switch (ty.vectorLen(mod)) {
11888 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
11889 .insert = .{ .vp_w, .insr },
11890 .extract = .{ .vp_w, .extr },
11891 } } else .{ .insert_extract = .{
11892 .insert = .{ .p_w, .insr },
11893 .extract = .{ .p_w, .extr },
11894 } },
11895 2 => return .{ .move = if (self.hasFeature(.avx))
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 => {},
11986 switch (class) {
11987 .general_purpose, .segment => return .{ .move = .{ ._, .mov } },
11988 .x87 => return .x87_load_store,
11989 .mmx => {},
11990 .sse => {
11991 switch (ty.zigTypeTag(mod)) {
11992 else => {
11993 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none);
11994 assert(std.mem.indexOfNone(abi.Class, classes, &.{
11995 .integer, .sse, .float, .float_combine,
11996 }) == null);
11997 const abi_size = ty.abiSize(mod);
11998 if (abi_size < 4 or
11999 std.mem.indexOfScalar(abi.Class, classes, .integer) != null) switch (abi_size) {
12000 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{
12001 .insert = .{ .vp_b, .insr },
12002 .extract = .{ .vp_b, .extr },
12003 } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{
12004 .insert = .{ .p_b, .insr },
12005 .extract = .{ .p_b, .extr },
12006 } },
12007 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12008 .insert = .{ .vp_w, .insr },
12009 .extract = .{ .vp_w, .extr },
12010 } } else .{ .insert_extract = .{
12011 .insert = .{ .p_w, .insr },
12012 .extract = .{ .p_w, .extr },
12013 } },
12014 3...4 => return .{ .move = if (self.hasFeature(.avx))
12015 .{ .v_d, .mov }
12016 else
12017 .{ ._d, .mov } },
12018 5...8 => return .{ .move = if (self.hasFeature(.avx))
12019 .{ .v_q, .mov }
12020 else
12021 .{ ._q, .mov } },
12022 9...16 => return .{ .move = if (self.hasFeature(.avx))
12023 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12024 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12025 17...32 => if (self.hasFeature(.avx))
12026 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
12027 else => {},
12028 } else switch (abi_size) {
12029 4 => return .{ .move = if (self.hasFeature(.avx))
12030 .{ .v_ss, .mov }
12031 else
12032 .{ ._ss, .mov } },
12033 5...8 => return .{ .move = if (self.hasFeature(.avx))
12034 .{ .v_sd, .mov }
12035 else
12036 .{ ._sd, .mov } },
12037 9...16 => return .{ .move = if (self.hasFeature(.avx))
12038 if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu }
12039 else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } },
12040 17...32 => if (self.hasFeature(.avx)) return .{ .move = if (aligned)
12041 .{ .v_pd, .mova }
12042 else
12043 .{ .v_pd, .movu } },
12044 else => {},
12045 }
1195012046 },
11951 else => {},
11952 },
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 = .{
12047 .Float => switch (ty.floatBits(self.target.*)) {
12048 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
1195612049 .insert = .{ .vp_w, .insr },
1195712050 .extract = .{ .vp_w, .extr },
1195812051 } } else .{ .insert_extract = .{
1195912052 .insert = .{ .p_w, .insr },
1196012053 .extract = .{ .p_w, .extr },
1196112054 } },
11962 2 => 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))
12055 32 => return .{ .move = if (self.hasFeature(.avx))
1197912056 .{ .v_ss, .mov }
1198012057 else
1198112058 .{ ._ss, .mov } },
11982 2 => 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))
12059 64 => return .{ .move = if (self.hasFeature(.avx))
1199512060 .{ .v_sd, .mov }
1199612061 else
1199712062 .{ ._sd, .mov } },
11998 2 => 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))
12063 128 => return .{ .move = if (self.hasFeature(.avx))
1200712064 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
1200812065 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12009 2 => if (self.hasFeature(.avx))
12010 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
1201112066 else => {},
1201212067 },
12013 else => {},
12014 },
12015 else => {},
12068 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
12069 .Bool => return .{ .move = .{ ._, .mov } },
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 }
1201612262 },
1201712263 }
1201812264 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
1203412280 .register_overflow,
1203512281 .lea_direct,
1203612282 .lea_got,
12037 .lea_extern_got,
1203812283 .lea_tlv,
1203912284 .lea_frame,
12285 .lea_symbol,
1204012286 .reserved_frame,
1204112287 .air_ref,
1204212288 => unreachable, // unmodifiable destination
......@@ -12060,37 +12306,58 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError
1206012306 } },
1206112307 }),
1206212308 .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 },
1206412320 .air_ref => |src_ref| return self.genCopy(ty, dst_mcv, try self.resolveInst(src_ref)),
12065 else => {},
12066 }
12321 else => return self.fail("TODO implement genCopy for {s} of {}", .{
12322 @tagName(src_mcv), ty.fmt(mod),
12323 }),
12324 };
12325 defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock);
12326
1206712327 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none);
1206812328 for (dst_regs, classes, 0..) |dst_reg, class, dst_reg_i| {
1206912329 const class_ty = switch (class) {
1207012330 .integer => Type.usize,
12071 .sse => Type.f64,
12331 .sse, .float, .float_combine => Type.f64,
1207212332 else => unreachable,
1207312333 };
12334 const off: i32 = @intCast(dst_reg_i * 8);
1207412335 switch (src_mcv) {
1207512336 .register_pair => |src_regs| try self.genSetReg(
1207612337 dst_reg,
1207712338 class_ty,
1207812339 .{ .register = src_regs[dst_reg_i] },
1207912340 ),
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(
1208112347 dst_reg,
1208212348 class_ty,
12083 src_mcv.address().offset(@intCast(dst_reg_i * 8)).deref(),
12349 .{ .indirect = .{ .reg = src_info.?.addr_reg, .off = off } },
1208412350 ),
12351 else => unreachable,
1208512352 }
1208612353 }
1208712354 },
1208812355 .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 => {
1209012357 switch (dst_mcv) {
1209112358 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
1209212359 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 => {},
1209412361 else => unreachable,
1209512362 }
1209612363
......@@ -12157,6 +12424,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1215712424 registerAlias(dst_reg, abi_size),
1215812425 src_reg,
1215912426 ),
12427 .x87, .mmx => unreachable,
1216012428 .sse => try self.asmRegisterRegister(
1216112429 switch (abi_size) {
1216212430 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
1216612434 registerAlias(dst_reg, @max(abi_size, 4)),
1216712435 src_reg.to128(),
1216812436 ),
12169 .x87, .mmx => unreachable,
1217012437 },
1217112438 .segment => try self.asmRegisterRegister(
1217212439 .{ ._, .mov },
1217312440 dst_reg,
1217412441 switch (src_reg.class()) {
1217512442 .general_purpose, .segment => registerAlias(src_reg, abi_size),
12176 .sse => try self.copyToTmpRegister(ty, src_mcv),
1217712443 .x87, .mmx => unreachable,
12444 .sse => try self.copyToTmpRegister(ty, src_mcv),
1217812445 },
1217912446 ),
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,
1218012461 .sse => switch (src_reg.class()) {
1218112462 .general_purpose => try self.asmRegisterRegister(
1218212463 switch (abi_size) {
......@@ -12192,6 +12473,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1219212473 ty,
1219312474 .{ .register = try self.copyToTmpRegister(ty, src_mcv) },
1219412475 ),
12476 .x87, .mmx => unreachable,
1219512477 .sse => try self.asmRegisterRegister(
1219612478 @as(?Mir.Inst.FixedTag, switch (ty.scalarType(mod).zigTypeTag(mod)) {
1219712479 else => switch (abi_size) {
......@@ -12217,9 +12499,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1221712499 registerAlias(dst_reg, abi_size),
1221812500 registerAlias(src_reg, abi_size),
1221912501 ),
12220 .x87, .mmx => unreachable,
1222112502 },
12222 .x87, .mmx => unreachable,
1222312503 },
1222412504 .register_pair => |src_regs| try self.genSetReg(dst_reg, ty, .{ .register = src_regs[0] }),
1222512505 .register_offset,
......@@ -12231,9 +12511,10 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1223112511 0 => return self.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }),
1223212512 else => .{ .move = .{ ._, .lea } },
1223312513 },
12234 .indirect => try self.moveStrategy(ty, false),
12514 .indirect => try self.moveStrategy(ty, dst_reg.class(), false),
1223512515 .load_frame => |frame_addr| try self.moveStrategy(
1223612516 ty,
12517 dst_reg.class(),
1223712518 self.getFrameAddrAlignment(frame_addr).compare(.gte, ty.abiAlignment(mod)),
1223812519 ),
1223912520 .lea_frame => .{ .move = .{ ._, .lea } },
......@@ -12252,18 +12533,19 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1225212533 else => unreachable,
1225312534 },
1225412535 )),
12255 .memory, .load_direct, .load_got, .load_extern_got, .load_tlv => {
12536 .memory, .load_symbol, .load_direct, .load_got, .load_tlv => {
1225612537 switch (src_mcv) {
1225712538 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
1225812539 return (try self.moveStrategy(
1225912540 ty,
12541 dst_reg.class(),
1226012542 ty.abiAlignment(mod).check(@as(u32, @bitCast(small_addr))),
1226112543 )).read(self, registerAlias(dst_reg, abi_size), Memory.sib(
1226212544 self.memPtrSize(ty),
1226312545 .{ .base = .{ .reg = .ds }, .disp = small_addr },
1226412546 )),
12265 .load_direct => |sym_index| switch (ty.zigTypeTag(mod)) {
12266 else => {
12547 .load_direct => |sym_index| switch (dst_reg.class()) {
12548 .general_purpose => {
1226712549 const atom_index = try self.owner.getSymbolIndex(self);
1226812550 _ = try self.addInst(.{
1226912551 .tag = .mov,
......@@ -12278,9 +12560,10 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1227812560 });
1227912561 return;
1228012562 },
12281 .Float, .Vector => {},
12563 .segment, .mmx => unreachable,
12564 .x87, .sse => {},
1228212565 },
12283 .load_got, .load_extern_got, .load_tlv => {},
12566 .load_symbol, .load_got, .load_tlv => {},
1228412567 else => unreachable,
1228512568 }
1228612569
......@@ -12288,34 +12571,47 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1228812571 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
1228912572 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(
1229212575 self,
1229312576 registerAlias(dst_reg, abi_size),
1229412577 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .{ .reg = addr_reg } }),
1229512578 );
1229612579 },
12297 .lea_direct, .lea_got, .lea_extern_got => |sym_index| {
12580 .lea_symbol, .lea_direct, .lea_got => |sym_index| {
1229812581 const atom_index = try self.owner.getSymbolIndex(self);
12299 _ = try self.addInst(.{
12300 .tag = switch (src_mcv) {
12301 .lea_direct => .lea,
12302 .lea_got, .lea_extern_got => .mov,
12303 else => unreachable,
12304 },
12305 .ops = switch (src_mcv) {
12306 .lea_direct => .direct_reloc,
12307 .lea_got => .got_reloc,
12308 .lea_extern_got => .extern_got_reloc,
12309 else => unreachable,
12310 },
12311 .data = .{ .rx = .{
12312 .r1 = dst_reg.to64(),
12313 .payload = try self.addExtra(Mir.Reloc{
12314 .atom_index = atom_index,
12315 .sym_index = sym_index,
12316 }),
12317 } },
12318 });
12582 if (self.bin_file.cast(link.File.Elf)) |_| {
12583 _ = try self.addInst(.{
12584 .tag = .lea,
12585 .ops = .linker_reloc,
12586 .data = .{ .rx = .{
12587 .r1 = dst_reg.to64(),
12588 .payload = try self.addExtra(Mir.Reloc{
12589 .atom_index = atom_index,
12590 .sym_index = sym_index,
12591 }),
12592 } },
12593 });
12594 } else {
12595 _ = try self.addInst(.{
12596 .tag = switch (src_mcv) {
12597 .lea_direct => .lea,
12598 .lea_got => .mov,
12599 else => unreachable,
12600 },
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 }
1231912615 },
1232012616 .lea_tlv => |sym_index| {
1232112617 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
1239312689 },
1239412690 },
1239512691 .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) {
1239712693 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
1239812694 .reg => |reg| switch (reg) {
1239912695 .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
1240812704 registerAlias(src_reg, abi_size),
1240912705 ),
1241012706 .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);
12412 try (try self.moveStrategy(ty, switch (base) {
12413 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12414 .reg => |reg| switch (reg) {
12415 .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12416 else => false,
12707 const part_size: u16 = @min(abi_size - src_reg_i * 8, 8);
12708 try (try self.moveStrategy(
12709 try mod.intType(.unsigned, part_size * 8),
12710 src_reg.class(),
12711 switch (base) {
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)),
1241712720 },
12418 .frame => |frame_index| self.getFrameAddrAlignment(
12419 .{ .index = frame_index, .off = disp },
12420 ).compare(.gte, ty.abiAlignment(mod)),
12421 })).write(self, Memory.sib(
12721 )).write(self, Memory.sib(
1242212722 Memory.PtrSize.fromSize(part_size),
1242312723 .{ .base = base, .disp = disp + @as(i32, @intCast(src_reg_i * 8)) },
1242412724 ), registerAlias(src_reg, part_size));
......@@ -12460,12 +12760,12 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
1246012760 .lea_direct,
1246112761 .load_got,
1246212762 .lea_got,
12463 .load_extern_got,
12464 .lea_extern_got,
1246512763 .load_tlv,
1246612764 .lea_tlv,
1246712765 .load_frame,
1246812766 .lea_frame,
12767 .load_symbol,
12768 .lea_symbol,
1246912769 => switch (abi_size) {
1247012770 0 => {},
1247112771 1, 2, 4, 8 => {
......@@ -12482,9 +12782,9 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
1248212782}
1248312783
1248412784fn genInlineMemcpy(self: *Self, dst_ptr: MCValue, src_ptr: MCValue, len: MCValue) InnerError!void {
12485 try self.spillRegisters(&.{ .rdi, .rsi, .rcx });
12486 try self.genSetReg(.rdi, Type.usize, dst_ptr);
12785 try self.spillRegisters(&.{ .rsi, .rdi, .rcx });
1248712786 try self.genSetReg(.rsi, Type.usize, src_ptr);
12787 try self.genSetReg(.rdi, Type.usize, dst_ptr);
1248812788 try self.genSetReg(.rcx, Type.usize, len);
1248912789 try self.asmOpOnly(.{ .@"rep _sb", .mov });
1249012790}
......@@ -12556,8 +12856,8 @@ fn genLazySymbolRef(
1255612856
1255712857 if (self.bin_file.options.pic) {
1255812858 switch (tag) {
12559 .lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym.esym_index }),
12560 .mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym.esym_index }),
12859 .lea, .call => try self.genSetReg(reg, Type.usize, .{ .load_symbol = sym.esym_index }),
12860 .mov => try self.genSetReg(reg, Type.usize, .{ .load_symbol = sym.esym_index }),
1256112861 else => unreachable,
1256212862 }
1256312863 switch (tag) {
......@@ -12573,7 +12873,7 @@ fn genLazySymbolRef(
1257312873 switch (tag) {
1257412874 .lea, .mov => _ = try self.addInst(.{
1257512875 .tag = .mov,
12576 .ops = .direct_got_reloc,
12876 .ops = .linker_reloc,
1257712877 .data = .{ .rx = .{
1257812878 .r1 = reg.to64(),
1257912879 .payload = try self.addExtra(reloc),
......@@ -12581,20 +12881,11 @@ fn genLazySymbolRef(
1258112881 }),
1258212882 .call => _ = try self.addInst(.{
1258312883 .tag = .call,
12584 .ops = .direct_got_reloc,
12884 .ops = .linker_reloc,
1258512885 .data = .{ .reloc = reloc },
1258612886 }),
1258712887 else => unreachable,
1258812888 }
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 }
1259812889 }
1259912890 } else if (self.bin_file.cast(link.File.Plan9)) |p9_file| {
1260012891 const atom_index = p9_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
......@@ -14481,10 +14772,11 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
1448114772 } else mcv: {
1448214773 const ip_index = Air.refToInterned(ref).?;
1448314774 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(.{
1448514776 .ty = ty,
1448614777 .val = ip_index.toValue(),
14487 }));
14778 });
14779 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(mcv);
1448814780 break :mcv gop.value_ptr.short;
1448914781 };
1449014782
......@@ -14531,9 +14823,9 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
1453114823 .undef => .undef,
1453214824 .immediate => |imm| .{ .immediate = imm },
1453314825 .memory => |addr| .{ .memory = addr },
14826 .load_symbol => |sym_index| .{ .load_symbol = sym_index },
1453414827 .load_direct => |sym_index| .{ .load_direct = sym_index },
1453514828 .load_got => |sym_index| .{ .lea_got = sym_index },
14536 .load_extern_got => |sym_index| .{ .lea_extern_got = sym_index },
1453714829 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
1453814830 },
1453914831 .fail => |msg| {
......@@ -14730,16 +15022,22 @@ fn resolveCallingConventionValues(
1473015022 arg_mcv_i += 1;
1473115023 },
1473215024 .sseup => assert(arg_mcv[arg_mcv_i - 1].register.class() == .sse),
14733 .x87, .x87up, .complex_x87, .memory => break,
14734 .none => unreachable,
14735 .win_i128 => {
14736 const param_int_reg =
14737 abi.getCAbiIntParamRegs(resolved_cc)[param_int_reg_i].to64();
14738 param_int_reg_i += 1;
14739
14740 arg_mcv[arg_mcv_i] = .{ .indirect = .{ .reg = param_int_reg } };
14741 arg_mcv_i += 1;
15025 .x87, .x87up, .complex_x87, .memory, .win_i128 => switch (resolved_cc) {
15026 .SysV => switch (class) {
15027 .x87, .x87up, .complex_x87, .memory => break,
15028 else => unreachable,
15029 },
15030 .Win64 => if (ty.abiSize(mod) > 8) {
15031 const param_int_reg =
15032 abi.getCAbiIntParamRegs(resolved_cc)[param_int_reg_i].to64();
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,
1474215039 },
15040 .none => unreachable,
1474315041 } else {
1474415042 arg.* = switch (arg_mcv_i) {
1474515043 else => unreachable,
......@@ -15017,34 +15315,32 @@ fn floatLibcAbiSuffix(ty: Type) []const u8 {
1501715315 };
1501815316}
1501915317
15020fn promoteVarArg(self: *Self, ty: Type) Type {
15318fn promoteInt(self: *Self, ty: Type) Type {
1502115319 const mod = self.bin_file.options.module.?;
15022 switch (ty.zigTypeTag(mod)) {
15023 .Bool => return Type.c_int,
15024 else => {
15025 const int_info = ty.intInfo(mod);
15026 for ([_]Type{
15027 Type.c_int, Type.c_uint,
15028 Type.c_long, Type.c_ulong,
15029 Type.c_longlong, Type.c_ulonglong,
15030 }) |promote_ty| {
15031 const promote_info = promote_ty.intInfo(mod);
15032 if (int_info.signedness == .signed and promote_info.signedness == .unsigned) continue;
15033 if (int_info.bits + @intFromBool(int_info.signedness == .unsigned and
15034 promote_info.signedness == .signed) <= promote_info.bits) return promote_ty;
15035 }
15036 unreachable;
15037 },
15038 .Float => switch (ty.floatBits(self.target.*)) {
15039 32, 64 => return Type.f64,
15040 else => |float_bits| {
15041 assert(float_bits == self.target.c_type_bit_size(.longdouble));
15042 return Type.c_longdouble;
15043 },
15044 },
15045 .Pointer => {
15046 assert(!ty.isSlice(mod));
15047 return ty;
15320 const int_info: InternPool.Key.IntType = switch (ty.toIntern()) {
15321 .bool_type => .{ .signedness = .unsigned, .bits = 1 },
15322 else => if (ty.isAbiInt(mod)) ty.intInfo(mod) else return ty,
15323 };
15324 for ([_]Type{
15325 Type.c_int, Type.c_uint,
15326 Type.c_long, Type.c_ulong,
15327 Type.c_longlong, Type.c_ulonglong,
15328 }) |promote_ty| {
15329 const promote_info = promote_ty.intInfo(mod);
15330 if (int_info.signedness == .signed and promote_info.signedness == .unsigned) continue;
15331 if (int_info.bits + @intFromBool(int_info.signedness == .unsigned and
15332 promote_info.signedness == .signed) <= promote_info.bits) return promote_ty;
15333 }
15334 return ty;
15335}
15336
15337fn promoteVarArg(self: *Self, ty: Type) Type {
15338 if (!ty.isRuntimeFloat()) return self.promoteInt(ty);
15339 switch (ty.floatBits(self.target.*)) {
15340 32, 64 => return Type.f64,
15341 else => |float_bits| {
15342 assert(float_bits == self.target.c_type_bit_size(.longdouble));
15343 return Type.c_longdouble;
1504815344 },
1504915345 }
1505015346}
src/arch/x86_64/Emit.zig+31-21
......@@ -78,31 +78,41 @@ pub fn emitMir(emit: *Emit) Error!void {
7878 } else return emit.fail("TODO implement extern reloc for {s}", .{
7979 @tagName(emit.bin_file.tag),
8080 }),
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,
81110 .linker_got,
82 .linker_extern_got,
83111 .linker_direct,
84 .linker_direct_got,
85112 .linker_import,
86113 .linker_tlv,
87 => |symbol| if (emit.bin_file.cast(link.File.Elf)) |elf_file| {
88 const r_type: u32 = switch (lowered_relocs[0].target) {
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 });
114 => |symbol| if (emit.bin_file.cast(link.File.Elf)) |_| {
115 unreachable;
106116 } else if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
107117 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?;
108118 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
src/arch/x86_64/Lower.zig+52-26
......@@ -1,5 +1,6 @@
11//! This file contains the functionality for lowering x86_64 MIR to Instructions
22
3bin_file: *link.File,
34allocator: Allocator,
45mir: Mir,
56cc: std.builtin.CallingConvention,
......@@ -49,11 +50,10 @@ pub const Reloc = struct {
4950
5051 const Target = union(enum) {
5152 inst: Mir.Inst.Index,
53 linker_reloc: Mir.Reloc,
5254 linker_extern_fn: Mir.Reloc,
5355 linker_got: Mir.Reloc,
54 linker_extern_got: Mir.Reloc,
5556 linker_direct: Mir.Reloc,
56 linker_direct_got: Mir.Reloc,
5757 linker_import: Mir.Reloc,
5858 linker_tlv: Mir.Reloc,
5959 };
......@@ -408,12 +408,57 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
408408 .m_sib, .m_rip, .rax_moffs, .moffs_rax => inst.data.x.fixes,
409409 .extern_fn_reloc,
410410 .got_reloc,
411 .extern_got_reloc,
412411 .direct_reloc,
413 .direct_got_reloc,
414412 .import_reloc,
415413 .tlv_reloc,
416414 => ._,
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 },
417462 else => return lower.fail("TODO lower .{s}", .{@tagName(inst.ops)}),
418463 };
419464 try lower.emit(switch (fixes) {
......@@ -545,32 +590,12 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
545590 .extern_fn_reloc => &.{
546591 .{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc }) },
547592 },
548 .direct_got_reloc => ops: {
549 switch (inst.tag) {
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: {
593 .linker_reloc => unreachable,
594 .got_reloc, .direct_reloc, .import_reloc, .tlv_reloc => ops: {
569595 const reg = inst.data.rx.r1;
570596 const extra = lower.mir.extraData(Mir.Reloc, inst.data.rx.payload).data;
571597 _ = lower.reloc(switch (inst.ops) {
572598 .got_reloc => .{ .linker_got = extra },
573 .extern_got_reloc => .{ .linker_extern_got = extra },
574599 .direct_reloc => .{ .linker_direct = extra },
575600 .import_reloc => .{ .linker_import = extra },
576601 .tlv_reloc => .{ .linker_tlv = extra },
......@@ -601,6 +626,7 @@ const abi = @import("abi.zig");
601626const assert = std.debug.assert;
602627const bits = @import("bits.zig");
603628const encoder = @import("encoder.zig");
629const link = @import("../../link.zig");
604630const std = @import("std");
605631
606632const Air = @import("../../Air.zig");
src/arch/x86_64/Mir.zig+3-6
......@@ -854,9 +854,6 @@ pub const Inst = struct {
854854 /// Linker relocation - GOT indirection.
855855 /// Uses `rx` payload with extra data of type `Reloc`.
856856 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,
860857 /// Linker relocation - direct reference.
861858 /// Uses `rx` payload with extra data of type `Reloc`.
862859 direct_reloc,
......@@ -866,9 +863,9 @@ pub const Inst = struct {
866863 /// Linker relocation - threadlocal variable via GOT indirection.
867864 /// Uses `rx` payload with extra data of type `Reloc`.
868865 tlv_reloc,
869 /// Linker relocation - non-PIC direct reference to GOT cell.
870 /// Uses `reloc` payload if tag is `call`, `rx` otherwise.
871 direct_got_reloc,
866 /// Linker relocation.
867 /// Uses `rx` payload with extra data of type `Reloc`.
868 linker_reloc,
872869
873870 // Pseudo instructions:
874871
src/codegen.zig+8-15
......@@ -791,13 +791,11 @@ fn lowerDeclRef(
791791
792792/// Helper struct to denote that the value is in memory but requires a linker relocation fixup:
793793/// * 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
795794/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
796795/// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
797796pub const LinkerLoad = struct {
798797 type: enum {
799798 got,
800 extern_got,
801799 direct,
802800 import,
803801 },
......@@ -827,8 +825,9 @@ pub const GenResult = union(enum) {
827825 load_got: u32,
828826 /// Direct by-address reference to memory location.
829827 memory: u64,
830 /// Pointer to extern variable via GOT.
831 load_extern_got: u32,
828 /// Reference to memory location but deferred until linker allocated the Decl in memory.
829 /// Traditionally, this corresponds to emitting a relocation in a relocatable object file.
830 load_symbol: u32,
832831 };
833832
834833 fn mcv(val: MCValue) GenResult {
......@@ -903,16 +902,14 @@ fn genDeclRef(
903902 mod.intern_pool.stringToSliceUnwrap(ov.lib_name)
904903 else
905904 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 });
907908 }
908909 const sym_index = try elf_file.getOrCreateMetadataForDecl(decl_index);
909910 const sym = elf_file.symbol(sym_index);
910911 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
911 if (bin_file.options.pic) {
912 return GenResult.mcv(.{ .load_got = sym.esym_index });
913 } else {
914 return GenResult.mcv(.{ .memory = sym.zigGotAddress(elf_file) });
915 }
912 return GenResult.mcv(.{ .load_symbol = sym.esym_index });
916913 } else if (bin_file.cast(link.File.MachO)) |macho_file| {
917914 const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
918915 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
......@@ -948,11 +945,7 @@ fn genUnnamedConst(
948945 };
949946 if (bin_file.cast(link.File.Elf)) |elf_file| {
950947 const local = elf_file.symbol(local_sym_index);
951 if (bin_file.options.pic) {
952 return GenResult.mcv(.{ .load_direct = local.esym_index });
953 } else {
954 return GenResult.mcv(.{ .memory = local.value });
955 }
948 return GenResult.mcv(.{ .load_symbol = local.esym_index });
956949 } else if (bin_file.cast(link.File.MachO)) |_| {
957950 return GenResult.mcv(.{ .load_direct = local_sym_index });
958951 } else if (bin_file.cast(link.File.Coff)) |_| {
src/link/Elf.zig+8-1
......@@ -3333,7 +3333,8 @@ pub fn updateDecl(
33333333 const variable = decl.getOwnedVariable(mod).?;
33343334 const name = mod.intern_pool.stringToSlice(decl.name);
33353335 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;
33373338 return;
33383339 }
33393340
......@@ -5955,6 +5956,12 @@ pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32
59555956 return lookup_gop.value_ptr.*;
59565957}
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
59585965const GetOrCreateComdatGroupOwnerResult = struct {
59595966 found_existing: bool,
59605967 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
370370 try self.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file);
371371 },
372372
373 elf.R_X86_64_GOT32,
373374 elf.R_X86_64_GOTPC32,
374375 elf.R_X86_64_GOTPC64,
375376 elf.R_X86_64_GOTPCREL,
......@@ -879,6 +880,8 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void {
879880 }
880881 },
881882
883 elf.R_X86_64_GOT32 => try cwriter.writeIntLittle(i32, @as(i32, @intCast(G + GOT + A))),
884
882885 // Zig custom relocations
883886 Elf.R_X86_64_ZIG_GOT32 => try cwriter.writeIntLittle(u32, @as(u32, @intCast(ZIG_GOT + A))),
884887 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) {
7373#define ZIG_NO_RAW_F16
7474#endif
7575
76#ifdef ZIG_BACKEND_STAGE2_X86_64
77#define ZIG_NO_COMPLEX
78#endif
79
8076#ifdef __i386__
8177#define ZIG_NO_RAW_F16
8278#endif
......@@ -278,7 +274,7 @@ void run_c_tests(void) {
278274 zig_u32(0xfffffffd);
279275 zig_u64(0xfffffffffffffffc);
280276
281#if !defined ZIG_NO_I128 && !defined ZIG_BACKEND_STAGE2_X86_64
277#ifndef ZIG_NO_I128
282278 {
283279 struct u128 s = {0xfffffffffffffffc};
284280 zig_struct_u128(s);
......@@ -292,7 +288,7 @@ void run_c_tests(void) {
292288 zig_i32(-3);
293289 zig_i64(-4);
294290
295#if !defined ZIG_NO_I128 && !defined ZIG_BACKEND_STAGE2_X86_64
291#ifndef ZIG_NO_I128
296292 {
297293 struct i128 s = {-6};
298294 zig_struct_i128(s);
......@@ -433,7 +429,7 @@ void run_c_tests(void) {
433429 }
434430#endif
435431
436#if !defined __mips__ && !defined ZIG_PPC32 && !defined ZIG_BACKEND_STAGE2_X86_64
432#if !defined __mips__ && !defined ZIG_PPC32
437433 {
438434 struct FloatRect r1 = {1, 21, 16, 4};
439435 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 {
4949}
5050
5151test "C ABI integers" {
52 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
53
5452 c_u8(0xff);
5553 c_u16(0xfffe);
5654 c_u32(0xfffffffd);
......@@ -187,10 +185,8 @@ const complex_abi_compatible = builtin.cpu.arch != .x86 and !builtin.cpu.arch.is
187185 !builtin.cpu.arch.isARM() and !builtin.cpu.arch.isPPC() and !builtin.cpu.arch.isRISCV();
188186
189187test "C ABI complex float" {
190 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
191
192188 if (!complex_abi_compatible) return error.SkipZigTest;
193 if (builtin.cpu.arch == .x86_64) return error.SkipZigTest; // See https://github.com/ziglang/zig/issues/8465
189 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest; // See https://github.com/ziglang/zig/issues/8465
194190
195191 const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };
196192 const b = ComplexFloat{ .real = 11.3, .imag = -1.5 };
......@@ -201,8 +197,6 @@ test "C ABI complex float" {
201197}
202198
203199test "C ABI complex float by component" {
204 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
205
206200 if (!complex_abi_compatible) return error.SkipZigTest;
207201
208202 const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };
......@@ -214,8 +208,6 @@ test "C ABI complex float by component" {
214208}
215209
216210test "C ABI complex double" {
217 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
218
219211 if (!complex_abi_compatible) return error.SkipZigTest;
220212
221213 const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };
......@@ -227,8 +219,6 @@ test "C ABI complex double" {
227219}
228220
229221test "C ABI complex double by component" {
230 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
231
232222 if (!complex_abi_compatible) return error.SkipZigTest;
233223
234224 const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };
......@@ -240,8 +230,6 @@ test "C ABI complex double by component" {
240230}
241231
242232export fn zig_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat {
243 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
244
245233 expect(a.real == 1.25) catch @panic("test failure: zig_cmultf 1");
246234 expect(a.imag == 2.6) catch @panic("test failure: zig_cmultf 2");
247235 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 {
251239}
252240
253241export fn zig_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble {
254 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
255
256242 expect(a.real == 1.25) catch @panic("test failure: zig_cmultd 1");
257243 expect(a.imag == 2.6) catch @panic("test failure: zig_cmultd 2");
258244 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 {
262248}
263249
264250export 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
267251 expect(a_r == 1.25) catch @panic("test failure: zig_cmultf_comp 1");
268252 expect(a_i == 2.6) catch @panic("test failure: zig_cmultf_comp 2");
269253 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 {
273257}
274258
275259export 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
278260 expect(a_r == 1.25) catch @panic("test failure: zig_cmultd_comp 1");
279261 expect(a_i == 2.6) catch @panic("test failure: zig_cmultd_comp 2");
280262 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;
352334extern fn c_ret_med_struct_mixed() MedStructMixed;
353335
354336test "C ABI medium struct of ints and floats" {
355 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
356
357337 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
358338 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
359339 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -422,8 +402,6 @@ extern fn c_med_struct_ints(MedStructInts) void;
422402extern fn c_ret_med_struct_ints() MedStructInts;
423403
424404test "C ABI medium struct of ints" {
425 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
426
427405 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
428406 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
429407 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -531,8 +509,6 @@ extern fn c_split_struct_mixed(SplitStructMixed) void;
531509extern fn c_ret_split_struct_mixed() SplitStructMixed;
532510
533511test "C ABI split struct of ints and floats" {
534 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
535
536512 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
537513 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
538514 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -614,8 +590,6 @@ const Vector5 = extern struct {
614590extern fn c_big_struct_floats(Vector5) void;
615591
616592test "C ABI structs of floats as parameter" {
617 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
618
619593 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
620594 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
621595 if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;
......@@ -683,8 +657,6 @@ const FloatRect = extern struct {
683657};
684658
685659export fn zig_multiple_struct_floats(x: FloatRect, y: FloatRect) void {
686 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
687
688660 expect(x.left == 1) catch @panic("test failure");
689661 expect(x.right == 21) catch @panic("test failure");
690662 expect(x.top == 16) catch @panic("test failure");
......@@ -696,8 +668,6 @@ export fn zig_multiple_struct_floats(x: FloatRect, y: FloatRect) void {
696668}
697669
698670test "C ABI structs of floats as multiple parameters" {
699 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
700
701671 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
702672 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
703673
......@@ -754,8 +724,6 @@ export fn zig_ret_small_struct_ints() SmallStructInts {
754724}
755725
756726export fn zig_ret_med_struct_ints() MedStructInts {
757 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
758
759727 return .{
760728 .x = 1,
761729 .y = 2,
......@@ -764,8 +732,6 @@ export fn zig_ret_med_struct_ints() MedStructInts {
764732}
765733
766734export fn zig_ret_med_struct_mixed() MedStructMixed {
767 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
768
769735 return .{
770736 .a = 1234,
771737 .b = 100.0,
......@@ -774,8 +740,6 @@ export fn zig_ret_med_struct_mixed() MedStructMixed {
774740}
775741
776742export fn zig_ret_split_struct_mixed() SplitStructMixed {
777 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
778
779743 return .{
780744 .a = 1234,
781745 .b = 100,
......@@ -816,8 +780,6 @@ extern fn c_struct_with_array(StructWithArray) void;
816780extern fn c_ret_struct_with_array() StructWithArray;
817781
818782test "Struct with array as padding." {
819 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
820
821783 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
822784 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
823785 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -889,7 +851,8 @@ extern fn c_medium_vec(MediumVec) void;
889851extern fn c_ret_medium_vec() MediumVec;
890852
891853test "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
894857 if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;
895858
......@@ -912,7 +875,7 @@ test "big simd vector" {
912875
913876 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
914877 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
917880 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;
933896extern fn c_ret_ptr_size_float_struct() Vector2;
934897
935898test "C ABI pointer sized float struct" {
936 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
937
938899 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
939900 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
940901 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
......@@ -958,8 +919,6 @@ pub inline fn expectOk(c_err: c_int) !void {
958919/// Tests for Double + Char struct
959920const DC = extern struct { v1: f64, v2: u8 };
960921test "DC: Zig passes to C" {
961 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
962
963922 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
964923 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
965924 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -967,8 +926,6 @@ test "DC: Zig passes to C" {
967926 try expectOk(c_assert_DC(.{ .v1 = -0.25, .v2 = 15 }));
968927}
969928test "DC: Zig returns to C" {
970 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
971
972929 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
973930 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
974931 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
......@@ -977,8 +934,6 @@ test "DC: Zig returns to C" {
977934 try expectOk(c_assert_ret_DC());
978935}
979936test "DC: C passes to Zig" {
980 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
981
982937 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
983938 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
984939 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -986,8 +941,6 @@ test "DC: C passes to Zig" {
986941 try expectOk(c_send_DC());
987942}
988943test "DC: C returns to Zig" {
989 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
990
991944 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
992945 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
993946 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
......@@ -1001,8 +954,6 @@ pub extern fn c_assert_ret_DC() c_int;
1001954pub extern fn c_send_DC() c_int;
1002955pub extern fn c_ret_DC() DC;
1003956pub export fn zig_assert_DC(lv: DC) c_int {
1004 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1005
1006957 var err: c_int = 0;
1007958 if (lv.v1 != -0.25) err = 1;
1008959 if (lv.v2 != 15) err = 2;
......@@ -1010,8 +961,6 @@ pub export fn zig_assert_DC(lv: DC) c_int {
1010961 return err;
1011962}
1012963pub export fn zig_ret_DC() DC {
1013 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1014
1015964 return .{ .v1 = -0.25, .v2 = 15 };
1016965}
1017966
......@@ -1019,8 +968,6 @@ pub export fn zig_ret_DC() DC {
1019968const CFF = extern struct { v1: u8, v2: f32, v3: f32 };
1020969
1021970test "CFF: Zig passes to C" {
1022 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1023
1024971 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
1025972 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1026973 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -1028,8 +975,6 @@ test "CFF: Zig passes to C" {
1028975 try expectOk(c_assert_CFF(.{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }));
1029976}
1030977test "CFF: Zig returns to C" {
1031 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1032
1033978 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
1034979 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1035980 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -1037,8 +982,6 @@ test "CFF: Zig returns to C" {
1037982 try expectOk(c_assert_ret_CFF());
1038983}
1039984test "CFF: C passes to Zig" {
1040 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1041
1042985 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
1043986 if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;
1044987 if (builtin.cpu.arch == .aarch64 and builtin.mode != .Debug) return error.SkipZigTest;
......@@ -1049,8 +992,6 @@ test "CFF: C passes to Zig" {
1049992 try expectOk(c_send_CFF());
1050993}
1051994test "CFF: C returns to Zig" {
1052 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1053
1054995 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
1055996 if (builtin.cpu.arch == .aarch64 and builtin.mode != .Debug) return error.SkipZigTest;
1056997 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;
10641005pub extern fn c_send_CFF() c_int;
10651006pub extern fn c_ret_CFF() CFF;
10661007pub export fn zig_assert_CFF(lv: CFF) c_int {
1067 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1068
10691008 var err: c_int = 0;
10701009 if (lv.v1 != 39) err = 1;
10711010 if (lv.v2 != 0.875) err = 2;
......@@ -1074,8 +1013,6 @@ pub export fn zig_assert_CFF(lv: CFF) c_int {
10741013 return err;
10751014}
10761015pub export fn zig_ret_CFF() CFF {
1077 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1078
10791016 return .{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 };
10801017}
10811018
......@@ -1083,8 +1020,6 @@ pub export fn zig_ret_CFF() CFF {
10831020const PD = extern struct { v1: ?*anyopaque, v2: f64 };
10841021
10851022test "PD: Zig passes to C" {
1086 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1087
10881023 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
10891024 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
10901025 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -1092,8 +1027,6 @@ test "PD: Zig passes to C" {
10921027 try expectOk(c_assert_PD(.{ .v1 = null, .v2 = 0.5 }));
10931028}
10941029test "PD: Zig returns to C" {
1095 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1096
10971030 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
10981031 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
10991032 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -1101,8 +1034,6 @@ test "PD: Zig returns to C" {
11011034 try expectOk(c_assert_ret_PD());
11021035}
11031036test "PD: C passes to Zig" {
1104 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1105
11061037 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
11071038 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
11081039 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -1110,8 +1041,6 @@ test "PD: C passes to Zig" {
11101041 try expectOk(c_send_PD());
11111042}
11121043test "PD: C returns to Zig" {
1113 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1114
11151044 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
11161045 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
11171046 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -1123,8 +1052,6 @@ pub extern fn c_assert_ret_PD() c_int;
11231052pub extern fn c_send_PD() c_int;
11241053pub extern fn c_ret_PD() PD;
11251054pub export fn zig_c_assert_PD(lv: PD) c_int {
1126 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1127
11281055 var err: c_int = 0;
11291056 if (lv.v1 != null) err = 1;
11301057 if (lv.v2 != 0.5) err = 2;
......@@ -1132,13 +1059,9 @@ pub export fn zig_c_assert_PD(lv: PD) c_int {
11321059 return err;
11331060}
11341061pub export fn zig_ret_PD() PD {
1135 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1136
11371062 return .{ .v1 = null, .v2 = 0.5 };
11381063}
11391064pub export fn zig_assert_PD(lv: PD) c_int {
1140 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1141
11421065 var err: c_int = 0;
11431066 if (lv.v1 != null) err = 1;
11441067 if (lv.v2 != 0.5) err = 2;
......@@ -1228,11 +1151,9 @@ const f80_struct = extern struct {
12281151};
12291152extern fn c_f80_struct(f80_struct) f80_struct;
12301153test "f80 struct" {
1231 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1232
12331154 if (!has_f80) return error.SkipZigTest;
12341155 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
12371158 const a = c_f80_struct(.{ .a = 12.34 });
12381159 try expect(@as(f64, @floatCast(a.a)) == 56.78);
......@@ -1317,8 +1238,6 @@ test "Stdcall ABI big union" {
13171238
13181239extern fn c_explict_win64(ByRef) callconv(.Win64) ByRef;
13191240test "explicit SysV calling convention" {
1320 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1321
13221241 if (builtin.cpu.arch != .x86_64) return error.SkipZigTest;
13231242
13241243 const res = c_explict_win64(.{ .val = 1, .arr = undefined });