InternPool: implement isSinglePointer

This commit is contained in:
Andrew Kelley 2023-05-03 13:56:01 -07:00
parent e77dede87e
commit aa1bb5517d
4 changed files with 41 additions and 29 deletions

View File

@ -2086,7 +2086,7 @@ fn failWithUseOfAsync(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError
fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, object_ty: Type, field_name: []const u8) CompileError {
const mod = sema.mod;
const inner_ty = if (object_ty.isSinglePointer()) object_ty.childType() else object_ty;
const inner_ty = if (object_ty.isSinglePointer(mod)) object_ty.childType() else object_ty;
if (inner_ty.zigTypeTag(mod) == .Optional) opt: {
var buf: Type.Payload.ElemType = undefined;
@ -3412,8 +3412,9 @@ fn indexablePtrLen(
src: LazySrcLoc,
object: Air.Inst.Ref,
) CompileError!Air.Inst.Ref {
const mod = sema.mod;
const object_ty = sema.typeOf(object);
const is_pointer_to = object_ty.isSinglePointer();
const is_pointer_to = object_ty.isSinglePointer(mod);
const indexable_ty = if (is_pointer_to) object_ty.childType() else object_ty;
try checkIndexable(sema, block, src, indexable_ty);
return sema.fieldVal(block, src, object, "len", src);
@ -12764,12 +12765,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.Pointer => try sema.resolveDefinedValue(block, rhs_src, rhs),
else => unreachable,
}) |rhs_val| {
const lhs_sub_val = if (lhs_ty.isSinglePointer())
const lhs_sub_val = if (lhs_ty.isSinglePointer(mod))
(try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).?
else
lhs_val;
const rhs_sub_val = if (rhs_ty.isSinglePointer())
const rhs_sub_val = if (rhs_ty.isSinglePointer(mod))
(try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty)).?
else
rhs_val;
@ -13022,7 +13023,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| {
const final_len_including_sent = result_len + @boolToInt(lhs_info.sentinel != null);
const lhs_sub_val = if (lhs_ty.isSinglePointer())
const lhs_sub_val = if (lhs_ty.isSinglePointer(mod))
(try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).?
else
lhs_val;
@ -17588,7 +17589,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
const elem_ty = blk: {
const air_inst = try sema.resolveInst(extra.data.elem_type);
const ty = sema.analyzeAsType(block, elem_ty_src, air_inst) catch |err| {
if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer()) {
if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer(mod)) {
try sema.errNote(block, elem_ty_src, sema.err.?, "use '.*' to dereference pointer", .{});
}
return err;
@ -23902,7 +23903,7 @@ fn fieldVal(
// Zig allows dereferencing a single pointer during field lookup. Note that
// we don't actually need to generate the dereference some field lookups, like the
// length of arrays and other comptime operations.
const is_pointer_to = object_ty.isSinglePointer();
const is_pointer_to = object_ty.isSinglePointer(mod);
const inner_ty = if (is_pointer_to)
object_ty.childType()
@ -24092,7 +24093,7 @@ fn fieldPtr(
// Zig allows dereferencing a single pointer during field lookup. Note that
// we don't actually need to generate the dereference some field lookups, like the
// length of arrays and other comptime operations.
const is_pointer_to = object_ty.isSinglePointer();
const is_pointer_to = object_ty.isSinglePointer(mod);
const inner_ty = if (is_pointer_to)
object_ty.childType()
@ -25622,7 +25623,7 @@ fn coerceExtra(
// *T to *[1]T
single_item: {
if (dest_info.size != .One) break :single_item;
if (!inst_ty.isSinglePointer()) break :single_item;
if (!inst_ty.isSinglePointer(mod)) break :single_item;
if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
const ptr_elem_ty = inst_ty.childType();
const array_ty = dest_info.pointee_type;
@ -25639,7 +25640,7 @@ fn coerceExtra(
// Coercions where the source is a single pointer to an array.
src_array_ptr: {
if (!inst_ty.isSinglePointer()) break :src_array_ptr;
if (!inst_ty.isSinglePointer(mod)) break :src_array_ptr;
if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
const array_ty = inst_ty.childType();
if (array_ty.zigTypeTag(mod) != .Array) break :src_array_ptr;
@ -25794,7 +25795,7 @@ fn coerceExtra(
.One => switch (dest_info.pointee_type.zigTypeTag(mod)) {
.Union => {
// pointer to anonymous struct to pointer to union
if (inst_ty.isSinglePointer() and
if (inst_ty.isSinglePointer(mod) and
inst_ty.childType().isAnonStruct() and
sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
{
@ -25803,7 +25804,7 @@ fn coerceExtra(
},
.Struct => {
// pointer to anonymous struct to pointer to struct
if (inst_ty.isSinglePointer() and
if (inst_ty.isSinglePointer(mod) and
inst_ty.childType().isAnonStruct() and
sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
{
@ -25815,7 +25816,7 @@ fn coerceExtra(
},
.Array => {
// pointer to tuple to pointer to array
if (inst_ty.isSinglePointer() and
if (inst_ty.isSinglePointer(mod) and
inst_ty.childType().isTuple() and
sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
{
@ -25834,7 +25835,7 @@ fn coerceExtra(
);
}
if (!inst_ty.isSinglePointer()) break :to_slice;
if (!inst_ty.isSinglePointer(mod)) break :to_slice;
const inst_child_ty = inst_ty.childType();
if (!inst_child_ty.isTuple()) break :to_slice;
@ -30807,7 +30808,7 @@ fn resolvePeerTypes(
.Vector => continue,
else => {},
},
.Fn => if (chosen_ty.isSinglePointer() and chosen_ty.isConstPtr() and chosen_ty.childType().zigTypeTag(mod) == .Fn) {
.Fn => if (chosen_ty.isSinglePointer(mod) and chosen_ty.isConstPtr() and chosen_ty.childType().zigTypeTag(mod) == .Fn) {
if (.ok == try sema.coerceInMemoryAllowedFns(block, chosen_ty.childType(), candidate_ty, target, src, src)) {
continue;
}

View File

@ -3873,7 +3873,7 @@ fn airCmpOp(
try reap(f, inst, &.{ data.lhs, data.rhs });
const rhs_ty = f.typeOf(data.rhs);
const need_cast = lhs_ty.isSinglePointer() or rhs_ty.isSinglePointer();
const need_cast = lhs_ty.isSinglePointer(mod) or rhs_ty.isSinglePointer(mod);
const writer = f.object.writer();
const local = try f.allocLocal(inst, inst_ty);
const v = try Vectorize.start(f, inst, writer, lhs_ty);

View File

@ -5929,7 +5929,7 @@ pub const FuncGen = struct {
const base_ptr = try self.resolveInst(bin_op.lhs);
const rhs = try self.resolveInst(bin_op.rhs);
// TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch
const ptr = if (ptr_ty.isSinglePointer()) ptr: {
const ptr = if (ptr_ty.isSinglePointer(mod)) ptr: {
// If this is a single-item pointer to an array, we need another index in the GEP.
const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs };
break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
@ -5962,7 +5962,7 @@ pub const FuncGen = struct {
if (elem_ptr.ptrInfo().data.vector_index != .none) return base_ptr;
const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty);
if (ptr_ty.isSinglePointer()) {
if (ptr_ty.isSinglePointer(mod)) {
// If this is a single-item pointer to an array, we need another index in the GEP.
const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs };
return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");

View File

@ -4039,19 +4039,25 @@ pub const Type = struct {
}
}
pub fn isSinglePointer(self: Type) bool {
return switch (self.tag()) {
.single_const_pointer,
.single_mut_pointer,
.single_const_pointer_to_comptime_int,
.inferred_alloc_const,
.inferred_alloc_mut,
=> true,
pub fn isSinglePointer(ty: Type, mod: *const Module) bool {
switch (ty.ip_index) {
.none => return switch (ty.tag()) {
.single_const_pointer,
.single_mut_pointer,
.single_const_pointer_to_comptime_int,
.inferred_alloc_const,
.inferred_alloc_mut,
=> true,
.pointer => self.castTag(.pointer).?.data.size == .One,
.pointer => ty.castTag(.pointer).?.data.size == .One,
else => false,
};
else => false,
},
else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
.ptr_type => |ptr_info| ptr_info.size == .One,
else => false,
},
}
}
/// Asserts `ty` is a pointer.
@ -6142,6 +6148,11 @@ pub const Type = struct {
}
pub fn declSrcLocOrNull(ty: Type, mod: *Module) ?Module.SrcLoc {
if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {
.struct_type => @panic("TODO"),
.union_type => @panic("TODO"),
else => return null,
};
switch (ty.tag()) {
.enum_full, .enum_nonexhaustive => {
const enum_full = ty.cast(Payload.EnumFull).?.data;