InternPool: implement typePtrOrOptionalPtrTy

This commit is contained in:
Andrew Kelley 2023-05-03 13:38:59 -07:00
parent 264292f430
commit e77dede87e
3 changed files with 51 additions and 6 deletions

View File

@ -1898,10 +1898,14 @@ fn resolveMaybeUndefVal(
inst: Air.Inst.Ref,
) CompileError!?Value {
const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
switch (val.tag()) {
.variable => return null,
switch (val.ip_index) {
.generic_poison => return error.GenericPoison,
else => return val,
.none => switch (val.tag()) {
.variable => return null,
.generic_poison => return error.GenericPoison,
else => return val,
},
}
}
@ -33497,6 +33501,33 @@ fn typePtrOrOptionalPtrTy(
buf: *Type.Payload.ElemType,
) !?Type {
const mod = sema.mod;
if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {
.ptr_type => |ptr_type| switch (ptr_type.size) {
.Slice => return null,
.C => return ptr_type.elem_type.toType(),
.One, .Many => return ty,
},
.optional_type => |o| switch (mod.intern_pool.indexToKey(o.payload_type)) {
.ptr_type => |ptr_type| switch (ptr_type.size) {
.Slice, .C => return null,
.Many, .One => {
if (ptr_type.is_allowzero) return null;
// optionals of zero sized types behave like bools, not pointers
const payload_ty = o.payload_type.toType();
if ((try sema.typeHasOnePossibleValue(payload_ty)) != null) {
return null;
}
return payload_ty;
},
},
else => return null,
},
else => return null,
};
switch (ty.tag()) {
.optional_single_const_pointer,
.optional_single_mut_pointer,

View File

@ -4319,8 +4319,20 @@ pub const Type = struct {
/// Returns true if the type is optional and would be lowered to a single pointer
/// address value, using 0 for null. Note that this returns true for C pointers.
pub fn isPtrLikeOptional(self: Type, mod: *const Module) bool {
switch (self.tag()) {
/// This function must be kept in sync with `Sema.typePtrOrOptionalPtrTy`.
pub fn isPtrLikeOptional(ty: Type, mod: *const Module) bool {
if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
.ptr_type => |ptr_type| ptr_type.size == .C,
.optional_type => |o| switch (mod.intern_pool.indexToKey(o.payload_type)) {
.ptr_type => |ptr_type| switch (ptr_type.size) {
.Slice, .C => false,
.Many, .One => !ptr_type.is_allowzero,
},
else => false,
},
else => false,
};
switch (ty.tag()) {
.optional_single_const_pointer,
.optional_single_mut_pointer,
.c_const_pointer,
@ -4328,7 +4340,7 @@ pub const Type = struct {
=> return true,
.optional => {
const child_ty = self.castTag(.optional).?.data;
const child_ty = ty.castTag(.optional).?.data;
if (child_ty.zigTypeTag(mod) != .Pointer) return false;
const info = child_ty.ptrInfo().data;
switch (info.size) {
@ -4337,7 +4349,7 @@ pub const Type = struct {
}
},
.pointer => return self.castTag(.pointer).?.data.size == .C,
.pointer => return ty.castTag(.pointer).?.data.size == .C,
else => return false,
}

View File

@ -117,6 +117,8 @@ pub const Value = struct {
int_big_negative,
function,
extern_fn,
/// A comptime-known pointer can point to the address of a global
/// variable. The child element value in this case will have this tag.
variable,
/// A wrapper for values which are comptime-known but should
/// semantically be runtime-known.