From d72917320449f449bcdeb6a20d5a98b1dfb901d4 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Tue, 12 Jul 2022 16:08:23 +0300 Subject: stage2: better pointer source location --- src/AstGen.zig | 47 ++++-------------------- src/Module.zig | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/Sema.zig | 91 ++++++++++++++++++++++----------------------- src/Zir.zig | 21 ++++------- src/print_zir.zig | 23 ++---------- 5 files changed, 169 insertions(+), 121 deletions(-) (limited to 'src') diff --git a/src/AstGen.zig b/src/AstGen.zig index 252610aeeb..9941fe54e8 100644 --- a/src/AstGen.zig +++ b/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]); diff --git a/src/Module.zig b/src/Module.zig index 4a5257a4f3..0f38da13e9 100644 --- a/src/Module.zig +++ b/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, diff --git a/src/Sema.zig b/src/Sema.zig index b821a32fc7..94909de78c 100644 --- a/src/Sema.zig +++ b/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 { diff --git a/src/Zir.zig b/src/Zir.zig index b3126ea2f3..73ba396e75 100644 --- a/src/Zir.zig +++ b/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 { diff --git a/src/print_zir.zig b/src/print_zir.zig index 878fa0c14c..96923c6d86 100644 --- a/src/print_zir.zig +++ b/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 { -- cgit v1.2.3