diff options
| author | David Rubin <daviru007@icloud.com> | 2024-07-23 18:36:51 -0700 |
|---|---|---|
| committer | David Rubin <daviru007@icloud.com> | 2024-07-26 04:05:44 -0700 |
| commit | 574028ed5ec6ad455961ed46babdb7a5fe9f68bb (patch) | |
| tree | d795c8e3f2b6611d7a610bb75469ebc2080df28c /src | |
| parent | 9bc7e8c85293fd737e7ca3fb2f783618069b6e61 (diff) | |
| download | zig-574028ed5ec6ad455961ed46babdb7a5fe9f68bb.tar.gz zig-574028ed5ec6ad455961ed46babdb7a5fe9f68bb.zip | |
riscv: boilerplate for creating lazy functions
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/riscv64/CodeGen.zig | 479 | ||||
| -rw-r--r-- | src/arch/riscv64/bits.zig | 3 | ||||
| -rw-r--r-- | src/codegen.zig | 4 |
3 files changed, 321 insertions, 165 deletions
diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index a509b799e4..d52f07438f 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -56,7 +56,6 @@ gpa: Allocator, mod: *Package.Module, target: *const std.Target, -func_index: InternPool.Index, debug_output: DebugInfoOutput, err_msg: ?*ErrorMsg, args: []MCValue, @@ -68,6 +67,8 @@ src_loc: Zcu.LazySrcLoc, mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, mir_extra: std.ArrayListUnmanaged(u32) = .{}, +owner: Owner, + /// Byte offset within the source file of the ending curly. end_di_line: u32, end_di_column: u32, @@ -112,6 +113,34 @@ const SymbolOffset = struct { sym: u32, off: i32 = 0 }; const RegisterOffset = struct { reg: Register, off: i32 = 0 }; pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 }; +const Owner = union(enum) { + func_index: InternPool.Index, + lazy_sym: link.File.LazySymbol, + + fn getDecl(owner: Owner, zcu: *Zcu) InternPool.DeclIndex { + return switch (owner) { + .func_index => |func_index| zcu.funcOwnerDeclIndex(func_index), + .lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(zcu), + }; + } + + fn getSymbolIndex(owner: Owner, func: *Func) !u32 { + const pt = func.pt; + switch (owner) { + .func_index => |func_index| { + const decl_index = func.pt.zcu.funcOwnerDeclIndex(func_index); + const elf_file = func.bin_file.cast(link.File.Elf).?; + return elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index); + }, + .lazy_sym => |lazy_sym| { + const elf_file = func.bin_file.cast(link.File.Elf).?; + return elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err| + func.fail("{s} creating lazy symbol", .{@errorName(err)}); + }, + } + } +}; + const MCValue = union(enum) { /// No runtime bits. `void` types, empty structs, u0, enums with 1 tag, etc. /// TODO Look into deleting this tag and using `dead` instead, since every use @@ -739,8 +768,8 @@ pub fn generate( .bin_file = bin_file, .liveness = liveness, .target = target, - .func_index = func_index, .debug_output = debug_output, + .owner = .{ .func_index = func_index }, .err_msg = null, .args = undefined, // populated after `resolveCallingConventionValues` .ret_mcv = undefined, // populated after `resolveCallingConventionValues` @@ -797,11 +826,11 @@ pub fn generate( function.args = call_info.args; function.ret_mcv = call_info.return_value; function.frame_allocs.set(@intFromEnum(FrameIndex.ret_addr), FrameAlloc.init(.{ - .size = Type.usize.abiSize(pt), - .alignment = Type.usize.abiAlignment(pt).min(call_info.stack_align), + .size = Type.u64.abiSize(pt), + .alignment = Type.u64.abiAlignment(pt).min(call_info.stack_align), })); function.frame_allocs.set(@intFromEnum(FrameIndex.base_ptr), FrameAlloc.init(.{ - .size = Type.usize.abiSize(pt), + .size = Type.u64.abiSize(pt), .alignment = Alignment.min( call_info.stack_align, Alignment.fromNonzeroByteUnits(function.target.stackAlignment()), @@ -813,7 +842,7 @@ pub fn generate( })); function.frame_allocs.set(@intFromEnum(FrameIndex.spill_frame), FrameAlloc.init(.{ .size = 0, - .alignment = Type.usize.abiAlignment(pt), + .alignment = Type.u64.abiAlignment(pt), })); function.gen() catch |err| switch (err) { @@ -876,6 +905,106 @@ pub fn generate( } } +pub fn generateLazy( + bin_file: *link.File, + pt: Zcu.PerThread, + src_loc: Zcu.LazySrcLoc, + lazy_sym: link.File.LazySymbol, + code: *std.ArrayList(u8), + debug_output: DebugInfoOutput, +) CodeGenError!Result { + const comp = bin_file.comp; + const gpa = comp.gpa; + const mod = comp.root_mod; + + var function: Func = .{ + .gpa = gpa, + .air = undefined, + .pt = pt, + .mod = mod, + .bin_file = bin_file, + .liveness = undefined, + .target = &mod.resolved_target.result, + .debug_output = debug_output, + .owner = .{ .lazy_sym = lazy_sym }, + .err_msg = null, + .args = undefined, // populated after `resolveCallingConventionValues` + .ret_mcv = undefined, // populated after `resolveCallingConventionValues` + .fn_type = undefined, + .arg_index = 0, + .branch_stack = undefined, + .src_loc = src_loc, + .end_di_line = undefined, + .end_di_column = undefined, + .scope_generation = 0, + .avl = null, + .vtype = null, + }; + defer { + function.mir_instructions.deinit(gpa); + function.mir_extra.deinit(gpa); + } + + function.genLazy(lazy_sym) catch |err| switch (err) { + error.CodegenFail => return Result{ .fail = function.err_msg.? }, + error.OutOfRegisters => return Result{ + .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}), + }, + else => |e| return e, + }; + + var mir: Mir = .{ + .instructions = function.mir_instructions.toOwnedSlice(), + .extra = try function.mir_extra.toOwnedSlice(gpa), + .frame_locs = function.frame_locs.toOwnedSlice(), + }; + defer mir.deinit(gpa); + + var emit: Emit = .{ + .lower = .{ + .pt = pt, + .allocator = gpa, + .mir = mir, + .cc = .Unspecified, + .src_loc = src_loc, + .output_mode = comp.config.output_mode, + .link_mode = comp.config.link_mode, + .pic = mod.pic, + }, + .bin_file = bin_file, + .debug_output = debug_output, + .code = code, + .prev_di_pc = undefined, // no debug info yet + .prev_di_line = undefined, // no debug info yet + .prev_di_column = undefined, // no debug info yet + }; + defer emit.deinit(); + + emit.emitMir() catch |err| switch (err) { + error.LowerFail, error.EmitFail => return Result{ .fail = emit.lower.err_msg.? }, + error.InvalidInstruction => |e| { + const msg = switch (e) { + error.InvalidInstruction => "CodeGen failed to find a viable instruction.", + }; + return Result{ + .fail = try ErrorMsg.create( + gpa, + src_loc, + "{s} This is a bug in the Zig compiler.", + .{msg}, + ), + }; + }, + else => |e| return e, + }; + + if (function.err_msg) |em| { + return Result{ .fail = em }; + } else { + return Result.ok; + } +} + const FormatWipMirData = struct { func: *Func, inst: Mir.Inst.Index, @@ -1050,7 +1179,7 @@ pub fn addExtraAssumeCapacity(func: *Func, extra: anytype) u32 { /// Caller's duty to lock the return register is needed. fn getCsr(func: *Func, csr: CSR) !Register { assert(func.hasFeature(.zicsr)); - const dst_reg = try func.register_manager.allocReg(null, func.regTempClassForType(Type.usize)); + const dst_reg = try func.register_manager.allocReg(null, func.regTempClassForType(Type.u64)); _ = try func.addInst(.{ .tag = .csrrs, .ops = .csr, @@ -1103,7 +1232,7 @@ fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void { }); } else { const options_int: u12 = @as(u12, 0) | @as(u8, @bitCast(options)); - const temp_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = avl }); + const temp_reg = try func.copyToTmpRegister(Type.u64, .{ .immediate = avl }); _ = try func.addInst(.{ .tag = .vsetvli, .ops = .rri, @@ -1155,11 +1284,11 @@ fn gen(func: *Func) !void { // The address where to store the return value for the caller is in a // register which the callee is free to clobber. Therefore, we purposely // spill it to stack immediately. - const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(Type.usize, pt)); + const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(Type.u64, pt)); try func.genSetMem( .{ .frame = frame_index }, 0, - Type.usize, + Type.u64, func.ret_mcv.long.address().offset(-func.ret_mcv.short.indirect.off), ); func.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } }; @@ -1300,6 +1429,102 @@ fn gen(func: *Func) !void { }); } +fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void { + const pt = func.pt; + const mod = pt.zcu; + const ip = &mod.intern_pool; + switch (lazy_sym.ty.zigTypeTag(mod)) { + .Enum => { + const enum_ty = lazy_sym.ty; + wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(pt)}); + + const param_regs = abi.Registers.Integer.function_arg_regs; + const ret_reg = param_regs[0]; + const enum_mcv: MCValue = .{ .register = param_regs[1] }; + + const exitlude_jump_relocs = try func.gpa.alloc(Mir.Inst.Index, enum_ty.enumFieldCount(mod)); + defer func.gpa.free(exitlude_jump_relocs); + + const data_reg, const data_lock = try func.allocReg(.int); + defer func.register_manager.unlockReg(data_lock); + + const elf_file = func.bin_file.cast(link.File.Elf).?; + const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, .{ + .kind = .const_data, + .ty = enum_ty, + }) catch |err| + return func.fail("{s} creating lazy symbol", .{@errorName(err)}); + const sym = elf_file.symbol(sym_index); + + try func.genSetReg(Type.u64, data_reg, .{ .lea_symbol = .{ .sym = sym.esym_index } }); + + const cmp_reg, const cmp_lock = try func.allocReg(.int); + defer func.register_manager.unlockReg(cmp_lock); + + var data_off: i32 = 0; + const tag_names = enum_ty.enumFields(mod); + for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, tag_index| { + const tag_name_len = tag_names.get(ip)[tag_index].length(ip); + const tag_val = try pt.enumValueFieldIndex(enum_ty, @intCast(tag_index)); + const tag_mcv = try func.genTypedValue(tag_val); + + _ = try func.genBinOp( + .cmp_neq, + enum_mcv, + enum_ty, + tag_mcv, + enum_ty, + cmp_reg, + ); + const skip_reloc = try func.condBr(Type.bool, .{ .register = cmp_reg }); + + try func.genSetMem( + .{ .reg = ret_reg }, + 0, + Type.u64, + .{ .register_offset = .{ .reg = data_reg, .off = data_off } }, + ); + + try func.genSetMem( + .{ .reg = ret_reg }, + 8, + Type.u64, + .{ .immediate = tag_name_len }, + ); + + exitlude_jump_reloc.* = try func.addInst(.{ + .tag = .pseudo, + .ops = .pseudo_j, + .data = .{ .inst = undefined }, + }); + func.performReloc(skip_reloc); + + data_off += @intCast(tag_name_len + 1); + } + + try func.airTrap(); + + for (exitlude_jump_relocs) |reloc| func.performReloc(reloc); + + _ = try func.addInst(.{ + .tag = .jalr, + .ops = .rri, + .data = .{ + .i_type = .{ + .rd = .zero, + .rs1 = .ra, + .imm12 = Immediate.s(0), + }, + }, + }); + }, + else => return func.fail( + "TODO implement {s} for {}", + .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(pt) }, + ), + } +} + fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { const pt = func.pt; const zcu = pt.zcu; @@ -1717,8 +1942,8 @@ fn computeFrameLayout(func: *Func) !FrameLayout { } break :blk i; }; - const saved_reg_size = save_reg_list.size(); + const saved_reg_size = save_reg_list.size(); frame_size[@intFromEnum(FrameIndex.spill_frame)] = @intCast(saved_reg_size); // 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 { } } -fn symbolIndex(func: *Func) !u32 { - const pt = func.pt; - const zcu = pt.zcu; - const decl_index = zcu.funcOwnerDeclIndex(func.func_index); - const elf_file = func.bin_file.cast(link.File.Elf).?; - const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index); - return atom_index; -} - fn allocFrameIndex(func: *Func, alloc: FrameAlloc) !FrameIndex { const frame_allocs_slice = func.frame_allocs.slice(); 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 try tracking.trackSpill(func, inst); } +pub fn spillRegisters(func: *Func, comptime registers: []const Register) !void { + inline for (registers) |reg| try func.register_manager.getKnownReg(reg, null); +} + /// Copies a value to a register without tracking the register. The register is not considered /// allocated. A second call to `copyToTmpRegister` may return the same register. /// This can have a side effect of spilling instructions to the stack to free up a register. @@ -2594,14 +2814,14 @@ fn genBinOp( // RISC-V has no immediate mul, so we copy the size to a temporary register const elem_size = lhs_ty.elemType2(zcu).abiSize(pt); - const elem_size_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = elem_size }); + const elem_size_reg = try func.copyToTmpRegister(Type.u64, .{ .immediate = elem_size }); try func.genBinOp( .mul, tmp_mcv, rhs_ty, .{ .register = elem_size_reg }, - Type.usize, + Type.u64, tmp_reg, ); @@ -2612,9 +2832,9 @@ fn genBinOp( else => unreachable, }, lhs_mcv, - Type.usize, // we know it's a pointer, so it'll be usize. + Type.u64, // we know it's a pointer, so it'll be usize. tmp_mcv, - Type.usize, + Type.u64, dst_reg, ); }, @@ -2980,7 +3200,7 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void { const rhs_reg, const rhs_lock = try func.promoteReg(rhs_ty, rhs); defer if (rhs_lock) |lock| func.register_manager.unlockReg(lock); - const overflow_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = 0 }); + const overflow_reg = try func.copyToTmpRegister(Type.u64, .{ .immediate = 0 }); const overflow_lock = func.register_manager.lockRegAssumeUnused(overflow_reg); defer func.register_manager.unlockReg(overflow_lock); @@ -3042,9 +3262,9 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void { try func.genBinOp( .cmp_neq, .{ .register = overflow_reg }, - Type.usize, + Type.u64, .{ .register = rhs_reg }, - Type.usize, + Type.u64, overflow_reg, ); @@ -3521,7 +3741,7 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void { if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv; const dst_mcv = try func.allocRegOrMem(ty, inst, true); - try func.genCopy(Type.usize, dst_mcv, len_mcv); + try func.genCopy(Type.u64, dst_mcv, len_mcv); break :result dst_mcv; }, .register_pair => |pair| { @@ -3530,7 +3750,7 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void { if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv; const dst_mcv = try func.allocRegOrMem(ty, inst, true); - try func.genCopy(Type.usize, dst_mcv, len_mcv); + try func.genCopy(Type.u64, dst_mcv, len_mcv); break :result dst_mcv; }, 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 { const addr_reg, const addr_lock = try func.allocReg(.int); defer func.register_manager.unlockReg(addr_lock); - try func.genSetReg(Type.usize, addr_reg, slice_mcv); + try func.genSetReg(Type.u64, addr_reg, slice_mcv); _ = try func.addInst(.{ .tag = .add, @@ -3657,12 +3877,12 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void { .register => { const frame_index = try func.allocFrameIndex(FrameAlloc.initType(array_ty, pt)); try func.genSetMem(.{ .frame = frame_index }, 0, array_ty, array_mcv); - try func.genSetReg(Type.usize, addr_reg, .{ .lea_frame = .{ .index = frame_index } }); + try func.genSetReg(Type.u64, addr_reg, .{ .lea_frame = .{ .index = frame_index } }); }, .load_frame => |frame_addr| { - try func.genSetReg(Type.usize, addr_reg, .{ .lea_frame = frame_addr }); + try func.genSetReg(Type.u64, addr_reg, .{ .lea_frame = frame_addr }); }, - else => try func.genSetReg(Type.usize, addr_reg, array_mcv.address()), + else => try func.genSetReg(Type.u64, addr_reg, array_mcv.address()), } const dst_mcv = try func.allocRegOrMem(result_ty, inst, false); @@ -3683,7 +3903,7 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void { // we can do a shortcut here where we don't need a vslicedown // and can just copy to the frame index. if (!(index_mcv == .immediate and index_mcv.immediate == 0)) { - const index_reg = try func.copyToTmpRegister(Type.usize, index_mcv); + const index_reg = try func.copyToTmpRegister(Type.u64, index_mcv); _ = try func.addInst(.{ .tag = .vslidedownvx, @@ -3766,7 +3986,7 @@ fn airPtrElemPtr(func: *Func, inst: Air.Inst.Index) !void { base_ptr_mcv, base_ptr_ty, index_mcv, - Type.usize, + Type.u64, result_reg, ); @@ -4371,7 +4591,7 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void { const dst_reg = if (field_off == 0) (try func.copyToNewRegister(inst, src_mcv)).register else - try func.copyToTmpRegister(Type.usize, .{ .register = src_reg }); + try func.copyToTmpRegister(Type.u64, .{ .register = src_reg }); const dst_mcv: MCValue = .{ .register = dst_reg }; const dst_lock = func.register_manager.lockReg(dst_reg); @@ -4431,8 +4651,8 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void { const hi_mcv = dst_mcv.address().offset(@intCast(field_bit_size / 64 * 8)).deref(); - try func.genSetReg(Type.usize, tmp_reg, hi_mcv); - try func.genCopy(Type.usize, hi_mcv, .{ .register = tmp_reg }); + try func.genSetReg(Type.u64, tmp_reg, hi_mcv); + try func.genCopy(Type.u64, hi_mcv, .{ .register = tmp_reg }); } break :result dst_mcv; } @@ -4456,7 +4676,7 @@ fn genArgDbgInfo(func: Func, inst: Air.Inst.Index, mcv: MCValue) !void { const zcu = pt.zcu; const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg; const ty = arg.ty.toType(); - const owner_decl = zcu.funcOwnerDeclIndex(func.func_index); + const owner_decl = func.owner.getDecl(zcu); if (arg.name == .none) return; const name = func.air.nullTerminatedString(@intFromEnum(arg.name)); @@ -4517,13 +4737,13 @@ fn airBreakpoint(func: *Func) !void { fn airRetAddr(func: *Func, inst: Air.Inst.Index) !void { const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true); - try func.genCopy(Type.usize, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } }); + try func.genCopy(Type.u64, dst_mcv, .{ .load_frame = .{ .index = .ret_addr } }); return func.finishAir(inst, dst_mcv, .{ .none, .none, .none }); } fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void { const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, true); - try func.genCopy(Type.usize, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } }); + try func.genCopy(Type.u64, dst_mcv, .{ .lea_frame = .{ .index = .base_ptr } }); return func.finishAir(inst, dst_mcv, .{ .none, .none, .none }); } @@ -4682,7 +4902,7 @@ fn genCall( .indirect => |reg_off| { const ret_ty = Type.fromInterned(fn_info.return_type); const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(ret_ty, pt)); - try func.genSetReg(Type.usize, reg_off.reg, .{ + try func.genSetReg(Type.u64, reg_off.reg, .{ .lea_frame = .{ .index = frame_index, .off = -reg_off.off }, }); call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } }; @@ -4700,7 +4920,7 @@ fn genCall( dst_reg, src_arg, ), - .indirect => |reg_off| try func.genSetReg(Type.usize, reg_off.reg, .{ + .indirect => |reg_off| try func.genSetReg(Type.u64, reg_off.reg, .{ .lea_frame = .{ .index = frame_index, .off = -reg_off.off }, }), else => return func.fail("TODO: genCall actual set {s}", .{@tagName(dst_arg)}), @@ -4728,7 +4948,7 @@ fn genCall( if (func.mod.pic) { return func.fail("TODO: genCall pic", .{}); } else { - try func.genSetReg(Type.usize, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } }); + try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } }); _ = try func.addInst(.{ .tag = .jalr, .ops = .rri, @@ -4745,7 +4965,7 @@ fn genCall( const owner_decl = zcu.declPtr(extern_func.decl); const lib_name = extern_func.lib_name.toSlice(&zcu.intern_pool); const decl_name = owner_decl.name.toSlice(&zcu.intern_pool); - const atom_index = try func.symbolIndex(); + const atom_index = try func.owner.getSymbolIndex(func); if (func.bin_file.cast(link.File.Elf)) |elf_file| { _ = try func.addInst(.{ @@ -4764,7 +4984,7 @@ fn genCall( assert(func.typeOf(callee).zigTypeTag(zcu) == .Pointer); const addr_reg, const addr_lock = try func.allocReg(.int); defer func.register_manager.unlockReg(addr_lock); - try func.genSetReg(Type.usize, addr_reg, .{ .air_ref = callee }); + try func.genSetReg(Type.u64, addr_reg, .{ .air_ref = callee }); _ = try func.addInst(.{ .tag = .jalr, @@ -4829,7 +5049,7 @@ fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void { const lock = func.register_manager.lockRegAssumeUnused(reg_off.reg); defer func.register_manager.unlockReg(lock); - try func.genSetReg(Type.usize, reg_off.reg, func.ret_mcv.long); + try func.genSetReg(Type.u64, reg_off.reg, func.ret_mcv.long); try func.genSetMem( .{ .reg = reg_off.reg }, reg_off.off, @@ -4897,14 +5117,14 @@ fn airCmp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { .Enum => lhs_ty.intTagType(zcu), .Int => lhs_ty, .Bool => Type.u1, - .Pointer => Type.usize, + .Pointer => Type.u64, .ErrorSet => Type.anyerror, .Optional => blk: { const payload_ty = lhs_ty.optionalChild(zcu); if (!payload_ty.hasRuntimeBitsIgnoreComptime(pt)) { break :blk Type.u1; } else if (lhs_ty.isPtrLikeOptional(zcu)) { - break :blk Type.usize; + break :blk Type.u64; } else { return func.fail("TODO riscv cmp non-pointer optionals", .{}); } @@ -5014,7 +5234,7 @@ fn genVarDbgInfo( break :blk .nop; }, }; - try dw.genVarDbgInfo(name, ty, zcu.funcOwnerDeclIndex(func.func_index), is_ptr, loc); + try dw.genVarDbgInfo(name, ty, func.owner.getDecl(zcu), is_ptr, loc); }, .plan9 => {}, .none => {}, @@ -5837,7 +6057,7 @@ fn genCopy(func: *Func, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void { const src_info: ?struct { addr_reg: Register, addr_lock: ?RegisterLock } = switch (src_mcv) { .register_pair, .memory, .indirect, .load_frame => null, .load_symbol => src: { - const src_addr_reg, const src_addr_lock = try func.promoteReg(Type.usize, src_mcv.address()); + const src_addr_reg, const src_addr_lock = try func.promoteReg(Type.u64, src_mcv.address()); errdefer func.register_manager.unlockReg(src_addr_lock); break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock }; @@ -5889,9 +6109,9 @@ fn genInlineMemcpy( const src = regs[2]; const dst = regs[3]; - try func.genSetReg(Type.usize, count, len); - try func.genSetReg(Type.usize, src, src_ptr); - try func.genSetReg(Type.usize, dst, dst_ptr); + try func.genSetReg(Type.u64, count, len); + try func.genSetReg(Type.u64, src, src_ptr); + try func.genSetReg(Type.u64, dst, dst_ptr); // if count is 0, there's nothing to copy _ = try func.addInst(.{ @@ -6003,9 +6223,9 @@ fn genInlineMemset( const src = regs[1]; const dst = regs[2]; - try func.genSetReg(Type.usize, count, len); - try func.genSetReg(Type.usize, src, src_value); - try func.genSetReg(Type.usize, dst, dst_ptr); + try func.genSetReg(Type.u64, count, len); + try func.genSetReg(Type.u64, src, src_value); + try func.genSetReg(Type.u64, dst, dst_ptr); // sb src, 0(dst) const first_inst = try func.addInst(.{ @@ -6355,7 +6575,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! }, .lea_symbol => |sym_off| { assert(sym_off.off == 0); - const atom_index = try func.symbolIndex(); + const atom_index = try func.owner.getSymbolIndex(func); _ = try func.addInst(.{ .tag = .pseudo, @@ -6437,7 +6657,7 @@ fn genSetMem( }, .register => |reg| { if (reg.class() == .vector) { - const addr_reg = try func.copyToTmpRegister(Type.usize, dst_ptr_mcv); + const addr_reg = try func.copyToTmpRegister(Type.u64, dst_ptr_mcv); const num_elem = ty.vectorLen(zcu); const elem_size = ty.childType(zcu).bitSize(pt); @@ -6614,7 +6834,7 @@ fn airArrayToSlice(func: *Func, inst: Air.Inst.Index) !void { try func.genSetMem( .{ .frame = frame_index }, @intCast(ptr_ty.abiSize(pt)), - Type.usize, + Type.u64, .{ .immediate = array_len }, ); @@ -6880,8 +7100,8 @@ fn airMemset(func: *Func, inst: Air.Inst.Index, safety: bool) !void { const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg }; - try func.genSetReg(Type.usize, second_elem_ptr_reg, .{ .register_offset = .{ - .reg = try func.copyToTmpRegister(Type.usize, dst_ptr), + try func.genSetReg(Type.u64, second_elem_ptr_reg, .{ .register_offset = .{ + .reg = try func.copyToTmpRegister(Type.u64, dst_ptr), .off = elem_abi_size, } }); @@ -6934,118 +7154,52 @@ fn airMemcpy(func: *Func, inst: Air.Inst.Index) !void { } fn airTagName(func: *Func, inst: Air.Inst.Index) !void { - const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op; - const operand = try func.resolveInst(un_op); - const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else { - _ = operand; - return func.fail("TODO implement airTagName for riscv64", .{}); - }; - return func.finishAir(inst, result, .{ un_op, .none, .none }); -} - -fn airErrorName(func: *Func, inst: Air.Inst.Index) !void { const pt = func.pt; const zcu = pt.zcu; + const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op; + const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: { + const enum_ty = func.typeOf(un_op); - const err_ty = func.typeOf(un_op); - const err_mcv = try func.resolveInst(un_op); + // TODO: work out the bugs + if (true) return func.fail("TODO: airTagName", .{}); - const err_reg = try func.copyToTmpRegister(err_ty, err_mcv); - const err_lock = func.register_manager.lockRegAssumeUnused(err_reg); - defer func.register_manager.unlockReg(err_lock); + const param_regs = abi.Registers.Integer.function_arg_regs; + const dst_mcv = try func.allocRegOrMem(Type.u64, inst, false); + try func.genSetReg(Type.u64, param_regs[0], dst_mcv.address()); - const addr_reg, const addr_lock = try func.allocReg(.int); - defer func.register_manager.unlockReg(addr_lock); + const operand = try func.resolveInst(un_op); + try func.genSetReg(enum_ty, param_regs[1], operand); - // this is now the base address of the error name table - const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, zcu); - if (func.bin_file.cast(link.File.Elf)) |elf_file| { + const lazy_sym = link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(zcu), zcu); + const elf_file = func.bin_file.cast(link.File.Elf).?; const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err| return func.fail("{s} creating lazy symbol", .{@errorName(err)}); const sym = elf_file.symbol(sym_index); - try func.genSetReg(Type.usize, addr_reg, .{ .load_symbol = .{ .sym = sym.esym_index } }); - } else { - return func.fail("TODO: riscv non-elf", .{}); - } - - const start_reg, const start_lock = try func.allocReg(.int); - defer func.register_manager.unlockReg(start_lock); - - const end_reg, const end_lock = try func.allocReg(.int); - defer func.register_manager.unlockReg(end_lock); - // const tmp_reg, const tmp_lock = try func.allocReg(.int); - // defer func.register_manager.unlockReg(tmp_lock); - - // we move the base address forward by the following formula: base + (errno * 8) - - // shifting left by 4 is the same as multiplying by 8 - _ = try func.addInst(.{ - .tag = .slli, - .ops = .rri, - .data = .{ .i_type = .{ - .imm12 = Immediate.u(4), - .rd = err_reg, - .rs1 = err_reg, - } }, - }); - - _ = try func.addInst(.{ - .tag = .add, - .ops = .rrr, - .data = .{ .r_type = .{ - .rd = addr_reg, - .rs1 = addr_reg, - .rs2 = err_reg, - } }, - }); - - _ = try func.addInst(.{ - .tag = .pseudo, - .ops = .pseudo_load_rm, - .data = .{ - .rm = .{ - .r = start_reg, - .m = .{ - .base = .{ .reg = addr_reg }, - .mod = .{ .size = .dword, .unsigned = true }, - }, - }, - }, - }); - - _ = try func.addInst(.{ - .tag = .pseudo, - .ops = .pseudo_load_rm, - .data = .{ - .rm = .{ - .r = end_reg, - .m = .{ - .base = .{ .reg = addr_reg }, - .mod = .{ .size = .dword, .unsigned = true }, - }, - }, - }, - }); - - const dst_mcv = try func.allocRegOrMem(func.typeOfIndex(inst), inst, false); - const frame = dst_mcv.load_frame; - try func.genSetMem( - .{ .frame = frame.index }, - frame.off, - Type.usize, - .{ .register = start_reg }, - ); + if (func.mod.pic) { + return func.fail("TODO: airTagName pic", .{}); + } else { + try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } }); + _ = try func.addInst(.{ + .tag = .jalr, + .ops = .rri, + .data = .{ .i_type = .{ + .rd = .ra, + .rs1 = .ra, + .imm12 = Immediate.s(0), + } }, + }); + } - try func.genSetMem( - .{ .frame = frame.index }, - frame.off + 8, - Type.usize, - .{ .register = end_reg }, - ); + break :result dst_mcv; + }; + return func.finishAir(inst, result, .{ un_op, .none, .none }); +} - return func.finishAir(inst, dst_mcv, .{ un_op, .none, .none }); +fn airErrorName(func: *Func, inst: Air.Inst.Index) !void { + _ = inst; + return func.fail("TODO: airErrorName", .{}); } fn airSplat(func: *Func, inst: Air.Inst.Index) !void { @@ -7231,9 +7385,10 @@ fn getResolvedInstValue(func: *Func, inst: Air.Inst.Index) *InstTracking { fn genTypedValue(func: *Func, val: Value) InnerError!MCValue { const pt = func.pt; + const zcu = pt.zcu; const gpa = func.gpa; - const owner_decl_index = pt.zcu.funcOwnerDeclIndex(func.func_index); + const owner_decl_index = func.owner.getDecl(zcu); const lf = func.bin_file; const src_loc = func.src_loc; diff --git a/src/arch/riscv64/bits.zig b/src/arch/riscv64/bits.zig index 97db43b50e..60efa077c5 100644 --- a/src/arch/riscv64/bits.zig +++ b/src/arch/riscv64/bits.zig @@ -251,8 +251,7 @@ pub const FrameIndex = enum(u32) { /// This index referes to a frame dedicated to setting up args for function called /// in this function. Useful for aligning args separately. call_frame, - /// This index referes to the frame where callee saved registers are spilled and restore - /// from. + /// This index referes to the frame where callee saved registers are spilled and restored from. spill_frame, /// Other indices are used for local variable stack slots _, diff --git a/src/codegen.zig b/src/codegen.zig index ce1488f020..9c3fd1914b 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -106,7 +106,9 @@ pub fn generateLazyFunction( const target = namespace.fileScope(zcu).mod.resolved_target.result; switch (target_util.zigBackend(target, false)) { else => unreachable, - inline .stage2_x86_64 => |backend| { + inline .stage2_x86_64, + .stage2_riscv64, + => |backend| { dev.check(devFeatureForBackend(backend)); return importBackend(backend).generateLazy(lf, pt, src_loc, lazy_sym, code, debug_output); }, |
