authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-09 22:15:58+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-11 20:05:49+01:00
log022b308d6a0a3d3cf178ddc6e887f24369f69deb
tree4d8c893a9dd0176515dcdc7c461b595bb002254d
parent4af8313f362e393f51af1bcefd0b91c3b1ce5611

x86_64: start converting MI references


2 files changed, 106 insertions(+), 173 deletions(-)

src/arch/x86_64/CodeGen.zig+78-173
...@@ -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}
511511
512fn 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
512fn asmRegisterMemory(self: *Self, tag: Mir.Inst.Tag, reg: Register, m: Memory) !void {535fn 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}
27772800
2778fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {2801fn 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], imm2836 .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 lower2841 // 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 }
29152922
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) == 02927 (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 // TODO5229 1, 2, 4 => {
5264 // 1, 2, 4 => {5230 // TODO
5265 // // We have a positive stack offset value but we want a twos complement negative5231 // 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], immediate5233 // 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}
53565308
5357fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: InlineMemcpyOpts) InnerError!void {5309fn 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 we5372 // 64 bit write to memory would take two mov's anyways so we
5443 // insted just use two 32 bit writes to avoid register allocation5373 // 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(
src/arch/x86_64/Emit.zig+28
...@@ -221,6 +221,34 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE...@@ -221,6 +221,34 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE
221 const mrip = emit.mir.extraData(Mir.MemoryRip, data.payload).data;221 const mrip = emit.mir.extraData(Mir.MemoryRip, data.payload).data;
222 operands[0] = .{ .mem = Mir.MemoryRip.decode(mrip) };222 operands[0] = .{ .mem = Mir.MemoryRip.decode(mrip) };
223 },223 },
224 .mi_u_sib => {
225 const msib = emit.mir.extraData(Mir.MemorySib, data.xi_u.payload).data;
226 operands[0..2].* = .{
227 .{ .mem = Mir.MemorySib.decode(msib) },
228 .{ .imm = Immediate.u(data.xi_u.imm) },
229 };
230 },
231 .mi_s_sib => {
232 const msib = emit.mir.extraData(Mir.MemorySib, data.xi_s.payload).data;
233 operands[0..2].* = .{
234 .{ .mem = Mir.MemorySib.decode(msib) },
235 .{ .imm = Immediate.s(data.xi_s.imm) },
236 };
237 },
238 .mi_u_rip => {
239 const mrip = emit.mir.extraData(Mir.MemoryRip, data.xi_u.payload).data;
240 operands[0..2].* = .{
241 .{ .mem = Mir.MemoryRip.decode(mrip) },
242 .{ .imm = Immediate.u(data.xi_u.imm) },
243 };
244 },
245 .mi_s_rip => {
246 const mrip = emit.mir.extraData(Mir.MemoryRip, data.xi_s.payload).data;
247 operands[0..2].* = .{
248 .{ .mem = Mir.MemoryRip.decode(mrip) },
249 .{ .imm = Immediate.s(data.xi_s.imm) },
250 };
251 },
224 .rm_sib, .mr_sib => {252 .rm_sib, .mr_sib => {
225 const msib = emit.mir.extraData(Mir.MemorySib, data.rx.payload).data;253 const msib = emit.mir.extraData(Mir.MemorySib, data.rx.payload).data;
226 const op1 = .{ .reg = data.rx.r1 };254 const op1 = .{ .reg = data.rx.r1 };