@@ -14715,51 +14715,64 @@ fn checkNumericType(
1471514715 }
1471614716}
1471714717
14718- fn checkAtomicOperandType(
14718+ /// Returns the casted pointer.
14719+ fn checkAtomicPtrOperand(
1471914720 sema: *Sema,
1472014721 block: *Block,
14721- ty_src: LazySrcLoc,
14722- ty: Type,
14723- ) CompileError!void {
14724- var buffer: Type.Payload.Bits = undefined;
14722+ elem_ty: Type,
14723+ elem_ty_src: LazySrcLoc,
14724+ ptr: Air.Inst.Ref,
14725+ ptr_src: LazySrcLoc,
14726+ ptr_const: bool,
14727+ ) CompileError!Air.Inst.Ref {
1472514728 const target = sema.mod.getTarget();
14726- const max_atomic_bits = target_util.largestAtomicBits(target);
14727- const int_ty = switch (ty.zigTypeTag()) {
14728- .Int => ty,
14729- .Enum => ty.intTagType(&buffer),
14730- .Float => {
14731- const bit_count = ty.floatBits(target);
14732- if (bit_count > max_atomic_bits) {
14733- return sema.fail(
14734- block,
14735- ty_src,
14736- "expected {d}-bit float type or smaller; found {d}-bit float type",
14737- .{ max_atomic_bits, bit_count },
14738- );
14739- }
14740- return;
14741- },
14742- .Bool => return, // Will be treated as `u8`.
14743- else => {
14744- if (ty.isPtrAtRuntime()) return;
14729+ var diag: target_util.AtomicPtrAlignmentDiagnostics = .{};
14730+ const alignment = target_util.atomicPtrAlignment(target, elem_ty, &diag) catch |err| switch (err) {
14731+ error.FloatTooBig => return sema.fail(
14732+ block,
14733+ elem_ty_src,
14734+ "expected {d}-bit float type or smaller; found {d}-bit float type",
14735+ .{ diag.max_bits, diag.bits },
14736+ ),
14737+ error.IntTooBig => return sema.fail(
14738+ block,
14739+ elem_ty_src,
14740+ "expected {d}-bit integer type or smaller; found {d}-bit integer type",
14741+ .{ diag.max_bits, diag.bits },
14742+ ),
14743+ error.BadType => return sema.fail(
14744+ block,
14745+ elem_ty_src,
14746+ "expected bool, integer, float, enum, or pointer type; found {}",
14747+ .{elem_ty.fmt(sema.mod)},
14748+ ),
14749+ };
1474514750
14746- return sema.fail(
14747- block,
14748- ty_src,
14749- "expected bool, integer, float, enum, or pointer type; found {}",
14750- .{ty.fmt(sema.mod)},
14751- );
14751+ var wanted_ptr_data: Type.Payload.Pointer.Data = .{
14752+ .pointee_type = elem_ty,
14753+ .@"align" = alignment,
14754+ .@"addrspace" = .generic,
14755+ .mutable = !ptr_const,
14756+ };
14757+
14758+ const ptr_ty = sema.typeOf(ptr);
14759+ const ptr_data = switch (try ptr_ty.zigTypeTagOrPoison()) {
14760+ .Pointer => ptr_ty.ptrInfo().data,
14761+ else => {
14762+ const wanted_ptr_ty = try Type.ptr(sema.arena, sema.mod, wanted_ptr_data);
14763+ _ = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src);
14764+ unreachable;
1475214765 },
1475314766 };
14754- const bit_count = int_ty.intInfo(target).bits;
14755- if (bit_count > max_atomic_bits) {
14756- return sema.fail(
14757- block,
14758- ty_src,
14759- "expected {d}-bit integer type or smaller; found {d}-bit integer type",
14760- .{ max_atomic_bits, bit_count },
14761- );
14762- }
14767+
14768+ wanted_ptr_data.@"addrspace" = ptr_data.@"addrspace";
14769+ wanted_ptr_data.@"allowzero" = ptr_data.@"allowzero";
14770+ wanted_ptr_data.@"volatile" = ptr_data.@"volatile";
14771+
14772+ const wanted_ptr_ty = try Type.ptr(sema.arena, sema.mod, wanted_ptr_data);
14773+ const casted_ptr = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src);
14774+
14775+ return casted_ptr;
1476314776}
1476414777
1476514778fn checkPtrIsNotComptimeMutable(
@@ -15036,10 +15049,8 @@ fn zirCmpxchg(
1503615049 const success_order_src: LazySrcLoc = .{ .node_offset_builtin_call_arg4 = inst_data.src_node };
1503715050 const failure_order_src: LazySrcLoc = .{ .node_offset_builtin_call_arg5 = inst_data.src_node };
1503815051 // zig fmt: on
15039- const ptr = sema.resolveInst(extra.ptr);
15040- const ptr_ty = sema.typeOf(ptr);
15041- const elem_ty = ptr_ty.elemType();
15042- try sema.checkAtomicOperandType(block, elem_ty_src, elem_ty);
15052+ const expected_value = sema.resolveInst(extra.expected_value);
15053+ const elem_ty = sema.typeOf(expected_value);
1504315054 if (elem_ty.zigTypeTag() == .Float) {
1504415055 return sema.fail(
1504515056 block,
@@ -15048,7 +15059,8 @@ fn zirCmpxchg(
1504815059 .{elem_ty.fmt(sema.mod)},
1504915060 );
1505015061 }
15051- const expected_value = try sema.coerce(block, elem_ty, sema.resolveInst(extra.expected_value), expected_src);
15062+ const uncasted_ptr = sema.resolveInst(extra.ptr);
15063+ const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, false);
1505215064 const new_value = try sema.coerce(block, elem_ty, sema.resolveInst(extra.new_value), new_value_src);
1505315065 const success_order = try sema.resolveAtomicOrder(block, success_order_src, extra.success_order);
1505415066 const failure_order = try sema.resolveAtomicOrder(block, failure_order_src, extra.failure_order);
@@ -15081,6 +15093,7 @@ fn zirCmpxchg(
1508115093 // to become undef as well
1508215094 return sema.addConstUndef(result_ty);
1508315095 }
15096+ const ptr_ty = sema.typeOf(ptr);
1508415097 const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src;
1508515098 const result_val = if (stored_val.eql(expected_val, elem_ty, sema.mod)) blk: {
1508615099 try sema.storePtr(block, src, ptr, new_value);
@@ -15487,17 +15500,16 @@ fn zirSelect(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1548715500
1548815501fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1548915502 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
15490- const extra = sema.code.extraData(Zir.Inst.Bin , inst_data.payload_index).data;
15503+ const extra = sema.code.extraData(Zir.Inst.AtomicLoad , inst_data.payload_index).data;
1549115504 // zig fmt: off
1549215505 const elem_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1549315506 const ptr_src : LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
1549415507 const order_src : LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
1549515508 // zig fmt: on
15496- const ptr = sema.resolveInst(extra.lhs);
15497- const ptr_ty = sema.typeOf(ptr);
15498- const elem_ty = ptr_ty.elemType();
15499- try sema.checkAtomicOperandType(block, elem_ty_src, elem_ty);
15500- const order = try sema.resolveAtomicOrder(block, order_src, extra.rhs);
15509+ const elem_ty = try sema.resolveType(block, elem_ty_src, extra.elem_type);
15510+ const uncasted_ptr = sema.resolveInst(extra.ptr);
15511+ const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, true);
15512+ const order = try sema.resolveAtomicOrder(block, order_src, extra.ordering);
1550115513
1550215514 switch (order) {
1550315515 .Release, .AcqRel => {
@@ -15516,7 +15528,7 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1551615528 }
1551715529
1551815530 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
15519- if (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty )) |elem_val| {
15531+ if (try sema.pointerDeref(block, ptr_src, ptr_val, sema.typeOf(ptr) )) |elem_val| {
1552015532 return sema.addConstant(elem_ty, elem_val);
1552115533 }
1552215534 }
@@ -15536,19 +15548,19 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1553615548 const extra = sema.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data;
1553715549 const src = inst_data.src();
1553815550 // zig fmt: off
15539- const operand_ty_src : LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
15551+ const elem_ty_src : LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1554015552 const ptr_src : LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
1554115553 const op_src : LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
1554215554 const operand_src : LazySrcLoc = .{ .node_offset_builtin_call_arg3 = inst_data.src_node };
1554315555 const order_src : LazySrcLoc = .{ .node_offset_builtin_call_arg4 = inst_data.src_node };
1554415556 // zig fmt: on
15545- const ptr = sema.resolveInst(extra.ptr );
15546- const ptr_ty = sema.typeOf(ptr );
15547- const operand_ty = ptr_ty.elemType( );
15548- try sema.checkAtomicOperandType (block, operand_ty_src, operand_ty );
15557+ const operand = sema.resolveInst(extra.operand );
15558+ const elem_ty = sema.typeOf(operand );
15559+ const uncasted_ptr = sema.resolveInst(extra.ptr );
15560+ const ptr = try sema.checkAtomicPtrOperand (block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, false );
1554915561 const op = try sema.resolveAtomicRmwOp(block, op_src, extra.operation);
1555015562
15551- switch (operand_ty .zigTypeTag()) {
15563+ switch (elem_ty .zigTypeTag()) {
1555215564 .Enum => if (op != .Xchg) {
1555315565 return sema.fail(block, op_src, "@atomicRmw with enum only allowed with .Xchg", .{});
1555415566 },
@@ -15561,16 +15573,15 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1556115573 },
1556215574 else => {},
1556315575 }
15564- const operand = try sema.coerce(block, operand_ty, sema.resolveInst(extra.operand), operand_src);
1556515576 const order = try sema.resolveAtomicOrder(block, order_src, extra.ordering);
1556615577
1556715578 if (order == .Unordered) {
1556815579 return sema.fail(block, order_src, "@atomicRmw atomic ordering must not be Unordered", .{});
1556915580 }
1557015581
1557115582 // special case zero bit types
15572- if (try sema.typeHasOnePossibleValue(block, operand_ty_src, operand_ty )) |val| {
15573- return sema.addConstant(operand_ty , val);
15583+ if (try sema.typeHasOnePossibleValue(block, elem_ty_src, elem_ty )) |val| {
15584+ return sema.addConstant(elem_ty , val);
1557415585 }
1557515586
1557615587 const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: {
@@ -15581,22 +15592,23 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1558115592 };
1558215593 if (ptr_val.isComptimeMutablePtr()) {
1558315594 const target = sema.mod.getTarget();
15595+ const ptr_ty = sema.typeOf(ptr);
1558415596 const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src;
1558515597 const new_val = switch (op) {
1558615598 // zig fmt: off
1558715599 .Xchg => operand_val,
15588- .Add => try stored_val.numberAddWrap(operand_val, operand_ty , sema.arena, target),
15589- .Sub => try stored_val.numberSubWrap(operand_val, operand_ty , sema.arena, target),
15590- .And => try stored_val.bitwiseAnd (operand_val, operand_ty , sema.arena, target),
15591- .Nand => try stored_val.bitwiseNand (operand_val, operand_ty , sema.arena, target),
15592- .Or => try stored_val.bitwiseOr (operand_val, operand_ty , sema.arena, target),
15593- .Xor => try stored_val.bitwiseXor (operand_val, operand_ty , sema.arena, target),
15594- .Max => stored_val.numberMax (operand_val, target),
15595- .Min => stored_val.numberMin (operand_val, target),
15600+ .Add => try stored_val.numberAddWrap(operand_val, elem_ty , sema.arena, target),
15601+ .Sub => try stored_val.numberSubWrap(operand_val, elem_ty , sema.arena, target),
15602+ .And => try stored_val.bitwiseAnd (operand_val, elem_ty , sema.arena, target),
15603+ .Nand => try stored_val.bitwiseNand (operand_val, elem_ty , sema.arena, target),
15604+ .Or => try stored_val.bitwiseOr (operand_val, elem_ty , sema.arena, target),
15605+ .Xor => try stored_val.bitwiseXor (operand_val, elem_ty , sema.arena, target),
15606+ .Max => stored_val.numberMax (operand_val, target),
15607+ .Min => stored_val.numberMin (operand_val, target),
1559615608 // zig fmt: on
1559715609 };
15598- try sema.storePtrVal(block, src, ptr_val, new_val, operand_ty );
15599- return sema.addConstant(operand_ty , stored_val);
15610+ try sema.storePtrVal(block, src, ptr_val, new_val, elem_ty );
15611+ return sema.addConstant(elem_ty , stored_val);
1560015612 } else break :rs ptr_src;
1560115613 } else ptr_src;
1560215614
@@ -15620,15 +15632,15 @@ fn zirAtomicStore(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1562015632 const extra = sema.code.extraData(Zir.Inst.AtomicStore, inst_data.payload_index).data;
1562115633 const src = inst_data.src();
1562215634 // zig fmt: off
15623- const operand_ty_src : LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
15635+ const elem_ty_src : LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1562415636 const ptr_src : LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
1562515637 const operand_src : LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
1562615638 const order_src : LazySrcLoc = .{ .node_offset_builtin_call_arg3 = inst_data.src_node };
1562715639 // zig fmt: on
15628- const ptr = sema.resolveInst(extra.ptr );
15629- const operand_ty = sema.typeOf(ptr).elemType( );
15630- try sema.checkAtomicOperandType(block, operand_ty_src, operand_ty );
15631- const operand = try sema.coerce (block, operand_ty, sema.resolveInst(extra.operand), operand_src );
15640+ const operand = sema.resolveInst(extra.operand );
15641+ const elem_ty = sema.typeOf(operand );
15642+ const uncasted_ptr = sema.resolveInst(extra.ptr );
15643+ const ptr = try sema.checkAtomicPtrOperand (block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, false );
1563215644 const order = try sema.resolveAtomicOrder(block, order_src, extra.ordering);
1563315645
1563415646 const air_tag: Air.Inst.Tag = switch (order) {
0 commit comments