mirror of
https://github.com/ziglang/zig.git
synced 2026-01-21 06:45:24 +00:00
stage2: implement @atomicStore
This commit is contained in:
parent
2a0c44fff3
commit
9fa723ee50
@ -2118,7 +2118,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
|
||||
.select,
|
||||
.atomic_load,
|
||||
.atomic_rmw,
|
||||
.atomic_store,
|
||||
.mul_add,
|
||||
.builtin_call,
|
||||
.field_ptr_type,
|
||||
@ -2164,6 +2163,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
|
||||
.@"export",
|
||||
.set_eval_branch_quota,
|
||||
.ensure_err_payload_void,
|
||||
.atomic_store,
|
||||
.store,
|
||||
.store_node,
|
||||
.store_to_block_ptr,
|
||||
|
||||
70
src/Sema.zig
70
src/Sema.zig
@ -314,7 +314,6 @@ pub fn analyzeBody(
|
||||
.select => try sema.zirSelect(block, inst),
|
||||
.atomic_load => try sema.zirAtomicLoad(block, inst),
|
||||
.atomic_rmw => try sema.zirAtomicRmw(block, inst),
|
||||
.atomic_store => try sema.zirAtomicStore(block, inst),
|
||||
.mul_add => try sema.zirMulAdd(block, inst),
|
||||
.builtin_call => try sema.zirBuiltinCall(block, inst),
|
||||
.field_ptr_type => try sema.zirFieldPtrType(block, inst),
|
||||
@ -413,6 +412,11 @@ pub fn analyzeBody(
|
||||
i += 1;
|
||||
continue;
|
||||
},
|
||||
.atomic_store => {
|
||||
try sema.zirAtomicStore(block, inst);
|
||||
i += 1;
|
||||
continue;
|
||||
},
|
||||
.store => {
|
||||
try sema.zirStore(block, inst);
|
||||
i += 1;
|
||||
@ -7669,6 +7673,8 @@ fn zirCmpxchg(
|
||||
if (try sema.resolveMaybeUndefVal(block, expected_src, expected_value)) |expected_val| {
|
||||
if (try sema.resolveMaybeUndefVal(block, new_value_src, new_value)) |new_val| {
|
||||
if (expected_val.isUndef() or new_val.isUndef()) {
|
||||
// TODO: this should probably cause the memory stored at the pointer
|
||||
// to become undef as well
|
||||
return sema.addConstUndef(result_ty);
|
||||
}
|
||||
const stored_val = (try ptr_val.pointerDeref(sema.arena)) orelse break :rs ptr_src;
|
||||
@ -7830,10 +7836,38 @@ fn zirAtomicRmw(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE
|
||||
});
|
||||
}
|
||||
|
||||
fn zirAtomicStore(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
fn zirAtomicStore(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void {
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const extra = sema.code.extraData(Zir.Inst.AtomicStore, inst_data.payload_index).data;
|
||||
const src = inst_data.src();
|
||||
return sema.mod.fail(&block.base, src, "TODO: Sema.zirAtomicStore", .{});
|
||||
// zig fmt: off
|
||||
const operand_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const ptr_src : LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
|
||||
const operand_src : LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
|
||||
const order_src : LazySrcLoc = .{ .node_offset_builtin_call_arg3 = inst_data.src_node };
|
||||
// zig fmt: on
|
||||
const ptr = sema.resolveInst(extra.ptr);
|
||||
const operand_ty = sema.typeOf(ptr).elemType();
|
||||
try sema.checkAtomicOperandType(block, operand_ty_src, operand_ty);
|
||||
const operand = try sema.coerce(block, operand_ty, sema.resolveInst(extra.operand), operand_src);
|
||||
const order = try sema.resolveAtomicOrder(block, order_src, extra.ordering);
|
||||
|
||||
const air_tag: Air.Inst.Tag = switch (order) {
|
||||
.Acquire, .AcqRel => {
|
||||
return sema.mod.fail(
|
||||
&block.base,
|
||||
order_src,
|
||||
"@atomicStore atomic ordering must not be Acquire or AcqRel",
|
||||
.{},
|
||||
);
|
||||
},
|
||||
.Unordered => .atomic_store_unordered,
|
||||
.Monotonic => .atomic_store_monotonic,
|
||||
.Release => .atomic_store_release,
|
||||
.SeqCst => .atomic_store_seq_cst,
|
||||
};
|
||||
|
||||
return sema.storePtr2(block, src, ptr, ptr_src, operand, operand_src, air_tag);
|
||||
}
|
||||
|
||||
fn zirMulAdd(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
@ -9310,25 +9344,39 @@ fn coerceVarArgParam(
|
||||
return inst;
|
||||
}
|
||||
|
||||
// TODO migrate callsites to use storePtr2 instead.
|
||||
fn storePtr(
|
||||
sema: *Sema,
|
||||
block: *Scope.Block,
|
||||
src: LazySrcLoc,
|
||||
ptr: Air.Inst.Ref,
|
||||
uncasted_value: Air.Inst.Ref,
|
||||
uncasted_operand: Air.Inst.Ref,
|
||||
) !void {
|
||||
return sema.storePtr2(block, src, ptr, src, uncasted_operand, src, .store);
|
||||
}
|
||||
|
||||
fn storePtr2(
|
||||
sema: *Sema,
|
||||
block: *Scope.Block,
|
||||
src: LazySrcLoc,
|
||||
ptr: Air.Inst.Ref,
|
||||
ptr_src: LazySrcLoc,
|
||||
uncasted_operand: Air.Inst.Ref,
|
||||
operand_src: LazySrcLoc,
|
||||
air_tag: Air.Inst.Tag,
|
||||
) !void {
|
||||
const ptr_ty = sema.typeOf(ptr);
|
||||
if (ptr_ty.isConstPtr())
|
||||
return sema.mod.fail(&block.base, src, "cannot assign to constant", .{});
|
||||
|
||||
const elem_ty = ptr_ty.elemType();
|
||||
const value = try sema.coerce(block, elem_ty, uncasted_value, src);
|
||||
const operand = try sema.coerce(block, elem_ty, uncasted_operand, operand_src);
|
||||
if ((try sema.typeHasOnePossibleValue(block, src, elem_ty)) != null)
|
||||
return;
|
||||
|
||||
if (try sema.resolveDefinedValue(block, src, ptr)) |ptr_val| {
|
||||
const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: {
|
||||
if (ptr_val.castTag(.decl_ref_mut)) |decl_ref_mut| {
|
||||
const const_val = (try sema.resolveMaybeUndefVal(block, src, value)) orelse
|
||||
const const_val = (try sema.resolveMaybeUndefVal(block, operand_src, operand)) orelse
|
||||
return sema.mod.fail(&block.base, src, "cannot store runtime value in compile time variable", .{});
|
||||
|
||||
if (decl_ref_mut.data.runtime_index < block.runtime_index) {
|
||||
@ -9365,11 +9413,13 @@ fn storePtr(
|
||||
old_arena.deinit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
break :rs operand_src;
|
||||
} else ptr_src;
|
||||
|
||||
// TODO handle if the element type requires comptime
|
||||
|
||||
try sema.requireRuntimeBlock(block, src);
|
||||
_ = try block.addBinOp(.store, ptr, value);
|
||||
try sema.requireRuntimeBlock(block, runtime_src);
|
||||
_ = try block.addBinOp(air_tag, ptr, operand);
|
||||
}
|
||||
|
||||
fn bitcast(
|
||||
|
||||
19
src/Zir.zig
19
src/Zir.zig
@ -3058,7 +3058,6 @@ const Writer = struct {
|
||||
.shuffle,
|
||||
.select,
|
||||
.atomic_rmw,
|
||||
.atomic_store,
|
||||
.mul_add,
|
||||
.builtin_call,
|
||||
.field_parent_ptr,
|
||||
@ -3071,9 +3070,8 @@ const Writer = struct {
|
||||
.struct_init_ref,
|
||||
=> try self.writeStructInit(stream, inst),
|
||||
|
||||
.cmpxchg_strong,
|
||||
.cmpxchg_weak,
|
||||
=> try self.writeCmpxchg(stream, inst),
|
||||
.cmpxchg_strong, .cmpxchg_weak => try self.writeCmpxchg(stream, inst),
|
||||
.atomic_store => try self.writeAtomicStore(stream, inst),
|
||||
|
||||
.struct_init_anon,
|
||||
.struct_init_anon_ref,
|
||||
@ -3493,6 +3491,19 @@ const Writer = struct {
|
||||
try self.writeSrc(stream, inst_data.src());
|
||||
}
|
||||
|
||||
fn writeAtomicStore(self: *Writer, stream: anytype, inst: Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
|
||||
const extra = self.code.extraData(Inst.AtomicStore, inst_data.payload_index).data;
|
||||
|
||||
try self.writeInstRef(stream, extra.ptr);
|
||||
try stream.writeAll(", ");
|
||||
try self.writeInstRef(stream, extra.operand);
|
||||
try stream.writeAll(", ");
|
||||
try self.writeInstRef(stream, extra.ordering);
|
||||
try stream.writeAll(") ");
|
||||
try self.writeSrc(stream, inst_data.src());
|
||||
}
|
||||
|
||||
fn writeStructInitAnon(self: *Writer, stream: anytype, inst: Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
|
||||
const extra = self.code.extraData(Inst.StructInitAnon, inst_data.payload_index);
|
||||
|
||||
@ -130,3 +130,11 @@ test "atomic load and rmw with enum" {
|
||||
try expect(@atomicLoad(Value, &x, .SeqCst) != .a);
|
||||
try expect(@atomicLoad(Value, &x, .SeqCst) != .b);
|
||||
}
|
||||
|
||||
test "atomic store" {
|
||||
var x: u32 = 0;
|
||||
@atomicStore(u32, &x, 1, .SeqCst);
|
||||
try expect(@atomicLoad(u32, &x, .SeqCst) == 1);
|
||||
@atomicStore(u32, &x, 12345678, .SeqCst);
|
||||
try expect(@atomicLoad(u32, &x, .SeqCst) == 12345678);
|
||||
}
|
||||
|
||||
@ -3,14 +3,6 @@ const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
test "atomic store" {
|
||||
var x: u32 = 0;
|
||||
@atomicStore(u32, &x, 1, .SeqCst);
|
||||
try expect(@atomicLoad(u32, &x, .SeqCst) == 1);
|
||||
@atomicStore(u32, &x, 12345678, .SeqCst);
|
||||
try expect(@atomicLoad(u32, &x, .SeqCst) == 12345678);
|
||||
}
|
||||
|
||||
test "atomic store comptime" {
|
||||
comptime try testAtomicStore();
|
||||
try testAtomicStore();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user