authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-11-04 14:24:59-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-11-04 14:24:59-04:00
loga7d8cd591c47536b0a1e359bf3b1806fc057ffe9
tree069ca321e822ea95d7265ece0b79173832a0745a
parentf6de3ec963e3a7d96cd4f6c72b0f076f0437c45d
parent095c4294aa8b275da0627adefad046923fcaae46
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #17788 from jacobly0/x86_64

x86_64: pass more tests

49 files changed, 1650 insertions(+), 962 deletions(-)

lib/std/Thread/Condition.zig-10
......@@ -324,8 +324,6 @@ test "Condition - wait and signal" {
324324 return error.SkipZigTest;
325325 }
326326
327 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
328
329327 const num_threads = 4;
330328
331329 const MultiWait = struct {
......@@ -371,8 +369,6 @@ test "Condition - signal" {
371369 return error.SkipZigTest;
372370 }
373371
374 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
375
376372 const num_threads = 4;
377373
378374 const SignalTest = struct {
......@@ -440,8 +436,6 @@ test "Condition - multi signal" {
440436 return error.SkipZigTest;
441437 }
442438
443 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
444
445439 const num_threads = 4;
446440 const num_iterations = 4;
447441
......@@ -504,8 +498,6 @@ test "Condition - broadcasting" {
504498 return error.SkipZigTest;
505499 }
506500
507 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
508
509501 const num_threads = 10;
510502
511503 const BroadcastTest = struct {
......@@ -573,8 +565,6 @@ test "Condition - broadcasting - wake all threads" {
573565 return error.SkipZigTest;
574566 }
575567
576 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
577
578568 var num_runs: usize = 1;
579569 const num_threads = 10;
580570
lib/std/Thread/Mutex.zig-2
......@@ -289,8 +289,6 @@ test "Mutex - many contended" {
289289 return error.SkipZigTest;
290290 }
291291
292 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
293
294292 const num_threads = 4;
295293 const num_increments = 1000;
296294
lib/std/Thread/RwLock.zig-2
......@@ -297,8 +297,6 @@ test "RwLock - concurrent access" {
297297 if (builtin.single_threaded)
298298 return;
299299
300 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
301
302300 const num_writers: usize = 2;
303301 const num_readers: usize = 4;
304302 const num_writes: usize = 10000;
lib/std/Thread/Semaphore.zig-2
......@@ -39,8 +39,6 @@ test "Thread.Semaphore" {
3939 return error.SkipZigTest;
4040 }
4141
42 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
43
4442 const TestContext = struct {
4543 sem: *Semaphore,
4644 n: *i32,
lib/std/atomic/Atomic.zig-2
......@@ -467,8 +467,6 @@ test "Atomic.fetchSub" {
467467}
468468
469469test "Atomic.fetchMin" {
470 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
471
472470 inline for (atomicIntTypes()) |Int| {
473471 inline for (atomic_rmw_orderings) |ordering| {
474472 var x = Atomic(Int).init(5);
lib/std/atomic/queue.zig-2
......@@ -175,8 +175,6 @@ const puts_per_thread = 500;
175175const put_thread_count = 3;
176176
177177test "std.atomic.Queue" {
178 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
179
180178 var plenty_of_memory = try std.heap.page_allocator.alloc(u8, 300 * 1024);
181179 defer std.heap.page_allocator.free(plenty_of_memory);
182180
lib/std/base64.zig-4
......@@ -355,8 +355,6 @@ pub const Base64DecoderWithIgnore = struct {
355355};
356356
357357test "base64" {
358 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
359
360358 @setEvalBranchQuota(8000);
361359 try testBase64();
362360 try comptime testAllApis(standard, "comptime", "Y29tcHRpbWU=");
......@@ -377,8 +375,6 @@ test "base64 padding dest overflow" {
377375}
378376
379377test "base64 url_safe_no_pad" {
380 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
381
382378 @setEvalBranchQuota(8000);
383379 try testBase64UrlSafeNoPad();
384380 try comptime testAllApis(url_safe_no_pad, "comptime", "Y29tcHRpbWU");
lib/std/bit_set.zig-3
......@@ -1638,7 +1638,6 @@ fn testStaticBitSet(comptime Set: type) !void {
16381638
16391639test "IntegerBitSet" {
16401640 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1641 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
16421641
16431642 try testStaticBitSet(IntegerBitSet(0));
16441643 try testStaticBitSet(IntegerBitSet(1));
......@@ -1651,8 +1650,6 @@ test "IntegerBitSet" {
16511650}
16521651
16531652test "ArrayBitSet" {
1654 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1655
16561653 inline for (.{ 0, 1, 2, 31, 32, 33, 63, 64, 65, 254, 500, 3000 }) |size| {
16571654 try testStaticBitSet(ArrayBitSet(u8, size));
16581655 try testStaticBitSet(ArrayBitSet(u16, size));
lib/std/compress/zstandard.zig-2
......@@ -264,8 +264,6 @@ fn testReader(data: []const u8, comptime expected: []const u8) !void {
264264}
265265
266266test "zstandard decompression" {
267 if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
268
269267 const uncompressed = @embedFile("testdata/rfc8478.txt");
270268 const compressed3 = @embedFile("testdata/rfc8478.txt.zst.3");
271269 const compressed19 = @embedFile("testdata/rfc8478.txt.zst.19");
lib/std/crypto/25519/ed25519.zig+2-13
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const crypto = std.crypto;
43const debug = std.debug;
54const fmt = std.fmt;
......@@ -276,8 +275,8 @@ pub const Ed25519 = struct {
276275 pub fn fromSecretKey(secret_key: SecretKey) (NonCanonicalError || EncodingError || IdentityElementError)!KeyPair {
277276 // It is critical for EdDSA to use the correct public key.
278277 // In order to enforce this, a SecretKey implicitly includes a copy of the public key.
279 // In Debug mode, we can still afford checking that the public key is correct for extra safety.
280 if (builtin.mode == .Debug) {
278 // With runtime safety, we can still afford checking that the public key is correct.
279 if (std.debug.runtime_safety) {
281280 const pk_p = try Curve.fromBytes(secret_key.publicKeyBytes());
282281 const recomputed_kp = try create(secret_key.seed());
283282 debug.assert(mem.eql(u8, &recomputed_kp.public_key.toBytes(), &pk_p.toBytes()));
......@@ -493,8 +492,6 @@ test "ed25519 key pair creation" {
493492}
494493
495494test "ed25519 signature" {
496 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
497
498495 var seed: [32]u8 = undefined;
499496 _ = try fmt.hexToBytes(seed[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");
500497 const key_pair = try Ed25519.KeyPair.create(seed);
......@@ -507,8 +504,6 @@ test "ed25519 signature" {
507504}
508505
509506test "ed25519 batch verification" {
510 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
511
512507 var i: usize = 0;
513508 while (i < 100) : (i += 1) {
514509 const key_pair = try Ed25519.KeyPair.create(null);
......@@ -538,8 +533,6 @@ test "ed25519 batch verification" {
538533}
539534
540535test "ed25519 test vectors" {
541 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
542
543536 const Vec = struct {
544537 msg_hex: *const [64:0]u8,
545538 public_key_hex: *const [64:0]u8,
......@@ -642,8 +635,6 @@ test "ed25519 test vectors" {
642635}
643636
644637test "ed25519 with blind keys" {
645 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
646
647638 const BlindKeyPair = Ed25519.key_blinding.BlindKeyPair;
648639
649640 // Create a standard Ed25519 key pair
......@@ -667,8 +658,6 @@ test "ed25519 with blind keys" {
667658}
668659
669660test "ed25519 signatures with streaming" {
670 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
671
672661 const kp = try Ed25519.KeyPair.create(null);
673662
674663 var signer = try kp.signer(null);
lib/std/crypto/Certificate.zig+13-13
......@@ -614,18 +614,18 @@ const Date = struct {
614614};
615615
616616pub fn parseTimeDigits(text: *const [2]u8, min: u8, max: u8) !u8 {
617 const nn: @Vector(2, u16) = .{ text[0], text[1] };
618 const zero: @Vector(2, u16) = .{ '0', '0' };
619 const mm: @Vector(2, u16) = .{ 10, 1 };
620 const result = @reduce(.Add, (nn -% zero) *% mm);
617 const result = if (use_vectors) result: {
618 const nn: @Vector(2, u16) = .{ text[0], text[1] };
619 const zero: @Vector(2, u16) = .{ '0', '0' };
620 const mm: @Vector(2, u16) = .{ 10, 1 };
621 break :result @reduce(.Add, (nn -% zero) *% mm);
622 } else std.fmt.parseInt(u8, text, 10) catch return error.CertificateTimeInvalid;
621623 if (result < min) return error.CertificateTimeInvalid;
622624 if (result > max) return error.CertificateTimeInvalid;
623625 return @truncate(result);
624626}
625627
626628test parseTimeDigits {
627 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
628
629629 const expectEqual = std.testing.expectEqual;
630630 try expectEqual(@as(u8, 0), try parseTimeDigits("00", 0, 99));
631631 try expectEqual(@as(u8, 99), try parseTimeDigits("99", 0, 99));
......@@ -638,17 +638,17 @@ test parseTimeDigits {
638638}
639639
640640pub fn parseYear4(text: *const [4]u8) !u16 {
641 const nnnn: @Vector(4, u32) = .{ text[0], text[1], text[2], text[3] };
642 const zero: @Vector(4, u32) = .{ '0', '0', '0', '0' };
643 const mmmm: @Vector(4, u32) = .{ 1000, 100, 10, 1 };
644 const result = @reduce(.Add, (nnnn -% zero) *% mmmm);
641 const result = if (use_vectors) result: {
642 const nnnn: @Vector(4, u32) = .{ text[0], text[1], text[2], text[3] };
643 const zero: @Vector(4, u32) = .{ '0', '0', '0', '0' };
644 const mmmm: @Vector(4, u32) = .{ 1000, 100, 10, 1 };
645 break :result @reduce(.Add, (nnnn -% zero) *% mmmm);
646 } else std.fmt.parseInt(u16, text, 10) catch return error.CertificateTimeInvalid;
645647 if (result > 9999) return error.CertificateTimeInvalid;
646648 return @truncate(result);
647649}
648650
649651test parseYear4 {
650 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
651
652652 const expectEqual = std.testing.expectEqual;
653653 try expectEqual(@as(u16, 0), try parseYear4("0000"));
654654 try expectEqual(@as(u16, 9999), try parseYear4("9999"));
......@@ -1124,4 +1124,4 @@ pub const rsa = struct {
11241124 }
11251125};
11261126
1127const builtin = @import("builtin");
1127const use_vectors = @import("builtin").zig_backend != .stage2_x86_64;
lib/std/crypto/Certificate/Bundle.zig-2
......@@ -318,8 +318,6 @@ const MapContext = struct {
318318test "scan for OS-provided certificates" {
319319 if (builtin.os.tag == .wasi) return error.SkipZigTest;
320320
321 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
322
323321 var bundle: Bundle = .{};
324322 defer bundle.deinit(std.testing.allocator);
325323
lib/std/crypto/aes.zig-2
......@@ -28,8 +28,6 @@ pub const Aes128 = impl.Aes128;
2828pub const Aes256 = impl.Aes256;
2929
3030test "ctr" {
31 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
32
3331 // NIST SP 800-38A pp 55-58
3432 const ctr = @import("modes.zig").ctr;
3533
lib/std/crypto/aes_gcm.zig+2-11
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const assert = std.debug.assert;
43const crypto = std.crypto;
54const debug = std.debug;
......@@ -42,7 +41,7 @@ fn AesGcm(comptime Aes: anytype) type {
4241 mac.pad();
4342
4443 mem.writeInt(u32, j[nonce_length..][0..4], 2, .big);
45 modes.ctr(@TypeOf(aes), aes, c, m, j, std.builtin.Endian.big);
44 modes.ctr(@TypeOf(aes), aes, c, m, j, .big);
4645 mac.update(c[0..m.len][0..]);
4746 mac.pad();
4847
......@@ -104,7 +103,7 @@ fn AesGcm(comptime Aes: anytype) type {
104103 }
105104
106105 mem.writeInt(u32, j[nonce_length..][0..4], 2, .big);
107 modes.ctr(@TypeOf(aes), aes, m, c, j, std.builtin.Endian.big);
106 modes.ctr(@TypeOf(aes), aes, m, c, j, .big);
108107 }
109108 };
110109}
......@@ -113,8 +112,6 @@ const htest = @import("test.zig");
113112const testing = std.testing;
114113
115114test "Aes256Gcm - Empty message and no associated data" {
116 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
117
118115 const key: [Aes256Gcm.key_length]u8 = [_]u8{0x69} ** Aes256Gcm.key_length;
119116 const nonce: [Aes256Gcm.nonce_length]u8 = [_]u8{0x42} ** Aes256Gcm.nonce_length;
120117 const ad = "";
......@@ -127,8 +124,6 @@ test "Aes256Gcm - Empty message and no associated data" {
127124}
128125
129126test "Aes256Gcm - Associated data only" {
130 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
131
132127 const key: [Aes256Gcm.key_length]u8 = [_]u8{0x69} ** Aes256Gcm.key_length;
133128 const nonce: [Aes256Gcm.nonce_length]u8 = [_]u8{0x42} ** Aes256Gcm.nonce_length;
134129 const m = "";
......@@ -141,8 +136,6 @@ test "Aes256Gcm - Associated data only" {
141136}
142137
143138test "Aes256Gcm - Message only" {
144 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
145
146139 const key: [Aes256Gcm.key_length]u8 = [_]u8{0x69} ** Aes256Gcm.key_length;
147140 const nonce: [Aes256Gcm.nonce_length]u8 = [_]u8{0x42} ** Aes256Gcm.nonce_length;
148141 const m = "Test with message only";
......@@ -160,8 +153,6 @@ test "Aes256Gcm - Message only" {
160153}
161154
162155test "Aes256Gcm - Message and associated data" {
163 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
164
165156 const key: [Aes256Gcm.key_length]u8 = [_]u8{0x69} ** Aes256Gcm.key_length;
166157 const nonce: [Aes256Gcm.nonce_length]u8 = [_]u8{0x42} ** Aes256Gcm.nonce_length;
167158 const m = "Test with message";
lib/std/crypto/argon2.zig-4
......@@ -896,8 +896,6 @@ test "kdf" {
896896}
897897
898898test "phc format hasher" {
899 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
900
901899 const allocator = std.testing.allocator;
902900 const password = "testpass";
903901
......@@ -913,8 +911,6 @@ test "phc format hasher" {
913911}
914912
915913test "password hash and password verify" {
916 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
917
918914 const allocator = std.testing.allocator;
919915 const password = "testpass";
920916
lib/std/crypto/bcrypt.zig-7
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const base64 = std.base64;
43const crypto = std.crypto;
54const debug = std.debug;
......@@ -754,8 +753,6 @@ pub fn strVerify(
754753}
755754
756755test "bcrypt codec" {
757 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
758
759756 var salt: [salt_length]u8 = undefined;
760757 crypto.random.bytes(&salt);
761758 var salt_str: [salt_str_length]u8 = undefined;
......@@ -766,8 +763,6 @@ test "bcrypt codec" {
766763}
767764
768765test "bcrypt crypt format" {
769 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
770
771766 var hash_options = HashOptions{
772767 .params = .{ .rounds_log = 5 },
773768 .encoding = .crypt,
......@@ -808,8 +803,6 @@ test "bcrypt crypt format" {
808803}
809804
810805test "bcrypt phc format" {
811 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
812
813806 var hash_options = HashOptions{
814807 .params = .{ .rounds_log = 5 },
815808 .encoding = .phc,
lib/std/crypto/cmac.zig-9
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const crypto = std.crypto;
43const mem = std.mem;
54
......@@ -94,8 +93,6 @@ pub fn Cmac(comptime BlockCipher: type) type {
9493const testing = std.testing;
9594
9695test "CmacAes128 - Example 1: len = 0" {
97 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
98
9996 const key = [_]u8{
10097 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
10198 };
......@@ -109,8 +106,6 @@ test "CmacAes128 - Example 1: len = 0" {
109106}
110107
111108test "CmacAes128 - Example 2: len = 16" {
112 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
113
114109 const key = [_]u8{
115110 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
116111 };
......@@ -126,8 +121,6 @@ test "CmacAes128 - Example 2: len = 16" {
126121}
127122
128123test "CmacAes128 - Example 3: len = 40" {
129 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
130
131124 const key = [_]u8{
132125 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
133126 };
......@@ -145,8 +138,6 @@ test "CmacAes128 - Example 3: len = 40" {
145138}
146139
147140test "CmacAes128 - Example 4: len = 64" {
148 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
149
150141 const key = [_]u8{
151142 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
152143 };
lib/std/crypto/ecdsa.zig-5
......@@ -373,7 +373,6 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type {
373373
374374test "ECDSA - Basic operations over EcdsaP384Sha384" {
375375 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
376 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
377376
378377 const Scheme = EcdsaP384Sha384;
379378 const kp = try Scheme.KeyPair.create(null);
......@@ -407,7 +406,6 @@ test "ECDSA - Basic operations over Secp256k1" {
407406
408407test "ECDSA - Basic operations over EcdsaP384Sha256" {
409408 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
410 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
411409
412410 const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256);
413411 const kp = try Scheme.KeyPair.create(null);
......@@ -424,7 +422,6 @@ test "ECDSA - Basic operations over EcdsaP384Sha256" {
424422
425423test "ECDSA - Verifying a existing signature with EcdsaP384Sha256" {
426424 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
427 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
428425
429426 const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256);
430427 // zig fmt: off
......@@ -469,7 +466,6 @@ const TestVector = struct {
469466
470467test "ECDSA - Test vectors from Project Wycheproof" {
471468 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
472 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
473469
474470 const vectors = [_]TestVector{
475471 .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1802204cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd76", .result = .valid },
......@@ -884,7 +880,6 @@ fn tvTry(vector: TestVector) !void {
884880
885881test "ECDSA - Sec1 encoding/decoding" {
886882 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
887 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
888883
889884 const Scheme = EcdsaP384Sha384;
890885 const kp = try Scheme.KeyPair.create(null);
lib/std/crypto/ghash_polyval.zig-4
......@@ -422,8 +422,6 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type {
422422const htest = @import("test.zig");
423423
424424test "ghash" {
425 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
426
427425 const key = [_]u8{0x42} ** 16;
428426 const m = [_]u8{0x69} ** 256;
429427
......@@ -441,8 +439,6 @@ test "ghash" {
441439}
442440
443441test "ghash2" {
444 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
445
446442 var key: [16]u8 = undefined;
447443 var i: usize = 0;
448444 while (i < key.len) : (i += 1) {
lib/std/crypto/pcurves/p256.zig-2
......@@ -478,7 +478,5 @@ pub const AffineCoordinates = struct {
478478};
479479
480480test {
481 if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
482
483481 _ = @import("tests/p256.zig");
484482}
lib/std/crypto/phc_encoding.zig-3
......@@ -1,7 +1,6 @@
11// https://github.com/P-H-C/phc-string-format
22
33const std = @import("std");
4const builtin = @import("builtin");
54const fmt = std.fmt;
65const io = std.io;
76const mem = std.mem;
......@@ -264,8 +263,6 @@ fn kvSplit(str: []const u8) !struct { key: []const u8, value: []const u8 } {
264263}
265264
266265test "phc format - encoding/decoding" {
267 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
268
269266 const Input = struct {
270267 str: []const u8,
271268 HashResult: type,
lib/std/crypto/sha2.zig+1-1
......@@ -238,7 +238,7 @@ fn Sha2x32(comptime params: Sha2Params32) type {
238238 return;
239239 },
240240 // C backend doesn't currently support passing vectors to inline asm.
241 .x86_64 => if (builtin.zig_backend != .stage2_c and comptime std.Target.x86.featureSetHasAll(builtin.cpu.features, .{ .sha, .avx2 })) {
241 .x86_64 => if (builtin.zig_backend != .stage2_c and builtin.zig_backend != .stage2_x86_64 and comptime std.Target.x86.featureSetHasAll(builtin.cpu.features, .{ .sha, .avx2 })) {
242242 var x: v4u32 = [_]u32{ d.s[5], d.s[4], d.s[1], d.s[0] };
243243 var y: v4u32 = [_]u32{ d.s[7], d.s[6], d.s[3], d.s[2] };
244244 const s_v = @as(*[16]v4u32, @ptrCast(&s));
lib/std/fmt/parse_float.zig-2
......@@ -83,8 +83,6 @@ test "fmt.parseFloat #11169" {
8383}
8484
8585test "fmt.parseFloat hex.special" {
86 if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
87
8886 try testing.expect(math.isNan(try parseFloat(f32, "nAn")));
8987 try testing.expect(math.isPositiveInf(try parseFloat(f32, "iNf")));
9088 try testing.expect(math.isPositiveInf(try parseFloat(f32, "+Inf")));
lib/std/hash/xxhash.zig+2-1
......@@ -2,6 +2,7 @@ const std = @import("std");
22const builtin = @import("builtin");
33const mem = std.mem;
44const expectEqual = std.testing.expectEqual;
5const native_endian = builtin.cpu.arch.endian();
56
67const rotl = std.math.rotl;
78
......@@ -472,7 +473,7 @@ pub const XxHash3 = struct {
472473 }
473474
474475 inline fn swap(x: anytype) @TypeOf(x) {
475 return if (builtin.cpu.arch.endian() == .big) @byteSwap(x) else x;
476 return if (native_endian == .big) @byteSwap(x) else x;
476477 }
477478
478479 inline fn disableAutoVectorization(x: anytype) void {
lib/std/http/Client.zig+16-10
......@@ -9,6 +9,7 @@ const net = std.net;
99const Uri = std.Uri;
1010const Allocator = mem.Allocator;
1111const assert = std.debug.assert;
12const use_vectors = builtin.zig_backend != .stage2_x86_64;
1213
1314const Client = @This();
1415const proto = @import("protocol.zig");
......@@ -408,7 +409,7 @@ pub const Response = struct {
408409 else => return error.HttpHeadersInvalid,
409410 };
410411 if (first_line[8] != ' ') return error.HttpHeadersInvalid;
411 const status = @as(http.Status, @enumFromInt(parseInt3(first_line[9..12].*)));
412 const status: http.Status = @enumFromInt(parseInt3(first_line[9..12]));
412413 const reason = mem.trimLeft(u8, first_line[12..], " ");
413414
414415 res.version = version;
......@@ -481,20 +482,24 @@ pub const Response = struct {
481482 }
482483
483484 inline fn int64(array: *const [8]u8) u64 {
484 return @as(u64, @bitCast(array.*));
485 return @bitCast(array.*);
485486 }
486487
487 fn parseInt3(nnn: @Vector(3, u8)) u10 {
488 const zero: @Vector(3, u8) = .{ '0', '0', '0' };
489 const mmm: @Vector(3, u10) = .{ 100, 10, 1 };
490 return @reduce(.Add, @as(@Vector(3, u10), nnn -% zero) *% mmm);
488 fn parseInt3(text: *const [3]u8) u10 {
489 if (use_vectors) {
490 const nnn: @Vector(3, u8) = text.*;
491 const zero: @Vector(3, u8) = .{ '0', '0', '0' };
492 const mmm: @Vector(3, u10) = .{ 100, 10, 1 };
493 return @reduce(.Add, @as(@Vector(3, u10), nnn -% zero) *% mmm);
494 }
495 return std.fmt.parseInt(u10, text, 10) catch unreachable;
491496 }
492497
493498 test parseInt3 {
494499 const expectEqual = testing.expectEqual;
495 try expectEqual(@as(u10, 0), parseInt3("000".*));
496 try expectEqual(@as(u10, 418), parseInt3("418".*));
497 try expectEqual(@as(u10, 999), parseInt3("999".*));
500 try expectEqual(@as(u10, 0), parseInt3("000"));
501 try expectEqual(@as(u10, 418), parseInt3("418"));
502 try expectEqual(@as(u10, 999), parseInt3("999"));
498503 }
499504
500505 version: http.Version,
......@@ -1588,7 +1593,8 @@ test {
15881593
15891594 if (builtin.os.tag == .wasi) return error.SkipZigTest;
15901595
1591 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1596 if (builtin.zig_backend == .stage2_x86_64 and
1597 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .avx)) return error.SkipZigTest;
15921598
15931599 std.testing.refAllDecls(@This());
15941600}
lib/std/http/Server.zig-2
......@@ -736,8 +736,6 @@ test "HTTP server handles a chunked transfer coding request" {
736736 return error.SkipZigTest;
737737 }
738738
739 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
740
741739 const native_endian = comptime builtin.cpu.arch.endian();
742740 if (builtin.zig_backend == .stage2_llvm and native_endian == .big) {
743741 // https://github.com/ziglang/zig/issues/13782
lib/std/http/protocol.zig+23-12
......@@ -1,8 +1,10 @@
11const std = @import("../std.zig");
2const builtin = @import("builtin");
23const testing = std.testing;
34const mem = std.mem;
45
56const assert = std.debug.assert;
7const use_vectors = builtin.zig_backend != .stage2_x86_64;
68
79pub const State = enum {
810 /// Begin header parsing states.
......@@ -83,7 +85,7 @@ pub const HeadersParser = struct {
8385 /// first byte of content is located at `bytes[result]`.
8486 pub fn findHeadersEnd(r: *HeadersParser, bytes: []const u8) u32 {
8587 const vector_len: comptime_int = @max(std.simd.suggestVectorSize(u8) orelse 1, 8);
86 const len = @as(u32, @intCast(bytes.len));
88 const len: u32 = @intCast(bytes.len);
8789 var index: u32 = 0;
8890
8991 while (true) {
......@@ -175,18 +177,27 @@ pub const HeadersParser = struct {
175177 continue;
176178 },
177179 else => {
178 const Vector = @Vector(vector_len, u8);
179 // const BoolVector = @Vector(vector_len, bool);
180 const BitVector = @Vector(vector_len, u1);
181 const SizeVector = @Vector(vector_len, u8);
182
183180 const chunk = bytes[index..][0..vector_len];
184 const v: Vector = chunk.*;
185 const matches_r = @as(BitVector, @bitCast(v == @as(Vector, @splat('\r'))));
186 const matches_n = @as(BitVector, @bitCast(v == @as(Vector, @splat('\n'))));
187 const matches_or: SizeVector = matches_r | matches_n;
188
189 const matches = @reduce(.Add, matches_or);
181 const matches = if (use_vectors) matches: {
182 const Vector = @Vector(vector_len, u8);
183 // const BoolVector = @Vector(vector_len, bool);
184 const BitVector = @Vector(vector_len, u1);
185 const SizeVector = @Vector(vector_len, u8);
186
187 const v: Vector = chunk.*;
188 const matches_r: BitVector = @bitCast(v == @as(Vector, @splat('\r')));
189 const matches_n: BitVector = @bitCast(v == @as(Vector, @splat('\n')));
190 const matches_or: SizeVector = matches_r | matches_n;
191
192 break :matches @reduce(.Add, matches_or);
193 } else matches: {
194 var matches: u8 = 0;
195 for (chunk) |byte| switch (byte) {
196 '\r', '\n' => matches += 1,
197 else => {},
198 };
199 break :matches matches;
200 };
190201 switch (matches) {
191202 0 => {},
192203 1 => switch (chunk[vector_len - 1]) {
lib/std/math.zig+2-21
......@@ -492,8 +492,6 @@ pub fn shl(comptime T: type, a: T, shift_amt: anytype) T {
492492}
493493
494494test "shl" {
495 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
496
497495 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
498496 // https://github.com/ziglang/zig/issues/12012
499497 return error.SkipZigTest;
......@@ -539,8 +537,6 @@ pub fn shr(comptime T: type, a: T, shift_amt: anytype) T {
539537}
540538
541539test "shr" {
542 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
543
544540 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
545541 // https://github.com/ziglang/zig/issues/12012
546542 return error.SkipZigTest;
......@@ -587,8 +583,6 @@ pub fn rotr(comptime T: type, x: T, r: anytype) T {
587583}
588584
589585test "rotr" {
590 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
591
592586 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
593587 // https://github.com/ziglang/zig/issues/12012
594588 return error.SkipZigTest;
......@@ -634,8 +628,6 @@ pub fn rotl(comptime T: type, x: T, r: anytype) T {
634628}
635629
636630test "rotl" {
637 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
638
639631 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
640632 // https://github.com/ziglang/zig/issues/12012
641633 return error.SkipZigTest;
......@@ -764,8 +756,6 @@ pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T {
764756}
765757
766758test "divTrunc" {
767 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
768
769759 try testDivTrunc();
770760 try comptime testDivTrunc();
771761}
......@@ -790,8 +780,6 @@ pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T {
790780}
791781
792782test "divFloor" {
793 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
794
795783 try testDivFloor();
796784 try comptime testDivFloor();
797785}
......@@ -829,8 +817,6 @@ pub fn divCeil(comptime T: type, numerator: T, denominator: T) !T {
829817}
830818
831819test "divCeil" {
832 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
833
834820 try testDivCeil();
835821 try comptime testDivCeil();
836822}
......@@ -875,8 +861,6 @@ pub fn divExact(comptime T: type, numerator: T, denominator: T) !T {
875861}
876862
877863test "divExact" {
878 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
879
880864 try testDivExact();
881865 try comptime testDivExact();
882866}
......@@ -903,8 +887,6 @@ pub fn mod(comptime T: type, numerator: T, denominator: T) !T {
903887}
904888
905889test "mod" {
906 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
907
908890 try testMod();
909891 try comptime testMod();
910892}
......@@ -931,8 +913,6 @@ pub fn rem(comptime T: type, numerator: T, denominator: T) !T {
931913}
932914
933915test "rem" {
934 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
935
936916 try testRem();
937917 try comptime testRem();
938918}
......@@ -1285,7 +1265,8 @@ pub fn lerp(a: anytype, b: anytype, t: anytype) @TypeOf(a, b, t) {
12851265}
12861266
12871267test "lerp" {
1288 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1268 if (builtin.zig_backend == .stage2_x86_64 and
1269 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .fma)) return error.SkipZigTest;
12891270
12901271 try testing.expectEqual(@as(f64, 75), lerp(50, 100, 0.5));
12911272 try testing.expectEqual(@as(f32, 43.75), lerp(50, 25, 0.25));
lib/std/math/big/int.zig+3-3
......@@ -1318,7 +1318,7 @@ pub const Mutable = struct {
13181318 ///
13191319 /// `limbs_buffer` is used for temporary storage.
13201320 /// The amount required is given by `calcPowLimbsBufferLen`.
1321 pub fn pow(r: *Mutable, a: Const, b: u32, limbs_buffer: []Limb) !void {
1321 pub fn pow(r: *Mutable, a: Const, b: u32, limbs_buffer: []Limb) void {
13221322 assert(r.limbs.ptr != a.limbs.ptr); // illegal aliasing
13231323
13241324 // Handle all the trivial cases first
......@@ -3213,7 +3213,7 @@ pub const Managed = struct {
32133213 var m = try Managed.initCapacity(rma.allocator, needed_limbs);
32143214 errdefer m.deinit();
32153215 var m_mut = m.toMutable();
3216 try m_mut.pow(a.toConst(), b, limbs_buffer);
3216 m_mut.pow(a.toConst(), b, limbs_buffer);
32173217 m.setMetadata(m_mut.positive, m_mut.len);
32183218
32193219 rma.deinit();
......@@ -3221,7 +3221,7 @@ pub const Managed = struct {
32213221 } else {
32223222 try rma.ensureCapacity(needed_limbs);
32233223 var rma_mut = rma.toMutable();
3224 try rma_mut.pow(a.toConst(), b, limbs_buffer);
3224 rma_mut.pow(a.toConst(), b, limbs_buffer);
32253225 rma.setMetadata(rma_mut.positive, rma_mut.len);
32263226 }
32273227 }
lib/std/math/big/int_test.zig-6
......@@ -2568,8 +2568,6 @@ test "big.int const to managed" {
25682568}
25692569
25702570test "big.int pow" {
2571 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2572
25732571 {
25742572 var a = try Managed.initSet(testing.allocator, -3);
25752573 defer a.deinit();
......@@ -2763,8 +2761,6 @@ fn popCountTest(val: *const Managed, bit_count: usize, expected: usize) !void {
27632761}
27642762
27652763test "big int conversion read/write twos complement" {
2766 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2767
27682764 var a = try Managed.initSet(testing.allocator, (1 << 493) - 1);
27692765 defer a.deinit();
27702766 var b = try Managed.initSet(testing.allocator, (1 << 493) - 1);
......@@ -2863,8 +2859,6 @@ test "big int write twos complement +/- zero" {
28632859}
28642860
28652861test "big int conversion write twos complement with padding" {
2866 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2867
28682862 var a = try Managed.initSet(testing.allocator, 0x01_ffffffff_ffffffff_ffffffff);
28692863 defer a.deinit();
28702864
lib/std/mem.zig-4
......@@ -315,8 +315,6 @@ pub fn zeroes(comptime T: type) T {
315315}
316316
317317test "zeroes" {
318 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
319
320318 const C_struct = extern struct {
321319 x: u32,
322320 y: u32 align(128),
......@@ -4342,8 +4340,6 @@ pub fn alignInSlice(slice: anytype, comptime new_alignment: usize) ?AlignedSlice
43424340}
43434341
43444342test "read/write(Var)PackedInt" {
4345 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
4346
43474343 switch (builtin.cpu.arch) {
43484344 // This test generates too much code to execute on WASI.
43494345 // LLVM backend fails with "too many locals: locals exceed maximum"
lib/std/multi_array_list.zig+1-1
......@@ -106,7 +106,7 @@ pub fn MultiArrayList(comptime T: type) type {
106106 }
107107
108108 pub fn toMultiArrayList(self: Slice) Self {
109 if (self.ptrs.len == 0) {
109 if (self.ptrs.len == 0 or self.capacity == 0) {
110110 return .{};
111111 }
112112 const unaligned_ptr = self.ptrs[sizes.fields[0]];
lib/std/net/test.zig+1-1
......@@ -60,7 +60,7 @@ test "parse and render IPv6 addresses" {
6060}
6161
6262test "invalid but parseable IPv6 scope ids" {
63 if (builtin.os.tag != .linux or comptime !builtin.os.tag.isDarwin()) {
63 if (builtin.os.tag != .linux and comptime !builtin.os.tag.isDarwin()) {
6464 // Currently, resolveIp6 with alphanumerical scope IDs only works on Linux.
6565 // TODO Make this test pass on other operating systems.
6666 return error.SkipZigTest;
lib/std/once.zig-2
......@@ -46,8 +46,6 @@ fn incr() void {
4646}
4747
4848test "Once executes its function just once" {
49 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
50
5149 if (builtin.single_threaded) {
5250 global_once.call();
5351 global_once.call();
lib/std/os/test.zig-4
......@@ -375,8 +375,6 @@ fn testThreadIdFn(thread_id: *Thread.Id) void {
375375test "std.Thread.getCurrentId" {
376376 if (builtin.single_threaded) return error.SkipZigTest;
377377
378 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
379
380378 var thread_current_id: Thread.Id = undefined;
381379 const thread = try Thread.spawn(.{}, testThreadIdFn, .{&thread_current_id});
382380 thread.join();
......@@ -420,8 +418,6 @@ test "cpu count" {
420418test "thread local storage" {
421419 if (builtin.single_threaded) return error.SkipZigTest;
422420
423 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
424
425421 const thread1 = try Thread.spawn(.{}, testTls, .{});
426422 const thread2 = try Thread.spawn(.{}, testTls, .{});
427423 try testTls();
lib/std/rand/test.zig-7
......@@ -1,5 +1,4 @@
11const std = @import("../std.zig");
2const builtin = @import("builtin");
32const math = std.math;
43const DefaultPrng = std.rand.DefaultPrng;
54const Random = std.rand.Random;
......@@ -200,8 +199,6 @@ fn testRandomIntLessThan() !void {
200199}
201200
202201test "Random intAtMost" {
203 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
204
205202 @setEvalBranchQuota(10000);
206203 try testRandomIntAtMost();
207204 try comptime testRandomIntAtMost();
......@@ -242,8 +239,6 @@ fn testRandomIntAtMost() !void {
242239}
243240
244241test "Random Biased" {
245 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
246
247242 var prng = DefaultPrng.init(0);
248243 const random = prng.random();
249244 // Not thoroughly checking the logic here.
......@@ -452,8 +447,6 @@ test "CSPRNG" {
452447}
453448
454449test "Random weightedIndex" {
455 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
456
457450 // Make sure weightedIndex works for various integers and floats
458451 inline for (.{ u64, i4, f32, f64 }) |T| {
459452 var prng = DefaultPrng.init(0);
lib/std/zig/tokenizer.zig-9
......@@ -1,5 +1,4 @@
11const std = @import("../std.zig");
2const builtin = @import("builtin");
32
43pub const Token = struct {
54 tag: Tag,
......@@ -1450,8 +1449,6 @@ test "chars" {
14501449}
14511450
14521451test "invalid token characters" {
1453 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1454
14551452 try testTokenize("#", &.{.invalid});
14561453 try testTokenize("`", &.{.invalid});
14571454 try testTokenize("'c", &.{.invalid});
......@@ -1571,8 +1568,6 @@ test "pipe and then invalid" {
15711568}
15721569
15731570test "line comment and doc comment" {
1574 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1575
15761571 try testTokenize("//", &.{});
15771572 try testTokenize("// a / b", &.{});
15781573 try testTokenize("// /", &.{});
......@@ -1647,8 +1642,6 @@ test "range literals" {
16471642}
16481643
16491644test "number literals decimal" {
1650 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1651
16521645 try testTokenize("0", &.{.number_literal});
16531646 try testTokenize("1", &.{.number_literal});
16541647 try testTokenize("2", &.{.number_literal});
......@@ -1897,8 +1890,6 @@ test "invalid token with unfinished escape right before eof" {
18971890}
18981891
18991892test "saturating operators" {
1900 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1901
19021893 try testTokenize("<<", &.{.angle_bracket_angle_bracket_left});
19031894 try testTokenize("<<|", &.{.angle_bracket_angle_bracket_left_pipe});
19041895 try testTokenize("<<|=", &.{.angle_bracket_angle_bracket_left_pipe_equal});
src/Compilation.zig+3-1
......@@ -1121,7 +1121,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
11211121 const include_compiler_rt = options.want_compiler_rt orelse needs_c_symbols;
11221122
11231123 const must_single_thread = target_util.isSingleThreaded(options.target);
1124 const single_threaded = options.single_threaded orelse must_single_thread;
1124 const single_threaded = options.single_threaded orelse must_single_thread or
1125 // x86_64 codegen doesn't support TLV for most object formats
1126 (!use_llvm and options.target.cpu.arch == .x86_64 and options.target.ofmt != .macho);
11251127 if (must_single_thread and !single_threaded) {
11261128 return error.TargetRequiresSingleThreaded;
11271129 }
src/arch/x86_64/CodeGen.zig+1440-681
......@@ -388,7 +388,7 @@ pub const MCValue = union(enum) {
388388 };
389389 }
390390
391 fn mem(mcv: MCValue, size: Memory.Size) Memory {
391 fn mem(mcv: MCValue, function: *Self, size: Memory.Size) !Memory {
392392 return switch (mcv) {
393393 .none,
394394 .unreach,
......@@ -409,7 +409,6 @@ pub const MCValue = union(enum) {
409409 .lea_frame,
410410 .reserved_frame,
411411 .air_ref,
412 .load_symbol,
413412 .lea_symbol,
414413 => unreachable,
415414 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| .{
......@@ -433,6 +432,19 @@ pub const MCValue = union(enum) {
433432 .disp = frame_addr.off,
434433 } },
435434 },
435 .load_symbol => |sym_off| {
436 assert(sym_off.off == 0);
437 return .{
438 .base = .{ .reloc = .{
439 .atom_index = try function.owner.getSymbolIndex(function),
440 .sym_index = sym_off.sym,
441 } },
442 .mod = .{ .rm = .{
443 .size = size,
444 .disp = sym_off.off,
445 } },
446 };
447 },
436448 };
437449 }
438450
......@@ -722,12 +734,14 @@ const InstTracking = struct {
722734
723735const FrameAlloc = struct {
724736 abi_size: u31,
737 spill_pad: u3,
725738 abi_align: Alignment,
726739 ref_count: u16,
727740
728 fn init(alloc_abi: struct { size: u64, alignment: Alignment }) FrameAlloc {
741 fn init(alloc_abi: struct { size: u64, pad: u3 = 0, alignment: Alignment }) FrameAlloc {
729742 return .{
730743 .abi_size = @intCast(alloc_abi.size),
744 .spill_pad = alloc_abi.pad,
731745 .abi_align = alloc_abi.alignment,
732746 .ref_count = 0,
733747 };
......@@ -738,6 +752,20 @@ const FrameAlloc = struct {
738752 .alignment = ty.abiAlignment(mod),
739753 });
740754 }
755 fn initSpill(ty: Type, mod: *Module) FrameAlloc {
756 const abi_size = ty.abiSize(mod);
757 const spill_size = if (abi_size < 8)
758 math.ceilPowerOfTwoAssert(u64, abi_size)
759 else
760 std.mem.alignForward(u64, abi_size, 8);
761 return init(.{
762 .size = spill_size,
763 .pad = @intCast(spill_size - abi_size),
764 .alignment = ty.abiAlignment(mod).maxStrict(
765 Alignment.fromNonzeroByteUnits(@min(spill_size, 8)),
766 ),
767 });
768 }
741769};
742770
743771const StackAllocation = struct {
......@@ -1668,8 +1696,7 @@ fn gen(self: *Self) InnerError!void {
16681696 // The address where to store the return value for the caller is in a
16691697 // register which the callee is free to clobber. Therefore, we purposely
16701698 // spill it to stack immediately.
1671 const frame_index =
1672 try self.allocFrameIndex(FrameAlloc.initType(Type.usize, mod));
1699 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(Type.usize, mod));
16731700 try self.genSetMem(
16741701 .{ .frame = frame_index },
16751702 0,
......@@ -2434,7 +2461,7 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b
24342461 }
24352462 }
24362463
2437 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ty, mod));
2464 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(ty, mod));
24382465 return .{ .load_frame = .{ .index = frame_index } };
24392466}
24402467
......@@ -2445,7 +2472,10 @@ fn regClassForType(self: *Self, ty: Type) RegisterManager.RegisterBitSet {
24452472 80 => abi.RegisterClass.x87,
24462473 else => abi.RegisterClass.sse,
24472474 },
2448 .Vector => abi.RegisterClass.sse,
2475 .Vector => switch (ty.childType(mod).toIntern()) {
2476 .bool_type => abi.RegisterClass.gp,
2477 else => abi.RegisterClass.sse,
2478 },
24492479 else => abi.RegisterClass.gp,
24502480 };
24512481}
......@@ -2503,6 +2533,19 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt
25032533 ) |inst, *tracking| tracking.resurrect(inst, state.scope_generation);
25042534 for (deaths) |death| try self.processDeath(death);
25052535
2536 const ExpectedContents = [@typeInfo(RegisterManager.TrackedRegisters).Array.len]RegisterLock;
2537 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
2538 if (opts.update_tracking) ({}) else std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
2539
2540 var reg_locks = if (opts.update_tracking) {} else try std.ArrayList(RegisterLock).initCapacity(
2541 stack.get(),
2542 @typeInfo(ExpectedContents).Array.len,
2543 );
2544 defer if (!opts.update_tracking) {
2545 for (reg_locks.items) |lock| self.register_manager.unlockReg(lock);
2546 reg_locks.deinit();
2547 };
2548
25062549 for (0..state.registers.len) |index| {
25072550 const current_maybe_inst = if (self.register_manager.free_registers.isSet(index))
25082551 null
......@@ -2519,11 +2562,8 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt
25192562 try self.inst_tracking.getPtr(current_inst).?.spill(self, current_inst);
25202563 }
25212564 if (target_maybe_inst) |target_inst| {
2522 try self.inst_tracking.getPtr(target_inst).?.materialize(
2523 self,
2524 target_inst,
2525 state.reg_tracking[index],
2526 );
2565 const target_tracking = self.inst_tracking.getPtr(target_inst).?;
2566 try target_tracking.materialize(self, target_inst, state.reg_tracking[index]);
25272567 }
25282568 }
25292569 if (opts.update_tracking) {
......@@ -2541,7 +2581,8 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt
25412581 state.reg_tracking[index],
25422582 );
25432583 }
2544 }
2584 } else if (target_maybe_inst) |_|
2585 try reg_locks.append(self.register_manager.lockRegIndexAssumeUnused(@intCast(index)));
25452586 }
25462587 if (opts.emit_instructions) if (self.eflags_inst) |inst|
25472588 try self.inst_tracking.getPtr(inst).?.spill(self, inst);
......@@ -2578,8 +2619,17 @@ pub fn spillEflagsIfOccupied(self: *Self) !void {
25782619 }
25792620}
25802621
2581pub fn spillRegisters(self: *Self, registers: []const Register) !void {
2582 for (registers) |reg| try self.register_manager.getReg(reg, null);
2622pub fn spillCallerPreservedRegs(self: *Self, cc: std.builtin.CallingConvention) !void {
2623 switch (cc) {
2624 inline .SysV, .Win64 => |known_cc| try self.spillRegisters(
2625 comptime abi.getCallerPreservedRegs(known_cc),
2626 ),
2627 else => unreachable,
2628 }
2629}
2630
2631pub fn spillRegisters(self: *Self, comptime registers: []const Register) !void {
2632 inline for (registers) |reg| try self.register_manager.getKnownReg(reg, null);
25832633}
25842634
25852635/// Copies a value to a register without tracking the register. The register is not considered
......@@ -2699,7 +2749,7 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
26992749 .{ .v_ss, .cvtsd2 },
27002750 dst_reg,
27012751 dst_reg,
2702 src_mcv.mem(.qword),
2752 try src_mcv.mem(self, .qword),
27032753 ) else try self.asmRegisterRegisterRegister(
27042754 .{ .v_ss, .cvtsd2 },
27052755 dst_reg,
......@@ -2711,7 +2761,7 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
27112761 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
27122762 .{ ._ss, .cvtsd2 },
27132763 dst_reg,
2714 src_mcv.mem(.qword),
2764 try src_mcv.mem(self, .qword),
27152765 ) else try self.asmRegisterRegister(
27162766 .{ ._ss, .cvtsd2 },
27172767 dst_reg,
......@@ -2798,7 +2848,7 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
27982848 .{ .v_sd, .cvtss2 },
27992849 dst_reg,
28002850 dst_reg,
2801 src_mcv.mem(.dword),
2851 try src_mcv.mem(self, .dword),
28022852 ) else try self.asmRegisterRegisterRegister(
28032853 .{ .v_sd, .cvtss2 },
28042854 dst_reg,
......@@ -2810,7 +2860,7 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
28102860 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
28112861 .{ ._sd, .cvtss2 },
28122862 dst_reg,
2813 src_mcv.mem(.dword),
2863 try src_mcv.mem(self, .dword),
28142864 ) else try self.asmRegisterRegister(
28152865 .{ ._sd, .cvtss2 },
28162866 dst_reg,
......@@ -2851,8 +2901,8 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
28512901 };
28522902
28532903 const dst_mcv = if (dst_int_info.bits <= src_storage_bits and
2854 std.math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==
2855 std.math.divCeil(u32, src_storage_bits, 64) catch unreachable and
2904 math.divCeil(u16, dst_int_info.bits, 64) catch unreachable ==
2905 math.divCeil(u32, src_storage_bits, 64) catch unreachable and
28562906 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
28572907 const dst_mcv = try self.allocRegOrMem(inst, true);
28582908 try self.genCopy(min_ty, dst_mcv, src_mcv);
......@@ -2869,22 +2919,28 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
28692919 break :result .{ .register = registerAlias(dst_mcv.getReg().?, abi_size) };
28702920 }
28712921
2872 const src_limbs_len = std.math.divCeil(u16, src_int_info.bits, 64) catch unreachable;
2873 const dst_limbs_len = std.math.divCeil(u16, dst_int_info.bits, 64) catch unreachable;
2922 const src_limbs_len = math.divCeil(u16, src_int_info.bits, 64) catch unreachable;
2923 const dst_limbs_len = math.divCeil(u16, dst_int_info.bits, 64) catch unreachable;
28742924
2875 const high_mcv = dst_mcv.address().offset((src_limbs_len - 1) * 8).deref();
2876 const high_reg = try self.copyToTmpRegister(switch (src_int_info.signedness) {
2877 .signed => Type.isize,
2878 .unsigned => Type.usize,
2879 }, high_mcv);
2925 const high_mcv: MCValue = if (dst_mcv.isMemory())
2926 dst_mcv.address().offset((src_limbs_len - 1) * 8).deref()
2927 else
2928 .{ .register = dst_mcv.register_pair[1] };
2929 const high_reg = if (high_mcv.isRegister())
2930 high_mcv.getReg().?
2931 else
2932 try self.copyToTmpRegister(switch (src_int_info.signedness) {
2933 .signed => Type.isize,
2934 .unsigned => Type.usize,
2935 }, high_mcv);
28802936 const high_lock = self.register_manager.lockRegAssumeUnused(high_reg);
28812937 defer self.register_manager.unlockReg(high_lock);
28822938
28832939 const high_bits = src_int_info.bits % 64;
28842940 if (high_bits > 0) {
2885 const high_ty = try mod.intType(extend, high_bits);
2886 try self.truncateRegister(high_ty, high_reg);
2887 try self.genCopy(Type.usize, high_mcv, .{ .register = high_reg });
2941 try self.truncateRegister(src_ty, high_reg);
2942 const high_ty = if (dst_int_info.bits >= 64) Type.usize else dst_ty;
2943 try self.genCopy(high_ty, high_mcv, .{ .register = high_reg });
28882944 }
28892945
28902946 if (dst_limbs_len > src_limbs_len) try self.genInlineMemset(
......@@ -2995,14 +3051,14 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
29953051 .{ .vp_, .@"and" },
29963052 dst_reg,
29973053 dst_reg,
2998 splat_addr_mcv.deref().mem(Memory.Size.fromSize(splat_abi_size)),
3054 try splat_addr_mcv.deref().mem(self, Memory.Size.fromSize(splat_abi_size)),
29993055 );
30003056 try self.asmRegisterRegisterRegister(mir_tag, dst_reg, dst_reg, dst_reg);
30013057 } else {
30023058 try self.asmRegisterMemory(
30033059 .{ .p_, .@"and" },
30043060 dst_reg,
3005 splat_addr_mcv.deref().mem(Memory.Size.fromSize(splat_abi_size)),
3061 try splat_addr_mcv.deref().mem(self, Memory.Size.fromSize(splat_abi_size)),
30063062 );
30073063 try self.asmRegisterRegister(mir_tag, dst_reg, dst_reg);
30083064 }
......@@ -3048,7 +3104,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
30483104 const len = try self.resolveInst(bin_op.rhs);
30493105 const len_ty = self.typeOf(bin_op.rhs);
30503106
3051 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(slice_ty, mod));
3107 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(slice_ty, mod));
30523108 try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr);
30533109 try self.genSetMem(
30543110 .{ .frame = frame_index },
......@@ -3068,8 +3124,36 @@ fn airUnOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
30683124}
30693125
30703126fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
3127 const mod = self.bin_file.options.module.?;
30713128 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
30723129 const dst_mcv = try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs);
3130
3131 const dst_ty = self.typeOfIndex(inst);
3132 if (dst_ty.isAbiInt(mod)) {
3133 const abi_size: u32 = @intCast(dst_ty.abiSize(mod));
3134 const bit_size: u32 = @intCast(dst_ty.bitSize(mod));
3135 if (abi_size * 8 > bit_size) {
3136 const dst_lock = switch (dst_mcv) {
3137 .register => |dst_reg| self.register_manager.lockRegAssumeUnused(dst_reg),
3138 else => null,
3139 };
3140 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
3141
3142 if (dst_mcv.isRegister()) {
3143 try self.truncateRegister(dst_ty, dst_mcv.getReg().?);
3144 } else {
3145 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
3146 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
3147 defer self.register_manager.unlockReg(tmp_lock);
3148
3149 const hi_ty = try mod.intType(.unsigned, @intCast((dst_ty.bitSize(mod) - 1) % 64 + 1));
3150 const hi_mcv = dst_mcv.address().offset(@intCast(bit_size / 64 * 8)).deref();
3151 try self.genSetReg(tmp_reg, hi_ty, hi_mcv);
3152 try self.truncateRegister(dst_ty, tmp_reg);
3153 try self.genCopy(hi_ty, hi_mcv, .{ .register = tmp_reg });
3154 }
3155 }
3156 }
30733157 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
30743158}
30753159
......@@ -3176,7 +3260,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
31763260 if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory(
31773261 .{ ._, .mov },
31783262 tmp_reg,
3179 mat_lhs_mcv.address().offset(8).deref().mem(.qword),
3263 try mat_lhs_mcv.address().offset(8).deref().mem(self, .qword),
31803264 ) else try self.asmRegisterRegister(
31813265 .{ ._, .mov },
31823266 tmp_reg,
......@@ -3200,7 +3284,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
32003284 if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory(
32013285 .{ ._, .xor },
32023286 tmp_reg,
3203 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
3287 try mat_rhs_mcv.address().offset(8).deref().mem(self, .qword),
32043288 ) else try self.asmRegisterRegister(
32053289 .{ ._, .xor },
32063290 tmp_reg,
......@@ -3300,12 +3384,12 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
33003384 try self.asmRegisterMemory(
33013385 .{ ._, .add },
33023386 tmp_regs[0],
3303 mat_rhs_mcv.mem(.qword),
3387 try mat_rhs_mcv.mem(self, .qword),
33043388 );
33053389 try self.asmRegisterMemory(
33063390 .{ ._, .adc },
33073391 tmp_regs[1],
3308 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
3392 try mat_rhs_mcv.address().offset(8).deref().mem(self, .qword),
33093393 );
33103394 } else for (
33113395 [_]Mir.Inst.Tag{ .add, .adc },
......@@ -3534,7 +3618,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
35343618 if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory(
35353619 .{ ._, .mov },
35363620 tmp_reg,
3537 mat_lhs_mcv.address().offset(8).deref().mem(.qword),
3621 try mat_lhs_mcv.address().offset(8).deref().mem(self, .qword),
35383622 ) else try self.asmRegisterRegister(
35393623 .{ ._, .mov },
35403624 tmp_reg,
......@@ -3558,7 +3642,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
35583642 if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory(
35593643 .{ ._, .xor },
35603644 tmp_reg,
3561 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
3645 try mat_rhs_mcv.address().offset(8).deref().mem(self, .qword),
35623646 ) else try self.asmRegisterRegister(
35633647 .{ ._, .xor },
35643648 tmp_reg,
......@@ -3567,7 +3651,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
35673651
35683652 try self.asmRegisterImmediate(.{ ._r, .sa }, tmp_reg, Immediate.u(63));
35693653 try self.asmRegister(.{ ._, .not }, tmp_reg);
3570 try self.asmMemoryImmediate(.{ ._, .cmp }, overflow.mem(.dword), Immediate.s(0));
3654 try self.asmMemoryImmediate(.{ ._, .cmp }, try overflow.mem(self, .dword), Immediate.s(0));
35713655 try self.freeValue(overflow);
35723656 try self.asmCmovccRegisterRegister(.ne, dst_mcv.register_pair[0], tmp_reg);
35733657 try self.asmRegisterImmediate(.{ ._c, .bt }, tmp_reg, Immediate.u(63));
......@@ -3665,7 +3749,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
36653749 }
36663750
36673751 const frame_index =
3668 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
3752 try self.allocFrameIndex(FrameAlloc.initSpill(tuple_ty, mod));
36693753 try self.genSetMem(
36703754 .{ .frame = frame_index },
36713755 @intCast(tuple_ty.structFieldOffset(1, mod)),
......@@ -3682,7 +3766,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
36823766 }
36833767
36843768 const frame_index =
3685 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
3769 try self.allocFrameIndex(FrameAlloc.initSpill(tuple_ty, mod));
36863770 try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc);
36873771 break :result .{ .load_frame = .{ .index = frame_index } };
36883772 },
......@@ -3738,7 +3822,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
37383822 }
37393823
37403824 const frame_index =
3741 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
3825 try self.allocFrameIndex(FrameAlloc.initSpill(tuple_ty, mod));
37423826 try self.genSetMem(
37433827 .{ .frame = frame_index },
37443828 @intCast(tuple_ty.structFieldOffset(1, mod)),
......@@ -3755,7 +3839,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
37553839 }
37563840
37573841 const frame_index =
3758 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
3842 try self.allocFrameIndex(FrameAlloc.initSpill(tuple_ty, mod));
37593843 try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc);
37603844 break :result .{ .load_frame = .{ .index = frame_index } };
37613845 },
......@@ -3874,7 +3958,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
38743958 );
38753959 try self.asmMemoryImmediate(
38763960 .{ ._, .cmp },
3877 overflow.mem(self.memSize(Type.c_int)),
3961 try overflow.mem(self, self.memSize(Type.c_int)),
38783962 Immediate.s(0),
38793963 );
38803964 try self.genSetMem(
......@@ -3926,14 +4010,19 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
39264010 };
39274011 defer if (mat_rhs_lock) |lock| self.register_manager.unlockReg(lock);
39284012
3929 if (mat_lhs_mcv.isMemory())
3930 try self.asmRegisterMemory(.{ ._, .mov }, .rax, mat_lhs_mcv.mem(.qword))
3931 else
3932 try self.asmRegisterRegister(.{ ._, .mov }, .rax, mat_lhs_mcv.register_pair[0]);
4013 if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory(
4014 .{ ._, .mov },
4015 .rax,
4016 try mat_lhs_mcv.mem(self, .qword),
4017 ) else try self.asmRegisterRegister(
4018 .{ ._, .mov },
4019 .rax,
4020 mat_lhs_mcv.register_pair[0],
4021 );
39334022 if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory(
39344023 .{ ._, .mov },
39354024 tmp_regs[0],
3936 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
4025 try mat_rhs_mcv.address().offset(8).deref().mem(self, .qword),
39374026 ) else try self.asmRegisterRegister(
39384027 .{ ._, .mov },
39394028 tmp_regs[0],
......@@ -3944,7 +4033,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
39444033 try self.asmRegisterRegister(.{ .i_, .mul }, tmp_regs[0], .rax);
39454034 try self.asmSetccRegister(.o, tmp_regs[2].to8());
39464035 if (mat_rhs_mcv.isMemory())
3947 try self.asmMemory(.{ ._, .mul }, mat_rhs_mcv.mem(.qword))
4036 try self.asmMemory(.{ ._, .mul }, try mat_rhs_mcv.mem(self, .qword))
39484037 else
39494038 try self.asmRegister(.{ ._, .mul }, mat_rhs_mcv.register_pair[0]);
39504039 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_regs[0]);
......@@ -3953,7 +4042,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
39534042 if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory(
39544043 .{ ._, .mov },
39554044 tmp_regs[0],
3956 mat_lhs_mcv.address().offset(8).deref().mem(.qword),
4045 try mat_lhs_mcv.address().offset(8).deref().mem(self, .qword),
39574046 ) else try self.asmRegisterRegister(
39584047 .{ ._, .mov },
39594048 tmp_regs[0],
......@@ -3967,14 +4056,15 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
39674056 tmp_regs[3].to8(),
39684057 );
39694058 try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[1].to8(), tmp_regs[2].to8());
3970 if (mat_rhs_mcv.isMemory())
3971 try self.asmRegisterMemory(.{ .i_, .mul }, tmp_regs[0], mat_rhs_mcv.mem(.qword))
3972 else
3973 try self.asmRegisterRegister(
3974 .{ .i_, .mul },
3975 tmp_regs[0],
3976 mat_rhs_mcv.register_pair[0],
3977 );
4059 if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory(
4060 .{ .i_, .mul },
4061 tmp_regs[0],
4062 try mat_rhs_mcv.mem(self, .qword),
4063 ) else try self.asmRegisterRegister(
4064 .{ .i_, .mul },
4065 tmp_regs[0],
4066 mat_rhs_mcv.register_pair[0],
4067 );
39784068 try self.asmSetccRegister(.o, tmp_regs[2].to8());
39794069 try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[1].to8(), tmp_regs[2].to8());
39804070 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_regs[0]);
......@@ -4020,8 +4110,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
40204110 self.eflags_inst = inst;
40214111 break :result .{ .register_overflow = .{ .reg = reg, .eflags = cc } };
40224112 } else {
4023 const frame_index =
4024 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
4113 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(tuple_ty, mod));
40254114 try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc);
40264115 break :result .{ .load_frame = .{ .index = frame_index } };
40274116 },
......@@ -4032,8 +4121,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
40324121 src_ty.fmt(mod), dst_ty.fmt(mod),
40334122 });
40344123
4035 const frame_index =
4036 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
4124 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(tuple_ty, mod));
40374125 if (dst_info.bits >= lhs_active_bits + rhs_active_bits) {
40384126 try self.genSetMem(
40394127 .{ .frame = frame_index },
......@@ -4106,7 +4194,7 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue
41064194 .register => |reg| try self.asmRegister(tag, registerAlias(reg, abi_size)),
41074195 .memory, .indirect, .load_frame => try self.asmMemory(
41084196 tag,
4109 mat_rhs.mem(Memory.Size.fromSize(abi_size)),
4197 try mat_rhs.mem(self, Memory.Size.fromSize(abi_size)),
41104198 ),
41114199 else => unreachable,
41124200 }
......@@ -4160,8 +4248,8 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa
41604248 );
41614249 try self.asmCmovccRegisterRegister(
41624250 .z,
4163 registerAlias(divisor, abi_size),
4164 registerAlias(.rdx, abi_size),
4251 registerAlias(divisor, @max(abi_size, 2)),
4252 registerAlias(.rdx, @max(abi_size, 2)),
41654253 );
41664254 try self.genBinOpMir(.{ ._, .add }, ty, .{ .register = divisor }, .{ .register = .rax });
41674255 return MCValue{ .register = divisor };
......@@ -4171,47 +4259,268 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {
41714259 const mod = self.bin_file.options.module.?;
41724260 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
41734261
4174 try self.spillRegisters(&.{.rcx});
4175
4176 const tag = self.air.instructions.items(.tag)[inst];
4177 try self.register_manager.getReg(.rcx, null);
4178 const lhs = try self.resolveInst(bin_op.lhs);
4179 const rhs = try self.resolveInst(bin_op.rhs);
4262 const air_tags = self.air.instructions.items(.tag);
4263 const tag = air_tags[inst];
41804264 const lhs_ty = self.typeOf(bin_op.lhs);
41814265 const rhs_ty = self.typeOf(bin_op.rhs);
4266 const result: MCValue = result: {
4267 switch (lhs_ty.zigTypeTag(mod)) {
4268 .Int => {
4269 try self.spillRegisters(&.{.rcx});
4270 try self.register_manager.getReg(.rcx, null);
4271 const lhs_mcv = try self.resolveInst(bin_op.lhs);
4272 const rhs_mcv = try self.resolveInst(bin_op.rhs);
41824273
4183 const dst_mcv = try self.genShiftBinOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);
4184 switch (tag) {
4185 .shr, .shr_exact, .shl_exact => {},
4186 .shl => switch (dst_mcv) {
4187 .register => |dst_reg| try self.truncateRegister(lhs_ty, dst_reg),
4188 .register_pair => |dst_regs| try self.truncateRegister(lhs_ty, dst_regs[1]),
4189 .load_frame => |frame_addr| {
4190 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
4191 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
4192 defer self.register_manager.unlockReg(tmp_lock);
4274 const dst_mcv = try self.genShiftBinOp(tag, inst, lhs_mcv, rhs_mcv, lhs_ty, rhs_ty);
4275 switch (tag) {
4276 .shr, .shr_exact, .shl_exact => {},
4277 .shl => switch (dst_mcv) {
4278 .register => |dst_reg| try self.truncateRegister(lhs_ty, dst_reg),
4279 .register_pair => |dst_regs| try self.truncateRegister(lhs_ty, dst_regs[1]),
4280 .load_frame => |frame_addr| {
4281 const tmp_reg =
4282 try self.register_manager.allocReg(null, abi.RegisterClass.gp);
4283 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
4284 defer self.register_manager.unlockReg(tmp_lock);
41934285
4194 const lhs_bits: u31 = @intCast(lhs_ty.bitSize(mod));
4195 const tmp_ty = if (lhs_bits > 64) Type.usize else lhs_ty;
4196 const off = frame_addr.off + lhs_bits / 64 * 8;
4197 try self.genSetReg(
4198 tmp_reg,
4199 tmp_ty,
4200 .{ .load_frame = .{ .index = frame_addr.index, .off = off } },
4201 );
4202 try self.truncateRegister(lhs_ty, tmp_reg);
4203 try self.genSetMem(
4204 .{ .frame = frame_addr.index },
4205 off,
4206 tmp_ty,
4207 .{ .register = tmp_reg },
4208 );
4286 const lhs_bits: u31 = @intCast(lhs_ty.bitSize(mod));
4287 const tmp_ty = if (lhs_bits > 64) Type.usize else lhs_ty;
4288 const off = frame_addr.off + (lhs_bits - 1) / 64 * 8;
4289 try self.genSetReg(
4290 tmp_reg,
4291 tmp_ty,
4292 .{ .load_frame = .{ .index = frame_addr.index, .off = off } },
4293 );
4294 try self.truncateRegister(lhs_ty, tmp_reg);
4295 try self.genSetMem(
4296 .{ .frame = frame_addr.index },
4297 off,
4298 tmp_ty,
4299 .{ .register = tmp_reg },
4300 );
4301 },
4302 else => {},
4303 },
4304 else => unreachable,
4305 }
4306 break :result dst_mcv;
4307 },
4308 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
4309 .Int => if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.childType(mod).intInfo(mod).bits) {
4310 else => null,
4311 16 => switch (lhs_ty.vectorLen(mod)) {
4312 else => null,
4313 1...8 => switch (tag) {
4314 else => unreachable,
4315 .shr, .shr_exact => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
4316 .signed => if (self.hasFeature(.avx))
4317 .{ .vp_w, .sra }
4318 else
4319 .{ .p_w, .sra },
4320 .unsigned => if (self.hasFeature(.avx))
4321 .{ .vp_w, .srl }
4322 else
4323 .{ .p_w, .srl },
4324 },
4325 .shl, .shl_exact => if (self.hasFeature(.avx))
4326 .{ .vp_w, .sll }
4327 else
4328 .{ .p_w, .sll },
4329 },
4330 9...16 => switch (tag) {
4331 else => unreachable,
4332 .shr, .shr_exact => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
4333 .signed => if (self.hasFeature(.avx2)) .{ .vp_w, .sra } else null,
4334 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_w, .srl } else null,
4335 },
4336 .shl, .shl_exact => if (self.hasFeature(.avx2)) .{ .vp_w, .sll } else null,
4337 },
4338 },
4339 32 => switch (lhs_ty.vectorLen(mod)) {
4340 else => null,
4341 1...4 => switch (tag) {
4342 else => unreachable,
4343 .shr, .shr_exact => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
4344 .signed => if (self.hasFeature(.avx))
4345 .{ .vp_d, .sra }
4346 else
4347 .{ .p_d, .sra },
4348 .unsigned => if (self.hasFeature(.avx))
4349 .{ .vp_d, .srl }
4350 else
4351 .{ .p_d, .srl },
4352 },
4353 .shl, .shl_exact => if (self.hasFeature(.avx))
4354 .{ .vp_d, .sll }
4355 else
4356 .{ .p_d, .sll },
4357 },
4358 5...8 => switch (tag) {
4359 else => unreachable,
4360 .shr, .shr_exact => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
4361 .signed => if (self.hasFeature(.avx2)) .{ .vp_d, .sra } else null,
4362 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_d, .srl } else null,
4363 },
4364 .shl, .shl_exact => if (self.hasFeature(.avx2)) .{ .vp_d, .sll } else null,
4365 },
4366 },
4367 64 => switch (lhs_ty.vectorLen(mod)) {
4368 else => null,
4369 1...2 => switch (tag) {
4370 else => unreachable,
4371 .shr, .shr_exact => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
4372 .signed => if (self.hasFeature(.avx))
4373 .{ .vp_q, .sra }
4374 else
4375 .{ .p_q, .sra },
4376 .unsigned => if (self.hasFeature(.avx))
4377 .{ .vp_q, .srl }
4378 else
4379 .{ .p_q, .srl },
4380 },
4381 .shl, .shl_exact => if (self.hasFeature(.avx))
4382 .{ .vp_q, .sll }
4383 else
4384 .{ .p_q, .sll },
4385 },
4386 3...4 => switch (tag) {
4387 else => unreachable,
4388 .shr, .shr_exact => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
4389 .signed => if (self.hasFeature(.avx2)) .{ .vp_q, .sra } else null,
4390 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_q, .srl } else null,
4391 },
4392 .shl, .shl_exact => if (self.hasFeature(.avx2)) .{ .vp_q, .sll } else null,
4393 },
4394 },
4395 })) |mir_tag| if (try self.air.value(bin_op.rhs, mod)) |rhs_val| {
4396 switch (mod.intern_pool.indexToKey(rhs_val.toIntern())) {
4397 .aggregate => |rhs_aggregate| switch (rhs_aggregate.storage) {
4398 .repeated_elem => |rhs_elem| {
4399 const abi_size: u32 = @intCast(lhs_ty.abiSize(mod));
4400
4401 const lhs_mcv = try self.resolveInst(bin_op.lhs);
4402 const dst_reg, const lhs_reg = if (lhs_mcv.isRegister() and
4403 self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv))
4404 .{lhs_mcv.getReg().?} ** 2
4405 else if (lhs_mcv.isRegister() and self.hasFeature(.avx)) .{
4406 try self.register_manager.allocReg(inst, abi.RegisterClass.sse),
4407 lhs_mcv.getReg().?,
4408 } else .{(try self.copyToRegisterWithInstTracking(
4409 inst,
4410 lhs_ty,
4411 lhs_mcv,
4412 )).register} ** 2;
4413 const reg_locks =
4414 self.register_manager.lockRegs(2, .{ dst_reg, lhs_reg });
4415 defer for (reg_locks) |reg_lock| if (reg_lock) |lock|
4416 self.register_manager.unlockReg(lock);
4417
4418 const shift_imm =
4419 Immediate.u(@intCast(rhs_elem.toValue().toUnsignedInt(mod)));
4420 if (self.hasFeature(.avx)) try self.asmRegisterRegisterImmediate(
4421 mir_tag,
4422 registerAlias(dst_reg, abi_size),
4423 registerAlias(lhs_reg, abi_size),
4424 shift_imm,
4425 ) else {
4426 assert(dst_reg.id() == lhs_reg.id());
4427 try self.asmRegisterImmediate(
4428 mir_tag,
4429 registerAlias(dst_reg, abi_size),
4430 shift_imm,
4431 );
4432 }
4433 break :result .{ .register = dst_reg };
4434 },
4435 else => {},
4436 },
4437 else => {},
4438 }
4439 } else if (Air.refToIndex(bin_op.rhs)) |rhs_inst| switch (air_tags[rhs_inst]) {
4440 .splat => {
4441 const abi_size: u32 = @intCast(lhs_ty.abiSize(mod));
4442
4443 const lhs_mcv = try self.resolveInst(bin_op.lhs);
4444 const dst_reg, const lhs_reg = if (lhs_mcv.isRegister() and
4445 self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv))
4446 .{lhs_mcv.getReg().?} ** 2
4447 else if (lhs_mcv.isRegister() and self.hasFeature(.avx)) .{
4448 try self.register_manager.allocReg(inst, abi.RegisterClass.sse),
4449 lhs_mcv.getReg().?,
4450 } else .{(try self.copyToRegisterWithInstTracking(
4451 inst,
4452 lhs_ty,
4453 lhs_mcv,
4454 )).register} ** 2;
4455 const reg_locks = self.register_manager.lockRegs(2, .{ dst_reg, lhs_reg });
4456 defer for (reg_locks) |reg_lock| if (reg_lock) |lock|
4457 self.register_manager.unlockReg(lock);
4458
4459 const shift_reg =
4460 try self.copyToTmpRegister(rhs_ty, .{ .air_ref = bin_op.rhs });
4461 const shift_lock = self.register_manager.lockRegAssumeUnused(shift_reg);
4462 defer self.register_manager.unlockReg(shift_lock);
4463
4464 const mask_ty = try mod.vectorType(.{ .len = 16, .child = .u8_type });
4465 const mask_mcv = try self.genTypedValue(.{
4466 .ty = mask_ty,
4467 .val = (try mod.intern(.{ .aggregate = .{
4468 .ty = mask_ty.toIntern(),
4469 .storage = .{ .elems = &([1]InternPool.Index{
4470 (try rhs_ty.childType(mod).maxIntScalar(mod, Type.u8)).toIntern(),
4471 } ++ [1]InternPool.Index{
4472 (try mod.intValue(Type.u8, 0)).toIntern(),
4473 } ** 15) },
4474 } })).toValue(),
4475 });
4476 const mask_addr_reg =
4477 try self.copyToTmpRegister(Type.usize, mask_mcv.address());
4478 const mask_addr_lock = self.register_manager.lockRegAssumeUnused(mask_addr_reg);
4479 defer self.register_manager.unlockReg(mask_addr_lock);
4480
4481 if (self.hasFeature(.avx)) {
4482 try self.asmRegisterRegisterMemory(
4483 .{ .vp_, .@"and" },
4484 shift_reg.to128(),
4485 shift_reg.to128(),
4486 .{
4487 .base = .{ .reg = mask_addr_reg },
4488 .mod = .{ .rm = .{ .size = .xword } },
4489 },
4490 );
4491 try self.asmRegisterRegisterRegister(
4492 mir_tag,
4493 registerAlias(dst_reg, abi_size),
4494 registerAlias(lhs_reg, abi_size),
4495 shift_reg.to128(),
4496 );
4497 } else {
4498 try self.asmRegisterMemory(
4499 .{ .p_, .@"and" },
4500 shift_reg.to128(),
4501 .{
4502 .base = .{ .reg = mask_addr_reg },
4503 .mod = .{ .rm = .{ .size = .xword } },
4504 },
4505 );
4506 assert(dst_reg.id() == lhs_reg.id());
4507 try self.asmRegisterRegister(
4508 mir_tag,
4509 registerAlias(dst_reg, abi_size),
4510 shift_reg.to128(),
4511 );
4512 }
4513 break :result .{ .register = dst_reg };
4514 },
4515 else => {},
4516 },
4517 else => {},
42094518 },
42104519 else => {},
4211 },
4212 else => unreachable,
4213 }
4214 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
4520 }
4521 return self.fail("TODO implement airShlShrBinOp for {}", .{lhs_ty.fmt(mod)});
4522 };
4523 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
42154524}
42164525
42174526fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
......@@ -4230,12 +4539,18 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
42304539
42314540 const opt_mcv = try self.resolveInst(ty_op.operand);
42324541 if (self.reuseOperand(inst, ty_op.operand, 0, opt_mcv)) {
4233 switch (opt_mcv) {
4234 .register => |reg| try self.truncateRegister(pl_ty, reg),
4235 .register_overflow => |ro| try self.truncateRegister(pl_ty, ro.reg),
4542 const pl_mcv: MCValue = switch (opt_mcv) {
4543 .register_overflow => |ro| pl: {
4544 self.eflags_inst = null; // actually stop tracking the overflow part
4545 break :pl .{ .register = ro.reg };
4546 },
4547 else => opt_mcv,
4548 };
4549 switch (pl_mcv) {
4550 .register => |pl_reg| try self.truncateRegister(pl_ty, pl_reg),
42364551 else => {},
42374552 }
4238 break :result opt_mcv;
4553 break :result pl_mcv;
42394554 }
42404555
42414556 const pl_mcv = try self.allocRegOrMem(inst, true);
......@@ -4472,8 +4787,9 @@ fn genUnwrapErrUnionPayloadMir(
44724787 const eu_lock = self.register_manager.lockReg(reg);
44734788 defer if (eu_lock) |lock| self.register_manager.unlockReg(lock);
44744789
4475 const result_mcv: MCValue = if (maybe_inst) |inst|
4476 try self.copyToRegisterWithInstTracking(inst, err_union_ty, err_union)
4790 const payload_in_gp = self.regClassForType(payload_ty).supersetOf(abi.RegisterClass.gp);
4791 const result_mcv: MCValue = if (payload_in_gp and maybe_inst != null)
4792 try self.copyToRegisterWithInstTracking(maybe_inst.?, err_union_ty, err_union)
44774793 else
44784794 .{ .register = try self.copyToTmpRegister(err_union_ty, err_union) };
44794795 if (payload_off > 0) try self.genShiftBinOpMir(
......@@ -4482,7 +4798,12 @@ fn genUnwrapErrUnionPayloadMir(
44824798 result_mcv,
44834799 .{ .immediate = @as(u6, @intCast(payload_off * 8)) },
44844800 ) else try self.truncateRegister(payload_ty, result_mcv.register);
4485 break :result result_mcv;
4801 break :result if (payload_in_gp)
4802 result_mcv
4803 else if (maybe_inst) |inst|
4804 try self.copyToRegisterWithInstTracking(inst, payload_ty, result_mcv)
4805 else
4806 .{ .register = try self.copyToTmpRegister(payload_ty, result_mcv) };
44864807 },
44874808 else => return self.fail("TODO implement genUnwrapErrUnionPayloadMir for {}", .{err_union}),
44884809 }
......@@ -4593,7 +4914,7 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
45934914 const result: MCValue = result: {
45944915 if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .{ .immediate = 0 };
45954916
4596 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(eu_ty, mod));
4917 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, mod));
45974918 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, mod));
45984919 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, mod));
45994920 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand);
......@@ -4615,7 +4936,7 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
46154936 const result: MCValue = result: {
46164937 if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result try self.resolveInst(ty_op.operand);
46174938
4618 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(eu_ty, mod));
4939 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, mod));
46194940 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, mod));
46204941 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, mod));
46214942 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, .undef);
......@@ -4770,14 +5091,19 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
47705091fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
47715092 const mod = self.bin_file.options.module.?;
47725093 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
4773 const slice_ty = self.typeOf(bin_op.lhs);
47745094
4775 const slice_ptr_field_type = slice_ty.slicePtrFieldType(mod);
4776 const elem_ptr = try self.genSliceElemPtr(bin_op.lhs, bin_op.rhs);
4777 const dst_mcv = try self.allocRegOrMem(inst, false);
4778 try self.load(dst_mcv, slice_ptr_field_type, elem_ptr);
5095 const result: MCValue = result: {
5096 const elem_ty = self.typeOfIndex(inst);
5097 if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
47795098
4780 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
5099 const slice_ty = self.typeOf(bin_op.lhs);
5100 const slice_ptr_field_type = slice_ty.slicePtrFieldType(mod);
5101 const elem_ptr = try self.genSliceElemPtr(bin_op.lhs, bin_op.rhs);
5102 const dst_mcv = try self.allocRegOrMem(inst, false);
5103 try self.load(dst_mcv, slice_ptr_field_type, elem_ptr);
5104 break :result dst_mcv;
5105 };
5106 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
47815107}
47825108
47835109fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
......@@ -4810,11 +5136,10 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
48105136 };
48115137 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);
48125138
4813 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
4814 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
4815 defer self.register_manager.unlockReg(offset_reg_lock);
4816
48175139 const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
5140 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
5141 defer self.register_manager.unlockReg(addr_lock);
5142
48185143 switch (array) {
48195144 .register => {
48205145 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, mod));
......@@ -4843,6 +5168,10 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
48435168 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
48445169 }
48455170
5171 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
5172 const offset_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
5173 defer self.register_manager.unlockReg(offset_lock);
5174
48465175 // TODO we could allocate register here, but need to expect addr register and potentially
48475176 // offset register.
48485177 try self.spillEflagsIfOccupied();
......@@ -5093,7 +5422,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
50935422 .{ ._, .sub },
50945423 dst_ty,
50955424 dst_mcv,
5096 .{ .immediate = 8 + self.regExtraBits(src_ty) },
5425 .{ .immediate = 32 - src_bits },
50975426 );
50985427 } else if (src_bits <= 64) {
50995428 try self.genBinOpMir(.{ ._, .lzcnt }, src_ty, dst_mcv, mat_src_mcv);
......@@ -5361,7 +5690,9 @@ fn airPopCount(self: *Self, inst: Air.Inst.Index) !void {
53615690 mat_src_mcv
53625691 else
53635692 .{ .register = mat_src_mcv.register_pair[0] }, false);
5364 try self.genPopCount(tmp_regs[1], Type.usize, if (mat_src_mcv.isMemory())
5693 const src_info = src_ty.intInfo(mod);
5694 const hi_ty = try mod.intType(src_info.signedness, (src_info.bits - 1) % 64 + 1);
5695 try self.genPopCount(tmp_regs[1], hi_ty, if (mat_src_mcv.isMemory())
53655696 mat_src_mcv.address().offset(8).deref()
53665697 else
53675698 .{ .register = mat_src_mcv.register_pair[1] }, false);
......@@ -5383,9 +5714,13 @@ fn genPopCount(
53835714 const src_abi_size: u32 = @intCast(src_ty.abiSize(mod));
53845715 if (self.hasFeature(.popcnt)) return self.genBinOpMir(
53855716 .{ ._, .popcnt },
5386 if (src_abi_size > 1) src_ty else Type.u16,
5717 if (src_abi_size > 1) src_ty else Type.u32,
53875718 .{ .register = dst_reg },
5388 src_mcv,
5719 if (src_abi_size > 1) src_mcv else src: {
5720 if (!dst_contains_src) try self.genSetReg(dst_reg, src_ty, src_mcv);
5721 try self.truncateRegister(try src_ty.toUnsigned(mod), dst_reg);
5722 break :src .{ .register = dst_reg };
5723 },
53895724 );
53905725
53915726 const mask = @as(u64, math.maxInt(u64)) >> @intCast(64 - src_abi_size * 8);
......@@ -5517,9 +5852,9 @@ fn genByteSwap(
55175852 try self.asmRegisterMemory(
55185853 .{ ._, .movbe },
55195854 dst_regs[0],
5520 src_mcv.address().offset(8).deref().mem(.qword),
5855 try src_mcv.address().offset(8).deref().mem(self, .qword),
55215856 );
5522 try self.asmRegisterMemory(.{ ._, .movbe }, dst_regs[1], src_mcv.mem(.qword));
5857 try self.asmRegisterMemory(.{ ._, .movbe }, dst_regs[1], try src_mcv.mem(self, .qword));
55235858 } else for (dst_regs, src_mcv.register_pair) |dst_reg, src_reg| {
55245859 try self.asmRegisterRegister(.{ ._, .mov }, dst_reg.to64(), src_reg.to64());
55255860 try self.asmRegister(.{ ._, .bswap }, dst_reg.to64());
......@@ -5762,7 +6097,7 @@ fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type)
57626097 else => unreachable,
57636098 } });
57646099 const sign_mem: Memory = if (sign_mcv.isMemory())
5765 sign_mcv.mem(Memory.Size.fromSize(abi_size))
6100 try sign_mcv.mem(self, Memory.Size.fromSize(abi_size))
57666101 else
57676102 .{
57686103 .base = .{ .reg = try self.copyToTmpRegister(Type.usize, sign_mcv.address()) },
......@@ -5945,7 +6280,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: Ro
59456280 mir_tag,
59466281 dst_alias,
59476282 dst_alias,
5948 src_mcv.mem(Memory.Size.fromSize(abi_size)),
6283 try src_mcv.mem(self, Memory.Size.fromSize(abi_size)),
59496284 Immediate.u(@as(u5, @bitCast(mode))),
59506285 ) else try self.asmRegisterRegisterRegisterImmediate(
59516286 mir_tag,
......@@ -5960,7 +6295,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: Ro
59606295 else => if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
59616296 mir_tag,
59626297 dst_alias,
5963 src_mcv.mem(Memory.Size.fromSize(abi_size)),
6298 try src_mcv.mem(self, Memory.Size.fromSize(abi_size)),
59646299 Immediate.u(@as(u5, @bitCast(mode))),
59656300 ) else try self.asmRegisterRegisterImmediate(
59666301 mir_tag,
......@@ -6000,7 +6335,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
60006335 .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory(
60016336 .l,
60026337 registerAlias(dst_mcv.register, cmov_abi_size),
6003 src_mcv.mem(Memory.Size.fromSize(cmov_abi_size)),
6338 try src_mcv.mem(self, Memory.Size.fromSize(cmov_abi_size)),
60046339 ),
60056340 else => {
60066341 const val_reg = try self.copyToTmpRegister(ty, src_mcv);
......@@ -6100,7 +6435,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
61006435 if (src_mcv.isMemory()) try self.asmRegisterMemory(
61016436 mir_tag,
61026437 dst_alias,
6103 src_mcv.mem(self.memSize(ty)),
6438 try src_mcv.mem(self, self.memSize(ty)),
61046439 ) else try self.asmRegisterRegister(
61056440 mir_tag,
61066441 dst_alias,
......@@ -6206,7 +6541,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
62066541 if (src_mcv.isMemory()) try self.asmRegisterMemory(
62076542 .{ .v_ps, .cvtph2 },
62086543 wide_reg,
6209 src_mcv.mem(Memory.Size.fromSize(
6544 try src_mcv.mem(self, Memory.Size.fromSize(
62106545 @intCast(@divExact(wide_reg.bitSize(), 16)),
62116546 )),
62126547 ) else try self.asmRegisterRegister(
......@@ -6254,7 +6589,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
62546589 mir_tag,
62556590 dst_reg,
62566591 dst_reg,
6257 src_mcv.mem(Memory.Size.fromSize(abi_size)),
6592 try src_mcv.mem(self, Memory.Size.fromSize(abi_size)),
62586593 ) else try self.asmRegisterRegisterRegister(
62596594 mir_tag,
62606595 dst_reg,
......@@ -6267,7 +6602,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
62676602 else => if (src_mcv.isMemory()) try self.asmRegisterMemory(
62686603 mir_tag,
62696604 dst_reg,
6270 src_mcv.mem(Memory.Size.fromSize(abi_size)),
6605 try src_mcv.mem(self, Memory.Size.fromSize(abi_size)),
62716606 ) else try self.asmRegisterRegister(
62726607 mir_tag,
62736608 dst_reg,
......@@ -6332,7 +6667,7 @@ fn reuseOperandAdvanced(
63326667 return false;
63336668
63346669 switch (mcv) {
6335 .register, .register_pair => for (mcv.getRegs()) |reg| {
6670 .register, .register_pair, .register_overflow => for (mcv.getRegs()) |reg| {
63366671 // If it's in the registers table, need to associate the register(s) with the
63376672 // new instruction.
63386673 if (maybe_tracked_inst) |tracked_inst| {
......@@ -6346,6 +6681,10 @@ fn reuseOperandAdvanced(
63466681 .load_frame => |frame_addr| if (frame_addr.index.isNamed()) return false,
63476682 else => return false,
63486683 }
6684 switch (mcv) {
6685 .eflags, .register_overflow => self.eflags_inst = maybe_tracked_inst,
6686 else => {},
6687 }
63496688
63506689 // Prevent the operand deaths processing code from deallocating it.
63516690 self.liveness.clearOperandDeath(inst, op_index);
......@@ -6363,11 +6702,36 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
63636702 if (!val_ty.hasRuntimeBitsIgnoreComptime(mod)) return;
63646703 const val_abi_size: u32 = @intCast(val_ty.abiSize(mod));
63656704
6705 if (ptr_info.packed_offset.bit_offset % 8 == 0) {
6706 try self.load(
6707 dst_mcv,
6708 ptr_ty,
6709 ptr_mcv.offset(@intCast(@divExact(ptr_info.packed_offset.bit_offset, 8))),
6710 );
6711 const val_bit_size: u32 = @intCast(val_ty.bitSize(mod));
6712 if (val_abi_size * 8 > val_bit_size) {
6713 if (dst_mcv.isRegister()) {
6714 try self.truncateRegister(val_ty, dst_mcv.getReg().?);
6715 } else {
6716 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
6717 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
6718 defer self.register_manager.unlockReg(tmp_lock);
6719
6720 const hi_mcv = dst_mcv.address().offset(@intCast(val_bit_size / 64 * 8)).deref();
6721 try self.genSetReg(tmp_reg, Type.usize, hi_mcv);
6722 try self.truncateRegister(val_ty, tmp_reg);
6723 try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg });
6724 }
6725 }
6726 return;
6727 }
6728
63666729 if (val_abi_size > 8) return self.fail("TODO implement packed load of {}", .{val_ty.fmt(mod)});
63676730
63686731 const limb_abi_size: u32 = @min(val_abi_size, 8);
63696732 const limb_abi_bits = limb_abi_size * 8;
6370 const val_byte_off: i32 = @intCast(ptr_info.packed_offset.bit_offset / limb_abi_bits * limb_abi_size);
6733 const val_byte_off: i32 =
6734 @intCast(ptr_info.packed_offset.bit_offset / limb_abi_bits * limb_abi_size);
63716735 const val_bit_off = ptr_info.packed_offset.bit_offset % limb_abi_bits;
63726736 const val_extra_bits = self.regExtraBits(val_ty);
63736737
......@@ -6393,6 +6757,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
63936757 .disp = val_byte_off,
63946758 } },
63956759 });
6760 try self.spillEflagsIfOccupied();
63966761 try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(val_bit_off));
63976762 } else {
63986763 const tmp_reg =
......@@ -6415,6 +6780,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
64156780 .disp = val_byte_off + 1,
64166781 } },
64176782 });
6783 try self.spillEflagsIfOccupied();
64186784 try self.asmRegisterRegisterImmediate(
64196785 .{ ._rd, .sh },
64206786 dst_alias,
......@@ -6498,6 +6864,27 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
64986864 } else {
64996865 try self.load(dst_mcv, ptr_ty, ptr_mcv);
65006866 }
6867
6868 if (elem_ty.isAbiInt(mod) and elem_size * 8 > elem_ty.bitSize(mod)) {
6869 const high_mcv: MCValue = switch (dst_mcv) {
6870 .register => |dst_reg| .{ .register = dst_reg },
6871 .register_pair => |dst_regs| .{ .register = dst_regs[1] },
6872 else => dst_mcv.address().offset(@intCast((elem_size - 1) / 8 * 8)).deref(),
6873 };
6874 const high_reg = if (high_mcv.isRegister())
6875 high_mcv.getReg().?
6876 else
6877 try self.copyToTmpRegister(Type.usize, high_mcv);
6878 const high_lock = self.register_manager.lockReg(high_reg);
6879 defer if (high_lock) |lock| self.register_manager.unlockReg(lock);
6880
6881 try self.truncateRegister(elem_ty, high_reg);
6882 if (!high_mcv.isRegister()) try self.genCopy(
6883 if (elem_size <= 8) elem_ty else Type.usize,
6884 high_mcv,
6885 .{ .register = high_reg },
6886 );
6887 }
65016888 break :result dst_mcv;
65026889 };
65036890 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
......@@ -6530,7 +6917,7 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In
65306917 .base = .{ .reg = ptr_reg },
65316918 .mod = .{ .rm = .{
65326919 .size = Memory.Size.fromSize(limb_abi_size),
6533 .disp = src_byte_off + limb_i * limb_abi_bits,
6920 .disp = src_byte_off + limb_i * limb_abi_size,
65346921 } },
65356922 };
65366923
......@@ -6575,6 +6962,22 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In
65756962 limb_mem,
65766963 registerAlias(tmp_reg, limb_abi_size),
65776964 );
6965 } else if (src_bit_size <= 128 and src_bit_off == 0) {
6966 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
6967 const tmp_mcv = MCValue{ .register = tmp_reg };
6968 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
6969 defer self.register_manager.unlockReg(tmp_lock);
6970
6971 try self.genSetReg(tmp_reg, limb_ty, switch (limb_i) {
6972 0 => src_mcv,
6973 else => src_mcv.address().offset(limb_i * limb_abi_size).deref(),
6974 });
6975 try self.genBinOpMir(.{ ._, .@"and" }, limb_ty, tmp_mcv, .{ .immediate = part_mask });
6976 try self.asmMemoryRegister(
6977 .{ ._, .@"or" },
6978 limb_mem,
6979 registerAlias(tmp_reg, limb_abi_size),
6980 );
65786981 } else return self.fail("TODO: implement packed store of {}", .{src_ty.fmt(mod)});
65796982 }
65806983}
......@@ -6627,6 +7030,11 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
66277030 } else {
66287031 // TODO if the value is undef, don't lower this instruction
66297032 }
7033
7034 try self.spillRegisters(&.{ .rdi, .rsi, .rcx });
7035 const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx });
7036 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
7037
66307038 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
66317039 const ptr_mcv = try self.resolveInst(bin_op.lhs);
66327040 const ptr_ty = self.typeOf(bin_op.lhs);
......@@ -6719,12 +7127,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
67197127 const dst_lock = self.register_manager.lockReg(dst_reg);
67207128 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
67217129
6722 if (field_off > 0) try self.genShiftBinOpMir(
6723 .{ ._r, .sh },
6724 Type.usize,
6725 dst_mcv,
6726 .{ .immediate = field_off },
6727 );
7130 if (field_off > 0) {
7131 try self.spillEflagsIfOccupied();
7132 try self.genShiftBinOpMir(
7133 .{ ._r, .sh },
7134 Type.usize,
7135 dst_mcv,
7136 .{ .immediate = field_off },
7137 );
7138 }
67287139 if (abi.RegisterClass.gp.isSet(RegisterManager.indexOfRegIntoTracked(dst_reg).?) and
67297140 container_ty.abiSize(mod) * 8 > field_ty.bitSize(mod))
67307141 try self.truncateRegister(field_ty, dst_reg);
......@@ -6759,12 +7170,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
67597170 defer for (dst_locks) |dst_lock| if (dst_lock) |lock|
67607171 self.register_manager.unlockReg(lock);
67617172
6762 if (field_off > 0) try self.genShiftBinOpMir(
6763 .{ ._r, .sh },
6764 Type.u128,
6765 dst_mcv,
6766 .{ .immediate = field_off },
6767 );
7173 if (field_off > 0) {
7174 try self.spillEflagsIfOccupied();
7175 try self.genShiftBinOpMir(
7176 .{ ._r, .sh },
7177 Type.u128,
7178 dst_mcv,
7179 .{ .immediate = field_off },
7180 );
7181 }
67687182
67697183 if (field_bit_size <= 64) {
67707184 if (self.regExtraBits(field_ty) > 0)
......@@ -6792,15 +7206,18 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
67927206 const dst_lock = self.register_manager.lockReg(dst_reg);
67937207 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
67947208
6795 if (field_off % 64 > 0) try self.genShiftBinOpMir(
6796 .{ ._r, .sh },
6797 Type.usize,
6798 dst_mcv,
6799 .{ .immediate = field_off % 64 },
6800 );
6801 if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg);
6802
6803 break :result if (field_rc.supersetOf(abi.RegisterClass.gp))
7209 if (field_off % 64 > 0) {
7210 try self.spillEflagsIfOccupied();
7211 try self.genShiftBinOpMir(
7212 .{ ._r, .sh },
7213 Type.usize,
7214 dst_mcv,
7215 .{ .immediate = field_off % 64 },
7216 );
7217 }
7218 if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg);
7219
7220 break :result if (field_rc.supersetOf(abi.RegisterClass.gp))
68047221 dst_mcv
68057222 else
68067223 try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv);
......@@ -6808,17 +7225,17 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
68087225 .register_overflow => |ro| {
68097226 switch (index) {
68107227 // Get wrapped value for overflow operation.
6811 0 => break :result if (self.liveness.operandDies(inst, 0))
6812 .{ .register = ro.reg }
6813 else
6814 try self.copyToRegisterWithInstTracking(
6815 inst,
6816 Type.usize,
6817 .{ .register = ro.reg },
6818 ),
7228 0 => if (self.reuseOperand(inst, extra.struct_operand, 0, src_mcv)) {
7229 self.eflags_inst = null; // actually stop tracking the overflow part
7230 break :result .{ .register = ro.reg };
7231 } else break :result try self.copyToRegisterWithInstTracking(
7232 inst,
7233 Type.usize,
7234 .{ .register = ro.reg },
7235 ),
68197236 // Get overflow bit.
6820 1 => if (self.liveness.operandDies(inst, 0)) {
6821 self.eflags_inst = inst;
7237 1 => if (self.reuseOperandAdvanced(inst, extra.struct_operand, 0, src_mcv, null)) {
7238 self.eflags_inst = inst; // actually keep tracking the overflow part
68227239 break :result .{ .eflags = ro.eflags };
68237240 } else {
68247241 const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp);
......@@ -6833,11 +7250,12 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
68337250 if (field_off % 8 == 0) {
68347251 const off_mcv =
68357252 src_mcv.address().offset(@intCast(@divExact(field_off, 8))).deref();
7253 const field_bit_size = field_ty.bitSize(mod);
68367254
68377255 if (field_abi_size <= 8) {
68387256 const int_ty = try mod.intType(
68397257 if (field_ty.isAbiInt(mod)) field_ty.intInfo(mod).signedness else .unsigned,
6840 @intCast(field_ty.bitSize(mod)),
7258 @intCast(field_bit_size),
68417259 );
68427260
68437261 const dst_reg = try self.register_manager.allocReg(
......@@ -6856,10 +7274,24 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
68567274 try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv);
68577275 }
68587276
6859 if (self.reuseOperand(inst, operand, 0, src_mcv)) break :result off_mcv;
6860
6861 const dst_mcv = try self.allocRegOrMem(inst, true);
6862 try self.genCopy(field_ty, dst_mcv, off_mcv);
7277 const dst_mcv = if (self.reuseOperand(inst, operand, 0, src_mcv))
7278 off_mcv
7279 else dst: {
7280 const dst_mcv = try self.allocRegOrMem(inst, true);
7281 try self.genCopy(field_ty, dst_mcv, off_mcv);
7282 break :dst dst_mcv;
7283 };
7284 if (field_abi_size * 8 > field_bit_size and dst_mcv.isMemory()) {
7285 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
7286 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7287 defer self.register_manager.unlockReg(tmp_lock);
7288
7289 const hi_mcv =
7290 dst_mcv.address().offset(@intCast(field_bit_size / 64 * 8)).deref();
7291 try self.genSetReg(tmp_reg, Type.usize, hi_mcv);
7292 try self.truncateRegister(field_ty, tmp_reg);
7293 try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg });
7294 }
68637295 break :result dst_mcv;
68647296 }
68657297
......@@ -6888,6 +7320,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
68887320 .disp = frame_addr.off + field_byte_off,
68897321 } },
68907322 });
7323 try self.spillEflagsIfOccupied();
68917324 try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(field_bit_off));
68927325 } else {
68937326 const tmp_reg = registerAlias(
......@@ -6916,6 +7349,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
69167349 .disp = frame_addr.off + field_byte_off + limb_abi_size,
69177350 } },
69187351 });
7352 try self.spillEflagsIfOccupied();
69197353 try self.asmRegisterRegisterImmediate(
69207354 .{ ._rd, .sh },
69217355 dst_alias,
......@@ -6960,13 +7394,18 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
69607394fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: Air.Inst.Ref) !MCValue {
69617395 const mod = self.bin_file.options.module.?;
69627396 const src_ty = self.typeOf(src_air);
6963 const src_mcv = try self.resolveInst(src_air);
69647397 if (src_ty.zigTypeTag(mod) == .Vector)
69657398 return self.fail("TODO implement genUnOp for {}", .{src_ty.fmt(mod)});
69667399
7400 var src_mcv = try self.resolveInst(src_air);
69677401 switch (src_mcv) {
69687402 .eflags => |cc| switch (tag) {
6969 .not => return .{ .eflags = cc.negate() },
7403 .not => {
7404 if (maybe_inst) |inst| if (self.reuseOperand(inst, src_air, 0, src_mcv))
7405 return .{ .eflags = cc.negate() };
7406 try self.spillEflagsIfOccupied();
7407 src_mcv = try self.resolveInst(src_air);
7408 },
69707409 else => {},
69717410 },
69727411 else => {},
......@@ -7013,7 +7452,25 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air:
70137452 } else try self.genUnOpMir(.{ ._, .not }, limb_ty, limb_mcv);
70147453 }
70157454 },
7016 .neg => try self.genUnOpMir(.{ ._, .neg }, src_ty, dst_mcv),
7455 .neg => {
7456 try self.genUnOpMir(.{ ._, .neg }, src_ty, dst_mcv);
7457 const abi_size: u16 = @intCast(src_ty.abiSize(mod));
7458 const bit_size = src_ty.intInfo(mod).bits;
7459 if (abi_size * 8 > bit_size) {
7460 if (dst_mcv.isRegister()) {
7461 try self.truncateRegister(src_ty, dst_mcv.getReg().?);
7462 } else {
7463 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
7464 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7465 defer self.register_manager.unlockReg(tmp_lock);
7466
7467 const hi_mcv = dst_mcv.address().offset(@intCast(bit_size / 64 * 8)).deref();
7468 try self.genSetReg(tmp_reg, Type.usize, hi_mcv);
7469 try self.truncateRegister(src_ty, tmp_reg);
7470 try self.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg });
7471 }
7472 }
7473 },
70177474 else => unreachable,
70187475 }
70197476 return dst_mcv;
......@@ -7054,7 +7511,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MC
70547511 },
70557512 .indirect, .load_frame => try self.asmMemory(
70567513 mir_tag,
7057 dst_mcv.mem(Memory.Size.fromSize(abi_size)),
7514 try dst_mcv.mem(self, Memory.Size.fromSize(abi_size)),
70587515 ),
70597516 }
70607517}
......@@ -7552,27 +8009,27 @@ fn genMulDivBinOp(
75528009 defer self.register_manager.unlockReg(tmp_lock);
75538010
75548011 if (mat_lhs_mcv.isMemory())
7555 try self.asmRegisterMemory(.{ ._, .mov }, .rax, mat_lhs_mcv.mem(.qword))
8012 try self.asmRegisterMemory(.{ ._, .mov }, .rax, try mat_lhs_mcv.mem(self, .qword))
75568013 else
75578014 try self.asmRegisterRegister(.{ ._, .mov }, .rax, mat_lhs_mcv.register_pair[0]);
75588015 if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory(
75598016 .{ ._, .mov },
75608017 tmp_reg,
7561 mat_rhs_mcv.address().offset(8).deref().mem(.qword),
8018 try mat_rhs_mcv.address().offset(8).deref().mem(self, .qword),
75628019 ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, mat_rhs_mcv.register_pair[1]);
75638020 try self.asmRegisterRegister(.{ .i_, .mul }, tmp_reg, .rax);
75648021 if (mat_rhs_mcv.isMemory())
7565 try self.asmMemory(.{ ._, .mul }, mat_rhs_mcv.mem(.qword))
8022 try self.asmMemory(.{ ._, .mul }, try mat_rhs_mcv.mem(self, .qword))
75668023 else
75678024 try self.asmRegister(.{ ._, .mul }, mat_rhs_mcv.register_pair[0]);
75688025 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_reg);
75698026 if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory(
75708027 .{ ._, .mov },
75718028 tmp_reg,
7572 mat_lhs_mcv.address().offset(8).deref().mem(.qword),
8029 try mat_lhs_mcv.address().offset(8).deref().mem(self, .qword),
75738030 ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, mat_lhs_mcv.register_pair[1]);
75748031 if (mat_rhs_mcv.isMemory())
7575 try self.asmRegisterMemory(.{ .i_, .mul }, tmp_reg, mat_rhs_mcv.mem(.qword))
8032 try self.asmRegisterMemory(.{ .i_, .mul }, tmp_reg, try mat_rhs_mcv.mem(self, .qword))
75768033 else
75778034 try self.asmRegisterRegister(.{ .i_, .mul }, tmp_reg, mat_rhs_mcv.register_pair[0]);
75788035 try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_reg);
......@@ -7833,7 +8290,7 @@ fn genBinOp(
78338290 .{ .vp_w, .insr },
78348291 dst_reg,
78358292 dst_reg,
7836 rhs_mcv.mem(.word),
8293 try rhs_mcv.mem(self, .word),
78378294 Immediate.u(1),
78388295 ) else try self.asmRegisterRegisterRegister(
78398296 .{ .vp_, .unpcklwd },
......@@ -7858,7 +8315,7 @@ fn genBinOp(
78588315 mir_tag,
78598316 dst_reg,
78608317 dst_reg,
7861 src_mcv.mem(Memory.Size.fromBitSize(float_bits)),
8318 try src_mcv.mem(self, Memory.Size.fromBitSize(float_bits)),
78628319 ) else try self.asmRegisterRegisterRegister(
78638320 mir_tag,
78648321 dst_reg,
......@@ -7877,7 +8334,7 @@ fn genBinOp(
78778334 if (src_mcv.isMemory()) try self.asmRegisterMemory(
78788335 mir_tag,
78798336 dst_reg,
7880 src_mcv.mem(Memory.Size.fromBitSize(float_bits)),
8337 try src_mcv.mem(self, Memory.Size.fromBitSize(float_bits)),
78818338 ) else try self.asmRegisterRegister(
78828339 mir_tag,
78838340 dst_reg,
......@@ -7919,12 +8376,18 @@ fn genBinOp(
79198376 };
79208377 }
79218378
7922 if ((lhs_ty.scalarType(mod).isRuntimeFloat() and
8379 const sse_op = switch (lhs_ty.zigTypeTag(mod)) {
8380 else => false,
8381 .Float => true,
8382 .Vector => switch (lhs_ty.childType(mod).toIntern()) {
8383 .bool_type => false,
8384 else => true,
8385 },
8386 };
8387 if (sse_op and ((lhs_ty.scalarType(mod).isRuntimeFloat() and
79238388 lhs_ty.scalarType(mod).floatBits(self.target.*) == 80) or
7924 lhs_ty.abiSize(mod) > @as(u6, if (self.hasFeature(.avx)) 32 else 16))
7925 return self.fail("TODO implement genBinOp for {s} {}", .{
7926 @tagName(air_tag), lhs_ty.fmt(mod),
7927 });
8389 lhs_ty.abiSize(mod) > @as(u6, if (self.hasFeature(.avx)) 32 else 16)))
8390 return self.fail("TODO implement genBinOp for {s} {}", .{ @tagName(air_tag), lhs_ty.fmt(mod) });
79288391
79298392 const maybe_mask_reg = switch (air_tag) {
79308393 else => null,
......@@ -7941,10 +8404,16 @@ fn genBinOp(
79418404 if (maybe_mask_reg) |mask_reg| self.register_manager.lockRegAssumeUnused(mask_reg) else null;
79428405 defer if (mask_lock) |lock| self.register_manager.unlockReg(lock);
79438406
7944 const ordered_air = if (lhs_ty.isVector(mod) and lhs_ty.childType(mod).isAbiInt(mod) and
7945 switch (air_tag) {
7946 .cmp_lt, .cmp_gte => true,
7947 else => false,
8407 const ordered_air = if (lhs_ty.isVector(mod) and switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
8408 .Int => switch (air_tag) {
8409 .cmp_lt, .cmp_gte => true,
8410 else => false,
8411 },
8412 .Float => switch (air_tag) {
8413 .cmp_gte, .cmp_gt => true,
8414 else => false,
8415 },
8416 else => unreachable,
79488417 }) .{ .lhs = rhs_air, .rhs = lhs_air } else .{ .lhs = lhs_air, .rhs = rhs_air };
79498418
79508419 const lhs_mcv = try self.resolveInst(ordered_air.lhs);
......@@ -7971,14 +8440,12 @@ fn genBinOp(
79718440 .xor,
79728441 .min,
79738442 .max,
8443 .cmp_eq,
8444 .cmp_neq,
79748445 => true,
79758446
79768447 else => false,
79778448 };
7978 const vec_op = switch (lhs_ty.zigTypeTag(mod)) {
7979 else => false,
7980 .Float, .Vector => true,
7981 };
79828449
79838450 const lhs_locks: [2]?RegisterLock = switch (lhs_mcv) {
79848451 .register => |lhs_reg| .{ self.register_manager.lockRegAssumeUnused(lhs_reg), null },
......@@ -8000,23 +8467,23 @@ fn genBinOp(
80008467 var flipped = false;
80018468 var copied_to_dst = true;
80028469 const dst_mcv: MCValue = dst: {
8470 const tracked_inst = switch (air_tag) {
8471 else => maybe_inst,
8472 .cmp_lt, .cmp_lte, .cmp_eq, .cmp_gte, .cmp_gt, .cmp_neq => null,
8473 };
80038474 if (maybe_inst) |inst| {
8004 const tracked_inst = switch (air_tag) {
8005 else => inst,
8006 .cmp_lt, .cmp_lte, .cmp_eq, .cmp_gte, .cmp_gt, .cmp_neq => null,
8007 };
8008 if ((!vec_op or lhs_mcv.isRegister()) and
8475 if ((!sse_op or lhs_mcv.isRegister()) and
80098476 self.reuseOperandAdvanced(inst, ordered_air.lhs, 0, lhs_mcv, tracked_inst))
80108477 break :dst lhs_mcv;
8011 if (is_commutative and (!vec_op or rhs_mcv.isRegister()) and
8478 if (is_commutative and (!sse_op or rhs_mcv.isRegister()) and
80128479 self.reuseOperandAdvanced(inst, ordered_air.rhs, 1, rhs_mcv, tracked_inst))
80138480 {
80148481 flipped = true;
80158482 break :dst rhs_mcv;
80168483 }
80178484 }
8018 const dst_mcv = try self.allocRegOrMemAdvanced(lhs_ty, maybe_inst, true);
8019 if (vec_op and lhs_mcv.isRegister() and self.hasFeature(.avx))
8485 const dst_mcv = try self.allocRegOrMemAdvanced(lhs_ty, tracked_inst, true);
8486 if (sse_op and lhs_mcv.isRegister() and self.hasFeature(.avx))
80208487 copied_to_dst = false
80218488 else
80228489 try self.genCopy(lhs_ty, dst_mcv, lhs_mcv);
......@@ -8046,7 +8513,7 @@ fn genBinOp(
80468513 };
80478514 defer for (src_locks) |src_lock| if (src_lock) |lock| self.register_manager.unlockReg(lock);
80488515
8049 if (!vec_op) {
8516 if (!sse_op) {
80508517 switch (air_tag) {
80518518 .add,
80528519 .add_wrap,
......@@ -8130,17 +8597,25 @@ fn genBinOp(
81308597
81318598 try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, dst_regs[1]);
81328599 if (src_mcv.isMemory()) {
8133 try self.asmRegisterMemory(.{ ._, .cmp }, dst_regs[0], src_mcv.mem(.qword));
8600 try self.asmRegisterMemory(
8601 .{ ._, .cmp },
8602 dst_regs[0],
8603 try src_mcv.mem(self, .qword),
8604 );
81348605 try self.asmRegisterMemory(
81358606 .{ ._, .sbb },
81368607 tmp_reg,
8137 src_mcv.address().offset(8).deref().mem(.qword),
8608 try src_mcv.address().offset(8).deref().mem(self, .qword),
8609 );
8610 try self.asmCmovccRegisterMemory(
8611 cc,
8612 dst_regs[0],
8613 try src_mcv.mem(self, .qword),
81388614 );
8139 try self.asmCmovccRegisterMemory(cc, dst_regs[0], src_mcv.mem(.qword));
81408615 try self.asmCmovccRegisterMemory(
81418616 cc,
81428617 dst_regs[1],
8143 src_mcv.address().offset(8).deref().mem(.qword),
8618 try src_mcv.address().offset(8).deref().mem(self, .qword),
81448619 );
81458620 } else {
81468621 try self.asmRegisterRegister(
......@@ -8292,7 +8767,7 @@ fn genBinOp(
82928767 .{ .vp_w, .insr },
82938768 dst_reg,
82948769 dst_reg,
8295 src_mcv.mem(.word),
8770 try src_mcv.mem(self, .word),
82968771 Immediate.u(1),
82978772 ) else try self.asmRegisterRegisterRegister(
82988773 .{ .vp_, .unpcklwd },
......@@ -8738,7 +9213,7 @@ fn genBinOp(
87389213 .{ .vp_w, .insr },
87399214 dst_reg,
87409215 dst_reg,
8741 src_mcv.mem(.word),
9216 try src_mcv.mem(self, .word),
87429217 Immediate.u(1),
87439218 ) else try self.asmRegisterRegisterRegister(
87449219 .{ .vp_, .unpcklwd },
......@@ -8784,7 +9259,7 @@ fn genBinOp(
87849259 if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
87859260 .{ .vp_d, .insr },
87869261 dst_reg,
8787 src_mcv.mem(.dword),
9262 try src_mcv.mem(self, .dword),
87889263 Immediate.u(1),
87899264 ) else try self.asmRegisterRegisterRegister(
87909265 .{ .v_ps, .unpckl },
......@@ -8836,7 +9311,7 @@ fn genBinOp(
88369311 if (src_mcv.isMemory()) try self.asmRegisterMemory(
88379312 .{ .v_ps, .cvtph2 },
88389313 tmp_reg,
8839 src_mcv.mem(.qword),
9314 try src_mcv.mem(self, .qword),
88409315 ) else try self.asmRegisterRegister(
88419316 .{ .v_ps, .cvtph2 },
88429317 tmp_reg,
......@@ -8879,7 +9354,7 @@ fn genBinOp(
88799354 if (src_mcv.isMemory()) try self.asmRegisterMemory(
88809355 .{ .v_ps, .cvtph2 },
88819356 tmp_reg,
8882 src_mcv.mem(.xword),
9357 try src_mcv.mem(self, .xword),
88839358 ) else try self.asmRegisterRegister(
88849359 .{ .v_ps, .cvtph2 },
88859360 tmp_reg,
......@@ -8925,6 +9400,13 @@ fn genBinOp(
89259400 => if (self.hasFeature(.avx)) .{ .v_ss, .div } else .{ ._ss, .div },
89269401 .max => if (self.hasFeature(.avx)) .{ .v_ss, .max } else .{ ._ss, .max },
89279402 .min => if (self.hasFeature(.avx)) .{ .v_ss, .min } else .{ ._ss, .min },
9403 .cmp_lt,
9404 .cmp_lte,
9405 .cmp_eq,
9406 .cmp_gte,
9407 .cmp_gt,
9408 .cmp_neq,
9409 => if (self.hasFeature(.avx)) .{ .v_ss, .cmp } else .{ ._ss, .cmp },
89289410 else => unreachable,
89299411 },
89309412 2...4 => switch (air_tag) {
......@@ -8938,6 +9420,13 @@ fn genBinOp(
89389420 => if (self.hasFeature(.avx)) .{ .v_ps, .div } else .{ ._ps, .div },
89399421 .max => if (self.hasFeature(.avx)) .{ .v_ps, .max } else .{ ._ps, .max },
89409422 .min => if (self.hasFeature(.avx)) .{ .v_ps, .min } else .{ ._ps, .min },
9423 .cmp_lt,
9424 .cmp_lte,
9425 .cmp_eq,
9426 .cmp_gte,
9427 .cmp_gt,
9428 .cmp_neq,
9429 => if (self.hasFeature(.avx)) .{ .v_ps, .cmp } else .{ ._ps, .cmp },
89419430 else => unreachable,
89429431 },
89439432 5...8 => if (self.hasFeature(.avx)) switch (air_tag) {
......@@ -8947,6 +9436,7 @@ fn genBinOp(
89479436 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },
89489437 .max => .{ .v_ps, .max },
89499438 .min => .{ .v_ps, .min },
9439 .cmp_lt, .cmp_lte, .cmp_eq, .cmp_gte, .cmp_gt, .cmp_neq => .{ .v_ps, .cmp },
89509440 else => unreachable,
89519441 } else null,
89529442 else => null,
......@@ -8963,6 +9453,13 @@ fn genBinOp(
89639453 => if (self.hasFeature(.avx)) .{ .v_sd, .div } else .{ ._sd, .div },
89649454 .max => if (self.hasFeature(.avx)) .{ .v_sd, .max } else .{ ._sd, .max },
89659455 .min => if (self.hasFeature(.avx)) .{ .v_sd, .min } else .{ ._sd, .min },
9456 .cmp_lt,
9457 .cmp_lte,
9458 .cmp_eq,
9459 .cmp_gte,
9460 .cmp_gt,
9461 .cmp_neq,
9462 => if (self.hasFeature(.avx)) .{ .v_sd, .cmp } else .{ ._sd, .cmp },
89669463 else => unreachable,
89679464 },
89689465 2 => switch (air_tag) {
......@@ -8976,6 +9473,13 @@ fn genBinOp(
89769473 => if (self.hasFeature(.avx)) .{ .v_pd, .div } else .{ ._pd, .div },
89779474 .max => if (self.hasFeature(.avx)) .{ .v_pd, .max } else .{ ._pd, .max },
89789475 .min => if (self.hasFeature(.avx)) .{ .v_pd, .min } else .{ ._pd, .min },
9476 .cmp_lt,
9477 .cmp_lte,
9478 .cmp_eq,
9479 .cmp_gte,
9480 .cmp_gt,
9481 .cmp_neq,
9482 => if (self.hasFeature(.avx)) .{ .v_pd, .cmp } else .{ ._pd, .cmp },
89799483 else => unreachable,
89809484 },
89819485 3...4 => if (self.hasFeature(.avx)) switch (air_tag) {
......@@ -8984,6 +9488,7 @@ fn genBinOp(
89849488 .mul => .{ .v_pd, .mul },
89859489 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_pd, .div },
89869490 .max => .{ .v_pd, .max },
9491 .cmp_lt, .cmp_lte, .cmp_eq, .cmp_gte, .cmp_gt, .cmp_neq => .{ .v_pd, .cmp },
89879492 .min => .{ .v_pd, .min },
89889493 else => unreachable,
89899494 } else null,
......@@ -9004,43 +9509,96 @@ fn genBinOp(
90049509 const lhs_copy_lock = if (lhs_copy_reg) |reg| self.register_manager.lockReg(reg) else null;
90059510 defer if (lhs_copy_lock) |lock| self.register_manager.unlockReg(lock);
90069511
9007 if (self.hasFeature(.avx)) {
9008 const lhs_reg =
9009 if (copied_to_dst) dst_reg else registerAlias(lhs_mcv.getReg().?, abi_size);
9010 if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
9011 mir_tag,
9012 dst_reg,
9013 lhs_reg,
9014 src_mcv.mem(switch (lhs_ty.zigTypeTag(mod)) {
9015 else => Memory.Size.fromSize(abi_size),
9016 .Vector => Memory.Size.fromBitSize(dst_reg.bitSize()),
9017 }),
9018 ) else try self.asmRegisterRegisterRegister(
9019 mir_tag,
9020 dst_reg,
9021 lhs_reg,
9022 registerAlias(if (src_mcv.isRegister())
9023 src_mcv.getReg().?
9024 else
9025 try self.copyToTmpRegister(rhs_ty, src_mcv), abi_size),
9026 );
9027 } else {
9028 assert(copied_to_dst);
9029 if (src_mcv.isMemory()) try self.asmRegisterMemory(
9030 mir_tag,
9031 dst_reg,
9032 src_mcv.mem(switch (lhs_ty.zigTypeTag(mod)) {
9033 else => Memory.Size.fromSize(abi_size),
9034 .Vector => Memory.Size.fromBitSize(dst_reg.bitSize()),
9035 }),
9036 ) else try self.asmRegisterRegister(
9037 mir_tag,
9038 dst_reg,
9039 registerAlias(if (src_mcv.isRegister())
9040 src_mcv.getReg().?
9041 else
9042 try self.copyToTmpRegister(rhs_ty, src_mcv), abi_size),
9043 );
9512 switch (mir_tag[1]) {
9513 else => if (self.hasFeature(.avx)) {
9514 const lhs_reg =
9515 if (copied_to_dst) dst_reg else registerAlias(lhs_mcv.getReg().?, abi_size);
9516 if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
9517 mir_tag,
9518 dst_reg,
9519 lhs_reg,
9520 try src_mcv.mem(self, switch (lhs_ty.zigTypeTag(mod)) {
9521 else => Memory.Size.fromSize(abi_size),
9522 .Vector => Memory.Size.fromBitSize(dst_reg.bitSize()),
9523 }),
9524 ) else try self.asmRegisterRegisterRegister(
9525 mir_tag,
9526 dst_reg,
9527 lhs_reg,
9528 registerAlias(if (src_mcv.isRegister())
9529 src_mcv.getReg().?
9530 else
9531 try self.copyToTmpRegister(rhs_ty, src_mcv), abi_size),
9532 );
9533 } else {
9534 assert(copied_to_dst);
9535 if (src_mcv.isMemory()) try self.asmRegisterMemory(
9536 mir_tag,
9537 dst_reg,
9538 try src_mcv.mem(self, switch (lhs_ty.zigTypeTag(mod)) {
9539 else => Memory.Size.fromSize(abi_size),
9540 .Vector => Memory.Size.fromBitSize(dst_reg.bitSize()),
9541 }),
9542 ) else try self.asmRegisterRegister(
9543 mir_tag,
9544 dst_reg,
9545 registerAlias(if (src_mcv.isRegister())
9546 src_mcv.getReg().?
9547 else
9548 try self.copyToTmpRegister(rhs_ty, src_mcv), abi_size),
9549 );
9550 },
9551 .cmp => {
9552 const imm = Immediate.u(switch (air_tag) {
9553 .cmp_eq => 0,
9554 .cmp_lt, .cmp_gt => 1,
9555 .cmp_lte, .cmp_gte => 2,
9556 .cmp_neq => 4,
9557 else => unreachable,
9558 });
9559 if (self.hasFeature(.avx)) {
9560 const lhs_reg =
9561 if (copied_to_dst) dst_reg else registerAlias(lhs_mcv.getReg().?, abi_size);
9562 if (src_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate(
9563 mir_tag,
9564 dst_reg,
9565 lhs_reg,
9566 try src_mcv.mem(self, switch (lhs_ty.zigTypeTag(mod)) {
9567 else => Memory.Size.fromSize(abi_size),
9568 .Vector => Memory.Size.fromBitSize(dst_reg.bitSize()),
9569 }),
9570 imm,
9571 ) else try self.asmRegisterRegisterRegisterImmediate(
9572 mir_tag,
9573 dst_reg,
9574 lhs_reg,
9575 registerAlias(if (src_mcv.isRegister())
9576 src_mcv.getReg().?
9577 else
9578 try self.copyToTmpRegister(rhs_ty, src_mcv), abi_size),
9579 imm,
9580 );
9581 } else {
9582 assert(copied_to_dst);
9583 if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
9584 mir_tag,
9585 dst_reg,
9586 try src_mcv.mem(self, switch (lhs_ty.zigTypeTag(mod)) {
9587 else => Memory.Size.fromSize(abi_size),
9588 .Vector => Memory.Size.fromBitSize(dst_reg.bitSize()),
9589 }),
9590 imm,
9591 ) else try self.asmRegisterRegisterImmediate(
9592 mir_tag,
9593 dst_reg,
9594 registerAlias(if (src_mcv.isRegister())
9595 src_mcv.getReg().?
9596 else
9597 try self.copyToTmpRegister(rhs_ty, src_mcv), abi_size),
9598 imm,
9599 );
9600 }
9601 },
90449602 }
90459603
90469604 switch (air_tag) {
......@@ -9281,48 +9839,46 @@ fn genBinOp(
92819839 );
92829840 }
92839841 },
9284 .cmp_lt,
9285 .cmp_lte,
9286 .cmp_eq,
9287 .cmp_gte,
9288 .cmp_gt,
9289 .cmp_neq,
9290 => {
9291 switch (air_tag) {
9292 .cmp_lt,
9293 .cmp_eq,
9294 .cmp_gt,
9295 => {},
9296 .cmp_lte,
9297 .cmp_gte,
9298 .cmp_neq,
9299 => {
9300 const unsigned_ty = try lhs_ty.toUnsigned(mod);
9301 const not_mcv = try self.genTypedValue(.{
9302 .ty = lhs_ty,
9303 .val = try unsigned_ty.maxInt(mod, unsigned_ty),
9304 });
9305 const not_mem: Memory = if (not_mcv.isMemory())
9306 not_mcv.mem(Memory.Size.fromSize(abi_size))
9307 else
9308 .{ .base = .{
9309 .reg = try self.copyToTmpRegister(Type.usize, not_mcv.address()),
9310 }, .mod = .{ .rm = .{ .size = Memory.Size.fromSize(abi_size) } } };
9311 switch (mir_tag[0]) {
9312 .vp_b, .vp_d, .vp_q, .vp_w => try self.asmRegisterRegisterMemory(
9313 .{ .vp_, .xor },
9314 dst_reg,
9315 dst_reg,
9316 not_mem,
9317 ),
9318 .p_b, .p_d, .p_q, .p_w => try self.asmRegisterMemory(
9319 .{ .p_, .xor },
9320 dst_reg,
9321 not_mem,
9322 ),
9323 else => unreachable,
9324 }
9842 .cmp_lt, .cmp_lte, .cmp_eq, .cmp_gte, .cmp_gt, .cmp_neq => {
9843 switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
9844 .Int => switch (air_tag) {
9845 .cmp_lt,
9846 .cmp_eq,
9847 .cmp_gt,
9848 => {},
9849 .cmp_lte,
9850 .cmp_gte,
9851 .cmp_neq,
9852 => {
9853 const unsigned_ty = try lhs_ty.toUnsigned(mod);
9854 const not_mcv = try self.genTypedValue(.{
9855 .ty = lhs_ty,
9856 .val = try unsigned_ty.maxInt(mod, unsigned_ty),
9857 });
9858 const not_mem: Memory = if (not_mcv.isMemory())
9859 try not_mcv.mem(self, Memory.Size.fromSize(abi_size))
9860 else
9861 .{ .base = .{
9862 .reg = try self.copyToTmpRegister(Type.usize, not_mcv.address()),
9863 }, .mod = .{ .rm = .{ .size = Memory.Size.fromSize(abi_size) } } };
9864 switch (mir_tag[0]) {
9865 .vp_b, .vp_d, .vp_q, .vp_w => try self.asmRegisterRegisterMemory(
9866 .{ .vp_, .xor },
9867 dst_reg,
9868 dst_reg,
9869 not_mem,
9870 ),
9871 .p_b, .p_d, .p_q, .p_w => try self.asmRegisterMemory(
9872 .{ .p_, .xor },
9873 dst_reg,
9874 not_mem,
9875 ),
9876 else => unreachable,
9877 }
9878 },
9879 else => unreachable,
93259880 },
9881 .Float => {},
93269882 else => unreachable,
93279883 }
93289884
......@@ -9331,8 +9887,12 @@ fn genBinOp(
93319887 defer self.register_manager.unlockReg(gp_lock);
93329888
93339889 try self.asmRegisterRegister(switch (mir_tag[0]) {
9334 .vp_b, .vp_d, .vp_q, .vp_w => .{ .vp_b, .movmsk },
9890 ._pd, ._sd => .{ ._pd, .movmsk },
9891 ._ps, ._ss => .{ ._ps, .movmsk },
93359892 .p_b, .p_d, .p_q, .p_w => .{ .p_b, .movmsk },
9893 .v_pd, .v_sd => .{ .v_pd, .movmsk },
9894 .v_ps, .v_ss => .{ .v_ps, .movmsk },
9895 .vp_b, .vp_d, .vp_q, .vp_w => .{ .vp_b, .movmsk },
93369896 else => unreachable,
93379897 }, gp_reg.to32(), dst_reg);
93389898 return .{ .register = gp_reg };
......@@ -9459,13 +10019,13 @@ fn genBinOpMir(
945910019 .load_frame,
946010020 .lea_frame,
946110021 => {
9462 blk: {
9463 return self.asmRegisterMemory(mir_limb_tag, dst_alias, switch (src_mcv) {
10022 direct: {
10023 try self.asmRegisterMemory(mir_limb_tag, dst_alias, switch (src_mcv) {
946410024 .memory => |addr| .{
946510025 .base = .{ .reg = .ds },
946610026 .mod = .{ .rm = .{
946710027 .size = Memory.Size.fromSize(limb_abi_size),
9468 .disp = math.cast(i32, addr + off) orelse break :blk,
10028 .disp = math.cast(i32, addr + off) orelse break :direct,
946910029 } },
947010030 },
947110031 .indirect => |reg_off| .{
......@@ -9482,8 +10042,9 @@ fn genBinOpMir(
948210042 .disp = frame_addr.off + off,
948310043 } },
948410044 },
9485 else => break :blk,
10045 else => break :direct,
948610046 });
10047 continue;
948710048 }
948810049
948910050 switch (src_mcv) {
......@@ -10142,30 +10703,30 @@ fn genCall(self: *Self, info: union(enum) {
1014210703 }
1014310704
1014410705 try self.spillEflagsIfOccupied();
10145 try self.spillRegisters(abi.getCallerPreservedRegs(resolved_cc));
10706 try self.spillCallerPreservedRegs(resolved_cc);
1014610707
1014710708 // set stack arguments first because this can clobber registers
1014810709 // also clobber spill arguments as we go
1014910710 switch (call_info.return_value.long) {
1015010711 .none, .unreach => {},
10151 .indirect => |reg_off| try self.spillRegisters(&.{reg_off.reg}),
10712 .indirect => |reg_off| try self.register_manager.getReg(reg_off.reg, null),
1015210713 else => unreachable,
1015310714 }
1015410715 for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, *frame_index|
1015510716 switch (dst_arg) {
1015610717 .none => {},
1015710718 .register => |reg| {
10158 try self.spillRegisters(&.{reg});
10719 try self.register_manager.getReg(reg, null);
1015910720 try reg_locks.append(self.register_manager.lockReg(reg));
1016010721 },
1016110722 .register_pair => |regs| {
10162 try self.spillRegisters(&regs);
10723 for (regs) |reg| try self.register_manager.getReg(reg, null);
1016310724 try reg_locks.appendSlice(&self.register_manager.lockRegs(2, regs));
1016410725 },
1016510726 .indirect => |reg_off| {
1016610727 frame_index.* = try self.allocFrameIndex(FrameAlloc.initType(arg_ty, mod));
1016710728 try self.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg);
10168 try self.spillRegisters(&.{reg_off.reg});
10729 try self.register_manager.getReg(reg_off.reg, null);
1016910730 try reg_locks.append(self.register_manager.lockReg(reg_off.reg));
1017010731 },
1017110732 .load_frame => {
......@@ -10180,7 +10741,7 @@ fn genCall(self: *Self, info: union(enum) {
1018010741 .none, .unreach => {},
1018110742 .indirect => |reg_off| {
1018210743 const ret_ty = fn_info.return_type.toType();
10183 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, mod));
10744 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(ret_ty, mod));
1018410745 try self.genSetReg(reg_off.reg, Type.usize, .{
1018510746 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
1018610747 });
......@@ -10306,19 +10867,20 @@ fn genCall(self: *Self, info: union(enum) {
1030610867fn airRet(self: *Self, inst: Air.Inst.Index) !void {
1030710868 const mod = self.bin_file.options.module.?;
1030810869 const un_op = self.air.instructions.items(.data)[inst].un_op;
10309 const operand = try self.resolveInst(un_op);
1031010870
1031110871 const ret_ty = self.fn_type.fnReturnType(mod);
1031210872 switch (self.ret_mcv.short) {
1031310873 .none => {},
10314 .register, .register_pair => try self.genCopy(ret_ty, self.ret_mcv.short, operand),
10874 .register,
10875 .register_pair,
10876 => try self.genCopy(ret_ty, self.ret_mcv.short, .{ .air_ref = un_op }),
1031510877 .indirect => |reg_off| {
1031610878 try self.register_manager.getReg(reg_off.reg, null);
1031710879 const lock = self.register_manager.lockRegAssumeUnused(reg_off.reg);
1031810880 defer self.register_manager.unlockReg(lock);
1031910881
1032010882 try self.genSetReg(reg_off.reg, Type.usize, self.ret_mcv.long);
10321 try self.genSetMem(.{ .reg = reg_off.reg }, reg_off.off, ret_ty, operand);
10883 try self.genSetMem(.{ .reg = reg_off.reg }, reg_off.off, ret_ty, .{ .air_ref = un_op });
1032210884 },
1032310885 else => unreachable,
1032410886 }
......@@ -10593,7 +11155,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1059311155 const locks = self.register_manager.lockRegsAssumeUnused(2, regs);
1059411156 defer for (locks) |lock| self.register_manager.unlockReg(lock);
1059511157
10596 const limbs_len = std.math.divCeil(u16, abi_size, 8) catch unreachable;
11158 const limbs_len = math.divCeil(u16, abi_size, 8) catch unreachable;
1059711159 var limb_i: u16 = 0;
1059811160 while (limb_i < limbs_len) : (limb_i += 1) {
1059911161 const off = limb_i * 8;
......@@ -10688,7 +11250,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1068811250 .{ .vp_w, .insr },
1068911251 tmp1_reg,
1069011252 dst_reg.to128(),
10691 src_mcv.mem(.word),
11253 try src_mcv.mem(self, .word),
1069211254 Immediate.u(1),
1069311255 ) else try self.asmRegisterRegisterRegister(
1069411256 .{ .vp_, .unpcklwd },
......@@ -10892,8 +11454,8 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !Mir.Inst.Index {
1089211454 },
1089311455 .register => |reg| {
1089411456 try self.spillEflagsIfOccupied();
10895 try self.asmRegisterImmediate(.{ ._, .@"test" }, reg, Immediate.u(1));
10896 return self.asmJccReloc(.e, undefined);
11457 try self.asmRegisterImmediate(.{ ._, .@"test" }, reg.to8(), Immediate.u(1));
11458 return self.asmJccReloc(.z, undefined);
1089711459 },
1089811460 .immediate,
1089911461 .load_frame,
......@@ -11366,8 +11928,18 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void {
1136611928 try self.spillEflagsIfOccupied();
1136711929 for (items, relocs, 0..) |item, *reloc, i| {
1136811930 const item_mcv = try self.resolveInst(item);
11369 try self.genBinOpMir(.{ ._, .cmp }, condition_ty, condition, item_mcv);
11370 reloc.* = try self.asmJccReloc(if (i < relocs.len - 1) .e else .ne, undefined);
11931 const cc: Condition = switch (condition) {
11932 .eflags => |cc| switch (item_mcv.immediate) {
11933 0 => cc.negate(),
11934 1 => cc,
11935 else => unreachable,
11936 },
11937 else => cc: {
11938 try self.genBinOpMir(.{ ._, .cmp }, condition_ty, condition, item_mcv);
11939 break :cc .e;
11940 },
11941 };
11942 reloc.* = try self.asmJccReloc(if (i < relocs.len - 1) cc else cc.negate(), undefined);
1137111943 }
1137211944
1137311945 for (liveness.deaths[case_i]) |operand| try self.processDeath(operand);
......@@ -11433,12 +12005,12 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
1143312005 if (self.reuseOperandAdvanced(inst, br.operand, 0, src_mcv, br.block_inst)) {
1143412006 if (first_br) break :result src_mcv;
1143512007
11436 if (block_tracking.getReg()) |block_reg|
12008 for (block_tracking.getRegs()) |block_reg|
1143712009 try self.register_manager.getReg(block_reg, br.block_inst);
1143812010 // .long = .none to avoid merging operand and block result stack frames.
1143912011 var current_tracking = InstTracking{ .long = .none, .short = src_mcv };
1144012012 try current_tracking.materializeUnsafe(self, br.block_inst, block_tracking.*);
11441 if (src_mcv.getReg()) |src_reg| self.register_manager.freeReg(src_reg);
12013 for (src_mcv.getRegs()) |src_reg| self.register_manager.freeReg(src_reg);
1144212014 break :result block_tracking.short;
1144312015 }
1144412016
......@@ -11492,8 +12064,9 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1149212064 var args = std.ArrayList(MCValue).init(self.gpa);
1149312065 try args.ensureTotalCapacity(outputs.len + inputs.len);
1149412066 defer {
11495 for (args.items) |arg| if (arg.getReg()) |reg|
11496 self.register_manager.unlockReg(.{ .register = reg });
12067 for (args.items) |arg| if (arg.getReg()) |reg| self.register_manager.unlockReg(.{
12068 .tracked_index = RegisterManager.indexOfRegIntoTracked(reg) orelse continue,
12069 });
1149712070 args.deinit();
1149812071 }
1149912072 var arg_map = std.StringHashMap(u8).init(self.gpa);
......@@ -12177,16 +12750,87 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo
1217712750 .general_purpose, .segment => return .{ .move = .{ ._, .mov } },
1217812751 .x87 => return .x87_load_store,
1217912752 .mmx => {},
12180 .sse => {
12181 switch (ty.zigTypeTag(mod)) {
12182 else => {
12183 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none);
12184 assert(std.mem.indexOfNone(abi.Class, classes, &.{
12185 .integer, .sse, .float, .float_combine,
12186 }) == null);
12187 const abi_size = ty.abiSize(mod);
12188 if (abi_size < 4 or
12189 std.mem.indexOfScalar(abi.Class, classes, .integer) != null) switch (abi_size) {
12753 .sse => switch (ty.zigTypeTag(mod)) {
12754 else => {
12755 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none);
12756 assert(std.mem.indexOfNone(abi.Class, classes, &.{
12757 .integer, .sse, .float, .float_combine,
12758 }) == null);
12759 const abi_size = ty.abiSize(mod);
12760 if (abi_size < 4 or
12761 std.mem.indexOfScalar(abi.Class, classes, .integer) != null) switch (abi_size) {
12762 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{
12763 .insert = .{ .vp_b, .insr },
12764 .extract = .{ .vp_b, .extr },
12765 } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{
12766 .insert = .{ .p_b, .insr },
12767 .extract = .{ .p_b, .extr },
12768 } },
12769 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12770 .insert = .{ .vp_w, .insr },
12771 .extract = .{ .vp_w, .extr },
12772 } } else .{ .insert_extract = .{
12773 .insert = .{ .p_w, .insr },
12774 .extract = .{ .p_w, .extr },
12775 } },
12776 3...4 => return .{ .move = if (self.hasFeature(.avx))
12777 .{ .v_d, .mov }
12778 else
12779 .{ ._d, .mov } },
12780 5...8 => return .{ .move = if (self.hasFeature(.avx))
12781 .{ .v_q, .mov }
12782 else
12783 .{ ._q, .mov } },
12784 9...16 => return .{ .move = if (self.hasFeature(.avx))
12785 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12786 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12787 17...32 => if (self.hasFeature(.avx))
12788 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
12789 else => {},
12790 } else switch (abi_size) {
12791 4 => return .{ .move = if (self.hasFeature(.avx))
12792 .{ .v_ss, .mov }
12793 else
12794 .{ ._ss, .mov } },
12795 5...8 => return .{ .move = if (self.hasFeature(.avx))
12796 .{ .v_sd, .mov }
12797 else
12798 .{ ._sd, .mov } },
12799 9...16 => return .{ .move = if (self.hasFeature(.avx))
12800 if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu }
12801 else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } },
12802 17...32 => if (self.hasFeature(.avx)) return .{ .move = if (aligned)
12803 .{ .v_pd, .mova }
12804 else
12805 .{ .v_pd, .movu } },
12806 else => {},
12807 }
12808 },
12809 .Float => switch (ty.floatBits(self.target.*)) {
12810 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12811 .insert = .{ .vp_w, .insr },
12812 .extract = .{ .vp_w, .extr },
12813 } } else .{ .insert_extract = .{
12814 .insert = .{ .p_w, .insr },
12815 .extract = .{ .p_w, .extr },
12816 } },
12817 32 => return .{ .move = if (self.hasFeature(.avx))
12818 .{ .v_ss, .mov }
12819 else
12820 .{ ._ss, .mov } },
12821 64 => return .{ .move = if (self.hasFeature(.avx))
12822 .{ .v_sd, .mov }
12823 else
12824 .{ ._sd, .mov } },
12825 128 => return .{ .move = if (self.hasFeature(.avx))
12826 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12827 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12828 else => {},
12829 },
12830 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
12831 .Bool => {},
12832 .Int => switch (ty.childType(mod).intInfo(mod).bits) {
12833 8 => switch (ty.vectorLen(mod)) {
1219012834 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{
1219112835 .insert = .{ .vp_b, .insr },
1219212836 .extract = .{ .vp_b, .extr },
......@@ -12213,242 +12857,169 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo
1221312857 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
1221412858 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
1221512859 17...32 => if (self.hasFeature(.avx))
12216 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
12860 return .{ .move = if (aligned)
12861 .{ .v_, .movdqa }
12862 else
12863 .{ .v_, .movdqu } },
1221712864 else => {},
12218 } else switch (abi_size) {
12219 4 => return .{ .move = if (self.hasFeature(.avx))
12220 .{ .v_ss, .mov }
12865 },
12866 16 => switch (ty.vectorLen(mod)) {
12867 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12868 .insert = .{ .vp_w, .insr },
12869 .extract = .{ .vp_w, .extr },
12870 } } else .{ .insert_extract = .{
12871 .insert = .{ .p_w, .insr },
12872 .extract = .{ .p_w, .extr },
12873 } },
12874 2 => return .{ .move = if (self.hasFeature(.avx))
12875 .{ .v_d, .mov }
1222112876 else
12222 .{ ._ss, .mov } },
12877 .{ ._d, .mov } },
12878 3...4 => return .{ .move = if (self.hasFeature(.avx))
12879 .{ .v_q, .mov }
12880 else
12881 .{ ._q, .mov } },
1222312882 5...8 => return .{ .move = if (self.hasFeature(.avx))
12224 .{ .v_sd, .mov }
12883 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12884 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12885 9...16 => if (self.hasFeature(.avx))
12886 return .{ .move = if (aligned)
12887 .{ .v_, .movdqa }
12888 else
12889 .{ .v_, .movdqu } },
12890 else => {},
12891 },
12892 32 => switch (ty.vectorLen(mod)) {
12893 1 => return .{ .move = if (self.hasFeature(.avx))
12894 .{ .v_d, .mov }
1222512895 else
12226 .{ ._sd, .mov } },
12227 9...16 => return .{ .move = if (self.hasFeature(.avx))
12228 if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu }
12229 else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } },
12230 17...32 => if (self.hasFeature(.avx)) return .{ .move = if (aligned)
12231 .{ .v_pd, .mova }
12896 .{ ._d, .mov } },
12897 2 => return .{ .move = if (self.hasFeature(.avx))
12898 .{ .v_q, .mov }
1223212899 else
12233 .{ .v_pd, .movu } },
12234 else => {},
12235 }
12236 },
12237 .Float => switch (ty.floatBits(self.target.*)) {
12238 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12239 .insert = .{ .vp_w, .insr },
12240 .extract = .{ .vp_w, .extr },
12241 } } else .{ .insert_extract = .{
12242 .insert = .{ .p_w, .insr },
12243 .extract = .{ .p_w, .extr },
12244 } },
12245 32 => return .{ .move = if (self.hasFeature(.avx))
12246 .{ .v_ss, .mov }
12247 else
12248 .{ ._ss, .mov } },
12249 64 => return .{ .move = if (self.hasFeature(.avx))
12250 .{ .v_sd, .mov }
12251 else
12252 .{ ._sd, .mov } },
12253 128 => return .{ .move = if (self.hasFeature(.avx))
12254 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12255 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12256 else => {},
12257 },
12258 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
12259 .Bool => return .{ .move = .{ ._, .mov } },
12260 .Int => switch (ty.childType(mod).intInfo(mod).bits) {
12261 8 => switch (ty.vectorLen(mod)) {
12262 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{
12263 .insert = .{ .vp_b, .insr },
12264 .extract = .{ .vp_b, .extr },
12265 } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{
12266 .insert = .{ .p_b, .insr },
12267 .extract = .{ .p_b, .extr },
12268 } },
12269 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12270 .insert = .{ .vp_w, .insr },
12271 .extract = .{ .vp_w, .extr },
12272 } } else .{ .insert_extract = .{
12273 .insert = .{ .p_w, .insr },
12274 .extract = .{ .p_w, .extr },
12275 } },
12276 3...4 => return .{ .move = if (self.hasFeature(.avx))
12277 .{ .v_d, .mov }
12278 else
12279 .{ ._d, .mov } },
12280 5...8 => return .{ .move = if (self.hasFeature(.avx))
12281 .{ .v_q, .mov }
12282 else
12283 .{ ._q, .mov } },
12284 9...16 => return .{ .move = if (self.hasFeature(.avx))
12285 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12286 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12287 17...32 => if (self.hasFeature(.avx))
12288 return .{ .move = if (aligned)
12289 .{ .v_, .movdqa }
12290 else
12291 .{ .v_, .movdqu } },
12292 else => {},
12293 },
12294 16 => switch (ty.vectorLen(mod)) {
12295 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12296 .insert = .{ .vp_w, .insr },
12297 .extract = .{ .vp_w, .extr },
12298 } } else .{ .insert_extract = .{
12299 .insert = .{ .p_w, .insr },
12300 .extract = .{ .p_w, .extr },
12301 } },
12302 2 => return .{ .move = if (self.hasFeature(.avx))
12303 .{ .v_d, .mov }
12304 else
12305 .{ ._d, .mov } },
12306 3...4 => return .{ .move = if (self.hasFeature(.avx))
12307 .{ .v_q, .mov }
12308 else
12309 .{ ._q, .mov } },
12310 5...8 => return .{ .move = if (self.hasFeature(.avx))
12311 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12312 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12313 9...16 => if (self.hasFeature(.avx))
12314 return .{ .move = if (aligned)
12315 .{ .v_, .movdqa }
12316 else
12317 .{ .v_, .movdqu } },
12318 else => {},
12319 },
12320 32 => switch (ty.vectorLen(mod)) {
12321 1 => return .{ .move = if (self.hasFeature(.avx))
12322 .{ .v_d, .mov }
12900 .{ ._q, .mov } },
12901 3...4 => return .{ .move = if (self.hasFeature(.avx))
12902 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12903 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12904 5...8 => if (self.hasFeature(.avx))
12905 return .{ .move = if (aligned)
12906 .{ .v_, .movdqa }
1232312907 else
12324 .{ ._d, .mov } },
12325 2 => return .{ .move = if (self.hasFeature(.avx))
12326 .{ .v_q, .mov }
12908 .{ .v_, .movdqu } },
12909 else => {},
12910 },
12911 64 => switch (ty.vectorLen(mod)) {
12912 1 => return .{ .move = if (self.hasFeature(.avx))
12913 .{ .v_q, .mov }
12914 else
12915 .{ ._q, .mov } },
12916 2 => return .{ .move = if (self.hasFeature(.avx))
12917 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12918 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12919 3...4 => if (self.hasFeature(.avx))
12920 return .{ .move = if (aligned)
12921 .{ .v_, .movdqa }
1232712922 else
12328 .{ ._q, .mov } },
12329 3...4 => return .{ .move = if (self.hasFeature(.avx))
12330 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12331 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12332 5...8 => if (self.hasFeature(.avx))
12333 return .{ .move = if (aligned)
12334 .{ .v_, .movdqa }
12335 else
12336 .{ .v_, .movdqu } },
12337 else => {},
12338 },
12339 64 => switch (ty.vectorLen(mod)) {
12340 1 => return .{ .move = if (self.hasFeature(.avx))
12341 .{ .v_q, .mov }
12923 .{ .v_, .movdqu } },
12924 else => {},
12925 },
12926 128 => switch (ty.vectorLen(mod)) {
12927 1 => return .{ .move = if (self.hasFeature(.avx))
12928 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12929 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12930 2 => if (self.hasFeature(.avx))
12931 return .{ .move = if (aligned)
12932 .{ .v_, .movdqa }
1234212933 else
12343 .{ ._q, .mov } },
12344 2 => return .{ .move = if (self.hasFeature(.avx))
12345 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12346 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12347 3...4 => if (self.hasFeature(.avx))
12348 return .{ .move = if (aligned)
12349 .{ .v_, .movdqa }
12350 else
12351 .{ .v_, .movdqu } },
12352 else => {},
12353 },
12354 128 => switch (ty.vectorLen(mod)) {
12355 1 => return .{ .move = if (self.hasFeature(.avx))
12356 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12357 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12358 2 => if (self.hasFeature(.avx))
12359 return .{ .move = if (aligned)
12360 .{ .v_, .movdqa }
12361 else
12362 .{ .v_, .movdqu } },
12363 else => {},
12364 },
12365 256 => switch (ty.vectorLen(mod)) {
12366 1 => if (self.hasFeature(.avx))
12367 return .{ .move = if (aligned)
12368 .{ .v_, .movdqa }
12369 else
12370 .{ .v_, .movdqu } },
12371 else => {},
12372 },
12934 .{ .v_, .movdqu } },
1237312935 else => {},
1237412936 },
12375 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
12376 16 => switch (ty.vectorLen(mod)) {
12377 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12378 .insert = .{ .vp_w, .insr },
12379 .extract = .{ .vp_w, .extr },
12380 } } else .{ .insert_extract = .{
12381 .insert = .{ .p_w, .insr },
12382 .extract = .{ .p_w, .extr },
12383 } },
12384 2 => return .{ .move = if (self.hasFeature(.avx))
12385 .{ .v_d, .mov }
12937 256 => switch (ty.vectorLen(mod)) {
12938 1 => if (self.hasFeature(.avx))
12939 return .{ .move = if (aligned)
12940 .{ .v_, .movdqa }
1238612941 else
12387 .{ ._d, .mov } },
12388 3...4 => return .{ .move = if (self.hasFeature(.avx))
12389 .{ .v_q, .mov }
12942 .{ .v_, .movdqu } },
12943 else => {},
12944 },
12945 else => {},
12946 },
12947 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
12948 16 => switch (ty.vectorLen(mod)) {
12949 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12950 .insert = .{ .vp_w, .insr },
12951 .extract = .{ .vp_w, .extr },
12952 } } else .{ .insert_extract = .{
12953 .insert = .{ .p_w, .insr },
12954 .extract = .{ .p_w, .extr },
12955 } },
12956 2 => return .{ .move = if (self.hasFeature(.avx))
12957 .{ .v_d, .mov }
12958 else
12959 .{ ._d, .mov } },
12960 3...4 => return .{ .move = if (self.hasFeature(.avx))
12961 .{ .v_q, .mov }
12962 else
12963 .{ ._q, .mov } },
12964 5...8 => return .{ .move = if (self.hasFeature(.avx))
12965 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12966 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12967 9...16 => if (self.hasFeature(.avx))
12968 return .{ .move = if (aligned)
12969 .{ .v_, .movdqa }
1239012970 else
12391 .{ ._q, .mov } },
12392 5...8 => return .{ .move = if (self.hasFeature(.avx))
12393 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12394 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12395 9...16 => if (self.hasFeature(.avx))
12396 return .{ .move = if (aligned)
12397 .{ .v_, .movdqa }
12398 else
12399 .{ .v_, .movdqu } },
12400 else => {},
12401 },
12402 32 => switch (ty.vectorLen(mod)) {
12403 1 => return .{ .move = if (self.hasFeature(.avx))
12404 .{ .v_ss, .mov }
12971 .{ .v_, .movdqu } },
12972 else => {},
12973 },
12974 32 => switch (ty.vectorLen(mod)) {
12975 1 => return .{ .move = if (self.hasFeature(.avx))
12976 .{ .v_ss, .mov }
12977 else
12978 .{ ._ss, .mov } },
12979 2 => return .{ .move = if (self.hasFeature(.avx))
12980 .{ .v_sd, .mov }
12981 else
12982 .{ ._sd, .mov } },
12983 3...4 => return .{ .move = if (self.hasFeature(.avx))
12984 if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu }
12985 else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu } },
12986 5...8 => if (self.hasFeature(.avx))
12987 return .{ .move = if (aligned)
12988 .{ .v_ps, .mova }
1240512989 else
12406 .{ ._ss, .mov } },
12407 2 => return .{ .move = if (self.hasFeature(.avx))
12408 .{ .v_sd, .mov }
12990 .{ .v_ps, .movu } },
12991 else => {},
12992 },
12993 64 => switch (ty.vectorLen(mod)) {
12994 1 => return .{ .move = if (self.hasFeature(.avx))
12995 .{ .v_sd, .mov }
12996 else
12997 .{ ._sd, .mov } },
12998 2 => return .{ .move = if (self.hasFeature(.avx))
12999 if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu }
13000 else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } },
13001 3...4 => if (self.hasFeature(.avx))
13002 return .{ .move = if (aligned)
13003 .{ .v_pd, .mova }
1240913004 else
12410 .{ ._sd, .mov } },
12411 3...4 => return .{ .move = if (self.hasFeature(.avx))
12412 if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu }
12413 else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu } },
12414 5...8 => if (self.hasFeature(.avx))
12415 return .{ .move = if (aligned)
12416 .{ .v_ps, .mova }
12417 else
12418 .{ .v_ps, .movu } },
12419 else => {},
12420 },
12421 64 => switch (ty.vectorLen(mod)) {
12422 1 => return .{ .move = if (self.hasFeature(.avx))
12423 .{ .v_sd, .mov }
13005 .{ .v_pd, .movu } },
13006 else => {},
13007 },
13008 128 => switch (ty.vectorLen(mod)) {
13009 1 => return .{ .move = if (self.hasFeature(.avx))
13010 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
13011 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
13012 2 => if (self.hasFeature(.avx))
13013 return .{ .move = if (aligned)
13014 .{ .v_, .movdqa }
1242413015 else
12425 .{ ._sd, .mov } },
12426 2 => return .{ .move = if (self.hasFeature(.avx))
12427 if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu }
12428 else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } },
12429 3...4 => if (self.hasFeature(.avx))
12430 return .{ .move = if (aligned)
12431 .{ .v_pd, .mova }
12432 else
12433 .{ .v_pd, .movu } },
12434 else => {},
12435 },
12436 128 => switch (ty.vectorLen(mod)) {
12437 1 => return .{ .move = if (self.hasFeature(.avx))
12438 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12439 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12440 2 => if (self.hasFeature(.avx))
12441 return .{ .move = if (aligned)
12442 .{ .v_, .movdqa }
12443 else
12444 .{ .v_, .movdqu } },
12445 else => {},
12446 },
13016 .{ .v_, .movdqu } },
1244713017 else => {},
1244813018 },
1244913019 else => {},
1245013020 },
12451 }
13021 else => {},
13022 },
1245213023 },
1245313024 }
1245413025 return self.fail("TODO moveStrategy for {}", .{ty.fmt(mod)});
......@@ -12514,32 +13085,18 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError
1251413085 };
1251513086 defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock);
1251613087
12517 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none);
12518 for (dst_regs, classes, 0..) |dst_reg, class, dst_reg_i| {
12519 const class_ty = switch (class) {
12520 .integer => Type.usize,
12521 .sse, .float, .float_combine => Type.f64,
12522 else => unreachable,
12523 };
12524 const off: i32 = @intCast(dst_reg_i * 8);
12525 switch (src_mcv) {
12526 .register_pair => |src_regs| try self.genSetReg(
12527 dst_reg,
12528 class_ty,
12529 .{ .register = src_regs[dst_reg_i] },
12530 ),
12531 .memory, .indirect, .load_frame => try self.genSetReg(
12532 dst_reg,
12533 class_ty,
12534 src_mcv.address().offset(off).deref(),
12535 ),
12536 .load_symbol, .load_direct, .load_got, .load_tlv => try self.genSetReg(
12537 dst_reg,
12538 class_ty,
12539 .{ .indirect = .{ .reg = src_info.?.addr_reg, .off = off } },
12540 ),
13088 var part_disp: i32 = 0;
13089 for (dst_regs, try self.splitType(ty), 0..) |dst_reg, dst_ty, part_i| {
13090 try self.genSetReg(dst_reg, dst_ty, switch (src_mcv) {
13091 .register_pair => |src_regs| .{ .register = src_regs[part_i] },
13092 .memory, .indirect, .load_frame => src_mcv.address().offset(part_disp).deref(),
13093 .load_symbol, .load_direct, .load_got, .load_tlv => .{ .indirect = .{
13094 .reg = src_info.?.addr_reg,
13095 .off = part_disp,
13096 } },
1254113097 else => unreachable,
12542 }
13098 });
13099 part_disp += @intCast(dst_ty.abiSize(mod));
1254313100 }
1254413101 },
1254513102 .indirect => |reg_off| try self.genSetMem(.{ .reg = reg_off.reg }, reg_off.off, ty, src_mcv),
......@@ -12584,6 +13141,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1258413141 if (imm == 0) {
1258513142 // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit
1258613143 // register is the fastest way to zero a register.
13144 try self.spillEflagsIfOccupied();
1258713145 try self.asmRegisterRegister(.{ ._, .xor }, dst_reg.to32(), dst_reg.to32());
1258813146 } else if (abi_size > 4 and math.cast(u32, imm) != null) {
1258913147 // 32-bit moves zero-extend to 64-bit.
......@@ -12933,44 +13491,65 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
1293313491 .eflags => |cc| try self.asmSetccMemory(cc, .{ .base = base, .mod = .{
1293413492 .rm = .{ .size = .byte, .disp = disp },
1293513493 } }),
12936 .register => |src_reg| try (try self.moveStrategy(ty, src_reg.class(), switch (base) {
12937 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12938 .reg => |reg| switch (reg) {
12939 .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12940 else => false,
12941 },
12942 .frame => |frame_index| self.getFrameAddrAlignment(
12943 .{ .index = frame_index, .off = disp },
12944 ).compare(.gte, ty.abiAlignment(mod)),
12945 .reloc => false,
12946 })).write(
12947 self,
12948 .{ .base = base, .mod = .{ .rm = .{
12949 .size = self.memSize(ty),
12950 .disp = disp,
12951 } } },
12952 registerAlias(src_reg, abi_size),
12953 ),
12954 .register_pair => |src_regs| for (src_regs, 0..) |src_reg, src_reg_i| {
12955 const part_size: u16 = @min(abi_size - src_reg_i * 8, 8);
12956 try (try self.moveStrategy(
12957 try mod.intType(.unsigned, part_size * 8),
12958 src_reg.class(),
12959 switch (base) {
12960 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12961 .reg => |reg| switch (reg) {
12962 .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12963 else => false,
12964 },
12965 .frame => |frame_index| self.getFrameAddrAlignment(
12966 .{ .index = frame_index, .off = disp },
12967 ).compare(.gte, ty.abiAlignment(mod)),
12968 .reloc => false,
13494 .register => |src_reg| {
13495 const mem_size = switch (base) {
13496 .frame => |base_fi| mem_size: {
13497 assert(disp >= 0);
13498 const frame_abi_size = self.frame_allocs.items(.abi_size)[@intFromEnum(base_fi)];
13499 const frame_spill_pad = self.frame_allocs.items(.spill_pad)[@intFromEnum(base_fi)];
13500 assert(frame_abi_size - frame_spill_pad - disp >= abi_size);
13501 break :mem_size if (frame_abi_size - frame_spill_pad - disp == abi_size)
13502 frame_abi_size
13503 else
13504 abi_size;
1296913505 },
12970 )).write(self, .{ .base = base, .mod = .{ .rm = .{
12971 .size = Memory.Size.fromSize(part_size),
12972 .disp = disp + @as(i32, @intCast(src_reg_i * 8)),
12973 } } }, registerAlias(src_reg, part_size));
13506 else => abi_size,
13507 };
13508 const src_alias = registerAlias(src_reg, abi_size);
13509 const src_size: u32 = @intCast(switch (src_alias.class()) {
13510 .general_purpose, .segment, .x87 => @divExact(src_alias.bitSize(), 8),
13511 .mmx, .sse => abi_size,
13512 });
13513 if (src_size > mem_size) {
13514 const frame_index = try self.allocFrameIndex(FrameAlloc.init(.{
13515 .size = src_size,
13516 .alignment = Alignment.fromNonzeroByteUnits(src_size),
13517 }));
13518 const frame_mcv: MCValue = .{ .load_frame = .{ .index = frame_index } };
13519 try (try self.moveStrategy(ty, src_alias.class(), true)).write(
13520 self,
13521 .{ .base = .{ .frame = frame_index }, .mod = .{ .rm = .{
13522 .size = Memory.Size.fromSize(src_size),
13523 } } },
13524 src_alias,
13525 );
13526 try self.genSetMem(base, disp, ty, frame_mcv);
13527 try self.freeValue(frame_mcv);
13528 } else try (try self.moveStrategy(ty, src_alias.class(), switch (base) {
13529 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
13530 .reg => |reg| switch (reg) {
13531 .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
13532 else => false,
13533 },
13534 .frame => |frame_index| self.getFrameAddrAlignment(
13535 .{ .index = frame_index, .off = disp },
13536 ).compare(.gte, ty.abiAlignment(mod)),
13537 .reloc => false,
13538 })).write(
13539 self,
13540 .{ .base = base, .mod = .{ .rm = .{
13541 .size = self.memSize(ty),
13542 .disp = disp,
13543 } } },
13544 src_alias,
13545 );
13546 },
13547 .register_pair => |src_regs| {
13548 var part_disp: i32 = disp;
13549 for (try self.splitType(ty), src_regs) |src_ty, src_reg| {
13550 try self.genSetMem(base, part_disp, src_ty, .{ .register = src_reg });
13551 part_disp += @intCast(src_ty.abiSize(mod));
13552 }
1297413553 },
1297513554 .register_overflow => |ro| switch (ty.zigTypeTag(mod)) {
1297613555 .Struct => {
......@@ -13226,50 +13805,43 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
1322613805 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
1322713806 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
1322813807
13229 const dst_mcv = if (dst_rc.supersetOf(src_rc) and
13230 self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
13231 src_mcv
13232 else dst: {
13808 const dst_mcv = if (dst_rc.supersetOf(src_rc) and dst_ty.abiSize(mod) <= src_ty.abiSize(mod) and
13809 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
1323313810 const dst_mcv = try self.allocRegOrMem(inst, true);
13234 try self.genCopy(
13235 if (!dst_mcv.isMemory() or src_mcv.isMemory()) dst_ty else src_ty,
13236 dst_mcv,
13237 src_mcv,
13238 );
13811 try self.genCopy(switch (math.order(dst_ty.abiSize(mod), src_ty.abiSize(mod))) {
13812 .lt => dst_ty,
13813 .eq => if (!dst_mcv.isMemory() or src_mcv.isMemory()) dst_ty else src_ty,
13814 .gt => src_ty,
13815 }, dst_mcv, src_mcv);
1323913816 break :dst dst_mcv;
1324013817 };
1324113818
1324213819 if (dst_ty.isRuntimeFloat()) break :result dst_mcv;
1324313820
13244 const dst_signedness =
13245 if (dst_ty.isAbiInt(mod)) dst_ty.intInfo(mod).signedness else .unsigned;
13246 if (!src_ty.isRuntimeFloat() or src_ty.floatBits(self.target.*) != 80) {
13247 const src_signedness =
13248 if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned;
13249 if (dst_signedness == src_signedness) break :result dst_mcv;
13250 }
13821 if (dst_ty.isAbiInt(mod) and src_ty.isAbiInt(mod) and
13822 dst_ty.intInfo(mod).signedness == src_ty.intInfo(mod).signedness) break :result dst_mcv;
1325113823
13252 const abi_size: u16 = @intCast(dst_ty.abiSize(mod));
13253 const bit_size: u16 = @intCast(dst_ty.bitSize(mod));
13254 if (abi_size * 8 <= bit_size) break :result dst_mcv;
13824 const abi_size = dst_ty.abiSize(mod);
13825 const bit_size = dst_ty.bitSize(mod);
13826 if (abi_size * 8 <= bit_size or dst_ty.isVector(mod)) break :result dst_mcv;
1325513827
13256 const dst_limbs_len = math.divCeil(i32, bit_size, 64) catch unreachable;
13257 const high_reg = if (dst_mcv.isRegister())
13258 dst_mcv.getReg().?
13828 const dst_limbs_len = math.divCeil(i32, @intCast(bit_size), 64) catch unreachable;
13829 const high_mcv: MCValue = switch (dst_mcv) {
13830 .register => |dst_reg| .{ .register = dst_reg },
13831 .register_pair => |dst_regs| .{ .register = dst_regs[1] },
13832 else => dst_mcv.address().offset((dst_limbs_len - 1) * 8).deref(),
13833 };
13834 const high_reg = if (high_mcv.isRegister())
13835 high_mcv.getReg().?
1325913836 else
13260 try self.copyToTmpRegister(
13261 Type.usize,
13262 dst_mcv.address().offset((dst_limbs_len - 1) * 8).deref(),
13263 );
13837 try self.copyToTmpRegister(Type.usize, high_mcv);
1326413838 const high_lock = self.register_manager.lockReg(high_reg);
1326513839 defer if (high_lock) |lock| self.register_manager.unlockReg(lock);
1326613840
13267 const high_ty = try mod.intType(dst_signedness, bit_size % 64);
13268
13269 try self.truncateRegister(high_ty, high_reg);
13270 if (!dst_mcv.isRegister()) try self.genCopy(
13271 Type.usize,
13272 dst_mcv.address().offset((dst_limbs_len - 1) * 8).deref(),
13841 try self.truncateRegister(dst_ty, high_reg);
13842 if (!high_mcv.isRegister()) try self.genCopy(
13843 if (abi_size <= 8) dst_ty else Type.usize,
13844 high_mcv,
1327313845 .{ .register = high_reg },
1327413846 );
1327513847 break :result dst_mcv;
......@@ -13287,7 +13859,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
1328713859 const array_ty = ptr_ty.childType(mod);
1328813860 const array_len = array_ty.arrayLen(mod);
1328913861
13290 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(slice_ty, mod));
13862 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(slice_ty, mod));
1329113863 try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr);
1329213864 try self.genSetMem(
1329313865 .{ .frame = frame_index },
......@@ -13497,7 +14069,7 @@ fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {
1349714069 const ptr_mcv = try self.resolveInst(extra.ptr);
1349814070 const mem_size = Memory.Size.fromSize(val_abi_size);
1349914071 const ptr_mem: Memory = switch (ptr_mcv) {
13500 .immediate, .register, .register_offset, .lea_frame => ptr_mcv.deref().mem(mem_size),
14072 .immediate, .register, .register_offset, .lea_frame => try ptr_mcv.deref().mem(self, mem_size),
1350114073 else => .{
1350214074 .base = .{ .reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv) },
1350314075 .mod = .{ .rm = .{ .size = mem_size } },
......@@ -13563,7 +14135,7 @@ fn atomicOp(
1356314135 const val_abi_size: u32 = @intCast(val_ty.abiSize(mod));
1356414136 const mem_size = Memory.Size.fromSize(val_abi_size);
1356514137 const ptr_mem: Memory = switch (ptr_mcv) {
13566 .immediate, .register, .register_offset, .lea_frame => ptr_mcv.deref().mem(mem_size),
14138 .immediate, .register, .register_offset, .lea_frame => try ptr_mcv.deref().mem(self, mem_size),
1356714139 else => .{
1356814140 .base = .{ .reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv) },
1356914141 .mod = .{ .rm = .{ .size = mem_size } },
......@@ -13671,27 +14243,41 @@ fn atomicOp(
1367114243 },
1367214244 };
1367314245
13674 try self.genBinOpMir(.{ ._, .cmp }, val_ty, tmp_mcv, val_mcv);
1367514246 const cmov_abi_size = @max(val_abi_size, 2);
1367614247 switch (val_mcv) {
13677 .register => |val_reg| try self.asmCmovccRegisterRegister(
13678 cc,
13679 registerAlias(tmp_reg, cmov_abi_size),
13680 registerAlias(val_reg, cmov_abi_size),
13681 ),
13682 .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory(
13683 cc,
13684 registerAlias(tmp_reg, cmov_abi_size),
13685 val_mcv.mem(Memory.Size.fromSize(cmov_abi_size)),
13686 ),
13687 else => {
13688 const val_reg = try self.copyToTmpRegister(val_ty, val_mcv);
14248 .register => |val_reg| {
14249 try self.genBinOpMir(.{ ._, .cmp }, val_ty, tmp_mcv, val_mcv);
1368914250 try self.asmCmovccRegisterRegister(
1369014251 cc,
1369114252 registerAlias(tmp_reg, cmov_abi_size),
1369214253 registerAlias(val_reg, cmov_abi_size),
1369314254 );
1369414255 },
14256 .memory, .indirect, .load_frame => {
14257 try self.genBinOpMir(.{ ._, .cmp }, val_ty, tmp_mcv, val_mcv);
14258 try self.asmCmovccRegisterMemory(
14259 cc,
14260 registerAlias(tmp_reg, cmov_abi_size),
14261 try val_mcv.mem(self, Memory.Size.fromSize(cmov_abi_size)),
14262 );
14263 },
14264 else => {
14265 const mat_reg = try self.copyToTmpRegister(val_ty, val_mcv);
14266 const mat_lock = self.register_manager.lockRegAssumeUnused(mat_reg);
14267 defer self.register_manager.unlockReg(mat_lock);
14268
14269 try self.genBinOpMir(
14270 .{ ._, .cmp },
14271 val_ty,
14272 tmp_mcv,
14273 .{ .register = mat_reg },
14274 );
14275 try self.asmCmovccRegisterRegister(
14276 cc,
14277 registerAlias(tmp_reg, cmov_abi_size),
14278 registerAlias(mat_reg, cmov_abi_size),
14279 );
14280 },
1369514281 }
1369614282 },
1369714283 };
......@@ -13728,8 +14314,8 @@ fn atomicOp(
1372814314 .reg = try self.copyToTmpRegister(Type.usize, val_mcv.address()),
1372914315 } },
1373014316 };
13731 const val_lo_mem = val_mem_mcv.mem(.qword);
13732 const val_hi_mem = val_mem_mcv.address().offset(8).deref().mem(.qword);
14317 const val_lo_mem = try val_mem_mcv.mem(self, .qword);
14318 const val_hi_mem = try val_mem_mcv.address().offset(8).deref().mem(self, .qword);
1373314319 if (rmw_op != std.builtin.AtomicRmwOp.Xchg) {
1373414320 try self.asmRegisterRegister(.{ ._, .mov }, .rbx, .rax);
1373514321 try self.asmRegisterRegister(.{ ._, .mov }, .rcx, .rdx);
......@@ -13859,6 +14445,10 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1385914445
1386014446 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1386114447
14448 try self.spillRegisters(&.{ .rdi, .rsi, .rcx });
14449 const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx });
14450 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
14451
1386214452 const dst_ptr = try self.resolveInst(bin_op.lhs);
1386314453 const dst_ptr_ty = self.typeOf(bin_op.lhs);
1386414454 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
......@@ -13976,6 +14566,10 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
1397614566 const mod = self.bin_file.options.module.?;
1397714567 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1397814568
14569 try self.spillRegisters(&.{ .rdi, .rsi, .rcx });
14570 const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx });
14571 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
14572
1397914573 const dst_ptr = try self.resolveInst(bin_op.lhs);
1398014574 const dst_ptr_ty = self.typeOf(bin_op.lhs);
1398114575 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
......@@ -14000,7 +14594,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
1400014594 try self.asmRegisterMemoryImmediate(
1400114595 .{ .i_, .mul },
1400214596 len_reg,
14003 dst_ptr.address().offset(8).deref().mem(.qword),
14597 try dst_ptr.address().offset(8).deref().mem(self, .qword),
1400414598 Immediate.s(@intCast(dst_ptr_ty.childType(mod).abiSize(mod))),
1400514599 );
1400614600 break :len .{ .register = len_reg };
......@@ -14046,7 +14640,7 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
1404614640 }
1404714641
1404814642 try self.spillEflagsIfOccupied();
14049 try self.spillRegisters(abi.getCallerPreservedRegs(resolved_cc));
14643 try self.spillCallerPreservedRegs(resolved_cc);
1405014644
1405114645 const param_regs = abi.getCAbiIntParamRegs(resolved_cc);
1405214646
......@@ -14171,28 +14765,162 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1417114765 const mod = self.bin_file.options.module.?;
1417214766 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1417314767 const vector_ty = self.typeOfIndex(inst);
14768 const vector_len = vector_ty.vectorLen(mod);
1417414769 const dst_rc = self.regClassForType(vector_ty);
14175 const scalar_ty = vector_ty.scalarType(mod);
14770 const scalar_ty = self.typeOf(ty_op.operand);
1417614771
14177 const src_mcv = try self.resolveInst(ty_op.operand);
1417814772 const result: MCValue = result: {
1417914773 switch (scalar_ty.zigTypeTag(mod)) {
1418014774 else => {},
14775 .Bool => {
14776 const regs =
14777 try self.register_manager.allocRegs(2, .{ inst, null }, abi.RegisterClass.gp);
14778 const reg_locks = self.register_manager.lockRegsAssumeUnused(2, regs);
14779 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
14780
14781 try self.genSetReg(regs[1], vector_ty, .{ .immediate = 0 });
14782 try self.genSetReg(
14783 regs[1],
14784 vector_ty,
14785 .{ .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - vector_len) },
14786 );
14787 const src_mcv = try self.resolveInst(ty_op.operand);
14788 const abi_size = @max(math.divCeil(u32, vector_len, 8) catch unreachable, 4);
14789 try self.asmCmovccRegisterRegister(
14790 switch (src_mcv) {
14791 .eflags => |cc| cc,
14792 .register => |src_reg| cc: {
14793 try self.asmRegisterImmediate(
14794 .{ ._, .@"test" },
14795 src_reg.to8(),
14796 Immediate.u(1),
14797 );
14798 break :cc .nz;
14799 },
14800 else => cc: {
14801 try self.asmMemoryImmediate(
14802 .{ ._, .@"test" },
14803 try src_mcv.mem(self, .byte),
14804 Immediate.u(1),
14805 );
14806 break :cc .nz;
14807 },
14808 },
14809 registerAlias(regs[0], abi_size),
14810 registerAlias(regs[1], abi_size),
14811 );
14812 break :result .{ .register = regs[0] };
14813 },
14814 .Int => if (self.hasFeature(.avx2)) avx2: {
14815 const mir_tag = @as(?Mir.Inst.FixedTag, switch (scalar_ty.intInfo(mod).bits) {
14816 else => null,
14817 1...8 => switch (vector_len) {
14818 else => null,
14819 1...32 => .{ .vp_b, .broadcast },
14820 },
14821 9...16 => switch (vector_len) {
14822 else => null,
14823 1...16 => .{ .vp_w, .broadcast },
14824 },
14825 17...32 => switch (vector_len) {
14826 else => null,
14827 1...8 => .{ .vp_d, .broadcast },
14828 },
14829 33...64 => switch (vector_len) {
14830 else => null,
14831 1...4 => .{ .vp_q, .broadcast },
14832 },
14833 65...128 => switch (vector_len) {
14834 else => null,
14835 1...2 => .{ .vp_i128, .broadcast },
14836 },
14837 }) orelse break :avx2;
14838
14839 const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.sse);
14840 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
14841 defer self.register_manager.unlockReg(dst_lock);
14842
14843 const src_mcv = try self.resolveInst(ty_op.operand);
14844 if (src_mcv.isMemory()) try self.asmRegisterMemory(
14845 mir_tag,
14846 registerAlias(dst_reg, @intCast(vector_ty.abiSize(mod))),
14847 try src_mcv.mem(self, self.memSize(scalar_ty)),
14848 ) else {
14849 if (mir_tag[0] == .vp_i128) break :avx2;
14850 try self.genSetReg(dst_reg, scalar_ty, src_mcv);
14851 try self.asmRegisterRegister(
14852 mir_tag,
14853 registerAlias(dst_reg, @intCast(vector_ty.abiSize(mod))),
14854 registerAlias(dst_reg, @intCast(scalar_ty.abiSize(mod))),
14855 );
14856 }
14857 break :result .{ .register = dst_reg };
14858 } else {
14859 const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.sse);
14860 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
14861 defer self.register_manager.unlockReg(dst_lock);
14862
14863 try self.genSetReg(dst_reg, scalar_ty, .{ .air_ref = ty_op.operand });
14864 if (vector_len == 1) break :result .{ .register = dst_reg };
14865
14866 const dst_alias = registerAlias(dst_reg, @intCast(vector_ty.abiSize(mod)));
14867 const scalar_bits = scalar_ty.intInfo(mod).bits;
14868 if (switch (scalar_bits) {
14869 1...8 => true,
14870 9...128 => false,
14871 else => unreachable,
14872 }) if (self.hasFeature(.avx)) try self.asmRegisterRegisterRegister(
14873 .{ .vp_, .unpcklbw },
14874 dst_alias,
14875 dst_alias,
14876 dst_alias,
14877 ) else try self.asmRegisterRegister(
14878 .{ .p_, .unpcklbw },
14879 dst_alias,
14880 dst_alias,
14881 );
14882 if (switch (scalar_bits) {
14883 1...8 => vector_len > 2,
14884 9...16 => true,
14885 17...128 => false,
14886 else => unreachable,
14887 }) try self.asmRegisterRegisterImmediate(
14888 .{ if (self.hasFeature(.avx)) .vp_w else .p_w, .shufl },
14889 dst_alias,
14890 dst_alias,
14891 Immediate.u(0),
14892 );
14893 if (switch (scalar_bits) {
14894 1...8 => vector_len > 4,
14895 9...16 => vector_len > 2,
14896 17...64 => true,
14897 65...128 => false,
14898 else => unreachable,
14899 }) try self.asmRegisterRegisterImmediate(
14900 .{ if (self.hasFeature(.avx)) .vp_d else .p_d, .shuf },
14901 dst_alias,
14902 dst_alias,
14903 Immediate.u(if (scalar_bits <= 64) 0b00_00_00_00 else 0b01_00_01_00),
14904 );
14905 break :result .{ .register = dst_reg };
14906 },
1418114907 .Float => switch (scalar_ty.floatBits(self.target.*)) {
14182 32 => switch (vector_ty.vectorLen(mod)) {
14908 32 => switch (vector_len) {
1418314909 1 => {
14910 const src_mcv = try self.resolveInst(ty_op.operand);
1418414911 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
1418514912 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
1418614913 try self.genSetReg(dst_reg, scalar_ty, src_mcv);
1418714914 break :result .{ .register = dst_reg };
1418814915 },
1418914916 2...4 => {
14917 const src_mcv = try self.resolveInst(ty_op.operand);
1419014918 if (self.hasFeature(.avx)) {
1419114919 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
1419214920 if (src_mcv.isMemory()) try self.asmRegisterMemory(
1419314921 .{ .v_ss, .broadcast },
1419414922 dst_reg.to128(),
14195 src_mcv.mem(.dword),
14923 try src_mcv.mem(self, .dword),
1419614924 ) else {
1419714925 const src_reg = if (src_mcv.isRegister())
1419814926 src_mcv.getReg().?
......@@ -14224,11 +14952,12 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1422414952 }
1422514953 },
1422614954 5...8 => if (self.hasFeature(.avx)) {
14955 const src_mcv = try self.resolveInst(ty_op.operand);
1422714956 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
1422814957 if (src_mcv.isMemory()) try self.asmRegisterMemory(
1422914958 .{ .v_ss, .broadcast },
1423014959 dst_reg.to256(),
14231 src_mcv.mem(.dword),
14960 try src_mcv.mem(self, .dword),
1423214961 ) else {
1423314962 const src_reg = if (src_mcv.isRegister())
1423414963 src_mcv.getReg().?
......@@ -14259,20 +14988,22 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1425914988 },
1426014989 else => {},
1426114990 },
14262 64 => switch (vector_ty.vectorLen(mod)) {
14991 64 => switch (vector_len) {
1426314992 1 => {
14993 const src_mcv = try self.resolveInst(ty_op.operand);
1426414994 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
1426514995 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
1426614996 try self.genSetReg(dst_reg, scalar_ty, src_mcv);
1426714997 break :result .{ .register = dst_reg };
1426814998 },
1426914999 2 => {
15000 const src_mcv = try self.resolveInst(ty_op.operand);
1427015001 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
1427115002 if (self.hasFeature(.sse3)) {
1427215003 if (src_mcv.isMemory()) try self.asmRegisterMemory(
1427315004 if (self.hasFeature(.avx)) .{ .v_, .movddup } else .{ ._, .movddup },
1427415005 dst_reg.to128(),
14275 src_mcv.mem(.qword),
15006 try src_mcv.mem(self, .qword),
1427615007 ) else try self.asmRegisterRegister(
1427715008 if (self.hasFeature(.avx)) .{ .v_, .movddup } else .{ ._, .movddup },
1427815009 dst_reg.to128(),
......@@ -14292,11 +15023,12 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1429215023 );
1429315024 },
1429415025 3...4 => if (self.hasFeature(.avx)) {
15026 const src_mcv = try self.resolveInst(ty_op.operand);
1429515027 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
1429615028 if (src_mcv.isMemory()) try self.asmRegisterMemory(
1429715029 .{ .v_sd, .broadcast },
1429815030 dst_reg.to256(),
14299 src_mcv.mem(.qword),
15031 try src_mcv.mem(self, .qword),
1430015032 ) else {
1430115033 const src_reg = if (src_mcv.isRegister())
1430215034 src_mcv.getReg().?
......@@ -14325,19 +15057,21 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1432515057 },
1432615058 else => {},
1432715059 },
14328 128 => switch (vector_ty.vectorLen(mod)) {
15060 128 => switch (vector_len) {
1432915061 1 => {
15062 const src_mcv = try self.resolveInst(ty_op.operand);
1433015063 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
1433115064 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
1433215065 try self.genSetReg(dst_reg, scalar_ty, src_mcv);
1433315066 break :result .{ .register = dst_reg };
1433415067 },
1433515068 2 => if (self.hasFeature(.avx)) {
15069 const src_mcv = try self.resolveInst(ty_op.operand);
1433615070 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
1433715071 if (src_mcv.isMemory()) try self.asmRegisterMemory(
1433815072 .{ .v_f128, .broadcast },
1433915073 dst_reg.to256(),
14340 src_mcv.mem(.xword),
15074 try src_mcv.mem(self, .xword),
1434115075 ) else {
1434215076 const src_reg = if (src_mcv.isRegister())
1434315077 src_mcv.getReg().?
......@@ -14389,7 +15123,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
1438915123 try self.spillEflagsIfOccupied();
1439015124
1439115125 const operand_mcv = try self.resolveInst(reduce.operand);
14392 const mask_len = (std.math.cast(u6, operand_ty.vectorLen(mod)) orelse
15126 const mask_len = (math.cast(u6, operand_ty.vectorLen(mod)) orelse
1439315127 return self.fail("TODO implement airReduce for {}", .{operand_ty.fmt(mod)}));
1439415128 const mask = (@as(u64, 1) << mask_len) - 1;
1439515129 const abi_size: u32 = @intCast(operand_ty.abiSize(mod));
......@@ -14397,7 +15131,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
1439715131 .Or => {
1439815132 if (operand_mcv.isMemory()) try self.asmMemoryImmediate(
1439915133 .{ ._, .@"test" },
14400 operand_mcv.mem(Memory.Size.fromSize(abi_size)),
15134 try operand_mcv.mem(self, Memory.Size.fromSize(abi_size)),
1440115135 Immediate.u(mask),
1440215136 ) else {
1440315137 const operand_reg = registerAlias(if (operand_mcv.isRegister())
......@@ -14445,8 +15179,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1444515179 const result: MCValue = result: {
1444615180 switch (result_ty.zigTypeTag(mod)) {
1444715181 .Struct => {
14448 const frame_index =
14449 try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod));
15182 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, mod));
1445015183 if (result_ty.containerLayout(mod) == .Packed) {
1445115184 const struct_type = mod.typeToStruct(result_ty).?;
1445215185 try self.genInlineMemset(
......@@ -14542,8 +15275,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1454215275 break :result .{ .load_frame = .{ .index = frame_index } };
1454315276 },
1454415277 .Array => {
14545 const frame_index =
14546 try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod));
15278 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, mod));
1454715279 const elem_ty = result_ty.childType(mod);
1454815280 const elem_size: u32 = @intCast(elem_ty.abiSize(mod));
1454915281
......@@ -14789,7 +15521,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
1478915521 mir_tag,
1479015522 mop1_reg,
1479115523 mop2_reg,
14792 mops[2].mem(Memory.Size.fromSize(abi_size)),
15524 try mops[2].mem(self, Memory.Size.fromSize(abi_size)),
1479315525 );
1479415526 break :result mops[0];
1479515527 };
......@@ -14807,7 +15539,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void {
1480715539 )) {
1480815540 .SysV => result: {
1480915541 const info = self.va_info.sysv;
14810 const dst_fi = try self.allocFrameIndex(FrameAlloc.initType(va_list_ty, mod));
15542 const dst_fi = try self.allocFrameIndex(FrameAlloc.initSpill(va_list_ty, mod));
1481115543 var field_off: u31 = 0;
1481215544 // gp_offset: c_uint,
1481315545 try self.genSetMem(
......@@ -15015,7 +15747,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
1501515747 .{ .v_ss, .cvtsd2 },
1501615748 dst_reg,
1501715749 dst_reg,
15018 promote_mcv.mem(.qword),
15750 try promote_mcv.mem(self, .qword),
1501915751 ) else try self.asmRegisterRegisterRegister(
1502015752 .{ .v_ss, .cvtsd2 },
1502115753 dst_reg,
......@@ -15027,7 +15759,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
1502715759 ) else if (promote_mcv.isMemory()) try self.asmRegisterMemory(
1502815760 .{ ._ss, .cvtsd2 },
1502915761 dst_reg,
15030 promote_mcv.mem(.qword),
15762 try promote_mcv.mem(self, .qword),
1503115763 ) else try self.asmRegisterRegister(
1503215764 .{ ._ss, .cvtsd2 },
1503315765 dst_reg,
......@@ -15473,6 +16205,33 @@ fn memSize(self: *Self, ty: Type) Memory.Size {
1547316205 };
1547416206}
1547516207
16208fn splitType(self: *Self, ty: Type) ![2]Type {
16209 const mod = self.bin_file.options.module.?;
16210 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none);
16211 var parts: [2]Type = undefined;
16212 if (classes.len == 2) for (&parts, classes, 0..) |*part, class, part_i| {
16213 part.* = switch (class) {
16214 .integer => switch (part_i) {
16215 0 => Type.u64,
16216 1 => part: {
16217 const elem_size = ty.abiAlignment(mod).minStrict(.@"8").toByteUnitsOptional().?;
16218 const elem_ty = try mod.intType(.unsigned, @intCast(elem_size * 8));
16219 break :part switch (@divExact(ty.abiSize(mod) - 8, elem_size)) {
16220 1 => elem_ty,
16221 else => |len| try mod.arrayType(.{ .len = len, .child = elem_ty.toIntern() }),
16222 };
16223 },
16224 else => unreachable,
16225 },
16226 .float => Type.f32,
16227 .float_combine => try mod.vectorType(.{ .len = 2, .child = .f32_type }),
16228 .sse => Type.f64,
16229 else => break,
16230 };
16231 } else if (parts[0].abiSize(mod) + parts[1].abiSize(mod) == ty.abiSize(mod)) return parts;
16232 return self.fail("TODO implement splitType for {}", .{ty.fmt(mod)});
16233}
16234
1547616235/// Truncates the value in the register in place.
1547716236/// Clobbers any remaining bits.
1547816237fn truncateRegister(self: *Self, ty: Type, reg: Register) !void {
src/arch/x86_64/Encoding.zig+13-17
......@@ -62,8 +62,7 @@ pub fn findByMnemonic(
6262 .rex, .rex_short => if (!rex_required) continue,
6363 else => {},
6464 }
65 for (input_ops, data.ops) |input_op, data_op|
66 if (!input_op.isSubset(data_op)) continue :next;
65 for (input_ops, data.ops) |input_op, data_op| if (!input_op.isSubset(data_op)) continue :next;
6766
6867 const enc = Encoding{ .mnemonic = mnemonic, .data = data };
6968 if (shortest_enc) |previous_shortest_enc| {
......@@ -410,6 +409,8 @@ pub const Mnemonic = enum {
410409 vfmadd132ps, vfmadd213ps, vfmadd231ps,
411410 vfmadd132sd, vfmadd213sd, vfmadd231sd,
412411 vfmadd132ss, vfmadd213ss, vfmadd231ss,
412 // AVX2
413 vpbroadcastb, vpbroadcastd, vpbroadcasti128, vpbroadcastq, vpbroadcastw,
413414 // zig fmt: on
414415};
415416
......@@ -444,7 +445,7 @@ pub const Op = enum {
444445 moffs,
445446 sreg,
446447 st, mm, mm_m64,
447 xmm0, xmm, xmm_m32, xmm_m64, xmm_m128,
448 xmm0, xmm, xmm_m8, xmm_m16, xmm_m32, xmm_m64, xmm_m128,
448449 ymm, ymm_m256,
449450 // zig fmt: on
450451
......@@ -534,7 +535,7 @@ pub const Op = enum {
534535 .eax, .r32, .rm32, .r32_m16 => unreachable,
535536 .rax, .r64, .rm64, .r64_m16 => unreachable,
536537 .st, .mm, .mm_m64 => unreachable,
537 .xmm0, .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => unreachable,
538 .xmm0, .xmm, .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128 => unreachable,
538539 .ymm, .ymm_m256 => unreachable,
539540 .m8, .m16, .m32, .m64, .m80, .m128, .m256 => unreachable,
540541 .unity => 1,
......@@ -556,7 +557,7 @@ pub const Op = enum {
556557 .eax, .r32, .rm32, .r32_m8, .r32_m16 => 32,
557558 .rax, .r64, .rm64, .r64_m16, .mm, .mm_m64 => 64,
558559 .st => 80,
559 .xmm0, .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => 128,
560 .xmm0, .xmm, .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128 => 128,
560561 .ymm, .ymm_m256 => 256,
561562 };
562563 }
......@@ -568,8 +569,8 @@ pub const Op = enum {
568569 .rel8, .rel16, .rel32 => unreachable,
569570 .al, .cl, .r8, .ax, .r16, .eax, .r32, .rax, .r64 => unreachable,
570571 .st, .mm, .xmm0, .xmm, .ymm => unreachable,
571 .m8, .rm8, .r32_m8 => 8,
572 .m16, .rm16, .r32_m16, .r64_m16 => 16,
572 .m8, .rm8, .r32_m8, .xmm_m8 => 8,
573 .m16, .rm16, .r32_m16, .r64_m16, .xmm_m16 => 16,
573574 .m32, .rm32, .xmm_m32 => 32,
574575 .m64, .rm64, .mm_m64, .xmm_m64 => 64,
575576 .m80 => 80,
......@@ -600,7 +601,7 @@ pub const Op = enum {
600601 .rm8, .rm16, .rm32, .rm64,
601602 .r32_m8, .r32_m16, .r64_m16,
602603 .st, .mm, .mm_m64,
603 .xmm0, .xmm, .xmm_m32, .xmm_m64, .xmm_m128,
604 .xmm0, .xmm, .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128,
604605 .ymm, .ymm_m256,
605606 => true,
606607 else => false,
......@@ -629,7 +630,7 @@ pub const Op = enum {
629630 .m8, .m16, .m32, .m64, .m80, .m128, .m256,
630631 .m,
631632 .mm_m64,
632 .xmm_m32, .xmm_m64, .xmm_m128,
633 .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128,
633634 .ymm_m256,
634635 => true,
635636 else => false,
......@@ -654,7 +655,7 @@ pub const Op = enum {
654655 .sreg => .segment,
655656 .st => .x87,
656657 .mm, .mm_m64 => .mmx,
657 .xmm0, .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => .sse,
658 .xmm0, .xmm, .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128 => .sse,
658659 .ymm, .ymm_m256 => .sse,
659660 };
660661 }
......@@ -826,18 +827,13 @@ const mnemonic_to_encodings_map = init: {
826827 for (&data_storage, entries, 0..) |*data, entry, data_index| {
827828 data.* = .{
828829 .op_en = entry[1],
829 .ops = undefined,
830 .ops = (entry[2] ++ .{.none} ** (data.ops.len - entry[2].len)).*,
830831 .opc_len = entry[3].len,
831 .opc = undefined,
832 .opc = (entry[3] ++ .{undefined} ** (data.opc.len - entry[3].len)).*,
832833 .modrm_ext = entry[4],
833834 .mode = entry[5],
834835 .feature = entry[6],
835836 };
836 // TODO: use `@memcpy` for these. When I did that, I got a false positive
837 // compile error for this copy happening at compile time.
838 std.mem.copyForwards(Op, &data.ops, entry[2]);
839 std.mem.copyForwards(u8, &data.opc, entry[3]);
840
841837 while (mnemonic_int < @intFromEnum(entry[0])) : (mnemonic_int += 1) {
842838 mnemonic_map[mnemonic_int] = data_storage[mnemonic_start..data_index];
843839 mnemonic_start = data_index;
src/arch/x86_64/Mir.zig+2
......@@ -255,6 +255,8 @@ pub const Inst = struct {
255255 vp_q,
256256 /// VEX-Encoded Packed ___ Double Quadword
257257 vp_dq,
258 /// VEX-Encoded Packed ___ Integer Data
259 vp_i128,
258260 /// VEX-Encoded ___ Scalar Single-Precision Values
259261 v_ss,
260262 /// VEX-Encoded ___ Packed Single-Precision Values
src/arch/x86_64/bits.zig+2-2
......@@ -222,7 +222,7 @@ pub const Register = enum(u7) {
222222 @intFromEnum(Register.eax) ... @intFromEnum(Register.r15d) => @intFromEnum(Register.eax),
223223 @intFromEnum(Register.ax) ... @intFromEnum(Register.r15w) => @intFromEnum(Register.ax),
224224 @intFromEnum(Register.al) ... @intFromEnum(Register.r15b) => @intFromEnum(Register.al),
225 @intFromEnum(Register.ah) ... @intFromEnum(Register.bh) => @intFromEnum(Register.ah) - 4,
225 @intFromEnum(Register.ah) ... @intFromEnum(Register.bh) => @intFromEnum(Register.ah),
226226
227227 @intFromEnum(Register.ymm0) ... @intFromEnum(Register.ymm15) => @intFromEnum(Register.ymm0) - 16,
228228 @intFromEnum(Register.xmm0) ... @intFromEnum(Register.xmm15) => @intFromEnum(Register.xmm0) - 16,
......@@ -237,7 +237,7 @@ pub const Register = enum(u7) {
237237 return @intCast(@intFromEnum(reg) - base);
238238 }
239239
240 pub fn bitSize(reg: Register) u64 {
240 pub fn bitSize(reg: Register) u10 {
241241 return switch (@intFromEnum(reg)) {
242242 // zig fmt: off
243243 @intFromEnum(Register.rax) ... @intFromEnum(Register.r15) => 64,
src/arch/x86_64/encodings.zig+10
......@@ -1742,6 +1742,16 @@ pub const table = [_]Entry{
17421742
17431743 .{ .vpandn, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0xdf }, 0, .vex_256_wig, .avx2 },
17441744
1745 .{ .vpbroadcastb, .rm, &.{ .xmm, .xmm_m8 }, &.{ 0x66, 0x0f, 0x38, 0x78 }, 0, .vex_128_w0, .avx2 },
1746 .{ .vpbroadcastb, .rm, &.{ .ymm, .xmm_m8 }, &.{ 0x66, 0x0f, 0x38, 0x78 }, 0, .vex_256_w0, .avx2 },
1747 .{ .vpbroadcastw, .rm, &.{ .xmm, .xmm_m16 }, &.{ 0x66, 0x0f, 0x38, 0x79 }, 0, .vex_128_w0, .avx2 },
1748 .{ .vpbroadcastw, .rm, &.{ .ymm, .xmm_m16 }, &.{ 0x66, 0x0f, 0x38, 0x79 }, 0, .vex_256_w0, .avx2 },
1749 .{ .vpbroadcastd, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0x66, 0x0f, 0x38, 0x58 }, 0, .vex_128_w0, .avx2 },
1750 .{ .vpbroadcastd, .rm, &.{ .ymm, .xmm_m32 }, &.{ 0x66, 0x0f, 0x38, 0x58 }, 0, .vex_256_w0, .avx2 },
1751 .{ .vpbroadcastq, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0x66, 0x0f, 0x38, 0x59 }, 0, .vex_128_w0, .avx2 },
1752 .{ .vpbroadcastq, .rm, &.{ .ymm, .xmm_m64 }, &.{ 0x66, 0x0f, 0x38, 0x59 }, 0, .vex_256_w0, .avx2 },
1753 .{ .vpbroadcasti128, .rm, &.{ .ymm, .m128 }, &.{ 0x66, 0x0f, 0x38, 0x5a }, 0, .vex_256_w0, .avx2 },
1754
17451755 .{ .vpcmpeqb, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x74 }, 0, .vex_256_wig, .avx2 },
17461756 .{ .vpcmpeqw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x75 }, 0, .vex_256_wig, .avx2 },
17471757 .{ .vpcmpeqd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x76 }, 0, .vex_256_wig, .avx2 },
src/codegen.zig+4-1
......@@ -376,7 +376,10 @@ pub fn generateSymbol(
376376 .val = switch (aggregate.storage) {
377377 .bytes => unreachable,
378378 .elems => |elems| elems[@as(usize, @intCast(index))],
379 .repeated_elem => |elem| elem,
379 .repeated_elem => |elem| if (index < array_type.len)
380 elem
381 else
382 array_type.sentinel,
380383 }.toValue(),
381384 }, code, debug_output, reloc_info)) {
382385 .ok => {},
src/link/Coff.zig+1
......@@ -388,6 +388,7 @@ fn populateMissingMetadata(self: *Coff) !void {
388388 self.rdata_section_index = try self.allocateSection(".rdata", file_size, .{
389389 .CNT_INITIALIZED_DATA = 1,
390390 .MEM_READ = 1,
391 .MEM_WRITE = 1,
391392 });
392393 }
393394
src/main.zig+1
......@@ -6492,6 +6492,7 @@ pub fn cmdDumpZir(
64926492 .mod = undefined,
64936493 .root_decl = .none,
64946494 };
6495 defer file.zir.deinit(gpa);
64956496
64966497 {
64976498 const instruction_bytes = file.zir.instructions.len *
src/print_zir.zig+6-9
......@@ -2456,20 +2456,15 @@ const Writer = struct {
24562456 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].save_err_ret_index;
24572457
24582458 try self.writeInstRef(stream, inst_data.operand);
2459
24592460 try stream.writeAll(")");
24602461 }
24612462
24622463 fn writeRestoreErrRetIndex(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
24632464 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].restore_err_ret_index;
24642465
2465 if (inst_data.block != .none) {
2466 try self.writeInstRef(stream, inst_data.block);
2467 }
2468
2469 if (inst_data.operand != .none) {
2470 if (inst_data.block != .none) try stream.writeAll(", ");
2471 try self.writeInstRef(stream, inst_data.operand);
2472 }
2466 try self.writeInstRef(stream, inst_data.block);
2467 try self.writeInstRef(stream, inst_data.operand);
24732468
24742469 try stream.writeAll(")");
24752470 }
......@@ -2615,7 +2610,9 @@ const Writer = struct {
26152610 }
26162611
26172612 fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void {
2618 if (ref.toIndex()) |i| {
2613 if (ref == .none) {
2614 return stream.writeAll(".none");
2615 } else if (ref.toIndex()) |i| {
26192616 return self.writeInstIndex(stream, i);
26202617 } else {
26212618 const val: InternPool.Index = @enumFromInt(@intFromEnum(ref));
src/register_manager.zig+102-60
......@@ -55,6 +55,7 @@ pub fn RegisterManager(
5555 const Self = @This();
5656
5757 pub const TrackedRegisters = [tracked_registers.len]Air.Inst.Index;
58 pub const TrackedIndex = std.math.IntFittingRange(0, tracked_registers.len - 1);
5859 pub const RegisterBitSet = StaticBitSet(tracked_registers.len);
5960
6061 fn getFunction(self: *Self) *Function {
......@@ -66,45 +67,64 @@ pub fn RegisterManager(
6667 return !register_class.isSet(index);
6768 }
6869
70 fn markRegIndexAllocated(self: *Self, tracked_index: TrackedIndex) void {
71 self.allocated_registers.set(tracked_index);
72 }
6973 fn markRegAllocated(self: *Self, reg: Register) void {
70 const index = indexOfRegIntoTracked(reg) orelse return;
71 self.allocated_registers.set(index);
74 self.markRegIndexAllocated(indexOfRegIntoTracked(reg) orelse return);
7275 }
7376
77 fn markRegIndexUsed(self: *Self, tracked_index: TrackedIndex) void {
78 self.free_registers.unset(tracked_index);
79 }
7480 fn markRegUsed(self: *Self, reg: Register) void {
75 const index = indexOfRegIntoTracked(reg) orelse return;
76 self.free_registers.unset(index);
81 self.markRegIndexUsed(indexOfRegIntoTracked(reg) orelse return);
7782 }
7883
84 fn markRegIndexFree(self: *Self, tracked_index: TrackedIndex) void {
85 self.free_registers.set(tracked_index);
86 }
7987 fn markRegFree(self: *Self, reg: Register) void {
80 const index = indexOfRegIntoTracked(reg) orelse return;
81 self.free_registers.set(index);
88 self.markRegIndexFree(indexOfRegIntoTracked(reg) orelse return);
8289 }
8390
8491 pub fn indexOfReg(
85 comptime registers: []const Register,
92 comptime set: []const Register,
8693 reg: Register,
87 ) ?std.math.IntFittingRange(0, registers.len - 1) {
88 inline for (tracked_registers, 0..) |cpreg, i| {
89 if (reg.id() == cpreg.id()) return i;
94 ) ?std.math.IntFittingRange(0, set.len - 1) {
95 const Id = @TypeOf(reg.id());
96 comptime var min_id: Id = std.math.maxInt(Id);
97 comptime var max_id: Id = std.math.minInt(Id);
98 inline for (set) |elem| {
99 const elem_id = comptime elem.id();
100 min_id = @min(elem_id, min_id);
101 max_id = @max(elem_id, max_id);
90102 }
91 return null;
103
104 const OptionalIndex = std.math.IntFittingRange(0, set.len);
105 comptime var map = [1]OptionalIndex{set.len} ** (max_id + 1 - min_id);
106 inline for (set, 0..) |elem, elem_index| map[comptime elem.id() - min_id] = elem_index;
107
108 const id_index = reg.id() -% min_id;
109 if (id_index >= map.len) return null;
110 const set_index = map[id_index];
111 return if (set_index < set.len) @intCast(set_index) else null;
92112 }
93113
94 pub fn indexOfRegIntoTracked(
95 reg: Register,
96 ) ?std.math.IntFittingRange(0, tracked_registers.len) {
114 pub fn indexOfRegIntoTracked(reg: Register) ?TrackedIndex {
97115 return indexOfReg(tracked_registers, reg);
98116 }
99117
100 pub fn regAtTrackedIndex(index: std.math.IntFittingRange(0, tracked_registers.len)) Register {
101 return tracked_registers[index];
118 pub fn regAtTrackedIndex(tracked_index: TrackedIndex) Register {
119 return tracked_registers[tracked_index];
102120 }
103121
104122 /// Returns true when this register is not tracked
123 pub fn isRegIndexFree(self: Self, tracked_index: TrackedIndex) bool {
124 return self.free_registers.isSet(tracked_index);
125 }
105126 pub fn isRegFree(self: Self, reg: Register) bool {
106 const index = indexOfRegIntoTracked(reg) orelse return true;
107 return self.free_registers.isSet(index);
127 return self.isRegIndexFree(indexOfRegIntoTracked(reg) orelse return true);
108128 }
109129
110130 /// Returns whether this register was allocated in the course
......@@ -119,14 +139,14 @@ pub fn RegisterManager(
119139 /// Returns whether this register is locked
120140 ///
121141 /// Returns false when this register is not tracked
142 fn isRegIndexLocked(self: Self, tracked_index: TrackedIndex) bool {
143 return self.locked_registers.isSet(tracked_index);
144 }
122145 pub fn isRegLocked(self: Self, reg: Register) bool {
123 const index = indexOfRegIntoTracked(reg) orelse return false;
124 return self.locked_registers.isSet(index);
146 return self.isRegIndexLocked(indexOfRegIntoTracked(reg) orelse return false);
125147 }
126148
127 pub const RegisterLock = struct {
128 register: Register,
129 };
149 pub const RegisterLock = struct { tracked_index: TrackedIndex };
130150
131151 /// Prevents the register from being allocated until they are
132152 /// unlocked again.
......@@ -134,25 +154,29 @@ pub fn RegisterManager(
134154 /// locked, or `null` otherwise.
135155 /// Only the owner of the `RegisterLock` can unlock the
136156 /// register later.
137 pub fn lockReg(self: *Self, reg: Register) ?RegisterLock {
138 log.debug("locking {}", .{reg});
139 if (self.isRegLocked(reg)) {
157 pub fn lockRegIndex(self: *Self, tracked_index: TrackedIndex) ?RegisterLock {
158 log.debug("locking {}", .{regAtTrackedIndex(tracked_index)});
159 if (self.isRegIndexLocked(tracked_index)) {
140160 log.debug(" register already locked", .{});
141161 return null;
142162 }
143 const index = indexOfRegIntoTracked(reg) orelse return null;
144 self.locked_registers.set(index);
145 return RegisterLock{ .register = reg };
163 self.locked_registers.set(tracked_index);
164 return RegisterLock{ .tracked_index = tracked_index };
165 }
166 pub fn lockReg(self: *Self, reg: Register) ?RegisterLock {
167 return self.lockRegIndex(indexOfRegIntoTracked(reg) orelse return null);
146168 }
147169
148170 /// Like `lockReg` but asserts the register was unused always
149171 /// returning a valid lock.
172 pub fn lockRegIndexAssumeUnused(self: *Self, tracked_index: TrackedIndex) RegisterLock {
173 log.debug("locking asserting free {}", .{regAtTrackedIndex(tracked_index)});
174 assert(!self.isRegIndexLocked(tracked_index));
175 self.locked_registers.set(tracked_index);
176 return RegisterLock{ .tracked_index = tracked_index };
177 }
150178 pub fn lockRegAssumeUnused(self: *Self, reg: Register) RegisterLock {
151 log.debug("locking asserting free {}", .{reg});
152 assert(!self.isRegLocked(reg));
153 const index = indexOfRegIntoTracked(reg) orelse unreachable;
154 self.locked_registers.set(index);
155 return RegisterLock{ .register = reg };
179 return self.lockRegIndexAssumeUnused(indexOfRegIntoTracked(reg) orelse unreachable);
156180 }
157181
158182 /// Like `lockReg` but locks multiple registers.
......@@ -181,9 +205,8 @@ pub fn RegisterManager(
181205 /// Requires `RegisterLock` to unlock a register.
182206 /// Call `lockReg` to obtain the lock first.
183207 pub fn unlockReg(self: *Self, lock: RegisterLock) void {
184 log.debug("unlocking {}", .{lock.register});
185 const index = indexOfRegIntoTracked(lock.register) orelse return;
186 self.locked_registers.unset(index);
208 log.debug("unlocking {}", .{regAtTrackedIndex(lock.tracked_index)});
209 self.locked_registers.unset(lock.tracked_index);
187210 }
188211
189212 /// Returns true when at least one register is locked
......@@ -319,44 +342,63 @@ pub fn RegisterManager(
319342 /// Spills the register if it is currently allocated. If a
320343 /// corresponding instruction is passed, will also track this
321344 /// register.
322 pub fn getReg(self: *Self, reg: Register, inst: ?Air.Inst.Index) AllocateRegistersError!void {
323 const index = indexOfRegIntoTracked(reg) orelse return;
324 log.debug("getReg {} for inst {?}", .{ reg, inst });
325
326 if (!self.isRegFree(reg)) {
327 self.markRegAllocated(reg);
345 fn getRegIndex(
346 self: *Self,
347 tracked_index: TrackedIndex,
348 inst: ?Air.Inst.Index,
349 ) AllocateRegistersError!void {
350 log.debug("getReg {} for inst {?}", .{ regAtTrackedIndex(tracked_index), inst });
351 if (!self.isRegIndexFree(tracked_index)) {
352 self.markRegIndexAllocated(tracked_index);
328353
329354 // Move the instruction that was previously there to a
330355 // stack allocation.
331 const spilled_inst = self.registers[index];
332 if (inst) |tracked_inst| self.registers[index] = tracked_inst;
333 try self.getFunction().spillInstruction(reg, spilled_inst);
334 if (inst == null) self.freeReg(reg);
335 } else self.getRegAssumeFree(reg, inst);
356 const spilled_inst = self.registers[tracked_index];
357 if (inst) |tracked_inst| self.registers[tracked_index] = tracked_inst;
358 try self.getFunction().spillInstruction(regAtTrackedIndex(tracked_index), spilled_inst);
359 if (inst == null) self.freeRegIndex(tracked_index);
360 } else self.getRegIndexAssumeFree(tracked_index, inst);
361 }
362 pub fn getReg(self: *Self, reg: Register, inst: ?Air.Inst.Index) AllocateRegistersError!void {
363 return self.getRegIndex(indexOfRegIntoTracked(reg) orelse return, inst);
364 }
365 pub fn getKnownReg(
366 self: *Self,
367 comptime reg: Register,
368 inst: ?Air.Inst.Index,
369 ) AllocateRegistersError!void {
370 return self.getRegIndex((comptime indexOfRegIntoTracked(reg)) orelse return, inst);
336371 }
337372
338373 /// Allocates the specified register with the specified
339374 /// instruction. Asserts that the register is free and no
340375 /// spilling is necessary.
341 pub fn getRegAssumeFree(self: *Self, reg: Register, inst: ?Air.Inst.Index) void {
342 const index = indexOfRegIntoTracked(reg) orelse return;
343 log.debug("getRegAssumeFree {} for inst {?}", .{ reg, inst });
344 self.markRegAllocated(reg);
376 fn getRegIndexAssumeFree(
377 self: *Self,
378 tracked_index: TrackedIndex,
379 inst: ?Air.Inst.Index,
380 ) void {
381 log.debug("getRegAssumeFree {} for inst {?}", .{ regAtTrackedIndex(tracked_index), inst });
382 self.markRegIndexAllocated(tracked_index);
345383
346 assert(self.isRegFree(reg));
384 assert(self.isRegIndexFree(tracked_index));
347385 if (inst) |tracked_inst| {
348 self.registers[index] = tracked_inst;
349 self.markRegUsed(reg);
386 self.registers[tracked_index] = tracked_inst;
387 self.markRegIndexUsed(tracked_index);
350388 }
351389 }
390 pub fn getRegAssumeFree(self: *Self, reg: Register, inst: ?Air.Inst.Index) void {
391 self.getRegIndexAssumeFree(indexOfRegIntoTracked(reg) orelse return, inst);
392 }
352393
353394 /// Marks the specified register as free
395 fn freeRegIndex(self: *Self, tracked_index: TrackedIndex) void {
396 log.debug("freeing register {}", .{regAtTrackedIndex(tracked_index)});
397 self.registers[tracked_index] = undefined;
398 self.markRegIndexFree(tracked_index);
399 }
354400 pub fn freeReg(self: *Self, reg: Register) void {
355 const index = indexOfRegIntoTracked(reg) orelse return;
356 log.debug("freeing register {}", .{reg});
357
358 self.registers[index] = undefined;
359 self.markRegFree(reg);
401 self.freeRegIndex(indexOfRegIntoTracked(reg) orelse return);
360402 }
361403 };
362404}
test/behavior/vector.zig-1
......@@ -1260,7 +1260,6 @@ test "zero multiplicand" {
12601260
12611261test "@intCast to u0" {
12621262 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1263 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12641263 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12651264 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12661265 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO