Commit aa1bb5517d

Andrew Kelley <andrew@ziglang.org>
2023-05-03 22:56:01
InternPool: implement isSinglePointer
1 parent e77dede
Changed files (4)
src/codegen/c.zig
@@ -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);
src/codegen/llvm.zig
@@ -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, "");
src/Sema.zig
@@ -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;
                 }
src/type.zig
@@ -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;