| author | |
| committer | |
| log | abc30f79489b68f6dc0ee4b408c63a8e783215d1 |
| tree | 0979982ebfa529405ae0e6014f910a3cf496aa14 |
| parent | 4b2d7a9c67760aa9a81bfd364ac0d88cbb9737f1 |
* Sema: zirAtomicLoad handles 0-bit types correctly
* LLVM backend: when lowering function types, elide parameters
with 0-bit types.
* Type: abiSize handles u0/i0 correctly6 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 | 7803 | else => {}, |
| 7804 | 7804 | } |
| 7805 | 7805 | |
| 7806 | if (try sema.typeHasOnePossibleValue(block, elem_ty_src, elem_ty)) |val| { | |
| 7807 | return sema.addConstant(elem_ty, val); | |
| 7808 | } | |
| 7809 | ||
| 7806 | 7810 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { |
| 7807 | 7811 | if (try ptr_val.pointerDeref(sema.arena)) |elem_val| { |
| 7808 | 7812 | return sema.addConstant(elem_ty, elem_val); |
src/codegen/llvm.zig+11-7| ... | ... | @@ -541,17 +541,21 @@ pub const DeclGen = struct { |
| 541 | 541 | defer self.gpa.free(fn_param_types); |
| 542 | 542 | zig_fn_type.fnParamTypes(fn_param_types); |
| 543 | 543 | |
| 544 | const llvm_param = try self.gpa.alloc(*const llvm.Type, fn_param_len); | |
| 545 | defer self.gpa.free(llvm_param); | |
| 546 | ||
| 547 | for (fn_param_types) |fn_param, i| { | |
| 548 | llvm_param[i] = try self.llvmType(fn_param); | |
| 544 | const llvm_param_buffer = try self.gpa.alloc(*const llvm.Type, fn_param_len); | |
| 545 | defer self.gpa.free(llvm_param_buffer); | |
| 546 | ||
| 547 | var llvm_params_len: c_uint = 0; | |
| 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 | } |
| 550 | 554 | |
| 551 | 555 | const fn_type = llvm.functionType( |
| 552 | 556 | try self.llvmType(return_type), |
| 553 | llvm_param.ptr, | |
| 554 | @intCast(c_uint, fn_param_len), | |
| 557 | llvm_param_buffer.ptr, | |
| 558 | llvm_params_len, | |
| 555 | 559 | .False, |
| 556 | 560 | ); |
| 557 | 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 | 1822 | |
| 1823 | 1823 | .int_signed, .int_unsigned => { |
| 1824 | 1824 | const bits: u16 = self.cast(Payload.Bits).?.data; |
| 1825 | if (bits == 0) return 0; | |
| 1825 | 1826 | return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8); |
| 1826 | 1827 | }, |
| 1827 | 1828 |
test/behavior.zig-1| ... | ... | @@ -23,7 +23,6 @@ test { |
| 23 | 23 | _ = @import("behavior/asm.zig"); |
| 24 | 24 | _ = @import("behavior/async_fn.zig"); |
| 25 | 25 | } |
| 26 | _ = @import("behavior/atomics_stage1.zig"); | |
| 27 | 26 | _ = @import("behavior/await_struct.zig"); |
| 28 | 27 | _ = @import("behavior/bit_shifting.zig"); |
| 29 | 28 | _ = @import("behavior/bitcast.zig"); |
test/behavior/atomics.zig+24| ... | ... | @@ -195,3 +195,27 @@ fn testAtomicRmwInt() !void { |
| 195 | 195 | _ = @atomicRmw(u8, &x, .Min, 1, .SeqCst); |
| 196 | 196 | try expect(x == 1); |
| 197 | 197 | } |
| 198 | ||
| 199 | test "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 | ||
| 212 | fn 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const expect = std.testing.expect; | |
| 3 | const expectEqual = std.testing.expectEqual; | |
| 4 | const builtin = @import("builtin"); | |
| 5 | ||
| 6 | test "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 | ||
| 19 | fn 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 | } |