| author | |
| committer | |
| log | 19cf987198ff4de0b1460263a62ff6c41e1e3915 |
| tree | 1acbb85972fbef799c1deb4de6a8c753b9b28a9e |
| parent | acf9151008d5a97e5d91b34cc29f73af79062b48 |
They are lowered directly as the integer tag type, with no typedef.3 files changed, 53 insertions(+), 9 deletions(-)
src/Sema.zig+14-5| ... | ... | @@ -1918,11 +1918,20 @@ fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr |
| 1918 | 1918 | switch (enum_tag.ty.tag()) { |
| 1919 | 1919 | .enum_full => { |
| 1920 | 1920 | const enum_full = enum_tag.ty.castTag(.enum_full).?.data; |
| 1921 | const val = enum_full.values.entries.items[field_index].key; | |
| 1922 | return mod.constInst(arena, src, .{ | |
| 1923 | .ty = int_tag_ty, | |
| 1924 | .val = val, | |
| 1925 | }); | |
| 1921 | if (enum_full.values.count() != 0) { | |
| 1922 | const val = enum_full.values.entries.items[field_index].key; | |
| 1923 | return mod.constInst(arena, src, .{ | |
| 1924 | .ty = int_tag_ty, | |
| 1925 | .val = val, | |
| 1926 | }); | |
| 1927 | } else { | |
| 1928 | // Field index and integer values are the same. | |
| 1929 | const val = try Value.Tag.int_u64.create(arena, field_index); | |
| 1930 | return mod.constInst(arena, src, .{ | |
| 1931 | .ty = int_tag_ty, | |
| 1932 | .val = val, | |
| 1933 | }); | |
| 1934 | } | |
| 1926 | 1935 | }, |
| 1927 | 1936 | .enum_simple => { |
| 1928 | 1937 | // Field index and integer values are the same. |
src/codegen/c.zig+36-1| ... | ... | @@ -172,7 +172,10 @@ pub const DeclGen = struct { |
| 172 | 172 | val: Value, |
| 173 | 173 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 174 | 174 | if (val.isUndef()) { |
| 175 | return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: properly handle undefined in all cases (with debug safety?)", .{}); | |
| 175 | // This should lower to 0xaa bytes in safe modes, and for unsafe modes should | |
| 176 | // lower to leaving variables uninitialized (that might need to be implemented | |
| 177 | // outside of this function). | |
| 178 | return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement renderValue undef", .{}); | |
| 176 | 179 | } |
| 177 | 180 | switch (t.zigTypeTag()) { |
| 178 | 181 | .Int => { |
| ... | ... | @@ -288,6 +291,31 @@ pub const DeclGen = struct { |
| 288 | 291 | try writer.writeAll(", .error = 0 }"); |
| 289 | 292 | } |
| 290 | 293 | }, |
| 294 | .Enum => { | |
| 295 | switch (val.tag()) { | |
| 296 | .enum_field_index => { | |
| 297 | const field_index = val.castTag(.enum_field_index).?.data; | |
| 298 | switch (t.tag()) { | |
| 299 | .enum_simple => return writer.print("{d}", .{field_index}), | |
| 300 | .enum_full, .enum_nonexhaustive => { | |
| 301 | const enum_full = t.cast(Type.Payload.EnumFull).?.data; | |
| 302 | if (enum_full.values.count() != 0) { | |
| 303 | const tag_val = enum_full.values.entries.items[field_index].key; | |
| 304 | return dg.renderValue(writer, enum_full.tag_ty, tag_val); | |
| 305 | } else { | |
| 306 | return writer.print("{d}", .{field_index}); | |
| 307 | } | |
| 308 | }, | |
| 309 | else => unreachable, | |
| 310 | } | |
| 311 | }, | |
| 312 | else => { | |
| 313 | var int_tag_ty_buffer: Type.Payload.Bits = undefined; | |
| 314 | const int_tag_ty = t.intTagType(&int_tag_ty_buffer); | |
| 315 | return dg.renderValue(writer, int_tag_ty, val); | |
| 316 | }, | |
| 317 | } | |
| 318 | }, | |
| 291 | 319 | else => |e| return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement value {s}", .{ |
| 292 | 320 | @tagName(e), |
| 293 | 321 | }), |
| ... | ... | @@ -472,6 +500,13 @@ pub const DeclGen = struct { |
| 472 | 500 | try w.writeAll(name); |
| 473 | 501 | dg.typedefs.putAssumeCapacityNoClobber(t, .{ .name = name, .rendered = rendered }); |
| 474 | 502 | }, |
| 503 | .Enum => { | |
| 504 | // For enums, we simply use the integer tag type. | |
| 505 | var int_tag_ty_buffer: Type.Payload.Bits = undefined; | |
| 506 | const int_tag_ty = t.intTagType(&int_tag_ty_buffer); | |
| 507 | ||
| 508 | try dg.renderType(w, int_tag_ty); | |
| 509 | }, | |
| 475 | 510 | .Null, .Undefined => unreachable, // must be const or comptime |
| 476 | 511 | else => |e| return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement type {s}", .{ |
| 477 | 512 | @tagName(e), |
src/type.zig+3-3| ... | ... | @@ -691,7 +691,7 @@ pub const Type = extern union { |
| 691 | 691 | return struct_obj.owner_decl.renderFullyQualifiedName(writer); |
| 692 | 692 | }, |
| 693 | 693 | .enum_full, .enum_nonexhaustive => { |
| 694 | const enum_full = ty.castTag(.enum_full).?.data; | |
| 694 | const enum_full = ty.cast(Payload.EnumFull).?.data; | |
| 695 | 695 | return enum_full.owner_decl.renderFullyQualifiedName(writer); |
| 696 | 696 | }, |
| 697 | 697 | .enum_simple => { |
| ... | ... | @@ -1344,7 +1344,7 @@ pub const Type = extern union { |
| 1344 | 1344 | /// Asserts the type is an enum. |
| 1345 | 1345 | pub fn intTagType(self: Type, buffer: *Payload.Bits) Type { |
| 1346 | 1346 | switch (self.tag()) { |
| 1347 | .enum_full, .enum_nonexhaustive => return self.castTag(.enum_full).?.data.tag_ty, | |
| 1347 | .enum_full, .enum_nonexhaustive => return self.cast(Payload.EnumFull).?.data.tag_ty, | |
| 1348 | 1348 | .enum_simple => { |
| 1349 | 1349 | const enum_simple = self.castTag(.enum_simple).?.data; |
| 1350 | 1350 | const bits = std.math.log2_int_ceil(usize, enum_simple.fields.count()); |
| ... | ... | @@ -1969,7 +1969,7 @@ pub const Type = extern union { |
| 1969 | 1969 | return null; |
| 1970 | 1970 | } |
| 1971 | 1971 | }, |
| 1972 | .enum_nonexhaustive => ty = ty.castTag(.enum_full).?.data.tag_ty, | |
| 1972 | .enum_nonexhaustive => ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty, | |
| 1973 | 1973 | |
| 1974 | 1974 | .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value), |
| 1975 | 1975 | .void => return Value.initTag(.void_value), |