Skip to content

Commit

Permalink
InternPool: eliminate var_args_param_type
Browse files Browse the repository at this point in the history
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: ziglang#19781
  • Loading branch information
mlugg committed May 2, 2024
1 parent d841f84 commit 302638c
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 30 deletions.
9 changes: 1 addition & 8 deletions src/Air.zig
Original file line number Diff line number Diff line change
Expand Up @@ -891,8 +891,7 @@ pub const Inst = struct {
/// The most-significant bit of the value is a tag bit. This bit is 1 if the value represents an
/// instruction index and 0 if it represents an InternPool index.
///
/// The hardcoded refs `none` and `var_args_param_type` are exceptions to this rule: they have
/// their tag bit set but refer to the InternPool.
/// The ref `none` is an exception: it has the tag bit set but refers to the InternPool.
pub const Ref = enum(u32) {
u0_type = @intFromEnum(InternPool.Index.u0_type),
i0_type = @intFromEnum(InternPool.Index.i0_type),
Expand Down Expand Up @@ -979,9 +978,6 @@ pub const Inst = struct {
empty_struct = @intFromEnum(InternPool.Index.empty_struct),
generic_poison = @intFromEnum(InternPool.Index.generic_poison),

/// This Ref does not correspond to any AIR instruction or constant
/// value. It is used to handle argument types of var args functions.
var_args_param_type = @intFromEnum(InternPool.Index.var_args_param_type),
/// This Ref does not correspond to any AIR instruction or constant
/// value and may instead be used as a sentinel to indicate null.
none = @intFromEnum(InternPool.Index.none),
Expand All @@ -994,7 +990,6 @@ pub const Inst = struct {

pub fn toInternedAllowNone(ref: Ref) ?InternPool.Index {
return switch (ref) {
.var_args_param_type => .var_args_param_type,
.none => .none,
else => if (@intFromEnum(ref) >> 31 == 0)
@enumFromInt(@as(u31, @truncate(@intFromEnum(ref))))
Expand All @@ -1010,7 +1005,6 @@ pub const Inst = struct {

pub fn toIndexAllowNone(ref: Ref) ?Index {
return switch (ref) {
.var_args_param_type, .none => null,
else => if (@intFromEnum(ref) >> 31 != 0)
@enumFromInt(@as(u31, @truncate(@intFromEnum(ref))))
else
Expand Down Expand Up @@ -1557,7 +1551,6 @@ pub fn deinit(air: *Air, gpa: std.mem.Allocator) void {

pub fn internedToRef(ip_index: InternPool.Index) Inst.Ref {
return switch (ip_index) {
.var_args_param_type => .var_args_param_type,
.none => .none,
else => {
assert(@intFromEnum(ip_index) >> 31 == 0);
Expand Down
4 changes: 0 additions & 4 deletions src/InternPool.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2818,7 +2818,6 @@ pub const Index = enum(u32) {
generic_poison,

/// Used by Air/Sema only.
var_args_param_type = std.math.maxInt(u32) - 1,
none = std.math.maxInt(u32),

_,
Expand Down Expand Up @@ -8938,7 +8937,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
.memoized_call => unreachable,
},

.var_args_param_type => unreachable,
.none => unreachable,
};
}
Expand Down Expand Up @@ -9153,8 +9151,6 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
.empty_struct => unreachable,
.generic_poison => unreachable,

.var_args_param_type => unreachable, // special tag

_ => switch (ip.items.items(.tag)[@intFromEnum(index)]) {
.removed => unreachable,

Expand Down
28 changes: 12 additions & 16 deletions src/Sema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1901,7 +1901,6 @@ pub fn resolveConstStringIntern(

pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type {
const air_inst = try sema.resolveInst(zir_ref);
assert(air_inst != .var_args_param_type);
const ty = try sema.analyzeAsType(block, src, air_inst);
if (ty.isGenericPoison()) return error.GenericPoison;
return ty;
Expand Down Expand Up @@ -4572,12 +4571,10 @@ fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
const src = un_tok.src();
// In case of GenericPoison, we don't actually have a type, so this will be
// treated as an untyped address-of operator.
if (un_tok.operand == .var_args_param_type) return;
const operand_air_inst = sema.resolveInst(un_tok.operand) catch |err| switch (err) {
error.GenericPoison => return,
else => |e| return e,
};
if (operand_air_inst == .var_args_param_type) return;
const ty_operand = sema.analyzeAsType(block, src, operand_air_inst) catch |err| switch (err) {
error.GenericPoison => return,
else => |e| return e,
Expand Down Expand Up @@ -7371,16 +7368,17 @@ const CallArgsInfo = union(enum) {
sema: *Sema,
block: *Block,
arg_index: usize,
param_ty: Type,
/// `null` means this is a varargs param.
maybe_param_ty: ?Type,
func_ty_info: InternPool.Key.FuncType,
func_inst: Air.Inst.Ref,
) CompileError!Air.Inst.Ref {
const mod = sema.mod;
const param_count = func_ty_info.param_types.len;
switch (param_ty.toIntern()) {
.generic_poison_type, .var_args_param_type => {},
if (maybe_param_ty) |param_ty| switch (param_ty.toIntern()) {
.generic_poison_type => {},
else => try sema.queueFullTypeResolution(param_ty),
}
};
const uncoerced_arg: Air.Inst.Ref = switch (cai) {
inline .resolved, .call_builtin => |resolved| resolved.args[arg_index],
.zir_call => |zir_call| arg_val: {
Expand Down Expand Up @@ -7409,7 +7407,8 @@ const CallArgsInfo = union(enum) {
// TODO set comptime_reason
}
// Give the arg its result type
sema.inst_map.putAssumeCapacity(zir_call.call_inst, Air.internedToRef(param_ty.toIntern()));
const provide_param_ty = if (maybe_param_ty) |t| t else Type.generic_poison;
sema.inst_map.putAssumeCapacity(zir_call.call_inst, Air.internedToRef(provide_param_ty.toIntern()));
// Resolve the arg!
const uncoerced_arg = try sema.resolveInlineBody(block, arg_body, zir_call.call_inst);

Expand All @@ -7426,9 +7425,11 @@ const CallArgsInfo = union(enum) {
break :arg_val uncoerced_arg;
},
};
const param_ty = maybe_param_ty orelse {
return sema.coerceVarArgParam(block, uncoerced_arg, cai.argSrc(block, arg_index));
};
switch (param_ty.toIntern()) {
.generic_poison_type => return uncoerced_arg,
.var_args_param_type => return sema.coerceVarArgParam(block, uncoerced_arg, cai.argSrc(block, arg_index)),
else => return sema.coerceExtra(
block,
param_ty,
Expand Down Expand Up @@ -7970,9 +7971,9 @@ fn analyzeCall(
const args = try sema.arena.alloc(Air.Inst.Ref, args_info.count());
for (args, 0..) |*arg_out, arg_idx| {
// Non-generic, so param types are already resolved
const param_ty = if (arg_idx < func_ty_info.param_types.len) ty: {
const param_ty: ?Type = if (arg_idx < func_ty_info.param_types.len) ty: {
break :ty Type.fromInterned(func_ty_info.param_types.get(ip)[arg_idx]);
} else Type.fromInterned(InternPool.Index.var_args_param_type);
} else null;
assert(!param_ty.isGenericPoison());
arg_out.* = try args_info.analyzeArg(sema, block, arg_idx, param_ty, func_ty_info, func);
try sema.validateRuntimeValue(block, args_info.argSrc(block, arg_idx), arg_out.*);
Expand Down Expand Up @@ -10226,12 +10227,10 @@ fn analyzeAs(
) CompileError!Air.Inst.Ref {
const mod = sema.mod;
const operand = try sema.resolveInst(zir_operand);
if (zir_dest_type == .var_args_param_type) return operand;
const operand_air_inst = sema.resolveInst(zir_dest_type) catch |err| switch (err) {
error.GenericPoison => return operand,
else => |e| return e,
};
if (operand_air_inst == .var_args_param_type) return operand;
const dest_ty = sema.analyzeAsType(block, src, operand_air_inst) catch |err| switch (err) {
error.GenericPoison => return operand,
else => |e| return e,
Expand Down Expand Up @@ -35656,8 +35655,6 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!void {
const ty_ip = ty.toIntern();

switch (ty_ip) {
.var_args_param_type => unreachable,

.none => unreachable,

.u0_type,
Expand Down Expand Up @@ -37176,7 +37173,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
.empty_struct,
.generic_poison,
// invalid
.var_args_param_type,
.none,
=> unreachable,

Expand Down
1 change: 0 additions & 1 deletion src/codegen/c/Type.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1468,7 +1468,6 @@ pub const Pool = struct {
.bool_false,
.empty_struct,
.generic_poison,
.var_args_param_type,
.none,
=> unreachable,

Expand Down
1 change: 0 additions & 1 deletion src/codegen/llvm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3235,7 +3235,6 @@ pub const Object = struct {
.bool_false,
.empty_struct,
.generic_poison,
.var_args_param_type,
.none,
=> unreachable,
else => switch (ip.indexToKey(t.toIntern())) {
Expand Down

0 comments on commit 302638c

Please sign in to comment.