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,...@@ -56,7 +56,6 @@ gpa: Allocator,
5656
57mod: *Package.Module,57mod: *Package.Module,
58target: *const std.Target,58target: *const std.Target,
59func_index: InternPool.Index,
60debug_output: DebugInfoOutput,59debug_output: DebugInfoOutput,
61err_msg: ?*ErrorMsg,60err_msg: ?*ErrorMsg,
62args: []MCValue,61args: []MCValue,
...@@ -68,6 +67,8 @@ src_loc: Zcu.LazySrcLoc,...@@ -68,6 +67,8 @@ src_loc: Zcu.LazySrcLoc,
68mir_instructions: std.MultiArrayList(Mir.Inst) = .{},67mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
69mir_extra: std.ArrayListUnmanaged(u32) = .{},68mir_extra: std.ArrayListUnmanaged(u32) = .{},
7069
70owner: Owner,
71
71/// Byte offset within the source file of the ending curly.72/// Byte offset within the source file of the ending curly.
72end_di_line: u32,73end_di_line: u32,
73end_di_column: u32,74end_di_column: u32,
...@@ -112,6 +113,34 @@ const SymbolOffset = struct { sym: u32, off: i32 = 0 };...@@ -112,6 +113,34 @@ const SymbolOffset = struct { sym: u32, off: i32 = 0 };
112const RegisterOffset = struct { reg: Register, off: i32 = 0 };113const RegisterOffset = struct { reg: Register, off: i32 = 0 };
113pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };114pub 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
115const MCValue = union(enum) {144const MCValue = union(enum) {
116 /// No runtime bits. `void` types, empty structs, u0, enums with 1 tag, etc.145 /// No runtime bits. `void` types, empty structs, u0, enums with 1 tag, etc.
117 /// TODO Look into deleting this tag and using `dead` instead, since every use146 /// TODO Look into deleting this tag and using `dead` instead, since every use
...@@ -739,8 +768,8 @@ pub fn generate(...@@ -739,8 +768,8 @@ pub fn generate(
739 .bin_file = bin_file,768 .bin_file = bin_file,
740 .liveness = liveness,769 .liveness = liveness,
741 .target = target,770 .target = target,
742 .func_index = func_index,
743 .debug_output = debug_output,771 .debug_output = debug_output,
772 .owner = .{ .func_index = func_index },
744 .err_msg = null,773 .err_msg = null,
745 .args = undefined, // populated after `resolveCallingConventionValues`774 .args = undefined, // populated after `resolveCallingConventionValues`
746 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`775 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
...@@ -797,11 +826,11 @@ pub fn generate(...@@ -797,11 +826,11 @@ pub fn generate(
797 function.args = call_info.args;826 function.args = call_info.args;
798 function.ret_mcv = call_info.return_value;827 function.ret_mcv = call_info.return_value;
799 function.frame_allocs.set(@intFromEnum(FrameIndex.ret_addr), FrameAlloc.init(.{828 function.frame_allocs.set(@intFromEnum(FrameIndex.ret_addr), FrameAlloc.init(.{
800 .size = Type.usize.abiSize(pt),829 .size = Type.u64.abiSize(pt),
801 .alignment = Type.usize.abiAlignment(pt).min(call_info.stack_align),830 .alignment = Type.u64.abiAlignment(pt).min(call_info.stack_align),
802 }));831 }));
803 function.frame_allocs.set(@intFromEnum(FrameIndex.base_ptr), FrameAlloc.init(.{832 function.frame_allocs.set(@intFromEnum(FrameIndex.base_ptr), FrameAlloc.init(.{
804 .size = Type.usize.abiSize(pt),833 .size = Type.u64.abiSize(pt),
805 .alignment = Alignment.min(834 .alignment = Alignment.min(
806 call_info.stack_align,835 call_info.stack_align,
807 Alignment.fromNonzeroByteUnits(function.target.stackAlignment()),836 Alignment.fromNonzeroByteUnits(function.target.stackAlignment()),
...@@ -813,7 +842,7 @@ pub fn generate(...@@ -813,7 +842,7 @@ pub fn generate(
813 }));842 }));
814 function.frame_allocs.set(@intFromEnum(FrameIndex.spill_frame), FrameAlloc.init(.{843 function.frame_allocs.set(@intFromEnum(FrameIndex.spill_frame), FrameAlloc.init(.{
815 .size = 0,844 .size = 0,
816 .alignment = Type.usize.abiAlignment(pt),845 .alignment = Type.u64.abiAlignment(pt),
817 }));846 }));
818847
819 function.gen() catch |err| switch (err) {848 function.gen() catch |err| switch (err) {
...@@ -876,6 +905,106 @@ pub fn generate(...@@ -876,6 +905,106 @@ pub fn generate(
876 }905 }
877}906}
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
879const FormatWipMirData = struct {1008const FormatWipMirData = struct {
880 func: *Func,1009 func: *Func,
881 inst: Mir.Inst.Index,1010 inst: Mir.Inst.Index,
...@@ -1050,7 +1179,7 @@ pub fn addExtraAssumeCapacity(func: *Func, extra: anytype) u32 {...@@ -1050,7 +1179,7 @@ pub fn addExtraAssumeCapacity(func: *Func, extra: anytype) u32 {
1050/// Caller's duty to lock the return register is needed.1179/// Caller's duty to lock the return register is needed.
1051fn getCsr(func: *Func, csr: CSR) !Register {1180fn getCsr(func: *Func, csr: CSR) !Register {
1052 assert(func.hasFeature(.zicsr));1181 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));
1054 _ = try func.addInst(.{1183 _ = try func.addInst(.{
1055 .tag = .csrrs,1184 .tag = .csrrs,
1056 .ops = .csr,1185 .ops = .csr,
...@@ -1103,7 +1232,7 @@ fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void {...@@ -1103,7 +1232,7 @@ fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void {
1103 });1232 });
1104 } else {1233 } else {
1105 const options_int: u12 = @as(u12, 0) | @as(u8, @bitCast(options));1234 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 });
1107 _ = try func.addInst(.{1236 _ = try func.addInst(.{
1108 .tag = .vsetvli,1237 .tag = .vsetvli,
1109 .ops = .rri,1238 .ops = .rri,
...@@ -1155,11 +1284,11 @@ fn gen(func: *Func) !void {...@@ -1155,11 +1284,11 @@ fn gen(func: *Func) !void {
1155 // The address where to store the return value for the caller is in a1284 // The address where to store the return value for the caller is in a
1156 // register which the callee is free to clobber. Therefore, we purposely1285 // register which the callee is free to clobber. Therefore, we purposely
1157 // spill it to stack immediately.1286 // 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));
1159 try func.genSetMem(1288 try func.genSetMem(
1160 .{ .frame = frame_index },1289 .{ .frame = frame_index },
1161 0,1290 0,
1162 Type.usize,1291 Type.u64,
1163 func.ret_mcv.long.address().offset(-func.ret_mcv.short.indirect.off),1292 func.ret_mcv.long.address().offset(-func.ret_mcv.short.indirect.off),
1164 );1293 );
1165 func.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };1294 func.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } };
...@@ -1300,6 +1429,102 @@ fn gen(func: *Func) !void {...@@ -1300,6 +1429,102 @@ fn gen(func: *Func) !void {
1300 });1429 });
1301}1430}
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
1303fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {1528fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1304 const pt = func.pt;1529 const pt = func.pt;
1305 const zcu = pt.zcu;1530 const zcu = pt.zcu;
...@@ -1717,8 +1942,8 @@ fn computeFrameLayout(func: *Func) !FrameLayout {...@@ -1717,8 +1942,8 @@ fn computeFrameLayout(func: *Func) !FrameLayout {
1717 }1942 }
1718 break :blk i;1943 break :blk i;
1719 };1944 };
1720 const saved_reg_size = save_reg_list.size();
17211945
1946 const saved_reg_size = save_reg_list.size();
1722 frame_size[@intFromEnum(FrameIndex.spill_frame)] = @intCast(saved_reg_size);1947 frame_size[@intFromEnum(FrameIndex.spill_frame)] = @intCast(saved_reg_size);
17231948
1724 // The total frame size is calculated by the amount of s registers you need to save * 8, as each1949 // 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 {...@@ -1879,15 +2104,6 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void {
1879 }2104 }
1880}2105}
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
1891fn allocFrameIndex(func: *Func, alloc: FrameAlloc) !FrameIndex {2107fn allocFrameIndex(func: *Func, alloc: FrameAlloc) !FrameIndex {
1892 const frame_allocs_slice = func.frame_allocs.slice();2108 const frame_allocs_slice = func.frame_allocs.slice();
1893 const frame_size = frame_allocs_slice.items(.abi_size);2109 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...@@ -2051,6 +2267,10 @@ pub fn spillInstruction(func: *Func, reg: Register, inst: Air.Inst.Index) !void
2051 try tracking.trackSpill(func, inst);2267 try tracking.trackSpill(func, inst);
2052}2268}
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
2054/// Copies a value to a register without tracking the register. The register is not considered2274/// Copies a value to a register without tracking the register. The register is not considered
2055/// allocated. A second call to `copyToTmpRegister` may return the same register.2275/// allocated. A second call to `copyToTmpRegister` may return the same register.
2056/// This can have a side effect of spilling instructions to the stack to free up a register.2276/// This can have a side effect of spilling instructions to the stack to free up a register.
...@@ -2594,14 +2814,14 @@ fn genBinOp(...@@ -2594,14 +2814,14 @@ fn genBinOp(
25942814
2595 // RISC-V has no immediate mul, so we copy the size to a temporary register2815 // RISC-V has no immediate mul, so we copy the size to a temporary register
2596 const elem_size = lhs_ty.elemType2(zcu).abiSize(pt);2816 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
2599 try func.genBinOp(2819 try func.genBinOp(
2600 .mul,2820 .mul,
2601 tmp_mcv,2821 tmp_mcv,
2602 rhs_ty,2822 rhs_ty,
2603 .{ .register = elem_size_reg },2823 .{ .register = elem_size_reg },
2604 Type.usize,2824 Type.u64,
2605 tmp_reg,2825 tmp_reg,
2606 );2826 );
26072827
...@@ -2612,9 +2832,9 @@ fn genBinOp(...@@ -2612,9 +2832,9 @@ fn genBinOp(
2612 else => unreachable,2832 else => unreachable,
2613 },2833 },
2614 lhs_mcv,2834 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.
2616 tmp_mcv,2836 tmp_mcv,
2617 Type.usize,2837 Type.u64,
2618 dst_reg,2838 dst_reg,
2619 );2839 );
2620 },2840 },
...@@ -2980,7 +3200,7 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -2980,7 +3200,7 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
2980 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs);3200 const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs);
2981 defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock);3201 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
2985 const overflow_lock = func.register_manager.lockRegAssumeUnused(overflow_reg);3205 const overflow_lock = func.register_manager.lockRegAssumeUnused(overflow_reg);
2986 defer func.register_manager.unlockReg(overflow_lock);3206 defer func.register_manager.unlockReg(overflow_lock);
...@@ -3042,9 +3262,9 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -3042,9 +3262,9 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
3042 try func.genBinOp(3262 try func.genBinOp(
3043 .cmp_neq,3263 .cmp_neq,
3044 .{ .register = overflow_reg },3264 .{ .register = overflow_reg },
3045 Type.usize,3265 Type.u64,
3046 .{ .register = rhs_reg },3266 .{ .register = rhs_reg },
3047 Type.usize,3267 Type.u64,
3048 overflow_reg,3268 overflow_reg,
3049 );3269 );
30503270
...@@ -3521,7 +3741,7 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {...@@ -3521,7 +3741,7 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {
3521 if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;3741 if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
35223742
3523 const dst_mcv = try func.allocRegOrMem(ty, inst, true);3743 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);
3525 break :result dst_mcv;3745 break :result dst_mcv;
3526 },3746 },
3527 .register_pair => |pair| {3747 .register_pair => |pair| {
...@@ -3530,7 +3750,7 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {...@@ -3530,7 +3750,7 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {
3530 if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;3750 if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv;
35313751
3532 const dst_mcv = try func.allocRegOrMem(ty, inst, true);3752 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);
3534 break :result dst_mcv;3754 break :result dst_mcv;
3535 },3755 },
3536 else => return func.fail("TODO airSliceLen for {}", .{src_mcv}),3756 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 {...@@ -3619,7 +3839,7 @@ fn genSliceElemPtr(func: *Func, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
36193839
3620 const addr_reg, const addr_lock = try func.allocReg(.int);3840 const addr_reg, const addr_lock = try func.allocReg(.int);
3621 defer func.register_manager.unlockReg(addr_lock);3841 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
3624 _ = try func.addInst(.{3844 _ = try func.addInst(.{
3625 .tag = .add,3845 .tag = .add,
...@@ -3657,12 +3877,12 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -3657,12 +3877,12 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {
3657 .register => {3877 .register => {
3658 const frame_index = try func.allocFrameIndex(FrameAlloc.initType(array_ty, pt));3878 const frame_index = try func.allocFrameIndex(FrameAlloc.initType(array_ty, pt));
3659 try func.genSetMem(.{ .frame = frame_index }, 0, array_ty, array_mcv);3879 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 } });
3661 },3881 },
3662 .load_frame => |frame_addr| {3882 .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 });
3664 },3884 },
3665 else => try func.genSetReg(Type.usize, addr_reg, array_mcv.address()),3885 else => try func.genSetReg(Type.u64, addr_reg, array_mcv.address()),
3666 }3886 }
36673887
3668 const dst_mcv = try func.allocRegOrMem(result_ty, inst, false);3888 const dst_mcv = try func.allocRegOrMem(result_ty, inst, false);
...@@ -3683,7 +3903,7 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -3683,7 +3903,7 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {
3683 // we can do a shortcut here where we don't need a vslicedown3903 // we can do a shortcut here where we don't need a vslicedown
3684 // and can just copy to the frame index.3904 // and can just copy to the frame index.
3685 if (!(index_mcv == .immediate and index_mcv.immediate == 0)) {3905 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
3688 _ = try func.addInst(.{3908 _ = try func.addInst(.{
3689 .tag = .vslidedownvx,3909 .tag = .vslidedownvx,
...@@ -3766,7 +3986,7 @@ fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void {...@@ -3766,7 +3986,7 @@ fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void {
3766 base_ptr_mcv,3986 base_ptr_mcv,
3767 base_ptr_ty,3987 base_ptr_ty,
3768 index_mcv,3988 index_mcv,
3769 Type.usize,3989 Type.u64,
3770 result_reg,3990 result_reg,
3771 );3991 );
37723992
...@@ -4371,7 +4591,7 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -4371,7 +4591,7 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {
4371 const dst_reg = if (field_off == 0)4591 const dst_reg = if (field_off == 0)
4372 (try func.copyToNewRegister(inst, src_mcv)).register4592 (try func.copyToNewRegister(inst, src_mcv)).register
4373 else4593 else
4374 try func.copyToTmpRegister(Type.usize, .{ .register = src_reg });4594 try func.copyToTmpRegister(Type.u64, .{ .register = src_reg });
43754595
4376 const dst_mcv: MCValue = .{ .register = dst_reg };4596 const dst_mcv: MCValue = .{ .register = dst_reg };
4377 const dst_lock = func.register_manager.lockReg(dst_reg);4597 const dst_lock = func.register_manager.lockReg(dst_reg);
...@@ -4431,8 +4651,8 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -4431,8 +4651,8 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {
44314651
4432 const hi_mcv =4652 const hi_mcv =
4433 dst_mcv.address().offset(@intCast(field_bit_size / 64 * 8)).deref();4653 dst_mcv.address().offset(@intCast(field_bit_size / 64 * 8)).deref();
4434 try func.genSetReg(Type.usize, tmp_reg, hi_mcv);4654 try func.genSetReg(Type.u64, tmp_reg, hi_mcv);
4435 try func.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg });4655 try func.genCopy(Type.u64, hi_mcv, .{ .register = tmp_reg });
4436 }4656 }
4437 break :result dst_mcv;4657 break :result dst_mcv;
4438 }4658 }
...@@ -4456,7 +4676,7 @@ fn genArgDbgInfo(func: Func, inst: Air.Inst.Index, mcv: MCValue) !void {...@@ -4456,7 +4676,7 @@ fn genArgDbgInfo(func: Func, inst: Air.Inst.Index, mcv: MCValue) !void {
4456 const zcu = pt.zcu;4676 const zcu = pt.zcu;
4457 const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg;4677 const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg;
4458 const ty = arg.ty.toType();4678 const ty = arg.ty.toType();
4459 const owner_decl = zcu.funcOwnerDeclIndex(func.func_index);4679 const owner_decl = func.owner.getDecl(zcu);
4460 if (arg.name == .none) return;4680 if (arg.name == .none) return;
4461 const name = func.air.nullTerminatedString(@intFromEnum(arg.name));4681 const name = func.air.nullTerminatedString(@intFromEnum(arg.name));
44624682
...@@ -4517,13 +4737,13 @@ fn airBreakpoint(func: *Func) !void {...@@ -4517,13 +4737,13 @@ fn airBreakpoint(func: *Func) !void {
45174737
4518fn airRetAddr(func: *Func, inst: Air.Inst.Index) !void {4738fn airRetAddr(func: *Func, inst: Air.Inst.Index) !void {
4519 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);4739 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 } });
4521 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });4741 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });
4522}4742}
45234743
4524fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void {4744fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void {
4525 const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true);4745 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 } });
4527 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });4747 return func.finishAir(inst, dst_mcv, .{ .none, .none, .none });
4528}4748}
45294749
...@@ -4682,7 +4902,7 @@ fn genCall(...@@ -4682,7 +4902,7 @@ fn genCall(
4682 .indirect => |reg_off| {4902 .indirect => |reg_off| {
4683 const ret_ty = Type.fromInterned(fn_info.return_type);4903 const ret_ty = Type.fromInterned(fn_info.return_type);
4684 const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(ret_ty, pt));4904 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, .{
4686 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },4906 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
4687 });4907 });
4688 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };4908 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };
...@@ -4700,7 +4920,7 @@ fn genCall(...@@ -4700,7 +4920,7 @@ fn genCall(
4700 dst_reg,4920 dst_reg,
4701 src_arg,4921 src_arg,
4702 ),4922 ),
4703 .indirect => |reg_off| try func.genSetReg(Type.usize, reg_off.reg, .{4923 .indirect => |reg_off| try func.genSetReg(Type.u64, reg_off.reg, .{
4704 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },4924 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
4705 }),4925 }),
4706 else => return func.fail("TODO: genCall actual set {s}", .{@tagName(dst_arg)}),4926 else => return func.fail("TODO: genCall actual set {s}", .{@tagName(dst_arg)}),
...@@ -4728,7 +4948,7 @@ fn genCall(...@@ -4728,7 +4948,7 @@ fn genCall(
4728 if (func.mod.pic) {4948 if (func.mod.pic) {
4729 return func.fail("TODO: genCall pic", .{});4949 return func.fail("TODO: genCall pic", .{});
4730 } else {4950 } 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 } });
4732 _ = try func.addInst(.{4952 _ = try func.addInst(.{
4733 .tag = .jalr,4953 .tag = .jalr,
4734 .ops = .rri,4954 .ops = .rri,
...@@ -4745,7 +4965,7 @@ fn genCall(...@@ -4745,7 +4965,7 @@ fn genCall(
4745 const owner_decl = zcu.declPtr(extern_func.decl);4965 const owner_decl = zcu.declPtr(extern_func.decl);
4746 const lib_name = extern_func.lib_name.toSlice(&zcu.intern_pool);4966 const lib_name = extern_func.lib_name.toSlice(&zcu.intern_pool);
4747 const decl_name = owner_decl.name.toSlice(&zcu.intern_pool);4967 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
4750 if (func.bin_file.cast(link.File.Elf)) |elf_file| {4970 if (func.bin_file.cast(link.File.Elf)) |elf_file| {
4751 _ = try func.addInst(.{4971 _ = try func.addInst(.{
...@@ -4764,7 +4984,7 @@ fn genCall(...@@ -4764,7 +4984,7 @@ fn genCall(
4764 assert(func.typeOf(callee).zigTypeTag(zcu) == .Pointer);4984 assert(func.typeOf(callee).zigTypeTag(zcu) == .Pointer);
4765 const addr_reg, const addr_lock = try func.allocReg(.int);4985 const addr_reg, const addr_lock = try func.allocReg(.int);
4766 defer func.register_manager.unlockReg(addr_lock);4986 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
4769 _ = try func.addInst(.{4989 _ = try func.addInst(.{
4770 .tag = .jalr,4990 .tag = .jalr,
...@@ -4829,7 +5049,7 @@ fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void {...@@ -4829,7 +5049,7 @@ fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
4829 const lock = func.register_manager.lockRegAssumeUnused(reg_off.reg);5049 const lock = func.register_manager.lockRegAssumeUnused(reg_off.reg);
4830 defer func.register_manager.unlockReg(lock);5050 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);
4833 try func.genSetMem(5053 try func.genSetMem(
4834 .{ .reg = reg_off.reg },5054 .{ .reg = reg_off.reg },
4835 reg_off.off,5055 reg_off.off,
...@@ -4897,14 +5117,14 @@ fn airCmp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {...@@ -4897,14 +5117,14 @@ fn airCmp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
4897 .Enum => lhs_ty.intTagType(zcu),5117 .Enum => lhs_ty.intTagType(zcu),
4898 .Int => lhs_ty,5118 .Int => lhs_ty,
4899 .Bool => Type.u1,5119 .Bool => Type.u1,
4900 .Pointer => Type.usize,5120 .Pointer => Type.u64,
4901 .ErrorSet => Type.anyerror,5121 .ErrorSet => Type.anyerror,
4902 .Optional => blk: {5122 .Optional => blk: {
4903 const payload_ty = lhs_ty.optionalChild(zcu);5123 const payload_ty = lhs_ty.optionalChild(zcu);
4904 if (!payload_ty.hasRuntimeBitsIgnoreComptime(pt)) {5124 if (!payload_ty.hasRuntimeBitsIgnoreComptime(pt)) {
4905 break :blk Type.u1;5125 break :blk Type.u1;
4906 } else if (lhs_ty.isPtrLikeOptional(zcu)) {5126 } else if (lhs_ty.isPtrLikeOptional(zcu)) {
4907 break :blk Type.usize;5127 break :blk Type.u64;
4908 } else {5128 } else {
4909 return func.fail("TODO riscv cmp non-pointer optionals", .{});5129 return func.fail("TODO riscv cmp non-pointer optionals", .{});
4910 }5130 }
...@@ -5014,7 +5234,7 @@ fn genVarDbgInfo(...@@ -5014,7 +5234,7 @@ fn genVarDbgInfo(
5014 break :blk .nop;5234 break :blk .nop;
5015 },5235 },
5016 };5236 };
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);
5018 },5238 },
5019 .plan9 => {},5239 .plan9 => {},
5020 .none => {},5240 .none => {},
...@@ -5837,7 +6057,7 @@ fn genCopy(func: *Func, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {...@@ -5837,7 +6057,7 @@ fn genCopy(func: *Func, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
5837 const src_info: ?struct { addr_reg: Register, addr_lock: ?RegisterLock } = switch (src_mcv) {6057 const src_info: ?struct { addr_reg: Register, addr_lock: ?RegisterLock } = switch (src_mcv) {
5838 .register_pair, .memory, .indirect, .load_frame => null,6058 .register_pair, .memory, .indirect, .load_frame => null,
5839 .load_symbol => src: {6059 .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());
5841 errdefer func.register_manager.unlockReg(src_addr_lock);6061 errdefer func.register_manager.unlockReg(src_addr_lock);
58426062
5843 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };6063 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };
...@@ -5889,9 +6109,9 @@ fn genInlineMemcpy(...@@ -5889,9 +6109,9 @@ fn genInlineMemcpy(
5889 const src = regs[2];6109 const src = regs[2];
5890 const dst = regs[3];6110 const dst = regs[3];
58916111
5892 try func.genSetReg(Type.usize, count, len);6112 try func.genSetReg(Type.u64, count, len);
5893 try func.genSetReg(Type.usize, src, src_ptr);6113 try func.genSetReg(Type.u64, src, src_ptr);
5894 try func.genSetReg(Type.usize, dst, dst_ptr);6114 try func.genSetReg(Type.u64, dst, dst_ptr);
58956115
5896 // if count is 0, there's nothing to copy6116 // if count is 0, there's nothing to copy
5897 _ = try func.addInst(.{6117 _ = try func.addInst(.{
...@@ -6003,9 +6223,9 @@ fn genInlineMemset(...@@ -6003,9 +6223,9 @@ fn genInlineMemset(
6003 const src = regs[1];6223 const src = regs[1];
6004 const dst = regs[2];6224 const dst = regs[2];
60056225
6006 try func.genSetReg(Type.usize, count, len);6226 try func.genSetReg(Type.u64, count, len);
6007 try func.genSetReg(Type.usize, src, src_value);6227 try func.genSetReg(Type.u64, src, src_value);
6008 try func.genSetReg(Type.usize, dst, dst_ptr);6228 try func.genSetReg(Type.u64, dst, dst_ptr);
60096229
6010 // sb src, 0(dst)6230 // sb src, 0(dst)
6011 const first_inst = try func.addInst(.{6231 const first_inst = try func.addInst(.{
...@@ -6355,7 +6575,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -6355,7 +6575,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
6355 },6575 },
6356 .lea_symbol => |sym_off| {6576 .lea_symbol => |sym_off| {
6357 assert(sym_off.off == 0);6577 assert(sym_off.off == 0);
6358 const atom_index = try func.symbolIndex();6578 const atom_index = try func.owner.getSymbolIndex(func);
63596579
6360 _ = try func.addInst(.{6580 _ = try func.addInst(.{
6361 .tag = .pseudo,6581 .tag = .pseudo,
...@@ -6437,7 +6657,7 @@ fn genSetMem(...@@ -6437,7 +6657,7 @@ fn genSetMem(
6437 },6657 },
6438 .register => |reg| {6658 .register => |reg| {
6439 if (reg.class() == .vector) {6659 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
6442 const num_elem = ty.vectorLen(zcu);6662 const num_elem = ty.vectorLen(zcu);
6443 const elem_size = ty.childType(zcu).bitSize(pt);6663 const elem_size = ty.childType(zcu).bitSize(pt);
...@@ -6614,7 +6834,7 @@ fn airArrayToSlice(func: *Func, inst: Air.Inst.Index) !void {...@@ -6614,7 +6834,7 @@ fn airArrayToSlice(func: *Func, inst: Air.Inst.Index) !void {
6614 try func.genSetMem(6834 try func.genSetMem(
6615 .{ .frame = frame_index },6835 .{ .frame = frame_index },
6616 @intCast(ptr_ty.abiSize(pt)),6836 @intCast(ptr_ty.abiSize(pt)),
6617 Type.usize,6837 Type.u64,
6618 .{ .immediate = array_len },6838 .{ .immediate = array_len },
6619 );6839 );
66206840
...@@ -6880,8 +7100,8 @@ fn airMemset(func: *Func, inst: Air.Inst.Index, safety: bool) !void {...@@ -6880,8 +7100,8 @@ fn airMemset(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
68807100
6881 const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg };7101 const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg };
68827102
6883 try func.genSetReg(Type.usize, second_elem_ptr_reg, .{ .register_offset = .{7103 try func.genSetReg(Type.u64, second_elem_ptr_reg, .{ .register_offset = .{
6884 .reg = try func.copyToTmpRegister(Type.usize, dst_ptr),7104 .reg = try func.copyToTmpRegister(Type.u64, dst_ptr),
6885 .off = elem_abi_size,7105 .off = elem_abi_size,
6886 } });7106 } });
68877107
...@@ -6934,118 +7154,52 @@ fn airMemcpy(func: *Func, inst: Air.Inst.Index) !void {...@@ -6934,118 +7154,52 @@ fn airMemcpy(func: *Func, inst: Air.Inst.Index) !void {
6934}7154}
69357155
6936fn airTagName(func: *Func, inst: Air.Inst.Index) !void {7156fn 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 {
6947 const pt = func.pt;7157 const pt = func.pt;
6948 const zcu = pt.zcu;7158 const zcu = pt.zcu;
7159
6949 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;7160 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);7164 // TODO: work out the bugs
6952 const err_mcv = try func.resolveInst(un_op);7165 if (true) return func.fail("TODO: airTagName", .{});
69537166
6954 const err_reg = try func.copyToTmpRegister(err_ty, err_mcv);7167 const param_regs = abi.Registers.Integer.function_arg_regs;
6955 const err_lock = func.register_manager.lockRegAssumeUnused(err_reg);7168 const dst_mcv = try func.allocRegOrMem(Type.u64, inst, false);
6956 defer func.register_manager.unlockReg(err_lock);7169 try func.genSetReg(Type.u64, param_regs[0], dst_mcv.address());
69577170
6958 const addr_reg, const addr_lock = try func.allocReg(.int);7171 const operand = try func.resolveInst(un_op);
6959 defer func.register_manager.unlockReg(addr_lock);7172 try func.genSetReg(enum_ty, param_regs[1], operand);
69607173
6961 // this is now the base address of the error name table7174 const lazy_sym = link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(zcu), zcu);
6962 const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, zcu);7175 const elf_file = func.bin_file.cast(link.File.Elf).?;
6963 if (func.bin_file.cast(link.File.Elf)) |elf_file| {
6964 const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err|7176 const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err|
6965 return func.fail("{s} creating lazy symbol", .{@errorName(err)});7177 return func.fail("{s} creating lazy symbol", .{@errorName(err)});
6966 const sym = elf_file.symbol(sym_index);7178 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);7180 if (func.mod.pic) {
6979 // defer func.register_manager.unlockReg(tmp_lock);7181 return func.fail("TODO: airTagName pic", .{});
69807182 } else {
6981 // we move the base address forward by the following formula: base + (errno * 8)7183 try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } });
69827184 _ = try func.addInst(.{
6983 // shifting left by 4 is the same as multiplying by 87185 .tag = .jalr,
6984 _ = try func.addInst(.{7186 .ops = .rri,
6985 .tag = .slli,7187 .data = .{ .i_type = .{
6986 .ops = .rri,7188 .rd = .ra,
6987 .data = .{ .i_type = .{7189 .rs1 = .ra,
6988 .imm12 = Immediate.u(4),7190 .imm12 = Immediate.s(0),
6989 .rd = err_reg,7191 } },
6990 .rs1 = err_reg,7192 });
6991 } },7193 }
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 );
70407194
7041 try func.genSetMem(7195 break :result dst_mcv;
7042 .{ .frame = frame.index },7196 };
7043 frame.off + 8,7197 return func.finishAir(inst, result, .{ un_op, .none, .none });
7044 Type.usize,7198}
7045 .{ .register = end_reg },
7046 );
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", .{});
7049}7203}
70507204
7051fn airSplat(func: *Func, inst: Air.Inst.Index) !void {7205fn airSplat(func: *Func, inst: Air.Inst.Index) !void {
...@@ -7231,9 +7385,10 @@ fn getResolvedInstValue(func: *Func, inst: Air.Inst.Index) *InstTracking {...@@ -7231,9 +7385,10 @@ fn getResolvedInstValue(func: *Func, inst: Air.Inst.Index) *InstTracking {
72317385
7232fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {7386fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {
7233 const pt = func.pt;7387 const pt = func.pt;
7388 const zcu = pt.zcu;
7234 const gpa = func.gpa;7389 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);
7237 const lf = func.bin_file;7392 const lf = func.bin_file;
7238 const src_loc = func.src_loc;7393 const src_loc = func.src_loc;
72397394
src/arch/riscv64/bits.zig+1-2
...@@ -251,8 +251,7 @@ pub const FrameIndex = enum(u32) {...@@ -251,8 +251,7 @@ pub const FrameIndex = enum(u32) {
251 /// This index referes to a frame dedicated to setting up args for function called251 /// This index referes to a frame dedicated to setting up args for function called
252 /// in this function. Useful for aligning args separately.252 /// in this function. Useful for aligning args separately.
253 call_frame,253 call_frame,
254 /// This index referes to the frame where callee saved registers are spilled and restore254 /// This index referes to the frame where callee saved registers are spilled and restored from.
255 /// from.
256 spill_frame,255 spill_frame,
257 /// Other indices are used for local variable stack slots256 /// Other indices are used for local variable stack slots
258 _,257 _,
src/codegen.zig+3-1
...@@ -106,7 +106,9 @@ pub fn generateLazyFunction(...@@ -106,7 +106,9 @@ pub fn generateLazyFunction(
106 const target = namespace.fileScope(zcu).mod.resolved_target.result;106 const target = namespace.fileScope(zcu).mod.resolved_target.result;
107 switch (target_util.zigBackend(target, false)) {107 switch (target_util.zigBackend(target, false)) {
108 else => unreachable,108 else => unreachable,
109 inline .stage2_x86_64 => |backend| {109 inline .stage2_x86_64,
110 .stage2_riscv64,
111 => |backend| {
110 dev.check(devFeatureForBackend(backend));112 dev.check(devFeatureForBackend(backend));
111 return importBackend(backend).generateLazy(lf, pt, src_loc, lazy_sym, code, debug_output);113 return importBackend(backend).generateLazy(lf, pt, src_loc, lazy_sym, code, debug_output);
112 },114 },