diff options
| author | David Rubin <daviru007@icloud.com> | 2024-04-16 22:44:55 -0700 |
|---|---|---|
| committer | David Rubin <daviru007@icloud.com> | 2024-05-11 02:17:24 -0700 |
| commit | ffb63a05a3327e64bcf8ec7fd05c6aab8d304480 (patch) | |
| tree | 5284c825f8126f35d756599f524a2f612620ddd4 /src | |
| parent | 2fd83d8c0a8dd28c2474b26ead8cb24d6bde0901 (diff) | |
| download | zig-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')
| -rw-r--r-- | src/arch/riscv64/CodeGen.zig | 86 | ||||
| -rw-r--r-- | src/arch/riscv64/abi.zig | 25 |
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(.{ |
