Commit 3ccf0fd4c2
Changed files (4)
lib
compiler
src
arch
riscv64
lib/compiler/test_runner.zig
@@ -12,7 +12,9 @@ var cmdline_buffer: [4096]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&cmdline_buffer);
pub fn main() void {
- if (builtin.zig_backend == .stage2_aarch64) {
+ if (builtin.zig_backend == .stage2_aarch64 or
+ builtin.zig_backend == .stage2_riscv64)
+ {
return mainSimple() catch @panic("test failure");
}
src/arch/riscv64/CodeGen.zig
@@ -1586,11 +1586,53 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty:
fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
- _ = ty_pl;
+ const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
+ const operand = extra.struct_operand;
+ const index = extra.field_index;
+ const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
+ const mod = self.bin_file.comp.module.?;
+ const src_mcv = try self.resolveInst(operand);
+ const struct_ty = self.typeOf(operand);
+ const field_ty = struct_ty.structFieldType(index, mod);
+ if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
+
+ const field_off = @as(u32, @intCast(struct_ty.structFieldOffset(index, mod)));
+
+ switch (src_mcv) {
+ .dead, .unreach => unreachable,
+ .register => |src_reg| {
+ const src_reg_lock = self.register_manager.lockRegAssumeUnused(src_reg);
+ defer self.register_manager.unlockReg(src_reg_lock);
+
+ const dst_reg = if (field_off == 0)
+ (try self.copyToNewRegister(inst, src_mcv)).register
+ else
+ try self.copyToTmpRegister(Type.usize, .{ .register = src_reg });
+
+ const dst_mcv: MCValue = .{ .register = dst_reg };
+ const dst_lock = self.register_manager.lockReg(dst_reg);
+ defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
+
+ if (field_off > 0) {
+ _ = try self.addInst(.{
+ .tag = .srli,
+ .data = .{
+ .i_type = .{
+ .imm12 = @intCast(field_off),
+ .rd = dst_reg,
+ .rs1 = dst_reg,
+ },
+ },
+ });
+ }
- return self.fail("TODO: airStructFieldVal", .{});
+ break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv);
+ },
+ else => return self.fail("TODO: airStructField {s}", .{@tagName(src_mcv)}),
+ }
+ };
- // return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
+ return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
}
fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
@@ -1626,8 +1668,6 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
self.arg_index = arg_index + 1;
const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {
- const arg_ty = self.typeOfIndex(inst);
- _ = arg_ty;
const src_mcv = self.args[arg_index];
const dst_mcv = switch (src_mcv) {
@@ -2471,12 +2511,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner
}
},
.stack_offset, .load_symbol => {
- if (true)
- return self.fail("TODO: genSetStack {s}", .{@tagName(src_val)});
+ switch (src_val) {
+ .stack_offset => |off| if (off == stack_offset) return,
+ else => {},
+ }
if (abi_size <= 8) {
const reg = try self.copyToTmpRegister(ty, src_val);
- return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
+ return self.genSetStack(ty, stack_offset, .{ .register = reg });
}
const ptr_ty = try mod.singleMutPtrType(ty);
@@ -2496,7 +2538,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner
switch (src_val) {
.stack_offset => |offset| {
- if (offset == stack_offset) return;
try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = offset });
},
.load_symbol => |sym_off| {
@@ -2553,11 +2594,34 @@ fn genInlineMemcpy(
) !void {
_ = src;
_ = dst;
- _ = len;
- _ = count;
- _ = tmp;
- return self.fail("TODO: genInlineMemcpy", .{});
+ // store 0 in the count
+ try self.genSetReg(Type.usize, count, .{ .immediate = 0 });
+
+ // compare count to length
+ const compare_inst = try self.addInst(.{
+ .tag = .cmp_gt,
+ .data = .{ .r_type = .{
+ .rd = tmp,
+ .rs1 = count,
+ .rs2 = len,
+ } },
+ });
+
+ // end if true
+ _ = try self.addInst(.{
+ .tag = .bne,
+ .data = .{
+ .b_type = .{
+ .inst = @intCast(self.mir_instructions.len + 0), // points after the last inst
+ .rs1 = .zero,
+ .rs2 = tmp,
+ },
+ },
+ });
+ _ = compare_inst;
+
+ return self.fail("TODO: finish genInlineMemcpy", .{});
}
/// Sets the value of `src_val` into `reg`. Assumes you have a lock on it.
@@ -2567,7 +2631,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_val: MCValue) InnerError!
switch (src_val) {
.dead => unreachable,
- .ptr_stack_offset => return self.fail("TODO genSetReg ptr_stack_offset", .{}),
+ .ptr_stack_offset => |off| try self.genSetReg(ty, reg, .{ .stack_offset = off }),
.unreach, .none => return, // Nothing to do.
.undef => {
if (!self.wantSafety())
src/arch/riscv64/Emit.zig
@@ -98,6 +98,8 @@ pub fn emitMir(
.sh => try emit.mirIType(inst),
.sb => try emit.mirIType(inst),
+ .srli => try emit.mirIType(inst),
+
.ldr_ptr_stack => try emit.mirIType(inst),
.load_symbol => try emit.mirLoadSymbol(inst),
@@ -224,6 +226,8 @@ fn mirIType(emit: *Emit, inst: Mir.Inst.Index) !void {
try emit.writeInstruction(Instruction.subw(i_type.rs1, i_type.rs1, i_type.rd));
},
+ .srli => try emit.writeInstruction(Instruction.srli(i_type.rd, i_type.rs1, @intCast(i_type.imm12))),
+
else => unreachable,
}
}
src/arch/riscv64/Mir.zig
@@ -41,6 +41,9 @@ pub const Inst = struct {
/// Absolute Value, uses i_type payload.
abs,
+ /// Logical Right Shift, uses i_type payload
+ srli,
+
jal,
/// Jumps. Uses `inst` payload.
j,