authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-06 23:19:46-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-06 23:19:46-07:00
log19cf987198ff4de0b1460263a62ff6c41e1e3915
tree1acbb85972fbef799c1deb4de6a8c753b9b28a9e
parentacf9151008d5a97e5d91b34cc29f73af79062b48

C backend: implement Enum types and values

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
19181918 switch (enum_tag.ty.tag()) {
19191919 .enum_full => {
19201920 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 }
19261935 },
19271936 .enum_simple => {
19281937 // Field index and integer values are the same.
src/codegen/c.zig+36-1
......@@ -172,7 +172,10 @@ pub const DeclGen = struct {
172172 val: Value,
173173 ) error{ OutOfMemory, AnalysisFail }!void {
174174 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", .{});
176179 }
177180 switch (t.zigTypeTag()) {
178181 .Int => {
......@@ -288,6 +291,31 @@ pub const DeclGen = struct {
288291 try writer.writeAll(", .error = 0 }");
289292 }
290293 },
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 },
291319 else => |e| return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement value {s}", .{
292320 @tagName(e),
293321 }),
......@@ -472,6 +500,13 @@ pub const DeclGen = struct {
472500 try w.writeAll(name);
473501 dg.typedefs.putAssumeCapacityNoClobber(t, .{ .name = name, .rendered = rendered });
474502 },
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 },
475510 .Null, .Undefined => unreachable, // must be const or comptime
476511 else => |e| return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement type {s}", .{
477512 @tagName(e),
src/type.zig+3-3
......@@ -691,7 +691,7 @@ pub const Type = extern union {
691691 return struct_obj.owner_decl.renderFullyQualifiedName(writer);
692692 },
693693 .enum_full, .enum_nonexhaustive => {
694 const enum_full = ty.castTag(.enum_full).?.data;
694 const enum_full = ty.cast(Payload.EnumFull).?.data;
695695 return enum_full.owner_decl.renderFullyQualifiedName(writer);
696696 },
697697 .enum_simple => {
......@@ -1344,7 +1344,7 @@ pub const Type = extern union {
13441344 /// Asserts the type is an enum.
13451345 pub fn intTagType(self: Type, buffer: *Payload.Bits) Type {
13461346 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,
13481348 .enum_simple => {
13491349 const enum_simple = self.castTag(.enum_simple).?.data;
13501350 const bits = std.math.log2_int_ceil(usize, enum_simple.fields.count());
......@@ -1969,7 +1969,7 @@ pub const Type = extern union {
19691969 return null;
19701970 }
19711971 },
1972 .enum_nonexhaustive => ty = ty.castTag(.enum_full).?.data.tag_ty,
1972 .enum_nonexhaustive => ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty,
19731973
19741974 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),
19751975 .void => return Value.initTag(.void_value),