| ... | @@ -509,6 +509,29 @@ fn asmMemory(self: *Self, tag: Mir.Inst.Tag, m: Memory) !void { | ... | @@ -509,6 +509,29 @@ fn asmMemory(self: *Self, tag: Mir.Inst.Tag, m: Memory) !void { |
| 509 | }); | 509 | }); |
| 510 | } | 510 | } |
| 511 | | 511 | |
| | 512 | fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.Tag, m: Memory, imm: Immediate) !void { |
| | 513 | const ops: Mir.Inst.Ops = switch (m) { |
| | 514 | .sib => if (imm == .signed) .mi_s_sib else .mi_u_sib, |
| | 515 | .rip => if (imm == .signed) .mi_s_rip else .mi_u_rip, |
| | 516 | else => unreachable, |
| | 517 | }; |
| | 518 | const payload: u32 = switch (ops) { |
| | 519 | .mi_s_sib, .mi_u_sib => try self.addExtra(Mir.MemorySib.encode(m)), |
| | 520 | .mi_s_rip, .mi_u_rip => try self.addExtra(Mir.MemoryRip.encode(m)), |
| | 521 | else => unreachable, |
| | 522 | }; |
| | 523 | const data: Mir.Inst.Data = switch (ops) { |
| | 524 | .mi_s_sib, .mi_s_rip => .{ .xi_s = .{ .imm = imm.signed, .payload = payload } }, |
| | 525 | .mi_u_sib, .mi_u_rip => .{ .xi_u = .{ .imm = @intCast(u32, imm.unsigned), .payload = payload } }, |
| | 526 | else => unreachable, |
| | 527 | }; |
| | 528 | _ = try self.addInst(.{ |
| | 529 | .tag = tag, |
| | 530 | .ops = ops, |
| | 531 | .data = data, |
| | 532 | }); |
| | 533 | } |
| | 534 | |
| 512 | fn asmRegisterMemory(self: *Self, tag: Mir.Inst.Tag, reg: Register, m: Memory) !void { | 535 | fn asmRegisterMemory(self: *Self, tag: Mir.Inst.Tag, reg: Register, m: Memory) !void { |
| 513 | const ops: Mir.Inst.Ops = switch (m) { | 536 | const ops: Mir.Inst.Ops = switch (m) { |
| 514 | .sib => .rm_sib, | 537 | .sib => .rm_sib, |
| ... | @@ -2776,7 +2799,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue | ... | @@ -2776,7 +2799,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue |
| 2776 | } | 2799 | } |
| 2777 | | 2800 | |
| 2778 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { | 2801 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { |
| 2779 | const abi_size = value_ty.abiSize(self.target.*); | 2802 | const abi_size = @intCast(u32, value_ty.abiSize(self.target.*)); |
| 2780 | switch (ptr) { | 2803 | switch (ptr) { |
| 2781 | .none => unreachable, | 2804 | .none => unreachable, |
| 2782 | .undef => unreachable, | 2805 | .undef => unreachable, |
| ... | @@ -2807,28 +2830,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2807,28 +2830,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2807 | try self.genSetReg(value_ty, reg, value); | 2830 | try self.genSetReg(value_ty, reg, value); |
| 2808 | }, | 2831 | }, |
| 2809 | .immediate => |imm| { | 2832 | .immediate => |imm| { |
| 2810 | _ = imm; | | |
| 2811 | switch (abi_size) { | 2833 | switch (abi_size) { |
| 2812 | 1, 2, 4 => { | 2834 | 1, 2, 4 => { |
| 2813 | // TODO this is wasteful! | 2835 | try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 2814 | // introduce new MIR tag specifically for mov [reg + 0], imm | 2836 | .base = reg.to64(), |
| 2815 | // const payload = try self.addExtra(Mir.ImmPair{ | 2837 | .disp = 0, |
| 2816 | // .dest_off = 0, | 2838 | }), Immediate.u(@truncate(u32, imm))); |
| 2817 | // .operand = @truncate(u32, imm), | | |
| 2818 | // }); | | |
| 2819 | // _ = try self.addInst(.{ | | |
| 2820 | // .tag = .mov_mem_imm, | | |
| 2821 | // .ops = Mir.Inst.Ops.encode(.{ | | |
| 2822 | // .reg1 = reg.to64(), | | |
| 2823 | // .flags = switch (abi_size) { | | |
| 2824 | // 1 => 0b00, | | |
| 2825 | // 2 => 0b01, | | |
| 2826 | // 4 => 0b10, | | |
| 2827 | // else => unreachable, | | |
| 2828 | // }, | | |
| 2829 | // }), | | |
| 2830 | // .data = .{ .payload = payload }, | | |
| 2831 | // }); | | |
| 2832 | }, | 2839 | }, |
| 2833 | 8 => { | 2840 | 8 => { |
| 2834 | // TODO: optimization: if the imm is only using the lower | 2841 | // TODO: optimization: if the imm is only using the lower |
| ... | @@ -2913,19 +2920,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2913,19 +2920,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2913 | return self.fail("TODO saving imm to memory for abi_size {}", .{abi_size}); | 2920 | return self.fail("TODO saving imm to memory for abi_size {}", .{abi_size}); |
| 2914 | } | 2921 | } |
| 2915 | | 2922 | |
| 2916 | // const payload = try self.addExtra(Mir.ImmPair{ | 2923 | if (abi_size == 8) { |
| 2917 | // .dest_off = 0, | 2924 | // TODO |
| 2918 | // // TODO check if this logic is correct | | |
| 2919 | // .operand = @intCast(u32, imm), | | |
| 2920 | // }); | | |
| 2921 | const flags: u2 = switch (abi_size) { | | |
| 2922 | 1 => 0b00, | | |
| 2923 | 2 => 0b01, | | |
| 2924 | 4 => 0b10, | | |
| 2925 | 8 => 0b11, | | |
| 2926 | else => unreachable, | | |
| 2927 | }; | | |
| 2928 | if (flags == 0b11) { | | |
| 2929 | const top_bits: u32 = @intCast(u32, imm >> 32); | 2925 | const top_bits: u32 = @intCast(u32, imm >> 32); |
| 2930 | const can_extend = if (value_ty.isUnsignedInt()) | 2926 | const can_extend = if (value_ty.isUnsignedInt()) |
| 2931 | (top_bits == 0) and (imm & 0x8000_0000) == 0 | 2927 | (top_bits == 0) and (imm & 0x8000_0000) == 0 |
| ... | @@ -2936,14 +2932,10 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2936,14 +2932,10 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2936 | return self.fail("TODO imm64 would get incorrectly sign extended", .{}); | 2932 | return self.fail("TODO imm64 would get incorrectly sign extended", .{}); |
| 2937 | } | 2933 | } |
| 2938 | } | 2934 | } |
| 2939 | // _ = try self.addInst(.{ | 2935 | try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 2940 | // .tag = .mov_mem_imm, | 2936 | .base = addr_reg.to64(), |
| 2941 | // .ops = Mir.Inst.Ops.encode(.{ | 2937 | .disp = 0, |
| 2942 | // .reg1 = addr_reg.to64(), | 2938 | }), Immediate.u(@intCast(u32, imm))); |
| 2943 | // .flags = flags, | | |
| 2944 | // }), | | |
| 2945 | // .data = .{ .payload = payload }, | | |
| 2946 | // }); | | |
| 2947 | }, | 2939 | }, |
| 2948 | .register => { | 2940 | .register => { |
| 2949 | return self.store(new_ptr, value, ptr_ty, value_ty); | 2941 | return self.store(new_ptr, value, ptr_ty, value_ty); |
| ... | @@ -3595,12 +3587,12 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -3595,12 +3587,12 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3595 | ), | 3587 | ), |
| 3596 | }, | 3588 | }, |
| 3597 | .immediate => |imm| { | 3589 | .immediate => |imm| { |
| 3598 | _ = imm; | 3590 | // TODO |
| 3599 | // _ = try self.addInst(.{ | 3591 | try self.asmRegisterImmediate( |
| 3600 | // .tag = mir_tag, | 3592 | mir_tag, |
| 3601 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = registerAlias(dst_reg, abi_size) }), | 3593 | registerAlias(dst_reg, abi_size), |
| 3602 | // .data = .{ .imm = @intCast(u32, imm) }, | 3594 | Immediate.u(@intCast(u32, imm)), |
| 3603 | // }); | 3595 | ); |
| 3604 | }, | 3596 | }, |
| 3605 | .memory, | 3597 | .memory, |
| 3606 | .linker_load, | 3598 | .linker_load, |
| ... | @@ -3645,36 +3637,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -3645,36 +3637,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3645 | }), registerAlias(src_reg, abi_size)); | 3637 | }), registerAlias(src_reg, abi_size)); |
| 3646 | }, | 3638 | }, |
| 3647 | .immediate => |imm| { | 3639 | .immediate => |imm| { |
| 3648 | _ = imm; | 3640 | // TODO |
| 3649 | // const tag: Mir.Inst.Tag = switch (mir_tag) { | 3641 | try self.asmMemoryImmediate(mir_tag, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 3650 | // .add => .add_mem_imm, | 3642 | .base = .rbp, |
| 3651 | // .@"or" => .or_mem_imm, | 3643 | .disp = -off, |
| 3652 | // .@"and" => .and_mem_imm, | 3644 | }), Immediate.u(@intCast(u32, imm))); |
| 3653 | // .sub => .sub_mem_imm, | | |
| 3654 | // .xor => .xor_mem_imm, | | |
| 3655 | // .cmp => .cmp_mem_imm, | | |
| 3656 | // else => unreachable, | | |
| 3657 | // }; | | |
| 3658 | const flags: u2 = switch (abi_size) { | | |
| 3659 | 1 => 0b00, | | |
| 3660 | 2 => 0b01, | | |
| 3661 | 4 => 0b10, | | |
| 3662 | 8 => 0b11, | | |
| 3663 | else => unreachable, | | |
| 3664 | }; | | |
| 3665 | // const payload = try self.addExtra(Mir.ImmPair{ | | |
| 3666 | // .dest_off = -off, | | |
| 3667 | // .operand = @intCast(u32, imm), | | |
| 3668 | // }); | | |
| 3669 | _ = flags; | | |
| 3670 | // _ = try self.addInst(.{ | | |
| 3671 | // .tag = tag, | | |
| 3672 | // .ops = Mir.Inst.Ops.encode(.{ | | |
| 3673 | // .reg1 = .rbp, | | |
| 3674 | // .flags = flags, | | |
| 3675 | // }), | | |
| 3676 | // .data = .{ .payload = payload }, | | |
| 3677 | // }); | | |
| 3678 | }, | 3645 | }, |
| 3679 | .memory, | 3646 | .memory, |
| 3680 | .stack_offset, | 3647 | .stack_offset, |
| ... | @@ -5258,33 +5225,18 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE | ... | @@ -5258,33 +5225,18 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 5258 | return self.genSetStackArg(ty, stack_offset, .{ .register = reg }); | 5225 | return self.genSetStackArg(ty, stack_offset, .{ .register = reg }); |
| 5259 | }, | 5226 | }, |
| 5260 | .immediate => |imm| { | 5227 | .immediate => |imm| { |
| 5261 | _ = imm; | | |
| 5262 | switch (abi_size) { | 5228 | switch (abi_size) { |
| 5263 | // TODO | 5229 | 1, 2, 4 => { |
| 5264 | // 1, 2, 4 => { | 5230 | // TODO |
| 5265 | // // We have a positive stack offset value but we want a twos complement negative | 5231 | // We have a positive stack offset value but we want a twos complement negative |
| 5266 | // // offset from rbp, which is at the top of the stack frame. | 5232 | // offset from rbp, which is at the top of the stack frame. |
| 5267 | // // mov [rbp+offset], immediate | 5233 | // mov [rbp+offset], immediate |
| 5268 | // const flags: u2 = switch (abi_size) { | 5234 | try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 5269 | // 1 => 0b00, | 5235 | .base = .rsp, |
| 5270 | // 2 => 0b01, | 5236 | .disp = -stack_offset, |
| 5271 | // 4 => 0b10, | 5237 | }), Immediate.u(@intCast(u32, imm))); |
| 5272 | // else => unreachable, | 5238 | }, |
| 5273 | // }; | 5239 | 8 => { |
| 5274 | // const payload = try self.addExtra(Mir.ImmPair{ | | |
| 5275 | // .dest_off = -stack_offset, | | |
| 5276 | // .operand = @intCast(u32, imm), | | |
| 5277 | // }); | | |
| 5278 | // _ = try self.addInst(.{ | | |
| 5279 | // .tag = .mov_mem_imm, | | |
| 5280 | // .ops = Mir.Inst.Ops.encode(.{ | | |
| 5281 | // .reg1 = .rsp, | | |
| 5282 | // .flags = flags, | | |
| 5283 | // }), | | |
| 5284 | // .data = .{ .payload = payload }, | | |
| 5285 | // }); | | |
| 5286 | // }, | | |
| 5287 | 1, 2, 4, 8 => { | | |
| 5288 | const reg = try self.copyToTmpRegister(ty, mcv); | 5240 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 5289 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); | 5241 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| 5290 | }, | 5242 | }, |
| ... | @@ -5355,7 +5307,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE | ... | @@ -5355,7 +5307,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 5355 | } | 5307 | } |
| 5356 | | 5308 | |
| 5357 | fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: InlineMemcpyOpts) InnerError!void { | 5309 | fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: InlineMemcpyOpts) InnerError!void { |
| 5358 | const abi_size = ty.abiSize(self.target.*); | 5310 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 5359 | switch (mcv) { | 5311 | switch (mcv) { |
| 5360 | .dead => unreachable, | 5312 | .dead => unreachable, |
| 5361 | .unreach, .none => return, // Nothing to do. | 5313 | .unreach, .none => return, // Nothing to do. |
| ... | @@ -5400,75 +5352,33 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl | ... | @@ -5400,75 +5352,33 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5400 | return self.genSetStack(ty, stack_offset, .{ .register = reg }, opts); | 5352 | return self.genSetStack(ty, stack_offset, .{ .register = reg }, opts); |
| 5401 | }, | 5353 | }, |
| 5402 | .immediate => |x_big| { | 5354 | .immediate => |x_big| { |
| 5403 | _ = x_big; | | |
| 5404 | const base_reg = opts.dest_stack_base orelse .rbp; | 5355 | const base_reg = opts.dest_stack_base orelse .rbp; |
| 5405 | _ = base_reg; | 5356 | // TODO |
| 5406 | switch (abi_size) { | 5357 | switch (abi_size) { |
| 5407 | 0 => { | 5358 | 0 => { |
| 5408 | assert(ty.isError()); | 5359 | assert(ty.isError()); |
| 5409 | // const payload = try self.addExtra(Mir.ImmPair{ | 5360 | try self.asmMemoryImmediate(.mov, Memory.sib(.byte, .{ |
| 5410 | // .dest_off = -stack_offset, | 5361 | .base = base_reg, |
| 5411 | // .operand = @truncate(u32, x_big), | 5362 | .disp = -stack_offset, |
| 5412 | // }); | 5363 | }), Immediate.u(@truncate(u32, x_big))); |
| 5413 | // _ = try self.addInst(.{ | | |
| 5414 | // .tag = .mov_mem_imm, | | |
| 5415 | // .ops = Mir.Inst.Ops.encode(.{ | | |
| 5416 | // .reg1 = base_reg, | | |
| 5417 | // .flags = 0b00, | | |
| 5418 | // }), | | |
| 5419 | // .data = .{ .payload = payload }, | | |
| 5420 | // }); | | |
| 5421 | }, | 5364 | }, |
| 5422 | 1, 2, 4 => { | 5365 | 1, 2, 4 => { |
| 5423 | // const payload = try self.addExtra(Mir.ImmPair{ | 5366 | try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 5424 | // .dest_off = -stack_offset, | 5367 | .base = base_reg, |
| 5425 | // .operand = @truncate(u32, x_big), | 5368 | .disp = -stack_offset, |
| 5426 | // }); | 5369 | }), Immediate.u(@truncate(u32, x_big))); |
| 5427 | // _ = try self.addInst(.{ | | |
| 5428 | // .tag = .mov_mem_imm, | | |
| 5429 | // .ops = Mir.Inst.Ops.encode(.{ | | |
| 5430 | // .reg1 = base_reg, | | |
| 5431 | // .flags = switch (abi_size) { | | |
| 5432 | // 1 => 0b00, | | |
| 5433 | // 2 => 0b01, | | |
| 5434 | // 4 => 0b10, | | |
| 5435 | // else => unreachable, | | |
| 5436 | // }, | | |
| 5437 | // }), | | |
| 5438 | // .data = .{ .payload = payload }, | | |
| 5439 | // }); | | |
| 5440 | }, | 5370 | }, |
| 5441 | 8 => { | 5371 | 8 => { |
| 5442 | // 64 bit write to memory would take two mov's anyways so we | 5372 | // 64 bit write to memory would take two mov's anyways so we |
| 5443 | // insted just use two 32 bit writes to avoid register allocation | 5373 | // insted just use two 32 bit writes to avoid register allocation |
| 5444 | { | 5374 | try self.asmMemoryImmediate(.mov, Memory.sib(.dword, .{ |
| 5445 | // const payload = try self.addExtra(Mir.ImmPair{ | 5375 | .base = base_reg, |
| 5446 | // .dest_off = -stack_offset + 4, | 5376 | .disp = -stack_offset + 4, |
| 5447 | // .operand = @truncate(u32, x_big >> 32), | 5377 | }), Immediate.u(@truncate(u32, x_big >> 32))); |
| 5448 | // }); | 5378 | try self.asmMemoryImmediate(.mov, Memory.sib(.dword, .{ |
| 5449 | // _ = try self.addInst(.{ | 5379 | .base = base_reg, |
| 5450 | // .tag = .mov_mem_imm, | 5380 | .disp = -stack_offset, |
| 5451 | // .ops = Mir.Inst.Ops.encode(.{ | 5381 | }), Immediate.u(@truncate(u32, x_big))); |
| 5452 | // .reg1 = base_reg, | | |
| 5453 | // .flags = 0b10, | | |
| 5454 | // }), | | |
| 5455 | // .data = .{ .payload = payload }, | | |
| 5456 | // }); | | |
| 5457 | } | | |
| 5458 | { | | |
| 5459 | // const payload = try self.addExtra(Mir.ImmPair{ | | |
| 5460 | // .dest_off = -stack_offset, | | |
| 5461 | // .operand = @truncate(u32, x_big), | | |
| 5462 | // }); | | |
| 5463 | // _ = try self.addInst(.{ | | |
| 5464 | // .tag = .mov_mem_imm, | | |
| 5465 | // .ops = Mir.Inst.Ops.encode(.{ | | |
| 5466 | // .reg1 = base_reg, | | |
| 5467 | // .flags = 0b10, | | |
| 5468 | // }), | | |
| 5469 | // .data = .{ .payload = payload }, | | |
| 5470 | // }); | | |
| 5471 | } | | |
| 5472 | }, | 5382 | }, |
| 5473 | else => { | 5383 | else => { |
| 5474 | return self.fail("TODO implement set abi_size=large stack variable with immediate", .{}); | 5384 | return self.fail("TODO implement set abi_size=large stack variable with immediate", .{}); |
| ... | @@ -5647,15 +5557,10 @@ fn genInlineMemcpy( | ... | @@ -5647,15 +5557,10 @@ fn genInlineMemcpy( |
| 5647 | try self.loadMemPtrIntoRegister(src_addr_reg, Type.usize, src_ptr); | 5557 | try self.loadMemPtrIntoRegister(src_addr_reg, Type.usize, src_ptr); |
| 5648 | }, | 5558 | }, |
| 5649 | .ptr_stack_offset, .stack_offset => |off| { | 5559 | .ptr_stack_offset, .stack_offset => |off| { |
| 5650 | _ = off; | 5560 | try self.asmRegisterMemory(.lea, src_addr_reg.to64(), Memory.sib(.qword, .{ |
| 5651 | // _ = try self.addInst(.{ | 5561 | .base = opts.source_stack_base orelse .rbp, |
| 5652 | // .tag = .lea, | 5562 | .disp = -off, |
| 5653 | // .ops = Mir.Inst.Ops.encode(.{ | 5563 | })); |
| 5654 | // .reg1 = src_addr_reg.to64(), | | |
| 5655 | // .reg2 = opts.source_stack_base orelse .rbp, | | |
| 5656 | // }), | | |
| 5657 | // .data = .{ .disp = -off }, | | |
| 5658 | // }); | | |
| 5659 | }, | 5564 | }, |
| 5660 | .register => |reg| { | 5565 | .register => |reg| { |
| 5661 | try self.asmRegisterRegister( | 5566 | try self.asmRegisterRegister( |