From efea52deb7b9ced2ce0b16169bd01bc563aab5b4 Mon Sep 17 00:00:00 2001 From: xtex Date: Sun, 30 Aug 2026 19:37:38 +0800 Subject: [PATCH 1/6] loongarch: implement add/sub with overflow --- src/codegen/loongarch/Select.zig | 45 +++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/src/codegen/loongarch/Select.zig b/src/codegen/loongarch/Select.zig index cc924320b4b82dc78de6fe38ca8b90bc7d17f045..fccd7d66eedb579f9646403158d926fe6339adf8 100644 --- a/src/codegen/loongarch/Select.zig +++ b/src/codegen/loongarch/Select.zig @@ -1026,7 +1026,7 @@ pub const Value = struct { } /// Defines a value with a register. - /// Returned registers are free-ed. + /// Returned registers are free-ed and marked as written. /// Extension unchanged. fn defReg(vi: Value.Index, isel: *Select) !?Register.Alias { const value = vi.get(isel); @@ -3573,6 +3573,26 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, }, }) else return isel.fail("unimplemented float", .{}); }, + .add_with_overflow, .sub_with_overflow => if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| { + defer res_vi.value.deref(isel); + + const ty_pl = air.data(air.inst_index).ty_pl; + const bin_op = isel.air.extraData(Air.Bin, ty_pl.payload).data; + const ty = isel.air.typeOf(bin_op.lhs, ip); + const lhs_vi = try isel.use(bin_op.lhs); + const rhs_vi = try isel.use(bin_op.rhs); + const ty_size = lhs_vi.size(isel); + + const wrapped_vi = try res_vi.value.partExact(isel, 0, ty_size); + const overflow_vi = try res_vi.value.partExact(isel, ty_size, 1); + try isel.addOrSubtract(ty, wrapped_vi, switch (air_tag) { + else => unreachable, + .add_with_overflow => .add, + .sub_with_overflow => .sub, + }, lhs_vi, rhs_vi, .{ + .overflow = if (try overflow_vi.defReg(isel)) |overflow_ra| .{ .overflow_ra = overflow_ra } else .wrap, + }); + }, .not => if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: { defer res_vi.value.deref(isel); @@ -3676,7 +3696,10 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, try rhs_mat.finish(isel); try lhs_mat.finish(isel); }, - else => try isel.failUnimplemented("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }), + else => { + _ = try res_vi.value.def(isel); + try isel.failUnimplemented("too big {t} {f}", .{ air_tag, isel.fmtType(ty) }); + }, } } else try isel.failUnimplemented("unimplemented float div", .{}); }, @@ -5996,7 +6019,7 @@ const AddOrSubtractOptions = struct { @"unreachable", panic: Zcu.SimplePanicId, wrap, - reg: Register, + overflow_ra: Register.Alias, }; }; @@ -6011,11 +6034,25 @@ fn addOrSubtract( opts: AddOrSubtractOptions, ) !void { 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 }); - // TODO: implement opts.overflow const zcu = isel.pt.zcu; assert(ty.isAbiInt(zcu)); const int_info = ty.intInfo(zcu); + switch (opts.overflow) { + .wrap, .@"unreachable" => {}, + .overflow_ra => |overflow_ra| { + const overflow_reg = if (overflow_ra.mod == .integer) overflow_ra.reg else try isel.allocRegForWrite(.int); + defer if (overflow_ra.mod != .integer) isel.freeReg(overflow_reg); + switch (op) { + .add => try isel.cmp(overflow_reg, ty, res_vi, .lt, lhs_vi), + .sub => try isel.cmp(overflow_reg, ty, res_vi, .gt, lhs_vi), + } + }, + .panic => { + try isel.failUnimplemented("unimplemented {t} with {t}", .{ op, opts.overflow }); + }, + } + if (int_info.bits <= 32) { try res_vi.reextendToGarbage(isel); // TODO optimize const res_reg = try res_vi.defRegMod(isel, .integer) orelse return; -- 2.54.0 From 4814caef6fe3dd6c8a3cae31b7934ab4cedf2199 Mon Sep 17 00:00:00 2001 From: xtex Date: Sun, 30 Aug 2026 19:38:34 +0800 Subject: [PATCH 2/6] loongarch: implement analysis for cmp_lte_errors_len --- src/codegen/loongarch/Select.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/codegen/loongarch/Select.zig b/src/codegen/loongarch/Select.zig index fccd7d66eedb579f9646403158d926fe6339adf8..cb5ede9cceb7119eeb456ce59a774f9e493a7850 100644 --- a/src/codegen/loongarch/Select.zig +++ b/src/codegen/loongarch/Select.zig @@ -2590,6 +2590,7 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void { .is_named_enum_value, .tag_name, .error_name, + .cmp_lte_errors_len, => { const un_op = air_data[@backingInt(air_inst_index)].un_op; -- 2.54.0 From 14bac1ffcf044c01362776cceb9ff8d381285fd4 Mon Sep 17 00:00:00 2001 From: xtex Date: Sun, 30 Aug 2026 20:31:11 +0800 Subject: [PATCH 3/6] loongarch: protect result register in cmp --- src/codegen/loongarch/Select.zig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/codegen/loongarch/Select.zig b/src/codegen/loongarch/Select.zig index cb5ede9cceb7119eeb456ce59a774f9e493a7850..8caf7098b3a0fcab38431635037465f81f43300f 100644 --- a/src/codegen/loongarch/Select.zig +++ b/src/codegen/loongarch/Select.zig @@ -5948,6 +5948,9 @@ fn cmp( rhs_vi: Value.Index, ) !void { wip_mir_log.debug(" | # cmp {f}, {t}, {f}, {t}, {f}", .{ isel.fmtType(ty), res_reg, lhs_vi, op, rhs_vi }); + const res_lock = isel.tryLockReg(res_reg); + defer res_lock.unlock(isel); + if (!ty.isRuntimeFloat() and !ty.isArrayOrVector(isel.pt.zcu)) { // integeral comparison const int_info: std.builtin.Type.Int = if (ty.toIntern() == .bool_type) -- 2.54.0 From c772fef715c2faec422fb68b69b912780d68762e Mon Sep 17 00:00:00 2001 From: xtex Date: Sun, 30 Aug 2026 20:43:21 +0800 Subject: [PATCH 4/6] loongarch: use movfr2gr for bit_cast only if values are stored in FPR For f80 (and f64/f32 on platforms without FP support), values should be stored in GPRs or stacks. Therefore, movfr2gr and movgr2fr should not be used. --- src/codegen/loongarch/Select.zig | 34 ++++++++++++++++++++++++++++---- src/codegen/loongarch/bits.zig | 2 +- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/codegen/loongarch/Select.zig b/src/codegen/loongarch/Select.zig index 8caf7098b3a0fcab38431635037465f81f43300f..04197dc7c4f41d43a2f5ed408823eeda83b2ee33 100644 --- a/src/codegen/loongarch/Select.zig +++ b/src/codegen/loongarch/Select.zig @@ -3758,12 +3758,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, } else if (dst_tag == .float and src_tag == .float) { assert(dst_ty.floatBits(isel.target) == src_ty.floatBits(isel.target)); try dst_vi.value.defMove(isel, ty_op.operand); - } else if (dst_ty.isAbiInt(zcu) and src_tag == .float) { + } else if (dst_ty.isAbiInt(zcu) and src_tag == .float and isel.canUseFprForFloat(src_ty)) { const dst_int_info = dst_ty.intInfo(zcu); assert(dst_int_info.bits == src_ty.floatBits(isel.target)); try dst_vi.value.reextendToGarbage(isel); - const dst_reg = try dst_vi.value.defRegMod(isel, .fromFloating(dst_int_info.bits)) orelse break :unused; + const dst_reg = try dst_vi.value.defRegMod(isel, .fromFloatBits(dst_int_info.bits)) orelse break :unused; const src_vi = try isel.use(ty_op.operand); const src_mat = try src_vi.matReg(isel); const src_reg = src_mat.reg(); @@ -3773,12 +3773,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 64 => .@"movfr2gr.d"(dst_reg, src_reg), }); try src_mat.finish(isel); - } else if (dst_tag == .float and src_ty.isAbiInt(zcu)) { + } else if (dst_tag == .float and src_ty.isAbiInt(zcu) and isel.canUseFprForFloat(dst_ty)) { const src_int_info = src_ty.intInfo(zcu); assert(dst_ty.floatBits(isel.target) == src_int_info.bits); try dst_vi.value.reextendToGarbage(isel); - const dst_reg = try dst_vi.value.defRegMod(isel, .fromFloating(src_int_info.bits)) orelse break :unused; + const dst_reg = try dst_vi.value.defRegMod(isel, .fromFloatBits(src_int_info.bits)) orelse break :unused; const src_vi = try isel.use(ty_op.operand); const src_mat = try src_vi.matReg(isel); const src_reg = src_mat.reg(); @@ -7258,6 +7258,32 @@ fn gprAlignment(isel: *Select) std.mem.Alignment { }; } +fn fprBits(isel: *Select) u7 { + const cpu = &isel.target.cpu; + if (cpu.has(.loongarch, .d)) { + return 64; + } else if (cpu.has(.loongarch, .f)) { + return 32; + } else { + return 0; + } +} + +fn vectorBits(isel: *Select) u7 { + const cpu = &isel.target.cpu; + if (cpu.has(.loongarch, .lasx)) { + return 256; + } else if (cpu.has(.loongarch, .lsx)) { + return 128; + } else { + return isel.fprBits(); + } +} + +fn canUseFprForFloat(isel: *Select, ty: ZigType) bool { + return ty.floatBits(isel.target) <= isel.fprBits(); +} + fn typeOfField(isel: *Select, ty: ZigType, offset: u64) ?ZigType { const zcu = isel.pt.zcu; const ip = &zcu.intern_pool; diff --git a/src/codegen/loongarch/bits.zig b/src/codegen/loongarch/bits.zig index d60646f4b040ac698f02a24a9e393cb9ee7758cf..f6032f13087f59e38487409ee9e13df4180df9af 100644 --- a/src/codegen/loongarch/bits.zig +++ b/src/codegen/loongarch/bits.zig @@ -85,7 +85,7 @@ pub const Register = enum(u7) { }; } - pub fn fromFloating(bits: u16) Modifier { + pub fn fromFloatBits(bits: u16) Modifier { return switch (bits) { else => unreachable, 32 => .floating32, -- 2.54.0 From cca7c50b54bbf5d763da839582edff69bd9d051d Mon Sep 17 00:00:00 2001 From: xtex Date: Sun, 30 Aug 2026 21:15:42 +0800 Subject: [PATCH 5/6] loongarch: ABI resolve for f16/f32/f64/f128 --- src/codegen/loongarch/Select.zig | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/codegen/loongarch/Select.zig b/src/codegen/loongarch/Select.zig index 04197dc7c4f41d43a2f5ed408823eeda83b2ee33..1b1dd5a4b858d781c19461ffae00da265c6e77a0 100644 --- a/src/codegen/loongarch/Select.zig +++ b/src/codegen/loongarch/Select.zig @@ -3758,7 +3758,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, } else if (dst_tag == .float and src_tag == .float) { assert(dst_ty.floatBits(isel.target) == src_ty.floatBits(isel.target)); try dst_vi.value.defMove(isel, ty_op.operand); - } else if (dst_ty.isAbiInt(zcu) and src_tag == .float and isel.canUseFprForFloat(src_ty)) { + } else if (dst_ty.isAbiInt(zcu) and src_tag == .float and isel.canUseFprForFloat(src_ty.floatBits(isel.target))) { const dst_int_info = dst_ty.intInfo(zcu); assert(dst_int_info.bits == src_ty.floatBits(isel.target)); @@ -3773,7 +3773,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, 64 => .@"movfr2gr.d"(dst_reg, src_reg), }); try src_mat.finish(isel); - } else if (dst_tag == .float and src_ty.isAbiInt(zcu) and isel.canUseFprForFloat(dst_ty)) { + } else if (dst_tag == .float and src_ty.isAbiInt(zcu) and isel.canUseFprForFloat(dst_ty.floatBits(isel.target))) { const src_int_info = src_ty.intInfo(zcu); assert(dst_ty.floatBits(isel.target) == src_int_info.bits); @@ -6942,6 +6942,7 @@ pub const CallAbiIterator = struct { }, .simple_type => |simple_type| switch (simple_type) { .f80 => continue :type_key .{ .int_type = .{ .signedness = .unsigned, .bits = 80 } }, + .f128 => continue :type_key .{ .int_type = .{ .signedness = .unsigned, .bits = 128 } }, .usize, .isize, .c_char, @@ -6959,7 +6960,22 @@ pub const CallAbiIterator = struct { .signedness = .unsigned, .bits = zcu.errorSetBits(), } }, - .f16, .f32, .f64, .f128, .c_longdouble => return isel.fail("CallAbiIterator.resolve({t})", .{simple_type}), + .f16, .f32, .f64 => { + const bits = ty.floatBits(isel.target); + if (isel.canUseFprForFloat(bits)) { + if (it.allocReg(.fpr)) |reg| { + wip_vi.setHintRegister(isel, reg); + if (bits != 16) { + wip_vi.setHintModifier(isel, .fromFloatBits(bits)); + } else { + wip_vi.setHintModifier(isel, .floating32); + } + } else it.assignStack(wip_vi); + } else { + continue :type_key .{ .int_type = .{ .signedness = .unsigned, .bits = bits } }; + } + }, + .c_longdouble => return isel.fail("CallAbiIterator.resolve({t})", .{simple_type}), else => return isel.fail("CallAbiIterator.resolve({t})", .{simple_type}), }, .struct_type => { @@ -7280,8 +7296,8 @@ fn vectorBits(isel: *Select) u7 { } } -fn canUseFprForFloat(isel: *Select, ty: ZigType) bool { - return ty.floatBits(isel.target) <= isel.fprBits(); +fn canUseFprForFloat(isel: *Select, bits: u16) bool { + return bits <= isel.fprBits(); } fn typeOfField(isel: *Select, ty: ZigType, offset: u64) ?ZigType { -- 2.54.0 From 9b9c1d8fe138bad6ecec5a32a180225b0c0c4826 Mon Sep 17 00:00:00 2001 From: xtex Date: Sun, 30 Aug 2026 22:15:46 +0800 Subject: [PATCH 6/6] loongarch: specify relocation type on reloc creation Previously relocation types are determined based on the opcode of target instructions. However, more than one relocation types can be applied on one opcode, when it comes to, for example, TLS. Therefore, the type of relocations should be determined when a relocation is added to the list. --- src/codegen/loongarch/Mir.zig | 110 ++++++------------------------- src/codegen/loongarch/Select.zig | 34 +++++----- 2 files changed, 40 insertions(+), 104 deletions(-) diff --git a/src/codegen/loongarch/Mir.zig b/src/codegen/loongarch/Mir.zig index 44f6cfd3165cdeb04d2f0e063d214b5da34be361..f81843ff4e24ce3c395cd250844e1bed9bb368cb 100644 --- a/src/codegen/loongarch/Mir.zig +++ b/src/codegen/loongarch/Mir.zig @@ -13,7 +13,8 @@ internal_relocs: []const Reloc.Internal, pub const Reloc = struct { label: u32, - addend: i64 align(@alignOf(u32)) = 0, + type: std.elf.R_LARCH, + addend: i64 = 0, pub const Nav = struct { nav: InternPool.Nav.Index, @@ -35,14 +36,10 @@ pub const Reloc = struct { reloc: Reloc, }; - pub const Literal = struct { - label: u32, - }; - pub const Internal = struct { // Target MIR index target: usize = 0, - label: u32, + reloc: Reloc, }; }; @@ -91,7 +88,7 @@ pub fn emit( pt, nav_reloc.nav, ), - mir.body[nav_reloc.reloc.label], + nav_reloc.reloc.type, body_end - @sizeOf(Instruction) * (1 + nav_reloc.reloc.label), nav_reloc.reloc.addend, ) catch |err| @@ -105,7 +102,7 @@ pub fn emit( uav_reloc.uav.val, ZigType.fromInterned(uav_reloc.uav.orig_ty).ptrAlignment(zcu), ), - mir.body[uav_reloc.reloc.label], + uav_reloc.reloc.type, body_end - @sizeOf(Instruction) * (1 + uav_reloc.reloc.label), uav_reloc.reloc.addend, ) catch |err| @@ -122,7 +119,7 @@ pub fn emit( return zcu.codegenFail(func.owner_nav, "emit lazy symbol: {t}", .{err}) else return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}), - mir.body[lazy_reloc.reloc.label], + lazy_reloc.reloc.type, body_end - @sizeOf(Instruction) * (1 + lazy_reloc.reloc.label), lazy_reloc.reloc.addend, ) catch |err| @@ -139,7 +136,7 @@ pub fn emit( .type = .FUNC, }) catch |err| 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)}), - mir.body[global_reloc.reloc.label], + global_reloc.reloc.type, body_end - @sizeOf(Instruction) * (1 + global_reloc.reloc.label), global_reloc.reloc.addend, ) catch |err| @@ -155,8 +152,8 @@ pub fn emit( zcu, atom_index, func_nav, - mir.body[internal_reloc.label], - body_end - @sizeOf(Instruction) * (1 + internal_reloc.label), + internal_reloc.reloc.type, + body_end - @sizeOf(Instruction) * (1 + internal_reloc.reloc.label), @sizeOf(Instruction) * (@as(i64, @intCast(mir.prologue.len + mir.body.len - internal_reloc.target))), ) catch |err| return zcu.codegenFail(func.owner_nav, "emit reloc failed: {t}", .{err}); @@ -182,86 +179,21 @@ fn emitReloc( zcu: *Zcu, atom_index: link.File.AtomId, sym_index: link.File.SymbolId, - instruction: Instruction, + reloc_type: std.elf.R_LARCH, offset: u32, addend: i64, ) !void { - const mnemonic = Disassemble.decodeMnemonic(instruction) orelse { - mir_log.debug("cannot decode instruction 0x{x}", .{instruction.word}); - unreachable; - }; - switch (mnemonic) { - else => { - mir_log.debug("unimplemented reloc on {t}", .{mnemonic}); - unreachable; - }, - .pcaddu18i => if (lf.cast(.elf2)) |ef| { - try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .CALL36 }); - } else if (lf.cast(.elf)) |ef| { - const zo = ef.zigObjectPtr().?; - const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?; - try atom.addReloc(zcu.gpa, .{ - .r_offset = offset, - .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.CALL36), - .r_addend = @bitCast(addend), - }, zo); - } else unreachable, - .b, .bl => if (lf.cast(.elf2)) |ef| { - try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .B26 }); - } else if (lf.cast(.elf)) |ef| { - const zo = ef.zigObjectPtr().?; - const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?; - try atom.addReloc(zcu.gpa, .{ - .r_offset = offset, - .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.B26), - .r_addend = @bitCast(addend), - }, zo); - } else unreachable, - .beq, .bne, .ble, .bgt, .bleu, .bgtu => if (lf.cast(.elf2)) |ef| { - try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .B16 }); - } else if (lf.cast(.elf)) |ef| { - const zo = ef.zigObjectPtr().?; - const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?; - try atom.addReloc(zcu.gpa, .{ - .r_offset = offset, - .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.B16), - .r_addend = @bitCast(addend), - }, zo); - } else unreachable, - .beqz, .bnez, .bceqz, .bcnez => if (lf.cast(.elf2)) |ef| { - try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .B21 }); - } else if (lf.cast(.elf)) |ef| { - const zo = ef.zigObjectPtr().?; - const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?; - try atom.addReloc(zcu.gpa, .{ - .r_offset = offset, - .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.B21), - .r_addend = @bitCast(addend), - }, zo); - } else unreachable, - .pcalau12i => if (lf.cast(.elf2)) |ef| { - try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .PCALA_HI20 }); - } else if (lf.cast(.elf)) |ef| { - const zo = ef.zigObjectPtr().?; - const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?; - try atom.addReloc(zcu.gpa, .{ - .r_offset = offset, - .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.PCALA_HI20), - .r_addend = @bitCast(addend), - }, zo); - } else unreachable, - .@"addi.d" => if (lf.cast(.elf2)) |ef| { - try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = .PCALA_LO12 }); - } else if (lf.cast(.elf)) |ef| { - const zo = ef.zigObjectPtr().?; - const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?; - try atom.addReloc(zcu.gpa, .{ - .r_offset = offset, - .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(std.elf.R_LARCH.PCALA_LO12), - .r_addend = @bitCast(addend), - }, zo); - } else unreachable, - } + if (lf.cast(.elf2)) |ef| { + try ef.addReloc(atom_index, offset, sym_index, addend, .{ .LARCH = reloc_type }); + } else if (lf.cast(.elf)) |ef| { + const zo = ef.zigObjectPtr().?; + const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?; + try atom.addReloc(zcu.gpa, .{ + .r_offset = offset, + .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(reloc_type), + .r_addend = @bitCast(addend), + }, zo); + } else unreachable; } const Air = @import("../../Air.zig"); diff --git a/src/codegen/loongarch/Select.zig b/src/codegen/loongarch/Select.zig index 1b1dd5a4b858d781c19461ffae00da265c6e77a0..ba97c62105485c98a9044dd6c9a75c332c4e933e 100644 --- a/src/codegen/loongarch/Select.zig +++ b/src/codegen/loongarch/Select.zig @@ -101,8 +101,8 @@ pub const Block = struct { fn branch(target_block: *Block, isel: *Select) !void { if (isel.instructions.items.len > target_block.target_label) { try isel.internal_relocs.append(isel.pt.zcu.gpa, .{ - .label = @intCast(isel.instructions.items.len), .target = target_block.target_label, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 }, }); try isel.emit(.b(0, 0)); } @@ -1449,6 +1449,7 @@ pub const Value = struct { .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = @intCast(total_root_offset), + .type = .PCALA_LO12, }, }); try isel.emit(.@"addi.d"(ptr_reg, ptr_reg, 0)); @@ -1460,6 +1461,7 @@ pub const Value = struct { .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = @intCast(total_root_offset), + .type = .PCALA_HI20, }, }); try isel.emit(.pcalau12i(ptr_reg, 0)); @@ -3164,8 +3166,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, const next_repeat_label = instruction.*; instruction.* = .b(0, 0); try isel.internal_relocs.append(gpa, .{ - .label = repeat_label, .target = isel.instructions.items.len, + .reloc = .{ .label = repeat_label, .type = .B26 }, }); repeat_label = @bitCast(next_repeat_label); } @@ -3197,8 +3199,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, .extension = .zero_ext, }); try isel.internal_relocs.append(gpa, .{ - .label = @intCast(isel.instructions.items.len), .target = else_label, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 }, }); try isel.emit(.beqz(cond_mat.reg(), 0, 0)); try cond_mat.finish(isel); @@ -3241,8 +3243,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, }); try isel.internal_relocs.append(gpa, .{ - .label = @intCast(isel.instructions.items.len), .target = next_label, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 }, }); try isel.emit(.b(0, 0)); @@ -3268,8 +3270,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, defer isel.freeReg(item_reg); try isel.internal_relocs.append(gpa, .{ - .label = @intCast(isel.instructions.items.len), .target = case_label, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B16 }, }); try isel.emit(.beq(cond_mat.reg(), item_reg, 0)); try isel.moveIntImm(item_reg, @bitCast(item_int)); @@ -3323,13 +3325,14 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, else => unreachable, inline .@"extern", .func => |func| .{ .nav = func.owner_nav, - .reloc = .{ .label = @intCast(isel.instructions.items.len) }, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .CALL36 }, }, .ptr => |ptr| .{ .nav = ptr.base_addr.nav, .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = @intCast(ptr.byte_offset), + .type = .CALL36, }, }, }); @@ -3920,13 +3923,13 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, .extension = .zero_ext, }); try isel.internal_relocs.append(gpa, .{ - .label = @intCast(isel.instructions.items.len), .target = cmp_label, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 }, }); try isel.emit(.beqz(lhs_tag_mat.reg(), 0, 0)); try isel.internal_relocs.append(gpa, .{ - .label = @intCast(isel.instructions.items.len), .target = cmp_label, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B21 }, }); try isel.emit(.beqz(res_reg, 0, 0)); @@ -4274,8 +4277,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, ); const error_set_part_mat = try error_set_part_vi.matIntRegZeroExt(isel); try isel.internal_relocs.append(gpa, .{ - .label = @intCast(isel.instructions.items.len), .target = cont_label, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 }, }); try isel.emit(.beqz(error_set_part_mat.reg(), 0, 0)); try error_set_part_mat.finish(isel); @@ -4312,8 +4315,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, defer isel.freeReg(tmp_reg); try isel.internal_relocs.append(gpa, .{ - .label = @intCast(isel.instructions.items.len), .target = cont_label, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .B26 }, }); try isel.emit(.beqz(tmp_reg, 0, 0)); @@ -6467,6 +6470,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = @intCast(ptr.byte_offset), + .type = .PCALA_LO12, }, }); try isel.emit(.@"addi.d"(rd, rd, 0)); @@ -6475,6 +6479,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = @intCast(ptr.byte_offset), + .type = .PCALA_HI20, }, }); try isel.emit(.pcalau12i(rd, 0)); @@ -6489,6 +6494,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = @intCast(ptr.byte_offset), + .type = .PCALA_LO12, }, }); try isel.emit(.@"addi.d"(rd, rd, 0)); @@ -6497,6 +6503,7 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = @intCast(ptr.byte_offset), + .type = .PCALA_HI20, }, }); try isel.emit(.pcalau12i(rd, 0)); @@ -6752,15 +6759,12 @@ fn moveConstant(isel: *Select, dst: Value.Location, init_constant: Constant, ini // load constant pointer try isel.uav_relocs.append(zcu.gpa, .{ .uav = uav, - .reloc = .{ .label = @intCast(isel.instructions.items.len), .addend = 0 }, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .PCALA_LO12 }, }); try isel.emit(.@"addi.d"(tmp_reg, tmp_reg, 0)); try isel.uav_relocs.append(zcu.gpa, .{ .uav = uav, - .reloc = .{ - .label = @intCast(isel.instructions.items.len), - .addend = 0, - }, + .reloc = .{ .label = @intCast(isel.instructions.items.len), .type = .PCALA_HI20 }, }); try isel.emit(.pcalau12i(tmp_reg, 0)); -- 2.54.0