AstGen: use RLS to infer the first argument of @fieldParentPtr
This commit is contained in:
@@ -316,8 +316,7 @@ const ResultInfo = struct {
|
||||
};
|
||||
|
||||
/// Find the result type for a cast builtin given the result location.
|
||||
/// If the location does not have a known result type, emits an error on
|
||||
/// the given node.
|
||||
/// If the location does not have a known result type, returns `null`.
|
||||
fn resultType(rl: Loc, gz: *GenZir, node: Ast.Node.Index) !?Zir.Inst.Ref {
|
||||
return switch (rl) {
|
||||
.discard, .none, .ref, .inferred_ptr, .destructure => null,
|
||||
@@ -330,6 +329,9 @@ const ResultInfo = struct {
|
||||
};
|
||||
}
|
||||
|
||||
/// Find the result type for a cast builtin given the result location.
|
||||
/// If the location does not have a known result type, emits an error on
|
||||
/// the given node.
|
||||
fn resultTypeForCast(rl: Loc, gz: *GenZir, node: Ast.Node.Index, builtin_name: []const u8) !Zir.Inst.Ref {
|
||||
const astgen = gz.astgen;
|
||||
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
|
||||
.atomic_load,
|
||||
.atomic_rmw,
|
||||
.mul_add,
|
||||
.field_parent_ptr,
|
||||
.max,
|
||||
.min,
|
||||
.c_import,
|
||||
@@ -8853,6 +8854,7 @@ fn ptrCast(
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
|
||||
const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).Struct.backing_integer.?;
|
||||
var flags: Zir.Inst.FullPtrCastFlags = .{};
|
||||
|
||||
// Note that all pointer cast builtins have one parameter, so we only need
|
||||
@@ -8870,36 +8872,62 @@ fn ptrCast(
|
||||
}
|
||||
|
||||
if (node_datas[node].lhs == 0) break; // 0 args
|
||||
if (node_datas[node].rhs != 0) break; // 2 args
|
||||
|
||||
const builtin_token = main_tokens[node];
|
||||
const builtin_name = tree.tokenSlice(builtin_token);
|
||||
const info = BuiltinFn.list.get(builtin_name) orelse break;
|
||||
if (info.param_count != 1) break;
|
||||
if (node_datas[node].rhs == 0) {
|
||||
// 1 arg
|
||||
if (info.param_count != 1) break;
|
||||
|
||||
switch (info.tag) {
|
||||
else => break,
|
||||
inline .ptr_cast,
|
||||
.align_cast,
|
||||
.addrspace_cast,
|
||||
.const_cast,
|
||||
.volatile_cast,
|
||||
=> |tag| {
|
||||
if (@field(flags, @tagName(tag))) {
|
||||
return astgen.failNode(node, "redundant {s}", .{builtin_name});
|
||||
}
|
||||
@field(flags, @tagName(tag)) = true;
|
||||
},
|
||||
switch (info.tag) {
|
||||
else => break,
|
||||
inline .ptr_cast,
|
||||
.align_cast,
|
||||
.addrspace_cast,
|
||||
.const_cast,
|
||||
.volatile_cast,
|
||||
=> |tag| {
|
||||
if (@field(flags, @tagName(tag))) {
|
||||
return astgen.failNode(node, "redundant {s}", .{builtin_name});
|
||||
}
|
||||
@field(flags, @tagName(tag)) = true;
|
||||
},
|
||||
}
|
||||
|
||||
node = node_datas[node].lhs;
|
||||
} else {
|
||||
// 2 args
|
||||
if (info.param_count != 2) break;
|
||||
|
||||
switch (info.tag) {
|
||||
else => break,
|
||||
.field_parent_ptr => {
|
||||
if (flags.ptr_cast) break;
|
||||
|
||||
const flags_int: FlagsInt = @bitCast(flags);
|
||||
const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node);
|
||||
const parent_ptr_type = try ri.rl.resultTypeForCast(gz, root_node, "@alignCast");
|
||||
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, node_datas[node].lhs);
|
||||
const field_ptr = try expr(gz, scope, .{ .rl = .none }, node_datas[node].rhs);
|
||||
try emitDbgStmt(gz, cursor);
|
||||
const result = try gz.addExtendedPayloadSmall(.field_parent_ptr, flags_int, Zir.Inst.FieldParentPtr{
|
||||
.src_node = gz.nodeIndexToRelative(node),
|
||||
.parent_ptr_type = parent_ptr_type,
|
||||
.field_name = field_name,
|
||||
.field_ptr = field_ptr,
|
||||
});
|
||||
return rvalue(gz, ri, result, root_node);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
node = node_datas[node].lhs;
|
||||
}
|
||||
|
||||
const flags_i: u5 = @bitCast(flags);
|
||||
assert(flags_i != 0);
|
||||
const flags_int: FlagsInt = @bitCast(flags);
|
||||
assert(flags_int != 0);
|
||||
|
||||
const ptr_only: Zir.Inst.FullPtrCastFlags = .{ .ptr_cast = true };
|
||||
if (flags_i == @as(u5, @bitCast(ptr_only))) {
|
||||
if (flags_int == @as(FlagsInt, @bitCast(ptr_only))) {
|
||||
// Special case: simpler representation
|
||||
return typeCast(gz, scope, ri, root_node, node, .ptr_cast, "@ptrCast");
|
||||
}
|
||||
@@ -8908,12 +8936,12 @@ fn ptrCast(
|
||||
.const_cast = true,
|
||||
.volatile_cast = true,
|
||||
};
|
||||
if ((flags_i & ~@as(u5, @bitCast(no_result_ty_flags))) == 0) {
|
||||
if ((flags_int & ~@as(FlagsInt, @bitCast(no_result_ty_flags))) == 0) {
|
||||
// Result type not needed
|
||||
const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node);
|
||||
const operand = try expr(gz, scope, .{ .rl = .none }, node);
|
||||
try emitDbgStmt(gz, cursor);
|
||||
const result = try gz.addExtendedPayloadSmall(.ptr_cast_no_dest, flags_i, Zir.Inst.UnNode{
|
||||
const result = try gz.addExtendedPayloadSmall(.ptr_cast_no_dest, flags_int, Zir.Inst.UnNode{
|
||||
.node = gz.nodeIndexToRelative(root_node),
|
||||
.operand = operand,
|
||||
});
|
||||
@@ -8926,7 +8954,7 @@ fn ptrCast(
|
||||
const result_type = try ri.rl.resultTypeForCast(gz, root_node, flags.needResultTypeBuiltinName());
|
||||
const operand = try expr(gz, scope, .{ .rl = .none }, node);
|
||||
try emitDbgStmt(gz, cursor);
|
||||
const result = try gz.addExtendedPayloadSmall(.ptr_cast_full, flags_i, Zir.Inst.BinNode{
|
||||
const result = try gz.addExtendedPayloadSmall(.ptr_cast_full, flags_int, Zir.Inst.BinNode{
|
||||
.node = gz.nodeIndexToRelative(root_node),
|
||||
.lhs = result_type,
|
||||
.rhs = operand,
|
||||
@@ -9379,7 +9407,7 @@ fn builtinCall(
|
||||
try emitDbgNode(gz, node);
|
||||
|
||||
const result = try gz.addExtendedPayload(.error_cast, Zir.Inst.BinNode{
|
||||
.lhs = try ri.rl.resultTypeForCast(gz, node, "@errorCast"),
|
||||
.lhs = try ri.rl.resultTypeForCast(gz, node, builtin_name),
|
||||
.rhs = try expr(gz, scope, .{ .rl = .none }, params[0]),
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
});
|
||||
@@ -9452,7 +9480,7 @@ fn builtinCall(
|
||||
},
|
||||
|
||||
.splat => {
|
||||
const result_type = try ri.rl.resultTypeForCast(gz, node, "@splat");
|
||||
const result_type = try ri.rl.resultTypeForCast(gz, node, builtin_name);
|
||||
const elem_type = try gz.addUnNode(.vector_elem_type, result_type, node);
|
||||
const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]);
|
||||
const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{
|
||||
@@ -9537,12 +9565,13 @@ fn builtinCall(
|
||||
return rvalue(gz, ri, result, node);
|
||||
},
|
||||
.field_parent_ptr => {
|
||||
const parent_type = try typeExpr(gz, scope, params[0]);
|
||||
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]);
|
||||
const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{
|
||||
.parent_type = parent_type,
|
||||
const parent_ptr_type = try ri.rl.resultTypeForCast(gz, node, builtin_name);
|
||||
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0]);
|
||||
const result = try gz.addExtendedPayloadSmall(.field_parent_ptr, 0, Zir.Inst.FieldParentPtr{
|
||||
.src_node = gz.nodeIndexToRelative(node),
|
||||
.parent_ptr_type = parent_ptr_type,
|
||||
.field_name = field_name,
|
||||
.field_ptr = try expr(gz, scope, .{ .rl = .none }, params[2]),
|
||||
.field_ptr = try expr(gz, scope, .{ .rl = .none }, params[1]),
|
||||
});
|
||||
return rvalue(gz, ri, result, node);
|
||||
},
|
||||
|
||||
@@ -911,6 +911,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
|
||||
.work_item_id,
|
||||
.work_group_size,
|
||||
.work_group_id,
|
||||
.field_parent_ptr,
|
||||
=> {
|
||||
_ = try astrl.expr(args[0], block, ResultInfo.type_only);
|
||||
return false;
|
||||
@@ -976,7 +977,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
|
||||
},
|
||||
.bit_offset_of,
|
||||
.offset_of,
|
||||
.field_parent_ptr,
|
||||
.has_decl,
|
||||
.has_field,
|
||||
.field,
|
||||
|
||||
@@ -504,7 +504,7 @@ pub const list = list: {
|
||||
"@fieldParentPtr",
|
||||
.{
|
||||
.tag = .field_parent_ptr,
|
||||
.param_count = 3,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
.{
|
||||
|
||||
@@ -940,9 +940,6 @@ pub const Inst = struct {
|
||||
/// The addend communicates the type of the builtin.
|
||||
/// The mulends need to be coerced to the same type.
|
||||
mul_add,
|
||||
/// Implements the `@fieldParentPtr` builtin.
|
||||
/// Uses the `pl_node` union field with payload `FieldParentPtr`.
|
||||
field_parent_ptr,
|
||||
/// Implements the `@memcpy` builtin.
|
||||
/// Uses the `pl_node` union field with payload `Bin`.
|
||||
memcpy,
|
||||
@@ -1230,7 +1227,6 @@ pub const Inst = struct {
|
||||
.atomic_store,
|
||||
.mul_add,
|
||||
.builtin_call,
|
||||
.field_parent_ptr,
|
||||
.max,
|
||||
.memcpy,
|
||||
.memset,
|
||||
@@ -1522,7 +1518,6 @@ pub const Inst = struct {
|
||||
.atomic_rmw,
|
||||
.mul_add,
|
||||
.builtin_call,
|
||||
.field_parent_ptr,
|
||||
.max,
|
||||
.min,
|
||||
.c_import,
|
||||
@@ -1794,7 +1789,6 @@ pub const Inst = struct {
|
||||
.atomic_store = .pl_node,
|
||||
.mul_add = .pl_node,
|
||||
.builtin_call = .pl_node,
|
||||
.field_parent_ptr = .pl_node,
|
||||
.max = .pl_node,
|
||||
.memcpy = .pl_node,
|
||||
.memset = .pl_node,
|
||||
@@ -2064,6 +2058,12 @@ pub const Inst = struct {
|
||||
/// with a specific value. For instance, this is used for the capture of an `errdefer`.
|
||||
/// This should never appear in a body.
|
||||
value_placeholder,
|
||||
/// Implements the `@fieldParentPtr` builtin.
|
||||
/// `operand` is payload index to `FieldParentPtr`.
|
||||
/// `small` contains `FullPtrCastFlags`.
|
||||
/// Guaranteed to not have the `ptr_cast` flag.
|
||||
/// Uses the `pl_node` union field with payload `FieldParentPtr`.
|
||||
field_parent_ptr,
|
||||
|
||||
pub const InstData = struct {
|
||||
opcode: Extended,
|
||||
@@ -3363,9 +3363,14 @@ pub const Inst = struct {
|
||||
};
|
||||
|
||||
pub const FieldParentPtr = struct {
|
||||
parent_type: Ref,
|
||||
src_node: i32,
|
||||
parent_ptr_type: Ref,
|
||||
field_name: Ref,
|
||||
field_ptr: Ref,
|
||||
|
||||
pub fn src(self: FieldParentPtr) LazySrcLoc {
|
||||
return LazySrcLoc.nodeOffset(self.src_node);
|
||||
}
|
||||
};
|
||||
|
||||
pub const Shuffle = struct {
|
||||
|
||||
Reference in New Issue
Block a user