| author | |
| committer | |
| log | cc394431ae6eb69e7abd677c268a8ab7299f8aeb |
| tree | d5aa705cdc7d701b53f32a8c2acc099c2dbd90c5 |
| parent | 10ea7accf76d4ad59222ea5ff3585d6cc7cfe3b0 |
| parent | ed00afbc4c1eec6d599ac277e364b4a1ed11fe5c |
| signature |
elf: allocated PHDR table always immediately succeeding the EHDR40 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 { |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | 44 | test "test_divmodti4" { |
| 45 | if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 46 | ||
| 47 | 45 | const cases = [_][4]i128{ |
| 48 | 46 | [_]i128{ 0, 1, 0, 0 }, |
| 49 | 47 | [_]i128{ 0, -1, 0, 0 }, |
lib/std/Thread/Condition.zig+2| ... | ... | @@ -371,6 +371,8 @@ test "Condition - signal" { |
| 371 | 371 | return error.SkipZigTest; |
| 372 | 372 | } |
| 373 | 373 | |
| 374 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 375 | ||
| 374 | 376 | const num_threads = 4; |
| 375 | 377 | |
| 376 | 378 | const SignalTest = struct { |
lib/std/Uri.zig-2| ... | ... | @@ -735,8 +735,6 @@ test "Special test" { |
| 735 | 735 | } |
| 736 | 736 | |
| 737 | 737 | test "URI escaping" { |
| 738 | if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 739 | ||
| 740 | 738 | const input = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad"; |
| 741 | 739 | const expected = "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad"; |
| 742 | 740 |
lib/std/builtin.zig+8-1| ... | ... | @@ -738,8 +738,8 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr |
| 738 | 738 | if (builtin.zig_backend == .stage2_wasm or |
| 739 | 739 | builtin.zig_backend == .stage2_arm or |
| 740 | 740 | builtin.zig_backend == .stage2_aarch64 or |
| 741 | builtin.zig_backend == .stage2_x86_64 or | |
| 742 | 741 | builtin.zig_backend == .stage2_x86 or |
| 742 | (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) or | |
| 743 | 743 | builtin.zig_backend == .stage2_riscv64 or |
| 744 | 744 | builtin.zig_backend == .stage2_sparc64 or |
| 745 | 745 | builtin.zig_backend == .stage2_spirv64) |
| ... | ... | @@ -808,6 +808,13 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr |
| 808 | 808 | std.os.abort(); |
| 809 | 809 | }, |
| 810 | 810 | .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 | }, | |
| 811 | 818 | else => { |
| 812 | 819 | const first_trace_addr = ret_addr orelse @returnAddress(); |
| 813 | 820 | 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 { |
| 23 | 23 | } |
| 24 | 24 | |
| 25 | 25 | test "LZMA: decompress empty world" { |
| 26 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 27 | ||
| 28 | 26 | try testDecompressEqual( |
| 29 | 27 | "", |
| 30 | 28 | &[_]u8{ |
| ... | ... | @@ -88,8 +86,6 @@ test "LZMA: known size with end of payload marker" { |
| 88 | 86 | } |
| 89 | 87 | |
| 90 | 88 | test "LZMA: too big uncompressed size in header" { |
| 91 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 92 | ||
| 93 | 89 | try testDecompressError( |
| 94 | 90 | error.CorruptInput, |
| 95 | 91 | @embedFile("testdata/bad-too_big_size-with_eopm.lzma"), |
| ... | ... | @@ -97,8 +93,6 @@ test "LZMA: too big uncompressed size in header" { |
| 97 | 93 | } |
| 98 | 94 | |
| 99 | 95 | test "LZMA: too small uncompressed size in header" { |
| 100 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 101 | ||
| 102 | 96 | try testDecompressError( |
| 103 | 97 | error.CorruptInput, |
| 104 | 98 | @embedFile("testdata/bad-too_small_size-without_eopm-3.lzma"), |
lib/std/crypto/25519/curve25519.zig-5| ... | ... | @@ -1,5 +1,4 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 3 | 2 | const crypto = std.crypto; |
| 4 | 3 | |
| 5 | 4 | const IdentityElementError = crypto.errors.IdentityElementError; |
| ... | ... | @@ -112,8 +111,6 @@ pub const Curve25519 = struct { |
| 112 | 111 | }; |
| 113 | 112 | |
| 114 | 113 | test "curve25519" { |
| 115 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 116 | ||
| 117 | 114 | 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 }; |
| 118 | 115 | const p = try Curve25519.basePoint.clampedMul(s); |
| 119 | 116 | try p.rejectIdentity(); |
| ... | ... | @@ -128,8 +125,6 @@ test "curve25519" { |
| 128 | 125 | } |
| 129 | 126 | |
| 130 | 127 | test "curve25519 small order check" { |
| 131 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 132 | ||
| 133 | 128 | var s: [32]u8 = [_]u8{1} ++ [_]u8{0} ** 31; |
| 134 | 129 | const small_order_ss: [7][32]u8 = .{ |
| 135 | 130 | .{ |
lib/std/crypto/25519/ed25519.zig-2| ... | ... | @@ -484,8 +484,6 @@ pub const Ed25519 = struct { |
| 484 | 484 | }; |
| 485 | 485 | |
| 486 | 486 | test "ed25519 key pair creation" { |
| 487 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 488 | ||
| 489 | 487 | var seed: [32]u8 = undefined; |
| 490 | 488 | _ = try fmt.hexToBytes(seed[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166"); |
| 491 | 489 | const key_pair = try Ed25519.KeyPair.create(seed); |
lib/std/crypto/25519/edwards25519.zig-11| ... | ... | @@ -1,5 +1,4 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 3 | 2 | const crypto = std.crypto; |
| 4 | 3 | const debug = std.debug; |
| 5 | 4 | const fmt = std.fmt; |
| ... | ... | @@ -495,8 +494,6 @@ pub const Edwards25519 = struct { |
| 495 | 494 | const htest = @import("../test.zig"); |
| 496 | 495 | |
| 497 | 496 | test "edwards25519 packing/unpacking" { |
| 498 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 499 | ||
| 500 | 497 | const s = [_]u8{170} ++ [_]u8{0} ** 31; |
| 501 | 498 | var b = Edwards25519.basePoint; |
| 502 | 499 | const pk = try b.mul(s); |
| ... | ... | @@ -533,8 +530,6 @@ test "edwards25519 packing/unpacking" { |
| 533 | 530 | } |
| 534 | 531 | |
| 535 | 532 | test "edwards25519 point addition/subtraction" { |
| 536 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 537 | ||
| 538 | 533 | var s1: [32]u8 = undefined; |
| 539 | 534 | var s2: [32]u8 = undefined; |
| 540 | 535 | crypto.random.bytes(&s1); |
| ... | ... | @@ -549,8 +544,6 @@ test "edwards25519 point addition/subtraction" { |
| 549 | 544 | } |
| 550 | 545 | |
| 551 | 546 | test "edwards25519 uniform-to-point" { |
| 552 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 553 | ||
| 554 | 547 | 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 }; |
| 555 | 548 | var p = Edwards25519.fromUniform(r); |
| 556 | 549 | try htest.assertEqual("0691eee3cf70a0056df6bfa03120635636581b5c4ea571dfc680f78c7e0b4137", p.toBytes()[0..]); |
| ... | ... | @@ -562,8 +555,6 @@ test "edwards25519 uniform-to-point" { |
| 562 | 555 | |
| 563 | 556 | // Test vectors from draft-irtf-cfrg-hash-to-curve-12 |
| 564 | 557 | test "edwards25519 hash-to-curve operation" { |
| 565 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 566 | ||
| 567 | 558 | var p = Edwards25519.fromString(true, "QUUX-V01-CS02-with-edwards25519_XMD:SHA-512_ELL2_RO_", "abc"); |
| 568 | 559 | try htest.assertEqual("31558a26887f23fb8218f143e69d5f0af2e7831130bd5b432ef23883b895839a", p.toBytes()[0..]); |
| 569 | 560 | |
| ... | ... | @@ -572,8 +563,6 @@ test "edwards25519 hash-to-curve operation" { |
| 572 | 563 | } |
| 573 | 564 | |
| 574 | 565 | test "edwards25519 implicit reduction of invalid scalars" { |
| 575 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 576 | ||
| 577 | 566 | const s = [_]u8{0} ** 31 ++ [_]u8{255}; |
| 578 | 567 | const p1 = try Edwards25519.basePoint.mulPublic(s); |
| 579 | 568 | const p2 = try Edwards25519.basePoint.mul(s); |
lib/std/crypto/25519/ristretto255.zig-2| ... | ... | @@ -168,8 +168,6 @@ pub const Ristretto255 = struct { |
| 168 | 168 | }; |
| 169 | 169 | |
| 170 | 170 | test "ristretto255" { |
| 171 | if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 172 | ||
| 173 | 171 | const p = Ristretto255.basePoint; |
| 174 | 172 | var buf: [256]u8 = undefined; |
| 175 | 173 | 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 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 3 | 2 | const crypto = std.crypto; |
| 4 | 3 | const mem = std.mem; |
| 5 | 4 | const fmt = std.fmt; |
| ... | ... | @@ -83,8 +82,6 @@ pub const X25519 = struct { |
| 83 | 82 | const htest = @import("../test.zig"); |
| 84 | 83 | |
| 85 | 84 | test "x25519 public key calculation from secret key" { |
| 86 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 87 | ||
| 88 | 85 | var sk: [32]u8 = undefined; |
| 89 | 86 | var pk_expected: [32]u8 = undefined; |
| 90 | 87 | _ = try fmt.hexToBytes(sk[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166"); |
| ... | ... | @@ -94,8 +91,6 @@ test "x25519 public key calculation from secret key" { |
| 94 | 91 | } |
| 95 | 92 | |
| 96 | 93 | test "x25519 rfc7748 vector1" { |
| 97 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 98 | ||
| 99 | 94 | 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 }; |
| 100 | 95 | 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 }; |
| 101 | 96 | |
| ... | ... | @@ -106,8 +101,6 @@ test "x25519 rfc7748 vector1" { |
| 106 | 101 | } |
| 107 | 102 | |
| 108 | 103 | test "x25519 rfc7748 vector2" { |
| 109 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 110 | ||
| 111 | 104 | 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 }; |
| 112 | 105 | 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 }; |
| 113 | 106 | |
| ... | ... | @@ -118,8 +111,6 @@ test "x25519 rfc7748 vector2" { |
| 118 | 111 | } |
| 119 | 112 | |
| 120 | 113 | test "x25519 rfc7748 one iteration" { |
| 121 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 122 | ||
| 123 | 114 | 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 }; |
| 124 | 115 | 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 }; |
| 125 | 116 | |
| ... | ... | @@ -180,8 +171,6 @@ test "x25519 rfc7748 1,000,000 iterations" { |
| 180 | 171 | } |
| 181 | 172 | |
| 182 | 173 | test "edwards25519 -> curve25519 map" { |
| 183 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 184 | ||
| 185 | 174 | const ed_kp = try crypto.sign.Ed25519.KeyPair.create([_]u8{0x42} ** 32); |
| 186 | 175 | const mont_kp = try X25519.KeyPair.fromEd25519(ed_kp); |
| 187 | 176 | try htest.assertEqual("90e7595fc89e52fdfddce9c6a43d74dbf6047025ee0462d2d172e8b6a2841d6e", &mont_kp.secret_key); |
lib/std/crypto/chacha20.zig-10| ... | ... | @@ -821,8 +821,6 @@ test "crypto.chacha20 test vector sunscreen" { |
| 821 | 821 | |
| 822 | 822 | // https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7 |
| 823 | 823 | test "crypto.chacha20 test vector 1" { |
| 824 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 825 | ||
| 826 | 824 | const expected_result = [_]u8{ |
| 827 | 825 | 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, |
| 828 | 826 | 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, |
| ... | ... | @@ -857,8 +855,6 @@ test "crypto.chacha20 test vector 1" { |
| 857 | 855 | } |
| 858 | 856 | |
| 859 | 857 | test "crypto.chacha20 test vector 2" { |
| 860 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 861 | ||
| 862 | 858 | const expected_result = [_]u8{ |
| 863 | 859 | 0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96, |
| 864 | 860 | 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96, |
| ... | ... | @@ -893,8 +889,6 @@ test "crypto.chacha20 test vector 2" { |
| 893 | 889 | } |
| 894 | 890 | |
| 895 | 891 | test "crypto.chacha20 test vector 3" { |
| 896 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 897 | ||
| 898 | 892 | const expected_result = [_]u8{ |
| 899 | 893 | 0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5, |
| 900 | 894 | 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a, |
| ... | ... | @@ -929,8 +923,6 @@ test "crypto.chacha20 test vector 3" { |
| 929 | 923 | } |
| 930 | 924 | |
| 931 | 925 | test "crypto.chacha20 test vector 4" { |
| 932 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 933 | ||
| 934 | 926 | const expected_result = [_]u8{ |
| 935 | 927 | 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb, |
| 936 | 928 | 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80, |
| ... | ... | @@ -965,8 +957,6 @@ test "crypto.chacha20 test vector 4" { |
| 965 | 957 | } |
| 966 | 958 | |
| 967 | 959 | test "crypto.chacha20 test vector 5" { |
| 968 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 969 | ||
| 970 | 960 | const expected_result = [_]u8{ |
| 971 | 961 | 0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69, |
| 972 | 962 | 0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75, |
lib/std/crypto/salsa20.zig-4| ... | ... | @@ -598,8 +598,6 @@ test "xsalsa20poly1305 secretbox" { |
| 598 | 598 | } |
| 599 | 599 | |
| 600 | 600 | test "xsalsa20poly1305 box" { |
| 601 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 602 | ||
| 603 | 601 | var msg: [100]u8 = undefined; |
| 604 | 602 | var msg2: [msg.len]u8 = undefined; |
| 605 | 603 | var nonce: [Box.nonce_length]u8 = undefined; |
| ... | ... | @@ -614,8 +612,6 @@ test "xsalsa20poly1305 box" { |
| 614 | 612 | } |
| 615 | 613 | |
| 616 | 614 | test "xsalsa20poly1305 sealedbox" { |
| 617 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 618 | ||
| 619 | 615 | var msg: [100]u8 = undefined; |
| 620 | 616 | var msg2: [msg.len]u8 = undefined; |
| 621 | 617 | var boxed: [msg.len + SealedBox.seal_length]u8 = undefined; |
lib/std/debug.zig+1-1| ... | ... | @@ -671,8 +671,8 @@ pub const StackIterator = struct { |
| 671 | 671 | if (self.unwind_state) |*unwind_state| { |
| 672 | 672 | if (!unwind_state.failed) { |
| 673 | 673 | if (unwind_state.dwarf_context.pc == 0) return null; |
| 674 | defer self.fp = unwind_state.dwarf_context.getFp() catch 0; | |
| 674 | 675 | if (self.next_unwind()) |return_address| { |
| 675 | self.fp = unwind_state.dwarf_context.getFp() catch 0; | |
| 676 | 676 | return return_address; |
| 677 | 677 | } else |err| { |
| 678 | 678 | unwind_state.last_error = err; |
lib/std/fmt.zig-18| ... | ... | @@ -2129,8 +2129,6 @@ test "int.small" { |
| 2129 | 2129 | } |
| 2130 | 2130 | |
| 2131 | 2131 | test "int.specifier" { |
| 2132 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 2133 | ||
| 2134 | 2132 | { |
| 2135 | 2133 | const value: u8 = 'a'; |
| 2136 | 2134 | try expectFmt("u8: a\n", "u8: {c}\n", .{value}); |
| ... | ... | @@ -2181,8 +2179,6 @@ test "int.padded" { |
| 2181 | 2179 | } |
| 2182 | 2180 | |
| 2183 | 2181 | test "buffer" { |
| 2184 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 2185 | ||
| 2186 | 2182 | { |
| 2187 | 2183 | var buf1: [32]u8 = undefined; |
| 2188 | 2184 | var fbs = std.io.fixedBufferStream(&buf1); |
| ... | ... | @@ -2379,8 +2375,6 @@ test "float.scientific" { |
| 2379 | 2375 | } |
| 2380 | 2376 | |
| 2381 | 2377 | test "float.scientific.precision" { |
| 2382 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 2383 | ||
| 2384 | 2378 | try expectFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)}); |
| 2385 | 2379 | try expectFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @as(f32, @bitCast(@as(u32, 814313563))))}); |
| 2386 | 2380 | 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" { |
| 2457 | 2451 | } |
| 2458 | 2452 | |
| 2459 | 2453 | test "float.decimal" { |
| 2460 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 2461 | ||
| 2462 | 2454 | try expectFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)}); |
| 2463 | 2455 | try expectFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)}); |
| 2464 | 2456 | try expectFmt("f32: 0", "f32: {d:.0}", .{@as(f32, 0.0)}); |
| ... | ... | @@ -2482,8 +2474,6 @@ test "float.decimal" { |
| 2482 | 2474 | } |
| 2483 | 2475 | |
| 2484 | 2476 | test "float.libc.sanity" { |
| 2485 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 2486 | ||
| 2487 | 2477 | try expectFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @as(f32, @bitCast(@as(u32, 916964781))))}); |
| 2488 | 2478 | try expectFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @as(f32, @bitCast(@as(u32, 925353389))))}); |
| 2489 | 2479 | try expectFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @as(f32, @bitCast(@as(u32, 1036831278))))}); |
| ... | ... | @@ -2503,8 +2493,6 @@ test "float.libc.sanity" { |
| 2503 | 2493 | } |
| 2504 | 2494 | |
| 2505 | 2495 | test "custom" { |
| 2506 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 2507 | ||
| 2508 | 2496 | const Vec2 = struct { |
| 2509 | 2497 | const SelfType = @This(); |
| 2510 | 2498 | x: f32, |
| ... | ... | @@ -2683,8 +2671,6 @@ test "formatFloatValue with comptime_float" { |
| 2683 | 2671 | } |
| 2684 | 2672 | |
| 2685 | 2673 | test "formatType max_depth" { |
| 2686 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 2687 | ||
| 2688 | 2674 | const Vec2 = struct { |
| 2689 | 2675 | const SelfType = @This(); |
| 2690 | 2676 | x: f32, |
| ... | ... | @@ -2759,14 +2745,10 @@ test "positional" { |
| 2759 | 2745 | } |
| 2760 | 2746 | |
| 2761 | 2747 | test "positional with specifier" { |
| 2762 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 2763 | ||
| 2764 | 2748 | try expectFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)}); |
| 2765 | 2749 | } |
| 2766 | 2750 | |
| 2767 | 2751 | test "positional/alignment/width/precision" { |
| 2768 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 2769 | ||
| 2770 | 2752 | try expectFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)}); |
| 2771 | 2753 | } |
| 2772 | 2754 |
lib/std/fmt/parse_float.zig-4| ... | ... | @@ -84,8 +84,6 @@ test "fmt.parseFloat nan and inf" { |
| 84 | 84 | } |
| 85 | 85 | |
| 86 | 86 | test "fmt.parseFloat #11169" { |
| 87 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 88 | ||
| 89 | 87 | try expectEqual(try parseFloat(f128, "9007199254740993.0"), 9007199254740993.0); |
| 90 | 88 | } |
| 91 | 89 | |
| ... | ... | @@ -162,8 +160,6 @@ test "fmt.parseFloat hex.f64" { |
| 162 | 160 | try testing.expectEqual(try parseFloat(f64, "-0x1p-1074"), -math.floatTrueMin(f64)); |
| 163 | 161 | } |
| 164 | 162 | test "fmt.parseFloat hex.f128" { |
| 165 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 166 | ||
| 167 | 163 | try testing.expectEqual(try parseFloat(f128, "0x1p0"), 1.0); |
| 168 | 164 | try testing.expectEqual(try parseFloat(f128, "-0x1p-1"), -0.5); |
| 169 | 165 | try testing.expectEqual(try parseFloat(f128, "0x10p+10"), 16384.0); |
lib/std/fs/test.zig-4| ... | ... | @@ -1604,8 +1604,6 @@ test "File.Permissions" { |
| 1604 | 1604 | if (builtin.os.tag == .wasi) |
| 1605 | 1605 | return error.SkipZigTest; |
| 1606 | 1606 | |
| 1607 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 1608 | ||
| 1609 | 1607 | var tmp = tmpDir(.{}); |
| 1610 | 1608 | defer tmp.cleanup(); |
| 1611 | 1609 | |
| ... | ... | @@ -1632,8 +1630,6 @@ test "File.PermissionsUnix" { |
| 1632 | 1630 | if (builtin.os.tag == .windows or builtin.os.tag == .wasi) |
| 1633 | 1631 | return error.SkipZigTest; |
| 1634 | 1632 | |
| 1635 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 1636 | ||
| 1637 | 1633 | var tmp = tmpDir(.{}); |
| 1638 | 1634 | defer tmp.cleanup(); |
| 1639 | 1635 |
lib/std/json.zig-4| ... | ... | @@ -24,8 +24,6 @@ test Scanner { |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | 26 | test parseFromSlice { |
| 27 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 28 | ||
| 29 | 27 | var parsed_str = try parseFromSlice([]const u8, testing.allocator, "\"a\\u0020b\"", .{}); |
| 30 | 28 | defer parsed_str.deinit(); |
| 31 | 29 | try testing.expectEqualSlices(u8, "a b", parsed_str.value); |
| ... | ... | @@ -44,8 +42,6 @@ test Value { |
| 44 | 42 | } |
| 45 | 43 | |
| 46 | 44 | test writeStream { |
| 47 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 48 | ||
| 49 | 45 | var out = ArrayList(u8).init(testing.allocator); |
| 50 | 46 | defer out.deinit(); |
| 51 | 47 | var write_stream = writeStream(out.writer(), .{ .whitespace = .indent_2 }); |
lib/std/json/static_test.zig-40| ... | ... | @@ -372,8 +372,6 @@ test "test all types" { |
| 372 | 372 | } |
| 373 | 373 | |
| 374 | 374 | test "parse" { |
| 375 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 376 | ||
| 377 | 375 | try testing.expectEqual(false, try parseFromSliceLeaky(bool, testing.allocator, "false", .{})); |
| 378 | 376 | try testing.expectEqual(true, try parseFromSliceLeaky(bool, testing.allocator, "true", .{})); |
| 379 | 377 | try testing.expectEqual(@as(u1, 1), try parseFromSliceLeaky(u1, testing.allocator, "1", .{})); |
| ... | ... | @@ -405,8 +403,6 @@ test "parse into enum" { |
| 405 | 403 | } |
| 406 | 404 | |
| 407 | 405 | test "parse into that allocates a slice" { |
| 408 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 409 | ||
| 410 | 406 | { |
| 411 | 407 | // string as string |
| 412 | 408 | const parsed = try parseFromSlice([]u8, testing.allocator, "\"foo\"", .{}); |
| ... | ... | @@ -427,16 +423,12 @@ test "parse into that allocates a slice" { |
| 427 | 423 | } |
| 428 | 424 | |
| 429 | 425 | test "parse into sentinel slice" { |
| 430 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 431 | ||
| 432 | 426 | const parsed = try parseFromSlice([:0]const u8, testing.allocator, "\"\\n\"", .{}); |
| 433 | 427 | defer parsed.deinit(); |
| 434 | 428 | try testing.expect(std.mem.eql(u8, parsed.value, "\n")); |
| 435 | 429 | } |
| 436 | 430 | |
| 437 | 431 | test "parse into tagged union" { |
| 438 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 439 | ||
| 440 | 432 | const T = union(enum) { |
| 441 | 433 | nothing, |
| 442 | 434 | int: i32, |
| ... | ... | @@ -452,8 +444,6 @@ test "parse into tagged union" { |
| 452 | 444 | } |
| 453 | 445 | |
| 454 | 446 | test "parse into tagged union errors" { |
| 455 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 456 | ||
| 457 | 447 | const T = union(enum) { |
| 458 | 448 | nothing, |
| 459 | 449 | int: i32, |
| ... | ... | @@ -485,8 +475,6 @@ test "parse into struct with no fields" { |
| 485 | 475 | const test_const_value: usize = 123; |
| 486 | 476 | |
| 487 | 477 | test "parse into struct with default const pointer field" { |
| 488 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 489 | ||
| 490 | 478 | const T = struct { a: *const usize = &test_const_value }; |
| 491 | 479 | const parsed = try parseFromSlice(T, testing.allocator, "{}", .{}); |
| 492 | 480 | defer parsed.deinit(); |
| ... | ... | @@ -502,8 +490,6 @@ const test_default_str_slice: [2][]const u8 = [_][]const u8{ |
| 502 | 490 | }; |
| 503 | 491 | |
| 504 | 492 | test "freeing parsed structs with pointers to default values" { |
| 505 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 506 | ||
| 507 | 493 | const T = struct { |
| 508 | 494 | int: *const usize = &test_default_usize, |
| 509 | 495 | int_ptr: *allowzero align(1) const usize = test_default_usize_ptr, |
| ... | ... | @@ -517,15 +503,11 @@ test "freeing parsed structs with pointers to default values" { |
| 517 | 503 | } |
| 518 | 504 | |
| 519 | 505 | test "parse into struct where destination and source lengths mismatch" { |
| 520 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 521 | ||
| 522 | 506 | const T = struct { a: [2]u8 }; |
| 523 | 507 | try testing.expectError(error.LengthMismatch, parseFromSlice(T, testing.allocator, "{\"a\": \"bbb\"}", .{})); |
| 524 | 508 | } |
| 525 | 509 | |
| 526 | 510 | test "parse into struct with misc fields" { |
| 527 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 528 | ||
| 529 | 511 | const T = struct { |
| 530 | 512 | int: i64, |
| 531 | 513 | float: f64, |
| ... | ... | @@ -601,8 +583,6 @@ test "parse into struct with misc fields" { |
| 601 | 583 | } |
| 602 | 584 | |
| 603 | 585 | test "parse into struct with strings and arrays with sentinels" { |
| 604 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 605 | ||
| 606 | 586 | const T = struct { |
| 607 | 587 | language: [:0]const u8, |
| 608 | 588 | language_without_sentinel: []const u8, |
| ... | ... | @@ -631,8 +611,6 @@ test "parse into struct with strings and arrays with sentinels" { |
| 631 | 611 | } |
| 632 | 612 | |
| 633 | 613 | test "parse into struct with duplicate field" { |
| 634 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 635 | ||
| 636 | 614 | const options_first = ParseOptions{ .duplicate_field_behavior = .use_first }; |
| 637 | 615 | const options_last = ParseOptions{ .duplicate_field_behavior = .use_last }; |
| 638 | 616 | |
| ... | ... | @@ -652,8 +630,6 @@ test "parse into struct with duplicate field" { |
| 652 | 630 | } |
| 653 | 631 | |
| 654 | 632 | test "parse into struct ignoring unknown fields" { |
| 655 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 656 | ||
| 657 | 633 | const T = struct { |
| 658 | 634 | int: i64, |
| 659 | 635 | language: []const u8, |
| ... | ... | @@ -692,8 +668,6 @@ test "parse into struct ignoring unknown fields" { |
| 692 | 668 | } |
| 693 | 669 | |
| 694 | 670 | test "parse into tuple" { |
| 695 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 696 | ||
| 697 | 671 | const Union = union(enum) { |
| 698 | 672 | char: u8, |
| 699 | 673 | float: f64, |
| ... | ... | @@ -749,8 +723,6 @@ const ParseIntoRecursiveUnionDefinitionValue = union(enum) { |
| 749 | 723 | }; |
| 750 | 724 | |
| 751 | 725 | test "parse into recursive union definition" { |
| 752 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 753 | ||
| 754 | 726 | const T = struct { |
| 755 | 727 | values: ParseIntoRecursiveUnionDefinitionValue, |
| 756 | 728 | }; |
| ... | ... | @@ -772,8 +744,6 @@ const ParseIntoDoubleRecursiveUnionValueSecond = union(enum) { |
| 772 | 744 | }; |
| 773 | 745 | |
| 774 | 746 | test "parse into double recursive union definition" { |
| 775 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 776 | ||
| 777 | 747 | const T = struct { |
| 778 | 748 | values: ParseIntoDoubleRecursiveUnionValueFirst, |
| 779 | 749 | }; |
| ... | ... | @@ -785,8 +755,6 @@ test "parse into double recursive union definition" { |
| 785 | 755 | } |
| 786 | 756 | |
| 787 | 757 | test "parse exponential into int" { |
| 788 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 789 | ||
| 790 | 758 | const T = struct { int: i64 }; |
| 791 | 759 | const r = try parseFromSliceLeaky(T, testing.allocator, "{ \"int\": 4.2e2 }", .{}); |
| 792 | 760 | try testing.expectEqual(@as(i64, 420), r.int); |
| ... | ... | @@ -795,8 +763,6 @@ test "parse exponential into int" { |
| 795 | 763 | } |
| 796 | 764 | |
| 797 | 765 | test "parseFromTokenSource" { |
| 798 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 799 | ||
| 800 | 766 | { |
| 801 | 767 | var scanner = JsonScanner.initCompleteInput(testing.allocator, "123"); |
| 802 | 768 | defer scanner.deinit(); |
| ... | ... | @@ -816,8 +782,6 @@ test "parseFromTokenSource" { |
| 816 | 782 | } |
| 817 | 783 | |
| 818 | 784 | test "max_value_len" { |
| 819 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 820 | ||
| 821 | 785 | try testing.expectError(error.ValueTooLong, parseFromSlice([]u8, testing.allocator, "\"0123456789\"", .{ .max_value_len = 5 })); |
| 822 | 786 | } |
| 823 | 787 | |
| ... | ... | @@ -856,8 +820,6 @@ fn assertKey( |
| 856 | 820 | } |
| 857 | 821 | } |
| 858 | 822 | test "json parse partial" { |
| 859 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 860 | ||
| 861 | 823 | const Inner = struct { |
| 862 | 824 | num: u32, |
| 863 | 825 | yes: bool, |
| ... | ... | @@ -913,8 +875,6 @@ test "json parse partial" { |
| 913 | 875 | } |
| 914 | 876 | |
| 915 | 877 | test "json parse allocate when streaming" { |
| 916 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 917 | ||
| 918 | 878 | const T = struct { |
| 919 | 879 | not_const: []u8, |
| 920 | 880 | is_const: []const u8, |
lib/std/json/stringify_test.zig-2| ... | ... | @@ -198,8 +198,6 @@ test "stringify struct" { |
| 198 | 198 | } |
| 199 | 199 | |
| 200 | 200 | test "emit_strings_as_arrays" { |
| 201 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 202 | ||
| 203 | 201 | // Should only affect string values, not object keys. |
| 204 | 202 | try testStringify("{\"foo\":\"bar\"}", .{ .foo = "bar" }, .{}); |
| 205 | 203 | 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" { |
| 1756 | 1756 | } |
| 1757 | 1757 | |
| 1758 | 1758 | test "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; | |
| 1763 | 1761 | |
| 1764 | 1762 | try testing.expect(readIntSliceBig(u0, &[_]u8{}) == 0x0); |
| 1765 | 1763 | try testing.expect(readIntSliceLittle(u0, &[_]u8{}) == 0x0); |
lib/std/net/test.zig-2| ... | ... | @@ -5,7 +5,6 @@ const mem = std.mem; |
| 5 | 5 | const testing = std.testing; |
| 6 | 6 | |
| 7 | 7 | test "parse and render IPv6 addresses" { |
| 8 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 9 | 8 | if (builtin.os.tag == .wasi) return error.SkipZigTest; |
| 10 | 9 | |
| 11 | 10 | var buffer: [100]u8 = undefined; |
| ... | ... | @@ -71,7 +70,6 @@ test "invalid but parseable IPv6 scope ids" { |
| 71 | 70 | } |
| 72 | 71 | |
| 73 | 72 | test "parse and render IPv4 addresses" { |
| 74 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 75 | 73 | if (builtin.os.tag == .wasi) return error.SkipZigTest; |
| 76 | 74 | |
| 77 | 75 | var buffer: [18]u8 = undefined; |
lib/std/os/linux/x86_64.zig+2-2| ... | ... | @@ -431,11 +431,11 @@ fn getContextInternal() callconv(.Naked) usize { |
| 431 | 431 | \\ leaq %[stack_offset:c](%%rdi), %%rsi |
| 432 | 432 | \\ movq %%rdi, %%r8 |
| 433 | 433 | \\ xorl %%edi, %%edi |
| 434 | \\ movq %[sigaltstack], %%rax | |
| 434 | \\ movl %[sigaltstack], %%eax | |
| 435 | 435 | \\ syscall |
| 436 | 436 | \\ testq %%rax, %%rax |
| 437 | 437 | \\ jnz 0f |
| 438 | \\ movq %[sigprocmask], %%rax | |
| 438 | \\ movl %[sigprocmask], %%eax | |
| 439 | 439 | \\ xorl %%esi, %%esi |
| 440 | 440 | \\ leaq %[sigmask_offset:c](%%r8), %%rdx |
| 441 | 441 | \\ 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 { |
| 509 | 509 | test "dl_iterate_phdr" { |
| 510 | 510 | if (builtin.object_format != .elf) return error.SkipZigTest; |
| 511 | 511 | |
| 512 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 513 | ||
| 514 | 512 | var counter: usize = 0; |
| 515 | 513 | try os.dl_iterate_phdr(&counter, IterFnError, iter_fn); |
| 516 | 514 | try expect(counter != 0); |
| ... | ... | @@ -804,8 +802,6 @@ test "sigaction" { |
| 804 | 802 | if (native_os == .wasi or native_os == .windows) |
| 805 | 803 | return error.SkipZigTest; |
| 806 | 804 | |
| 807 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 808 | ||
| 809 | 805 | // https://github.com/ziglang/zig/issues/7427 |
| 810 | 806 | if (native_os == .linux and builtin.target.cpu.arch == .x86) |
| 811 | 807 | return error.SkipZigTest; |
lib/std/rand/test.zig-2| ... | ... | @@ -158,8 +158,6 @@ fn testRandomEnumValue() !void { |
| 158 | 158 | } |
| 159 | 159 | |
| 160 | 160 | test "Random intLessThan" { |
| 161 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 162 | ||
| 163 | 161 | @setEvalBranchQuota(10000); |
| 164 | 162 | try testRandomIntLessThan(); |
| 165 | 163 | try comptime testRandomIntLessThan(); |
lib/std/target.zig+30-6| ... | ... | @@ -733,7 +733,14 @@ pub const Target = struct { |
| 733 | 733 | |
| 734 | 734 | /// Adds the specified feature set but not its dependencies. |
| 735 | 735 | 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 | } | |
| 737 | 744 | } |
| 738 | 745 | |
| 739 | 746 | /// Removes the specified feature but not its dependents. |
| ... | ... | @@ -745,7 +752,14 @@ pub const Target = struct { |
| 745 | 752 | |
| 746 | 753 | /// Removes the specified feature but not its dependents. |
| 747 | 754 | 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 | } | |
| 749 | 763 | } |
| 750 | 764 | |
| 751 | 765 | pub fn populateDependencies(set: *Set, all_features_list: []const Cpu.Feature) void { |
| ... | ... | @@ -774,10 +788,20 @@ pub const Target = struct { |
| 774 | 788 | } |
| 775 | 789 | |
| 776 | 790 | 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 | } | |
| 781 | 805 | } |
| 782 | 806 | }; |
| 783 | 807 |
lib/std/zig/CrossTarget.zig-2| ... | ... | @@ -791,8 +791,6 @@ fn parseOs(result: *CrossTarget, diags: *ParseOptions.Diagnostics, text: []const |
| 791 | 791 | } |
| 792 | 792 | |
| 793 | 793 | test "CrossTarget.parse" { |
| 794 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 795 | ||
| 796 | 794 | if (builtin.target.isGnuLibC()) { |
| 797 | 795 | var cross_target = try CrossTarget.parse(.{}); |
| 798 | 796 | 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) { |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | 97 | test "escape invalid identifiers" { |
| 98 | if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 99 | ||
| 100 | 98 | const expectFmt = std.testing.expectFmt; |
| 101 | 99 | try expectFmt("@\"while\"", "{}", .{fmtId("while")}); |
| 102 | 100 | try expectFmt("hello", "{}", .{fmtId("hello")}); |
src/Module.zig+2-1| ... | ... | @@ -5846,7 +5846,8 @@ pub const Feature = enum { |
| 5846 | 5846 | pub fn backendSupportsFeature(mod: Module, feature: Feature) bool { |
| 5847 | 5847 | return switch (feature) { |
| 5848 | 5848 | .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, | |
| 5850 | 5851 | .panic_unwrap_error => mod.comp.bin_file.options.target.ofmt == .c or |
| 5851 | 5852 | mod.comp.bin_file.options.use_llvm, |
| 5852 | 5853 | .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 { |
| 1145 | 1145 | } |
| 1146 | 1146 | |
| 1147 | 1147 | /// A `cc` of `.z_and_np` clobbers `reg2`! |
| 1148 | fn asmCmovccRegisterRegister(self: *Self, cc: bits.Condition, reg1: Register, reg2: Register) !void { | |
| 1148 | fn asmCmovccRegisterRegister(self: *Self, cc: Condition, reg1: Register, reg2: Register) !void { | |
| 1149 | 1149 | _ = try self.addInst(.{ |
| 1150 | 1150 | .tag = switch (cc) { |
| 1151 | 1151 | else => .cmov, |
| ... | ... | @@ -1168,7 +1168,7 @@ fn asmCmovccRegisterRegister(self: *Self, cc: bits.Condition, reg1: Register, re |
| 1168 | 1168 | } |
| 1169 | 1169 | |
| 1170 | 1170 | /// A `cc` of `.z_and_np` is not supported by this encoding! |
| 1171 | fn asmCmovccRegisterMemory(self: *Self, cc: bits.Condition, reg: Register, m: Memory) !void { | |
| 1171 | fn asmCmovccRegisterMemory(self: *Self, cc: Condition, reg: Register, m: Memory) !void { | |
| 1172 | 1172 | _ = try self.addInst(.{ |
| 1173 | 1173 | .tag = switch (cc) { |
| 1174 | 1174 | else => .cmov, |
| ... | ... | @@ -1204,7 +1204,7 @@ fn asmCmovccRegisterMemory(self: *Self, cc: bits.Condition, reg: Register, m: Me |
| 1204 | 1204 | }); |
| 1205 | 1205 | } |
| 1206 | 1206 | |
| 1207 | fn asmSetccRegister(self: *Self, reg: Register, cc: bits.Condition) !void { | |
| 1207 | fn asmSetccRegister(self: *Self, cc: Condition, reg: Register) !void { | |
| 1208 | 1208 | _ = try self.addInst(.{ |
| 1209 | 1209 | .tag = switch (cc) { |
| 1210 | 1210 | else => .set, |
| ... | ... | @@ -1228,7 +1228,7 @@ fn asmSetccRegister(self: *Self, reg: Register, cc: bits.Condition) !void { |
| 1228 | 1228 | }); |
| 1229 | 1229 | } |
| 1230 | 1230 | |
| 1231 | fn asmSetccMemory(self: *Self, m: Memory, cc: bits.Condition) !void { | |
| 1231 | fn asmSetccMemory(self: *Self, cc: Condition, m: Memory) !void { | |
| 1232 | 1232 | const payload = switch (m) { |
| 1233 | 1233 | .sib => try self.addExtra(Mir.MemorySib.encode(m)), |
| 1234 | 1234 | .rip => try self.addExtra(Mir.MemoryRip.encode(m)), |
| ... | ... | @@ -1279,7 +1279,7 @@ fn asmJmpReloc(self: *Self, target: Mir.Inst.Index) !Mir.Inst.Index { |
| 1279 | 1279 | }); |
| 1280 | 1280 | } |
| 1281 | 1281 | |
| 1282 | fn asmJccReloc(self: *Self, target: Mir.Inst.Index, cc: bits.Condition) !Mir.Inst.Index { | |
| 1282 | fn asmJccReloc(self: *Self, cc: Condition, target: Mir.Inst.Index) !Mir.Inst.Index { | |
| 1283 | 1283 | return self.addInst(.{ |
| 1284 | 1284 | .tag = switch (cc) { |
| 1285 | 1285 | else => .j, |
| ... | ... | @@ -1759,8 +1759,8 @@ fn gen(self: *Self) InnerError!void { |
| 1759 | 1759 | const cc = abi.resolveCallingConvention(fn_info.cc, self.target.*); |
| 1760 | 1760 | if (cc != .Naked) { |
| 1761 | 1761 | try self.asmRegister(.{ ._, .push }, .rbp); |
| 1762 | const backpatch_push_callee_preserved_regs = try self.asmPlaceholder(); | |
| 1763 | 1762 | try self.asmRegisterRegister(.{ ._, .mov }, .rbp, .rsp); |
| 1763 | const backpatch_push_callee_preserved_regs = try self.asmPlaceholder(); | |
| 1764 | 1764 | const backpatch_frame_align = try self.asmPlaceholder(); |
| 1765 | 1765 | const backpatch_frame_align_extra = try self.asmPlaceholder(); |
| 1766 | 1766 | const backpatch_stack_alloc = try self.asmPlaceholder(); |
| ... | ... | @@ -1805,7 +1805,7 @@ fn gen(self: *Self) InnerError!void { |
| 1805 | 1805 | ); |
| 1806 | 1806 | |
| 1807 | 1807 | 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); | |
| 1809 | 1809 | |
| 1810 | 1810 | const vec_2_f64 = try mod.vectorType(.{ .len = 2, .child = .f64_type }); |
| 1811 | 1811 | 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 { |
| 1913 | 1913 | } |
| 1914 | 1914 | if (need_frame_align or need_stack_adjust) { |
| 1915 | 1915 | 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 = .{ | |
| 1919 | 1919 | .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 | }))), | |
| 1921 | 1924 | } }, |
| 1922 | 1925 | }); |
| 1923 | 1926 | } |
| ... | ... | @@ -2262,7 +2265,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 2262 | 2265 | const tag_val = try mod.enumValueFieldIndex(enum_ty, index); |
| 2263 | 2266 | const tag_mcv = try self.genTypedValue(.{ .ty = enum_ty, .val = tag_val }); |
| 2264 | 2267 | 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); | |
| 2266 | 2269 | |
| 2267 | 2270 | try self.genSetMem( |
| 2268 | 2271 | .{ .reg = ret_reg }, |
| ... | ... | @@ -2298,8 +2301,8 @@ fn getValue(self: *Self, value: MCValue, inst: ?Air.Inst.Index) void { |
| 2298 | 2301 | fn freeValue(self: *Self, value: MCValue) !void { |
| 2299 | 2302 | switch (value) { |
| 2300 | 2303 | .register => |reg| { |
| 2301 | if (reg.class() == .x87) try self.asmRegister(.{ .f_, .free }, reg); | |
| 2302 | 2304 | self.register_manager.freeReg(reg); |
| 2305 | if (reg.class() == .x87) try self.asmRegister(.{ .f_, .free }, reg); | |
| 2303 | 2306 | }, |
| 2304 | 2307 | .register_pair => |regs| for (regs) |reg| self.register_manager.freeReg(reg), |
| 2305 | 2308 | .register_offset => |reg_off| self.register_manager.freeReg(reg_off.reg), |
| ... | ... | @@ -2416,17 +2419,19 @@ fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayo |
| 2416 | 2419 | const callee_preserved_regs = |
| 2417 | 2420 | abi.getCalleePreservedRegs(abi.resolveCallingConvention(cc, self.target.*)); |
| 2418 | 2421 | for (callee_preserved_regs) |reg| { |
| 2419 | if (self.register_manager.isRegAllocated(reg)) { | |
| 2422 | if (self.register_manager.isRegAllocated(reg) or true) { | |
| 2420 | 2423 | save_reg_list.push(callee_preserved_regs, reg); |
| 2421 | 2424 | } |
| 2422 | 2425 | } |
| 2423 | 2426 | |
| 2424 | var rbp_offset: i32 = @intCast(save_reg_list.count() * 8); | |
| 2427 | var rbp_offset: i32 = 0; | |
| 2425 | 2428 | self.setFrameLoc(.base_ptr, .rbp, &rbp_offset, false); |
| 2426 | 2429 | self.setFrameLoc(.ret_addr, .rbp, &rbp_offset, false); |
| 2427 | 2430 | 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)]; | |
| 2430 | 2435 | |
| 2431 | 2436 | var rsp_offset: i32 = 0; |
| 2432 | 2437 | self.setFrameLoc(.call_frame, .rsp, &rsp_offset, true); |
| ... | ... | @@ -3242,7 +3247,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3242 | 3247 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 3243 | 3248 | const ty = self.typeOf(bin_op.lhs); |
| 3244 | 3249 | if (ty.zigTypeTag(mod) == .Vector or ty.abiSize(mod) > 8) return self.fail( |
| 3245 | "TODO implement addMulSat for {}", | |
| 3250 | "TODO implement airAddSat for {}", | |
| 3246 | 3251 | .{ty.fmt(mod)}, |
| 3247 | 3252 | ); |
| 3248 | 3253 | |
| ... | ... | @@ -3325,7 +3330,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3325 | 3330 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 3326 | 3331 | const ty = self.typeOf(bin_op.lhs); |
| 3327 | 3332 | if (ty.zigTypeTag(mod) == .Vector or ty.abiSize(mod) > 8) return self.fail( |
| 3328 | "TODO implement addMulSat for {}", | |
| 3333 | "TODO implement airSubSat for {}", | |
| 3329 | 3334 | .{ty.fmt(mod)}, |
| 3330 | 3335 | ); |
| 3331 | 3336 | |
| ... | ... | @@ -3401,7 +3406,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3401 | 3406 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 3402 | 3407 | const ty = self.typeOf(bin_op.lhs); |
| 3403 | 3408 | if (ty.zigTypeTag(mod) == .Vector or ty.abiSize(mod) > 8) return self.fail( |
| 3404 | "TODO implement addMulSat for {}", | |
| 3409 | "TODO implement airMulSat for {}", | |
| 3405 | 3410 | .{ty.fmt(mod)}, |
| 3406 | 3411 | ); |
| 3407 | 3412 | |
| ... | ... | @@ -3617,7 +3622,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3617 | 3622 | defer for (temp_locks) |lock| self.register_manager.unlockReg(lock); |
| 3618 | 3623 | |
| 3619 | 3624 | 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()); | |
| 3621 | 3626 | |
| 3622 | 3627 | const scratch_reg = temp_regs[1]; |
| 3623 | 3628 | const hi_limb_off = if (int_info.bits <= 64) 0 else (int_info.bits - 1) / 64 * 8; |
| ... | ... | @@ -3631,7 +3636,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3631 | 3636 | |
| 3632 | 3637 | const eq_reg = temp_regs[2]; |
| 3633 | 3638 | if (overflow_cc) |_| { |
| 3634 | try self.asmSetccRegister(eq_reg.to8(), .ne); | |
| 3639 | try self.asmSetccRegister(.ne, eq_reg.to8()); | |
| 3635 | 3640 | try self.genBinOpMir( |
| 3636 | 3641 | .{ ._, .@"or" }, |
| 3637 | 3642 | Type.u8, |
| ... | ... | @@ -3660,28 +3665,150 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3660 | 3665 | const mod = self.bin_file.options.module.?; |
| 3661 | 3666 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 3662 | 3667 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3668 | const tuple_ty = self.typeOfIndex(inst); | |
| 3663 | 3669 | const dst_ty = self.typeOf(bin_op.lhs); |
| 3664 | 3670 | const result: MCValue = switch (dst_ty.zigTypeTag(mod)) { |
| 3665 | 3671 | .Vector => return self.fail("TODO implement airMulWithOverflow for {}", .{dst_ty.fmt(mod)}), |
| 3666 | 3672 | .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 | ||
| 3667 | 3801 | try self.spillEflagsIfOccupied(); |
| 3668 | 3802 | try self.spillRegisters(&.{ .rax, .rdx }); |
| 3669 | 3803 | |
| 3670 | const dst_info = dst_ty.intInfo(mod); | |
| 3671 | 3804 | const cc: Condition = switch (dst_info.signedness) { |
| 3672 | 3805 | .unsigned => .c, |
| 3673 | 3806 | .signed => .o, |
| 3674 | 3807 | }; |
| 3675 | 3808 | |
| 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 | ||
| 3681 | 3809 | const lhs = try self.resolveInst(bin_op.lhs); |
| 3682 | 3810 | const rhs = try self.resolveInst(bin_op.rhs); |
| 3683 | 3811 | |
| 3684 | const tuple_ty = self.typeOfIndex(inst); | |
| 3685 | 3812 | const extra_bits = if (dst_info.bits <= 64) |
| 3686 | 3813 | self.regExtraBits(dst_ty) |
| 3687 | 3814 | else |
| ... | ... | @@ -3741,6 +3868,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3741 | 3868 | fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue, rhs: MCValue) !void { |
| 3742 | 3869 | const mod = self.bin_file.options.module.?; |
| 3743 | 3870 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 3871 | const bit_size: u32 = @intCast(self.regBitSize(ty)); | |
| 3744 | 3872 | if (abi_size > 8) { |
| 3745 | 3873 | return self.fail("TODO implement genIntMulDivOpMir for ABI size larger than 8", .{}); |
| 3746 | 3874 | } |
| ... | ... | @@ -3752,14 +3880,14 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue |
| 3752 | 3880 | .div => switch (tag[0]) { |
| 3753 | 3881 | ._ => { |
| 3754 | 3882 | const hi_reg: Register = |
| 3755 | switch (self.regBitSize(ty)) { | |
| 3883 | switch (bit_size) { | |
| 3756 | 3884 | 8 => .ah, |
| 3757 | 3885 | 16, 32, 64 => .edx, |
| 3758 | 3886 | else => unreachable, |
| 3759 | 3887 | }; |
| 3760 | 3888 | try self.asmRegisterRegister(.{ ._, .xor }, hi_reg, hi_reg); |
| 3761 | 3889 | }, |
| 3762 | .i_ => try self.asmOpOnly(.{ ._, switch (self.regBitSize(ty)) { | |
| 3890 | .i_ => try self.asmOpOnly(.{ ._, switch (bit_size) { | |
| 3763 | 3891 | 8 => .cbw, |
| 3764 | 3892 | 16 => .cwd, |
| 3765 | 3893 | 32 => .cdq, |
| ... | ... | @@ -3782,6 +3910,7 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue |
| 3782 | 3910 | ), |
| 3783 | 3911 | else => unreachable, |
| 3784 | 3912 | } |
| 3913 | if (tag[1] == .div and bit_size == 8) try self.asmRegisterRegister(.{ ._, .mov }, .dl, .ah); | |
| 3785 | 3914 | } |
| 3786 | 3915 | |
| 3787 | 3916 | /// Always returns a register. |
| ... | ... | @@ -3981,54 +4110,12 @@ fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 3981 | 4110 | |
| 3982 | 4111 | fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 3983 | 4112 | 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); | |
| 3985 | 4114 | 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); | |
| 3987 | 4116 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 3988 | 4117 | } |
| 3989 | 4118 | |
| 3990 | fn 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 | ||
| 4032 | 4119 | // *(E!T) -> E |
| 4033 | 4120 | fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4034 | 4121 | const mod = self.bin_file.options.module.?; |
| ... | ... | @@ -4067,38 +4154,11 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4067 | 4154 | |
| 4068 | 4155 | // *(E!T) -> *T |
| 4069 | 4156 | fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4070 | const mod = self.bin_file.options.module.?; | |
| 4071 | 4157 | 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 }); | |
| 4102 | 4162 | } |
| 4103 | 4163 | |
| 4104 | 4164 | fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -4150,6 +4210,71 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 4150 | 4210 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 4151 | 4211 | } |
| 4152 | 4212 | |
| 4213 | fn 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 | ||
| 4255 | fn 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 | ||
| 4153 | 4278 | fn airErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { |
| 4154 | 4279 | _ = inst; |
| 4155 | 4280 | return self.fail("TODO implement airErrReturnTrace for {}", .{self.target.cpu.arch}); |
| ... | ... | @@ -6425,7 +6550,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 6425 | 6550 | break :result .{ .eflags = ro.eflags }; |
| 6426 | 6551 | } else { |
| 6427 | 6552 | 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()); | |
| 6429 | 6554 | break :result .{ .register = dst_reg.to8() }; |
| 6430 | 6555 | }, |
| 6431 | 6556 | else => unreachable, |
| ... | ... | @@ -9712,55 +9837,59 @@ fn genCall(self: *Self, info: union(enum) { |
| 9712 | 9837 | switch (info) { |
| 9713 | 9838 | .air => |callee| if (try self.air.value(callee, mod)) |func_value| { |
| 9714 | 9839 | 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, | |
| 9717 | 9842 | .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, | |
| 9720 | 9845 | }, |
| 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 }); | |
| 9729 | 9870 | 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", .{}), | |
| 9764 | 9893 | } |
| 9765 | 9894 | } else { |
| 9766 | 9895 | assert(self.typeOf(callee).zigTypeTag(mod) == .Pointer); |
| ... | ... | @@ -10241,47 +10370,46 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void { |
| 10241 | 10370 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 10242 | 10371 | const extra = self.air.extraData(Air.Try, pl_op.payload); |
| 10243 | 10372 | 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); | |
| 10246 | 10375 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 10247 | 10376 | } |
| 10248 | 10377 | |
| 10249 | 10378 | fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 10250 | const mod = self.bin_file.options.module.?; | |
| 10251 | 10379 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 10252 | 10380 | const extra = self.air.extraData(Air.TryPtr, ty_pl.payload); |
| 10253 | 10381 | 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); | |
| 10256 | 10384 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 10257 | 10385 | } |
| 10258 | 10386 | |
| 10259 | 10387 | fn genTry( |
| 10260 | 10388 | self: *Self, |
| 10261 | 10389 | inst: Air.Inst.Index, |
| 10262 | err_union: Air.Inst.Ref, | |
| 10390 | operand: Air.Inst.Ref, | |
| 10263 | 10391 | body: []const Air.Inst.Index, |
| 10264 | err_union_ty: Type, | |
| 10392 | operand_ty: Type, | |
| 10265 | 10393 | operand_is_ptr: bool, |
| 10266 | 10394 | ) !MCValue { |
| 10267 | if (operand_is_ptr) { | |
| 10268 | return self.fail("TODO genTry for pointers", .{}); | |
| 10269 | } | |
| 10270 | 10395 | const liveness_cond_br = self.liveness.getCondBr(inst); |
| 10271 | 10396 | |
| 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); | |
| 10274 | 10402 | |
| 10275 | 10403 | const reloc = try self.genCondBrMir(Type.anyerror, is_err_mcv); |
| 10276 | 10404 | |
| 10277 | 10405 | 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); | |
| 10279 | 10407 | } |
| 10280 | 10408 | |
| 10281 | 10409 | self.scope_generation += 1; |
| 10282 | 10410 | const state = try self.saveState(); |
| 10283 | 10411 | |
| 10284 | for (liveness_cond_br.else_deaths) |operand| try self.processDeath(operand); | |
| 10412 | for (liveness_cond_br.else_deaths) |death| try self.processDeath(death); | |
| 10285 | 10413 | try self.genBody(body); |
| 10286 | 10414 | try self.restoreState(state, &.{}, .{ |
| 10287 | 10415 | .emit_instructions = false, |
| ... | ... | @@ -10292,12 +10420,14 @@ fn genTry( |
| 10292 | 10420 | |
| 10293 | 10421 | try self.performReloc(reloc); |
| 10294 | 10422 | |
| 10295 | for (liveness_cond_br.then_deaths) |operand| try self.processDeath(operand); | |
| 10423 | for (liveness_cond_br.then_deaths) |death| try self.processDeath(death); | |
| 10296 | 10424 | |
| 10297 | 10425 | const result = if (self.liveness.isUnused(inst)) |
| 10298 | 10426 | .unreach |
| 10427 | else if (operand_is_ptr) | |
| 10428 | try self.genUnwrapErrUnionPayloadPtrMir(inst, operand_ty, operand_mcv) | |
| 10299 | 10429 | else |
| 10300 | try self.genUnwrapErrorUnionPayloadMir(inst, err_union_ty, err_union_mcv); | |
| 10430 | try self.genUnwrapErrUnionPayloadMir(inst, operand_ty, operand_mcv); | |
| 10301 | 10431 | return result; |
| 10302 | 10432 | } |
| 10303 | 10433 | |
| ... | ... | @@ -10348,12 +10478,12 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !Mir.Inst.Index { |
| 10348 | 10478 | switch (mcv) { |
| 10349 | 10479 | .eflags => |cc| { |
| 10350 | 10480 | // 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); | |
| 10352 | 10482 | }, |
| 10353 | 10483 | .register => |reg| { |
| 10354 | 10484 | try self.spillEflagsIfOccupied(); |
| 10355 | 10485 | try self.asmRegisterImmediate(.{ ._, .@"test" }, reg, Immediate.u(1)); |
| 10356 | return self.asmJccReloc(undefined, .e); | |
| 10486 | return self.asmJccReloc(.e, undefined); | |
| 10357 | 10487 | }, |
| 10358 | 10488 | .immediate, |
| 10359 | 10489 | .load_frame, |
| ... | ... | @@ -10391,7 +10521,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 10391 | 10521 | self.scope_generation += 1; |
| 10392 | 10522 | const state = try self.saveState(); |
| 10393 | 10523 | |
| 10394 | for (liveness_cond_br.then_deaths) |operand| try self.processDeath(operand); | |
| 10524 | for (liveness_cond_br.then_deaths) |death| try self.processDeath(death); | |
| 10395 | 10525 | try self.genBody(then_body); |
| 10396 | 10526 | try self.restoreState(state, &.{}, .{ |
| 10397 | 10527 | .emit_instructions = false, |
| ... | ... | @@ -10402,7 +10532,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 10402 | 10532 | |
| 10403 | 10533 | try self.performReloc(reloc); |
| 10404 | 10534 | |
| 10405 | for (liveness_cond_br.else_deaths) |operand| try self.processDeath(operand); | |
| 10535 | for (liveness_cond_br.else_deaths) |death| try self.processDeath(death); | |
| 10406 | 10536 | try self.genBody(else_body); |
| 10407 | 10537 | try self.restoreState(state, &.{}, .{ |
| 10408 | 10538 | .emit_instructions = false, |
| ... | ... | @@ -10517,11 +10647,11 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 10517 | 10647 | |
| 10518 | 10648 | fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue { |
| 10519 | 10649 | const mod = self.bin_file.options.module.?; |
| 10520 | try self.spillEflagsIfOccupied(); | |
| 10521 | ||
| 10522 | 10650 | const opt_ty = ptr_ty.childType(mod); |
| 10523 | 10651 | const pl_ty = opt_ty.optionalChild(mod); |
| 10524 | 10652 | |
| 10653 | try self.spillEflagsIfOccupied(); | |
| 10654 | ||
| 10525 | 10655 | const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(mod)) |
| 10526 | 10656 | .{ .off = 0, .ty = if (pl_ty.isSlice(mod)) pl_ty.slicePtrFieldType(mod) else pl_ty } |
| 10527 | 10657 | else |
| ... | ... | @@ -10548,27 +10678,24 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) |
| 10548 | 10678 | return .{ .eflags = .e }; |
| 10549 | 10679 | } |
| 10550 | 10680 | |
| 10551 | fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !MCValue { | |
| 10681 | fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MCValue { | |
| 10552 | 10682 | 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 | |
| 10558 | 10685 | |
| 10559 | 10686 | try self.spillEflagsIfOccupied(); |
| 10560 | 10687 | |
| 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) { | |
| 10563 | 10690 | .register => |reg| { |
| 10564 | 10691 | const eu_lock = self.register_manager.lockReg(reg); |
| 10565 | 10692 | defer if (eu_lock) |lock| self.register_manager.unlockReg(lock); |
| 10566 | 10693 | |
| 10567 | const tmp_reg = try self.copyToTmpRegister(ty, operand); | |
| 10694 | const tmp_reg = try self.copyToTmpRegister(eu_ty, eu_mcv); | |
| 10568 | 10695 | if (err_off > 0) { |
| 10569 | 10696 | try self.genShiftBinOpMir( |
| 10570 | 10697 | .{ ._r, .sh }, |
| 10571 | ty, | |
| 10698 | eu_ty, | |
| 10572 | 10699 | .{ .register = tmp_reg }, |
| 10573 | 10700 | .{ .immediate = @as(u6, @intCast(err_off * 8)) }, |
| 10574 | 10701 | ); |
| ... | ... | @@ -10587,19 +10714,63 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) ! |
| 10587 | 10714 | Type.anyerror, |
| 10588 | 10715 | .{ .load_frame = .{ |
| 10589 | 10716 | .index = frame_addr.index, |
| 10590 | .off = frame_addr.off + @as(i32, @intCast(err_off)), | |
| 10717 | .off = frame_addr.off + err_off, | |
| 10591 | 10718 | } }, |
| 10592 | 10719 | .{ .immediate = 0 }, |
| 10593 | 10720 | ), |
| 10594 | else => return self.fail("TODO implement isErr for {}", .{operand}), | |
| 10721 | else => return self.fail("TODO implement isErr for {}", .{eu_mcv}), | |
| 10595 | 10722 | } |
| 10596 | 10723 | |
| 10597 | 10724 | if (maybe_inst) |inst| self.eflags_inst = inst; |
| 10598 | 10725 | return MCValue{ .eflags = .a }; |
| 10599 | 10726 | } |
| 10600 | 10727 | |
| 10601 | fn isNonErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue { | |
| 10602 | const is_err_res = try self.isErr(inst, ty, operand); | |
| 10728 | fn 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 | ||
| 10757 | fn 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 | ||
| 10772 | fn 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); | |
| 10603 | 10774 | switch (is_err_res) { |
| 10604 | 10775 | .eflags => |cc| { |
| 10605 | 10776 | assert(cc == .a); |
| ... | ... | @@ -10607,7 +10778,7 @@ fn isNonErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCVa |
| 10607 | 10778 | }, |
| 10608 | 10779 | .immediate => |imm| { |
| 10609 | 10780 | assert(imm == 0); |
| 10610 | return MCValue{ .immediate = 1 }; | |
| 10781 | return MCValue{ .immediate = @intFromBool(imm == 0) }; | |
| 10611 | 10782 | }, |
| 10612 | 10783 | else => unreachable, |
| 10613 | 10784 | } |
| ... | ... | @@ -10660,29 +10831,10 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void { |
| 10660 | 10831 | } |
| 10661 | 10832 | |
| 10662 | 10833 | fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 10663 | const mod = self.bin_file.options.module.?; | |
| 10664 | 10834 | 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); | |
| 10686 | 10838 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 10687 | 10839 | } |
| 10688 | 10840 | |
| ... | ... | @@ -10695,29 +10847,10 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void { |
| 10695 | 10847 | } |
| 10696 | 10848 | |
| 10697 | 10849 | fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 10698 | const mod = self.bin_file.options.module.?; | |
| 10699 | 10850 | 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); | |
| 10721 | 10854 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 10722 | 10855 | } |
| 10723 | 10856 | |
| ... | ... | @@ -10810,7 +10943,7 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void { |
| 10810 | 10943 | for (items, relocs, 0..) |item, *reloc, i| { |
| 10811 | 10944 | const item_mcv = try self.resolveInst(item); |
| 10812 | 10945 | 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); | |
| 10814 | 10947 | } |
| 10815 | 10948 | |
| 10816 | 10949 | for (liveness.deaths[case_i]) |operand| try self.processDeath(operand); |
| ... | ... | @@ -11210,6 +11343,15 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 11210 | 11343 | mnem_size = null; |
| 11211 | 11344 | break :mnem std.meta.stringToEnum(Instruction.Mnemonic, mnem_str); |
| 11212 | 11345 | } 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 | } | |
| 11213 | 11355 | const mnem_name = @tagName(mnem_tag); |
| 11214 | 11356 | const mnem_fixed_tag: Mir.Inst.FixedTag = for (std.enums.values(Mir.Inst.Fixes)) |fixes| { |
| 11215 | 11357 | const fixes_name = @tagName(fixes); |
| ... | ... | @@ -11359,8 +11501,31 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 11359 | 11501 | if (sib_it.next()) |_| return self.fail("invalid memory operand: '{s}'", .{op_str}); |
| 11360 | 11502 | op.* = .{ .mem = Memory.sib(mnem_size orelse |
| 11361 | 11503 | 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, | |
| 11364 | 11529 | .base = if (base_str.len > 0) .{ .reg = parseRegName(base_str["%%".len..]) orelse |
| 11365 | 11530 | return self.fail("invalid base register: '{s}'", .{base_str}) } else .none, |
| 11366 | 11531 | .scale_index = if (index_str.len > 0) .{ |
| ... | ... | @@ -11840,7 +12005,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 11840 | 12005 | .reserved_frame, |
| 11841 | 12006 | => unreachable, |
| 11842 | 12007 | .undef => {}, |
| 11843 | .eflags => |cc| try self.asmSetccRegister(dst_reg.to8(), cc), | |
| 12008 | .eflags => |cc| try self.asmSetccRegister(cc, dst_reg.to8()), | |
| 11844 | 12009 | .immediate => |imm| { |
| 11845 | 12010 | if (imm == 0) { |
| 11846 | 12011 | // 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 |
| 12110 | 12275 | ); |
| 12111 | 12276 | }, |
| 12112 | 12277 | }, |
| 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 })), | |
| 12114 | 12279 | .register => |src_reg| try (try self.moveStrategy(ty, switch (base) { |
| 12115 | 12280 | .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))), |
| 12116 | 12281 | .reg => |reg| switch (reg) { |
| ... | ... | @@ -12870,7 +13035,7 @@ fn atomicOp( |
| 12870 | 13035 | ptr_mem, |
| 12871 | 13036 | registerAlias(tmp_reg, val_abi_size), |
| 12872 | 13037 | ); |
| 12873 | _ = try self.asmJccReloc(loop, .ne); | |
| 13038 | _ = try self.asmJccReloc(.ne, loop); | |
| 12874 | 13039 | return if (unused) .unreach else .{ .register = .rax }; |
| 12875 | 13040 | } else { |
| 12876 | 13041 | try self.asmRegisterMemory(.{ ._, .mov }, .rax, Memory.sib(.qword, .{ |
| ... | ... | @@ -12932,7 +13097,7 @@ fn atomicOp( |
| 12932 | 13097 | }), |
| 12933 | 13098 | }; |
| 12934 | 13099 | try self.asmMemory(.{ .@"lock _16b", .cmpxchg }, ptr_mem); |
| 12935 | _ = try self.asmJccReloc(loop, .ne); | |
| 13100 | _ = try self.asmJccReloc(.ne, loop); | |
| 12936 | 13101 | |
| 12937 | 13102 | if (unused) return .unreach; |
| 12938 | 13103 | const dst_mcv = try self.allocTempRegOrMem(val_ty, false); |
| ... | ... | @@ -13084,7 +13249,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 13084 | 13249 | |
| 13085 | 13250 | try self.genSetReg(len_reg, Type.usize, len); |
| 13086 | 13251 | |
| 13087 | const skip_reloc = try self.asmJccReloc(undefined, .z); | |
| 13252 | const skip_reloc = try self.asmJccReloc(.z, undefined); | |
| 13088 | 13253 | try self.store(slice_ptr_ty, ptr, src_val); |
| 13089 | 13254 | |
| 13090 | 13255 | 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 { |
| 14041 | 14206 | try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, Immediate.u( |
| 14042 | 14207 | abi.SysV.c_abi_int_param_regs.len * 8, |
| 14043 | 14208 | )); |
| 14044 | const mem_reloc = try self.asmJccReloc(undefined, .ae); | |
| 14209 | const mem_reloc = try self.asmJccReloc(.ae, undefined); | |
| 14045 | 14210 | |
| 14046 | 14211 | try self.genSetReg(addr_reg, ptr_anyopaque_ty, reg_save_area); |
| 14047 | 14212 | if (!unused) |
| ... | ... | @@ -14080,7 +14245,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { |
| 14080 | 14245 | try self.asmRegisterImmediate(.{ ._, .cmp }, offset_reg, Immediate.u( |
| 14081 | 14246 | abi.SysV.c_abi_int_param_regs.len * 8 + abi.SysV.c_abi_sse_param_regs.len * 16, |
| 14082 | 14247 | )); |
| 14083 | const mem_reloc = try self.asmJccReloc(undefined, .ae); | |
| 14248 | const mem_reloc = try self.asmJccReloc(.ae, undefined); | |
| 14084 | 14249 | |
| 14085 | 14250 | try self.genSetReg(addr_reg, ptr_anyopaque_ty, reg_save_area); |
| 14086 | 14251 | if (!unused) |
src/arch/x86_64/Disassembler.zig+1-1| ... | ... | @@ -38,7 +38,7 @@ pub fn next(dis: *Disassembler) Error!?Instruction { |
| 38 | 38 | |
| 39 | 39 | const enc = try dis.parseEncoding(prefixes) orelse return error.UnknownOpcode; |
| 40 | 40 | switch (enc.data.op_en) { |
| 41 | .np => return inst(enc, .{}), | |
| 41 | .zo => return inst(enc, .{}), | |
| 42 | 42 | .d, .i => { |
| 43 | 43 | const imm = try dis.parseImm(enc.data.ops[0]); |
| 44 | 44 | return inst(enc, .{ |
src/arch/x86_64/Encoding.zig+13-8| ... | ... | @@ -166,7 +166,7 @@ pub fn format( |
| 166 | 166 | for (opc) |byte| try writer.print("{x:0>2} ", .{byte}); |
| 167 | 167 | |
| 168 | 168 | switch (encoding.data.op_en) { |
| 169 | .np, .fd, .td, .i, .zi, .d => {}, | |
| 169 | .zo, .fd, .td, .i, .zi, .d => {}, | |
| 170 | 170 | .o, .oi => { |
| 171 | 171 | const tag = switch (encoding.data.ops[0]) { |
| 172 | 172 | .r8 => "rb", |
| ... | ... | @@ -203,7 +203,7 @@ pub fn format( |
| 203 | 203 | try writer.print("{s} ", .{tag}); |
| 204 | 204 | }, |
| 205 | 205 | .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 => {}, | |
| 207 | 207 | } |
| 208 | 208 | |
| 209 | 209 | try writer.print("{s} ", .{@tagName(encoding.mnemonic)}); |
| ... | ... | @@ -246,7 +246,7 @@ pub const Mnemonic = enum { |
| 246 | 246 | movsx, movsxd, movzx, mul, |
| 247 | 247 | neg, nop, not, |
| 248 | 248 | @"or", |
| 249 | pause, pop, popcnt, push, | |
| 249 | pause, pop, popcnt, popfq, push, pushfq, | |
| 250 | 250 | rcl, rcr, ret, rol, ror, |
| 251 | 251 | sal, sar, sbb, |
| 252 | 252 | scas, scasb, scasd, scasq, scasw, |
| ... | ... | @@ -260,7 +260,7 @@ pub const Mnemonic = enum { |
| 260 | 260 | ud2, |
| 261 | 261 | xadd, xchg, xgetbv, xor, |
| 262 | 262 | // X87 |
| 263 | fabs, fchs, ffree, fisttp, fld, fst, fstp, | |
| 263 | fabs, fchs, ffree, fisttp, fld, fldenv, fnstenv, fst, fstenv, fstp, | |
| 264 | 264 | // MMX |
| 265 | 265 | movd, movq, |
| 266 | 266 | packssdw, packsswb, packuswb, |
| ... | ... | @@ -280,6 +280,7 @@ pub const Mnemonic = enum { |
| 280 | 280 | cmpps, cmpss, |
| 281 | 281 | cvtpi2ps, cvtps2pi, cvtsi2ss, cvtss2si, cvttps2pi, cvttss2si, |
| 282 | 282 | divps, divss, |
| 283 | ldmxcsr, | |
| 283 | 284 | maxps, maxss, |
| 284 | 285 | minps, minss, |
| 285 | 286 | movaps, movhlps, movlhps, |
| ... | ... | @@ -291,6 +292,7 @@ pub const Mnemonic = enum { |
| 291 | 292 | pmaxsw, pmaxub, pminsw, pminub, pmovmskb, |
| 292 | 293 | shufps, |
| 293 | 294 | sqrtps, sqrtss, |
| 295 | stmxcsr, | |
| 294 | 296 | subps, subss, |
| 295 | 297 | ucomiss, |
| 296 | 298 | xorps, |
| ... | ... | @@ -358,6 +360,7 @@ pub const Mnemonic = enum { |
| 358 | 360 | vdivpd, vdivps, vdivsd, vdivss, |
| 359 | 361 | vextractf128, vextractps, |
| 360 | 362 | vinsertf128, vinsertps, |
| 363 | vldmxcsr, | |
| 361 | 364 | vmaxpd, vmaxps, vmaxsd, vmaxss, |
| 362 | 365 | vminpd, vminps, vminsd, vminss, |
| 363 | 366 | vmovapd, vmovaps, |
| ... | ... | @@ -397,6 +400,7 @@ pub const Mnemonic = enum { |
| 397 | 400 | vroundpd, vroundps, vroundsd, vroundss, |
| 398 | 401 | vshufpd, vshufps, |
| 399 | 402 | vsqrtpd, vsqrtps, vsqrtsd, vsqrtss, |
| 403 | vstmxcsr, | |
| 400 | 404 | vsubpd, vsubps, vsubsd, vsubss, |
| 401 | 405 | vxorpd, vxorps, |
| 402 | 406 | // F16C |
| ... | ... | @@ -411,7 +415,7 @@ pub const Mnemonic = enum { |
| 411 | 415 | |
| 412 | 416 | pub const OpEn = enum { |
| 413 | 417 | // zig fmt: off |
| 414 | np, | |
| 418 | zo, | |
| 415 | 419 | o, oi, |
| 416 | 420 | i, zi, |
| 417 | 421 | d, m, |
| ... | ... | @@ -481,6 +485,7 @@ pub const Op = enum { |
| 481 | 485 | .mem => |mem| switch (mem) { |
| 482 | 486 | .moffs => .moffs, |
| 483 | 487 | .sib, .rip => switch (mem.bitSize()) { |
| 488 | 0 => .m, | |
| 484 | 489 | 8 => .m8, |
| 485 | 490 | 16 => .m16, |
| 486 | 491 | 32 => .m32, |
| ... | ... | @@ -610,7 +615,7 @@ pub const Op = enum { |
| 610 | 615 | .imm8s, .imm16s, .imm32s, |
| 611 | 616 | .rel8, .rel16, .rel32, |
| 612 | 617 | .unity, |
| 613 | => true, | |
| 618 | => true, | |
| 614 | 619 | else => false, |
| 615 | 620 | }; |
| 616 | 621 | // zig fmt: on |
| ... | ... | @@ -626,7 +631,7 @@ pub const Op = enum { |
| 626 | 631 | .mm_m64, |
| 627 | 632 | .xmm_m32, .xmm_m64, .xmm_m128, |
| 628 | 633 | .ymm_m256, |
| 629 | => true, | |
| 634 | => true, | |
| 630 | 635 | else => false, |
| 631 | 636 | }; |
| 632 | 637 | // zig fmt: on |
| ... | ... | @@ -657,7 +662,7 @@ pub const Op = enum { |
| 657 | 662 | /// Given an operand `op` checks if `target` is a subset for the purposes of the encoding. |
| 658 | 663 | pub fn isSubset(op: Op, target: Op) bool { |
| 659 | 664 | switch (op) { |
| 660 | .m, .o16, .o32, .o64 => unreachable, | |
| 665 | .o16, .o32, .o64 => unreachable, | |
| 661 | 666 | .moffs, .sreg => return op == target, |
| 662 | 667 | .none => switch (target) { |
| 663 | 668 | .o16, .o32, .o64, .none => return true, |
src/arch/x86_64/Mir.zig+20-1| ... | ... | @@ -394,8 +394,12 @@ pub const Inst = struct { |
| 394 | 394 | pop, |
| 395 | 395 | /// Return the count of number of bits set to 1 |
| 396 | 396 | popcnt, |
| 397 | /// Pop stack into EFLAGS register | |
| 398 | popfq, | |
| 397 | 399 | /// Push |
| 398 | 400 | push, |
| 401 | /// Push EFLAGS register onto the stack | |
| 402 | pushfq, | |
| 399 | 403 | /// Rotate left through carry |
| 400 | 404 | /// Rotate right through carry |
| 401 | 405 | rc, |
| ... | ... | @@ -458,8 +462,14 @@ pub const Inst = struct { |
| 458 | 462 | istt, |
| 459 | 463 | /// Load floating-point value |
| 460 | 464 | ld, |
| 465 | /// Load x87 FPU environment | |
| 466 | ldenv, | |
| 467 | /// Store x87 FPU environment | |
| 468 | nstenv, | |
| 461 | 469 | /// Store floating-point value |
| 462 | 470 | st, |
| 471 | /// Store x87 FPU environment | |
| 472 | stenv, | |
| 463 | 473 | |
| 464 | 474 | /// Pack with signed saturation |
| 465 | 475 | ackssw, |
| ... | ... | @@ -505,6 +515,11 @@ pub const Inst = struct { |
| 505 | 515 | /// Subtract packed unsigned integers with unsigned saturation |
| 506 | 516 | subus, |
| 507 | 517 | |
| 518 | /// Load MXCSR register | |
| 519 | ldmxcsr, | |
| 520 | /// Store MXCSR register state | |
| 521 | stmxcsr, | |
| 522 | ||
| 508 | 523 | /// Convert packed doubleword integers to packed single-precision floating-point values |
| 509 | 524 | /// Convert packed doubleword integers to packed double-precision floating-point values |
| 510 | 525 | cvtpi2, |
| ... | ... | @@ -1079,9 +1094,13 @@ pub const RegisterList = struct { |
| 1079 | 1094 | return self.bitset.iterator(options); |
| 1080 | 1095 | } |
| 1081 | 1096 | |
| 1082 | pub fn count(self: Self) u32 { | |
| 1097 | pub fn count(self: Self) i32 { | |
| 1083 | 1098 | return @intCast(self.bitset.count()); |
| 1084 | 1099 | } |
| 1100 | ||
| 1101 | pub fn size(self: Self) i32 { | |
| 1102 | return @intCast(self.bitset.count() * 8); | |
| 1103 | } | |
| 1085 | 1104 | }; |
| 1086 | 1105 | |
| 1087 | 1106 | pub const Imm32 = struct { |
src/arch/x86_64/bits.zig+13| ... | ... | @@ -470,6 +470,7 @@ pub const Memory = union(enum) { |
| 470 | 470 | }; |
| 471 | 471 | |
| 472 | 472 | pub const PtrSize = enum { |
| 473 | none, | |
| 473 | 474 | byte, |
| 474 | 475 | word, |
| 475 | 476 | dword, |
| ... | ... | @@ -508,6 +509,7 @@ pub const Memory = union(enum) { |
| 508 | 509 | |
| 509 | 510 | pub fn bitSize(s: PtrSize) u64 { |
| 510 | 511 | return switch (s) { |
| 512 | .none => 0, | |
| 511 | 513 | .byte => 8, |
| 512 | 514 | .word => 16, |
| 513 | 515 | .dword => 32, |
| ... | ... | @@ -518,6 +520,17 @@ pub const Memory = union(enum) { |
| 518 | 520 | .zword => 512, |
| 519 | 521 | }; |
| 520 | 522 | } |
| 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 | } | |
| 521 | 534 | }; |
| 522 | 535 | |
| 523 | 536 | pub const Sib = struct { |
src/arch/x86_64/encoder.zig+6-6| ... | ... | @@ -102,7 +102,7 @@ pub const Instruction = struct { |
| 102 | 102 | .reg => |reg| try writer.writeAll(@tagName(reg)), |
| 103 | 103 | .mem => |mem| switch (mem) { |
| 104 | 104 | .rip => |rip| { |
| 105 | try writer.print("{s} ptr [rip", .{@tagName(rip.ptr_size)}); | |
| 105 | try writer.print("{} [rip", .{rip.ptr_size}); | |
| 106 | 106 | if (rip.disp != 0) try writer.print(" {c} 0x{x}", .{ |
| 107 | 107 | @as(u8, if (rip.disp < 0) '-' else '+'), |
| 108 | 108 | @abs(rip.disp), |
| ... | ... | @@ -110,7 +110,7 @@ pub const Instruction = struct { |
| 110 | 110 | try writer.writeByte(']'); |
| 111 | 111 | }, |
| 112 | 112 | .sib => |sib| { |
| 113 | try writer.print("{s} ptr ", .{@tagName(sib.ptr_size)}); | |
| 113 | try writer.print("{} ", .{sib.ptr_size}); | |
| 114 | 114 | |
| 115 | 115 | if (mem.isSegmentRegister()) { |
| 116 | 116 | return writer.print("{s}:0x{x}", .{ @tagName(sib.base.reg), sib.disp }); |
| ... | ... | @@ -222,7 +222,7 @@ pub const Instruction = struct { |
| 222 | 222 | } |
| 223 | 223 | |
| 224 | 224 | switch (data.op_en) { |
| 225 | .np, .o => {}, | |
| 225 | .zo, .o => {}, | |
| 226 | 226 | .i, .d => try encodeImm(inst.ops[0].imm, data.ops[0], encoder), |
| 227 | 227 | .zi, .oi => try encodeImm(inst.ops[1].imm, data.ops[1], encoder), |
| 228 | 228 | .fd => try encoder.imm64(inst.ops[1].mem.moffs.offset), |
| ... | ... | @@ -300,7 +300,7 @@ pub const Instruction = struct { |
| 300 | 300 | } |
| 301 | 301 | |
| 302 | 302 | const segment_override: ?Register = switch (op_en) { |
| 303 | .i, .zi, .o, .oi, .d, .np => null, | |
| 303 | .zo, .i, .zi, .o, .oi, .d => null, | |
| 304 | 304 | .fd => inst.ops[1].mem.base().reg, |
| 305 | 305 | .td => inst.ops[0].mem.base().reg, |
| 306 | 306 | .rm, .rmi, .rm0 => if (inst.ops[1].isSegmentRegister()) |
| ... | ... | @@ -336,7 +336,7 @@ pub const Instruction = struct { |
| 336 | 336 | rex.w = inst.encoding.data.mode == .long; |
| 337 | 337 | |
| 338 | 338 | switch (op_en) { |
| 339 | .np, .i, .zi, .fd, .td, .d => {}, | |
| 339 | .zo, .i, .zi, .fd, .td, .d => {}, | |
| 340 | 340 | .o, .oi => rex.b = inst.ops[0].reg.isExtended(), |
| 341 | 341 | .m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc, .rm0 => { |
| 342 | 342 | const r_op = switch (op_en) { |
| ... | ... | @@ -370,7 +370,7 @@ pub const Instruction = struct { |
| 370 | 370 | vex.w = inst.encoding.data.mode.isLong(); |
| 371 | 371 | |
| 372 | 372 | switch (op_en) { |
| 373 | .np, .i, .zi, .fd, .td, .d => {}, | |
| 373 | .zo, .i, .zi, .fd, .td, .d => {}, | |
| 374 | 374 | .o, .oi => vex.b = inst.ops[0].reg.isExtended(), |
| 375 | 375 | .m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc, .rm0, .vmi, .rvm, .rvmr, .rvmi, .mvr => { |
| 376 | 376 | const r_op = switch (op_en) { |
src/arch/x86_64/encodings.zig+76-60| ... | ... | @@ -121,17 +121,16 @@ pub const table = [_]Entry{ |
| 121 | 121 | .{ .bts, .mi, &.{ .rm32, .imm8 }, &.{ 0x0f, 0xba }, 5, .none, .none }, |
| 122 | 122 | .{ .bts, .mi, &.{ .rm64, .imm8 }, &.{ 0x0f, 0xba }, 5, .long, .none }, |
| 123 | 123 | |
| 124 | // This is M encoding according to Intel, but D makes more sense here. | |
| 125 | 124 | .{ .call, .d, &.{ .rel32 }, &.{ 0xe8 }, 0, .none, .none }, |
| 126 | 125 | .{ .call, .m, &.{ .rm64 }, &.{ 0xff }, 2, .none, .none }, |
| 127 | 126 | |
| 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 }, | |
| 131 | 130 | |
| 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 }, | |
| 135 | 134 | |
| 136 | 135 | .{ .cmova, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x47 }, 0, .short, .none }, |
| 137 | 136 | .{ .cmova, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x47 }, 0, .none, .none }, |
| ... | ... | @@ -247,15 +246,15 @@ pub const table = [_]Entry{ |
| 247 | 246 | .{ .cmp, .rm, &.{ .r32, .rm32 }, &.{ 0x3b }, 0, .none, .none }, |
| 248 | 247 | .{ .cmp, .rm, &.{ .r64, .rm64 }, &.{ 0x3b }, 0, .long, .none }, |
| 249 | 248 | |
| 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 }, | |
| 254 | 253 | |
| 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 }, | |
| 259 | 258 | |
| 260 | 259 | .{ .cmpxchg, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xb0 }, 0, .none, .none }, |
| 261 | 260 | .{ .cmpxchg, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xb0 }, 0, .rex, .none }, |
| ... | ... | @@ -266,7 +265,7 @@ pub const table = [_]Entry{ |
| 266 | 265 | .{ .cmpxchg8b, .m, &.{ .m64 }, &.{ 0x0f, 0xc7 }, 1, .none, .none }, |
| 267 | 266 | .{ .cmpxchg16b, .m, &.{ .m128 }, &.{ 0x0f, 0xc7 }, 1, .long, .none }, |
| 268 | 267 | |
| 269 | .{ .cpuid, .np, &.{}, &.{ 0x0f, 0xa2 }, 0, .none, .none }, | |
| 268 | .{ .cpuid, .zo, &.{}, &.{ 0x0f, 0xa2 }, 0, .none, .none }, | |
| 270 | 269 | |
| 271 | 270 | .{ .div, .m, &.{ .rm8 }, &.{ 0xf6 }, 6, .none, .none }, |
| 272 | 271 | .{ .div, .m, &.{ .rm8 }, &.{ 0xf6 }, 6, .rex, .none }, |
| ... | ... | @@ -295,7 +294,7 @@ pub const table = [_]Entry{ |
| 295 | 294 | .{ .imul, .rmi, &.{ .r32, .rm32, .imm32 }, &.{ 0x69 }, 0, .none, .none }, |
| 296 | 295 | .{ .imul, .rmi, &.{ .r64, .rm64, .imm32 }, &.{ 0x69 }, 0, .long, .none }, |
| 297 | 296 | |
| 298 | .{ .int3, .np, &.{}, &.{ 0xcc }, 0, .none, .none }, | |
| 297 | .{ .int3, .zo, &.{}, &.{ 0xcc }, 0, .none, .none }, | |
| 299 | 298 | |
| 300 | 299 | .{ .ja, .d, &.{ .rel32 }, &.{ 0x0f, 0x87 }, 0, .none, .none }, |
| 301 | 300 | .{ .jae, .d, &.{ .rel32 }, &.{ 0x0f, 0x83 }, 0, .none, .none }, |
| ... | ... | @@ -336,23 +335,23 @@ pub const table = [_]Entry{ |
| 336 | 335 | .{ .lea, .rm, &.{ .r32, .m }, &.{ 0x8d }, 0, .none, .none }, |
| 337 | 336 | .{ .lea, .rm, &.{ .r64, .m }, &.{ 0x8d }, 0, .long, .none }, |
| 338 | 337 | |
| 339 | .{ .lfence, .np, &.{}, &.{ 0x0f, 0xae, 0xe8 }, 0, .none, .none }, | |
| 338 | .{ .lfence, .zo, &.{}, &.{ 0x0f, 0xae, 0xe8 }, 0, .none, .none }, | |
| 340 | 339 | |
| 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 }, | |
| 345 | 344 | |
| 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 }, | |
| 350 | 349 | |
| 351 | 350 | .{ .lzcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .short, .lzcnt }, |
| 352 | 351 | .{ .lzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .none, .lzcnt }, |
| 353 | 352 | .{ .lzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .long, .lzcnt }, |
| 354 | 353 | |
| 355 | .{ .mfence, .np, &.{}, &.{ 0x0f, 0xae, 0xf0 }, 0, .none, .none }, | |
| 354 | .{ .mfence, .zo, &.{}, &.{ 0x0f, 0xae, 0xf0 }, 0, .none, .none }, | |
| 356 | 355 | |
| 357 | 356 | .{ .mov, .mr, &.{ .rm8, .r8 }, &.{ 0x88 }, 0, .none, .none }, |
| 358 | 357 | .{ .mov, .mr, &.{ .rm8, .r8 }, &.{ 0x88 }, 0, .rex, .none }, |
| ... | ... | @@ -396,15 +395,15 @@ pub const table = [_]Entry{ |
| 396 | 395 | .{ .movbe, .mr, &.{ .m32, .r32 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .none, .movbe }, |
| 397 | 396 | .{ .movbe, .mr, &.{ .m64, .r64 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .long, .movbe }, |
| 398 | 397 | |
| 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 }, | |
| 403 | 402 | |
| 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 }, | |
| 408 | 407 | |
| 409 | 408 | .{ .movsx, .rm, &.{ .r16, .rm8 }, &.{ 0x0f, 0xbe }, 0, .short, .none }, |
| 410 | 409 | .{ .movsx, .rm, &.{ .r16, .rm8 }, &.{ 0x0f, 0xbe }, 0, .rex_short, .none }, |
| ... | ... | @@ -440,7 +439,7 @@ pub const table = [_]Entry{ |
| 440 | 439 | .{ .neg, .m, &.{ .rm32 }, &.{ 0xf7 }, 3, .none, .none }, |
| 441 | 440 | .{ .neg, .m, &.{ .rm64 }, &.{ 0xf7 }, 3, .long, .none }, |
| 442 | 441 | |
| 443 | .{ .nop, .np, &.{}, &.{ 0x90 }, 0, .none, .none }, | |
| 442 | .{ .nop, .zo, &.{}, &.{ 0x90 }, 0, .none, .none }, | |
| 444 | 443 | |
| 445 | 444 | .{ .not, .m, &.{ .rm8 }, &.{ 0xf6 }, 2, .none, .none }, |
| 446 | 445 | .{ .not, .m, &.{ .rm8 }, &.{ 0xf6 }, 2, .rex, .none }, |
| ... | ... | @@ -471,7 +470,7 @@ pub const table = [_]Entry{ |
| 471 | 470 | .{ .@"or", .rm, &.{ .r32, .rm32 }, &.{ 0x0b }, 0, .none, .none }, |
| 472 | 471 | .{ .@"or", .rm, &.{ .r64, .rm64 }, &.{ 0x0b }, 0, .long, .none }, |
| 473 | 472 | |
| 474 | .{ .pause, .np, &.{}, &.{ 0xf3, 0x90 }, 0, .none, .none }, | |
| 473 | .{ .pause, .zo, &.{}, &.{ 0xf3, 0x90 }, 0, .none, .none }, | |
| 475 | 474 | |
| 476 | 475 | .{ .pop, .o, &.{ .r16 }, &.{ 0x58 }, 0, .short, .none }, |
| 477 | 476 | .{ .pop, .o, &.{ .r64 }, &.{ 0x58 }, 0, .none, .none }, |
| ... | ... | @@ -482,6 +481,8 @@ pub const table = [_]Entry{ |
| 482 | 481 | .{ .popcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none, .popcnt }, |
| 483 | 482 | .{ .popcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .long, .popcnt }, |
| 484 | 483 | |
| 484 | .{ .popfq, .zo, &.{}, &.{ 0x9d }, 0, .none, .none }, | |
| 485 | ||
| 485 | 486 | .{ .push, .o, &.{ .r16 }, &.{ 0x50 }, 0, .short, .none }, |
| 486 | 487 | .{ .push, .o, &.{ .r64 }, &.{ 0x50 }, 0, .none, .none }, |
| 487 | 488 | .{ .push, .m, &.{ .rm16 }, &.{ 0xff }, 6, .short, .none }, |
| ... | ... | @@ -490,7 +491,9 @@ pub const table = [_]Entry{ |
| 490 | 491 | .{ .push, .i, &.{ .imm16 }, &.{ 0x68 }, 0, .short, .none }, |
| 491 | 492 | .{ .push, .i, &.{ .imm32 }, &.{ 0x68 }, 0, .none, .none }, |
| 492 | 493 | |
| 493 | .{ .ret, .np, &.{}, &.{ 0xc3 }, 0, .none, .none }, | |
| 494 | .{ .pushfq, .zo, &.{}, &.{ 0x9c }, 0, .none, .none }, | |
| 495 | ||
| 496 | .{ .ret, .zo, &.{}, &.{ 0xc3 }, 0, .none, .none }, | |
| 494 | 497 | |
| 495 | 498 | .{ .rcl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 2, .none, .none }, |
| 496 | 499 | .{ .rcl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 2, .rex, .none }, |
| ... | ... | @@ -611,15 +614,15 @@ pub const table = [_]Entry{ |
| 611 | 614 | .{ .sbb, .rm, &.{ .r32, .rm32 }, &.{ 0x1b }, 0, .none, .none }, |
| 612 | 615 | .{ .sbb, .rm, &.{ .r64, .rm64 }, &.{ 0x1b }, 0, .long, .none }, |
| 613 | 616 | |
| 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 }, | |
| 618 | 621 | |
| 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 }, | |
| 623 | 626 | |
| 624 | 627 | .{ .seta, .m, &.{ .rm8 }, &.{ 0x0f, 0x97 }, 0, .none, .none }, |
| 625 | 628 | .{ .seta, .m, &.{ .rm8 }, &.{ 0x0f, 0x97 }, 0, .rex, .none }, |
| ... | ... | @@ -682,7 +685,7 @@ pub const table = [_]Entry{ |
| 682 | 685 | .{ .setz, .m, &.{ .rm8 }, &.{ 0x0f, 0x94 }, 0, .none, .none }, |
| 683 | 686 | .{ .setz, .m, &.{ .rm8 }, &.{ 0x0f, 0x94 }, 0, .rex, .none }, |
| 684 | 687 | |
| 685 | .{ .sfence, .np, &.{}, &.{ 0x0f, 0xae, 0xf8 }, 0, .none, .none }, | |
| 688 | .{ .sfence, .zo, &.{}, &.{ 0x0f, 0xae, 0xf8 }, 0, .none, .none }, | |
| 686 | 689 | |
| 687 | 690 | .{ .shl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .none, .none }, |
| 688 | 691 | .{ .shl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .rex, .none }, |
| ... | ... | @@ -730,15 +733,15 @@ pub const table = [_]Entry{ |
| 730 | 733 | .{ .shrd, .mrc, &.{ .rm32, .r32, .cl }, &.{ 0x0f, 0xad }, 0, .none, .none }, |
| 731 | 734 | .{ .shrd, .mrc, &.{ .rm64, .r64, .cl }, &.{ 0x0f, 0xad }, 0, .long, .none }, |
| 732 | 735 | |
| 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 }, | |
| 737 | 740 | |
| 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 }, | |
| 742 | 745 | |
| 743 | 746 | .{ .sub, .zi, &.{ .al, .imm8 }, &.{ 0x2c }, 0, .none, .none }, |
| 744 | 747 | .{ .sub, .zi, &.{ .ax, .imm16 }, &.{ 0x2d }, 0, .short, .none }, |
| ... | ... | @@ -763,7 +766,7 @@ pub const table = [_]Entry{ |
| 763 | 766 | .{ .sub, .rm, &.{ .r32, .rm32 }, &.{ 0x2b }, 0, .none, .none }, |
| 764 | 767 | .{ .sub, .rm, &.{ .r64, .rm64 }, &.{ 0x2b }, 0, .long, .none }, |
| 765 | 768 | |
| 766 | .{ .syscall, .np, &.{}, &.{ 0x0f, 0x05 }, 0, .none, .none }, | |
| 769 | .{ .syscall, .zo, &.{}, &.{ 0x0f, 0x05 }, 0, .none, .none }, | |
| 767 | 770 | |
| 768 | 771 | .{ .@"test", .zi, &.{ .al, .imm8 }, &.{ 0xa8 }, 0, .none, .none }, |
| 769 | 772 | .{ .@"test", .zi, &.{ .ax, .imm16 }, &.{ 0xa9 }, 0, .short, .none }, |
| ... | ... | @@ -784,7 +787,7 @@ pub const table = [_]Entry{ |
| 784 | 787 | .{ .tzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .none, .bmi }, |
| 785 | 788 | .{ .tzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .long, .bmi }, |
| 786 | 789 | |
| 787 | .{ .ud2, .np, &.{}, &.{ 0x0f, 0x0b }, 0, .none, .none }, | |
| 790 | .{ .ud2, .zo, &.{}, &.{ 0x0f, 0x0b }, 0, .none, .none }, | |
| 788 | 791 | |
| 789 | 792 | .{ .xadd, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xc0 }, 0, .none, .none }, |
| 790 | 793 | .{ .xadd, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xc0 }, 0, .rex, .none }, |
| ... | ... | @@ -809,7 +812,7 @@ pub const table = [_]Entry{ |
| 809 | 812 | .{ .xchg, .rm, &.{ .r32, .rm32 }, &.{ 0x87 }, 0, .none, .none }, |
| 810 | 813 | .{ .xchg, .rm, &.{ .r64, .rm64 }, &.{ 0x87 }, 0, .long, .none }, |
| 811 | 814 | |
| 812 | .{ .xgetbv, .np, &.{}, &.{ 0x0f, 0x01 }, 0, .none, .none }, | |
| 815 | .{ .xgetbv, .zo, &.{}, &.{ 0x0f, 0x01, 0xd0 }, 0, .none, .none }, | |
| 813 | 816 | |
| 814 | 817 | .{ .xor, .zi, &.{ .al, .imm8 }, &.{ 0x34 }, 0, .none, .none }, |
| 815 | 818 | .{ .xor, .zi, &.{ .ax, .imm16 }, &.{ 0x35 }, 0, .short, .none }, |
| ... | ... | @@ -835,9 +838,9 @@ pub const table = [_]Entry{ |
| 835 | 838 | .{ .xor, .rm, &.{ .r64, .rm64 }, &.{ 0x33 }, 0, .long, .none }, |
| 836 | 839 | |
| 837 | 840 | // X87 |
| 838 | .{ .fabs, .np, &.{}, &.{ 0xd9, 0xe1 }, 0, .none, .x87 }, | |
| 841 | .{ .fabs, .zo, &.{}, &.{ 0xd9, 0xe1 }, 0, .none, .x87 }, | |
| 839 | 842 | |
| 840 | .{ .fchs, .np, &.{}, &.{ 0xd9, 0xe0 }, 0, .none, .x87 }, | |
| 843 | .{ .fchs, .zo, &.{}, &.{ 0xd9, 0xe0 }, 0, .none, .x87 }, | |
| 841 | 844 | |
| 842 | 845 | .{ .ffree, .o, &.{ .st }, &.{ 0xdd, 0xc0 }, 0, .none, .x87 }, |
| 843 | 846 | |
| ... | ... | @@ -850,6 +853,8 @@ pub const table = [_]Entry{ |
| 850 | 853 | .{ .fld, .m, &.{ .m80 }, &.{ 0xdb }, 5, .none, .x87 }, |
| 851 | 854 | .{ .fld, .o, &.{ .st }, &.{ 0xd9, 0xc0 }, 0, .none, .x87 }, |
| 852 | 855 | |
| 856 | .{ .fldenv, .m, &.{ .m }, &.{ 0xd9 }, 4, .none, .x87 }, | |
| 857 | ||
| 853 | 858 | .{ .fst, .m, &.{ .m32 }, &.{ 0xd9 }, 2, .none, .x87 }, |
| 854 | 859 | .{ .fst, .m, &.{ .m64 }, &.{ 0xdd }, 2, .none, .x87 }, |
| 855 | 860 | .{ .fst, .o, &.{ .st }, &.{ 0xdd, 0xd0 }, 0, .none, .x87 }, |
| ... | ... | @@ -858,6 +863,9 @@ pub const table = [_]Entry{ |
| 858 | 863 | .{ .fstp, .m, &.{ .m80 }, &.{ 0xdb }, 7, .none, .x87 }, |
| 859 | 864 | .{ .fstp, .o, &.{ .st }, &.{ 0xdd, 0xd8 }, 0, .none, .x87 }, |
| 860 | 865 | |
| 866 | .{ .fstenv, .m, &.{ .m }, &.{ 0x9b, 0xd9 }, 6, .none, .x87 }, | |
| 867 | .{ .fnstenv, .m, &.{ .m }, &.{ 0xd9 }, 6, .none, .x87 }, | |
| 868 | ||
| 861 | 869 | // SSE |
| 862 | 870 | .{ .addps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x58 }, 0, .none, .sse }, |
| 863 | 871 | |
| ... | ... | @@ -890,6 +898,8 @@ pub const table = [_]Entry{ |
| 890 | 898 | |
| 891 | 899 | .{ .divss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5e }, 0, .none, .sse }, |
| 892 | 900 | |
| 901 | .{ .ldmxcsr, .m, &.{ .m32 }, &.{ 0x0f, 0xae }, 2, .none, .sse }, | |
| 902 | ||
| 893 | 903 | .{ .maxps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5f }, 0, .none, .sse }, |
| 894 | 904 | |
| 895 | 905 | .{ .maxss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5f }, 0, .none, .sse }, |
| ... | ... | @@ -929,6 +939,8 @@ pub const table = [_]Entry{ |
| 929 | 939 | |
| 930 | 940 | .{ .sqrtss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x51 }, 0, .none, .sse }, |
| 931 | 941 | |
| 942 | .{ .stmxcsr, .m, &.{ .m32 }, &.{ 0x0f, 0xae }, 3, .none, .sse }, | |
| 943 | ||
| 932 | 944 | .{ .subps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5c }, 0, .none, .sse }, |
| 933 | 945 | |
| 934 | 946 | .{ .subss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5c }, 0, .none, .sse }, |
| ... | ... | @@ -1365,6 +1377,8 @@ pub const table = [_]Entry{ |
| 1365 | 1377 | |
| 1366 | 1378 | .{ .vinsertps, .rvmi, &.{ .xmm, .xmm, .xmm_m32, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x21 }, 0, .vex_128_wig, .avx }, |
| 1367 | 1379 | |
| 1380 | .{ .vldmxcsr, .m, &.{ .m32 }, &.{ 0x0f, 0xae }, 2, .vex_lz_wig, .avx }, | |
| 1381 | ||
| 1368 | 1382 | .{ .vmaxpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5f }, 0, .vex_128_wig, .avx }, |
| 1369 | 1383 | .{ .vmaxpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5f }, 0, .vex_256_wig, .avx }, |
| 1370 | 1384 | |
| ... | ... | @@ -1635,6 +1649,8 @@ pub const table = [_]Entry{ |
| 1635 | 1649 | |
| 1636 | 1650 | .{ .vsqrtss, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x51 }, 0, .vex_lig_wig, .avx }, |
| 1637 | 1651 | |
| 1652 | .{ .vstmxcsr, .m, &.{ .m32 }, &.{ 0x0f, 0xae }, 3, .vex_lz_wig, .avx }, | |
| 1653 | ||
| 1638 | 1654 | .{ .vsubpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5c }, 0, .vex_128_wig, .avx }, |
| 1639 | 1655 | .{ .vsubpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5c }, 0, .vex_256_wig, .avx }, |
| 1640 | 1656 |
src/codegen.zig+7-1| ... | ... | @@ -850,7 +850,7 @@ fn genDeclRef( |
| 850 | 850 | bin_file: *link.File, |
| 851 | 851 | src_loc: Module.SrcLoc, |
| 852 | 852 | tv: TypedValue, |
| 853 | decl_index: Module.Decl.Index, | |
| 853 | ptr_decl_index: Module.Decl.Index, | |
| 854 | 854 | ) CodeGenError!GenResult { |
| 855 | 855 | const mod = bin_file.options.module.?; |
| 856 | 856 | log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmt(mod), tv.val.fmtValue(tv.ty, mod) }); |
| ... | ... | @@ -859,6 +859,12 @@ fn genDeclRef( |
| 859 | 859 | const ptr_bits = target.ptrBitWidth(); |
| 860 | 860 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 861 | 861 | |
| 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 | }; | |
| 862 | 868 | const decl = mod.declPtr(decl_index); |
| 863 | 869 | |
| 864 | 870 | if (!decl.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) { |
src/link/Coff.zig+1-2| ... | ... | @@ -1461,7 +1461,6 @@ pub fn updateDeclExports( |
| 1461 | 1461 | const decl = mod.declPtr(decl_index); |
| 1462 | 1462 | const atom_index = try self.getOrCreateAtomForDecl(decl_index); |
| 1463 | 1463 | const atom = self.getAtom(atom_index); |
| 1464 | const decl_sym = atom.getSymbol(self); | |
| 1465 | 1464 | const decl_metadata = self.decls.getPtr(decl_index).?; |
| 1466 | 1465 | |
| 1467 | 1466 | for (exports) |exp| { |
| ... | ... | @@ -1505,7 +1504,7 @@ pub fn updateDeclExports( |
| 1505 | 1504 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null }; |
| 1506 | 1505 | const sym = self.getSymbolPtr(sym_loc); |
| 1507 | 1506 | try self.setSymbolName(sym, mod.intern_pool.stringToSlice(exp.opts.name)); |
| 1508 | sym.value = decl_sym.value; | |
| 1507 | sym.value = atom.getSymbol(self).value; | |
| 1509 | 1508 | sym.section_number = @as(coff.SectionNumber, @enumFromInt(self.text_section_index.? + 1)); |
| 1510 | 1509 | sym.type = .{ .complex_type = .FUNCTION, .base_type = .NULL }; |
| 1511 | 1510 |
src/link/Elf.zig+91-23| ... | ... | @@ -48,7 +48,7 @@ phdr_zig_load_zerofill_index: ?u16 = null, |
| 48 | 48 | /// PT_PHDR |
| 49 | 49 | phdr_table_index: ?u16 = null, |
| 50 | 50 | /// 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 | |
| 52 | 52 | /// loaded into memory. |
| 53 | 53 | phdr_table_load_index: ?u16 = null, |
| 54 | 54 | /// PT_INTERP |
| ... | ... | @@ -289,22 +289,33 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option |
| 289 | 289 | .p64 => @alignOf(elf.Elf64_Phdr), |
| 290 | 290 | }; |
| 291 | 291 | const image_base = self.calcImageBase(); |
| 292 | const offset: u64 = switch (self.ptr_width) { | |
| 292 | const ehsize: u64 = switch (self.ptr_width) { | |
| 293 | 293 | .p32 => @sizeOf(elf.Elf32_Ehdr), |
| 294 | 294 | .p64 => @sizeOf(elf.Elf64_Ehdr), |
| 295 | 295 | }; |
| 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); | |
| 296 | 302 | self.phdr_table_index = try self.addPhdr(.{ |
| 297 | 303 | .type = elf.PT_PHDR, |
| 298 | 304 | .flags = elf.PF_R, |
| 299 | 305 | .@"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, | |
| 302 | 310 | }); |
| 303 | 311 | self.phdr_table_load_index = try self.addPhdr(.{ |
| 304 | 312 | .type = elf.PT_LOAD, |
| 305 | 313 | .flags = elf.PF_R, |
| 306 | 314 | .@"align" = self.page_size, |
| 307 | 315 | .addr = image_base, |
| 316 | .offset = 0, | |
| 317 | .filesz = reserved + ehsize, | |
| 318 | .memsz = reserved + ehsize, | |
| 308 | 319 | }); |
| 309 | 320 | } |
| 310 | 321 | |
| ... | ... | @@ -543,7 +554,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { |
| 543 | 554 | const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr); |
| 544 | 555 | const tight_size = self.shdrs.items.len * shdr_size; |
| 545 | 556 | const increased_size = padToIdeal(tight_size); |
| 546 | const test_end = off + increased_size; | |
| 557 | const test_end = off +| increased_size; | |
| 547 | 558 | if (end > off and start < test_end) { |
| 548 | 559 | return test_end; |
| 549 | 560 | } |
| ... | ... | @@ -552,7 +563,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { |
| 552 | 563 | for (self.shdrs.items) |shdr| { |
| 553 | 564 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 554 | 565 | 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; | |
| 556 | 567 | if (end > shdr.sh_offset and start < test_end) { |
| 557 | 568 | return test_end; |
| 558 | 569 | } |
| ... | ... | @@ -561,7 +572,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { |
| 561 | 572 | for (self.phdrs.items) |phdr| { |
| 562 | 573 | if (phdr.p_type != elf.PT_LOAD) continue; |
| 563 | 574 | 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; | |
| 565 | 576 | if (end > phdr.p_offset and start < test_end) { |
| 566 | 577 | return test_end; |
| 567 | 578 | } |
| ... | ... | @@ -653,6 +664,7 @@ pub fn allocateAllocSection(self: *Elf, opts: AllocateAllocSectionOpts) error{Ou |
| 653 | 664 | .type = opts.type, |
| 654 | 665 | .flags = opts.flags, |
| 655 | 666 | .addralign = opts.alignment, |
| 667 | .offset = std.math.maxInt(u64), | |
| 656 | 668 | }); |
| 657 | 669 | const shdr = &self.shdrs.items[index]; |
| 658 | 670 | try self.phdr_to_shdr_table.putNoClobber(gpa, index, opts.phdr_index); |
| ... | ... | @@ -690,6 +702,7 @@ fn allocateNonAllocSection(self: *Elf, opts: AllocateNonAllocSectionOpts) error{ |
| 690 | 702 | .info = opts.info, |
| 691 | 703 | .addralign = opts.alignment, |
| 692 | 704 | .entsize = opts.entsize, |
| 705 | .offset = std.math.maxInt(u64), | |
| 693 | 706 | }); |
| 694 | 707 | const shdr = &self.shdrs.items[index]; |
| 695 | 708 | const off = self.findFreeSpace(opts.size, opts.alignment); |
| ... | ... | @@ -706,6 +719,8 @@ pub fn initMetadata(self: *Elf) !void { |
| 706 | 719 | const ptr_bit_width = self.base.options.target.ptrBitWidth(); |
| 707 | 720 | const is_linux = self.base.options.target.os.tag == .linux; |
| 708 | 721 | |
| 722 | comptime assert(number_of_zig_segments == 5); | |
| 723 | ||
| 709 | 724 | if (self.phdr_zig_load_re_index == null) { |
| 710 | 725 | self.phdr_zig_load_re_index = try self.allocateSegment(.{ |
| 711 | 726 | .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 { |
| 868 | 883 | const is_zerofill = shdr.sh_type == elf.SHT_NOBITS; |
| 869 | 884 | |
| 870 | 885 | 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); | |
| 873 | 886 | const existing_size = shdr.sh_size; |
| 874 | 887 | shdr.sh_size = 0; |
| 888 | // Must move the entire section. | |
| 889 | const new_offset = self.findFreeSpace(needed_size, self.page_size); | |
| 875 | 890 | |
| 876 | 891 | log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{ |
| 877 | 892 | self.shstrtab.getAssumeExists(shdr.sh_name), |
| ... | ... | @@ -1600,7 +1615,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1600 | 1615 | try self.setVersionSymtab(); |
| 1601 | 1616 | try self.updateSectionSizes(); |
| 1602 | 1617 | |
| 1603 | self.allocatePhdrTable(); | |
| 1618 | try self.allocatePhdrTable(); | |
| 1604 | 1619 | try self.allocateAllocSections(); |
| 1605 | 1620 | try self.sortPhdrs(); |
| 1606 | 1621 | try self.allocateNonAllocSections(); |
| ... | ... | @@ -3841,6 +3856,7 @@ fn initSections(self: *Elf) !void { |
| 3841 | 3856 | .type = elf.SHT_PROGBITS, |
| 3842 | 3857 | .flags = elf.SHF_ALLOC, |
| 3843 | 3858 | .addralign = ptr_size, |
| 3859 | .offset = std.math.maxInt(u64), | |
| 3844 | 3860 | }); |
| 3845 | 3861 | |
| 3846 | 3862 | if (self.base.options.eh_frame_hdr) { |
| ... | ... | @@ -3849,6 +3865,7 @@ fn initSections(self: *Elf) !void { |
| 3849 | 3865 | .type = elf.SHT_PROGBITS, |
| 3850 | 3866 | .flags = elf.SHF_ALLOC, |
| 3851 | 3867 | .addralign = 4, |
| 3868 | .offset = std.math.maxInt(u64), | |
| 3852 | 3869 | }); |
| 3853 | 3870 | } |
| 3854 | 3871 | } |
| ... | ... | @@ -3859,6 +3876,7 @@ fn initSections(self: *Elf) !void { |
| 3859 | 3876 | .type = elf.SHT_PROGBITS, |
| 3860 | 3877 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| 3861 | 3878 | .addralign = ptr_size, |
| 3879 | .offset = std.math.maxInt(u64), | |
| 3862 | 3880 | }); |
| 3863 | 3881 | } |
| 3864 | 3882 | |
| ... | ... | @@ -3880,6 +3898,7 @@ fn initSections(self: *Elf) !void { |
| 3880 | 3898 | .flags = elf.SHF_ALLOC, |
| 3881 | 3899 | .addralign = @alignOf(elf.Elf64_Rela), |
| 3882 | 3900 | .entsize = @sizeOf(elf.Elf64_Rela), |
| 3901 | .offset = std.math.maxInt(u64), | |
| 3883 | 3902 | }); |
| 3884 | 3903 | } |
| 3885 | 3904 | |
| ... | ... | @@ -3889,12 +3908,14 @@ fn initSections(self: *Elf) !void { |
| 3889 | 3908 | .type = elf.SHT_PROGBITS, |
| 3890 | 3909 | .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, |
| 3891 | 3910 | .addralign = 16, |
| 3911 | .offset = std.math.maxInt(u64), | |
| 3892 | 3912 | }); |
| 3893 | 3913 | self.got_plt_section_index = try self.addSection(.{ |
| 3894 | 3914 | .name = ".got.plt", |
| 3895 | 3915 | .type = elf.SHT_PROGBITS, |
| 3896 | 3916 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| 3897 | 3917 | .addralign = @alignOf(u64), |
| 3918 | .offset = std.math.maxInt(u64), | |
| 3898 | 3919 | }); |
| 3899 | 3920 | self.rela_plt_section_index = try self.addSection(.{ |
| 3900 | 3921 | .name = ".rela.plt", |
| ... | ... | @@ -3902,6 +3923,7 @@ fn initSections(self: *Elf) !void { |
| 3902 | 3923 | .flags = elf.SHF_ALLOC, |
| 3903 | 3924 | .addralign = @alignOf(elf.Elf64_Rela), |
| 3904 | 3925 | .entsize = @sizeOf(elf.Elf64_Rela), |
| 3926 | .offset = std.math.maxInt(u64), | |
| 3905 | 3927 | }); |
| 3906 | 3928 | } |
| 3907 | 3929 | |
| ... | ... | @@ -3911,6 +3933,7 @@ fn initSections(self: *Elf) !void { |
| 3911 | 3933 | .type = elf.SHT_PROGBITS, |
| 3912 | 3934 | .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, |
| 3913 | 3935 | .addralign = 16, |
| 3936 | .offset = std.math.maxInt(u64), | |
| 3914 | 3937 | }); |
| 3915 | 3938 | } |
| 3916 | 3939 | |
| ... | ... | @@ -3919,6 +3942,7 @@ fn initSections(self: *Elf) !void { |
| 3919 | 3942 | .name = ".copyrel", |
| 3920 | 3943 | .type = elf.SHT_NOBITS, |
| 3921 | 3944 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| 3945 | .offset = std.math.maxInt(u64), | |
| 3922 | 3946 | }); |
| 3923 | 3947 | } |
| 3924 | 3948 | |
| ... | ... | @@ -3937,6 +3961,7 @@ fn initSections(self: *Elf) !void { |
| 3937 | 3961 | .type = elf.SHT_PROGBITS, |
| 3938 | 3962 | .flags = elf.SHF_ALLOC, |
| 3939 | 3963 | .addralign = 1, |
| 3964 | .offset = std.math.maxInt(u64), | |
| 3940 | 3965 | }); |
| 3941 | 3966 | } |
| 3942 | 3967 | |
| ... | ... | @@ -3947,6 +3972,7 @@ fn initSections(self: *Elf) !void { |
| 3947 | 3972 | .type = elf.SHT_STRTAB, |
| 3948 | 3973 | .entsize = 1, |
| 3949 | 3974 | .addralign = 1, |
| 3975 | .offset = std.math.maxInt(u64), | |
| 3950 | 3976 | }); |
| 3951 | 3977 | self.dynamic_section_index = try self.addSection(.{ |
| 3952 | 3978 | .name = ".dynamic", |
| ... | ... | @@ -3954,6 +3980,7 @@ fn initSections(self: *Elf) !void { |
| 3954 | 3980 | .type = elf.SHT_DYNAMIC, |
| 3955 | 3981 | .entsize = @sizeOf(elf.Elf64_Dyn), |
| 3956 | 3982 | .addralign = @alignOf(elf.Elf64_Dyn), |
| 3983 | .offset = std.math.maxInt(u64), | |
| 3957 | 3984 | }); |
| 3958 | 3985 | self.dynsymtab_section_index = try self.addSection(.{ |
| 3959 | 3986 | .name = ".dynsym", |
| ... | ... | @@ -3962,6 +3989,7 @@ fn initSections(self: *Elf) !void { |
| 3962 | 3989 | .addralign = @alignOf(elf.Elf64_Sym), |
| 3963 | 3990 | .entsize = @sizeOf(elf.Elf64_Sym), |
| 3964 | 3991 | .info = 1, |
| 3992 | .offset = std.math.maxInt(u64), | |
| 3965 | 3993 | }); |
| 3966 | 3994 | self.hash_section_index = try self.addSection(.{ |
| 3967 | 3995 | .name = ".hash", |
| ... | ... | @@ -3969,12 +3997,14 @@ fn initSections(self: *Elf) !void { |
| 3969 | 3997 | .type = elf.SHT_HASH, |
| 3970 | 3998 | .addralign = 4, |
| 3971 | 3999 | .entsize = 4, |
| 4000 | .offset = std.math.maxInt(u64), | |
| 3972 | 4001 | }); |
| 3973 | 4002 | self.gnu_hash_section_index = try self.addSection(.{ |
| 3974 | 4003 | .name = ".gnu.hash", |
| 3975 | 4004 | .flags = elf.SHF_ALLOC, |
| 3976 | 4005 | .type = elf.SHT_GNU_HASH, |
| 3977 | 4006 | .addralign = 8, |
| 4007 | .offset = std.math.maxInt(u64), | |
| 3978 | 4008 | }); |
| 3979 | 4009 | |
| 3980 | 4010 | const needs_versions = for (self.dynsym.entries.items) |entry| { |
| ... | ... | @@ -3988,12 +4018,14 @@ fn initSections(self: *Elf) !void { |
| 3988 | 4018 | .type = elf.SHT_GNU_VERSYM, |
| 3989 | 4019 | .addralign = @alignOf(elf.Elf64_Versym), |
| 3990 | 4020 | .entsize = @sizeOf(elf.Elf64_Versym), |
| 4021 | .offset = std.math.maxInt(u64), | |
| 3991 | 4022 | }); |
| 3992 | 4023 | self.verneed_section_index = try self.addSection(.{ |
| 3993 | 4024 | .name = ".gnu.version_r", |
| 3994 | 4025 | .flags = elf.SHF_ALLOC, |
| 3995 | 4026 | .type = elf.SHT_GNU_VERNEED, |
| 3996 | 4027 | .addralign = @alignOf(elf.Elf64_Verneed), |
| 4028 | .offset = std.math.maxInt(u64), | |
| 3997 | 4029 | }); |
| 3998 | 4030 | } |
| 3999 | 4031 | } |
| ... | ... | @@ -4004,6 +4036,7 @@ fn initSections(self: *Elf) !void { |
| 4004 | 4036 | .type = elf.SHT_SYMTAB, |
| 4005 | 4037 | .addralign = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym), |
| 4006 | 4038 | .entsize = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym), |
| 4039 | .offset = std.math.maxInt(u64), | |
| 4007 | 4040 | }); |
| 4008 | 4041 | } |
| 4009 | 4042 | if (self.strtab_section_index == null) { |
| ... | ... | @@ -4012,6 +4045,7 @@ fn initSections(self: *Elf) !void { |
| 4012 | 4045 | .type = elf.SHT_STRTAB, |
| 4013 | 4046 | .entsize = 1, |
| 4014 | 4047 | .addralign = 1, |
| 4048 | .offset = std.math.maxInt(u64), | |
| 4015 | 4049 | }); |
| 4016 | 4050 | } |
| 4017 | 4051 | if (self.shstrtab_section_index == null) { |
| ... | ... | @@ -4020,11 +4054,14 @@ fn initSections(self: *Elf) !void { |
| 4020 | 4054 | .type = elf.SHT_STRTAB, |
| 4021 | 4055 | .entsize = 1, |
| 4022 | 4056 | .addralign = 1, |
| 4057 | .offset = std.math.maxInt(u64), | |
| 4023 | 4058 | }); |
| 4024 | 4059 | } |
| 4025 | 4060 | } |
| 4026 | 4061 | |
| 4027 | 4062 | fn initSpecialPhdrs(self: *Elf) !void { |
| 4063 | comptime assert(max_number_of_special_phdrs == 5); | |
| 4064 | ||
| 4028 | 4065 | if (self.interp_section_index != null) { |
| 4029 | 4066 | self.phdr_interp_index = try self.addPhdr(.{ |
| 4030 | 4067 | .type = elf.PT_INTERP, |
| ... | ... | @@ -4613,6 +4650,21 @@ fn shdrToPhdrFlags(sh_flags: u64) u32 { |
| 4613 | 4650 | return out_flags; |
| 4614 | 4651 | } |
| 4615 | 4652 | |
| 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.) | |
| 4656 | fn 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 | ||
| 4616 | 4668 | /// Calculates how many segments (PT_LOAD progam headers) are required |
| 4617 | 4669 | /// to cover the set of sections. |
| 4618 | 4670 | /// We permit a maximum of 3**2 number of segments. |
| ... | ... | @@ -4633,30 +4685,36 @@ fn calcNumberOfSegments(self: *Elf) usize { |
| 4633 | 4685 | } |
| 4634 | 4686 | |
| 4635 | 4687 | /// Allocates PHDR table in virtual memory and in file. |
| 4636 | fn allocatePhdrTable(self: *Elf) void { | |
| 4688 | fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { | |
| 4637 | 4689 | const new_load_segments = self.calcNumberOfSegments(); |
| 4638 | 4690 | const phdr_table = &self.phdrs.items[self.phdr_table_index.?]; |
| 4639 | 4691 | const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?]; |
| 4640 | 4692 | |
| 4693 | const ehsize: u64 = switch (self.ptr_width) { | |
| 4694 | .p32 => @sizeOf(elf.Elf32_Ehdr), | |
| 4695 | .p64 => @sizeOf(elf.Elf64_Ehdr), | |
| 4696 | }; | |
| 4641 | 4697 | const phsize: u64 = switch (self.ptr_width) { |
| 4642 | 4698 | .p32 => @sizeOf(elf.Elf32_Phdr), |
| 4643 | 4699 | .p64 => @sizeOf(elf.Elf64_Phdr), |
| 4644 | 4700 | }; |
| 4645 | 4701 | const needed_size = (self.phdrs.items.len + new_load_segments) * phsize; |
| 4702 | const available_space = self.allocatedSize(phdr_table.p_offset); | |
| 4646 | 4703 | |
| 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 }); | |
| 4650 | 4713 | } |
| 4651 | 4714 | |
| 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; | |
| 4657 | 4717 | 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; | |
| 4660 | 4718 | phdr_table.p_memsz = needed_size; |
| 4661 | 4719 | } |
| 4662 | 4720 | |
| ... | ... | @@ -4701,7 +4759,7 @@ fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void { |
| 4701 | 4759 | // with `findFreeSpace` mechanics than anything else. |
| 4702 | 4760 | const Cover = std.ArrayList(u16); |
| 4703 | 4761 | const gpa = self.base.allocator; |
| 4704 | var covers: [9]Cover = undefined; | |
| 4762 | var covers: [max_number_of_object_segments]Cover = undefined; | |
| 4705 | 4763 | for (&covers) |*cover| { |
| 4706 | 4764 | cover.* = Cover.init(gpa); |
| 4707 | 4765 | } |
| ... | ... | @@ -5651,6 +5709,7 @@ pub const AddSectionOpts = struct { |
| 5651 | 5709 | info: u32 = 0, |
| 5652 | 5710 | addralign: u64 = 0, |
| 5653 | 5711 | entsize: u64 = 0, |
| 5712 | offset: u64 = 0, | |
| 5654 | 5713 | }; |
| 5655 | 5714 | |
| 5656 | 5715 | pub fn addSection(self: *Elf, opts: AddSectionOpts) !u16 { |
| ... | ... | @@ -5662,7 +5721,7 @@ pub fn addSection(self: *Elf, opts: AddSectionOpts) !u16 { |
| 5662 | 5721 | .sh_type = opts.type, |
| 5663 | 5722 | .sh_flags = opts.flags, |
| 5664 | 5723 | .sh_addr = 0, |
| 5665 | .sh_offset = 0, | |
| 5724 | .sh_offset = opts.offset, | |
| 5666 | 5725 | .sh_size = 0, |
| 5667 | 5726 | .sh_link = opts.link, |
| 5668 | 5727 | .sh_info = opts.info, |
| ... | ... | @@ -6231,6 +6290,15 @@ pub fn lsearch(comptime T: type, haystack: []align(1) const T, predicate: anytyp |
| 6231 | 6290 | return i; |
| 6232 | 6291 | } |
| 6233 | 6292 | |
| 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. | |
| 6298 | const number_of_zig_segments = 5; | |
| 6299 | const max_number_of_object_segments = 9; | |
| 6300 | const max_number_of_special_phdrs = 5; | |
| 6301 | ||
| 6234 | 6302 | const default_entry_addr = 0x8000000; |
| 6235 | 6303 | |
| 6236 | 6304 | pub 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 { |
| 670 | 670 | |
| 671 | 671 | test "128-bit multiplication" { |
| 672 | 672 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 673 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 674 | 673 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 675 | 674 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 676 | 675 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 677 | 676 | 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; | |
| 678 | 678 | if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; |
| 679 | 679 | |
| 680 | 680 | { |
test/tests.zig+1-1| ... | ... | @@ -1006,7 +1006,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { |
| 1006 | 1006 | |
| 1007 | 1007 | // TODO get std lib tests passing for other self-hosted backends. |
| 1008 | 1008 | if ((test_target.target.getCpuArch() != .x86_64 or |
| 1009 | test_target.target.getObjectFormat() != .elf) and | |
| 1009 | test_target.target.getOsTag() != .linux) and | |
| 1010 | 1010 | test_target.use_llvm == false and mem.eql(u8, options.name, "std")) |
| 1011 | 1011 | continue; |
| 1012 | 1012 |