| ... | ... | @@ -104,7 +104,7 @@ const Owner = union(enum) { |
| 104 | 104 | nav_index: InternPool.Nav.Index, |
| 105 | 105 | lazy_sym: link.File.LazySymbol, |
| 106 | 106 | |
| 107 | | fn getSymbolIndex(owner: Owner, ctx: *Self) !u32 { |
| 107 | fn getSymbolIndex(owner: Owner, ctx: *CodeGen) !u32 { |
| 108 | 108 | const pt = ctx.pt; |
| 109 | 109 | switch (owner) { |
| 110 | 110 | .nav_index => |nav_index| if (ctx.bin_file.cast(.elf)) |elf_file| { |
| ... | ... | @@ -394,7 +394,7 @@ pub const MCValue = union(enum) { |
| 394 | 394 | }; |
| 395 | 395 | } |
| 396 | 396 | |
| 397 | | fn mem(mcv: MCValue, function: *Self, size: Memory.Size) !Memory { |
| 397 | fn mem(mcv: MCValue, function: *CodeGen, mod_rm: Memory.Mod.Rm) !Memory { |
| 398 | 398 | return switch (mcv) { |
| 399 | 399 | .none, |
| 400 | 400 | .unreach, |
| ... | ... | @@ -420,22 +420,28 @@ pub const MCValue = union(enum) { |
| 420 | 420 | .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| .{ |
| 421 | 421 | .base = .{ .reg = .ds }, |
| 422 | 422 | .mod = .{ .rm = .{ |
| 423 | | .size = size, |
| 424 | | .disp = small_addr, |
| 423 | .size = mod_rm.size, |
| 424 | .index = mod_rm.index, |
| 425 | .scale = mod_rm.scale, |
| 426 | .disp = small_addr + mod_rm.disp, |
| 425 | 427 | } }, |
| 426 | 428 | } else .{ .base = .{ .reg = .ds }, .mod = .{ .off = addr } }, |
| 427 | 429 | .indirect => |reg_off| .{ |
| 428 | 430 | .base = .{ .reg = reg_off.reg }, |
| 429 | 431 | .mod = .{ .rm = .{ |
| 430 | | .size = size, |
| 431 | | .disp = reg_off.off, |
| 432 | .size = mod_rm.size, |
| 433 | .index = mod_rm.index, |
| 434 | .scale = mod_rm.scale, |
| 435 | .disp = reg_off.off + mod_rm.disp, |
| 432 | 436 | } }, |
| 433 | 437 | }, |
| 434 | 438 | .load_frame => |frame_addr| .{ |
| 435 | 439 | .base = .{ .frame = frame_addr.index }, |
| 436 | 440 | .mod = .{ .rm = .{ |
| 437 | | .size = size, |
| 438 | | .disp = frame_addr.off, |
| 441 | .size = mod_rm.size, |
| 442 | .index = mod_rm.index, |
| 443 | .scale = mod_rm.scale, |
| 444 | .disp = frame_addr.off + mod_rm.disp, |
| 439 | 445 | } }, |
| 440 | 446 | }, |
| 441 | 447 | .load_symbol => |sym_off| { |
| ... | ... | @@ -443,12 +449,14 @@ pub const MCValue = union(enum) { |
| 443 | 449 | return .{ |
| 444 | 450 | .base = .{ .reloc = sym_off.sym_index }, |
| 445 | 451 | .mod = .{ .rm = .{ |
| 446 | | .size = size, |
| 447 | | .disp = sym_off.off, |
| 452 | .size = mod_rm.size, |
| 453 | .index = mod_rm.index, |
| 454 | .scale = mod_rm.scale, |
| 455 | .disp = sym_off.off + mod_rm.disp, |
| 448 | 456 | } }, |
| 449 | 457 | }; |
| 450 | 458 | }, |
| 451 | | .air_ref => |ref| (try function.resolveInst(ref)).mem(function, size), |
| 459 | .air_ref => |ref| (try function.resolveInst(ref)).mem(function, mod_rm), |
| 452 | 460 | }; |
| 453 | 461 | } |
| 454 | 462 | |
| ... | ... | @@ -537,7 +545,7 @@ const InstTracking = struct { |
| 537 | 545 | return self.short.getCondition(); |
| 538 | 546 | } |
| 539 | 547 | |
| 540 | | fn spill(self: *InstTracking, function: *Self, inst: Air.Inst.Index) !void { |
| 548 | fn spill(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) !void { |
| 541 | 549 | if (std.meta.eql(self.long, self.short)) return; // Already spilled |
| 542 | 550 | // Allocate or reuse frame index |
| 543 | 551 | switch (self.long) { |
| ... | ... | @@ -586,7 +594,7 @@ const InstTracking = struct { |
| 586 | 594 | }; |
| 587 | 595 | } |
| 588 | 596 | |
| 589 | | fn trackSpill(self: *InstTracking, function: *Self, inst: Air.Inst.Index) !void { |
| 597 | fn trackSpill(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) !void { |
| 590 | 598 | try function.freeValue(self.short); |
| 591 | 599 | self.reuseFrame(); |
| 592 | 600 | tracking_log.debug("{} => {} (spilled)", .{ inst, self.* }); |
| ... | ... | @@ -633,7 +641,7 @@ const InstTracking = struct { |
| 633 | 641 | |
| 634 | 642 | fn materialize( |
| 635 | 643 | self: *InstTracking, |
| 636 | | function: *Self, |
| 644 | function: *CodeGen, |
| 637 | 645 | inst: Air.Inst.Index, |
| 638 | 646 | target: InstTracking, |
| 639 | 647 | ) !void { |
| ... | ... | @@ -643,7 +651,7 @@ const InstTracking = struct { |
| 643 | 651 | |
| 644 | 652 | fn materializeUnsafe( |
| 645 | 653 | self: InstTracking, |
| 646 | | function: *Self, |
| 654 | function: *CodeGen, |
| 647 | 655 | inst: Air.Inst.Index, |
| 648 | 656 | target: InstTracking, |
| 649 | 657 | ) !void { |
| ... | ... | @@ -675,7 +683,7 @@ const InstTracking = struct { |
| 675 | 683 | } |
| 676 | 684 | } |
| 677 | 685 | |
| 678 | | fn die(self: *InstTracking, function: *Self, inst: Air.Inst.Index) !void { |
| 686 | fn die(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) !void { |
| 679 | 687 | if (self.short == .dead) return; |
| 680 | 688 | try function.freeValue(self.short); |
| 681 | 689 | self.short = .{ .dead = function.scope_generation }; |
| ... | ... | @@ -684,7 +692,7 @@ const InstTracking = struct { |
| 684 | 692 | |
| 685 | 693 | fn reuse( |
| 686 | 694 | self: *InstTracking, |
| 687 | | function: *Self, |
| 695 | function: *CodeGen, |
| 688 | 696 | new_inst: ?Air.Inst.Index, |
| 689 | 697 | old_inst: Air.Inst.Index, |
| 690 | 698 | ) void { |
| ... | ... | @@ -692,7 +700,7 @@ const InstTracking = struct { |
| 692 | 700 | tracking_log.debug("{?} => {} (reuse {})", .{ new_inst, self.*, old_inst }); |
| 693 | 701 | } |
| 694 | 702 | |
| 695 | | fn liveOut(self: *InstTracking, function: *Self, inst: Air.Inst.Index) void { |
| 703 | fn liveOut(self: *InstTracking, function: *CodeGen, inst: Air.Inst.Index) void { |
| 696 | 704 | for (self.getRegs()) |reg| { |
| 697 | 705 | if (function.register_manager.isRegFree(reg)) { |
| 698 | 706 | tracking_log.debug("{} => {} (live-out)", .{ inst, self.* }); |
| ... | ... | @@ -789,7 +797,7 @@ const BlockData = struct { |
| 789 | 797 | } |
| 790 | 798 | }; |
| 791 | 799 | |
| 792 | | const Self = @This(); |
| 800 | const CodeGen = @This(); |
| 793 | 801 | |
| 794 | 802 | pub fn generate( |
| 795 | 803 | bin_file: *link.File, |
| ... | ... | @@ -809,7 +817,7 @@ pub fn generate( |
| 809 | 817 | const fn_type: Type = .fromInterned(func.ty); |
| 810 | 818 | const mod = zcu.navFileScope(func.owner_nav).mod; |
| 811 | 819 | |
| 812 | | var function: Self = .{ |
| 820 | var function: CodeGen = .{ |
| 813 | 821 | .gpa = gpa, |
| 814 | 822 | .pt = pt, |
| 815 | 823 | .air = air, |
| ... | ... | @@ -962,7 +970,7 @@ pub fn generateLazy( |
| 962 | 970 | const gpa = comp.gpa; |
| 963 | 971 | // This function is for generating global code, so we use the root module. |
| 964 | 972 | const mod = comp.root_mod; |
| 965 | | var function: Self = .{ |
| 973 | var function: CodeGen = .{ |
| 966 | 974 | .gpa = gpa, |
| 967 | 975 | .pt = pt, |
| 968 | 976 | .air = undefined, |
| ... | ... | @@ -1050,7 +1058,7 @@ fn fmtNav(nav_index: InternPool.Nav.Index, ip: *const InternPool) std.fmt.Format |
| 1050 | 1058 | } |
| 1051 | 1059 | |
| 1052 | 1060 | const FormatAirData = struct { |
| 1053 | | self: *Self, |
| 1061 | self: *CodeGen, |
| 1054 | 1062 | inst: Air.Inst.Index, |
| 1055 | 1063 | }; |
| 1056 | 1064 | fn formatAir( |
| ... | ... | @@ -1066,12 +1074,12 @@ fn formatAir( |
| 1066 | 1074 | data.self.liveness, |
| 1067 | 1075 | ); |
| 1068 | 1076 | } |
| 1069 | | fn fmtAir(self: *Self, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) { |
| 1077 | fn fmtAir(self: *CodeGen, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) { |
| 1070 | 1078 | return .{ .data = .{ .self = self, .inst = inst } }; |
| 1071 | 1079 | } |
| 1072 | 1080 | |
| 1073 | 1081 | const FormatWipMirData = struct { |
| 1074 | | self: *Self, |
| 1082 | self: *CodeGen, |
| 1075 | 1083 | inst: Mir.Inst.Index, |
| 1076 | 1084 | }; |
| 1077 | 1085 | fn formatWipMir( |
| ... | ... | @@ -1192,12 +1200,12 @@ fn formatWipMir( |
| 1192 | 1200 | } |
| 1193 | 1201 | } |
| 1194 | 1202 | } |
| 1195 | | fn fmtWipMir(self: *Self, inst: Mir.Inst.Index) std.fmt.Formatter(formatWipMir) { |
| 1203 | fn fmtWipMir(self: *CodeGen, inst: Mir.Inst.Index) std.fmt.Formatter(formatWipMir) { |
| 1196 | 1204 | return .{ .data = .{ .self = self, .inst = inst } }; |
| 1197 | 1205 | } |
| 1198 | 1206 | |
| 1199 | 1207 | const FormatTrackingData = struct { |
| 1200 | | self: *Self, |
| 1208 | self: *CodeGen, |
| 1201 | 1209 | }; |
| 1202 | 1210 | fn formatTracking( |
| 1203 | 1211 | data: FormatTrackingData, |
| ... | ... | @@ -1208,26 +1216,26 @@ fn formatTracking( |
| 1208 | 1216 | var it = data.self.inst_tracking.iterator(); |
| 1209 | 1217 | while (it.next()) |entry| try writer.print("\n{} = {}", .{ entry.key_ptr.*, entry.value_ptr.* }); |
| 1210 | 1218 | } |
| 1211 | | fn fmtTracking(self: *Self) std.fmt.Formatter(formatTracking) { |
| 1219 | fn fmtTracking(self: *CodeGen) std.fmt.Formatter(formatTracking) { |
| 1212 | 1220 | return .{ .data = .{ .self = self } }; |
| 1213 | 1221 | } |
| 1214 | 1222 | |
| 1215 | | fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index { |
| 1223 | fn addInst(self: *CodeGen, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index { |
| 1216 | 1224 | const gpa = self.gpa; |
| 1217 | 1225 | try self.mir_instructions.ensureUnusedCapacity(gpa, 1); |
| 1218 | 1226 | const result_index: Mir.Inst.Index = @intCast(self.mir_instructions.len); |
| 1219 | 1227 | self.mir_instructions.appendAssumeCapacity(inst); |
| 1220 | | wip_mir_log.debug("{}", .{self.fmtWipMir(result_index)}); |
| 1228 | if (inst.ops != .pseudo_dead_none) wip_mir_log.debug("{}", .{self.fmtWipMir(result_index)}); |
| 1221 | 1229 | return result_index; |
| 1222 | 1230 | } |
| 1223 | 1231 | |
| 1224 | | fn addExtra(self: *Self, extra: anytype) Allocator.Error!u32 { |
| 1232 | fn addExtra(self: *CodeGen, extra: anytype) Allocator.Error!u32 { |
| 1225 | 1233 | const fields = std.meta.fields(@TypeOf(extra)); |
| 1226 | 1234 | try self.mir_extra.ensureUnusedCapacity(self.gpa, fields.len); |
| 1227 | 1235 | return self.addExtraAssumeCapacity(extra); |
| 1228 | 1236 | } |
| 1229 | 1237 | |
| 1230 | | fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { |
| 1238 | fn addExtraAssumeCapacity(self: *CodeGen, extra: anytype) u32 { |
| 1231 | 1239 | const fields = std.meta.fields(@TypeOf(extra)); |
| 1232 | 1240 | const result: u32 = @intCast(self.mir_extra.items.len); |
| 1233 | 1241 | inline for (fields) |field| { |
| ... | ... | @@ -1241,7 +1249,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { |
| 1241 | 1249 | return result; |
| 1242 | 1250 | } |
| 1243 | 1251 | |
| 1244 | | fn asmOps(self: *Self, tag: Mir.Inst.FixedTag, ops: [4]Operand) !void { |
| 1252 | fn asmOps(self: *CodeGen, tag: Mir.Inst.FixedTag, ops: [4]Operand) !void { |
| 1245 | 1253 | return switch (ops[0]) { |
| 1246 | 1254 | .none => self.asmOpOnly(tag), |
| 1247 | 1255 | .reg => |reg0| switch (ops[1]) { |
| ... | ... | @@ -1316,7 +1324,7 @@ fn asmOps(self: *Self, tag: Mir.Inst.FixedTag, ops: [4]Operand) !void { |
| 1316 | 1324 | } |
| 1317 | 1325 | |
| 1318 | 1326 | /// A `cc` of `.z_and_np` clobbers `reg2`! |
| 1319 | | fn asmCmovccRegisterRegister(self: *Self, cc: Condition, reg1: Register, reg2: Register) !void { |
| 1327 | fn asmCmovccRegisterRegister(self: *CodeGen, cc: Condition, reg1: Register, reg2: Register) !void { |
| 1320 | 1328 | _ = try self.addInst(.{ |
| 1321 | 1329 | .tag = switch (cc) { |
| 1322 | 1330 | else => .cmov, |
| ... | ... | @@ -1339,7 +1347,7 @@ fn asmCmovccRegisterRegister(self: *Self, cc: Condition, reg1: Register, reg2: R |
| 1339 | 1347 | } |
| 1340 | 1348 | |
| 1341 | 1349 | /// A `cc` of `.z_and_np` is not supported by this encoding! |
| 1342 | | fn asmCmovccRegisterMemory(self: *Self, cc: Condition, reg: Register, m: Memory) !void { |
| 1350 | fn asmCmovccRegisterMemory(self: *CodeGen, cc: Condition, reg: Register, m: Memory) !void { |
| 1343 | 1351 | _ = try self.addInst(.{ |
| 1344 | 1352 | .tag = switch (cc) { |
| 1345 | 1353 | else => .cmov, |
| ... | ... | @@ -1363,7 +1371,7 @@ fn asmCmovccRegisterMemory(self: *Self, cc: Condition, reg: Register, m: Memory) |
| 1363 | 1371 | }); |
| 1364 | 1372 | } |
| 1365 | 1373 | |
| 1366 | | fn asmSetccRegister(self: *Self, cc: Condition, reg: Register) !void { |
| 1374 | fn asmSetccRegister(self: *CodeGen, cc: Condition, reg: Register) !void { |
| 1367 | 1375 | _ = try self.addInst(.{ |
| 1368 | 1376 | .tag = switch (cc) { |
| 1369 | 1377 | else => .set, |
| ... | ... | @@ -1387,7 +1395,7 @@ fn asmSetccRegister(self: *Self, cc: Condition, reg: Register) !void { |
| 1387 | 1395 | }); |
| 1388 | 1396 | } |
| 1389 | 1397 | |
| 1390 | | fn asmSetccMemory(self: *Self, cc: Condition, m: Memory) !void { |
| 1398 | fn asmSetccMemory(self: *CodeGen, cc: Condition, m: Memory) !void { |
| 1391 | 1399 | const payload = try self.addExtra(Mir.Memory.encode(m)); |
| 1392 | 1400 | _ = try self.addInst(.{ |
| 1393 | 1401 | .tag = switch (cc) { |
| ... | ... | @@ -1412,7 +1420,7 @@ fn asmSetccMemory(self: *Self, cc: Condition, m: Memory) !void { |
| 1412 | 1420 | }); |
| 1413 | 1421 | } |
| 1414 | 1422 | |
| 1415 | | fn asmJmpReloc(self: *Self, target: Mir.Inst.Index) !Mir.Inst.Index { |
| 1423 | fn asmJmpReloc(self: *CodeGen, target: Mir.Inst.Index) !Mir.Inst.Index { |
| 1416 | 1424 | return self.addInst(.{ |
| 1417 | 1425 | .tag = .jmp, |
| 1418 | 1426 | .ops = .inst, |
| ... | ... | @@ -1422,7 +1430,7 @@ fn asmJmpReloc(self: *Self, target: Mir.Inst.Index) !Mir.Inst.Index { |
| 1422 | 1430 | }); |
| 1423 | 1431 | } |
| 1424 | 1432 | |
| 1425 | | fn asmJccReloc(self: *Self, cc: Condition, target: Mir.Inst.Index) !Mir.Inst.Index { |
| 1433 | fn asmJccReloc(self: *CodeGen, cc: Condition, target: Mir.Inst.Index) !Mir.Inst.Index { |
| 1426 | 1434 | return self.addInst(.{ |
| 1427 | 1435 | .tag = switch (cc) { |
| 1428 | 1436 | else => .j, |
| ... | ... | @@ -1443,7 +1451,7 @@ fn asmJccReloc(self: *Self, cc: Condition, target: Mir.Inst.Index) !Mir.Inst.Ind |
| 1443 | 1451 | }); |
| 1444 | 1452 | } |
| 1445 | 1453 | |
| 1446 | | fn asmReloc(self: *Self, tag: Mir.Inst.FixedTag, target: Mir.Inst.Index) !void { |
| 1454 | fn asmReloc(self: *CodeGen, tag: Mir.Inst.FixedTag, target: Mir.Inst.Index) !void { |
| 1447 | 1455 | _ = try self.addInst(.{ |
| 1448 | 1456 | .tag = tag[1], |
| 1449 | 1457 | .ops = .inst, |
| ... | ... | @@ -1454,7 +1462,7 @@ fn asmReloc(self: *Self, tag: Mir.Inst.FixedTag, target: Mir.Inst.Index) !void { |
| 1454 | 1462 | }); |
| 1455 | 1463 | } |
| 1456 | 1464 | |
| 1457 | | fn asmPlaceholder(self: *Self) !Mir.Inst.Index { |
| 1465 | fn asmPlaceholder(self: *CodeGen) !Mir.Inst.Index { |
| 1458 | 1466 | return self.addInst(.{ |
| 1459 | 1467 | .tag = .pseudo, |
| 1460 | 1468 | .ops = .pseudo_dead_none, |
| ... | ... | @@ -1464,7 +1472,7 @@ fn asmPlaceholder(self: *Self) !Mir.Inst.Index { |
| 1464 | 1472 | |
| 1465 | 1473 | const MirTagAir = enum { dbg_local }; |
| 1466 | 1474 | |
| 1467 | | fn asmAir(self: *Self, tag: MirTagAir, inst: Air.Inst.Index) !void { |
| 1475 | fn asmAir(self: *CodeGen, tag: MirTagAir, inst: Air.Inst.Index) !void { |
| 1468 | 1476 | _ = try self.addInst(.{ |
| 1469 | 1477 | .tag = .pseudo, |
| 1470 | 1478 | .ops = switch (tag) { |
| ... | ... | @@ -1474,7 +1482,7 @@ fn asmAir(self: *Self, tag: MirTagAir, inst: Air.Inst.Index) !void { |
| 1474 | 1482 | }); |
| 1475 | 1483 | } |
| 1476 | 1484 | |
| 1477 | | fn asmAirImmediate(self: *Self, tag: MirTagAir, inst: Air.Inst.Index, imm: Immediate) !void { |
| 1485 | fn asmAirImmediate(self: *CodeGen, tag: MirTagAir, inst: Air.Inst.Index, imm: Immediate) !void { |
| 1478 | 1486 | switch (imm) { |
| 1479 | 1487 | .signed => |s| _ = try self.addInst(.{ |
| 1480 | 1488 | .tag = .pseudo, |
| ... | ... | @@ -1528,7 +1536,7 @@ fn asmAirImmediate(self: *Self, tag: MirTagAir, inst: Air.Inst.Index, imm: Immed |
| 1528 | 1536 | } |
| 1529 | 1537 | |
| 1530 | 1538 | fn asmAirRegisterImmediate( |
| 1531 | | self: *Self, |
| 1539 | self: *CodeGen, |
| 1532 | 1540 | tag: MirTagAir, |
| 1533 | 1541 | inst: Air.Inst.Index, |
| 1534 | 1542 | reg: Register, |
| ... | ... | @@ -1550,7 +1558,7 @@ fn asmAirRegisterImmediate( |
| 1550 | 1558 | } |
| 1551 | 1559 | |
| 1552 | 1560 | fn asmAirFrameAddress( |
| 1553 | | self: *Self, |
| 1561 | self: *CodeGen, |
| 1554 | 1562 | tag: MirTagAir, |
| 1555 | 1563 | inst: Air.Inst.Index, |
| 1556 | 1564 | frame_addr: bits.FrameAddr, |
| ... | ... | @@ -1567,7 +1575,7 @@ fn asmAirFrameAddress( |
| 1567 | 1575 | }); |
| 1568 | 1576 | } |
| 1569 | 1577 | |
| 1570 | | fn asmAirMemory(self: *Self, tag: MirTagAir, inst: Air.Inst.Index, m: Memory) !void { |
| 1578 | fn asmAirMemory(self: *CodeGen, tag: MirTagAir, inst: Air.Inst.Index, m: Memory) !void { |
| 1571 | 1579 | _ = try self.addInst(.{ |
| 1572 | 1580 | .tag = .pseudo, |
| 1573 | 1581 | .ops = switch (tag) { |
| ... | ... | @@ -1580,7 +1588,7 @@ fn asmAirMemory(self: *Self, tag: MirTagAir, inst: Air.Inst.Index, m: Memory) !v |
| 1580 | 1588 | }); |
| 1581 | 1589 | } |
| 1582 | 1590 | |
| 1583 | | fn asmOpOnly(self: *Self, tag: Mir.Inst.FixedTag) !void { |
| 1591 | fn asmOpOnly(self: *CodeGen, tag: Mir.Inst.FixedTag) !void { |
| 1584 | 1592 | _ = try self.addInst(.{ |
| 1585 | 1593 | .tag = tag[1], |
| 1586 | 1594 | .ops = .none, |
| ... | ... | @@ -1590,7 +1598,7 @@ fn asmOpOnly(self: *Self, tag: Mir.Inst.FixedTag) !void { |
| 1590 | 1598 | }); |
| 1591 | 1599 | } |
| 1592 | 1600 | |
| 1593 | | fn asmPseudo(self: *Self, ops: Mir.Inst.Ops) !void { |
| 1601 | fn asmPseudo(self: *CodeGen, ops: Mir.Inst.Ops) !void { |
| 1594 | 1602 | assert(std.mem.startsWith(u8, @tagName(ops), "pseudo_") and |
| 1595 | 1603 | std.mem.endsWith(u8, @tagName(ops), "_none")); |
| 1596 | 1604 | _ = try self.addInst(.{ |
| ... | ... | @@ -1600,7 +1608,7 @@ fn asmPseudo(self: *Self, ops: Mir.Inst.Ops) !void { |
| 1600 | 1608 | }); |
| 1601 | 1609 | } |
| 1602 | 1610 | |
| 1603 | | fn asmPseudoRegister(self: *Self, ops: Mir.Inst.Ops, reg: Register) !void { |
| 1611 | fn asmPseudoRegister(self: *CodeGen, ops: Mir.Inst.Ops, reg: Register) !void { |
| 1604 | 1612 | assert(std.mem.startsWith(u8, @tagName(ops), "pseudo_") and |
| 1605 | 1613 | std.mem.endsWith(u8, @tagName(ops), "_r")); |
| 1606 | 1614 | _ = try self.addInst(.{ |
| ... | ... | @@ -1610,7 +1618,7 @@ fn asmPseudoRegister(self: *Self, ops: Mir.Inst.Ops, reg: Register) !void { |
| 1610 | 1618 | }); |
| 1611 | 1619 | } |
| 1612 | 1620 | |
| 1613 | | fn asmPseudoImmediate(self: *Self, ops: Mir.Inst.Ops, imm: Immediate) !void { |
| 1621 | fn asmPseudoImmediate(self: *CodeGen, ops: Mir.Inst.Ops, imm: Immediate) !void { |
| 1614 | 1622 | assert(std.mem.startsWith(u8, @tagName(ops), "pseudo_") and |
| 1615 | 1623 | std.mem.endsWith(u8, @tagName(ops), "_i_s")); |
| 1616 | 1624 | _ = try self.addInst(.{ |
| ... | ... | @@ -1620,7 +1628,7 @@ fn asmPseudoImmediate(self: *Self, ops: Mir.Inst.Ops, imm: Immediate) !void { |
| 1620 | 1628 | }); |
| 1621 | 1629 | } |
| 1622 | 1630 | |
| 1623 | | fn asmPseudoRegisterRegister(self: *Self, ops: Mir.Inst.Ops, reg1: Register, reg2: Register) !void { |
| 1631 | fn asmPseudoRegisterRegister(self: *CodeGen, ops: Mir.Inst.Ops, reg1: Register, reg2: Register) !void { |
| 1624 | 1632 | assert(std.mem.startsWith(u8, @tagName(ops), "pseudo_") and |
| 1625 | 1633 | std.mem.endsWith(u8, @tagName(ops), "_rr")); |
| 1626 | 1634 | _ = try self.addInst(.{ |
| ... | ... | @@ -1630,7 +1638,7 @@ fn asmPseudoRegisterRegister(self: *Self, ops: Mir.Inst.Ops, reg1: Register, reg |
| 1630 | 1638 | }); |
| 1631 | 1639 | } |
| 1632 | 1640 | |
| 1633 | | fn asmPseudoRegisterImmediate(self: *Self, ops: Mir.Inst.Ops, reg: Register, imm: Immediate) !void { |
| 1641 | fn asmPseudoRegisterImmediate(self: *CodeGen, ops: Mir.Inst.Ops, reg: Register, imm: Immediate) !void { |
| 1634 | 1642 | assert(std.mem.startsWith(u8, @tagName(ops), "pseudo_") and |
| 1635 | 1643 | std.mem.endsWith(u8, @tagName(ops), "_ri_s")); |
| 1636 | 1644 | _ = try self.addInst(.{ |
| ... | ... | @@ -1640,7 +1648,7 @@ fn asmPseudoRegisterImmediate(self: *Self, ops: Mir.Inst.Ops, reg: Register, imm |
| 1640 | 1648 | }); |
| 1641 | 1649 | } |
| 1642 | 1650 | |
| 1643 | | fn asmRegister(self: *Self, tag: Mir.Inst.FixedTag, reg: Register) !void { |
| 1651 | fn asmRegister(self: *CodeGen, tag: Mir.Inst.FixedTag, reg: Register) !void { |
| 1644 | 1652 | _ = try self.addInst(.{ |
| 1645 | 1653 | .tag = tag[1], |
| 1646 | 1654 | .ops = .r, |
| ... | ... | @@ -1651,7 +1659,7 @@ fn asmRegister(self: *Self, tag: Mir.Inst.FixedTag, reg: Register) !void { |
| 1651 | 1659 | }); |
| 1652 | 1660 | } |
| 1653 | 1661 | |
| 1654 | | fn asmImmediate(self: *Self, tag: Mir.Inst.FixedTag, imm: Immediate) !void { |
| 1662 | fn asmImmediate(self: *CodeGen, tag: Mir.Inst.FixedTag, imm: Immediate) !void { |
| 1655 | 1663 | _ = try self.addInst(.{ |
| 1656 | 1664 | .tag = tag[1], |
| 1657 | 1665 | .ops = switch (imm) { |
| ... | ... | @@ -1676,7 +1684,7 @@ fn asmImmediate(self: *Self, tag: Mir.Inst.FixedTag, imm: Immediate) !void { |
| 1676 | 1684 | }); |
| 1677 | 1685 | } |
| 1678 | 1686 | |
| 1679 | | fn asmRegisterRegister(self: *Self, tag: Mir.Inst.FixedTag, reg1: Register, reg2: Register) !void { |
| 1687 | fn asmRegisterRegister(self: *CodeGen, tag: Mir.Inst.FixedTag, reg1: Register, reg2: Register) !void { |
| 1680 | 1688 | _ = try self.addInst(.{ |
| 1681 | 1689 | .tag = tag[1], |
| 1682 | 1690 | .ops = .rr, |
| ... | ... | @@ -1688,7 +1696,7 @@ fn asmRegisterRegister(self: *Self, tag: Mir.Inst.FixedTag, reg1: Register, reg2 |
| 1688 | 1696 | }); |
| 1689 | 1697 | } |
| 1690 | 1698 | |
| 1691 | | fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, imm: Immediate) !void { |
| 1699 | fn asmRegisterImmediate(self: *CodeGen, tag: Mir.Inst.FixedTag, reg: Register, imm: Immediate) !void { |
| 1692 | 1700 | const ops: Mir.Inst.Ops, const i: u32 = switch (imm) { |
| 1693 | 1701 | .signed => |s| .{ .ri_s, @bitCast(s) }, |
| 1694 | 1702 | .unsigned => |u| if (std.math.cast(u32, u)) |small| |
| ... | ... | @@ -1709,7 +1717,7 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, imm: |
| 1709 | 1717 | } |
| 1710 | 1718 | |
| 1711 | 1719 | fn asmRegisterRegisterRegister( |
| 1712 | | self: *Self, |
| 1720 | self: *CodeGen, |
| 1713 | 1721 | tag: Mir.Inst.FixedTag, |
| 1714 | 1722 | reg1: Register, |
| 1715 | 1723 | reg2: Register, |
| ... | ... | @@ -1728,7 +1736,7 @@ fn asmRegisterRegisterRegister( |
| 1728 | 1736 | } |
| 1729 | 1737 | |
| 1730 | 1738 | fn asmRegisterRegisterRegisterRegister( |
| 1731 | | self: *Self, |
| 1739 | self: *CodeGen, |
| 1732 | 1740 | tag: Mir.Inst.FixedTag, |
| 1733 | 1741 | reg1: Register, |
| 1734 | 1742 | reg2: Register, |
| ... | ... | @@ -1749,7 +1757,7 @@ fn asmRegisterRegisterRegisterRegister( |
| 1749 | 1757 | } |
| 1750 | 1758 | |
| 1751 | 1759 | fn asmRegisterRegisterRegisterImmediate( |
| 1752 | | self: *Self, |
| 1760 | self: *CodeGen, |
| 1753 | 1761 | tag: Mir.Inst.FixedTag, |
| 1754 | 1762 | reg1: Register, |
| 1755 | 1763 | reg2: Register, |
| ... | ... | @@ -1774,7 +1782,7 @@ fn asmRegisterRegisterRegisterImmediate( |
| 1774 | 1782 | } |
| 1775 | 1783 | |
| 1776 | 1784 | fn asmRegisterRegisterImmediate( |
| 1777 | | self: *Self, |
| 1785 | self: *CodeGen, |
| 1778 | 1786 | tag: Mir.Inst.FixedTag, |
| 1779 | 1787 | reg1: Register, |
| 1780 | 1788 | reg2: Register, |
| ... | ... | @@ -1801,7 +1809,7 @@ fn asmRegisterRegisterImmediate( |
| 1801 | 1809 | } |
| 1802 | 1810 | |
| 1803 | 1811 | fn asmRegisterRegisterMemory( |
| 1804 | | self: *Self, |
| 1812 | self: *CodeGen, |
| 1805 | 1813 | tag: Mir.Inst.FixedTag, |
| 1806 | 1814 | reg1: Register, |
| 1807 | 1815 | reg2: Register, |
| ... | ... | @@ -1820,7 +1828,7 @@ fn asmRegisterRegisterMemory( |
| 1820 | 1828 | } |
| 1821 | 1829 | |
| 1822 | 1830 | fn asmRegisterRegisterMemoryRegister( |
| 1823 | | self: *Self, |
| 1831 | self: *CodeGen, |
| 1824 | 1832 | tag: Mir.Inst.FixedTag, |
| 1825 | 1833 | reg1: Register, |
| 1826 | 1834 | reg2: Register, |
| ... | ... | @@ -1840,7 +1848,7 @@ fn asmRegisterRegisterMemoryRegister( |
| 1840 | 1848 | }); |
| 1841 | 1849 | } |
| 1842 | 1850 | |
| 1843 | | fn asmMemory(self: *Self, tag: Mir.Inst.FixedTag, m: Memory) !void { |
| 1851 | fn asmMemory(self: *CodeGen, tag: Mir.Inst.FixedTag, m: Memory) !void { |
| 1844 | 1852 | _ = try self.addInst(.{ |
| 1845 | 1853 | .tag = tag[1], |
| 1846 | 1854 | .ops = .m, |
| ... | ... | @@ -1851,7 +1859,7 @@ fn asmMemory(self: *Self, tag: Mir.Inst.FixedTag, m: Memory) !void { |
| 1851 | 1859 | }); |
| 1852 | 1860 | } |
| 1853 | 1861 | |
| 1854 | | fn asmRegisterMemory(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, m: Memory) !void { |
| 1862 | fn asmRegisterMemory(self: *CodeGen, tag: Mir.Inst.FixedTag, reg: Register, m: Memory) !void { |
| 1855 | 1863 | _ = try self.addInst(.{ |
| 1856 | 1864 | .tag = tag[1], |
| 1857 | 1865 | .ops = .rm, |
| ... | ... | @@ -1864,7 +1872,7 @@ fn asmRegisterMemory(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, m: Memo |
| 1864 | 1872 | } |
| 1865 | 1873 | |
| 1866 | 1874 | fn asmRegisterMemoryRegister( |
| 1867 | | self: *Self, |
| 1875 | self: *CodeGen, |
| 1868 | 1876 | tag: Mir.Inst.FixedTag, |
| 1869 | 1877 | reg1: Register, |
| 1870 | 1878 | m: Memory, |
| ... | ... | @@ -1883,7 +1891,7 @@ fn asmRegisterMemoryRegister( |
| 1883 | 1891 | } |
| 1884 | 1892 | |
| 1885 | 1893 | fn asmRegisterMemoryImmediate( |
| 1886 | | self: *Self, |
| 1894 | self: *CodeGen, |
| 1887 | 1895 | tag: Mir.Inst.FixedTag, |
| 1888 | 1896 | reg: Register, |
| 1889 | 1897 | m: Memory, |
| ... | ... | @@ -1928,7 +1936,7 @@ fn asmRegisterMemoryImmediate( |
| 1928 | 1936 | } |
| 1929 | 1937 | |
| 1930 | 1938 | fn asmRegisterRegisterMemoryImmediate( |
| 1931 | | self: *Self, |
| 1939 | self: *CodeGen, |
| 1932 | 1940 | tag: Mir.Inst.FixedTag, |
| 1933 | 1941 | reg1: Register, |
| 1934 | 1942 | reg2: Register, |
| ... | ... | @@ -1948,7 +1956,7 @@ fn asmRegisterRegisterMemoryImmediate( |
| 1948 | 1956 | }); |
| 1949 | 1957 | } |
| 1950 | 1958 | |
| 1951 | | fn asmMemoryRegister(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, reg: Register) !void { |
| 1959 | fn asmMemoryRegister(self: *CodeGen, tag: Mir.Inst.FixedTag, m: Memory, reg: Register) !void { |
| 1952 | 1960 | _ = try self.addInst(.{ |
| 1953 | 1961 | .tag = tag[1], |
| 1954 | 1962 | .ops = .mr, |
| ... | ... | @@ -1960,7 +1968,7 @@ fn asmMemoryRegister(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, reg: Regist |
| 1960 | 1968 | }); |
| 1961 | 1969 | } |
| 1962 | 1970 | |
| 1963 | | fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, imm: Immediate) !void { |
| 1971 | fn asmMemoryImmediate(self: *CodeGen, tag: Mir.Inst.FixedTag, m: Memory, imm: Immediate) !void { |
| 1964 | 1972 | const payload = try self.addExtra(Mir.Imm32{ .imm = switch (imm) { |
| 1965 | 1973 | .signed => |s| @bitCast(s), |
| 1966 | 1974 | .unsigned => |u| @intCast(u), |
| ... | ... | @@ -1982,7 +1990,7 @@ fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, imm: Immed |
| 1982 | 1990 | } |
| 1983 | 1991 | |
| 1984 | 1992 | fn asmMemoryRegisterRegister( |
| 1985 | | self: *Self, |
| 1993 | self: *CodeGen, |
| 1986 | 1994 | tag: Mir.Inst.FixedTag, |
| 1987 | 1995 | m: Memory, |
| 1988 | 1996 | reg1: Register, |
| ... | ... | @@ -2001,7 +2009,7 @@ fn asmMemoryRegisterRegister( |
| 2001 | 2009 | } |
| 2002 | 2010 | |
| 2003 | 2011 | fn asmMemoryRegisterImmediate( |
| 2004 | | self: *Self, |
| 2012 | self: *CodeGen, |
| 2005 | 2013 | tag: Mir.Inst.FixedTag, |
| 2006 | 2014 | m: Memory, |
| 2007 | 2015 | reg: Register, |
| ... | ... | @@ -2019,7 +2027,7 @@ fn asmMemoryRegisterImmediate( |
| 2019 | 2027 | }); |
| 2020 | 2028 | } |
| 2021 | 2029 | |
| 2022 | | fn gen(self: *Self) InnerError!void { |
| 2030 | fn gen(self: *CodeGen) InnerError!void { |
| 2023 | 2031 | const pt = self.pt; |
| 2024 | 2032 | const zcu = pt.zcu; |
| 2025 | 2033 | const fn_info = zcu.typeToFunc(self.fn_type).?; |
| ... | ... | @@ -2229,7 +2237,7 @@ fn gen(self: *Self) InnerError!void { |
| 2229 | 2237 | }); |
| 2230 | 2238 | } |
| 2231 | 2239 | |
| 2232 | | fn checkInvariantsAfterAirInst(self: *Self) void { |
| 2240 | fn checkInvariantsAfterAirInst(self: *CodeGen) void { |
| 2233 | 2241 | assert(!self.register_manager.lockedRegsExist()); |
| 2234 | 2242 | |
| 2235 | 2243 | if (std.debug.runtime_safety) { |
| ... | ... | @@ -2245,13 +2253,13 @@ fn checkInvariantsAfterAirInst(self: *Self) void { |
| 2245 | 2253 | } |
| 2246 | 2254 | } |
| 2247 | 2255 | |
| 2248 | | fn genBodyBlock(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 2256 | fn genBodyBlock(self: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2249 | 2257 | try self.asmPseudo(.pseudo_dbg_enter_block_none); |
| 2250 | 2258 | try self.genBody(body); |
| 2251 | 2259 | try self.asmPseudo(.pseudo_dbg_leave_block_none); |
| 2252 | 2260 | } |
| 2253 | 2261 | |
| 2254 | | fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 2262 | fn genBody(self: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2255 | 2263 | const pt = self.pt; |
| 2256 | 2264 | const zcu = pt.zcu; |
| 2257 | 2265 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -2461,15 +2469,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 2461 | 2469 | try slot.moveTo(inst, self); |
| 2462 | 2470 | }, |
| 2463 | 2471 | .assembly => try self.airAsm(inst), |
| 2464 | | inline .bit_and, .bit_or, .xor => |tag| if (use_old or self.typeOfIndex(inst).abiSize(zcu) > @as( |
| 2465 | | u64, |
| 2466 | | if (!self.typeOfIndex(inst).isVector(zcu)) |
| 2467 | | 8 |
| 2468 | | else if (!self.hasFeature(.avx2)) |
| 2469 | | 16 |
| 2470 | | else |
| 2471 | | 32, |
| 2472 | | )) try self.airBinOp(inst, tag) else { |
| 2472 | inline .bit_and, .bit_or, .xor => |tag| if (use_old) try self.airBinOp(inst, tag) else { |
| 2473 | 2473 | const bin_op = air_datas[@intFromEnum(inst)].bin_op; |
| 2474 | 2474 | var ops = try self.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 2475 | 2475 | try self.spillEflagsIfOccupied(); |
| ... | ... | @@ -2481,30 +2481,109 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 2481 | 2481 | }; |
| 2482 | 2482 | var res: [1]Temp = undefined; |
| 2483 | 2483 | try self.select(&res, &.{ &ops[0], &ops[1] }, &.{ |
| 2484 | | .{ .tag = .{ .vp_, mir_tag }, .ops = &.{ .ymm, .ymm, .mem }, .features = &.{.avx2} }, |
| 2485 | | .{ .tag = .{ .vp_, mir_tag }, .ops = &.{ .ymm, .mem, .ymm }, .commute = .{ 1, 2 }, .features = &.{.avx2} }, |
| 2486 | | .{ .tag = .{ .vp_, mir_tag }, .ops = &.{ .ymm, .ymm, .ymm }, .features = &.{.avx2} }, |
| 2487 | | .{ .tag = .{ .vp_, mir_tag }, .ops = &.{ .xmm, .xmm, .mem }, .features = &.{.avx} }, |
| 2488 | | .{ .tag = .{ .vp_, mir_tag }, .ops = &.{ .xmm, .mem, .xmm }, .commute = .{ 1, 2 }, .features = &.{.avx} }, |
| 2489 | | .{ .tag = .{ .vp_, mir_tag }, .ops = &.{ .xmm, .xmm, .xmm }, .features = &.{.avx} }, |
| 2490 | | .{ .tag = .{ .p_, mir_tag }, .ops = &.{ .xmm, .{ .match = 0 }, .mem }, .features = &.{.sse2} }, |
| 2491 | | .{ .tag = .{ .p_, mir_tag }, .ops = &.{ .xmm, .mem, .{ .match = 0 } }, .features = &.{.sse2} }, |
| 2492 | | .{ .tag = .{ .p_, mir_tag }, .ops = &.{ .xmm, .{ .match = 0 }, .xmm }, .features = &.{.sse2} }, |
| 2493 | | .{ .tag = .{ .p_, mir_tag }, .ops = &.{ .xmm, .xmm, .{ .match = 0 } }, .features = &.{.sse2} }, |
| 2494 | | .{ .tag = .{ .p_, mir_tag }, .ops = &.{ .mm, .{ .match = 0 }, .mem }, .features = &.{.mmx} }, |
| 2495 | | .{ .tag = .{ .p_, mir_tag }, .ops = &.{ .mm, .mem, .{ .match = 0 } }, .features = &.{.mmx} }, |
| 2496 | | .{ .tag = .{ .p_, mir_tag }, .ops = &.{ .mm, .{ .match = 0 }, .mm }, .features = &.{.mmx} }, |
| 2497 | | .{ .tag = .{ .p_, mir_tag }, .ops = &.{ .mm, .mm, .{ .match = 0 } }, .features = &.{.mmx} }, |
| 2498 | | .{ .tag = .{ ._, mir_tag }, .ops = &.{ .mem, .{ .match = 0 }, .simm32 } }, |
| 2499 | | .{ .tag = .{ ._, mir_tag }, .ops = &.{ .mem, .simm32, .{ .match = 0 } } }, |
| 2500 | | .{ .tag = .{ ._, mir_tag }, .ops = &.{ .mem, .{ .match = 0 }, .gpr } }, |
| 2501 | | .{ .tag = .{ ._, mir_tag }, .ops = &.{ .mem, .gpr, .{ .match = 0 } } }, |
| 2502 | | .{ .tag = .{ ._, mir_tag }, .ops = &.{ .gpr, .{ .match = 0 }, .simm32 } }, |
| 2503 | | .{ .tag = .{ ._, mir_tag }, .ops = &.{ .gpr, .simm32, .{ .match = 0 } } }, |
| 2504 | | .{ .tag = .{ ._, mir_tag }, .ops = &.{ .gpr, .{ .match = 0 }, .mem } }, |
| 2505 | | .{ .tag = .{ ._, mir_tag }, .ops = &.{ .gpr, .mem, .{ .match = 0 } } }, |
| 2506 | | .{ .tag = .{ ._, mir_tag }, .ops = &.{ .gpr, .{ .match = 0 }, .gpr } }, |
| 2507 | | .{ .tag = .{ ._, mir_tag }, .ops = &.{ .gpr, .gpr, .{ .match = 0 } } }, |
| 2484 | .{ |
| 2485 | .required_features = &.{.avx2}, |
| 2486 | .mir_tag = .{ .vp_, mir_tag }, |
| 2487 | .patterns = &.{ |
| 2488 | .{ .ops = &.{ .ymm, .ymm, .mem } }, |
| 2489 | .{ .ops = &.{ .ymm, .mem, .ymm }, .commute = .{ 1, 2 } }, |
| 2490 | .{ .ops = &.{ .ymm, .ymm, .ymm } }, |
| 2491 | }, |
| 2492 | }, |
| 2493 | .{ |
| 2494 | .required_features = &.{.avx}, |
| 2495 | .mir_tag = .{ .vp_, mir_tag }, |
| 2496 | .patterns = &.{ |
| 2497 | .{ .ops = &.{ .xmm, .xmm, .mem } }, |
| 2498 | .{ .ops = &.{ .xmm, .mem, .xmm }, .commute = .{ 1, 2 } }, |
| 2499 | .{ .ops = &.{ .xmm, .xmm, .xmm } }, |
| 2500 | }, |
| 2501 | }, |
| 2502 | .{ |
| 2503 | .required_features = &.{.sse2}, |
| 2504 | .mir_tag = .{ .p_, mir_tag }, |
| 2505 | .patterns = &.{ |
| 2506 | .{ .ops = &.{ .xmm, .{ .implicit = 0 }, .mem } }, |
| 2507 | .{ .ops = &.{ .xmm, .mem, .{ .implicit = 0 } } }, |
| 2508 | .{ .ops = &.{ .xmm, .{ .implicit = 0 }, .xmm } }, |
| 2509 | .{ .ops = &.{ .xmm, .xmm, .{ .implicit = 0 } } }, |
| 2510 | }, |
| 2511 | }, |
| 2512 | .{ |
| 2513 | .required_features = &.{.mmx}, |
| 2514 | .mir_tag = .{ .p_, mir_tag }, |
| 2515 | .patterns = &.{ |
| 2516 | .{ .ops = &.{ .mm, .{ .implicit = 0 }, .mem } }, |
| 2517 | .{ .ops = &.{ .mm, .mem, .{ .implicit = 0 } } }, |
| 2518 | .{ .ops = &.{ .mm, .{ .implicit = 0 }, .mm } }, |
| 2519 | .{ .ops = &.{ .mm, .mm, .{ .implicit = 0 } } }, |
| 2520 | }, |
| 2521 | }, |
| 2522 | .{ |
| 2523 | .mir_tag = .{ ._, mir_tag }, |
| 2524 | .patterns = &.{ |
| 2525 | .{ .ops = &.{ .mem, .{ .implicit = 0 }, .simm32 } }, |
| 2526 | .{ .ops = &.{ .mem, .simm32, .{ .implicit = 0 } } }, |
| 2527 | .{ .ops = &.{ .mem, .{ .implicit = 0 }, .gpr } }, |
| 2528 | .{ .ops = &.{ .mem, .gpr, .{ .implicit = 0 } } }, |
| 2529 | .{ .ops = &.{ .gpr, .{ .implicit = 0 }, .simm32 } }, |
| 2530 | .{ .ops = &.{ .gpr, .simm32, .{ .implicit = 0 } } }, |
| 2531 | .{ .ops = &.{ .gpr, .{ .implicit = 0 }, .mem } }, |
| 2532 | .{ .ops = &.{ .gpr, .mem, .{ .implicit = 0 } } }, |
| 2533 | .{ .ops = &.{ .gpr, .{ .implicit = 0 }, .gpr } }, |
| 2534 | .{ .ops = &.{ .gpr, .gpr, .{ .implicit = 0 } } }, |
| 2535 | }, |
| 2536 | }, |
| 2537 | |
| 2538 | .{ |
| 2539 | .required_features = &.{.avx2}, |
| 2540 | .loop = .bitwise, |
| 2541 | .mir_tag = .{ .vp_, mir_tag }, |
| 2542 | .patterns = &.{ |
| 2543 | .{ .ops = &.{ .ymm_limb, .{ .explicit = 0 }, .mem_limb } }, |
| 2544 | .{ .ops = &.{ .ymm_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } }, |
| 2545 | .{ .ops = &.{ .ymm_limb, .ymm_limb, .mem_limb } }, |
| 2546 | }, |
| 2547 | }, |
| 2548 | .{ |
| 2549 | .required_features = &.{.avx}, |
| 2550 | .loop = .bitwise, |
| 2551 | .mir_tag = .{ .vp_, mir_tag }, |
| 2552 | .patterns = &.{ |
| 2553 | .{ .ops = &.{ .xmm_limb, .{ .explicit = 0 }, .mem_limb } }, |
| 2554 | .{ .ops = &.{ .xmm_limb, .mem_limb, .{ .explicit = 0 } }, .commute = .{ 1, 2 } }, |
| 2555 | .{ .ops = &.{ .xmm_limb, .xmm_limb, .mem_limb } }, |
| 2556 | }, |
| 2557 | }, |
| 2558 | .{ |
| 2559 | .required_features = &.{.sse2}, |
| 2560 | .loop = .bitwise, |
| 2561 | .mir_tag = .{ .p_, mir_tag }, |
| 2562 | .patterns = &.{ |
| 2563 | .{ .ops = &.{ .xmm_limb, .{ .implicit = 0 }, .mem_limb } }, |
| 2564 | .{ .ops = &.{ .xmm_limb, .mem_limb, .{ .implicit = 0 } } }, |
| 2565 | }, |
| 2566 | }, |
| 2567 | .{ |
| 2568 | .required_features = &.{.mmx}, |
| 2569 | .loop = .bitwise, |
| 2570 | .mir_tag = .{ .p_, mir_tag }, |
| 2571 | .patterns = &.{ |
| 2572 | .{ .ops = &.{ .mm_limb, .{ .implicit = 0 }, .mem_limb } }, |
| 2573 | .{ .ops = &.{ .mm_limb, .mem_limb, .{ .implicit = 0 } } }, |
| 2574 | }, |
| 2575 | }, |
| 2576 | .{ |
| 2577 | .loop = .bitwise, |
| 2578 | .mir_tag = .{ ._, mir_tag }, |
| 2579 | .patterns = &.{ |
| 2580 | .{ .ops = &.{ .mem_limb, .{ .implicit = 0 }, .gpr_limb } }, |
| 2581 | .{ .ops = &.{ .mem_limb, .gpr_limb, .{ .implicit = 0 } } }, |
| 2582 | .{ .ops = &.{ .gpr_limb, .{ .implicit = 0 }, .mem_limb } }, |
| 2583 | .{ .ops = &.{ .gpr_limb, .mem_limb, .{ .implicit = 0 } } }, |
| 2584 | .{ .ops = &.{ .gpr_limb, .{ .implicit = 0 }, .gpr_limb } }, |
| 2585 | }, |
| 2586 | }, |
| 2508 | 2587 | }); |
| 2509 | 2588 | if (ops[0].index != res[0].index) try ops[0].die(self); |
| 2510 | 2589 | if (ops[1].index != res[0].index) try ops[1].die(self); |
| ... | ... | @@ -2620,12 +2699,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 2620 | 2699 | while (try ops[0].toLea(self)) {} |
| 2621 | 2700 | try self.asmMemoryImmediate( |
| 2622 | 2701 | .{ ._, .cmp }, |
| 2623 | | try ops[0].tracking(self).short.deref().mem(self, if (!opt_repr_is_pl) |
| 2702 | try ops[0].tracking(self).short.deref().mem(self, .{ .size = if (!opt_repr_is_pl) |
| 2624 | 2703 | .byte |
| 2625 | 2704 | else if (opt_child_ty.isSlice(zcu)) |
| 2626 | 2705 | .qword |
| 2627 | 2706 | else |
| 2628 | | .fromSize(opt_child_abi_size)), |
| 2707 | .fromSize(opt_child_abi_size) }), |
| 2629 | 2708 | .u(0), |
| 2630 | 2709 | ); |
| 2631 | 2710 | var is_null = try self.tempFromValue(self.typeOfIndex(inst), .{ .eflags = .e }); |
| ... | ... | @@ -2643,12 +2722,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 2643 | 2722 | while (try ops[0].toLea(self)) {} |
| 2644 | 2723 | try self.asmMemoryImmediate( |
| 2645 | 2724 | .{ ._, .cmp }, |
| 2646 | | try ops[0].tracking(self).short.deref().mem(self, if (!opt_repr_is_pl) |
| 2725 | try ops[0].tracking(self).short.deref().mem(self, .{ .size = if (!opt_repr_is_pl) |
| 2647 | 2726 | .byte |
| 2648 | 2727 | else if (opt_child_ty.isSlice(zcu)) |
| 2649 | 2728 | .qword |
| 2650 | 2729 | else |
| 2651 | | .fromSize(opt_child_abi_size)), |
| 2730 | .fromSize(opt_child_abi_size) }), |
| 2652 | 2731 | .u(0), |
| 2653 | 2732 | ); |
| 2654 | 2733 | var is_non_null = try self.tempFromValue(self.typeOfIndex(inst), .{ .eflags = .ne }); |
| ... | ... | @@ -2666,7 +2745,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 2666 | 2745 | while (try ops[0].toLea(self)) {} |
| 2667 | 2746 | try self.asmMemoryImmediate( |
| 2668 | 2747 | .{ ._, .cmp }, |
| 2669 | | try ops[0].tracking(self).short.deref().mem(self, self.memSize(eu_err_ty)), |
| 2748 | try ops[0].tracking(self).short.deref().mem(self, .{ .size = self.memSize(eu_err_ty) }), |
| 2670 | 2749 | .u(0), |
| 2671 | 2750 | ); |
| 2672 | 2751 | var is_err = try self.tempFromValue(self.typeOfIndex(inst), .{ .eflags = .ne }); |
| ... | ... | @@ -2684,7 +2763,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 2684 | 2763 | while (try ops[0].toLea(self)) {} |
| 2685 | 2764 | try self.asmMemoryImmediate( |
| 2686 | 2765 | .{ ._, .cmp }, |
| 2687 | | try ops[0].tracking(self).short.deref().mem(self, self.memSize(eu_err_ty)), |
| 2766 | try ops[0].tracking(self).short.deref().mem(self, .{ .size = self.memSize(eu_err_ty) }), |
| 2688 | 2767 | .u(0), |
| 2689 | 2768 | ); |
| 2690 | 2769 | var is_non_err = try self.tempFromValue(self.typeOfIndex(inst), .{ .eflags = .e }); |
| ... | ... | @@ -2950,7 +3029,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 2950 | 3029 | verbose_tracking_log.debug("{}", .{self.fmtTracking()}); |
| 2951 | 3030 | } |
| 2952 | 3031 | |
| 2953 | | fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 3032 | fn genLazy(self: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 2954 | 3033 | const pt = self.pt; |
| 2955 | 3034 | const zcu = pt.zcu; |
| 2956 | 3035 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -3017,7 +3096,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 3017 | 3096 | } |
| 3018 | 3097 | } |
| 3019 | 3098 | |
| 3020 | | fn getValue(self: *Self, value: MCValue, inst: ?Air.Inst.Index) !void { |
| 3099 | fn getValue(self: *CodeGen, value: MCValue, inst: ?Air.Inst.Index) !void { |
| 3021 | 3100 | for (value.getRegs()) |reg| try self.register_manager.getReg(reg, inst); |
| 3022 | 3101 | switch (value) { |
| 3023 | 3102 | else => {}, |
| ... | ... | @@ -3025,21 +3104,23 @@ fn getValue(self: *Self, value: MCValue, inst: ?Air.Inst.Index) !void { |
| 3025 | 3104 | } |
| 3026 | 3105 | } |
| 3027 | 3106 | |
| 3028 | | fn getValueIfFree(self: *Self, value: MCValue, inst: ?Air.Inst.Index) void { |
| 3107 | fn getValueIfFree(self: *CodeGen, value: MCValue, inst: ?Air.Inst.Index) void { |
| 3029 | 3108 | for (value.getRegs()) |reg| if (self.register_manager.isRegFree(reg)) |
| 3030 | 3109 | self.register_manager.getRegAssumeFree(reg, inst); |
| 3031 | 3110 | } |
| 3032 | 3111 | |
| 3033 | | fn freeValue(self: *Self, value: MCValue) !void { |
| 3112 | fn freeReg(self: *CodeGen, reg: Register) !void { |
| 3113 | self.register_manager.freeReg(reg); |
| 3114 | if (reg.class() == .x87) try self.asmRegister(.{ .f_, .free }, reg); |
| 3115 | } |
| 3116 | |
| 3117 | fn freeValue(self: *CodeGen, value: MCValue) !void { |
| 3034 | 3118 | switch (value) { |
| 3035 | | .register => |reg| { |
| 3036 | | self.register_manager.freeReg(reg); |
| 3037 | | if (reg.class() == .x87) try self.asmRegister(.{ .f_, .free }, reg); |
| 3038 | | }, |
| 3039 | | .register_pair => |regs| for (regs) |reg| self.register_manager.freeReg(reg), |
| 3040 | | .register_offset => |reg_off| self.register_manager.freeReg(reg_off.reg), |
| 3119 | .register => |reg| try self.freeReg(reg), |
| 3120 | .register_pair => |regs| for (regs) |reg| try self.freeReg(reg), |
| 3121 | .register_offset, .indirect => |reg_off| try self.freeReg(reg_off.reg), |
| 3041 | 3122 | .register_overflow => |reg_ov| { |
| 3042 | | self.register_manager.freeReg(reg_ov.reg); |
| 3123 | try self.freeReg(reg_ov.reg); |
| 3043 | 3124 | self.eflags_inst = null; |
| 3044 | 3125 | }, |
| 3045 | 3126 | .eflags => self.eflags_inst = null, |
| ... | ... | @@ -3047,16 +3128,16 @@ fn freeValue(self: *Self, value: MCValue) !void { |
| 3047 | 3128 | } |
| 3048 | 3129 | } |
| 3049 | 3130 | |
| 3050 | | fn feed(self: *Self, bt: *Liveness.BigTomb, operand: Air.Inst.Ref) !void { |
| 3131 | fn feed(self: *CodeGen, bt: *Liveness.BigTomb, operand: Air.Inst.Ref) !void { |
| 3051 | 3132 | if (bt.feed()) if (operand.toIndex()) |inst| try self.processDeath(inst); |
| 3052 | 3133 | } |
| 3053 | 3134 | |
| 3054 | 3135 | /// Asserts there is already capacity to insert into top branch inst_table. |
| 3055 | | fn processDeath(self: *Self, inst: Air.Inst.Index) !void { |
| 3136 | fn processDeath(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 3056 | 3137 | try self.inst_tracking.getPtr(inst).?.die(self, inst); |
| 3057 | 3138 | } |
| 3058 | 3139 | |
| 3059 | | fn finishAirResult(self: *Self, inst: Air.Inst.Index, result: MCValue) void { |
| 3140 | fn finishAirResult(self: *CodeGen, inst: Air.Inst.Index, result: MCValue) void { |
| 3060 | 3141 | if (self.liveness.isUnused(inst) and self.air.instructions.items(.tag)[@intFromEnum(inst)] != .arg) switch (result) { |
| 3061 | 3142 | .none, .dead, .unreach => {}, |
| 3062 | 3143 | else => unreachable, // Why didn't the result die? |
| ... | ... | @@ -3071,7 +3152,7 @@ fn finishAirResult(self: *Self, inst: Air.Inst.Index, result: MCValue) void { |
| 3071 | 3152 | } |
| 3072 | 3153 | |
| 3073 | 3154 | fn finishAir( |
| 3074 | | self: *Self, |
| 3155 | self: *CodeGen, |
| 3075 | 3156 | inst: Air.Inst.Index, |
| 3076 | 3157 | result: MCValue, |
| 3077 | 3158 | operands: [Liveness.bpi - 1]Air.Inst.Ref, |
| ... | ... | @@ -3092,7 +3173,7 @@ const FrameLayout = struct { |
| 3092 | 3173 | }; |
| 3093 | 3174 | |
| 3094 | 3175 | fn setFrameLoc( |
| 3095 | | self: *Self, |
| 3176 | self: *CodeGen, |
| 3096 | 3177 | frame_index: FrameIndex, |
| 3097 | 3178 | base: Register, |
| 3098 | 3179 | offset: *i32, |
| ... | ... | @@ -3107,7 +3188,7 @@ fn setFrameLoc( |
| 3107 | 3188 | offset.* += self.frame_allocs.items(.abi_size)[frame_i]; |
| 3108 | 3189 | } |
| 3109 | 3190 | |
| 3110 | | fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayout { |
| 3191 | fn computeFrameLayout(self: *CodeGen, cc: std.builtin.CallingConvention) !FrameLayout { |
| 3111 | 3192 | const frame_allocs_len = self.frame_allocs.len; |
| 3112 | 3193 | try self.frame_locs.resize(self.gpa, frame_allocs_len); |
| 3113 | 3194 | const stack_frame_order = try self.gpa.alloc(FrameIndex, frame_allocs_len - FrameIndex.named_count); |
| ... | ... | @@ -3173,16 +3254,16 @@ fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayo |
| 3173 | 3254 | }; |
| 3174 | 3255 | } |
| 3175 | 3256 | |
| 3176 | | fn getFrameAddrAlignment(self: *Self, frame_addr: bits.FrameAddr) InternPool.Alignment { |
| 3257 | fn getFrameAddrAlignment(self: *CodeGen, frame_addr: bits.FrameAddr) InternPool.Alignment { |
| 3177 | 3258 | const alloc_align = self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_align; |
| 3178 | 3259 | return @enumFromInt(@min(@intFromEnum(alloc_align), @ctz(frame_addr.off))); |
| 3179 | 3260 | } |
| 3180 | 3261 | |
| 3181 | | fn getFrameAddrSize(self: *Self, frame_addr: bits.FrameAddr) u32 { |
| 3262 | fn getFrameAddrSize(self: *CodeGen, frame_addr: bits.FrameAddr) u32 { |
| 3182 | 3263 | return self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_size - @as(u31, @intCast(frame_addr.off)); |
| 3183 | 3264 | } |
| 3184 | 3265 | |
| 3185 | | fn allocFrameIndex(self: *Self, alloc: FrameAlloc) !FrameIndex { |
| 3266 | fn allocFrameIndex(self: *CodeGen, alloc: FrameAlloc) !FrameIndex { |
| 3186 | 3267 | const frame_allocs_slice = self.frame_allocs.slice(); |
| 3187 | 3268 | const frame_size = frame_allocs_slice.items(.abi_size); |
| 3188 | 3269 | const frame_align = frame_allocs_slice.items(.abi_align); |
| ... | ... | @@ -3205,7 +3286,7 @@ fn allocFrameIndex(self: *Self, alloc: FrameAlloc) !FrameIndex { |
| 3205 | 3286 | } |
| 3206 | 3287 | |
| 3207 | 3288 | /// Use a pointer instruction as the basis for allocating stack memory. |
| 3208 | | fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !FrameIndex { |
| 3289 | fn allocMemPtr(self: *CodeGen, inst: Air.Inst.Index) !FrameIndex { |
| 3209 | 3290 | const pt = self.pt; |
| 3210 | 3291 | const zcu = pt.zcu; |
| 3211 | 3292 | const ptr_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -3218,15 +3299,15 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !FrameIndex { |
| 3218 | 3299 | })); |
| 3219 | 3300 | } |
| 3220 | 3301 | |
| 3221 | | fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 3302 | fn allocRegOrMem(self: *CodeGen, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 3222 | 3303 | return self.allocRegOrMemAdvanced(self.typeOfIndex(inst), inst, reg_ok); |
| 3223 | 3304 | } |
| 3224 | 3305 | |
| 3225 | | fn allocTempRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool) !MCValue { |
| 3306 | fn allocTempRegOrMem(self: *CodeGen, elem_ty: Type, reg_ok: bool) !MCValue { |
| 3226 | 3307 | return self.allocRegOrMemAdvanced(elem_ty, null, reg_ok); |
| 3227 | 3308 | } |
| 3228 | 3309 | |
| 3229 | | fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: bool) !MCValue { |
| 3310 | fn allocRegOrMemAdvanced(self: *CodeGen, ty: Type, inst: ?Air.Inst.Index, reg_ok: bool) !MCValue { |
| 3230 | 3311 | const pt = self.pt; |
| 3231 | 3312 | const zcu = pt.zcu; |
| 3232 | 3313 | const abi_size = std.math.cast(u32, ty.abiSize(zcu)) orelse { |
| ... | ... | @@ -3260,7 +3341,7 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b |
| 3260 | 3341 | return .{ .load_frame = .{ .index = frame_index } }; |
| 3261 | 3342 | } |
| 3262 | 3343 | |
| 3263 | | fn regClassForType(self: *Self, ty: Type) Register.Class { |
| 3344 | fn regClassForType(self: *CodeGen, ty: Type) Register.Class { |
| 3264 | 3345 | const pt = self.pt; |
| 3265 | 3346 | const zcu = pt.zcu; |
| 3266 | 3347 | return switch (ty.zigTypeTag(zcu)) { |
| ... | ... | @@ -3289,7 +3370,7 @@ fn regSetForRegClass(rc: Register.Class) RegisterManager.RegisterBitSet { |
| 3289 | 3370 | }; |
| 3290 | 3371 | } |
| 3291 | 3372 | |
| 3292 | | fn regSetForType(self: *Self, ty: Type) RegisterManager.RegisterBitSet { |
| 3373 | fn regSetForType(self: *CodeGen, ty: Type) RegisterManager.RegisterBitSet { |
| 3293 | 3374 | return regSetForRegClass(self.regClassForType(ty)); |
| 3294 | 3375 | } |
| 3295 | 3376 | |
| ... | ... | @@ -3301,14 +3382,14 @@ const State = struct { |
| 3301 | 3382 | scope_generation: u32, |
| 3302 | 3383 | }; |
| 3303 | 3384 | |
| 3304 | | fn initRetroactiveState(self: *Self) State { |
| 3385 | fn initRetroactiveState(self: *CodeGen) State { |
| 3305 | 3386 | var state: State = undefined; |
| 3306 | 3387 | state.inst_tracking_len = @intCast(self.inst_tracking.count()); |
| 3307 | 3388 | state.scope_generation = self.scope_generation; |
| 3308 | 3389 | return state; |
| 3309 | 3390 | } |
| 3310 | 3391 | |
| 3311 | | fn saveRetroactiveState(self: *Self, state: *State) !void { |
| 3392 | fn saveRetroactiveState(self: *CodeGen, state: *State) !void { |
| 3312 | 3393 | try self.spillEflagsIfOccupied(); |
| 3313 | 3394 | const free_registers = self.register_manager.free_registers; |
| 3314 | 3395 | var it = free_registers.iterator(.{ .kind = .unset }); |
| ... | ... | @@ -3320,13 +3401,13 @@ fn saveRetroactiveState(self: *Self, state: *State) !void { |
| 3320 | 3401 | state.free_registers = free_registers; |
| 3321 | 3402 | } |
| 3322 | 3403 | |
| 3323 | | fn saveState(self: *Self) !State { |
| 3404 | fn saveState(self: *CodeGen) !State { |
| 3324 | 3405 | var state = self.initRetroactiveState(); |
| 3325 | 3406 | try self.saveRetroactiveState(&state); |
| 3326 | 3407 | return state; |
| 3327 | 3408 | } |
| 3328 | 3409 | |
| 3329 | | fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, comptime opts: struct { |
| 3410 | fn restoreState(self: *CodeGen, state: State, deaths: []const Air.Inst.Index, comptime opts: struct { |
| 3330 | 3411 | emit_instructions: bool, |
| 3331 | 3412 | update_tracking: bool, |
| 3332 | 3413 | resurrect: bool, |
| ... | ... | @@ -3414,7 +3495,7 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt |
| 3414 | 3495 | } |
| 3415 | 3496 | } |
| 3416 | 3497 | |
| 3417 | | pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void { |
| 3498 | pub fn spillInstruction(self: *CodeGen, reg: Register, inst: Air.Inst.Index) !void { |
| 3418 | 3499 | const tracking = self.inst_tracking.getPtr(inst) orelse return; |
| 3419 | 3500 | for (tracking.getRegs()) |tracked_reg| { |
| 3420 | 3501 | if (tracked_reg.id() == reg.id()) break; |
| ... | ... | @@ -3423,7 +3504,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void |
| 3423 | 3504 | try tracking.trackSpill(self, inst); |
| 3424 | 3505 | } |
| 3425 | 3506 | |
| 3426 | | pub fn spillEflagsIfOccupied(self: *Self) !void { |
| 3507 | pub fn spillEflagsIfOccupied(self: *CodeGen) !void { |
| 3427 | 3508 | if (self.eflags_inst) |inst| { |
| 3428 | 3509 | self.eflags_inst = null; |
| 3429 | 3510 | const tracking = self.inst_tracking.getPtr(inst).?; |
| ... | ... | @@ -3433,7 +3514,7 @@ pub fn spillEflagsIfOccupied(self: *Self) !void { |
| 3433 | 3514 | } |
| 3434 | 3515 | } |
| 3435 | 3516 | |
| 3436 | | pub fn spillCallerPreservedRegs(self: *Self, cc: std.builtin.CallingConvention) !void { |
| 3517 | pub fn spillCallerPreservedRegs(self: *CodeGen, cc: std.builtin.CallingConvention) !void { |
| 3437 | 3518 | switch (cc) { |
| 3438 | 3519 | .x86_64_sysv => try self.spillRegisters(abi.getCallerPreservedRegs(.{ .x86_64_sysv = .{} })), |
| 3439 | 3520 | .x86_64_win => try self.spillRegisters(abi.getCallerPreservedRegs(.{ .x86_64_win = .{} })), |
| ... | ... | @@ -3441,14 +3522,14 @@ pub fn spillCallerPreservedRegs(self: *Self, cc: std.builtin.CallingConvention) |
| 3441 | 3522 | } |
| 3442 | 3523 | } |
| 3443 | 3524 | |
| 3444 | | pub fn spillRegisters(self: *Self, comptime registers: []const Register) !void { |
| 3525 | pub fn spillRegisters(self: *CodeGen, comptime registers: []const Register) !void { |
| 3445 | 3526 | inline for (registers) |reg| try self.register_manager.getKnownReg(reg, null); |
| 3446 | 3527 | } |
| 3447 | 3528 | |
| 3448 | 3529 | /// Copies a value to a register without tracking the register. The register is not considered |
| 3449 | 3530 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 3450 | 3531 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 3451 | | fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 3532 | fn copyToTmpRegister(self: *CodeGen, ty: Type, mcv: MCValue) !Register { |
| 3452 | 3533 | const reg = try self.register_manager.allocReg(null, self.regSetForType(ty)); |
| 3453 | 3534 | try self.genSetReg(reg, ty, mcv, .{}); |
| 3454 | 3535 | return reg; |
| ... | ... | @@ -3459,7 +3540,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 3459 | 3540 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 3460 | 3541 | /// WARNING make sure that the allocated register matches the returned MCValue from an instruction! |
| 3461 | 3542 | fn copyToRegisterWithInstTracking( |
| 3462 | | self: *Self, |
| 3543 | self: *CodeGen, |
| 3463 | 3544 | reg_owner: Air.Inst.Index, |
| 3464 | 3545 | ty: Type, |
| 3465 | 3546 | mcv: MCValue, |
| ... | ... | @@ -3469,12 +3550,12 @@ fn copyToRegisterWithInstTracking( |
| 3469 | 3550 | return MCValue{ .register = reg }; |
| 3470 | 3551 | } |
| 3471 | 3552 | |
| 3472 | | fn airAlloc(self: *Self, inst: Air.Inst.Index) !void { |
| 3553 | fn airAlloc(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 3473 | 3554 | const result = MCValue{ .lea_frame = .{ .index = try self.allocMemPtr(inst) } }; |
| 3474 | 3555 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 3475 | 3556 | } |
| 3476 | 3557 | |
| 3477 | | fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3558 | fn airRetPtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 3478 | 3559 | const result: MCValue = switch (self.ret_mcv.long) { |
| 3479 | 3560 | else => unreachable, |
| 3480 | 3561 | .none => .{ .lea_frame = .{ .index = try self.allocMemPtr(inst) } }, |
| ... | ... | @@ -3490,7 +3571,7 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3490 | 3571 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 3491 | 3572 | } |
| 3492 | 3573 | |
| 3493 | | fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 3574 | fn airFptrunc(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 3494 | 3575 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 3495 | 3576 | const dst_ty = self.typeOfIndex(inst); |
| 3496 | 3577 | const dst_bits = dst_ty.floatBits(self.target.*); |
| ... | ... | @@ -3562,7 +3643,7 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 3562 | 3643 | .{ .v_ss, .cvtsd2 }, |
| 3563 | 3644 | dst_reg, |
| 3564 | 3645 | dst_reg, |
| 3565 | | try src_mcv.mem(self, .qword), |
| 3646 | try src_mcv.mem(self, .{ .size = .qword }), |
| 3566 | 3647 | ) else try self.asmRegisterRegisterRegister( |
| 3567 | 3648 | .{ .v_ss, .cvtsd2 }, |
| 3568 | 3649 | dst_reg, |
| ... | ... | @@ -3574,7 +3655,7 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 3574 | 3655 | ) else if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 3575 | 3656 | .{ ._ss, .cvtsd2 }, |
| 3576 | 3657 | dst_reg, |
| 3577 | | try src_mcv.mem(self, .qword), |
| 3658 | try src_mcv.mem(self, .{ .size = .qword }), |
| 3578 | 3659 | ) else try self.asmRegisterRegister( |
| 3579 | 3660 | .{ ._ss, .cvtsd2 }, |
| 3580 | 3661 | dst_reg, |
| ... | ... | @@ -3589,7 +3670,7 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 3589 | 3670 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 3590 | 3671 | } |
| 3591 | 3672 | |
| 3592 | | fn airFpext(self: *Self, inst: Air.Inst.Index) !void { |
| 3673 | fn airFpext(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 3593 | 3674 | const pt = self.pt; |
| 3594 | 3675 | const zcu = pt.zcu; |
| 3595 | 3676 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -3674,7 +3755,7 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void { |
| 3674 | 3755 | .{ .v_sd, .cvtss2 }, |
| 3675 | 3756 | dst_alias, |
| 3676 | 3757 | dst_alias, |
| 3677 | | try src_mcv.mem(self, self.memSize(src_ty)), |
| 3758 | try src_mcv.mem(self, .{ .size = self.memSize(src_ty) }), |
| 3678 | 3759 | ) else try self.asmRegisterRegisterRegister( |
| 3679 | 3760 | .{ .v_sd, .cvtss2 }, |
| 3680 | 3761 | dst_alias, |
| ... | ... | @@ -3687,7 +3768,7 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void { |
| 3687 | 3768 | 2...4 => if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 3688 | 3769 | .{ .v_pd, .cvtps2 }, |
| 3689 | 3770 | dst_alias, |
| 3690 | | try src_mcv.mem(self, self.memSize(src_ty)), |
| 3771 | try src_mcv.mem(self, .{ .size = self.memSize(src_ty) }), |
| 3691 | 3772 | ) else try self.asmRegisterRegister( |
| 3692 | 3773 | .{ .v_pd, .cvtps2 }, |
| 3693 | 3774 | dst_alias, |
| ... | ... | @@ -3704,7 +3785,7 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void { |
| 3704 | 3785 | else => break :result null, |
| 3705 | 3786 | }, |
| 3706 | 3787 | dst_alias, |
| 3707 | | try src_mcv.mem(self, self.memSize(src_ty)), |
| 3788 | try src_mcv.mem(self, .{ .size = self.memSize(src_ty) }), |
| 3708 | 3789 | ) else try self.asmRegisterRegister( |
| 3709 | 3790 | switch (vec_len) { |
| 3710 | 3791 | 1 => .{ ._sd, .cvtss2 }, |
| ... | ... | @@ -3725,7 +3806,7 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void { |
| 3725 | 3806 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 3726 | 3807 | } |
| 3727 | 3808 | |
| 3728 | | fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 3809 | fn airIntCast(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 3729 | 3810 | const pt = self.pt; |
| 3730 | 3811 | const zcu = pt.zcu; |
| 3731 | 3812 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -3841,7 +3922,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 3841 | 3922 | if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 3842 | 3923 | mir_tag, |
| 3843 | 3924 | dst_alias, |
| 3844 | | try src_mcv.mem(self, self.memSize(src_ty)), |
| 3925 | try src_mcv.mem(self, .{ .size = self.memSize(src_ty) }), |
| 3845 | 3926 | ) else try self.asmRegisterRegister( |
| 3846 | 3927 | mir_tag, |
| 3847 | 3928 | dst_alias, |
| ... | ... | @@ -3984,7 +4065,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 3984 | 4065 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 3985 | 4066 | } |
| 3986 | 4067 | |
| 3987 | | fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 4068 | fn airTrunc(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 3988 | 4069 | const pt = self.pt; |
| 3989 | 4070 | const zcu = pt.zcu; |
| 3990 | 4071 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -4080,7 +4161,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 4080 | 4161 | .{ .vp_, .@"and" }, |
| 4081 | 4162 | dst_alias, |
| 4082 | 4163 | dst_alias, |
| 4083 | | try splat_addr_mcv.deref().mem(self, .fromSize(splat_abi_size)), |
| 4164 | try splat_addr_mcv.deref().mem(self, .{ .size = .fromSize(splat_abi_size) }), |
| 4084 | 4165 | ); |
| 4085 | 4166 | if (src_abi_size > 16) { |
| 4086 | 4167 | const temp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.sse); |
| ... | ... | @@ -4104,7 +4185,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 4104 | 4185 | try self.asmRegisterMemory( |
| 4105 | 4186 | .{ .p_, .@"and" }, |
| 4106 | 4187 | dst_alias, |
| 4107 | | try splat_addr_mcv.deref().mem(self, .fromSize(splat_abi_size)), |
| 4188 | try splat_addr_mcv.deref().mem(self, .{ .size = .fromSize(splat_abi_size) }), |
| 4108 | 4189 | ); |
| 4109 | 4190 | try self.asmRegisterRegister(mir_tag, dst_alias, dst_alias); |
| 4110 | 4191 | } |
| ... | ... | @@ -4130,7 +4211,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 4130 | 4211 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 4131 | 4212 | } |
| 4132 | 4213 | |
| 4133 | | fn airIntFromBool(self: *Self, inst: Air.Inst.Index) !void { |
| 4214 | fn airIntFromBool(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 4134 | 4215 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 4135 | 4216 | const ty = self.typeOfIndex(inst); |
| 4136 | 4217 | |
| ... | ... | @@ -4143,7 +4224,7 @@ fn airIntFromBool(self: *Self, inst: Air.Inst.Index) !void { |
| 4143 | 4224 | return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none }); |
| 4144 | 4225 | } |
| 4145 | 4226 | |
| 4146 | | fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 4227 | fn airSlice(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 4147 | 4228 | const zcu = self.pt.zcu; |
| 4148 | 4229 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4149 | 4230 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| ... | ... | @@ -4167,13 +4248,13 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 4167 | 4248 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 4168 | 4249 | } |
| 4169 | 4250 | |
| 4170 | | fn airUnOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 4251 | fn airUnOp(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 4171 | 4252 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 4172 | 4253 | const dst_mcv = try self.genUnOp(inst, tag, ty_op.operand); |
| 4173 | 4254 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); |
| 4174 | 4255 | } |
| 4175 | 4256 | |
| 4176 | | fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 4257 | fn airBinOp(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 4177 | 4258 | const pt = self.pt; |
| 4178 | 4259 | const zcu = pt.zcu; |
| 4179 | 4260 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -4208,14 +4289,14 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 4208 | 4289 | return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 4209 | 4290 | } |
| 4210 | 4291 | |
| 4211 | | fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 4292 | fn airPtrArithmetic(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 4212 | 4293 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 4213 | 4294 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 4214 | 4295 | const dst_mcv = try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs); |
| 4215 | 4296 | return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 4216 | 4297 | } |
| 4217 | 4298 | |
| 4218 | | fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 { |
| 4299 | fn activeIntBits(self: *CodeGen, dst_air: Air.Inst.Ref) u16 { |
| 4219 | 4300 | const pt = self.pt; |
| 4220 | 4301 | const zcu = pt.zcu; |
| 4221 | 4302 | const air_tag = self.air.instructions.items(.tag); |
| ... | ... | @@ -4250,7 +4331,7 @@ fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 { |
| 4250 | 4331 | return dst_info.bits; |
| 4251 | 4332 | } |
| 4252 | 4333 | |
| 4253 | | fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| 4334 | fn airMulDivBinOp(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 4254 | 4335 | const pt = self.pt; |
| 4255 | 4336 | const zcu = pt.zcu; |
| 4256 | 4337 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -4314,7 +4395,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| 4314 | 4395 | if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 4315 | 4396 | .{ ._, .mov }, |
| 4316 | 4397 | tmp_reg, |
| 4317 | | try mat_lhs_mcv.address().offset(8).deref().mem(self, .qword), |
| 4398 | try mat_lhs_mcv.address().offset(8).deref().mem(self, .{ .size = .qword }), |
| 4318 | 4399 | ) else try self.asmRegisterRegister( |
| 4319 | 4400 | .{ ._, .mov }, |
| 4320 | 4401 | tmp_reg, |
| ... | ... | @@ -4338,7 +4419,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| 4338 | 4419 | if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 4339 | 4420 | .{ ._, .xor }, |
| 4340 | 4421 | tmp_reg, |
| 4341 | | try mat_rhs_mcv.address().offset(8).deref().mem(self, .qword), |
| 4422 | try mat_rhs_mcv.address().offset(8).deref().mem(self, .{ .size = .qword }), |
| 4342 | 4423 | ) else try self.asmRegisterRegister( |
| 4343 | 4424 | .{ ._, .xor }, |
| 4344 | 4425 | tmp_reg, |
| ... | ... | @@ -4441,12 +4522,12 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| 4441 | 4522 | try self.asmRegisterMemory( |
| 4442 | 4523 | .{ ._, .add }, |
| 4443 | 4524 | tmp_regs[0], |
| 4444 | | try mat_rhs_mcv.mem(self, .qword), |
| 4525 | try mat_rhs_mcv.mem(self, .{ .size = .qword }), |
| 4445 | 4526 | ); |
| 4446 | 4527 | try self.asmRegisterMemory( |
| 4447 | 4528 | .{ ._, .adc }, |
| 4448 | 4529 | tmp_regs[1], |
| 4449 | | try mat_rhs_mcv.address().offset(8).deref().mem(self, .qword), |
| 4530 | try mat_rhs_mcv.address().offset(8).deref().mem(self, .{ .size = .qword }), |
| 4450 | 4531 | ); |
| 4451 | 4532 | } else for ( |
| 4452 | 4533 | [_]Mir.Inst.Tag{ .add, .adc }, |
| ... | ... | @@ -4476,7 +4557,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| 4476 | 4557 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 4477 | 4558 | } |
| 4478 | 4559 | |
| 4479 | | fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 4560 | fn airAddSat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 4480 | 4561 | const pt = self.pt; |
| 4481 | 4562 | const zcu = pt.zcu; |
| 4482 | 4563 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -4577,7 +4658,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 4577 | 4658 | return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 4578 | 4659 | } |
| 4579 | 4660 | |
| 4580 | | fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 4661 | fn airSubSat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 4581 | 4662 | const pt = self.pt; |
| 4582 | 4663 | const zcu = pt.zcu; |
| 4583 | 4664 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -4671,7 +4752,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 4671 | 4752 | return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 4672 | 4753 | } |
| 4673 | 4754 | |
| 4674 | | fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 4755 | fn airMulSat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 4675 | 4756 | const pt = self.pt; |
| 4676 | 4757 | const zcu = pt.zcu; |
| 4677 | 4758 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -4715,7 +4796,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 4715 | 4796 | if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 4716 | 4797 | .{ ._, .mov }, |
| 4717 | 4798 | tmp_reg, |
| 4718 | | try mat_lhs_mcv.address().offset(8).deref().mem(self, .qword), |
| 4799 | try mat_lhs_mcv.address().offset(8).deref().mem(self, .{ .size = .qword }), |
| 4719 | 4800 | ) else try self.asmRegisterRegister( |
| 4720 | 4801 | .{ ._, .mov }, |
| 4721 | 4802 | tmp_reg, |
| ... | ... | @@ -4739,7 +4820,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 4739 | 4820 | if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 4740 | 4821 | .{ ._, .xor }, |
| 4741 | 4822 | tmp_reg, |
| 4742 | | try mat_rhs_mcv.address().offset(8).deref().mem(self, .qword), |
| 4823 | try mat_rhs_mcv.address().offset(8).deref().mem(self, .{ .size = .qword }), |
| 4743 | 4824 | ) else try self.asmRegisterRegister( |
| 4744 | 4825 | .{ ._, .xor }, |
| 4745 | 4826 | tmp_reg, |
| ... | ... | @@ -4748,7 +4829,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 4748 | 4829 | |
| 4749 | 4830 | try self.asmRegisterImmediate(.{ ._r, .sa }, tmp_reg, .u(63)); |
| 4750 | 4831 | try self.asmRegister(.{ ._, .not }, tmp_reg); |
| 4751 | | try self.asmMemoryImmediate(.{ ._, .cmp }, try overflow.mem(self, .dword), .s(0)); |
| 4832 | try self.asmMemoryImmediate(.{ ._, .cmp }, try overflow.mem(self, .{ .size = .dword }), .s(0)); |
| 4752 | 4833 | try self.freeValue(overflow); |
| 4753 | 4834 | try self.asmCmovccRegisterRegister(.ne, dst_mcv.register_pair[0], tmp_reg); |
| 4754 | 4835 | try self.asmRegisterImmediate(.{ ._c, .bt }, tmp_reg, .u(63)); |
| ... | ... | @@ -4818,7 +4899,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 4818 | 4899 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 4819 | 4900 | } |
| 4820 | 4901 | |
| 4821 | | fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 4902 | fn airAddSubWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 4822 | 4903 | const pt = self.pt; |
| 4823 | 4904 | const zcu = pt.zcu; |
| 4824 | 4905 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -4883,7 +4964,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 4883 | 4964 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 4884 | 4965 | } |
| 4885 | 4966 | |
| 4886 | | fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 4967 | fn airShlWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 4887 | 4968 | const pt = self.pt; |
| 4888 | 4969 | const zcu = pt.zcu; |
| 4889 | 4970 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -4961,7 +5042,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 4961 | 5042 | } |
| 4962 | 5043 | |
| 4963 | 5044 | fn genSetFrameTruncatedOverflowCompare( |
| 4964 | | self: *Self, |
| 5045 | self: *CodeGen, |
| 4965 | 5046 | tuple_ty: Type, |
| 4966 | 5047 | frame_index: FrameIndex, |
| 4967 | 5048 | src_mcv: MCValue, |
| ... | ... | @@ -5039,7 +5120,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 5039 | 5120 | ); |
| 5040 | 5121 | } |
| 5041 | 5122 | |
| 5042 | | fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 5123 | fn airMulWithOverflow(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5043 | 5124 | const pt = self.pt; |
| 5044 | 5125 | const zcu = pt.zcu; |
| 5045 | 5126 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -5214,7 +5295,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 5214 | 5295 | ); |
| 5215 | 5296 | try self.asmMemoryImmediate( |
| 5216 | 5297 | .{ ._, .cmp }, |
| 5217 | | try overflow.mem(self, self.memSize(Type.c_int)), |
| 5298 | try overflow.mem(self, .{ .size = self.memSize(Type.c_int) }), |
| 5218 | 5299 | .s(0), |
| 5219 | 5300 | ); |
| 5220 | 5301 | try self.genSetMem( |
| ... | ... | @@ -5270,7 +5351,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 5270 | 5351 | if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 5271 | 5352 | .{ ._, .mov }, |
| 5272 | 5353 | .rax, |
| 5273 | | try mat_lhs_mcv.mem(self, .qword), |
| 5354 | try mat_lhs_mcv.mem(self, .{ .size = .qword }), |
| 5274 | 5355 | ) else try self.asmRegisterRegister( |
| 5275 | 5356 | .{ ._, .mov }, |
| 5276 | 5357 | .rax, |
| ... | ... | @@ -5279,7 +5360,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 5279 | 5360 | if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 5280 | 5361 | .{ ._, .mov }, |
| 5281 | 5362 | tmp_regs[0], |
| 5282 | | try mat_rhs_mcv.address().offset(8).deref().mem(self, .qword), |
| 5363 | try mat_rhs_mcv.address().offset(8).deref().mem(self, .{ .size = .qword }), |
| 5283 | 5364 | ) else try self.asmRegisterRegister( |
| 5284 | 5365 | .{ ._, .mov }, |
| 5285 | 5366 | tmp_regs[0], |
| ... | ... | @@ -5290,7 +5371,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 5290 | 5371 | try self.asmRegisterRegister(.{ .i_, .mul }, tmp_regs[0], .rax); |
| 5291 | 5372 | try self.asmSetccRegister(.o, tmp_regs[2].to8()); |
| 5292 | 5373 | if (mat_rhs_mcv.isMemory()) |
| 5293 | | try self.asmMemory(.{ ._, .mul }, try mat_rhs_mcv.mem(self, .qword)) |
| 5374 | try self.asmMemory(.{ ._, .mul }, try mat_rhs_mcv.mem(self, .{ .size = .qword })) |
| 5294 | 5375 | else |
| 5295 | 5376 | try self.asmRegister(.{ ._, .mul }, mat_rhs_mcv.register_pair[0]); |
| 5296 | 5377 | try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_regs[0]); |
| ... | ... | @@ -5299,7 +5380,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 5299 | 5380 | if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 5300 | 5381 | .{ ._, .mov }, |
| 5301 | 5382 | tmp_regs[0], |
| 5302 | | try mat_lhs_mcv.address().offset(8).deref().mem(self, .qword), |
| 5383 | try mat_lhs_mcv.address().offset(8).deref().mem(self, .{ .size = .qword }), |
| 5303 | 5384 | ) else try self.asmRegisterRegister( |
| 5304 | 5385 | .{ ._, .mov }, |
| 5305 | 5386 | tmp_regs[0], |
| ... | ... | @@ -5316,7 +5397,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 5316 | 5397 | if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 5317 | 5398 | .{ .i_, .mul }, |
| 5318 | 5399 | tmp_regs[0], |
| 5319 | | try mat_rhs_mcv.mem(self, .qword), |
| 5400 | try mat_rhs_mcv.mem(self, .{ .size = .qword }), |
| 5320 | 5401 | ) else try self.asmRegisterRegister( |
| 5321 | 5402 | .{ .i_, .mul }, |
| 5322 | 5403 | tmp_regs[0], |
| ... | ... | @@ -5416,7 +5497,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 5416 | 5497 | /// Generates signed or unsigned integer multiplication/division. |
| 5417 | 5498 | /// Clobbers .rax and .rdx registers. |
| 5418 | 5499 | /// Quotient is saved in .rax and remainder in .rdx. |
| 5419 | | fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue, rhs: MCValue) !void { |
| 5500 | fn genIntMulDivOpMir(self: *CodeGen, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue, rhs: MCValue) !void { |
| 5420 | 5501 | const pt = self.pt; |
| 5421 | 5502 | const abi_size: u32 = @intCast(ty.abiSize(pt.zcu)); |
| 5422 | 5503 | const bit_size: u32 = @intCast(self.regBitSize(ty)); |
| ... | ... | @@ -5455,7 +5536,10 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue |
| 5455 | 5536 | }; |
| 5456 | 5537 | switch (mat_rhs) { |
| 5457 | 5538 | .register => |reg| try self.asmRegister(tag, registerAlias(reg, abi_size)), |
| 5458 | | .memory, .indirect, .load_frame => try self.asmMemory(tag, try mat_rhs.mem(self, .fromSize(abi_size))), |
| 5539 | .memory, .indirect, .load_frame => try self.asmMemory( |
| 5540 | tag, |
| 5541 | try mat_rhs.mem(self, .{ .size = .fromSize(abi_size) }), |
| 5542 | ), |
| 5459 | 5543 | else => unreachable, |
| 5460 | 5544 | } |
| 5461 | 5545 | if (tag[1] == .div and bit_size == 8) try self.asmRegisterRegister(.{ ._, .mov }, .dl, .ah); |
| ... | ... | @@ -5463,7 +5547,7 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue |
| 5463 | 5547 | |
| 5464 | 5548 | /// Always returns a register. |
| 5465 | 5549 | /// Clobbers .rax and .rdx registers. |
| 5466 | | fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCValue { |
| 5550 | fn genInlineIntDivFloor(self: *CodeGen, ty: Type, lhs: MCValue, rhs: MCValue) !MCValue { |
| 5467 | 5551 | const pt = self.pt; |
| 5468 | 5552 | const zcu = pt.zcu; |
| 5469 | 5553 | const abi_size: u32 = @intCast(ty.abiSize(zcu)); |
| ... | ... | @@ -5516,7 +5600,7 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa |
| 5516 | 5600 | return MCValue{ .register = divisor }; |
| 5517 | 5601 | } |
| 5518 | 5602 | |
| 5519 | | fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| 5603 | fn airShlShrBinOp(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5520 | 5604 | const pt = self.pt; |
| 5521 | 5605 | const zcu = pt.zcu; |
| 5522 | 5606 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -5784,14 +5868,14 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| 5784 | 5868 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 5785 | 5869 | } |
| 5786 | 5870 | |
| 5787 | | fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { |
| 5871 | fn airShlSat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5788 | 5872 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 5789 | 5873 | _ = bin_op; |
| 5790 | 5874 | return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch}); |
| 5791 | 5875 | //return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 5792 | 5876 | } |
| 5793 | 5877 | |
| 5794 | | fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 5878 | fn airOptionalPayload(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5795 | 5879 | const zcu = self.pt.zcu; |
| 5796 | 5880 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5797 | 5881 | const result: MCValue = result: { |
| ... | ... | @@ -5824,7 +5908,7 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 5824 | 5908 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 5825 | 5909 | } |
| 5826 | 5910 | |
| 5827 | | fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 5911 | fn airOptionalPayloadPtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5828 | 5912 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5829 | 5913 | |
| 5830 | 5914 | const dst_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -5837,7 +5921,7 @@ fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 5837 | 5921 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); |
| 5838 | 5922 | } |
| 5839 | 5923 | |
| 5840 | | fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 5924 | fn airOptionalPayloadPtrSet(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5841 | 5925 | const pt = self.pt; |
| 5842 | 5926 | const zcu = pt.zcu; |
| 5843 | 5927 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -5878,7 +5962,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 5878 | 5962 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 5879 | 5963 | } |
| 5880 | 5964 | |
| 5881 | | fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 5965 | fn airUnwrapErrUnionErr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5882 | 5966 | const pt = self.pt; |
| 5883 | 5967 | const zcu = pt.zcu; |
| 5884 | 5968 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -5923,7 +6007,7 @@ fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 5923 | 6007 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 5924 | 6008 | } |
| 5925 | 6009 | |
| 5926 | | fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 6010 | fn airUnwrapErrUnionPayload(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5927 | 6011 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5928 | 6012 | const operand_ty = self.typeOf(ty_op.operand); |
| 5929 | 6013 | const operand = try self.resolveInst(ty_op.operand); |
| ... | ... | @@ -5932,7 +6016,7 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 5932 | 6016 | } |
| 5933 | 6017 | |
| 5934 | 6018 | // *(E!T) -> E |
| 5935 | | fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 6019 | fn airUnwrapErrUnionErrPtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5936 | 6020 | const pt = self.pt; |
| 5937 | 6021 | const zcu = pt.zcu; |
| 5938 | 6022 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -5972,7 +6056,7 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 5972 | 6056 | } |
| 5973 | 6057 | |
| 5974 | 6058 | // *(E!T) -> *T |
| 5975 | | fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 6059 | fn airUnwrapErrUnionPayloadPtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5976 | 6060 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5977 | 6061 | const operand_ty = self.typeOf(ty_op.operand); |
| 5978 | 6062 | const operand = try self.resolveInst(ty_op.operand); |
| ... | ... | @@ -5980,7 +6064,7 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 5980 | 6064 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 5981 | 6065 | } |
| 5982 | 6066 | |
| 5983 | | fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 6067 | fn airErrUnionPayloadPtrSet(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 5984 | 6068 | const pt = self.pt; |
| 5985 | 6069 | const zcu = pt.zcu; |
| 5986 | 6070 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -6037,7 +6121,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 6037 | 6121 | } |
| 6038 | 6122 | |
| 6039 | 6123 | fn genUnwrapErrUnionPayloadMir( |
| 6040 | | self: *Self, |
| 6124 | self: *CodeGen, |
| 6041 | 6125 | maybe_inst: ?Air.Inst.Index, |
| 6042 | 6126 | err_union_ty: Type, |
| 6043 | 6127 | err_union: MCValue, |
| ... | ... | @@ -6087,7 +6171,7 @@ fn genUnwrapErrUnionPayloadMir( |
| 6087 | 6171 | } |
| 6088 | 6172 | |
| 6089 | 6173 | fn genUnwrapErrUnionPayloadPtrMir( |
| 6090 | | self: *Self, |
| 6174 | self: *CodeGen, |
| 6091 | 6175 | maybe_inst: ?Air.Inst.Index, |
| 6092 | 6176 | ptr_ty: Type, |
| 6093 | 6177 | ptr_mcv: MCValue, |
| ... | ... | @@ -6110,23 +6194,23 @@ fn genUnwrapErrUnionPayloadPtrMir( |
| 6110 | 6194 | return result; |
| 6111 | 6195 | } |
| 6112 | 6196 | |
| 6113 | | fn airErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { |
| 6197 | fn airErrReturnTrace(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6114 | 6198 | _ = inst; |
| 6115 | 6199 | return self.fail("TODO implement airErrReturnTrace for {}", .{self.target.cpu.arch}); |
| 6116 | 6200 | //return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 6117 | 6201 | } |
| 6118 | 6202 | |
| 6119 | | fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { |
| 6203 | fn airSetErrReturnTrace(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6120 | 6204 | _ = inst; |
| 6121 | 6205 | return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); |
| 6122 | 6206 | } |
| 6123 | 6207 | |
| 6124 | | fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void { |
| 6208 | fn airSaveErrReturnTraceIndex(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6125 | 6209 | _ = inst; |
| 6126 | 6210 | return self.fail("TODO implement airSaveErrReturnTraceIndex for {}", .{self.target.cpu.arch}); |
| 6127 | 6211 | } |
| 6128 | 6212 | |
| 6129 | | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 6213 | fn airWrapOptional(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6130 | 6214 | const pt = self.pt; |
| 6131 | 6215 | const zcu = pt.zcu; |
| 6132 | 6216 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -6181,7 +6265,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 6181 | 6265 | } |
| 6182 | 6266 | |
| 6183 | 6267 | /// T to E!T |
| 6184 | | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 6268 | fn airWrapErrUnionPayload(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6185 | 6269 | const pt = self.pt; |
| 6186 | 6270 | const zcu = pt.zcu; |
| 6187 | 6271 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -6205,7 +6289,7 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 6205 | 6289 | } |
| 6206 | 6290 | |
| 6207 | 6291 | /// E to E!T |
| 6208 | | fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 6292 | fn airWrapErrUnionErr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6209 | 6293 | const pt = self.pt; |
| 6210 | 6294 | const zcu = pt.zcu; |
| 6211 | 6295 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -6228,7 +6312,7 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 6228 | 6312 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 6229 | 6313 | } |
| 6230 | 6314 | |
| 6231 | | fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { |
| 6315 | fn airSlicePtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6232 | 6316 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6233 | 6317 | const result = result: { |
| 6234 | 6318 | const src_mcv = try self.resolveInst(ty_op.operand); |
| ... | ... | @@ -6251,7 +6335,7 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { |
| 6251 | 6335 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 6252 | 6336 | } |
| 6253 | 6337 | |
| 6254 | | fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 6338 | fn airSliceLen(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6255 | 6339 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6256 | 6340 | const result = result: { |
| 6257 | 6341 | const src_mcv = try self.resolveInst(ty_op.operand); |
| ... | ... | @@ -6279,7 +6363,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 6279 | 6363 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 6280 | 6364 | } |
| 6281 | 6365 | |
| 6282 | | fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 6366 | fn airPtrSliceLenPtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6283 | 6367 | const pt = self.pt; |
| 6284 | 6368 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6285 | 6369 | |
| ... | ... | @@ -6314,7 +6398,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 6314 | 6398 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); |
| 6315 | 6399 | } |
| 6316 | 6400 | |
| 6317 | | fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 6401 | fn airPtrSlicePtrPtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6318 | 6402 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6319 | 6403 | |
| 6320 | 6404 | const dst_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -6327,7 +6411,7 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 6327 | 6411 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); |
| 6328 | 6412 | } |
| 6329 | 6413 | |
| 6330 | | fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Register { |
| 6414 | fn elemOffset(self: *CodeGen, index_ty: Type, index: MCValue, elem_size: u64) !Register { |
| 6331 | 6415 | const reg: Register = blk: { |
| 6332 | 6416 | switch (index) { |
| 6333 | 6417 | .immediate => |imm| { |
| ... | ... | @@ -6347,7 +6431,7 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi |
| 6347 | 6431 | return reg; |
| 6348 | 6432 | } |
| 6349 | 6433 | |
| 6350 | | fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 6434 | fn genSliceElemPtr(self: *CodeGen, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 6351 | 6435 | const pt = self.pt; |
| 6352 | 6436 | const zcu = pt.zcu; |
| 6353 | 6437 | const slice_ty = self.typeOf(lhs); |
| ... | ... | @@ -6384,7 +6468,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 6384 | 6468 | return MCValue{ .register = addr_reg.to64() }; |
| 6385 | 6469 | } |
| 6386 | 6470 | |
| 6387 | | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 6471 | fn airSliceElemVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6388 | 6472 | const pt = self.pt; |
| 6389 | 6473 | const zcu = pt.zcu; |
| 6390 | 6474 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -6403,14 +6487,14 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 6403 | 6487 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 6404 | 6488 | } |
| 6405 | 6489 | |
| 6406 | | fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 6490 | fn airSliceElemPtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6407 | 6491 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 6408 | 6492 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 6409 | 6493 | const dst_mcv = try self.genSliceElemPtr(extra.lhs, extra.rhs); |
| 6410 | 6494 | return self.finishAir(inst, dst_mcv, .{ extra.lhs, extra.rhs, .none }); |
| 6411 | 6495 | } |
| 6412 | 6496 | |
| 6413 | | fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 6497 | fn airArrayElemVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6414 | 6498 | const pt = self.pt; |
| 6415 | 6499 | const zcu = pt.zcu; |
| 6416 | 6500 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -6463,7 +6547,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 6463 | 6547 | }, |
| 6464 | 6548 | .load_frame => try self.asmMemoryRegister( |
| 6465 | 6549 | .{ ._, .bt }, |
| 6466 | | try array_mcv.mem(self, .qword), |
| 6550 | try array_mcv.mem(self, .{ .size = .qword }), |
| 6467 | 6551 | index_reg.to64(), |
| 6468 | 6552 | ), |
| 6469 | 6553 | .memory, .load_symbol, .load_direct, .load_got, .load_tlv => try self.asmMemoryRegister( |
| ... | ... | @@ -6540,7 +6624,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 6540 | 6624 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 6541 | 6625 | } |
| 6542 | 6626 | |
| 6543 | | fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 6627 | fn airPtrElemVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6544 | 6628 | const pt = self.pt; |
| 6545 | 6629 | const zcu = pt.zcu; |
| 6546 | 6630 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -6591,7 +6675,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 6591 | 6675 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 6592 | 6676 | } |
| 6593 | 6677 | |
| 6594 | | fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 6678 | fn airPtrElemPtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6595 | 6679 | const pt = self.pt; |
| 6596 | 6680 | const zcu = pt.zcu; |
| 6597 | 6681 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -6637,7 +6721,7 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 6637 | 6721 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); |
| 6638 | 6722 | } |
| 6639 | 6723 | |
| 6640 | | fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 6724 | fn airSetUnionTag(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6641 | 6725 | const pt = self.pt; |
| 6642 | 6726 | const zcu = pt.zcu; |
| 6643 | 6727 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -6682,7 +6766,7 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 6682 | 6766 | return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 6683 | 6767 | } |
| 6684 | 6768 | |
| 6685 | | fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 6769 | fn airGetUnionTag(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6686 | 6770 | const zcu = self.pt.zcu; |
| 6687 | 6771 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6688 | 6772 | |
| ... | ... | @@ -6739,7 +6823,7 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 6739 | 6823 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); |
| 6740 | 6824 | } |
| 6741 | 6825 | |
| 6742 | | fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 6826 | fn airClz(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6743 | 6827 | const pt = self.pt; |
| 6744 | 6828 | const zcu = pt.zcu; |
| 6745 | 6829 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -6936,7 +7020,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 6936 | 7020 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 6937 | 7021 | } |
| 6938 | 7022 | |
| 6939 | | fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 7023 | fn airCtz(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 6940 | 7024 | const pt = self.pt; |
| 6941 | 7025 | const zcu = pt.zcu; |
| 6942 | 7026 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -7098,7 +7182,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 7098 | 7182 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 7099 | 7183 | } |
| 7100 | 7184 | |
| 7101 | | fn airPopCount(self: *Self, inst: Air.Inst.Index) !void { |
| 7185 | fn airPopCount(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 7102 | 7186 | const pt = self.pt; |
| 7103 | 7187 | const zcu = pt.zcu; |
| 7104 | 7188 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -7157,7 +7241,7 @@ fn airPopCount(self: *Self, inst: Air.Inst.Index) !void { |
| 7157 | 7241 | } |
| 7158 | 7242 | |
| 7159 | 7243 | fn genPopCount( |
| 7160 | | self: *Self, |
| 7244 | self: *CodeGen, |
| 7161 | 7245 | dst_reg: Register, |
| 7162 | 7246 | src_ty: Type, |
| 7163 | 7247 | src_mcv: MCValue, |
| ... | ... | @@ -7249,7 +7333,7 @@ fn genPopCount( |
| 7249 | 7333 | } |
| 7250 | 7334 | |
| 7251 | 7335 | fn genByteSwap( |
| 7252 | | self: *Self, |
| 7336 | self: *CodeGen, |
| 7253 | 7337 | inst: Air.Inst.Index, |
| 7254 | 7338 | src_ty: Type, |
| 7255 | 7339 | src_mcv: MCValue, |
| ... | ... | @@ -7308,7 +7392,7 @@ fn genByteSwap( |
| 7308 | 7392 | try self.asmRegisterMemory( |
| 7309 | 7393 | .{ ._, if (has_movbe) .movbe else .mov }, |
| 7310 | 7394 | dst_reg.to64(), |
| 7311 | | try src_mcv.address().offset(@intCast(limb_index * 8)).deref().mem(self, .qword), |
| 7395 | try src_mcv.address().offset(@intCast(limb_index * 8)).deref().mem(self, .{ .size = .qword }), |
| 7312 | 7396 | ); |
| 7313 | 7397 | if (!has_movbe) try self.asmRegister(.{ ._, .bswap }, dst_reg.to64()); |
| 7314 | 7398 | } else { |
| ... | ... | @@ -7414,7 +7498,7 @@ fn genByteSwap( |
| 7414 | 7498 | return dst_mcv; |
| 7415 | 7499 | } |
| 7416 | 7500 | |
| 7417 | | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 7501 | fn airByteSwap(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 7418 | 7502 | const pt = self.pt; |
| 7419 | 7503 | const zcu = pt.zcu; |
| 7420 | 7504 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -7437,7 +7521,7 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 7437 | 7521 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); |
| 7438 | 7522 | } |
| 7439 | 7523 | |
| 7440 | | fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { |
| 7524 | fn airBitReverse(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 7441 | 7525 | const pt = self.pt; |
| 7442 | 7526 | const zcu = pt.zcu; |
| 7443 | 7527 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -7560,7 +7644,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { |
| 7560 | 7644 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); |
| 7561 | 7645 | } |
| 7562 | 7646 | |
| 7563 | | fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type) !void { |
| 7647 | fn floatSign(self: *CodeGen, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type) !void { |
| 7564 | 7648 | const pt = self.pt; |
| 7565 | 7649 | const zcu = pt.zcu; |
| 7566 | 7650 | const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)]; |
| ... | ... | @@ -7623,7 +7707,7 @@ fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type) |
| 7623 | 7707 | else => unreachable, |
| 7624 | 7708 | }); |
| 7625 | 7709 | const sign_mem: Memory = if (sign_mcv.isMemory()) |
| 7626 | | try sign_mcv.mem(self, .fromSize(abi_size)) |
| 7710 | try sign_mcv.mem(self, .{ .size = .fromSize(abi_size) }) |
| 7627 | 7711 | else |
| 7628 | 7712 | .{ |
| 7629 | 7713 | .base = .{ .reg = try self.copyToTmpRegister(Type.usize, sign_mcv.address()) }, |
| ... | ... | @@ -7688,7 +7772,7 @@ fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type) |
| 7688 | 7772 | return self.finishAir(inst, result, .{ operand, .none, .none }); |
| 7689 | 7773 | } |
| 7690 | 7774 | |
| 7691 | | fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { |
| 7775 | fn airFloatSign(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 7692 | 7776 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 7693 | 7777 | const ty = self.typeOf(un_op); |
| 7694 | 7778 | return self.floatSign(inst, un_op, ty); |
| ... | ... | @@ -7713,7 +7797,7 @@ const RoundMode = packed struct(u5) { |
| 7713 | 7797 | } = .normal, |
| 7714 | 7798 | }; |
| 7715 | 7799 | |
| 7716 | | fn airRound(self: *Self, inst: Air.Inst.Index, mode: RoundMode) !void { |
| 7800 | fn airRound(self: *CodeGen, inst: Air.Inst.Index, mode: RoundMode) !void { |
| 7717 | 7801 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 7718 | 7802 | const ty = self.typeOf(un_op); |
| 7719 | 7803 | |
| ... | ... | @@ -7737,7 +7821,7 @@ fn airRound(self: *Self, inst: Air.Inst.Index, mode: RoundMode) !void { |
| 7737 | 7821 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 7738 | 7822 | } |
| 7739 | 7823 | |
| 7740 | | fn getRoundTag(self: *Self, ty: Type) ?Mir.Inst.FixedTag { |
| 7824 | fn getRoundTag(self: *CodeGen, ty: Type) ?Mir.Inst.FixedTag { |
| 7741 | 7825 | const pt = self.pt; |
| 7742 | 7826 | const zcu = pt.zcu; |
| 7743 | 7827 | return if (self.hasFeature(.sse4_1)) switch (ty.zigTypeTag(zcu)) { |
| ... | ... | @@ -7770,7 +7854,7 @@ fn getRoundTag(self: *Self, ty: Type) ?Mir.Inst.FixedTag { |
| 7770 | 7854 | } else null; |
| 7771 | 7855 | } |
| 7772 | 7856 | |
| 7773 | | fn genRoundLibcall(self: *Self, ty: Type, src_mcv: MCValue, mode: RoundMode) !MCValue { |
| 7857 | fn genRoundLibcall(self: *CodeGen, ty: Type, src_mcv: MCValue, mode: RoundMode) !MCValue { |
| 7774 | 7858 | const pt = self.pt; |
| 7775 | 7859 | const zcu = pt.zcu; |
| 7776 | 7860 | if (self.getRoundTag(ty)) |_| return .none; |
| ... | ... | @@ -7795,7 +7879,7 @@ fn genRoundLibcall(self: *Self, ty: Type, src_mcv: MCValue, mode: RoundMode) !MC |
| 7795 | 7879 | } }, &.{ty}, &.{src_mcv}); |
| 7796 | 7880 | } |
| 7797 | 7881 | |
| 7798 | | fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: RoundMode) !void { |
| 7882 | fn genRound(self: *CodeGen, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: RoundMode) !void { |
| 7799 | 7883 | const pt = self.pt; |
| 7800 | 7884 | const mir_tag = self.getRoundTag(ty) orelse { |
| 7801 | 7885 | const result = try self.genRoundLibcall(ty, src_mcv, mode); |
| ... | ... | @@ -7808,7 +7892,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: Ro |
| 7808 | 7892 | mir_tag, |
| 7809 | 7893 | dst_alias, |
| 7810 | 7894 | dst_alias, |
| 7811 | | try src_mcv.mem(self, .fromSize(abi_size)), |
| 7895 | try src_mcv.mem(self, .{ .size = .fromSize(abi_size) }), |
| 7812 | 7896 | .u(@as(u5, @bitCast(mode))), |
| 7813 | 7897 | ) else try self.asmRegisterRegisterRegisterImmediate( |
| 7814 | 7898 | mir_tag, |
| ... | ... | @@ -7823,7 +7907,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: Ro |
| 7823 | 7907 | else => if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate( |
| 7824 | 7908 | mir_tag, |
| 7825 | 7909 | dst_alias, |
| 7826 | | try src_mcv.mem(self, .fromSize(abi_size)), |
| 7910 | try src_mcv.mem(self, .{ .size = .fromSize(abi_size) }), |
| 7827 | 7911 | .u(@as(u5, @bitCast(mode))), |
| 7828 | 7912 | ) else try self.asmRegisterRegisterImmediate( |
| 7829 | 7913 | mir_tag, |
| ... | ... | @@ -7837,7 +7921,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: Ro |
| 7837 | 7921 | } |
| 7838 | 7922 | } |
| 7839 | 7923 | |
| 7840 | | fn airAbs(self: *Self, inst: Air.Inst.Index) !void { |
| 7924 | fn airAbs(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 7841 | 7925 | const pt = self.pt; |
| 7842 | 7926 | const zcu = pt.zcu; |
| 7843 | 7927 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -7865,7 +7949,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void { |
| 7865 | 7949 | .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory( |
| 7866 | 7950 | .l, |
| 7867 | 7951 | registerAlias(dst_mcv.register, cmov_abi_size), |
| 7868 | | try src_mcv.mem(self, .fromSize(cmov_abi_size)), |
| 7952 | try src_mcv.mem(self, .{ .size = .fromSize(cmov_abi_size) }), |
| 7869 | 7953 | ), |
| 7870 | 7954 | else => { |
| 7871 | 7955 | const val_reg = try self.copyToTmpRegister(ty, src_mcv); |
| ... | ... | @@ -7931,7 +8015,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void { |
| 7931 | 8015 | |
| 7932 | 8016 | try self.asmMemoryImmediate( |
| 7933 | 8017 | .{ ._, .cmp }, |
| 7934 | | try dst_mcv.address().offset((limb_len - 1) * 8).deref().mem(self, .qword), |
| 8018 | try dst_mcv.address().offset((limb_len - 1) * 8).deref().mem(self, .{ .size = .qword }), |
| 7935 | 8019 | .u(0), |
| 7936 | 8020 | ); |
| 7937 | 8021 | const positive = try self.asmJccReloc(.ns, undefined); |
| ... | ... | @@ -8024,7 +8108,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void { |
| 8024 | 8108 | if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 8025 | 8109 | mir_tag, |
| 8026 | 8110 | dst_alias, |
| 8027 | | try src_mcv.mem(self, self.memSize(ty)), |
| 8111 | try src_mcv.mem(self, .{ .size = self.memSize(ty) }), |
| 8028 | 8112 | ) else try self.asmRegisterRegister( |
| 8029 | 8113 | mir_tag, |
| 8030 | 8114 | dst_alias, |
| ... | ... | @@ -8038,7 +8122,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void { |
| 8038 | 8122 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 8039 | 8123 | } |
| 8040 | 8124 | |
| 8041 | | fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 8125 | fn airSqrt(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 8042 | 8126 | const pt = self.pt; |
| 8043 | 8127 | const zcu = pt.zcu; |
| 8044 | 8128 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| ... | ... | @@ -8131,9 +8215,9 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 8131 | 8215 | if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 8132 | 8216 | .{ .v_ps, .cvtph2 }, |
| 8133 | 8217 | wide_reg, |
| 8134 | | try src_mcv.mem(self, .fromSize( |
| 8218 | try src_mcv.mem(self, .{ .size = .fromSize( |
| 8135 | 8219 | @intCast(@divExact(wide_reg.bitSize(), 16)), |
| 8136 | | )), |
| 8220 | ) }), |
| 8137 | 8221 | ) else try self.asmRegisterRegister( |
| 8138 | 8222 | .{ .v_ps, .cvtph2 }, |
| 8139 | 8223 | wide_reg, |
| ... | ... | @@ -8177,7 +8261,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 8177 | 8261 | mir_tag, |
| 8178 | 8262 | dst_reg, |
| 8179 | 8263 | dst_reg, |
| 8180 | | try src_mcv.mem(self, .fromSize(abi_size)), |
| 8264 | try src_mcv.mem(self, .{ .size = .fromSize(abi_size) }), |
| 8181 | 8265 | ) else try self.asmRegisterRegisterRegister( |
| 8182 | 8266 | mir_tag, |
| 8183 | 8267 | dst_reg, |
| ... | ... | @@ -8190,7 +8274,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 8190 | 8274 | else => if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 8191 | 8275 | mir_tag, |
| 8192 | 8276 | dst_reg, |
| 8193 | | try src_mcv.mem(self, .fromSize(abi_size)), |
| 8277 | try src_mcv.mem(self, .{ .size = .fromSize(abi_size) }), |
| 8194 | 8278 | ) else try self.asmRegisterRegister( |
| 8195 | 8279 | mir_tag, |
| 8196 | 8280 | dst_reg, |
| ... | ... | @@ -8205,7 +8289,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 8205 | 8289 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 8206 | 8290 | } |
| 8207 | 8291 | |
| 8208 | | fn airUnaryMath(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 8292 | fn airUnaryMath(self: *CodeGen, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 8209 | 8293 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 8210 | 8294 | const ty = self.typeOf(un_op); |
| 8211 | 8295 | var callee_buf: ["__round?".len]u8 = undefined; |
| ... | ... | @@ -8234,7 +8318,7 @@ fn airUnaryMath(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 8234 | 8318 | } |
| 8235 | 8319 | |
| 8236 | 8320 | fn reuseOperand( |
| 8237 | | self: *Self, |
| 8321 | self: *CodeGen, |
| 8238 | 8322 | inst: Air.Inst.Index, |
| 8239 | 8323 | operand: Air.Inst.Ref, |
| 8240 | 8324 | op_index: Liveness.OperandInt, |
| ... | ... | @@ -8244,7 +8328,7 @@ fn reuseOperand( |
| 8244 | 8328 | } |
| 8245 | 8329 | |
| 8246 | 8330 | fn reuseOperandAdvanced( |
| 8247 | | self: *Self, |
| 8331 | self: *CodeGen, |
| 8248 | 8332 | inst: Air.Inst.Index, |
| 8249 | 8333 | operand: Air.Inst.Ref, |
| 8250 | 8334 | op_index: Liveness.OperandInt, |
| ... | ... | @@ -8282,7 +8366,7 @@ fn reuseOperandAdvanced( |
| 8282 | 8366 | return true; |
| 8283 | 8367 | } |
| 8284 | 8368 | |
| 8285 | | fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerError!void { |
| 8369 | fn packedLoad(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerError!void { |
| 8286 | 8370 | const pt = self.pt; |
| 8287 | 8371 | const zcu = pt.zcu; |
| 8288 | 8372 | |
| ... | ... | @@ -8390,7 +8474,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn |
| 8390 | 8474 | try self.genCopy(val_ty, dst_mcv, .{ .register = dst_reg }, .{}); |
| 8391 | 8475 | } |
| 8392 | 8476 | |
| 8393 | | fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerError!void { |
| 8477 | fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerError!void { |
| 8394 | 8478 | const pt = self.pt; |
| 8395 | 8479 | const zcu = pt.zcu; |
| 8396 | 8480 | const dst_ty = ptr_ty.childType(zcu); |
| ... | ... | @@ -8433,7 +8517,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro |
| 8433 | 8517 | } |
| 8434 | 8518 | } |
| 8435 | 8519 | |
| 8436 | | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 8520 | fn airLoad(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 8437 | 8521 | const pt = self.pt; |
| 8438 | 8522 | const zcu = pt.zcu; |
| 8439 | 8523 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -8492,7 +8576,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 8492 | 8576 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 8493 | 8577 | } |
| 8494 | 8578 | |
| 8495 | | fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerError!void { |
| 8579 | fn packedStore(self: *CodeGen, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerError!void { |
| 8496 | 8580 | const pt = self.pt; |
| 8497 | 8581 | const zcu = pt.zcu; |
| 8498 | 8582 | const ptr_info = ptr_ty.ptrInfo(zcu); |
| ... | ... | @@ -8593,7 +8677,7 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In |
| 8593 | 8677 | } |
| 8594 | 8678 | |
| 8595 | 8679 | fn store( |
| 8596 | | self: *Self, |
| 8680 | self: *CodeGen, |
| 8597 | 8681 | ptr_ty: Type, |
| 8598 | 8682 | ptr_mcv: MCValue, |
| 8599 | 8683 | src_mcv: MCValue, |
| ... | ... | @@ -8641,7 +8725,7 @@ fn store( |
| 8641 | 8725 | } |
| 8642 | 8726 | } |
| 8643 | 8727 | |
| 8644 | | fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 8728 | fn airStore(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void { |
| 8645 | 8729 | const pt = self.pt; |
| 8646 | 8730 | const zcu = pt.zcu; |
| 8647 | 8731 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -8667,20 +8751,20 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 8667 | 8751 | return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 8668 | 8752 | } |
| 8669 | 8753 | |
| 8670 | | fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 8754 | fn airStructFieldPtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 8671 | 8755 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 8672 | 8756 | const extra = self.air.extraData(Air.StructField, ty_pl.payload).data; |
| 8673 | 8757 | const result = try self.fieldPtr(inst, extra.struct_operand, extra.field_index); |
| 8674 | 8758 | return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none }); |
| 8675 | 8759 | } |
| 8676 | 8760 | |
| 8677 | | fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, field_index: u8) !void { |
| 8761 | fn airStructFieldPtrIndex(self: *CodeGen, inst: Air.Inst.Index, field_index: u8) !void { |
| 8678 | 8762 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 8679 | 8763 | const result = try self.fieldPtr(inst, ty_op.operand, field_index); |
| 8680 | 8764 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 8681 | 8765 | } |
| 8682 | 8766 | |
| 8683 | | fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, field_index: u32) !MCValue { |
| 8767 | fn fieldPtr(self: *CodeGen, inst: Air.Inst.Index, operand: Air.Inst.Ref, field_index: u32) !MCValue { |
| 8684 | 8768 | const ptr_field_ty = self.typeOfIndex(inst); |
| 8685 | 8769 | |
| 8686 | 8770 | const src_mcv = try self.resolveInst(operand); |
| ... | ... | @@ -8692,7 +8776,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, field_inde |
| 8692 | 8776 | return dst_mcv.offset(self.fieldOffset(self.typeOf(operand), ptr_field_ty, field_index)); |
| 8693 | 8777 | } |
| 8694 | 8778 | |
| 8695 | | fn fieldOffset(self: *Self, ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u32) i32 { |
| 8779 | fn fieldOffset(self: *CodeGen, ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u32) i32 { |
| 8696 | 8780 | const pt = self.pt; |
| 8697 | 8781 | const zcu = pt.zcu; |
| 8698 | 8782 | const agg_ty = ptr_agg_ty.childType(zcu); |
| ... | ... | @@ -8704,7 +8788,7 @@ fn fieldOffset(self: *Self, ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u |
| 8704 | 8788 | }; |
| 8705 | 8789 | } |
| 8706 | 8790 | |
| 8707 | | fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 8791 | fn airStructFieldVal(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 8708 | 8792 | const pt = self.pt; |
| 8709 | 8793 | const zcu = pt.zcu; |
| 8710 | 8794 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -8993,7 +9077,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 8993 | 9077 | return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none }); |
| 8994 | 9078 | } |
| 8995 | 9079 | |
| 8996 | | fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 9080 | fn airFieldParentPtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 8997 | 9081 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 8998 | 9082 | const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; |
| 8999 | 9083 | |
| ... | ... | @@ -9008,7 +9092,7 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 9008 | 9092 | return self.finishAir(inst, result, .{ extra.field_ptr, .none, .none }); |
| 9009 | 9093 | } |
| 9010 | 9094 | |
| 9011 | | fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: Air.Inst.Ref) !MCValue { |
| 9095 | fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: Air.Inst.Ref) !MCValue { |
| 9012 | 9096 | const pt = self.pt; |
| 9013 | 9097 | const zcu = pt.zcu; |
| 9014 | 9098 | const src_ty = self.typeOf(src_air); |
| ... | ... | @@ -9097,7 +9181,7 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: |
| 9097 | 9181 | return dst_mcv; |
| 9098 | 9182 | } |
| 9099 | 9183 | |
| 9100 | | fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MCValue) !void { |
| 9184 | fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MCValue) !void { |
| 9101 | 9185 | const pt = self.pt; |
| 9102 | 9186 | const abi_size: u32 = @intCast(dst_ty.abiSize(pt.zcu)); |
| 9103 | 9187 | if (abi_size > 8) return self.fail("TODO implement {} for {}", .{ mir_tag, dst_ty.fmt(pt) }); |
| ... | ... | @@ -9133,14 +9217,14 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MC |
| 9133 | 9217 | }, |
| 9134 | 9218 | .indirect, .load_frame => try self.asmMemory( |
| 9135 | 9219 | mir_tag, |
| 9136 | | try dst_mcv.mem(self, .fromSize(abi_size)), |
| 9220 | try dst_mcv.mem(self, .{ .size = .fromSize(abi_size) }), |
| 9137 | 9221 | ), |
| 9138 | 9222 | } |
| 9139 | 9223 | } |
| 9140 | 9224 | |
| 9141 | 9225 | /// Clobbers .rcx for non-immediate shift value. |
| 9142 | 9226 | fn genShiftBinOpMir( |
| 9143 | | self: *Self, |
| 9227 | self: *CodeGen, |
| 9144 | 9228 | tag: Mir.Inst.FixedTag, |
| 9145 | 9229 | lhs_ty: Type, |
| 9146 | 9230 | lhs_mcv: MCValue, |
| ... | ... | @@ -9773,7 +9857,7 @@ fn genShiftBinOpMir( |
| 9773 | 9857 | /// Clobbers .rcx for non-immediate rhs, therefore care is needed to spill .rcx upfront. |
| 9774 | 9858 | /// Asserts .rcx is free. |
| 9775 | 9859 | fn genShiftBinOp( |
| 9776 | | self: *Self, |
| 9860 | self: *CodeGen, |
| 9777 | 9861 | air_tag: Air.Inst.Tag, |
| 9778 | 9862 | maybe_inst: ?Air.Inst.Index, |
| 9779 | 9863 | lhs_mcv: MCValue, |
| ... | ... | @@ -9832,7 +9916,7 @@ fn genShiftBinOp( |
| 9832 | 9916 | /// Clobbers .rax and .rdx therefore care is needed to spill .rax and .rdx upfront. |
| 9833 | 9917 | /// Asserts .rax and .rdx are free. |
| 9834 | 9918 | fn genMulDivBinOp( |
| 9835 | | self: *Self, |
| 9919 | self: *CodeGen, |
| 9836 | 9920 | tag: Air.Inst.Tag, |
| 9837 | 9921 | maybe_inst: ?Air.Inst.Index, |
| 9838 | 9922 | dst_ty: Type, |
| ... | ... | @@ -9891,27 +9975,27 @@ fn genMulDivBinOp( |
| 9891 | 9975 | defer self.register_manager.unlockReg(tmp_lock); |
| 9892 | 9976 | |
| 9893 | 9977 | if (mat_lhs_mcv.isMemory()) |
| 9894 | | try self.asmRegisterMemory(.{ ._, .mov }, .rax, try mat_lhs_mcv.mem(self, .qword)) |
| 9978 | try self.asmRegisterMemory(.{ ._, .mov }, .rax, try mat_lhs_mcv.mem(self, .{ .size = .qword })) |
| 9895 | 9979 | else |
| 9896 | 9980 | try self.asmRegisterRegister(.{ ._, .mov }, .rax, mat_lhs_mcv.register_pair[0]); |
| 9897 | 9981 | if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 9898 | 9982 | .{ ._, .mov }, |
| 9899 | 9983 | tmp_reg, |
| 9900 | | try mat_rhs_mcv.address().offset(8).deref().mem(self, .qword), |
| 9984 | try mat_rhs_mcv.address().offset(8).deref().mem(self, .{ .size = .qword }), |
| 9901 | 9985 | ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, mat_rhs_mcv.register_pair[1]); |
| 9902 | 9986 | try self.asmRegisterRegister(.{ .i_, .mul }, tmp_reg, .rax); |
| 9903 | 9987 | if (mat_rhs_mcv.isMemory()) |
| 9904 | | try self.asmMemory(.{ ._, .mul }, try mat_rhs_mcv.mem(self, .qword)) |
| 9988 | try self.asmMemory(.{ ._, .mul }, try mat_rhs_mcv.mem(self, .{ .size = .qword })) |
| 9905 | 9989 | else |
| 9906 | 9990 | try self.asmRegister(.{ ._, .mul }, mat_rhs_mcv.register_pair[0]); |
| 9907 | 9991 | try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_reg); |
| 9908 | 9992 | if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 9909 | 9993 | .{ ._, .mov }, |
| 9910 | 9994 | tmp_reg, |
| 9911 | | try mat_lhs_mcv.address().offset(8).deref().mem(self, .qword), |
| 9995 | try mat_lhs_mcv.address().offset(8).deref().mem(self, .{ .size = .qword }), |
| 9912 | 9996 | ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, mat_lhs_mcv.register_pair[1]); |
| 9913 | 9997 | if (mat_rhs_mcv.isMemory()) |
| 9914 | | try self.asmRegisterMemory(.{ .i_, .mul }, tmp_reg, try mat_rhs_mcv.mem(self, .qword)) |
| 9998 | try self.asmRegisterMemory(.{ .i_, .mul }, tmp_reg, try mat_rhs_mcv.mem(self, .{ .size = .qword })) |
| 9915 | 9999 | else |
| 9916 | 10000 | try self.asmRegisterRegister(.{ .i_, .mul }, tmp_reg, mat_rhs_mcv.register_pair[0]); |
| 9917 | 10001 | try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_reg); |
| ... | ... | @@ -10238,7 +10322,7 @@ fn genMulDivBinOp( |
| 10238 | 10322 | } |
| 10239 | 10323 | |
| 10240 | 10324 | fn genBinOp( |
| 10241 | | self: *Self, |
| 10325 | self: *CodeGen, |
| 10242 | 10326 | maybe_inst: ?Air.Inst.Index, |
| 10243 | 10327 | air_tag: Air.Inst.Tag, |
| 10244 | 10328 | lhs_air: Air.Inst.Ref, |
| ... | ... | @@ -10334,7 +10418,7 @@ fn genBinOp( |
| 10334 | 10418 | .{ .vp_w, .insr }, |
| 10335 | 10419 | dst_reg, |
| 10336 | 10420 | dst_reg, |
| 10337 | | try rhs_mcv.mem(self, .word), |
| 10421 | try rhs_mcv.mem(self, .{ .size = .word }), |
| 10338 | 10422 | .u(1), |
| 10339 | 10423 | ) else try self.asmRegisterRegisterRegister( |
| 10340 | 10424 | .{ .vp_, .unpcklwd }, |
| ... | ... | @@ -10359,7 +10443,7 @@ fn genBinOp( |
| 10359 | 10443 | mir_tag, |
| 10360 | 10444 | dst_reg, |
| 10361 | 10445 | dst_reg, |
| 10362 | | try src_mcv.mem(self, .fromBitSize(float_bits)), |
| 10446 | try src_mcv.mem(self, .{ .size = .fromBitSize(float_bits) }), |
| 10363 | 10447 | ) else try self.asmRegisterRegisterRegister( |
| 10364 | 10448 | mir_tag, |
| 10365 | 10449 | dst_reg, |
| ... | ... | @@ -10378,7 +10462,7 @@ fn genBinOp( |
| 10378 | 10462 | if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 10379 | 10463 | mir_tag, |
| 10380 | 10464 | dst_reg, |
| 10381 | | try src_mcv.mem(self, .fromBitSize(float_bits)), |
| 10465 | try src_mcv.mem(self, .{ .size = .fromBitSize(float_bits) }), |
| 10382 | 10466 | ) else try self.asmRegisterRegister( |
| 10383 | 10467 | mir_tag, |
| 10384 | 10468 | dst_reg, |
| ... | ... | @@ -10651,22 +10735,22 @@ fn genBinOp( |
| 10651 | 10735 | try self.asmRegisterMemory( |
| 10652 | 10736 | .{ ._, .cmp }, |
| 10653 | 10737 | dst_regs[0], |
| 10654 | | try src_mcv.mem(self, .qword), |
| 10738 | try src_mcv.mem(self, .{ .size = .qword }), |
| 10655 | 10739 | ); |
| 10656 | 10740 | try self.asmRegisterMemory( |
| 10657 | 10741 | .{ ._, .sbb }, |
| 10658 | 10742 | tmp_reg, |
| 10659 | | try src_mcv.address().offset(8).deref().mem(self, .qword), |
| 10743 | try src_mcv.address().offset(8).deref().mem(self, .{ .size = .qword }), |
| 10660 | 10744 | ); |
| 10661 | 10745 | try self.asmCmovccRegisterMemory( |
| 10662 | 10746 | cc, |
| 10663 | 10747 | dst_regs[0], |
| 10664 | | try src_mcv.mem(self, .qword), |
| 10748 | try src_mcv.mem(self, .{ .size = .qword }), |
| 10665 | 10749 | ); |
| 10666 | 10750 | try self.asmCmovccRegisterMemory( |
| 10667 | 10751 | cc, |
| 10668 | 10752 | dst_regs[1], |
| 10669 | | try src_mcv.address().offset(8).deref().mem(self, .qword), |
| 10753 | try src_mcv.address().offset(8).deref().mem(self, .{ .size = .qword }), |
| 10670 | 10754 | ); |
| 10671 | 10755 | } else { |
| 10672 | 10756 | try self.asmRegisterRegister( |
| ... | ... | @@ -10829,7 +10913,7 @@ fn genBinOp( |
| 10829 | 10913 | .{ .vp_w, .insr }, |
| 10830 | 10914 | dst_reg, |
| 10831 | 10915 | dst_reg, |
| 10832 | | try src_mcv.mem(self, .word), |
| 10916 | try src_mcv.mem(self, .{ .size = .word }), |
| 10833 | 10917 | .u(1), |
| 10834 | 10918 | ) else try self.asmRegisterRegisterRegister( |
| 10835 | 10919 | .{ .vp_, .unpcklwd }, |
| ... | ... | @@ -11275,7 +11359,7 @@ fn genBinOp( |
| 11275 | 11359 | .{ .vp_w, .insr }, |
| 11276 | 11360 | dst_reg, |
| 11277 | 11361 | dst_reg, |
| 11278 | | try src_mcv.mem(self, .word), |
| 11362 | try src_mcv.mem(self, .{ .size = .word }), |
| 11279 | 11363 | .u(1), |
| 11280 | 11364 | ) else try self.asmRegisterRegisterRegister( |
| 11281 | 11365 | .{ .vp_, .unpcklwd }, |
| ... | ... | @@ -11321,7 +11405,7 @@ fn genBinOp( |
| 11321 | 11405 | if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate( |
| 11322 | 11406 | .{ .vp_d, .insr }, |
| 11323 | 11407 | dst_reg, |
| 11324 | | try src_mcv.mem(self, .dword), |
| 11408 | try src_mcv.mem(self, .{ .size = .dword }), |
| 11325 | 11409 | .u(1), |
| 11326 | 11410 | ) else try self.asmRegisterRegisterRegister( |
| 11327 | 11411 | .{ .v_ps, .unpckl }, |
| ... | ... | @@ -11373,7 +11457,7 @@ fn genBinOp( |
| 11373 | 11457 | if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 11374 | 11458 | .{ .v_ps, .cvtph2 }, |
| 11375 | 11459 | tmp_reg, |
| 11376 | | try src_mcv.mem(self, .qword), |
| 11460 | try src_mcv.mem(self, .{ .size = .qword }), |
| 11377 | 11461 | ) else try self.asmRegisterRegister( |
| 11378 | 11462 | .{ .v_ps, .cvtph2 }, |
| 11379 | 11463 | tmp_reg, |
| ... | ... | @@ -11416,7 +11500,7 @@ fn genBinOp( |
| 11416 | 11500 | if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 11417 | 11501 | .{ .v_ps, .cvtph2 }, |
| 11418 | 11502 | tmp_reg, |
| 11419 | | try src_mcv.mem(self, .xword), |
| 11503 | try src_mcv.mem(self, .{ .size = .xword }), |
| 11420 | 11504 | ) else try self.asmRegisterRegister( |
| 11421 | 11505 | .{ .v_ps, .cvtph2 }, |
| 11422 | 11506 | tmp_reg, |
| ... | ... | @@ -11579,10 +11663,10 @@ fn genBinOp( |
| 11579 | 11663 | mir_tag, |
| 11580 | 11664 | dst_reg, |
| 11581 | 11665 | lhs_reg, |
| 11582 | | try src_mcv.mem(self, switch (lhs_ty.zigTypeTag(zcu)) { |
| 11666 | try src_mcv.mem(self, .{ .size = switch (lhs_ty.zigTypeTag(zcu)) { |
| 11583 | 11667 | else => .fromSize(abi_size), |
| 11584 | 11668 | .vector => .fromBitSize(dst_reg.bitSize()), |
| 11585 | | }), |
| 11669 | } }), |
| 11586 | 11670 | ) else try self.asmRegisterRegisterRegister( |
| 11587 | 11671 | mir_tag, |
| 11588 | 11672 | dst_reg, |
| ... | ... | @@ -11597,10 +11681,10 @@ fn genBinOp( |
| 11597 | 11681 | if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 11598 | 11682 | mir_tag, |
| 11599 | 11683 | dst_reg, |
| 11600 | | try src_mcv.mem(self, switch (lhs_ty.zigTypeTag(zcu)) { |
| 11684 | try src_mcv.mem(self, .{ .size = switch (lhs_ty.zigTypeTag(zcu)) { |
| 11601 | 11685 | else => .fromSize(abi_size), |
| 11602 | 11686 | .vector => .fromBitSize(dst_reg.bitSize()), |
| 11603 | | }), |
| 11687 | } }), |
| 11604 | 11688 | ) else try self.asmRegisterRegister( |
| 11605 | 11689 | mir_tag, |
| 11606 | 11690 | dst_reg, |
| ... | ... | @@ -11625,10 +11709,10 @@ fn genBinOp( |
| 11625 | 11709 | mir_tag, |
| 11626 | 11710 | dst_reg, |
| 11627 | 11711 | lhs_reg, |
| 11628 | | try src_mcv.mem(self, switch (lhs_ty.zigTypeTag(zcu)) { |
| 11712 | try src_mcv.mem(self, .{ .size = switch (lhs_ty.zigTypeTag(zcu)) { |
| 11629 | 11713 | else => .fromSize(abi_size), |
| 11630 | 11714 | .vector => .fromBitSize(dst_reg.bitSize()), |
| 11631 | | }), |
| 11715 | } }), |
| 11632 | 11716 | imm, |
| 11633 | 11717 | ) else try self.asmRegisterRegisterRegisterImmediate( |
| 11634 | 11718 | mir_tag, |
| ... | ... | @@ -11645,10 +11729,10 @@ fn genBinOp( |
| 11645 | 11729 | if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate( |
| 11646 | 11730 | mir_tag, |
| 11647 | 11731 | dst_reg, |
| 11648 | | try src_mcv.mem(self, switch (lhs_ty.zigTypeTag(zcu)) { |
| 11732 | try src_mcv.mem(self, .{ .size = switch (lhs_ty.zigTypeTag(zcu)) { |
| 11649 | 11733 | else => .fromSize(abi_size), |
| 11650 | 11734 | .vector => .fromBitSize(dst_reg.bitSize()), |
| 11651 | | }), |
| 11735 | } }), |
| 11652 | 11736 | imm, |
| 11653 | 11737 | ) else try self.asmRegisterRegisterImmediate( |
| 11654 | 11738 | mir_tag, |
| ... | ... | @@ -11854,7 +11938,7 @@ fn genBinOp( |
| 11854 | 11938 | const unsigned_ty = try lhs_ty.toUnsigned(pt); |
| 11855 | 11939 | const not_mcv = try self.genTypedValue(try unsigned_ty.maxInt(pt, unsigned_ty)); |
| 11856 | 11940 | const not_mem: Memory = if (not_mcv.isMemory()) |
| 11857 | | try not_mcv.mem(self, .fromSize(abi_size)) |
| 11941 | try not_mcv.mem(self, .{ .size = .fromSize(abi_size) }) |
| 11858 | 11942 | else |
| 11859 | 11943 | .{ .base = .{ |
| 11860 | 11944 | .reg = try self.copyToTmpRegister(Type.usize, not_mcv.address()), |
| ... | ... | @@ -11915,7 +11999,7 @@ fn genBinOp( |
| 11915 | 11999 | } |
| 11916 | 12000 | |
| 11917 | 12001 | fn genBinOpMir( |
| 11918 | | self: *Self, |
| 12002 | self: *CodeGen, |
| 11919 | 12003 | mir_tag: Mir.Inst.FixedTag, |
| 11920 | 12004 | ty: Type, |
| 11921 | 12005 | dst_mcv: MCValue, |
| ... | ... | @@ -12341,7 +12425,7 @@ fn genBinOpMir( |
| 12341 | 12425 | |
| 12342 | 12426 | /// Performs multi-operand integer multiplication between dst_mcv and src_mcv, storing the result in dst_mcv. |
| 12343 | 12427 | /// Does not support byte-size operands. |
| 12344 | | fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void { |
| 12428 | fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void { |
| 12345 | 12429 | const pt = self.pt; |
| 12346 | 12430 | const abi_size: u32 = @intCast(dst_ty.abiSize(pt.zcu)); |
| 12347 | 12431 | try self.spillEflagsIfOccupied(); |
| ... | ... | @@ -12468,7 +12552,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 12468 | 12552 | } |
| 12469 | 12553 | } |
| 12470 | 12554 | |
| 12471 | | fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 12555 | fn airArg(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 12472 | 12556 | const pt = self.pt; |
| 12473 | 12557 | const zcu = pt.zcu; |
| 12474 | 12558 | // skip zero-bit arguments as they don't have a corresponding arg instruction |
| ... | ... | @@ -12522,7 +12606,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 12522 | 12606 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 12523 | 12607 | if (regs_frame_addr.regs > 0) try self.asmMemoryRegister( |
| 12524 | 12608 | .{ ._, .mov }, |
| 12525 | | try dst_mcv.mem(self, .byte), |
| 12609 | try dst_mcv.mem(self, .{ .size = .byte }), |
| 12526 | 12610 | prev_reg.to8(), |
| 12527 | 12611 | ); |
| 12528 | 12612 | try self.genInlineMemset( |
| ... | ... | @@ -12554,7 +12638,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 12554 | 12638 | const unset = try self.asmJccReloc(.e, undefined); |
| 12555 | 12639 | try self.asmMemoryRegister( |
| 12556 | 12640 | .{ ._s, .bt }, |
| 12557 | | try dst_mcv.mem(self, .dword), |
| 12641 | try dst_mcv.mem(self, .{ .size = .dword }), |
| 12558 | 12642 | index_reg.to32(), |
| 12559 | 12643 | ); |
| 12560 | 12644 | self.performReloc(unset); |
| ... | ... | @@ -12578,7 +12662,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 12578 | 12662 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 12579 | 12663 | } |
| 12580 | 12664 | |
| 12581 | | fn airDbgArg(self: *Self, inst: Air.Inst.Index) !void { |
| 12665 | fn airDbgArg(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 12582 | 12666 | // skip zero-bit arguments as they don't have a corresponding arg instruction |
| 12583 | 12667 | var arg_index = self.arg_index; |
| 12584 | 12668 | while (self.args[arg_index] == .none) arg_index += 1; |
| ... | ... | @@ -12594,13 +12678,13 @@ fn airDbgArg(self: *Self, inst: Air.Inst.Index) !void { |
| 12594 | 12678 | } else try self.airDbgVarArgs(); |
| 12595 | 12679 | } |
| 12596 | 12680 | |
| 12597 | | fn airDbgVarArgs(self: *Self) !void { |
| 12681 | fn airDbgVarArgs(self: *CodeGen) !void { |
| 12598 | 12682 | if (self.pt.zcu.typeToFunc(self.fn_type).?.is_var_args) |
| 12599 | 12683 | try self.asmPseudo(.pseudo_dbg_var_args_none); |
| 12600 | 12684 | } |
| 12601 | 12685 | |
| 12602 | 12686 | fn genLocalDebugInfo( |
| 12603 | | self: *Self, |
| 12687 | self: *CodeGen, |
| 12604 | 12688 | inst: Air.Inst.Index, |
| 12605 | 12689 | mcv: MCValue, |
| 12606 | 12690 | ) !void { |
| ... | ... | @@ -12656,19 +12740,19 @@ fn genLocalDebugInfo( |
| 12656 | 12740 | } |
| 12657 | 12741 | } |
| 12658 | 12742 | |
| 12659 | | fn airRetAddr(self: *Self, inst: Air.Inst.Index) !void { |
| 12743 | fn airRetAddr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 12660 | 12744 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 12661 | 12745 | try self.genCopy(Type.usize, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } }, .{}); |
| 12662 | 12746 | return self.finishAir(inst, dst_mcv, .{ .none, .none, .none }); |
| 12663 | 12747 | } |
| 12664 | 12748 | |
| 12665 | | fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void { |
| 12749 | fn airFrameAddress(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 12666 | 12750 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 12667 | 12751 | try self.genCopy(Type.usize, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } }, .{}); |
| 12668 | 12752 | return self.finishAir(inst, dst_mcv, .{ .none, .none, .none }); |
| 12669 | 12753 | } |
| 12670 | 12754 | |
| 12671 | | fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { |
| 12755 | fn airCall(self: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { |
| 12672 | 12756 | if (modifier == .always_tail) return self.fail("TODO implement tail calls for x86_64", .{}); |
| 12673 | 12757 | |
| 12674 | 12758 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| ... | ... | @@ -12702,7 +12786,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 12702 | 12786 | return self.finishAirResult(inst, result); |
| 12703 | 12787 | } |
| 12704 | 12788 | |
| 12705 | | fn genCall(self: *Self, info: union(enum) { |
| 12789 | fn genCall(self: *CodeGen, info: union(enum) { |
| 12706 | 12790 | air: Air.Inst.Ref, |
| 12707 | 12791 | lib: struct { |
| 12708 | 12792 | return_type: InternPool.Index, |
| ... | ... | @@ -12808,7 +12892,7 @@ fn genCall(self: *Self, info: union(enum) { |
| 12808 | 12892 | const index_lock = self.register_manager.lockRegAssumeUnused(index_reg); |
| 12809 | 12893 | defer self.register_manager.unlockReg(index_lock); |
| 12810 | 12894 | |
| 12811 | | const src_mem: Memory = if (src_arg.isMemory()) try src_arg.mem(self, .dword) else .{ |
| 12895 | const src_mem: Memory = if (src_arg.isMemory()) try src_arg.mem(self, .{ .size = .dword }) else .{ |
| 12812 | 12896 | .base = .{ .reg = try self.copyToTmpRegister( |
| 12813 | 12897 | Type.usize, |
| 12814 | 12898 | switch (src_arg) { |
| ... | ... | @@ -12900,7 +12984,7 @@ fn genCall(self: *Self, info: union(enum) { |
| 12900 | 12984 | .lea_frame = .{ .index = frame_index, .off = -reg_off.off }, |
| 12901 | 12985 | }, .{}), |
| 12902 | 12986 | .elementwise_regs_then_frame => |regs_frame_addr| { |
| 12903 | | const src_mem: Memory = if (src_arg.isMemory()) try src_arg.mem(self, .dword) else .{ |
| 12987 | const src_mem: Memory = if (src_arg.isMemory()) try src_arg.mem(self, .{ .size = .dword }) else .{ |
| 12904 | 12988 | .base = .{ .reg = try self.copyToTmpRegister( |
| 12905 | 12989 | Type.usize, |
| 12906 | 12990 | switch (src_arg) { |
| ... | ... | @@ -13006,7 +13090,7 @@ fn genCall(self: *Self, info: union(enum) { |
| 13006 | 13090 | return call_info.return_value.short; |
| 13007 | 13091 | } |
| 13008 | 13092 | |
| 13009 | | fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 13093 | fn airRet(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void { |
| 13010 | 13094 | const pt = self.pt; |
| 13011 | 13095 | const zcu = pt.zcu; |
| 13012 | 13096 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| ... | ... | @@ -13042,7 +13126,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 13042 | 13126 | try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc); |
| 13043 | 13127 | } |
| 13044 | 13128 | |
| 13045 | | fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 13129 | fn airRetLoad(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 13046 | 13130 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 13047 | 13131 | const ptr = try self.resolveInst(un_op); |
| 13048 | 13132 | |
| ... | ... | @@ -13062,7 +13146,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 13062 | 13146 | try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc); |
| 13063 | 13147 | } |
| 13064 | 13148 | |
| 13065 | | fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) !void { |
| 13149 | fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !void { |
| 13066 | 13150 | const pt = self.pt; |
| 13067 | 13151 | const zcu = pt.zcu; |
| 13068 | 13152 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -13145,7 +13229,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) !void |
| 13145 | 13229 | if (lhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 13146 | 13230 | .{ ._, .mov }, |
| 13147 | 13231 | temp_lhs_reg.to8(), |
| 13148 | | try lhs_mcv.address().offset(payload_abi_size).deref().mem(self, .byte), |
| 13232 | try lhs_mcv.address().offset(payload_abi_size).deref().mem(self, .{ .size = .byte }), |
| 13149 | 13233 | ) else { |
| 13150 | 13234 | try self.genSetReg(temp_lhs_reg, opt_ty, lhs_mcv, .{}); |
| 13151 | 13235 | try self.asmRegisterImmediate( |
| ... | ... | @@ -13158,7 +13242,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) !void |
| 13158 | 13242 | const payload_compare = payload_compare: { |
| 13159 | 13243 | if (rhs_mcv.isMemory()) { |
| 13160 | 13244 | const rhs_mem = |
| 13161 | | try rhs_mcv.address().offset(payload_abi_size).deref().mem(self, .byte); |
| 13245 | try rhs_mcv.address().offset(payload_abi_size).deref().mem(self, .{ .size = .byte }); |
| 13162 | 13246 | try self.asmMemoryRegister(.{ ._, .@"test" }, rhs_mem, temp_lhs_reg.to8()); |
| 13163 | 13247 | const payload_compare = try self.asmJccReloc(.nz, undefined); |
| 13164 | 13248 | try self.asmRegisterMemory(.{ ._, .cmp }, temp_lhs_reg.to8(), rhs_mem); |
| ... | ... | @@ -13459,7 +13543,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) !void |
| 13459 | 13543 | .{ .vp_w, .insr }, |
| 13460 | 13544 | tmp1_reg, |
| 13461 | 13545 | dst_reg.to128(), |
| 13462 | | try src_mcv.mem(self, .word), |
| 13546 | try src_mcv.mem(self, .{ .size = .word }), |
| 13463 | 13547 | .u(1), |
| 13464 | 13548 | ) else try self.asmRegisterRegisterRegister( |
| 13465 | 13549 | .{ .vp_, .unpcklwd }, |
| ... | ... | @@ -13505,7 +13589,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) !void |
| 13505 | 13589 | return self.finishAir(inst, .{ .eflags = result }, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 13506 | 13590 | } |
| 13507 | 13591 | |
| 13508 | | fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void { |
| 13592 | fn airCmpVector(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 13509 | 13593 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 13510 | 13594 | const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data; |
| 13511 | 13595 | const dst_mcv = try self.genBinOp( |
| ... | ... | @@ -13517,7 +13601,7 @@ fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void { |
| 13517 | 13601 | return self.finishAir(inst, dst_mcv, .{ extra.lhs, extra.rhs, .none }); |
| 13518 | 13602 | } |
| 13519 | 13603 | |
| 13520 | | fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { |
| 13604 | fn airCmpLtErrorsLen(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 13521 | 13605 | const pt = self.pt; |
| 13522 | 13606 | const zcu = pt.zcu; |
| 13523 | 13607 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| ... | ... | @@ -13550,7 +13634,7 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { |
| 13550 | 13634 | return self.finishAir(inst, .{ .eflags = .b }, .{ un_op, .none, .none }); |
| 13551 | 13635 | } |
| 13552 | 13636 | |
| 13553 | | fn airTry(self: *Self, inst: Air.Inst.Index) !void { |
| 13637 | fn airTry(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 13554 | 13638 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 13555 | 13639 | const extra = self.air.extraData(Air.Try, pl_op.payload); |
| 13556 | 13640 | const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]); |
| ... | ... | @@ -13559,7 +13643,7 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void { |
| 13559 | 13643 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 13560 | 13644 | } |
| 13561 | 13645 | |
| 13562 | | fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 13646 | fn airTryPtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 13563 | 13647 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 13564 | 13648 | const extra = self.air.extraData(Air.TryPtr, ty_pl.payload); |
| 13565 | 13649 | const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]); |
| ... | ... | @@ -13569,7 +13653,7 @@ fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 13569 | 13653 | } |
| 13570 | 13654 | |
| 13571 | 13655 | fn genTry( |
| 13572 | | self: *Self, |
| 13656 | self: *CodeGen, |
| 13573 | 13657 | inst: Air.Inst.Index, |
| 13574 | 13658 | operand: Air.Inst.Ref, |
| 13575 | 13659 | body: []const Air.Inst.Index, |
| ... | ... | @@ -13615,7 +13699,7 @@ fn genTry( |
| 13615 | 13699 | return result; |
| 13616 | 13700 | } |
| 13617 | 13701 | |
| 13618 | | fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { |
| 13702 | fn airDbgStmt(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 13619 | 13703 | const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt; |
| 13620 | 13704 | _ = try self.addInst(.{ |
| 13621 | 13705 | .tag = .pseudo, |
| ... | ... | @@ -13627,14 +13711,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { |
| 13627 | 13711 | }); |
| 13628 | 13712 | } |
| 13629 | 13713 | |
| 13630 | | fn airDbgEmptyStmt(self: *Self) !void { |
| 13714 | fn airDbgEmptyStmt(self: *CodeGen) !void { |
| 13631 | 13715 | if (self.mir_instructions.len > 0 and |
| 13632 | 13716 | self.mir_instructions.items(.ops)[self.mir_instructions.len - 1] == .pseudo_dbg_line_stmt_line_column) |
| 13633 | 13717 | self.mir_instructions.items(.ops)[self.mir_instructions.len - 1] = .pseudo_dbg_line_line_column; |
| 13634 | 13718 | try self.asmOpOnly(.{ ._, .nop }); |
| 13635 | 13719 | } |
| 13636 | 13720 | |
| 13637 | | fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void { |
| 13721 | fn airDbgInlineBlock(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 13638 | 13722 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 13639 | 13723 | const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload); |
| 13640 | 13724 | const old_inline_func = self.inline_func; |
| ... | ... | @@ -13653,13 +13737,13 @@ fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void { |
| 13653 | 13737 | }); |
| 13654 | 13738 | } |
| 13655 | 13739 | |
| 13656 | | fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { |
| 13740 | fn airDbgVar(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 13657 | 13741 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 13658 | 13742 | try self.genLocalDebugInfo(inst, try self.resolveInst(pl_op.operand)); |
| 13659 | 13743 | return self.finishAir(inst, .unreach, .{ pl_op.operand, .none, .none }); |
| 13660 | 13744 | } |
| 13661 | 13745 | |
| 13662 | | fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !Mir.Inst.Index { |
| 13746 | fn genCondBrMir(self: *CodeGen, ty: Type, mcv: MCValue) !Mir.Inst.Index { |
| 13663 | 13747 | const pt = self.pt; |
| 13664 | 13748 | const abi_size = ty.abiSize(pt.zcu); |
| 13665 | 13749 | switch (mcv) { |
| ... | ... | @@ -13686,7 +13770,7 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !Mir.Inst.Index { |
| 13686 | 13770 | } |
| 13687 | 13771 | } |
| 13688 | 13772 | |
| 13689 | | fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 13773 | fn airCondBr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 13690 | 13774 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 13691 | 13775 | const cond = try self.resolveInst(pl_op.operand); |
| 13692 | 13776 | const cond_ty = self.typeOf(pl_op.operand); |
| ... | ... | @@ -13731,7 +13815,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 13731 | 13815 | // We already took care of pl_op.operand earlier, so there's nothing left to do. |
| 13732 | 13816 | } |
| 13733 | 13817 | |
| 13734 | | fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MCValue { |
| 13818 | fn isNull(self: *CodeGen, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MCValue { |
| 13735 | 13819 | const pt = self.pt; |
| 13736 | 13820 | const zcu = pt.zcu; |
| 13737 | 13821 | switch (opt_mcv) { |
| ... | ... | @@ -13862,7 +13946,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 13862 | 13946 | } |
| 13863 | 13947 | } |
| 13864 | 13948 | |
| 13865 | | fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue { |
| 13949 | fn isNullPtr(self: *CodeGen, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue { |
| 13866 | 13950 | const pt = self.pt; |
| 13867 | 13951 | const zcu = pt.zcu; |
| 13868 | 13952 | const opt_ty = ptr_ty.childType(zcu); |
| ... | ... | @@ -13899,7 +13983,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) |
| 13899 | 13983 | return .{ .eflags = .e }; |
| 13900 | 13984 | } |
| 13901 | 13985 | |
| 13902 | | fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MCValue { |
| 13986 | fn isErr(self: *CodeGen, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MCValue { |
| 13903 | 13987 | const pt = self.pt; |
| 13904 | 13988 | const zcu = pt.zcu; |
| 13905 | 13989 | const err_ty = eu_ty.errorUnionSet(zcu); |
| ... | ... | @@ -13948,7 +14032,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) |
| 13948 | 14032 | return MCValue{ .eflags = .a }; |
| 13949 | 14033 | } |
| 13950 | 14034 | |
| 13951 | | fn isErrPtr(self: *Self, maybe_inst: ?Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue { |
| 14035 | fn isErrPtr(self: *CodeGen, maybe_inst: ?Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue { |
| 13952 | 14036 | const pt = self.pt; |
| 13953 | 14037 | const zcu = pt.zcu; |
| 13954 | 14038 | const eu_ty = ptr_ty.childType(zcu); |
| ... | ... | @@ -13981,7 +14065,7 @@ fn isErrPtr(self: *Self, maybe_inst: ?Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCV |
| 13981 | 14065 | return MCValue{ .eflags = .a }; |
| 13982 | 14066 | } |
| 13983 | 14067 | |
| 13984 | | fn isNonErr(self: *Self, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MCValue { |
| 14068 | fn isNonErr(self: *CodeGen, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MCValue { |
| 13985 | 14069 | const is_err_res = try self.isErr(inst, eu_ty, eu_mcv); |
| 13986 | 14070 | switch (is_err_res) { |
| 13987 | 14071 | .eflags => |cc| { |
| ... | ... | @@ -13996,7 +14080,7 @@ fn isNonErr(self: *Self, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MC |
| 13996 | 14080 | } |
| 13997 | 14081 | } |
| 13998 | 14082 | |
| 13999 | | fn isNonErrPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue { |
| 14083 | fn isNonErrPtr(self: *CodeGen, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue { |
| 14000 | 14084 | const is_err_res = try self.isErrPtr(inst, ptr_ty, ptr_mcv); |
| 14001 | 14085 | switch (is_err_res) { |
| 14002 | 14086 | .eflags => |cc| { |
| ... | ... | @@ -14011,7 +14095,7 @@ fn isNonErrPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue |
| 14011 | 14095 | } |
| 14012 | 14096 | } |
| 14013 | 14097 | |
| 14014 | | fn airIsNull(self: *Self, inst: Air.Inst.Index) !void { |
| 14098 | fn airIsNull(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 14015 | 14099 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 14016 | 14100 | const operand = try self.resolveInst(un_op); |
| 14017 | 14101 | const ty = self.typeOf(un_op); |
| ... | ... | @@ -14019,7 +14103,7 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void { |
| 14019 | 14103 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 14020 | 14104 | } |
| 14021 | 14105 | |
| 14022 | | fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 14106 | fn airIsNullPtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 14023 | 14107 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 14024 | 14108 | const operand = try self.resolveInst(un_op); |
| 14025 | 14109 | const ty = self.typeOf(un_op); |
| ... | ... | @@ -14027,7 +14111,7 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 14027 | 14111 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 14028 | 14112 | } |
| 14029 | 14113 | |
| 14030 | | fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void { |
| 14114 | fn airIsNonNull(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 14031 | 14115 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 14032 | 14116 | const operand = try self.resolveInst(un_op); |
| 14033 | 14117 | const ty = self.typeOf(un_op); |
| ... | ... | @@ -14039,7 +14123,7 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void { |
| 14039 | 14123 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 14040 | 14124 | } |
| 14041 | 14125 | |
| 14042 | | fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 14126 | fn airIsNonNullPtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 14043 | 14127 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 14044 | 14128 | const operand = try self.resolveInst(un_op); |
| 14045 | 14129 | const ty = self.typeOf(un_op); |
| ... | ... | @@ -14050,7 +14134,7 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 14050 | 14134 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 14051 | 14135 | } |
| 14052 | 14136 | |
| 14053 | | fn airIsErr(self: *Self, inst: Air.Inst.Index) !void { |
| 14137 | fn airIsErr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 14054 | 14138 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 14055 | 14139 | const operand = try self.resolveInst(un_op); |
| 14056 | 14140 | const ty = self.typeOf(un_op); |
| ... | ... | @@ -14058,7 +14142,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void { |
| 14058 | 14142 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 14059 | 14143 | } |
| 14060 | 14144 | |
| 14061 | | fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 14145 | fn airIsErrPtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 14062 | 14146 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 14063 | 14147 | const operand = try self.resolveInst(un_op); |
| 14064 | 14148 | const ty = self.typeOf(un_op); |
| ... | ... | @@ -14066,7 +14150,7 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 14066 | 14150 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 14067 | 14151 | } |
| 14068 | 14152 | |
| 14069 | | fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void { |
| 14153 | fn airIsNonErr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 14070 | 14154 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 14071 | 14155 | const operand = try self.resolveInst(un_op); |
| 14072 | 14156 | const ty = self.typeOf(un_op); |
| ... | ... | @@ -14074,7 +14158,7 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void { |
| 14074 | 14158 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 14075 | 14159 | } |
| 14076 | 14160 | |
| 14077 | | fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 14161 | fn airIsNonErrPtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 14078 | 14162 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 14079 | 14163 | const operand = try self.resolveInst(un_op); |
| 14080 | 14164 | const ty = self.typeOf(un_op); |
| ... | ... | @@ -14082,7 +14166,7 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 14082 | 14166 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 14083 | 14167 | } |
| 14084 | 14168 | |
| 14085 | | fn airLoop(self: *Self, inst: Air.Inst.Index) !void { |
| 14169 | fn airLoop(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 14086 | 14170 | // A loop is a setup to be able to jump back to the beginning. |
| 14087 | 14171 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 14088 | 14172 | const loop = self.air.extraData(Air.Block, ty_pl.payload); |
| ... | ... | @@ -14100,7 +14184,7 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void { |
| 14100 | 14184 | try self.genBodyBlock(body); |
| 14101 | 14185 | } |
| 14102 | 14186 | |
| 14103 | | fn airBlock(self: *Self, inst: Air.Inst.Index) !void { |
| 14187 | fn airBlock(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 14104 | 14188 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 14105 | 14189 | const extra = self.air.extraData(Air.Block, ty_pl.payload); |
| 14106 | 14190 | try self.asmPseudo(.pseudo_dbg_enter_block_none); |
| ... | ... | @@ -14108,7 +14192,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void { |
| 14108 | 14192 | try self.asmPseudo(.pseudo_dbg_leave_block_none); |
| 14109 | 14193 | } |
| 14110 | 14194 | |
| 14111 | | fn lowerBlock(self: *Self, inst: Air.Inst.Index, body: []const Air.Inst.Index) !void { |
| 14195 | fn lowerBlock(self: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index) !void { |
| 14112 | 14196 | // A block is a setup to be able to jump to the end. |
| 14113 | 14197 | const inst_tracking_i = self.inst_tracking.count(); |
| 14114 | 14198 | self.inst_tracking.putAssumeCapacityNoClobber(inst, .init(.unreach)); |
| ... | ... | @@ -14137,7 +14221,7 @@ fn lowerBlock(self: *Self, inst: Air.Inst.Index, body: []const Air.Inst.Index) ! |
| 14137 | 14221 | self.getValueIfFree(tracking.short, inst); |
| 14138 | 14222 | } |
| 14139 | 14223 | |
| 14140 | | fn lowerSwitchBr(self: *Self, inst: Air.Inst.Index, switch_br: Air.UnwrappedSwitch, condition: MCValue) !void { |
| 14224 | fn lowerSwitchBr(self: *CodeGen, inst: Air.Inst.Index, switch_br: Air.UnwrappedSwitch, condition: MCValue) !void { |
| 14141 | 14225 | const zcu = self.pt.zcu; |
| 14142 | 14226 | const condition_ty = self.typeOf(switch_br.operand); |
| 14143 | 14227 | const liveness = try self.liveness.getSwitchBr(self.gpa, inst, switch_br.cases_len + 1); |
| ... | ... | @@ -14255,7 +14339,7 @@ fn lowerSwitchBr(self: *Self, inst: Air.Inst.Index, switch_br: Air.UnwrappedSwit |
| 14255 | 14339 | } |
| 14256 | 14340 | } |
| 14257 | 14341 | |
| 14258 | | fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void { |
| 14342 | fn airSwitchBr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 14259 | 14343 | const switch_br = self.air.unwrapSwitch(inst); |
| 14260 | 14344 | const condition = try self.resolveInst(switch_br.operand); |
| 14261 | 14345 | |
| ... | ... | @@ -14271,7 +14355,7 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void { |
| 14271 | 14355 | // We already took care of pl_op.operand earlier, so there's nothing left to do |
| 14272 | 14356 | } |
| 14273 | 14357 | |
| 14274 | | fn airLoopSwitchBr(self: *Self, inst: Air.Inst.Index) !void { |
| 14358 | fn airLoopSwitchBr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 14275 | 14359 | const switch_br = self.air.unwrapSwitch(inst); |
| 14276 | 14360 | const condition = try self.resolveInst(switch_br.operand); |
| 14277 | 14361 | |
| ... | ... | @@ -14309,7 +14393,7 @@ fn airLoopSwitchBr(self: *Self, inst: Air.Inst.Index) !void { |
| 14309 | 14393 | try self.processDeath(inst); |
| 14310 | 14394 | } |
| 14311 | 14395 | |
| 14312 | | fn airSwitchDispatch(self: *Self, inst: Air.Inst.Index) !void { |
| 14396 | fn airSwitchDispatch(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 14313 | 14397 | const br = self.air.instructions.items(.data)[@intFromEnum(inst)].br; |
| 14314 | 14398 | |
| 14315 | 14399 | const block_ty = self.typeOfIndex(br.block_inst); |
| ... | ... | @@ -14354,7 +14438,7 @@ fn airSwitchDispatch(self: *Self, inst: Air.Inst.Index) !void { |
| 14354 | 14438 | try self.freeValue(block_tracking.short); |
| 14355 | 14439 | } |
| 14356 | 14440 | |
| 14357 | | fn performReloc(self: *Self, reloc: Mir.Inst.Index) void { |
| 14441 | fn performReloc(self: *CodeGen, reloc: Mir.Inst.Index) void { |
| 14358 | 14442 | const next_inst: u32 = @intCast(self.mir_instructions.len); |
| 14359 | 14443 | switch (self.mir_instructions.items(.tag)[reloc]) { |
| 14360 | 14444 | .j, .jmp => {}, |
| ... | ... | @@ -14367,7 +14451,7 @@ fn performReloc(self: *Self, reloc: Mir.Inst.Index) void { |
| 14367 | 14451 | self.mir_instructions.items(.data)[reloc].inst.inst = next_inst; |
| 14368 | 14452 | } |
| 14369 | 14453 | |
| 14370 | | fn airBr(self: *Self, inst: Air.Inst.Index) !void { |
| 14454 | fn airBr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 14371 | 14455 | const zcu = self.pt.zcu; |
| 14372 | 14456 | const br = self.air.instructions.items(.data)[@intFromEnum(inst)].br; |
| 14373 | 14457 | |
| ... | ... | @@ -14426,7 +14510,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { |
| 14426 | 14510 | try self.freeValue(block_tracking.short); |
| 14427 | 14511 | } |
| 14428 | 14512 | |
| 14429 | | fn airRepeat(self: *Self, inst: Air.Inst.Index) !void { |
| 14513 | fn airRepeat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 14430 | 14514 | const loop_inst = self.air.instructions.items(.data)[@intFromEnum(inst)].repeat.loop_inst; |
| 14431 | 14515 | const repeat_info = self.loops.get(loop_inst).?; |
| 14432 | 14516 | try self.restoreState(repeat_info.state, &.{}, .{ |
| ... | ... | @@ -14438,7 +14522,7 @@ fn airRepeat(self: *Self, inst: Air.Inst.Index) !void { |
| 14438 | 14522 | _ = try self.asmJmpReloc(repeat_info.target); |
| 14439 | 14523 | } |
| 14440 | 14524 | |
| 14441 | | fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 14525 | fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 14442 | 14526 | const pt = self.pt; |
| 14443 | 14527 | const zcu = pt.zcu; |
| 14444 | 14528 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -15110,7 +15194,7 @@ const MoveStrategy = union(enum) { |
| 15110 | 15194 | extract: Mir.Inst.FixedTag, |
| 15111 | 15195 | }; |
| 15112 | 15196 | |
| 15113 | | pub fn read(strat: MoveStrategy, self: *Self, dst_reg: Register, src_mem: Memory) !void { |
| 15197 | pub fn read(strat: MoveStrategy, self: *CodeGen, dst_reg: Register, src_mem: Memory) !void { |
| 15114 | 15198 | switch (strat) { |
| 15115 | 15199 | .move => |tag| try self.asmRegisterMemory(tag, switch (tag[1]) { |
| 15116 | 15200 | else => dst_reg, |
| ... | ... | @@ -15136,7 +15220,7 @@ const MoveStrategy = union(enum) { |
| 15136 | 15220 | ), |
| 15137 | 15221 | } |
| 15138 | 15222 | } |
| 15139 | | pub fn write(strat: MoveStrategy, self: *Self, dst_mem: Memory, src_reg: Register) !void { |
| 15223 | pub fn write(strat: MoveStrategy, self: *CodeGen, dst_mem: Memory, src_reg: Register) !void { |
| 15140 | 15224 | switch (strat) { |
| 15141 | 15225 | .move => |tag| try self.asmMemoryRegister(tag, dst_mem, src_reg), |
| 15142 | 15226 | .x87_load_store => { |
| ... | ... | @@ -15152,7 +15236,7 @@ const MoveStrategy = union(enum) { |
| 15152 | 15236 | } |
| 15153 | 15237 | } |
| 15154 | 15238 | }; |
| 15155 | | fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !MoveStrategy { |
| 15239 | fn moveStrategy(self: *CodeGen, ty: Type, class: Register.Class, aligned: bool) !MoveStrategy { |
| 15156 | 15240 | const pt = self.pt; |
| 15157 | 15241 | const zcu = pt.zcu; |
| 15158 | 15242 | switch (class) { |
| ... | ... | @@ -15383,7 +15467,7 @@ const CopyOptions = struct { |
| 15383 | 15467 | safety: bool = false, |
| 15384 | 15468 | }; |
| 15385 | 15469 | |
| 15386 | | fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: CopyOptions) InnerError!void { |
| 15470 | fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: CopyOptions) InnerError!void { |
| 15387 | 15471 | const pt = self.pt; |
| 15388 | 15472 | |
| 15389 | 15473 | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| ... | ... | @@ -15496,7 +15580,7 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: Copy |
| 15496 | 15580 | } |
| 15497 | 15581 | |
| 15498 | 15582 | fn genSetReg( |
| 15499 | | self: *Self, |
| 15583 | self: *CodeGen, |
| 15500 | 15584 | dst_reg: Register, |
| 15501 | 15585 | ty: Type, |
| 15502 | 15586 | src_mcv: MCValue, |
| ... | ... | @@ -15781,7 +15865,7 @@ fn genSetReg( |
| 15781 | 15865 | } |
| 15782 | 15866 | |
| 15783 | 15867 | fn genSetMem( |
| 15784 | | self: *Self, |
| 15868 | self: *CodeGen, |
| 15785 | 15869 | base: Memory.Base, |
| 15786 | 15870 | disp: i32, |
| 15787 | 15871 | ty: Type, |
| ... | ... | @@ -16012,7 +16096,7 @@ fn genSetMem( |
| 16012 | 16096 | } |
| 16013 | 16097 | } |
| 16014 | 16098 | |
| 16015 | | fn genInlineMemcpy(self: *Self, dst_ptr: MCValue, src_ptr: MCValue, len: MCValue) InnerError!void { |
| 16099 | fn genInlineMemcpy(self: *CodeGen, dst_ptr: MCValue, src_ptr: MCValue, len: MCValue) InnerError!void { |
| 16016 | 16100 | try self.spillRegisters(&.{ .rsi, .rdi, .rcx }); |
| 16017 | 16101 | try self.genSetReg(.rsi, Type.usize, src_ptr, .{}); |
| 16018 | 16102 | try self.genSetReg(.rdi, Type.usize, dst_ptr, .{}); |
| ... | ... | @@ -16021,7 +16105,7 @@ fn genInlineMemcpy(self: *Self, dst_ptr: MCValue, src_ptr: MCValue, len: MCValue |
| 16021 | 16105 | } |
| 16022 | 16106 | |
| 16023 | 16107 | fn genInlineMemset( |
| 16024 | | self: *Self, |
| 16108 | self: *CodeGen, |
| 16025 | 16109 | dst_ptr: MCValue, |
| 16026 | 16110 | value: MCValue, |
| 16027 | 16111 | len: MCValue, |
| ... | ... | @@ -16035,7 +16119,7 @@ fn genInlineMemset( |
| 16035 | 16119 | } |
| 16036 | 16120 | |
| 16037 | 16121 | fn genExternSymbolRef( |
| 16038 | | self: *Self, |
| 16122 | self: *CodeGen, |
| 16039 | 16123 | comptime tag: Mir.Inst.Tag, |
| 16040 | 16124 | lib: ?[]const u8, |
| 16041 | 16125 | callee: []const u8, |
| ... | ... | @@ -16061,7 +16145,7 @@ fn genExternSymbolRef( |
| 16061 | 16145 | } |
| 16062 | 16146 | |
| 16063 | 16147 | fn genLazySymbolRef( |
| 16064 | | self: *Self, |
| 16148 | self: *CodeGen, |
| 16065 | 16149 | comptime tag: Mir.Inst.Tag, |
| 16066 | 16150 | reg: Register, |
| 16067 | 16151 | lazy_sym: link.File.LazySymbol, |
| ... | ... | @@ -16159,7 +16243,7 @@ fn genLazySymbolRef( |
| 16159 | 16243 | } |
| 16160 | 16244 | } |
| 16161 | 16245 | |
| 16162 | | fn airIntFromPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 16246 | fn airIntFromPtr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 16163 | 16247 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 16164 | 16248 | const result = result: { |
| 16165 | 16249 | // TODO: handle case where the operand is a slice not a raw pointer |
| ... | ... | @@ -16174,7 +16258,7 @@ fn airIntFromPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 16174 | 16258 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 16175 | 16259 | } |
| 16176 | 16260 | |
| 16177 | | fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 16261 | fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 16178 | 16262 | const pt = self.pt; |
| 16179 | 16263 | const zcu = pt.zcu; |
| 16180 | 16264 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -16239,7 +16323,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 16239 | 16323 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 16240 | 16324 | } |
| 16241 | 16325 | |
| 16242 | | fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 16326 | fn airArrayToSlice(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 16243 | 16327 | const pt = self.pt; |
| 16244 | 16328 | const zcu = pt.zcu; |
| 16245 | 16329 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -16264,7 +16348,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 16264 | 16348 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 16265 | 16349 | } |
| 16266 | 16350 | |
| 16267 | | fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void { |
| 16351 | fn airFloatFromInt(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 16268 | 16352 | const pt = self.pt; |
| 16269 | 16353 | const zcu = pt.zcu; |
| 16270 | 16354 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -16344,7 +16428,7 @@ fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void { |
| 16344 | 16428 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 16345 | 16429 | } |
| 16346 | 16430 | |
| 16347 | | fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 16431 | fn airIntFromFloat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 16348 | 16432 | const pt = self.pt; |
| 16349 | 16433 | const zcu = pt.zcu; |
| 16350 | 16434 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -16416,7 +16500,7 @@ fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 16416 | 16500 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 16417 | 16501 | } |
| 16418 | 16502 | |
| 16419 | | fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void { |
| 16503 | fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 16420 | 16504 | const pt = self.pt; |
| 16421 | 16505 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 16422 | 16506 | const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data; |
| ... | ... | @@ -16463,7 +16547,7 @@ fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void { |
| 16463 | 16547 | const ptr_mcv = try self.resolveInst(extra.ptr); |
| 16464 | 16548 | const mem_size: Memory.Size = .fromSize(val_abi_size); |
| 16465 | 16549 | const ptr_mem: Memory = switch (ptr_mcv) { |
| 16466 | | .immediate, .register, .register_offset, .lea_frame => try ptr_mcv.deref().mem(self, mem_size), |
| 16550 | .immediate, .register, .register_offset, .lea_frame => try ptr_mcv.deref().mem(self, .{ .size = mem_size }), |
| 16467 | 16551 | else => .{ |
| 16468 | 16552 | .base = .{ .reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv) }, |
| 16469 | 16553 | .mod = .{ .rm = .{ .size = mem_size } }, |
| ... | ... | @@ -16504,7 +16588,7 @@ fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void { |
| 16504 | 16588 | } |
| 16505 | 16589 | |
| 16506 | 16590 | fn atomicOp( |
| 16507 | | self: *Self, |
| 16591 | self: *CodeGen, |
| 16508 | 16592 | ptr_mcv: MCValue, |
| 16509 | 16593 | val_mcv: MCValue, |
| 16510 | 16594 | ptr_ty: Type, |
| ... | ... | @@ -16530,7 +16614,7 @@ fn atomicOp( |
| 16530 | 16614 | const val_abi_size: u32 = @intCast(val_ty.abiSize(zcu)); |
| 16531 | 16615 | const mem_size: Memory.Size = .fromSize(val_abi_size); |
| 16532 | 16616 | const ptr_mem: Memory = switch (ptr_mcv) { |
| 16533 | | .immediate, .register, .register_offset, .lea_frame => try ptr_mcv.deref().mem(self, mem_size), |
| 16617 | .immediate, .register, .register_offset, .lea_frame => try ptr_mcv.deref().mem(self, .{ .size = mem_size }), |
| 16534 | 16618 | else => .{ |
| 16535 | 16619 | .base = .{ .reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv) }, |
| 16536 | 16620 | .mod = .{ .rm = .{ .size = mem_size } }, |
| ... | ... | @@ -16649,7 +16733,7 @@ fn atomicOp( |
| 16649 | 16733 | mir_tag, |
| 16650 | 16734 | sse_reg.to128(), |
| 16651 | 16735 | sse_reg.to128(), |
| 16652 | | try val_mcv.mem(self, self.memSize(val_ty)), |
| 16736 | try val_mcv.mem(self, .{ .size = self.memSize(val_ty) }), |
| 16653 | 16737 | ) else try self.asmRegisterRegisterRegister( |
| 16654 | 16738 | mir_tag, |
| 16655 | 16739 | sse_reg.to128(), |
| ... | ... | @@ -16662,7 +16746,7 @@ fn atomicOp( |
| 16662 | 16746 | ._ss, ._sd => if (val_mcv.isMemory()) try self.asmRegisterMemory( |
| 16663 | 16747 | mir_tag, |
| 16664 | 16748 | sse_reg.to128(), |
| 16665 | | try val_mcv.mem(self, self.memSize(val_ty)), |
| 16749 | try val_mcv.mem(self, .{ .size = self.memSize(val_ty) }), |
| 16666 | 16750 | ) else try self.asmRegisterRegister( |
| 16667 | 16751 | mir_tag, |
| 16668 | 16752 | sse_reg.to128(), |
| ... | ... | @@ -16717,7 +16801,7 @@ fn atomicOp( |
| 16717 | 16801 | try self.asmCmovccRegisterMemory( |
| 16718 | 16802 | cc, |
| 16719 | 16803 | registerAlias(tmp_reg, cmov_abi_size), |
| 16720 | | try val_mcv.mem(self, .fromSize(cmov_abi_size)), |
| 16804 | try val_mcv.mem(self, .{ .size = .fromSize(cmov_abi_size) }), |
| 16721 | 16805 | ); |
| 16722 | 16806 | }, |
| 16723 | 16807 | else => { |
| ... | ... | @@ -16773,8 +16857,8 @@ fn atomicOp( |
| 16773 | 16857 | .reg = try self.copyToTmpRegister(Type.usize, val_mcv.address()), |
| 16774 | 16858 | } }, |
| 16775 | 16859 | }; |
| 16776 | | const val_lo_mem = try val_mem_mcv.mem(self, .qword); |
| 16777 | | const val_hi_mem = try val_mem_mcv.address().offset(8).deref().mem(self, .qword); |
| 16860 | const val_lo_mem = try val_mem_mcv.mem(self, .{ .size = .qword }); |
| 16861 | const val_hi_mem = try val_mem_mcv.address().offset(8).deref().mem(self, .{ .size = .qword }); |
| 16778 | 16862 | if (rmw_op != std.builtin.AtomicRmwOp.Xchg) { |
| 16779 | 16863 | try self.asmRegisterRegister(.{ ._, .mov }, .rbx, .rax); |
| 16780 | 16864 | try self.asmRegisterRegister(.{ ._, .mov }, .rcx, .rdx); |
| ... | ... | @@ -16862,7 +16946,7 @@ fn atomicOp( |
| 16862 | 16946 | } |
| 16863 | 16947 | } |
| 16864 | 16948 | |
| 16865 | | fn airAtomicRmw(self: *Self, inst: Air.Inst.Index) !void { |
| 16949 | fn airAtomicRmw(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 16866 | 16950 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 16867 | 16951 | const extra = self.air.extraData(Air.AtomicRmw, pl_op.payload).data; |
| 16868 | 16952 | |
| ... | ... | @@ -16883,7 +16967,7 @@ fn airAtomicRmw(self: *Self, inst: Air.Inst.Index) !void { |
| 16883 | 16967 | return self.finishAir(inst, result, .{ pl_op.operand, extra.operand, .none }); |
| 16884 | 16968 | } |
| 16885 | 16969 | |
| 16886 | | fn airAtomicLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 16970 | fn airAtomicLoad(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 16887 | 16971 | const atomic_load = self.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; |
| 16888 | 16972 | |
| 16889 | 16973 | const ptr_ty = self.typeOf(atomic_load.ptr); |
| ... | ... | @@ -16904,7 +16988,7 @@ fn airAtomicLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 16904 | 16988 | return self.finishAir(inst, dst_mcv, .{ atomic_load.ptr, .none, .none }); |
| 16905 | 16989 | } |
| 16906 | 16990 | |
| 16907 | | fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOrder) !void { |
| 16991 | fn airAtomicStore(self: *CodeGen, inst: Air.Inst.Index, order: std.builtin.AtomicOrder) !void { |
| 16908 | 16992 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 16909 | 16993 | |
| 16910 | 16994 | const ptr_ty = self.typeOf(bin_op.lhs); |
| ... | ... | @@ -16917,7 +17001,7 @@ fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOr |
| 16917 | 17001 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 16918 | 17002 | } |
| 16919 | 17003 | |
| 16920 | | fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 17004 | fn airMemset(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void { |
| 16921 | 17005 | const pt = self.pt; |
| 16922 | 17006 | const zcu = pt.zcu; |
| 16923 | 17007 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -17059,7 +17143,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 17059 | 17143 | return self.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 17060 | 17144 | } |
| 17061 | 17145 | |
| 17062 | | fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { |
| 17146 | fn airMemcpy(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 17063 | 17147 | const pt = self.pt; |
| 17064 | 17148 | const zcu = pt.zcu; |
| 17065 | 17149 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| ... | ... | @@ -17107,7 +17191,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { |
| 17107 | 17191 | else => try self.asmRegisterMemoryImmediate( |
| 17108 | 17192 | .{ .i_, .mul }, |
| 17109 | 17193 | len_reg, |
| 17110 | | try dst.address().offset(8).deref().mem(self, .qword), |
| 17194 | try dst.address().offset(8).deref().mem(self, .{ .size = .qword }), |
| 17111 | 17195 | .s(@intCast(dst_ty.childType(zcu).abiSize(zcu))), |
| 17112 | 17196 | ), |
| 17113 | 17197 | } |
| ... | ... | @@ -17139,7 +17223,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { |
| 17139 | 17223 | return self.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 17140 | 17224 | } |
| 17141 | 17225 | |
| 17142 | | fn airTagName(self: *Self, inst: Air.Inst.Index) !void { |
| 17226 | fn airTagName(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 17143 | 17227 | const pt = self.pt; |
| 17144 | 17228 | const zcu = pt.zcu; |
| 17145 | 17229 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| ... | ... | @@ -17179,7 +17263,7 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void { |
| 17179 | 17263 | return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none }); |
| 17180 | 17264 | } |
| 17181 | 17265 | |
| 17182 | | fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { |
| 17266 | fn airErrorName(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 17183 | 17267 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 17184 | 17268 | |
| 17185 | 17269 | const err_ty = self.typeOf(un_op); |
| ... | ... | @@ -17281,7 +17365,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { |
| 17281 | 17365 | return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none }); |
| 17282 | 17366 | } |
| 17283 | 17367 | |
| 17284 | | fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 17368 | fn airSplat(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 17285 | 17369 | const pt = self.pt; |
| 17286 | 17370 | const zcu = pt.zcu; |
| 17287 | 17371 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -17318,7 +17402,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 17318 | 17402 | else => cc: { |
| 17319 | 17403 | try self.asmMemoryImmediate( |
| 17320 | 17404 | .{ ._, .@"test" }, |
| 17321 | | try src_mcv.mem(self, .byte), |
| 17405 | try src_mcv.mem(self, .{ .size = .byte }), |
| 17322 | 17406 | .u(1), |
| 17323 | 17407 | ); |
| 17324 | 17408 | break :cc .nz; |
| ... | ... | @@ -17362,7 +17446,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 17362 | 17446 | if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 17363 | 17447 | mir_tag, |
| 17364 | 17448 | registerAlias(dst_reg, @intCast(vector_ty.abiSize(zcu))), |
| 17365 | | try src_mcv.mem(self, self.memSize(scalar_ty)), |
| 17449 | try src_mcv.mem(self, .{ .size = self.memSize(scalar_ty) }), |
| 17366 | 17450 | ) else { |
| 17367 | 17451 | if (mir_tag[0] == .v_i128) break :avx2; |
| 17368 | 17452 | try self.genSetReg(dst_reg, scalar_ty, src_mcv, .{}); |
| ... | ... | @@ -17438,7 +17522,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 17438 | 17522 | if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 17439 | 17523 | .{ .v_ss, .broadcast }, |
| 17440 | 17524 | dst_reg.to128(), |
| 17441 | | try src_mcv.mem(self, .dword), |
| 17525 | try src_mcv.mem(self, .{ .size = .dword }), |
| 17442 | 17526 | ) else { |
| 17443 | 17527 | const src_reg = if (src_mcv.isRegister()) |
| 17444 | 17528 | src_mcv.getReg().? |
| ... | ... | @@ -17475,7 +17559,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 17475 | 17559 | if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 17476 | 17560 | .{ .v_ss, .broadcast }, |
| 17477 | 17561 | dst_reg.to256(), |
| 17478 | | try src_mcv.mem(self, .dword), |
| 17562 | try src_mcv.mem(self, .{ .size = .dword }), |
| 17479 | 17563 | ) else { |
| 17480 | 17564 | const src_reg = if (src_mcv.isRegister()) |
| 17481 | 17565 | src_mcv.getReg().? |
| ... | ... | @@ -17521,7 +17605,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 17521 | 17605 | if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 17522 | 17606 | if (self.hasFeature(.avx)) .{ .v_, .movddup } else .{ ._, .movddup }, |
| 17523 | 17607 | dst_reg.to128(), |
| 17524 | | try src_mcv.mem(self, .qword), |
| 17608 | try src_mcv.mem(self, .{ .size = .qword }), |
| 17525 | 17609 | ) else try self.asmRegisterRegister( |
| 17526 | 17610 | if (self.hasFeature(.avx)) .{ .v_, .movddup } else .{ ._, .movddup }, |
| 17527 | 17611 | dst_reg.to128(), |
| ... | ... | @@ -17546,7 +17630,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 17546 | 17630 | if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 17547 | 17631 | .{ .v_sd, .broadcast }, |
| 17548 | 17632 | dst_reg.to256(), |
| 17549 | | try src_mcv.mem(self, .qword), |
| 17633 | try src_mcv.mem(self, .{ .size = .qword }), |
| 17550 | 17634 | ) else { |
| 17551 | 17635 | const src_reg = if (src_mcv.isRegister()) |
| 17552 | 17636 | src_mcv.getReg().? |
| ... | ... | @@ -17589,7 +17673,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 17589 | 17673 | if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 17590 | 17674 | .{ .v_f128, .broadcast }, |
| 17591 | 17675 | dst_reg.to256(), |
| 17592 | | try src_mcv.mem(self, .xword), |
| 17676 | try src_mcv.mem(self, .{ .size = .xword }), |
| 17593 | 17677 | ) else { |
| 17594 | 17678 | const src_reg = if (src_mcv.isRegister()) |
| 17595 | 17679 | src_mcv.getReg().? |
| ... | ... | @@ -17616,7 +17700,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 17616 | 17700 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 17617 | 17701 | } |
| 17618 | 17702 | |
| 17619 | | fn airSelect(self: *Self, inst: Air.Inst.Index) !void { |
| 17703 | fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 17620 | 17704 | const pt = self.pt; |
| 17621 | 17705 | const zcu = pt.zcu; |
| 17622 | 17706 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| ... | ... | @@ -17695,7 +17779,7 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void { |
| 17695 | 17779 | else => unreachable, |
| 17696 | 17780 | }, .broadcast }, |
| 17697 | 17781 | mask_alias, |
| 17698 | | if (pred_mcv.isMemory()) try pred_mcv.mem(self, .byte) else .{ |
| 17782 | if (pred_mcv.isMemory()) try pred_mcv.mem(self, .{ .size = .byte }) else .{ |
| 17699 | 17783 | .base = .{ .reg = (try self.copyToTmpRegister( |
| 17700 | 17784 | Type.usize, |
| 17701 | 17785 | pred_mcv.address(), |
| ... | ... | @@ -17893,7 +17977,7 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void { |
| 17893 | 17977 | mir_tag, |
| 17894 | 17978 | dst_alias, |
| 17895 | 17979 | rhs_alias, |
| 17896 | | try lhs_mcv.mem(self, self.memSize(ty)), |
| 17980 | try lhs_mcv.mem(self, .{ .size = self.memSize(ty) }), |
| 17897 | 17981 | mask_alias, |
| 17898 | 17982 | ) else try self.asmRegisterRegisterRegisterRegister( |
| 17899 | 17983 | mir_tag, |
| ... | ... | @@ -17908,7 +17992,7 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void { |
| 17908 | 17992 | } else if (has_blend) if (lhs_mcv.isMemory()) try self.asmRegisterMemoryRegister( |
| 17909 | 17993 | mir_tag, |
| 17910 | 17994 | dst_alias, |
| 17911 | | try lhs_mcv.mem(self, self.memSize(ty)), |
| 17995 | try lhs_mcv.mem(self, .{ .size = self.memSize(ty) }), |
| 17912 | 17996 | mask_alias, |
| 17913 | 17997 | ) else try self.asmRegisterRegisterRegister( |
| 17914 | 17998 | mir_tag, |
| ... | ... | @@ -17933,7 +18017,7 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void { |
| 17933 | 18017 | if (rhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 17934 | 18018 | .{ mir_fixes, .andn }, |
| 17935 | 18019 | mask_alias, |
| 17936 | | try rhs_mcv.mem(self, .fromSize(abi_size)), |
| 18020 | try rhs_mcv.mem(self, .{ .size = .fromSize(abi_size) }), |
| 17937 | 18021 | ) else try self.asmRegisterRegister( |
| 17938 | 18022 | .{ mir_fixes, .andn }, |
| 17939 | 18023 | mask_alias, |
| ... | ... | @@ -17949,7 +18033,7 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void { |
| 17949 | 18033 | return self.finishAir(inst, result, .{ pl_op.operand, extra.lhs, extra.rhs }); |
| 17950 | 18034 | } |
| 17951 | 18035 | |
| 17952 | | fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18036 | fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 17953 | 18037 | const pt = self.pt; |
| 17954 | 18038 | const zcu = pt.zcu; |
| 17955 | 18039 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| ... | ... | @@ -18074,7 +18158,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18074 | 18158 | mir_tag, |
| 18075 | 18159 | dst_alias, |
| 18076 | 18160 | registerAlias(lhs_mcv.getReg() orelse dst_reg, max_abi_size), |
| 18077 | | try rhs_mcv.mem(self, .fromSize(max_abi_size)), |
| 18161 | try rhs_mcv.mem(self, .{ .size = .fromSize(max_abi_size) }), |
| 18078 | 18162 | ) else try self.asmRegisterRegisterRegister( |
| 18079 | 18163 | mir_tag, |
| 18080 | 18164 | dst_alias, |
| ... | ... | @@ -18086,7 +18170,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18086 | 18170 | ) else if (rhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 18087 | 18171 | mir_tag, |
| 18088 | 18172 | dst_alias, |
| 18089 | | try rhs_mcv.mem(self, .fromSize(max_abi_size)), |
| 18173 | try rhs_mcv.mem(self, .{ .size = .fromSize(max_abi_size) }), |
| 18090 | 18174 | ) else try self.asmRegisterRegister( |
| 18091 | 18175 | mir_tag, |
| 18092 | 18176 | dst_alias, |
| ... | ... | @@ -18135,7 +18219,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18135 | 18219 | if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate( |
| 18136 | 18220 | .{ if (has_avx) .vp_d else .p_d, .shuf }, |
| 18137 | 18221 | dst_alias, |
| 18138 | | try src_mcv.mem(self, .fromSize(max_abi_size)), |
| 18222 | try src_mcv.mem(self, .{ .size = .fromSize(max_abi_size) }), |
| 18139 | 18223 | .u(control), |
| 18140 | 18224 | ) else try self.asmRegisterRegisterImmediate( |
| 18141 | 18225 | .{ if (has_avx) .vp_d else .p_d, .shuf }, |
| ... | ... | @@ -18192,7 +18276,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18192 | 18276 | .{ .v_ps, .shuf }, |
| 18193 | 18277 | dst_alias, |
| 18194 | 18278 | registerAlias(lhs_mcv.getReg() orelse dst_reg, max_abi_size), |
| 18195 | | try rhs_mcv.mem(self, .fromSize(max_abi_size)), |
| 18279 | try rhs_mcv.mem(self, .{ .size = .fromSize(max_abi_size) }), |
| 18196 | 18280 | .u(control), |
| 18197 | 18281 | ) else try self.asmRegisterRegisterRegisterImmediate( |
| 18198 | 18282 | .{ .v_ps, .shuf }, |
| ... | ... | @@ -18206,7 +18290,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18206 | 18290 | ) else if (rhs_mcv.isMemory()) try self.asmRegisterMemoryImmediate( |
| 18207 | 18291 | .{ ._ps, .shuf }, |
| 18208 | 18292 | dst_alias, |
| 18209 | | try rhs_mcv.mem(self, .fromSize(max_abi_size)), |
| 18293 | try rhs_mcv.mem(self, .{ .size = .fromSize(max_abi_size) }), |
| 18210 | 18294 | .u(control), |
| 18211 | 18295 | ) else try self.asmRegisterRegisterImmediate( |
| 18212 | 18296 | .{ ._ps, .shuf }, |
| ... | ... | @@ -18259,7 +18343,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18259 | 18343 | .{ .v_pd, .shuf }, |
| 18260 | 18344 | dst_alias, |
| 18261 | 18345 | registerAlias(lhs_mcv.getReg() orelse dst_reg, max_abi_size), |
| 18262 | | try rhs_mcv.mem(self, .fromSize(max_abi_size)), |
| 18346 | try rhs_mcv.mem(self, .{ .size = .fromSize(max_abi_size) }), |
| 18263 | 18347 | .u(control), |
| 18264 | 18348 | ) else try self.asmRegisterRegisterRegisterImmediate( |
| 18265 | 18349 | .{ .v_pd, .shuf }, |
| ... | ... | @@ -18273,7 +18357,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18273 | 18357 | ) else if (rhs_mcv.isMemory()) try self.asmRegisterMemoryImmediate( |
| 18274 | 18358 | .{ ._pd, .shuf }, |
| 18275 | 18359 | dst_alias, |
| 18276 | | try rhs_mcv.mem(self, .fromSize(max_abi_size)), |
| 18360 | try rhs_mcv.mem(self, .{ .size = .fromSize(max_abi_size) }), |
| 18277 | 18361 | .u(control), |
| 18278 | 18362 | ) else try self.asmRegisterRegisterImmediate( |
| 18279 | 18363 | .{ ._pd, .shuf }, |
| ... | ... | @@ -18329,7 +18413,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18329 | 18413 | .{ .vp_d, .blend }, |
| 18330 | 18414 | registerAlias(dst_reg, dst_abi_size), |
| 18331 | 18415 | registerAlias(lhs_reg, dst_abi_size), |
| 18332 | | try rhs_mcv.mem(self, .fromSize(dst_abi_size)), |
| 18416 | try rhs_mcv.mem(self, .{ .size = .fromSize(dst_abi_size) }), |
| 18333 | 18417 | .u(expanded_control), |
| 18334 | 18418 | ) else try self.asmRegisterRegisterRegisterImmediate( |
| 18335 | 18419 | .{ .vp_d, .blend }, |
| ... | ... | @@ -18384,7 +18468,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18384 | 18468 | lhs_mcv.getReg().? |
| 18385 | 18469 | else |
| 18386 | 18470 | dst_reg, dst_abi_size), |
| 18387 | | try rhs_mcv.mem(self, .fromSize(dst_abi_size)), |
| 18471 | try rhs_mcv.mem(self, .{ .size = .fromSize(dst_abi_size) }), |
| 18388 | 18472 | .u(expanded_control), |
| 18389 | 18473 | ) else try self.asmRegisterRegisterRegisterImmediate( |
| 18390 | 18474 | .{ .vp_w, .blend }, |
| ... | ... | @@ -18401,7 +18485,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18401 | 18485 | ) else if (rhs_mcv.isMemory()) try self.asmRegisterMemoryImmediate( |
| 18402 | 18486 | .{ .p_w, .blend }, |
| 18403 | 18487 | registerAlias(dst_reg, dst_abi_size), |
| 18404 | | try rhs_mcv.mem(self, .fromSize(dst_abi_size)), |
| 18488 | try rhs_mcv.mem(self, .{ .size = .fromSize(dst_abi_size) }), |
| 18405 | 18489 | .u(expanded_control), |
| 18406 | 18490 | ) else try self.asmRegisterRegisterImmediate( |
| 18407 | 18491 | .{ .p_w, .blend }, |
| ... | ... | @@ -18445,7 +18529,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18445 | 18529 | lhs_mcv.getReg().? |
| 18446 | 18530 | else |
| 18447 | 18531 | dst_reg, dst_abi_size), |
| 18448 | | try rhs_mcv.mem(self, .fromSize(dst_abi_size)), |
| 18532 | try rhs_mcv.mem(self, .{ .size = .fromSize(dst_abi_size) }), |
| 18449 | 18533 | .u(expanded_control), |
| 18450 | 18534 | ) else try self.asmRegisterRegisterRegisterImmediate( |
| 18451 | 18535 | switch (elem_abi_size) { |
| ... | ... | @@ -18470,7 +18554,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18470 | 18554 | else => unreachable, |
| 18471 | 18555 | }, |
| 18472 | 18556 | registerAlias(dst_reg, dst_abi_size), |
| 18473 | | try rhs_mcv.mem(self, .fromSize(dst_abi_size)), |
| 18557 | try rhs_mcv.mem(self, .{ .size = .fromSize(dst_abi_size) }), |
| 18474 | 18558 | .u(expanded_control), |
| 18475 | 18559 | ) else try self.asmRegisterRegisterImmediate( |
| 18476 | 18560 | switch (elem_abi_size) { |
| ... | ... | @@ -18560,7 +18644,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18560 | 18644 | registerAlias(lhs_mcv.getReg().?, dst_abi_size) |
| 18561 | 18645 | else |
| 18562 | 18646 | dst_alias, |
| 18563 | | try rhs_mcv.mem(self, .fromSize(dst_abi_size)), |
| 18647 | try rhs_mcv.mem(self, .{ .size = .fromSize(dst_abi_size) }), |
| 18564 | 18648 | select_mask_alias, |
| 18565 | 18649 | ) else try self.asmRegisterRegisterRegisterRegister( |
| 18566 | 18650 | mir_tag, |
| ... | ... | @@ -18577,7 +18661,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18577 | 18661 | ) else if (rhs_mcv.isMemory()) try self.asmRegisterMemoryRegister( |
| 18578 | 18662 | mir_tag, |
| 18579 | 18663 | dst_alias, |
| 18580 | | try rhs_mcv.mem(self, .fromSize(dst_abi_size)), |
| 18664 | try rhs_mcv.mem(self, .{ .size = .fromSize(dst_abi_size) }), |
| 18581 | 18665 | select_mask_alias, |
| 18582 | 18666 | ) else try self.asmRegisterRegisterRegister( |
| 18583 | 18667 | mir_tag, |
| ... | ... | @@ -18620,7 +18704,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18620 | 18704 | if (lhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 18621 | 18705 | .{ mir_fixes, .andn }, |
| 18622 | 18706 | mask_alias, |
| 18623 | | try lhs_mcv.mem(self, .fromSize(dst_abi_size)), |
| 18707 | try lhs_mcv.mem(self, .{ .size = .fromSize(dst_abi_size) }), |
| 18624 | 18708 | ) else try self.asmRegisterRegister( |
| 18625 | 18709 | .{ mir_fixes, .andn }, |
| 18626 | 18710 | mask_alias, |
| ... | ... | @@ -18757,7 +18841,7 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 18757 | 18841 | return self.finishAir(inst, result, .{ extra.a, extra.b, .none }); |
| 18758 | 18842 | } |
| 18759 | 18843 | |
| 18760 | | fn airReduce(self: *Self, inst: Air.Inst.Index) !void { |
| 18844 | fn airReduce(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 18761 | 18845 | const pt = self.pt; |
| 18762 | 18846 | const zcu = pt.zcu; |
| 18763 | 18847 | const reduce = self.air.instructions.items(.data)[@intFromEnum(inst)].reduce; |
| ... | ... | @@ -18776,7 +18860,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void { |
| 18776 | 18860 | .Or => { |
| 18777 | 18861 | if (operand_mcv.isMemory()) try self.asmMemoryImmediate( |
| 18778 | 18862 | .{ ._, .@"test" }, |
| 18779 | | try operand_mcv.mem(self, .fromSize(abi_size)), |
| 18863 | try operand_mcv.mem(self, .{ .size = .fromSize(abi_size) }), |
| 18780 | 18864 | .u(mask), |
| 18781 | 18865 | ) else { |
| 18782 | 18866 | const operand_reg = registerAlias(if (operand_mcv.isRegister()) |
| ... | ... | @@ -18815,7 +18899,7 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void { |
| 18815 | 18899 | return self.finishAir(inst, result, .{ reduce.operand, .none, .none }); |
| 18816 | 18900 | } |
| 18817 | 18901 | |
| 18818 | | fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 18902 | fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 18819 | 18903 | const pt = self.pt; |
| 18820 | 18904 | const zcu = pt.zcu; |
| 18821 | 18905 | const result_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -19007,7 +19091,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 19007 | 19091 | return self.finishAirResult(inst, result); |
| 19008 | 19092 | } |
| 19009 | 19093 | |
| 19010 | | fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { |
| 19094 | fn airUnionInit(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 19011 | 19095 | const pt = self.pt; |
| 19012 | 19096 | const zcu = pt.zcu; |
| 19013 | 19097 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -19053,12 +19137,12 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { |
| 19053 | 19137 | return self.finishAir(inst, result, .{ extra.init, .none, .none }); |
| 19054 | 19138 | } |
| 19055 | 19139 | |
| 19056 | | fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void { |
| 19140 | fn airPrefetch(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 19057 | 19141 | const prefetch = self.air.instructions.items(.data)[@intFromEnum(inst)].prefetch; |
| 19058 | 19142 | return self.finishAir(inst, .unreach, .{ prefetch.ptr, .none, .none }); |
| 19059 | 19143 | } |
| 19060 | 19144 | |
| 19061 | | fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 19145 | fn airMulAdd(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 19062 | 19146 | const pt = self.pt; |
| 19063 | 19147 | const zcu = pt.zcu; |
| 19064 | 19148 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| ... | ... | @@ -19219,14 +19303,14 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 19219 | 19303 | mir_tag, |
| 19220 | 19304 | mop1_reg, |
| 19221 | 19305 | mop2_reg, |
| 19222 | | try mops[2].mem(self, .fromSize(abi_size)), |
| 19306 | try mops[2].mem(self, .{ .size = .fromSize(abi_size) }), |
| 19223 | 19307 | ); |
| 19224 | 19308 | break :result mops[0]; |
| 19225 | 19309 | }; |
| 19226 | 19310 | return self.finishAir(inst, result, ops); |
| 19227 | 19311 | } |
| 19228 | 19312 | |
| 19229 | | fn airVaStart(self: *Self, inst: Air.Inst.Index) !void { |
| 19313 | fn airVaStart(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 19230 | 19314 | const pt = self.pt; |
| 19231 | 19315 | const zcu = pt.zcu; |
| 19232 | 19316 | const va_list_ty = self.air.instructions.items(.data)[@intFromEnum(inst)].ty; |
| ... | ... | @@ -19284,7 +19368,7 @@ fn airVaStart(self: *Self, inst: Air.Inst.Index) !void { |
| 19284 | 19368 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 19285 | 19369 | } |
| 19286 | 19370 | |
| 19287 | | fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { |
| 19371 | fn airVaArg(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 19288 | 19372 | const pt = self.pt; |
| 19289 | 19373 | const zcu = pt.zcu; |
| 19290 | 19374 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -19451,7 +19535,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { |
| 19451 | 19535 | .{ .v_ss, .cvtsd2 }, |
| 19452 | 19536 | dst_reg, |
| 19453 | 19537 | dst_reg, |
| 19454 | | try promote_mcv.mem(self, .qword), |
| 19538 | try promote_mcv.mem(self, .{ .size = .qword }), |
| 19455 | 19539 | ) else try self.asmRegisterRegisterRegister( |
| 19456 | 19540 | .{ .v_ss, .cvtsd2 }, |
| 19457 | 19541 | dst_reg, |
| ... | ... | @@ -19463,7 +19547,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { |
| 19463 | 19547 | ) else if (promote_mcv.isMemory()) try self.asmRegisterMemory( |
| 19464 | 19548 | .{ ._ss, .cvtsd2 }, |
| 19465 | 19549 | dst_reg, |
| 19466 | | try promote_mcv.mem(self, .qword), |
| 19550 | try promote_mcv.mem(self, .{ .size = .qword }), |
| 19467 | 19551 | ) else try self.asmRegisterRegister( |
| 19468 | 19552 | .{ ._ss, .cvtsd2 }, |
| 19469 | 19553 | dst_reg, |
| ... | ... | @@ -19480,7 +19564,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { |
| 19480 | 19564 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 19481 | 19565 | } |
| 19482 | 19566 | |
| 19483 | | fn airVaCopy(self: *Self, inst: Air.Inst.Index) !void { |
| 19567 | fn airVaCopy(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 19484 | 19568 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 19485 | 19569 | const ptr_va_list_ty = self.typeOf(ty_op.operand); |
| 19486 | 19570 | |
| ... | ... | @@ -19489,12 +19573,12 @@ fn airVaCopy(self: *Self, inst: Air.Inst.Index) !void { |
| 19489 | 19573 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); |
| 19490 | 19574 | } |
| 19491 | 19575 | |
| 19492 | | fn airVaEnd(self: *Self, inst: Air.Inst.Index) !void { |
| 19576 | fn airVaEnd(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 19493 | 19577 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 19494 | 19578 | return self.finishAir(inst, .unreach, .{ un_op, .none, .none }); |
| 19495 | 19579 | } |
| 19496 | 19580 | |
| 19497 | | fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { |
| 19581 | fn resolveInst(self: *CodeGen, ref: Air.Inst.Ref) InnerError!MCValue { |
| 19498 | 19582 | const zcu = self.pt.zcu; |
| 19499 | 19583 | const ty = self.typeOf(ref); |
| 19500 | 19584 | |
| ... | ... | @@ -19543,7 +19627,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { |
| 19543 | 19627 | } |
| 19544 | 19628 | } |
| 19545 | 19629 | |
| 19546 | | fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) *InstTracking { |
| 19630 | fn getResolvedInstValue(self: *CodeGen, inst: Air.Inst.Index) *InstTracking { |
| 19547 | 19631 | const tracking = self.inst_tracking.getPtr(inst).?; |
| 19548 | 19632 | return switch (tracking.short) { |
| 19549 | 19633 | .none, .unreach, .dead => unreachable, |
| ... | ... | @@ -19556,7 +19640,7 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) *InstTracking { |
| 19556 | 19640 | /// A potential opportunity for future optimization here would be keeping track |
| 19557 | 19641 | /// of the fact that the instruction is available both as an immediate |
| 19558 | 19642 | /// and as a register. |
| 19559 | | fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCValue { |
| 19643 | fn limitImmediateType(self: *CodeGen, operand: Air.Inst.Ref, comptime T: type) !MCValue { |
| 19560 | 19644 | const mcv = try self.resolveInst(operand); |
| 19561 | 19645 | const ti = @typeInfo(T).int; |
| 19562 | 19646 | switch (mcv) { |
| ... | ... | @@ -19572,7 +19656,7 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV |
| 19572 | 19656 | return mcv; |
| 19573 | 19657 | } |
| 19574 | 19658 | |
| 19575 | | fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { |
| 19659 | fn genTypedValue(self: *CodeGen, val: Value) InnerError!MCValue { |
| 19576 | 19660 | const pt = self.pt; |
| 19577 | 19661 | return switch (try codegen.genTypedValue(self.bin_file, pt, self.src_loc, val, self.target.*)) { |
| 19578 | 19662 | .mcv => |mcv| switch (mcv) { |
| ... | ... | @@ -19599,7 +19683,7 @@ const CallMCValues = struct { |
| 19599 | 19683 | gp_count: u32, |
| 19600 | 19684 | fp_count: u32, |
| 19601 | 19685 | |
| 19602 | | fn deinit(self: *CallMCValues, func: *Self) void { |
| 19686 | fn deinit(self: *CallMCValues, func: *CodeGen) void { |
| 19603 | 19687 | func.gpa.free(self.args); |
| 19604 | 19688 | self.* = undefined; |
| 19605 | 19689 | } |
| ... | ... | @@ -19607,7 +19691,7 @@ const CallMCValues = struct { |
| 19607 | 19691 | |
| 19608 | 19692 | /// Caller must call `CallMCValues.deinit`. |
| 19609 | 19693 | fn resolveCallingConventionValues( |
| 19610 | | self: *Self, |
| 19694 | self: *CodeGen, |
| 19611 | 19695 | fn_info: InternPool.Key.FuncType, |
| 19612 | 19696 | var_args: []const Type, |
| 19613 | 19697 | stack_frame_base: FrameIndex, |
| ... | ... | @@ -19889,7 +19973,7 @@ fn resolveCallingConventionValues( |
| 19889 | 19973 | return result; |
| 19890 | 19974 | } |
| 19891 | 19975 | |
| 19892 | | fn fail(self: *Self, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } { |
| 19976 | fn fail(self: *CodeGen, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } { |
| 19893 | 19977 | @branchHint(.cold); |
| 19894 | 19978 | const zcu = self.pt.zcu; |
| 19895 | 19979 | switch (self.owner) { |
| ... | ... | @@ -19899,7 +19983,7 @@ fn fail(self: *Self, comptime format: []const u8, args: anytype) error{ OutOfMem |
| 19899 | 19983 | return error.CodegenFail; |
| 19900 | 19984 | } |
| 19901 | 19985 | |
| 19902 | | fn failMsg(self: *Self, msg: *Zcu.ErrorMsg) error{ OutOfMemory, CodegenFail } { |
| 19986 | fn failMsg(self: *CodeGen, msg: *Zcu.ErrorMsg) error{ OutOfMemory, CodegenFail } { |
| 19903 | 19987 | @branchHint(.cold); |
| 19904 | 19988 | const zcu = self.pt.zcu; |
| 19905 | 19989 | switch (self.owner) { |
| ... | ... | @@ -19960,7 +20044,7 @@ fn registerAlias(reg: Register, size_bytes: u32) Register { |
| 19960 | 20044 | }; |
| 19961 | 20045 | } |
| 19962 | 20046 | |
| 19963 | | fn memSize(self: *Self, ty: Type) Memory.Size { |
| 20047 | fn memSize(self: *CodeGen, ty: Type) Memory.Size { |
| 19964 | 20048 | const zcu = self.pt.zcu; |
| 19965 | 20049 | return switch (ty.zigTypeTag(zcu)) { |
| 19966 | 20050 | .float => .fromBitSize(ty.floatBits(self.target.*)), |
| ... | ... | @@ -19968,7 +20052,7 @@ fn memSize(self: *Self, ty: Type) Memory.Size { |
| 19968 | 20052 | }; |
| 19969 | 20053 | } |
| 19970 | 20054 | |
| 19971 | | fn splitType(self: *Self, ty: Type) ![2]Type { |
| 20055 | fn splitType(self: *CodeGen, ty: Type) ![2]Type { |
| 19972 | 20056 | const pt = self.pt; |
| 19973 | 20057 | const zcu = pt.zcu; |
| 19974 | 20058 | const classes = std.mem.sliceTo(&abi.classifySystemV(ty, zcu, self.target.*, .other), .none); |
| ... | ... | @@ -19998,7 +20082,7 @@ fn splitType(self: *Self, ty: Type) ![2]Type { |
| 19998 | 20082 | |
| 19999 | 20083 | /// Truncates the value in the register in place. |
| 20000 | 20084 | /// Clobbers any remaining bits. |
| 20001 | | fn truncateRegister(self: *Self, ty: Type, reg: Register) !void { |
| 20085 | fn truncateRegister(self: *CodeGen, ty: Type, reg: Register) !void { |
| 20002 | 20086 | const pt = self.pt; |
| 20003 | 20087 | const zcu = pt.zcu; |
| 20004 | 20088 | const int_info = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else std.builtin.Type.Int{ |
| ... | ... | @@ -20046,7 +20130,7 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void { |
| 20046 | 20130 | } |
| 20047 | 20131 | } |
| 20048 | 20132 | |
| 20049 | | fn regBitSize(self: *Self, ty: Type) u64 { |
| 20133 | fn regBitSize(self: *CodeGen, ty: Type) u64 { |
| 20050 | 20134 | const zcu = self.pt.zcu; |
| 20051 | 20135 | const abi_size = ty.abiSize(zcu); |
| 20052 | 20136 | return switch (ty.zigTypeTag(zcu)) { |
| ... | ... | @@ -20065,27 +20149,27 @@ fn regBitSize(self: *Self, ty: Type) u64 { |
| 20065 | 20149 | }; |
| 20066 | 20150 | } |
| 20067 | 20151 | |
| 20068 | | fn regExtraBits(self: *Self, ty: Type) u64 { |
| 20152 | fn regExtraBits(self: *CodeGen, ty: Type) u64 { |
| 20069 | 20153 | return self.regBitSize(ty) - ty.bitSize(self.pt.zcu); |
| 20070 | 20154 | } |
| 20071 | 20155 | |
| 20072 | | fn hasFeature(self: *Self, feature: std.Target.x86.Feature) bool { |
| 20156 | fn hasFeature(self: *CodeGen, feature: std.Target.x86.Feature) bool { |
| 20073 | 20157 | return std.Target.x86.featureSetHas(self.target.cpu.features, feature); |
| 20074 | 20158 | } |
| 20075 | | fn hasAnyFeatures(self: *Self, features: anytype) bool { |
| 20159 | fn hasAnyFeatures(self: *CodeGen, features: anytype) bool { |
| 20076 | 20160 | return std.Target.x86.featureSetHasAny(self.target.cpu.features, features); |
| 20077 | 20161 | } |
| 20078 | | fn hasAllFeatures(self: *Self, features: anytype) bool { |
| 20162 | fn hasAllFeatures(self: *CodeGen, features: anytype) bool { |
| 20079 | 20163 | return std.Target.x86.featureSetHasAll(self.target.cpu.features, features); |
| 20080 | 20164 | } |
| 20081 | 20165 | |
| 20082 | | fn typeOf(self: *Self, inst: Air.Inst.Ref) Type { |
| 20166 | fn typeOf(self: *CodeGen, inst: Air.Inst.Ref) Type { |
| 20083 | 20167 | const pt = self.pt; |
| 20084 | 20168 | const zcu = pt.zcu; |
| 20085 | 20169 | return self.air.typeOf(inst, &zcu.intern_pool); |
| 20086 | 20170 | } |
| 20087 | 20171 | |
| 20088 | | fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type { |
| 20172 | fn typeOfIndex(self: *CodeGen, inst: Air.Inst.Index) Type { |
| 20089 | 20173 | const pt = self.pt; |
| 20090 | 20174 | const zcu = pt.zcu; |
| 20091 | 20175 | const temp: Temp = .{ .index = inst }; |
| ... | ... | @@ -20118,7 +20202,7 @@ fn floatCompilerRtAbiName(float_bits: u32) u8 { |
| 20118 | 20202 | }; |
| 20119 | 20203 | } |
| 20120 | 20204 | |
| 20121 | | fn floatCompilerRtAbiType(self: *Self, ty: Type, other_ty: Type) Type { |
| 20205 | fn floatCompilerRtAbiType(self: *CodeGen, ty: Type, other_ty: Type) Type { |
| 20122 | 20206 | if (ty.toIntern() == .f16_type and |
| 20123 | 20207 | (other_ty.toIntern() == .f32_type or other_ty.toIntern() == .f64_type) and |
| 20124 | 20208 | self.target.isDarwin()) return Type.u16; |
| ... | ... | @@ -20145,7 +20229,7 @@ fn floatLibcAbiSuffix(ty: Type) []const u8 { |
| 20145 | 20229 | }; |
| 20146 | 20230 | } |
| 20147 | 20231 | |
| 20148 | | fn promoteInt(self: *Self, ty: Type) Type { |
| 20232 | fn promoteInt(self: *CodeGen, ty: Type) Type { |
| 20149 | 20233 | const pt = self.pt; |
| 20150 | 20234 | const zcu = pt.zcu; |
| 20151 | 20235 | const int_info: InternPool.Key.IntType = switch (ty.toIntern()) { |
| ... | ... | @@ -20165,7 +20249,7 @@ fn promoteInt(self: *Self, ty: Type) Type { |
| 20165 | 20249 | return ty; |
| 20166 | 20250 | } |
| 20167 | 20251 | |
| 20168 | | fn promoteVarArg(self: *Self, ty: Type) Type { |
| 20252 | fn promoteVarArg(self: *CodeGen, ty: Type) Type { |
| 20169 | 20253 | if (!ty.isRuntimeFloat()) return self.promoteInt(ty); |
| 20170 | 20254 | switch (ty.floatBits(self.target.*)) { |
| 20171 | 20255 | 32, 64 => return Type.f64, |
| ... | ... | @@ -20181,7 +20265,7 @@ fn promoteVarArg(self: *Self, ty: Type) Type { |
| 20181 | 20265 | const Temp = struct { |
| 20182 | 20266 | index: Air.Inst.Index, |
| 20183 | 20267 | |
| 20184 | | fn unwrap(temp: Temp, self: *Self) union(enum) { |
| 20268 | fn unwrap(temp: Temp, cg: *CodeGen) union(enum) { |
| 20185 | 20269 | ref: Air.Inst.Ref, |
| 20186 | 20270 | temp: Index, |
| 20187 | 20271 | } { |
| ... | ... | @@ -20189,38 +20273,69 @@ const Temp = struct { |
| 20189 | 20273 | .ref => |ref| return .{ .ref = ref }, |
| 20190 | 20274 | .target => |target_index| { |
| 20191 | 20275 | const temp_index: Index = @enumFromInt(target_index); |
| 20192 | | assert(temp_index.isValid(self)); |
| 20276 | assert(temp_index.isValid(cg)); |
| 20193 | 20277 | return .{ .temp = temp_index }; |
| 20194 | 20278 | }, |
| 20195 | 20279 | } |
| 20196 | 20280 | } |
| 20197 | 20281 | |
| 20198 | | fn typeOf(temp: Temp, self: *Self) Type { |
| 20199 | | return switch (temp.unwrap(self)) { |
| 20200 | | .ref => |ref| self.typeOf(ref), |
| 20201 | | .temp => |temp_index| temp_index.typeOf(self), |
| 20282 | fn typeOf(temp: Temp, cg: *CodeGen) Type { |
| 20283 | return switch (temp.unwrap(cg)) { |
| 20284 | .ref => |ref| cg.typeOf(ref), |
| 20285 | .temp => |temp_index| temp_index.typeOf(cg), |
| 20202 | 20286 | }; |
| 20203 | 20287 | } |
| 20204 | 20288 | |
| 20205 | | fn isMut(temp: Temp, self: *Self) bool { |
| 20206 | | return temp.unwrap(self) == .temp; |
| 20289 | fn isMut(temp: Temp, cg: *CodeGen) bool { |
| 20290 | return switch (temp.unwrap(cg)) { |
| 20291 | .ref => false, |
| 20292 | .temp => |temp_index| switch (temp_index.tracking(cg).short) { |
| 20293 | .none, |
| 20294 | .unreach, |
| 20295 | .dead, |
| 20296 | .undef, |
| 20297 | .immediate, |
| 20298 | .eflags, |
| 20299 | .register_offset, |
| 20300 | .memory, |
| 20301 | .load_symbol, |
| 20302 | .lea_symbol, |
| 20303 | .indirect, |
| 20304 | .load_direct, |
| 20305 | .lea_direct, |
| 20306 | .load_got, |
| 20307 | .lea_got, |
| 20308 | .load_tlv, |
| 20309 | .lea_tlv, |
| 20310 | .lea_frame, |
| 20311 | .elementwise_regs_then_frame, |
| 20312 | .reserved_frame, |
| 20313 | .air_ref, |
| 20314 | => false, |
| 20315 | .register, |
| 20316 | .register_pair, |
| 20317 | .register_overflow, |
| 20318 | => true, |
| 20319 | .load_frame => |frame_addr| !frame_addr.index.isNamed(), |
| 20320 | }, |
| 20321 | }; |
| 20207 | 20322 | } |
| 20208 | 20323 | |
| 20209 | | fn tracking(temp: Temp, self: *Self) InstTracking { |
| 20210 | | return self.inst_tracking.get(temp.index).?; |
| 20324 | fn tracking(temp: Temp, cg: *CodeGen) InstTracking { |
| 20325 | return cg.inst_tracking.get(temp.index).?; |
| 20211 | 20326 | } |
| 20212 | 20327 | |
| 20213 | | fn getOffset(temp: Temp, off: i32, self: *Self) !Temp { |
| 20214 | | const new_temp_index = self.next_temp_index; |
| 20215 | | self.temp_type[@intFromEnum(new_temp_index)] = Type.usize; |
| 20216 | | self.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1); |
| 20217 | | switch (temp.tracking(self).short) { |
| 20328 | fn getOffset(temp: Temp, off: i32, cg: *CodeGen) !Temp { |
| 20329 | const new_temp_index = cg.next_temp_index; |
| 20330 | cg.temp_type[@intFromEnum(new_temp_index)] = Type.usize; |
| 20331 | cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1); |
| 20332 | switch (temp.tracking(cg).short) { |
| 20218 | 20333 | else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }), |
| 20219 | 20334 | .register => |reg| { |
| 20220 | 20335 | const new_reg = |
| 20221 | | try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20222 | | new_temp_index.tracking(self).* = .init(.{ .register = new_reg }); |
| 20223 | | try self.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{ |
| 20336 | try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20337 | new_temp_index.tracking(cg).* = .init(.{ .register = new_reg }); |
| 20338 | try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{ |
| 20224 | 20339 | .base = .{ .reg = reg.to64() }, |
| 20225 | 20340 | .mod = .{ .rm = .{ |
| 20226 | 20341 | .size = .qword, |
| ... | ... | @@ -20230,9 +20345,9 @@ const Temp = struct { |
| 20230 | 20345 | }, |
| 20231 | 20346 | .register_offset => |reg_off| { |
| 20232 | 20347 | const new_reg = |
| 20233 | | try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20234 | | new_temp_index.tracking(self).* = .init(.{ .register = new_reg }); |
| 20235 | | try self.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{ |
| 20348 | try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20349 | new_temp_index.tracking(cg).* = .init(.{ .register = new_reg }); |
| 20350 | try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{ |
| 20236 | 20351 | .base = .{ .reg = reg_off.reg.to64() }, |
| 20237 | 20352 | .mod = .{ .rm = .{ |
| 20238 | 20353 | .size = .qword, |
| ... | ... | @@ -20240,18 +20355,18 @@ const Temp = struct { |
| 20240 | 20355 | } }, |
| 20241 | 20356 | }); |
| 20242 | 20357 | }, |
| 20243 | | .lea_symbol => |sym_off| new_temp_index.tracking(self).* = .init(.{ .lea_symbol = .{ |
| 20358 | .lea_symbol => |sym_off| new_temp_index.tracking(cg).* = .init(.{ .lea_symbol = .{ |
| 20244 | 20359 | .sym_index = sym_off.sym_index, |
| 20245 | 20360 | .off = sym_off.off + off, |
| 20246 | 20361 | } }), |
| 20247 | 20362 | .load_frame => |frame_addr| { |
| 20248 | 20363 | const new_reg = |
| 20249 | | try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20250 | | new_temp_index.tracking(self).* = .init(.{ .register_offset = .{ |
| 20364 | try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20365 | new_temp_index.tracking(cg).* = .init(.{ .register_offset = .{ |
| 20251 | 20366 | .reg = new_reg, |
| 20252 | 20367 | .off = off, |
| 20253 | 20368 | } }); |
| 20254 | | try self.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{ |
| 20369 | try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{ |
| 20255 | 20370 | .base = .{ .frame = frame_addr.index }, |
| 20256 | 20371 | .mod = .{ .rm = .{ |
| 20257 | 20372 | .size = .qword, |
| ... | ... | @@ -20259,7 +20374,7 @@ const Temp = struct { |
| 20259 | 20374 | } }, |
| 20260 | 20375 | }); |
| 20261 | 20376 | }, |
| 20262 | | .lea_frame => |frame_addr| new_temp_index.tracking(self).* = .init(.{ .lea_frame = .{ |
| 20377 | .lea_frame => |frame_addr| new_temp_index.tracking(cg).* = .init(.{ .lea_frame = .{ |
| 20263 | 20378 | .index = frame_addr.index, |
| 20264 | 20379 | .off = frame_addr.off + off, |
| 20265 | 20380 | } }), |
| ... | ... | @@ -20267,16 +20382,16 @@ const Temp = struct { |
| 20267 | 20382 | return .{ .index = new_temp_index.toIndex() }; |
| 20268 | 20383 | } |
| 20269 | 20384 | |
| 20270 | | fn toOffset(temp: *Temp, off: i32, self: *Self) !void { |
| 20385 | fn toOffset(temp: *Temp, off: i32, cg: *CodeGen) !void { |
| 20271 | 20386 | if (off == 0) return; |
| 20272 | | switch (temp.unwrap(self)) { |
| 20387 | switch (temp.unwrap(cg)) { |
| 20273 | 20388 | .ref => {}, |
| 20274 | 20389 | .temp => |temp_index| { |
| 20275 | | const temp_tracking = temp_index.tracking(self); |
| 20390 | const temp_tracking = temp_index.tracking(cg); |
| 20276 | 20391 | switch (temp_tracking.short) { |
| 20277 | 20392 | else => {}, |
| 20278 | 20393 | .register => |reg| { |
| 20279 | | try self.freeValue(temp_tracking.long); |
| 20394 | try cg.freeValue(temp_tracking.long); |
| 20280 | 20395 | temp_tracking.* = .init(.{ .register_offset = .{ |
| 20281 | 20396 | .reg = reg, |
| 20282 | 20397 | .off = off, |
| ... | ... | @@ -20284,7 +20399,7 @@ const Temp = struct { |
| 20284 | 20399 | return; |
| 20285 | 20400 | }, |
| 20286 | 20401 | .register_offset => |reg_off| { |
| 20287 | | try self.freeValue(temp_tracking.long); |
| 20402 | try cg.freeValue(temp_tracking.long); |
| 20288 | 20403 | temp_tracking.* = .init(.{ .register_offset = .{ |
| 20289 | 20404 | .reg = reg_off.reg, |
| 20290 | 20405 | .off = reg_off.off + off, |
| ... | ... | @@ -20310,39 +20425,39 @@ const Temp = struct { |
| 20310 | 20425 | } |
| 20311 | 20426 | }, |
| 20312 | 20427 | } |
| 20313 | | const new_temp = try temp.getOffset(off, self); |
| 20314 | | try temp.die(self); |
| 20428 | const new_temp = try temp.getOffset(off, cg); |
| 20429 | try temp.die(cg); |
| 20315 | 20430 | temp.* = new_temp; |
| 20316 | 20431 | } |
| 20317 | 20432 | |
| 20318 | | fn getLimb(temp: Temp, limb_index: u28, self: *Self) !Temp { |
| 20319 | | const new_temp_index = self.next_temp_index; |
| 20320 | | self.temp_type[@intFromEnum(new_temp_index)] = Type.usize; |
| 20321 | | switch (temp.tracking(self).short) { |
| 20433 | fn getLimb(temp: Temp, limb_index: u28, cg: *CodeGen) !Temp { |
| 20434 | const new_temp_index = cg.next_temp_index; |
| 20435 | cg.temp_type[@intFromEnum(new_temp_index)] = Type.usize; |
| 20436 | switch (temp.tracking(cg).short) { |
| 20322 | 20437 | else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }), |
| 20323 | 20438 | .immediate => |imm| { |
| 20324 | 20439 | assert(limb_index == 0); |
| 20325 | | new_temp_index.tracking(self).* = .init(.{ .immediate = imm }); |
| 20440 | new_temp_index.tracking(cg).* = .init(.{ .immediate = imm }); |
| 20326 | 20441 | }, |
| 20327 | 20442 | .register => |reg| { |
| 20328 | 20443 | assert(limb_index == 0); |
| 20329 | 20444 | const new_reg = |
| 20330 | | try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20331 | | new_temp_index.tracking(self).* = .init(.{ .register = new_reg }); |
| 20332 | | try self.asmRegisterRegister(.{ ._, .mov }, new_reg.to64(), reg.to64()); |
| 20445 | try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20446 | new_temp_index.tracking(cg).* = .init(.{ .register = new_reg }); |
| 20447 | try cg.asmRegisterRegister(.{ ._, .mov }, new_reg.to64(), reg.to64()); |
| 20333 | 20448 | }, |
| 20334 | 20449 | .register_pair => |regs| { |
| 20335 | 20450 | const new_reg = |
| 20336 | | try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20337 | | new_temp_index.tracking(self).* = .init(.{ .register = new_reg }); |
| 20338 | | try self.asmRegisterRegister(.{ ._, .mov }, new_reg.to64(), regs[limb_index].to64()); |
| 20451 | try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20452 | new_temp_index.tracking(cg).* = .init(.{ .register = new_reg }); |
| 20453 | try cg.asmRegisterRegister(.{ ._, .mov }, new_reg.to64(), regs[limb_index].to64()); |
| 20339 | 20454 | }, |
| 20340 | 20455 | .register_offset => |reg_off| { |
| 20341 | 20456 | assert(limb_index == 0); |
| 20342 | 20457 | const new_reg = |
| 20343 | | try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20344 | | new_temp_index.tracking(self).* = .init(.{ .register = new_reg }); |
| 20345 | | try self.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{ |
| 20458 | try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20459 | new_temp_index.tracking(cg).* = .init(.{ .register = new_reg }); |
| 20460 | try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{ |
| 20346 | 20461 | .base = .{ .reg = reg_off.reg.to64() }, |
| 20347 | 20462 | .mod = .{ .rm = .{ |
| 20348 | 20463 | .size = .qword, |
| ... | ... | @@ -20352,9 +20467,9 @@ const Temp = struct { |
| 20352 | 20467 | }, |
| 20353 | 20468 | .load_symbol => |sym_off| { |
| 20354 | 20469 | const new_reg = |
| 20355 | | try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20356 | | new_temp_index.tracking(self).* = .init(.{ .register = new_reg }); |
| 20357 | | try self.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{ |
| 20470 | try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20471 | new_temp_index.tracking(cg).* = .init(.{ .register = new_reg }); |
| 20472 | try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{ |
| 20358 | 20473 | .base = .{ .reloc = sym_off.sym_index }, |
| 20359 | 20474 | .mod = .{ .rm = .{ |
| 20360 | 20475 | .size = .qword, |
| ... | ... | @@ -20364,13 +20479,13 @@ const Temp = struct { |
| 20364 | 20479 | }, |
| 20365 | 20480 | .lea_symbol => |sym_off| { |
| 20366 | 20481 | assert(limb_index == 0); |
| 20367 | | new_temp_index.tracking(self).* = .init(.{ .lea_symbol = sym_off }); |
| 20482 | new_temp_index.tracking(cg).* = .init(.{ .lea_symbol = sym_off }); |
| 20368 | 20483 | }, |
| 20369 | 20484 | .load_frame => |frame_addr| { |
| 20370 | 20485 | const new_reg = |
| 20371 | | try self.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20372 | | new_temp_index.tracking(self).* = .init(.{ .register = new_reg }); |
| 20373 | | try self.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{ |
| 20486 | try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20487 | new_temp_index.tracking(cg).* = .init(.{ .register = new_reg }); |
| 20488 | try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{ |
| 20374 | 20489 | .base = .{ .frame = frame_addr.index }, |
| 20375 | 20490 | .mod = .{ .rm = .{ |
| 20376 | 20491 | .size = .qword, |
| ... | ... | @@ -20380,23 +20495,23 @@ const Temp = struct { |
| 20380 | 20495 | }, |
| 20381 | 20496 | .lea_frame => |frame_addr| { |
| 20382 | 20497 | assert(limb_index == 0); |
| 20383 | | new_temp_index.tracking(self).* = .init(.{ .lea_frame = frame_addr }); |
| 20498 | new_temp_index.tracking(cg).* = .init(.{ .lea_frame = frame_addr }); |
| 20384 | 20499 | }, |
| 20385 | 20500 | } |
| 20386 | | self.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1); |
| 20501 | cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1); |
| 20387 | 20502 | return .{ .index = new_temp_index.toIndex() }; |
| 20388 | 20503 | } |
| 20389 | 20504 | |
| 20390 | | fn toLimb(temp: *Temp, limb_index: u28, self: *Self) !void { |
| 20391 | | switch (temp.unwrap(self)) { |
| 20505 | fn toLimb(temp: *Temp, limb_index: u28, cg: *CodeGen) !void { |
| 20506 | switch (temp.unwrap(cg)) { |
| 20392 | 20507 | .ref => {}, |
| 20393 | 20508 | .temp => |temp_index| { |
| 20394 | | const temp_tracking = temp_index.tracking(self); |
| 20509 | const temp_tracking = temp_index.tracking(cg); |
| 20395 | 20510 | switch (temp_tracking.short) { |
| 20396 | 20511 | else => {}, |
| 20397 | 20512 | .register, .lea_symbol, .lea_frame => { |
| 20398 | 20513 | assert(limb_index == 0); |
| 20399 | | self.temp_type[@intFromEnum(temp_index)] = Type.usize; |
| 20514 | cg.temp_type[@intFromEnum(temp_index)] = Type.usize; |
| 20400 | 20515 | return; |
| 20401 | 20516 | }, |
| 20402 | 20517 | .register_pair => |regs| { |
| ... | ... | @@ -20406,9 +20521,9 @@ const Temp = struct { |
| 20406 | 20521 | temp_tracking.long.address().offset(@as(u31, limb_index) * 8).deref(), |
| 20407 | 20522 | } |
| 20408 | 20523 | for (regs, 0..) |reg, reg_index| if (reg_index != limb_index) |
| 20409 | | self.register_manager.freeReg(reg); |
| 20524 | cg.register_manager.freeReg(reg); |
| 20410 | 20525 | temp_tracking.* = .init(.{ .register = regs[limb_index] }); |
| 20411 | | self.temp_type[@intFromEnum(temp_index)] = Type.usize; |
| 20526 | cg.temp_type[@intFromEnum(temp_index)] = Type.usize; |
| 20412 | 20527 | return; |
| 20413 | 20528 | }, |
| 20414 | 20529 | .load_symbol => |sym_off| { |
| ... | ... | @@ -20417,7 +20532,7 @@ const Temp = struct { |
| 20417 | 20532 | .sym_index = sym_off.sym_index, |
| 20418 | 20533 | .off = sym_off.off + @as(u31, limb_index) * 8, |
| 20419 | 20534 | } }); |
| 20420 | | self.temp_type[@intFromEnum(temp_index)] = Type.usize; |
| 20535 | cg.temp_type[@intFromEnum(temp_index)] = Type.usize; |
| 20421 | 20536 | return; |
| 20422 | 20537 | }, |
| 20423 | 20538 | .load_frame => |frame_addr| if (!frame_addr.index.isNamed()) { |
| ... | ... | @@ -20426,102 +20541,102 @@ const Temp = struct { |
| 20426 | 20541 | .index = frame_addr.index, |
| 20427 | 20542 | .off = frame_addr.off + @as(u31, limb_index) * 8, |
| 20428 | 20543 | } }); |
| 20429 | | self.temp_type[@intFromEnum(temp_index)] = Type.usize; |
| 20544 | cg.temp_type[@intFromEnum(temp_index)] = Type.usize; |
| 20430 | 20545 | return; |
| 20431 | 20546 | }, |
| 20432 | 20547 | } |
| 20433 | 20548 | }, |
| 20434 | 20549 | } |
| 20435 | | const new_temp = try temp.getLimb(limb_index, self); |
| 20436 | | try temp.die(self); |
| 20550 | const new_temp = try temp.getLimb(limb_index, cg); |
| 20551 | try temp.die(cg); |
| 20437 | 20552 | temp.* = new_temp; |
| 20438 | 20553 | } |
| 20439 | 20554 | |
| 20440 | | fn toReg(temp: *Temp, new_reg: Register, self: *Self) !bool { |
| 20441 | | const val, const ty = switch (temp.unwrap(self)) { |
| 20442 | | .ref => |ref| .{ temp.tracking(self).short, self.typeOf(ref) }, |
| 20443 | | .temp => |temp_index| val: { |
| 20444 | | const temp_tracking = temp_index.tracking(self); |
| 20555 | fn toReg(temp: *Temp, new_reg: Register, cg: *CodeGen) !bool { |
| 20556 | const val, const ty = val_ty: switch (temp.unwrap(cg)) { |
| 20557 | .ref => |ref| .{ temp.tracking(cg).short, cg.typeOf(ref) }, |
| 20558 | .temp => |temp_index| { |
| 20559 | const temp_tracking = temp_index.tracking(cg); |
| 20445 | 20560 | if (temp_tracking.short == .register and |
| 20446 | 20561 | temp_tracking.short.register == new_reg) return false; |
| 20447 | | break :val .{ temp_tracking.short, temp_index.typeOf(self) }; |
| 20562 | break :val_ty .{ temp_tracking.short, temp_index.typeOf(cg) }; |
| 20448 | 20563 | }, |
| 20449 | 20564 | }; |
| 20450 | | const new_temp_index = self.next_temp_index; |
| 20451 | | self.temp_type[@intFromEnum(new_temp_index)] = ty; |
| 20452 | | try self.genSetReg(new_reg, ty, val, .{}); |
| 20453 | | new_temp_index.tracking(self).* = .init(.{ .register = new_reg }); |
| 20454 | | try temp.die(self); |
| 20455 | | self.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1); |
| 20565 | const new_temp_index = cg.next_temp_index; |
| 20566 | cg.temp_type[@intFromEnum(new_temp_index)] = ty; |
| 20567 | try cg.genSetReg(new_reg, ty, val, .{}); |
| 20568 | new_temp_index.tracking(cg).* = .init(.{ .register = new_reg }); |
| 20569 | try temp.die(cg); |
| 20570 | cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1); |
| 20456 | 20571 | temp.* = .{ .index = new_temp_index.toIndex() }; |
| 20457 | 20572 | return true; |
| 20458 | 20573 | } |
| 20459 | 20574 | |
| 20460 | | fn toAnyReg(temp: *Temp, self: *Self) !bool { |
| 20461 | | const val, const ty = switch (temp.unwrap(self)) { |
| 20462 | | .ref => |ref| .{ temp.tracking(self).short, self.typeOf(ref) }, |
| 20575 | fn toAnyReg(temp: *Temp, cg: *CodeGen) !bool { |
| 20576 | const val, const ty = switch (temp.unwrap(cg)) { |
| 20577 | .ref => |ref| .{ temp.tracking(cg).short, cg.typeOf(ref) }, |
| 20463 | 20578 | .temp => |temp_index| val: { |
| 20464 | | const temp_tracking = temp_index.tracking(self); |
| 20579 | const temp_tracking = temp_index.tracking(cg); |
| 20465 | 20580 | if (temp_tracking.short == .register) return false; |
| 20466 | | break :val .{ temp_tracking.short, temp_index.typeOf(self) }; |
| 20581 | break :val .{ temp_tracking.short, temp_index.typeOf(cg) }; |
| 20467 | 20582 | }, |
| 20468 | 20583 | }; |
| 20469 | | const new_temp_index = self.next_temp_index; |
| 20470 | | self.temp_type[@intFromEnum(new_temp_index)] = ty; |
| 20584 | const new_temp_index = cg.next_temp_index; |
| 20585 | cg.temp_type[@intFromEnum(new_temp_index)] = ty; |
| 20471 | 20586 | const new_reg = |
| 20472 | | try self.register_manager.allocReg(new_temp_index.toIndex(), self.regSetForType(ty)); |
| 20473 | | try self.genSetReg(new_reg, ty, val, .{}); |
| 20474 | | new_temp_index.tracking(self).* = .init(.{ .register = new_reg }); |
| 20475 | | try temp.die(self); |
| 20476 | | self.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1); |
| 20587 | try cg.register_manager.allocReg(new_temp_index.toIndex(), cg.regSetForType(ty)); |
| 20588 | try cg.genSetReg(new_reg, ty, val, .{}); |
| 20589 | new_temp_index.tracking(cg).* = .init(.{ .register = new_reg }); |
| 20590 | try temp.die(cg); |
| 20591 | cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1); |
| 20477 | 20592 | temp.* = .{ .index = new_temp_index.toIndex() }; |
| 20478 | 20593 | return true; |
| 20479 | 20594 | } |
| 20480 | 20595 | |
| 20481 | | fn toRegClass(temp: *Temp, rc: Register.Class, self: *Self) !bool { |
| 20482 | | const val, const ty = switch (temp.unwrap(self)) { |
| 20483 | | .ref => |ref| .{ temp.tracking(self).short, self.typeOf(ref) }, |
| 20596 | fn toRegClass(temp: *Temp, rc: Register.Class, cg: *CodeGen) !bool { |
| 20597 | const val, const ty = switch (temp.unwrap(cg)) { |
| 20598 | .ref => |ref| .{ temp.tracking(cg).short, cg.typeOf(ref) }, |
| 20484 | 20599 | .temp => |temp_index| val: { |
| 20485 | | const temp_tracking = temp_index.tracking(self); |
| 20600 | const temp_tracking = temp_index.tracking(cg); |
| 20486 | 20601 | switch (temp_tracking.short) { |
| 20487 | 20602 | else => {}, |
| 20488 | 20603 | .register => |reg| if (reg.class() == rc) return false, |
| 20489 | 20604 | } |
| 20490 | | break :val .{ temp_tracking.short, temp_index.typeOf(self) }; |
| 20605 | break :val .{ temp_tracking.short, temp_index.typeOf(cg) }; |
| 20491 | 20606 | }, |
| 20492 | 20607 | }; |
| 20493 | | const new_temp_index = self.next_temp_index; |
| 20494 | | self.temp_type[@intFromEnum(new_temp_index)] = ty; |
| 20495 | | const new_reg = try self.register_manager.allocReg(new_temp_index.toIndex(), regSetForRegClass(rc)); |
| 20496 | | try self.genSetReg(new_reg, ty, val, .{}); |
| 20497 | | new_temp_index.tracking(self).* = .init(.{ .register = new_reg }); |
| 20498 | | try temp.die(self); |
| 20499 | | self.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1); |
| 20608 | const new_temp_index = cg.next_temp_index; |
| 20609 | cg.temp_type[@intFromEnum(new_temp_index)] = ty; |
| 20610 | const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), regSetForRegClass(rc)); |
| 20611 | try cg.genSetReg(new_reg, ty, val, .{}); |
| 20612 | new_temp_index.tracking(cg).* = .init(.{ .register = new_reg }); |
| 20613 | try temp.die(cg); |
| 20614 | cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1); |
| 20500 | 20615 | temp.* = .{ .index = new_temp_index.toIndex() }; |
| 20501 | 20616 | return true; |
| 20502 | 20617 | } |
| 20503 | 20618 | |
| 20504 | | fn toPair(first_temp: *Temp, second_temp: *Temp, self: *Self) !void { |
| 20619 | fn toPair(first_temp: *Temp, second_temp: *Temp, cg: *CodeGen) !void { |
| 20505 | 20620 | while (true) for ([_]*Temp{ first_temp, second_temp }) |part_temp| { |
| 20506 | | if (try part_temp.toAnyReg(self)) break; |
| 20621 | if (try part_temp.toAnyReg(cg)) break; |
| 20507 | 20622 | } else break; |
| 20508 | | const first_temp_tracking = first_temp.unwrap(self).temp.tracking(self); |
| 20509 | | const second_temp_tracking = second_temp.unwrap(self).temp.tracking(self); |
| 20623 | const first_temp_tracking = first_temp.unwrap(cg).temp.tracking(cg); |
| 20624 | const second_temp_tracking = second_temp.unwrap(cg).temp.tracking(cg); |
| 20510 | 20625 | const result: MCValue = .{ .register_pair = .{ |
| 20511 | 20626 | first_temp_tracking.short.register, |
| 20512 | 20627 | second_temp_tracking.short.register, |
| 20513 | 20628 | } }; |
| 20514 | | const result_temp_index = self.next_temp_index; |
| 20629 | const result_temp_index = cg.next_temp_index; |
| 20515 | 20630 | const result_temp: Temp = .{ .index = result_temp_index.toIndex() }; |
| 20516 | | assert(self.reuseTemp(result_temp.index, first_temp.index, first_temp_tracking)); |
| 20517 | | assert(self.reuseTemp(result_temp.index, second_temp.index, second_temp_tracking)); |
| 20518 | | self.temp_type[@intFromEnum(result_temp_index)] = Type.slice_const_u8; |
| 20519 | | result_temp_index.tracking(self).* = .init(result); |
| 20631 | assert(cg.reuseTemp(result_temp.index, first_temp.index, first_temp_tracking)); |
| 20632 | assert(cg.reuseTemp(result_temp.index, second_temp.index, second_temp_tracking)); |
| 20633 | cg.temp_type[@intFromEnum(result_temp_index)] = Type.slice_const_u8; |
| 20634 | result_temp_index.tracking(cg).* = .init(result); |
| 20520 | 20635 | first_temp.* = result_temp; |
| 20521 | 20636 | } |
| 20522 | 20637 | |
| 20523 | | fn toLea(temp: *Temp, self: *Self) !bool { |
| 20524 | | switch (temp.tracking(self).short) { |
| 20638 | fn toLea(temp: *Temp, cg: *CodeGen) !bool { |
| 20639 | switch (temp.tracking(cg).short) { |
| 20525 | 20640 | .none, |
| 20526 | 20641 | .unreach, |
| 20527 | 20642 | .dead, |
| ... | ... | @@ -20548,65 +20663,83 @@ const Temp = struct { |
| 20548 | 20663 | .load_got, |
| 20549 | 20664 | .load_tlv, |
| 20550 | 20665 | .load_frame, |
| 20551 | | => return temp.toAnyReg(self), |
| 20666 | => return temp.toAnyReg(cg), |
| 20552 | 20667 | .lea_symbol => |sym_off| { |
| 20553 | 20668 | const off = sym_off.off; |
| 20554 | 20669 | if (off == 0) return false; |
| 20555 | | try temp.toOffset(-off, self); |
| 20556 | | while (try temp.toAnyReg(self)) {} |
| 20557 | | try temp.toOffset(off, self); |
| 20670 | try temp.toOffset(-off, cg); |
| 20671 | while (try temp.toAnyReg(cg)) {} |
| 20672 | try temp.toOffset(off, cg); |
| 20558 | 20673 | return true; |
| 20559 | 20674 | }, |
| 20560 | 20675 | } |
| 20561 | 20676 | } |
| 20562 | 20677 | |
| 20563 | | fn load(ptr: *Temp, val_ty: Type, self: *Self) !Temp { |
| 20564 | | const val_abi_size: u32 = @intCast(val_ty.abiSize(self.pt.zcu)); |
| 20565 | | const val = try self.tempAlloc(val_ty); |
| 20566 | | switch (val.tracking(self).short) { |
| 20678 | fn toBase(temp: *Temp, cg: *CodeGen) !bool { |
| 20679 | const temp_tracking = temp.tracking(cg); |
| 20680 | switch (temp_tracking.short) { |
| 20681 | else => {}, |
| 20682 | .indirect, .load_frame => return false, |
| 20683 | } |
| 20684 | const new_temp_index = cg.next_temp_index; |
| 20685 | cg.temp_type[@intFromEnum(new_temp_index)] = temp.typeOf(cg); |
| 20686 | const new_reg = |
| 20687 | try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| 20688 | try cg.genSetReg(new_reg, Type.usize, temp_tracking.short.address(), .{}); |
| 20689 | new_temp_index.tracking(cg).* = .init(.{ .indirect = .{ .reg = new_reg } }); |
| 20690 | try temp.die(cg); |
| 20691 | cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1); |
| 20692 | temp.* = .{ .index = new_temp_index.toIndex() }; |
| 20693 | return true; |
| 20694 | } |
| 20695 | |
| 20696 | fn load(ptr: *Temp, val_ty: Type, cg: *CodeGen) !Temp { |
| 20697 | const val_abi_size: u32 = @intCast(val_ty.abiSize(cg.pt.zcu)); |
| 20698 | const val = try cg.tempAlloc(val_ty); |
| 20699 | switch (val.tracking(cg).short) { |
| 20567 | 20700 | else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }), |
| 20568 | 20701 | .register => |val_reg| { |
| 20569 | | while (try ptr.toLea(self)) {} |
| 20702 | while (try ptr.toLea(cg)) {} |
| 20570 | 20703 | switch (val_reg.class()) { |
| 20571 | | .general_purpose => try self.asmRegisterMemory( |
| 20704 | .general_purpose => try cg.asmRegisterMemory( |
| 20572 | 20705 | .{ ._, .mov }, |
| 20573 | 20706 | registerAlias(val_reg, val_abi_size), |
| 20574 | | try ptr.tracking(self).short.deref().mem(self, self.memSize(val_ty)), |
| 20707 | try ptr.tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(val_ty) }), |
| 20575 | 20708 | ), |
| 20576 | 20709 | else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }), |
| 20577 | 20710 | } |
| 20578 | 20711 | }, |
| 20579 | 20712 | .load_frame => |val_frame_addr| { |
| 20580 | | var val_ptr = try self.tempFromValue(Type.usize, .{ .lea_frame = val_frame_addr }); |
| 20581 | | var len = try self.tempFromValue(Type.usize, .{ .immediate = val_abi_size }); |
| 20582 | | try val_ptr.memcpy(ptr, &len, self); |
| 20583 | | try val_ptr.die(self); |
| 20584 | | try len.die(self); |
| 20713 | var val_ptr = try cg.tempFromValue(Type.usize, .{ .lea_frame = val_frame_addr }); |
| 20714 | var len = try cg.tempFromValue(Type.usize, .{ .immediate = val_abi_size }); |
| 20715 | try val_ptr.memcpy(ptr, &len, cg); |
| 20716 | try val_ptr.die(cg); |
| 20717 | try len.die(cg); |
| 20585 | 20718 | }, |
| 20586 | 20719 | } |
| 20587 | 20720 | return val; |
| 20588 | 20721 | } |
| 20589 | 20722 | |
| 20590 | | fn store(ptr: *Temp, val: *Temp, self: *Self) !void { |
| 20591 | | const val_ty = val.typeOf(self); |
| 20592 | | const val_abi_size: u32 = @intCast(val_ty.abiSize(self.pt.zcu)); |
| 20593 | | val: switch (val.tracking(self).short) { |
| 20723 | fn store(ptr: *Temp, val: *Temp, cg: *CodeGen) !void { |
| 20724 | const val_ty = val.typeOf(cg); |
| 20725 | const val_abi_size: u32 = @intCast(val_ty.abiSize(cg.pt.zcu)); |
| 20726 | val: switch (val.tracking(cg).short) { |
| 20594 | 20727 | else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }), |
| 20595 | 20728 | .immediate => |imm| if (std.math.cast(i32, imm)) |s| { |
| 20596 | | while (try ptr.toLea(self)) {} |
| 20597 | | try self.asmMemoryImmediate( |
| 20729 | while (try ptr.toLea(cg)) {} |
| 20730 | try cg.asmMemoryImmediate( |
| 20598 | 20731 | .{ ._, .mov }, |
| 20599 | | try ptr.tracking(self).short.deref().mem(self, self.memSize(val_ty)), |
| 20732 | try ptr.tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(val_ty) }), |
| 20600 | 20733 | .s(s), |
| 20601 | 20734 | ); |
| 20602 | 20735 | } else continue :val .{ .register = undefined }, |
| 20603 | 20736 | .register => { |
| 20604 | | while (try ptr.toLea(self) or try val.toAnyReg(self)) {} |
| 20605 | | const val_reg = val.tracking(self).short.register; |
| 20737 | while (try ptr.toLea(cg) or try val.toAnyReg(cg)) {} |
| 20738 | const val_reg = val.tracking(cg).short.register; |
| 20606 | 20739 | switch (val_reg.class()) { |
| 20607 | | .general_purpose => try self.asmMemoryRegister( |
| 20740 | .general_purpose => try cg.asmMemoryRegister( |
| 20608 | 20741 | .{ ._, .mov }, |
| 20609 | | try ptr.tracking(self).short.deref().mem(self, self.memSize(val_ty)), |
| 20742 | try ptr.tracking(cg).short.deref().mem(cg, .{ .size = cg.memSize(val_ty) }), |
| 20610 | 20743 | registerAlias(val_reg, val_abi_size), |
| 20611 | 20744 | ), |
| 20612 | 20745 | else => |tag| std.debug.panic("{s}: {any}\n", .{ @src().fn_name, tag }), |
| ... | ... | @@ -20615,64 +20748,64 @@ const Temp = struct { |
| 20615 | 20748 | } |
| 20616 | 20749 | } |
| 20617 | 20750 | |
| 20618 | | fn memcpy(dst: *Temp, src: *Temp, len: *Temp, self: *Self) !void { |
| 20751 | fn memcpy(dst: *Temp, src: *Temp, len: *Temp, cg: *CodeGen) !void { |
| 20619 | 20752 | while (true) for ([_]*Temp{ dst, src, len }, [_]Register{ .rdi, .rsi, .rcx }) |temp, reg| { |
| 20620 | | if (try temp.toReg(reg, self)) break; |
| 20753 | if (try temp.toReg(reg, cg)) break; |
| 20621 | 20754 | } else break; |
| 20622 | | try self.asmOpOnly(.{ .@"rep _sb", .mov }); |
| 20755 | try cg.asmOpOnly(.{ .@"rep _sb", .mov }); |
| 20623 | 20756 | } |
| 20624 | 20757 | |
| 20625 | 20758 | // i, m, r |
| 20626 | | fn add(lhs: *Temp, rhs: *Temp, self: *Self) !Temp { |
| 20627 | | const res_index = self.next_temp_index; |
| 20759 | fn add(lhs: *Temp, rhs: *Temp, cg: *CodeGen) !Temp { |
| 20760 | const res_index = cg.next_temp_index; |
| 20628 | 20761 | var res: Temp = .{ .index = res_index.toIndex() }; |
| 20629 | | try self.select(&.{ &res, lhs, rhs }, .{ ._, .add }, &.{ |
| 20762 | try cg.select(&.{ &res, lhs, rhs }, .{ ._, .add }, &.{ |
| 20630 | 20763 | .{ .ops = &.{ .{ .match = 1 }, .r, .i } }, |
| 20631 | 20764 | .{ .ops = &.{ .{ .match = 1 }, .m, .i } }, |
| 20632 | 20765 | .{ .ops = &.{ .{ .match = 1 }, .r, .m } }, |
| 20633 | 20766 | .{ .ops = &.{ .{ .match = 1 }, .m, .r } }, |
| 20634 | 20767 | .{ .ops = &.{ .{ .match = 1 }, .r, .r } }, |
| 20635 | 20768 | }); |
| 20636 | | self.next_temp_index = @enumFromInt(@intFromEnum(res_index) + 1); |
| 20637 | | self.temp_type[@intFromEnum(res_index)] = lhs.typeOf(self); |
| 20769 | cg.next_temp_index = @enumFromInt(@intFromEnum(res_index) + 1); |
| 20770 | cg.temp_type[@intFromEnum(res_index)] = lhs.typeOf(cg); |
| 20638 | 20771 | return res; |
| 20639 | 20772 | } |
| 20640 | 20773 | |
| 20641 | | fn mul(lhs: *Temp, rhs: *Temp, self: *Self) !Temp { |
| 20642 | | const res_index = self.next_temp_index; |
| 20643 | | var res: Temp = .{ .index = self.next_temp_index.toIndex() }; |
| 20644 | | try self.select(&.{ &res, lhs, rhs }, .{ .i_, .mul }, &.{ |
| 20774 | fn mul(lhs: *Temp, rhs: *Temp, cg: *CodeGen) !Temp { |
| 20775 | const res_index = cg.next_temp_index; |
| 20776 | var res: Temp = .{ .index = cg.next_temp_index.toIndex() }; |
| 20777 | try cg.select(&.{ &res, lhs, rhs }, .{ .i_, .mul }, &.{ |
| 20645 | 20778 | .{ .ops = &.{ .r, .m, .i } }, |
| 20646 | 20779 | .{ .ops = &.{ .r, .r, .i } }, |
| 20647 | 20780 | .{ .ops = &.{ .{ .match = 1 }, .r, .m } }, |
| 20648 | 20781 | .{ .ops = &.{ .{ .match = 1 }, .r, .r } }, |
| 20649 | 20782 | }); |
| 20650 | | self.next_temp_index = @enumFromInt(@intFromEnum(res_index) + 1); |
| 20651 | | self.temp_type[@intFromEnum(res_index)] = lhs.typeOf(self); |
| 20783 | cg.next_temp_index = @enumFromInt(@intFromEnum(res_index) + 1); |
| 20784 | cg.temp_type[@intFromEnum(res_index)] = lhs.typeOf(cg); |
| 20652 | 20785 | return res; |
| 20653 | 20786 | } |
| 20654 | 20787 | |
| 20655 | | fn moveTo(temp: Temp, inst: Air.Inst.Index, self: *Self) !void { |
| 20656 | | if (self.liveness.isUnused(inst)) try temp.die(self) else switch (temp.unwrap(self)) { |
| 20788 | fn moveTo(temp: Temp, inst: Air.Inst.Index, cg: *CodeGen) !void { |
| 20789 | if (cg.liveness.isUnused(inst)) try temp.die(cg) else switch (temp.unwrap(cg)) { |
| 20657 | 20790 | .ref => { |
| 20658 | | const result = try self.allocRegOrMem(inst, true); |
| 20659 | | try self.genCopy(self.typeOfIndex(inst), result, temp.tracking(self).short, .{}); |
| 20791 | const result = try cg.allocRegOrMem(inst, true); |
| 20792 | try cg.genCopy(cg.typeOfIndex(inst), result, temp.tracking(cg).short, .{}); |
| 20660 | 20793 | tracking_log.debug("{} => {} (birth)", .{ inst, result }); |
| 20661 | | self.inst_tracking.putAssumeCapacityNoClobber(inst, .init(result)); |
| 20794 | cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(result)); |
| 20662 | 20795 | }, |
| 20663 | 20796 | .temp => |temp_index| { |
| 20664 | | const temp_tracking = temp_index.tracking(self); |
| 20797 | const temp_tracking = temp_index.tracking(cg); |
| 20665 | 20798 | tracking_log.debug("{} => {} (birth)", .{ inst, temp_tracking.short }); |
| 20666 | | self.inst_tracking.putAssumeCapacityNoClobber(inst, temp_tracking.*); |
| 20667 | | assert(self.reuseTemp(inst, temp_index.toIndex(), temp_tracking)); |
| 20799 | cg.inst_tracking.putAssumeCapacityNoClobber(inst, temp_tracking.*); |
| 20800 | assert(cg.reuseTemp(inst, temp_index.toIndex(), temp_tracking)); |
| 20668 | 20801 | }, |
| 20669 | 20802 | } |
| 20670 | 20803 | } |
| 20671 | 20804 | |
| 20672 | | fn die(temp: Temp, self: *Self) !void { |
| 20673 | | switch (temp.unwrap(self)) { |
| 20805 | fn die(temp: Temp, cg: *CodeGen) !void { |
| 20806 | switch (temp.unwrap(cg)) { |
| 20674 | 20807 | .ref => {}, |
| 20675 | | .temp => |temp_index| try temp_index.tracking(self).die(self, temp_index.toIndex()), |
| 20808 | .temp => |temp_index| try temp_index.tracking(cg).die(cg, temp_index.toIndex()), |
| 20676 | 20809 | } |
| 20677 | 20810 | } |
| 20678 | 20811 | |
| ... | ... | @@ -20687,17 +20820,17 @@ const Temp = struct { |
| 20687 | 20820 | return @enumFromInt(index.toTargetIndex()); |
| 20688 | 20821 | } |
| 20689 | 20822 | |
| 20690 | | fn tracking(index: Index, self: *Self) *InstTracking { |
| 20691 | | return &self.inst_tracking.values()[@intFromEnum(index)]; |
| 20823 | fn tracking(index: Index, cg: *CodeGen) *InstTracking { |
| 20824 | return &cg.inst_tracking.values()[@intFromEnum(index)]; |
| 20692 | 20825 | } |
| 20693 | 20826 | |
| 20694 | | fn isValid(index: Index, self: *Self) bool { |
| 20695 | | return index.tracking(self).short != .dead; |
| 20827 | fn isValid(index: Index, cg: *CodeGen) bool { |
| 20828 | return index.tracking(cg).short != .dead; |
| 20696 | 20829 | } |
| 20697 | 20830 | |
| 20698 | | fn typeOf(index: Index, self: *Self) Type { |
| 20699 | | assert(index.isValid(self)); |
| 20700 | | return self.temp_type[@intFromEnum(index)]; |
| 20831 | fn typeOf(index: Index, cg: *CodeGen) Type { |
| 20832 | assert(index.isValid(cg)); |
| 20833 | return cg.temp_type[@intFromEnum(index)]; |
| 20701 | 20834 | } |
| 20702 | 20835 | |
| 20703 | 20836 | const max = std.math.maxInt(@typeInfo(Index).@"enum".tag_type); |
| ... | ... | @@ -20723,17 +20856,17 @@ const Temp = struct { |
| 20723 | 20856 | }; |
| 20724 | 20857 | }; |
| 20725 | 20858 | |
| 20726 | | fn resetTemps(self: *Self) void { |
| 20727 | | for (0..@intFromEnum(self.next_temp_index)) |temp_index| { |
| 20859 | fn resetTemps(cg: *CodeGen) void { |
| 20860 | for (0..@intFromEnum(cg.next_temp_index)) |temp_index| { |
| 20728 | 20861 | const temp: Temp.Index = @enumFromInt(temp_index); |
| 20729 | | assert(!temp.isValid(self)); |
| 20730 | | self.temp_type[temp_index] = undefined; |
| 20862 | assert(!temp.isValid(cg)); |
| 20863 | cg.temp_type[temp_index] = undefined; |
| 20731 | 20864 | } |
| 20732 | | self.next_temp_index = @enumFromInt(0); |
| 20865 | cg.next_temp_index = @enumFromInt(0); |
| 20733 | 20866 | } |
| 20734 | 20867 | |
| 20735 | 20868 | fn reuseTemp( |
| 20736 | | self: *Self, |
| 20869 | cg: *CodeGen, |
| 20737 | 20870 | new_inst: Air.Inst.Index, |
| 20738 | 20871 | old_inst: Air.Inst.Index, |
| 20739 | 20872 | tracking: *InstTracking, |
| ... | ... | @@ -20743,79 +20876,80 @@ fn reuseTemp( |
| 20743 | 20876 | .register_pair, |
| 20744 | 20877 | .register_offset, |
| 20745 | 20878 | .register_overflow, |
| 20879 | .indirect, |
| 20746 | 20880 | => for (tracking.short.getRegs()) |tracked_reg| { |
| 20747 | 20881 | if (RegisterManager.indexOfRegIntoTracked(tracked_reg)) |tracked_index| { |
| 20748 | | self.register_manager.registers[tracked_index] = new_inst; |
| 20882 | cg.register_manager.registers[tracked_index] = new_inst; |
| 20749 | 20883 | } |
| 20750 | 20884 | }, |
| 20751 | 20885 | .load_frame => |frame_addr| if (frame_addr.index.isNamed()) return false, |
| 20752 | 20886 | else => {}, |
| 20753 | 20887 | } |
| 20754 | 20888 | switch (tracking.short) { |
| 20755 | | .eflags, .register_overflow => self.eflags_inst = new_inst, |
| 20889 | .eflags, .register_overflow => cg.eflags_inst = new_inst, |
| 20756 | 20890 | else => {}, |
| 20757 | 20891 | } |
| 20758 | | tracking.reuse(self, new_inst, old_inst); |
| 20892 | tracking.reuse(cg, new_inst, old_inst); |
| 20759 | 20893 | return true; |
| 20760 | 20894 | } |
| 20761 | 20895 | |
| 20762 | | fn tempAlloc(self: *Self, ty: Type) !Temp { |
| 20763 | | const temp_index = self.next_temp_index; |
| 20764 | | temp_index.tracking(self).* = .init( |
| 20765 | | try self.allocRegOrMemAdvanced(ty, temp_index.toIndex(), true), |
| 20896 | fn tempAlloc(cg: *CodeGen, ty: Type) !Temp { |
| 20897 | const temp_index = cg.next_temp_index; |
| 20898 | temp_index.tracking(cg).* = .init( |
| 20899 | try cg.allocRegOrMemAdvanced(ty, temp_index.toIndex(), true), |
| 20766 | 20900 | ); |
| 20767 | | self.temp_type[@intFromEnum(temp_index)] = ty; |
| 20768 | | self.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1); |
| 20901 | cg.temp_type[@intFromEnum(temp_index)] = ty; |
| 20902 | cg.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1); |
| 20769 | 20903 | return .{ .index = temp_index.toIndex() }; |
| 20770 | 20904 | } |
| 20771 | 20905 | |
| 20772 | | fn tempAllocReg(self: *Self, ty: Type, rc: RegisterManager.RegisterBitSet) !Temp { |
| 20773 | | const temp_index = self.next_temp_index; |
| 20774 | | temp_index.tracking(self).* = .init( |
| 20775 | | .{ .register = try self.register_manager.allocReg(temp_index.toIndex(), rc) }, |
| 20906 | fn tempAllocReg(cg: *CodeGen, ty: Type, rc: RegisterManager.RegisterBitSet) !Temp { |
| 20907 | const temp_index = cg.next_temp_index; |
| 20908 | temp_index.tracking(cg).* = .init( |
| 20909 | .{ .register = try cg.register_manager.allocReg(temp_index.toIndex(), rc) }, |
| 20776 | 20910 | ); |
| 20777 | | self.temp_type[@intFromEnum(temp_index)] = ty; |
| 20778 | | self.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1); |
| 20911 | cg.temp_type[@intFromEnum(temp_index)] = ty; |
| 20912 | cg.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1); |
| 20779 | 20913 | return .{ .index = temp_index.toIndex() }; |
| 20780 | 20914 | } |
| 20781 | 20915 | |
| 20782 | | fn tempFromValue(self: *Self, ty: Type, value: MCValue) !Temp { |
| 20783 | | const temp_index = self.next_temp_index; |
| 20784 | | temp_index.tracking(self).* = .init(value); |
| 20785 | | self.temp_type[@intFromEnum(temp_index)] = ty; |
| 20786 | | try self.getValue(value, temp_index.toIndex()); |
| 20787 | | self.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1); |
| 20916 | fn tempFromValue(cg: *CodeGen, ty: Type, value: MCValue) !Temp { |
| 20917 | const temp_index = cg.next_temp_index; |
| 20918 | temp_index.tracking(cg).* = .init(value); |
| 20919 | cg.temp_type[@intFromEnum(temp_index)] = ty; |
| 20920 | try cg.getValue(value, temp_index.toIndex()); |
| 20921 | cg.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1); |
| 20788 | 20922 | return .{ .index = temp_index.toIndex() }; |
| 20789 | 20923 | } |
| 20790 | 20924 | |
| 20791 | 20925 | fn tempFromOperand( |
| 20792 | | self: *Self, |
| 20926 | cg: *CodeGen, |
| 20793 | 20927 | inst: Air.Inst.Index, |
| 20794 | 20928 | op_index: Liveness.OperandInt, |
| 20795 | 20929 | op_ref: Air.Inst.Ref, |
| 20796 | 20930 | ) !Temp { |
| 20797 | | const zcu = self.pt.zcu; |
| 20931 | const zcu = cg.pt.zcu; |
| 20798 | 20932 | const ip = &zcu.intern_pool; |
| 20799 | 20933 | |
| 20800 | | if (!self.liveness.operandDies(inst, op_index)) { |
| 20934 | if (!cg.liveness.operandDies(inst, op_index)) { |
| 20801 | 20935 | if (op_ref.toIndex()) |op_inst| return .{ .index = op_inst }; |
| 20802 | 20936 | const val = op_ref.toInterned().?; |
| 20803 | | const gop = try self.const_tracking.getOrPut(self.gpa, val); |
| 20937 | const gop = try cg.const_tracking.getOrPut(cg.gpa, val); |
| 20804 | 20938 | if (!gop.found_existing) gop.value_ptr.* = .init(init: { |
| 20805 | | const const_mcv = try self.genTypedValue(.fromInterned(val)); |
| 20939 | const const_mcv = try cg.genTypedValue(.fromInterned(val)); |
| 20806 | 20940 | switch (const_mcv) { |
| 20807 | | .lea_tlv => |tlv_sym| switch (self.bin_file.tag) { |
| 20941 | .lea_tlv => |tlv_sym| switch (cg.bin_file.tag) { |
| 20808 | 20942 | .elf, .macho => { |
| 20809 | | if (self.mod.pic) { |
| 20810 | | try self.spillRegisters(&.{ .rdi, .rax }); |
| 20943 | if (cg.mod.pic) { |
| 20944 | try cg.spillRegisters(&.{ .rdi, .rax }); |
| 20811 | 20945 | } else { |
| 20812 | | try self.spillRegisters(&.{.rax}); |
| 20946 | try cg.spillRegisters(&.{.rax}); |
| 20813 | 20947 | } |
| 20814 | | const frame_index = try self.allocFrameIndex(.init(.{ |
| 20948 | const frame_index = try cg.allocFrameIndex(.init(.{ |
| 20815 | 20949 | .size = 8, |
| 20816 | 20950 | .alignment = .@"8", |
| 20817 | 20951 | })); |
| 20818 | | try self.genSetMem( |
| 20952 | try cg.genSetMem( |
| 20819 | 20953 | .{ .frame = frame_index }, |
| 20820 | 20954 | 0, |
| 20821 | 20955 | Type.usize, |
| ... | ... | @@ -20829,24 +20963,24 @@ fn tempFromOperand( |
| 20829 | 20963 | else => break :init const_mcv, |
| 20830 | 20964 | } |
| 20831 | 20965 | }); |
| 20832 | | return self.tempFromValue(.fromInterned(ip.typeOf(val)), gop.value_ptr.short); |
| 20966 | return cg.tempFromValue(.fromInterned(ip.typeOf(val)), gop.value_ptr.short); |
| 20833 | 20967 | } |
| 20834 | 20968 | |
| 20835 | | const temp_index = self.next_temp_index; |
| 20969 | const temp_index = cg.next_temp_index; |
| 20836 | 20970 | const temp: Temp = .{ .index = temp_index.toIndex() }; |
| 20837 | 20971 | const op_inst = op_ref.toIndex().?; |
| 20838 | | const tracking = self.getResolvedInstValue(op_inst); |
| 20839 | | temp_index.tracking(self).* = tracking.*; |
| 20840 | | if (!self.reuseTemp(temp.index, op_inst, tracking)) return .{ .index = op_ref.toIndex().? }; |
| 20841 | | self.temp_type[@intFromEnum(temp_index)] = self.typeOf(op_ref); |
| 20842 | | self.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1); |
| 20972 | const tracking = cg.getResolvedInstValue(op_inst); |
| 20973 | temp_index.tracking(cg).* = tracking.*; |
| 20974 | if (!cg.reuseTemp(temp.index, op_inst, tracking)) return .{ .index = op_ref.toIndex().? }; |
| 20975 | cg.temp_type[@intFromEnum(temp_index)] = cg.typeOf(op_ref); |
| 20976 | cg.next_temp_index = @enumFromInt(@intFromEnum(temp_index) + 1); |
| 20843 | 20977 | return temp; |
| 20844 | 20978 | } |
| 20845 | 20979 | |
| 20846 | | inline fn tempsFromOperands(self: *Self, inst: Air.Inst.Index, op_refs: anytype) ![op_refs.len]Temp { |
| 20980 | inline fn tempsFromOperands(cg: *CodeGen, inst: Air.Inst.Index, op_refs: anytype) ![op_refs.len]Temp { |
| 20847 | 20981 | var temps: [op_refs.len]Temp = undefined; |
| 20848 | 20982 | inline for (&temps, 0.., op_refs) |*temp, op_index, op_ref| { |
| 20849 | | temp.* = try self.tempFromOperand(inst, op_index, op_ref); |
| 20983 | temp.* = try cg.tempFromOperand(inst, op_index, op_ref); |
| 20850 | 20984 | } |
| 20851 | 20985 | return temps; |
| 20852 | 20986 | } |
| ... | ... | @@ -20859,15 +20993,55 @@ const Operand = union(enum) { |
| 20859 | 20993 | inst: Mir.Inst.Index, |
| 20860 | 20994 | }; |
| 20861 | 20995 | |
| 20996 | const SelectLoop = struct { |
| 20997 | element_reloc: Mir.Inst.Index, |
| 20998 | element_offset: union(enum) { |
| 20999 | unused, |
| 21000 | known: u31, |
| 21001 | temp: Temp, |
| 21002 | }, |
| 21003 | element_size: ?u13, |
| 21004 | limb_reloc: Mir.Inst.Index, |
| 21005 | limb_offset: union(enum) { |
| 21006 | unused, |
| 21007 | known: u31, |
| 21008 | temp: Temp, |
| 21009 | }, |
| 21010 | limb_size: ?u8, |
| 21011 | remaining_size: ?u64, |
| 21012 | }; |
| 21013 | |
| 20862 | 21014 | const Pattern = struct { |
| 20863 | | tag: Mir.Inst.FixedTag, |
| 20864 | 21015 | ops: []const Op, |
| 20865 | 21016 | commute: struct { u8, u8 } = .{ 0, 0 }, |
| 20866 | | features: []const std.Target.x86.Feature = &.{}, |
| 21017 | |
| 21018 | const Set = struct { |
| 21019 | required_features: []const std.Target.x86.Feature = &.{}, |
| 21020 | loop: enum { |
| 21021 | /// only execute the instruction once |
| 21022 | once, |
| 21023 | /// execute the instruction on all groups of non-overlapping bits in the entire value |
| 21024 | bitwise, |
| 21025 | /// for each element, execute the instruction on each limb, propogating the carry flag |
| 21026 | limbwise_carry, |
| 21027 | /// for each element, execute the instruction on pairs of limbs, starting from the |
| 21028 | /// least significant, propogating a limb |
| 21029 | limbwise_pairs_forward, |
| 21030 | /// for each element, execute the instruction on pairs of limbs, starting from the |
| 21031 | /// most significant, propogating a limb |
| 21032 | limbwise_pairs_reverse, |
| 21033 | /// for each element, execute the instruction |
| 21034 | elementwise, |
| 21035 | } = .once, |
| 21036 | mir_tag: Mir.Inst.FixedTag, |
| 21037 | patterns: []const Pattern, |
| 21038 | }; |
| 20867 | 21039 | |
| 20868 | 21040 | const Op = union(enum) { |
| 20869 | | /// match another operand |
| 20870 | | match: u8, |
| 21041 | /// reuse another operand |
| 21042 | implicit: u8, |
| 21043 | /// repeat another operand |
| 21044 | explicit: u8, |
| 20871 | 21045 | /// any general purpose register |
| 20872 | 21046 | gpr, |
| 20873 | 21047 | /// any 64-bit mmx register |
| ... | ... | @@ -20878,165 +21052,449 @@ const Pattern = struct { |
| 20878 | 21052 | ymm, |
| 20879 | 21053 | /// any memory |
| 20880 | 21054 | mem, |
| 21055 | /// a limb stored in a gpr |
| 21056 | gpr_limb, |
| 21057 | /// a limb stored in a 64-bit mmx register |
| 21058 | mm_limb, |
| 21059 | /// a limb stored in a 128-bit sse register |
| 21060 | xmm_limb, |
| 21061 | /// a limb stored in a 256-bit sse register |
| 21062 | ymm_limb, |
| 21063 | /// a limb stored in memory |
| 21064 | mem_limb, |
| 20881 | 21065 | /// specific immediate |
| 20882 | 21066 | imm: i8, |
| 20883 | 21067 | /// any immediate signed extended from 32 bits |
| 20884 | 21068 | simm32, |
| 20885 | 21069 | |
| 20886 | | fn matches(op: Op, is_mut: bool, temp: Temp, self: *Self) bool { |
| 21070 | fn matches(op: Op, is_mut: bool, temp: Temp, cg: *CodeGen) bool { |
| 21071 | const abi_size = temp.typeOf(cg).abiSize(cg.pt.zcu); |
| 20887 | 21072 | return switch (op) { |
| 20888 | | .match => unreachable, |
| 20889 | | .gpr => switch (temp.tracking(self).short) { |
| 21073 | .implicit, .explicit => unreachable, |
| 21074 | .gpr => abi_size <= 8 and switch (temp.tracking(cg).short) { |
| 20890 | 21075 | .register => |reg| reg.class() == .general_purpose, |
| 20891 | 21076 | .register_offset => |reg_off| reg_off.reg.class() == .general_purpose and |
| 20892 | 21077 | reg_off.off == 0, |
| 20893 | | else => self.regClassForType(temp.typeOf(self)) == .general_purpose, |
| 21078 | else => cg.regClassForType(temp.typeOf(cg)) == .general_purpose, |
| 20894 | 21079 | }, |
| 20895 | | .mm => switch (temp.tracking(self).short) { |
| 21080 | .mm => abi_size <= 8 and switch (temp.tracking(cg).short) { |
| 20896 | 21081 | .register => |reg| reg.class() == .mmx, |
| 20897 | 21082 | .register_offset => |reg_off| reg_off.reg.class() == .mmx and reg_off.off == 0, |
| 20898 | | else => self.regClassForType(temp.typeOf(self)) == .mmx, |
| 21083 | else => cg.regClassForType(temp.typeOf(cg)) == .mmx, |
| 20899 | 21084 | }, |
| 20900 | | .xmm => switch (temp.tracking(self).short) { |
| 21085 | .xmm => abi_size > 8 and abi_size <= 16 and switch (temp.tracking(cg).short) { |
| 20901 | 21086 | .register => |reg| reg.class() == .sse, |
| 20902 | 21087 | .register_offset => |reg_off| reg_off.reg.class() == .sse and reg_off.off == 0, |
| 20903 | | else => self.regClassForType(temp.typeOf(self)) == .sse, |
| 21088 | else => cg.regClassForType(temp.typeOf(cg)) == .sse, |
| 20904 | 21089 | }, |
| 20905 | | .ymm => switch (temp.tracking(self).short) { |
| 21090 | .ymm => abi_size > 16 and abi_size <= 32 and switch (temp.tracking(cg).short) { |
| 20906 | 21091 | .register => |reg| reg.class() == .sse, |
| 20907 | 21092 | .register_offset => |reg_off| reg_off.reg.class() == .sse and reg_off.off == 0, |
| 20908 | | else => self.regClassForType(temp.typeOf(self)) == .sse, |
| 20909 | | } and temp.typeOf(self).abiSize(self.pt.zcu) > 16, |
| 20910 | | .mem => (!is_mut or temp.isMut(self)) and temp.tracking(self).short.isMemory(), |
| 20911 | | .imm => |specific_imm| if (is_mut) unreachable else switch (temp.tracking(self).short) { |
| 21093 | else => cg.regClassForType(temp.typeOf(cg)) == .sse, |
| 21094 | }, |
| 21095 | .mem, .mem_limb => (!is_mut or temp.isMut(cg)) and temp.tracking(cg).short.isMemory(), |
| 21096 | .gpr_limb => abi_size > 8, |
| 21097 | .mm_limb => abi_size > 8 and (!is_mut or temp.isMut(cg)) and temp.tracking(cg).short.isMemory() and cg.regClassForType(temp.typeOf(cg)) == .mmx, |
| 21098 | .xmm_limb => abi_size > 16 and (!is_mut or temp.isMut(cg)) and temp.tracking(cg).short.isMemory(), |
| 21099 | .ymm_limb => abi_size > 32 and (!is_mut or temp.isMut(cg)) and temp.tracking(cg).short.isMemory(), |
| 21100 | .imm => |specific_imm| if (is_mut) unreachable else switch (temp.tracking(cg).short) { |
| 20912 | 21101 | .immediate => |imm| @as(i64, @bitCast(imm)) == specific_imm, |
| 20913 | 21102 | else => false, |
| 20914 | 21103 | }, |
| 20915 | | .simm32 => if (is_mut) unreachable else switch (temp.tracking(self).short) { |
| 20916 | | .immediate => |imm| temp.typeOf(self).abiSize(self.pt.zcu) <= 4 or |
| 20917 | | std.math.cast(i32, @as(i64, @bitCast(imm))) != null, |
| 21104 | .simm32 => if (is_mut) unreachable else switch (temp.tracking(cg).short) { |
| 21105 | .immediate => |imm| abi_size <= 4 or std.math.cast(i32, @as(i64, @bitCast(imm))) != null, |
| 20918 | 21106 | else => false, |
| 20919 | 21107 | }, |
| 20920 | 21108 | }; |
| 20921 | 21109 | } |
| 20922 | 21110 | }; |
| 20923 | 21111 | }; |
| 20924 | | fn select(self: *Self, dst_temps: []Temp, src_temps: []const *Temp, patterns: []const Pattern) !void { |
| 20925 | | patterns: for (patterns) |pattern| { |
| 20926 | | for (pattern.features) |feature| if (!self.hasFeature(feature)) continue :patterns; |
| 20927 | | for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| if (!switch (src_op) { |
| 20928 | | .match => |match_index| pattern.ops[match_index], |
| 20929 | | else => src_op, |
| 20930 | | }.matches(src_op == .match, src_temp.*, self)) continue :patterns; |
| 20931 | | while (true) for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| { |
| 20932 | | if (switch (switch (src_op) { |
| 20933 | | .match => |match_index| pattern.ops[match_index], |
| 20934 | | else => src_op, |
| 20935 | | }) { |
| 20936 | | .match => unreachable, |
| 20937 | | .gpr => try src_temp.toRegClass(.general_purpose, self), |
| 20938 | | .mm => try src_temp.toRegClass(.mmx, self), |
| 20939 | | .xmm, .ymm => try src_temp.toRegClass(.sse, self), |
| 20940 | | .mem, .imm, .simm32 => false, |
| 20941 | | }) break; |
| 20942 | | } else break; |
| 20943 | | var mir_ops: [4]Operand = @splat(.none); |
| 20944 | | var mir_ops_len = dst_temps.len; |
| 20945 | | for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| { |
| 20946 | | const mir_op, const matched_src_op = op: switch (src_op) { |
| 20947 | | .match => |match_index| { |
| 20948 | | dst_temps[match_index] = src_temp.*; |
| 20949 | | break :op .{ &mir_ops[match_index], pattern.ops[match_index] }; |
| 20950 | | }, |
| 20951 | | else => { |
| 20952 | | defer mir_ops_len += 1; |
| 20953 | | break :op .{ &mir_ops[mir_ops_len], src_op }; |
| 20954 | | }, |
| 20955 | | }; |
| 20956 | | const src_mcv = src_temp.tracking(self).short; |
| 20957 | | mir_op.* = switch (matched_src_op) { |
| 20958 | | .match => unreachable, |
| 20959 | | .gpr => .{ .reg = registerAlias( |
| 20960 | | src_mcv.register, |
| 20961 | | @intCast(src_temp.typeOf(self).abiSize(self.pt.zcu)), |
| 20962 | | ) }, |
| 20963 | | .mm => .{ .reg = src_mcv.register }, |
| 20964 | | .xmm => .{ .reg = src_mcv.register.to128() }, |
| 20965 | | .ymm => .{ .reg = src_mcv.register.to256() }, |
| 20966 | | .mem => .{ .mem = try src_mcv.mem(self, self.memSize(src_temp.typeOf(self))) }, |
| 20967 | | .imm => |imm| .{ .imm = .s(imm) }, |
| 20968 | | .simm32 => switch (src_temp.typeOf(self).abiSize(self.pt.zcu)) { |
| 20969 | | else => unreachable, |
| 20970 | | 1 => .{ .imm = if (std.math.cast(i8, @as(i64, @bitCast(src_mcv.immediate)))) |small| |
| 20971 | | .s(small) |
| 20972 | | else |
| 20973 | | .u(@as(u8, @intCast(src_mcv.immediate))) }, |
| 20974 | | 2 => .{ .imm = if (std.math.cast(i16, @as(i64, @bitCast(src_mcv.immediate)))) |small| |
| 20975 | | .s(small) |
| 20976 | | else |
| 20977 | | .u(@as(u16, @intCast(src_mcv.immediate))) }, |
| 20978 | | 3...8 => .{ .imm = if (std.math.cast(i32, @as(i64, @bitCast(src_mcv.immediate)))) |small| |
| 20979 | | .s(small) |
| 20980 | | else |
| 20981 | | .u(@as(u32, @intCast(src_mcv.immediate))) }, |
| 20982 | | }, |
| 20983 | | }; |
| 20984 | | } |
| 20985 | | for ( |
| 20986 | | pattern.ops[0..dst_temps.len], |
| 20987 | | dst_temps, |
| 20988 | | mir_ops[0..dst_temps.len], |
| 20989 | | ) |dst_op, *dst_temp, *mir_op| { |
| 20990 | | if (mir_op.* != .none) continue; |
| 20991 | | const ty = src_temps[0].typeOf(self); |
| 20992 | | switch (dst_op) { |
| 20993 | | .match => |match_index| { |
| 20994 | | dst_temp.* = dst_temps[match_index]; |
| 20995 | | mir_op.* = mir_ops[match_index]; |
| 20996 | | }, |
| 20997 | | .gpr => { |
| 20998 | | dst_temp.* = try self.tempAllocReg(ty, abi.RegisterClass.gp); |
| 20999 | | mir_op.* = .{ .reg = registerAlias( |
| 21000 | | dst_temp.tracking(self).short.register, |
| 21001 | | @intCast(ty.abiSize(self.pt.zcu)), |
| 21002 | | ) }; |
| 21003 | | }, |
| 21004 | | .mm => @panic("TODO"), |
| 21005 | | .xmm => { |
| 21006 | | dst_temp.* = try self.tempAllocReg(ty, abi.RegisterClass.sse); |
| 21007 | | mir_op.* = .{ .reg = dst_temp.tracking(self).short.register.to128() }; |
| 21008 | | }, |
| 21009 | | .ymm => { |
| 21010 | | dst_temp.* = try self.tempAllocReg(ty, abi.RegisterClass.sse); |
| 21011 | | mir_op.* = .{ .reg = dst_temp.tracking(self).short.register.to256() }; |
| 21112 | fn select(cg: *CodeGen, dst_temps: []Temp, src_temps: []const *Temp, pattern_sets: []const Pattern.Set) !void { |
| 21113 | var loop: SelectLoop = .{ |
| 21114 | .element_reloc = undefined, |
| 21115 | .element_offset = .unused, |
| 21116 | .element_size = null, |
| 21117 | .limb_reloc = undefined, |
| 21118 | .limb_offset = .unused, |
| 21119 | .limb_size = null, |
| 21120 | .remaining_size = null, |
| 21121 | }; |
| 21122 | var extra_temps: [4]?Temp = @splat(null); |
| 21123 | pattern_sets: for (pattern_sets) |pattern_set| { |
| 21124 | for (pattern_set.required_features) |required_feature| if (!cg.hasFeature(required_feature)) continue :pattern_sets; |
| 21125 | patterns: for (pattern_set.patterns) |pattern| { |
| 21126 | for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| { |
| 21127 | const ref_src_op, const is_mut = switch (src_op) { |
| 21128 | .implicit, .explicit => |op_index| .{ pattern.ops[op_index], true }, |
| 21129 | else => .{ src_op, false }, |
| 21130 | }; |
| 21131 | if (!ref_src_op.matches(is_mut, src_temp.*, cg)) continue :patterns; |
| 21132 | } |
| 21133 | while (true) for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| { |
| 21134 | if (switch (switch (src_op) { |
| 21135 | .implicit, .explicit => |op_index| pattern.ops[op_index], |
| 21136 | else => src_op, |
| 21137 | }) { |
| 21138 | .implicit, .explicit => unreachable, |
| 21139 | .gpr => try src_temp.toRegClass(.general_purpose, cg), |
| 21140 | .mm => try src_temp.toRegClass(.mmx, cg), |
| 21141 | .xmm, .ymm => try src_temp.toRegClass(.sse, cg), |
| 21142 | .mem, .imm, .simm32 => false, |
| 21143 | .gpr_limb, .mm_limb, .xmm_limb, .ymm_limb, .mem_limb => switch (src_temp.tracking(cg).short) { |
| 21144 | .register_pair => false, |
| 21145 | else => try src_temp.toBase(cg), |
| 21146 | }, |
| 21147 | }) break; |
| 21148 | } else break; |
| 21149 | var mir_ops_len = dst_temps.len; |
| 21150 | for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| { |
| 21151 | const ref_src_op, const extra_temp = op: switch (src_op) { |
| 21152 | .implicit => |op_index| { |
| 21153 | dst_temps[op_index] = if (src_temp.isMut(cg)) |
| 21154 | src_temp.* |
| 21155 | else |
| 21156 | try cg.tempAlloc(src_temp.typeOf(cg)); |
| 21157 | break :op .{ pattern.ops[op_index], &extra_temps[op_index] }; |
| 21158 | }, |
| 21159 | .explicit => |op_index| { |
| 21160 | dst_temps[op_index] = if (src_temp.isMut(cg)) |
| 21161 | src_temp.* |
| 21162 | else |
| 21163 | try cg.tempAlloc(src_temp.typeOf(cg)); |
| 21164 | defer mir_ops_len += 1; |
| 21165 | break :op .{ pattern.ops[op_index], &extra_temps[mir_ops_len] }; |
| 21166 | }, |
| 21167 | else => { |
| 21168 | defer mir_ops_len += 1; |
| 21169 | break :op .{ src_op, &extra_temps[mir_ops_len] }; |
| 21170 | }, |
| 21171 | }; |
| 21172 | const limb_size: u8, const rc = switch (ref_src_op) { |
| 21173 | else => continue, |
| 21174 | .gpr_limb => .{ 8, abi.RegisterClass.gp }, |
| 21175 | .mm_limb => .{ 8, @panic("TODO") }, |
| 21176 | .xmm_limb => .{ 16, abi.RegisterClass.sse }, |
| 21177 | .ymm_limb => .{ 32, abi.RegisterClass.sse }, |
| 21178 | }; |
| 21179 | assert(loop.limb_size == null or loop.limb_size == limb_size); |
| 21180 | loop.limb_size = limb_size; |
| 21181 | loop.remaining_size = loop.remaining_size orelse src_temp.typeOf(cg).abiSize(cg.pt.zcu); |
| 21182 | switch (src_temp.tracking(cg).short) { |
| 21183 | .register_pair => switch (loop.limb_offset) { |
| 21184 | .unused, .temp => loop.limb_offset = .{ .known = 0 }, |
| 21185 | .known => {}, |
| 21186 | }, |
| 21187 | else => { |
| 21188 | switch (loop.limb_offset) { |
| 21189 | .unused => loop.limb_offset = .{ .temp = undefined }, |
| 21190 | .known, .temp => {}, |
| 21191 | } |
| 21192 | extra_temp.* = try cg.tempAllocReg(Type.usize, rc); |
| 21193 | }, |
| 21194 | } |
| 21195 | } |
| 21196 | switch (loop.element_offset) { |
| 21197 | .unused, .known => {}, |
| 21198 | .temp => |*element_offset| { |
| 21199 | element_offset.* = try cg.tempAllocReg(Type.usize, abi.RegisterClass.gp); |
| 21200 | const element_offset_reg = element_offset.tracking(cg).short.register; |
| 21201 | try cg.asmRegisterRegister(.{ ._, .xor }, element_offset_reg.to32(), element_offset_reg.to32()); |
| 21202 | loop.element_reloc = @intCast(cg.mir_instructions.len); |
| 21012 | 21203 | }, |
| 21013 | | .mem => @panic("TODO"), |
| 21014 | | .imm, .simm32 => unreachable, // unmodifiable destination |
| 21015 | 21204 | } |
| 21016 | | } |
| 21017 | | std.mem.swap(Operand, &mir_ops[pattern.commute[0]], &mir_ops[pattern.commute[1]]); |
| 21018 | | self.asmOps(pattern.tag, mir_ops) catch |err| switch (err) { |
| 21019 | | error.InvalidInstruction => { |
| 21020 | | const fixes = @tagName(pattern.tag[0]); |
| 21021 | | const fixes_replace = std.mem.indexOfScalar(u8, fixes, '_').?; |
| 21022 | | return self.fail( |
| 21023 | | "invalid instruction: '{s}{s}{s} {s} {s} {s} {s}'", |
| 21024 | | .{ |
| 21025 | | fixes[0..fixes_replace], |
| 21026 | | @tagName(pattern.tag[1]), |
| 21027 | | fixes[fixes_replace + 1 ..], |
| 21028 | | @tagName(mir_ops[0]), |
| 21029 | | @tagName(mir_ops[1]), |
| 21030 | | @tagName(mir_ops[2]), |
| 21031 | | @tagName(mir_ops[3]), |
| 21205 | while (true) { |
| 21206 | switch (loop.limb_offset) { |
| 21207 | .unused, .known => {}, |
| 21208 | .temp => |*limb_offset| { |
| 21209 | limb_offset.* = try cg.tempAllocReg(Type.usize, abi.RegisterClass.gp); |
| 21210 | const limb_offset_reg = limb_offset.tracking(cg).short.register; |
| 21211 | try cg.asmRegisterRegister(.{ ._, .xor }, limb_offset_reg.to32(), limb_offset_reg.to32()); |
| 21212 | loop.limb_reloc = @intCast(cg.mir_instructions.len); |
| 21032 | 21213 | }, |
| 21033 | | ); |
| 21034 | | }, |
| 21035 | | else => |e| return e, |
| 21036 | | }; |
| 21037 | | return; |
| 21214 | } |
| 21215 | while (true) { |
| 21216 | var mir_ops: [4]Operand = @splat(.none); |
| 21217 | mir_ops_len = dst_temps.len; |
| 21218 | for (src_temps, pattern.ops[dst_temps.len..]) |src_temp, src_op| { |
| 21219 | const mir_op, const ref_src_op, const extra_temp = op: switch (src_op) { |
| 21220 | .implicit => |op_index| .{ &mir_ops[op_index], pattern.ops[op_index], &extra_temps[op_index] }, |
| 21221 | .explicit => |op_index| { |
| 21222 | defer mir_ops_len += 1; |
| 21223 | break :op .{ &mir_ops[mir_ops_len], pattern.ops[op_index], &extra_temps[mir_ops_len] }; |
| 21224 | }, |
| 21225 | else => { |
| 21226 | defer mir_ops_len += 1; |
| 21227 | break :op .{ &mir_ops[mir_ops_len], src_op, &extra_temps[mir_ops_len] }; |
| 21228 | }, |
| 21229 | }; |
| 21230 | const src_mcv = src_temp.tracking(cg).short; |
| 21231 | switch (ref_src_op) { |
| 21232 | else => {}, |
| 21233 | .gpr_limb, .mm_limb, .xmm_limb, .ymm_limb => switch (src_mcv) { |
| 21234 | .register_pair => {}, |
| 21235 | else => try cg.asmRegisterMemory( |
| 21236 | switch (ref_src_op) { |
| 21237 | else => unreachable, |
| 21238 | .gpr_limb => .{ ._, .mov }, |
| 21239 | .mm_limb => .{ ._q, .mov }, |
| 21240 | .xmm_limb, .ymm_limb => .{ if (cg.hasFeature(.avx)) .v_ else ._, .movdqu }, |
| 21241 | }, |
| 21242 | registerAlias(extra_temp.*.?.tracking(cg).short.register, loop.limb_size.?), |
| 21243 | try src_mcv.mem(cg, switch (loop.limb_offset) { |
| 21244 | .unused => unreachable, |
| 21245 | .known => |limb_offset| .{ |
| 21246 | .size = .fromSize(loop.limb_size.?), |
| 21247 | .disp = limb_offset, |
| 21248 | }, |
| 21249 | .temp => |limb_offset| .{ |
| 21250 | .size = .fromSize(loop.limb_size.?), |
| 21251 | .index = limb_offset.tracking(cg).short.register.to64(), |
| 21252 | }, |
| 21253 | }), |
| 21254 | ), |
| 21255 | }, |
| 21256 | } |
| 21257 | mir_op.* = switch (ref_src_op) { |
| 21258 | .implicit, .explicit => unreachable, |
| 21259 | .gpr => .{ .reg = registerAlias( |
| 21260 | src_mcv.register, |
| 21261 | @intCast(src_temp.typeOf(cg).abiSize(cg.pt.zcu)), |
| 21262 | ) }, |
| 21263 | .mm => .{ .reg = src_mcv.register }, |
| 21264 | .xmm => .{ .reg = src_mcv.register.to128() }, |
| 21265 | .ymm => .{ .reg = src_mcv.register.to256() }, |
| 21266 | .mem => .{ .mem = try src_mcv.mem(cg, .{ .size = cg.memSize(src_temp.typeOf(cg)) }) }, |
| 21267 | .gpr_limb, .mm_limb, .xmm_limb, .ymm_limb => switch (src_mcv) { |
| 21268 | .register_pair => |src_regs| switch (loop.limb_offset) { |
| 21269 | .unused => unreachable, |
| 21270 | .known => |limb_offset| .{ .reg = registerAlias( |
| 21271 | src_regs[@divExact(limb_offset, loop.limb_size.?)], |
| 21272 | loop.limb_size.?, |
| 21273 | ) }, |
| 21274 | .temp => unreachable, |
| 21275 | }, |
| 21276 | else => .{ .reg = registerAlias( |
| 21277 | extra_temp.*.?.tracking(cg).short.register, |
| 21278 | loop.limb_size.?, |
| 21279 | ) }, |
| 21280 | }, |
| 21281 | .mem_limb => .{ .mem = switch (src_mcv) { |
| 21282 | .register_pair => unreachable, |
| 21283 | else => switch (loop.limb_offset) { |
| 21284 | .unused => unreachable, |
| 21285 | .known => |limb_offset| try src_mcv.mem(cg, .{ |
| 21286 | .size = .fromSize(loop.limb_size.?), |
| 21287 | .disp = limb_offset, |
| 21288 | }), |
| 21289 | .temp => |limb_offset| try src_mcv.mem(cg, .{ |
| 21290 | .size = .fromSize(loop.limb_size.?), |
| 21291 | .index = limb_offset.tracking(cg).short.register.to64(), |
| 21292 | }), |
| 21293 | }, |
| 21294 | } }, |
| 21295 | .imm => |imm| .{ .imm = .s(imm) }, |
| 21296 | .simm32 => switch (src_temp.typeOf(cg).abiSize(cg.pt.zcu)) { |
| 21297 | else => unreachable, |
| 21298 | 1 => .{ .imm = if (std.math.cast(i8, @as(i64, @bitCast(src_mcv.immediate)))) |small| |
| 21299 | .s(small) |
| 21300 | else |
| 21301 | .u(@as(u8, @intCast(src_mcv.immediate))) }, |
| 21302 | 2 => .{ .imm = if (std.math.cast(i16, @as(i64, @bitCast(src_mcv.immediate)))) |small| |
| 21303 | .s(small) |
| 21304 | else |
| 21305 | .u(@as(u16, @intCast(src_mcv.immediate))) }, |
| 21306 | 3...8 => .{ .imm = if (std.math.cast(i32, @as(i64, @bitCast(src_mcv.immediate)))) |small| |
| 21307 | .s(small) |
| 21308 | else |
| 21309 | .u(@as(u32, @intCast(src_mcv.immediate))) }, |
| 21310 | }, |
| 21311 | }; |
| 21312 | } |
| 21313 | for ( |
| 21314 | pattern.ops[0..dst_temps.len], |
| 21315 | dst_temps, |
| 21316 | mir_ops[0..dst_temps.len], |
| 21317 | extra_temps[0..dst_temps.len], |
| 21318 | ) |dst_op, *dst_temp, *mir_op, *extra_temp| { |
| 21319 | if (mir_op.* != .none) continue; |
| 21320 | const ty = src_temps[0].typeOf(cg); |
| 21321 | switch (dst_op) { |
| 21322 | .implicit => unreachable, |
| 21323 | .explicit => |op_index| { |
| 21324 | dst_temp.* = dst_temps[op_index]; |
| 21325 | mir_op.* = mir_ops[op_index]; |
| 21326 | }, |
| 21327 | .gpr => { |
| 21328 | dst_temp.* = try cg.tempAllocReg(ty, abi.RegisterClass.gp); |
| 21329 | mir_op.* = .{ .reg = registerAlias( |
| 21330 | dst_temp.tracking(cg).short.register, |
| 21331 | @intCast(ty.abiSize(cg.pt.zcu)), |
| 21332 | ) }; |
| 21333 | }, |
| 21334 | .mm => @panic("TODO"), |
| 21335 | .xmm => { |
| 21336 | dst_temp.* = try cg.tempAllocReg(ty, abi.RegisterClass.sse); |
| 21337 | mir_op.* = .{ .reg = dst_temp.tracking(cg).short.register.to128() }; |
| 21338 | }, |
| 21339 | .ymm => { |
| 21340 | dst_temp.* = try cg.tempAllocReg(ty, abi.RegisterClass.sse); |
| 21341 | mir_op.* = .{ .reg = dst_temp.tracking(cg).short.register.to256() }; |
| 21342 | }, |
| 21343 | .mem => @panic("TODO"), |
| 21344 | .gpr_limb => { |
| 21345 | dst_temp.* = try cg.tempAlloc(ty); |
| 21346 | extra_temp.* = try cg.tempAllocReg(Type.usize, abi.RegisterClass.gp); |
| 21347 | mir_op.* = .{ .reg = extra_temp.*.?.tracking(cg).short.register.to64() }; |
| 21348 | }, |
| 21349 | .mm_limb => { |
| 21350 | dst_temp.* = try cg.tempAlloc(ty); |
| 21351 | extra_temp.* = try cg.tempAllocReg(Type.usize, @panic("TODO")); |
| 21352 | mir_op.* = .{ .reg = extra_temp.*.?.tracking(cg).short.register }; |
| 21353 | }, |
| 21354 | .xmm_limb => { |
| 21355 | dst_temp.* = try cg.tempAlloc(ty); |
| 21356 | extra_temp.* = try cg.tempAllocReg(Type.usize, abi.RegisterClass.sse); |
| 21357 | mir_op.* = .{ .reg = extra_temp.*.?.tracking(cg).short.register.to128() }; |
| 21358 | }, |
| 21359 | .ymm_limb => { |
| 21360 | dst_temp.* = try cg.tempAlloc(ty); |
| 21361 | extra_temp.* = try cg.tempAllocReg(Type.usize, abi.RegisterClass.sse); |
| 21362 | mir_op.* = .{ .reg = extra_temp.*.?.tracking(cg).short.register.to256() }; |
| 21363 | }, |
| 21364 | .mem_limb => { |
| 21365 | dst_temp.* = try cg.tempAlloc(ty); |
| 21366 | mir_op.* = .{ .mem = try dst_temp.tracking(cg).short.mem(cg, switch (loop.limb_offset) { |
| 21367 | .unused => unreachable, |
| 21368 | .known => |limb_offset| .{ |
| 21369 | .size = .fromSize(loop.limb_size.?), |
| 21370 | .disp = limb_offset, |
| 21371 | }, |
| 21372 | .temp => |limb_offset| .{ |
| 21373 | .size = .fromSize(loop.limb_size.?), |
| 21374 | .index = limb_offset.tracking(cg).short.register.to64(), |
| 21375 | }, |
| 21376 | }) }; |
| 21377 | }, |
| 21378 | .imm, .simm32 => unreachable, // unmodifiable destination |
| 21379 | } |
| 21380 | } |
| 21381 | std.mem.swap(Operand, &mir_ops[pattern.commute[0]], &mir_ops[pattern.commute[1]]); |
| 21382 | cg.asmOps(pattern_set.mir_tag, mir_ops) catch |err| switch (err) { |
| 21383 | error.InvalidInstruction => { |
| 21384 | const fixes = @tagName(pattern_set.mir_tag[0]); |
| 21385 | const fixes_blank = std.mem.indexOfScalar(u8, fixes, '_').?; |
| 21386 | return cg.fail( |
| 21387 | "invalid instruction: '{s}{s}{s} {s} {s} {s} {s}'", |
| 21388 | .{ |
| 21389 | fixes[0..fixes_blank], |
| 21390 | @tagName(pattern_set.mir_tag[1]), |
| 21391 | fixes[fixes_blank + 1 ..], |
| 21392 | @tagName(mir_ops[0]), |
| 21393 | @tagName(mir_ops[1]), |
| 21394 | @tagName(mir_ops[2]), |
| 21395 | @tagName(mir_ops[3]), |
| 21396 | }, |
| 21397 | ); |
| 21398 | }, |
| 21399 | else => |e| return e, |
| 21400 | }; |
| 21401 | for ( |
| 21402 | extra_temps[0..dst_temps.len], |
| 21403 | pattern.ops[0..dst_temps.len], |
| 21404 | dst_temps, |
| 21405 | ) |maybe_extra_temp, dst_op, dst_temp| if (maybe_extra_temp) |extra_temp| switch (dst_op) { |
| 21406 | else => {}, |
| 21407 | .gpr_limb, .mm_limb, .xmm_limb, .ymm_limb => switch (dst_temp.tracking(cg).short) { |
| 21408 | .register_pair => |dst_regs| switch (loop.limb_offset) { |
| 21409 | .unused => unreachable, |
| 21410 | .known => |limb_offset| try cg.asmRegisterRegister( |
| 21411 | .{ ._, .mov }, |
| 21412 | dst_regs[@divExact(limb_offset, loop.limb_size.?)].to64(), |
| 21413 | extra_temp.tracking(cg).short.register.to64(), |
| 21414 | ), |
| 21415 | .temp => unreachable, |
| 21416 | }, |
| 21417 | else => |dst_mcv| try cg.asmMemoryRegister( |
| 21418 | switch (dst_op) { |
| 21419 | else => unreachable, |
| 21420 | .gpr_limb => .{ ._, .mov }, |
| 21421 | .mm_limb => .{ ._q, .mov }, |
| 21422 | .xmm_limb, .ymm_limb => .{ if (cg.hasFeature(.avx)) .v_ else ._, .movdqu }, |
| 21423 | }, |
| 21424 | try dst_mcv.mem(cg, switch (loop.limb_offset) { |
| 21425 | .unused => unreachable, |
| 21426 | .known => |limb_offset| .{ |
| 21427 | .size = .fromSize(loop.limb_size.?), |
| 21428 | .disp = limb_offset, |
| 21429 | }, |
| 21430 | .temp => |limb_offset| .{ |
| 21431 | .size = .fromSize(loop.limb_size.?), |
| 21432 | .index = limb_offset.tracking(cg).short.register.to64(), |
| 21433 | }, |
| 21434 | }), |
| 21435 | registerAlias(extra_temp.tracking(cg).short.register, loop.limb_size.?), |
| 21436 | ), |
| 21437 | }, |
| 21438 | }; |
| 21439 | switch (pattern_set.loop) { |
| 21440 | .once => break :pattern_sets, |
| 21441 | .bitwise => {}, |
| 21442 | .limbwise_carry => @panic("TODO"), |
| 21443 | .limbwise_pairs_forward => @panic("TODO"), |
| 21444 | .limbwise_pairs_reverse => @panic("TODO"), |
| 21445 | .elementwise => @panic("TODO"), |
| 21446 | } |
| 21447 | switch (loop.limb_offset) { |
| 21448 | .unused => break, |
| 21449 | .known => |*limb_offset| { |
| 21450 | limb_offset.* += loop.limb_size.?; |
| 21451 | loop.remaining_size.? -= loop.limb_size.?; |
| 21452 | if (loop.remaining_size.? < loop.limb_size.? or |
| 21453 | (loop.element_size != null and limb_offset.* >= loop.element_size.?)) |
| 21454 | { |
| 21455 | limb_offset.* = 0; |
| 21456 | break; |
| 21457 | } |
| 21458 | }, |
| 21459 | .temp => |limb_offset| { |
| 21460 | const limb_offset_reg = limb_offset.tracking(cg).short.register; |
| 21461 | try cg.asmRegisterMemory(.{ ._, .lea }, limb_offset_reg.to32(), .{ |
| 21462 | .base = .{ .reg = limb_offset_reg.to64() }, |
| 21463 | .mod = .{ .rm = .{ |
| 21464 | .size = .qword, |
| 21465 | .disp = loop.limb_size.?, |
| 21466 | } }, |
| 21467 | }); |
| 21468 | try cg.asmRegisterImmediate( |
| 21469 | .{ ._, .cmp }, |
| 21470 | limb_offset_reg.to32(), |
| 21471 | .u(loop.element_size orelse loop.remaining_size.?), |
| 21472 | ); |
| 21473 | _ = try cg.asmJccReloc(.b, loop.limb_reloc); |
| 21474 | try limb_offset.die(cg); |
| 21475 | break; |
| 21476 | }, |
| 21477 | } |
| 21478 | } |
| 21479 | switch (loop.element_offset) { |
| 21480 | .unused => break :pattern_sets, |
| 21481 | .known => |*element_offset| { |
| 21482 | if (loop.remaining_size.? == 0) break :pattern_sets; |
| 21483 | element_offset.* += loop.element_size.?; |
| 21484 | }, |
| 21485 | .temp => |element_offset| { |
| 21486 | if (true) @panic("TODO"); |
| 21487 | try element_offset.die(cg); |
| 21488 | if (loop.remaining_size.? == 0) break :pattern_sets; |
| 21489 | break; |
| 21490 | }, |
| 21491 | } |
| 21492 | } |
| 21493 | } |
| 21494 | } else { |
| 21495 | log.err("failed to select:", .{}); |
| 21496 | for (src_temps) |src_temp| log.err("{}", .{src_temp.tracking(cg)}); |
| 21497 | return cg.fail("failed to select", .{}); |
| 21038 | 21498 | } |
| 21039 | | log.err("failed to select:", .{}); |
| 21040 | | for (src_temps) |src_temp| log.err("{}", .{src_temp.tracking(self)}); |
| 21041 | | return self.fail("failed to select", .{}); |
| 21499 | for (extra_temps) |extra_temp| if (extra_temp) |temp| try temp.die(cg); |
| 21042 | 21500 | } |