authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-05-02 02:07:28-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-06-13 02:19:40-07:00
log55b28c7e4438b3b8404a0fd703aad45db9dfe2ff
treecda0f8217e49b044c41fa587e56a640d4de5668c
parentc457f35da565e589071db9e55d0866f35cd095dc
signaturelock-open Commit is signed but in an unrecognized format.

riscv: PRO member function calls

this is enough progress for us to be able to call `stdout.write`!

2 files changed, 291 insertions(+), 79 deletions(-)

src/arch/riscv64/CodeGen.zig+290-73
...@@ -932,6 +932,25 @@ fn gen(self: *Self) !void {...@@ -932,6 +932,25 @@ fn gen(self: *Self) !void {
932 const backpatch_fp_add = try self.addPseudo(.pseudo_dead);932 const backpatch_fp_add = try self.addPseudo(.pseudo_dead);
933 const backpatch_spill_callee_preserved_regs = try self.addPseudo(.pseudo_dead);933 const backpatch_spill_callee_preserved_regs = try self.addPseudo(.pseudo_dead);
934934
935 switch (self.ret_mcv.long) {
936 .none, .unreach => {},
937 .indirect => {
938 // The address where to store the return value for the caller is in a
939 // register which the callee is free to clobber. Therefore, we purposely
940 // spill it to stack immediately.
941 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(Type.usize, mod));
942 try self.genSetMem(
943 .{ .frame = frame_index },
944 0,
945 Type.usize,
946 self.ret_mcv.long.address().offset(-self.ret_mcv.short.indirect.off),
947 );
948 self.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };
949 tracking_log.debug("spill {} to {}", .{ self.ret_mcv.long, frame_index });
950 },
951 else => unreachable,
952 }
953
935 try self.genBody(self.air.getMainBody());954 try self.genBody(self.air.getMainBody());
936955
937 for (self.exitlude_jump_relocs.items) |jmp_reloc| {956 for (self.exitlude_jump_relocs.items) |jmp_reloc| {
...@@ -1306,12 +1325,13 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1306,12 +1325,13 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1306 var it = self.register_manager.free_registers.iterator(.{ .kind = .unset });1325 var it = self.register_manager.free_registers.iterator(.{ .kind = .unset });
1307 while (it.next()) |index| {1326 while (it.next()) |index| {
1308 const tracked_inst = self.register_manager.registers[index];1327 const tracked_inst = self.register_manager.registers[index];
1328 tracking_log.debug("tracked inst: {}", .{tracked_inst});
1309 const tracking = self.getResolvedInstValue(tracked_inst);1329 const tracking = self.getResolvedInstValue(tracked_inst);
1310 for (tracking.getRegs()) |reg| {1330 for (tracking.getRegs()) |reg| {
1311 if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;1331 if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;
1312 } else return self.fail(1332 } else return std.debug.panic(
1313 \\%{} takes up these regs: {any}, however those regs don't use it1333 \\%{} takes up these regs: {any}, however these regs {any}, don't use it
1314 , .{ index, tracking.getRegs() });1334 , .{ tracked_inst, tracking.getRegs(), RegisterManager.regAtTrackedIndex(@intCast(index)) });
1315 }1335 }
1316 }1336 }
1317 }1337 }
...@@ -1540,7 +1560,7 @@ fn symbolIndex(self: *Self) !u32 {...@@ -1540,7 +1560,7 @@ fn symbolIndex(self: *Self) !u32 {
1540 const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);1560 const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
1541 break :blk atom_index;1561 break :blk atom_index;
1542 },1562 },
1543 else => return self.fail("TODO genSetReg load_symbol for {s}", .{@tagName(self.bin_file.tag)}),1563 else => return self.fail("TODO symbolIndex {s}", .{@tagName(self.bin_file.tag)}),
1544 };1564 };
1545}1565}
15461566
...@@ -1961,7 +1981,7 @@ fn binOp(...@@ -1961,7 +1981,7 @@ fn binOp(
1961 switch (lhs_ty.zigTypeTag(zcu)) {1981 switch (lhs_ty.zigTypeTag(zcu)) {
1962 .Float => return self.fail("TODO binary operations on floats", .{}),1982 .Float => return self.fail("TODO binary operations on floats", .{}),
1963 .Vector => return self.fail("TODO binary operations on vectors", .{}),1983 .Vector => return self.fail("TODO binary operations on vectors", .{}),
1964 .Int, .Enum => {1984 .Int, .Enum, .ErrorSet => {
1965 assert(lhs_ty.eql(rhs_ty, zcu));1985 assert(lhs_ty.eql(rhs_ty, zcu));
1966 const int_info = lhs_ty.intInfo(zcu);1986 const int_info = lhs_ty.intInfo(zcu);
1967 if (int_info.bits <= 64) {1987 if (int_info.bits <= 64) {
...@@ -2304,8 +2324,127 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2304,8 +2324,127 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2304}2324}
23052325
2306fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {2326fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2307 _ = inst;2327 const zcu = self.bin_file.comp.module.?;
2308 return self.fail("TODO implement airSubWithOverflow for {}", .{self.target.cpu.arch});2328 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2329 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2330
2331 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {
2332 const lhs = try self.resolveInst(extra.lhs);
2333 const rhs = try self.resolveInst(extra.rhs);
2334 const lhs_ty = self.typeOf(extra.lhs);
2335 const rhs_ty = self.typeOf(extra.rhs);
2336
2337 const int_info = lhs_ty.intInfo(zcu);
2338
2339 if (!math.isPowerOfTwo(int_info.bits) or !(int_info.bits >= 8)) {
2340 return self.fail("TODO: airSubWithOverflow non-power of 2 and less than 8 bits", .{});
2341 }
2342
2343 const tuple_ty = self.typeOfIndex(inst);
2344 const result_mcv = try self.allocRegOrMem(inst, false);
2345 const offset = result_mcv.load_frame;
2346
2347 const lhs_reg, const lhs_lock = blk: {
2348 if (lhs == .register) break :blk .{ lhs.register, null };
2349
2350 const lhs_reg, const lhs_lock = try self.allocReg();
2351 try self.genSetReg(lhs_ty, lhs_reg, lhs);
2352 break :blk .{ lhs_reg, lhs_lock };
2353 };
2354 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
2355
2356 const rhs_reg, const rhs_lock = blk: {
2357 if (rhs == .register) break :blk .{ rhs.register, null };
2358
2359 const rhs_reg, const rhs_lock = try self.allocReg();
2360 try self.genSetReg(rhs_ty, rhs_reg, rhs);
2361 break :blk .{ rhs_reg, rhs_lock };
2362 };
2363 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
2364
2365 const dest_reg, const dest_lock = try self.allocReg();
2366 defer self.register_manager.unlockReg(dest_lock);
2367
2368 switch (int_info.signedness) {
2369 .unsigned => return self.fail("TODO: airSubWithOverflow unsigned", .{}),
2370 .signed => {
2371 switch (int_info.bits) {
2372 64 => {
2373 // result
2374 _ = try self.addInst(.{
2375 .tag = .sub,
2376 .ops = .rrr,
2377 .data = .{ .r_type = .{
2378 .rd = dest_reg,
2379 .rs1 = lhs_reg,
2380 .rs2 = rhs_reg,
2381 } },
2382 });
2383
2384 try self.genSetMem(
2385 .{ .frame = offset.index },
2386 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, zcu))),
2387 lhs_ty,
2388 .{ .register = dest_reg },
2389 );
2390
2391 // overflow check
2392 const overflow_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = 0 });
2393
2394 _ = try self.addInst(.{
2395 .tag = .slt,
2396 .ops = .rrr,
2397 .data = .{ .r_type = .{
2398 .rd = overflow_reg,
2399 .rs1 = overflow_reg,
2400 .rs2 = rhs_reg,
2401 } },
2402 });
2403
2404 _ = try self.addInst(.{
2405 .tag = .slt,
2406 .ops = .rrr,
2407 .data = .{ .r_type = .{
2408 .rd = rhs_reg,
2409 .rs1 = rhs_reg,
2410 .rs2 = lhs_reg,
2411 } },
2412 });
2413
2414 _ = try self.addInst(.{
2415 .tag = .xor,
2416 .ops = .rrr,
2417 .data = .{ .r_type = .{
2418 .rd = lhs_reg,
2419 .rs1 = overflow_reg,
2420 .rs2 = rhs_reg,
2421 } },
2422 });
2423
2424 const overflow_mcv = try self.binOp(
2425 .cmp_neq,
2426 .{ .register = overflow_reg },
2427 Type.usize,
2428 .{ .register = rhs_reg },
2429 Type.usize,
2430 );
2431
2432 try self.genSetMem(
2433 .{ .frame = offset.index },
2434 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, zcu))),
2435 Type.u1,
2436 overflow_mcv,
2437 );
2438
2439 break :result result_mcv;
2440 },
2441 else => |int_bits| return self.fail("TODO: airSubWithOverflow signed {}", .{int_bits}),
2442 }
2443 },
2444 }
2445 };
2446
2447 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
2309}2448}
23102449
2311fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {2450fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
...@@ -2644,8 +2783,25 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {...@@ -2644,8 +2783,25 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
26442783
2645/// T to E!T2784/// T to E!T
2646fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {2785fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
2786 const zcu = self.bin_file.comp.module.?;
2647 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2787 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2648 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement wrap errunion payload for {}", .{self.target.cpu.arch});2788
2789 const eu_ty = ty_op.ty.toType();
2790 const pl_ty = eu_ty.errorUnionPayload(zcu);
2791 const err_ty = eu_ty.errorUnionSet(zcu);
2792 const operand = try self.resolveInst(ty_op.operand);
2793
2794 const result: MCValue = result: {
2795 if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .{ .immediate = 0 };
2796
2797 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu));
2798 const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu));
2799 const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu));
2800 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand);
2801 try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 });
2802 break :result .{ .load_frame = .{ .index = frame_index } };
2803 };
2804
2649 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2805 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2650}2806}
26512807
...@@ -3361,8 +3517,6 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3361,8 +3517,6 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3361 .rs1 = dst_reg,3517 .rs1 = dst_reg,
3362 } },3518 } },
3363 });3519 });
3364
3365 return self.fail("TODO: airStructFieldVal register with field_off > 0", .{});
3366 }3520 }
33673521
3368 break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv);3522 break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv);
...@@ -3444,7 +3598,6 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {...@@ -3444,7 +3598,6 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
3444}3598}
34453599
3446fn airArg(self: *Self, inst: Air.Inst.Index) !void {3600fn airArg(self: *Self, inst: Air.Inst.Index) !void {
3447 const zcu = self.bin_file.comp.module.?;
3448 var arg_index = self.arg_index;3601 var arg_index = self.arg_index;
34493602
3450 // we skip over args that have no bits3603 // we skip over args that have no bits
...@@ -3453,31 +3606,10 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -3453,31 +3606,10 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
34533606
3454 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {3607 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {
3455 const src_mcv = self.args[arg_index];3608 const src_mcv = self.args[arg_index];
3456
3457 const arg_ty = self.typeOfIndex(inst);3609 const arg_ty = self.typeOfIndex(inst);
34583610
3459 const dst_mcv = switch (src_mcv) {3611 const dst_mcv = try self.allocRegOrMem(inst, false);
3460 .register => dst: {3612 try self.genCopy(arg_ty, dst_mcv, src_mcv);
3461 const frame = try self.allocFrameIndex(FrameAlloc.init(.{
3462 .size = Type.usize.abiSize(zcu),
3463 .alignment = Type.usize.abiAlignment(zcu),
3464 }));
3465 const dst_mcv: MCValue = .{ .load_frame = .{ .index = frame } };
3466 try self.genCopy(Type.usize, dst_mcv, src_mcv);
3467 break :dst dst_mcv;
3468 },
3469 .register_pair => dst: {
3470 const frame = try self.allocFrameIndex(FrameAlloc.init(.{
3471 .size = Type.usize.abiSize(zcu) * 2,
3472 .alignment = Type.usize.abiAlignment(zcu),
3473 }));
3474 const dst_mcv: MCValue = .{ .load_frame = .{ .index = frame } };
3475 try self.genCopy(arg_ty, dst_mcv, src_mcv);
3476 break :dst dst_mcv;
3477 },
3478 .load_frame => src_mcv,
3479 else => return self.fail("TODO: airArg {s}", .{@tagName(src_mcv)}),
3480 };
34813613
3482 try self.genArgDbgInfo(inst, src_mcv);3614 try self.genArgDbgInfo(inst, src_mcv);
3483 break :result dst_mcv;3615 break :result dst_mcv;
...@@ -3612,7 +3744,68 @@ fn genCall(...@@ -3612,7 +3744,68 @@ fn genCall(
3612 stack_frame_align.* = stack_frame_align.max(needed_call_frame.abi_align);3744 stack_frame_align.* = stack_frame_align.max(needed_call_frame.abi_align);
3613 }3745 }
36143746
3615 for (call_info.args, 0..) |mc_arg, arg_i| try self.genCopy(arg_tys[arg_i], mc_arg, args[arg_i]);3747 var reg_locks = std.ArrayList(?RegisterLock).init(allocator);
3748 defer reg_locks.deinit();
3749 try reg_locks.ensureTotalCapacity(8);
3750 defer for (reg_locks.items) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock);
3751
3752 const frame_indices = try allocator.alloc(FrameIndex, args.len);
3753 defer allocator.free(frame_indices);
3754
3755 switch (call_info.return_value.long) {
3756 .none, .unreach => {},
3757 .indirect => |reg_off| try self.register_manager.getReg(reg_off.reg, null),
3758 else => unreachable,
3759 }
3760 for (call_info.args, args, arg_tys, frame_indices) |dst_arg, src_arg, arg_ty, *frame_index| {
3761 switch (dst_arg) {
3762 .none => {},
3763 .register => |reg| {
3764 try self.register_manager.getReg(reg, null);
3765 try reg_locks.append(self.register_manager.lockReg(reg));
3766 },
3767 .register_pair => |regs| {
3768 for (regs) |reg| try self.register_manager.getReg(reg, null);
3769 try reg_locks.appendSlice(&self.register_manager.lockRegs(2, regs));
3770 },
3771 .indirect => |reg_off| {
3772 frame_index.* = try self.allocFrameIndex(FrameAlloc.initType(arg_ty, zcu));
3773 try self.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg);
3774 try self.register_manager.getReg(reg_off.reg, null);
3775 try reg_locks.append(self.register_manager.lockReg(reg_off.reg));
3776 },
3777 else => return self.fail("TODO: genCall set arg {s}", .{@tagName(dst_arg)}),
3778 }
3779 }
3780
3781 switch (call_info.return_value.long) {
3782 .none, .unreach => {},
3783 .indirect => |reg_off| {
3784 const ret_ty = Type.fromInterned(fn_info.return_type);
3785 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(ret_ty, zcu));
3786 try self.genSetReg(Type.usize, reg_off.reg, .{
3787 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
3788 });
3789 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };
3790 try reg_locks.append(self.register_manager.lockReg(reg_off.reg));
3791 },
3792 else => unreachable,
3793 }
3794
3795 for (call_info.args, arg_tys, args, frame_indices) |dst_arg, arg_ty, src_arg, frame_index| {
3796 switch (dst_arg) {
3797 .register_pair => try self.genCopy(arg_ty, dst_arg, src_arg),
3798 .register => |dst_reg| try self.genSetReg(
3799 arg_ty,
3800 dst_reg,
3801 src_arg,
3802 ),
3803 .indirect => |reg_off| try self.genSetReg(Type.usize, reg_off.reg, .{
3804 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
3805 }),
3806 else => return self.fail("TODO: genCall actual set {s}", .{@tagName(dst_arg)}),
3807 }
3808 }
36163809
3617 // Due to incremental compilation, how function calls are generated depends3810 // Due to incremental compilation, how function calls are generated depends
3618 // on linking.3811 // on linking.
...@@ -3715,9 +3908,10 @@ fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -3715,9 +3908,10 @@ fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
3715 defer self.register_manager.unlockReg(lock);3908 defer self.register_manager.unlockReg(lock);
37163909
3717 try self.genSetReg(Type.usize, reg_off.reg, self.ret_mcv.long);3910 try self.genSetReg(Type.usize, reg_off.reg, self.ret_mcv.long);
3718 try self.genCopy(3911 try self.genSetMem(
3912 .{ .reg = reg_off.reg },
3913 reg_off.off,
3719 ret_ty,3914 ret_ty,
3720 .{ .register_offset = reg_off },
3721 .{ .air_ref = un_op },3915 .{ .air_ref = un_op },
3722 );3916 );
3723 },3917 },
...@@ -3745,6 +3939,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -3745,6 +3939,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
3745 switch (self.ret_mcv.short) {3939 switch (self.ret_mcv.short) {
3746 .none => {},3940 .none => {},
3747 .register, .register_pair => try self.load(self.ret_mcv.short, ptr, ptr_ty),3941 .register, .register_pair => try self.load(self.ret_mcv.short, ptr, ptr_ty),
3942 .indirect => |reg_off| try self.genSetReg(ptr_ty, reg_off.reg, ptr),
3748 else => unreachable,3943 else => unreachable,
3749 }3944 }
3750 self.ret_mcv.liveOut(self, inst);3945 self.ret_mcv.liveOut(self, inst);
...@@ -4058,7 +4253,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue)...@@ -4058,7 +4253,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue)
40584253
4059 _ = maybe_inst;4254 _ = maybe_inst;
40604255
4061 const err_off = errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu);4256 const err_off: u31 = @intCast(errUnionErrorOffset(eu_ty.errorUnionPayload(zcu), zcu));
40624257
4063 switch (eu_mcv) {4258 switch (eu_mcv) {
4064 .register => |reg| {4259 .register => |reg| {
...@@ -4081,15 +4276,25 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue)...@@ -4081,15 +4276,25 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue)
4081 );4276 );
4082 }4277 }
40834278
4084 return_mcv = try self.binOp(4279 return try self.binOp(
4085 .cmp_neq,4280 .cmp_neq,
4086 return_mcv,4281 return_mcv,
4087 Type.u16,4282 Type.u16,
4088 .{ .immediate = 0 },4283 .{ .immediate = 0 },
4089 Type.u16,4284 Type.u16,
4090 );4285 );
40914286 },
4092 return return_mcv;4287 .load_frame => |frame_addr| {
4288 return self.binOp(
4289 .cmp_neq,
4290 .{ .load_frame = .{
4291 .index = frame_addr.index,
4292 .off = frame_addr.off + err_off,
4293 } },
4294 Type.anyerror,
4295 .{ .immediate = 0 },
4296 Type.anyerror,
4297 );
4093 },4298 },
4094 else => return self.fail("TODO implement isErr for {}", .{eu_mcv}),4299 else => return self.fail("TODO implement isErr for {}", .{eu_mcv}),
4095 }4300 }
...@@ -4839,7 +5044,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -4839,7 +5044,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
4839 const zcu = self.bin_file.comp.module.?;5044 const zcu = self.bin_file.comp.module.?;
4840 const abi_size: u32 = @intCast(ty.abiSize(zcu));5045 const abi_size: u32 = @intCast(ty.abiSize(zcu));
48415046
4842 if (abi_size > 8) return self.fail("tried to set reg with size {}", .{abi_size});5047 if (abi_size > 8) return std.debug.panic("tried to set reg with size {}", .{abi_size});
48435048
4844 switch (src_mcv) {5049 switch (src_mcv) {
4845 .dead => unreachable,5050 .dead => unreachable,
...@@ -4924,7 +5129,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -4924,7 +5129,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
4924 if (src_reg.id() == reg.id())5129 if (src_reg.id() == reg.id())
4925 return;5130 return;
49265131
4927 // mov reg, src_reg5132 // mv reg, src_reg
4928 _ = try self.addInst(.{5133 _ = try self.addInst(.{
4929 .tag = .pseudo,5134 .tag = .pseudo,
4930 .ops = .pseudo_mv,5135 .ops = .pseudo_mv,
...@@ -4934,20 +5139,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -4934,20 +5139,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
4934 } },5139 } },
4935 });5140 });
4936 },5141 },
4937 .register_pair => |pair| try self.genSetReg(ty, reg, .{ .register = pair[0] }),5142 .register_pair => return self.fail("genSetReg should we allow reg -> reg_pair?", .{}),
4938 .memory => |addr| {
4939 try self.genSetReg(ty, reg, .{ .immediate = addr });
4940
4941 _ = try self.addInst(.{
4942 .tag = .ld,
4943 .ops = .rri,
4944 .data = .{ .i_type = .{
4945 .rd = reg,
4946 .rs1 = reg,
4947 .imm12 = Immediate.s(0),
4948 } },
4949 });
4950 },
4951 .load_frame => |frame| {5143 .load_frame => |frame| {
4952 _ = try self.addInst(.{5144 _ = try self.addInst(.{
4953 .tag = .pseudo,5145 .tag = .pseudo,
...@@ -4966,28 +5158,49 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -4966,28 +5158,49 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
4966 } },5158 } },
4967 });5159 });
4968 },5160 },
4969 .lea_frame => |frame| {5161 .memory => |addr| {
5162 try self.genSetReg(ty, reg, .{ .immediate = addr });
5163
5164 _ = try self.addInst(.{
5165 .tag = .ld,
5166 .ops = .rri,
5167 .data = .{ .i_type = .{
5168 .rd = reg,
5169 .rs1 = reg,
5170 .imm12 = Immediate.s(0),
5171 } },
5172 });
5173 },
5174 .lea_frame, .register_offset => {
4970 _ = try self.addInst(.{5175 _ = try self.addInst(.{
4971 .tag = .pseudo,5176 .tag = .pseudo,
4972 .ops = .pseudo_lea_rm,5177 .ops = .pseudo_lea_rm,
4973 .data = .{ .rm = .{5178 .data = .{ .rm = .{
4974 .r = reg,5179 .r = reg,
4975 .m = .{5180 .m = switch (src_mcv) {
4976 .base = .{ .frame = frame.index },5181 .register_offset => |reg_off| .{
4977 .mod = .{5182 .base = .{ .reg = reg_off.reg },
4978 .rm = .{5183 .mod = .{
4979 .size = self.memSize(ty),5184 .rm = .{
4980 .disp = frame.off,5185 .size = self.memSize(ty),
5186 .disp = reg_off.off,
5187 },
5188 },
5189 },
5190 .lea_frame => |frame| .{
5191 .base = .{ .frame = frame.index },
5192 .mod = .{
5193 .rm = .{
5194 .size = self.memSize(ty),
5195 .disp = frame.off,
5196 },
4981 },5197 },
4982 },5198 },
5199 else => unreachable,
4983 },5200 },
4984 } },5201 } },
4985 });5202 });
4986 },5203 },
4987 .load_symbol => {
4988 try self.genSetReg(ty, reg, src_mcv.address());
4989 try self.genSetReg(ty, reg, .{ .indirect = .{ .reg = reg } });
4990 },
4991 .indirect => |reg_off| {5204 .indirect => |reg_off| {
4992 const load_tag: Mir.Inst.Tag = switch (abi_size) {5205 const load_tag: Mir.Inst.Tag = switch (abi_size) {
4993 1 => .lb,5206 1 => .lb,
...@@ -5022,6 +5235,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5022,6 +5235,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5022 }) },5235 }) },
5023 });5236 });
5024 },5237 },
5238 .load_symbol => {
5239 try self.genSetReg(ty, reg, src_mcv.address());
5240 try self.genSetReg(ty, reg, .{ .indirect = .{ .reg = reg } });
5241 },
5025 .air_ref => |ref| try self.genSetReg(ty, reg, try self.resolveInst(ref)),5242 .air_ref => |ref| try self.genSetReg(ty, reg, try self.resolveInst(ref)),
5026 else => return self.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}),5243 else => return self.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}),
5027 }5244 }
...@@ -5052,7 +5269,6 @@ fn genSetMem(...@@ -5052,7 +5269,6 @@ fn genSetMem(
5052 src_mcv,5269 src_mcv,
5053 .{ .immediate = abi_size },5270 .{ .immediate = abi_size },
5054 ),5271 ),
5055
5056 .register_offset,5272 .register_offset,
5057 .memory,5273 .memory,
5058 .indirect,5274 .indirect,
...@@ -5100,14 +5316,15 @@ fn genSetMem(...@@ -5100,14 +5316,15 @@ fn genSetMem(
5100 _ = try self.addInst(.{5316 _ = try self.addInst(.{
5101 .tag = .pseudo,5317 .tag = .pseudo,
5102 .ops = .pseudo_store_rm,5318 .ops = .pseudo_store_rm,
5103 .data = .{5319 .data = .{ .rm = .{
5104 .rm = .{ .r = reg, .m = .{5320 .r = reg,
5321 .m = .{
5105 .base = .{ .frame = frame_index },5322 .base = .{ .frame = frame_index },
5106 .mod = .{ .rm = .{5323 .mod = .{ .rm = .{
5107 .size = Memory.Size.fromByteSize(src_size),5324 .size = Memory.Size.fromByteSize(src_size),
5108 } },5325 } },
5109 } },5326 },
5110 },5327 } },
5111 });5328 });
5112 try self.genSetMem(base, disp, ty, frame_mcv);5329 try self.genSetMem(base, disp, ty, frame_mcv);
5113 try self.freeValue(frame_mcv);5330 try self.freeValue(frame_mcv);
src/arch/riscv64/abi.zig+1-6
...@@ -149,12 +149,7 @@ pub fn classifySystem(ty: Type, zcu: *Module) [8]Class {...@@ -149,12 +149,7 @@ pub fn classifySystem(ty: Type, zcu: *Module) [8]Class {
149 // anyerror!void can fit into one register149 // anyerror!void can fit into one register
150 if (payload_bits == 0) return result;150 if (payload_bits == 0) return result;
151151
152 if (payload_bits <= 64) {152 return memory_class;
153 result[1] = .integer;
154 return result;
155 }
156
157 std.debug.panic("TODO: classifySystem ErrorUnion > 64 bit payload", .{});
158 },153 },
159 .Struct => {154 .Struct => {
160 const layout = ty.containerLayout(zcu);155 const layout = ty.containerLayout(zcu);