authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-11-13 14:35:55+07:00
committergravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-12-10 21:11:14+07:00
logfb9357f06c39622534e5a85fa3f1442deec84dc3
tree0c30cb552bbec2f026e2c5bd88836dc4127e132c
parent219b5f0ad6eada2174c20147a34b51986c8f44d5

stage2: sparc64: Implement atomic ops


3 files changed, 72 insertions(+), 7 deletions(-)

src/arch/sparc64/CodeGen.zig+70-7
...@@ -596,10 +596,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -596,10 +596,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
596 .array_to_slice => try self.airArrayToSlice(inst),596 .array_to_slice => try self.airArrayToSlice(inst),
597 .int_to_float => try self.airIntToFloat(inst),597 .int_to_float => try self.airIntToFloat(inst),
598 .float_to_int => try self.airFloatToInt(inst),598 .float_to_int => try self.airFloatToInt(inst),
599 .cmpxchg_strong => @panic("TODO try self.airCmpxchg(inst)"),599 .cmpxchg_strong,
600 .cmpxchg_weak => @panic("TODO try self.airCmpxchg(inst)"),600 .cmpxchg_weak,
601 .atomic_rmw => @panic("TODO try self.airAtomicRmw(inst)"),601 => try self.airCmpxchg(inst),
602 .atomic_load => @panic("TODO try self.airAtomicLoad(inst)"),602 .atomic_rmw => try self.airAtomicRmw(inst),
603 .atomic_load => try self.airAtomicLoad(inst),
603 .memcpy => @panic("TODO try self.airMemcpy(inst)"),604 .memcpy => @panic("TODO try self.airMemcpy(inst)"),
604 .memset => try self.airMemset(inst),605 .memset => try self.airMemset(inst),
605 .set_union_tag => try self.airSetUnionTag(inst),606 .set_union_tag => try self.airSetUnionTag(inst),
...@@ -1023,6 +1024,22 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -1023,6 +1024,22 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
1023 return self.finishAir(inst, mcv, .{ .none, .none, .none });1024 return self.finishAir(inst, mcv, .{ .none, .none, .none });
1024}1025}
10251026
1027fn airAtomicLoad(self: *Self, inst: Air.Inst.Index) !void {
1028 _ = self.air.instructions.items(.data)[inst].atomic_load;
1029
1030 return self.fail("TODO implement airAtomicLoad for {}", .{
1031 self.target.cpu.arch,
1032 });
1033}
1034
1035fn airAtomicRmw(self: *Self, inst: Air.Inst.Index) !void {
1036 _ = self.air.instructions.items(.data)[inst].pl_op;
1037
1038 return self.fail("TODO implement airAtomicRmw for {}", .{
1039 self.target.cpu.arch,
1040 });
1041}
1042
1026fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {1043fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
1027 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1044 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1028 const lhs = try self.resolveInst(bin_op.lhs);1045 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -1332,6 +1349,16 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {...@@ -1332,6 +1349,16 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {
1332 return self.finishAir(inst, result, .{ un_op, .none, .none });1349 return self.finishAir(inst, result, .{ un_op, .none, .none });
1333}1350}
13341351
1352fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {
1353 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1354 const extra = self.air.extraData(Air.Block, ty_pl.payload);
1355 _ = extra;
1356
1357 return self.fail("TODO implement airCmpxchg for {}", .{
1358 self.target.cpu.arch,
1359 });
1360}
1361
1335fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {1362fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
1336 const pl_op = self.air.instructions.items(.data)[inst].pl_op;1363 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
1337 const condition = try self.resolveInst(pl_op.operand);1364 const condition = try self.resolveInst(pl_op.operand);
...@@ -1416,6 +1443,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1416,6 +1443,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
1416 const else_value = else_values[else_idx];1443 const else_value = else_values[else_idx];
1417 const canon_mcv = if (saved_then_branch.inst_table.fetchSwapRemove(else_key)) |then_entry| blk: {1444 const canon_mcv = if (saved_then_branch.inst_table.fetchSwapRemove(else_key)) |then_entry| blk: {
1418 // The instruction's MCValue is overridden in both branches.1445 // The instruction's MCValue is overridden in both branches.
1446 log.debug("condBr put branch table (key = %{d}, value = {})", .{ else_key, then_entry.value });
1419 parent_branch.inst_table.putAssumeCapacity(else_key, then_entry.value);1447 parent_branch.inst_table.putAssumeCapacity(else_key, then_entry.value);
1420 if (else_value == .dead) {1448 if (else_value == .dead) {
1421 assert(then_entry.value == .dead);1449 assert(then_entry.value == .dead);
...@@ -2908,7 +2936,18 @@ fn binOpImmediate(...@@ -2908,7 +2936,18 @@ fn binOpImmediate(
29082936
2909 const reg = try self.register_manager.allocReg(track_inst, gp);2937 const reg = try self.register_manager.allocReg(track_inst, gp);
29102938
2911 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });2939 if (track_inst) |inst| {
2940 const mcv = .{ .register = reg };
2941 log.debug("binOpRegister move lhs %{d} to register: {} -> {}", .{ inst, lhs, mcv });
2942 branch.inst_table.putAssumeCapacity(inst, mcv);
2943
2944 // If we're moving a condition flag MCV to register,
2945 // mark it as free.
2946 if (lhs == .condition_flags) {
2947 assert(self.condition_flags_inst.? == inst);
2948 self.condition_flags_inst = null;
2949 }
2950 }
29122951
2913 break :blk reg;2952 break :blk reg;
2914 };2953 };
...@@ -3035,7 +3074,18 @@ fn binOpRegister(...@@ -3035,7 +3074,18 @@ fn binOpRegister(
3035 } else null;3074 } else null;
30363075
3037 const reg = try self.register_manager.allocReg(track_inst, gp);3076 const reg = try self.register_manager.allocReg(track_inst, gp);
3038 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });3077 if (track_inst) |inst| {
3078 const mcv = .{ .register = reg };
3079 log.debug("binOpRegister move lhs %{d} to register: {} -> {}", .{ inst, lhs, mcv });
3080 branch.inst_table.putAssumeCapacity(inst, mcv);
3081
3082 // If we're moving a condition flag MCV to register,
3083 // mark it as free.
3084 if (lhs == .condition_flags) {
3085 assert(self.condition_flags_inst.? == inst);
3086 self.condition_flags_inst = null;
3087 }
3088 }
30393089
3040 break :blk reg;3090 break :blk reg;
3041 };3091 };
...@@ -3048,7 +3098,18 @@ fn binOpRegister(...@@ -3048,7 +3098,18 @@ fn binOpRegister(
3048 } else null;3098 } else null;
30493099
3050 const reg = try self.register_manager.allocReg(track_inst, gp);3100 const reg = try self.register_manager.allocReg(track_inst, gp);
3051 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });3101 if (track_inst) |inst| {
3102 const mcv = .{ .register = reg };
3103 log.debug("binOpRegister move rhs %{d} to register: {} -> {}", .{ inst, rhs, mcv });
3104 branch.inst_table.putAssumeCapacity(inst, mcv);
3105
3106 // If we're moving a condition flag MCV to register,
3107 // mark it as free.
3108 if (rhs == .condition_flags) {
3109 assert(self.condition_flags_inst.? == inst);
3110 self.condition_flags_inst = null;
3111 }
3112 }
30523113
3053 break :blk reg;3114 break :blk reg;
3054 };3115 };
...@@ -3867,6 +3928,7 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -3867,6 +3928,7 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
3867 while (true) {3928 while (true) {
3868 i -= 1;3929 i -= 1;
3869 if (self.branch_stack.items[i].inst_table.get(inst)) |mcv| {3930 if (self.branch_stack.items[i].inst_table.get(inst)) |mcv| {
3931 log.debug("getResolvedInstValue %{} => {}", .{ inst, mcv });
3870 assert(mcv != .dead);3932 assert(mcv != .dead);
3871 return mcv;3933 return mcv;
3872 }3934 }
...@@ -4082,6 +4144,7 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {...@@ -4082,6 +4144,7 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {
4082 const prev_value = self.getResolvedInstValue(inst);4144 const prev_value = self.getResolvedInstValue(inst);
4083 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];4145 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
4084 branch.inst_table.putAssumeCapacity(inst, .dead);4146 branch.inst_table.putAssumeCapacity(inst, .dead);
4147 log.debug("%{} death: {} -> .dead", .{ inst, prev_value });
4085 switch (prev_value) {4148 switch (prev_value) {
4086 .register => |reg| {4149 .register => |reg| {
4087 self.register_manager.freeReg(reg);4150 self.register_manager.freeReg(reg);
test/behavior/bugs/13159.zig+1
...@@ -9,6 +9,7 @@ const Bar = packed struct {...@@ -9,6 +9,7 @@ const Bar = packed struct {
9};9};
1010
11test {11test {
12 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12 var foo = Bar.Baz.fizz;13 var foo = Bar.Baz.fizz;
13 try expect(foo == .fizz);14 try expect(foo == .fizz);
14}15}
test/behavior/type.zig+1
...@@ -261,6 +261,7 @@ test "Type.Struct" {...@@ -261,6 +261,7 @@ test "Type.Struct" {
261 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO261 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
262 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO262 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
263 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO263 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
264 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
264265
265 const A = @Type(@typeInfo(struct { x: u8, y: u32 }));266 const A = @Type(@typeInfo(struct { x: u8, y: u32 }));
266 const infoA = @typeInfo(A).Struct;267 const infoA = @typeInfo(A).Struct;