authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-03-19 11:55:15+01:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-03-30 20:50:48-04:00
log17673dcd6e3ffeb25fc9dc1cfc72334ab4e71b37
treea75acd8f0b41030563015bdcdc47b374fb3f8dc3
parente409afb79bcadeabd2d5d4cc3cd5dcc54a964e94

AstGen: use RLS to infer the first argument of `@fieldParentPtr`


9 files changed, 128 insertions(+), 85 deletions(-)

lib/std/zig/AstGen.zig+62-33
...@@ -316,8 +316,7 @@ const ResultInfo = struct {...@@ -316,8 +316,7 @@ const ResultInfo = struct {
316 };316 };
317317
318 /// Find the result type for a cast builtin given the result location.318 /// Find the result type for a cast builtin given the result location.
319 /// If the location does not have a known result type, emits an error on319 /// If the location does not have a known result type, returns `null`.
320 /// the given node.
321 fn resultType(rl: Loc, gz: *GenZir, node: Ast.Node.Index) !?Zir.Inst.Ref {320 fn resultType(rl: Loc, gz: *GenZir, node: Ast.Node.Index) !?Zir.Inst.Ref {
322 return switch (rl) {321 return switch (rl) {
323 .discard, .none, .ref, .inferred_ptr, .destructure => null,322 .discard, .none, .ref, .inferred_ptr, .destructure => null,
...@@ -330,6 +329,9 @@ const ResultInfo = struct {...@@ -330,6 +329,9 @@ const ResultInfo = struct {
330 };329 };
331 }330 }
332331
332 /// Find the result type for a cast builtin given the result location.
333 /// If the location does not have a known result type, emits an error on
334 /// the given node.
333 fn resultTypeForCast(rl: Loc, gz: *GenZir, node: Ast.Node.Index, builtin_name: []const u8) !Zir.Inst.Ref {335 fn resultTypeForCast(rl: Loc, gz: *GenZir, node: Ast.Node.Index, builtin_name: []const u8) !Zir.Inst.Ref {
334 const astgen = gz.astgen;336 const astgen = gz.astgen;
335 if (try rl.resultType(gz, node)) |ty| return ty;337 if (try rl.resultType(gz, node)) |ty| return ty;
...@@ -2786,7 +2788,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2786,7 +2788,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2786 .atomic_load,2788 .atomic_load,
2787 .atomic_rmw,2789 .atomic_rmw,
2788 .mul_add,2790 .mul_add,
2789 .field_parent_ptr,
2790 .max,2791 .max,
2791 .min,2792 .min,
2792 .c_import,2793 .c_import,
...@@ -8853,6 +8854,7 @@ fn ptrCast(...@@ -8853,6 +8854,7 @@ fn ptrCast(
8853 const node_datas = tree.nodes.items(.data);8854 const node_datas = tree.nodes.items(.data);
8854 const node_tags = tree.nodes.items(.tag);8855 const node_tags = tree.nodes.items(.tag);
88558856
8857 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?;
8856 var flags: Zir.Inst.FullPtrCastFlags = .{};8858 var flags: Zir.Inst.FullPtrCastFlags = .{};
88578859
8858 // Note that all pointer cast builtins have one parameter, so we only need8860 // Note that all pointer cast builtins have one parameter, so we only need
...@@ -8870,36 +8872,62 @@ fn ptrCast(...@@ -8870,36 +8872,62 @@ fn ptrCast(
8870 }8872 }
88718873
8872 if (node_datas[node].lhs == 0) break; // 0 args8874 if (node_datas[node].lhs == 0) break; // 0 args
8873 if (node_datas[node].rhs != 0) break; // 2 args
88748875
8875 const builtin_token = main_tokens[node];8876 const builtin_token = main_tokens[node];
8876 const builtin_name = tree.tokenSlice(builtin_token);8877 const builtin_name = tree.tokenSlice(builtin_token);
8877 const info = BuiltinFn.list.get(builtin_name) orelse break;8878 const info = BuiltinFn.list.get(builtin_name) orelse break;
8878 if (info.param_count != 1) break;8879 if (node_datas[node].rhs == 0) {
8880 // 1 arg
8881 if (info.param_count != 1) break;
8882
8883 switch (info.tag) {
8884 else => break,
8885 inline .ptr_cast,
8886 .align_cast,
8887 .addrspace_cast,
8888 .const_cast,
8889 .volatile_cast,
8890 => |tag| {
8891 if (@field(flags, @tagName(tag))) {
8892 return astgen.failNode(node, "redundant {s}", .{builtin_name});
8893 }
8894 @field(flags, @tagName(tag)) = true;
8895 },
8896 }
88798897
8880 switch (info.tag) {8898 node = node_datas[node].lhs;
8881 else => break,8899 } else {
8882 inline .ptr_cast,8900 // 2 args
8883 .align_cast,8901 if (info.param_count != 2) break;
8884 .addrspace_cast,8902
8885 .const_cast,8903 switch (info.tag) {
8886 .volatile_cast,8904 else => break,
8887 => |tag| {8905 .field_parent_ptr => {
8888 if (@field(flags, @tagName(tag))) {8906 if (flags.ptr_cast) break;
8889 return astgen.failNode(node, "redundant {s}", .{builtin_name});8907
8890 }8908 const flags_int: FlagsInt = @bitCast(flags);
8891 @field(flags, @tagName(tag)) = true;8909 const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node);
8892 },8910 const parent_ptr_type = try ri.rl.resultTypeForCast(gz, root_node, "@alignCast");
8911 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, node_datas[node].lhs);
8912 const field_ptr = try expr(gz, scope, .{ .rl = .none }, node_datas[node].rhs);
8913 try emitDbgStmt(gz, cursor);
8914 const result = try gz.addExtendedPayloadSmall(.field_parent_ptr, flags_int, Zir.Inst.FieldParentPtr{
8915 .src_node = gz.nodeIndexToRelative(node),
8916 .parent_ptr_type = parent_ptr_type,
8917 .field_name = field_name,
8918 .field_ptr = field_ptr,
8919 });
8920 return rvalue(gz, ri, result, root_node);
8921 },
8922 }
8893 }8923 }
8894
8895 node = node_datas[node].lhs;
8896 }8924 }
88978925
8898 const flags_i: u5 = @bitCast(flags);8926 const flags_int: FlagsInt = @bitCast(flags);
8899 assert(flags_i != 0);8927 assert(flags_int != 0);
89008928
8901 const ptr_only: Zir.Inst.FullPtrCastFlags = .{ .ptr_cast = true };8929 const ptr_only: Zir.Inst.FullPtrCastFlags = .{ .ptr_cast = true };
8902 if (flags_i == @as(u5, @bitCast(ptr_only))) {8930 if (flags_int == @as(FlagsInt, @bitCast(ptr_only))) {
8903 // Special case: simpler representation8931 // Special case: simpler representation
8904 return typeCast(gz, scope, ri, root_node, node, .ptr_cast, "@ptrCast");8932 return typeCast(gz, scope, ri, root_node, node, .ptr_cast, "@ptrCast");
8905 }8933 }
...@@ -8908,12 +8936,12 @@ fn ptrCast(...@@ -8908,12 +8936,12 @@ fn ptrCast(
8908 .const_cast = true,8936 .const_cast = true,
8909 .volatile_cast = true,8937 .volatile_cast = true,
8910 };8938 };
8911 if ((flags_i & ~@as(u5, @bitCast(no_result_ty_flags))) == 0) {8939 if ((flags_int & ~@as(FlagsInt, @bitCast(no_result_ty_flags))) == 0) {
8912 // Result type not needed8940 // Result type not needed
8913 const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node);8941 const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node);
8914 const operand = try expr(gz, scope, .{ .rl = .none }, node);8942 const operand = try expr(gz, scope, .{ .rl = .none }, node);
8915 try emitDbgStmt(gz, cursor);8943 try emitDbgStmt(gz, cursor);
8916 const result = try gz.addExtendedPayloadSmall(.ptr_cast_no_dest, flags_i, Zir.Inst.UnNode{8944 const result = try gz.addExtendedPayloadSmall(.ptr_cast_no_dest, flags_int, Zir.Inst.UnNode{
8917 .node = gz.nodeIndexToRelative(root_node),8945 .node = gz.nodeIndexToRelative(root_node),
8918 .operand = operand,8946 .operand = operand,
8919 });8947 });
...@@ -8926,7 +8954,7 @@ fn ptrCast(...@@ -8926,7 +8954,7 @@ fn ptrCast(
8926 const result_type = try ri.rl.resultTypeForCast(gz, root_node, flags.needResultTypeBuiltinName());8954 const result_type = try ri.rl.resultTypeForCast(gz, root_node, flags.needResultTypeBuiltinName());
8927 const operand = try expr(gz, scope, .{ .rl = .none }, node);8955 const operand = try expr(gz, scope, .{ .rl = .none }, node);
8928 try emitDbgStmt(gz, cursor);8956 try emitDbgStmt(gz, cursor);
8929 const result = try gz.addExtendedPayloadSmall(.ptr_cast_full, flags_i, Zir.Inst.BinNode{8957 const result = try gz.addExtendedPayloadSmall(.ptr_cast_full, flags_int, Zir.Inst.BinNode{
8930 .node = gz.nodeIndexToRelative(root_node),8958 .node = gz.nodeIndexToRelative(root_node),
8931 .lhs = result_type,8959 .lhs = result_type,
8932 .rhs = operand,8960 .rhs = operand,
...@@ -9379,7 +9407,7 @@ fn builtinCall(...@@ -9379,7 +9407,7 @@ fn builtinCall(
9379 try emitDbgNode(gz, node);9407 try emitDbgNode(gz, node);
93809408
9381 const result = try gz.addExtendedPayload(.error_cast, Zir.Inst.BinNode{9409 const result = try gz.addExtendedPayload(.error_cast, Zir.Inst.BinNode{
9382 .lhs = try ri.rl.resultTypeForCast(gz, node, "@errorCast"),9410 .lhs = try ri.rl.resultTypeForCast(gz, node, builtin_name),
9383 .rhs = try expr(gz, scope, .{ .rl = .none }, params[0]),9411 .rhs = try expr(gz, scope, .{ .rl = .none }, params[0]),
9384 .node = gz.nodeIndexToRelative(node),9412 .node = gz.nodeIndexToRelative(node),
9385 });9413 });
...@@ -9452,7 +9480,7 @@ fn builtinCall(...@@ -9452,7 +9480,7 @@ fn builtinCall(
9452 },9480 },
94539481
9454 .splat => {9482 .splat => {
9455 const result_type = try ri.rl.resultTypeForCast(gz, node, "@splat");9483 const result_type = try ri.rl.resultTypeForCast(gz, node, builtin_name);
9456 const elem_type = try gz.addUnNode(.vector_elem_type, result_type, node);9484 const elem_type = try gz.addUnNode(.vector_elem_type, result_type, node);
9457 const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]);9485 const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]);
9458 const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{9486 const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{
...@@ -9537,12 +9565,13 @@ fn builtinCall(...@@ -9537,12 +9565,13 @@ fn builtinCall(
9537 return rvalue(gz, ri, result, node);9565 return rvalue(gz, ri, result, node);
9538 },9566 },
9539 .field_parent_ptr => {9567 .field_parent_ptr => {
9540 const parent_type = try typeExpr(gz, scope, params[0]);9568 const parent_ptr_type = try ri.rl.resultTypeForCast(gz, node, builtin_name);
9541 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]);9569 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0]);
9542 const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{9570 const result = try gz.addExtendedPayloadSmall(.field_parent_ptr, 0, Zir.Inst.FieldParentPtr{
9543 .parent_type = parent_type,9571 .src_node = gz.nodeIndexToRelative(node),
9572 .parent_ptr_type = parent_ptr_type,
9544 .field_name = field_name,9573 .field_name = field_name,
9545 .field_ptr = try expr(gz, scope, .{ .rl = .none }, params[2]),9574 .field_ptr = try expr(gz, scope, .{ .rl = .none }, params[1]),
9546 });9575 });
9547 return rvalue(gz, ri, result, node);9576 return rvalue(gz, ri, result, node);
9548 },9577 },
lib/std/zig/AstRlAnnotate.zig+1-1
...@@ -911,6 +911,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast....@@ -911,6 +911,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
911 .work_item_id,911 .work_item_id,
912 .work_group_size,912 .work_group_size,
913 .work_group_id,913 .work_group_id,
914 .field_parent_ptr,
914 => {915 => {
915 _ = try astrl.expr(args[0], block, ResultInfo.type_only);916 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
916 return false;917 return false;
...@@ -976,7 +977,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast....@@ -976,7 +977,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
976 },977 },
977 .bit_offset_of,978 .bit_offset_of,
978 .offset_of,979 .offset_of,
979 .field_parent_ptr,
980 .has_decl,980 .has_decl,
981 .has_field,981 .has_field,
982 .field,982 .field,
lib/std/zig/BuiltinFn.zig+1-1
...@@ -504,7 +504,7 @@ pub const list = list: {...@@ -504,7 +504,7 @@ pub const list = list: {
504 "@fieldParentPtr",504 "@fieldParentPtr",
505 .{505 .{
506 .tag = .field_parent_ptr,506 .tag = .field_parent_ptr,
507 .param_count = 3,507 .param_count = 2,
508 },508 },
509 },509 },
510 .{510 .{
lib/std/zig/Zir.zig+12-7
...@@ -940,9 +940,6 @@ pub const Inst = struct {...@@ -940,9 +940,6 @@ pub const Inst = struct {
940 /// The addend communicates the type of the builtin.940 /// The addend communicates the type of the builtin.
941 /// The mulends need to be coerced to the same type.941 /// The mulends need to be coerced to the same type.
942 mul_add,942 mul_add,
943 /// Implements the `@fieldParentPtr` builtin.
944 /// Uses the `pl_node` union field with payload `FieldParentPtr`.
945 field_parent_ptr,
946 /// Implements the `@memcpy` builtin.943 /// Implements the `@memcpy` builtin.
947 /// Uses the `pl_node` union field with payload `Bin`.944 /// Uses the `pl_node` union field with payload `Bin`.
948 memcpy,945 memcpy,
...@@ -1230,7 +1227,6 @@ pub const Inst = struct {...@@ -1230,7 +1227,6 @@ pub const Inst = struct {
1230 .atomic_store,1227 .atomic_store,
1231 .mul_add,1228 .mul_add,
1232 .builtin_call,1229 .builtin_call,
1233 .field_parent_ptr,
1234 .max,1230 .max,
1235 .memcpy,1231 .memcpy,
1236 .memset,1232 .memset,
...@@ -1522,7 +1518,6 @@ pub const Inst = struct {...@@ -1522,7 +1518,6 @@ pub const Inst = struct {
1522 .atomic_rmw,1518 .atomic_rmw,
1523 .mul_add,1519 .mul_add,
1524 .builtin_call,1520 .builtin_call,
1525 .field_parent_ptr,
1526 .max,1521 .max,
1527 .min,1522 .min,
1528 .c_import,1523 .c_import,
...@@ -1794,7 +1789,6 @@ pub const Inst = struct {...@@ -1794,7 +1789,6 @@ pub const Inst = struct {
1794 .atomic_store = .pl_node,1789 .atomic_store = .pl_node,
1795 .mul_add = .pl_node,1790 .mul_add = .pl_node,
1796 .builtin_call = .pl_node,1791 .builtin_call = .pl_node,
1797 .field_parent_ptr = .pl_node,
1798 .max = .pl_node,1792 .max = .pl_node,
1799 .memcpy = .pl_node,1793 .memcpy = .pl_node,
1800 .memset = .pl_node,1794 .memset = .pl_node,
...@@ -2064,6 +2058,12 @@ pub const Inst = struct {...@@ -2064,6 +2058,12 @@ pub const Inst = struct {
2064 /// with a specific value. For instance, this is used for the capture of an `errdefer`.2058 /// with a specific value. For instance, this is used for the capture of an `errdefer`.
2065 /// This should never appear in a body.2059 /// This should never appear in a body.
2066 value_placeholder,2060 value_placeholder,
2061 /// Implements the `@fieldParentPtr` builtin.
2062 /// `operand` is payload index to `FieldParentPtr`.
2063 /// `small` contains `FullPtrCastFlags`.
2064 /// Guaranteed to not have the `ptr_cast` flag.
2065 /// Uses the `pl_node` union field with payload `FieldParentPtr`.
2066 field_parent_ptr,
20672067
2068 pub const InstData = struct {2068 pub const InstData = struct {
2069 opcode: Extended,2069 opcode: Extended,
...@@ -3363,9 +3363,14 @@ pub const Inst = struct {...@@ -3363,9 +3363,14 @@ pub const Inst = struct {
3363 };3363 };
33643364
3365 pub const FieldParentPtr = struct {3365 pub const FieldParentPtr = struct {
3366 parent_type: Ref,3366 src_node: i32,
3367 parent_ptr_type: Ref,
3367 field_name: Ref,3368 field_name: Ref,
3368 field_ptr: Ref,3369 field_ptr: Ref,
3370
3371 pub fn src(self: FieldParentPtr) LazySrcLoc {
3372 return LazySrcLoc.nodeOffset(self.src_node);
3373 }
3369 };3374 };
33703375
3371 pub const Shuffle = struct {3376 pub const Shuffle = struct {
src/Sema.zig+34-32
...@@ -1131,7 +1131,6 @@ fn analyzeBodyInner(...@@ -1131,7 +1131,6 @@ fn analyzeBodyInner(
1131 .atomic_rmw => try sema.zirAtomicRmw(block, inst),1131 .atomic_rmw => try sema.zirAtomicRmw(block, inst),
1132 .mul_add => try sema.zirMulAdd(block, inst),1132 .mul_add => try sema.zirMulAdd(block, inst),
1133 .builtin_call => try sema.zirBuiltinCall(block, inst),1133 .builtin_call => try sema.zirBuiltinCall(block, inst),
1134 .field_parent_ptr => try sema.zirFieldParentPtr(block, inst),
1135 .@"resume" => try sema.zirResume(block, inst),1134 .@"resume" => try sema.zirResume(block, inst),
1136 .@"await" => try sema.zirAwait(block, inst),1135 .@"await" => try sema.zirAwait(block, inst),
1137 .for_len => try sema.zirForLen(block, inst),1136 .for_len => try sema.zirForLen(block, inst),
...@@ -1296,6 +1295,7 @@ fn analyzeBodyInner(...@@ -1296,6 +1295,7 @@ fn analyzeBodyInner(
1296 continue;1295 continue;
1297 },1296 },
1298 .value_placeholder => unreachable, // never appears in a body1297 .value_placeholder => unreachable, // never appears in a body
1298 .field_parent_ptr => try sema.zirFieldParentPtr(block, extended),
1299 };1299 };
1300 },1300 },
13011301
...@@ -22757,10 +22757,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -22757,10 +22757,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
22757}22757}
2275822758
22759fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {22759fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
22760 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(22760 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?;
22761 @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?,22761 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
22762 @truncate(extended.small),
22763 ));
22764 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;22762 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
22765 const src = LazySrcLoc.nodeOffset(extra.node);22763 const src = LazySrcLoc.nodeOffset(extra.node);
22766 const operand_src: LazySrcLoc = .{ .node_offset_ptrcast_operand = extra.node };22764 const operand_src: LazySrcLoc = .{ .node_offset_ptrcast_operand = extra.node };
...@@ -22773,6 +22771,7 @@ fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa...@@ -22773,6 +22771,7 @@ fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa
22773 operand,22771 operand,
22774 operand_src,22772 operand_src,
22775 dest_ty,22773 dest_ty,
22774 flags.needResultTypeBuiltinName(),
22776 );22775 );
22777}22776}
2277822777
...@@ -22791,6 +22790,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -22791,6 +22790,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
22791 operand,22790 operand,
22792 operand_src,22791 operand_src,
22793 dest_ty,22792 dest_ty,
22793 "@ptrCast",
22794 );22794 );
22795}22795}
2279622796
...@@ -22802,6 +22802,7 @@ fn ptrCastFull(...@@ -22802,6 +22802,7 @@ fn ptrCastFull(
22802 operand: Air.Inst.Ref,22802 operand: Air.Inst.Ref,
22803 operand_src: LazySrcLoc,22803 operand_src: LazySrcLoc,
22804 dest_ty: Type,22804 dest_ty: Type,
22805 operation: []const u8,
22805) CompileError!Air.Inst.Ref {22806) CompileError!Air.Inst.Ref {
22806 const mod = sema.mod;22807 const mod = sema.mod;
22807 const operand_ty = sema.typeOf(operand);22808 const operand_ty = sema.typeOf(operand);
...@@ -22834,7 +22835,7 @@ fn ptrCastFull(...@@ -22834,7 +22835,7 @@ fn ptrCastFull(
22834 };22835 };
22835 const dest_elem_size = Type.fromInterned(dest_info.child).abiSize(mod);22836 const dest_elem_size = Type.fromInterned(dest_info.child).abiSize(mod);
22836 if (src_elem_size != dest_elem_size) {22837 if (src_elem_size != dest_elem_size) {
22837 return sema.fail(block, src, "TODO: implement @ptrCast between slices changing the length", .{});22838 return sema.fail(block, src, "TODO: implement {s} between slices changing the length", .{operation});
22838 }22839 }
22839 }22840 }
2284022841
...@@ -22983,7 +22984,7 @@ fn ptrCastFull(...@@ -22983,7 +22984,7 @@ fn ptrCastFull(
22983 if (!flags.align_cast) {22984 if (!flags.align_cast) {
22984 if (dest_align.compare(.gt, src_align)) {22985 if (dest_align.compare(.gt, src_align)) {
22985 return sema.failWithOwnedErrorMsg(block, msg: {22986 return sema.failWithOwnedErrorMsg(block, msg: {
22986 const msg = try sema.errMsg(block, src, "cast increases pointer alignment", .{});22987 const msg = try sema.errMsg(block, src, "{s} increases pointer alignment", .{operation});
22987 errdefer msg.destroy(sema.gpa);22988 errdefer msg.destroy(sema.gpa);
22988 try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{22989 try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{
22989 operand_ty.fmt(mod), src_align.toByteUnits() orelse 0,22990 operand_ty.fmt(mod), src_align.toByteUnits() orelse 0,
...@@ -23000,7 +23001,7 @@ fn ptrCastFull(...@@ -23000,7 +23001,7 @@ fn ptrCastFull(
23000 if (!flags.addrspace_cast) {23001 if (!flags.addrspace_cast) {
23001 if (src_info.flags.address_space != dest_info.flags.address_space) {23002 if (src_info.flags.address_space != dest_info.flags.address_space) {
23002 return sema.failWithOwnedErrorMsg(block, msg: {23003 return sema.failWithOwnedErrorMsg(block, msg: {
23003 const msg = try sema.errMsg(block, src, "cast changes pointer address space", .{});23004 const msg = try sema.errMsg(block, src, "{s} changes pointer address space", .{operation});
23004 errdefer msg.destroy(sema.gpa);23005 errdefer msg.destroy(sema.gpa);
23005 try sema.errNote(block, operand_src, msg, "'{}' has address space '{s}'", .{23006 try sema.errNote(block, operand_src, msg, "'{}' has address space '{s}'", .{
23006 operand_ty.fmt(mod), @tagName(src_info.flags.address_space),23007 operand_ty.fmt(mod), @tagName(src_info.flags.address_space),
...@@ -23030,7 +23031,7 @@ fn ptrCastFull(...@@ -23030,7 +23031,7 @@ fn ptrCastFull(
23030 if (!flags.const_cast) {23031 if (!flags.const_cast) {
23031 if (src_info.flags.is_const and !dest_info.flags.is_const) {23032 if (src_info.flags.is_const and !dest_info.flags.is_const) {
23032 return sema.failWithOwnedErrorMsg(block, msg: {23033 return sema.failWithOwnedErrorMsg(block, msg: {
23033 const msg = try sema.errMsg(block, src, "cast discards const qualifier", .{});23034 const msg = try sema.errMsg(block, src, "{s} discards const qualifier", .{operation});
23034 errdefer msg.destroy(sema.gpa);23035 errdefer msg.destroy(sema.gpa);
23035 try sema.errNote(block, src, msg, "use @constCast to discard const qualifier", .{});23036 try sema.errNote(block, src, msg, "use @constCast to discard const qualifier", .{});
23036 break :msg msg;23037 break :msg msg;
...@@ -23041,7 +23042,7 @@ fn ptrCastFull(...@@ -23041,7 +23042,7 @@ fn ptrCastFull(
23041 if (!flags.volatile_cast) {23042 if (!flags.volatile_cast) {
23042 if (src_info.flags.is_volatile and !dest_info.flags.is_volatile) {23043 if (src_info.flags.is_volatile and !dest_info.flags.is_volatile) {
23043 return sema.failWithOwnedErrorMsg(block, msg: {23044 return sema.failWithOwnedErrorMsg(block, msg: {
23044 const msg = try sema.errMsg(block, src, "cast discards volatile qualifier", .{});23045 const msg = try sema.errMsg(block, src, "{s} discards volatile qualifier", .{operation});
23045 errdefer msg.destroy(sema.gpa);23046 errdefer msg.destroy(sema.gpa);
23046 try sema.errNote(block, src, msg, "use @volatileCast to discard volatile qualifier", .{});23047 try sema.errNote(block, src, msg, "use @volatileCast to discard volatile qualifier", .{});
23047 break :msg msg;23048 break :msg msg;
...@@ -23187,10 +23188,8 @@ fn ptrCastFull(...@@ -23187,10 +23188,8 @@ fn ptrCastFull(
2318723188
23188fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {23189fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
23189 const mod = sema.mod;23190 const mod = sema.mod;
23190 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(23191 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?;
23191 @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?,23192 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
23192 @truncate(extended.small),
23193 ));
23194 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;23193 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
23195 const src = LazySrcLoc.nodeOffset(extra.node);23194 const src = LazySrcLoc.nodeOffset(extra.node);
23196 const operand_src: LazySrcLoc = .{ .node_offset_ptrcast_operand = extra.node };23195 const operand_src: LazySrcLoc = .{ .node_offset_ptrcast_operand = extra.node };
...@@ -24859,25 +24858,28 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -24859,25 +24858,28 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
24859 );24858 );
24860}24859}
2486124860
24862fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {24861fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
24863 const mod = sema.mod;24862 const mod = sema.mod;
24864 const ip = &mod.intern_pool;24863 const ip = &mod.intern_pool;
2486524864
24866 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;24865 const extra = sema.code.extraData(Zir.Inst.FieldParentPtr, extended.operand).data;
24867 const extra = sema.code.extraData(Zir.Inst.FieldParentPtr, inst_data.payload_index).data;24866 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?;
24868 const inst_src = inst_data.src();24867 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
24869 const parent_ptr_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };24868 assert(!flags.ptr_cast);
24870 const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };24869 const inst_src = extra.src();
24871 const field_ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };24870 const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.src_node };
2487224871 const field_ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.src_node };
24873 const parent_ptr_ty = try sema.resolveType(block, parent_ptr_ty_src, extra.parent_type);24872
24874 try sema.checkPtrType(block, parent_ptr_ty_src, parent_ptr_ty, false);24873 const parent_ptr_ty = try sema.resolveDestType(block, inst_src, extra.parent_ptr_type, .remove_eu, "@fieldParentPtr");
24875 if (!parent_ptr_ty.isSinglePointer(mod)) {24874 try sema.checkPtrType(block, inst_src, parent_ptr_ty, true);
24876 return sema.fail(block, parent_ptr_ty_src, "expected single pointer type, found '{}'", .{parent_ptr_ty.fmt(sema.mod)});24875 const parent_ptr_info = parent_ptr_ty.ptrInfo(mod);
24877 }24876 if (parent_ptr_info.flags.size != .One) {
24878 const parent_ty = parent_ptr_ty.childType(mod);24877 return sema.fail(block, inst_src, "expected single pointer type, found '{}'", .{parent_ptr_ty.fmt(sema.mod)});
24879 if (parent_ty.zigTypeTag(mod) != .Struct and parent_ty.zigTypeTag(mod) != .Union) {24878 }
24880 return sema.fail(block, parent_ptr_ty_src, "expected pointer to struct or union type, found '{}'", .{parent_ptr_ty.fmt(sema.mod)});24879 const parent_ty = Type.fromInterned(parent_ptr_info.child);
24880 switch (parent_ty.zigTypeTag(mod)) {
24881 .Struct, .Union => {},
24882 else => return sema.fail(block, inst_src, "expected pointer to struct or union type, found '{}'", .{parent_ptr_ty.fmt(sema.mod)}),
24881 }24883 }
24882 try sema.resolveTypeLayout(parent_ty);24884 try sema.resolveTypeLayout(parent_ty);
2488324885
...@@ -24916,7 +24918,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -24916,7 +24918,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
24916 .is_allowzero = field_ptr_info.flags.is_allowzero,24918 .is_allowzero = field_ptr_info.flags.is_allowzero,
24917 .address_space = field_ptr_info.flags.address_space,24919 .address_space = field_ptr_info.flags.address_space,
24918 },24920 },
24919 .packed_offset = parent_ptr_ty.ptrInfo(mod).packed_offset,24921 .packed_offset = parent_ptr_info.packed_offset,
24920 };24922 };
24921 const field_ty = parent_ty.structFieldType(field_index, mod);24923 const field_ty = parent_ty.structFieldType(field_index, mod);
24922 var actual_field_ptr_info: InternPool.Key.PtrType = .{24924 var actual_field_ptr_info: InternPool.Key.PtrType = .{
...@@ -25000,7 +25002,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -25000,7 +25002,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
25000 } },25002 } },
25001 });25003 });
25002 };25004 };
25003 return sema.coerce(block, parent_ptr_ty, result, inst_src);25005 return sema.ptrCastFull(block, flags, inst_src, result, inst_src, parent_ptr_ty, "@fieldParentPtr");
25004}25006}
2500525007
25006fn zirMinMax(25008fn zirMinMax(
src/print_zir.zig+15-8
...@@ -355,7 +355,6 @@ const Writer = struct {...@@ -355,7 +355,6 @@ const Writer = struct {
355 .atomic_rmw => try self.writeAtomicRmw(stream, inst),355 .atomic_rmw => try self.writeAtomicRmw(stream, inst),
356 .shuffle => try self.writeShuffle(stream, inst),356 .shuffle => try self.writeShuffle(stream, inst),
357 .mul_add => try self.writeMulAdd(stream, inst),357 .mul_add => try self.writeMulAdd(stream, inst),
358 .field_parent_ptr => try self.writeFieldParentPtr(stream, inst),
359 .builtin_call => try self.writeBuiltinCall(stream, inst),358 .builtin_call => try self.writeBuiltinCall(stream, inst),
360359
361 .field_type_ref => try self.writeFieldTypeRef(stream, inst),360 .field_type_ref => try self.writeFieldTypeRef(stream, inst),
...@@ -609,6 +608,7 @@ const Writer = struct {...@@ -609,6 +608,7 @@ const Writer = struct {
609608
610 .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, extended),609 .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, extended),
611 .closure_get => try self.writeClosureGet(stream, extended),610 .closure_get => try self.writeClosureGet(stream, extended),
611 .field_parent_ptr => try self.writeFieldParentPtr(stream, extended),
612 }612 }
613 }613 }
614614
...@@ -901,16 +901,21 @@ const Writer = struct {...@@ -901,16 +901,21 @@ const Writer = struct {
901 try self.writeSrc(stream, inst_data.src());901 try self.writeSrc(stream, inst_data.src());
902 }902 }
903903
904 fn writeFieldParentPtr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {904 fn writeFieldParentPtr(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
905 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;905 const extra = self.code.extraData(Zir.Inst.FieldParentPtr, extended.operand).data;
906 const extra = self.code.extraData(Zir.Inst.FieldParentPtr, inst_data.payload_index).data;906 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?;
907 try self.writeInstRef(stream, extra.parent_type);907 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
908 if (flags.align_cast) try stream.writeAll("align_cast, ");
909 if (flags.addrspace_cast) try stream.writeAll("addrspace_cast, ");
910 if (flags.const_cast) try stream.writeAll("const_cast, ");
911 if (flags.volatile_cast) try stream.writeAll("volatile_cast, ");
912 try self.writeInstRef(stream, extra.parent_ptr_type);
908 try stream.writeAll(", ");913 try stream.writeAll(", ");
909 try self.writeInstRef(stream, extra.field_name);914 try self.writeInstRef(stream, extra.field_name);
910 try stream.writeAll(", ");915 try stream.writeAll(", ");
911 try self.writeInstRef(stream, extra.field_ptr);916 try self.writeInstRef(stream, extra.field_ptr);
912 try stream.writeAll(") ");917 try stream.writeAll(") ");
913 try self.writeSrc(stream, inst_data.src());918 try self.writeSrc(stream, extra.src());
914 }919 }
915920
916 fn writeBuiltinAsyncCall(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {921 fn writeBuiltinAsyncCall(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
...@@ -1069,7 +1074,8 @@ const Writer = struct {...@@ -1069,7 +1074,8 @@ const Writer = struct {
1069 }1074 }
10701075
1071 fn writePtrCastFull(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {1076 fn writePtrCastFull(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
1072 const flags = @as(Zir.Inst.FullPtrCastFlags, @bitCast(@as(u5, @truncate(extended.small))));1077 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?;
1078 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
1073 const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;1079 const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
1074 const src = LazySrcLoc.nodeOffset(extra.node);1080 const src = LazySrcLoc.nodeOffset(extra.node);
1075 if (flags.ptr_cast) try stream.writeAll("ptr_cast, ");1081 if (flags.ptr_cast) try stream.writeAll("ptr_cast, ");
...@@ -1085,7 +1091,8 @@ const Writer = struct {...@@ -1085,7 +1091,8 @@ const Writer = struct {
1085 }1091 }
10861092
1087 fn writePtrCastNoDest(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {1093 fn writePtrCastNoDest(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
1088 const flags = @as(Zir.Inst.FullPtrCastFlags, @bitCast(@as(u5, @truncate(extended.small))));1094 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?;
1095 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
1089 const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;1096 const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
1090 const src = LazySrcLoc.nodeOffset(extra.node);1097 const src = LazySrcLoc.nodeOffset(extra.node);
1091 if (flags.const_cast) try stream.writeAll("const_cast, ");1098 if (flags.const_cast) try stream.writeAll("const_cast, ");
test/cases/compile_errors/increase_pointer_alignment_in_ptrCast.zig+1-1
...@@ -8,7 +8,7 @@ export fn entry() u32 {...@@ -8,7 +8,7 @@ export fn entry() u32 {
8// backend=stage28// backend=stage2
9// target=native9// target=native
10//10//
11// :3:23: error: cast increases pointer alignment11// :3:23: error: @ptrCast increases pointer alignment
12// :3:32: note: '*u8' has alignment '1'12// :3:32: note: '*u8' has alignment '1'
13// :3:23: note: '*u32' has alignment '4'13// :3:23: note: '*u32' has alignment '4'
14// :3:23: note: use @alignCast to assert pointer alignment14// :3:23: note: use @alignCast to assert pointer alignment
test/cases/compile_errors/nested_ptr_cast_bad_operand.zig+1-1
...@@ -16,7 +16,7 @@ export fn c() void {...@@ -16,7 +16,7 @@ export fn c() void {
16//16//
17// :3:45: error: null pointer casted to type '*const u32'17// :3:45: error: null pointer casted to type '*const u32'
18// :6:34: error: expected pointer type, found 'comptime_int'18// :6:34: error: expected pointer type, found 'comptime_int'
19// :9:22: error: cast increases pointer alignment19// :9:22: error: @ptrCast increases pointer alignment
20// :9:71: note: '?*const u8' has alignment '1'20// :9:71: note: '?*const u8' has alignment '1'
21// :9:22: note: '?*f32' has alignment '4'21// :9:22: note: '?*f32' has alignment '4'
22// :9:22: note: use @alignCast to assert pointer alignment22// :9:22: note: use @alignCast to assert pointer alignment
test/cases/compile_errors/ptrCast_discards_const_qualifier.zig+1-1
...@@ -8,5 +8,5 @@ export fn entry() void {...@@ -8,5 +8,5 @@ export fn entry() void {
8// backend=stage28// backend=stage2
9// target=native9// target=native
10//10//
11// :3:21: error: cast discards const qualifier11// :3:21: error: @ptrCast discards const qualifier
12// :3:21: note: use @constCast to discard const qualifier12// :3:21: note: use @constCast to discard const qualifier