diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-05-12 16:22:37 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-06-10 20:46:17 -0700 |
| commit | 88dbd62bcbac24c09791a7838d2f08c2f540967a (patch) | |
| tree | 9935a67bb6644fc448513eb728a1f22a587a89fb /src/Module.zig | |
| parent | d89807efbb1bd5af0a92544298fc08ad6ba2d255 (diff) | |
| download | zig-88dbd62bcbac24c09791a7838d2f08c2f540967a.tar.gz zig-88dbd62bcbac24c09791a7838d2f08c2f540967a.zip | |
stage2: move enum tag values into the InternPool
I'm seeing a new assertion trip: the call to `enumTagFieldIndex` in the
implementation of `@Type` is attempting to query the field index of an
union's enum tag, but the type of the enum tag value provided is not the
same as the union's tag type. Most likely this is a problem with type
coercion, since values are now typed.
Another problem is that I added some hacks in std.builtin because I
didn't see any convenient way to access them from Sema. That should
definitely be cleaned up before merging this branch.
Diffstat (limited to 'src/Module.zig')
| -rw-r--r-- | src/Module.zig | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/src/Module.zig b/src/Module.zig index 426d274011..cf1fea3444 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -6896,6 +6896,43 @@ pub fn ptrIntValue_ptronly(mod: *Module, ty: Type, x: u64) Allocator.Error!Value return i.toValue(); } +/// Creates an enum tag value based on the integer tag value. +pub fn enumValue(mod: *Module, ty: Type, tag_int: InternPool.Index) Allocator.Error!Value { + if (std.debug.runtime_safety) { + const tag = ty.zigTypeTag(mod); + assert(tag == .Enum); + } + const i = try intern(mod, .{ .enum_tag = .{ + .ty = ty.ip_index, + .int = tag_int, + } }); + return i.toValue(); +} + +/// Creates an enum tag value based on the field index according to source code +/// declaration order. +pub fn enumValueFieldIndex(mod: *Module, ty: Type, field_index: u32) Allocator.Error!Value { + const ip = &mod.intern_pool; + const gpa = mod.gpa; + const enum_type = ip.indexToKey(ty.ip_index).enum_type; + + if (enum_type.values.len == 0) { + // Auto-numbered fields. + return (try ip.get(gpa, .{ .enum_tag = .{ + .ty = ty.ip_index, + .int = try ip.get(gpa, .{ .int = .{ + .ty = enum_type.tag_ty, + .storage = .{ .u64 = field_index }, + } }), + } })).toValue(); + } + + return (try ip.get(gpa, .{ .enum_tag = .{ + .ty = ty.ip_index, + .int = enum_type.values[field_index], + } })).toValue(); +} + pub fn intValue(mod: *Module, ty: Type, x: anytype) Allocator.Error!Value { if (std.debug.runtime_safety) { const tag = ty.zigTypeTag(mod); @@ -6967,8 +7004,8 @@ pub fn smallestUnsignedInt(mod: *Module, max: u64) Allocator.Error!Type { /// `max`. Asserts that neither value is undef. /// TODO: if #3806 is implemented, this becomes trivial pub fn intFittingRange(mod: *Module, min: Value, max: Value) !Type { - assert(!min.isUndef()); - assert(!max.isUndef()); + assert(!min.isUndef(mod)); + assert(!max.isUndef(mod)); if (std.debug.runtime_safety) { assert(Value.order(min, max, mod).compare(.lte)); @@ -6990,7 +7027,7 @@ pub fn intFittingRange(mod: *Module, min: Value, max: Value) !Type { /// twos-complement integer; otherwise in an unsigned integer. /// Asserts that `val` is not undef. If `val` is negative, asserts that `sign` is true. pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 { - assert(!val.isUndef()); + assert(!val.isUndef(mod)); const key = mod.intern_pool.indexToKey(val.ip_index); switch (key.int.storage) { @@ -7193,3 +7230,7 @@ pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQu return owner_decl.srcLoc(mod); } } + +pub fn toEnum(mod: *Module, comptime E: type, val: Value) E { + return mod.intern_pool.toEnum(E, val.ip_index); +} |
