diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2025-08-31 20:40:15 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2025-08-31 20:40:15 -0700 |
| commit | f250802ce794589f77367113335216c1993f7412 (patch) | |
| tree | 80f260bc0447d67924caa4162344ad21bf71ea2a /src | |
| parent | fc23fe90ce1f3d28841c5a5a93a8bdf7edaefc54 (diff) | |
| download | zig-f250802ce794589f77367113335216c1993f7412.tar.gz zig-f250802ce794589f77367113335216c1993f7412.zip | |
compiler: introduce `@Restrict` builtinrestricted-function-pointers
conservative, incomplete change
Diffstat (limited to 'src')
| -rw-r--r-- | src/InternPool.zig | 41 | ||||
| -rw-r--r-- | src/Sema.zig | 22 | ||||
| -rw-r--r-- | src/Zcu/PerThread.zig | 6 | ||||
| -rw-r--r-- | src/print_zir.zig | 1 |
4 files changed, 70 insertions, 0 deletions
diff --git a/src/InternPool.zig b/src/InternPool.zig index 9965497742..ed20d939a9 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -117,6 +117,13 @@ pub const empty: InternPool = .{ .free_dep_entries = .empty, }; +pub const RestrictedSetIndex = enum(u32) { + /// placeholder while I slowly work my way towards a more complete implementation + some = 0, + none = std.math.maxInt(u32), + _, +}; + /// A `TrackedInst.Index` provides a single, unchanging reference to a ZIR instruction across a whole /// compilation. From this index, you can acquire a `TrackedInst`, which containss a reference to both /// the file which the instruction lives in, and the instruction index itself, which is updated on @@ -2079,6 +2086,7 @@ pub const Key = union(enum) { sentinel: Index = .none, flags: Flags = .{}, packed_offset: PackedOffset = .{ .bit_offset = 0, .host_size = 0 }, + restricted_set: RestrictedSetIndex = .none, pub const VectorIndex = enum(u16) { none = std.math.maxInt(u16), @@ -5389,6 +5397,9 @@ pub const Tag = enum(u8) { type_vector, /// A fully explicitly specified pointer type. type_pointer, + /// A pointer type created by using the `@Restrict` builtin. + /// data is `Index` of underlying, non-restrict pointer type. + type_pointer_restricted, /// A slice type. /// data is Index of underlying pointer type. type_slice, @@ -5666,6 +5677,7 @@ pub const Tag = enum(u8) { .type_array_small = .{ .summary = .@"[{.payload.len%value}]{.payload.child%summary}", .payload = Vector }, .type_vector = .{ .summary = .@"@Vector({.payload.len%value}, {.payload.child%summary})", .payload = Vector }, .type_pointer = .{ .summary = .@"*... {.payload.child%summary}", .payload = TypePointer }, + .type_pointer_restricted = .{ .summary = .@"@Restrict(*... {.payload.child%summary})", .data = Index }, .type_slice = .{ .summary = .@"[]... {.data.unwrapped.payload.child%summary}", .data = Index }, .type_optional = .{ .summary = .@"?{.data%summary}", .data = Index }, .type_anyframe = .{ .summary = .@"anyframe->{.data%summary}", .data = Index }, @@ -6970,6 +6982,16 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { .type_pointer => .{ .ptr_type = extraData(unwrapped_index.getExtra(ip), Tag.TypePointer, data) }, + .type_pointer_restricted => { + const child_ptr_index: Index = @enumFromInt(data); + const child_ptr_unwrapped = child_ptr_index.unwrap(ip); + const child_ptr_item = child_ptr_unwrapped.getItem(ip); + assert(child_ptr_item.tag == .type_pointer); + var ptr_info = extraData(child_ptr_unwrapped.getExtra(ip), Tag.TypePointer, child_ptr_item.data); + ptr_info.restricted_set = .some; + return .{ .ptr_type = ptr_info }; + }, + .type_slice => { const many_ptr_index: Index = @enumFromInt(data); const many_ptr_unwrapped = many_ptr_index.unwrap(ip); @@ -10388,6 +10410,7 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 { TrackedInst.Index, TrackedInst.Index.Optional, ComptimeAllocIndex, + RestrictedSetIndex, => @intFromEnum(@field(item, field.name)), u32, @@ -10451,6 +10474,7 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat TrackedInst.Index, TrackedInst.Index.Optional, ComptimeAllocIndex, + RestrictedSetIndex, => @enumFromInt(extra_item), u32, @@ -11092,6 +11116,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { .type_array_big => @sizeOf(Array), .type_vector => @sizeOf(Vector), .type_pointer => @sizeOf(Tag.TypePointer), + .type_pointer_restricted => 0, .type_slice => 0, .type_optional => 0, .type_anyframe => 0, @@ -11319,6 +11344,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { .type_array_big, .type_vector, .type_pointer, + .type_pointer_restricted, .type_optional, .type_anyframe, .type_error_union, @@ -11902,6 +11928,19 @@ pub fn getOrPutTrailingString( return value; } +pub fn restrictedFunctionPointerType( + ip: *InternPool, + gpa: Allocator, + tid: Zcu.PerThread.Id, + fn_ty: Index, +) Allocator.Error!Index { + _ = ip; + _ = gpa; + _ = tid; + _ = fn_ty; + @panic("TODO"); +} + pub fn getString(ip: *InternPool, key: []const u8) OptionalNullTerminatedString { const full_hash = Hash.hash(0, key); const hash: u32 = @truncate(full_hash >> 32); @@ -12055,6 +12094,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { .type_array_small, .type_vector, .type_pointer, + .type_pointer_restricted, .type_slice, .type_optional, .type_anyframe, @@ -12411,6 +12451,7 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId { .type_vector => .vector, .type_pointer, + .type_pointer_restricted, .type_slice, => .pointer, diff --git a/src/Sema.zig b/src/Sema.zig index 007e1a7fef..a714bda4e3 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1305,6 +1305,7 @@ fn analyzeBodyInner( .validate_array_init_ref_ty => try sema.zirValidateArrayInitRefTy(block, inst), .opt_eu_base_ptr_init => try sema.zirOptEuBasePtrInit(block, inst), .coerce_ptr_elem_ty => try sema.zirCoercePtrElemTy(block, inst), + .restrict => try sema.zirRestrict(block, inst), .clz => try sema.zirBitCount(block, inst, .clz, Value.clz), .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz), @@ -4681,6 +4682,26 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE } } +fn zirRestrict(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { + const pt = sema.pt; + const zcu = pt.zcu; + + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; + const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const ptr_ty = try sema.resolveType(block, ty_src, inst_data.operand); + + try sema.checkPtrOperand(block, ty_src, ptr_ty); + + const ptr_info = ptr_ty.ptrInfo(zcu); + const pointee_ty: Type = .fromInterned(ptr_info.child); + if (ptr_info.flags.size != .one or pointee_ty.zigTypeTag(zcu) == .@"fn") { + return sema.fail(block, ty_src, "expected function pointer type; found {f}", .{ptr_ty.fmt(pt)}); + } + + const new_ty = try pt.restrictedFunctionPointerType(pointee_ty); + return .fromType(new_ty); +} + fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; @@ -36062,6 +36083,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { .type_int_signed, // i0 handled above .type_int_unsigned, // u0 handled above .type_pointer, + .type_pointer_restricted, .type_slice, .type_anyframe, .type_error_union, diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 3c2bb27dab..f3daa13ccd 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -3420,6 +3420,8 @@ pub fn internUnion(pt: Zcu.PerThread, un: InternPool.Key.Union) Allocator.Error! /// this because it requires potentially pushing to the job queue. pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!Value { const ip = &pt.zcu.intern_pool; + // TODO: avoid indexToKey + // TODO: check if dest is restricted function pointer type switch (ip.indexToKey(val.toIntern())) { .@"extern" => |e| { const coerced = try pt.getExtern(.{ @@ -3544,6 +3546,10 @@ pub fn funcType(pt: Zcu.PerThread, key: InternPool.GetFuncTypeKey) Allocator.Err return Type.fromInterned(try pt.zcu.intern_pool.getFuncType(pt.zcu.gpa, pt.tid, key)); } +pub fn restrictedFunctionPointerType(pt: Zcu.PerThread, fn_ty: Type) Allocator.Error!Type { + return .fromInterned(try pt.zcu.intern_pool.restrictedFunctionPointerType(pt.zcu.gpa, pt.tid, fn_ty.toIntern())); +} + /// Use this for `anyframe->T` only. /// For `anyframe`, use the `InternPool.Index.anyframe` tag directly. pub fn anyframeType(pt: Zcu.PerThread, payload_ty: Type) Allocator.Error!Type { diff --git a/src/print_zir.zig b/src/print_zir.zig index f875aaa552..bc0d02a5fd 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -266,6 +266,7 @@ const Writer = struct { .opt_eu_base_ptr_init, .restore_err_ret_index_unconditional, .restore_err_ret_index_fn_entry, + .restrict, => try self.writeUnNode(stream, inst), .ref, |
