authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-05-02 01:59:38+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-22 07:01:07-07:00
log33809a0c538b77770ef4f80e8208117d6bcb494e
tree73cd9f783fbb3e4fe91af5e1df1d62b85e1a41bc
parent2648e3651eb3025d6ea958e269f4cb8b8786ce07

InternPool: eliminate `var_args_param_type`

This was a "fake" type used to handle C varargs parameters, much like generic poison. In fact, it is treated identically to generic poison in all cases other than one (the final coercion of a call argument), which is trivially special-cased. Thus, it makes sense to remove this special tag and instead use `generic_poison_type` in its place. This fixes several bugs in Sema related to missing handling of this tag. Resolves: #19781

6 files changed, 15 insertions(+), 35 deletions(-)

lib/std/zig/Zir.zig-3
...@@ -2194,9 +2194,6 @@ pub const Inst = struct {...@@ -2194,9 +2194,6 @@ pub const Inst = struct {
2194 empty_struct,2194 empty_struct,
2195 generic_poison,2195 generic_poison,
21962196
2197 /// This tag is here to match Air and InternPool, however it is unused
2198 /// for ZIR purposes.
2199 var_args_param_type = std.math.maxInt(u32) - 1,
2200 /// This Ref does not correspond to any ZIR instruction or constant2197 /// This Ref does not correspond to any ZIR instruction or constant
2201 /// value and may instead be used as a sentinel to indicate null.2198 /// value and may instead be used as a sentinel to indicate null.
2202 none = std.math.maxInt(u32),2199 none = std.math.maxInt(u32),
src/Air.zig+2-8
...@@ -891,8 +891,7 @@ pub const Inst = struct {...@@ -891,8 +891,7 @@ pub const Inst = struct {
891 /// The most-significant bit of the value is a tag bit. This bit is 1 if the value represents an891 /// The most-significant bit of the value is a tag bit. This bit is 1 if the value represents an
892 /// instruction index and 0 if it represents an InternPool index.892 /// instruction index and 0 if it represents an InternPool index.
893 ///893 ///
894 /// The hardcoded refs `none` and `var_args_param_type` are exceptions to this rule: they have894 /// The ref `none` is an exception: it has the tag bit set but refers to the InternPool.
895 /// their tag bit set but refer to the InternPool.
896 pub const Ref = enum(u32) {895 pub const Ref = enum(u32) {
897 u0_type = @intFromEnum(InternPool.Index.u0_type),896 u0_type = @intFromEnum(InternPool.Index.u0_type),
898 i0_type = @intFromEnum(InternPool.Index.i0_type),897 i0_type = @intFromEnum(InternPool.Index.i0_type),
...@@ -979,9 +978,6 @@ pub const Inst = struct {...@@ -979,9 +978,6 @@ pub const Inst = struct {
979 empty_struct = @intFromEnum(InternPool.Index.empty_struct),978 empty_struct = @intFromEnum(InternPool.Index.empty_struct),
980 generic_poison = @intFromEnum(InternPool.Index.generic_poison),979 generic_poison = @intFromEnum(InternPool.Index.generic_poison),
981980
982 /// This Ref does not correspond to any AIR instruction or constant
983 /// value. It is used to handle argument types of var args functions.
984 var_args_param_type = @intFromEnum(InternPool.Index.var_args_param_type),
985 /// This Ref does not correspond to any AIR instruction or constant981 /// This Ref does not correspond to any AIR instruction or constant
986 /// value and may instead be used as a sentinel to indicate null.982 /// value and may instead be used as a sentinel to indicate null.
987 none = @intFromEnum(InternPool.Index.none),983 none = @intFromEnum(InternPool.Index.none),
...@@ -994,7 +990,6 @@ pub const Inst = struct {...@@ -994,7 +990,6 @@ pub const Inst = struct {
994990
995 pub fn toInternedAllowNone(ref: Ref) ?InternPool.Index {991 pub fn toInternedAllowNone(ref: Ref) ?InternPool.Index {
996 return switch (ref) {992 return switch (ref) {
997 .var_args_param_type => .var_args_param_type,
998 .none => .none,993 .none => .none,
999 else => if (@intFromEnum(ref) >> 31 == 0)994 else => if (@intFromEnum(ref) >> 31 == 0)
1000 @enumFromInt(@as(u31, @truncate(@intFromEnum(ref))))995 @enumFromInt(@as(u31, @truncate(@intFromEnum(ref))))
...@@ -1010,7 +1005,7 @@ pub const Inst = struct {...@@ -1010,7 +1005,7 @@ pub const Inst = struct {
10101005
1011 pub fn toIndexAllowNone(ref: Ref) ?Index {1006 pub fn toIndexAllowNone(ref: Ref) ?Index {
1012 return switch (ref) {1007 return switch (ref) {
1013 .var_args_param_type, .none => null,1008 .none => null,
1014 else => if (@intFromEnum(ref) >> 31 != 0)1009 else => if (@intFromEnum(ref) >> 31 != 0)
1015 @enumFromInt(@as(u31, @truncate(@intFromEnum(ref))))1010 @enumFromInt(@as(u31, @truncate(@intFromEnum(ref))))
1016 else1011 else
...@@ -1557,7 +1552,6 @@ pub fn deinit(air: *Air, gpa: std.mem.Allocator) void {...@@ -1557,7 +1552,6 @@ pub fn deinit(air: *Air, gpa: std.mem.Allocator) void {
15571552
1558pub fn internedToRef(ip_index: InternPool.Index) Inst.Ref {1553pub fn internedToRef(ip_index: InternPool.Index) Inst.Ref {
1559 return switch (ip_index) {1554 return switch (ip_index) {
1560 .var_args_param_type => .var_args_param_type,
1561 .none => .none,1555 .none => .none,
1562 else => {1556 else => {
1563 assert(@intFromEnum(ip_index) >> 31 == 0);1557 assert(@intFromEnum(ip_index) >> 31 == 0);
src/InternPool.zig-4
...@@ -2818,7 +2818,6 @@ pub const Index = enum(u32) {...@@ -2818,7 +2818,6 @@ pub const Index = enum(u32) {
2818 generic_poison,2818 generic_poison,
28192819
2820 /// Used by Air/Sema only.2820 /// Used by Air/Sema only.
2821 var_args_param_type = std.math.maxInt(u32) - 1,
2822 none = std.math.maxInt(u32),2821 none = std.math.maxInt(u32),
28232822
2824 _,2823 _,
...@@ -8938,7 +8937,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -8938,7 +8937,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
8938 .memoized_call => unreachable,8937 .memoized_call => unreachable,
8939 },8938 },
89408939
8941 .var_args_param_type => unreachable,
8942 .none => unreachable,8940 .none => unreachable,
8943 };8941 };
8944}8942}
...@@ -9153,8 +9151,6 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois...@@ -9153,8 +9151,6 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
9153 .empty_struct => unreachable,9151 .empty_struct => unreachable,
9154 .generic_poison => unreachable,9152 .generic_poison => unreachable,
91559153
9156 .var_args_param_type => unreachable, // special tag
9157
9158 _ => switch (ip.items.items(.tag)[@intFromEnum(index)]) {9154 _ => switch (ip.items.items(.tag)[@intFromEnum(index)]) {
9159 .removed => unreachable,9155 .removed => unreachable,
91609156
src/Sema.zig+13-18
...@@ -1901,7 +1901,6 @@ pub fn resolveConstStringIntern(...@@ -1901,7 +1901,6 @@ pub fn resolveConstStringIntern(
19011901
1902pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type {1902pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type {
1903 const air_inst = try sema.resolveInst(zir_ref);1903 const air_inst = try sema.resolveInst(zir_ref);
1904 assert(air_inst != .var_args_param_type);
1905 const ty = try sema.analyzeAsType(block, src, air_inst);1904 const ty = try sema.analyzeAsType(block, src, air_inst);
1906 if (ty.isGenericPoison()) return error.GenericPoison;1905 if (ty.isGenericPoison()) return error.GenericPoison;
1907 return ty;1906 return ty;
...@@ -4572,12 +4571,10 @@ fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -4572,12 +4571,10 @@ fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
4572 const src = un_tok.src();4571 const src = un_tok.src();
4573 // In case of GenericPoison, we don't actually have a type, so this will be4572 // In case of GenericPoison, we don't actually have a type, so this will be
4574 // treated as an untyped address-of operator.4573 // treated as an untyped address-of operator.
4575 if (un_tok.operand == .var_args_param_type) return;
4576 const operand_air_inst = sema.resolveInst(un_tok.operand) catch |err| switch (err) {4574 const operand_air_inst = sema.resolveInst(un_tok.operand) catch |err| switch (err) {
4577 error.GenericPoison => return,4575 error.GenericPoison => return,
4578 else => |e| return e,4576 else => |e| return e,
4579 };4577 };
4580 if (operand_air_inst == .var_args_param_type) return;
4581 const ty_operand = sema.analyzeAsType(block, src, operand_air_inst) catch |err| switch (err) {4578 const ty_operand = sema.analyzeAsType(block, src, operand_air_inst) catch |err| switch (err) {
4582 error.GenericPoison => return,4579 error.GenericPoison => return,
4583 else => |e| return e,4580 else => |e| return e,
...@@ -7363,7 +7360,7 @@ const CallArgsInfo = union(enum) {...@@ -7363,7 +7360,7 @@ const CallArgsInfo = union(enum) {
7363 }7360 }
73647361
7365 /// Analyzes the arg at `arg_index` and coerces it to `param_ty`.7362 /// Analyzes the arg at `arg_index` and coerces it to `param_ty`.
7366 /// `param_ty` may be `generic_poison` or `var_args_param`.7363 /// `param_ty` may be `generic_poison`. A value of `null` indicates a varargs parameter.
7367 /// `func_ty_info` may be the type before instantiation, even if a generic7364 /// `func_ty_info` may be the type before instantiation, even if a generic
7368 /// instantiation has been partially completed.7365 /// instantiation has been partially completed.
7369 fn analyzeArg(7366 fn analyzeArg(
...@@ -7371,16 +7368,16 @@ const CallArgsInfo = union(enum) {...@@ -7371,16 +7368,16 @@ const CallArgsInfo = union(enum) {
7371 sema: *Sema,7368 sema: *Sema,
7372 block: *Block,7369 block: *Block,
7373 arg_index: usize,7370 arg_index: usize,
7374 param_ty: Type,7371 maybe_param_ty: ?Type,
7375 func_ty_info: InternPool.Key.FuncType,7372 func_ty_info: InternPool.Key.FuncType,
7376 func_inst: Air.Inst.Ref,7373 func_inst: Air.Inst.Ref,
7377 ) CompileError!Air.Inst.Ref {7374 ) CompileError!Air.Inst.Ref {
7378 const mod = sema.mod;7375 const mod = sema.mod;
7379 const param_count = func_ty_info.param_types.len;7376 const param_count = func_ty_info.param_types.len;
7380 switch (param_ty.toIntern()) {7377 if (maybe_param_ty) |param_ty| switch (param_ty.toIntern()) {
7381 .generic_poison_type, .var_args_param_type => {},7378 .generic_poison_type => {},
7382 else => try sema.queueFullTypeResolution(param_ty),7379 else => try sema.queueFullTypeResolution(param_ty),
7383 }7380 };
7384 const uncoerced_arg: Air.Inst.Ref = switch (cai) {7381 const uncoerced_arg: Air.Inst.Ref = switch (cai) {
7385 inline .resolved, .call_builtin => |resolved| resolved.args[arg_index],7382 inline .resolved, .call_builtin => |resolved| resolved.args[arg_index],
7386 .zir_call => |zir_call| arg_val: {7383 .zir_call => |zir_call| arg_val: {
...@@ -7409,7 +7406,8 @@ const CallArgsInfo = union(enum) {...@@ -7409,7 +7406,8 @@ const CallArgsInfo = union(enum) {
7409 // TODO set comptime_reason7406 // TODO set comptime_reason
7410 }7407 }
7411 // Give the arg its result type7408 // Give the arg its result type
7412 sema.inst_map.putAssumeCapacity(zir_call.call_inst, Air.internedToRef(param_ty.toIntern()));7409 const provide_param_ty = if (maybe_param_ty) |t| t else Type.generic_poison;
7410 sema.inst_map.putAssumeCapacity(zir_call.call_inst, Air.internedToRef(provide_param_ty.toIntern()));
7413 // Resolve the arg!7411 // Resolve the arg!
7414 const uncoerced_arg = try sema.resolveInlineBody(block, arg_body, zir_call.call_inst);7412 const uncoerced_arg = try sema.resolveInlineBody(block, arg_body, zir_call.call_inst);
74157413
...@@ -7426,9 +7424,11 @@ const CallArgsInfo = union(enum) {...@@ -7426,9 +7424,11 @@ const CallArgsInfo = union(enum) {
7426 break :arg_val uncoerced_arg;7424 break :arg_val uncoerced_arg;
7427 },7425 },
7428 };7426 };
7427 const param_ty = maybe_param_ty orelse {
7428 return sema.coerceVarArgParam(block, uncoerced_arg, cai.argSrc(block, arg_index));
7429 };
7429 switch (param_ty.toIntern()) {7430 switch (param_ty.toIntern()) {
7430 .generic_poison_type => return uncoerced_arg,7431 .generic_poison_type => return uncoerced_arg,
7431 .var_args_param_type => return sema.coerceVarArgParam(block, uncoerced_arg, cai.argSrc(block, arg_index)),
7432 else => return sema.coerceExtra(7432 else => return sema.coerceExtra(
7433 block,7433 block,
7434 param_ty,7434 param_ty,
...@@ -7970,10 +7970,10 @@ fn analyzeCall(...@@ -7970,10 +7970,10 @@ fn analyzeCall(
7970 const args = try sema.arena.alloc(Air.Inst.Ref, args_info.count());7970 const args = try sema.arena.alloc(Air.Inst.Ref, args_info.count());
7971 for (args, 0..) |*arg_out, arg_idx| {7971 for (args, 0..) |*arg_out, arg_idx| {
7972 // Non-generic, so param types are already resolved7972 // Non-generic, so param types are already resolved
7973 const param_ty = if (arg_idx < func_ty_info.param_types.len) ty: {7973 const param_ty: ?Type = if (arg_idx < func_ty_info.param_types.len) ty: {
7974 break :ty Type.fromInterned(func_ty_info.param_types.get(ip)[arg_idx]);7974 break :ty Type.fromInterned(func_ty_info.param_types.get(ip)[arg_idx]);
7975 } else Type.fromInterned(InternPool.Index.var_args_param_type);7975 } else null;
7976 assert(!param_ty.isGenericPoison());7976 if (param_ty) |t| assert(!t.isGenericPoison());
7977 arg_out.* = try args_info.analyzeArg(sema, block, arg_idx, param_ty, func_ty_info, func);7977 arg_out.* = try args_info.analyzeArg(sema, block, arg_idx, param_ty, func_ty_info, func);
7978 try sema.validateRuntimeValue(block, args_info.argSrc(block, arg_idx), arg_out.*);7978 try sema.validateRuntimeValue(block, args_info.argSrc(block, arg_idx), arg_out.*);
7979 if (sema.typeOf(arg_out.*).zigTypeTag(mod) == .NoReturn) {7979 if (sema.typeOf(arg_out.*).zigTypeTag(mod) == .NoReturn) {
...@@ -10226,12 +10226,10 @@ fn analyzeAs(...@@ -10226,12 +10226,10 @@ fn analyzeAs(
10226) CompileError!Air.Inst.Ref {10226) CompileError!Air.Inst.Ref {
10227 const mod = sema.mod;10227 const mod = sema.mod;
10228 const operand = try sema.resolveInst(zir_operand);10228 const operand = try sema.resolveInst(zir_operand);
10229 if (zir_dest_type == .var_args_param_type) return operand;
10230 const operand_air_inst = sema.resolveInst(zir_dest_type) catch |err| switch (err) {10229 const operand_air_inst = sema.resolveInst(zir_dest_type) catch |err| switch (err) {
10231 error.GenericPoison => return operand,10230 error.GenericPoison => return operand,
10232 else => |e| return e,10231 else => |e| return e,
10233 };10232 };
10234 if (operand_air_inst == .var_args_param_type) return operand;
10235 const dest_ty = sema.analyzeAsType(block, src, operand_air_inst) catch |err| switch (err) {10233 const dest_ty = sema.analyzeAsType(block, src, operand_air_inst) catch |err| switch (err) {
10236 error.GenericPoison => return operand,10234 error.GenericPoison => return operand,
10237 else => |e| return e,10235 else => |e| return e,
...@@ -35664,8 +35662,6 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!void {...@@ -35664,8 +35662,6 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!void {
35664 const ty_ip = ty.toIntern();35662 const ty_ip = ty.toIntern();
3566535663
35666 switch (ty_ip) {35664 switch (ty_ip) {
35667 .var_args_param_type => unreachable,
35668
35669 .none => unreachable,35665 .none => unreachable,
3567035666
35671 .u0_type,35667 .u0_type,
...@@ -37184,7 +37180,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -37184,7 +37180,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
37184 .empty_struct,37180 .empty_struct,
37185 .generic_poison,37181 .generic_poison,
37186 // invalid37182 // invalid
37187 .var_args_param_type,
37188 .none,37183 .none,
37189 => unreachable,37184 => unreachable,
3719037185
src/codegen/c/Type.zig-1
...@@ -1468,7 +1468,6 @@ pub const Pool = struct {...@@ -1468,7 +1468,6 @@ pub const Pool = struct {
1468 .bool_false,1468 .bool_false,
1469 .empty_struct,1469 .empty_struct,
1470 .generic_poison,1470 .generic_poison,
1471 .var_args_param_type,
1472 .none,1471 .none,
1473 => unreachable,1472 => unreachable,
14741473
src/codegen/llvm.zig-1
...@@ -3235,7 +3235,6 @@ pub const Object = struct {...@@ -3235,7 +3235,6 @@ pub const Object = struct {
3235 .bool_false,3235 .bool_false,
3236 .empty_struct,3236 .empty_struct,
3237 .generic_poison,3237 .generic_poison,
3238 .var_args_param_type,
3239 .none,3238 .none,
3240 => unreachable,3239 => unreachable,
3241 else => switch (ip.indexToKey(t.toIntern())) {3240 else => switch (ip.indexToKey(t.toIntern())) {