Commit d729173204

Veikka Tuominen <git@vexu.eu>
2022-07-12 15:08:23
stage2: better pointer source location
1 parent 29815fe
src/AstGen.zig
@@ -1347,7 +1347,7 @@ fn arrayInitExpr(
             }
         }
         const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);
-        _ = try gz.addUnNode(.validate_array_init_ty, array_type_inst, node);
+        _ = try gz.addUnNode(.validate_array_init_ty, array_type_inst, array_init.ast.type_expr);
         break :inst .{
             .array = array_type_inst,
             .elem = .none,
@@ -2332,7 +2332,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
             .err_union_code,
             .err_union_code_ptr,
             .ptr_type,
-            .ptr_type_simple,
+            .overflow_arithmetic_ptr,
             .enum_literal,
             .merge_error_sets,
             .error_union_type,
@@ -3110,24 +3110,6 @@ fn ptrType(
 
     const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type);
 
-    const simple = ptr_info.ast.align_node == 0 and
-        ptr_info.ast.addrspace_node == 0 and
-        ptr_info.ast.sentinel == 0 and
-        ptr_info.ast.bit_range_start == 0;
-
-    if (simple) {
-        const result = try gz.add(.{ .tag = .ptr_type_simple, .data = .{
-            .ptr_type_simple = .{
-                .is_allowzero = ptr_info.allowzero_token != null,
-                .is_mutable = ptr_info.const_token == null,
-                .is_volatile = ptr_info.volatile_token != null,
-                .size = ptr_info.size,
-                .elem_type = elem_type,
-            },
-        } });
-        return rvalue(gz, rl, result, node);
-    }
-
     var sentinel_ref: Zir.Inst.Ref = .none;
     var align_ref: Zir.Inst.Ref = .none;
     var addrspace_ref: Zir.Inst.Ref = .none;
@@ -3160,7 +3142,10 @@ fn ptrType(
     try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.PtrType).Struct.fields.len +
         trailing_count);
 
-    const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.PtrType{ .elem_type = elem_type });
+    const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.PtrType{
+        .elem_type = elem_type,
+        .src_node = gz.nodeIndexToRelative(node),
+    });
     if (sentinel_ref != .none) {
         gz.astgen.extra.appendAssumeCapacity(@enumToInt(sentinel_ref));
     }
