aboutsummaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorDavid Rubin <daviru007@icloud.com>2024-04-16 22:44:55 -0700
committerDavid Rubin <daviru007@icloud.com>2024-05-11 02:17:24 -0700
commitffb63a05a3327e64bcf8ec7fd05c6aab8d304480 (patch)
tree5284c825f8126f35d756599f524a2f612620ddd4 /src/arch
parent2fd83d8c0a8dd28c2474b26ead8cb24d6bde0901 (diff)
downloadzig-ffb63a05a3327e64bcf8ec7fd05c6aab8d304480.tar.gz
zig-ffb63a05a3327e64bcf8ec7fd05c6aab8d304480.zip
riscv: finally fix bug + `airAggregateInit`
i just hadn't realized that I placed the `riscv_start` branch in the non-simplified starts
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/riscv64/CodeGen.zig86
-rw-r--r--src/arch/riscv64/abi.zig25
2 files changed, 81 insertions, 30 deletions
diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig
index 38d77c9c5f..ed177ed1f1 100644
--- a/src/arch/riscv64/CodeGen.zig
+++ b/src/arch/riscv64/CodeGen.zig
@@ -43,6 +43,8 @@ const callee_preserved_regs = abi.callee_preserved_regs;
const gp = abi.RegisterClass.gp;
/// Function Args
const fa = abi.RegisterClass.fa;
+/// Function Returns
+const fr = abi.RegisterClass.fr;
/// Temporary Use
const tp = abi.RegisterClass.tp;
@@ -1083,8 +1085,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.mod => try self.airMod(inst),
.shl, .shl_exact => try self.airShl(inst),
.shl_sat => try self.airShlSat(inst),
- .min => try self.airMin(inst),
- .max => try self.airMax(inst),
+ .min => try self.airMinMax(inst, .min),
+ .max => try self.airMinMax(inst, .max),
.slice => try self.airSlice(inst),
.sqrt,
@@ -1672,7 +1674,6 @@ fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {
fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
const result: MCValue = switch (self.ret_mcv.long) {
- else => unreachable,
.none => .{ .lea_frame = .{ .index = try self.allocMemPtr(inst) } },
.load_frame => .{ .register_offset = .{
.reg = (try self.copyToNewRegister(
@@ -1681,6 +1682,7 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
)).register,
.off = self.ret_mcv.short.indirect.off,
} },
+ else => |t| return self.fail("TODO: airRetPtr {s}", .{@tagName(t)}),
};
return self.finishAir(inst, result, .{ .none, .none, .none });
}
@@ -1799,7 +1801,14 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
-fn airMin(self: *Self, inst: Air.Inst.Index) !void {
+fn airMinMax(
+ self: *Self,
+ inst: Air.Inst.Index,
+ comptime tag: enum {
+ max,
+ min,
+ },
+) !void {
const zcu = self.bin_file.comp.module.?;
const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
@@ -1882,7 +1891,7 @@ fn airMin(self: *Self, inst: Air.Inst.Index) !void {
.ops = .rrr,
.data = .{ .r_type = .{
.rd = result_reg,
- .rs1 = rhs_reg,
+ .rs1 = if (tag == .min) rhs_reg else lhs_reg,
.rs2 = mask_reg,
} },
});
@@ -1892,12 +1901,6 @@ fn airMin(self: *Self, inst: Air.Inst.Index) !void {
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
}
-fn airMax(self: *Self, inst: Air.Inst.Index) !void {
- const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
- const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else return self.fail("TODO implement max for {}", .{self.target.cpu.arch});
- return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
-}
-
fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
@@ -3577,10 +3580,10 @@ fn genCall(
const func_key = zcu.intern_pool.indexToKey(func_value.ip_index);
switch (switch (func_key) {
else => func_key,
- .ptr => |ptr| switch (ptr.addr) {
+ .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) {
.decl => |decl| zcu.intern_pool.indexToKey(zcu.declPtr(decl).val.toIntern()),
else => func_key,
- },
+ } else func_key,
}) {
.func => |func| {
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
@@ -4174,8 +4177,7 @@ fn performReloc(self: *Self, inst: Mir.Inst.Index) void {
.bne,
.beq,
=> self.mir_instructions.items(.data)[inst].b_type.inst = target,
- .jal,
- => self.mir_instructions.items(.data)[inst].j_type.inst = target,
+ .jal => self.mir_instructions.items(.data)[inst].j_type.inst = target,
.pseudo => switch (ops) {
.pseudo_j => self.mir_instructions.items(.data)[inst].inst = target,
else => std.debug.panic("TODO: performReloc {s}", .{@tagName(ops)}),
@@ -5021,13 +5023,36 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
const zcu = self.bin_file.comp.module.?;
- const vector_ty = self.typeOfIndex(inst);
- const len = vector_ty.vectorLen(zcu);
+ const result_ty = self.typeOfIndex(inst);
+ const len: usize = @intCast(result_ty.arrayLen(zcu));
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra[ty_pl.payload..][0..len]);
- const result: MCValue = res: {
- if (self.liveness.isUnused(inst)) break :res .unreach;
- return self.fail("TODO implement airAggregateInit for riscv64", .{});
+ const result: MCValue = result: {
+ switch (result_ty.zigTypeTag(zcu)) {
+ .Struct => {
+ const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, zcu));
+
+ if (result_ty.containerLayout(zcu) == .@"packed") {} else for (elements, 0..) |elem, elem_i| {
+ if ((try result_ty.structFieldValueComptime(zcu, elem_i)) != null) continue;
+
+ const elem_ty = result_ty.structFieldType(elem_i, zcu);
+ const elem_off: i32 = @intCast(result_ty.structFieldOffset(elem_i, zcu));
+ const elem_mcv = try self.resolveInst(elem);
+
+ const elem_frame: FrameAddr = .{
+ .index = frame_index,
+ .off = elem_off,
+ };
+ try self.genSetStack(
+ elem_ty,
+ elem_frame,
+ elem_mcv,
+ );
+ }
+ },
+ else => return self.fail("TODO: airAggregateInit {}", .{result_ty.fmt(zcu)}),
+ }
+ break :result .{ .register = .zero };
};
if (elements.len <= Liveness.bpi - 1) {
@@ -5189,12 +5214,24 @@ fn resolveCallingConventionValues(
for (classes) |class| switch (class) {
.integer => {
- const ret_int_reg = abi.function_arg_regs[ret_int_reg_i];
+ const ret_int_reg = abi.function_ret_regs[ret_int_reg_i];
ret_int_reg_i += 1;
ret_tracking[ret_tracking_i] = InstTracking.init(.{ .register = ret_int_reg });
ret_tracking_i += 1;
},
+ .memory => {
+ const ret_int_reg = abi.function_ret_regs[ret_int_reg_i];
+ ret_int_reg_i += 1;
+ const ret_indirect_reg = abi.function_arg_regs[param_int_reg_i];
+ param_int_reg_i += 1;
+
+ ret_tracking[ret_tracking_i] = .{
+ .short = .{ .indirect = .{ .reg = ret_int_reg } },
+ .long = .{ .indirect = .{ .reg = ret_indirect_reg } },
+ };
+ ret_tracking_i += 1;
+ },
else => return self.fail("TODO: C calling convention return class {}", .{class}),
};
@@ -5226,6 +5263,13 @@ fn resolveCallingConventionValues(
arg_mcv[arg_mcv_i] = .{ .register = param_int_reg };
arg_mcv_i += 1;
},
+ .memory => {
+ const param_int_regs = abi.function_arg_regs;
+ const param_int_reg = param_int_regs[param_int_reg_i];
+
+ arg_mcv[arg_mcv_i] = .{ .indirect = .{ .reg = param_int_reg } };
+ arg_mcv_i += 1;
+ },
else => return self.fail("TODO: C calling convention arg class {}", .{class}),
} else {
arg.* = switch (arg_mcv_i) {
diff --git a/src/arch/riscv64/abi.zig b/src/arch/riscv64/abi.zig
index 5c5b0b0acd..35f5659685 100644
--- a/src/arch/riscv64/abi.zig
+++ b/src/arch/riscv64/abi.zig
@@ -96,7 +96,6 @@ pub fn classifyType(ty: Type, mod: *Module) Class {
/// There are a maximum of 8 possible return slots. Returned values are in
/// the beginning of the array; unused slots are filled with .none.
pub fn classifySystem(ty: Type, zcu: *Module) [8]Class {
- const ip = zcu.intern_pool;
var result = [1]Class{.none} ** 8;
const memory_class = [_]Class{
.memory, .none, .none, .none,
@@ -158,22 +157,17 @@ pub fn classifySystem(ty: Type, zcu: *Module) [8]Class {
std.debug.panic("TODO: classifySystem ErrorUnion > 64 bit payload", .{});
},
.Struct => {
- const loaded_struct = ip.loadStructType(ty.toIntern());
+ const layout = ty.containerLayout(zcu);
const ty_size = ty.abiSize(zcu);
- if (loaded_struct.layout == .@"packed") {
+ if (layout == .@"packed") {
assert(ty_size <= 16);
result[0] = .integer;
if (ty_size > 8) result[1] = .integer;
return result;
}
- if (ty_size > 64)
- return memory_class;
- var byte_offset: u64 = 0;
- classifyStruct(&result, &byte_offset, loaded_struct, zcu);
-
- return result;
+ return memory_class;
},
else => |bad_ty| std.debug.panic("classifySystem {s}", .{@tagName(bad_ty)}),
}
@@ -245,6 +239,10 @@ pub const function_arg_regs = [_]Register{
.a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7,
};
+pub const function_ret_regs = [_]Register{
+ .a0, .a1,
+};
+
pub const temporary_regs = [_]Register{
.t0, .t1, .t2, .t3, .t4, .t5, .t6,
};
@@ -273,6 +271,15 @@ pub const RegisterClass = struct {
break :blk set;
};
+ pub const fr: RegisterBitSet = blk: {
+ var set = RegisterBitSet.initEmpty();
+ set.setRangeValue(.{
+ .start = callee_preserved_regs.len,
+ .end = callee_preserved_regs.len + function_ret_regs.len,
+ }, true);
+ break :blk set;
+ };
+
pub const tp: RegisterBitSet = blk: {
var set = RegisterBitSet.initEmpty();
set.setRangeValue(.{