Commit 574028ed5e
Changed files (3)
src
arch
riscv64
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
_,
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;
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);
},