authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-08 19:57:01+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-14 22:09:43+01:00
logf47245865eea35fa0b08cb2a87e3620fa904dd88
tree61995c5a806a91a2cc90cba8cd5eab40655d226b
parentf598d2ae056e72bda1efb3bc7d77e8183e95e191
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: minor refactors in Mir + Emit


3 files changed, 78 insertions(+), 98 deletions(-)

src/arch/aarch64/CodeGen.zig+30-49
...@@ -2121,8 +2121,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -2121,8 +2121,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
2121 .immediate => |imm| {2121 .immediate => |imm| {
2122 _ = try self.addInst(.{2122 _ = try self.addInst(.{
2123 .tag = .cmp_immediate,2123 .tag = .cmp_immediate,
2124 .data = .{ .rr_imm12_sh = .{2124 .data = .{ .r_imm12_sh = .{
2125 .rd = .xzr,
2126 .rn = lhs_mcv.register,2125 .rn = lhs_mcv.register,
2127 .imm12 = @intCast(u12, imm),2126 .imm12 = @intCast(u12, imm),
2128 } },2127 } },
...@@ -2334,8 +2333,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {...@@ -2334,8 +2333,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
23342333
2335 _ = try self.addInst(.{2334 _ = try self.addInst(.{
2336 .tag = .cmp_immediate,2335 .tag = .cmp_immediate,
2337 .data = .{ .rr_imm12_sh = .{2336 .data = .{ .r_imm12_sh = .{
2338 .rd = .xzr,
2339 .rn = reg_mcv.register,2337 .rn = reg_mcv.register,
2340 .imm12 = 0,2338 .imm12 = 0,
2341 } },2339 } },
...@@ -2559,7 +2557,16 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {...@@ -2559,7 +2557,16 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
2559 const operand_mcv = try self.resolveInst(operand);2557 const operand_mcv = try self.resolveInst(operand);
2560 const block_mcv = block_data.mcv;2558 const block_mcv = block_data.mcv;
2561 if (block_mcv == .none) {2559 if (block_mcv == .none) {
2562 block_data.mcv = operand_mcv;2560 block_data.mcv = switch (operand_mcv) {
2561 .none, .dead, .unreach => unreachable,
2562 .register, .stack_offset, .memory => operand_mcv,
2563 .immediate => blk: {
2564 const new_mcv = try self.allocRegOrMem(block, true);
2565 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);
2566 break :blk new_mcv;
2567 },
2568 else => return self.fail("TODO implement block_data.mcv = operand_mcv for {}", .{operand_mcv}),
2569 };
2563 } else {2570 } else {
2564 try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv);2571 try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv);
2565 }2572 }
...@@ -2845,10 +2852,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -2845,10 +2852,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
28452852
2846 _ = try self.addInst(.{2853 _ = try self.addInst(.{
2847 .tag = .cset,2854 .tag = .cset,
2848 .data = .{ .rrr_cond = .{2855 .data = .{ .r_cond = .{
2849 .rd = reg,2856 .rd = reg,
2850 .rn = .xzr,
2851 .rm = .xzr,
2852 .cond = condition,2857 .cond = condition,
2853 } },2858 } },
2854 });2859 });
...@@ -2933,7 +2938,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -2933,7 +2938,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
2933 } },2938 } },
2934 });2939 });
2935 },2940 },
2936 3 => return self.fail("TODO implement genSetReg types size 3", .{}),2941 3, 5, 6, 7 => return self.fail("TODO implement genSetReg types size {}", .{abi_size}),
2937 else => unreachable,2942 else => unreachable,
2938 }2943 }
2939 },2944 },
...@@ -3114,27 +3119,6 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -3114,27 +3119,6 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
3114 }3119 }
3115}3120}
31163121
3117/// If the MCValue is an immediate, and it does not fit within this type,
3118/// we put it in a register.
3119/// A potential opportunity for future optimization here would be keeping track
3120/// of the fact that the instruction is available both as an immediate
3121/// and as a register.
3122fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCValue {
3123 const mcv = try self.resolveInst(operand);
3124 const ti = @typeInfo(T).Int;
3125 switch (mcv) {
3126 .immediate => |imm| {
3127 // This immediate is unsigned.
3128 const U = std.meta.Int(.unsigned, ti.bits - @boolToInt(ti.signedness == .signed));
3129 if (imm >= math.maxInt(U)) {
3130 return MCValue{ .register = try self.copyToTmpRegister(Type.initTag(.usize), mcv) };
3131 }
3132 },
3133 else => {},
3134 }
3135 return mcv;
3136}
3137
3138fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue {3122fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue {
3139 const ptr_bits = self.target.cpu.arch.ptrBitWidth();3123 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
3140 const ptr_bytes: u64 = @divExact(ptr_bits, 8);3124 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
...@@ -3248,19 +3232,11 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -3248,19 +3232,11 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
3248 }3232 }
3249 },3233 },
3250 .ErrorSet => {3234 .ErrorSet => {
3251 switch (typed_value.val.tag()) {3235 const err_name = typed_value.val.castTag(.@"error").?.data.name;
3252 .@"error" => {3236 const module = self.bin_file.options.module.?;
3253 const err_name = typed_value.val.castTag(.@"error").?.data.name;3237 const global_error_set = module.global_error_set;
3254 const module = self.bin_file.options.module.?;3238 const error_index = global_error_set.get(err_name).?;
3255 const global_error_set = module.global_error_set;3239 return MCValue{ .immediate = error_index };
3256 const error_index = global_error_set.get(err_name).?;
3257 return MCValue{ .immediate = error_index };
3258 },
3259 else => {
3260 // In this case we are rendering an error union which has a 0 bits payload.
3261 return MCValue{ .immediate = 0 };
3262 },
3263 }
3264 },3240 },
3265 .ErrorUnion => {3241 .ErrorUnion => {
3266 const error_type = typed_value.ty.errorUnionSet();3242 const error_type = typed_value.ty.errorUnionSet();
...@@ -3425,13 +3401,18 @@ fn parseRegName(name: []const u8) ?Register {...@@ -3425,13 +3401,18 @@ fn parseRegName(name: []const u8) ?Register {
3425}3401}
34263402
3427fn registerAlias(reg: Register, size_bytes: u32) Register {3403fn registerAlias(reg: Register, size_bytes: u32) Register {
3428 _ = size_bytes;3404 if (size_bytes == 0) {
34293405 unreachable; // should be comptime known
3430 return reg;3406 } else if (size_bytes <= 4) {
3407 return reg.to32();
3408 } else if (size_bytes <= 8) {
3409 return reg.to64();
3410 } else {
3411 unreachable; // TODO handle floating-point registers
3412 }
3431}3413}
34323414
3433/// For most architectures this does nothing. For x86_64 it resolves any aliased registers3415/// Resolves any aliased registers to the 64-bit wide ones.
3434/// to the 64-bit wide ones.
3435fn toCanonicalReg(reg: Register) Register {3416fn toCanonicalReg(reg: Register) Register {
3436 return reg;3417 return reg.to64();
3437}3418}
src/arch/aarch64/Emit.zig+33-40
...@@ -423,27 +423,30 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {...@@ -423,27 +423,30 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
423423
424fn mirAddSubtractImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {424fn mirAddSubtractImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
425 const tag = emit.mir.instructions.items(.tag)[inst];425 const tag = emit.mir.instructions.items(.tag)[inst];
426 const rr_imm12_sh = emit.mir.instructions.items(.data)[inst].rr_imm12_sh;
427
428 switch (tag) {426 switch (tag) {
429 .add_immediate => try emit.writeInstruction(Instruction.add(427 .add_immediate,
430 rr_imm12_sh.rd,428 .sub_immediate,
431 rr_imm12_sh.rn,429 => {
432 rr_imm12_sh.imm12,430 const rr_imm12_sh = emit.mir.instructions.items(.data)[inst].rr_imm12_sh;
433 rr_imm12_sh.sh == 1,431 const rd = rr_imm12_sh.rd;
434 )),432 const rn = rr_imm12_sh.rn;
435 .cmp_immediate => try emit.writeInstruction(Instruction.subs(433 const imm12 = rr_imm12_sh.imm12;
436 rr_imm12_sh.rd,434 const sh = rr_imm12_sh.sh == 1;
437 rr_imm12_sh.rn,435
438 rr_imm12_sh.imm12,436 switch (tag) {
439 rr_imm12_sh.sh == 1,437 .add_immediate => try emit.writeInstruction(Instruction.add(rd, rn, imm12, sh)),
440 )),438 .sub_immediate => try emit.writeInstruction(Instruction.sub(rd, rn, imm12, sh)),
441 .sub_immediate => try emit.writeInstruction(Instruction.sub(439 else => unreachable,
442 rr_imm12_sh.rd,440 }
443 rr_imm12_sh.rn,441 },
444 rr_imm12_sh.imm12,442 .cmp_immediate => {
445 rr_imm12_sh.sh == 1,443 const r_imm12_sh = emit.mir.instructions.items(.data)[inst].r_imm12_sh;
446 )),444 const rn = r_imm12_sh.rn;
445 const imm12 = r_imm12_sh.imm12;
446 const sh = r_imm12_sh.sh == 1;
447
448 try emit.writeInstruction(Instruction.subs(.xzr, rn, imm12, sh));
449 },
447 else => unreachable,450 else => unreachable,
448 }451 }
449}452}
...@@ -589,15 +592,11 @@ fn mirAddSubtractShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -589,15 +592,11 @@ fn mirAddSubtractShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
589592
590fn mirConditionalSelect(emit: *Emit, inst: Mir.Inst.Index) !void {593fn mirConditionalSelect(emit: *Emit, inst: Mir.Inst.Index) !void {
591 const tag = emit.mir.instructions.items(.tag)[inst];594 const tag = emit.mir.instructions.items(.tag)[inst];
592 const rrr_cond = emit.mir.instructions.items(.data)[inst].rrr_cond;
593
594 switch (tag) {595 switch (tag) {
595 .cset => try emit.writeInstruction(Instruction.csinc(596 .cset => {
596 rrr_cond.rd,597 const r_cond = emit.mir.instructions.items(.data)[inst].r_cond;
597 rrr_cond.rn,598 try emit.writeInstruction(Instruction.csinc(r_cond.rd, .xzr, .xzr, r_cond.cond));
598 rrr_cond.rm,599 },
599 rrr_cond.cond,
600 )),
601 else => unreachable,600 else => unreachable,
602 }601 }
603}602}
...@@ -662,20 +661,14 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -662,20 +661,14 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {
662fn mirLoadStoreRegisterPair(emit: *Emit, inst: Mir.Inst.Index) !void {661fn mirLoadStoreRegisterPair(emit: *Emit, inst: Mir.Inst.Index) !void {
663 const tag = emit.mir.instructions.items(.tag)[inst];662 const tag = emit.mir.instructions.items(.tag)[inst];
664 const load_store_register_pair = emit.mir.instructions.items(.data)[inst].load_store_register_pair;663 const load_store_register_pair = emit.mir.instructions.items(.data)[inst].load_store_register_pair;
664 const rt = load_store_register_pair.rt;
665 const rt2 = load_store_register_pair.rt2;
666 const rn = load_store_register_pair.rn;
667 const offset = load_store_register_pair.offset;
665668
666 switch (tag) {669 switch (tag) {
667 .stp => try emit.writeInstruction(Instruction.stp(670 .stp => try emit.writeInstruction(Instruction.stp(rt, rt2, rn, offset)),
668 load_store_register_pair.rt,671 .ldp => try emit.writeInstruction(Instruction.ldp(rt, rt2, rn, offset)),
669 load_store_register_pair.rt2,
670 load_store_register_pair.rn,
671 load_store_register_pair.offset,
672 )),
673 .ldp => try emit.writeInstruction(Instruction.ldp(
674 load_store_register_pair.rt,
675 load_store_register_pair.rt2,
676 load_store_register_pair.rn,
677 load_store_register_pair.offset,
678 )),
679 else => unreachable,672 else => unreachable,
680 }673 }
681}674}
src/arch/aarch64/Mir.zig+15-9
...@@ -175,6 +175,13 @@ pub const Inst = struct {...@@ -175,6 +175,13 @@ pub const Inst = struct {
175 imm16: u16,175 imm16: u16,
176 hw: u2 = 0,176 hw: u2 = 0,
177 },177 },
178 /// A register and a condition
179 ///
180 /// Used by e.g. cset
181 r_cond: struct {
182 rd: Register,
183 cond: bits.Instruction.Condition,
184 },
178 /// Two registers185 /// Two registers
179 ///186 ///
180 /// Used by e.g. mov_register187 /// Used by e.g. mov_register
...@@ -182,6 +189,14 @@ pub const Inst = struct {...@@ -182,6 +189,14 @@ pub const Inst = struct {
182 rd: Register,189 rd: Register,
183 rn: Register,190 rn: Register,
184 },191 },
192 /// A register, an unsigned 12-bit immediate, and an optional shift
193 ///
194 /// Used by e.g. cmp_immediate
195 r_imm12_sh: struct {
196 rn: Register,
197 imm12: u12,
198 sh: u1 = 0,
199 },
185 /// Two registers, an unsigned 12-bit immediate, and an optional shift200 /// Two registers, an unsigned 12-bit immediate, and an optional shift
186 ///201 ///
187 /// Used by e.g. sub_immediate202 /// Used by e.g. sub_immediate
...@@ -209,15 +224,6 @@ pub const Inst = struct {...@@ -209,15 +224,6 @@ pub const Inst = struct {
209 imm6: u6,224 imm6: u6,
210 shift: bits.Instruction.AddSubtractShiftedRegisterShift,225 shift: bits.Instruction.AddSubtractShiftedRegisterShift,
211 },226 },
212 /// Three registers and a condition
213 ///
214 /// Used by e.g. cset
215 rrr_cond: struct {
216 rd: Register,
217 rn: Register,
218 rm: Register,
219 cond: bits.Instruction.Condition,
220 },
221 /// Two registers and a LoadStoreOffsetImmediate227 /// Two registers and a LoadStoreOffsetImmediate
222 ///228 ///
223 /// Used by e.g. str_immediate229 /// Used by e.g. str_immediate