authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-09-01 10:37:50+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-09-01 10:37:50+02:00
log0a2af0b09a435e95f07fb4624ed1ee1025761a4e
treed9fac4ef1eab54ee00c2632782e22232bd93d50b
parent67f39b551d457478f4c18d6709a04037ce168c75
parent9b9c1d8fe138bad6ecec5a32a180225b0c0c4826

Merge pull request 'loongarch: minor backend improvements' (#36701) from AstraFall/zig:loongarch/pr into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36701 Reviewed-by: Alex Rønne Petersen <alex@alexrp.com>

3 files changed, 133 insertions(+), 114 deletions(-)

src/codegen/loongarch/Mir.zig+21-89
......@@ -13,7 +13,8 @@ internal_relocs: []const Reloc.Internal,
1313
1414pub const Reloc = struct {
1515 label: u32,
16 addend: i64 align(@alignOf(u32)) = 0,
16 type: std.elf.R_LARCH,
17 addend: i64 = 0,
1718
1819 pub const Nav = struct {
1920 nav: InternPool.Nav.Index,
......@@ -35,14 +36,10 @@ pub const Reloc = struct {
3536 reloc: Reloc,
3637 };
3738
38 pub const Literal = struct {
39 label: u32,
40 };
41
4239 pub const Internal = struct {
4340 // Target MIR index
4441 target: usize = 0,
45 label: u32,
42 reloc: Reloc,
4643 };
4744};
4845
......@@ -91,7 +88,7 @@ pub fn emit(
9188 pt,
9289 nav_reloc.nav,
9390 ),
94 mir.body[nav_reloc.reloc.label],
91 nav_reloc.reloc.type,
9592 body_end - @sizeOf(Instruction) * (1 + nav_reloc.reloc.label),
9693 nav_reloc.reloc.addend,
9794 ) catch |err|
......@@ -105,7 +102,7 @@ pub fn emit(
105102 uav_reloc.uav.val,
106103 ZigType.fromInterned(uav_reloc.uav.orig_ty).ptrAlignment(zcu),
107104 ),
108 mir.body[uav_reloc.reloc.label],
105 uav_reloc.reloc.type,
109106 body_end - @sizeOf(Instruction) * (1 + uav_reloc.reloc.label),
110107 uav_reloc.reloc.addend,
111108 ) catch |err|
......@@ -122,7 +119,7 @@ pub fn emit(
122119 return zcu.codegenFail(func.owner_nav, "emit lazy symbol: {t}", .{err})
123120 else
124121 return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}),
125 mir.body[lazy_reloc.reloc.label],
122 lazy_reloc.reloc.type,
126123 body_end - @sizeOf(Instruction) * (1 + lazy_reloc.reloc.label),
127124 lazy_reloc.reloc.addend,
128125 ) catch |err|
......@@ -139,7 +136,7 @@ pub fn emit(
139136 .type = .FUNC,
140137 }) catch |err|
141138 return zcu.codegenFail(func.owner_nav, "emit global symbol failed: {t}", .{err}) else return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}),
142 mir.body[global_reloc.reloc.label],
139 global_reloc.reloc.type,
143140 body_end - @sizeOf(Instruction) * (1 + global_reloc.reloc.label),
144141 global_reloc.reloc.addend,
145142 ) catch |err|
......@@ -155,8 +152,8 @@ pub fn emit(
155152 zcu,
156153 atom_index,
157154 func_nav,
158 mir.body[internal_reloc.label],
159 body_end - @sizeOf(Instruction) * (1 + internal_reloc.label),
155 internal_reloc.reloc.type,
156 body_end - @sizeOf(Instruction) * (1 + internal_reloc.reloc.label),
160157 @sizeOf(Instruction) * (@as(i64, @intCast(mir.prologue.len + mir.body.len - internal_reloc.target))),
161158 ) catch |err|
162159 return zcu.codegenFail(func.owner_nav, "emit reloc failed: {t}", .{err});
......@@ -182,86 +179,21 @@ fn emitReloc(
182179 zcu: *Zcu,
183180 atom_index: link.File.AtomId,
184181 sym_index: link.File.SymbolId,
185 instruction: Instruction,
182 reloc_type: std.elf.R_LARCH,
186183 offset: u32,
187184 addend: i64,
188185) !void {
189 const mnemonic = Disassemble.decodeMnemonic(instruction) orelse {
190 mir_log.debug("cannot decode instruction 0x{x}", .{instruction.word});
191 unreachable;
192 };
193 switch (mnemonic) {
194 else => {
195 mir_log.debug("unimplemented reloc on {t}", .{mnemonic});
196 unreachable;
197 },
198 .pcaddu18i => if (lf.cast(.elf2)) |ef| {
199 try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .CALL36 });
200 } else if (lf.cast(.elf)) |ef| {
201 const zo = ef.zigObjectPtr().?;
202 const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?;
203 try atom.addReloc(zcu.gpa, .{
204 .r_offset = offset,
205 .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.CALL36),
206 .r_addend = @bitCast(addend),
207 }, zo);
208 } else unreachable,
209 .b, .bl => if (lf.cast(.elf2)) |ef| {
210 try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .B26 });
211 } else if (lf.cast(.elf)) |ef| {
212 const zo = ef.zigObjectPtr().?;
213 const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?;
214 try atom.addReloc(zcu.gpa, .{
215 .r_offset = offset,
216 .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.B26),
217 .r_addend = @bitCast(addend),
218 }, zo);
219 } else unreachable,
220 .beq, .bne, .ble, .bgt, .bleu, .bgtu => if (lf.cast(.elf2)) |ef| {
221 try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .B16 });
222 } else if (lf.cast(.elf)) |ef| {
223 const zo = ef.zigObjectPtr().?;
224 const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?;
225 try atom.addReloc(zcu.gpa, .{
226 .r_offset = offset,
227 .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.B16),
228 .r_addend = @bitCast(addend),
229 }, zo);
230 } else unreachable,
231 .beqz, .bnez, .bceqz, .bcnez => if (lf.cast(.elf2)) |ef| {
232 try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .B21 });
233 } else if (lf.cast(.elf)) |ef| {
234 const zo = ef.zigObjectPtr().?;
235 const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?;
236 try atom.addReloc(zcu.gpa, .{
237 .r_offset = offset,
238 .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.B21),
239 .r_addend = @bitCast(addend),
240 }, zo);
241 } else unreachable,
242 .pcalau12i => if (lf.cast(.elf2)) |ef| {
243 try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .PCALA_HI20 });
244 } else if (lf.cast(.elf)) |ef| {
245 const zo = ef.zigObjectPtr().?;
246 const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?;
247 try atom.addReloc(zcu.gpa, .{
248 .r_offset = offset,
249 .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.PCALA_HI20),
250 .r_addend = @bitCast(addend),
251 }, zo);
252 } else unreachable,
253 .@"addi.d" => if (lf.cast(.elf2)) |ef| {
254 try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .PCALA_LO12 });
255 } else if (lf.cast(.elf)) |ef| {
256 const zo = ef.zigObjectPtr().?;
257 const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?;
258 try atom.addReloc(zcu.gpa, .{
259 .r_offset = offset,
260 .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.PCALA_LO12),
261 .r_addend = @bitCast(addend),
262 }, zo);
263 } else unreachable,
264 }
186 if (lf.cast(.elf2)) |ef| {
187 try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = reloc_type });
188 } else if (lf.cast(.elf)) |ef| {
189 const zo = ef.zigObjectPtr().?;
190 const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?;
191 try atom.addReloc(zcu.gpa, .{
192 .r_offset = offset,
193 .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(reloc_type),
194 .r_addend = @bitCast(addend),
195 }, zo);
196 } else unreachable;
265197}
266198
267199const Air = @import("../../Air.zig");
src/codegen/loongarch/Select.zig+111-24
......@@ -101,8 +101,8 @@ pub const Block = struct {
101101 fn branch(target_block: *Block, isel: *Select) !void {
102102 if (isel.instructions.items.len > target_block.target_label) {
103103 try isel.internal_relocs.append(isel.pt.zcu.gpa, .{
104 .label = @intCast(isel.instructions.items.len),
105104 .target = target_block.target_label,
105 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 },
106106 });
107107 try isel.emit(.b(0, 0));
108108 }
......@@ -1026,7 +1026,7 @@ pub const Value = struct {
10261026 }
10271027
10281028 /// Defines a value with a register.
1029 /// Returned registers are free-ed.
1029 /// Returned registers are free-ed and marked as written.
10301030 /// Extension unchanged.
10311031 fn defReg(vi: Value.Index, isel: *Select) !?Register.Alias {
10321032 const value = vi.get(isel);
......@@ -1449,6 +1449,7 @@ pub const Value = struct {
14491449 .reloc = .{
14501450 .label = @intCast(isel.instructions.items.len),
14511451 .addend = @intCast(total_root_offset),
1452 .type = .PCALA_LO12,
14521453 },
14531454 });
14541455 try isel.emit(.@"addi.d"(ptr_reg, ptr_reg, 0));
......@@ -1460,6 +1461,7 @@ pub const Value = struct {
14601461 .reloc = .{
14611462 .label = @intCast(isel.instructions.items.len),
14621463 .addend = @intCast(total_root_offset),
1464 .type = .PCALA_HI20,
14631465 },
14641466 });
14651467 try isel.emit(.pcalau12i(ptr_reg, 0));
......@@ -2590,6 +2592,7 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
25902592 .is_named_enum_value,
25912593 .tag_name,
25922594 .error_name,
2595 .cmp_lte_errors_len,
25932596 => {
25942597 const un_op = air_data[@backingInt(air_inst_index)].un_op;
25952598
......@@ -3163,8 +3166,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
31633166 const next_repeat_label = instruction.*;
31643167 instruction.* = .b(0, 0);
31653168 try isel.internal_relocs.append(gpa, .{
3166 .label = repeat_label,
31673169 .target = isel.instructions.items.len,
3170 .reloc = .{ .label = repeat_label, .type = .B26 },
31683171 });
31693172 repeat_label = @bitCast(next_repeat_label);
31703173 }
......@@ -3196,8 +3199,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
31963199 .extension = .zero_ext,
31973200 });
31983201 try isel.internal_relocs.append(gpa, .{
3199 .label = @intCast(isel.instructions.items.len),
32003202 .target = else_label,
3203 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 },
32013204 });
32023205 try isel.emit(.beqz(cond_mat.reg(), 0, 0));
32033206 try cond_mat.finish(isel);
......@@ -3240,8 +3243,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
32403243 });
32413244
32423245 try isel.internal_relocs.append(gpa, .{
3243 .label = @intCast(isel.instructions.items.len),
32443246 .target = next_label,
3247 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 },
32453248 });
32463249 try isel.emit(.b(0, 0));
32473250
......@@ -3267,8 +3270,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
32673270 defer isel.freeReg(item_reg);
32683271
32693272 try isel.internal_relocs.append(gpa, .{
3270 .label = @intCast(isel.instructions.items.len),
32713273 .target = case_label,
3274 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B16 },
32723275 });
32733276 try isel.emit(.beq(cond_mat.reg(), item_reg, 0));
32743277 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,
33223325 else => unreachable,
33233326 inline .@"extern", .func => |func| .{
33243327 .nav = func.owner_nav,
3325 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
3328 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .CALL36 },
33263329 },
33273330 .ptr => |ptr| .{
33283331 .nav = ptr.base_addr.nav,
33293332 .reloc = .{
33303333 .label = @intCast(isel.instructions.items.len),
33313334 .addend = @intCast(ptr.byte_offset),
3335 .type = .CALL36,
33323336 },
33333337 },
33343338 });
......@@ -3573,6 +3577,26 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
35733577 },
35743578 }) else return isel.fail("unimplemented float", .{});
35753579 },
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 },
35763600 .not => if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
35773601 defer res_vi.value.deref(isel);
35783602
......@@ -3676,7 +3700,10 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
36763700 try rhs_mat.finish(isel);
36773701 try lhs_mat.finish(isel);
36783702 },
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 },
36803707 }
36813708 } else try isel.failUnimplemented("unimplemented float div", .{});
36823709 },
......@@ -3734,12 +3761,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
37343761 } else if (dst_tag == .float and src_tag == .float) {
37353762 assert(dst_ty.floatBits(isel.target) == src_ty.floatBits(isel.target));
37363763 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))) {
37383765 const dst_int_info = dst_ty.intInfo(zcu);
37393766 assert(dst_int_info.bits == src_ty.floatBits(isel.target));
37403767
37413768 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;
37433770 const src_vi = try isel.use(ty_op.operand);
37443771 const src_mat = try src_vi.matReg(isel);
37453772 const src_reg = src_mat.reg();
......@@ -3749,12 +3776,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
37493776 64 => .@"movfr2gr.d"(dst_reg, src_reg),
37503777 });
37513778 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))) {
37533780 const src_int_info = src_ty.intInfo(zcu);
37543781 assert(dst_ty.floatBits(isel.target) == src_int_info.bits);
37553782
37563783 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;
37583785 const src_vi = try isel.use(ty_op.operand);
37593786 const src_mat = try src_vi.matReg(isel);
37603787 const src_reg = src_mat.reg();
......@@ -3896,13 +3923,13 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
38963923 .extension = .zero_ext,
38973924 });
38983925 try isel.internal_relocs.append(gpa, .{
3899 .label = @intCast(isel.instructions.items.len),
39003926 .target = cmp_label,
3927 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 },
39013928 });
39023929 try isel.emit(.beqz(lhs_tag_mat.reg(), 0, 0));
39033930 try isel.internal_relocs.append(gpa, .{
3904 .label = @intCast(isel.instructions.items.len),
39053931 .target = cmp_label,
3932 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 },
39063933 });
39073934 try isel.emit(.beqz(res_reg, 0, 0));
39083935
......@@ -4250,8 +4277,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
42504277 );
42514278 const error_set_part_mat = try error_set_part_vi.matIntRegZeroExt(isel);
42524279 try isel.internal_relocs.append(gpa, .{
4253 .label = @intCast(isel.instructions.items.len),
42544280 .target = cont_label,
4281 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 },
42554282 });
42564283 try isel.emit(.beqz(error_set_part_mat.reg(), 0, 0));
42574284 try error_set_part_mat.finish(isel);
......@@ -4288,8 +4315,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
42884315 defer isel.freeReg(tmp_reg);
42894316
42904317 try isel.internal_relocs.append(gpa, .{
4291 .label = @intCast(isel.instructions.items.len),
42924318 .target = cont_label,
4319 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 },
42934320 });
42944321 try isel.emit(.beqz(tmp_reg, 0, 0));
42954322
......@@ -5924,6 +5951,9 @@ fn cmp(
59245951 rhs_vi: Value.Index,
59255952) !void {
59265953 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
59275957 if (!ty.isRuntimeFloat() and !ty.isArrayOrVector(isel.pt.zcu)) {
59285958 // integeral comparison
59295959 const int_info: std.builtin.Type.Int = if (ty.toIntern() == .bool_type)
......@@ -5996,7 +6026,7 @@ const AddOrSubtractOptions = struct {
59966026 @"unreachable",
59976027 panic: Zcu.SimplePanicId,
59986028 wrap,
5999 reg: Register,
6029 overflow_ra: Register.Alias,
60006030 };
60016031};
60026032
......@@ -6011,11 +6041,25 @@ fn addOrSubtract(
60116041 opts: AddOrSubtractOptions,
60126042) !void {
60136043 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
60156044 const zcu = isel.pt.zcu;
60166045 assert(ty.isAbiInt(zcu));
60176046 const int_info = ty.intInfo(zcu);
60186047
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
60196063 if (int_info.bits <= 32) {
60206064 try res_vi.reextendToGarbage(isel); // TODO optimize
60216065 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
64266470 .reloc = .{
64276471 .label = @intCast(isel.instructions.items.len),
64286472 .addend = @intCast(ptr.byte_offset),
6473 .type = .PCALA_LO12,
64296474 },
64306475 });
64316476 try isel.emit(.@"addi.d"(rd, rd, 0));
......@@ -6434,6 +6479,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini
64346479 .reloc = .{
64356480 .label = @intCast(isel.instructions.items.len),
64366481 .addend = @intCast(ptr.byte_offset),
6482 .type = .PCALA_HI20,
64376483 },
64386484 });
64396485 try isel.emit(.pcalau12i(rd, 0));
......@@ -6448,6 +6494,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini
64486494 .reloc = .{
64496495 .label = @intCast(isel.instructions.items.len),
64506496 .addend = @intCast(ptr.byte_offset),
6497 .type = .PCALA_LO12,
64516498 },
64526499 });
64536500 try isel.emit(.@"addi.d"(rd, rd, 0));
......@@ -6456,6 +6503,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini
64566503 .reloc = .{
64576504 .label = @intCast(isel.instructions.items.len),
64586505 .addend = @intCast(ptr.byte_offset),
6506 .type = .PCALA_HI20,
64596507 },
64606508 });
64616509 try isel.emit(.pcalau12i(rd, 0));
......@@ -6711,15 +6759,12 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini
67116759 // load constant pointer
67126760 try isel.uav_relocs.append(zcu.gpa, .{
67136761 .uav = uav,
6714 .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = 0 },
6762 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .PCALA_LO12 },
67156763 });
67166764 try isel.emit(.@"addi.d"(tmp_reg, tmp_reg, 0));
67176765 try isel.uav_relocs.append(zcu.gpa, .{
67186766 .uav = uav,
6719 .reloc = .{
6720 .label = @intCast(isel.instructions.items.len),
6721 .addend = 0,
6722 },
6767 .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .PCALA_HI20 },
67236768 });
67246769 try isel.emit(.pcalau12i(tmp_reg, 0));
67256770
......@@ -6901,6 +6946,7 @@ pub const CallAbiIterator = struct {
69016946 },
69026947 .simple_type => |simple_type| switch (simple_type) {
69036948 .f80 => continue :type_key .{ .int_type = .{ .signedness = .unsigned, .bits = 80 } },
6949 .f128 => continue :type_key .{ .int_type = .{ .signedness = .unsigned, .bits = 128 } },
69046950 .usize,
69056951 .isize,
69066952 .c_char,
......@@ -6918,7 +6964,22 @@ pub const CallAbiIterator = struct {
69186964 .signedness = .unsigned,
69196965 .bits = zcu.errorSetBits(),
69206966 } },
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}),
69226983 else => return isel.fail("CallAbiIterator.resolve({t})", .{simple_type}),
69236984 },
69246985 .struct_type => {
......@@ -7217,6 +7278,32 @@ fn gprAlignment(isel: *Select) std.mem.Alignment {
72177278 };
72187279}
72197280
7281fn 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
7292fn 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
7303fn canUseFprForFloat(isel: *Select, bits: u16) bool {
7304 return bits <= isel.fprBits();
7305}
7306
72207307fn typeOfField(isel: *Select, ty: ZigType, offset: u64) ?ZigType {
72217308 const zcu = isel.pt.zcu;
72227309 const ip = &zcu.intern_pool;
src/codegen/loongarch/bits.zig+1-1
......@@ -85,7 +85,7 @@ pub const Register = enum(u7) {
8585 };
8686 }
8787
88 pub fn fromFloating(bits: u16) Modifier {
88 pub fn fromFloatBits(bits: u16) Modifier {
8989 return switch (bits) {
9090 else => unreachable,
9191 32 => .floating32,