Commit abc30f7948

Andrew Kelley <andrew@ziglang.org>
2021-09-21 01:48:42
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
1 parent 4b2d7a9
src/codegen/llvm.zig
@@ -541,17 +541,21 @@ pub const DeclGen = struct {
         defer self.gpa.free(fn_param_types);
         zig_fn_type.fnParamTypes(fn_param_types);
 
-        const llvm_param = try self.gpa.alloc(*const llvm.Type, fn_param_len);
-        defer self.gpa.free(llvm_param);
-
-        for (fn_param_types) |fn_param, i| {
-            llvm_param[i] = try self.llvmType(fn_param);
+        const llvm_param_buffer = try self.gpa.alloc(*const llvm.Type, fn_param_len);
+        defer self.gpa.free(llvm_param_buffer);
+
+        var llvm_params_len: c_uint = 0;
+        for (fn_param_types) |fn_param| {
+            if (fn_param.hasCodeGenBits()) {
+                llvm_param_buffer[llvm_params_len] = try self.llvmType(fn_param);
+                llvm_params_len += 1;
+            }
         }
 
         const fn_type = llvm.functionType(
             try self.llvmType(return_type),
-            llvm_param.ptr,
-            @intCast(c_uint, fn_param_len),
+            llvm_param_buffer.ptr,
+            llvm_params_len,
             .False,
         );
         const llvm_fn = self.llvmModule().addFunction(decl.name, fn_type);
src/Sema.zig
@@ -7803,6 +7803,10 @@ fn zirAtomicLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile
         else => {},
     }
 
+    if (try sema.typeHasOnePossibleValue(block, elem_ty_src, elem_ty)) |val| {
+        return sema.addConstant(elem_ty, val);
+    }
+
     if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
         if (try ptr_val.pointerDeref(sema.arena)) |elem_val| {
             return sema.addConstant(elem_ty, elem_val);
src/type.zig
@@ -1822,6 +1822,7 @@ pub const Type = extern union {
 
             .int_signed, .int_unsigned => {
                 const bits: u16 = self.cast(Payload.Bits).?.data;
+                if (bits == 0) return 0;
                 return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8);
             },
 
test/behavior/atomics.zig
@@ -195,3 +195,27 @@ fn testAtomicRmwInt() !void {
     _ = @atomicRmw(u8, &x, .Min, 1, .SeqCst);
     try expect(x == 1);
 }
+
+test "atomics with different types" {
+    try testAtomicsWithType(bool, true, false);
+
+    try testAtomicsWithType(u1, 0, 1);
+    try testAtomicsWithType(i4, 0, 1);
+    try testAtomicsWithType(u5, 0, 1);
+    try testAtomicsWithType(i15, 0, 1);
+    try testAtomicsWithType(u24, 0, 1);
+
+    try testAtomicsWithType(u0, 0, 0);
+    try testAtomicsWithType(i0, 0, 0);
+}
+
+fn testAtomicsWithType(comptime T: type, a: T, b: T) !void {
+    var x: T = b;
+    @atomicStore(T, &x, a, .SeqCst);
+    try expect(x == a);
+    try expect(@atomicLoad(T, &x, .SeqCst) == a);
+    try expect(@atomicRmw(T, &x, .Xchg, b, .SeqCst) == a);
+    try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst) == null);
+    if (@sizeOf(T) != 0)
+        try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst).? == a);
+}
test/behavior/atomics_stage1.zig
@@ -1,28 +0,0 @@
-const std = @import("std");
-const expect = std.testing.expect;
-const expectEqual = std.testing.expectEqual;
-const builtin = @import("builtin");
-
-test "atomics with different types" {
-    try testAtomicsWithType(bool, true, false);
-
-    try testAtomicsWithType(u1, 0, 1);
-    try testAtomicsWithType(i4, 0, 1);
-    try testAtomicsWithType(u5, 0, 1);
-    try testAtomicsWithType(i15, 0, 1);
-    try testAtomicsWithType(u24, 0, 1);
-
-    try testAtomicsWithType(u0, 0, 0);
-    try testAtomicsWithType(i0, 0, 0);
-}
-
-fn testAtomicsWithType(comptime T: type, a: T, b: T) !void {
-    var x: T = b;
-    @atomicStore(T, &x, a, .SeqCst);
-    try expect(x == a);
-    try expect(@atomicLoad(T, &x, .SeqCst) == a);
-    try expect(@atomicRmw(T, &x, .Xchg, b, .SeqCst) == a);
-    try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst) == null);
-    if (@sizeOf(T) != 0)
-        try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst).? == a);
-}
test/behavior.zig
@@ -23,7 +23,6 @@ test {
             _ = @import("behavior/asm.zig");
             _ = @import("behavior/async_fn.zig");
         }
-        _ = @import("behavior/atomics_stage1.zig");
         _ = @import("behavior/await_struct.zig");
         _ = @import("behavior/bit_shifting.zig");
         _ = @import("behavior/bitcast.zig");