mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
Type: make hasRuntimeBitsAdvanced take AbiAlignmentAdvancedStrat
I wasn't able to create a reduced test case for this but the reasoning can be seen in `abiAlignmentAdvancedUnion` where if `strat` was lazy `hasRuntimeBitsAdvanced` would be given `null` instead of `sema` which would cause eager evaluation when it is not valid or desired.
This commit is contained in:
parent
44f8714dfb
commit
e5a3eb9777
@ -128,7 +128,7 @@ pub const Block = struct {
|
||||
/// Shared among all child blocks.
|
||||
sema: *Sema,
|
||||
/// The namespace to use for lookups from this source block
|
||||
/// When analyzing fields, this is different from src_decl.src_namepsace.
|
||||
/// When analyzing fields, this is different from src_decl.src_namespace.
|
||||
namespace: *Namespace,
|
||||
/// The AIR instructions generated for this block.
|
||||
instructions: std.ArrayListUnmanaged(Air.Inst.Index),
|
||||
@ -31298,7 +31298,10 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
|
||||
}
|
||||
|
||||
pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {
|
||||
return ty.hasRuntimeBitsAdvanced(false, sema);
|
||||
return ty.hasRuntimeBitsAdvanced(false, .{ .sema = sema }) catch |err| switch (err) {
|
||||
error.NeedLazy => unreachable,
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
|
||||
fn typeAbiSize(sema: *Sema, ty: Type) !u64 {
|
||||
|
||||
@ -262,9 +262,10 @@ const Writer = struct {
|
||||
=> try self.writeBreak(stream, inst),
|
||||
.array_init,
|
||||
.array_init_ref,
|
||||
=> try self.writeArrayInit(stream, inst),
|
||||
.array_init_anon,
|
||||
.array_init_anon_ref,
|
||||
=> try self.writeArrayInit(stream, inst),
|
||||
=> try self.writeArrayInitAnon(stream, inst),
|
||||
|
||||
.slice_start => try self.writeSliceStart(stream, inst),
|
||||
.slice_end => try self.writeSliceEnd(stream, inst),
|
||||
@ -2316,6 +2317,21 @@ const Writer = struct {
|
||||
try self.writeSrc(stream, inst_data.src());
|
||||
}
|
||||
|
||||
fn writeArrayInitAnon(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
|
||||
|
||||
const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
|
||||
const args = self.code.refSlice(extra.end, extra.data.operands_len);
|
||||
|
||||
try stream.writeAll("{");
|
||||
for (args) |arg, i| {
|
||||
if (i != 0) try stream.writeAll(", ");
|
||||
try self.writeInstRef(stream, arg);
|
||||
}
|
||||
try stream.writeAll("}) ");
|
||||
try self.writeSrc(stream, inst_data.src());
|
||||
}
|
||||
|
||||
fn writeArrayInitSent(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
|
||||
|
||||
|
||||
81
src/type.zig
81
src/type.zig
@ -2312,6 +2312,8 @@ pub const Type = extern union {
|
||||
}
|
||||
}
|
||||
|
||||
const RuntimeBitsError = Module.CompileError || error{NeedLazy};
|
||||
|
||||
/// true if and only if the type takes up space in memory at runtime.
|
||||
/// There are two reasons a type will return false:
|
||||
/// * the type is a comptime-only type. For example, the type `type` itself.
|
||||
@ -2326,8 +2328,8 @@ pub const Type = extern union {
|
||||
pub fn hasRuntimeBitsAdvanced(
|
||||
ty: Type,
|
||||
ignore_comptime_only: bool,
|
||||
opt_sema: ?*Sema,
|
||||
) Module.CompileError!bool {
|
||||
strat: AbiAlignmentAdvancedStrat,
|
||||
) RuntimeBitsError!bool {
|
||||
switch (ty.tag()) {
|
||||
.u1,
|
||||
.u8,
|
||||
@ -2406,8 +2408,8 @@ pub const Type = extern union {
|
||||
return true;
|
||||
} else if (ty.childType().zigTypeTag() == .Fn) {
|
||||
return !ty.childType().fnInfo().is_generic;
|
||||
} else if (opt_sema) |sema| {
|
||||
return !(try sema.typeRequiresComptime(ty));
|
||||
} else if (strat == .sema) {
|
||||
return !(try strat.sema.typeRequiresComptime(ty));
|
||||
} else {
|
||||
return !comptimeOnly(ty);
|
||||
}
|
||||
@ -2445,8 +2447,8 @@ pub const Type = extern union {
|
||||
}
|
||||
if (ignore_comptime_only) {
|
||||
return true;
|
||||
} else if (opt_sema) |sema| {
|
||||
return !(try sema.typeRequiresComptime(child_ty));
|
||||
} else if (strat == .sema) {
|
||||
return !(try strat.sema.typeRequiresComptime(child_ty));
|
||||
} else {
|
||||
return !comptimeOnly(child_ty);
|
||||
}
|
||||
@ -2459,13 +2461,14 @@ pub const Type = extern union {
|
||||
// and then later if our guess was incorrect, we emit a compile error.
|
||||
return true;
|
||||
}
|
||||
if (opt_sema) |sema| {
|
||||
_ = try sema.resolveTypeFields(ty);
|
||||
switch (strat) {
|
||||
.sema => |sema| _ = try sema.resolveTypeFields(ty),
|
||||
.eager => assert(struct_obj.haveFieldTypes()),
|
||||
.lazy => if (!struct_obj.haveFieldTypes()) return error.NeedLazy,
|
||||
}
|
||||
assert(struct_obj.haveFieldTypes());
|
||||
for (struct_obj.fields.values()) |field| {
|
||||
if (field.is_comptime) continue;
|
||||
if (try field.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema))
|
||||
if (try field.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat))
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -2474,7 +2477,7 @@ pub const Type = extern union {
|
||||
|
||||
.enum_full => {
|
||||
const enum_full = ty.castTag(.enum_full).?.data;
|
||||
return enum_full.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema);
|
||||
return enum_full.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat);
|
||||
},
|
||||
.enum_simple => {
|
||||
const enum_simple = ty.castTag(.enum_simple).?.data;
|
||||
@ -2483,17 +2486,18 @@ pub const Type = extern union {
|
||||
.enum_numbered, .enum_nonexhaustive => {
|
||||
var buffer: Payload.Bits = undefined;
|
||||
const int_tag_ty = ty.intTagType(&buffer);
|
||||
return int_tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema);
|
||||
return int_tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat);
|
||||
},
|
||||
|
||||
.@"union" => {
|
||||
const union_obj = ty.castTag(.@"union").?.data;
|
||||
if (opt_sema) |sema| {
|
||||
_ = try sema.resolveTypeFields(ty);
|
||||
switch (strat) {
|
||||
.sema => |sema| _ = try sema.resolveTypeFields(ty),
|
||||
.eager => assert(union_obj.haveFieldTypes()),
|
||||
.lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy,
|
||||
}
|
||||
assert(union_obj.haveFieldTypes());
|
||||
for (union_obj.fields.values()) |value| {
|
||||
if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema))
|
||||
if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat))
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -2501,16 +2505,17 @@ pub const Type = extern union {
|
||||
},
|
||||
.union_safety_tagged, .union_tagged => {
|
||||
const union_obj = ty.cast(Payload.Union).?.data;
|
||||
if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema)) {
|
||||
if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (opt_sema) |sema| {
|
||||
_ = try sema.resolveTypeFields(ty);
|
||||
switch (strat) {
|
||||
.sema => |sema| _ = try sema.resolveTypeFields(ty),
|
||||
.eager => assert(union_obj.haveFieldTypes()),
|
||||
.lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy,
|
||||
}
|
||||
assert(union_obj.haveFieldTypes());
|
||||
for (union_obj.fields.values()) |value| {
|
||||
if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema))
|
||||
if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat))
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -2518,9 +2523,9 @@ pub const Type = extern union {
|
||||
},
|
||||
|
||||
.array, .vector => return ty.arrayLen() != 0 and
|
||||
try ty.elemType().hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema),
|
||||
try ty.elemType().hasRuntimeBitsAdvanced(ignore_comptime_only, strat),
|
||||
.array_u8 => return ty.arrayLen() != 0,
|
||||
.array_sentinel => return ty.childType().hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema),
|
||||
.array_sentinel => return ty.childType().hasRuntimeBitsAdvanced(ignore_comptime_only, strat),
|
||||
|
||||
.int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data != 0,
|
||||
|
||||
@ -2529,7 +2534,7 @@ pub const Type = extern union {
|
||||
for (tuple.types) |field_ty, i| {
|
||||
const val = tuple.values[i];
|
||||
if (val.tag() != .unreachable_value) continue; // comptime field
|
||||
if (try field_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema)) return true;
|
||||
if (try field_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
@ -2665,11 +2670,11 @@ pub const Type = extern union {
|
||||
}
|
||||
|
||||
pub fn hasRuntimeBits(ty: Type) bool {
|
||||
return hasRuntimeBitsAdvanced(ty, false, null) catch unreachable;
|
||||
return hasRuntimeBitsAdvanced(ty, false, .eager) catch unreachable;
|
||||
}
|
||||
|
||||
pub fn hasRuntimeBitsIgnoreComptime(ty: Type) bool {
|
||||
return hasRuntimeBitsAdvanced(ty, true, null) catch unreachable;
|
||||
return hasRuntimeBitsAdvanced(ty, true, .eager) catch unreachable;
|
||||
}
|
||||
|
||||
pub fn isFnOrHasRuntimeBits(ty: Type) bool {
|
||||
@ -2812,12 +2817,12 @@ pub const Type = extern union {
|
||||
}
|
||||
}
|
||||
|
||||
const AbiAlignmentAdvanced = union(enum) {
|
||||
pub const AbiAlignmentAdvanced = union(enum) {
|
||||
scalar: u32,
|
||||
val: Value,
|
||||
};
|
||||
|
||||
const AbiAlignmentAdvancedStrat = union(enum) {
|
||||
pub const AbiAlignmentAdvancedStrat = union(enum) {
|
||||
eager,
|
||||
lazy: Allocator,
|
||||
sema: *Sema,
|
||||
@ -2971,7 +2976,10 @@ pub const Type = extern union {
|
||||
|
||||
switch (strat) {
|
||||
.eager, .sema => {
|
||||
if (!(try child_type.hasRuntimeBitsAdvanced(false, opt_sema))) {
|
||||
if (!(child_type.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
|
||||
error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
|
||||
else => |e| return e,
|
||||
})) {
|
||||
return AbiAlignmentAdvanced{ .scalar = 1 };
|
||||
}
|
||||
return child_type.abiAlignmentAdvanced(target, strat);
|
||||
@ -2990,7 +2998,10 @@ pub const Type = extern union {
|
||||
const code_align = abiAlignment(Type.anyerror, target);
|
||||
switch (strat) {
|
||||
.eager, .sema => {
|
||||
if (!(try data.payload.hasRuntimeBitsAdvanced(false, opt_sema))) {
|
||||
if (!(data.payload.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
|
||||
error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
|
||||
else => |e| return e,
|
||||
})) {
|
||||
return AbiAlignmentAdvanced{ .scalar = code_align };
|
||||
}
|
||||
return AbiAlignmentAdvanced{ .scalar = @max(
|
||||
@ -3044,7 +3055,10 @@ pub const Type = extern union {
|
||||
const fields = ty.structFields();
|
||||
var big_align: u32 = 0;
|
||||
for (fields.values()) |field| {
|
||||
if (!(try field.ty.hasRuntimeBitsAdvanced(false, opt_sema))) continue;
|
||||
if (!(field.ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
|
||||
error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
|
||||
else => |e| return e,
|
||||
})) continue;
|
||||
|
||||
const field_align = if (field.abi_align != 0)
|
||||
field.abi_align
|
||||
@ -3161,7 +3175,10 @@ pub const Type = extern union {
|
||||
var max_align: u32 = 0;
|
||||
if (have_tag) max_align = union_obj.tag_ty.abiAlignment(target);
|
||||
for (union_obj.fields.values()) |field| {
|
||||
if (!(try field.ty.hasRuntimeBitsAdvanced(false, opt_sema))) continue;
|
||||
if (!(field.ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
|
||||
error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
|
||||
else => |e| return e,
|
||||
})) continue;
|
||||
|
||||
const field_align = if (field.abi_align != 0)
|
||||
field.abi_align
|
||||
|
||||
@ -1911,7 +1911,11 @@ pub const Value = extern union {
|
||||
|
||||
.lazy_align => {
|
||||
const ty = lhs.castTag(.lazy_align).?.data;
|
||||
if (try ty.hasRuntimeBitsAdvanced(false, opt_sema)) {
|
||||
const strat: Type.AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager;
|
||||
if (ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
|
||||
error.NeedLazy => unreachable,
|
||||
else => |e| return e,
|
||||
}) {
|
||||
return .gt;
|
||||
} else {
|
||||
return .eq;
|
||||
@ -1919,7 +1923,11 @@ pub const Value = extern union {
|
||||
},
|
||||
.lazy_size => {
|
||||
const ty = lhs.castTag(.lazy_size).?.data;
|
||||
if (try ty.hasRuntimeBitsAdvanced(false, opt_sema)) {
|
||||
const strat: Type.AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager;
|
||||
if (ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
|
||||
error.NeedLazy => unreachable,
|
||||
else => |e| return e,
|
||||
}) {
|
||||
return .gt;
|
||||
} else {
|
||||
return .eq;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user