authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-09-20 16:48:42-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-09-20 16:48:42-07:00
logabc30f79489b68f6dc0ee4b408c63a8e783215d1
tree0979982ebfa529405ae0e6014f910a3cf496aa14
parent4b2d7a9c67760aa9a81bfd364ac0d88cbb9737f1

stage2: improve handling of 0 bit types

* Sema: zirAtomicLoad handles 0-bit types correctly * LLVM backend: when lowering function types, elide parameters with 0-bit types. * Type: abiSize handles u0/i0 correctly

6 files changed, 40 insertions(+), 36 deletions(-)

src/Sema.zig+4
...@@ -7803,6 +7803,10 @@ fn zirAtomicLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile...@@ -7803,6 +7803,10 @@ fn zirAtomicLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile
7803 else => {},7803 else => {},
7804 }7804 }
78057805
7806 if (try sema.typeHasOnePossibleValue(block, elem_ty_src, elem_ty)) |val| {
7807 return sema.addConstant(elem_ty, val);
7808 }
7809
7806 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {7810 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
7807 if (try ptr_val.pointerDeref(sema.arena)) |elem_val| {7811 if (try ptr_val.pointerDeref(sema.arena)) |elem_val| {
7808 return sema.addConstant(elem_ty, elem_val);7812 return sema.addConstant(elem_ty, elem_val);
src/codegen/llvm.zig+11-7
...@@ -541,17 +541,21 @@ pub const DeclGen = struct {...@@ -541,17 +541,21 @@ pub const DeclGen = struct {
541 defer self.gpa.free(fn_param_types);541 defer self.gpa.free(fn_param_types);
542 zig_fn_type.fnParamTypes(fn_param_types);542 zig_fn_type.fnParamTypes(fn_param_types);
543543
544 const llvm_param = try self.gpa.alloc(*const llvm.Type, fn_param_len);544 const llvm_param_buffer = try self.gpa.alloc(*const llvm.Type, fn_param_len);
545 defer self.gpa.free(llvm_param);545 defer self.gpa.free(llvm_param_buffer);
546546
547 for (fn_param_types) |fn_param, i| {547 var llvm_params_len: c_uint = 0;
548 llvm_param[i] = try self.llvmType(fn_param);548 for (fn_param_types) |fn_param| {
549 if (fn_param.hasCodeGenBits()) {
550 llvm_param_buffer[llvm_params_len] = try self.llvmType(fn_param);
551 llvm_params_len += 1;
552 }
549 }553 }
550554
551 const fn_type = llvm.functionType(555 const fn_type = llvm.functionType(
552 try self.llvmType(return_type),556 try self.llvmType(return_type),
553 llvm_param.ptr,557 llvm_param_buffer.ptr,
554 @intCast(c_uint, fn_param_len),558 llvm_params_len,
555 .False,559 .False,
556 );560 );
557 const llvm_fn = self.llvmModule().addFunction(decl.name, fn_type);561 const llvm_fn = self.llvmModule().addFunction(decl.name, fn_type);
src/type.zig+1
...@@ -1822,6 +1822,7 @@ pub const Type = extern union {...@@ -1822,6 +1822,7 @@ pub const Type = extern union {
18221822
1823 .int_signed, .int_unsigned => {1823 .int_signed, .int_unsigned => {
1824 const bits: u16 = self.cast(Payload.Bits).?.data;1824 const bits: u16 = self.cast(Payload.Bits).?.data;
1825 if (bits == 0) return 0;
1825 return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8);1826 return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8);
1826 },1827 },
18271828
test/behavior.zig-1
...@@ -23,7 +23,6 @@ test {...@@ -23,7 +23,6 @@ test {
23 _ = @import("behavior/asm.zig");23 _ = @import("behavior/asm.zig");
24 _ = @import("behavior/async_fn.zig");24 _ = @import("behavior/async_fn.zig");
25 }25 }
26 _ = @import("behavior/atomics_stage1.zig");
27 _ = @import("behavior/await_struct.zig");26 _ = @import("behavior/await_struct.zig");
28 _ = @import("behavior/bit_shifting.zig");27 _ = @import("behavior/bit_shifting.zig");
29 _ = @import("behavior/bitcast.zig");28 _ = @import("behavior/bitcast.zig");
test/behavior/atomics.zig+24
...@@ -195,3 +195,27 @@ fn testAtomicRmwInt() !void {...@@ -195,3 +195,27 @@ fn testAtomicRmwInt() !void {
195 _ = @atomicRmw(u8, &x, .Min, 1, .SeqCst);195 _ = @atomicRmw(u8, &x, .Min, 1, .SeqCst);
196 try expect(x == 1);196 try expect(x == 1);
197}197}
198
199test "atomics with different types" {
200 try testAtomicsWithType(bool, true, false);
201
202 try testAtomicsWithType(u1, 0, 1);
203 try testAtomicsWithType(i4, 0, 1);
204 try testAtomicsWithType(u5, 0, 1);
205 try testAtomicsWithType(i15, 0, 1);
206 try testAtomicsWithType(u24, 0, 1);
207
208 try testAtomicsWithType(u0, 0, 0);
209 try testAtomicsWithType(i0, 0, 0);
210}
211
212fn testAtomicsWithType(comptime T: type, a: T, b: T) !void {
213 var x: T = b;
214 @atomicStore(T, &x, a, .SeqCst);
215 try expect(x == a);
216 try expect(@atomicLoad(T, &x, .SeqCst) == a);
217 try expect(@atomicRmw(T, &x, .Xchg, b, .SeqCst) == a);
218 try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst) == null);
219 if (@sizeOf(T) != 0)
220 try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst).? == a);
221}
test/behavior/atomics_stage1.zig deleted-28
...@@ -1,28 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const builtin = @import("builtin");
5
6test "atomics with different types" {
7 try testAtomicsWithType(bool, true, false);
8
9 try testAtomicsWithType(u1, 0, 1);
10 try testAtomicsWithType(i4, 0, 1);
11 try testAtomicsWithType(u5, 0, 1);
12 try testAtomicsWithType(i15, 0, 1);
13 try testAtomicsWithType(u24, 0, 1);
14
15 try testAtomicsWithType(u0, 0, 0);
16 try testAtomicsWithType(i0, 0, 0);
17}
18
19fn testAtomicsWithType(comptime T: type, a: T, b: T) !void {
20 var x: T = b;
21 @atomicStore(T, &x, a, .SeqCst);
22 try expect(x == a);
23 try expect(@atomicLoad(T, &x, .SeqCst) == a);
24 try expect(@atomicRmw(T, &x, .Xchg, b, .SeqCst) == a);
25 try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst) == null);
26 if (@sizeOf(T) != 0)
27 try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst).? == a);
28}