| ... | @@ -374,71 +374,99 @@ pub fn generate( | ... | @@ -374,71 +374,99 @@ pub fn generate( |
| 374 | fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index { | 374 | fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index { |
| 375 | const gpa = self.gpa; | 375 | const gpa = self.gpa; |
| 376 | try self.mir_instructions.ensureUnusedCapacity(gpa, 1); | 376 | try self.mir_instructions.ensureUnusedCapacity(gpa, 1); |
| 377 | const result_index = @intCast(Air.Inst.Index, self.mir_instructions.len); | 377 | const result_index = @intCast(Mir.Inst.Index, self.mir_instructions.len); |
| 378 | self.mir_instructions.appendAssumeCapacity(inst); | 378 | self.mir_instructions.appendAssumeCapacity(inst); |
| 379 | return result_index; | 379 | return result_index; |
| 380 | } | 380 | } |
| 381 | | 381 | |
| 382 | pub fn addExtra(self: *Self, extra: anytype) Allocator.Error!u32 { | 382 | fn addExtra(self: *Self, extra: anytype) Allocator.Error!u32 { |
| 383 | const fields = std.meta.fields(@TypeOf(extra)); | 383 | const fields = std.meta.fields(@TypeOf(extra)); |
| 384 | try self.mir_extra.ensureUnusedCapacity(self.gpa, fields.len); | 384 | try self.mir_extra.ensureUnusedCapacity(self.gpa, fields.len); |
| 385 | return self.addExtraAssumeCapacity(extra); | 385 | return self.addExtraAssumeCapacity(extra); |
| 386 | } | 386 | } |
| 387 | | 387 | |
| 388 | fn extraData(self: *Self, comptime T: type, index: u32) struct { data: T, end: u32 } { | 388 | fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { |
| 389 | const fields = std.meta.fields(T); | | |
| 390 | var i: u32 = index; | | |
| 391 | var result: T = undefined; | | |
| 392 | inline for (fields) |field| { | | |
| 393 | @field(result, field.name) = switch (field.type) { | | |
| 394 | u32 => self.mir_extra.items[i], | | |
| 395 | i32 => @bitCast(i32, self.mir_extra.items[i]), | | |
| 396 | else => @compileError("bad field type"), | | |
| 397 | }; | | |
| 398 | i += 1; | | |
| 399 | } | | |
| 400 | return .{ | | |
| 401 | .data = result, | | |
| 402 | .end = i, | | |
| 403 | }; | | |
| 404 | } | | |
| 405 | | | |
| 406 | pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { | | |
| 407 | const fields = std.meta.fields(@TypeOf(extra)); | 389 | const fields = std.meta.fields(@TypeOf(extra)); |
| 408 | const result = @intCast(u32, self.mir_extra.items.len); | 390 | const result = @intCast(u32, self.mir_extra.items.len); |
| 409 | inline for (fields) |field| { | 391 | inline for (fields) |field| { |
| 410 | self.mir_extra.appendAssumeCapacity(switch (field.type) { | 392 | self.mir_extra.appendAssumeCapacity(switch (field.type) { |
| 411 | u32 => @field(extra, field.name), | 393 | u32 => @field(extra, field.name), |
| 412 | i32 => @bitCast(u32, @field(extra, field.name)), | 394 | i32 => @bitCast(u32, @field(extra, field.name)), |
| 413 | else => @compileError("bad field type"), | 395 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), |
| 414 | }); | 396 | }); |
| 415 | } | 397 | } |
| 416 | return result; | 398 | return result; |
| 417 | } | 399 | } |
| 418 | | 400 | |
| | 401 | fn assemble(self: *Self, tag: Mir.Inst.Tag, args: struct { |
| | 402 | op1: Mir.Operand = .none, |
| | 403 | op2: Mir.Operand = .none, |
| | 404 | op3: Mir.Operand = .none, |
| | 405 | op4: Mir.Operand = .none, |
| | 406 | }) !void { |
| | 407 | const ops: Mir.Inst.Ops = blk: { |
| | 408 | if (args.op1 == .none and args.op2 == .none and args.op3 == .none and args.op4 == .none) |
| | 409 | break :blk .none; |
| | 410 | |
| | 411 | if (args.op1 == .reg and args.op2 == .reg) |
| | 412 | break :blk .rr; |
| | 413 | if (args.op1 == .reg and args.op2 == .imm) switch (args.op2.imm) { |
| | 414 | .signed => break :blk .ri_s, |
| | 415 | .unsigned => break :blk .ri_u, |
| | 416 | }; |
| | 417 | if (args.op1 == .reg) |
| | 418 | break :blk .r; |
| | 419 | if (args.op1 == .imm) switch (args.op1.imm) { |
| | 420 | .signed => break :blk .imm_s, |
| | 421 | .unsigned => break :blk .imm_u, // TODO 64bits |
| | 422 | }; |
| | 423 | |
| | 424 | unreachable; |
| | 425 | }; |
| | 426 | const data: Mir.Inst.Data = switch (ops) { |
| | 427 | .none => undefined, |
| | 428 | .imm_s => .{ .imm_s = args.op1.imm.signed }, |
| | 429 | .imm_u => .{ .imm_u = @intCast(u32, args.op1.imm.unsigned) }, |
| | 430 | .r => .{ .r = args.op1.reg }, |
| | 431 | .rr => .{ .rr = .{ |
| | 432 | .r1 = args.op1.reg, |
| | 433 | .r2 = args.op2.reg, |
| | 434 | } }, |
| | 435 | .ri_s => .{ .ri_s = .{ |
| | 436 | .r1 = args.op1.reg, |
| | 437 | .imm = args.op2.imm.signed, |
| | 438 | } }, |
| | 439 | .ri_u => .{ .ri_u = .{ |
| | 440 | .r1 = args.op1.reg, |
| | 441 | .imm = @intCast(u32, args.op2.imm.unsigned), |
| | 442 | } }, |
| | 443 | else => unreachable, |
| | 444 | }; |
| | 445 | _ = try self.addInst(.{ |
| | 446 | .tag = tag, |
| | 447 | .ops = ops, |
| | 448 | .data = data, |
| | 449 | }); |
| | 450 | } |
| | 451 | |
| 419 | fn gen(self: *Self) InnerError!void { | 452 | fn gen(self: *Self) InnerError!void { |
| 420 | const cc = self.fn_type.fnCallingConvention(); | 453 | const cc = self.fn_type.fnCallingConvention(); |
| 421 | if (cc != .Naked) { | 454 | if (cc != .Naked) { |
| 422 | _ = try self.addInst(.{ | 455 | try self.assemble(.push, .{ |
| 423 | .tag = .push, | 456 | .op1 = .{ .reg = .rbp }, |
| 424 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = .rbp }), | | |
| 425 | .data = undefined, // unused for push reg, | | |
| 426 | }); | 457 | }); |
| 427 | _ = try self.addInst(.{ | 458 | try self.assemble(.mov, .{ |
| 428 | .tag = .mov, | 459 | .op1 = .{ .reg = .rbp }, |
| 429 | .ops = Mir.Inst.Ops.encode(.{ | 460 | .op2 = .{ .reg = .rsp }, |
| 430 | .reg1 = .rbp, | | |
| 431 | .reg2 = .rsp, | | |
| 432 | }), | | |
| 433 | .data = undefined, | | |
| 434 | }); | 461 | }); |
| | 462 | |
| 435 | // We want to subtract the aligned stack frame size from rsp here, but we don't | 463 | // We want to subtract the aligned stack frame size from rsp here, but we don't |
| 436 | // yet know how big it will be, so we leave room for a 4-byte stack size. | 464 | // yet know how big it will be, so we leave room for a 4-byte stack size. |
| 437 | // TODO During semantic analysis, check if there are no function calls. If there | 465 | // TODO During semantic analysis, check if there are no function calls. If there |
| 438 | // are none, here we can omit the part where we subtract and then add rsp. | 466 | // are none, here we can omit the part where we subtract and then add rsp. |
| 439 | const backpatch_stack_sub = try self.addInst(.{ | 467 | const backpatch_stack_sub = try self.addInst(.{ |
| 440 | .tag = .nop, | 468 | .tag = .nop, |
| 441 | .ops = undefined, | 469 | .ops = .none, |
| 442 | .data = undefined, | 470 | .data = undefined, |
| 443 | }); | 471 | }); |
| 444 | | 472 | |
| ... | @@ -465,7 +493,7 @@ fn gen(self: *Self) InnerError!void { | ... | @@ -465,7 +493,7 @@ fn gen(self: *Self) InnerError!void { |
| 465 | // Push callee-preserved regs that were used actually in use. | 493 | // Push callee-preserved regs that were used actually in use. |
| 466 | const backpatch_push_callee_preserved_regs = try self.addInst(.{ | 494 | const backpatch_push_callee_preserved_regs = try self.addInst(.{ |
| 467 | .tag = .nop, | 495 | .tag = .nop, |
| 468 | .ops = undefined, | 496 | .ops = .none, |
| 469 | .data = undefined, | 497 | .data = undefined, |
| 470 | }); | 498 | }); |
| 471 | | 499 | |
| ... | @@ -496,7 +524,7 @@ fn gen(self: *Self) InnerError!void { | ... | @@ -496,7 +524,7 @@ fn gen(self: *Self) InnerError!void { |
| 496 | // Pop saved callee-preserved regs. | 524 | // Pop saved callee-preserved regs. |
| 497 | const backpatch_pop_callee_preserved_regs = try self.addInst(.{ | 525 | const backpatch_pop_callee_preserved_regs = try self.addInst(.{ |
| 498 | .tag = .nop, | 526 | .tag = .nop, |
| 499 | .ops = undefined, | 527 | .ops = .none, |
| 500 | .data = undefined, | 528 | .data = undefined, |
| 501 | }); | 529 | }); |
| 502 | | 530 | |
| ... | @@ -509,21 +537,12 @@ fn gen(self: *Self) InnerError!void { | ... | @@ -509,21 +537,12 @@ fn gen(self: *Self) InnerError!void { |
| 509 | // Maybe add rsp, x if required. This is backpatched later. | 537 | // Maybe add rsp, x if required. This is backpatched later. |
| 510 | const backpatch_stack_add = try self.addInst(.{ | 538 | const backpatch_stack_add = try self.addInst(.{ |
| 511 | .tag = .nop, | 539 | .tag = .nop, |
| 512 | .ops = undefined, | 540 | .ops = .none, |
| 513 | .data = undefined, | 541 | .data = undefined, |
| 514 | }); | 542 | }); |
| 515 | | 543 | |
| 516 | _ = try self.addInst(.{ | 544 | try self.assemble(.pop, .{ .op1 = .{ .reg = .rbp } }); |
| 517 | .tag = .pop, | 545 | try self.assemble(.ret, .{}); |
| 518 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = .rbp }), | | |
| 519 | .data = undefined, | | |
| 520 | }); | | |
| 521 | | | |
| 522 | _ = try self.addInst(.{ | | |
| 523 | .tag = .ret, | | |
| 524 | .ops = Mir.Inst.Ops.encode(.{ .flags = 0b11 }), | | |
| 525 | .data = undefined, | | |
| 526 | }); | | |
| 527 | | 546 | |
| 528 | // Adjust the stack | 547 | // Adjust the stack |
| 529 | if (self.max_end_stack > math.maxInt(i32)) { | 548 | if (self.max_end_stack > math.maxInt(i32)) { |
| ... | @@ -537,27 +556,34 @@ fn gen(self: *Self) InnerError!void { | ... | @@ -537,27 +556,34 @@ fn gen(self: *Self) InnerError!void { |
| 537 | if (aligned_stack_end > 0) { | 556 | if (aligned_stack_end > 0) { |
| 538 | self.mir_instructions.set(backpatch_stack_sub, .{ | 557 | self.mir_instructions.set(backpatch_stack_sub, .{ |
| 539 | .tag = .sub, | 558 | .tag = .sub, |
| 540 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = .rsp }), | 559 | .ops = .ri_u, |
| 541 | .data = .{ .imm = aligned_stack_end }, | 560 | .data = .{ .ri_u = .{ |
| | 561 | .r1 = .rsp, |
| | 562 | .imm = aligned_stack_end, |
| | 563 | } }, |
| 542 | }); | 564 | }); |
| 543 | self.mir_instructions.set(backpatch_stack_add, .{ | 565 | self.mir_instructions.set(backpatch_stack_add, .{ |
| 544 | .tag = .add, | 566 | .tag = .add, |
| 545 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = .rsp }), | 567 | .ops = .ri_u, |
| 546 | .data = .{ .imm = aligned_stack_end }, | 568 | .data = .{ .ri_u = .{ |
| | 569 | .r1 = .rsp, |
| | 570 | .imm = aligned_stack_end, |
| | 571 | } }, |
| 547 | }); | 572 | }); |
| 548 | | 573 | |
| 549 | const save_reg_list = try self.addExtra(Mir.SaveRegisterList{ | 574 | const save_reg_list = try self.addExtra(Mir.SaveRegisterList{ |
| | 575 | .base_reg = @enumToInt(Register.rbp), |
| 550 | .register_list = reg_list.asInt(), | 576 | .register_list = reg_list.asInt(), |
| 551 | .stack_end = aligned_stack_end, | 577 | .stack_end = aligned_stack_end, |
| 552 | }); | 578 | }); |
| 553 | self.mir_instructions.set(backpatch_push_callee_preserved_regs, .{ | 579 | self.mir_instructions.set(backpatch_push_callee_preserved_regs, .{ |
| 554 | .tag = .push_regs, | 580 | .tag = .push_regs, |
| 555 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = .rbp }), | 581 | .ops = undefined, |
| 556 | .data = .{ .payload = save_reg_list }, | 582 | .data = .{ .payload = save_reg_list }, |
| 557 | }); | 583 | }); |
| 558 | self.mir_instructions.set(backpatch_pop_callee_preserved_regs, .{ | 584 | self.mir_instructions.set(backpatch_pop_callee_preserved_regs, .{ |
| 559 | .tag = .pop_regs, | 585 | .tag = .pop_regs, |
| 560 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = .rbp }), | 586 | .ops = undefined, |
| 561 | .data = .{ .payload = save_reg_list }, | 587 | .data = .{ .payload = save_reg_list }, |
| 562 | }); | 588 | }); |
| 563 | } | 589 | } |
| ... | @@ -1306,14 +1332,15 @@ fn airMin(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1306,14 +1332,15 @@ fn airMin(self: *Self, inst: Air.Inst.Index) !void { |
| 1306 | .unsigned => .b, | 1332 | .unsigned => .b, |
| 1307 | .signed => .l, | 1333 | .signed => .l, |
| 1308 | }; | 1334 | }; |
| 1309 | _ = try self.addInst(.{ | 1335 | _ = cc; |
| 1310 | .tag = .cond_mov, | 1336 | // _ = try self.addInst(.{ |
| 1311 | .ops = Mir.Inst.Ops.encode(.{ | 1337 | // .tag = .cond_mov, |
| 1312 | .reg1 = dst_mcv.register, | 1338 | // .ops = Mir.Inst.Ops.encode(.{ |
| 1313 | .reg2 = lhs_reg, | 1339 | // .reg1 = dst_mcv.register, |
| 1314 | }), | 1340 | // .reg2 = lhs_reg, |
| 1315 | .data = .{ .cc = cc }, | 1341 | // }), |
| 1316 | }); | 1342 | // .data = .{ .cc = cc }, |
| | 1343 | // }); |
| 1317 | | 1344 | |
| 1318 | break :result dst_mcv; | 1345 | break :result dst_mcv; |
| 1319 | }; | 1346 | }; |
| ... | @@ -1513,13 +1540,14 @@ fn genSetStackTruncatedOverflowCompare( | ... | @@ -1513,13 +1540,14 @@ fn genSetStackTruncatedOverflowCompare( |
| 1513 | .signed => .o, | 1540 | .signed => .o, |
| 1514 | .unsigned => .c, | 1541 | .unsigned => .c, |
| 1515 | }; | 1542 | }; |
| 1516 | _ = try self.addInst(.{ | 1543 | _ = cc; |
| 1517 | .tag = .cond_set_byte, | 1544 | // _ = try self.addInst(.{ |
| 1518 | .ops = Mir.Inst.Ops.encode(.{ | 1545 | // .tag = .cond_set_byte, |
| 1519 | .reg1 = overflow_reg.to8(), | 1546 | // .ops = Mir.Inst.Ops.encode(.{ |
| 1520 | }), | 1547 | // .reg1 = overflow_reg.to8(), |
| 1521 | .data = .{ .cc = cc }, | 1548 | // }), |
| 1522 | }); | 1549 | // .data = .{ .cc = cc }, |
| | 1550 | // }); |
| 1523 | | 1551 | |
| 1524 | const scratch_reg = temp_regs[1]; | 1552 | const scratch_reg = temp_regs[1]; |
| 1525 | try self.genSetReg(extended_ty, scratch_reg, .{ .register = reg }); | 1553 | try self.genSetReg(extended_ty, scratch_reg, .{ .register = reg }); |
| ... | @@ -1532,11 +1560,11 @@ fn genSetStackTruncatedOverflowCompare( | ... | @@ -1532,11 +1560,11 @@ fn genSetStackTruncatedOverflowCompare( |
| 1532 | ); | 1560 | ); |
| 1533 | | 1561 | |
| 1534 | const eq_reg = temp_regs[2]; | 1562 | const eq_reg = temp_regs[2]; |
| 1535 | _ = try self.addInst(.{ | 1563 | // _ = try self.addInst(.{ |
| 1536 | .tag = .cond_set_byte, | 1564 | // .tag = .cond_set_byte, |
| 1537 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = eq_reg.to8() }), | 1565 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = eq_reg.to8() }), |
| 1538 | .data = .{ .cc = .ne }, | 1566 | // .data = .{ .cc = .ne }, |
| 1539 | }); | 1567 | // }); |
| 1540 | | 1568 | |
| 1541 | try self.genBinOpMir( | 1569 | try self.genBinOpMir( |
| 1542 | .@"or", | 1570 | .@"or", |
| ... | @@ -1680,25 +1708,26 @@ fn genIntMulDivOpMir( | ... | @@ -1680,25 +1708,26 @@ fn genIntMulDivOpMir( |
| 1680 | try self.genSetReg(ty, .rax, lhs); | 1708 | try self.genSetReg(ty, .rax, lhs); |
| 1681 | } | 1709 | } |
| 1682 | | 1710 | |
| 1683 | switch (signedness) { | 1711 | _ = signedness; |
| 1684 | .signed => { | 1712 | // switch (signedness) { |
| 1685 | _ = try self.addInst(.{ | 1713 | // .signed => { |
| 1686 | .tag = .cwd, | 1714 | // _ = try self.addInst(.{ |
| 1687 | .ops = Mir.Inst.Ops.encode(.{ .flags = 0b11 }), | 1715 | // .tag = .cwd, |
| 1688 | .data = undefined, | 1716 | // .ops = Mir.Inst.Ops.encode(.{ .flags = 0b11 }), |
| 1689 | }); | 1717 | // .data = undefined, |
| 1690 | }, | 1718 | // }); |
| 1691 | .unsigned => { | 1719 | // }, |
| 1692 | _ = try self.addInst(.{ | 1720 | // .unsigned => { |
| 1693 | .tag = .xor, | 1721 | // _ = try self.addInst(.{ |
| 1694 | .ops = Mir.Inst.Ops.encode(.{ | 1722 | // .tag = .xor, |
| 1695 | .reg1 = .rdx, | 1723 | // .ops = Mir.Inst.Ops.encode(.{ |
| 1696 | .reg2 = .rdx, | 1724 | // .reg1 = .rdx, |
| 1697 | }), | 1725 | // .reg2 = .rdx, |
| 1698 | .data = undefined, | 1726 | // }), |
| 1699 | }); | 1727 | // .data = undefined, |
| 1700 | }, | 1728 | // }); |
| 1701 | } | 1729 | // }, |
| | 1730 | // } |
| 1702 | | 1731 | |
| 1703 | const factor = switch (rhs) { | 1732 | const factor = switch (rhs) { |
| 1704 | .register => rhs, | 1733 | .register => rhs, |
| ... | @@ -1708,33 +1737,35 @@ fn genIntMulDivOpMir( | ... | @@ -1708,33 +1737,35 @@ fn genIntMulDivOpMir( |
| 1708 | break :blk MCValue{ .register = reg }; | 1737 | break :blk MCValue{ .register = reg }; |
| 1709 | }, | 1738 | }, |
| 1710 | }; | 1739 | }; |
| 1711 | | 1740 | _ = factor; |
| 1712 | switch (factor) { | 1741 | _ = tag; |
| 1713 | .register => |reg| { | 1742 | |
| 1714 | _ = try self.addInst(.{ | 1743 | // switch (factor) { |
| 1715 | .tag = tag, | 1744 | // .register => |reg| { |
| 1716 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = reg }), | 1745 | // _ = try self.addInst(.{ |
| 1717 | .data = undefined, | 1746 | // .tag = tag, |
| 1718 | }); | 1747 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = reg }), |
| 1719 | }, | 1748 | // .data = undefined, |
| 1720 | .stack_offset => |off| { | 1749 | // }); |
| 1721 | _ = try self.addInst(.{ | 1750 | // }, |
| 1722 | .tag = tag, | 1751 | // .stack_offset => |off| { |
| 1723 | .ops = Mir.Inst.Ops.encode(.{ | 1752 | // _ = try self.addInst(.{ |
| 1724 | .reg2 = .rbp, | 1753 | // .tag = tag, |
| 1725 | .flags = switch (abi_size) { | 1754 | // .ops = Mir.Inst.Ops.encode(.{ |
| 1726 | 1 => 0b00, | 1755 | // .reg2 = .rbp, |
| 1727 | 2 => 0b01, | 1756 | // .flags = switch (abi_size) { |
| 1728 | 4 => 0b10, | 1757 | // 1 => 0b00, |
| 1729 | 8 => 0b11, | 1758 | // 2 => 0b01, |
| 1730 | else => unreachable, | 1759 | // 4 => 0b10, |
| 1731 | }, | 1760 | // 8 => 0b11, |
| 1732 | }), | 1761 | // else => unreachable, |
| 1733 | .data = .{ .disp = -off }, | 1762 | // }, |
| 1734 | }); | 1763 | // }), |
| 1735 | }, | 1764 | // .data = .{ .disp = -off }, |
| 1736 | else => unreachable, | 1765 | // }); |
| 1737 | } | 1766 | // }, |
| | 1767 | // else => unreachable, |
| | 1768 | // } |
| 1738 | } | 1769 | } |
| 1739 | | 1770 | |
| 1740 | /// Always returns a register. | 1771 | /// Always returns a register. |
| ... | @@ -1760,38 +1791,38 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa | ... | @@ -1760,38 +1791,38 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa |
| 1760 | .unsigned => .div, | 1791 | .unsigned => .div, |
| 1761 | }, Type.isize, signedness, .{ .register = dividend }, .{ .register = divisor }); | 1792 | }, Type.isize, signedness, .{ .register = dividend }, .{ .register = divisor }); |
| 1762 | | 1793 | |
| 1763 | _ = try self.addInst(.{ | 1794 | // _ = try self.addInst(.{ |
| 1764 | .tag = .xor, | 1795 | // .tag = .xor, |
| 1765 | .ops = Mir.Inst.Ops.encode(.{ | 1796 | // .ops = Mir.Inst.Ops.encode(.{ |
| 1766 | .reg1 = divisor.to64(), | 1797 | // .reg1 = divisor.to64(), |
| 1767 | .reg2 = dividend.to64(), | 1798 | // .reg2 = dividend.to64(), |
| 1768 | }), | 1799 | // }), |
| 1769 | .data = undefined, | 1800 | // .data = undefined, |
| 1770 | }); | 1801 | // }); |
| 1771 | _ = try self.addInst(.{ | 1802 | // _ = try self.addInst(.{ |
| 1772 | .tag = .sar, | 1803 | // .tag = .sar, |
| 1773 | .ops = Mir.Inst.Ops.encode(.{ | 1804 | // .ops = Mir.Inst.Ops.encode(.{ |
| 1774 | .reg1 = divisor.to64(), | 1805 | // .reg1 = divisor.to64(), |
| 1775 | .flags = 0b10, | 1806 | // .flags = 0b10, |
| 1776 | }), | 1807 | // }), |
| 1777 | .data = .{ .imm = 63 }, | 1808 | // .data = .{ .imm = 63 }, |
| 1778 | }); | 1809 | // }); |
| 1779 | _ = try self.addInst(.{ | 1810 | // _ = try self.addInst(.{ |
| 1780 | .tag = .@"test", | 1811 | // .tag = .@"test", |
| 1781 | .ops = Mir.Inst.Ops.encode(.{ | 1812 | // .ops = Mir.Inst.Ops.encode(.{ |
| 1782 | .reg1 = .rdx, | 1813 | // .reg1 = .rdx, |
| 1783 | .reg2 = .rdx, | 1814 | // .reg2 = .rdx, |
| 1784 | }), | 1815 | // }), |
| 1785 | .data = undefined, | 1816 | // .data = undefined, |
| 1786 | }); | 1817 | // }); |
| 1787 | _ = try self.addInst(.{ | 1818 | // _ = try self.addInst(.{ |
| 1788 | .tag = .cond_mov, | 1819 | // .tag = .cond_mov, |
| 1789 | .ops = Mir.Inst.Ops.encode(.{ | 1820 | // .ops = Mir.Inst.Ops.encode(.{ |
| 1790 | .reg1 = divisor.to64(), | 1821 | // .reg1 = divisor.to64(), |
| 1791 | .reg2 = .rdx, | 1822 | // .reg2 = .rdx, |
| 1792 | }), | 1823 | // }), |
| 1793 | .data = .{ .cc = .e }, | 1824 | // .data = .{ .cc = .e }, |
| 1794 | }); | 1825 | // }); |
| 1795 | try self.genBinOpMir(.add, Type.isize, .{ .register = divisor }, .{ .register = .rax }); | 1826 | try self.genBinOpMir(.add, Type.isize, .{ .register = divisor }, .{ .register = .rax }); |
| 1796 | return MCValue{ .register = divisor }; | 1827 | return MCValue{ .register = divisor }; |
| 1797 | } | 1828 | } |
| ... | @@ -2226,16 +2257,17 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { | ... | @@ -2226,16 +2257,17 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 2226 | const addr_reg = try self.register_manager.allocReg(null, gp); | 2257 | const addr_reg = try self.register_manager.allocReg(null, gp); |
| 2227 | switch (slice_mcv) { | 2258 | switch (slice_mcv) { |
| 2228 | .stack_offset => |off| { | 2259 | .stack_offset => |off| { |
| | 2260 | _ = off; |
| 2229 | // mov reg, [rbp - 8] | 2261 | // mov reg, [rbp - 8] |
| 2230 | _ = try self.addInst(.{ | 2262 | // _ = try self.addInst(.{ |
| 2231 | .tag = .mov, | 2263 | // .tag = .mov, |
| 2232 | .ops = Mir.Inst.Ops.encode(.{ | 2264 | // .ops = Mir.Inst.Ops.encode(.{ |
| 2233 | .reg1 = addr_reg.to64(), | 2265 | // .reg1 = addr_reg.to64(), |
| 2234 | .reg2 = .rbp, | 2266 | // .reg2 = .rbp, |
| 2235 | .flags = 0b01, | 2267 | // .flags = 0b01, |
| 2236 | }), | 2268 | // }), |
| 2237 | .data = .{ .disp = -@intCast(i32, off) }, | 2269 | // .data = .{ .disp = -@intCast(i32, off) }, |
| 2238 | }); | 2270 | // }); |
| 2239 | }, | 2271 | }, |
| 2240 | else => return self.fail("TODO implement slice_elem_ptr when slice is {}", .{slice_mcv}), | 2272 | else => return self.fail("TODO implement slice_elem_ptr when slice is {}", .{slice_mcv}), |
| 2241 | } | 2273 | } |
| ... | @@ -2312,25 +2344,26 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2312,25 +2344,26 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2312 | )); | 2344 | )); |
| 2313 | try self.genSetStack(array_ty, off, array, .{}); | 2345 | try self.genSetStack(array_ty, off, array, .{}); |
| 2314 | // lea reg, [rbp] | 2346 | // lea reg, [rbp] |
| 2315 | _ = try self.addInst(.{ | 2347 | // _ = try self.addInst(.{ |
| 2316 | .tag = .lea, | 2348 | // .tag = .lea, |
| 2317 | .ops = Mir.Inst.Ops.encode(.{ | 2349 | // .ops = Mir.Inst.Ops.encode(.{ |
| 2318 | .reg1 = addr_reg.to64(), | 2350 | // .reg1 = addr_reg.to64(), |
| 2319 | .reg2 = .rbp, | 2351 | // .reg2 = .rbp, |
| 2320 | }), | 2352 | // }), |
| 2321 | .data = .{ .disp = -off }, | 2353 | // .data = .{ .disp = -off }, |
| 2322 | }); | 2354 | // }); |
| 2323 | }, | 2355 | }, |
| 2324 | .stack_offset => |off| { | 2356 | .stack_offset => |off| { |
| | 2357 | _ = off; |
| 2325 | // lea reg, [rbp] | 2358 | // lea reg, [rbp] |
| 2326 | _ = try self.addInst(.{ | 2359 | // _ = try self.addInst(.{ |
| 2327 | .tag = .lea, | 2360 | // .tag = .lea, |
| 2328 | .ops = Mir.Inst.Ops.encode(.{ | 2361 | // .ops = Mir.Inst.Ops.encode(.{ |
| 2329 | .reg1 = addr_reg.to64(), | 2362 | // .reg1 = addr_reg.to64(), |
| 2330 | .reg2 = .rbp, | 2363 | // .reg2 = .rbp, |
| 2331 | }), | 2364 | // }), |
| 2332 | .data = .{ .disp = -off }, | 2365 | // .data = .{ .disp = -off }, |
| 2333 | }); | 2366 | // }); |
| 2334 | }, | 2367 | }, |
| 2335 | .memory, .linker_load => { | 2368 | .memory, .linker_load => { |
| 2336 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, array); | 2369 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, array); |
| ... | @@ -2388,15 +2421,15 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2388,15 +2421,15 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2388 | return self.fail("TODO copy value with size {} from pointer", .{elem_abi_size}); | 2421 | return self.fail("TODO copy value with size {} from pointer", .{elem_abi_size}); |
| 2389 | } else { | 2422 | } else { |
| 2390 | // mov dst_mcv, [dst_mcv] | 2423 | // mov dst_mcv, [dst_mcv] |
| 2391 | _ = try self.addInst(.{ | 2424 | // _ = try self.addInst(.{ |
| 2392 | .tag = .mov, | 2425 | // .tag = .mov, |
| 2393 | .ops = Mir.Inst.Ops.encode(.{ | 2426 | // .ops = Mir.Inst.Ops.encode(.{ |
| 2394 | .reg1 = registerAlias(dst_mcv.register, @intCast(u32, elem_abi_size)), | 2427 | // .reg1 = registerAlias(dst_mcv.register, @intCast(u32, elem_abi_size)), |
| 2395 | .reg2 = dst_mcv.register, | 2428 | // .reg2 = dst_mcv.register, |
| 2396 | .flags = 0b01, | 2429 | // .flags = 0b01, |
| 2397 | }), | 2430 | // }), |
| 2398 | .data = .{ .disp = 0 }, | 2431 | // .data = .{ .disp = 0 }, |
| 2399 | }); | 2432 | // }); |
| 2400 | break :result .{ .register = registerAlias(dst_mcv.register, @intCast(u32, elem_abi_size)) }; | 2433 | break :result .{ .register = registerAlias(dst_mcv.register, @intCast(u32, elem_abi_size)) }; |
| 2401 | } | 2434 | } |
| 2402 | }; | 2435 | }; |
| ... | @@ -2650,16 +2683,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -2650,16 +2683,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2650 | .undef => unreachable, | 2683 | .undef => unreachable, |
| 2651 | .eflags => unreachable, | 2684 | .eflags => unreachable, |
| 2652 | .register => |dst_reg| { | 2685 | .register => |dst_reg| { |
| | 2686 | _ = dst_reg; |
| 2653 | // mov dst_reg, [reg] | 2687 | // mov dst_reg, [reg] |
| 2654 | _ = try self.addInst(.{ | 2688 | // _ = try self.addInst(.{ |
| 2655 | .tag = .mov, | 2689 | // .tag = .mov, |
| 2656 | .ops = Mir.Inst.Ops.encode(.{ | 2690 | // .ops = Mir.Inst.Ops.encode(.{ |
| 2657 | .reg1 = registerAlias(dst_reg, @intCast(u32, abi_size)), | 2691 | // .reg1 = registerAlias(dst_reg, @intCast(u32, abi_size)), |
| 2658 | .reg2 = reg, | 2692 | // .reg2 = reg, |
| 2659 | .flags = 0b01, | 2693 | // .flags = 0b01, |
| 2660 | }), | 2694 | // }), |
| 2661 | .data = .{ .disp = 0 }, | 2695 | // .data = .{ .disp = 0 }, |
| 2662 | }); | 2696 | // }); |
| 2663 | }, | 2697 | }, |
| 2664 | .stack_offset => |off| { | 2698 | .stack_offset => |off| { |
| 2665 | if (abi_size <= 8) { | 2699 | if (abi_size <= 8) { |
| ... | @@ -2724,19 +2758,22 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue | ... | @@ -2724,19 +2758,22 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue |
| 2724 | .direct => 0b01, | 2758 | .direct => 0b01, |
| 2725 | .import => 0b10, | 2759 | .import => 0b10, |
| 2726 | }; | 2760 | }; |
| 2727 | _ = try self.addInst(.{ | 2761 | _ = abi_size; |
| 2728 | .tag = .lea_pic, | 2762 | _ = atom_index; |
| 2729 | .ops = Mir.Inst.Ops.encode(.{ | 2763 | _ = flags; |
| 2730 | .reg1 = registerAlias(reg, abi_size), | 2764 | // _ = try self.addInst(.{ |
| 2731 | .flags = flags, | 2765 | // .tag = .lea_pic, |
| 2732 | }), | 2766 | // .ops = Mir.Inst.Ops.encode(.{ |
| 2733 | .data = .{ | 2767 | // .reg1 = registerAlias(reg, abi_size), |
| 2734 | .relocation = .{ | 2768 | // .flags = flags, |
| 2735 | .atom_index = atom_index, | 2769 | // }), |
| 2736 | .sym_index = load_struct.sym_index, | 2770 | // .data = .{ |
| 2737 | }, | 2771 | // .relocation = .{ |
| 2738 | }, | 2772 | // .atom_index = atom_index, |
| 2739 | }); | 2773 | // .sym_index = load_struct.sym_index, |
| | 2774 | // }, |
| | 2775 | // }, |
| | 2776 | // }); |
| 2740 | }, | 2777 | }, |
| 2741 | .memory => |addr| { | 2778 | .memory => |addr| { |
| 2742 | // TODO: in case the address fits in an imm32 we can use [ds:imm32] | 2779 | // TODO: in case the address fits in an imm32 we can use [ds:imm32] |
| ... | @@ -2779,27 +2816,28 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2779,27 +2816,28 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2779 | try self.genSetReg(value_ty, reg, value); | 2816 | try self.genSetReg(value_ty, reg, value); |
| 2780 | }, | 2817 | }, |
| 2781 | .immediate => |imm| { | 2818 | .immediate => |imm| { |
| | 2819 | _ = imm; |
| 2782 | switch (abi_size) { | 2820 | switch (abi_size) { |
| 2783 | 1, 2, 4 => { | 2821 | 1, 2, 4 => { |
| 2784 | // TODO this is wasteful! | 2822 | // TODO this is wasteful! |
| 2785 | // introduce new MIR tag specifically for mov [reg + 0], imm | 2823 | // introduce new MIR tag specifically for mov [reg + 0], imm |
| 2786 | const payload = try self.addExtra(Mir.ImmPair{ | 2824 | // const payload = try self.addExtra(Mir.ImmPair{ |
| 2787 | .dest_off = 0, | 2825 | // .dest_off = 0, |
| 2788 | .operand = @truncate(u32, imm), | 2826 | // .operand = @truncate(u32, imm), |
| 2789 | }); | 2827 | // }); |
| 2790 | _ = try self.addInst(.{ | 2828 | // _ = try self.addInst(.{ |
| 2791 | .tag = .mov_mem_imm, | 2829 | // .tag = .mov_mem_imm, |
| 2792 | .ops = Mir.Inst.Ops.encode(.{ | 2830 | // .ops = Mir.Inst.Ops.encode(.{ |
| 2793 | .reg1 = reg.to64(), | 2831 | // .reg1 = reg.to64(), |
| 2794 | .flags = switch (abi_size) { | 2832 | // .flags = switch (abi_size) { |
| 2795 | 1 => 0b00, | 2833 | // 1 => 0b00, |
| 2796 | 2 => 0b01, | 2834 | // 2 => 0b01, |
| 2797 | 4 => 0b10, | 2835 | // 4 => 0b10, |
| 2798 | else => unreachable, | 2836 | // else => unreachable, |
| 2799 | }, | 2837 | // }, |
| 2800 | }), | 2838 | // }), |
| 2801 | .data = .{ .payload = payload }, | 2839 | // .data = .{ .payload = payload }, |
| 2802 | }); | 2840 | // }); |
| 2803 | }, | 2841 | }, |
| 2804 | 8 => { | 2842 | 8 => { |
| 2805 | // TODO: optimization: if the imm is only using the lower | 2843 | // TODO: optimization: if the imm is only using the lower |
| ... | @@ -2829,13 +2867,13 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2829,13 +2867,13 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2829 | const overflow_bit_ty = value_ty.structFieldType(1); | 2867 | const overflow_bit_ty = value_ty.structFieldType(1); |
| 2830 | const overflow_bit_offset = value_ty.structFieldOffset(1, self.target.*); | 2868 | const overflow_bit_offset = value_ty.structFieldOffset(1, self.target.*); |
| 2831 | const tmp_reg = try self.register_manager.allocReg(null, gp); | 2869 | const tmp_reg = try self.register_manager.allocReg(null, gp); |
| 2832 | _ = try self.addInst(.{ | 2870 | // _ = try self.addInst(.{ |
| 2833 | .tag = .cond_set_byte, | 2871 | // .tag = .cond_set_byte, |
| 2834 | .ops = Mir.Inst.Ops.encode(.{ | 2872 | // .ops = Mir.Inst.Ops.encode(.{ |
| 2835 | .reg1 = tmp_reg.to8(), | 2873 | // .reg1 = tmp_reg.to8(), |
| 2836 | }), | 2874 | // }), |
| 2837 | .data = .{ .cc = ro.eflags }, | 2875 | // .data = .{ .cc = ro.eflags }, |
| 2838 | }); | 2876 | // }); |
| 2839 | try self.genInlineMemcpyRegisterRegister( | 2877 | try self.genInlineMemcpyRegisterRegister( |
| 2840 | overflow_bit_ty, | 2878 | overflow_bit_ty, |
| 2841 | reg, | 2879 | reg, |
| ... | @@ -2878,15 +2916,15 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2878,15 +2916,15 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2878 | | 2916 | |
| 2879 | // to get the actual address of the value we want to modify we have to go through the GOT | 2917 | // to get the actual address of the value we want to modify we have to go through the GOT |
| 2880 | // mov reg, [reg] | 2918 | // mov reg, [reg] |
| 2881 | _ = try self.addInst(.{ | 2919 | // _ = try self.addInst(.{ |
| 2882 | .tag = .mov, | 2920 | // .tag = .mov, |
| 2883 | .ops = Mir.Inst.Ops.encode(.{ | 2921 | // .ops = Mir.Inst.Ops.encode(.{ |
| 2884 | .reg1 = addr_reg.to64(), | 2922 | // .reg1 = addr_reg.to64(), |
| 2885 | .reg2 = addr_reg.to64(), | 2923 | // .reg2 = addr_reg.to64(), |
| 2886 | .flags = 0b01, | 2924 | // .flags = 0b01, |
| 2887 | }), | 2925 | // }), |
| 2888 | .data = .{ .disp = 0 }, | 2926 | // .data = .{ .disp = 0 }, |
| 2889 | }); | 2927 | // }); |
| 2890 | | 2928 | |
| 2891 | const new_ptr = MCValue{ .register = addr_reg.to64() }; | 2929 | const new_ptr = MCValue{ .register = addr_reg.to64() }; |
| 2892 | | 2930 | |
| ... | @@ -2896,11 +2934,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2896,11 +2934,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2896 | return self.fail("TODO saving imm to memory for abi_size {}", .{abi_size}); | 2934 | return self.fail("TODO saving imm to memory for abi_size {}", .{abi_size}); |
| 2897 | } | 2935 | } |
| 2898 | | 2936 | |
| 2899 | const payload = try self.addExtra(Mir.ImmPair{ | 2937 | // const payload = try self.addExtra(Mir.ImmPair{ |
| 2900 | .dest_off = 0, | 2938 | // .dest_off = 0, |
| 2901 | // TODO check if this logic is correct | 2939 | // // TODO check if this logic is correct |
| 2902 | .operand = @intCast(u32, imm), | 2940 | // .operand = @intCast(u32, imm), |
| 2903 | }); | 2941 | // }); |
| 2904 | const flags: u2 = switch (abi_size) { | 2942 | const flags: u2 = switch (abi_size) { |
| 2905 | 1 => 0b00, | 2943 | 1 => 0b00, |
| 2906 | 2 => 0b01, | 2944 | 2 => 0b01, |
| ... | @@ -2919,14 +2957,14 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2919,14 +2957,14 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2919 | return self.fail("TODO imm64 would get incorrectly sign extended", .{}); | 2957 | return self.fail("TODO imm64 would get incorrectly sign extended", .{}); |
| 2920 | } | 2958 | } |
| 2921 | } | 2959 | } |
| 2922 | _ = try self.addInst(.{ | 2960 | // _ = try self.addInst(.{ |
| 2923 | .tag = .mov_mem_imm, | 2961 | // .tag = .mov_mem_imm, |
| 2924 | .ops = Mir.Inst.Ops.encode(.{ | 2962 | // .ops = Mir.Inst.Ops.encode(.{ |
| 2925 | .reg1 = addr_reg.to64(), | 2963 | // .reg1 = addr_reg.to64(), |
| 2926 | .flags = flags, | 2964 | // .flags = flags, |
| 2927 | }), | 2965 | // }), |
| 2928 | .data = .{ .payload = payload }, | 2966 | // .data = .{ .payload = payload }, |
| 2929 | }); | 2967 | // }); |
| 2930 | }, | 2968 | }, |
| 2931 | .register => { | 2969 | .register => { |
| 2932 | return self.store(new_ptr, value, ptr_ty, value_ty); | 2970 | return self.store(new_ptr, value, ptr_ty, value_ty); |
| ... | @@ -2939,15 +2977,15 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2939,15 +2977,15 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2939 | | 2977 | |
| 2940 | try self.loadMemPtrIntoRegister(tmp_reg, value_ty, value); | 2978 | try self.loadMemPtrIntoRegister(tmp_reg, value_ty, value); |
| 2941 | | 2979 | |
| 2942 | _ = try self.addInst(.{ | 2980 | // _ = try self.addInst(.{ |
| 2943 | .tag = .mov, | 2981 | // .tag = .mov, |
| 2944 | .ops = Mir.Inst.Ops.encode(.{ | 2982 | // .ops = Mir.Inst.Ops.encode(.{ |
| 2945 | .reg1 = tmp_reg, | 2983 | // .reg1 = tmp_reg, |
| 2946 | .reg2 = tmp_reg, | 2984 | // .reg2 = tmp_reg, |
| 2947 | .flags = 0b01, | 2985 | // .flags = 0b01, |
| 2948 | }), | 2986 | // }), |
| 2949 | .data = .{ .disp = 0 }, | 2987 | // .data = .{ .disp = 0 }, |
| 2950 | }); | 2988 | // }); |
| 2951 | return self.store(new_ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); | 2989 | return self.store(new_ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); |
| 2952 | } | 2990 | } |
| 2953 | | 2991 | |
| ... | @@ -3109,14 +3147,14 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3109,14 +3147,14 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 3109 | }; | 3147 | }; |
| 3110 | const field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*)); | 3148 | const field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*)); |
| 3111 | if (signedness == .signed and field_size < 8) { | 3149 | if (signedness == .signed and field_size < 8) { |
| 3112 | _ = try self.addInst(.{ | 3150 | // _ = try self.addInst(.{ |
| 3113 | .tag = .mov_sign_extend, | 3151 | // .tag = .mov_sign_extend, |
| 3114 | .ops = Mir.Inst.Ops.encode(.{ | 3152 | // .ops = Mir.Inst.Ops.encode(.{ |
| 3115 | .reg1 = dst_mcv.register, | 3153 | // .reg1 = dst_mcv.register, |
| 3116 | .reg2 = registerAlias(dst_mcv.register, field_size), | 3154 | // .reg2 = registerAlias(dst_mcv.register, field_size), |
| 3117 | }), | 3155 | // }), |
| 3118 | .data = undefined, | 3156 | // .data = undefined, |
| 3119 | }); | 3157 | // }); |
| 3120 | } | 3158 | } |
| 3121 | | 3159 | |
| 3122 | break :result dst_mcv; | 3160 | break :result dst_mcv; |
| ... | @@ -3133,13 +3171,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3133,13 +3171,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 3133 | defer self.register_manager.unlockReg(reg_lock); | 3171 | defer self.register_manager.unlockReg(reg_lock); |
| 3134 | | 3172 | |
| 3135 | const dst_reg = try self.register_manager.allocReg(inst, gp); | 3173 | const dst_reg = try self.register_manager.allocReg(inst, gp); |
| 3136 | _ = try self.addInst(.{ | 3174 | // _ = try self.addInst(.{ |
| 3137 | .tag = .cond_set_byte, | 3175 | // .tag = .cond_set_byte, |
| 3138 | .ops = Mir.Inst.Ops.encode(.{ | 3176 | // .ops = Mir.Inst.Ops.encode(.{ |
| 3139 | .reg1 = dst_reg.to8(), | 3177 | // .reg1 = dst_reg.to8(), |
| 3140 | }), | 3178 | // }), |
| 3141 | .data = .{ .cc = ro.eflags }, | 3179 | // .data = .{ .cc = ro.eflags }, |
| 3142 | }); | 3180 | // }); |
| 3143 | break :result MCValue{ .register = dst_reg.to8() }; | 3181 | break :result MCValue{ .register = dst_reg.to8() }; |
| 3144 | }, | 3182 | }, |
| 3145 | else => unreachable, | 3183 | else => unreachable, |
| ... | @@ -3176,22 +3214,22 @@ fn genShiftBinOpMir(self: *Self, tag: Mir.Inst.Tag, ty: Type, reg: Register, shi | ... | @@ -3176,22 +3214,22 @@ fn genShiftBinOpMir(self: *Self, tag: Mir.Inst.Tag, ty: Type, reg: Register, shi |
| 3176 | .immediate => |imm| switch (imm) { | 3214 | .immediate => |imm| switch (imm) { |
| 3177 | 0 => return, | 3215 | 0 => return, |
| 3178 | 1 => { | 3216 | 1 => { |
| 3179 | _ = try self.addInst(.{ | 3217 | // _ = try self.addInst(.{ |
| 3180 | .tag = tag, | 3218 | // .tag = tag, |
| 3181 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = registerAlias(reg, abi_size) }), | 3219 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = registerAlias(reg, abi_size) }), |
| 3182 | .data = undefined, | 3220 | // .data = undefined, |
| 3183 | }); | 3221 | // }); |
| 3184 | return; | 3222 | return; |
| 3185 | }, | 3223 | }, |
| 3186 | else => { | 3224 | else => { |
| 3187 | _ = try self.addInst(.{ | 3225 | // _ = try self.addInst(.{ |
| 3188 | .tag = tag, | 3226 | // .tag = tag, |
| 3189 | .ops = Mir.Inst.Ops.encode(.{ | 3227 | // .ops = Mir.Inst.Ops.encode(.{ |
| 3190 | .reg1 = registerAlias(reg, abi_size), | 3228 | // .reg1 = registerAlias(reg, abi_size), |
| 3191 | .flags = 0b10, | 3229 | // .flags = 0b10, |
| 3192 | }), | 3230 | // }), |
| 3193 | .data = .{ .imm = @intCast(u8, imm) }, | 3231 | // .data = .{ .imm = @intCast(u8, imm) }, |
| 3194 | }); | 3232 | // }); |
| 3195 | return; | 3233 | return; |
| 3196 | }, | 3234 | }, |
| 3197 | }, | 3235 | }, |
| ... | @@ -3204,15 +3242,16 @@ fn genShiftBinOpMir(self: *Self, tag: Mir.Inst.Tag, ty: Type, reg: Register, shi | ... | @@ -3204,15 +3242,16 @@ fn genShiftBinOpMir(self: *Self, tag: Mir.Inst.Tag, ty: Type, reg: Register, shi |
| 3204 | try self.register_manager.getReg(.rcx, null); | 3242 | try self.register_manager.getReg(.rcx, null); |
| 3205 | try self.genSetReg(Type.u8, .rcx, shift); | 3243 | try self.genSetReg(Type.u8, .rcx, shift); |
| 3206 | } | 3244 | } |
| | 3245 | _ = abi_size; |
| 3207 | | 3246 | |
| 3208 | _ = try self.addInst(.{ | 3247 | // _ = try self.addInst(.{ |
| 3209 | .tag = tag, | 3248 | // .tag = tag, |
| 3210 | .ops = Mir.Inst.Ops.encode(.{ | 3249 | // .ops = Mir.Inst.Ops.encode(.{ |
| 3211 | .reg1 = registerAlias(reg, abi_size), | 3250 | // .reg1 = registerAlias(reg, abi_size), |
| 3212 | .flags = 0b01, | 3251 | // .flags = 0b01, |
| 3213 | }), | 3252 | // }), |
| 3214 | .data = undefined, | 3253 | // .data = undefined, |
| 3215 | }); | 3254 | // }); |
| 3216 | } | 3255 | } |
| 3217 | | 3256 | |
| 3218 | /// Result is always a register. | 3257 | /// Result is always a register. |
| ... | @@ -3583,49 +3622,51 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -3583,49 +3622,51 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3583 | .register => |src_reg| switch (dst_ty.zigTypeTag()) { | 3622 | .register => |src_reg| switch (dst_ty.zigTypeTag()) { |
| 3584 | .Float => { | 3623 | .Float => { |
| 3585 | if (intrinsicsAllowed(self.target.*, dst_ty)) { | 3624 | if (intrinsicsAllowed(self.target.*, dst_ty)) { |
| 3586 | const actual_tag: Mir.Inst.Tag = switch (dst_ty.tag()) { | 3625 | // const actual_tag: Mir.Inst.Tag = switch (dst_ty.tag()) { |
| 3587 | .f32 => switch (mir_tag) { | 3626 | // .f32 => switch (mir_tag) { |
| 3588 | .add => Mir.Inst.Tag.add_f32, | 3627 | // .add => Mir.Inst.Tag.add_f32, |
| 3589 | .cmp => Mir.Inst.Tag.cmp_f32, | 3628 | // .cmp => Mir.Inst.Tag.cmp_f32, |
| 3590 | else => return self.fail("TODO genBinOpMir for f32 register-register with MIR tag {}", .{mir_tag}), | 3629 | // else => return self.fail("TODO genBinOpMir for f32 register-register with MIR tag {}", .{mir_tag}), |
| 3591 | }, | 3630 | // }, |
| 3592 | .f64 => switch (mir_tag) { | 3631 | // .f64 => switch (mir_tag) { |
| 3593 | .add => Mir.Inst.Tag.add_f64, | 3632 | // .add => Mir.Inst.Tag.add_f64, |
| 3594 | .cmp => Mir.Inst.Tag.cmp_f64, | 3633 | // .cmp => Mir.Inst.Tag.cmp_f64, |
| 3595 | else => return self.fail("TODO genBinOpMir for f64 register-register with MIR tag {}", .{mir_tag}), | 3634 | // else => return self.fail("TODO genBinOpMir for f64 register-register with MIR tag {}", .{mir_tag}), |
| 3596 | }, | 3635 | // }, |
| 3597 | else => return self.fail("TODO genBinOpMir for float register-register and type {}", .{dst_ty.fmtDebug()}), | 3636 | // else => return self.fail("TODO genBinOpMir for float register-register and type {}", .{dst_ty.fmtDebug()}), |
| 3598 | }; | 3637 | // }; |
| 3599 | _ = try self.addInst(.{ | 3638 | // _ = try self.addInst(.{ |
| 3600 | .tag = actual_tag, | 3639 | // .tag = actual_tag, |
| 3601 | .ops = Mir.Inst.Ops.encode(.{ | 3640 | // .ops = Mir.Inst.Ops.encode(.{ |
| 3602 | .reg1 = dst_reg.to128(), | 3641 | // .reg1 = dst_reg.to128(), |
| 3603 | .reg2 = src_reg.to128(), | 3642 | // .reg2 = src_reg.to128(), |
| 3604 | }), | 3643 | // }), |
| 3605 | .data = undefined, | 3644 | // .data = undefined, |
| 3606 | }); | 3645 | // }); |
| 3607 | return; | 3646 | return; |
| 3608 | } | 3647 | } |
| 3609 | | 3648 | |
| 3610 | return self.fail("TODO genBinOpMir for float register-register and no intrinsics", .{}); | 3649 | return self.fail("TODO genBinOpMir for float register-register and no intrinsics", .{}); |
| 3611 | }, | 3650 | }, |
| 3612 | else => { | 3651 | else => { |
| 3613 | _ = try self.addInst(.{ | 3652 | _ = src_reg; |
| 3614 | .tag = mir_tag, | 3653 | // _ = try self.addInst(.{ |
| 3615 | .ops = Mir.Inst.Ops.encode(.{ | 3654 | // .tag = mir_tag, |
| 3616 | .reg1 = registerAlias(dst_reg, abi_size), | 3655 | // .ops = Mir.Inst.Ops.encode(.{ |
| 3617 | .reg2 = registerAlias(src_reg, abi_size), | 3656 | // .reg1 = registerAlias(dst_reg, abi_size), |
| 3618 | }), | 3657 | // .reg2 = registerAlias(src_reg, abi_size), |
| 3619 | .data = undefined, | 3658 | // }), |
| 3620 | }); | 3659 | // .data = undefined, |
| | 3660 | // }); |
| 3621 | }, | 3661 | }, |
| 3622 | }, | 3662 | }, |
| 3623 | .immediate => |imm| { | 3663 | .immediate => |imm| { |
| 3624 | _ = try self.addInst(.{ | 3664 | _ = imm; |
| 3625 | .tag = mir_tag, | 3665 | // _ = try self.addInst(.{ |
| 3626 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = registerAlias(dst_reg, abi_size) }), | 3666 | // .tag = mir_tag, |
| 3627 | .data = .{ .imm = @intCast(u32, imm) }, | 3667 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = registerAlias(dst_reg, abi_size) }), |
| 3628 | }); | 3668 | // .data = .{ .imm = @intCast(u32, imm) }, |
| | 3669 | // }); |
| 3629 | }, | 3670 | }, |
| 3630 | .memory, | 3671 | .memory, |
| 3631 | .linker_load, | 3672 | .linker_load, |
| ... | @@ -3642,15 +3683,15 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -3642,15 +3683,15 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3642 | if (off > math.maxInt(i32)) { | 3683 | if (off > math.maxInt(i32)) { |
| 3643 | return self.fail("stack offset too large", .{}); | 3684 | return self.fail("stack offset too large", .{}); |
| 3644 | } | 3685 | } |
| 3645 | _ = try self.addInst(.{ | 3686 | // _ = try self.addInst(.{ |
| 3646 | .tag = mir_tag, | 3687 | // .tag = mir_tag, |
| 3647 | .ops = Mir.Inst.Ops.encode(.{ | 3688 | // .ops = Mir.Inst.Ops.encode(.{ |
| 3648 | .reg1 = registerAlias(dst_reg, abi_size), | 3689 | // .reg1 = registerAlias(dst_reg, abi_size), |
| 3649 | .reg2 = .rbp, | 3690 | // .reg2 = .rbp, |
| 3650 | .flags = 0b01, | 3691 | // .flags = 0b01, |
| 3651 | }), | 3692 | // }), |
| 3652 | .data = .{ .disp = -off }, | 3693 | // .data = .{ .disp = -off }, |
| 3653 | }); | 3694 | // }); |
| 3654 | }, | 3695 | }, |
| 3655 | } | 3696 | } |
| 3656 | }, | 3697 | }, |
| ... | @@ -3668,26 +3709,28 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -3668,26 +3709,28 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3668 | .dead, .unreach => unreachable, | 3709 | .dead, .unreach => unreachable, |
| 3669 | .register_overflow => unreachable, | 3710 | .register_overflow => unreachable, |
| 3670 | .register => |src_reg| { | 3711 | .register => |src_reg| { |
| 3671 | _ = try self.addInst(.{ | 3712 | _ = src_reg; |
| 3672 | .tag = mir_tag, | 3713 | // _ = try self.addInst(.{ |
| 3673 | .ops = Mir.Inst.Ops.encode(.{ | 3714 | // .tag = mir_tag, |
| 3674 | .reg1 = .rbp, | 3715 | // .ops = Mir.Inst.Ops.encode(.{ |
| 3675 | .reg2 = registerAlias(src_reg, abi_size), | 3716 | // .reg1 = .rbp, |
| 3676 | .flags = 0b10, | 3717 | // .reg2 = registerAlias(src_reg, abi_size), |
| 3677 | }), | 3718 | // .flags = 0b10, |
| 3678 | .data = .{ .disp = -off }, | 3719 | // }), |
| 3679 | }); | 3720 | // .data = .{ .disp = -off }, |
| | 3721 | // }); |
| 3680 | }, | 3722 | }, |
| 3681 | .immediate => |imm| { | 3723 | .immediate => |imm| { |
| 3682 | const tag: Mir.Inst.Tag = switch (mir_tag) { | 3724 | _ = imm; |
| 3683 | .add => .add_mem_imm, | 3725 | // const tag: Mir.Inst.Tag = switch (mir_tag) { |
| 3684 | .@"or" => .or_mem_imm, | 3726 | // .add => .add_mem_imm, |
| 3685 | .@"and" => .and_mem_imm, | 3727 | // .@"or" => .or_mem_imm, |
| 3686 | .sub => .sub_mem_imm, | 3728 | // .@"and" => .and_mem_imm, |
| 3687 | .xor => .xor_mem_imm, | 3729 | // .sub => .sub_mem_imm, |
| 3688 | .cmp => .cmp_mem_imm, | 3730 | // .xor => .xor_mem_imm, |
| 3689 | else => unreachable, | 3731 | // .cmp => .cmp_mem_imm, |
| 3690 | }; | 3732 | // else => unreachable, |
| | 3733 | // }; |
| 3691 | const flags: u2 = switch (abi_size) { | 3734 | const flags: u2 = switch (abi_size) { |
| 3692 | 1 => 0b00, | 3735 | 1 => 0b00, |
| 3693 | 2 => 0b01, | 3736 | 2 => 0b01, |
| ... | @@ -3695,18 +3738,19 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -3695,18 +3738,19 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3695 | 8 => 0b11, | 3738 | 8 => 0b11, |
| 3696 | else => unreachable, | 3739 | else => unreachable, |
| 3697 | }; | 3740 | }; |
| 3698 | const payload = try self.addExtra(Mir.ImmPair{ | 3741 | // const payload = try self.addExtra(Mir.ImmPair{ |
| 3699 | .dest_off = -off, | 3742 | // .dest_off = -off, |
| 3700 | .operand = @intCast(u32, imm), | 3743 | // .operand = @intCast(u32, imm), |
| 3701 | }); | 3744 | // }); |
| 3702 | _ = try self.addInst(.{ | 3745 | _ = flags; |
| 3703 | .tag = tag, | 3746 | // _ = try self.addInst(.{ |
| 3704 | .ops = Mir.Inst.Ops.encode(.{ | 3747 | // .tag = tag, |
| 3705 | .reg1 = .rbp, | 3748 | // .ops = Mir.Inst.Ops.encode(.{ |
| 3706 | .flags = flags, | 3749 | // .reg1 = .rbp, |
| 3707 | }), | 3750 | // .flags = flags, |
| 3708 | .data = .{ .payload = payload }, | 3751 | // }), |
| 3709 | }); | 3752 | // .data = .{ .payload = payload }, |
| | 3753 | // }); |
| 3710 | }, | 3754 | }, |
| 3711 | .memory, | 3755 | .memory, |
| 3712 | .stack_offset, | 3756 | .stack_offset, |
| ... | @@ -3735,6 +3779,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -3735,6 +3779,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3735 | /// Does not support byte-size operands. | 3779 | /// Does not support byte-size operands. |
| 3736 | fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void { | 3780 | fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void { |
| 3737 | const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*)); | 3781 | const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*)); |
| | 3782 | _ = abi_size; |
| 3738 | switch (dst_mcv) { | 3783 | switch (dst_mcv) { |
| 3739 | .none => unreachable, | 3784 | .none => unreachable, |
| 3740 | .undef => unreachable, | 3785 | .undef => unreachable, |
| ... | @@ -3750,29 +3795,30 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M | ... | @@ -3750,29 +3795,30 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3750 | .ptr_stack_offset => unreachable, | 3795 | .ptr_stack_offset => unreachable, |
| 3751 | .register_overflow => unreachable, | 3796 | .register_overflow => unreachable, |
| 3752 | .register => |src_reg| { | 3797 | .register => |src_reg| { |
| | 3798 | _ = src_reg; |
| 3753 | // register, register | 3799 | // register, register |
| 3754 | _ = try self.addInst(.{ | 3800 | // _ = try self.addInst(.{ |
| 3755 | .tag = .imul_complex, | 3801 | // .tag = .imul_complex, |
| 3756 | .ops = Mir.Inst.Ops.encode(.{ | 3802 | // .ops = Mir.Inst.Ops.encode(.{ |
| 3757 | .reg1 = registerAlias(dst_reg, abi_size), | 3803 | // .reg1 = registerAlias(dst_reg, abi_size), |
| 3758 | .reg2 = registerAlias(src_reg, abi_size), | 3804 | // .reg2 = registerAlias(src_reg, abi_size), |
| 3759 | }), | 3805 | // }), |
| 3760 | .data = undefined, | 3806 | // .data = undefined, |
| 3761 | }); | 3807 | // }); |
| 3762 | }, | 3808 | }, |
| 3763 | .immediate => |imm| { | 3809 | .immediate => |imm| { |
| 3764 | // TODO take into account the type's ABI size when selecting the register alias | 3810 | // TODO take into account the type's ABI size when selecting the register alias |
| 3765 | // register, immediate | 3811 | // register, immediate |
| 3766 | if (math.minInt(i32) <= imm and imm <= math.maxInt(i32)) { | 3812 | if (math.minInt(i32) <= imm and imm <= math.maxInt(i32)) { |
| 3767 | _ = try self.addInst(.{ | 3813 | // _ = try self.addInst(.{ |
| 3768 | .tag = .imul_complex, | 3814 | // .tag = .imul_complex, |
| 3769 | .ops = Mir.Inst.Ops.encode(.{ | 3815 | // .ops = Mir.Inst.Ops.encode(.{ |
| 3770 | .reg1 = dst_reg.to32(), | 3816 | // .reg1 = dst_reg.to32(), |
| 3771 | .reg2 = dst_reg.to32(), | 3817 | // .reg2 = dst_reg.to32(), |
| 3772 | .flags = 0b10, | 3818 | // .flags = 0b10, |
| 3773 | }), | 3819 | // }), |
| 3774 | .data = .{ .imm = @intCast(u32, imm) }, | 3820 | // .data = .{ .imm = @intCast(u32, imm) }, |
| 3775 | }); | 3821 | // }); |
| 3776 | } else { | 3822 | } else { |
| 3777 | // TODO verify we don't spill and assign to the same register as dst_mcv | 3823 | // TODO verify we don't spill and assign to the same register as dst_mcv |
| 3778 | const src_reg = try self.copyToTmpRegister(dst_ty, src_mcv); | 3824 | const src_reg = try self.copyToTmpRegister(dst_ty, src_mcv); |
| ... | @@ -3780,15 +3826,16 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M | ... | @@ -3780,15 +3826,16 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3780 | } | 3826 | } |
| 3781 | }, | 3827 | }, |
| 3782 | .stack_offset => |off| { | 3828 | .stack_offset => |off| { |
| 3783 | _ = try self.addInst(.{ | 3829 | _ = off; |
| 3784 | .tag = .imul_complex, | 3830 | // _ = try self.addInst(.{ |
| 3785 | .ops = Mir.Inst.Ops.encode(.{ | 3831 | // .tag = .imul_complex, |
| 3786 | .reg1 = registerAlias(dst_reg, abi_size), | 3832 | // .ops = Mir.Inst.Ops.encode(.{ |
| 3787 | .reg2 = .rbp, | 3833 | // .reg1 = registerAlias(dst_reg, abi_size), |
| 3788 | .flags = 0b01, | 3834 | // .reg2 = .rbp, |
| 3789 | }), | 3835 | // .flags = 0b01, |
| 3790 | .data = .{ .disp = -off }, | 3836 | // }), |
| 3791 | }); | 3837 | // .data = .{ .disp = -off }, |
| | 3838 | // }); |
| 3792 | }, | 3839 | }, |
| 3793 | .memory => { | 3840 | .memory => { |
| 3794 | return self.fail("TODO implement x86 multiply source memory", .{}); | 3841 | return self.fail("TODO implement x86 multiply source memory", .{}); |
| ... | @@ -3811,16 +3858,17 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M | ... | @@ -3811,16 +3858,17 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3811 | .register => |src_reg| { | 3858 | .register => |src_reg| { |
| 3812 | // copy dst to a register | 3859 | // copy dst to a register |
| 3813 | const dst_reg = try self.copyToTmpRegister(dst_ty, dst_mcv); | 3860 | const dst_reg = try self.copyToTmpRegister(dst_ty, dst_mcv); |
| | 3861 | _ = src_reg; |
| 3814 | // multiply into dst_reg | 3862 | // multiply into dst_reg |
| 3815 | // register, register | 3863 | // register, register |
| 3816 | _ = try self.addInst(.{ | 3864 | // _ = try self.addInst(.{ |
| 3817 | .tag = .imul_complex, | 3865 | // .tag = .imul_complex, |
| 3818 | .ops = Mir.Inst.Ops.encode(.{ | 3866 | // .ops = Mir.Inst.Ops.encode(.{ |
| 3819 | .reg1 = registerAlias(dst_reg, abi_size), | 3867 | // .reg1 = registerAlias(dst_reg, abi_size), |
| 3820 | .reg2 = registerAlias(src_reg, abi_size), | 3868 | // .reg2 = registerAlias(src_reg, abi_size), |
| 3821 | }), | 3869 | // }), |
| 3822 | .data = undefined, | 3870 | // .data = undefined, |
| 3823 | }); | 3871 | // }); |
| 3824 | // copy dst_reg back out | 3872 | // copy dst_reg back out |
| 3825 | return self.genSetStack(dst_ty, off, .{ .register = dst_reg }, .{}); | 3873 | return self.genSetStack(dst_ty, off, .{ .register = dst_reg }, .{}); |
| 3826 | }, | 3874 | }, |
| ... | @@ -3946,20 +3994,20 @@ fn genVarDbgInfo( | ... | @@ -3946,20 +3994,20 @@ fn genVarDbgInfo( |
| 3946 | } | 3994 | } |
| 3947 | | 3995 | |
| 3948 | fn airTrap(self: *Self) !void { | 3996 | fn airTrap(self: *Self) !void { |
| 3949 | _ = try self.addInst(.{ | 3997 | // _ = try self.addInst(.{ |
| 3950 | .tag = .ud, | 3998 | // .tag = .ud, |
| 3951 | .ops = Mir.Inst.Ops.encode(.{}), | 3999 | // .ops = Mir.Inst.Ops.encode(.{}), |
| 3952 | .data = undefined, | 4000 | // .data = undefined, |
| 3953 | }); | 4001 | // }); |
| 3954 | return self.finishAirBookkeeping(); | 4002 | return self.finishAirBookkeeping(); |
| 3955 | } | 4003 | } |
| 3956 | | 4004 | |
| 3957 | fn airBreakpoint(self: *Self) !void { | 4005 | fn airBreakpoint(self: *Self) !void { |
| 3958 | _ = try self.addInst(.{ | 4006 | // _ = try self.addInst(.{ |
| 3959 | .tag = .interrupt, | 4007 | // .tag = .interrupt, |
| 3960 | .ops = Mir.Inst.Ops.encode(.{}), | 4008 | // .ops = Mir.Inst.Ops.encode(.{}), |
| 3961 | .data = undefined, | 4009 | // .data = undefined, |
| 3962 | }); | 4010 | // }); |
| 3963 | return self.finishAirBookkeeping(); | 4011 | return self.finishAirBookkeeping(); |
| 3964 | } | 4012 | } |
| 3965 | | 4013 | |
| ... | @@ -4054,11 +4102,11 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4054,11 +4102,11 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4054 | | 4102 | |
| 4055 | if (info.stack_byte_count > 0) { | 4103 | if (info.stack_byte_count > 0) { |
| 4056 | // Adjust the stack | 4104 | // Adjust the stack |
| 4057 | _ = try self.addInst(.{ | 4105 | // _ = try self.addInst(.{ |
| 4058 | .tag = .sub, | 4106 | // .tag = .sub, |
| 4059 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = .rsp }), | 4107 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = .rsp }), |
| 4060 | .data = .{ .imm = info.stack_byte_count }, | 4108 | // .data = .{ .imm = info.stack_byte_count }, |
| 4061 | }); | 4109 | // }); |
| 4062 | } | 4110 | } |
| 4063 | | 4111 | |
| 4064 | // Due to incremental compilation, how function calls are generated depends | 4112 | // Due to incremental compilation, how function calls are generated depends |
| ... | @@ -4072,11 +4120,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4072,11 +4120,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4072 | const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl); | 4120 | const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl); |
| 4073 | const atom = elf_file.getAtom(atom_index); | 4121 | const atom = elf_file.getAtom(atom_index); |
| 4074 | const got_addr = @intCast(i32, atom.getOffsetTableAddress(elf_file)); | 4122 | const got_addr = @intCast(i32, atom.getOffsetTableAddress(elf_file)); |
| 4075 | _ = try self.addInst(.{ | 4123 | _ = got_addr; |
| 4076 | .tag = .call, | 4124 | // _ = try self.addInst(.{ |
| 4077 | .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }), | 4125 | // .tag = .call, |
| 4078 | .data = .{ .disp = got_addr }, | 4126 | // .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }), |
| 4079 | }); | 4127 | // .data = .{ .disp = got_addr }, |
| | 4128 | // }); |
| 4080 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | 4129 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { |
| 4081 | const atom_index = try coff_file.getOrCreateAtomForDecl(func.owner_decl); | 4130 | const atom_index = try coff_file.getOrCreateAtomForDecl(func.owner_decl); |
| 4082 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; | 4131 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; |
| ... | @@ -4086,14 +4135,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4086,14 +4135,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4086 | .sym_index = sym_index, | 4135 | .sym_index = sym_index, |
| 4087 | }, | 4136 | }, |
| 4088 | }); | 4137 | }); |
| 4089 | _ = try self.addInst(.{ | 4138 | // _ = try self.addInst(.{ |
| 4090 | .tag = .call, | 4139 | // .tag = .call, |
| 4091 | .ops = Mir.Inst.Ops.encode(.{ | 4140 | // .ops = Mir.Inst.Ops.encode(.{ |
| 4092 | .reg1 = .rax, | 4141 | // .reg1 = .rax, |
| 4093 | .flags = 0b01, | 4142 | // .flags = 0b01, |
| 4094 | }), | 4143 | // }), |
| 4095 | .data = undefined, | 4144 | // .data = undefined, |
| 4096 | }); | 4145 | // }); |
| 4097 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | 4146 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 4098 | const atom_index = try macho_file.getOrCreateAtomForDecl(func.owner_decl); | 4147 | const atom_index = try macho_file.getOrCreateAtomForDecl(func.owner_decl); |
| 4099 | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; | 4148 | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; |
| ... | @@ -4103,14 +4152,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4103,14 +4152,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4103 | .sym_index = sym_index, | 4152 | .sym_index = sym_index, |
| 4104 | }, | 4153 | }, |
| 4105 | }); | 4154 | }); |
| 4106 | _ = try self.addInst(.{ | 4155 | // _ = try self.addInst(.{ |
| 4107 | .tag = .call, | 4156 | // .tag = .call, |
| 4108 | .ops = Mir.Inst.Ops.encode(.{ | 4157 | // .ops = Mir.Inst.Ops.encode(.{ |
| 4109 | .reg1 = .rax, | 4158 | // .reg1 = .rax, |
| 4110 | .flags = 0b01, | 4159 | // .flags = 0b01, |
| 4111 | }), | 4160 | // }), |
| 4112 | .data = undefined, | 4161 | // .data = undefined, |
| 4113 | }); | 4162 | // }); |
| 4114 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { | 4163 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 4115 | const decl_block_index = try p9.seeDecl(func.owner_decl); | 4164 | const decl_block_index = try p9.seeDecl(func.owner_decl); |
| 4116 | const decl_block = p9.getDeclBlock(decl_block_index); | 4165 | const decl_block = p9.getDeclBlock(decl_block_index); |
| ... | @@ -4119,11 +4168,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4119,11 +4168,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4119 | const got_addr = p9.bases.data; | 4168 | const got_addr = p9.bases.data; |
| 4120 | const got_index = decl_block.got_index.?; | 4169 | const got_index = decl_block.got_index.?; |
| 4121 | const fn_got_addr = got_addr + got_index * ptr_bytes; | 4170 | const fn_got_addr = got_addr + got_index * ptr_bytes; |
| 4122 | _ = try self.addInst(.{ | 4171 | _ = fn_got_addr; |
| 4123 | .tag = .call, | 4172 | // _ = try self.addInst(.{ |
| 4124 | .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }), | 4173 | // .tag = .call, |
| 4125 | .data = .{ .disp = @intCast(i32, fn_got_addr) }, | 4174 | // .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }), |
| 4126 | }); | 4175 | // .data = .{ .disp = @intCast(i32, fn_got_addr) }, |
| | 4176 | // }); |
| 4127 | } else unreachable; | 4177 | } else unreachable; |
| 4128 | } else if (func_value.castTag(.extern_fn)) |func_payload| { | 4178 | } else if (func_value.castTag(.extern_fn)) |func_payload| { |
| 4129 | const extern_fn = func_payload.data; | 4179 | const extern_fn = func_payload.data; |
| ... | @@ -4143,26 +4193,28 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4143,26 +4193,28 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4143 | .sym_index = sym_index, | 4193 | .sym_index = sym_index, |
| 4144 | }, | 4194 | }, |
| 4145 | }); | 4195 | }); |
| 4146 | _ = try self.addInst(.{ | 4196 | // _ = try self.addInst(.{ |
| 4147 | .tag = .call, | 4197 | // .tag = .call, |
| 4148 | .ops = Mir.Inst.Ops.encode(.{ | 4198 | // .ops = Mir.Inst.Ops.encode(.{ |
| 4149 | .reg1 = .rax, | 4199 | // .reg1 = .rax, |
| 4150 | .flags = 0b01, | 4200 | // .flags = 0b01, |
| 4151 | }), | 4201 | // }), |
| 4152 | .data = undefined, | 4202 | // .data = undefined, |
| 4153 | }); | 4203 | // }); |
| 4154 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | 4204 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 4155 | const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0)); | 4205 | const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0)); |
| 4156 | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); | 4206 | const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl); |
| 4157 | const atom_index = macho_file.getAtom(atom).getSymbolIndex().?; | 4207 | const atom_index = macho_file.getAtom(atom).getSymbolIndex().?; |
| 4158 | _ = try self.addInst(.{ | 4208 | _ = sym_index; |
| 4159 | .tag = .call_extern, | 4209 | _ = atom_index; |
| 4160 | .ops = undefined, | 4210 | // _ = try self.addInst(.{ |
| 4161 | .data = .{ .relocation = .{ | 4211 | // .tag = .call_extern, |
| 4162 | .atom_index = atom_index, | 4212 | // .ops = undefined, |
| 4163 | .sym_index = sym_index, | 4213 | // .data = .{ .relocation = .{ |
| 4164 | } }, | 4214 | // .atom_index = atom_index, |
| 4165 | }); | 4215 | // .sym_index = sym_index, |
| | 4216 | // } }, |
| | 4217 | // }); |
| 4166 | } else { | 4218 | } else { |
| 4167 | return self.fail("TODO implement calling extern functions", .{}); | 4219 | return self.fail("TODO implement calling extern functions", .{}); |
| 4168 | } | 4220 | } |
| ... | @@ -4173,23 +4225,23 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4173,23 +4225,23 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4173 | assert(ty.zigTypeTag() == .Pointer); | 4225 | assert(ty.zigTypeTag() == .Pointer); |
| 4174 | const mcv = try self.resolveInst(callee); | 4226 | const mcv = try self.resolveInst(callee); |
| 4175 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); | 4227 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); |
| 4176 | _ = try self.addInst(.{ | 4228 | // _ = try self.addInst(.{ |
| 4177 | .tag = .call, | 4229 | // .tag = .call, |
| 4178 | .ops = Mir.Inst.Ops.encode(.{ | 4230 | // .ops = Mir.Inst.Ops.encode(.{ |
| 4179 | .reg1 = .rax, | 4231 | // .reg1 = .rax, |
| 4180 | .flags = 0b01, | 4232 | // .flags = 0b01, |
| 4181 | }), | 4233 | // }), |
| 4182 | .data = undefined, | 4234 | // .data = undefined, |
| 4183 | }); | 4235 | // }); |
| 4184 | } | 4236 | } |
| 4185 | | 4237 | |
| 4186 | if (info.stack_byte_count > 0) { | 4238 | if (info.stack_byte_count > 0) { |
| 4187 | // Readjust the stack | 4239 | // Readjust the stack |
| 4188 | _ = try self.addInst(.{ | 4240 | // _ = try self.addInst(.{ |
| 4189 | .tag = .add, | 4241 | // .tag = .add, |
| 4190 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = .rsp }), | 4242 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = .rsp }), |
| 4191 | .data = .{ .imm = info.stack_byte_count }, | 4243 | // .data = .{ .imm = info.stack_byte_count }, |
| 4192 | }); | 4244 | // }); |
| 4193 | } | 4245 | } |
| 4194 | | 4246 | |
| 4195 | const result: MCValue = result: { | 4247 | const result: MCValue = result: { |
| ... | @@ -4246,12 +4298,12 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4246,12 +4298,12 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 4246 | // TODO when implementing defer, this will need to jump to the appropriate defer expression. | 4298 | // TODO when implementing defer, this will need to jump to the appropriate defer expression. |
| 4247 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction | 4299 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction |
| 4248 | // which is available if the jump is 127 bytes or less forward. | 4300 | // which is available if the jump is 127 bytes or less forward. |
| 4249 | const jmp_reloc = try self.addInst(.{ | 4301 | // const jmp_reloc = try self.addInst(.{ |
| 4250 | .tag = .jmp, | 4302 | // .tag = .jmp, |
| 4251 | .ops = Mir.Inst.Ops.encode(.{}), | 4303 | // .ops = Mir.Inst.Ops.encode(.{}), |
| 4252 | .data = .{ .inst = undefined }, | 4304 | // .data = .{ .inst = undefined }, |
| 4253 | }); | 4305 | // }); |
| 4254 | try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc); | 4306 | // try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc); |
| 4255 | return self.finishAir(inst, .dead, .{ un_op, .none, .none }); | 4307 | return self.finishAir(inst, .dead, .{ un_op, .none, .none }); |
| 4256 | } | 4308 | } |
| 4257 | | 4309 | |
| ... | @@ -4282,12 +4334,12 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4282,12 +4334,12 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 4282 | // TODO when implementing defer, this will need to jump to the appropriate defer expression. | 4334 | // TODO when implementing defer, this will need to jump to the appropriate defer expression. |
| 4283 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction | 4335 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction |
| 4284 | // which is available if the jump is 127 bytes or less forward. | 4336 | // which is available if the jump is 127 bytes or less forward. |
| 4285 | const jmp_reloc = try self.addInst(.{ | 4337 | // const jmp_reloc = try self.addInst(.{ |
| 4286 | .tag = .jmp, | 4338 | // .tag = .jmp, |
| 4287 | .ops = Mir.Inst.Ops.encode(.{}), | 4339 | // .ops = Mir.Inst.Ops.encode(.{}), |
| 4288 | .data = .{ .inst = undefined }, | 4340 | // .data = .{ .inst = undefined }, |
| 4289 | }); | 4341 | // }); |
| 4290 | try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc); | 4342 | // try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc); |
| 4291 | return self.finishAir(inst, .dead, .{ un_op, .none, .none }); | 4343 | return self.finishAir(inst, .dead, .{ un_op, .none, .none }); |
| 4292 | } | 4344 | } |
| 4293 | | 4345 | |
| ... | @@ -4461,33 +4513,35 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 { | ... | @@ -4461,33 +4513,35 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 { |
| 4461 | const abi_size = ty.abiSize(self.target.*); | 4513 | const abi_size = ty.abiSize(self.target.*); |
| 4462 | switch (mcv) { | 4514 | switch (mcv) { |
| 4463 | .eflags => |cc| { | 4515 | .eflags => |cc| { |
| 4464 | return self.addInst(.{ | 4516 | _ = cc; |
| 4465 | .tag = .cond_jmp, | 4517 | // return self.addInst(.{ |
| 4466 | .ops = Mir.Inst.Ops.encode(.{}), | 4518 | // .tag = .cond_jmp, |
| 4467 | .data = .{ | 4519 | // .ops = Mir.Inst.Ops.encode(.{}), |
| 4468 | .inst_cc = .{ | 4520 | // .data = .{ |
| 4469 | .inst = undefined, | 4521 | // .inst_cc = .{ |
| 4470 | // Here we map the opposites since the jump is to the false branch. | 4522 | // .inst = undefined, |
| 4471 | .cc = cc.negate(), | 4523 | // // Here we map the opposites since the jump is to the false branch. |
| 4472 | }, | 4524 | // .cc = cc.negate(), |
| 4473 | }, | 4525 | // }, |
| 4474 | }); | 4526 | // }, |
| | 4527 | // }); |
| 4475 | }, | 4528 | }, |
| 4476 | .register => |reg| { | 4529 | .register => |reg| { |
| | 4530 | _ = reg; |
| 4477 | try self.spillEflagsIfOccupied(); | 4531 | try self.spillEflagsIfOccupied(); |
| 4478 | _ = try self.addInst(.{ | 4532 | // _ = try self.addInst(.{ |
| 4479 | .tag = .@"test", | 4533 | // .tag = .@"test", |
| 4480 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = reg }), | 4534 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = reg }), |
| 4481 | .data = .{ .imm = 1 }, | 4535 | // .data = .{ .imm = 1 }, |
| 4482 | }); | 4536 | // }); |
| 4483 | return self.addInst(.{ | 4537 | // return self.addInst(.{ |
| 4484 | .tag = .cond_jmp, | 4538 | // .tag = .cond_jmp, |
| 4485 | .ops = Mir.Inst.Ops.encode(.{}), | 4539 | // .ops = Mir.Inst.Ops.encode(.{}), |
| 4486 | .data = .{ .inst_cc = .{ | 4540 | // .data = .{ .inst_cc = .{ |
| 4487 | .inst = undefined, | 4541 | // .inst = undefined, |
| 4488 | .cc = .e, | 4542 | // .cc = .e, |
| 4489 | } }, | 4543 | // } }, |
| 4490 | }); | 4544 | // }); |
| 4491 | }, | 4545 | }, |
| 4492 | .immediate, | 4546 | .immediate, |
| 4493 | .stack_offset, | 4547 | .stack_offset, |
| ... | @@ -4501,6 +4555,7 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 { | ... | @@ -4501,6 +4555,7 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 { |
| 4501 | }, | 4555 | }, |
| 4502 | else => return self.fail("TODO implement condbr when condition is {s}", .{@tagName(mcv)}), | 4556 | else => return self.fail("TODO implement condbr when condition is {s}", .{@tagName(mcv)}), |
| 4503 | } | 4557 | } |
| | 4558 | return 0; // TODO |
| 4504 | } | 4559 | } |
| 4505 | | 4560 | |
| 4506 | fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | 4561 | fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| ... | @@ -4825,12 +4880,13 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4825,12 +4880,13 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void { |
| 4825 | const loop = self.air.extraData(Air.Block, ty_pl.payload); | 4880 | const loop = self.air.extraData(Air.Block, ty_pl.payload); |
| 4826 | const body = self.air.extra[loop.end..][0..loop.data.body_len]; | 4881 | const body = self.air.extra[loop.end..][0..loop.data.body_len]; |
| 4827 | const jmp_target = @intCast(u32, self.mir_instructions.len); | 4882 | const jmp_target = @intCast(u32, self.mir_instructions.len); |
| | 4883 | _ = jmp_target; |
| 4828 | try self.genBody(body); | 4884 | try self.genBody(body); |
| 4829 | _ = try self.addInst(.{ | 4885 | // _ = try self.addInst(.{ |
| 4830 | .tag = .jmp, | 4886 | // .tag = .jmp, |
| 4831 | .ops = Mir.Inst.Ops.encode(.{}), | 4887 | // .ops = Mir.Inst.Ops.encode(.{}), |
| 4832 | .data = .{ .inst = jmp_target }, | 4888 | // .data = .{ .inst = jmp_target }, |
| 4833 | }); | 4889 | // }); |
| 4834 | return self.finishAirBookkeeping(); | 4890 | return self.finishAirBookkeeping(); |
| 4835 | } | 4891 | } |
| 4836 | | 4892 | |
| ... | @@ -4876,21 +4932,23 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u | ... | @@ -4876,21 +4932,23 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u |
| 4876 | .undef => unreachable, | 4932 | .undef => unreachable, |
| 4877 | .dead, .unreach => unreachable, | 4933 | .dead, .unreach => unreachable, |
| 4878 | .immediate => |imm| { | 4934 | .immediate => |imm| { |
| 4879 | _ = try self.addInst(.{ | 4935 | _ = imm; |
| 4880 | .tag = .xor, | 4936 | // _ = try self.addInst(.{ |
| 4881 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = registerAlias(cond_reg, abi_size) }), | 4937 | // .tag = .xor, |
| 4882 | .data = .{ .imm = @intCast(u32, imm) }, | 4938 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = registerAlias(cond_reg, abi_size) }), |
| 4883 | }); | 4939 | // .data = .{ .imm = @intCast(u32, imm) }, |
| | 4940 | // }); |
| 4884 | }, | 4941 | }, |
| 4885 | .register => |reg| { | 4942 | .register => |reg| { |
| 4886 | _ = try self.addInst(.{ | 4943 | _ = reg; |
| 4887 | .tag = .xor, | 4944 | // _ = try self.addInst(.{ |
| 4888 | .ops = Mir.Inst.Ops.encode(.{ | 4945 | // .tag = .xor, |
| 4889 | .reg1 = registerAlias(cond_reg, abi_size), | 4946 | // .ops = Mir.Inst.Ops.encode(.{ |
| 4890 | .reg2 = registerAlias(reg, abi_size), | 4947 | // .reg1 = registerAlias(cond_reg, abi_size), |
| 4891 | }), | 4948 | // .reg2 = registerAlias(reg, abi_size), |
| 4892 | .data = undefined, | 4949 | // }), |
| 4893 | }); | 4950 | // .data = undefined, |
| | 4951 | // }); |
| 4894 | }, | 4952 | }, |
| 4895 | .stack_offset => { | 4953 | .stack_offset => { |
| 4896 | if (abi_size <= 8) { | 4954 | if (abi_size <= 8) { |
| ... | @@ -4905,22 +4963,22 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u | ... | @@ -4905,22 +4963,22 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u |
| 4905 | }, | 4963 | }, |
| 4906 | } | 4964 | } |
| 4907 | | 4965 | |
| 4908 | _ = try self.addInst(.{ | 4966 | // _ = try self.addInst(.{ |
| 4909 | .tag = .@"test", | 4967 | // .tag = .@"test", |
| 4910 | .ops = Mir.Inst.Ops.encode(.{ | 4968 | // .ops = Mir.Inst.Ops.encode(.{ |
| 4911 | .reg1 = registerAlias(cond_reg, abi_size), | 4969 | // .reg1 = registerAlias(cond_reg, abi_size), |
| 4912 | .reg2 = registerAlias(cond_reg, abi_size), | 4970 | // .reg2 = registerAlias(cond_reg, abi_size), |
| 4913 | }), | 4971 | // }), |
| 4914 | .data = undefined, | 4972 | // .data = undefined, |
| 4915 | }); | 4973 | // }); |
| 4916 | return self.addInst(.{ | 4974 | // return self.addInst(.{ |
| 4917 | .tag = .cond_jmp, | 4975 | // .tag = .cond_jmp, |
| 4918 | .ops = Mir.Inst.Ops.encode(.{}), | 4976 | // .ops = Mir.Inst.Ops.encode(.{}), |
| 4919 | .data = .{ .inst_cc = .{ | 4977 | // .data = .{ .inst_cc = .{ |
| 4920 | .inst = undefined, | 4978 | // .inst = undefined, |
| 4921 | .cc = .ne, | 4979 | // .cc = .ne, |
| 4922 | } }, | 4980 | // } }, |
| 4923 | }); | 4981 | // }); |
| 4924 | }, | 4982 | }, |
| 4925 | .stack_offset => { | 4983 | .stack_offset => { |
| 4926 | try self.spillEflagsIfOccupied(); | 4984 | try self.spillEflagsIfOccupied(); |
| ... | @@ -4938,6 +4996,7 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u | ... | @@ -4938,6 +4996,7 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u |
| 4938 | return self.fail("TODO implemenent switch mir when condition is {}", .{condition}); | 4996 | return self.fail("TODO implemenent switch mir when condition is {}", .{condition}); |
| 4939 | }, | 4997 | }, |
| 4940 | } | 4998 | } |
| | 4999 | return 0; // TODO |
| 4941 | } | 5000 | } |
| 4942 | | 5001 | |
| 4943 | fn airSwitch(self: *Self, inst: Air.Inst.Index) !void { | 5002 | fn airSwitch(self: *Self, inst: Air.Inst.Index) !void { |
| ... | @@ -5132,9 +5191,9 @@ fn canonicaliseBranches(self: *Self, parent_branch: *Branch, canon_branch: *Bran | ... | @@ -5132,9 +5191,9 @@ fn canonicaliseBranches(self: *Self, parent_branch: *Branch, canon_branch: *Bran |
| 5132 | fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void { | 5191 | fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void { |
| 5133 | const next_inst = @intCast(u32, self.mir_instructions.len); | 5192 | const next_inst = @intCast(u32, self.mir_instructions.len); |
| 5134 | switch (self.mir_instructions.items(.tag)[reloc]) { | 5193 | switch (self.mir_instructions.items(.tag)[reloc]) { |
| 5135 | .cond_jmp => { | 5194 | // .cond_jmp => { |
| 5136 | self.mir_instructions.items(.data)[reloc].inst_cc.inst = next_inst; | 5195 | // self.mir_instructions.items(.data)[reloc].inst_cc.inst = next_inst; |
| 5137 | }, | 5196 | // }, |
| 5138 | .jmp => { | 5197 | .jmp => { |
| 5139 | self.mir_instructions.items(.data)[reloc].inst = next_inst; | 5198 | self.mir_instructions.items(.data)[reloc].inst = next_inst; |
| 5140 | }, | 5199 | }, |
| ... | @@ -5177,12 +5236,12 @@ fn brVoid(self: *Self, block: Air.Inst.Index) !void { | ... | @@ -5177,12 +5236,12 @@ fn brVoid(self: *Self, block: Air.Inst.Index) !void { |
| 5177 | // Emit a jump with a relocation. It will be patched up after the block ends. | 5236 | // Emit a jump with a relocation. It will be patched up after the block ends. |
| 5178 | try block_data.relocs.ensureUnusedCapacity(self.gpa, 1); | 5237 | try block_data.relocs.ensureUnusedCapacity(self.gpa, 1); |
| 5179 | // Leave the jump offset undefined | 5238 | // Leave the jump offset undefined |
| 5180 | const jmp_reloc = try self.addInst(.{ | 5239 | // const jmp_reloc = try self.addInst(.{ |
| 5181 | .tag = .jmp, | 5240 | // .tag = .jmp, |
| 5182 | .ops = Mir.Inst.Ops.encode(.{}), | 5241 | // .ops = Mir.Inst.Ops.encode(.{}), |
| 5183 | .data = .{ .inst = undefined }, | 5242 | // .data = .{ .inst = undefined }, |
| 5184 | }); | 5243 | // }); |
| 5185 | block_data.relocs.appendAssumeCapacity(jmp_reloc); | 5244 | // block_data.relocs.appendAssumeCapacity(jmp_reloc); |
| 5186 | } | 5245 | } |
| 5187 | | 5246 | |
| 5188 | fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | 5247 | fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| ... | @@ -5254,30 +5313,22 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5254,30 +5313,22 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 5254 | var iter = std.mem.tokenize(u8, asm_source, "\n\r"); | 5313 | var iter = std.mem.tokenize(u8, asm_source, "\n\r"); |
| 5255 | while (iter.next()) |ins| { | 5314 | while (iter.next()) |ins| { |
| 5256 | if (mem.eql(u8, ins, "syscall")) { | 5315 | if (mem.eql(u8, ins, "syscall")) { |
| 5257 | _ = try self.addInst(.{ | 5316 | try self.assemble(.syscall, .{}); |
| 5258 | .tag = .syscall, | | |
| 5259 | .ops = undefined, | | |
| 5260 | .data = undefined, | | |
| 5261 | }); | | |
| 5262 | } else if (mem.indexOf(u8, ins, "push")) |_| { | 5317 | } else if (mem.indexOf(u8, ins, "push")) |_| { |
| 5263 | const arg = ins[4..]; | 5318 | const arg = ins[4..]; |
| 5264 | if (mem.indexOf(u8, arg, "$")) |l| { | 5319 | if (mem.indexOf(u8, arg, "$")) |l| { |
| 5265 | const n = std.fmt.parseInt(u8, ins[4 + l + 1 ..], 10) catch { | 5320 | const n = std.fmt.parseInt(u8, ins[4 + l + 1 ..], 10) catch { |
| 5266 | return self.fail("TODO implement more inline asm int parsing", .{}); | 5321 | return self.fail("TODO implement more inline asm int parsing", .{}); |
| 5267 | }; | 5322 | }; |
| 5268 | _ = try self.addInst(.{ | 5323 | try self.assemble(.push, .{ |
| 5269 | .tag = .push, | 5324 | .op1 = .{ .imm = Mir.Operand.Immediate.u(n) }, |
| 5270 | .ops = Mir.Inst.Ops.encode(.{ .flags = 0b10 }), | | |
| 5271 | .data = .{ .imm = n }, | | |
| 5272 | }); | 5325 | }); |
| 5273 | } else if (mem.indexOf(u8, arg, "%%")) |l| { | 5326 | } else if (mem.indexOf(u8, arg, "%%")) |l| { |
| 5274 | const reg_name = ins[4 + l + 2 ..]; | 5327 | const reg_name = ins[4 + l + 2 ..]; |
| 5275 | const reg = parseRegName(reg_name) orelse | 5328 | const reg = parseRegName(reg_name) orelse |
| 5276 | return self.fail("unrecognized register: '{s}'", .{reg_name}); | 5329 | return self.fail("unrecognized register: '{s}'", .{reg_name}); |
| 5277 | _ = try self.addInst(.{ | 5330 | try self.assemble(.push, .{ |
| 5278 | .tag = .push, | 5331 | .op1 = .{ .reg = reg }, |
| 5279 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = reg }), | | |
| 5280 | .data = undefined, | | |
| 5281 | }); | 5332 | }); |
| 5282 | } else return self.fail("TODO more push operands", .{}); | 5333 | } else return self.fail("TODO more push operands", .{}); |
| 5283 | } else if (mem.indexOf(u8, ins, "pop")) |_| { | 5334 | } else if (mem.indexOf(u8, ins, "pop")) |_| { |
| ... | @@ -5286,10 +5337,8 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5286,10 +5337,8 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 5286 | const reg_name = ins[3 + l + 2 ..]; | 5337 | const reg_name = ins[3 + l + 2 ..]; |
| 5287 | const reg = parseRegName(reg_name) orelse | 5338 | const reg = parseRegName(reg_name) orelse |
| 5288 | return self.fail("unrecognized register: '{s}'", .{reg_name}); | 5339 | return self.fail("unrecognized register: '{s}'", .{reg_name}); |
| 5289 | _ = try self.addInst(.{ | 5340 | try self.assemble(.pop, .{ |
| 5290 | .tag = .pop, | 5341 | .op1 = .{ .reg = reg }, |
| 5291 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = reg }), | | |
| 5292 | .data = undefined, | | |
| 5293 | }); | 5342 | }); |
| 5294 | } else return self.fail("TODO more pop operands", .{}); | 5343 | } else return self.fail("TODO more pop operands", .{}); |
| 5295 | } else { | 5344 | } else { |
| ... | @@ -5433,39 +5482,40 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE | ... | @@ -5433,39 +5482,40 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 5433 | switch (ty.zigTypeTag()) { | 5482 | switch (ty.zigTypeTag()) { |
| 5434 | .Float => { | 5483 | .Float => { |
| 5435 | if (intrinsicsAllowed(self.target.*, ty)) { | 5484 | if (intrinsicsAllowed(self.target.*, ty)) { |
| 5436 | const tag: Mir.Inst.Tag = switch (ty.tag()) { | 5485 | // const tag: Mir.Inst.Tag = switch (ty.tag()) { |
| 5437 | .f32 => Mir.Inst.Tag.mov_f32, | 5486 | // .f32 => Mir.Inst.Tag.mov_f32, |
| 5438 | .f64 => Mir.Inst.Tag.mov_f64, | 5487 | // .f64 => Mir.Inst.Tag.mov_f64, |
| 5439 | else => return self.fail("TODO genSetStackArg for register for type {}", .{ty.fmtDebug()}), | 5488 | // else => return self.fail("TODO genSetStackArg for register for type {}", .{ty.fmtDebug()}), |
| 5440 | }; | 5489 | // }; |
| 5441 | _ = try self.addInst(.{ | 5490 | _ = reg; |
| 5442 | .tag = tag, | 5491 | // _ = try self.addInst(.{ |
| 5443 | .ops = Mir.Inst.Ops.encode(.{ | 5492 | // .tag = tag, |
| 5444 | .reg1 = switch (ty.tag()) { | 5493 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5445 | .f32 => .esp, | 5494 | // .reg1 = switch (ty.tag()) { |
| 5446 | .f64 => .rsp, | 5495 | // .f32 => .esp, |
| 5447 | else => unreachable, | 5496 | // .f64 => .rsp, |
| 5448 | }, | 5497 | // else => unreachable, |
| 5449 | .reg2 = reg.to128(), | 5498 | // }, |
| 5450 | .flags = 0b01, | 5499 | // .reg2 = reg.to128(), |
| 5451 | }), | 5500 | // .flags = 0b01, |
| 5452 | .data = .{ .disp = -stack_offset }, | 5501 | // }), |
| 5453 | }); | 5502 | // .data = .{ .disp = -stack_offset }, |
| | 5503 | // }); |
| 5454 | return; | 5504 | return; |
| 5455 | } | 5505 | } |
| 5456 | | 5506 | |
| 5457 | return self.fail("TODO genSetStackArg for register with no intrinsics", .{}); | 5507 | return self.fail("TODO genSetStackArg for register with no intrinsics", .{}); |
| 5458 | }, | 5508 | }, |
| 5459 | else => { | 5509 | else => { |
| 5460 | _ = try self.addInst(.{ | 5510 | // _ = try self.addInst(.{ |
| 5461 | .tag = .mov, | 5511 | // .tag = .mov, |
| 5462 | .ops = Mir.Inst.Ops.encode(.{ | 5512 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5463 | .reg1 = .rsp, | 5513 | // .reg1 = .rsp, |
| 5464 | .reg2 = registerAlias(reg, @intCast(u32, abi_size)), | 5514 | // .reg2 = registerAlias(reg, @intCast(u32, abi_size)), |
| 5465 | .flags = 0b10, | 5515 | // .flags = 0b10, |
| 5466 | }), | 5516 | // }), |
| 5467 | .data = .{ .disp = -stack_offset }, | 5517 | // .data = .{ .disp = -stack_offset }, |
| 5468 | }); | 5518 | // }); |
| 5469 | }, | 5519 | }, |
| 5470 | } | 5520 | } |
| 5471 | }, | 5521 | }, |
| ... | @@ -5519,13 +5569,13 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl | ... | @@ -5519,13 +5569,13 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5519 | const overflow_bit_ty = ty.structFieldType(1); | 5569 | const overflow_bit_ty = ty.structFieldType(1); |
| 5520 | const overflow_bit_offset = ty.structFieldOffset(1, self.target.*); | 5570 | const overflow_bit_offset = ty.structFieldOffset(1, self.target.*); |
| 5521 | const tmp_reg = try self.register_manager.allocReg(null, gp); | 5571 | const tmp_reg = try self.register_manager.allocReg(null, gp); |
| 5522 | _ = try self.addInst(.{ | 5572 | // _ = try self.addInst(.{ |
| 5523 | .tag = .cond_set_byte, | 5573 | // .tag = .cond_set_byte, |
| 5524 | .ops = Mir.Inst.Ops.encode(.{ | 5574 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5525 | .reg1 = tmp_reg.to8(), | 5575 | // .reg1 = tmp_reg.to8(), |
| 5526 | }), | 5576 | // }), |
| 5527 | .data = .{ .cc = ro.eflags }, | 5577 | // .data = .{ .cc = ro.eflags }, |
| 5528 | }); | 5578 | // }); |
| 5529 | | 5579 | |
| 5530 | return self.genSetStack( | 5580 | return self.genSetStack( |
| 5531 | overflow_bit_ty, | 5581 | overflow_bit_ty, |
| ... | @@ -5539,72 +5589,74 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl | ... | @@ -5539,72 +5589,74 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5539 | return self.genSetStack(ty, stack_offset, .{ .register = reg }, opts); | 5589 | return self.genSetStack(ty, stack_offset, .{ .register = reg }, opts); |
| 5540 | }, | 5590 | }, |
| 5541 | .immediate => |x_big| { | 5591 | .immediate => |x_big| { |
| | 5592 | _ = x_big; |
| 5542 | const base_reg = opts.dest_stack_base orelse .rbp; | 5593 | const base_reg = opts.dest_stack_base orelse .rbp; |
| | 5594 | _ = base_reg; |
| 5543 | switch (abi_size) { | 5595 | switch (abi_size) { |
| 5544 | 0 => { | 5596 | 0 => { |
| 5545 | assert(ty.isError()); | 5597 | assert(ty.isError()); |
| 5546 | const payload = try self.addExtra(Mir.ImmPair{ | 5598 | // const payload = try self.addExtra(Mir.ImmPair{ |
| 5547 | .dest_off = -stack_offset, | 5599 | // .dest_off = -stack_offset, |
| 5548 | .operand = @truncate(u32, x_big), | 5600 | // .operand = @truncate(u32, x_big), |
| 5549 | }); | 5601 | // }); |
| 5550 | _ = try self.addInst(.{ | 5602 | // _ = try self.addInst(.{ |
| 5551 | .tag = .mov_mem_imm, | 5603 | // .tag = .mov_mem_imm, |
| 5552 | .ops = Mir.Inst.Ops.encode(.{ | 5604 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5553 | .reg1 = base_reg, | 5605 | // .reg1 = base_reg, |
| 5554 | .flags = 0b00, | 5606 | // .flags = 0b00, |
| 5555 | }), | 5607 | // }), |
| 5556 | .data = .{ .payload = payload }, | 5608 | // .data = .{ .payload = payload }, |
| 5557 | }); | 5609 | // }); |
| 5558 | }, | 5610 | }, |
| 5559 | 1, 2, 4 => { | 5611 | 1, 2, 4 => { |
| 5560 | const payload = try self.addExtra(Mir.ImmPair{ | 5612 | // const payload = try self.addExtra(Mir.ImmPair{ |
| 5561 | .dest_off = -stack_offset, | 5613 | // .dest_off = -stack_offset, |
| 5562 | .operand = @truncate(u32, x_big), | 5614 | // .operand = @truncate(u32, x_big), |
| 5563 | }); | 5615 | // }); |
| 5564 | _ = try self.addInst(.{ | 5616 | // _ = try self.addInst(.{ |
| 5565 | .tag = .mov_mem_imm, | 5617 | // .tag = .mov_mem_imm, |
| 5566 | .ops = Mir.Inst.Ops.encode(.{ | 5618 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5567 | .reg1 = base_reg, | 5619 | // .reg1 = base_reg, |
| 5568 | .flags = switch (abi_size) { | 5620 | // .flags = switch (abi_size) { |
| 5569 | 1 => 0b00, | 5621 | // 1 => 0b00, |
| 5570 | 2 => 0b01, | 5622 | // 2 => 0b01, |
| 5571 | 4 => 0b10, | 5623 | // 4 => 0b10, |
| 5572 | else => unreachable, | 5624 | // else => unreachable, |
| 5573 | }, | 5625 | // }, |
| 5574 | }), | 5626 | // }), |
| 5575 | .data = .{ .payload = payload }, | 5627 | // .data = .{ .payload = payload }, |
| 5576 | }); | 5628 | // }); |
| 5577 | }, | 5629 | }, |
| 5578 | 8 => { | 5630 | 8 => { |
| 5579 | // 64 bit write to memory would take two mov's anyways so we | 5631 | // 64 bit write to memory would take two mov's anyways so we |
| 5580 | // insted just use two 32 bit writes to avoid register allocation | 5632 | // insted just use two 32 bit writes to avoid register allocation |
| 5581 | { | 5633 | { |
| 5582 | const payload = try self.addExtra(Mir.ImmPair{ | 5634 | // const payload = try self.addExtra(Mir.ImmPair{ |
| 5583 | .dest_off = -stack_offset + 4, | 5635 | // .dest_off = -stack_offset + 4, |
| 5584 | .operand = @truncate(u32, x_big >> 32), | 5636 | // .operand = @truncate(u32, x_big >> 32), |
| 5585 | }); | 5637 | // }); |
| 5586 | _ = try self.addInst(.{ | 5638 | // _ = try self.addInst(.{ |
| 5587 | .tag = .mov_mem_imm, | 5639 | // .tag = .mov_mem_imm, |
| 5588 | .ops = Mir.Inst.Ops.encode(.{ | 5640 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5589 | .reg1 = base_reg, | 5641 | // .reg1 = base_reg, |
| 5590 | .flags = 0b10, | 5642 | // .flags = 0b10, |
| 5591 | }), | 5643 | // }), |
| 5592 | .data = .{ .payload = payload }, | 5644 | // .data = .{ .payload = payload }, |
| 5593 | }); | 5645 | // }); |
| 5594 | } | 5646 | } |
| 5595 | { | 5647 | { |
| 5596 | const payload = try self.addExtra(Mir.ImmPair{ | 5648 | // const payload = try self.addExtra(Mir.ImmPair{ |
| 5597 | .dest_off = -stack_offset, | 5649 | // .dest_off = -stack_offset, |
| 5598 | .operand = @truncate(u32, x_big), | 5650 | // .operand = @truncate(u32, x_big), |
| 5599 | }); | 5651 | // }); |
| 5600 | _ = try self.addInst(.{ | 5652 | // _ = try self.addInst(.{ |
| 5601 | .tag = .mov_mem_imm, | 5653 | // .tag = .mov_mem_imm, |
| 5602 | .ops = Mir.Inst.Ops.encode(.{ | 5654 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5603 | .reg1 = base_reg, | 5655 | // .reg1 = base_reg, |
| 5604 | .flags = 0b10, | 5656 | // .flags = 0b10, |
| 5605 | }), | 5657 | // }), |
| 5606 | .data = .{ .payload = payload }, | 5658 | // .data = .{ .payload = payload }, |
| 5607 | }); | 5659 | // }); |
| 5608 | } | 5660 | } |
| 5609 | }, | 5661 | }, |
| 5610 | else => { | 5662 | else => { |
| ... | @@ -5622,24 +5674,24 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl | ... | @@ -5622,24 +5674,24 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5622 | switch (ty.zigTypeTag()) { | 5674 | switch (ty.zigTypeTag()) { |
| 5623 | .Float => { | 5675 | .Float => { |
| 5624 | if (intrinsicsAllowed(self.target.*, ty)) { | 5676 | if (intrinsicsAllowed(self.target.*, ty)) { |
| 5625 | const tag: Mir.Inst.Tag = switch (ty.tag()) { | 5677 | // const tag: Mir.Inst.Tag = switch (ty.tag()) { |
| 5626 | .f32 => Mir.Inst.Tag.mov_f32, | 5678 | // .f32 => Mir.Inst.Tag.mov_f32, |
| 5627 | .f64 => Mir.Inst.Tag.mov_f64, | 5679 | // .f64 => Mir.Inst.Tag.mov_f64, |
| 5628 | else => return self.fail("TODO genSetStack for register for type {}", .{ty.fmtDebug()}), | 5680 | // else => return self.fail("TODO genSetStack for register for type {}", .{ty.fmtDebug()}), |
| 5629 | }; | 5681 | // }; |
| 5630 | _ = try self.addInst(.{ | 5682 | // _ = try self.addInst(.{ |
| 5631 | .tag = tag, | 5683 | // .tag = tag, |
| 5632 | .ops = Mir.Inst.Ops.encode(.{ | 5684 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5633 | .reg1 = switch (ty.tag()) { | 5685 | // .reg1 = switch (ty.tag()) { |
| 5634 | .f32 => base_reg.to32(), | 5686 | // .f32 => base_reg.to32(), |
| 5635 | .f64 => base_reg.to64(), | 5687 | // .f64 => base_reg.to64(), |
| 5636 | else => unreachable, | 5688 | // else => unreachable, |
| 5637 | }, | 5689 | // }, |
| 5638 | .reg2 = reg.to128(), | 5690 | // .reg2 = reg.to128(), |
| 5639 | .flags = 0b01, | 5691 | // .flags = 0b01, |
| 5640 | }), | 5692 | // }), |
| 5641 | .data = .{ .disp = -stack_offset }, | 5693 | // .data = .{ .disp = -stack_offset }, |
| 5642 | }); | 5694 | // }); |
| 5643 | return; | 5695 | return; |
| 5644 | } | 5696 | } |
| 5645 | | 5697 | |
| ... | @@ -5706,15 +5758,15 @@ fn genInlineMemcpyRegisterRegister( | ... | @@ -5706,15 +5758,15 @@ fn genInlineMemcpyRegisterRegister( |
| 5706 | while (remainder > 0) { | 5758 | while (remainder > 0) { |
| 5707 | const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder)); | 5759 | const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder)); |
| 5708 | | 5760 | |
| 5709 | _ = try self.addInst(.{ | 5761 | // _ = try self.addInst(.{ |
| 5710 | .tag = .mov, | 5762 | // .tag = .mov, |
| 5711 | .ops = Mir.Inst.Ops.encode(.{ | 5763 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5712 | .reg1 = dst_reg, | 5764 | // .reg1 = dst_reg, |
| 5713 | .reg2 = registerAlias(tmp_reg, nearest_power_of_two), | 5765 | // .reg2 = registerAlias(tmp_reg, nearest_power_of_two), |
| 5714 | .flags = 0b10, | 5766 | // .flags = 0b10, |
| 5715 | }), | 5767 | // }), |
| 5716 | .data = .{ .disp = -next_offset }, | 5768 | // .data = .{ .disp = -next_offset }, |
| 5717 | }); | 5769 | // }); |
| 5718 | | 5770 | |
| 5719 | if (nearest_power_of_two > 1) { | 5771 | if (nearest_power_of_two > 1) { |
| 5720 | try self.genShiftBinOpMir(.shr, ty, tmp_reg, .{ | 5772 | try self.genShiftBinOpMir(.shr, ty, tmp_reg, .{ |
| ... | @@ -5726,15 +5778,15 @@ fn genInlineMemcpyRegisterRegister( | ... | @@ -5726,15 +5778,15 @@ fn genInlineMemcpyRegisterRegister( |
| 5726 | next_offset -= nearest_power_of_two; | 5778 | next_offset -= nearest_power_of_two; |
| 5727 | } | 5779 | } |
| 5728 | } else { | 5780 | } else { |
| 5729 | _ = try self.addInst(.{ | 5781 | // _ = try self.addInst(.{ |
| 5730 | .tag = .mov, | 5782 | // .tag = .mov, |
| 5731 | .ops = Mir.Inst.Ops.encode(.{ | 5783 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5732 | .reg1 = dst_reg, | 5784 | // .reg1 = dst_reg, |
| 5733 | .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)), | 5785 | // .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)), |
| 5734 | .flags = 0b10, | 5786 | // .flags = 0b10, |
| 5735 | }), | 5787 | // }), |
| 5736 | .data = .{ .disp = -offset }, | 5788 | // .data = .{ .disp = -offset }, |
| 5737 | }); | 5789 | // }); |
| 5738 | } | 5790 | } |
| 5739 | } | 5791 | } |
| 5740 | | 5792 | |
| ... | @@ -5768,30 +5820,34 @@ fn genInlineMemcpy( | ... | @@ -5768,30 +5820,34 @@ fn genInlineMemcpy( |
| 5768 | const index_reg = regs[2].to64(); | 5820 | const index_reg = regs[2].to64(); |
| 5769 | const count_reg = regs[3].to64(); | 5821 | const count_reg = regs[3].to64(); |
| 5770 | const tmp_reg = regs[4].to8(); | 5822 | const tmp_reg = regs[4].to8(); |
| | 5823 | _ = index_reg; |
| | 5824 | _ = tmp_reg; |
| 5771 | | 5825 | |
| 5772 | switch (dst_ptr) { | 5826 | switch (dst_ptr) { |
| 5773 | .memory, .linker_load => { | 5827 | .memory, .linker_load => { |
| 5774 | try self.loadMemPtrIntoRegister(dst_addr_reg, Type.usize, dst_ptr); | 5828 | try self.loadMemPtrIntoRegister(dst_addr_reg, Type.usize, dst_ptr); |
| 5775 | }, | 5829 | }, |
| 5776 | .ptr_stack_offset, .stack_offset => |off| { | 5830 | .ptr_stack_offset, .stack_offset => |off| { |
| 5777 | _ = try self.addInst(.{ | 5831 | _ = off; |
| 5778 | .tag = .lea, | 5832 | // _ = try self.addInst(.{ |
| 5779 | .ops = Mir.Inst.Ops.encode(.{ | 5833 | // .tag = .lea, |
| 5780 | .reg1 = dst_addr_reg.to64(), | 5834 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5781 | .reg2 = opts.dest_stack_base orelse .rbp, | 5835 | // .reg1 = dst_addr_reg.to64(), |
| 5782 | }), | 5836 | // .reg2 = opts.dest_stack_base orelse .rbp, |
| 5783 | .data = .{ .disp = -off }, | 5837 | // }), |
| 5784 | }); | 5838 | // .data = .{ .disp = -off }, |
| | 5839 | // }); |
| 5785 | }, | 5840 | }, |
| 5786 | .register => |reg| { | 5841 | .register => |reg| { |
| 5787 | _ = try self.addInst(.{ | 5842 | _ = reg; |
| 5788 | .tag = .mov, | 5843 | // _ = try self.addInst(.{ |
| 5789 | .ops = Mir.Inst.Ops.encode(.{ | 5844 | // .tag = .mov, |
| 5790 | .reg1 = registerAlias(dst_addr_reg, @intCast(u32, @divExact(reg.bitSize(), 8))), | 5845 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5791 | .reg2 = reg, | 5846 | // .reg1 = registerAlias(dst_addr_reg, @intCast(u32, @divExact(reg.bitSize(), 8))), |
| 5792 | }), | 5847 | // .reg2 = reg, |
| 5793 | .data = undefined, | 5848 | // }), |
| 5794 | }); | 5849 | // .data = undefined, |
| | 5850 | // }); |
| 5795 | }, | 5851 | }, |
| 5796 | else => { | 5852 | else => { |
| 5797 | return self.fail("TODO implement memcpy for setting stack when dest is {}", .{dst_ptr}); | 5853 | return self.fail("TODO implement memcpy for setting stack when dest is {}", .{dst_ptr}); |
| ... | @@ -5803,24 +5859,26 @@ fn genInlineMemcpy( | ... | @@ -5803,24 +5859,26 @@ fn genInlineMemcpy( |
| 5803 | try self.loadMemPtrIntoRegister(src_addr_reg, Type.usize, src_ptr); | 5859 | try self.loadMemPtrIntoRegister(src_addr_reg, Type.usize, src_ptr); |
| 5804 | }, | 5860 | }, |
| 5805 | .ptr_stack_offset, .stack_offset => |off| { | 5861 | .ptr_stack_offset, .stack_offset => |off| { |
| 5806 | _ = try self.addInst(.{ | 5862 | _ = off; |
| 5807 | .tag = .lea, | 5863 | // _ = try self.addInst(.{ |
| 5808 | .ops = Mir.Inst.Ops.encode(.{ | 5864 | // .tag = .lea, |
| 5809 | .reg1 = src_addr_reg.to64(), | 5865 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5810 | .reg2 = opts.source_stack_base orelse .rbp, | 5866 | // .reg1 = src_addr_reg.to64(), |
| 5811 | }), | 5867 | // .reg2 = opts.source_stack_base orelse .rbp, |
| 5812 | .data = .{ .disp = -off }, | 5868 | // }), |
| 5813 | }); | 5869 | // .data = .{ .disp = -off }, |
| | 5870 | // }); |
| 5814 | }, | 5871 | }, |
| 5815 | .register => |reg| { | 5872 | .register => |reg| { |
| 5816 | _ = try self.addInst(.{ | 5873 | _ = reg; |
| 5817 | .tag = .mov, | 5874 | // _ = try self.addInst(.{ |
| 5818 | .ops = Mir.Inst.Ops.encode(.{ | 5875 | // .tag = .mov, |
| 5819 | .reg1 = registerAlias(src_addr_reg, @intCast(u32, @divExact(reg.bitSize(), 8))), | 5876 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5820 | .reg2 = reg, | 5877 | // .reg1 = registerAlias(src_addr_reg, @intCast(u32, @divExact(reg.bitSize(), 8))), |
| 5821 | }), | 5878 | // .reg2 = reg, |
| 5822 | .data = undefined, | 5879 | // }), |
| 5823 | }); | 5880 | // .data = undefined, |
| | 5881 | // }); |
| 5824 | }, | 5882 | }, |
| 5825 | else => { | 5883 | else => { |
| 5826 | return self.fail("TODO implement memcpy for setting stack when src is {}", .{src_ptr}); | 5884 | return self.fail("TODO implement memcpy for setting stack when src is {}", .{src_ptr}); |
| ... | @@ -5830,73 +5888,73 @@ fn genInlineMemcpy( | ... | @@ -5830,73 +5888,73 @@ fn genInlineMemcpy( |
| 5830 | try self.genSetReg(Type.usize, count_reg, len); | 5888 | try self.genSetReg(Type.usize, count_reg, len); |
| 5831 | | 5889 | |
| 5832 | // mov index_reg, 0 | 5890 | // mov index_reg, 0 |
| 5833 | _ = try self.addInst(.{ | 5891 | // _ = try self.addInst(.{ |
| 5834 | .tag = .mov, | 5892 | // .tag = .mov, |
| 5835 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = index_reg }), | 5893 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = index_reg }), |
| 5836 | .data = .{ .imm = 0 }, | 5894 | // .data = .{ .imm = 0 }, |
| 5837 | }); | 5895 | // }); |
| 5838 | | 5896 | |
| 5839 | // loop: | 5897 | // loop: |
| 5840 | // cmp count, 0 | 5898 | // cmp count, 0 |
| 5841 | const loop_start = try self.addInst(.{ | 5899 | // const loop_start = try self.addInst(.{ |
| 5842 | .tag = .cmp, | 5900 | // .tag = .cmp, |
| 5843 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = count_reg }), | 5901 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = count_reg }), |
| 5844 | .data = .{ .imm = 0 }, | 5902 | // .data = .{ .imm = 0 }, |
| 5845 | }); | 5903 | // }); |
| 5846 | | 5904 | |
| 5847 | // je end | 5905 | // je end |
| 5848 | const loop_reloc = try self.addInst(.{ | 5906 | // const loop_reloc = try self.addInst(.{ |
| 5849 | .tag = .cond_jmp, | 5907 | // .tag = .cond_jmp, |
| 5850 | .ops = Mir.Inst.Ops.encode(.{}), | 5908 | // .ops = Mir.Inst.Ops.encode(.{}), |
| 5851 | .data = .{ .inst_cc = .{ | 5909 | // .data = .{ .inst_cc = .{ |
| 5852 | .inst = undefined, | 5910 | // .inst = undefined, |
| 5853 | .cc = .e, | 5911 | // .cc = .e, |
| 5854 | } }, | 5912 | // } }, |
| 5855 | }); | 5913 | // }); |
| 5856 | | 5914 | |
| 5857 | // mov tmp, [addr + index_reg] | 5915 | // mov tmp, [addr + index_reg] |
| 5858 | _ = try self.addInst(.{ | 5916 | // _ = try self.addInst(.{ |
| 5859 | .tag = .mov_scale_src, | 5917 | // .tag = .mov_scale_src, |
| 5860 | .ops = Mir.Inst.Ops.encode(.{ | 5918 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5861 | .reg1 = tmp_reg.to8(), | 5919 | // .reg1 = tmp_reg.to8(), |
| 5862 | .reg2 = src_addr_reg, | 5920 | // .reg2 = src_addr_reg, |
| 5863 | }), | 5921 | // }), |
| 5864 | .data = .{ .payload = try self.addExtra(Mir.IndexRegisterDisp.encode(index_reg, 0)) }, | 5922 | // .data = .{ .payload = try self.addExtra(Mir.IndexRegisterDisp.encode(index_reg, 0)) }, |
| 5865 | }); | 5923 | // }); |
| 5866 | | 5924 | |
| 5867 | // mov [stack_offset + index_reg], tmp | 5925 | // mov [stack_offset + index_reg], tmp |
| 5868 | _ = try self.addInst(.{ | 5926 | // _ = try self.addInst(.{ |
| 5869 | .tag = .mov_scale_dst, | 5927 | // .tag = .mov_scale_dst, |
| 5870 | .ops = Mir.Inst.Ops.encode(.{ | 5928 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5871 | .reg1 = dst_addr_reg, | 5929 | // .reg1 = dst_addr_reg, |
| 5872 | .reg2 = tmp_reg.to8(), | 5930 | // .reg2 = tmp_reg.to8(), |
| 5873 | }), | 5931 | // }), |
| 5874 | .data = .{ .payload = try self.addExtra(Mir.IndexRegisterDisp.encode(index_reg, 0)) }, | 5932 | // .data = .{ .payload = try self.addExtra(Mir.IndexRegisterDisp.encode(index_reg, 0)) }, |
| 5875 | }); | 5933 | // }); |
| 5876 | | 5934 | |
| 5877 | // add index_reg, 1 | 5935 | // add index_reg, 1 |
| 5878 | _ = try self.addInst(.{ | 5936 | // _ = try self.addInst(.{ |
| 5879 | .tag = .add, | 5937 | // .tag = .add, |
| 5880 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = index_reg }), | 5938 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = index_reg }), |
| 5881 | .data = .{ .imm = 1 }, | 5939 | // .data = .{ .imm = 1 }, |
| 5882 | }); | 5940 | // }); |
| 5883 | | 5941 | |
| 5884 | // sub count, 1 | 5942 | // sub count, 1 |
| 5885 | _ = try self.addInst(.{ | 5943 | // _ = try self.addInst(.{ |
| 5886 | .tag = .sub, | 5944 | // .tag = .sub, |
| 5887 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = count_reg }), | 5945 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = count_reg }), |
| 5888 | .data = .{ .imm = 1 }, | 5946 | // .data = .{ .imm = 1 }, |
| 5889 | }); | 5947 | // }); |
| 5890 | | 5948 | |
| 5891 | // jmp loop | 5949 | // jmp loop |
| 5892 | _ = try self.addInst(.{ | 5950 | // _ = try self.addInst(.{ |
| 5893 | .tag = .jmp, | 5951 | // .tag = .jmp, |
| 5894 | .ops = Mir.Inst.Ops.encode(.{}), | 5952 | // .ops = Mir.Inst.Ops.encode(.{}), |
| 5895 | .data = .{ .inst = loop_start }, | 5953 | // .data = .{ .inst = loop_start }, |
| 5896 | }); | 5954 | // }); |
| 5897 | | 5955 | |
| 5898 | // end: | 5956 | // end: |
| 5899 | try self.performReloc(loop_reloc); | 5957 | // try self.performReloc(loop_reloc); |
| 5900 | } | 5958 | } |
| 5901 | | 5959 | |
| 5902 | fn genInlineMemset( | 5960 | fn genInlineMemset( |
| ... | @@ -5927,24 +5985,26 @@ fn genInlineMemset( | ... | @@ -5927,24 +5985,26 @@ fn genInlineMemset( |
| 5927 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, dst_ptr); | 5985 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, dst_ptr); |
| 5928 | }, | 5986 | }, |
| 5929 | .ptr_stack_offset, .stack_offset => |off| { | 5987 | .ptr_stack_offset, .stack_offset => |off| { |
| 5930 | _ = try self.addInst(.{ | 5988 | _ = off; |
| 5931 | .tag = .lea, | 5989 | // _ = try self.addInst(.{ |
| 5932 | .ops = Mir.Inst.Ops.encode(.{ | 5990 | // .tag = .lea, |
| 5933 | .reg1 = addr_reg.to64(), | 5991 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5934 | .reg2 = opts.dest_stack_base orelse .rbp, | 5992 | // .reg1 = addr_reg.to64(), |
| 5935 | }), | 5993 | // .reg2 = opts.dest_stack_base orelse .rbp, |
| 5936 | .data = .{ .disp = -off }, | 5994 | // }), |
| 5937 | }); | 5995 | // .data = .{ .disp = -off }, |
| | 5996 | // }); |
| 5938 | }, | 5997 | }, |
| 5939 | .register => |reg| { | 5998 | .register => |reg| { |
| 5940 | _ = try self.addInst(.{ | 5999 | _ = reg; |
| 5941 | .tag = .mov, | 6000 | // _ = try self.addInst(.{ |
| 5942 | .ops = Mir.Inst.Ops.encode(.{ | 6001 | // .tag = .mov, |
| 5943 | .reg1 = registerAlias(addr_reg, @intCast(u32, @divExact(reg.bitSize(), 8))), | 6002 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5944 | .reg2 = reg, | 6003 | // .reg1 = registerAlias(addr_reg, @intCast(u32, @divExact(reg.bitSize(), 8))), |
| 5945 | }), | 6004 | // .reg2 = reg, |
| 5946 | .data = undefined, | 6005 | // }), |
| 5947 | }); | 6006 | // .data = undefined, |
| | 6007 | // }); |
| 5948 | }, | 6008 | }, |
| 5949 | else => { | 6009 | else => { |
| 5950 | return self.fail("TODO implement memcpy for setting stack when dest is {}", .{dst_ptr}); | 6010 | return self.fail("TODO implement memcpy for setting stack when dest is {}", .{dst_ptr}); |
| ... | @@ -5956,24 +6016,24 @@ fn genInlineMemset( | ... | @@ -5956,24 +6016,24 @@ fn genInlineMemset( |
| 5956 | | 6016 | |
| 5957 | // loop: | 6017 | // loop: |
| 5958 | // cmp index_reg, -1 | 6018 | // cmp index_reg, -1 |
| 5959 | const loop_start = try self.addInst(.{ | 6019 | // const loop_start = try self.addInst(.{ |
| 5960 | .tag = .cmp, | 6020 | // .tag = .cmp, |
| 5961 | .ops = Mir.Inst.Ops.encode(.{ | 6021 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5962 | .reg1 = index_reg, | 6022 | // .reg1 = index_reg, |
| 5963 | .flags = 0b11, | 6023 | // .flags = 0b11, |
| 5964 | }), | 6024 | // }), |
| 5965 | .data = .{ .imm_s = -1 }, | 6025 | // .data = .{ .imm_s = -1 }, |
| 5966 | }); | 6026 | // }); |
| 5967 | | 6027 | |
| 5968 | // je end | 6028 | // je end |
| 5969 | const loop_reloc = try self.addInst(.{ | 6029 | // const loop_reloc = try self.addInst(.{ |
| 5970 | .tag = .cond_jmp, | 6030 | // .tag = .cond_jmp, |
| 5971 | .ops = Mir.Inst.Ops.encode(.{}), | 6031 | // .ops = Mir.Inst.Ops.encode(.{}), |
| 5972 | .data = .{ .inst_cc = .{ | 6032 | // .data = .{ .inst_cc = .{ |
| 5973 | .inst = undefined, | 6033 | // .inst = undefined, |
| 5974 | .cc = .e, | 6034 | // .cc = .e, |
| 5975 | } }, | 6035 | // } }, |
| 5976 | }); | 6036 | // }); |
| 5977 | | 6037 | |
| 5978 | switch (value) { | 6038 | switch (value) { |
| 5979 | .immediate => |x| { | 6039 | .immediate => |x| { |
| ... | @@ -5981,37 +6041,37 @@ fn genInlineMemset( | ... | @@ -5981,37 +6041,37 @@ fn genInlineMemset( |
| 5981 | return self.fail("TODO inline memset for value immediate larger than 32bits", .{}); | 6041 | return self.fail("TODO inline memset for value immediate larger than 32bits", .{}); |
| 5982 | } | 6042 | } |
| 5983 | // mov byte ptr [rbp + index_reg + stack_offset], imm | 6043 | // mov byte ptr [rbp + index_reg + stack_offset], imm |
| 5984 | _ = try self.addInst(.{ | 6044 | // _ = try self.addInst(.{ |
| 5985 | .tag = .mov_mem_index_imm, | 6045 | // .tag = .mov_mem_index_imm, |
| 5986 | .ops = Mir.Inst.Ops.encode(.{ | 6046 | // .ops = Mir.Inst.Ops.encode(.{ |
| 5987 | .reg1 = addr_reg, | 6047 | // .reg1 = addr_reg, |
| 5988 | }), | 6048 | // }), |
| 5989 | .data = .{ .payload = try self.addExtra(Mir.IndexRegisterDispImm.encode( | 6049 | // .data = .{ .payload = try self.addExtra(Mir.IndexRegisterDispImm.encode( |
| 5990 | index_reg, | 6050 | // index_reg, |
| 5991 | 0, | 6051 | // 0, |
| 5992 | @intCast(u32, x), | 6052 | // @intCast(u32, x), |
| 5993 | )) }, | 6053 | // )) }, |
| 5994 | }); | 6054 | // }); |
| 5995 | }, | 6055 | }, |
| 5996 | else => return self.fail("TODO inline memset for value of type {}", .{value}), | 6056 | else => return self.fail("TODO inline memset for value of type {}", .{value}), |
| 5997 | } | 6057 | } |
| 5998 | | 6058 | |
| 5999 | // sub index_reg, 1 | 6059 | // sub index_reg, 1 |
| 6000 | _ = try self.addInst(.{ | 6060 | // _ = try self.addInst(.{ |
| 6001 | .tag = .sub, | 6061 | // .tag = .sub, |
| 6002 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = index_reg }), | 6062 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = index_reg }), |
| 6003 | .data = .{ .imm = 1 }, | 6063 | // .data = .{ .imm = 1 }, |
| 6004 | }); | 6064 | // }); |
| 6005 | | 6065 | |
| 6006 | // jmp loop | 6066 | // jmp loop |
| 6007 | _ = try self.addInst(.{ | 6067 | // _ = try self.addInst(.{ |
| 6008 | .tag = .jmp, | 6068 | // .tag = .jmp, |
| 6009 | .ops = Mir.Inst.Ops.encode(.{}), | 6069 | // .ops = Mir.Inst.Ops.encode(.{}), |
| 6010 | .data = .{ .inst = loop_start }, | 6070 | // .data = .{ .inst = loop_start }, |
| 6011 | }); | 6071 | // }); |
| 6012 | | 6072 | |
| 6013 | // end: | 6073 | // end: |
| 6014 | try self.performReloc(loop_reloc); | 6074 | // try self.performReloc(loop_reloc); |
| 6015 | } | 6075 | } |
| 6016 | | 6076 | |
| 6017 | fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { | 6077 | fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { |
| ... | @@ -6023,14 +6083,14 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -6023,14 +6083,14 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6023 | if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) { | 6083 | if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) { |
| 6024 | return self.fail("stack offset too large", .{}); | 6084 | return self.fail("stack offset too large", .{}); |
| 6025 | } | 6085 | } |
| 6026 | _ = try self.addInst(.{ | 6086 | // _ = try self.addInst(.{ |
| 6027 | .tag = .lea, | 6087 | // .tag = .lea, |
| 6028 | .ops = Mir.Inst.Ops.encode(.{ | 6088 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6029 | .reg1 = registerAlias(reg, abi_size), | 6089 | // .reg1 = registerAlias(reg, abi_size), |
| 6030 | .reg2 = .rbp, | 6090 | // .reg2 = .rbp, |
| 6031 | }), | 6091 | // }), |
| 6032 | .data = .{ .disp = -off }, | 6092 | // .data = .{ .disp = -off }, |
| 6033 | }); | 6093 | // }); |
| 6034 | }, | 6094 | }, |
| 6035 | .unreach, .none => return, // Nothing to do. | 6095 | .unreach, .none => return, // Nothing to do. |
| 6036 | .undef => { | 6096 | .undef => { |
| ... | @@ -6046,34 +6106,30 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -6046,34 +6106,30 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6046 | } | 6106 | } |
| 6047 | }, | 6107 | }, |
| 6048 | .eflags => |cc| { | 6108 | .eflags => |cc| { |
| 6049 | _ = try self.addInst(.{ | 6109 | _ = cc; |
| 6050 | .tag = .cond_set_byte, | 6110 | // _ = try self.addInst(.{ |
| 6051 | .ops = Mir.Inst.Ops.encode(.{ | 6111 | // .tag = .cond_set_byte, |
| 6052 | .reg1 = reg.to8(), | 6112 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6053 | }), | 6113 | // .reg1 = reg.to8(), |
| 6054 | .data = .{ .cc = cc }, | 6114 | // }), |
| 6055 | }); | 6115 | // .data = .{ .cc = cc }, |
| | 6116 | // }); |
| 6056 | }, | 6117 | }, |
| 6057 | .immediate => |x| { | 6118 | .immediate => |x| { |
| 6058 | // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit | 6119 | // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit |
| 6059 | // register is the fastest way to zero a register. | 6120 | // register is the fastest way to zero a register. |
| 6060 | if (x == 0) { | 6121 | if (x == 0) { |
| 6061 | _ = try self.addInst(.{ | 6122 | try self.assemble(.xor, .{ |
| 6062 | .tag = .xor, | 6123 | .op1 = .{ .reg = reg.to32() }, |
| 6063 | .ops = Mir.Inst.Ops.encode(.{ | 6124 | .op2 = .{ .reg = reg.to32() }, |
| 6064 | .reg1 = reg.to32(), | | |
| 6065 | .reg2 = reg.to32(), | | |
| 6066 | }), | | |
| 6067 | .data = undefined, | | |
| 6068 | }); | 6125 | }); |
| 6069 | return; | 6126 | return; |
| 6070 | } | 6127 | } |
| 6071 | if (x <= math.maxInt(i32)) { | 6128 | if (x <= math.maxInt(i32)) { |
| 6072 | // Next best case: if we set the lower four bytes, the upper four will be zeroed. | 6129 | // Next best case: if we set the lower four bytes, the upper four will be zeroed. |
| 6073 | _ = try self.addInst(.{ | 6130 | try self.assemble(.mov, .{ |
| 6074 | .tag = .mov, | 6131 | .op1 = .{ .reg = registerAlias(reg, abi_size) }, |
| 6075 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = registerAlias(reg, abi_size) }), | 6132 | .op2 = .{ .imm = Mir.Operand.Immediate.u(@intCast(u32, x)) }, |
| 6076 | .data = .{ .imm = @intCast(u32, x) }, | | |
| 6077 | }); | 6133 | }); |
| 6078 | return; | 6134 | return; |
| 6079 | } | 6135 | } |
| ... | @@ -6084,12 +6140,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -6084,12 +6140,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6084 | // This encoding is, in fact, the *same* as the one used for 32-bit loads. The only | 6140 | // This encoding is, in fact, the *same* as the one used for 32-bit loads. The only |
| 6085 | // difference is that we set REX.W before the instruction, which extends the load to | 6141 | // difference is that we set REX.W before the instruction, which extends the load to |
| 6086 | // 64-bit and uses the full bit-width of the register. | 6142 | // 64-bit and uses the full bit-width of the register. |
| 6087 | const payload = try self.addExtra(Mir.Imm64.encode(x)); | 6143 | // const payload = try self.addExtra(Mir.Imm64.encode(x)); |
| 6088 | _ = try self.addInst(.{ | 6144 | // _ = try self.addInst(.{ |
| 6089 | .tag = .movabs, | 6145 | // .tag = .movabs, |
| 6090 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = reg.to64() }), | 6146 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = reg.to64() }), |
| 6091 | .data = .{ .payload = payload }, | 6147 | // .data = .{ .payload = payload }, |
| 6092 | }); | 6148 | // }); |
| 6093 | }, | 6149 | }, |
| 6094 | .register => |src_reg| { | 6150 | .register => |src_reg| { |
| 6095 | // If the registers are the same, nothing to do. | 6151 | // If the registers are the same, nothing to do. |
| ... | @@ -6100,47 +6156,47 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -6100,47 +6156,47 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6100 | .Int => switch (ty.intInfo(self.target.*).signedness) { | 6156 | .Int => switch (ty.intInfo(self.target.*).signedness) { |
| 6101 | .signed => { | 6157 | .signed => { |
| 6102 | if (abi_size <= 4) { | 6158 | if (abi_size <= 4) { |
| 6103 | _ = try self.addInst(.{ | 6159 | // _ = try self.addInst(.{ |
| 6104 | .tag = .mov_sign_extend, | 6160 | // .tag = .mov_sign_extend, |
| 6105 | .ops = Mir.Inst.Ops.encode(.{ | 6161 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6106 | .reg1 = reg.to64(), | 6162 | // .reg1 = reg.to64(), |
| 6107 | .reg2 = registerAlias(src_reg, abi_size), | 6163 | // .reg2 = registerAlias(src_reg, abi_size), |
| 6108 | }), | 6164 | // }), |
| 6109 | .data = undefined, | 6165 | // .data = undefined, |
| 6110 | }); | 6166 | // }); |
| 6111 | return; | 6167 | return; |
| 6112 | } | 6168 | } |
| 6113 | }, | 6169 | }, |
| 6114 | .unsigned => { | 6170 | .unsigned => { |
| 6115 | if (abi_size <= 2) { | 6171 | if (abi_size <= 2) { |
| 6116 | _ = try self.addInst(.{ | 6172 | // _ = try self.addInst(.{ |
| 6117 | .tag = .mov_zero_extend, | 6173 | // .tag = .mov_zero_extend, |
| 6118 | .ops = Mir.Inst.Ops.encode(.{ | 6174 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6119 | .reg1 = reg.to64(), | 6175 | // .reg1 = reg.to64(), |
| 6120 | .reg2 = registerAlias(src_reg, abi_size), | 6176 | // .reg2 = registerAlias(src_reg, abi_size), |
| 6121 | }), | 6177 | // }), |
| 6122 | .data = undefined, | 6178 | // .data = undefined, |
| 6123 | }); | 6179 | // }); |
| 6124 | return; | 6180 | return; |
| 6125 | } | 6181 | } |
| 6126 | }, | 6182 | }, |
| 6127 | }, | 6183 | }, |
| 6128 | .Float => { | 6184 | .Float => { |
| 6129 | if (intrinsicsAllowed(self.target.*, ty)) { | 6185 | if (intrinsicsAllowed(self.target.*, ty)) { |
| 6130 | const tag: Mir.Inst.Tag = switch (ty.tag()) { | 6186 | // const tag: Mir.Inst.Tag = switch (ty.tag()) { |
| 6131 | .f32 => Mir.Inst.Tag.mov_f32, | 6187 | // .f32 => Mir.Inst.Tag.mov_f32, |
| 6132 | .f64 => Mir.Inst.Tag.mov_f64, | 6188 | // .f64 => Mir.Inst.Tag.mov_f64, |
| 6133 | else => return self.fail("TODO genSetReg from register for {}", .{ty.fmtDebug()}), | 6189 | // else => return self.fail("TODO genSetReg from register for {}", .{ty.fmtDebug()}), |
| 6134 | }; | 6190 | // }; |
| 6135 | _ = try self.addInst(.{ | 6191 | // _ = try self.addInst(.{ |
| 6136 | .tag = tag, | 6192 | // .tag = tag, |
| 6137 | .ops = Mir.Inst.Ops.encode(.{ | 6193 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6138 | .reg1 = reg.to128(), | 6194 | // .reg1 = reg.to128(), |
| 6139 | .reg2 = src_reg.to128(), | 6195 | // .reg2 = src_reg.to128(), |
| 6140 | .flags = 0b10, | 6196 | // .flags = 0b10, |
| 6141 | }), | 6197 | // }), |
| 6142 | .data = undefined, | 6198 | // .data = undefined, |
| 6143 | }); | 6199 | // }); |
| 6144 | return; | 6200 | return; |
| 6145 | } | 6201 | } |
| 6146 | | 6202 | |
| ... | @@ -6149,14 +6205,14 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -6149,14 +6205,14 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6149 | else => {}, | 6205 | else => {}, |
| 6150 | } | 6206 | } |
| 6151 | | 6207 | |
| 6152 | _ = try self.addInst(.{ | 6208 | // _ = try self.addInst(.{ |
| 6153 | .tag = .mov, | 6209 | // .tag = .mov, |
| 6154 | .ops = Mir.Inst.Ops.encode(.{ | 6210 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6155 | .reg1 = registerAlias(reg, abi_size), | 6211 | // .reg1 = registerAlias(reg, abi_size), |
| 6156 | .reg2 = registerAlias(src_reg, abi_size), | 6212 | // .reg2 = registerAlias(src_reg, abi_size), |
| 6157 | }), | 6213 | // }), |
| 6158 | .data = undefined, | 6214 | // .data = undefined, |
| 6159 | }); | 6215 | // }); |
| 6160 | }, | 6216 | }, |
| 6161 | .linker_load => { | 6217 | .linker_load => { |
| 6162 | switch (ty.zigTypeTag()) { | 6218 | switch (ty.zigTypeTag()) { |
| ... | @@ -6165,24 +6221,24 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -6165,24 +6221,24 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6165 | try self.loadMemPtrIntoRegister(base_reg, Type.usize, mcv); | 6221 | try self.loadMemPtrIntoRegister(base_reg, Type.usize, mcv); |
| 6166 | | 6222 | |
| 6167 | if (intrinsicsAllowed(self.target.*, ty)) { | 6223 | if (intrinsicsAllowed(self.target.*, ty)) { |
| 6168 | const tag: Mir.Inst.Tag = switch (ty.tag()) { | 6224 | // const tag: Mir.Inst.Tag = switch (ty.tag()) { |
| 6169 | .f32 => Mir.Inst.Tag.mov_f32, | 6225 | // .f32 => Mir.Inst.Tag.mov_f32, |
| 6170 | .f64 => Mir.Inst.Tag.mov_f64, | 6226 | // .f64 => Mir.Inst.Tag.mov_f64, |
| 6171 | else => return self.fail("TODO genSetReg from memory for {}", .{ty.fmtDebug()}), | 6227 | // else => return self.fail("TODO genSetReg from memory for {}", .{ty.fmtDebug()}), |
| 6172 | }; | 6228 | // }; |
| 6173 | | 6229 | |
| 6174 | _ = try self.addInst(.{ | 6230 | // _ = try self.addInst(.{ |
| 6175 | .tag = tag, | 6231 | // .tag = tag, |
| 6176 | .ops = Mir.Inst.Ops.encode(.{ | 6232 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6177 | .reg1 = reg.to128(), | 6233 | // .reg1 = reg.to128(), |
| 6178 | .reg2 = switch (ty.tag()) { | 6234 | // .reg2 = switch (ty.tag()) { |
| 6179 | .f32 => base_reg.to32(), | 6235 | // .f32 => base_reg.to32(), |
| 6180 | .f64 => base_reg.to64(), | 6236 | // .f64 => base_reg.to64(), |
| 6181 | else => unreachable, | 6237 | // else => unreachable, |
| 6182 | }, | 6238 | // }, |
| 6183 | }), | 6239 | // }), |
| 6184 | .data = .{ .disp = 0 }, | 6240 | // .data = .{ .disp = 0 }, |
| 6185 | }); | 6241 | // }); |
| 6186 | return; | 6242 | return; |
| 6187 | } | 6243 | } |
| 6188 | | 6244 | |
| ... | @@ -6190,15 +6246,15 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -6190,15 +6246,15 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6190 | }, | 6246 | }, |
| 6191 | else => { | 6247 | else => { |
| 6192 | try self.loadMemPtrIntoRegister(reg, Type.usize, mcv); | 6248 | try self.loadMemPtrIntoRegister(reg, Type.usize, mcv); |
| 6193 | _ = try self.addInst(.{ | 6249 | // _ = try self.addInst(.{ |
| 6194 | .tag = .mov, | 6250 | // .tag = .mov, |
| 6195 | .ops = Mir.Inst.Ops.encode(.{ | 6251 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6196 | .reg1 = registerAlias(reg, abi_size), | 6252 | // .reg1 = registerAlias(reg, abi_size), |
| 6197 | .reg2 = reg.to64(), | 6253 | // .reg2 = reg.to64(), |
| 6198 | .flags = 0b01, | 6254 | // .flags = 0b01, |
| 6199 | }), | 6255 | // }), |
| 6200 | .data = .{ .disp = 0 }, | 6256 | // .data = .{ .disp = 0 }, |
| 6201 | }); | 6257 | // }); |
| 6202 | }, | 6258 | }, |
| 6203 | } | 6259 | } |
| 6204 | }, | 6260 | }, |
| ... | @@ -6208,24 +6264,24 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -6208,24 +6264,24 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6208 | try self.loadMemPtrIntoRegister(base_reg, Type.usize, mcv); | 6264 | try self.loadMemPtrIntoRegister(base_reg, Type.usize, mcv); |
| 6209 | | 6265 | |
| 6210 | if (intrinsicsAllowed(self.target.*, ty)) { | 6266 | if (intrinsicsAllowed(self.target.*, ty)) { |
| 6211 | const tag: Mir.Inst.Tag = switch (ty.tag()) { | 6267 | // const tag: Mir.Inst.Tag = switch (ty.tag()) { |
| 6212 | .f32 => Mir.Inst.Tag.mov_f32, | 6268 | // .f32 => Mir.Inst.Tag.mov_f32, |
| 6213 | .f64 => Mir.Inst.Tag.mov_f64, | 6269 | // .f64 => Mir.Inst.Tag.mov_f64, |
| 6214 | else => return self.fail("TODO genSetReg from memory for {}", .{ty.fmtDebug()}), | 6270 | // else => return self.fail("TODO genSetReg from memory for {}", .{ty.fmtDebug()}), |
| 6215 | }; | 6271 | // }; |
| 6216 | | 6272 | |
| 6217 | _ = try self.addInst(.{ | 6273 | // _ = try self.addInst(.{ |
| 6218 | .tag = tag, | 6274 | // .tag = tag, |
| 6219 | .ops = Mir.Inst.Ops.encode(.{ | 6275 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6220 | .reg1 = reg.to128(), | 6276 | // .reg1 = reg.to128(), |
| 6221 | .reg2 = switch (ty.tag()) { | 6277 | // .reg2 = switch (ty.tag()) { |
| 6222 | .f32 => base_reg.to32(), | 6278 | // .f32 => base_reg.to32(), |
| 6223 | .f64 => base_reg.to64(), | 6279 | // .f64 => base_reg.to64(), |
| 6224 | else => unreachable, | 6280 | // else => unreachable, |
| 6225 | }, | 6281 | // }, |
| 6226 | }), | 6282 | // }), |
| 6227 | .data = .{ .disp = 0 }, | 6283 | // .data = .{ .disp = 0 }, |
| 6228 | }); | 6284 | // }); |
| 6229 | return; | 6285 | return; |
| 6230 | } | 6286 | } |
| 6231 | | 6287 | |
| ... | @@ -6234,42 +6290,42 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -6234,42 +6290,42 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6234 | else => { | 6290 | else => { |
| 6235 | if (x <= math.maxInt(i32)) { | 6291 | if (x <= math.maxInt(i32)) { |
| 6236 | // mov reg, [ds:imm32] | 6292 | // mov reg, [ds:imm32] |
| 6237 | _ = try self.addInst(.{ | 6293 | // _ = try self.addInst(.{ |
| 6238 | .tag = .mov, | 6294 | // .tag = .mov, |
| 6239 | .ops = Mir.Inst.Ops.encode(.{ | 6295 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6240 | .reg1 = registerAlias(reg, abi_size), | 6296 | // .reg1 = registerAlias(reg, abi_size), |
| 6241 | .flags = 0b01, | 6297 | // .flags = 0b01, |
| 6242 | }), | 6298 | // }), |
| 6243 | .data = .{ .disp = @intCast(i32, x) }, | 6299 | // .data = .{ .disp = @intCast(i32, x) }, |
| 6244 | }); | 6300 | // }); |
| 6245 | } else { | 6301 | } else { |
| 6246 | // If this is RAX, we can use a direct load. | 6302 | // If this is RAX, we can use a direct load. |
| 6247 | // Otherwise, we need to load the address, then indirectly load the value. | 6303 | // Otherwise, we need to load the address, then indirectly load the value. |
| 6248 | if (reg.id() == 0) { | 6304 | if (reg.id() == 0) { |
| 6249 | // movabs rax, ds:moffs64 | 6305 | // movabs rax, ds:moffs64 |
| 6250 | const payload = try self.addExtra(Mir.Imm64.encode(x)); | 6306 | // const payload = try self.addExtra(Mir.Imm64.encode(x)); |
| 6251 | _ = try self.addInst(.{ | 6307 | // _ = try self.addInst(.{ |
| 6252 | .tag = .movabs, | 6308 | // .tag = .movabs, |
| 6253 | .ops = Mir.Inst.Ops.encode(.{ | 6309 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6254 | .reg1 = .rax, | 6310 | // .reg1 = .rax, |
| 6255 | .flags = 0b01, // imm64 will become moffs64 | 6311 | // .flags = 0b01, // imm64 will become moffs64 |
| 6256 | }), | 6312 | // }), |
| 6257 | .data = .{ .payload = payload }, | 6313 | // .data = .{ .payload = payload }, |
| 6258 | }); | 6314 | // }); |
| 6259 | } else { | 6315 | } else { |
| 6260 | // Rather than duplicate the logic used for the move, we just use a self-call with a new MCValue. | 6316 | // Rather than duplicate the logic used for the move, we just use a self-call with a new MCValue. |
| 6261 | try self.genSetReg(ty, reg, MCValue{ .immediate = x }); | 6317 | try self.genSetReg(ty, reg, MCValue{ .immediate = x }); |
| 6262 | | 6318 | |
| 6263 | // mov reg, [reg + 0x0] | 6319 | // mov reg, [reg + 0x0] |
| 6264 | _ = try self.addInst(.{ | 6320 | // _ = try self.addInst(.{ |
| 6265 | .tag = .mov, | 6321 | // .tag = .mov, |
| 6266 | .ops = Mir.Inst.Ops.encode(.{ | 6322 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6267 | .reg1 = registerAlias(reg, abi_size), | 6323 | // .reg1 = registerAlias(reg, abi_size), |
| 6268 | .reg2 = reg.to64(), | 6324 | // .reg2 = reg.to64(), |
| 6269 | .flags = 0b01, | 6325 | // .flags = 0b01, |
| 6270 | }), | 6326 | // }), |
| 6271 | .data = .{ .disp = 0 }, | 6327 | // .data = .{ .disp = 0 }, |
| 6272 | }); | 6328 | // }); |
| 6273 | } | 6329 | } |
| 6274 | } | 6330 | } |
| 6275 | }, | 6331 | }, |
| ... | @@ -6289,15 +6345,16 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -6289,15 +6345,16 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6289 | 4 => 0b11, | 6345 | 4 => 0b11, |
| 6290 | else => unreachable, | 6346 | else => unreachable, |
| 6291 | }; | 6347 | }; |
| 6292 | _ = try self.addInst(.{ | 6348 | _ = flags; |
| 6293 | .tag = .mov_sign_extend, | 6349 | // _ = try self.addInst(.{ |
| 6294 | .ops = Mir.Inst.Ops.encode(.{ | 6350 | // .tag = .mov_sign_extend, |
| 6295 | .reg1 = reg.to64(), | 6351 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6296 | .reg2 = .rbp, | 6352 | // .reg1 = reg.to64(), |
| 6297 | .flags = flags, | 6353 | // .reg2 = .rbp, |
| 6298 | }), | 6354 | // .flags = flags, |
| 6299 | .data = .{ .disp = -off }, | 6355 | // }), |
| 6300 | }); | 6356 | // .data = .{ .disp = -off }, |
| | 6357 | // }); |
| 6301 | return; | 6358 | return; |
| 6302 | } | 6359 | } |
| 6303 | }, | 6360 | }, |
| ... | @@ -6308,38 +6365,39 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -6308,38 +6365,39 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6308 | 2 => 0b10, | 6365 | 2 => 0b10, |
| 6309 | else => unreachable, | 6366 | else => unreachable, |
| 6310 | }; | 6367 | }; |
| 6311 | _ = try self.addInst(.{ | 6368 | _ = flags; |
| 6312 | .tag = .mov_zero_extend, | 6369 | // _ = try self.addInst(.{ |
| 6313 | .ops = Mir.Inst.Ops.encode(.{ | 6370 | // .tag = .mov_zero_extend, |
| 6314 | .reg1 = reg.to64(), | 6371 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6315 | .reg2 = .rbp, | 6372 | // .reg1 = reg.to64(), |
| 6316 | .flags = flags, | 6373 | // .reg2 = .rbp, |
| 6317 | }), | 6374 | // .flags = flags, |
| 6318 | .data = .{ .disp = -off }, | 6375 | // }), |
| 6319 | }); | 6376 | // .data = .{ .disp = -off }, |
| | 6377 | // }); |
| 6320 | return; | 6378 | return; |
| 6321 | } | 6379 | } |
| 6322 | }, | 6380 | }, |
| 6323 | }, | 6381 | }, |
| 6324 | .Float => { | 6382 | .Float => { |
| 6325 | if (intrinsicsAllowed(self.target.*, ty)) { | 6383 | if (intrinsicsAllowed(self.target.*, ty)) { |
| 6326 | const tag: Mir.Inst.Tag = switch (ty.tag()) { | 6384 | // const tag: Mir.Inst.Tag = switch (ty.tag()) { |
| 6327 | .f32 => Mir.Inst.Tag.mov_f32, | 6385 | // .f32 => Mir.Inst.Tag.mov_f32, |
| 6328 | .f64 => Mir.Inst.Tag.mov_f64, | 6386 | // .f64 => Mir.Inst.Tag.mov_f64, |
| 6329 | else => return self.fail("TODO genSetReg from stack offset for {}", .{ty.fmtDebug()}), | 6387 | // else => return self.fail("TODO genSetReg from stack offset for {}", .{ty.fmtDebug()}), |
| 6330 | }; | 6388 | // }; |
| 6331 | _ = try self.addInst(.{ | 6389 | // _ = try self.addInst(.{ |
| 6332 | .tag = tag, | 6390 | // .tag = tag, |
| 6333 | .ops = Mir.Inst.Ops.encode(.{ | 6391 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6334 | .reg1 = reg.to128(), | 6392 | // .reg1 = reg.to128(), |
| 6335 | .reg2 = switch (ty.tag()) { | 6393 | // .reg2 = switch (ty.tag()) { |
| 6336 | .f32 => .ebp, | 6394 | // .f32 => .ebp, |
| 6337 | .f64 => .rbp, | 6395 | // .f64 => .rbp, |
| 6338 | else => unreachable, | 6396 | // else => unreachable, |
| 6339 | }, | 6397 | // }, |
| 6340 | }), | 6398 | // }), |
| 6341 | .data = .{ .disp = -off }, | 6399 | // .data = .{ .disp = -off }, |
| 6342 | }); | 6400 | // }); |
| 6343 | return; | 6401 | return; |
| 6344 | } | 6402 | } |
| 6345 | return self.fail("TODO genSetReg from stack offset for float with no intrinsics", .{}); | 6403 | return self.fail("TODO genSetReg from stack offset for float with no intrinsics", .{}); |
| ... | @@ -6347,15 +6405,15 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -6347,15 +6405,15 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6347 | else => {}, | 6405 | else => {}, |
| 6348 | } | 6406 | } |
| 6349 | | 6407 | |
| 6350 | _ = try self.addInst(.{ | 6408 | // _ = try self.addInst(.{ |
| 6351 | .tag = .mov, | 6409 | // .tag = .mov, |
| 6352 | .ops = Mir.Inst.Ops.encode(.{ | 6410 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6353 | .reg1 = registerAlias(reg, abi_size), | 6411 | // .reg1 = registerAlias(reg, abi_size), |
| 6354 | .reg2 = .rbp, | 6412 | // .reg2 = .rbp, |
| 6355 | .flags = 0b01, | 6413 | // .flags = 0b01, |
| 6356 | }), | 6414 | // }), |
| 6357 | .data = .{ .disp = -off }, | 6415 | // .data = .{ .disp = -off }, |
| 6358 | }); | 6416 | // }); |
| 6359 | }, | 6417 | }, |
| 6360 | } | 6418 | } |
| 6361 | } | 6419 | } |
| ... | @@ -6419,6 +6477,7 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6419,6 +6477,7 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 6419 | const src_ty = self.air.typeOf(ty_op.operand); | 6477 | const src_ty = self.air.typeOf(ty_op.operand); |
| 6420 | const dst_ty = self.air.typeOfIndex(inst); | 6478 | const dst_ty = self.air.typeOfIndex(inst); |
| 6421 | const operand = try self.resolveInst(ty_op.operand); | 6479 | const operand = try self.resolveInst(ty_op.operand); |
| | 6480 | _ = dst_ty; |
| 6422 | | 6481 | |
| 6423 | // move float src to ST(0) | 6482 | // move float src to ST(0) |
| 6424 | const stack_offset = switch (operand) { | 6483 | const stack_offset = switch (operand) { |
| ... | @@ -6433,34 +6492,35 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6433,34 +6492,35 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 6433 | break :blk offset; | 6492 | break :blk offset; |
| 6434 | }, | 6493 | }, |
| 6435 | }; | 6494 | }; |
| 6436 | _ = try self.addInst(.{ | 6495 | _ = stack_offset; |
| 6437 | .tag = .fld, | 6496 | // _ = try self.addInst(.{ |
| 6438 | .ops = Mir.Inst.Ops.encode(.{ | 6497 | // .tag = .fld, |
| 6439 | .reg1 = .rbp, | 6498 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6440 | .flags = switch (src_ty.abiSize(self.target.*)) { | 6499 | // .reg1 = .rbp, |
| 6441 | 4 => 0b01, | 6500 | // .flags = switch (src_ty.abiSize(self.target.*)) { |
| 6442 | 8 => 0b10, | 6501 | // 4 => 0b01, |
| 6443 | else => |size| return self.fail("TODO load ST(0) with abiSize={}", .{size}), | 6502 | // 8 => 0b10, |
| 6444 | }, | 6503 | // else => |size| return self.fail("TODO load ST(0) with abiSize={}", .{size}), |
| 6445 | }), | 6504 | // }, |
| 6446 | .data = .{ .disp = -stack_offset }, | 6505 | // }), |
| 6447 | }); | 6506 | // .data = .{ .disp = -stack_offset }, |
| | 6507 | // }); |
| 6448 | | 6508 | |
| 6449 | // convert | 6509 | // convert |
| 6450 | const stack_dst = try self.allocRegOrMem(inst, false); | 6510 | const stack_dst = try self.allocRegOrMem(inst, false); |
| 6451 | _ = try self.addInst(.{ | 6511 | // _ = try self.addInst(.{ |
| 6452 | .tag = .fisttp, | 6512 | // .tag = .fisttp, |
| 6453 | .ops = Mir.Inst.Ops.encode(.{ | 6513 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6454 | .reg1 = .rbp, | 6514 | // .reg1 = .rbp, |
| 6455 | .flags = switch (dst_ty.abiSize(self.target.*)) { | 6515 | // .flags = switch (dst_ty.abiSize(self.target.*)) { |
| 6456 | 1...2 => 0b00, | 6516 | // 1...2 => 0b00, |
| 6457 | 3...4 => 0b01, | 6517 | // 3...4 => 0b01, |
| 6458 | 5...8 => 0b10, | 6518 | // 5...8 => 0b10, |
| 6459 | else => |size| return self.fail("TODO convert float with abiSize={}", .{size}), | 6519 | // else => |size| return self.fail("TODO convert float with abiSize={}", .{size}), |
| 6460 | }, | 6520 | // }, |
| 6461 | }), | 6521 | // }), |
| 6462 | .data = .{ .disp = -stack_dst.stack_offset }, | 6522 | // .data = .{ .disp = -stack_dst.stack_offset }, |
| 6463 | }); | 6523 | // }); |
| 6464 | | 6524 | |
| 6465 | return self.finishAir(inst, stack_dst, .{ ty_op.operand, .none, .none }); | 6525 | return self.finishAir(inst, stack_dst, .{ ty_op.operand, .none, .none }); |
| 6466 | } | 6526 | } |
| ... | @@ -6551,15 +6611,15 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6551,15 +6611,15 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { |
| 6551 | .linker_load, .memory => { | 6611 | .linker_load, .memory => { |
| 6552 | const reg = try self.register_manager.allocReg(null, gp); | 6612 | const reg = try self.register_manager.allocReg(null, gp); |
| 6553 | try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr); | 6613 | try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr); |
| 6554 | _ = try self.addInst(.{ | 6614 | // _ = try self.addInst(.{ |
| 6555 | .tag = .mov, | 6615 | // .tag = .mov, |
| 6556 | .ops = Mir.Inst.Ops.encode(.{ | 6616 | // .ops = Mir.Inst.Ops.encode(.{ |
| 6557 | .reg1 = reg, | 6617 | // .reg1 = reg, |
| 6558 | .reg2 = reg, | 6618 | // .reg2 = reg, |
| 6559 | .flags = 0b01, | 6619 | // .flags = 0b01, |
| 6560 | }), | 6620 | // }), |
| 6561 | .data = .{ .disp = 0 }, | 6621 | // .data = .{ .disp = 0 }, |
| 6562 | }); | 6622 | // }); |
| 6563 | break :blk MCValue{ .register = reg }; | 6623 | break :blk MCValue{ .register = reg }; |
| 6564 | }, | 6624 | }, |
| 6565 | else => break :blk src_ptr, | 6625 | else => break :blk src_ptr, |