authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-25 23:25:56+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-10-25 23:25:56+02:00
logcc394431ae6eb69e7abd677c268a8ab7299f8aeb
treed5aa705cdc7d701b53f32a8c2acc099c2dbd90c5
parent10ea7accf76d4ad59222ea5ff3585d6cc7cfe3b0
parented00afbc4c1eec6d599ac277e364b4a1ed11fe5c
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #17699 from ziglang/elf-better-alloc

elf: allocated PHDR table always immediately succeeding the EHDR

40 files changed, 686 insertions(+), 502 deletions(-)

lib/compiler_rt/int.zig-2
......@@ -42,8 +42,6 @@ pub fn __divmodti4(a: i128, b: i128, rem: *i128) callconv(.C) i128 {
4242}
4343
4444test "test_divmodti4" {
45 if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
46
4745 const cases = [_][4]i128{
4846 [_]i128{ 0, 1, 0, 0 },
4947 [_]i128{ 0, -1, 0, 0 },
lib/std/Thread/Condition.zig+2
......@@ -371,6 +371,8 @@ test "Condition - signal" {
371371 return error.SkipZigTest;
372372 }
373373
374 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
375
374376 const num_threads = 4;
375377
376378 const SignalTest = struct {
lib/std/Uri.zig-2
......@@ -735,8 +735,6 @@ test "Special test" {
735735}
736736
737737test "URI escaping" {
738 if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
739
740738 const input = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad";
741739 const expected = "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad";
742740
lib/std/builtin.zig+8-1
......@@ -738,8 +738,8 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr
738738 if (builtin.zig_backend == .stage2_wasm or
739739 builtin.zig_backend == .stage2_arm or
740740 builtin.zig_backend == .stage2_aarch64 or
741 builtin.zig_backend == .stage2_x86_64 or
742741 builtin.zig_backend == .stage2_x86 or
742 (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) or
743743 builtin.zig_backend == .stage2_riscv64 or
744744 builtin.zig_backend == .stage2_sparc64 or
745745 builtin.zig_backend == .stage2_spirv64)
......@@ -808,6 +808,13 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr
808808 std.os.abort();
809809 },
810810 .cuda, .amdhsa => std.os.abort(),
811 .plan9 => {
812 var status: [std.os.plan9.ERRMAX]u8 = undefined;
813 const len = @min(msg.len, status.len - 1);
814 @memcpy(status[0..len], msg[0..len]);
815 status[len] = 0;
816 std.os.plan9.exits(status[0..len :0]);
817 },
811818 else => {
812819 const first_trace_addr = ret_addr orelse @returnAddress();
813820 std.debug.panicImpl(error_return_trace, first_trace_addr, msg);
lib/std/compress/lzma/test.zig-6
......@@ -23,8 +23,6 @@ fn testDecompressError(expected: anyerror, compressed: []const u8) !void {
2323}
2424
2525test "LZMA: decompress empty world" {
26 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
27
2826 try testDecompressEqual(
2927 "",
3028 &[_]u8{
......@@ -88,8 +86,6 @@ test "LZMA: known size with end of payload marker" {
8886}
8987
9088test "LZMA: too big uncompressed size in header" {
91 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
92
9389 try testDecompressError(
9490 error.CorruptInput,
9591 @embedFile("testdata/bad-too_big_size-with_eopm.lzma"),
......@@ -97,8 +93,6 @@ test "LZMA: too big uncompressed size in header" {
9793}
9894
9995test "LZMA: too small uncompressed size in header" {
100 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
101
10296 try testDecompressError(
10397 error.CorruptInput,
10498 @embedFile("testdata/bad-too_small_size-without_eopm-3.lzma"),
lib/std/crypto/25519/curve25519.zig-5
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const crypto = std.crypto;
43
54const IdentityElementError = crypto.errors.IdentityElementError;
......@@ -112,8 +111,6 @@ pub const Curve25519 = struct {
112111};
113112
114113test "curve25519" {
115 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
116
117114 var s = [32]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 };
118115 const p = try Curve25519.basePoint.clampedMul(s);
119116 try p.rejectIdentity();
......@@ -128,8 +125,6 @@ test "curve25519" {
128125}
129126
130127test "curve25519 small order check" {
131 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
132
133128 var s: [32]u8 = [_]u8{1} ++ [_]u8{0} ** 31;
134129 const small_order_ss: [7][32]u8 = .{
135130 .{
lib/std/crypto/25519/ed25519.zig-2
......@@ -484,8 +484,6 @@ pub const Ed25519 = struct {
484484};
485485
486486test "ed25519 key pair creation" {
487 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
488
489487 var seed: [32]u8 = undefined;
490488 _ = try fmt.hexToBytes(seed[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");
491489 const key_pair = try Ed25519.KeyPair.create(seed);
lib/std/crypto/25519/edwards25519.zig-11
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const crypto = std.crypto;
43const debug = std.debug;
54const fmt = std.fmt;
......@@ -495,8 +494,6 @@ pub const Edwards25519 = struct {
495494const htest = @import("../test.zig");
496495
497496test "edwards25519 packing/unpacking" {
498 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
499
500497 const s = [_]u8{170} ++ [_]u8{0} ** 31;
501498 var b = Edwards25519.basePoint;
502499 const pk = try b.mul(s);
......@@ -533,8 +530,6 @@ test "edwards25519 packing/unpacking" {
533530}
534531
535532test "edwards25519 point addition/subtraction" {
536 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
537
538533 var s1: [32]u8 = undefined;
539534 var s2: [32]u8 = undefined;
540535 crypto.random.bytes(&s1);
......@@ -549,8 +544,6 @@ test "edwards25519 point addition/subtraction" {
549544}
550545
551546test "edwards25519 uniform-to-point" {
552 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
553
554547 var r = [32]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
555548 var p = Edwards25519.fromUniform(r);
556549 try htest.assertEqual("0691eee3cf70a0056df6bfa03120635636581b5c4ea571dfc680f78c7e0b4137", p.toBytes()[0..]);
......@@ -562,8 +555,6 @@ test "edwards25519 uniform-to-point" {
562555
563556// Test vectors from draft-irtf-cfrg-hash-to-curve-12
564557test "edwards25519 hash-to-curve operation" {
565 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
566
567558 var p = Edwards25519.fromString(true, "QUUX-V01-CS02-with-edwards25519_XMD:SHA-512_ELL2_RO_", "abc");
568559 try htest.assertEqual("31558a26887f23fb8218f143e69d5f0af2e7831130bd5b432ef23883b895839a", p.toBytes()[0..]);
569560
......@@ -572,8 +563,6 @@ test "edwards25519 hash-to-curve operation" {
572563}
573564
574565test "edwards25519 implicit reduction of invalid scalars" {
575 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
576
577566 const s = [_]u8{0} ** 31 ++ [_]u8{255};
578567 const p1 = try Edwards25519.basePoint.mulPublic(s);
579568 const p2 = try Edwards25519.basePoint.mul(s);
lib/std/crypto/25519/ristretto255.zig-2
......@@ -168,8 +168,6 @@ pub const Ristretto255 = struct {
168168};
169169
170170test "ristretto255" {
171 if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
172
173171 const p = Ristretto255.basePoint;
174172 var buf: [256]u8 = undefined;
175173 try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&p.toBytes())}), "E2F2AE0A6ABC4E71A884A961C500515F58E30B6AA582DD8DB6A65945E08D2D76");
lib/std/crypto/25519/x25519.zig-11
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const crypto = std.crypto;
43const mem = std.mem;
54const fmt = std.fmt;
......@@ -83,8 +82,6 @@ pub const X25519 = struct {
8382const htest = @import("../test.zig");
8483
8584test "x25519 public key calculation from secret key" {
86 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
87
8885 var sk: [32]u8 = undefined;
8986 var pk_expected: [32]u8 = undefined;
9087 _ = try fmt.hexToBytes(sk[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");
......@@ -94,8 +91,6 @@ test "x25519 public key calculation from secret key" {
9491}
9592
9693test "x25519 rfc7748 vector1" {
97 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
98
9994 const secret_key = [32]u8{ 0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46, 0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4 };
10095 const public_key = [32]u8{ 0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f, 0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c };
10196
......@@ -106,8 +101,6 @@ test "x25519 rfc7748 vector1" {
106101}
107102
108103test "x25519 rfc7748 vector2" {
109 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
110
111104 const secret_key = [32]u8{ 0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26, 0x91, 0x95, 0x7d, 0x6a, 0xf5, 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, 0x01, 0xd4, 0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18, 0xba, 0x0d };
112105 const public_key = [32]u8{ 0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, 0xf4, 0xb7, 0x95, 0x9d, 0x05, 0x38, 0xae, 0x2c, 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0, 0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93 };
113106
......@@ -118,8 +111,6 @@ test "x25519 rfc7748 vector2" {
118111}
119112
120113test "x25519 rfc7748 one iteration" {
121 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
122
123114 const initial_value = [32]u8{ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
124115 const expected_output = [32]u8{ 0x42, 0x2c, 0x8e, 0x7a, 0x62, 0x27, 0xd7, 0xbc, 0xa1, 0x35, 0x0b, 0x3e, 0x2b, 0xb7, 0x27, 0x9f, 0x78, 0x97, 0xb8, 0x7b, 0xb6, 0x85, 0x4b, 0x78, 0x3c, 0x60, 0xe8, 0x03, 0x11, 0xae, 0x30, 0x79 };
125116
......@@ -180,8 +171,6 @@ test "x25519 rfc7748 1,000,000 iterations" {
180171}
181172
182173test "edwards25519 -> curve25519 map" {
183 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
184
185174 const ed_kp = try crypto.sign.Ed25519.KeyPair.create([_]u8{0x42} ** 32);
186175 const mont_kp = try X25519.KeyPair.fromEd25519(ed_kp);
187176 try htest.assertEqual("90e7595fc89e52fdfddce9c6a43d74dbf6047025ee0462d2d172e8b6a2841d6e", &mont_kp.secret_key);
lib/std/crypto/chacha20.zig-10
......@@ -821,8 +821,6 @@ test "crypto.chacha20 test vector sunscreen" {
821821
822822// https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7
823823test "crypto.chacha20 test vector 1" {
824 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
825
826824 const expected_result = [_]u8{
827825 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
828826 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
......@@ -857,8 +855,6 @@ test "crypto.chacha20 test vector 1" {
857855}
858856
859857test "crypto.chacha20 test vector 2" {
860 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
861
862858 const expected_result = [_]u8{
863859 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
864860 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
......@@ -893,8 +889,6 @@ test "crypto.chacha20 test vector 2" {
893889}
894890
895891test "crypto.chacha20 test vector 3" {
896 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
897
898892 const expected_result = [_]u8{
899893 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
900894 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
......@@ -929,8 +923,6 @@ test "crypto.chacha20 test vector 3" {
929923}
930924
931925test "crypto.chacha20 test vector 4" {
932 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
933
934926 const expected_result = [_]u8{
935927 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
936928 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
......@@ -965,8 +957,6 @@ test "crypto.chacha20 test vector 4" {
965957}
966958
967959test "crypto.chacha20 test vector 5" {
968 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
969
970960 const expected_result = [_]u8{
971961 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
972962 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
lib/std/crypto/salsa20.zig-4
......@@ -598,8 +598,6 @@ test "xsalsa20poly1305 secretbox" {
598598}
599599
600600test "xsalsa20poly1305 box" {
601 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
602
603601 var msg: [100]u8 = undefined;
604602 var msg2: [msg.len]u8 = undefined;
605603 var nonce: [Box.nonce_length]u8 = undefined;
......@@ -614,8 +612,6 @@ test "xsalsa20poly1305 box" {
614612}
615613
616614test "xsalsa20poly1305 sealedbox" {
617 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
618
619615 var msg: [100]u8 = undefined;
620616 var msg2: [msg.len]u8 = undefined;
621617 var boxed: [msg.len + SealedBox.seal_length]u8 = undefined;
lib/std/debug.zig+1-1
......@@ -671,8 +671,8 @@ pub const StackIterator = struct {
671671 if (self.unwind_state) |*unwind_state| {
672672 if (!unwind_state.failed) {
673673 if (unwind_state.dwarf_context.pc == 0) return null;
674 defer self.fp = unwind_state.dwarf_context.getFp() catch 0;
674675 if (self.next_unwind()) |return_address| {
675 self.fp = unwind_state.dwarf_context.getFp() catch 0;
676676 return return_address;
677677 } else |err| {
678678 unwind_state.last_error = err;
lib/std/fmt.zig-18
......@@ -2129,8 +2129,6 @@ test "int.small" {
21292129}
21302130
21312131test "int.specifier" {
2132 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2133
21342132 {
21352133 const value: u8 = 'a';
21362134 try expectFmt("u8: a\n", "u8: {c}\n", .{value});
......@@ -2181,8 +2179,6 @@ test "int.padded" {
21812179}
21822180
21832181test "buffer" {
2184 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2185
21862182 {
21872183 var buf1: [32]u8 = undefined;
21882184 var fbs = std.io.fixedBufferStream(&buf1);
......@@ -2379,8 +2375,6 @@ test "float.scientific" {
23792375}
23802376
23812377test "float.scientific.precision" {
2382 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2383
23842378 try expectFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)});
23852379 try expectFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @as(f32, @bitCast(@as(u32, 814313563))))});
23862380 try expectFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @as(f32, @bitCast(@as(u32, 1006632960))))});
......@@ -2457,8 +2451,6 @@ test "float.hexadecimal.precision" {
24572451}
24582452
24592453test "float.decimal" {
2460 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2461
24622454 try expectFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
24632455 try expectFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
24642456 try expectFmt("f32: 0", "f32: {d:.0}", .{@as(f32, 0.0)});
......@@ -2482,8 +2474,6 @@ test "float.decimal" {
24822474}
24832475
24842476test "float.libc.sanity" {
2485 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2486
24872477 try expectFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @as(f32, @bitCast(@as(u32, 916964781))))});
24882478 try expectFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @as(f32, @bitCast(@as(u32, 925353389))))});
24892479 try expectFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @as(f32, @bitCast(@as(u32, 1036831278))))});
......@@ -2503,8 +2493,6 @@ test "float.libc.sanity" {
25032493}
25042494
25052495test "custom" {
2506 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2507
25082496 const Vec2 = struct {
25092497 const SelfType = @This();
25102498 x: f32,
......@@ -2683,8 +2671,6 @@ test "formatFloatValue with comptime_float" {
26832671}
26842672
26852673test "formatType max_depth" {
2686 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2687
26882674 const Vec2 = struct {
26892675 const SelfType = @This();
26902676 x: f32,
......@@ -2759,14 +2745,10 @@ test "positional" {
27592745}
27602746
27612747test "positional with specifier" {
2762 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2763
27642748 try expectFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)});
27652749}
27662750
27672751test "positional/alignment/width/precision" {
2768 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2769
27702752 try expectFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)});
27712753}
27722754
lib/std/fmt/parse_float.zig-4
......@@ -84,8 +84,6 @@ test "fmt.parseFloat nan and inf" {
8484}
8585
8686test "fmt.parseFloat #11169" {
87 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
88
8987 try expectEqual(try parseFloat(f128, "9007199254740993.0"), 9007199254740993.0);
9088}
9189
......@@ -162,8 +160,6 @@ test "fmt.parseFloat hex.f64" {
162160 try testing.expectEqual(try parseFloat(f64, "-0x1p-1074"), -math.floatTrueMin(f64));
163161}
164162test "fmt.parseFloat hex.f128" {
165 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
166
167163 try testing.expectEqual(try parseFloat(f128, "0x1p0"), 1.0);
168164 try testing.expectEqual(try parseFloat(f128, "-0x1p-1"), -0.5);
169165 try testing.expectEqual(try parseFloat(f128, "0x10p+10"), 16384.0);
lib/std/fs/test.zig-4
......@@ -1604,8 +1604,6 @@ test "File.Permissions" {
16041604 if (builtin.os.tag == .wasi)
16051605 return error.SkipZigTest;
16061606
1607 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1608
16091607 var tmp = tmpDir(.{});
16101608 defer tmp.cleanup();
16111609
......@@ -1632,8 +1630,6 @@ test "File.PermissionsUnix" {
16321630 if (builtin.os.tag == .windows or builtin.os.tag == .wasi)
16331631 return error.SkipZigTest;
16341632
1635 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1636
16371633 var tmp = tmpDir(.{});
16381634 defer tmp.cleanup();
16391635
lib/std/json.zig-4
......@@ -24,8 +24,6 @@ test Scanner {
2424}
2525
2626test parseFromSlice {
27 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
28
2927 var parsed_str = try parseFromSlice([]const u8, testing.allocator, "\"a\\u0020b\"", .{});
3028 defer parsed_str.deinit();
3129 try testing.expectEqualSlices(u8, "a b", parsed_str.value);
......@@ -44,8 +42,6 @@ test Value {
4442}
4543
4644test writeStream {
47 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
48
4945 var out = ArrayList(u8).init(testing.allocator);
5046 defer out.deinit();
5147 var write_stream = writeStream(out.writer(), .{ .whitespace = .indent_2 });
lib/std/json/static_test.zig-40
......@@ -372,8 +372,6 @@ test "test all types" {
372372}
373373
374374test "parse" {
375 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
376
377375 try testing.expectEqual(false, try parseFromSliceLeaky(bool, testing.allocator, "false", .{}));
378376 try testing.expectEqual(true, try parseFromSliceLeaky(bool, testing.allocator, "true", .{}));
379377 try testing.expectEqual(@as(u1, 1), try parseFromSliceLeaky(u1, testing.allocator, "1", .{}));
......@@ -405,8 +403,6 @@ test "parse into enum" {
405403}
406404
407405test "parse into that allocates a slice" {
408 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
409
410406 {
411407 // string as string
412408 const parsed = try parseFromSlice([]u8, testing.allocator, "\"foo\"", .{});
......@@ -427,16 +423,12 @@ test "parse into that allocates a slice" {
427423}
428424
429425test "parse into sentinel slice" {
430 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
431
432426 const parsed = try parseFromSlice([:0]const u8, testing.allocator, "\"\\n\"", .{});
433427 defer parsed.deinit();
434428 try testing.expect(std.mem.eql(u8, parsed.value, "\n"));
435429}
436430
437431test "parse into tagged union" {
438 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
439
440432 const T = union(enum) {
441433 nothing,
442434 int: i32,
......@@ -452,8 +444,6 @@ test "parse into tagged union" {
452444}
453445
454446test "parse into tagged union errors" {
455 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
456
457447 const T = union(enum) {
458448 nothing,
459449 int: i32,
......@@ -485,8 +475,6 @@ test "parse into struct with no fields" {
485475const test_const_value: usize = 123;
486476
487477test "parse into struct with default const pointer field" {
488 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
489
490478 const T = struct { a: *const usize = &test_const_value };
491479 const parsed = try parseFromSlice(T, testing.allocator, "{}", .{});
492480 defer parsed.deinit();
......@@ -502,8 +490,6 @@ const test_default_str_slice: [2][]const u8 = [_][]const u8{
502490};
503491
504492test "freeing parsed structs with pointers to default values" {
505 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
506
507493 const T = struct {
508494 int: *const usize = &test_default_usize,
509495 int_ptr: *allowzero align(1) const usize = test_default_usize_ptr,
......@@ -517,15 +503,11 @@ test "freeing parsed structs with pointers to default values" {
517503}
518504
519505test "parse into struct where destination and source lengths mismatch" {
520 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
521
522506 const T = struct { a: [2]u8 };
523507 try testing.expectError(error.LengthMismatch, parseFromSlice(T, testing.allocator, "{\"a\": \"bbb\"}", .{}));
524508}
525509
526510test "parse into struct with misc fields" {
527 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
528
529511 const T = struct {
530512 int: i64,
531513 float: f64,
......@@ -601,8 +583,6 @@ test "parse into struct with misc fields" {
601583}
602584
603585test "parse into struct with strings and arrays with sentinels" {
604 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
605
606586 const T = struct {
607587 language: [:0]const u8,
608588 language_without_sentinel: []const u8,
......@@ -631,8 +611,6 @@ test "parse into struct with strings and arrays with sentinels" {
631611}
632612
633613test "parse into struct with duplicate field" {
634 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
635
636614 const options_first = ParseOptions{ .duplicate_field_behavior = .use_first };
637615 const options_last = ParseOptions{ .duplicate_field_behavior = .use_last };
638616
......@@ -652,8 +630,6 @@ test "parse into struct with duplicate field" {
652630}
653631
654632test "parse into struct ignoring unknown fields" {
655 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
656
657633 const T = struct {
658634 int: i64,
659635 language: []const u8,
......@@ -692,8 +668,6 @@ test "parse into struct ignoring unknown fields" {
692668}
693669
694670test "parse into tuple" {
695 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
696
697671 const Union = union(enum) {
698672 char: u8,
699673 float: f64,
......@@ -749,8 +723,6 @@ const ParseIntoRecursiveUnionDefinitionValue = union(enum) {
749723};
750724
751725test "parse into recursive union definition" {
752 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
753
754726 const T = struct {
755727 values: ParseIntoRecursiveUnionDefinitionValue,
756728 };
......@@ -772,8 +744,6 @@ const ParseIntoDoubleRecursiveUnionValueSecond = union(enum) {
772744};
773745
774746test "parse into double recursive union definition" {
775 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
776
777747 const T = struct {
778748 values: ParseIntoDoubleRecursiveUnionValueFirst,
779749 };
......@@ -785,8 +755,6 @@ test "parse into double recursive union definition" {
785755}
786756
787757test "parse exponential into int" {
788 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
789
790758 const T = struct { int: i64 };
791759 const r = try parseFromSliceLeaky(T, testing.allocator, "{ \"int\": 4.2e2 }", .{});
792760 try testing.expectEqual(@as(i64, 420), r.int);
......@@ -795,8 +763,6 @@ test "parse exponential into int" {
795763}
796764
797765test "parseFromTokenSource" {
798 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
799
800766 {
801767 var scanner = JsonScanner.initCompleteInput(testing.allocator, "123");
802768 defer scanner.deinit();
......@@ -816,8 +782,6 @@ test "parseFromTokenSource" {
816782}
817783
818784test "max_value_len" {
819 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
820
821785 try testing.expectError(error.ValueTooLong, parseFromSlice([]u8, testing.allocator, "\"0123456789\"", .{ .max_value_len = 5 }));
822786}
823787
......@@ -856,8 +820,6 @@ fn assertKey(
856820 }
857821}
858822test "json parse partial" {
859 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
860
861823 const Inner = struct {
862824 num: u32,
863825 yes: bool,
......@@ -913,8 +875,6 @@ test "json parse partial" {
913875}
914876
915877test "json parse allocate when streaming" {
916 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
917
918878 const T = struct {
919879 not_const: []u8,
920880 is_const: []const u8,
lib/std/json/stringify_test.zig-2
......@@ -198,8 +198,6 @@ test "stringify struct" {
198198}
199199
200200test "emit_strings_as_arrays" {
201 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
202
203201 // Should only affect string values, not object keys.
204202 try testStringify("{\"foo\":\"bar\"}", .{ .foo = "bar" }, .{});
205203 try testStringify("{\"foo\":[98,97,114]}", .{ .foo = "bar" }, .{ .emit_strings_as_arrays = true });
lib/std/mem.zig+2-4
......@@ -1756,10 +1756,8 @@ test "comptime read/write int" {
17561756}
17571757
17581758test "readIntBig and readIntLittle" {
1759 switch (builtin.zig_backend) {
1760 .stage2_c, .stage2_x86_64 => return error.SkipZigTest,
1761 else => {},
1762 }
1759 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1760 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
17631761
17641762 try testing.expect(readIntSliceBig(u0, &[_]u8{}) == 0x0);
17651763 try testing.expect(readIntSliceLittle(u0, &[_]u8{}) == 0x0);
lib/std/net/test.zig-2
......@@ -5,7 +5,6 @@ const mem = std.mem;
55const testing = std.testing;
66
77test "parse and render IPv6 addresses" {
8 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
98 if (builtin.os.tag == .wasi) return error.SkipZigTest;
109
1110 var buffer: [100]u8 = undefined;
......@@ -71,7 +70,6 @@ test "invalid but parseable IPv6 scope ids" {
7170}
7271
7372test "parse and render IPv4 addresses" {
74 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
7573 if (builtin.os.tag == .wasi) return error.SkipZigTest;
7674
7775 var buffer: [18]u8 = undefined;
lib/std/os/linux/x86_64.zig+2-2
......@@ -431,11 +431,11 @@ fn getContextInternal() callconv(.Naked) usize {
431431 \\ leaq %[stack_offset:c](%%rdi), %%rsi
432432 \\ movq %%rdi, %%r8
433433 \\ xorl %%edi, %%edi
434 \\ movq %[sigaltstack], %%rax
434 \\ movl %[sigaltstack], %%eax
435435 \\ syscall
436436 \\ testq %%rax, %%rax
437437 \\ jnz 0f
438 \\ movq %[sigprocmask], %%rax
438 \\ movl %[sigprocmask], %%eax
439439 \\ xorl %%esi, %%esi
440440 \\ leaq %[sigmask_offset:c](%%r8), %%rdx
441441 \\ movl %[sigset_size], %%r10d
lib/std/os/test.zig-4
......@@ -509,8 +509,6 @@ fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void {
509509test "dl_iterate_phdr" {
510510 if (builtin.object_format != .elf) return error.SkipZigTest;
511511
512 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
513
514512 var counter: usize = 0;
515513 try os.dl_iterate_phdr(&counter, IterFnError, iter_fn);
516514 try expect(counter != 0);
......@@ -804,8 +802,6 @@ test "sigaction" {
804802 if (native_os == .wasi or native_os == .windows)
805803 return error.SkipZigTest;
806804
807 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
808
809805 // https://github.com/ziglang/zig/issues/7427
810806 if (native_os == .linux and builtin.target.cpu.arch == .x86)
811807 return error.SkipZigTest;
lib/std/rand/test.zig-2
......@@ -158,8 +158,6 @@ fn testRandomEnumValue() !void {
158158}
159159
160160test "Random intLessThan" {
161 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
162
163161 @setEvalBranchQuota(10000);
164162 try testRandomIntLessThan();
165163 try comptime testRandomIntLessThan();
lib/std/target.zig+30-6
......@@ -733,7 +733,14 @@ pub const Target = struct {
733733
734734 /// Adds the specified feature set but not its dependencies.
735735 pub fn addFeatureSet(set: *Set, other_set: Set) void {
736 set.ints = @as(@Vector(usize_count, usize), set.ints) | @as(@Vector(usize_count, usize), other_set.ints);
736 switch (builtin.zig_backend) {
737 .stage2_x86_64 => {
738 for (&set.ints, other_set.ints) |*set_int, other_set_int| set_int.* |= other_set_int;
739 },
740 else => {
741 set.ints = @as(@Vector(usize_count, usize), set.ints) | @as(@Vector(usize_count, usize), other_set.ints);
742 },
743 }
737744 }
738745
739746 /// Removes the specified feature but not its dependents.
......@@ -745,7 +752,14 @@ pub const Target = struct {
745752
746753 /// Removes the specified feature but not its dependents.
747754 pub fn removeFeatureSet(set: *Set, other_set: Set) void {
748 set.ints = @as(@Vector(usize_count, usize), set.ints) & ~@as(@Vector(usize_count, usize), other_set.ints);
755 switch (builtin.zig_backend) {
756 .stage2_x86_64 => {
757 for (&set.ints, other_set.ints) |*set_int, other_set_int| set_int.* &= ~other_set_int;
758 },
759 else => {
760 set.ints = @as(@Vector(usize_count, usize), set.ints) & ~@as(@Vector(usize_count, usize), other_set.ints);
761 },
762 }
749763 }
750764
751765 pub fn populateDependencies(set: *Set, all_features_list: []const Cpu.Feature) void {
......@@ -774,10 +788,20 @@ pub const Target = struct {
774788 }
775789
776790 pub fn isSuperSetOf(set: Set, other_set: Set) bool {
777 const V = @Vector(usize_count, usize);
778 const set_v: V = set.ints;
779 const other_v: V = other_set.ints;
780 return @reduce(.And, (set_v & other_v) == other_v);
791 switch (builtin.zig_backend) {
792 .stage2_x86_64 => {
793 var result = true;
794 for (&set.ints, other_set.ints) |*set_int, other_set_int|
795 result = result and (set_int.* & other_set_int) == other_set_int;
796 return result;
797 },
798 else => {
799 const V = @Vector(usize_count, usize);
800 const set_v: V = set.ints;
801 const other_v: V = other_set.ints;
802 return @reduce(.And, (set_v & other_v) == other_v);
803 },
804 }
781805 }
782806 };
783807
lib/std/zig/CrossTarget.zig-2
......@@ -791,8 +791,6 @@ fn parseOs(result: *CrossTarget, diags: *ParseOptions.Diagnostics, text: []const
791791}
792792
793793test "CrossTarget.parse" {
794 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
795
796794 if (builtin.target.isGnuLibC()) {
797795 var cross_target = try CrossTarget.parse(.{});
798796 cross_target.setGnuLibCVersion(2, 1, 1);
lib/std/zig/fmt.zig-2
......@@ -95,8 +95,6 @@ pub fn fmtEscapes(bytes: []const u8) std.fmt.Formatter(stringEscape) {
9595}
9696
9797test "escape invalid identifiers" {
98 if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
99
10098 const expectFmt = std.testing.expectFmt;
10199 try expectFmt("@\"while\"", "{}", .{fmtId("while")});
102100 try expectFmt("hello", "{}", .{fmtId("hello")});
src/Module.zig+2-1
......@@ -5846,7 +5846,8 @@ pub const Feature = enum {
58465846pub fn backendSupportsFeature(mod: Module, feature: Feature) bool {
58475847 return switch (feature) {
58485848 .panic_fn => mod.comp.bin_file.options.target.ofmt == .c or
5849 mod.comp.bin_file.options.use_llvm,
5849 mod.comp.bin_file.options.use_llvm or
5850 mod.comp.bin_file.options.target.cpu.arch == .x86_64,
58505851 .panic_unwrap_error => mod.comp.bin_file.options.target.ofmt == .c or
58515852 mod.comp.bin_file.options.use_llvm,
58525853 .safety_check_formatted => mod.comp.bin_file.options.target.ofmt == .c or
src/arch/x86_64/CodeGen.zig+409-244
......@@ -1145,7 +1145,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
11451145}
11461146
11471147/// A `cc` of `.z_and_np` clobbers `reg2`!
1148fn asmCmovccRegisterRegister(self: *Self, cc: bits.Condition, reg1: Register, reg2: Register) !void {
1148fn asmCmovccRegisterRegister(self: *Self, cc: Condition, reg1: Register, reg2: Register) !void {
11491149 _ = try self.addInst(.{
11501150 .tag = switch (cc) {
11511151 else => .cmov,
......@@ -1168,7 +1168,7 @@ fn asmCmovccRegisterRegister(self: *Self, cc: bits.Condition, reg1: Register, re
11681168}
11691169
11701170/// A `cc` of `.z_and_np` is not supported by this encoding!
1171fn asmCmovccRegisterMemory(self: *Self, cc: bits.Condition, reg: Register, m: Memory) !void {
1171fn asmCmovccRegisterMemory(self: *Self, cc: Condition, reg: Register, m: Memory) !void {
11721172 _ = try self.addInst(.{
11731173 .tag = switch (cc) {
11741174 else => .cmov,
......@@ -1204,7 +1204,7 @@ fn asmCmovccRegisterMemory(self: *Self, cc: bits.Condition, reg: Register, m: Me
12041204 });
12051205}
12061206
1207fn asmSetccRegister(self: *Self, reg: Register, cc: bits.Condition) !void {
1207fn asmSetccRegister(self: *Self, cc: Condition, reg: Register) !void {
12081208 _ = try self.addInst(.{
12091209 .tag = switch (cc) {
12101210 else => .set,
......@@ -1228,7 +1228,7 @@ fn asmSetccRegister(self: *Self, reg: Register, cc: bits.Condition) !void {
12281228 });
12291229}
12301230
1231fn asmSetccMemory(self: *Self, m: Memory, cc: bits.Condition) !void {
1231fn asmSetccMemory(self: *Self, cc: Condition, m: Memory) !void {
12321232 const payload = switch (m) {
12331233 .sib => try self.addExtra(Mir.MemorySib.encode(m)),
12341234 .rip => try self.addExtra(Mir.MemoryRip.encode(m)),
......@@ -1279,7 +1279,7 @@ fn asmJmpReloc(self: *Self, target: Mir.Inst.Index) !Mir.Inst.Index {
12791279 });
12801280}
12811281
1282fn asmJccReloc(self: *Self, target: Mir.Inst.Index, cc: bits.Condition) !Mir.Inst.Index {
1282fn asmJccReloc(self: *Self, cc: Condition, target: Mir.Inst.Index) !Mir.Inst.Index {
12831283 return self.addInst(.{
12841284 .tag = switch (cc) {
12851285 else => .j,
......@@ -1759,8 +1759,8 @@ fn gen(self: *Self) InnerError!void {
17591759 const cc = abi.resolveCallingConvention(fn_info.cc, self.target.*);
17601760 if (cc != .Naked) {
17611761 try self.asmRegister(.{ ._, .push }, .rbp);
1762 const backpatch_push_callee_preserved_regs = try self.asmPlaceholder();
17631762 try self.asmRegisterRegister(.{ ._, .mov }, .rbp, .rsp);
1763 const backpatch_push_callee_preserved_regs = try self.asmPlaceholder();
17641764 const backpatch_frame_align = try self.asmPlaceholder();
17651765 const backpatch_frame_align_extra = try self.asmPlaceholder();
17661766 const backpatch_stack_alloc = try self.asmPlaceholder();
......@@ -1805,7 +1805,7 @@ fn gen(self: *Self) InnerError!void {
18051805 );
18061806
18071807 try self.asmRegisterImmediate(.{ ._, .cmp }, .al, Immediate.u(info.fp_count));
1808 const skip_sse_reloc = try self.asmJccReloc(undefined, .na);
1808 const skip_sse_reloc = try self.asmJccReloc(.na, undefined);
18091809
18101810 const vec_2_f64 = try mod.vectorType(.{ .len = 2, .child = .f64_type });
18111811 for (abi.SysV.c_abi_sse_param_regs[info.fp_count..], info.fp_count..) |reg, reg_i|
......@@ -1913,11 +1913,14 @@ fn gen(self: *Self) InnerError!void {
19131913 }
19141914 if (need_frame_align or need_stack_adjust) {
19151915 self.mir_instructions.set(backpatch_stack_dealloc, .{
1916 .tag = .mov,
1917 .ops = .rr,
1918 .data = .{ .rr = .{
1916 .tag = .lea,
1917 .ops = .rm_sib,
1918 .data = .{ .rx = .{
19191919 .r1 = .rsp,
1920 .r2 = .rbp,
1920 .payload = try self.addExtra(Mir.MemorySib.encode(Memory.sib(.qword, .{
1921 .base = .{ .reg = .rbp },
1922 .disp = -frame_layout.save_reg_list.size(),
1923 }))),
19211924 } },
19221925 });
19231926 }
......@@ -2262,7 +2265,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
22622265 const tag_val = try mod.enumValueFieldIndex(enum_ty, index);
22632266 const tag_mcv = try self.genTypedValue(.{ .ty = enum_ty, .val = tag_val });
22642267 try self.genBinOpMir(.{ ._, .cmp }, enum_ty, enum_mcv, tag_mcv);
2265 const skip_reloc = try self.asmJccReloc(undefined, .ne);
2268 const skip_reloc = try self.asmJccReloc(.ne, undefined);
22662269
22672270 try self.genSetMem(
22682271 .{ .reg = ret_reg },
......@@ -2298,8 +2301,8 @@ fn getValue(self: *Self, value: MCValue, inst: ?Air.Inst.Index) void {
22982301fn freeValue(self: *Self, value: MCValue) !void {
22992302 switch (value) {
23002303 .register => |reg| {
2301 if (reg.class() == .x87) try self.asmRegister(.{ .f_, .free }, reg);
23022304 self.register_manager.freeReg(reg);
2305 if (reg.class() == .x87) try self.asmRegister(.{ .f_, .free }, reg);
23032306 },
23042307 .register_pair => |regs| for (regs) |reg| self.register_manager.freeReg(reg),
23052308 .register_offset => |reg_off| self.register_manager.freeReg(reg_off.reg),
......@@ -2416,17 +2419,19 @@ fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayo
24162419 const callee_preserved_regs =
24172420 abi.getCalleePreservedRegs(abi.resolveCallingConvention(cc, self.target.*));
24182421 for (callee_preserved_regs) |reg| {
2419 if (self.register_manager.isRegAllocated(reg)) {
2422 if (self.register_manager.isRegAllocated(reg) or true) {
24202423 save_reg_list.push(callee_preserved_regs, reg);
24212424 }
24222425 }
24232426
2424 var rbp_offset: i32 = @intCast(save_reg_list.count() * 8);
2427 var rbp_offset: i32 = 0;
24252428 self.setFrameLoc(.base_ptr, .rbp, &rbp_offset, false);
24262429 self.setFrameLoc(.ret_addr, .rbp, &rbp_offset, false);
24272430 self.setFrameLoc(.args_frame, .rbp, &rbp_offset, false);
2428 const stack_frame_align_offset =
2429 if (need_align_stack) 0 else frame_offset[@intFromEnum(FrameIndex.args_frame)];
2431 const stack_frame_align_offset = if (need_align_stack)
2432 0
2433 else
2434 save_reg_list.size() + frame_offset[@intFromEnum(FrameIndex.args_frame)];
24302435
24312436 var rsp_offset: i32 = 0;
24322437 self.setFrameLoc(.call_frame, .rsp, &rsp_offset, true);
......@@ -3242,7 +3247,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
32423247 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
32433248 const ty = self.typeOf(bin_op.lhs);
32443249 if (ty.zigTypeTag(mod) == .Vector or ty.abiSize(mod) > 8) return self.fail(
3245 "TODO implement addMulSat for {}",
3250 "TODO implement airAddSat for {}",
32463251 .{ty.fmt(mod)},
32473252 );
32483253
......@@ -3325,7 +3330,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
33253330 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
33263331 const ty = self.typeOf(bin_op.lhs);
33273332 if (ty.zigTypeTag(mod) == .Vector or ty.abiSize(mod) > 8) return self.fail(
3328 "TODO implement addMulSat for {}",
3333 "TODO implement airSubSat for {}",
33293334 .{ty.fmt(mod)},
33303335 );
33313336
......@@ -3401,7 +3406,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
34013406 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
34023407 const ty = self.typeOf(bin_op.lhs);
34033408 if (ty.zigTypeTag(mod) == .Vector or ty.abiSize(mod) > 8) return self.fail(
3404 "TODO implement addMulSat for {}",
3409 "TODO implement airMulSat for {}",
34053410 .{ty.fmt(mod)},
34063411 );
34073412
......@@ -3617,7 +3622,7 @@ fn genSetFrameTruncatedOverflowCompare(
36173622 defer for (temp_locks) |lock| self.register_manager.unlockReg(lock);
36183623
36193624 const overflow_reg = temp_regs[0];
3620 if (overflow_cc) |cc| try self.asmSetccRegister(overflow_reg.to8(), cc);
3625 if (overflow_cc) |cc| try self.asmSetccRegister(cc, overflow_reg.to8());
36213626
36223627 const scratch_reg = temp_regs[1];
36233628 const hi_limb_off = if (int_info.bits <= 64) 0 else (int_info.bits - 1) / 64 * 8;
......@@ -3631,7 +3636,7 @@ fn genSetFrameTruncatedOverflowCompare(
36313636
36323637 const eq_reg = temp_regs[2];
36333638 if (overflow_cc) |_| {
3634 try self.asmSetccRegister(eq_reg.to8(), .ne);
3639 try self.asmSetccRegister(.ne, eq_reg.to8());
36353640 try self.genBinOpMir(
36363641 .{ ._, .@"or" },
36373642 Type.u8,
......@@ -3660,28 +3665,150 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
36603665 const mod = self.bin_file.options.module.?;
36613666 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
36623667 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
3668 const tuple_ty = self.typeOfIndex(inst);
36633669 const dst_ty = self.typeOf(bin_op.lhs);
36643670 const result: MCValue = switch (dst_ty.zigTypeTag(mod)) {
36653671 .Vector => return self.fail("TODO implement airMulWithOverflow for {}", .{dst_ty.fmt(mod)}),
36663672 .Int => result: {
3673 const dst_info = dst_ty.intInfo(mod);
3674 const lhs_active_bits = self.activeIntBits(bin_op.lhs);
3675 const rhs_active_bits = self.activeIntBits(bin_op.rhs);
3676 const src_bits = @max(lhs_active_bits, rhs_active_bits, dst_info.bits / 2);
3677 const src_ty = try mod.intType(dst_info.signedness, src_bits);
3678
3679 if (src_bits > 64 and src_bits <= 128 and
3680 dst_info.bits > 64 and dst_info.bits <= 128) switch (dst_info.signedness) {
3681 .signed => {
3682 const ptr_c_int = try mod.singleMutPtrType(Type.c_int);
3683 const overflow = try self.allocTempRegOrMem(Type.c_int, false);
3684 const result = try self.genCall(.{ .lib = .{
3685 .return_type = .i128_type,
3686 .param_types = &.{ .i128_type, .i128_type, ptr_c_int.toIntern() },
3687 .callee = "__muloti4",
3688 } }, &.{ Type.i128, Type.i128, ptr_c_int }, &.{
3689 .{ .air_ref = bin_op.lhs },
3690 .{ .air_ref = bin_op.rhs },
3691 overflow.address(),
3692 });
3693
3694 const dst_mcv = try self.allocRegOrMem(inst, false);
3695 try self.genSetMem(
3696 .{ .frame = dst_mcv.load_frame.index },
3697 @intCast(tuple_ty.structFieldOffset(0, mod)),
3698 tuple_ty.structFieldType(0, mod),
3699 result,
3700 );
3701 try self.asmMemoryImmediate(
3702 .{ ._, .cmp },
3703 overflow.mem(self.memPtrSize(Type.c_int)),
3704 Immediate.s(0),
3705 );
3706 try self.genSetMem(
3707 .{ .frame = dst_mcv.load_frame.index },
3708 @intCast(tuple_ty.structFieldOffset(1, mod)),
3709 tuple_ty.structFieldType(1, mod),
3710 .{ .eflags = .ne },
3711 );
3712 try self.freeValue(overflow);
3713 break :result dst_mcv;
3714 },
3715 .unsigned => {
3716 try self.spillEflagsIfOccupied();
3717 try self.spillRegisters(&.{ .rax, .rdx });
3718 const reg_locks = self.register_manager.lockRegsAssumeUnused(2, .{ .rax, .rdx });
3719 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
3720
3721 const tmp_regs =
3722 try self.register_manager.allocRegs(4, .{null} ** 4, abi.RegisterClass.gp);
3723 const tmp_locks = self.register_manager.lockRegsAssumeUnused(4, tmp_regs);
3724 defer for (tmp_locks) |lock| self.register_manager.unlockReg(lock);
3725
3726 const lhs_mcv = try self.resolveInst(bin_op.lhs);
3727 const rhs_mcv = try self.resolveInst(bin_op.rhs);
3728
3729 if (lhs_mcv.isMemory())
3730 try self.asmRegisterMemory(.{ ._, .mov }, .rax, lhs_mcv.mem(.qword))
3731 else
3732 try self.asmRegisterRegister(.{ ._, .mov }, .rax, lhs_mcv.register_pair[0]);
3733 if (rhs_mcv.isMemory()) try self.asmRegisterMemory(
3734 .{ ._, .mov },
3735 tmp_regs[0],
3736 rhs_mcv.address().offset(8).deref().mem(.qword),
3737 ) else try self.asmRegisterRegister(
3738 .{ ._, .mov },
3739 tmp_regs[0],
3740 rhs_mcv.register_pair[1],
3741 );
3742 try self.asmRegisterRegister(.{ ._, .@"test" }, tmp_regs[0], tmp_regs[0]);
3743 try self.asmSetccRegister(.nz, tmp_regs[1].to8());
3744 try self.asmRegisterRegister(.{ .i_, .mul }, tmp_regs[0], .rax);
3745 try self.asmSetccRegister(.o, tmp_regs[2].to8());
3746 if (rhs_mcv.isMemory())
3747 try self.asmMemory(.{ ._, .mul }, rhs_mcv.mem(.qword))
3748 else
3749 try self.asmRegister(.{ ._, .mul }, rhs_mcv.register_pair[0]);
3750 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_regs[0]);
3751 try self.asmSetccRegister(.c, tmp_regs[3].to8());
3752 try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[2].to8(), tmp_regs[3].to8());
3753 if (lhs_mcv.isMemory()) try self.asmRegisterMemory(
3754 .{ ._, .mov },
3755 tmp_regs[0],
3756 lhs_mcv.address().offset(8).deref().mem(.qword),
3757 ) else try self.asmRegisterRegister(
3758 .{ ._, .mov },
3759 tmp_regs[0],
3760 lhs_mcv.register_pair[1],
3761 );
3762 try self.asmRegisterRegister(.{ ._, .@"test" }, tmp_regs[0], tmp_regs[0]);
3763 try self.asmSetccRegister(.nz, tmp_regs[3].to8());
3764 try self.asmRegisterRegister(
3765 .{ ._, .@"and" },
3766 tmp_regs[1].to8(),
3767 tmp_regs[3].to8(),
3768 );
3769 try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[1].to8(), tmp_regs[2].to8());
3770 if (rhs_mcv.isMemory())
3771 try self.asmRegisterMemory(.{ .i_, .mul }, tmp_regs[0], rhs_mcv.mem(.qword))
3772 else
3773 try self.asmRegisterRegister(
3774 .{ .i_, .mul },
3775 tmp_regs[0],
3776 rhs_mcv.register_pair[0],
3777 );
3778 try self.asmSetccRegister(.o, tmp_regs[2].to8());
3779 try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[1].to8(), tmp_regs[2].to8());
3780 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_regs[0]);
3781 try self.asmSetccRegister(.c, tmp_regs[2].to8());
3782 try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[1].to8(), tmp_regs[2].to8());
3783
3784 const dst_mcv = try self.allocRegOrMem(inst, false);
3785 try self.genSetMem(
3786 .{ .frame = dst_mcv.load_frame.index },
3787 @intCast(tuple_ty.structFieldOffset(0, mod)),
3788 tuple_ty.structFieldType(0, mod),
3789 .{ .register_pair = .{ .rax, .rdx } },
3790 );
3791 try self.genSetMem(
3792 .{ .frame = dst_mcv.load_frame.index },
3793 @intCast(tuple_ty.structFieldOffset(1, mod)),
3794 tuple_ty.structFieldType(1, mod),
3795 .{ .register = tmp_regs[1] },
3796 );
3797 break :result dst_mcv;
3798 },
3799 };
3800
36673801 try self.spillEflagsIfOccupied();
36683802 try self.spillRegisters(&.{ .rax, .rdx });
36693803
3670 const dst_info = dst_ty.intInfo(mod);
36713804 const cc: Condition = switch (dst_info.signedness) {
36723805 .unsigned => .c,
36733806 .signed => .o,
36743807 };
36753808
3676 const lhs_active_bits = self.activeIntBits(bin_op.lhs);
3677 const rhs_active_bits = self.activeIntBits(bin_op.rhs);
3678 const src_bits = @max(lhs_active_bits, rhs_active_bits, dst_info.bits / 2);
3679 const src_ty = try mod.intType(dst_info.signedness, src_bits);
3680
36813809 const lhs = try self.resolveInst(bin_op.lhs);
36823810 const rhs = try self.resolveInst(bin_op.rhs);
36833811
3684 const tuple_ty = self.typeOfIndex(inst);
36853812 const extra_bits = if (dst_info.bits <= 64)
36863813 self.regExtraBits(dst_ty)
36873814 else
......@@ -3741,6 +3868,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
37413868fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue, rhs: MCValue) !void {
37423869 const mod = self.bin_file.options.module.?;
37433870 const abi_size: u32 = @intCast(ty.abiSize(mod));
3871 const bit_size: u32 = @intCast(self.regBitSize(ty));
37443872 if (abi_size > 8) {
37453873 return self.fail("TODO implement genIntMulDivOpMir for ABI size larger than 8", .{});
37463874 }
......@@ -3752,14 +3880,14 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue
37523880 .div => switch (tag[0]) {
37533881 ._ => {
37543882 const hi_reg: Register =
3755 switch (self.regBitSize(ty)) {
3883 switch (bit_size) {
37563884 8 => .ah,
37573885 16, 32, 64 => .edx,
37583886 else => unreachable,
37593887 };
37603888 try self.asmRegisterRegister(.{ ._, .xor }, hi_reg, hi_reg);
37613889 },
3762 .i_ => try self.asmOpOnly(.{ ._, switch (self.regBitSize(ty)) {
3890 .i_ => try self.asmOpOnly(.{ ._, switch (bit_size) {
37633891 8 => .cbw,
37643892 16 => .cwd,
37653893 32 => .cdq,
......@@ -3782,6 +3910,7 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue
37823910 ),
37833911 else => unreachable,
37843912 }
3913 if (tag[1] == .div and bit_size == 8) try self.asmRegisterRegister(.{ ._, .mov }, .dl, .ah);
37853914}
37863915
37873916/// Always returns a register.
......@@ -3981,54 +4110,12 @@ fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
39814110
39824111fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
39834112 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3984 const err_union_ty = self.typeOf(ty_op.operand);
4113 const operand_ty = self.typeOf(ty_op.operand);
39854114 const operand = try self.resolveInst(ty_op.operand);
3986 const result = try self.genUnwrapErrorUnionPayloadMir(inst, err_union_ty, operand);
4115 const result = try self.genUnwrapErrUnionPayloadMir(inst, operand_ty, operand);
39874116 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
39884117}
39894118
3990fn genUnwrapErrorUnionPayloadMir(
3991 self: *Self,
3992 maybe_inst: ?Air.Inst.Index,
3993 err_union_ty: Type,
3994 err_union: MCValue,
3995) !MCValue {
3996 const mod = self.bin_file.options.module.?;
3997 const payload_ty = err_union_ty.errorUnionPayload(mod);
3998
3999 const result: MCValue = result: {
4000 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
4001
4002 const payload_off = errUnionPayloadOffset(payload_ty, mod);
4003 switch (err_union) {
4004 .load_frame => |frame_addr| break :result .{ .load_frame = .{
4005 .index = frame_addr.index,
4006 .off = frame_addr.off + @as(i32, @intCast(payload_off)),
4007 } },
4008 .register => |reg| {
4009 // TODO reuse operand
4010 const eu_lock = self.register_manager.lockReg(reg);
4011 defer if (eu_lock) |lock| self.register_manager.unlockReg(lock);
4012
4013 const result_mcv: MCValue = if (maybe_inst) |inst|
4014 try self.copyToRegisterWithInstTracking(inst, err_union_ty, err_union)
4015 else
4016 .{ .register = try self.copyToTmpRegister(err_union_ty, err_union) };
4017 if (payload_off > 0) try self.genShiftBinOpMir(
4018 .{ ._r, .sh },
4019 err_union_ty,
4020 result_mcv,
4021 .{ .immediate = @as(u6, @intCast(payload_off * 8)) },
4022 ) else try self.truncateRegister(payload_ty, result_mcv.register);
4023 break :result result_mcv;
4024 },
4025 else => return self.fail("TODO implement genUnwrapErrorUnionPayloadMir for {}", .{err_union}),
4026 }
4027 };
4028
4029 return result;
4030}
4031
40324119// *(E!T) -> E
40334120fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {
40344121 const mod = self.bin_file.options.module.?;
......@@ -4067,38 +4154,11 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {
40674154
40684155// *(E!T) -> *T
40694156fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
4070 const mod = self.bin_file.options.module.?;
40714157 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
4072
4073 const src_ty = self.typeOf(ty_op.operand);
4074 const src_mcv = try self.resolveInst(ty_op.operand);
4075 const src_reg = switch (src_mcv) {
4076 .register => |reg| reg,
4077 else => try self.copyToTmpRegister(src_ty, src_mcv),
4078 };
4079 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
4080 defer self.register_manager.unlockReg(src_lock);
4081
4082 const dst_ty = self.typeOfIndex(inst);
4083 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
4084 src_reg
4085 else
4086 try self.register_manager.allocReg(inst, abi.RegisterClass.gp);
4087 const dst_mcv = MCValue{ .register = dst_reg };
4088 const dst_lock = self.register_manager.lockReg(dst_reg);
4089 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
4090
4091 const eu_ty = src_ty.childType(mod);
4092 const pl_ty = eu_ty.errorUnionPayload(mod);
4093 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, mod));
4094 const dst_abi_size: u32 = @intCast(dst_ty.abiSize(mod));
4095 try self.asmRegisterMemory(
4096 .{ ._, .lea },
4097 registerAlias(dst_reg, dst_abi_size),
4098 Memory.sib(.qword, .{ .base = .{ .reg = src_reg }, .disp = pl_off }),
4099 );
4100
4101 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
4158 const operand_ty = self.typeOf(ty_op.operand);
4159 const operand = try self.resolveInst(ty_op.operand);
4160 const result = try self.genUnwrapErrUnionPayloadPtrMir(inst, operand_ty, operand);
4161 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
41024162}
41034163
41044164fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
......@@ -4150,6 +4210,71 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
41504210 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
41514211}
41524212
4213fn genUnwrapErrUnionPayloadMir(
4214 self: *Self,
4215 maybe_inst: ?Air.Inst.Index,
4216 err_union_ty: Type,
4217 err_union: MCValue,
4218) !MCValue {
4219 const mod = self.bin_file.options.module.?;
4220 const payload_ty = err_union_ty.errorUnionPayload(mod);
4221
4222 const result: MCValue = result: {
4223 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
4224
4225 const payload_off: u31 = @intCast(errUnionPayloadOffset(payload_ty, mod));
4226 switch (err_union) {
4227 .load_frame => |frame_addr| break :result .{ .load_frame = .{
4228 .index = frame_addr.index,
4229 .off = frame_addr.off + payload_off,
4230 } },
4231 .register => |reg| {
4232 // TODO reuse operand
4233 const eu_lock = self.register_manager.lockReg(reg);
4234 defer if (eu_lock) |lock| self.register_manager.unlockReg(lock);
4235
4236 const result_mcv: MCValue = if (maybe_inst) |inst|
4237 try self.copyToRegisterWithInstTracking(inst, err_union_ty, err_union)
4238 else
4239 .{ .register = try self.copyToTmpRegister(err_union_ty, err_union) };
4240 if (payload_off > 0) try self.genShiftBinOpMir(
4241 .{ ._r, .sh },
4242 err_union_ty,
4243 result_mcv,
4244 .{ .immediate = @as(u6, @intCast(payload_off * 8)) },
4245 ) else try self.truncateRegister(payload_ty, result_mcv.register);
4246 break :result result_mcv;
4247 },
4248 else => return self.fail("TODO implement genUnwrapErrUnionPayloadMir for {}", .{err_union}),
4249 }
4250 };
4251
4252 return result;
4253}
4254
4255fn genUnwrapErrUnionPayloadPtrMir(
4256 self: *Self,
4257 maybe_inst: ?Air.Inst.Index,
4258 ptr_ty: Type,
4259 ptr_mcv: MCValue,
4260) !MCValue {
4261 const mod = self.bin_file.options.module.?;
4262 const err_union_ty = ptr_ty.childType(mod);
4263 const payload_ty = err_union_ty.errorUnionPayload(mod);
4264
4265 const result: MCValue = result: {
4266 const payload_off = errUnionPayloadOffset(payload_ty, mod);
4267 const result_mcv: MCValue = if (maybe_inst) |inst|
4268 try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr_mcv)
4269 else
4270 .{ .register = try self.copyToTmpRegister(ptr_ty, ptr_mcv) };
4271 try self.genBinOpMir(.{ ._, .add }, ptr_ty, result_mcv, .{ .immediate = payload_off });
4272 break :result result_mcv;
4273 };
4274
4275 return result;
4276}
4277
41534278fn airErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void {
41544279 _ = inst;
41554280 return self.fail("TODO implement airErrReturnTrace for {}", .{self.target.cpu.arch});
......@@ -6425,7 +6550,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
64256550 break :result .{ .eflags = ro.eflags };
64266551 } else {
64276552 const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp);
6428 try self.asmSetccRegister(dst_reg.to8(), ro.eflags);
6553 try self.asmSetccRegister(ro.eflags, dst_reg.to8());
64296554 break :result .{ .register = dst_reg.to8() };
64306555 },
64316556 else => unreachable,
......@@ -9712,55 +9837,59 @@ fn genCall(self: *Self, info: union(enum) {
97129837 switch (info) {
97139838 .air => |callee| if (try self.air.value(callee, mod)) |func_value| {
97149839 const func_key = mod.intern_pool.indexToKey(func_value.ip_index);
9715 if (switch (func_key) {
9716 .func => |func| func.owner_decl,
9840 switch (switch (func_key) {
9841 else => func_key,
97179842 .ptr => |ptr| switch (ptr.addr) {
9718 .decl => |decl| decl,
9719 else => null,
9843 .decl => |decl| mod.intern_pool.indexToKey(try mod.declPtr(decl).internValue(mod)),
9844 else => func_key,
97209845 },
9721 else => null,
9722 }) |owner_decl| {
9723 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
9724 const sym_index = try elf_file.getOrCreateMetadataForDecl(owner_decl);
9725 const sym = elf_file.symbol(sym_index);
9726 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
9727 if (self.bin_file.options.pic) {
9728 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym.esym_index });
9846 }) {
9847 .func => |func| {
9848 try mod.markDeclAlive(mod.declPtr(func.owner_decl));
9849 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
9850 const sym_index = try elf_file.getOrCreateMetadataForDecl(func.owner_decl);
9851 const sym = elf_file.symbol(sym_index);
9852 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
9853 if (self.bin_file.options.pic) {
9854 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym.esym_index });
9855 try self.asmRegister(.{ ._, .call }, .rax);
9856 } else {
9857 _ = try self.addInst(.{
9858 .tag = .call,
9859 .ops = .direct_got_reloc,
9860 .data = .{ .reloc = .{
9861 .atom_index = try self.owner.getSymbolIndex(self),
9862 .sym_index = sym.esym_index,
9863 } },
9864 });
9865 }
9866 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
9867 const atom = try coff_file.getOrCreateAtomForDecl(func.owner_decl);
9868 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
9869 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
97299870 try self.asmRegister(.{ ._, .call }, .rax);
9730 } else {
9731 _ = try self.addInst(.{
9732 .tag = .call,
9733 .ops = .direct_got_reloc,
9734 .data = .{ .reloc = .{
9735 .atom_index = try self.owner.getSymbolIndex(self),
9736 .sym_index = sym.esym_index,
9737 } },
9738 });
9739 }
9740 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
9741 const atom = try coff_file.getOrCreateAtomForDecl(owner_decl);
9742 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
9743 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
9744 try self.asmRegister(.{ ._, .call }, .rax);
9745 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
9746 const atom = try macho_file.getOrCreateAtomForDecl(owner_decl);
9747 const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
9748 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
9749 try self.asmRegister(.{ ._, .call }, .rax);
9750 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
9751 const atom_index = try p9.seeDecl(owner_decl);
9752 const atom = p9.getAtom(atom_index);
9753 try self.asmMemory(.{ ._, .call }, Memory.sib(.qword, .{
9754 .base = .{ .reg = .ds },
9755 .disp = @intCast(atom.getOffsetTableAddress(p9)),
9756 }));
9757 } else unreachable;
9758 } else if (func_value.getExternFunc(mod)) |extern_func| {
9759 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
9760 const decl_name = mod.intern_pool.stringToSlice(mod.declPtr(extern_func.decl).name);
9761 try self.genExternSymbolRef(.call, lib_name, decl_name);
9762 } else {
9763 return self.fail("TODO implement calling bitcasted functions", .{});
9871 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
9872 const atom = try macho_file.getOrCreateAtomForDecl(func.owner_decl);
9873 const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
9874 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
9875 try self.asmRegister(.{ ._, .call }, .rax);
9876 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
9877 const atom_index = try p9.seeDecl(func.owner_decl);
9878 const atom = p9.getAtom(atom_index);
9879 try self.asmMemory(.{ ._, .call }, Memory.sib(.qword, .{
9880 .base = .{ .reg = .ds },
9881 .disp = @intCast(atom.getOffsetTableAddress(p9)),
9882 }));
9883 } else unreachable;
9884 },
9885 .extern_func => |extern_func| {
9886 const owner_decl = mod.declPtr(extern_func.decl);
9887 try mod.markDeclAlive(owner_decl);
9888 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
9889 const decl_name = mod.intern_pool.stringToSlice(owner_decl.name);
9890 try self.genExternSymbolRef(.call, lib_name, decl_name);
9891 },
9892 else => return self.fail("TODO implement calling bitcasted functions", .{}),
97649893 }
97659894 } else {
97669895 assert(self.typeOf(callee).zigTypeTag(mod) == .Pointer);
......@@ -10241,47 +10370,46 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void {
1024110370 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
1024210371 const extra = self.air.extraData(Air.Try, pl_op.payload);
1024310372 const body = self.air.extra[extra.end..][0..extra.data.body_len];
10244 const err_union_ty = self.typeOf(pl_op.operand);
10245 const result = try self.genTry(inst, pl_op.operand, body, err_union_ty, false);
10373 const operand_ty = self.typeOf(pl_op.operand);
10374 const result = try self.genTry(inst, pl_op.operand, body, operand_ty, false);
1024610375 return self.finishAir(inst, result, .{ .none, .none, .none });
1024710376}
1024810377
1024910378fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void {
10250 const mod = self.bin_file.options.module.?;
1025110379 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1025210380 const extra = self.air.extraData(Air.TryPtr, ty_pl.payload);
1025310381 const body = self.air.extra[extra.end..][0..extra.data.body_len];
10254 const err_union_ty = self.typeOf(extra.data.ptr).childType(mod);
10255 const result = try self.genTry(inst, extra.data.ptr, body, err_union_ty, true);
10382 const operand_ty = self.typeOf(extra.data.ptr);
10383 const result = try self.genTry(inst, extra.data.ptr, body, operand_ty, true);
1025610384 return self.finishAir(inst, result, .{ .none, .none, .none });
1025710385}
1025810386
1025910387fn genTry(
1026010388 self: *Self,
1026110389 inst: Air.Inst.Index,
10262 err_union: Air.Inst.Ref,
10390 operand: Air.Inst.Ref,
1026310391 body: []const Air.Inst.Index,
10264 err_union_ty: Type,
10392 operand_ty: Type,
1026510393 operand_is_ptr: bool,
1026610394) !MCValue {
10267 if (operand_is_ptr) {
10268 return self.fail("TODO genTry for pointers", .{});
10269 }
1027010395 const liveness_cond_br = self.liveness.getCondBr(inst);
1027110396
10272 const err_union_mcv = try self.resolveInst(err_union);
10273 const is_err_mcv = try self.isErr(null, err_union_ty, err_union_mcv);
10397 const operand_mcv = try self.resolveInst(operand);
10398 const is_err_mcv = if (operand_is_ptr)
10399 try self.isErrPtr(null, operand_ty, operand_mcv)
10400 else
10401 try self.isErr(null, operand_ty, operand_mcv);
1027410402
1027510403 const reloc = try self.genCondBrMir(Type.anyerror, is_err_mcv);
1027610404
1027710405 if (self.liveness.operandDies(inst, 0)) {
10278 if (Air.refToIndex(err_union)) |err_union_inst| try self.processDeath(err_union_inst);
10406 if (Air.refToIndex(operand)) |operand_inst| try self.processDeath(operand_inst);
1027910407 }
1028010408
1028110409 self.scope_generation += 1;
1028210410 const state = try self.saveState();
1028310411
10284 for (liveness_cond_br.else_deaths) |operand| try self.processDeath(operand);
10412 for (liveness_cond_br.else_deaths) |death| try self.processDeath(death);
1028510413 try self.genBody(body);
1028610414 try self.restoreState(state, &.{}, .{
1028710415 .emit_instructions = false,
......@@ -10292,12 +10420,14 @@ fn genTry(
1029210420
1029310421 try self.performReloc(reloc);
1029410422
10295 for (liveness_cond_br.then_deaths) |operand| try self.processDeath(operand);
10423 for (liveness_cond_br.then_deaths) |death| try self.processDeath(death);
1029610424
1029710425 const result = if (self.liveness.isUnused(inst))
1029810426 .unreach
10427 else if (operand_is_ptr)
10428 try self.genUnwrapErrUnionPayloadPtrMir(inst, operand_ty, operand_mcv)
1029910429 else
10300 try self.genUnwrapErrorUnionPayloadMir(inst, err_union_ty, err_union_mcv);
10430 try self.genUnwrapErrUnionPayloadMir(inst, operand_ty, operand_mcv);
1030110431 return result;
1030210432}
1030310433
......@@ -10348,12 +10478,12 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !Mir.Inst.Index {
1034810478 switch (mcv) {
1034910479 .eflags => |cc| {
1035010480 // Here we map the opposites since the jump is to the false branch.
10351 return self.asmJccReloc(undefined, cc.negate());
10481 return self.asmJccReloc(cc.negate(), undefined);
1035210482 },
1035310483 .register => |reg| {
1035410484 try self.spillEflagsIfOccupied();
1035510485 try self.asmRegisterImmediate(.{ ._, .@"test" }, reg, Immediate.u(1));
10356 return self.asmJccReloc(undefined, .e);
10486 return self.asmJccReloc(.e, undefined);
1035710487 },
1035810488 .immediate,
1035910489 .load_frame,
......@@ -10391,7 +10521,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
1039110521 self.scope_generation += 1;
1039210522 const state = try self.saveState();
1039310523
10394 for (liveness_cond_br.then_deaths) |operand| try self.processDeath(operand);
10524 for (liveness_cond_br.then_deaths) |death| try self.processDeath(death);
1039510525 try self.genBody(then_body);
1039610526 try self.restoreState(state, &.{}, .{
1039710527 .emit_instructions = false,
......@@ -10402,7 +10532,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
1040210532
1040310533 try self.performReloc(reloc);
1040410534
10405 for (liveness_cond_br.else_deaths) |operand| try self.processDeath(operand);
10535 for (liveness_cond_br.else_deaths) |death| try self.processDeath(death);
1040610536 try self.genBody(else_body);
1040710537 try self.restoreState(state, &.{}, .{
1040810538 .emit_instructions = false,
......@@ -10517,11 +10647,11 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
1051710647
1051810648fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue {
1051910649 const mod = self.bin_file.options.module.?;
10520 try self.spillEflagsIfOccupied();
10521
1052210650 const opt_ty = ptr_ty.childType(mod);
1052310651 const pl_ty = opt_ty.optionalChild(mod);
1052410652
10653 try self.spillEflagsIfOccupied();
10654
1052510655 const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(mod))
1052610656 .{ .off = 0, .ty = if (pl_ty.isSlice(mod)) pl_ty.slicePtrFieldType(mod) else pl_ty }
1052710657 else
......@@ -10548,27 +10678,24 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue)
1054810678 return .{ .eflags = .e };
1054910679}
1055010680
10551fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {
10681fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MCValue {
1055210682 const mod = self.bin_file.options.module.?;
10553 const err_type = ty.errorUnionSet(mod);
10554
10555 if (err_type.errorSetIsEmpty(mod)) {
10556 return MCValue{ .immediate = 0 }; // always false
10557 }
10683 const err_ty = eu_ty.errorUnionSet(mod);
10684 if (err_ty.errorSetIsEmpty(mod)) return MCValue{ .immediate = 0 }; // always false
1055810685
1055910686 try self.spillEflagsIfOccupied();
1056010687
10561 const err_off = errUnionErrorOffset(ty.errorUnionPayload(mod), mod);
10562 switch (operand) {
10688 const err_off: u31 = @intCast(errUnionErrorOffset(eu_ty.errorUnionPayload(mod), mod));
10689 switch (eu_mcv) {
1056310690 .register => |reg| {
1056410691 const eu_lock = self.register_manager.lockReg(reg);
1056510692 defer if (eu_lock) |lock| self.register_manager.unlockReg(lock);
1056610693
10567 const tmp_reg = try self.copyToTmpRegister(ty, operand);
10694 const tmp_reg = try self.copyToTmpRegister(eu_ty, eu_mcv);
1056810695 if (err_off > 0) {
1056910696 try self.genShiftBinOpMir(
1057010697 .{ ._r, .sh },
10571 ty,
10698 eu_ty,
1057210699 .{ .register = tmp_reg },
1057310700 .{ .immediate = @as(u6, @intCast(err_off * 8)) },
1057410701 );
......@@ -10587,19 +10714,63 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !
1058710714 Type.anyerror,
1058810715 .{ .load_frame = .{
1058910716 .index = frame_addr.index,
10590 .off = frame_addr.off + @as(i32, @intCast(err_off)),
10717 .off = frame_addr.off + err_off,
1059110718 } },
1059210719 .{ .immediate = 0 },
1059310720 ),
10594 else => return self.fail("TODO implement isErr for {}", .{operand}),
10721 else => return self.fail("TODO implement isErr for {}", .{eu_mcv}),
1059510722 }
1059610723
1059710724 if (maybe_inst) |inst| self.eflags_inst = inst;
1059810725 return MCValue{ .eflags = .a };
1059910726}
1060010727
10601fn isNonErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {
10602 const is_err_res = try self.isErr(inst, ty, operand);
10728fn isErrPtr(self: *Self, maybe_inst: ?Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue {
10729 const mod = self.bin_file.options.module.?;
10730 const eu_ty = ptr_ty.childType(mod);
10731 const err_ty = eu_ty.errorUnionSet(mod);
10732 if (err_ty.errorSetIsEmpty(mod)) return MCValue{ .immediate = 0 }; // always false
10733
10734 try self.spillEflagsIfOccupied();
10735
10736 const ptr_reg = switch (ptr_mcv) {
10737 .register => |reg| reg,
10738 else => try self.copyToTmpRegister(ptr_ty, ptr_mcv),
10739 };
10740 const ptr_lock = self.register_manager.lockReg(ptr_reg);
10741 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
10742
10743 const err_off: u31 = @intCast(errUnionErrorOffset(eu_ty.errorUnionPayload(mod), mod));
10744 try self.asmMemoryImmediate(
10745 .{ ._, .cmp },
10746 Memory.sib(self.memPtrSize(Type.anyerror), .{
10747 .base = .{ .reg = ptr_reg },
10748 .disp = err_off,
10749 }),
10750 Immediate.u(0),
10751 );
10752
10753 if (maybe_inst) |inst| self.eflags_inst = inst;
10754 return MCValue{ .eflags = .a };
10755}
10756
10757fn isNonErr(self: *Self, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MCValue {
10758 const is_err_res = try self.isErr(inst, eu_ty, eu_mcv);
10759 switch (is_err_res) {
10760 .eflags => |cc| {
10761 assert(cc == .a);
10762 return MCValue{ .eflags = cc.negate() };
10763 },
10764 .immediate => |imm| {
10765 assert(imm == 0);
10766 return MCValue{ .immediate = @intFromBool(imm == 0) };
10767 },
10768 else => unreachable,
10769 }
10770}
10771
10772fn isNonErrPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue {
10773 const is_err_res = try self.isErrPtr(inst, ptr_ty, ptr_mcv);
1060310774 switch (is_err_res) {
1060410775 .eflags => |cc| {
1060510776 assert(cc == .a);
......@@ -10607,7 +10778,7 @@ fn isNonErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCVa
1060710778 },
1060810779 .immediate => |imm| {
1060910780 assert(imm == 0);
10610 return MCValue{ .immediate = 1 };
10781 return MCValue{ .immediate = @intFromBool(imm == 0) };
1061110782 },
1061210783 else => unreachable,
1061310784 }
......@@ -10660,29 +10831,10 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
1066010831}
1066110832
1066210833fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
10663 const mod = self.bin_file.options.module.?;
1066410834 const un_op = self.air.instructions.items(.data)[inst].un_op;
10665
10666 const operand_ptr = try self.resolveInst(un_op);
10667 const operand_ptr_lock: ?RegisterLock = switch (operand_ptr) {
10668 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
10669 else => null,
10670 };
10671 defer if (operand_ptr_lock) |lock| self.register_manager.unlockReg(lock);
10672
10673 const operand: MCValue = blk: {
10674 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
10675 // The MCValue that holds the pointer can be re-used as the value.
10676 break :blk operand_ptr;
10677 } else {
10678 break :blk try self.allocRegOrMem(inst, true);
10679 }
10680 };
10681 const ptr_ty = self.typeOf(un_op);
10682 try self.load(operand, ptr_ty, operand_ptr);
10683
10684 const result = try self.isErr(inst, ptr_ty.childType(mod), operand);
10685
10835 const operand = try self.resolveInst(un_op);
10836 const ty = self.typeOf(un_op);
10837 const result = try self.isErrPtr(inst, ty, operand);
1068610838 return self.finishAir(inst, result, .{ un_op, .none, .none });
1068710839}
1068810840
......@@ -10695,29 +10847,10 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
1069510847}
1069610848
1069710849fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
10698 const mod = self.bin_file.options.module.?;
1069910850 const un_op = self.air.instructions.items(.data)[inst].un_op;
10700
10701 const operand_ptr = try self.resolveInst(un_op);
10702 const operand_ptr_lock: ?RegisterLock = switch (operand_ptr) {
10703 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
10704 else => null,
10705 };
10706 defer if (operand_ptr_lock) |lock| self.register_manager.unlockReg(lock);
10707
10708 const operand: MCValue = blk: {
10709 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
10710 // The MCValue that holds the pointer can be re-used as the value.
10711 break :blk operand_ptr;
10712 } else {
10713 break :blk try self.allocRegOrMem(inst, true);
10714 }
10715 };
10716 const ptr_ty = self.typeOf(un_op);
10717 try self.load(operand, ptr_ty, operand_ptr);
10718
10719 const result = try self.isNonErr(inst, ptr_ty.childType(mod), operand);
10720
10851 const operand = try self.resolveInst(un_op);
10852 const ty = self.typeOf(un_op);
10853 const result = try self.isNonErrPtr(inst, ty, operand);
1072110854 return self.finishAir(inst, result, .{ un_op, .none, .none });
1072210855}
1072310856
......@@ -10810,7 +10943,7 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void {
1081010943 for (items, relocs, 0..) |item, *reloc, i| {
1081110944 const item_mcv = try self.resolveInst(item);
1081210945 try self.genBinOpMir(.{ ._, .cmp }, condition_ty, condition, item_mcv);
10813 reloc.* = try self.asmJccReloc(undefined, if (i < relocs.len - 1) .e else .ne);
10946 reloc.* = try self.asmJccReloc(if (i < relocs.len - 1) .e else .ne, undefined);
1081410947 }
1081510948
1081610949 for (liveness.deaths[case_i]) |operand| try self.processDeath(operand);
......@@ -11210,6 +11343,15 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1121011343 mnem_size = null;
1121111344 break :mnem std.meta.stringToEnum(Instruction.Mnemonic, mnem_str);
1121211345 } orelse return self.fail("invalid mnemonic: '{s}'", .{mnem_str});
11346 if (@as(?Memory.PtrSize, switch (mnem_tag) {
11347 .fldenv, .fnstenv, .fstenv => .none,
11348 .ldmxcsr, .stmxcsr, .vldmxcsr, .vstmxcsr => .dword,
11349 else => null,
11350 })) |fixed_mnem_size| {
11351 if (mnem_size) |size| if (size != fixed_mnem_size)
11352 return self.fail("invalid size: '{s}'", .{mnem_str});
11353 mnem_size = fixed_mnem_size;
11354 }
1121311355 const mnem_name = @tagName(mnem_tag);
1121411356 const mnem_fixed_tag: Mir.Inst.FixedTag = for (std.enums.values(Mir.Inst.Fixes)) |fixes| {
1121511357 const fixes_name = @tagName(fixes);
......@@ -11359,8 +11501,31 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1135911501 if (sib_it.next()) |_| return self.fail("invalid memory operand: '{s}'", .{op_str});
1136011502 op.* = .{ .mem = Memory.sib(mnem_size orelse
1136111503 return self.fail("unknown size: '{s}'", .{op_str}), .{
11362 .disp = if (open > 0) std.fmt.parseInt(i32, op_str[0..open], 0) catch
11363 return self.fail("invalid displacement: '{s}'", .{op_str}) else 0,
11504 .disp = if (mem.startsWith(u8, op_str[0..open], "%[") and
11505 mem.endsWith(u8, op_str[0..open], "]"))
11506 disp: {
11507 const colon = mem.indexOfScalarPos(u8, op_str[0..open], "%[".len, ':');
11508 const modifier = if (colon) |colon_pos|
11509 op_str[colon_pos + ":".len .. open - "]".len]
11510 else
11511 "";
11512 break :disp switch (args.items[
11513 arg_map.get(op_str["%[".len .. colon orelse open - "]".len]) orelse
11514 return self.fail("no matching constraint: '{s}'", .{op_str})
11515 ]) {
11516 .immediate => |imm| if (mem.eql(u8, modifier, "") or
11517 mem.eql(u8, modifier, "c"))
11518 math.cast(i32, @as(i64, @bitCast(imm))) orelse
11519 return self.fail("invalid displacement: '{s}'", .{op_str})
11520 else
11521 return self.fail("invalid modifier: '{s}'", .{modifier}),
11522 else => return self.fail("invalid constraint: '{s}'", .{op_str}),
11523 };
11524 } else if (open > 0)
11525 std.fmt.parseInt(i32, op_str[0..open], 0) catch
11526 return self.fail("invalid displacement: '{s}'", .{op_str})
11527 else
11528 0,
1136411529 .base = if (base_str.len > 0) .{ .reg = parseRegName(base_str["%%".len..]) orelse
1136511530 return self.fail("invalid base register: '{s}'", .{base_str}) } else .none,
1136611531 .scale_index = if (index_str.len > 0) .{
......@@ -11840,7 +12005,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1184012005 .reserved_frame,
1184112006 => unreachable,
1184212007 .undef => {},
11843 .eflags => |cc| try self.asmSetccRegister(dst_reg.to8(), cc),
12008 .eflags => |cc| try self.asmSetccRegister(cc, dst_reg.to8()),
1184412009 .immediate => |imm| {
1184512010 if (imm == 0) {
1184612011 // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit
......@@ -12110,7 +12275,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
1211012275 );
1211112276 },
1211212277 },
12113 .eflags => |cc| try self.asmSetccMemory(Memory.sib(.byte, .{ .base = base, .disp = disp }), cc),
12278 .eflags => |cc| try self.asmSetccMemory(cc, Memory.sib(.byte, .{ .base = base, .disp = disp })),
1211412279 .register => |src_reg| try (try self.moveStrategy(ty, switch (base) {
1211512280 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
1211612281 .reg => |reg| switch (reg) {
......@@ -12870,7 +13035,7 @@ fn atomicOp(
1287013035 ptr_mem,
1287113036 registerAlias(tmp_reg, val_abi_size),
1287213037 );
12873 _ = try self.asmJccReloc(loop, .ne);
13038 _ = try self.asmJccReloc(.ne, loop);
1287413039 return if (unused) .unreach else .{ .register = .rax };
1287513040 } else {
1287613041 try self.asmRegisterMemory(.{ ._, .mov }, .rax, Memory.sib(.qword, .{
......@@ -12932,7 +13097,7 @@ fn atomicOp(
1293213097 }),
1293313098 };
1293413099 try self.asmMemory(.{ .@"lock _16b", .cmpxchg }, ptr_mem);
12935 _ = try self.asmJccReloc(loop, .ne);
13100 _ = try self.asmJccReloc(.ne, loop);
1293613101
1293713102 if (unused) return .unreach;
1293813103 const dst_mcv = try self.allocTempRegOrMem(val_ty, false);
......@@ -13084,7 +13249,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1308413249
1308513250 try self.genSetReg(len_reg, Type.usize, len);
1308613251
13087 const skip_reloc = try self.asmJccReloc(undefined, .z);
13252 const skip_reloc = try self.asmJccReloc(.z, undefined);
1308813253 try self.store(slice_ptr_ty, ptr, src_val);
1308913254
1309013255 const second_elem_ptr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
......@@ -14041,7 +14206,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
1404114206 try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, Immediate.u(
1404214207 abi.SysV.c_abi_int_param_regs.len * 8,
1404314208 ));
14044 const mem_reloc = try self.asmJccReloc(undefined, .ae);
14209 const mem_reloc = try self.asmJccReloc(.ae, undefined);
1404514210
1404614211 try self.genSetReg(addr_reg, ptr_anyopaque_ty, reg_save_area);
1404714212 if (!unused)
......@@ -14080,7 +14245,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
1408014245 try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, Immediate.u(
1408114246 abi.SysV.c_abi_int_param_regs.len * 8 + abi.SysV.c_abi_sse_param_regs.len * 16,
1408214247 ));
14083 const mem_reloc = try self.asmJccReloc(undefined, .ae);
14248 const mem_reloc = try self.asmJccReloc(.ae, undefined);
1408414249
1408514250 try self.genSetReg(addr_reg, ptr_anyopaque_ty, reg_save_area);
1408614251 if (!unused)
src/arch/x86_64/Disassembler.zig+1-1
......@@ -38,7 +38,7 @@ pub fn next(dis: *Disassembler) Error!?Instruction {
3838
3939 const enc = try dis.parseEncoding(prefixes) orelse return error.UnknownOpcode;
4040 switch (enc.data.op_en) {
41 .np => return inst(enc, .{}),
41 .zo => return inst(enc, .{}),
4242 .d, .i => {
4343 const imm = try dis.parseImm(enc.data.ops[0]);
4444 return inst(enc, .{
src/arch/x86_64/Encoding.zig+13-8
......@@ -166,7 +166,7 @@ pub fn format(
166166 for (opc) |byte| try writer.print("{x:0>2} ", .{byte});
167167
168168 switch (encoding.data.op_en) {
169 .np, .fd, .td, .i, .zi, .d => {},
169 .zo, .fd, .td, .i, .zi, .d => {},
170170 .o, .oi => {
171171 const tag = switch (encoding.data.ops[0]) {
172172 .r8 => "rb",
......@@ -203,7 +203,7 @@ pub fn format(
203203 try writer.print("{s} ", .{tag});
204204 },
205205 .rvmr => try writer.writeAll("/is4 "),
206 .np, .fd, .td, .o, .m, .m1, .mc, .mr, .rm, .mrc, .rm0, .rvm, .mvr => {},
206 .zo, .fd, .td, .o, .m, .m1, .mc, .mr, .rm, .mrc, .rm0, .rvm, .mvr => {},
207207 }
208208
209209 try writer.print("{s} ", .{@tagName(encoding.mnemonic)});
......@@ -246,7 +246,7 @@ pub const Mnemonic = enum {
246246 movsx, movsxd, movzx, mul,
247247 neg, nop, not,
248248 @"or",
249 pause, pop, popcnt, push,
249 pause, pop, popcnt, popfq, push, pushfq,
250250 rcl, rcr, ret, rol, ror,
251251 sal, sar, sbb,
252252 scas, scasb, scasd, scasq, scasw,
......@@ -260,7 +260,7 @@ pub const Mnemonic = enum {
260260 ud2,
261261 xadd, xchg, xgetbv, xor,
262262 // X87
263 fabs, fchs, ffree, fisttp, fld, fst, fstp,
263 fabs, fchs, ffree, fisttp, fld, fldenv, fnstenv, fst, fstenv, fstp,
264264 // MMX
265265 movd, movq,
266266 packssdw, packsswb, packuswb,
......@@ -280,6 +280,7 @@ pub const Mnemonic = enum {
280280 cmpps, cmpss,
281281 cvtpi2ps, cvtps2pi, cvtsi2ss, cvtss2si, cvttps2pi, cvttss2si,
282282 divps, divss,
283 ldmxcsr,
283284 maxps, maxss,
284285 minps, minss,
285286 movaps, movhlps, movlhps,
......@@ -291,6 +292,7 @@ pub const Mnemonic = enum {
291292 pmaxsw, pmaxub, pminsw, pminub, pmovmskb,
292293 shufps,
293294 sqrtps, sqrtss,
295 stmxcsr,
294296 subps, subss,
295297 ucomiss,
296298 xorps,
......@@ -358,6 +360,7 @@ pub const Mnemonic = enum {
358360 vdivpd, vdivps, vdivsd, vdivss,
359361 vextractf128, vextractps,
360362 vinsertf128, vinsertps,
363 vldmxcsr,
361364 vmaxpd, vmaxps, vmaxsd, vmaxss,
362365 vminpd, vminps, vminsd, vminss,
363366 vmovapd, vmovaps,
......@@ -397,6 +400,7 @@ pub const Mnemonic = enum {
397400 vroundpd, vroundps, vroundsd, vroundss,
398401 vshufpd, vshufps,
399402 vsqrtpd, vsqrtps, vsqrtsd, vsqrtss,
403 vstmxcsr,
400404 vsubpd, vsubps, vsubsd, vsubss,
401405 vxorpd, vxorps,
402406 // F16C
......@@ -411,7 +415,7 @@ pub const Mnemonic = enum {
411415
412416pub const OpEn = enum {
413417 // zig fmt: off
414 np,
418 zo,
415419 o, oi,
416420 i, zi,
417421 d, m,
......@@ -481,6 +485,7 @@ pub const Op = enum {
481485 .mem => |mem| switch (mem) {
482486 .moffs => .moffs,
483487 .sib, .rip => switch (mem.bitSize()) {
488 0 => .m,
484489 8 => .m8,
485490 16 => .m16,
486491 32 => .m32,
......@@ -610,7 +615,7 @@ pub const Op = enum {
610615 .imm8s, .imm16s, .imm32s,
611616 .rel8, .rel16, .rel32,
612617 .unity,
613 => true,
618 => true,
614619 else => false,
615620 };
616621 // zig fmt: on
......@@ -626,7 +631,7 @@ pub const Op = enum {
626631 .mm_m64,
627632 .xmm_m32, .xmm_m64, .xmm_m128,
628633 .ymm_m256,
629 => true,
634 => true,
630635 else => false,
631636 };
632637 // zig fmt: on
......@@ -657,7 +662,7 @@ pub const Op = enum {
657662 /// Given an operand `op` checks if `target` is a subset for the purposes of the encoding.
658663 pub fn isSubset(op: Op, target: Op) bool {
659664 switch (op) {
660 .m, .o16, .o32, .o64 => unreachable,
665 .o16, .o32, .o64 => unreachable,
661666 .moffs, .sreg => return op == target,
662667 .none => switch (target) {
663668 .o16, .o32, .o64, .none => return true,
src/arch/x86_64/Mir.zig+20-1
......@@ -394,8 +394,12 @@ pub const Inst = struct {
394394 pop,
395395 /// Return the count of number of bits set to 1
396396 popcnt,
397 /// Pop stack into EFLAGS register
398 popfq,
397399 /// Push
398400 push,
401 /// Push EFLAGS register onto the stack
402 pushfq,
399403 /// Rotate left through carry
400404 /// Rotate right through carry
401405 rc,
......@@ -458,8 +462,14 @@ pub const Inst = struct {
458462 istt,
459463 /// Load floating-point value
460464 ld,
465 /// Load x87 FPU environment
466 ldenv,
467 /// Store x87 FPU environment
468 nstenv,
461469 /// Store floating-point value
462470 st,
471 /// Store x87 FPU environment
472 stenv,
463473
464474 /// Pack with signed saturation
465475 ackssw,
......@@ -505,6 +515,11 @@ pub const Inst = struct {
505515 /// Subtract packed unsigned integers with unsigned saturation
506516 subus,
507517
518 /// Load MXCSR register
519 ldmxcsr,
520 /// Store MXCSR register state
521 stmxcsr,
522
508523 /// Convert packed doubleword integers to packed single-precision floating-point values
509524 /// Convert packed doubleword integers to packed double-precision floating-point values
510525 cvtpi2,
......@@ -1079,9 +1094,13 @@ pub const RegisterList = struct {
10791094 return self.bitset.iterator(options);
10801095 }
10811096
1082 pub fn count(self: Self) u32 {
1097 pub fn count(self: Self) i32 {
10831098 return @intCast(self.bitset.count());
10841099 }
1100
1101 pub fn size(self: Self) i32 {
1102 return @intCast(self.bitset.count() * 8);
1103 }
10851104};
10861105
10871106pub const Imm32 = struct {
src/arch/x86_64/bits.zig+13
......@@ -470,6 +470,7 @@ pub const Memory = union(enum) {
470470 };
471471
472472 pub const PtrSize = enum {
473 none,
473474 byte,
474475 word,
475476 dword,
......@@ -508,6 +509,7 @@ pub const Memory = union(enum) {
508509
509510 pub fn bitSize(s: PtrSize) u64 {
510511 return switch (s) {
512 .none => 0,
511513 .byte => 8,
512514 .word => 16,
513515 .dword => 32,
......@@ -518,6 +520,17 @@ pub const Memory = union(enum) {
518520 .zword => 512,
519521 };
520522 }
523
524 pub fn format(
525 s: PtrSize,
526 comptime _: []const u8,
527 _: std.fmt.FormatOptions,
528 writer: anytype,
529 ) @TypeOf(writer).Error!void {
530 if (s == .none) return;
531 try writer.writeAll(@tagName(s));
532 try writer.writeAll(" ptr");
533 }
521534 };
522535
523536 pub const Sib = struct {
src/arch/x86_64/encoder.zig+6-6
......@@ -102,7 +102,7 @@ pub const Instruction = struct {
102102 .reg => |reg| try writer.writeAll(@tagName(reg)),
103103 .mem => |mem| switch (mem) {
104104 .rip => |rip| {
105 try writer.print("{s} ptr [rip", .{@tagName(rip.ptr_size)});
105 try writer.print("{} [rip", .{rip.ptr_size});
106106 if (rip.disp != 0) try writer.print(" {c} 0x{x}", .{
107107 @as(u8, if (rip.disp < 0) '-' else '+'),
108108 @abs(rip.disp),
......@@ -110,7 +110,7 @@ pub const Instruction = struct {
110110 try writer.writeByte(']');
111111 },
112112 .sib => |sib| {
113 try writer.print("{s} ptr ", .{@tagName(sib.ptr_size)});
113 try writer.print("{} ", .{sib.ptr_size});
114114
115115 if (mem.isSegmentRegister()) {
116116 return writer.print("{s}:0x{x}", .{ @tagName(sib.base.reg), sib.disp });
......@@ -222,7 +222,7 @@ pub const Instruction = struct {
222222 }
223223
224224 switch (data.op_en) {
225 .np, .o => {},
225 .zo, .o => {},
226226 .i, .d => try encodeImm(inst.ops[0].imm, data.ops[0], encoder),
227227 .zi, .oi => try encodeImm(inst.ops[1].imm, data.ops[1], encoder),
228228 .fd => try encoder.imm64(inst.ops[1].mem.moffs.offset),
......@@ -300,7 +300,7 @@ pub const Instruction = struct {
300300 }
301301
302302 const segment_override: ?Register = switch (op_en) {
303 .i, .zi, .o, .oi, .d, .np => null,
303 .zo, .i, .zi, .o, .oi, .d => null,
304304 .fd => inst.ops[1].mem.base().reg,
305305 .td => inst.ops[0].mem.base().reg,
306306 .rm, .rmi, .rm0 => if (inst.ops[1].isSegmentRegister())
......@@ -336,7 +336,7 @@ pub const Instruction = struct {
336336 rex.w = inst.encoding.data.mode == .long;
337337
338338 switch (op_en) {
339 .np, .i, .zi, .fd, .td, .d => {},
339 .zo, .i, .zi, .fd, .td, .d => {},
340340 .o, .oi => rex.b = inst.ops[0].reg.isExtended(),
341341 .m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc, .rm0 => {
342342 const r_op = switch (op_en) {
......@@ -370,7 +370,7 @@ pub const Instruction = struct {
370370 vex.w = inst.encoding.data.mode.isLong();
371371
372372 switch (op_en) {
373 .np, .i, .zi, .fd, .td, .d => {},
373 .zo, .i, .zi, .fd, .td, .d => {},
374374 .o, .oi => vex.b = inst.ops[0].reg.isExtended(),
375375 .m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc, .rm0, .vmi, .rvm, .rvmr, .rvmi, .mvr => {
376376 const r_op = switch (op_en) {
src/arch/x86_64/encodings.zig+76-60
......@@ -121,17 +121,16 @@ pub const table = [_]Entry{
121121 .{ .bts, .mi, &.{ .rm32, .imm8 }, &.{ 0x0f, 0xba }, 5, .none, .none },
122122 .{ .bts, .mi, &.{ .rm64, .imm8 }, &.{ 0x0f, 0xba }, 5, .long, .none },
123123
124 // This is M encoding according to Intel, but D makes more sense here.
125124 .{ .call, .d, &.{ .rel32 }, &.{ 0xe8 }, 0, .none, .none },
126125 .{ .call, .m, &.{ .rm64 }, &.{ 0xff }, 2, .none, .none },
127126
128 .{ .cbw, .np, &.{ .o16 }, &.{ 0x98 }, 0, .short, .none },
129 .{ .cwde, .np, &.{ .o32 }, &.{ 0x98 }, 0, .none, .none },
130 .{ .cdqe, .np, &.{ .o64 }, &.{ 0x98 }, 0, .long, .none },
127 .{ .cbw, .zo, &.{ .o16 }, &.{ 0x98 }, 0, .short, .none },
128 .{ .cwde, .zo, &.{ .o32 }, &.{ 0x98 }, 0, .none, .none },
129 .{ .cdqe, .zo, &.{ .o64 }, &.{ 0x98 }, 0, .long, .none },
131130
132 .{ .cwd, .np, &.{ .o16 }, &.{ 0x99 }, 0, .short, .none },
133 .{ .cdq, .np, &.{ .o32 }, &.{ 0x99 }, 0, .none, .none },
134 .{ .cqo, .np, &.{ .o64 }, &.{ 0x99 }, 0, .long, .none },
131 .{ .cwd, .zo, &.{ .o16 }, &.{ 0x99 }, 0, .short, .none },
132 .{ .cdq, .zo, &.{ .o32 }, &.{ 0x99 }, 0, .none, .none },
133 .{ .cqo, .zo, &.{ .o64 }, &.{ 0x99 }, 0, .long, .none },
135134
136135 .{ .cmova, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x47 }, 0, .short, .none },
137136 .{ .cmova, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x47 }, 0, .none, .none },
......@@ -247,15 +246,15 @@ pub const table = [_]Entry{
247246 .{ .cmp, .rm, &.{ .r32, .rm32 }, &.{ 0x3b }, 0, .none, .none },
248247 .{ .cmp, .rm, &.{ .r64, .rm64 }, &.{ 0x3b }, 0, .long, .none },
249248
250 .{ .cmps, .np, &.{ .m8, .m8 }, &.{ 0xa6 }, 0, .none, .none },
251 .{ .cmps, .np, &.{ .m16, .m16 }, &.{ 0xa7 }, 0, .short, .none },
252 .{ .cmps, .np, &.{ .m32, .m32 }, &.{ 0xa7 }, 0, .none, .none },
253 .{ .cmps, .np, &.{ .m64, .m64 }, &.{ 0xa7 }, 0, .long, .none },
249 .{ .cmps, .zo, &.{ .m8, .m8 }, &.{ 0xa6 }, 0, .none, .none },
250 .{ .cmps, .zo, &.{ .m16, .m16 }, &.{ 0xa7 }, 0, .short, .none },
251 .{ .cmps, .zo, &.{ .m32, .m32 }, &.{ 0xa7 }, 0, .none, .none },
252 .{ .cmps, .zo, &.{ .m64, .m64 }, &.{ 0xa7 }, 0, .long, .none },
254253
255 .{ .cmpsb, .np, &.{}, &.{ 0xa6 }, 0, .none, .none },
256 .{ .cmpsw, .np, &.{}, &.{ 0xa7 }, 0, .short, .none },
257 .{ .cmpsd, .np, &.{}, &.{ 0xa7 }, 0, .none, .none },
258 .{ .cmpsq, .np, &.{}, &.{ 0xa7 }, 0, .long, .none },
254 .{ .cmpsb, .zo, &.{}, &.{ 0xa6 }, 0, .none, .none },
255 .{ .cmpsw, .zo, &.{}, &.{ 0xa7 }, 0, .short, .none },
256 .{ .cmpsd, .zo, &.{}, &.{ 0xa7 }, 0, .none, .none },
257 .{ .cmpsq, .zo, &.{}, &.{ 0xa7 }, 0, .long, .none },
259258
260259 .{ .cmpxchg, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xb0 }, 0, .none, .none },
261260 .{ .cmpxchg, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xb0 }, 0, .rex, .none },
......@@ -266,7 +265,7 @@ pub const table = [_]Entry{
266265 .{ .cmpxchg8b, .m, &.{ .m64 }, &.{ 0x0f, 0xc7 }, 1, .none, .none },
267266 .{ .cmpxchg16b, .m, &.{ .m128 }, &.{ 0x0f, 0xc7 }, 1, .long, .none },
268267
269 .{ .cpuid, .np, &.{}, &.{ 0x0f, 0xa2 }, 0, .none, .none },
268 .{ .cpuid, .zo, &.{}, &.{ 0x0f, 0xa2 }, 0, .none, .none },
270269
271270 .{ .div, .m, &.{ .rm8 }, &.{ 0xf6 }, 6, .none, .none },
272271 .{ .div, .m, &.{ .rm8 }, &.{ 0xf6 }, 6, .rex, .none },
......@@ -295,7 +294,7 @@ pub const table = [_]Entry{
295294 .{ .imul, .rmi, &.{ .r32, .rm32, .imm32 }, &.{ 0x69 }, 0, .none, .none },
296295 .{ .imul, .rmi, &.{ .r64, .rm64, .imm32 }, &.{ 0x69 }, 0, .long, .none },
297296
298 .{ .int3, .np, &.{}, &.{ 0xcc }, 0, .none, .none },
297 .{ .int3, .zo, &.{}, &.{ 0xcc }, 0, .none, .none },
299298
300299 .{ .ja, .d, &.{ .rel32 }, &.{ 0x0f, 0x87 }, 0, .none, .none },
301300 .{ .jae, .d, &.{ .rel32 }, &.{ 0x0f, 0x83 }, 0, .none, .none },
......@@ -336,23 +335,23 @@ pub const table = [_]Entry{
336335 .{ .lea, .rm, &.{ .r32, .m }, &.{ 0x8d }, 0, .none, .none },
337336 .{ .lea, .rm, &.{ .r64, .m }, &.{ 0x8d }, 0, .long, .none },
338337
339 .{ .lfence, .np, &.{}, &.{ 0x0f, 0xae, 0xe8 }, 0, .none, .none },
338 .{ .lfence, .zo, &.{}, &.{ 0x0f, 0xae, 0xe8 }, 0, .none, .none },
340339
341 .{ .lods, .np, &.{ .m8 }, &.{ 0xac }, 0, .none, .none },
342 .{ .lods, .np, &.{ .m16 }, &.{ 0xad }, 0, .short, .none },
343 .{ .lods, .np, &.{ .m32 }, &.{ 0xad }, 0, .none, .none },
344 .{ .lods, .np, &.{ .m64 }, &.{ 0xad }, 0, .long, .none },
340 .{ .lods, .zo, &.{ .m8 }, &.{ 0xac }, 0, .none, .none },
341 .{ .lods, .zo, &.{ .m16 }, &.{ 0xad }, 0, .short, .none },
342 .{ .lods, .zo, &.{ .m32 }, &.{ 0xad }, 0, .none, .none },
343 .{ .lods, .zo, &.{ .m64 }, &.{ 0xad }, 0, .long, .none },
345344
346 .{ .lodsb, .np, &.{}, &.{ 0xac }, 0, .none, .none },
347 .{ .lodsw, .np, &.{}, &.{ 0xad }, 0, .short, .none },
348 .{ .lodsd, .np, &.{}, &.{ 0xad }, 0, .none, .none },
349 .{ .lodsq, .np, &.{}, &.{ 0xad }, 0, .long, .none },
345 .{ .lodsb, .zo, &.{}, &.{ 0xac }, 0, .none, .none },
346 .{ .lodsw, .zo, &.{}, &.{ 0xad }, 0, .short, .none },
347 .{ .lodsd, .zo, &.{}, &.{ 0xad }, 0, .none, .none },
348 .{ .lodsq, .zo, &.{}, &.{ 0xad }, 0, .long, .none },
350349
351350 .{ .lzcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .short, .lzcnt },
352351 .{ .lzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .none, .lzcnt },
353352 .{ .lzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .long, .lzcnt },
354353
355 .{ .mfence, .np, &.{}, &.{ 0x0f, 0xae, 0xf0 }, 0, .none, .none },
354 .{ .mfence, .zo, &.{}, &.{ 0x0f, 0xae, 0xf0 }, 0, .none, .none },
356355
357356 .{ .mov, .mr, &.{ .rm8, .r8 }, &.{ 0x88 }, 0, .none, .none },
358357 .{ .mov, .mr, &.{ .rm8, .r8 }, &.{ 0x88 }, 0, .rex, .none },
......@@ -396,15 +395,15 @@ pub const table = [_]Entry{
396395 .{ .movbe, .mr, &.{ .m32, .r32 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .none, .movbe },
397396 .{ .movbe, .mr, &.{ .m64, .r64 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .long, .movbe },
398397
399 .{ .movs, .np, &.{ .m8, .m8 }, &.{ 0xa4 }, 0, .none, .none },
400 .{ .movs, .np, &.{ .m16, .m16 }, &.{ 0xa5 }, 0, .short, .none },
401 .{ .movs, .np, &.{ .m32, .m32 }, &.{ 0xa5 }, 0, .none, .none },
402 .{ .movs, .np, &.{ .m64, .m64 }, &.{ 0xa5 }, 0, .long, .none },
398 .{ .movs, .zo, &.{ .m8, .m8 }, &.{ 0xa4 }, 0, .none, .none },
399 .{ .movs, .zo, &.{ .m16, .m16 }, &.{ 0xa5 }, 0, .short, .none },
400 .{ .movs, .zo, &.{ .m32, .m32 }, &.{ 0xa5 }, 0, .none, .none },
401 .{ .movs, .zo, &.{ .m64, .m64 }, &.{ 0xa5 }, 0, .long, .none },
403402
404 .{ .movsb, .np, &.{}, &.{ 0xa4 }, 0, .none, .none },
405 .{ .movsw, .np, &.{}, &.{ 0xa5 }, 0, .short, .none },
406 .{ .movsd, .np, &.{}, &.{ 0xa5 }, 0, .none, .none },
407 .{ .movsq, .np, &.{}, &.{ 0xa5 }, 0, .long, .none },
403 .{ .movsb, .zo, &.{}, &.{ 0xa4 }, 0, .none, .none },
404 .{ .movsw, .zo, &.{}, &.{ 0xa5 }, 0, .short, .none },
405 .{ .movsd, .zo, &.{}, &.{ 0xa5 }, 0, .none, .none },
406 .{ .movsq, .zo, &.{}, &.{ 0xa5 }, 0, .long, .none },
408407
409408 .{ .movsx, .rm, &.{ .r16, .rm8 }, &.{ 0x0f, 0xbe }, 0, .short, .none },
410409 .{ .movsx, .rm, &.{ .r16, .rm8 }, &.{ 0x0f, 0xbe }, 0, .rex_short, .none },
......@@ -440,7 +439,7 @@ pub const table = [_]Entry{
440439 .{ .neg, .m, &.{ .rm32 }, &.{ 0xf7 }, 3, .none, .none },
441440 .{ .neg, .m, &.{ .rm64 }, &.{ 0xf7 }, 3, .long, .none },
442441
443 .{ .nop, .np, &.{}, &.{ 0x90 }, 0, .none, .none },
442 .{ .nop, .zo, &.{}, &.{ 0x90 }, 0, .none, .none },
444443
445444 .{ .not, .m, &.{ .rm8 }, &.{ 0xf6 }, 2, .none, .none },
446445 .{ .not, .m, &.{ .rm8 }, &.{ 0xf6 }, 2, .rex, .none },
......@@ -471,7 +470,7 @@ pub const table = [_]Entry{
471470 .{ .@"or", .rm, &.{ .r32, .rm32 }, &.{ 0x0b }, 0, .none, .none },
472471 .{ .@"or", .rm, &.{ .r64, .rm64 }, &.{ 0x0b }, 0, .long, .none },
473472
474 .{ .pause, .np, &.{}, &.{ 0xf3, 0x90 }, 0, .none, .none },
473 .{ .pause, .zo, &.{}, &.{ 0xf3, 0x90 }, 0, .none, .none },
475474
476475 .{ .pop, .o, &.{ .r16 }, &.{ 0x58 }, 0, .short, .none },
477476 .{ .pop, .o, &.{ .r64 }, &.{ 0x58 }, 0, .none, .none },
......@@ -482,6 +481,8 @@ pub const table = [_]Entry{
482481 .{ .popcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none, .popcnt },
483482 .{ .popcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .long, .popcnt },
484483
484 .{ .popfq, .zo, &.{}, &.{ 0x9d }, 0, .none, .none },
485
485486 .{ .push, .o, &.{ .r16 }, &.{ 0x50 }, 0, .short, .none },
486487 .{ .push, .o, &.{ .r64 }, &.{ 0x50 }, 0, .none, .none },
487488 .{ .push, .m, &.{ .rm16 }, &.{ 0xff }, 6, .short, .none },
......@@ -490,7 +491,9 @@ pub const table = [_]Entry{
490491 .{ .push, .i, &.{ .imm16 }, &.{ 0x68 }, 0, .short, .none },
491492 .{ .push, .i, &.{ .imm32 }, &.{ 0x68 }, 0, .none, .none },
492493
493 .{ .ret, .np, &.{}, &.{ 0xc3 }, 0, .none, .none },
494 .{ .pushfq, .zo, &.{}, &.{ 0x9c }, 0, .none, .none },
495
496 .{ .ret, .zo, &.{}, &.{ 0xc3 }, 0, .none, .none },
494497
495498 .{ .rcl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 2, .none, .none },
496499 .{ .rcl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 2, .rex, .none },
......@@ -611,15 +614,15 @@ pub const table = [_]Entry{
611614 .{ .sbb, .rm, &.{ .r32, .rm32 }, &.{ 0x1b }, 0, .none, .none },
612615 .{ .sbb, .rm, &.{ .r64, .rm64 }, &.{ 0x1b }, 0, .long, .none },
613616
614 .{ .scas, .np, &.{ .m8 }, &.{ 0xae }, 0, .none, .none },
615 .{ .scas, .np, &.{ .m16 }, &.{ 0xaf }, 0, .short, .none },
616 .{ .scas, .np, &.{ .m32 }, &.{ 0xaf }, 0, .none, .none },
617 .{ .scas, .np, &.{ .m64 }, &.{ 0xaf }, 0, .long, .none },
617 .{ .scas, .zo, &.{ .m8 }, &.{ 0xae }, 0, .none, .none },
618 .{ .scas, .zo, &.{ .m16 }, &.{ 0xaf }, 0, .short, .none },
619 .{ .scas, .zo, &.{ .m32 }, &.{ 0xaf }, 0, .none, .none },
620 .{ .scas, .zo, &.{ .m64 }, &.{ 0xaf }, 0, .long, .none },
618621
619 .{ .scasb, .np, &.{}, &.{ 0xae }, 0, .none, .none },
620 .{ .scasw, .np, &.{}, &.{ 0xaf }, 0, .short, .none },
621 .{ .scasd, .np, &.{}, &.{ 0xaf }, 0, .none, .none },
622 .{ .scasq, .np, &.{}, &.{ 0xaf }, 0, .long, .none },
622 .{ .scasb, .zo, &.{}, &.{ 0xae }, 0, .none, .none },
623 .{ .scasw, .zo, &.{}, &.{ 0xaf }, 0, .short, .none },
624 .{ .scasd, .zo, &.{}, &.{ 0xaf }, 0, .none, .none },
625 .{ .scasq, .zo, &.{}, &.{ 0xaf }, 0, .long, .none },
623626
624627 .{ .seta, .m, &.{ .rm8 }, &.{ 0x0f, 0x97 }, 0, .none, .none },
625628 .{ .seta, .m, &.{ .rm8 }, &.{ 0x0f, 0x97 }, 0, .rex, .none },
......@@ -682,7 +685,7 @@ pub const table = [_]Entry{
682685 .{ .setz, .m, &.{ .rm8 }, &.{ 0x0f, 0x94 }, 0, .none, .none },
683686 .{ .setz, .m, &.{ .rm8 }, &.{ 0x0f, 0x94 }, 0, .rex, .none },
684687
685 .{ .sfence, .np, &.{}, &.{ 0x0f, 0xae, 0xf8 }, 0, .none, .none },
688 .{ .sfence, .zo, &.{}, &.{ 0x0f, 0xae, 0xf8 }, 0, .none, .none },
686689
687690 .{ .shl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .none, .none },
688691 .{ .shl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .rex, .none },
......@@ -730,15 +733,15 @@ pub const table = [_]Entry{
730733 .{ .shrd, .mrc, &.{ .rm32, .r32, .cl }, &.{ 0x0f, 0xad }, 0, .none, .none },
731734 .{ .shrd, .mrc, &.{ .rm64, .r64, .cl }, &.{ 0x0f, 0xad }, 0, .long, .none },
732735
733 .{ .stos, .np, &.{ .m8 }, &.{ 0xaa }, 0, .none, .none },
734 .{ .stos, .np, &.{ .m16 }, &.{ 0xab }, 0, .short, .none },
735 .{ .stos, .np, &.{ .m32 }, &.{ 0xab }, 0, .none, .none },
736 .{ .stos, .np, &.{ .m64 }, &.{ 0xab }, 0, .long, .none },
736 .{ .stos, .zo, &.{ .m8 }, &.{ 0xaa }, 0, .none, .none },
737 .{ .stos, .zo, &.{ .m16 }, &.{ 0xab }, 0, .short, .none },
738 .{ .stos, .zo, &.{ .m32 }, &.{ 0xab }, 0, .none, .none },
739 .{ .stos, .zo, &.{ .m64 }, &.{ 0xab }, 0, .long, .none },
737740
738 .{ .stosb, .np, &.{}, &.{ 0xaa }, 0, .none, .none },
739 .{ .stosw, .np, &.{}, &.{ 0xab }, 0, .short, .none },
740 .{ .stosd, .np, &.{}, &.{ 0xab }, 0, .none, .none },
741 .{ .stosq, .np, &.{}, &.{ 0xab }, 0, .long, .none },
741 .{ .stosb, .zo, &.{}, &.{ 0xaa }, 0, .none, .none },
742 .{ .stosw, .zo, &.{}, &.{ 0xab }, 0, .short, .none },
743 .{ .stosd, .zo, &.{}, &.{ 0xab }, 0, .none, .none },
744 .{ .stosq, .zo, &.{}, &.{ 0xab }, 0, .long, .none },
742745
743746 .{ .sub, .zi, &.{ .al, .imm8 }, &.{ 0x2c }, 0, .none, .none },
744747 .{ .sub, .zi, &.{ .ax, .imm16 }, &.{ 0x2d }, 0, .short, .none },
......@@ -763,7 +766,7 @@ pub const table = [_]Entry{
763766 .{ .sub, .rm, &.{ .r32, .rm32 }, &.{ 0x2b }, 0, .none, .none },
764767 .{ .sub, .rm, &.{ .r64, .rm64 }, &.{ 0x2b }, 0, .long, .none },
765768
766 .{ .syscall, .np, &.{}, &.{ 0x0f, 0x05 }, 0, .none, .none },
769 .{ .syscall, .zo, &.{}, &.{ 0x0f, 0x05 }, 0, .none, .none },
767770
768771 .{ .@"test", .zi, &.{ .al, .imm8 }, &.{ 0xa8 }, 0, .none, .none },
769772 .{ .@"test", .zi, &.{ .ax, .imm16 }, &.{ 0xa9 }, 0, .short, .none },
......@@ -784,7 +787,7 @@ pub const table = [_]Entry{
784787 .{ .tzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .none, .bmi },
785788 .{ .tzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .long, .bmi },
786789
787 .{ .ud2, .np, &.{}, &.{ 0x0f, 0x0b }, 0, .none, .none },
790 .{ .ud2, .zo, &.{}, &.{ 0x0f, 0x0b }, 0, .none, .none },
788791
789792 .{ .xadd, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xc0 }, 0, .none, .none },
790793 .{ .xadd, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xc0 }, 0, .rex, .none },
......@@ -809,7 +812,7 @@ pub const table = [_]Entry{
809812 .{ .xchg, .rm, &.{ .r32, .rm32 }, &.{ 0x87 }, 0, .none, .none },
810813 .{ .xchg, .rm, &.{ .r64, .rm64 }, &.{ 0x87 }, 0, .long, .none },
811814
812 .{ .xgetbv, .np, &.{}, &.{ 0x0f, 0x01 }, 0, .none, .none },
815 .{ .xgetbv, .zo, &.{}, &.{ 0x0f, 0x01, 0xd0 }, 0, .none, .none },
813816
814817 .{ .xor, .zi, &.{ .al, .imm8 }, &.{ 0x34 }, 0, .none, .none },
815818 .{ .xor, .zi, &.{ .ax, .imm16 }, &.{ 0x35 }, 0, .short, .none },
......@@ -835,9 +838,9 @@ pub const table = [_]Entry{
835838 .{ .xor, .rm, &.{ .r64, .rm64 }, &.{ 0x33 }, 0, .long, .none },
836839
837840 // X87
838 .{ .fabs, .np, &.{}, &.{ 0xd9, 0xe1 }, 0, .none, .x87 },
841 .{ .fabs, .zo, &.{}, &.{ 0xd9, 0xe1 }, 0, .none, .x87 },
839842
840 .{ .fchs, .np, &.{}, &.{ 0xd9, 0xe0 }, 0, .none, .x87 },
843 .{ .fchs, .zo, &.{}, &.{ 0xd9, 0xe0 }, 0, .none, .x87 },
841844
842845 .{ .ffree, .o, &.{ .st }, &.{ 0xdd, 0xc0 }, 0, .none, .x87 },
843846
......@@ -850,6 +853,8 @@ pub const table = [_]Entry{
850853 .{ .fld, .m, &.{ .m80 }, &.{ 0xdb }, 5, .none, .x87 },
851854 .{ .fld, .o, &.{ .st }, &.{ 0xd9, 0xc0 }, 0, .none, .x87 },
852855
856 .{ .fldenv, .m, &.{ .m }, &.{ 0xd9 }, 4, .none, .x87 },
857
853858 .{ .fst, .m, &.{ .m32 }, &.{ 0xd9 }, 2, .none, .x87 },
854859 .{ .fst, .m, &.{ .m64 }, &.{ 0xdd }, 2, .none, .x87 },
855860 .{ .fst, .o, &.{ .st }, &.{ 0xdd, 0xd0 }, 0, .none, .x87 },
......@@ -858,6 +863,9 @@ pub const table = [_]Entry{
858863 .{ .fstp, .m, &.{ .m80 }, &.{ 0xdb }, 7, .none, .x87 },
859864 .{ .fstp, .o, &.{ .st }, &.{ 0xdd, 0xd8 }, 0, .none, .x87 },
860865
866 .{ .fstenv, .m, &.{ .m }, &.{ 0x9b, 0xd9 }, 6, .none, .x87 },
867 .{ .fnstenv, .m, &.{ .m }, &.{ 0xd9 }, 6, .none, .x87 },
868
861869 // SSE
862870 .{ .addps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x58 }, 0, .none, .sse },
863871
......@@ -890,6 +898,8 @@ pub const table = [_]Entry{
890898
891899 .{ .divss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5e }, 0, .none, .sse },
892900
901 .{ .ldmxcsr, .m, &.{ .m32 }, &.{ 0x0f, 0xae }, 2, .none, .sse },
902
893903 .{ .maxps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5f }, 0, .none, .sse },
894904
895905 .{ .maxss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5f }, 0, .none, .sse },
......@@ -929,6 +939,8 @@ pub const table = [_]Entry{
929939
930940 .{ .sqrtss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x51 }, 0, .none, .sse },
931941
942 .{ .stmxcsr, .m, &.{ .m32 }, &.{ 0x0f, 0xae }, 3, .none, .sse },
943
932944 .{ .subps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5c }, 0, .none, .sse },
933945
934946 .{ .subss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5c }, 0, .none, .sse },
......@@ -1365,6 +1377,8 @@ pub const table = [_]Entry{
13651377
13661378 .{ .vinsertps, .rvmi, &.{ .xmm, .xmm, .xmm_m32, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x21 }, 0, .vex_128_wig, .avx },
13671379
1380 .{ .vldmxcsr, .m, &.{ .m32 }, &.{ 0x0f, 0xae }, 2, .vex_lz_wig, .avx },
1381
13681382 .{ .vmaxpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5f }, 0, .vex_128_wig, .avx },
13691383 .{ .vmaxpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5f }, 0, .vex_256_wig, .avx },
13701384
......@@ -1635,6 +1649,8 @@ pub const table = [_]Entry{
16351649
16361650 .{ .vsqrtss, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x51 }, 0, .vex_lig_wig, .avx },
16371651
1652 .{ .vstmxcsr, .m, &.{ .m32 }, &.{ 0x0f, 0xae }, 3, .vex_lz_wig, .avx },
1653
16381654 .{ .vsubpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5c }, 0, .vex_128_wig, .avx },
16391655 .{ .vsubpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5c }, 0, .vex_256_wig, .avx },
16401656
src/codegen.zig+7-1
......@@ -850,7 +850,7 @@ fn genDeclRef(
850850 bin_file: *link.File,
851851 src_loc: Module.SrcLoc,
852852 tv: TypedValue,
853 decl_index: Module.Decl.Index,
853 ptr_decl_index: Module.Decl.Index,
854854) CodeGenError!GenResult {
855855 const mod = bin_file.options.module.?;
856856 log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmt(mod), tv.val.fmtValue(tv.ty, mod) });
......@@ -859,6 +859,12 @@ fn genDeclRef(
859859 const ptr_bits = target.ptrBitWidth();
860860 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
861861
862 const ptr_decl = mod.declPtr(ptr_decl_index);
863 const decl_index = switch (mod.intern_pool.indexToKey(try ptr_decl.internValue(mod))) {
864 .func => |func| func.owner_decl,
865 .extern_func => |extern_func| extern_func.decl,
866 else => ptr_decl_index,
867 };
862868 const decl = mod.declPtr(decl_index);
863869
864870 if (!decl.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) {
src/link/Coff.zig+1-2
......@@ -1461,7 +1461,6 @@ pub fn updateDeclExports(
14611461 const decl = mod.declPtr(decl_index);
14621462 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
14631463 const atom = self.getAtom(atom_index);
1464 const decl_sym = atom.getSymbol(self);
14651464 const decl_metadata = self.decls.getPtr(decl_index).?;
14661465
14671466 for (exports) |exp| {
......@@ -1505,7 +1504,7 @@ pub fn updateDeclExports(
15051504 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
15061505 const sym = self.getSymbolPtr(sym_loc);
15071506 try self.setSymbolName(sym, mod.intern_pool.stringToSlice(exp.opts.name));
1508 sym.value = decl_sym.value;
1507 sym.value = atom.getSymbol(self).value;
15091508 sym.section_number = @as(coff.SectionNumber, @enumFromInt(self.text_section_index.? + 1));
15101509 sym.type = .{ .complex_type = .FUNCTION, .base_type = .NULL };
15111510
src/link/Elf.zig+91-23
......@@ -48,7 +48,7 @@ phdr_zig_load_zerofill_index: ?u16 = null,
4848/// PT_PHDR
4949phdr_table_index: ?u16 = null,
5050/// PT_LOAD for PHDR table
51/// We add this special load segment to ensure the PHDR table is always
51/// We add this special load segment to ensure the EHDR and PHDR table are always
5252/// loaded into memory.
5353phdr_table_load_index: ?u16 = null,
5454/// PT_INTERP
......@@ -289,22 +289,33 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
289289 .p64 => @alignOf(elf.Elf64_Phdr),
290290 };
291291 const image_base = self.calcImageBase();
292 const offset: u64 = switch (self.ptr_width) {
292 const ehsize: u64 = switch (self.ptr_width) {
293293 .p32 => @sizeOf(elf.Elf32_Ehdr),
294294 .p64 => @sizeOf(elf.Elf64_Ehdr),
295295 };
296 const phsize: u64 = switch (self.ptr_width) {
297 .p32 => @sizeOf(elf.Elf32_Phdr),
298 .p64 => @sizeOf(elf.Elf64_Phdr),
299 };
300 const max_nphdrs = comptime getMaxNumberOfPhdrs();
301 const reserved: u64 = mem.alignForward(u64, padToIdeal(max_nphdrs * phsize), self.page_size);
296302 self.phdr_table_index = try self.addPhdr(.{
297303 .type = elf.PT_PHDR,
298304 .flags = elf.PF_R,
299305 .@"align" = p_align,
300 .addr = image_base + offset,
301 .offset = offset,
306 .addr = image_base + ehsize,
307 .offset = ehsize,
308 .filesz = reserved,
309 .memsz = reserved,
302310 });
303311 self.phdr_table_load_index = try self.addPhdr(.{
304312 .type = elf.PT_LOAD,
305313 .flags = elf.PF_R,
306314 .@"align" = self.page_size,
307315 .addr = image_base,
316 .offset = 0,
317 .filesz = reserved + ehsize,
318 .memsz = reserved + ehsize,
308319 });
309320 }
310321
......@@ -543,7 +554,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {
543554 const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr);
544555 const tight_size = self.shdrs.items.len * shdr_size;
545556 const increased_size = padToIdeal(tight_size);
546 const test_end = off + increased_size;
557 const test_end = off +| increased_size;
547558 if (end > off and start < test_end) {
548559 return test_end;
549560 }
......@@ -552,7 +563,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {
552563 for (self.shdrs.items) |shdr| {
553564 if (shdr.sh_type == elf.SHT_NOBITS) continue;
554565 const increased_size = padToIdeal(shdr.sh_size);
555 const test_end = shdr.sh_offset + increased_size;
566 const test_end = shdr.sh_offset +| increased_size;
556567 if (end > shdr.sh_offset and start < test_end) {
557568 return test_end;
558569 }
......@@ -561,7 +572,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {
561572 for (self.phdrs.items) |phdr| {
562573 if (phdr.p_type != elf.PT_LOAD) continue;
563574 const increased_size = padToIdeal(phdr.p_filesz);
564 const test_end = phdr.p_offset + increased_size;
575 const test_end = phdr.p_offset +| increased_size;
565576 if (end > phdr.p_offset and start < test_end) {
566577 return test_end;
567578 }
......@@ -653,6 +664,7 @@ pub fn allocateAllocSection(self: *Elf, opts: AllocateAllocSectionOpts) error{Ou
653664 .type = opts.type,
654665 .flags = opts.flags,
655666 .addralign = opts.alignment,
667 .offset = std.math.maxInt(u64),
656668 });
657669 const shdr = &self.shdrs.items[index];
658670 try self.phdr_to_shdr_table.putNoClobber(gpa, index, opts.phdr_index);
......@@ -690,6 +702,7 @@ fn allocateNonAllocSection(self: *Elf, opts: AllocateNonAllocSectionOpts) error{
690702 .info = opts.info,
691703 .addralign = opts.alignment,
692704 .entsize = opts.entsize,
705 .offset = std.math.maxInt(u64),
693706 });
694707 const shdr = &self.shdrs.items[index];
695708 const off = self.findFreeSpace(opts.size, opts.alignment);
......@@ -706,6 +719,8 @@ pub fn initMetadata(self: *Elf) !void {
706719 const ptr_bit_width = self.base.options.target.ptrBitWidth();
707720 const is_linux = self.base.options.target.os.tag == .linux;
708721
722 comptime assert(number_of_zig_segments == 5);
723
709724 if (self.phdr_zig_load_re_index == null) {
710725 self.phdr_zig_load_re_index = try self.allocateSegment(.{
711726 .addr = if (ptr_bit_width >= 32) 0x8000000 else 0x8000,
......@@ -868,10 +883,10 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {
868883 const is_zerofill = shdr.sh_type == elf.SHT_NOBITS;
869884
870885 if (needed_size > self.allocatedSize(shdr.sh_offset) and !is_zerofill) {
871 // Must move the entire section.
872 const new_offset = self.findFreeSpace(needed_size, self.page_size);
873886 const existing_size = shdr.sh_size;
874887 shdr.sh_size = 0;
888 // Must move the entire section.
889 const new_offset = self.findFreeSpace(needed_size, self.page_size);
875890
876891 log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{
877892 self.shstrtab.getAssumeExists(shdr.sh_name),
......@@ -1600,7 +1615,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
16001615 try self.setVersionSymtab();
16011616 try self.updateSectionSizes();
16021617
1603 self.allocatePhdrTable();
1618 try self.allocatePhdrTable();
16041619 try self.allocateAllocSections();
16051620 try self.sortPhdrs();
16061621 try self.allocateNonAllocSections();
......@@ -3841,6 +3856,7 @@ fn initSections(self: *Elf) !void {
38413856 .type = elf.SHT_PROGBITS,
38423857 .flags = elf.SHF_ALLOC,
38433858 .addralign = ptr_size,
3859 .offset = std.math.maxInt(u64),
38443860 });
38453861
38463862 if (self.base.options.eh_frame_hdr) {
......@@ -3849,6 +3865,7 @@ fn initSections(self: *Elf) !void {
38493865 .type = elf.SHT_PROGBITS,
38503866 .flags = elf.SHF_ALLOC,
38513867 .addralign = 4,
3868 .offset = std.math.maxInt(u64),
38523869 });
38533870 }
38543871 }
......@@ -3859,6 +3876,7 @@ fn initSections(self: *Elf) !void {
38593876 .type = elf.SHT_PROGBITS,
38603877 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
38613878 .addralign = ptr_size,
3879 .offset = std.math.maxInt(u64),
38623880 });
38633881 }
38643882
......@@ -3880,6 +3898,7 @@ fn initSections(self: *Elf) !void {
38803898 .flags = elf.SHF_ALLOC,
38813899 .addralign = @alignOf(elf.Elf64_Rela),
38823900 .entsize = @sizeOf(elf.Elf64_Rela),
3901 .offset = std.math.maxInt(u64),
38833902 });
38843903 }
38853904
......@@ -3889,12 +3908,14 @@ fn initSections(self: *Elf) !void {
38893908 .type = elf.SHT_PROGBITS,
38903909 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
38913910 .addralign = 16,
3911 .offset = std.math.maxInt(u64),
38923912 });
38933913 self.got_plt_section_index = try self.addSection(.{
38943914 .name = ".got.plt",
38953915 .type = elf.SHT_PROGBITS,
38963916 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
38973917 .addralign = @alignOf(u64),
3918 .offset = std.math.maxInt(u64),
38983919 });
38993920 self.rela_plt_section_index = try self.addSection(.{
39003921 .name = ".rela.plt",
......@@ -3902,6 +3923,7 @@ fn initSections(self: *Elf) !void {
39023923 .flags = elf.SHF_ALLOC,
39033924 .addralign = @alignOf(elf.Elf64_Rela),
39043925 .entsize = @sizeOf(elf.Elf64_Rela),
3926 .offset = std.math.maxInt(u64),
39053927 });
39063928 }
39073929
......@@ -3911,6 +3933,7 @@ fn initSections(self: *Elf) !void {
39113933 .type = elf.SHT_PROGBITS,
39123934 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
39133935 .addralign = 16,
3936 .offset = std.math.maxInt(u64),
39143937 });
39153938 }
39163939
......@@ -3919,6 +3942,7 @@ fn initSections(self: *Elf) !void {
39193942 .name = ".copyrel",
39203943 .type = elf.SHT_NOBITS,
39213944 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
3945 .offset = std.math.maxInt(u64),
39223946 });
39233947 }
39243948
......@@ -3937,6 +3961,7 @@ fn initSections(self: *Elf) !void {
39373961 .type = elf.SHT_PROGBITS,
39383962 .flags = elf.SHF_ALLOC,
39393963 .addralign = 1,
3964 .offset = std.math.maxInt(u64),
39403965 });
39413966 }
39423967
......@@ -3947,6 +3972,7 @@ fn initSections(self: *Elf) !void {
39473972 .type = elf.SHT_STRTAB,
39483973 .entsize = 1,
39493974 .addralign = 1,
3975 .offset = std.math.maxInt(u64),
39503976 });
39513977 self.dynamic_section_index = try self.addSection(.{
39523978 .name = ".dynamic",
......@@ -3954,6 +3980,7 @@ fn initSections(self: *Elf) !void {
39543980 .type = elf.SHT_DYNAMIC,
39553981 .entsize = @sizeOf(elf.Elf64_Dyn),
39563982 .addralign = @alignOf(elf.Elf64_Dyn),
3983 .offset = std.math.maxInt(u64),
39573984 });
39583985 self.dynsymtab_section_index = try self.addSection(.{
39593986 .name = ".dynsym",
......@@ -3962,6 +3989,7 @@ fn initSections(self: *Elf) !void {
39623989 .addralign = @alignOf(elf.Elf64_Sym),
39633990 .entsize = @sizeOf(elf.Elf64_Sym),
39643991 .info = 1,
3992 .offset = std.math.maxInt(u64),
39653993 });
39663994 self.hash_section_index = try self.addSection(.{
39673995 .name = ".hash",
......@@ -3969,12 +3997,14 @@ fn initSections(self: *Elf) !void {
39693997 .type = elf.SHT_HASH,
39703998 .addralign = 4,
39713999 .entsize = 4,
4000 .offset = std.math.maxInt(u64),
39724001 });
39734002 self.gnu_hash_section_index = try self.addSection(.{
39744003 .name = ".gnu.hash",
39754004 .flags = elf.SHF_ALLOC,
39764005 .type = elf.SHT_GNU_HASH,
39774006 .addralign = 8,
4007 .offset = std.math.maxInt(u64),
39784008 });
39794009
39804010 const needs_versions = for (self.dynsym.entries.items) |entry| {
......@@ -3988,12 +4018,14 @@ fn initSections(self: *Elf) !void {
39884018 .type = elf.SHT_GNU_VERSYM,
39894019 .addralign = @alignOf(elf.Elf64_Versym),
39904020 .entsize = @sizeOf(elf.Elf64_Versym),
4021 .offset = std.math.maxInt(u64),
39914022 });
39924023 self.verneed_section_index = try self.addSection(.{
39934024 .name = ".gnu.version_r",
39944025 .flags = elf.SHF_ALLOC,
39954026 .type = elf.SHT_GNU_VERNEED,
39964027 .addralign = @alignOf(elf.Elf64_Verneed),
4028 .offset = std.math.maxInt(u64),
39974029 });
39984030 }
39994031 }
......@@ -4004,6 +4036,7 @@ fn initSections(self: *Elf) !void {
40044036 .type = elf.SHT_SYMTAB,
40054037 .addralign = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym),
40064038 .entsize = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym),
4039 .offset = std.math.maxInt(u64),
40074040 });
40084041 }
40094042 if (self.strtab_section_index == null) {
......@@ -4012,6 +4045,7 @@ fn initSections(self: *Elf) !void {
40124045 .type = elf.SHT_STRTAB,
40134046 .entsize = 1,
40144047 .addralign = 1,
4048 .offset = std.math.maxInt(u64),
40154049 });
40164050 }
40174051 if (self.shstrtab_section_index == null) {
......@@ -4020,11 +4054,14 @@ fn initSections(self: *Elf) !void {
40204054 .type = elf.SHT_STRTAB,
40214055 .entsize = 1,
40224056 .addralign = 1,
4057 .offset = std.math.maxInt(u64),
40234058 });
40244059 }
40254060}
40264061
40274062fn initSpecialPhdrs(self: *Elf) !void {
4063 comptime assert(max_number_of_special_phdrs == 5);
4064
40284065 if (self.interp_section_index != null) {
40294066 self.phdr_interp_index = try self.addPhdr(.{
40304067 .type = elf.PT_INTERP,
......@@ -4613,6 +4650,21 @@ fn shdrToPhdrFlags(sh_flags: u64) u32 {
46134650 return out_flags;
46144651}
46154652
4653/// Returns maximum number of program headers that may be emitted by the linker.
4654/// (This is an upper bound so that we can reserve enough space for the header and progam header
4655/// table without running out of space and being forced to move things around.)
4656fn getMaxNumberOfPhdrs() u64 {
4657 // First, assume we compile Zig's source incrementally, this gives us:
4658 var num: u64 = number_of_zig_segments;
4659 // Next, the estimated maximum number of segments the linker can emit for input sections are:
4660 num += max_number_of_object_segments;
4661 // Next, any other non-loadable program headers, including TLS, DYNAMIC, GNU_STACK, GNU_EH_FRAME, INTERP:
4662 num += max_number_of_special_phdrs;
4663 // Finally, PHDR program header and corresponding read-only load segment:
4664 num += 2;
4665 return num;
4666}
4667
46164668/// Calculates how many segments (PT_LOAD progam headers) are required
46174669/// to cover the set of sections.
46184670/// We permit a maximum of 3**2 number of segments.
......@@ -4633,30 +4685,36 @@ fn calcNumberOfSegments(self: *Elf) usize {
46334685}
46344686
46354687/// Allocates PHDR table in virtual memory and in file.
4636fn allocatePhdrTable(self: *Elf) void {
4688fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {
46374689 const new_load_segments = self.calcNumberOfSegments();
46384690 const phdr_table = &self.phdrs.items[self.phdr_table_index.?];
46394691 const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?];
46404692
4693 const ehsize: u64 = switch (self.ptr_width) {
4694 .p32 => @sizeOf(elf.Elf32_Ehdr),
4695 .p64 => @sizeOf(elf.Elf64_Ehdr),
4696 };
46414697 const phsize: u64 = switch (self.ptr_width) {
46424698 .p32 => @sizeOf(elf.Elf32_Phdr),
46434699 .p64 => @sizeOf(elf.Elf64_Phdr),
46444700 };
46454701 const needed_size = (self.phdrs.items.len + new_load_segments) * phsize;
4702 const available_space = self.allocatedSize(phdr_table.p_offset);
46464703
4647 if (needed_size > self.allocatedSize(phdr_table.p_offset)) {
4648 phdr_table.p_offset = 0;
4649 phdr_table.p_offset = self.findFreeSpace(needed_size, phdr_table.p_align);
4704 if (needed_size > available_space) {
4705 // In this case, we have two options:
4706 // 1. increase the available padding for EHDR + PHDR table so that we don't overflow it
4707 // (revisit getMaxNumberOfPhdrs())
4708 // 2. shift everything in file to free more space for EHDR + PHDR table
4709 // TODO verify `getMaxNumberOfPhdrs()` is accurate and convert this into no-op
4710 var err = try self.addErrorWithNotes(1);
4711 try err.addMsg(self, "fatal linker error: not enough space reserved for EHDR and PHDR table", .{});
4712 try err.addNote(self, "required 0x{x}, available 0x{x}", .{ needed_size, available_space });
46504713 }
46514714
4652 phdr_table_load.p_offset = mem.alignBackward(u64, phdr_table.p_offset, phdr_table_load.p_align);
4653 const load_align_offset = phdr_table.p_offset - phdr_table_load.p_offset;
4654 phdr_table_load.p_filesz = load_align_offset + needed_size;
4655 phdr_table_load.p_memsz = load_align_offset + needed_size;
4656
4715 phdr_table_load.p_filesz = needed_size + ehsize;
4716 phdr_table_load.p_memsz = needed_size + ehsize;
46574717 phdr_table.p_filesz = needed_size;
4658 phdr_table.p_vaddr = phdr_table_load.p_vaddr + load_align_offset;
4659 phdr_table.p_paddr = phdr_table_load.p_paddr + load_align_offset;
46604718 phdr_table.p_memsz = needed_size;
46614719}
46624720
......@@ -4701,7 +4759,7 @@ fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void {
47014759 // with `findFreeSpace` mechanics than anything else.
47024760 const Cover = std.ArrayList(u16);
47034761 const gpa = self.base.allocator;
4704 var covers: [9]Cover = undefined;
4762 var covers: [max_number_of_object_segments]Cover = undefined;
47054763 for (&covers) |*cover| {
47064764 cover.* = Cover.init(gpa);
47074765 }
......@@ -5651,6 +5709,7 @@ pub const AddSectionOpts = struct {
56515709 info: u32 = 0,
56525710 addralign: u64 = 0,
56535711 entsize: u64 = 0,
5712 offset: u64 = 0,
56545713};
56555714
56565715pub fn addSection(self: *Elf, opts: AddSectionOpts) !u16 {
......@@ -5662,7 +5721,7 @@ pub fn addSection(self: *Elf, opts: AddSectionOpts) !u16 {
56625721 .sh_type = opts.type,
56635722 .sh_flags = opts.flags,
56645723 .sh_addr = 0,
5665 .sh_offset = 0,
5724 .sh_offset = opts.offset,
56665725 .sh_size = 0,
56675726 .sh_link = opts.link,
56685727 .sh_info = opts.info,
......@@ -6231,6 +6290,15 @@ pub fn lsearch(comptime T: type, haystack: []align(1) const T, predicate: anytyp
62316290 return i;
62326291}
62336292
6293/// The following three values are only observed at compile-time and used to emit a compile error
6294/// to remind the programmer to update expected maximum numbers of different program header types
6295/// so that we reserve enough space for the program header table up-front.
6296/// Bump these numbers when adding or deleting a Zig specific pre-allocated segment, or adding
6297/// more special-purpose program headers.
6298const number_of_zig_segments = 5;
6299const max_number_of_object_segments = 9;
6300const max_number_of_special_phdrs = 5;
6301
62346302const default_entry_addr = 0x8000000;
62356303
62366304pub const base_tag: link.File.Tag = .elf;
test/behavior/math.zig+1-1
......@@ -670,11 +670,11 @@ fn should_not_be_zero(x: f128) !void {
670670
671671test "128-bit multiplication" {
672672 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
673 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
674673 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
675674 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
676675 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
677676 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
677 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
678678 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
679679
680680 {
test/tests.zig+1-1
......@@ -1006,7 +1006,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
10061006
10071007 // TODO get std lib tests passing for other self-hosted backends.
10081008 if ((test_target.target.getCpuArch() != .x86_64 or
1009 test_target.target.getObjectFormat() != .elf) and
1009 test_target.target.getOsTag() != .linux) and
10101010 test_target.use_llvm == false and mem.eql(u8, options.name, "std"))
10111011 continue;
10121012