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 {
509509 });
510510}
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
512535fn asmRegisterMemory(self: *Self, tag: Mir.Inst.Tag, reg: Register, m: Memory) !void {
513536 const ops: Mir.Inst.Ops = switch (m) {
514537 .sib => .rm_sib,
......@@ -2776,7 +2799,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
27762799}
27772800
27782801fn 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.*));
27802803 switch (ptr) {
27812804 .none => unreachable,
27822805 .undef => unreachable,
......@@ -2807,28 +2830,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
28072830 try self.genSetReg(value_ty, reg, value);
28082831 },
28092832 .immediate => |imm| {
2810 _ = imm;
28112833 switch (abi_size) {
28122834 1, 2, 4 => {
2813 // TODO this is wasteful!
2814 // introduce new MIR tag specifically for mov [reg + 0], imm
2815 // const payload = try self.addExtra(Mir.ImmPair{
2816 // .dest_off = 0,
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 // });
2835 try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{
2836 .base = reg.to64(),
2837 .disp = 0,
2838 }), Immediate.u(@truncate(u32, imm)));
28322839 },
28332840 8 => {
28342841 // 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
29132920 return self.fail("TODO saving imm to memory for abi_size {}", .{abi_size});
29142921 }
29152922
2916 // const payload = try self.addExtra(Mir.ImmPair{
2917 // .dest_off = 0,
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) {
2923 if (abi_size == 8) {
2924 // TODO
29292925 const top_bits: u32 = @intCast(u32, imm >> 32);
29302926 const can_extend = if (value_ty.isUnsignedInt())
29312927 (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
29362932 return self.fail("TODO imm64 would get incorrectly sign extended", .{});
29372933 }
29382934 }
2939 // _ = try self.addInst(.{
2940 // .tag = .mov_mem_imm,
2941 // .ops = Mir.Inst.Ops.encode(.{
2942 // .reg1 = addr_reg.to64(),
2943 // .flags = flags,
2944 // }),
2945 // .data = .{ .payload = payload },
2946 // });
2935 try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{
2936 .base = addr_reg.to64(),
2937 .disp = 0,
2938 }), Immediate.u(@intCast(u32, imm)));
29472939 },
29482940 .register => {
29492941 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
35953587 ),
35963588 },
35973589 .immediate => |imm| {
3598 _ = imm;
3599 // _ = try self.addInst(.{
3600 // .tag = mir_tag,
3601 // .ops = Mir.Inst.Ops.encode(.{ .reg1 = registerAlias(dst_reg, abi_size) }),
3602 // .data = .{ .imm = @intCast(u32, imm) },
3603 // });
3590 // TODO
3591 try self.asmRegisterImmediate(
3592 mir_tag,
3593 registerAlias(dst_reg, abi_size),
3594 Immediate.u(@intCast(u32, imm)),
3595 );
36043596 },
36053597 .memory,
36063598 .linker_load,
......@@ -3645,36 +3637,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu
36453637 }), registerAlias(src_reg, abi_size));
36463638 },
36473639 .immediate => |imm| {
3648 _ = imm;
3649 // const tag: Mir.Inst.Tag = switch (mir_tag) {
3650 // .add => .add_mem_imm,
3651 // .@"or" => .or_mem_imm,
3652 // .@"and" => .and_mem_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 // });
3640 // TODO
3641 try self.asmMemoryImmediate(mir_tag, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{
3642 .base = .rbp,
3643 .disp = -off,
3644 }), Immediate.u(@intCast(u32, imm)));
36783645 },
36793646 .memory,
36803647 .stack_offset,
......@@ -5258,33 +5225,18 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
52585225 return self.genSetStackArg(ty, stack_offset, .{ .register = reg });
52595226 },
52605227 .immediate => |imm| {
5261 _ = imm;
52625228 switch (abi_size) {
5263 // TODO
5264 // 1, 2, 4 => {
5265 // // 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.
5267 // // mov [rbp+offset], immediate
5268 // const flags: u2 = switch (abi_size) {
5269 // 1 => 0b00,
5270 // 2 => 0b01,
5271 // 4 => 0b10,
5272 // else => unreachable,
5273 // };
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 => {
5229 1, 2, 4 => {
5230 // TODO
5231 // We have a positive stack offset value but we want a twos complement negative
5232 // offset from rbp, which is at the top of the stack frame.
5233 // mov [rbp+offset], immediate
5234 try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{
5235 .base = .rsp,
5236 .disp = -stack_offset,
5237 }), Immediate.u(@intCast(u32, imm)));
5238 },
5239 8 => {
52885240 const reg = try self.copyToTmpRegister(ty, mcv);
52895241 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
52905242 },
......@@ -5355,7 +5307,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
53555307}
53565308
53575309fn 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.*));
53595311 switch (mcv) {
53605312 .dead => unreachable,
53615313 .unreach, .none => return, // Nothing to do.
......@@ -5400,75 +5352,33 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
54005352 return self.genSetStack(ty, stack_offset, .{ .register = reg }, opts);
54015353 },
54025354 .immediate => |x_big| {
5403 _ = x_big;
54045355 const base_reg = opts.dest_stack_base orelse .rbp;
5405 _ = base_reg;
5356 // TODO
54065357 switch (abi_size) {
54075358 0 => {
54085359 assert(ty.isError());
5409 // const payload = try self.addExtra(Mir.ImmPair{
5410 // .dest_off = -stack_offset,
5411 // .operand = @truncate(u32, x_big),
5412 // });
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 // });
5360 try self.asmMemoryImmediate(.mov, Memory.sib(.byte, .{
5361 .base = base_reg,
5362 .disp = -stack_offset,
5363 }), Immediate.u(@truncate(u32, x_big)));
54215364 },
54225365 1, 2, 4 => {
5423 // const payload = try self.addExtra(Mir.ImmPair{
5424 // .dest_off = -stack_offset,
5425 // .operand = @truncate(u32, x_big),
5426 // });
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 // });
5366 try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{
5367 .base = base_reg,
5368 .disp = -stack_offset,
5369 }), Immediate.u(@truncate(u32, x_big)));
54405370 },
54415371 8 => {
54425372 // 64 bit write to memory would take two mov's anyways so we
54435373 // insted just use two 32 bit writes to avoid register allocation
5444 {
5445 // const payload = try self.addExtra(Mir.ImmPair{
5446 // .dest_off = -stack_offset + 4,
5447 // .operand = @truncate(u32, x_big >> 32),
5448 // });
5449 // _ = try self.addInst(.{
5450 // .tag = .mov_mem_imm,
5451 // .ops = Mir.Inst.Ops.encode(.{
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 }
5374 try self.asmMemoryImmediate(.mov, Memory.sib(.dword, .{
5375 .base = base_reg,
5376 .disp = -stack_offset + 4,
5377 }), Immediate.u(@truncate(u32, x_big >> 32)));
5378 try self.asmMemoryImmediate(.mov, Memory.sib(.dword, .{
5379 .base = base_reg,
5380 .disp = -stack_offset,
5381 }), Immediate.u(@truncate(u32, x_big)));
54725382 },
54735383 else => {
54745384 return self.fail("TODO implement set abi_size=large stack variable with immediate", .{});
......@@ -5647,15 +5557,10 @@ fn genInlineMemcpy(
56475557 try self.loadMemPtrIntoRegister(src_addr_reg, Type.usize, src_ptr);
56485558 },
56495559 .ptr_stack_offset, .stack_offset => |off| {
5650 _ = off;
5651 // _ = try self.addInst(.{
5652 // .tag = .lea,
5653 // .ops = Mir.Inst.Ops.encode(.{
5654 // .reg1 = src_addr_reg.to64(),
5655 // .reg2 = opts.source_stack_base orelse .rbp,
5656 // }),
5657 // .data = .{ .disp = -off },
5658 // });
5560 try self.asmRegisterMemory(.lea, src_addr_reg.to64(), Memory.sib(.qword, .{
5561 .base = opts.source_stack_base orelse .rbp,
5562 .disp = -off,
5563 }));
56595564 },
56605565 .register => |reg| {
56615566 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
221221 const mrip = emit.mir.extraData(Mir.MemoryRip, data.payload).data;
222222 operands[0] = .{ .mem = Mir.MemoryRip.decode(mrip) };
223223 },
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 },
224252 .rm_sib, .mr_sib => {
225253 const msib = emit.mir.extraData(Mir.MemorySib, data.rx.payload).data;
226254 const op1 = .{ .reg = data.rx.r1 };