Commit 2be3033acd
Changed files (4)
lib
std
src
arch
riscv64
lib/std/builtin.zig
@@ -759,11 +759,6 @@ else
pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr: ?usize) noreturn {
@setCold(true);
- // stage2_riscv64 backend doesn't support loops yet.
- if (builtin.zig_backend == .stage2_riscv64) {
- unreachable;
- }
-
// For backends that cannot handle the language features depended on by the
// default panic handler, we have a simpler panic handler:
if (builtin.zig_backend == .stage2_wasm or
@@ -772,7 +767,8 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr
builtin.zig_backend == .stage2_x86 or
(builtin.zig_backend == .stage2_x86_64 and (builtin.target.ofmt != .elf and builtin.target.ofmt != .macho)) or
builtin.zig_backend == .stage2_sparc64 or
- builtin.zig_backend == .stage2_spirv64)
+ builtin.zig_backend == .stage2_spirv64 or
+ builtin.zig_backend == .stage2_riscv64)
{
while (true) {
@breakpoint();
src/arch/riscv64/CodeGen.zig
@@ -301,6 +301,7 @@ pub fn generate(
.prev_di_line = func.lbrace_line,
.prev_di_column = func.lbrace_column,
.stack_size = @max(32, function.max_end_stack),
+ .code_offset_mapping = .{},
};
defer emit.deinit();
@@ -929,21 +930,16 @@ fn binOpRegister(
.cmp_gt => .cmp_gt,
else => return self.fail("TODO: binOpRegister {s}", .{@tagName(tag)}),
};
- const mir_data: Mir.Inst.Data = switch (tag) {
- .add,
- .sub,
- .cmp_eq,
- => .{ .r_type = .{
- .rd = dest_reg,
- .rs1 = lhs_reg,
- .rs2 = rhs_reg,
- } },
- else => return self.fail("TODO: binOpRegister {s}", .{@tagName(tag)}),
- };
_ = try self.addInst(.{
.tag = mir_tag,
- .data = mir_data,
+ .data = .{
+ .r_type = .{
+ .rd = dest_reg,
+ .rs1 = lhs_reg,
+ .rs2 = rhs_reg,
+ },
+ },
});
return MCValue{ .register = dest_reg };
@@ -1636,7 +1632,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
const dst_mcv = switch (src_mcv) {
.register => |src_reg| dst: {
- self.register_manager.getRegAssumeFree(src_reg, inst);
+ try self.register_manager.getReg(src_reg, inst);
break :dst src_mcv;
},
else => return self.fail("TODO: airArg {s}", .{@tagName(src_mcv)}),
@@ -1914,6 +1910,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
self.processDeath(operand);
}
try self.genBody(then_body);
+ // point at the to-be-generated else case
+ try self.performReloc(reloc, @intCast(self.mir_instructions.len));
// Revert to the previous register and stack allocation state.
@@ -1929,7 +1927,6 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
self.next_stack_offset = parent_next_stack_offset;
self.register_manager.free_registers = parent_free_registers;
- try self.performReloc(reloc);
const else_branch = self.branch_stack.addOneAssumeCapacity();
else_branch.* = .{};
@@ -2014,8 +2011,6 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
var item = self.branch_stack.pop();
item.deinit(self.gpa);
}
-
- return self.finishAir(inst, .unreach, .{ .none, .none, .none });
}
fn condBr(self: *Self, cond_ty: Type, condition: MCValue) !Mir.Inst.Index {
@@ -2027,12 +2022,12 @@ fn condBr(self: *Self, cond_ty: Type, condition: MCValue) !Mir.Inst.Index {
};
return try self.addInst(.{
- .tag = .beq,
+ .tag = .bne,
.data = .{
.b_type = .{
.rs1 = reg,
.rs2 = .zero,
- .imm12 = 0, // patched later.
+ .inst = undefined,
},
},
});
@@ -2218,7 +2213,13 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
try self.genBody(body);
for (self.blocks.getPtr(inst).?.relocs.items) |reloc| {
- try self.performReloc(reloc);
+ // here we are relocing to point at the instruction after the block.
+ // [then case]
+ // [jump to end] // this is reloced
+ // [else case]
+ // [jump to end] // this is reloced
+ // [this isn't generated yet] // point to here
+ try self.performReloc(reloc, @intCast(self.mir_instructions.len));
}
const result = self.blocks.getPtr(inst).?.mcv;
@@ -2233,11 +2234,14 @@ fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
// return self.finishAir(inst, .dead, .{ condition, .none, .none });
}
-fn performReloc(self: *Self, inst: Mir.Inst.Index) !void {
+fn performReloc(self: *Self, inst: Mir.Inst.Index, target: Mir.Inst.Index) !void {
const tag = self.mir_instructions.items(.tag)[inst];
switch (tag) {
- .beq => self.mir_instructions.items(.data)[inst].b_type.imm12 = @intCast(inst),
+ .bne,
+ .beq,
+ => self.mir_instructions.items(.data)[inst].b_type.inst = target,
+ .jal => self.mir_instructions.items(.data)[inst].j_type.inst = target,
else => return self.fail("TODO: performReloc {s}", .{@tagName(tag)}),
}
}
@@ -2283,7 +2287,7 @@ fn brVoid(self: *Self, block: Air.Inst.Index) !void {
.data = .{
.j_type = .{
.rd = .ra,
- .imm21 = undefined, // populated later through performReloc
+ .inst = undefined,
},
},
}));
@@ -2467,6 +2471,9 @@ 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)});
+
if (abi_size <= 8) {
const reg = try self.copyToTmpRegister(ty, src_val);
return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
src/arch/riscv64/Emit.zig
@@ -26,8 +26,14 @@ prev_di_line: u32,
prev_di_column: u32,
/// Relative to the beginning of `code`.
prev_di_pc: usize,
-
+/// Function's stack size. Used for backpatching.
stack_size: u32,
+/// For backward branches: stores the code offset of the target
+/// instruction
+///
+/// For forward branches: stores the code offset of the branch
+/// instruction
+code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .{},
const log = std.log.scoped(.emit);
@@ -100,6 +106,10 @@ pub fn emitMir(
}
pub fn deinit(emit: *Emit) void {
+ const comp = emit.bin_file.comp;
+ const gpa = comp.gpa;
+
+ emit.code_offset_mapping.deinit(gpa);
emit.* = undefined;
}
@@ -118,10 +128,8 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError {
}
fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) !void {
- log.debug("Line: {} {}\n", .{ line, emit.prev_di_line });
const delta_line = @as(i32, @intCast(line)) - @as(i32, @intCast(emit.prev_di_line));
const delta_pc: usize = emit.code.items.len - emit.prev_di_pc;
- log.debug("(advance pc={d} and line={d})", .{ delta_pc, delta_line });
switch (emit.debug_output) {
.dwarf => |dw| {
if (column != emit.prev_di_column) try dw.setColumn(column);
@@ -166,7 +174,7 @@ fn mirRType(emit: *Emit, inst: Mir.Inst.Index) !void {
switch (tag) {
.add => try emit.writeInstruction(Instruction.add(r_type.rd, r_type.rs1, r_type.rs2)),
.sub => try emit.writeInstruction(Instruction.sub(r_type.rd, r_type.rs1, r_type.rs2)),
- .cmp_eq => try emit.writeInstruction(Instruction.slt(r_type.rd, r_type.rs1, r_type.rs2)),
+ .cmp_gt => try emit.writeInstruction(Instruction.slt(r_type.rd, r_type.rs1, r_type.rs2)),
else => unreachable,
}
}
@@ -175,8 +183,17 @@ fn mirBType(emit: *Emit, inst: Mir.Inst.Index) !void {
const tag = emit.mir.instructions.items(.tag)[inst];
const b_type = emit.mir.instructions.items(.data)[inst].b_type;
+ const offset = @as(i64, @intCast(emit.code_offset_mapping.get(b_type.inst).?)) - @as(i64, @intCast(emit.code.items.len));
+
switch (tag) {
- .beq => try emit.writeInstruction(Instruction.beq(b_type.rs1, b_type.rs2, b_type.imm12)),
+ .beq => {
+ log.debug("beq: {} offset={}", .{ inst, offset });
+ try emit.writeInstruction(Instruction.beq(b_type.rs1, b_type.rs2, @intCast(offset)));
+ },
+ .bne => {
+ log.debug("bne: {} offset={}", .{ inst, offset });
+ try emit.writeInstruction(Instruction.bne(b_type.rs1, b_type.rs2, @intCast(offset)));
+ },
else => unreachable,
}
}
@@ -215,9 +232,12 @@ fn mirJType(emit: *Emit, inst: Mir.Inst.Index) !void {
const tag = emit.mir.instructions.items(.tag)[inst];
const j_type = emit.mir.instructions.items(.data)[inst].j_type;
+ const offset = @as(i64, @intCast(emit.code_offset_mapping.get(j_type.inst).?)) - @as(i64, @intCast(emit.code.items.len));
+
switch (tag) {
.jal => {
- try emit.writeInstruction(Instruction.jal(j_type.rd, j_type.imm21));
+ log.debug("jal: {} offset={}", .{ inst, offset });
+ try emit.writeInstruction(Instruction.jal(j_type.rd, @intCast(offset)));
},
else => unreachable,
}
@@ -304,12 +324,8 @@ fn mirPsuedo(emit: *Emit, inst: Mir.Inst.Index) !void {
},
.j => {
- const target = data.inst;
- const offset: i12 = @intCast(emit.code.items.len);
- _ = target;
-
- try emit.writeInstruction(Instruction.jal(.s0, offset));
- unreachable; // TODO: mirPsuedo j
+ const offset = @as(i64, @intCast(emit.code_offset_mapping.get(data.inst).?)) - @as(i64, @intCast(emit.code.items.len));
+ try emit.writeInstruction(Instruction.jal(.s0, @intCast(offset)));
},
else => unreachable,
@@ -401,7 +417,51 @@ fn isLoad(tag: Mir.Inst.Tag) bool {
};
}
+pub fn isBranch(tag: Mir.Inst.Tag) bool {
+ return switch (tag) {
+ .beq => true,
+ .bne => true,
+ .jal => true,
+ .j => true,
+ else => false,
+ };
+}
+
+pub fn branchTarget(emit: *Emit, inst: Mir.Inst.Index) Mir.Inst.Index {
+ const tag = emit.mir.instructions.items(.tag)[inst];
+ const data = emit.mir.instructions.items(.data)[inst];
+
+ switch (tag) {
+ .bne,
+ .beq,
+ => return data.b_type.inst,
+ .jal => return data.j_type.inst,
+ .j => return data.inst,
+ else => std.debug.panic("branchTarget {s}", .{@tagName(tag)}),
+ }
+}
+
+fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize {
+ const tag = emit.mir.instructions.items(.tag)[inst];
+
+ return switch (tag) {
+ .dbg_line,
+ .dbg_epilogue_begin,
+ .dbg_prologue_end,
+ => 0,
+
+ .psuedo_epilogue => 12, // 3 * 4
+ .psuedo_prologue => 16, // 4 * 4
+
+ .abs => 12, // 3 * 4
+
+ else => 4,
+ };
+}
+
fn lowerMir(emit: *Emit) !void {
+ const comp = emit.bin_file.comp;
+ const gpa = comp.gpa;
const mir_tags = emit.mir.instructions.items(.tag);
const mir_datas = emit.mir.instructions.items(.data);
@@ -419,5 +479,19 @@ fn lowerMir(emit: *Emit) !void {
mir_datas[inst].i_type.imm12 = -(casted_size - 12 - offset);
}
}
+
+ if (isBranch(tag)) {
+ const target_inst = emit.branchTarget(inst);
+ try emit.code_offset_mapping.put(gpa, target_inst, 0);
+ }
+ }
+ var current_code_offset: usize = 0;
+
+ for (0..mir_tags.len) |index| {
+ const inst = @as(u32, @intCast(index));
+ if (emit.code_offset_mapping.getPtr(inst)) |offset| {
+ offset.* = current_code_offset;
+ }
+ current_code_offset += emit.instructionSize(inst);
}
}
src/arch/riscv64/Mir.zig
@@ -158,14 +158,14 @@ pub const Inst = struct {
b_type: struct {
rs1: Register,
rs2: Register,
- imm12: i13,
+ inst: Inst.Index,
},
/// J-Type
///
/// Used by e.g. jal
j_type: struct {
rd: Register,
- imm21: i21,
+ inst: Inst.Index,
},
/// U-Type
///