| ... | @@ -101,8 +101,8 @@ pub const Block = struct { | ... | @@ -101,8 +101,8 @@ pub const Block = struct { |
| 101 | fn branch(target_block: *Block, isel: *Select) !void { | 101 | fn branch(target_block: *Block, isel: *Select) !void { |
| 102 | if (isel.instructions.items.len > target_block.target_label) { | 102 | if (isel.instructions.items.len > target_block.target_label) { |
| 103 | try isel.internal_relocs.append(isel.pt.zcu.gpa, .{ | 103 | try isel.internal_relocs.append(isel.pt.zcu.gpa, .{ |
| 104 | .label = @intCast(isel.instructions.items.len), | | |
| 105 | .target = target_block.target_label, | 104 | .target = target_block.target_label, |
| | 105 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 }, |
| 106 | }); | 106 | }); |
| 107 | try isel.emit(.b(0, 0)); | 107 | try isel.emit(.b(0, 0)); |
| 108 | } | 108 | } |
| ... | @@ -1026,7 +1026,7 @@ pub const Value = struct { | ... | @@ -1026,7 +1026,7 @@ pub const Value = struct { |
| 1026 | } | 1026 | } |
| 1027 | | 1027 | |
| 1028 | /// Defines a value with a register. | 1028 | /// Defines a value with a register. |
| 1029 | /// Returned registers are free-ed. | 1029 | /// Returned registers are free-ed and marked as written. |
| 1030 | /// Extension unchanged. | 1030 | /// Extension unchanged. |
| 1031 | fn defReg(vi: Value.Index, isel: *Select) !?Register.Alias { | 1031 | fn defReg(vi: Value.Index, isel: *Select) !?Register.Alias { |
| 1032 | const value = vi.get(isel); | 1032 | const value = vi.get(isel); |
| ... | @@ -1449,6 +1449,7 @@ pub const Value = struct { | ... | @@ -1449,6 +1449,7 @@ pub const Value = struct { |
| 1449 | .reloc = .{ | 1449 | .reloc = .{ |
| 1450 | .label = @intCast(isel.instructions.items.len), | 1450 | .label = @intCast(isel.instructions.items.len), |
| 1451 | .addend = @intCast(total_root_offset), | 1451 | .addend = @intCast(total_root_offset), |
| | 1452 | .type = .PCALA_LO12, |
| 1452 | }, | 1453 | }, |
| 1453 | }); | 1454 | }); |
| 1454 | try isel.emit(.@"addi.d"(ptr_reg, ptr_reg, 0)); | 1455 | try isel.emit(.@"addi.d"(ptr_reg, ptr_reg, 0)); |
| ... | @@ -1460,6 +1461,7 @@ pub const Value = struct { | ... | @@ -1460,6 +1461,7 @@ pub const Value = struct { |
| 1460 | .reloc = .{ | 1461 | .reloc = .{ |
| 1461 | .label = @intCast(isel.instructions.items.len), | 1462 | .label = @intCast(isel.instructions.items.len), |
| 1462 | .addend = @intCast(total_root_offset), | 1463 | .addend = @intCast(total_root_offset), |
| | 1464 | .type = .PCALA_HI20, |
| 1463 | }, | 1465 | }, |
| 1464 | }); | 1466 | }); |
| 1465 | try isel.emit(.pcalau12i(ptr_reg, 0)); | 1467 | try isel.emit(.pcalau12i(ptr_reg, 0)); |
| ... | @@ -2590,6 +2592,7 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -2590,6 +2592,7 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 2590 | .is_named_enum_value, | 2592 | .is_named_enum_value, |
| 2591 | .tag_name, | 2593 | .tag_name, |
| 2592 | .error_name, | 2594 | .error_name, |
| | 2595 | .cmp_lte_errors_len, |
| 2593 | => { | 2596 | => { |
| 2594 | const un_op = air_data[@backingInt(air_inst_index)].un_op; | 2597 | const un_op = air_data[@backingInt(air_inst_index)].un_op; |
| 2595 | | 2598 | |
| ... | @@ -3163,8 +3166,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3163,8 +3166,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3163 | const next_repeat_label = instruction.*; | 3166 | const next_repeat_label = instruction.*; |
| 3164 | instruction.* = .b(0, 0); | 3167 | instruction.* = .b(0, 0); |
| 3165 | try isel.internal_relocs.append(gpa, .{ | 3168 | try isel.internal_relocs.append(gpa, .{ |
| 3166 | .label = repeat_label, | | |
| 3167 | .target = isel.instructions.items.len, | 3169 | .target = isel.instructions.items.len, |
| | 3170 | .reloc = .{ .label = repeat_label, .type = .B26 }, |
| 3168 | }); | 3171 | }); |
| 3169 | repeat_label = @bitCast(next_repeat_label); | 3172 | repeat_label = @bitCast(next_repeat_label); |
| 3170 | } | 3173 | } |
| ... | @@ -3196,8 +3199,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3196,8 +3199,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3196 | .extension = .zero_ext, | 3199 | .extension = .zero_ext, |
| 3197 | }); | 3200 | }); |
| 3198 | try isel.internal_relocs.append(gpa, .{ | 3201 | try isel.internal_relocs.append(gpa, .{ |
| 3199 | .label = @intCast(isel.instructions.items.len), | | |
| 3200 | .target = else_label, | 3202 | .target = else_label, |
| | 3203 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 }, |
| 3201 | }); | 3204 | }); |
| 3202 | try isel.emit(.beqz(cond_mat.reg(), 0, 0)); | 3205 | try isel.emit(.beqz(cond_mat.reg(), 0, 0)); |
| 3203 | try cond_mat.finish(isel); | 3206 | try cond_mat.finish(isel); |
| ... | @@ -3240,8 +3243,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3240,8 +3243,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3240 | }); | 3243 | }); |
| 3241 | | 3244 | |
| 3242 | try isel.internal_relocs.append(gpa, .{ | 3245 | try isel.internal_relocs.append(gpa, .{ |
| 3243 | .label = @intCast(isel.instructions.items.len), | | |
| 3244 | .target = next_label, | 3246 | .target = next_label, |
| | 3247 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 }, |
| 3245 | }); | 3248 | }); |
| 3246 | try isel.emit(.b(0, 0)); | 3249 | try isel.emit(.b(0, 0)); |
| 3247 | | 3250 | |
| ... | @@ -3267,8 +3270,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3267,8 +3270,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3267 | defer isel.freeReg(item_reg); | 3270 | defer isel.freeReg(item_reg); |
| 3268 | | 3271 | |
| 3269 | try isel.internal_relocs.append(gpa, .{ | 3272 | try isel.internal_relocs.append(gpa, .{ |
| 3270 | .label = @intCast(isel.instructions.items.len), | | |
| 3271 | .target = case_label, | 3273 | .target = case_label, |
| | 3274 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B16 }, |
| 3272 | }); | 3275 | }); |
| 3273 | try isel.emit(.beq(cond_mat.reg(), item_reg, 0)); | 3276 | try isel.emit(.beq(cond_mat.reg(), item_reg, 0)); |
| 3274 | try isel.moveIntImm(item_reg, @bitCast(item_int)); | 3277 | try isel.moveIntImm(item_reg, @bitCast(item_int)); |
| ... | @@ -3322,13 +3325,14 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3322,13 +3325,14 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3322 | else => unreachable, | 3325 | else => unreachable, |
| 3323 | inline .@"extern", .func => |func| .{ | 3326 | inline .@"extern", .func => |func| .{ |
| 3324 | .nav = func.owner_nav, | 3327 | .nav = func.owner_nav, |
| 3325 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | 3328 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .CALL36 }, |
| 3326 | }, | 3329 | }, |
| 3327 | .ptr => |ptr| .{ | 3330 | .ptr => |ptr| .{ |
| 3328 | .nav = ptr.base_addr.nav, | 3331 | .nav = ptr.base_addr.nav, |
| 3329 | .reloc = .{ | 3332 | .reloc = .{ |
| 3330 | .label = @intCast(isel.instructions.items.len), | 3333 | .label = @intCast(isel.instructions.items.len), |
| 3331 | .addend = @intCast(ptr.byte_offset), | 3334 | .addend = @intCast(ptr.byte_offset), |
| | 3335 | .type = .CALL36, |
| 3332 | }, | 3336 | }, |
| 3333 | }, | 3337 | }, |
| 3334 | }); | 3338 | }); |
| ... | @@ -3573,6 +3577,26 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3573,6 +3577,26 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3573 | }, | 3577 | }, |
| 3574 | }) else return isel.fail("unimplemented float", .{}); | 3578 | }) else return isel.fail("unimplemented float", .{}); |
| 3575 | }, | 3579 | }, |
| | 3580 | .add_with_overflow, .sub_with_overflow => if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| { |
| | 3581 | defer res_vi.value.deref(isel); |
| | 3582 | |
| | 3583 | const ty_pl = air.data(air.inst_index).ty_pl; |
| | 3584 | const bin_op = isel.air.extraData(Air.Bin, ty_pl.payload).data; |
| | 3585 | const ty = isel.air.typeOf(bin_op.lhs, ip); |
| | 3586 | const lhs_vi = try isel.use(bin_op.lhs); |
| | 3587 | const rhs_vi = try isel.use(bin_op.rhs); |
| | 3588 | const ty_size = lhs_vi.size(isel); |
| | 3589 | |
| | 3590 | const wrapped_vi = try res_vi.value.partExact(isel, 0, ty_size); |
| | 3591 | const overflow_vi = try res_vi.value.partExact(isel, ty_size, 1); |
| | 3592 | try isel.addOrSubtract(ty, wrapped_vi, switch (air_tag) { |
| | 3593 | else => unreachable, |
| | 3594 | .add_with_overflow => .add, |
| | 3595 | .sub_with_overflow => .sub, |
| | 3596 | }, lhs_vi, rhs_vi, .{ |
| | 3597 | .overflow = if (try overflow_vi.defReg(isel)) |overflow_ra| .{ .overflow_ra = overflow_ra } else .wrap, |
| | 3598 | }); |
| | 3599 | }, |
| 3576 | .not => if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: { | 3600 | .not => if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: { |
| 3577 | defer res_vi.value.deref(isel); | 3601 | defer res_vi.value.deref(isel); |
| 3578 | | 3602 | |
| ... | @@ -3676,7 +3700,10 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3676,7 +3700,10 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3676 | try rhs_mat.finish(isel); | 3700 | try rhs_mat.finish(isel); |
| 3677 | try lhs_mat.finish(isel); | 3701 | try lhs_mat.finish(isel); |
| 3678 | }, | 3702 | }, |
| 3679 | else => try isel.failUnimplemented("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }), | 3703 | else => { |
| | 3704 | _ = try res_vi.value.def(isel); |
| | 3705 | try isel.failUnimplemented("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }); |
| | 3706 | }, |
| 3680 | } | 3707 | } |
| 3681 | } else try isel.failUnimplemented("unimplemented float div", .{}); | 3708 | } else try isel.failUnimplemented("unimplemented float div", .{}); |
| 3682 | }, | 3709 | }, |
| ... | @@ -3734,12 +3761,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3734,12 +3761,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3734 | } else if (dst_tag == .float and src_tag == .float) { | 3761 | } else if (dst_tag == .float and src_tag == .float) { |
| 3735 | assert(dst_ty.floatBits(isel.target) == src_ty.floatBits(isel.target)); | 3762 | assert(dst_ty.floatBits(isel.target) == src_ty.floatBits(isel.target)); |
| 3736 | try dst_vi.value.defMove(isel, ty_op.operand); | 3763 | try dst_vi.value.defMove(isel, ty_op.operand); |
| 3737 | } else if (dst_ty.isAbiInt(zcu) and src_tag == .float) { | 3764 | } else if (dst_ty.isAbiInt(zcu) and src_tag == .float and isel.canUseFprForFloat(src_ty.floatBits(isel.target))) { |
| 3738 | const dst_int_info = dst_ty.intInfo(zcu); | 3765 | const dst_int_info = dst_ty.intInfo(zcu); |
| 3739 | assert(dst_int_info.bits == src_ty.floatBits(isel.target)); | 3766 | assert(dst_int_info.bits == src_ty.floatBits(isel.target)); |
| 3740 | | 3767 | |
| 3741 | try dst_vi.value.reextendToGarbage(isel); | 3768 | try dst_vi.value.reextendToGarbage(isel); |
| 3742 | const dst_reg = try dst_vi.value.defRegMod(isel, .fromFloating(dst_int_info.bits)) orelse break :unused; | 3769 | const dst_reg = try dst_vi.value.defRegMod(isel, .fromFloatBits(dst_int_info.bits)) orelse break :unused; |
| 3743 | const src_vi = try isel.use(ty_op.operand); | 3770 | const src_vi = try isel.use(ty_op.operand); |
| 3744 | const src_mat = try src_vi.matReg(isel); | 3771 | const src_mat = try src_vi.matReg(isel); |
| 3745 | const src_reg = src_mat.reg(); | 3772 | const src_reg = src_mat.reg(); |
| ... | @@ -3749,12 +3776,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3749,12 +3776,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3749 | 64 => .@"movfr2gr.d"(dst_reg, src_reg), | 3776 | 64 => .@"movfr2gr.d"(dst_reg, src_reg), |
| 3750 | }); | 3777 | }); |
| 3751 | try src_mat.finish(isel); | 3778 | try src_mat.finish(isel); |
| 3752 | } else if (dst_tag == .float and src_ty.isAbiInt(zcu)) { | 3779 | } else if (dst_tag == .float and src_ty.isAbiInt(zcu) and isel.canUseFprForFloat(dst_ty.floatBits(isel.target))) { |
| 3753 | const src_int_info = src_ty.intInfo(zcu); | 3780 | const src_int_info = src_ty.intInfo(zcu); |
| 3754 | assert(dst_ty.floatBits(isel.target) == src_int_info.bits); | 3781 | assert(dst_ty.floatBits(isel.target) == src_int_info.bits); |
| 3755 | | 3782 | |
| 3756 | try dst_vi.value.reextendToGarbage(isel); | 3783 | try dst_vi.value.reextendToGarbage(isel); |
| 3757 | const dst_reg = try dst_vi.value.defRegMod(isel, .fromFloating(src_int_info.bits)) orelse break :unused; | 3784 | const dst_reg = try dst_vi.value.defRegMod(isel, .fromFloatBits(src_int_info.bits)) orelse break :unused; |
| 3758 | const src_vi = try isel.use(ty_op.operand); | 3785 | const src_vi = try isel.use(ty_op.operand); |
| 3759 | const src_mat = try src_vi.matReg(isel); | 3786 | const src_mat = try src_vi.matReg(isel); |
| 3760 | const src_reg = src_mat.reg(); | 3787 | const src_reg = src_mat.reg(); |
| ... | @@ -3896,13 +3923,13 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -3896,13 +3923,13 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 3896 | .extension = .zero_ext, | 3923 | .extension = .zero_ext, |
| 3897 | }); | 3924 | }); |
| 3898 | try isel.internal_relocs.append(gpa, .{ | 3925 | try isel.internal_relocs.append(gpa, .{ |
| 3899 | .label = @intCast(isel.instructions.items.len), | | |
| 3900 | .target = cmp_label, | 3926 | .target = cmp_label, |
| | 3927 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 }, |
| 3901 | }); | 3928 | }); |
| 3902 | try isel.emit(.beqz(lhs_tag_mat.reg(), 0, 0)); | 3929 | try isel.emit(.beqz(lhs_tag_mat.reg(), 0, 0)); |
| 3903 | try isel.internal_relocs.append(gpa, .{ | 3930 | try isel.internal_relocs.append(gpa, .{ |
| 3904 | .label = @intCast(isel.instructions.items.len), | | |
| 3905 | .target = cmp_label, | 3931 | .target = cmp_label, |
| | 3932 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 }, |
| 3906 | }); | 3933 | }); |
| 3907 | try isel.emit(.beqz(res_reg, 0, 0)); | 3934 | try isel.emit(.beqz(res_reg, 0, 0)); |
| 3908 | | 3935 | |
| ... | @@ -4250,8 +4277,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -4250,8 +4277,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4250 | ); | 4277 | ); |
| 4251 | const error_set_part_mat = try error_set_part_vi.matIntRegZeroExt(isel); | 4278 | const error_set_part_mat = try error_set_part_vi.matIntRegZeroExt(isel); |
| 4252 | try isel.internal_relocs.append(gpa, .{ | 4279 | try isel.internal_relocs.append(gpa, .{ |
| 4253 | .label = @intCast(isel.instructions.items.len), | | |
| 4254 | .target = cont_label, | 4280 | .target = cont_label, |
| | 4281 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 }, |
| 4255 | }); | 4282 | }); |
| 4256 | try isel.emit(.beqz(error_set_part_mat.reg(), 0, 0)); | 4283 | try isel.emit(.beqz(error_set_part_mat.reg(), 0, 0)); |
| 4257 | try error_set_part_mat.finish(isel); | 4284 | try error_set_part_mat.finish(isel); |
| ... | @@ -4288,8 +4315,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, | ... | @@ -4288,8 +4315,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4288 | defer isel.freeReg(tmp_reg); | 4315 | defer isel.freeReg(tmp_reg); |
| 4289 | | 4316 | |
| 4290 | try isel.internal_relocs.append(gpa, .{ | 4317 | try isel.internal_relocs.append(gpa, .{ |
| 4291 | .label = @intCast(isel.instructions.items.len), | | |
| 4292 | .target = cont_label, | 4318 | .target = cont_label, |
| | 4319 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 }, |
| 4293 | }); | 4320 | }); |
| 4294 | try isel.emit(.beqz(tmp_reg, 0, 0)); | 4321 | try isel.emit(.beqz(tmp_reg, 0, 0)); |
| 4295 | | 4322 | |
| ... | @@ -5924,6 +5951,9 @@ fn cmp( | ... | @@ -5924,6 +5951,9 @@ fn cmp( |
| 5924 | rhs_vi: Value.Index, | 5951 | rhs_vi: Value.Index, |
| 5925 | ) !void { | 5952 | ) !void { |
| 5926 | wip_mir_log.debug(" | # cmp {f}, {t}, {f}, {t}, {f}", .{ isel.fmtType(ty), res_reg, lhs_vi, op, rhs_vi }); | 5953 | wip_mir_log.debug(" | # cmp {f}, {t}, {f}, {t}, {f}", .{ isel.fmtType(ty), res_reg, lhs_vi, op, rhs_vi }); |
| | 5954 | const res_lock = isel.tryLockReg(res_reg); |
| | 5955 | defer res_lock.unlock(isel); |
| | 5956 | |
| 5927 | if (!ty.isRuntimeFloat() and !ty.isArrayOrVector(isel.pt.zcu)) { | 5957 | if (!ty.isRuntimeFloat() and !ty.isArrayOrVector(isel.pt.zcu)) { |
| 5928 | // integeral comparison | 5958 | // integeral comparison |
| 5929 | const int_info: std.builtin.Type.Int = if (ty.toIntern() == .bool_type) | 5959 | const int_info: std.builtin.Type.Int = if (ty.toIntern() == .bool_type) |
| ... | @@ -5996,7 +6026,7 @@ const AddOrSubtractOptions = struct { | ... | @@ -5996,7 +6026,7 @@ const AddOrSubtractOptions = struct { |
| 5996 | @"unreachable", | 6026 | @"unreachable", |
| 5997 | panic: Zcu.SimplePanicId, | 6027 | panic: Zcu.SimplePanicId, |
| 5998 | wrap, | 6028 | wrap, |
| 5999 | reg: Register, | 6029 | overflow_ra: Register.Alias, |
| 6000 | }; | 6030 | }; |
| 6001 | }; | 6031 | }; |
| 6002 | | 6032 | |
| ... | @@ -6011,11 +6041,25 @@ fn addOrSubtract( | ... | @@ -6011,11 +6041,25 @@ fn addOrSubtract( |
| 6011 | opts: AddOrSubtractOptions, | 6041 | opts: AddOrSubtractOptions, |
| 6012 | ) !void { | 6042 | ) !void { |
| 6013 | wip_mir_log.debug(" | # {t} ty = {f}, res = {f}, lhs = {f}, rhs = {f}, overflow = {t}", .{ op, isel.fmtType(ty), res_vi, lhs_vi, rhs_vi, opts.overflow }); | 6043 | wip_mir_log.debug(" | # {t} ty = {f}, res = {f}, lhs = {f}, rhs = {f}, overflow = {t}", .{ op, isel.fmtType(ty), res_vi, lhs_vi, rhs_vi, opts.overflow }); |
| 6014 | // TODO: implement opts.overflow | | |
| 6015 | const zcu = isel.pt.zcu; | 6044 | const zcu = isel.pt.zcu; |
| 6016 | assert(ty.isAbiInt(zcu)); | 6045 | assert(ty.isAbiInt(zcu)); |
| 6017 | const int_info = ty.intInfo(zcu); | 6046 | const int_info = ty.intInfo(zcu); |
| 6018 | | 6047 | |
| | 6048 | switch (opts.overflow) { |
| | 6049 | .wrap, .@"unreachable" => {}, |
| | 6050 | .overflow_ra => |overflow_ra| { |
| | 6051 | const overflow_reg = if (overflow_ra.mod == .integer) overflow_ra.reg else try isel.allocRegForWrite(.int); |
| | 6052 | defer if (overflow_ra.mod != .integer) isel.freeReg(overflow_reg); |
| | 6053 | switch (op) { |
| | 6054 | .add => try isel.cmp(overflow_reg, ty, res_vi, .lt, lhs_vi), |
| | 6055 | .sub => try isel.cmp(overflow_reg, ty, res_vi, .gt, lhs_vi), |
| | 6056 | } |
| | 6057 | }, |
| | 6058 | .panic => { |
| | 6059 | try isel.failUnimplemented("unimplemented {t} with {t}", .{ op, opts.overflow }); |
| | 6060 | }, |
| | 6061 | } |
| | 6062 | |
| 6019 | if (int_info.bits <= 32) { | 6063 | if (int_info.bits <= 32) { |
| 6020 | try res_vi.reextendToGarbage(isel); // TODO optimize | 6064 | try res_vi.reextendToGarbage(isel); // TODO optimize |
| 6021 | const res_reg = try res_vi.defRegMod(isel, .integer) orelse return; | 6065 | const res_reg = try res_vi.defRegMod(isel, .integer) orelse return; |
| ... | @@ -6426,6 +6470,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini | ... | @@ -6426,6 +6470,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini |
| 6426 | .reloc = .{ | 6470 | .reloc = .{ |
| 6427 | .label = @intCast(isel.instructions.items.len), | 6471 | .label = @intCast(isel.instructions.items.len), |
| 6428 | .addend = @intCast(ptr.byte_offset), | 6472 | .addend = @intCast(ptr.byte_offset), |
| | 6473 | .type = .PCALA_LO12, |
| 6429 | }, | 6474 | }, |
| 6430 | }); | 6475 | }); |
| 6431 | try isel.emit(.@"addi.d"(rd, rd, 0)); | 6476 | try isel.emit(.@"addi.d"(rd, rd, 0)); |
| ... | @@ -6434,6 +6479,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini | ... | @@ -6434,6 +6479,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini |
| 6434 | .reloc = .{ | 6479 | .reloc = .{ |
| 6435 | .label = @intCast(isel.instructions.items.len), | 6480 | .label = @intCast(isel.instructions.items.len), |
| 6436 | .addend = @intCast(ptr.byte_offset), | 6481 | .addend = @intCast(ptr.byte_offset), |
| | 6482 | .type = .PCALA_HI20, |
| 6437 | }, | 6483 | }, |
| 6438 | }); | 6484 | }); |
| 6439 | try isel.emit(.pcalau12i(rd, 0)); | 6485 | try isel.emit(.pcalau12i(rd, 0)); |
| ... | @@ -6448,6 +6494,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini | ... | @@ -6448,6 +6494,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini |
| 6448 | .reloc = .{ | 6494 | .reloc = .{ |
| 6449 | .label = @intCast(isel.instructions.items.len), | 6495 | .label = @intCast(isel.instructions.items.len), |
| 6450 | .addend = @intCast(ptr.byte_offset), | 6496 | .addend = @intCast(ptr.byte_offset), |
| | 6497 | .type = .PCALA_LO12, |
| 6451 | }, | 6498 | }, |
| 6452 | }); | 6499 | }); |
| 6453 | try isel.emit(.@"addi.d"(rd, rd, 0)); | 6500 | try isel.emit(.@"addi.d"(rd, rd, 0)); |
| ... | @@ -6456,6 +6503,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini | ... | @@ -6456,6 +6503,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini |
| 6456 | .reloc = .{ | 6503 | .reloc = .{ |
| 6457 | .label = @intCast(isel.instructions.items.len), | 6504 | .label = @intCast(isel.instructions.items.len), |
| 6458 | .addend = @intCast(ptr.byte_offset), | 6505 | .addend = @intCast(ptr.byte_offset), |
| | 6506 | .type = .PCALA_HI20, |
| 6459 | }, | 6507 | }, |
| 6460 | }); | 6508 | }); |
| 6461 | try isel.emit(.pcalau12i(rd, 0)); | 6509 | try isel.emit(.pcalau12i(rd, 0)); |
| ... | @@ -6711,15 +6759,12 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini | ... | @@ -6711,15 +6759,12 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini |
| 6711 | // load constant pointer | 6759 | // load constant pointer |
| 6712 | try isel.uav_relocs.append(zcu.gpa, .{ | 6760 | try isel.uav_relocs.append(zcu.gpa, .{ |
| 6713 | .uav = uav, | 6761 | .uav = uav, |
| 6714 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = 0 }, | 6762 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .PCALA_LO12 }, |
| 6715 | }); | 6763 | }); |
| 6716 | try isel.emit(.@"addi.d"(tmp_reg, tmp_reg, 0)); | 6764 | try isel.emit(.@"addi.d"(tmp_reg, tmp_reg, 0)); |
| 6717 | try isel.uav_relocs.append(zcu.gpa, .{ | 6765 | try isel.uav_relocs.append(zcu.gpa, .{ |
| 6718 | .uav = uav, | 6766 | .uav = uav, |
| 6719 | .reloc = .{ | 6767 | .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .PCALA_HI20 }, |
| 6720 | .label = @intCast(isel.instructions.items.len), | | |
| 6721 | .addend = 0, | | |
| 6722 | }, | | |
| 6723 | }); | 6768 | }); |
| 6724 | try isel.emit(.pcalau12i(tmp_reg, 0)); | 6769 | try isel.emit(.pcalau12i(tmp_reg, 0)); |
| 6725 | | 6770 | |
| ... | @@ -6901,6 +6946,7 @@ pub const CallAbiIterator = struct { | ... | @@ -6901,6 +6946,7 @@ pub const CallAbiIterator = struct { |
| 6901 | }, | 6946 | }, |
| 6902 | .simple_type => |simple_type| switch (simple_type) { | 6947 | .simple_type => |simple_type| switch (simple_type) { |
| 6903 | .f80 => continue :type_key .{ .int_type = .{ .signedness = .unsigned, .bits = 80 } }, | 6948 | .f80 => continue :type_key .{ .int_type = .{ .signedness = .unsigned, .bits = 80 } }, |
| | 6949 | .f128 => continue :type_key .{ .int_type = .{ .signedness = .unsigned, .bits = 128 } }, |
| 6904 | .usize, | 6950 | .usize, |
| 6905 | .isize, | 6951 | .isize, |
| 6906 | .c_char, | 6952 | .c_char, |
| ... | @@ -6918,7 +6964,22 @@ pub const CallAbiIterator = struct { | ... | @@ -6918,7 +6964,22 @@ pub const CallAbiIterator = struct { |
| 6918 | .signedness = .unsigned, | 6964 | .signedness = .unsigned, |
| 6919 | .bits = zcu.errorSetBits(), | 6965 | .bits = zcu.errorSetBits(), |
| 6920 | } }, | 6966 | } }, |
| 6921 | .f16, .f32, .f64, .f128, .c_longdouble => return isel.fail("CallAbiIterator.resolve({t})", .{simple_type}), | 6967 | .f16, .f32, .f64 => { |
| | 6968 | const bits = ty.floatBits(isel.target); |
| | 6969 | if (isel.canUseFprForFloat(bits)) { |
| | 6970 | if (it.allocReg(.fpr)) |reg| { |
| | 6971 | wip_vi.setHintRegister(isel, reg); |
| | 6972 | if (bits != 16) { |
| | 6973 | wip_vi.setHintModifier(isel, .fromFloatBits(bits)); |
| | 6974 | } else { |
| | 6975 | wip_vi.setHintModifier(isel, .floating32); |
| | 6976 | } |
| | 6977 | } else it.assignStack(wip_vi); |
| | 6978 | } else { |
| | 6979 | continue :type_key .{ .int_type = .{ .signedness = .unsigned, .bits = bits } }; |
| | 6980 | } |
| | 6981 | }, |
| | 6982 | .c_longdouble => return isel.fail("CallAbiIterator.resolve({t})", .{simple_type}), |
| 6922 | else => return isel.fail("CallAbiIterator.resolve({t})", .{simple_type}), | 6983 | else => return isel.fail("CallAbiIterator.resolve({t})", .{simple_type}), |
| 6923 | }, | 6984 | }, |
| 6924 | .struct_type => { | 6985 | .struct_type => { |
| ... | @@ -7217,6 +7278,32 @@ fn gprAlignment(isel: *Select) std.mem.Alignment { | ... | @@ -7217,6 +7278,32 @@ fn gprAlignment(isel: *Select) std.mem.Alignment { |
| 7217 | }; | 7278 | }; |
| 7218 | } | 7279 | } |
| 7219 | | 7280 | |
| | 7281 | fn fprBits(isel: *Select) u7 { |
| | 7282 | const cpu = &isel.target.cpu; |
| | 7283 | if (cpu.has(.loongarch, .d)) { |
| | 7284 | return 64; |
| | 7285 | } else if (cpu.has(.loongarch, .f)) { |
| | 7286 | return 32; |
| | 7287 | } else { |
| | 7288 | return 0; |
| | 7289 | } |
| | 7290 | } |
| | 7291 | |
| | 7292 | fn vectorBits(isel: *Select) u7 { |
| | 7293 | const cpu = &isel.target.cpu; |
| | 7294 | if (cpu.has(.loongarch, .lasx)) { |
| | 7295 | return 256; |
| | 7296 | } else if (cpu.has(.loongarch, .lsx)) { |
| | 7297 | return 128; |
| | 7298 | } else { |
| | 7299 | return isel.fprBits(); |
| | 7300 | } |
| | 7301 | } |
| | 7302 | |
| | 7303 | fn canUseFprForFloat(isel: *Select, bits: u16) bool { |
| | 7304 | return bits <= isel.fprBits(); |
| | 7305 | } |
| | 7306 | |
| 7220 | fn typeOfField(isel: *Select, ty: ZigType, offset: u64) ?ZigType { | 7307 | fn typeOfField(isel: *Select, ty: ZigType, offset: u64) ?ZigType { |
| 7221 | const zcu = isel.pt.zcu; | 7308 | const zcu = isel.pt.zcu; |
| 7222 | const ip = &zcu.intern_pool; | 7309 | const ip = &zcu.intern_pool; |