| ... | @@ -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 { |
| 2334 | | 2333 | |
| 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 |
| 2845 | | 2852 | |
| 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 | } |
| 3116 | | 3121 | |
| 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. | | |
| 3122 | fn 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 | | | |
| 3138 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue { | 3122 | fn 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 | } |
| 3426 | | 3402 | |
| 3427 | fn registerAlias(reg: Register, size_bytes: u32) Register { | 3403 | fn registerAlias(reg: Register, size_bytes: u32) Register { |
| 3428 | _ = size_bytes; | 3404 | if (size_bytes == 0) { |
| 3429 | | 3405 | 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 | } |
| 3432 | | 3414 | |
| 3433 | /// For most architectures this does nothing. For x86_64 it resolves any aliased registers | 3415 | /// Resolves any aliased registers to the 64-bit wide ones. |
| 3434 | /// to the 64-bit wide ones. | | |
| 3435 | fn toCanonicalReg(reg: Register) Register { | 3416 | fn toCanonicalReg(reg: Register) Register { |
| 3436 | return reg; | 3417 | return reg.to64(); |
| 3437 | } | 3418 | } |