| ... | @@ -56,7 +56,6 @@ gpa: Allocator, | ... | @@ -56,7 +56,6 @@ gpa: Allocator, |
| 56 | | 56 | |
| 57 | mod: *Package.Module, | 57 | mod: *Package.Module, |
| 58 | target: *const std.Target, | 58 | target: *const std.Target, |
| 59 | func_index: InternPool.Index, | | |
| 60 | debug_output: DebugInfoOutput, | 59 | debug_output: DebugInfoOutput, |
| 61 | err_msg: ?*ErrorMsg, | 60 | err_msg: ?*ErrorMsg, |
| 62 | args: []MCValue, | 61 | args: []MCValue, |
| ... | @@ -68,6 +67,8 @@ src_loc: Zcu.LazySrcLoc, | ... | @@ -68,6 +67,8 @@ src_loc: Zcu.LazySrcLoc, |
| 68 | mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, | 67 | mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, |
| 69 | mir_extra: std.ArrayListUnmanaged(u32) = .{}, | 68 | mir_extra: std.ArrayListUnmanaged(u32) = .{}, |
| 70 | | 69 | |
| | 70 | owner: Owner, |
| | 71 | |
| 71 | /// Byte offset within the source file of the ending curly. | 72 | /// Byte offset within the source file of the ending curly. |
| 72 | end_di_line: u32, | 73 | end_di_line: u32, |
| 73 | end_di_column: u32, | 74 | end_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 }; |
| 112 | const RegisterOffset = struct { reg: Register, off: i32 = 0 }; | 113 | const RegisterOffset = struct { reg: Register, off: i32 = 0 }; |
| 113 | pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 }; | 114 | pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 }; |
| 114 | | 115 | |
| | 116 | const 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 | |
| 115 | const MCValue = union(enum) { | 144 | const 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 use | 146 | /// 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 | })); |
| 818 | | 847 | |
| 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 | } |
| 878 | | 907 | |
| | 908 | pub 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 | |
| 879 | const FormatWipMirData = struct { | 1008 | const 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. |
| 1051 | fn getCsr(func: *Func, csr: CSR) !Register { | 1180 | fn 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 a | 1284 | // 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 purposely | 1285 | // 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 | } |
| 1302 | | 1431 | |
| | 1432 | fn 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 | |
| 1303 | fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { | 1528 | fn 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(); | | |
| 1721 | | 1945 | |
| | 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); |
| 1723 | | 1948 | |
| 1724 | // The total frame size is calculated by the amount of s registers you need to save * 8, as each | 1949 | // 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 | } |
| 1881 | | 2106 | |
| 1882 | fn 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 | | | |
| 1891 | fn allocFrameIndex(func: *Func, alloc: FrameAlloc) !FrameIndex { | 2107 | fn 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 | } |
| 2053 | | 2269 | |
| | 2270 | pub 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 considered | 2274 | /// 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( |
| 2594 | | 2814 | |
| 2595 | // RISC-V has no immediate mul, so we copy the size to a temporary register | 2815 | // 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 }); |
| 2598 | | 2818 | |
| 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 | ); |
| 2607 | | 2827 | |
| ... | @@ -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); |
| 2982 | | 3202 | |
| 2983 | const overflow_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = 0 }); | 3203 | const overflow_reg = try func.copyToTmpRegister(Type.u64, .{ .immediate = 0 }); |
| 2984 | | 3204 | |
| 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 | ); |
| 3050 | | 3270 | |
| ... | @@ -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; |
| 3522 | | 3742 | |
| 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; |
| 3531 | | 3751 | |
| 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 { |
| 3619 | | 3839 | |
| 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); |
| 3623 | | 3843 | |
| 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 | } |
| 3667 | | 3887 | |
| 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 vslicedown | 3903 | // 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); |
| 3687 | | 3907 | |
| 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 | ); |
| 3772 | | 3992 | |
| ... | @@ -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)).register | 4592 | (try func.copyToNewRegister(inst, src_mcv)).register |
| 4373 | else | 4593 | else |
| 4374 | try func.copyToTmpRegister(Type.usize, .{ .register = src_reg }); | 4594 | try func.copyToTmpRegister(Type.u64, .{ .register = src_reg }); |
| 4375 | | 4595 | |
| 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 { |
| 4431 | | 4651 | |
| 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)); |
| 4462 | | 4682 | |
| ... | @@ -4517,13 +4737,13 @@ fn airBreakpoint(func: *Func) !void { | ... | @@ -4517,13 +4737,13 @@ fn airBreakpoint(func: *Func) !void { |
| 4517 | | 4737 | |
| 4518 | fn airRetAddr(func: *Func, inst: Air.Inst.Index) !void { | 4738 | fn 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 | } |
| 4523 | | 4743 | |
| 4524 | fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void { | 4744 | fn 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 | } |
| 4529 | | 4749 | |
| ... | @@ -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); |
| 4749 | | 4969 | |
| 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 }); |
| 4768 | | 4988 | |
| 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); |
| 4831 | | 5051 | |
| 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); |
| 5842 | | 6062 | |
| 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]; |
| 5891 | | 6111 | |
| 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); |
| 5895 | | 6115 | |
| 5896 | // if count is 0, there's nothing to copy | 6116 | // 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]; |
| 6005 | | 6225 | |
| 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); |
| 6009 | | 6229 | |
| 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); |
| 6359 | | 6579 | |
| 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); |
| 6441 | | 6661 | |
| 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 | ); |
| 6620 | | 6840 | |
| ... | @@ -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 { |
| 6880 | | 7100 | |
| 6881 | const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg }; | 7101 | const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg }; |
| 6882 | | 7102 | |
| 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 | } }); |
| 6887 | | 7107 | |
| ... | @@ -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 | } |
| 6935 | | 7155 | |
| 6936 | fn airTagName(func: *Func, inst: Air.Inst.Index) !void { | 7156 | fn 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 | | | |
| 6946 | fn 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); |
| 6950 | | 7163 | |
| 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", .{}); |
| 6953 | | 7166 | |
| 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()); |
| 6957 | | 7170 | |
| 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); |
| 6960 | | 7173 | |
| 6961 | // this is now the base address of the error name table | 7174 | 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); | | |
| 6977 | | 7179 | |
| 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", .{}); |
| 6980 | | 7182 | } 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 } }); |
| 6982 | | 7184 | _ = try func.addInst(.{ |
| 6983 | // shifting left by 4 is the same as multiplying by 8 | 7185 | .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 | ); | | |
| 7040 | | 7194 | |
| 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 | ); | | |
| 7047 | | 7199 | |
| 7048 | return func.finishAir(inst, dst_mcv, .{ un_op, .none, .none }); | 7200 | fn airErrorName(func: *Func, inst: Air.Inst.Index) !void { |
| | 7201 | _ = inst; |
| | 7202 | return func.fail("TODO: airErrorName", .{}); |
| 7049 | } | 7203 | } |
| 7050 | | 7204 | |
| 7051 | fn airSplat(func: *Func, inst: Air.Inst.Index) !void { | 7205 | fn 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 { |
| 7231 | | 7385 | |
| 7232 | fn genTypedValue(func: *Func, val: Value) InnerError!MCValue { | 7386 | fn 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; |
| 7235 | | 7390 | |
| 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; |
| 7239 | | 7394 | |