@@ -7588,15 +7573,7 @@ fn builtinCall(
         .shl_with_overflow => {
             const int_type = try typeExpr(gz, scope, params[0]);
             const log2_int_type = try gz.addUnNode(.log2_int_type, int_type, params[0]);
-            const ptr_type = try gz.add(.{ .tag = .ptr_type_simple, .data = .{
-                .ptr_type_simple = .{
-                    .is_allowzero = false,
-                    .is_mutable = true,
-                    .is_volatile = false,
-                    .size = .One,
-                    .elem_type = int_type,
-                },
-            } });
+            const ptr_type = try gz.addUnNode(.overflow_arithmetic_ptr, int_type, params[0]);
             const lhs = try expr(gz, scope, .{ .ty = int_type }, params[1]);
             const rhs = try expr(gz, scope, .{ .ty = log2_int_type }, params[2]);
             const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[3]);
@@ -7987,15 +7964,7 @@ fn overflowArithmetic(
     tag: Zir.Inst.Extended,
 ) InnerError!Zir.Inst.Ref {
     const int_type = try typeExpr(gz, scope, params[0]);
-    const ptr_type = try gz.add(.{ .tag = .ptr_type_simple, .data = .{
-        .ptr_type_simple = .{
-            .is_allowzero = false,
-            .is_mutable = true,
-            .is_volatile = false,
-            .size = .One,
-            .elem_type = int_type,
-        },
-    } });
+    const ptr_type = try gz.addUnNode(.overflow_arithmetic_ptr, int_type, params[0]);
     const lhs = try expr(gz, scope, .{ .ty = int_type }, params[1]);
     const rhs = try expr(gz, scope, .{ .ty = int_type }, params[2]);
     const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[3]);
src/Module.zig
@@ -2466,6 +2466,90 @@ pub const SrcLoc = struct {
 
                 return nodeToSpan(tree, node_datas[node].lhs);
             },
+            .node_offset_ptr_elem => |node_off| {
+                const tree = try src_loc.file_scope.getTree(gpa);
+                const node_tags = tree.nodes.items(.tag);
+                const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+
+                const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
+                    .ptr_type_aligned => tree.ptrTypeAligned(parent_node),
+                    .ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
+                    .ptr_type => tree.ptrType(parent_node),
+                    .ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
+                    else => unreachable,
+                };
+                return nodeToSpan(tree, full.ast.child_type);
+            },
+            .node_offset_ptr_sentinel => |node_off| {
+                const tree = try src_loc.file_scope.getTree(gpa);
+                const node_tags = tree.nodes.items(.tag);
+                const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+
+                const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
+                    .ptr_type_aligned => tree.ptrTypeAligned(parent_node),
+                    .ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
+                    .ptr_type => tree.ptrType(parent_node),
+                    .ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
+                    else => unreachable,
+                };
+                return nodeToSpan(tree, full.ast.sentinel);
+            },
+            .node_offset_ptr_align => |node_off| {
+                const tree = try src_loc.file_scope.getTree(gpa);
+                const node_tags = tree.nodes.items(.tag);
+                const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+
+                const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
+                    .ptr_type_aligned => tree.ptrTypeAligned(parent_node),
+                    .ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
+                    .ptr_type => tree.ptrType(parent_node),
+                    .ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
+                    else => unreachable,
+                };
+                return nodeToSpan(tree, full.ast.align_node);
+            },
+            .node_offset_ptr_addrspace => |node_off| {
+                const tree = try src_loc.file_scope.getTree(gpa);
+                const node_tags = tree.nodes.items(.tag);
+                const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+
+                const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
+                    .ptr_type_aligned => tree.ptrTypeAligned(parent_node),
+                    .ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
+                    .ptr_type => tree.ptrType(parent_node),
+                    .ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
+                    else => unreachable,
+                };
+                return nodeToSpan(tree, full.ast.addrspace_node);
+            },
+            .node_offset_ptr_bitoffset => |node_off| {
+                const tree = try src_loc.file_scope.getTree(gpa);
+                const node_tags = tree.nodes.items(.tag);
+                const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+
+                const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
+                    .ptr_type_aligned => tree.ptrTypeAligned(parent_node),
+                    .ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
+                    .ptr_type => tree.ptrType(parent_node),
+                    .ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
+                    else => unreachable,
+                };
+                return nodeToSpan(tree, full.ast.bit_range_start);
+            },
+            .node_offset_ptr_hostsize => |node_off| {
+                const tree = try src_loc.file_scope.getTree(gpa);
+                const node_tags = tree.nodes.items(.tag);
+                const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+
+                const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
+                    .ptr_type_aligned => tree.ptrTypeAligned(parent_node),
+                    .ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
+                    .ptr_type => tree.ptrType(parent_node),
+                    .ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
+                    else => unreachable,
+                };
+                return nodeToSpan(tree, full.ast.bit_range_end);
+            },
         }
     }
 
