From d17f492017c77d5d52d2fbd65eaa5c1e08b24161 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 16 Jul 2021 23:06:59 -0700 Subject: stage2: miscellaneous fixes for the branch * Breaking language change: inline assembly must use string literal syntax. This is in preparation for inline assembly improvements that involve more integration with the Zig language. This means we cannot rely on text substitution. * Liveness: properly handle inline assembly and function calls with more than 3 operands. - More than 35 operands is not yet supported. This is a low priority to implement. - This required implementation in codegen.zig as well. * Liveness: fix bug causing incorrect tomb bits. * Sema: enable switch expressions that are evaluated at compile-time. - Runtime switch instructions still need to be reworked in this branch. There was a TODO left here (by me) with a suggestion to do some bigger changes as part of the AIR memory reworking. Now that time has come and I plan to honor the suggestion in a future commit before merging this branch. * AIR printing: fix missing ')' on alive instructions. We're back to "hello world" working for the x86_64 backend. --- lib/std/atomic/Atomic.zig | 88 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 18 deletions(-) (limited to 'lib/std/atomic') diff --git a/lib/std/atomic/Atomic.zig b/lib/std/atomic/Atomic.zig index 80fb1ae297..f4e3ebda9d 100644 --- a/lib/std/atomic/Atomic.zig +++ b/lib/std/atomic/Atomic.zig @@ -178,26 +178,78 @@ pub fn Atomic(comptime T: type) type { ) u1 { // x86 supports dedicated bitwise instructions if (comptime target.cpu.arch.isX86() and @sizeOf(T) >= 2 and @sizeOf(T) <= 8) { - const instruction = switch (op) { - .Set => "lock bts", - .Reset => "lock btr", - .Toggle => "lock btc", - }; - - const suffix = switch (@sizeOf(T)) { - 2 => "w", - 4 => "l", - 8 => "q", + const old_bit: u8 = switch (@sizeOf(T)) { + 2 => switch (op) { + .Set => asm volatile ("lock btsw %[bit], %[ptr]" + // LLVM doesn't support u1 flag register return values + : [result] "={@ccc}" (-> u8) + : [ptr] "*p" (&self.value), + [bit] "X" (@as(T, bit)) + : "cc", "memory" + ), + .Reset => asm volatile ("lock btrw %[bit], %[ptr]" + // LLVM doesn't support u1 flag register return values + : [result] "={@ccc}" (-> u8) + : [ptr] "*p" (&self.value), + [bit] "X" (@as(T, bit)) + : "cc", "memory" + ), + .Toggle => asm volatile ("lock btcw %[bit], %[ptr]" + // LLVM doesn't support u1 flag register return values + : [result] "={@ccc}" (-> u8) + : [ptr] "*p" (&self.value), + [bit] "X" (@as(T, bit)) + : "cc", "memory" + ), + }, + 4 => switch (op) { + .Set => asm volatile ("lock btsl %[bit], %[ptr]" + // LLVM doesn't support u1 flag register return values + : [result] "={@ccc}" (-> u8) + : [ptr] "*p" (&self.value), + [bit] "X" (@as(T, bit)) + : "cc", "memory" + ), + .Reset => asm volatile ("lock btrl %[bit], %[ptr]" + // LLVM doesn't support u1 flag register return values + : [result] "={@ccc}" (-> u8) + : [ptr] "*p" (&self.value), + [bit] "X" (@as(T, bit)) + : "cc", "memory" + ), + .Toggle => asm volatile ("lock btcl %[bit], %[ptr]" + // LLVM doesn't support u1 flag register return values + : [result] "={@ccc}" (-> u8) + : [ptr] "*p" (&self.value), + [bit] "X" (@as(T, bit)) + : "cc", "memory" + ), + }, + 8 => switch (op) { + .Set => asm volatile ("lock btsq %[bit], %[ptr]" + // LLVM doesn't support u1 flag register return values + : [result] "={@ccc}" (-> u8) + : [ptr] "*p" (&self.value), + [bit] "X" (@as(T, bit)) + : "cc", "memory" + ), + .Reset => asm volatile ("lock btrq %[bit], %[ptr]" + // LLVM doesn't support u1 flag register return values + : [result] "={@ccc}" (-> u8) + : [ptr] "*p" (&self.value), + [bit] "X" (@as(T, bit)) + : "cc", "memory" + ), + .Toggle => asm volatile ("lock btcq %[bit], %[ptr]" + // LLVM doesn't support u1 flag register return values + : [result] "={@ccc}" (-> u8) + : [ptr] "*p" (&self.value), + [bit] "X" (@as(T, bit)) + : "cc", "memory" + ), + }, else => @compileError("Invalid atomic type " ++ @typeName(T)), }; - - const old_bit = asm volatile (instruction ++ suffix ++ " %[bit], %[ptr]" - : [result] "={@ccc}" (-> u8) // LLVM doesn't support u1 flag register return values - : [ptr] "*p" (&self.value), - [bit] "X" (@as(T, bit)) - : "cc", "memory" - ); - return @intCast(u1, old_bit); } -- cgit v1.2.3