| ... | ... | @@ -385,6 +385,24 @@ pub fn addExtra(self: *Self, extra: anytype) Allocator.Error!u32 { |
| 385 | 385 | return self.addExtraAssumeCapacity(extra); |
| 386 | 386 | } |
| 387 | 387 | |
| 388 | fn extraData(self: *Self, comptime T: type, index: u32) struct { data: T, end: 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 | |
| 388 | 406 | pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { |
| 389 | 407 | const fields = std.meta.fields(@TypeOf(extra)); |
| 390 | 408 | const result = @intCast(u32, self.mir_extra.items.len); |
| ... | ... | @@ -2759,9 +2777,15 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2759 | 2777 | 1, 2, 4 => { |
| 2760 | 2778 | // TODO this is wasteful! |
| 2761 | 2779 | // introduce new MIR tag specifically for mov [reg + 0], imm |
| 2780 | const operand = switch (abi_size) { |
| 2781 | 1 => @truncate(u8, imm), |
| 2782 | 2 => @truncate(u16, imm), |
| 2783 | 4 => @truncate(u32, imm), |
| 2784 | else => unreachable, |
| 2785 | }; |
| 2762 | 2786 | const payload = try self.addExtra(Mir.ImmPair{ |
| 2763 | 2787 | .dest_off = 0, |
| 2764 | | .operand = @truncate(u32, imm), |
| 2788 | .operand = operand, |
| 2765 | 2789 | }); |
| 2766 | 2790 | _ = try self.addInst(.{ |
| 2767 | 2791 | .tag = .mov_mem_imm, |
| ... | ... | @@ -2872,10 +2896,17 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2872 | 2896 | return self.fail("TODO saving imm to memory for abi_size {}", .{abi_size}); |
| 2873 | 2897 | } |
| 2874 | 2898 | |
| 2899 | const operand = switch (abi_size) { |
| 2900 | 1 => @truncate(u8, imm), |
| 2901 | 2 => @truncate(u16, imm), |
| 2902 | 4 => @truncate(u32, imm), |
| 2903 | 8 => @truncate(u32, imm), |
| 2904 | else => unreachable, |
| 2905 | }; |
| 2875 | 2906 | const payload = try self.addExtra(Mir.ImmPair{ |
| 2876 | 2907 | .dest_off = 0, |
| 2877 | 2908 | // TODO check if this logic is correct |
| 2878 | | .operand = @truncate(u32, imm), |
| 2909 | .operand = operand, |
| 2879 | 2910 | }); |
| 2880 | 2911 | const flags: u2 = switch (abi_size) { |
| 2881 | 2912 | 1 => 0b00, |
| ... | ... | @@ -3600,7 +3631,13 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3600 | 3631 | _ = try self.addInst(.{ |
| 3601 | 3632 | .tag = mir_tag, |
| 3602 | 3633 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = registerAlias(dst_reg, abi_size) }), |
| 3603 | | .data = .{ .imm = @truncate(u32, imm) }, |
| 3634 | .data = .{ .imm = switch (abi_size) { |
| 3635 | 1 => @truncate(u8, imm), |
| 3636 | 2 => @truncate(u16, imm), |
| 3637 | 4 => @truncate(u32, imm), |
| 3638 | 8 => @truncate(u32, imm), |
| 3639 | else => unreachable, |
| 3640 | } }, |
| 3604 | 3641 | }); |
| 3605 | 3642 | }, |
| 3606 | 3643 | .memory, |
| ... | ... | @@ -3671,9 +3708,16 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3671 | 3708 | 8 => 0b11, |
| 3672 | 3709 | else => unreachable, |
| 3673 | 3710 | }; |
| 3711 | const operand = switch (abi_size) { |
| 3712 | 1 => @truncate(u8, imm), |
| 3713 | 2 => @truncate(u16, imm), |
| 3714 | 4 => @truncate(u32, imm), |
| 3715 | 8 => @truncate(u32, imm), |
| 3716 | else => unreachable, |
| 3717 | }; |
| 3674 | 3718 | const payload = try self.addExtra(Mir.ImmPair{ |
| 3675 | 3719 | .dest_off = -off, |
| 3676 | | .operand = @truncate(u32, imm), |
| 3720 | .operand = operand, |
| 3677 | 3721 | }); |
| 3678 | 3722 | _ = try self.addInst(.{ |
| 3679 | 3723 | .tag = tag, |
| ... | ... | @@ -4855,7 +4899,13 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u |
| 4855 | 4899 | _ = try self.addInst(.{ |
| 4856 | 4900 | .tag = .xor, |
| 4857 | 4901 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = registerAlias(cond_reg, abi_size) }), |
| 4858 | | .data = .{ .imm = @intCast(u32, imm) }, |
| 4902 | .data = .{ .imm = switch (abi_size) { |
| 4903 | 1 => @truncate(u8, imm), |
| 4904 | 2 => @truncate(u16, imm), |
| 4905 | 4 => @truncate(u32, imm), |
| 4906 | 8 => @truncate(u32, imm), |
| 4907 | else => unreachable, |
| 4908 | } }, |
| 4859 | 4909 | }); |
| 4860 | 4910 | }, |
| 4861 | 4911 | .register => |reg| { |
| ... | ... | @@ -5366,20 +5416,27 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 5366 | 5416 | // We have a positive stack offset value but we want a twos complement negative |
| 5367 | 5417 | // offset from rbp, which is at the top of the stack frame. |
| 5368 | 5418 | // mov [rbp+offset], immediate |
| 5419 | const operand = switch (abi_size) { |
| 5420 | 1 => @truncate(u8, imm), |
| 5421 | 2 => @truncate(u16, imm), |
| 5422 | 4 => @truncate(u32, imm), |
| 5423 | else => unreachable, |
| 5424 | }; |
| 5425 | const flags: u2 = switch (abi_size) { |
| 5426 | 1 => 0b00, |
| 5427 | 2 => 0b01, |
| 5428 | 4 => 0b10, |
| 5429 | else => unreachable, |
| 5430 | }; |
| 5369 | 5431 | const payload = try self.addExtra(Mir.ImmPair{ |
| 5370 | 5432 | .dest_off = -stack_offset, |
| 5371 | | .operand = @truncate(u32, imm), |
| 5433 | .operand = operand, |
| 5372 | 5434 | }); |
| 5373 | 5435 | _ = try self.addInst(.{ |
| 5374 | 5436 | .tag = .mov_mem_imm, |
| 5375 | 5437 | .ops = Mir.Inst.Ops.encode(.{ |
| 5376 | 5438 | .reg1 = .rsp, |
| 5377 | | .flags = switch (abi_size) { |
| 5378 | | 1 => 0b00, |
| 5379 | | 2 => 0b01, |
| 5380 | | 4 => 0b10, |
| 5381 | | else => unreachable, |
| 5382 | | }, |
| 5439 | .flags = flags, |
| 5383 | 5440 | }), |
| 5384 | 5441 | .data = .{ .payload = payload }, |
| 5385 | 5442 | }); |
| ... | ... | @@ -5518,7 +5575,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5518 | 5575 | assert(ty.isError()); |
| 5519 | 5576 | const payload = try self.addExtra(Mir.ImmPair{ |
| 5520 | 5577 | .dest_off = -stack_offset, |
| 5521 | | .operand = @truncate(u32, x_big), |
| 5578 | .operand = @truncate(u8, x_big), |
| 5522 | 5579 | }); |
| 5523 | 5580 | _ = try self.addInst(.{ |
| 5524 | 5581 | .tag = .mov_mem_imm, |
| ... | ... | @@ -5530,9 +5587,15 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5530 | 5587 | }); |
| 5531 | 5588 | }, |
| 5532 | 5589 | 1, 2, 4 => { |
| 5590 | const operand = switch (abi_size) { |
| 5591 | 1 => @truncate(u8, x_big), |
| 5592 | 2 => @truncate(u16, x_big), |
| 5593 | 4 => @truncate(u32, x_big), |
| 5594 | else => unreachable, |
| 5595 | }; |
| 5533 | 5596 | const payload = try self.addExtra(Mir.ImmPair{ |
| 5534 | 5597 | .dest_off = -stack_offset, |
| 5535 | | .operand = @truncate(u32, x_big), |
| 5598 | .operand = operand, |
| 5536 | 5599 | }); |
| 5537 | 5600 | _ = try self.addInst(.{ |
| 5538 | 5601 | .tag = .mov_mem_imm, |
| ... | ... | @@ -5932,7 +5995,7 @@ fn genInlineMemset( |
| 5932 | 5995 | const loop_start = try self.addInst(.{ |
| 5933 | 5996 | .tag = .cmp, |
| 5934 | 5997 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = index_reg }), |
| 5935 | | .data = .{ .imm = @bitCast(u32, @as(i32, -1)) }, |
| 5998 | .data = .{ .imm = @bitCast(u8, @as(i8, -1)) }, |
| 5936 | 5999 | }); |
| 5937 | 6000 | |
| 5938 | 6001 | // je end |
| ... | ... | @@ -6037,7 +6100,13 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6037 | 6100 | _ = try self.addInst(.{ |
| 6038 | 6101 | .tag = .mov, |
| 6039 | 6102 | .ops = Mir.Inst.Ops.encode(.{ .reg1 = registerAlias(reg, abi_size) }), |
| 6040 | | .data = .{ .imm = @truncate(u32, x) }, |
| 6103 | .data = .{ .imm = switch (abi_size) { |
| 6104 | 1 => @truncate(u8, x), |
| 6105 | 2 => @truncate(u16, x), |
| 6106 | 4 => @truncate(u32, x), |
| 6107 | 8 => @truncate(u32, x), |
| 6108 | else => unreachable, |
| 6109 | } }, |
| 6041 | 6110 | }); |
| 6042 | 6111 | return; |
| 6043 | 6112 | } |
| ... | ... | @@ -6204,7 +6273,13 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6204 | 6273 | .reg1 = registerAlias(reg, abi_size), |
| 6205 | 6274 | .flags = 0b01, |
| 6206 | 6275 | }), |
| 6207 | | .data = .{ .imm = @truncate(u32, x) }, |
| 6276 | .data = .{ .imm = switch (abi_size) { |
| 6277 | 1 => @truncate(u8, x), |
| 6278 | 2 => @truncate(u16, x), |
| 6279 | 4 => @truncate(u32, x), |
| 6280 | 8 => @truncate(u32, x), |
| 6281 | else => unreachable, |
| 6282 | } }, |
| 6208 | 6283 | }); |
| 6209 | 6284 | } else { |
| 6210 | 6285 | // If this is RAX, we can use a direct load. |