@@ -2739,6 +2823,24 @@ pub const LazySrcLoc = union(enum) {
     /// The source location points to the operand of an unary expression.
     /// The Decl is determined contextually.
     node_offset_un_op: i32,
+    /// The source location points to the elem type of a pointer.
+    /// The Decl is determined contextually.
+    node_offset_ptr_elem: i32,
+    /// The source location points to the sentinel of a pointer.
+    /// The Decl is determined contextually.
+    node_offset_ptr_sentinel: i32,
+    /// The source location points to the align expr of a pointer.
+    /// The Decl is determined contextually.
+    node_offset_ptr_align: i32,
+    /// The source location points to the addrspace expr of a pointer.
+    /// The Decl is determined contextually.
+    node_offset_ptr_addrspace: i32,
+    /// The source location points to the bit-offset of a pointer.
+    /// The Decl is determined contextually.
+    node_offset_ptr_bitoffset: i32,
+    /// The source location points to the host size of a pointer.
+    /// The Decl is determined contextually.
+    node_offset_ptr_hostsize: i32,
 
     pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
 
@@ -2803,6 +2905,12 @@ pub const LazySrcLoc = union(enum) {
             .node_offset_array_type_sentinel,
             .node_offset_array_type_elem,
             .node_offset_un_op,
+            .node_offset_ptr_elem,
+            .node_offset_ptr_sentinel,
+            .node_offset_ptr_align,
+            .node_offset_ptr_addrspace,
+            .node_offset_ptr_bitoffset,
+            .node_offset_ptr_hostsize,
             => .{
                 .file_scope = decl.getFileScope(),
                 .parent_decl_node = decl.src_node,
src/print_zir.zig
@@ -233,6 +233,7 @@ const Writer = struct {
             .validate_struct_init_ty,
             .make_ptr_const,
             .validate_deref,
+            .overflow_arithmetic_ptr,
             => try self.writeUnNode(stream, inst),
 
             .ref,
@@ -247,7 +248,6 @@ const Writer = struct {
 
             .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),
             .param_type => try self.writeParamType(stream, inst),
-            .ptr_type_simple => try self.writePtrTypeSimple(stream, inst),
             .ptr_type => try self.writePtrType(stream, inst),
             .int => try self.writeInt(stream, inst),
             .int_big => try self.writeIntBig(stream, inst),
@@ -601,24 +601,6 @@ const Writer = struct {
         try stream.print(", {d})", .{inst_data.param_index});
     }
 
-    fn writePtrTypeSimple(
-        self: *Writer,
-        stream: anytype,
-        inst: Zir.Inst.Index,
-    ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
-        const inst_data = self.code.instructions.items(.data)[inst].ptr_type_simple;
-        const str_allowzero = if (inst_data.is_allowzero) "allowzero, " else "";
-        const str_const = if (!inst_data.is_mutable) "const, " else "";
-        const str_volatile = if (inst_data.is_volatile) "volatile, " else "";
-        try self.writeInstRef(stream, inst_data.elem_type);
-        try stream.print(", {s}{s}{s}{s})", .{
-            str_allowzero,
-            str_const,
-            str_volatile,
-            @tagName(inst_data.size),
-        });
-    }
-
     fn writePtrType(
         self: *Writer,
         stream: anytype,
@@ -660,7 +642,8 @@ const Writer = struct {
             try self.writeInstRef(stream, @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]));
             try stream.writeAll(")");
         }
-        try stream.writeAll(")");
+        try stream.writeAll(") ");
+        try self.writeSrc(stream, LazySrcLoc.nodeOffset(extra.data.src_node));
     }
 
     fn writeInt(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
src/Sema.zig
@@ -768,7 +768,7 @@ fn analyzeBodyInner(
             .optional_type                => try sema.zirOptionalType(block, inst),
             .param_type                   => try sema.zirParamType(block, inst),
             .ptr_type                     => try sema.zirPtrType(block, inst),
-            .ptr_type_simple              => try sema.zirPtrTypeSimple(block, inst),
+            .overflow_arithmetic_ptr      => try sema.zirOverflowArithmeticPtr(block, inst),
             .ref                          => try sema.zirRef(block, inst),
             .ret_err_value_code           => try sema.zirRetErrValueCode(inst),
             .shr                          => try sema.zirShr(block, inst, .shr),
@@ -13835,22 +13835,21 @@ fn floatOpAllowed(tag: Zir.Inst.Tag) bool {
     };
 }
 
-fn zirPtrTypeSimple(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
+fn zirOverflowArithmeticPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
     const tracy = trace(@src());
     defer tracy.end();
 
-    const inst_data = sema.code.instructions.items(.data)[inst].ptr_type_simple;
-    const elem_ty_src = sema.src; // TODO better source location
-    const elem_type = try sema.resolveType(block, elem_ty_src, inst_data.elem_type);
+    const inst_data = sema.code.instructions.items(.data)[inst].un_node;
+    const elem_ty_src = inst_data.src();
+    const elem_type = try sema.resolveType(block, elem_ty_src, inst_data.operand);
     const ty = try Type.ptr(sema.arena, sema.mod, .{
         .pointee_type = elem_type,
         .@"addrspace" = .generic,
-        .mutable = inst_data.is_mutable,
-        .@"allowzero" = inst_data.is_allowzero or inst_data.size == .C,
-        .@"volatile" = inst_data.is_volatile,
-        .size = inst_data.size,
+        .mutable = true,
+        .@"allowzero" = false,
+        .@"volatile" = false,
+        .size = .One,
     });
-    try sema.validatePtrTy(block, elem_ty_src, ty);
     return sema.addType(ty);
 }
 
@@ -13858,14 +13857,15 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
     const tracy = trace(@src());
     defer tracy.end();
 
-    const src: LazySrcLoc = sema.src; // TODO better source location
-    const elem_ty_src: LazySrcLoc = sema.src; // TODO better source location
-    const sentinel_src: LazySrcLoc = sema.src; // TODO better source location
-    const addrspace_src: LazySrcLoc = sema.src; // TODO better source location
-    const bitoffset_src: LazySrcLoc = sema.src; // TODO better source location
-    const hostsize_src: LazySrcLoc = sema.src; // TODO better source location
     const inst_data = sema.code.instructions.items(.data)[inst].ptr_type;
     const extra = sema.code.extraData(Zir.Inst.PtrType, inst_data.payload_index);
+    const elem_ty_src: LazySrcLoc = .{ .node_offset_ptr_elem = extra.data.src_node };
+    const sentinel_src: LazySrcLoc = .{ .node_offset_ptr_sentinel = extra.data.src_node };
+    const align_src: LazySrcLoc = .{ .node_offset_ptr_align = extra.data.src_node };
+    const addrspace_src: LazySrcLoc = .{ .node_offset_ptr_addrspace = extra.data.src_node };
+    const bitoffset_src: LazySrcLoc = .{ .node_offset_ptr_bitoffset = extra.data.src_node };
+    const hostsize_src: LazySrcLoc = .{ .node_offset_ptr_hostsize = extra.data.src_node };
+
     const unresolved_elem_ty = try sema.resolveType(block, elem_ty_src, extra.data.elem_type);
     const target = sema.mod.getTarget();
 
@@ -13880,8 +13880,8 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
     const abi_align: u32 = if (inst_data.flags.has_align) blk: {
         const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
         extra_i += 1;
-        const coerced = try sema.coerce(block, Type.u32, try sema.resolveInst(ref), src);
-        const val = try sema.resolveConstValue(block, src, coerced);
+        const coerced = try sema.coerce(block, Type.u32, try sema.resolveInst(ref), align_src);
+        const val = try sema.resolveConstValue(block, align_src, coerced);
         // Check if this happens to be the lazy alignment of our element type, in
         // which case we can make this 0 without resolving it.
         if (val.castTag(.lazy_align)) |payload| {
@@ -13889,7 +13889,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
                 break :blk 0;
             }
         }
-        const abi_align = (try val.getUnsignedIntAdvanced(target, sema.kit(block, src))).?;
+        const abi_align = (try val.getUnsignedIntAdvanced(target, sema.kit(block, align_src))).?;
         break :blk @intCast(u32, abi_align);
     } else 0;
 
@@ -13914,7 +13914,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
     } else 0;
 
     if (host_size != 0 and bit_offset >= host_size * 8) {
-        return sema.fail(block, src, "bit offset starts after end of host integer", .{});
+        return sema.fail(block, bitoffset_src, "bit offset starts after end of host integer", .{});
     }
 
     const elem_ty = if (abi_align == 0)
@@ -13924,48 +13924,43 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
         try sema.resolveTypeLayout(block, elem_ty_src, elem_ty);
         break :t elem_ty;
     };
