authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-07-23 18:36:51-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-07-26 04:05:44-07:00
log574028ed5ec6ad455961ed46babdb7a5fe9f68bb
treed795c8e3f2b6611d7a610bb75469ebc2080df28c
parent9bc7e8c85293fd737e7ca3fb2f783618069b6e61
signaturelock-open Commit is signed but in an unrecognized format.

riscv: boilerplate for creating lazy functions


3 files changed, 321 insertions(+), 165 deletions(-)

src/arch/riscv64/CodeGen.zig+317-162
......@@ -56,7 +56,6 @@ gpa: Allocator,
5656
5757mod: *Package.Module,
5858target: *const std.Target,
59func_index: InternPool.Index,
6059debug_output: DebugInfoOutput,
6160err_msg: ?*ErrorMsg,
6261args: []MCValue,
......@@ -68,6 +67,8 @@ src_loc: Zcu.LazySrcLoc,
6867mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
6968mir_extra: std.ArrayListUnmanaged(u32) = .{},
7069
70owner: Owner,
71
7172/// Byte offset within the source file of the ending curly.
7273end_di_line: u32,
7374end_di_column: u32,
......@@ -112,6 +113,34 @@ const SymbolOffset = struct { sym: u32, off: i32 = 0 };
112113const RegisterOffset = struct { reg: Register, off: i32 = 0 };
113114pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
114115
116const Owner = union(enum) {
117 func_index: InternPool.Index,
118 lazy_sym: link.File.LazySymbol,
119
120 fn getDecl(owner: Owner, zcu: *Zcu) InternPool.DeclIndex {
121 return switch (owner) {
122 .func_index => |func_index| zcu.funcOwnerDeclIndex(func_index),
123 .lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(zcu),
124 };
125 }
126
127 fn getSymbolIndex(owner: Owner, func: *Func) !u32 {
128 const pt = func.pt;
129 switch (owner) {
130 .func_index => |func_index| {
131 const decl_index = func.pt.zcu.funcOwnerDeclIndex(func_index);
132 const elf_file = func.bin_file.cast(link.File.Elf).?;
133 return elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
134 },
135 .lazy_sym => |lazy_sym| {
136 const elf_file = func.bin_file.cast(link.File.Elf).?;
137 return elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err|
138 func.fail("{s} creating lazy symbol", .{@errorName(err)});
139 },
140 }
141 }
142};
143
115144const MCValue = union(enum) {
116145 /// No runtime bits. `void` types, empty structs, u0, enums with 1 tag, etc.
117146 /// TODO Look into deleting this tag and using `dead` instead, since every use
......@@ -739,8 +768,8 @@ pub fn generate(
739768 .bin_file = bin_file,
740769 .liveness = liveness,
741770 .target = target,
742 .func_index = func_index,
743771 .debug_output = debug_output,
772 .owner = .{ .func_index = func_index },
744773 .err_msg = null,
745774 .args = undefined, // populated after `resolveCallingConventionValues`
746775 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
......@@ -797,11 +826,11 @@ pub fn generate(
797826 function.args = call_info.args;
798827 function.ret_mcv = call_info.return_value;
799828 function.frame_allocs.set(@intFromEnum(FrameIndex.ret_addr), FrameAlloc.init(.{
800 .size = Type.usize.abiSize(pt),
801 .alignment = Type.usize.abiAlignment(pt).min(call_info.stack_align),
829 .size = Type.u64.abiSize(pt),
830 .alignment = Type.u64.abiAlignment(pt).min(call_info.stack_align),
802831 }));
803832 function.frame_allocs.set(@intFromEnum(FrameIndex.base_ptr), FrameAlloc.init(.{
804 .size = Type.usize.abiSize(pt),
833 .size = Type.u64.abiSize(pt),
805834 .alignment = Alignment.min(
806835 call_info.stack_align,
807836 Alignment.fromNonzeroByteUnits(function.target.stackAlignment()),
......@@ -813,7 +842,7 @@ pub fn generate(
813842 }));
814843 function.frame_allocs.set(@intFromEnum(FrameIndex.spill_frame), FrameAlloc.init(.{
815844 .size = 0,
816 .alignment = Type.usize.abiAlignment(pt),
845 .alignment = Type.u64.abiAlignment(pt),
817846 }));
818847
819848 function.gen() catch |err| switch (err) {
......@@ -876,6 +905,106 @@ pub fn generate(
876905 }
877906}
878907
908pub fn generateLazy(
909 bin_file: *link.File,
910 pt: Zcu.PerThread,
911 src_loc: Zcu.LazySrcLoc,
912 lazy_sym: link.File.LazySymbol,
913 code: *std.ArrayList(u8),
914 debug_output: DebugInfoOutput,
915) CodeGenError!Result {
916 const comp = bin_file.comp;
917 const gpa = comp.gpa;
918 const mod = comp.root_mod;
919
920 var function: Func = .{
921 .gpa = gpa,
922 .air = undefined,
923 .pt = pt,
924 .mod = mod,
925 .bin_file = bin_file,
926 .liveness = undefined,
927 .target = &mod.resolved_target.result,
928 .debug_output = debug_output,
929 .owner = .{ .lazy_sym = lazy_sym },
930 .err_msg = null,
931 .args = undefined, // populated after `resolveCallingConventionValues`
932 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
933 .fn_type = undefined,
934 .arg_index = 0,
935 .branch_stack = undefined,
936 .src_loc = src_loc,
937 .end_di_line = undefined,
938 .end_di_column = undefined,
939 .scope_generation = 0,
940 .avl = null,
941 .vtype = null,
942 };
943 defer {
944 function.mir_instructions.deinit(gpa);
945 function.mir_extra.deinit(gpa);
946 }
947
948 function.genLazy(lazy_sym) catch |err| switch (err) {
949 error.CodegenFail => return Result{ .fail = function.err_msg.? },
950 error.OutOfRegisters => return Result{
951 .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
952 },
953 else => |e| return e,
954 };
955
956 var mir: Mir = .{
957 .instructions = function.mir_instructions.toOwnedSlice(),
958 .extra = try function.mir_extra.toOwnedSlice(gpa),
959 .frame_locs = function.frame_locs.toOwnedSlice(),
960 };
961 defer mir.deinit(gpa);
962
963 var emit: Emit = .{
964 .lower = .{
965 .pt = pt,
966 .allocator = gpa,
967 .mir = mir,
968 .cc = .Unspecified,
969 .src_loc = src_loc,
970 .output_mode = comp.config.output_mode,
971 .link_mode = comp.config.link_mode,
972 .pic = mod.pic,
973 },
974 .bin_file = bin_file,
975 .debug_output = debug_output,
976 .code = code,
977 .prev_di_pc = undefined, // no debug info yet
978 .prev_di_line = undefined, // no debug info yet
979 .prev_di_column = undefined, // no debug info yet
980 };
981 defer emit.deinit();
982
983 emit.emitMir() catch |err| switch (err) {
984 error.LowerFail, error.EmitFail => return Result{ .fail = emit.lower.err_msg.? },
985 error.InvalidInstruction => |e| {
986 const msg = switch (e) {
987 error.InvalidInstruction => "CodeGen failed to find a viable instruction.",
988 };
989 return Result{
990 .fail = try ErrorMsg.create(
991 gpa,
992 src_loc,
993 "{s} This is a bug in the Zig compiler.",
994 .{msg},
995 ),
996 };
997 },
998 else => |e| return e,
999 };
1000
1001 if (function.err_msg) |em| {
1002 return Result{ .fail = em };
1003 } else {
1004 return Result.ok;
1005 }
1006}
1007
8791008const FormatWipMirData = struct {
8801009 func: *Func,
8811010 inst: Mir.Inst.Index,
......@@ -1050,7 +1179,7 @@ pub fn addExtraAssumeCapacity(func: *Func, extra: anytype) u32 {
10501179/// Caller's duty to lock the return register is needed.
10511180fn getCsr(func: *Func, csr: CSR) !Register {
10521181 assert(func.hasFeature(.zicsr));
1053 const dst_reg = try func.register_manager.allocReg(null, func.regTempClassForType(Type.usize));
1182 const dst_reg = try func.register_manager.allocReg(null, func.regTempClassForType(Type.u64));
10541183 _ = try func.addInst(.{
10551184 .tag = .csrrs,
10561185 .ops = .csr,
......@@ -1103,7 +1232,7 @@ fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void {
11031232 });
11041233 } else {
11051234 const options_int: u12 = @as(u12, 0) | @as(u8, @bitCast(options));
1106 const temp_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = avl });
1235 const temp_reg = try func.copyToTmpRegister(Type.u64, .{ .immediate = avl });
11071236 _ = try func.addInst(.{
11081237 .tag = .vsetvli,
11091238 .ops = .rri,
......@@ -1155,11 +1284,11 @@ fn gen(func: *Func) !void {
11551284 // The address where to store the return value for the caller is in a
11561285 // register which the callee is free to clobber. Therefore, we purposely
11571286 // spill it to stack immediately.
1158 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(Type.usize, pt));
1287 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(Type.u64, pt));
11591288 try func.genSetMem(
11601289 .{ .frame = frame_index },
11611290 0,
1162 Type.usize,
1291 Type.u64,
11631292 func.ret_mcv.long.address().offset(-func.ret_mcv.short.indirect.off),
11641293 );
11651294 func.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };
......@@ -1300,6 +1429,102 @@ fn gen(func: *Func) !void {
13001429 });
13011430}
13021431
1432fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {
1433 const pt = func.pt;
1434 const mod = pt.zcu;
1435 const ip = &mod.intern_pool;
1436 switch (lazy_sym.ty.zigTypeTag(mod)) {
1437 .Enum => {
1438 const enum_ty = lazy_sym.ty;
1439 wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(pt)});
1440
1441 const param_regs = abi.Registers.Integer.function_arg_regs;
1442 const ret_reg = param_regs[0];
1443 const enum_mcv: MCValue = .{ .register = param_regs[1] };
1444
1445 const exitlude_jump_relocs = try func.gpa.alloc(Mir.Inst.Index, enum_ty.enumFieldCount(mod));
1446 defer func.gpa.free(exitlude_jump_relocs);
1447
1448 const data_reg, const data_lock = try func.allocReg(.int);
1449 defer func.register_manager.unlockReg(data_lock);
1450
1451 const elf_file = func.bin_file.cast(link.File.Elf).?;
1452 const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, .{
1453 .kind = .const_data,
1454 .ty = enum_ty,
1455 }) catch |err|
1456 return func.fail("{s} creating lazy symbol", .{@errorName(err)});
1457 const sym = elf_file.symbol(sym_index);
1458
1459 try func.genSetReg(Type.u64, data_reg, .{ .lea_symbol = .{ .sym = sym.esym_index } });
1460
1461 const cmp_reg, const cmp_lock = try func.allocReg(.int);
1462 defer func.register_manager.unlockReg(cmp_lock);
1463
1464 var data_off: i32 = 0;
1465 const tag_names = enum_ty.enumFields(mod);
1466 for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, tag_index| {
1467 const tag_name_len = tag_names.get(ip)[tag_index].length(ip);
1468 const tag_val = try pt.enumValueFieldIndex(enum_ty, @intCast(tag_index));
1469 const tag_mcv = try func.genTypedValue(tag_val);
1470
1471 _ = try func.genBinOp(
1472 .cmp_neq,
1473 enum_mcv,
1474 enum_ty,
1475 tag_mcv,
1476 enum_ty,
1477 cmp_reg,
1478 );
1479 const skip_reloc = try func.condBr(Type.bool, .{ .register = cmp_reg });
1480
1481 try func.genSetMem(
1482 .{ .reg = ret_reg },
1483 0,
1484 Type.u64,
1485 .{ .register_offset = .{ .reg = data_reg, .off = data_off } },
1486 );
1487
1488 try func.genSetMem(
1489 .{ .reg = ret_reg },
1490 8,
1491 Type.u64,
1492 .{ .immediate = tag_name_len },
1493 );
1494
1495 exitlude_jump_reloc.* = try func.addInst(.{
1496 .tag = .pseudo,
1497 .ops = .pseudo_j,
1498 .data = .{ .inst = undefined },
1499 });
1500 func.performReloc(skip_reloc);
1501
1502 data_off += @intCast(tag_name_len + 1);
1503 }
1504
1505 try func.airTrap();
1506
1507 for (exitlude_jump_relocs) |reloc| func.performReloc(reloc);
1508
1509 _ = try func.addInst(.{
1510 .tag = .jalr,
1511 .ops = .rri,
1512 .data = .{
1513 .i_type = .{
1514 .rd = .zero,
1515 .rs1 = .ra,
1516 .imm12 = Immediate.s(0),
1517 },
1518 },
1519 });
1520 },
1521 else => return func.fail(
1522 "TODO implement {s} for {}",
1523 .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(pt) },
1524 ),
1525 }
1526}
1527
13031528fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
13041529 const pt = func.pt;
13051530 const zcu = pt.zcu;
......@@ -1717,8 +1942,8 @@ fn computeFrameLayout(func: *Func) !FrameLayout {
17171942 }
17181943 break :blk i;
17191944 };
1720 const saved_reg_size = save_reg_list.size();
17211945
1946 const saved_reg_size = save_reg_list.size();
17221947 frame_size[@intFromEnum(FrameIndex.spill_frame)] = @intCast(saved_reg_size);
17231948
17241949 // The total frame size is calculated by the amount of s registers you need to save * 8, as each
......@@ -1879,15 +2104,6 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {
18792104 }
18802105}
18812106
1882fn symbolIndex(func: *Func) !u32 {
1883 const pt = func.pt;
1884 const zcu = pt.zcu;
1885 const decl_index = zcu.funcOwnerDeclIndex(func.func_index);
1886 const elf_file = func.bin_file.cast(link.File.Elf).?;
1887 const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
1888 return atom_index;
1889}
1890
18912107fn allocFrameIndex(func: *Func, alloc: FrameAlloc) !FrameIndex {
18922108 const frame_allocs_slice = func.frame_allocs.slice();
18932109 const frame_size = frame_allocs_slice.items(.abi_size);
......@@ -2051,6 +2267,10 @@ pub fn spillInstruction(func: *Func, reg: Register, inst: Air.Inst.Index) !void
20512267 try tracking.trackSpill(func, inst);
20522268}
20532269
2270pub fn spillRegisters(func: *Func, comptime registers: []const Register) !void {
2271 inline for (registers) |reg| try func.register_manager.getKnownReg(reg, null);
2272}
2273
20542274/// Copies a value to a register without tracking the register. The register is not considered
20552275/// allocated. A second call to `copyToTmpRegister` may return the same register.
20562276/// This can have a side effect of spilling instructions to the stack to free up a register.
......@@ -2594,14 +2814,14 @@ fn genBinOp(
25942814
25952815 // RISC-V has no immediate mul, so we copy the size to a temporary register
25962816 const elem_size = lhs_ty.elemType2(zcu).abiSize(pt);
2597 const elem_size_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = elem_size });
2817 const elem_size_reg = try func.copyToTmpRegister(Type.u64, .{ .immediate = elem_size });
25982818
25992819 try func.genBinOp(
26002820 .mul,
26012821 tmp_mcv,
26022822 rhs_ty,
26032823 .{ .register = elem_size_reg },
2604 Type.usize,
2824 Type.u64,
26052825 tmp_reg,
26062826 );
26072827
......@@ -2612,9 +2832,9 @@ fn genBinOp(
26122832 else => unreachable,
26132833 },
26142834 lhs_mcv,
2615 Type.usize, // we know it's a pointer, so it'll be usize.
2835 Type.u64, // we know it's a pointer, so it'll be usize.
26162836 tmp_mcv,
2617 Type.usize,
2837 Type.u64,
26182838 dst_reg,
26192839 );
26202840 },
......@@ -2980,7 +3200,7 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
29803200 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs);
29813201 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);
29823202
2983 const overflow_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = 0 });
3203 const overflow_reg = try func.copyToTmpRegister(Type.u64, .{ .immediate = 0 });
29843204
29853205 const overflow_lock = func.register_manager.lockRegAssumeUnused(overflow_reg);
29863206 defer func.register_manager.unlockReg(overflow_lock);
......@@ -3042,9 +3262,9 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
30423262 try func.genBinOp(
30433263 .cmp_neq,
30443264 .{ .register = overflow_reg },
3045 Type.usize,
3265 Type.u64,
30463266 .{ .register = rhs_reg },
3047 Type.usize,
3267 Type.u64,
30483268 overflow_reg,
30493269 );
30503270
......@@ -3521,7 +3741,7 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {
35213741 if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
35223742
35233743 const dst_mcv = try func.allocRegOrMem(ty, inst, true);
3524 try func.genCopy(Type.usize, dst_mcv, len_mcv);
3744 try func.genCopy(Type.u64, dst_mcv, len_mcv);
35253745 break :result dst_mcv;
35263746 },
35273747 .register_pair => |pair| {
......@@ -3530,7 +3750,7 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {
35303750 if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
35313751
35323752 const dst_mcv = try func.allocRegOrMem(ty, inst, true);
3533 try func.genCopy(Type.usize, dst_mcv, len_mcv);
3753 try func.genCopy(Type.u64, dst_mcv, len_mcv);
35343754 break :result dst_mcv;
35353755 },
35363756 else => return func.fail("TODO airSliceLen for {}", .{src_mcv}),
......@@ -3619,7 +3839,7 @@ fn genSliceElemPtr(func: *Func, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
36193839
36203840 const addr_reg, const addr_lock = try func.allocReg(.int);
36213841 defer func.register_manager.unlockReg(addr_lock);
3622 try func.genSetReg(Type.usize, addr_reg, slice_mcv);
3842 try func.genSetReg(Type.u64, addr_reg, slice_mcv);
36233843
36243844 _ = try func.addInst(.{
36253845 .tag = .add,
......@@ -3657,12 +3877,12 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {
36573877 .register => {
36583878 const frame_index = try func.allocFrameIndex(FrameAlloc.initType(array_ty, pt));
36593879 try func.genSetMem(.{ .frame = frame_index }, 0, array_ty, array_mcv);
3660 try func.genSetReg(Type.usize, addr_reg, .{ .lea_frame = .{ .index = frame_index } });
3880 try func.genSetReg(Type.u64, addr_reg, .{ .lea_frame = .{ .index = frame_index } });
36613881 },
36623882 .load_frame => |frame_addr| {
3663 try func.genSetReg(Type.usize, addr_reg, .{ .lea_frame = frame_addr });
3883 try func.genSetReg(Type.u64, addr_reg, .{ .lea_frame = frame_addr });
36643884 },
3665 else => try func.genSetReg(Type.usize, addr_reg, array_mcv.address()),
3885 else => try func.genSetReg(Type.u64, addr_reg, array_mcv.address()),
36663886 }
36673887
36683888 const dst_mcv = try func.allocRegOrMem(result_ty, inst, false);
......@@ -3683,7 +3903,7 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {
36833903 // we can do a shortcut here where we don't need a vslicedown
36843904 // and can just copy to the frame index.
36853905 if (!(index_mcv == .immediate and index_mcv.immediate == 0)) {
3686 const index_reg = try func.copyToTmpRegister(Type.usize, index_mcv);
3906 const index_reg = try func.copyToTmpRegister(Type.u64, index_mcv);
36873907
36883908 _ = try func.addInst(.{
36893909 .tag = .vslidedownvx,
......@@ -3766,7 +3986,7 @@ fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void {
37663986 base_ptr_mcv,
37673987 base_ptr_ty,
37683988 index_mcv,
3769 Type.usize,
3989 Type.u64,
37703990 result_reg,
37713991 );
37723992
......@@ -4371,7 +4591,7 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {
43714591 const dst_reg = if (field_off == 0)
43724592 (try func.copyToNewRegister(inst, src_mcv)).register
43734593 else
4374 try func.copyToTmpRegister(Type.usize, .{ .register = src_reg });
4594 try func.copyToTmpRegister(Type.u64, .{ .register = src_reg });
43754595
43764596 const dst_mcv: MCValue = .{ .register = dst_reg };
43774597 const dst_lock = func.register_manager.lockReg(dst_reg);
......@@ -4431,8 +4651,8 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {
44314651
44324652 const hi_mcv =
44334653 dst_mcv.address().offset(@intCast(field_bit_size / 64 * 8)).deref();
4434 try func.genSetReg(Type.usize, tmp_reg, hi_mcv);
4435 try func.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg });
4654 try func.genSetReg(Type.u64, tmp_reg, hi_mcv);
4655 try func.genCopy(Type.u64, hi_mcv, .{ .register = tmp_reg });
44364656 }
44374657 break :result dst_mcv;
44384658 }
......@@ -4456,7 +4676,7 @@ fn genArgDbgInfo(func: Func, inst: Air.Inst.Index, mcv: MCValue) !void {
44564676 const zcu = pt.zcu;
44574677 const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg;
44584678 const ty = arg.ty.toType();
4459 const owner_decl = zcu.funcOwnerDeclIndex(func.func_index);
4679 const owner_decl = func.owner.getDecl(zcu);
44604680 if (arg.name == .none) return;
44614681 const name = func.air.nullTerminatedString(@intFromEnum(arg.name));
44624682
......@@ -4517,13 +4737,13 @@ fn airBreakpoint(func: *Func) !void {
45174737
45184738fn airRetAddr(func: *Func, inst: Air.Inst.Index) !void {
45194739 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
4520 try func.genCopy(Type.usize, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } });
4740 try func.genCopy(Type.u64, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } });
45214741 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });
45224742}
45234743
45244744fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void {
45254745 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);
4526 try func.genCopy(Type.usize, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } });
4746 try func.genCopy(Type.u64, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } });
45274747 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });
45284748}
45294749
......@@ -4682,7 +4902,7 @@ fn genCall(
46824902 .indirect => |reg_off| {
46834903 const ret_ty = Type.fromInterned(fn_info.return_type);
46844904 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(ret_ty, pt));
4685 try func.genSetReg(Type.usize, reg_off.reg, .{
4905 try func.genSetReg(Type.u64, reg_off.reg, .{
46864906 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
46874907 });
46884908 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };
......@@ -4700,7 +4920,7 @@ fn genCall(
47004920 dst_reg,
47014921 src_arg,
47024922 ),
4703 .indirect => |reg_off| try func.genSetReg(Type.usize, reg_off.reg, .{
4923 .indirect => |reg_off| try func.genSetReg(Type.u64, reg_off.reg, .{
47044924 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
47054925 }),
47064926 else => return func.fail("TODO: genCall actual set {s}", .{@tagName(dst_arg)}),
......@@ -4728,7 +4948,7 @@ fn genCall(
47284948 if (func.mod.pic) {
47294949 return func.fail("TODO: genCall pic", .{});
47304950 } else {
4731 try func.genSetReg(Type.usize, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } });
4951 try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } });
47324952 _ = try func.addInst(.{
47334953 .tag = .jalr,
47344954 .ops = .rri,
......@@ -4745,7 +4965,7 @@ fn genCall(
47454965 const owner_decl = zcu.declPtr(extern_func.decl);
47464966 const lib_name = extern_func.lib_name.toSlice(&zcu.intern_pool);
47474967 const decl_name = owner_decl.name.toSlice(&zcu.intern_pool);
4748 const atom_index = try func.symbolIndex();
4968 const atom_index = try func.owner.getSymbolIndex(func);
47494969
47504970 if (func.bin_file.cast(link.File.Elf)) |elf_file| {
47514971 _ = try func.addInst(.{
......@@ -4764,7 +4984,7 @@ fn genCall(
47644984 assert(func.typeOf(callee).zigTypeTag(zcu) == .Pointer);
47654985 const addr_reg, const addr_lock = try func.allocReg(.int);
47664986 defer func.register_manager.unlockReg(addr_lock);
4767 try func.genSetReg(Type.usize, addr_reg, .{ .air_ref = callee });
4987 try func.genSetReg(Type.u64, addr_reg, .{ .air_ref = callee });
47684988
47694989 _ = try func.addInst(.{
47704990 .tag = .jalr,
......@@ -4829,7 +5049,7 @@ fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
48295049 const lock = func.register_manager.lockRegAssumeUnused(reg_off.reg);
48305050 defer func.register_manager.unlockReg(lock);
48315051
4832 try func.genSetReg(Type.usize, reg_off.reg, func.ret_mcv.long);
5052 try func.genSetReg(Type.u64, reg_off.reg, func.ret_mcv.long);
48335053 try func.genSetMem(
48345054 .{ .reg = reg_off.reg },
48355055 reg_off.off,
......@@ -4897,14 +5117,14 @@ fn airCmp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
48975117 .Enum => lhs_ty.intTagType(zcu),
48985118 .Int => lhs_ty,
48995119 .Bool => Type.u1,
4900 .Pointer => Type.usize,
5120 .Pointer => Type.u64,
49015121 .ErrorSet => Type.anyerror,
49025122 .Optional => blk: {
49035123 const payload_ty = lhs_ty.optionalChild(zcu);
49045124 if (!payload_ty.hasRuntimeBitsIgnoreComptime(pt)) {
49055125 break :blk Type.u1;
49065126 } else if (lhs_ty.isPtrLikeOptional(zcu)) {
4907 break :blk Type.usize;
5127 break :blk Type.u64;
49085128 } else {
49095129 return func.fail("TODO riscv cmp non-pointer optionals", .{});
49105130 }
......@@ -5014,7 +5234,7 @@ fn genVarDbgInfo(
50145234 break :blk .nop;
50155235 },
50165236 };
5017 try dw.genVarDbgInfo(name, ty, zcu.funcOwnerDeclIndex(func.func_index), is_ptr, loc);
5237 try dw.genVarDbgInfo(name, ty, func.owner.getDecl(zcu), is_ptr, loc);
50185238 },
50195239 .plan9 => {},
50205240 .none => {},
......@@ -5837,7 +6057,7 @@ fn genCopy(func: *Func, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
58376057 const src_info: ?struct { addr_reg: Register, addr_lock: ?RegisterLock } = switch (src_mcv) {
58386058 .register_pair, .memory, .indirect, .load_frame => null,
58396059 .load_symbol => src: {
5840 const src_addr_reg, const src_addr_lock = try func.promoteReg(Type.usize, src_mcv.address());
6060 const src_addr_reg, const src_addr_lock = try func.promoteReg(Type.u64, src_mcv.address());
58416061 errdefer func.register_manager.unlockReg(src_addr_lock);
58426062
58436063 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };
......@@ -5889,9 +6109,9 @@ fn genInlineMemcpy(
58896109 const src = regs[2];
58906110 const dst = regs[3];
58916111
5892 try func.genSetReg(Type.usize, count, len);
5893 try func.genSetReg(Type.usize, src, src_ptr);
5894 try func.genSetReg(Type.usize, dst, dst_ptr);
6112 try func.genSetReg(Type.u64, count, len);
6113 try func.genSetReg(Type.u64, src, src_ptr);
6114 try func.genSetReg(Type.u64, dst, dst_ptr);
58956115
58966116 // if count is 0, there's nothing to copy
58976117 _ = try func.addInst(.{
......@@ -6003,9 +6223,9 @@ fn genInlineMemset(
60036223 const src = regs[1];
60046224 const dst = regs[2];
60056225
6006 try func.genSetReg(Type.usize, count, len);
6007 try func.genSetReg(Type.usize, src, src_value);
6008 try func.genSetReg(Type.usize, dst, dst_ptr);
6226 try func.genSetReg(Type.u64, count, len);
6227 try func.genSetReg(Type.u64, src, src_value);
6228 try func.genSetReg(Type.u64, dst, dst_ptr);
60096229
60106230 // sb src, 0(dst)
60116231 const first_inst = try func.addInst(.{
......@@ -6355,7 +6575,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
63556575 },
63566576 .lea_symbol => |sym_off| {
63576577 assert(sym_off.off == 0);
6358 const atom_index = try func.symbolIndex();
6578 const atom_index = try func.owner.getSymbolIndex(func);
63596579
63606580 _ = try func.addInst(.{
63616581 .tag = .pseudo,
......@@ -6437,7 +6657,7 @@ fn genSetMem(
64376657 },
64386658 .register => |reg| {
64396659 if (reg.class() == .vector) {
6440 const addr_reg = try func.copyToTmpRegister(Type.usize, dst_ptr_mcv);
6660 const addr_reg = try func.copyToTmpRegister(Type.u64, dst_ptr_mcv);
64416661
64426662 const num_elem = ty.vectorLen(zcu);
64436663 const elem_size = ty.childType(zcu).bitSize(pt);
......@@ -6614,7 +6834,7 @@ fn airArrayToSlice(func: *Func, inst: Air.Inst.Index) !void {
66146834 try func.genSetMem(
66156835 .{ .frame = frame_index },
66166836 @intCast(ptr_ty.abiSize(pt)),
6617 Type.usize,
6837 Type.u64,
66186838 .{ .immediate = array_len },
66196839 );
66206840
......@@ -6880,8 +7100,8 @@ fn airMemset(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
68807100
68817101 const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg };
68827102
6883 try func.genSetReg(Type.usize, second_elem_ptr_reg, .{ .register_offset = .{
6884 .reg = try func.copyToTmpRegister(Type.usize, dst_ptr),
7103 try func.genSetReg(Type.u64, second_elem_ptr_reg, .{ .register_offset = .{
7104 .reg = try func.copyToTmpRegister(Type.u64, dst_ptr),
68857105 .off = elem_abi_size,
68867106 } });
68877107
......@@ -6934,118 +7154,52 @@ fn airMemcpy(func: *Func, inst: Air.Inst.Index) !void {
69347154}
69357155
69367156fn airTagName(func: *Func, inst: Air.Inst.Index) !void {
6937 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
6938 const operand = try func.resolveInst(un_op);
6939 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else {
6940 _ = operand;
6941 return func.fail("TODO implement airTagName for riscv64", .{});
6942 };
6943 return func.finishAir(inst, result, .{ un_op, .none, .none });
6944}
6945
6946fn airErrorName(func: *Func, inst: Air.Inst.Index) !void {
69477157 const pt = func.pt;
69487158 const zcu = pt.zcu;
7159
69497160 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
7161 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
7162 const enum_ty = func.typeOf(un_op);
69507163
6951 const err_ty = func.typeOf(un_op);
6952 const err_mcv = try func.resolveInst(un_op);
7164 // TODO: work out the bugs
7165 if (true) return func.fail("TODO: airTagName", .{});
69537166
6954 const err_reg = try func.copyToTmpRegister(err_ty, err_mcv);
6955 const err_lock = func.register_manager.lockRegAssumeUnused(err_reg);
6956 defer func.register_manager.unlockReg(err_lock);
7167 const param_regs = abi.Registers.Integer.function_arg_regs;
7168 const dst_mcv = try func.allocRegOrMem(Type.u64, inst, false);
7169 try func.genSetReg(Type.u64, param_regs[0], dst_mcv.address());
69577170
6958 const addr_reg, const addr_lock = try func.allocReg(.int);
6959 defer func.register_manager.unlockReg(addr_lock);
7171 const operand = try func.resolveInst(un_op);
7172 try func.genSetReg(enum_ty, param_regs[1], operand);
69607173
6961 // this is now the base address of the error name table
6962 const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, zcu);
6963 if (func.bin_file.cast(link.File.Elf)) |elf_file| {
7174 const lazy_sym = link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(zcu), zcu);
7175 const elf_file = func.bin_file.cast(link.File.Elf).?;
69647176 const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err|
69657177 return func.fail("{s} creating lazy symbol", .{@errorName(err)});
69667178 const sym = elf_file.symbol(sym_index);
6967 try func.genSetReg(Type.usize, addr_reg, .{ .load_symbol = .{ .sym = sym.esym_index } });
6968 } else {
6969 return func.fail("TODO: riscv non-elf", .{});
6970 }
6971
6972 const start_reg, const start_lock = try func.allocReg(.int);
6973 defer func.register_manager.unlockReg(start_lock);
6974
6975 const end_reg, const end_lock = try func.allocReg(.int);
6976 defer func.register_manager.unlockReg(end_lock);
69777179
6978 // const tmp_reg, const tmp_lock = try func.allocReg(.int);
6979 // defer func.register_manager.unlockReg(tmp_lock);
6980
6981 // we move the base address forward by the following formula: base + (errno * 8)
6982
6983 // shifting left by 4 is the same as multiplying by 8
6984 _ = try func.addInst(.{
6985 .tag = .slli,
6986 .ops = .rri,
6987 .data = .{ .i_type = .{
6988 .imm12 = Immediate.u(4),
6989 .rd = err_reg,
6990 .rs1 = err_reg,
6991 } },
6992 });
6993
6994 _ = try func.addInst(.{
6995 .tag = .add,
6996 .ops = .rrr,
6997 .data = .{ .r_type = .{
6998 .rd = addr_reg,
6999 .rs1 = addr_reg,
7000 .rs2 = err_reg,
7001 } },
7002 });
7003
7004 _ = try func.addInst(.{
7005 .tag = .pseudo,
7006 .ops = .pseudo_load_rm,
7007 .data = .{
7008 .rm = .{
7009 .r = start_reg,
7010 .m = .{
7011 .base = .{ .reg = addr_reg },
7012 .mod = .{ .size = .dword, .unsigned = true },
7013 },
7014 },
7015 },
7016 });
7017
7018 _ = try func.addInst(.{
7019 .tag = .pseudo,
7020 .ops = .pseudo_load_rm,
7021 .data = .{
7022 .rm = .{
7023 .r = end_reg,
7024 .m = .{
7025 .base = .{ .reg = addr_reg },
7026 .mod = .{ .size = .dword, .unsigned = true },
7027 },
7028 },
7029 },
7030 });
7031
7032 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, false);
7033 const frame = dst_mcv.load_frame;
7034 try func.genSetMem(
7035 .{ .frame = frame.index },
7036 frame.off,
7037 Type.usize,
7038 .{ .register = start_reg },
7039 );
7180 if (func.mod.pic) {
7181 return func.fail("TODO: airTagName pic", .{});
7182 } else {
7183 try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } });
7184 _ = try func.addInst(.{
7185 .tag = .jalr,
7186 .ops = .rri,
7187 .data = .{ .i_type = .{
7188 .rd = .ra,
7189 .rs1 = .ra,
7190 .imm12 = Immediate.s(0),
7191 } },
7192 });
7193 }
70407194
7041 try func.genSetMem(
7042 .{ .frame = frame.index },
7043 frame.off + 8,
7044 Type.usize,
7045 .{ .register = end_reg },
7046 );
7195 break :result dst_mcv;
7196 };
7197 return func.finishAir(inst, result, .{ un_op, .none, .none });
7198}
70477199
7048 return func.finishAir(inst, dst_mcv, .{ un_op, .none, .none });
7200fn airErrorName(func: *Func, inst: Air.Inst.Index) !void {
7201 _ = inst;
7202 return func.fail("TODO: airErrorName", .{});
70497203}
70507204
70517205fn airSplat(func: *Func, inst: Air.Inst.Index) !void {
......@@ -7231,9 +7385,10 @@ fn getResolvedInstValue(func: *Func, inst: Air.Inst.Index) *InstTracking {
72317385
72327386fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {
72337387 const pt = func.pt;
7388 const zcu = pt.zcu;
72347389 const gpa = func.gpa;
72357390
7236 const owner_decl_index = pt.zcu.funcOwnerDeclIndex(func.func_index);
7391 const owner_decl_index = func.owner.getDecl(zcu);
72377392 const lf = func.bin_file;
72387393 const src_loc = func.src_loc;
72397394
src/arch/riscv64/bits.zig+1-2
......@@ -251,8 +251,7 @@ pub const FrameIndex = enum(u32) {
251251 /// This index referes to a frame dedicated to setting up args for function called
252252 /// in this function. Useful for aligning args separately.
253253 call_frame,
254 /// This index referes to the frame where callee saved registers are spilled and restore
255 /// from.
254 /// This index referes to the frame where callee saved registers are spilled and restored from.
256255 spill_frame,
257256 /// Other indices are used for local variable stack slots
258257 _,
src/codegen.zig+3-1
......@@ -106,7 +106,9 @@ pub fn generateLazyFunction(
106106 const target = namespace.fileScope(zcu).mod.resolved_target.result;
107107 switch (target_util.zigBackend(target, false)) {
108108 else => unreachable,
109 inline .stage2_x86_64 => |backend| {
109 inline .stage2_x86_64,
110 .stage2_riscv64,
111 => |backend| {
110112 dev.check(devFeatureForBackend(backend));
111113 return importBackend(backend).generateLazy(lf, pt, src_loc, lazy_sym, code, debug_output);
112114 },