diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-09-15 18:55:39 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-09-15 19:00:35 -0700 |
| commit | b67d1810be3234c363ee2929ffcc91083bfb0ae5 (patch) | |
| tree | c4fda56637928dc68069dcdd28411d37cafd721b /src/Air.zig | |
| parent | f83a4b444c4c2fca7086fe6dbdaccc7b6d8f35ca (diff) | |
| download | zig-b67d1810be3234c363ee2929ffcc91083bfb0ae5.tar.gz zig-b67d1810be3234c363ee2929ffcc91083bfb0ae5.zip | |
stage2: implement `@atomicRmw` and `@atomicLoad`
* langref: add some more "see also" links for atomics
* Add the following AIR instructions
- atomic_load
- atomic_store_unordered
- atomic_store_monotonic
- atomic_store_release
- atomic_store_seq_cst
- atomic_rmw
* Implement those AIR instructions in LLVM and C backends.
* AstGen: make the `ty` result locations for `@atomicRmw`, `@atomicLoad`,
and `@atomicStore` be `coerced_ty` to avoid unnecessary ZIR
instructions when Sema will be doing the coercions redundantly.
* Sema for `@atomicLoad` and `@atomicRmw` is done, however Sema for
`@atomicStore` is not yet implemented.
- comptime eval for `@atomicRmw` is not yet implemented.
* Sema: flesh out `coerceInMemoryAllowed` a little bit more. It can now
handle pointers.
Diffstat (limited to 'src/Air.zig')
| -rw-r--r-- | src/Air.zig | 60 |
1 files changed, 56 insertions, 4 deletions
diff --git a/src/Air.zig b/src/Air.zig index e4289c2826..2834699d69 100644 --- a/src/Air.zig +++ b/src/Air.zig @@ -127,14 +127,11 @@ pub const Inst = struct { /// Lowers to a hardware trap instruction, or the next best thing. /// Result type is always void. breakpoint, - /// Lowers to a memory fence instruction. - /// Result type is always void. - /// Uses the `fence` field. - fence, /// Function call. /// Result type is the return type of the function being called. /// Uses the `pl_op` field with the `Call` payload. operand is the callee. call, + /// `<`. Result type is always bool. /// Uses the `bin_op` field. cmp_lt, @@ -153,6 +150,7 @@ pub const Inst = struct { /// `!=`. Result type is always bool. /// Uses the `bin_op` field. cmp_neq, + /// Conditional branch. /// Result type is always noreturn; no instructions in a block follow this one. /// Uses the `pl_op` field. Operand is the condition. Payload is `CondBr`. @@ -313,10 +311,33 @@ pub const Inst = struct { /// Given a pointer to an array, return a slice. /// Uses the `ty_op` field. array_to_slice, + /// Uses the `ty_pl` field with payload `Cmpxchg`. cmpxchg_weak, /// Uses the `ty_pl` field with payload `Cmpxchg`. cmpxchg_strong, + /// Lowers to a memory fence instruction. + /// Result type is always void. + /// Uses the `fence` field. + fence, + /// Atomically load from a pointer. + /// Result type is the element type of the pointer. + /// Uses the `atomic_load` field. + atomic_load, + /// Atomically store through a pointer. + /// Result type is always `void`. + /// Uses the `bin_op` field. LHS is pointer, RHS is element. + atomic_store_unordered, + /// Same as `atomic_store_unordered` but with `AtomicOrder.Monotonic`. + atomic_store_monotonic, + /// Same as `atomic_store_unordered` but with `AtomicOrder.Release`. + atomic_store_release, + /// Same as `atomic_store_unordered` but with `AtomicOrder.SeqCst`. + atomic_store_seq_cst, + /// Atomically read-modify-write via a pointer. + /// Result type is the element type of the pointer. + /// Uses the `pl_op` field with payload `AtomicRmw`. Operand is `ptr`. + atomic_rmw, pub fn fromCmpOp(op: std.math.CompareOperator) Tag { return switch (op) { @@ -385,6 +406,10 @@ pub const Inst = struct { column: u32, }, fence: std.builtin.AtomicOrder, + atomic_load: struct { + ptr: Ref, + order: std.builtin.AtomicOrder, + }, // Make sure we don't accidentally add a field to make this union // bigger than expected. Note that in Debug builds, Zig is allowed @@ -469,6 +494,21 @@ pub const Cmpxchg = struct { } }; +pub const AtomicRmw = struct { + operand: Inst.Ref, + /// 0b00000000000000000000000000000XXX - ordering + /// 0b0000000000000000000000000XXXX000 - op + flags: u32, + + pub fn ordering(self: AtomicRmw) std.builtin.AtomicOrder { + return @intToEnum(std.builtin.AtomicOrder, @truncate(u3, self.flags)); + } + + pub fn op(self: AtomicRmw) std.builtin.AtomicRmwOp { + return @intToEnum(std.builtin.AtomicRmwOp, @truncate(u4, self.flags >> 3)); + } +}; + pub fn getMainBody(air: Air) []const Air.Inst.Index { const body_index = air.extra[@enumToInt(ExtraIndex.main_block)]; const extra = air.extraData(Block, body_index); @@ -572,6 +612,10 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { .dbg_stmt, .store, .fence, + .atomic_store_unordered, + .atomic_store_monotonic, + .atomic_store_release, + .atomic_store_seq_cst, => return Type.initTag(.void), .ptrtoint, @@ -594,6 +638,14 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { const inner_ptr_ty = outer_ptr_ty.elemType(); return inner_ptr_ty.elemType(); }, + .atomic_load => { + const ptr_ty = air.typeOf(datas[inst].atomic_load.ptr); + return ptr_ty.elemType(); + }, + .atomic_rmw => { + const ptr_ty = air.typeOf(datas[inst].pl_op.operand); + return ptr_ty.elemType(); + }, } } |