-    const ty = try Type.ptr(sema.arena, sema.mod, .{
-        .pointee_type = elem_ty,
-        .sentinel = sentinel,
-        .@"align" = abi_align,
-        .@"addrspace" = address_space,
-        .bit_offset = bit_offset,
-        .host_size = host_size,
-        .mutable = inst_data.flags.is_mutable,
-        .@"allowzero" = inst_data.flags.is_allowzero,
-        .@"volatile" = inst_data.flags.is_volatile,
-        .size = inst_data.size,
-    });
-    try sema.validatePtrTy(block, elem_ty_src, ty);
-    return sema.addType(ty);
-}
 
-fn validatePtrTy(sema: *Sema, block: *Block, elem_src: LazySrcLoc, ty: Type) CompileError!void {
-    const ptr_info = ty.ptrInfo().data;
-    const pointee_tag = ptr_info.pointee_type.zigTypeTag();
-    if (pointee_tag == .NoReturn) {
-        return sema.fail(block, elem_src, "pointer to noreturn not allowed", .{});
-    } else if (ptr_info.size == .Many and pointee_tag == .Opaque) {
-        return sema.fail(block, elem_src, "unknown-length pointer to opaque not allowed", .{});
-    } else if (ptr_info.size == .C) {
-        const elem_ty = ptr_info.pointee_type;
+    if (elem_ty.zigTypeTag() == .NoReturn) {
+        return sema.fail(block, elem_ty_src, "pointer to noreturn not allowed", .{});
+    } else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) {
+        return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});
+    } else if (inst_data.size == .C) {
         if (!(try sema.validateExternType(elem_ty, .other))) {
             const msg = msg: {
-                const msg = try sema.errMsg(block, elem_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
+                const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
                 errdefer msg.destroy(sema.gpa);
 
                 const src_decl = sema.mod.declPtr(block.src_decl);
-                try sema.explainWhyTypeIsNotExtern(block, elem_src, msg, elem_src.toSrcLoc(src_decl), elem_ty, .other);
+                try sema.explainWhyTypeIsNotExtern(block, elem_ty_src, msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other);
 
                 try sema.addDeclaredHereNote(msg, elem_ty);
                 break :msg msg;
             };
             return sema.failWithOwnedErrorMsg(block, msg);
         }
-        if (pointee_tag == .Opaque) {
-            return sema.fail(block, elem_src, "C pointers cannot point to opaque types", .{});
+        if (elem_ty.zigTypeTag() == .Opaque) {
+            return sema.fail(block, elem_ty_src, "C pointers cannot point to opaque types", .{});
         }
     }
+
+    const ty = try Type.ptr(sema.arena, sema.mod, .{
+        .pointee_type = elem_ty,
+        .sentinel = sentinel,
+        .@"align" = abi_align,
+        .@"addrspace" = address_space,
+        .bit_offset = bit_offset,
+        .host_size = host_size,
+        .mutable = inst_data.flags.is_mutable,
+        .@"allowzero" = inst_data.flags.is_allowzero,
+        .@"volatile" = inst_data.flags.is_volatile,
+        .size = inst_data.size,
+    });
+    return sema.addType(ty);
 }
 
 fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
src/Zir.zig
@@ -534,9 +534,9 @@ pub const Inst = struct {
         /// Obtains the return type of the in-scope function.
         /// Uses the `node` union field.
         ret_type,
-        /// Create a pointer type that does not have a sentinel, alignment, address space, or bit range specified.
-        /// Uses the `ptr_type_simple` union field.
-        ptr_type_simple,
+        /// Create a pointer type for overflow arithmetic.
+        /// TODO remove when doing https://github.com/ziglang/zig/issues/10248
+        overflow_arithmetic_ptr,
         /// Create a pointer type which can have a sentinel, alignment, address space, and/or bit range.
         /// Uses the `ptr_type` union field.
         ptr_type,
@@ -1121,7 +1121,7 @@ pub const Inst = struct {
                 .err_union_code,
                 .err_union_code_ptr,
                 .ptr_type,
-                .ptr_type_simple,
+                .overflow_arithmetic_ptr,
                 .ensure_err_payload_void,
                 .enum_literal,
                 .merge_error_sets,
@@ -1417,7 +1417,7 @@ pub const Inst = struct {
                 .err_union_code,
                 .err_union_code_ptr,
                 .ptr_type,
-                .ptr_type_simple,
+                .overflow_arithmetic_ptr,
                 .enum_literal,
                 .merge_error_sets,
                 .error_union_type,
@@ -1659,7 +1659,7 @@ pub const Inst = struct {
                 .ret_err_value_code = .str_tok,
                 .ret_ptr = .node,
                 .ret_type = .node,
-                .ptr_type_simple = .ptr_type_simple,
+                .overflow_arithmetic_ptr = .un_node,
                 .ptr_type = .ptr_type,
                 .slice_start = .pl_node,
                 .slice_end = .pl_node,
@@ -2499,13 +2499,6 @@ pub const Inst = struct {
         node: i32,
         int: u64,
         float: f64,
-        ptr_type_simple: struct {
-            is_allowzero: bool,
-            is_mutable: bool,
-            is_volatile: bool,
-            size: std.builtin.Type.Pointer.Size,
-            elem_type: Ref,
-        },
         ptr_type: struct {
             flags: packed struct {
                 is_allowzero: bool,
@@ -2608,7 +2601,6 @@ pub const Inst = struct {
             node,
             int,
             float,
-            ptr_type_simple,
             ptr_type,
             int_type,
             bool_br,
@@ -2869,6 +2861,7 @@ pub const Inst = struct {
     /// 4. host_size: Ref // if `has_bit_range` flag is set
     pub const PtrType = struct {
         elem_type: Ref,
+        src_node: i32,
     };
 
     pub const ArrayTypeSentinel = struct {
test/cases/compile_errors/stage1/obj/C_pointer_pointing_to_non_C_ABI_compatible_type_or_has_align_attr.zig
@@ -1,12 +0,0 @@
-const Foo = struct {};
-export fn a() void {
-    const T = [*c]Foo;
-    var t: T = undefined;
-    _ = t;
-}
-
-// error
-// backend=stage1
-// target=native
-//
-// tmp.zig:3:19: error: C pointers cannot point to non-C-ABI-compatible type 'Foo'
test/cases/compile_errors/stage1/obj/unknown_length_pointer_to_opaque.zig
@@ -1,7 +0,0 @@
-export const T = [*]opaque {};
-
-// error
-// backend=stage1
-// target=native
-//
-// tmp.zig:1:21: error: unknown-length pointer to opaque
test/cases/compile_errors/stage1/obj/attempt_to_use_0_bit_type_in_extern_fn.zig → test/cases/compile_errors/stage1/attempt_to_use_0_bit_type_in_extern_fn.zig
File renamed without changes
test/cases/compile_errors/stage1/obj/issue_2687_coerce_from_undefined_array_pointer_to_slice.zig → test/cases/compile_errors/stage1/issue_2687_coerce_from_undefined_array_pointer_to_slice.zig
File renamed without changes
test/cases/compile_errors/C_pointer_pointing_to_non_C_ABI_compatible_type_or_has_align_attr.zig
@@ -0,0 +1,14 @@
+const Foo = struct {};
+export fn a() void {
+    const T = [*c]Foo;
+    var t: T = undefined;
+    _ = t;
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :3:19: error: C pointers cannot point to non-C-ABI-compatible type 'tmp.Foo'
+// :3:19: note: only structs with packed or extern layout are extern compatible
+// :1:13: note: struct declared here
test/cases/compile_errors/stage1/obj/C_pointer_to_anyopaque.zig → test/cases/compile_errors/C_pointer_to_anyopaque.zig
@@ -5,7 +5,7 @@ export fn a() void {
 }
 
 // error
-// backend=stage1
+// backend=stage2
 // target=native
 //
-// tmp.zig:3:16: error: C pointers cannot point to opaque types
+// :3:16: error: C pointers cannot point to opaque types
test/cases/compile_errors/c_pointer_to_void.zig
@@ -7,5 +7,5 @@ export fn entry() void {
 // backend=stage2
 // target=native
 //
-// :1:1: error: C pointers cannot point to non-C-ABI-compatible type 'void'
-// :1:1: note: 'void' is a zero bit type; for C 'void' use 'anyopaque'
+// :2:16: error: C pointers cannot point to non-C-ABI-compatible type 'void'
+// :2:16: note: 'void' is a zero bit type; for C 'void' use 'anyopaque'
test/cases/compile_errors/container_init_with_non-type.zig
@@ -7,4 +7,4 @@ export fn entry() usize { return @sizeOf(@TypeOf(a)); }
 // backend=stage2
 // target=native
 //
-// :2:15: error: expected type 'type', found 'i32'
+// :2:11: error: expected type 'type', found 'i32'
test/cases/compile_errors/stage1/obj/pointer_to_noreturn.zig → test/cases/compile_errors/pointer_to_noreturn.zig
@@ -2,7 +2,7 @@ fn a() *noreturn {}
 export fn entry() void { _ = a(); }
 
 // error
-// backend=stage1
+// backend=stage2
 // target=native
 //
-// tmp.zig:1:9: error: pointer to noreturn not allowed
+// :1:9: error: pointer to noreturn not allowed
test/cases/compile_errors/slice_passed_as_array_init_type_with_elems.zig
@@ -7,5 +7,5 @@ export fn entry() void {
 // backend=stage2
 // target=native
 //
-// :2:19: error: type '[]u8' does not support array initialization syntax
-// :2:19: note: inferred array length is specified with an underscore: '[_]u8'
+// :2:15: error: type '[]u8' does not support array initialization syntax
+// :2:15: note: inferred array length is specified with an underscore: '[_]u8'
test/cases/compile_errors/unknown_length_pointer_to_opaque.zig
@@ -0,0 +1,7 @@
+export const T = [*]opaque {};
+
+// error
+// backend=stage2
+// target=native
+//
+// :1:21: error: unknown-length pointer to opaque not allowed
test/cases/compile_errors/stage1/obj/using_an_unknown_len_ptr_type_instead_of_array.zig → test/cases/compile_errors/using_an_unknown_len_ptr_type_instead_of_array.zig
@@ -7,7 +7,7 @@ comptime {
 }
 
 // error
-// backend=stage1
+// backend=stage2
 // target=native
 //
-// tmp.zig:1:21: error: expected array type or [_], found '[*][*]const u8'
+// :1:22: error: type '[*][*]const u8' does not support array initialization syntax