mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
C backend: implement Enum types and values
They are lowered directly as the integer tag type, with no typedef.
This commit is contained in:
parent
acf9151008
commit
19cf987198
19
src/Sema.zig
19
src/Sema.zig
@ -1918,11 +1918,20 @@ fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr
|
||||
switch (enum_tag.ty.tag()) {
|
||||
.enum_full => {
|
||||
const enum_full = enum_tag.ty.castTag(.enum_full).?.data;
|
||||
const val = enum_full.values.entries.items[field_index].key;
|
||||
return mod.constInst(arena, src, .{
|
||||
.ty = int_tag_ty,
|
||||
.val = val,
|
||||
});
|
||||
if (enum_full.values.count() != 0) {
|
||||
const val = enum_full.values.entries.items[field_index].key;
|
||||
return mod.constInst(arena, src, .{
|
||||
.ty = int_tag_ty,
|
||||
.val = val,
|
||||
});
|
||||
} else {
|
||||
// Field index and integer values are the same.
|
||||
const val = try Value.Tag.int_u64.create(arena, field_index);
|
||||
return mod.constInst(arena, src, .{
|
||||
.ty = int_tag_ty,
|
||||
.val = val,
|
||||
});
|
||||
}
|
||||
},
|
||||
.enum_simple => {
|
||||
// Field index and integer values are the same.
|
||||
|
||||
@ -172,7 +172,10 @@ pub const DeclGen = struct {
|
||||
val: Value,
|
||||
) error{ OutOfMemory, AnalysisFail }!void {
|
||||
if (val.isUndef()) {
|
||||
return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: properly handle undefined in all cases (with debug safety?)", .{});
|
||||
// This should lower to 0xaa bytes in safe modes, and for unsafe modes should
|
||||
// lower to leaving variables uninitialized (that might need to be implemented
|
||||
// outside of this function).
|
||||
return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement renderValue undef", .{});
|
||||
}
|
||||
switch (t.zigTypeTag()) {
|
||||
.Int => {
|
||||
@ -288,6 +291,31 @@ pub const DeclGen = struct {
|
||||
try writer.writeAll(", .error = 0 }");
|
||||
}
|
||||
},
|
||||
.Enum => {
|
||||
switch (val.tag()) {
|
||||
.enum_field_index => {
|
||||
const field_index = val.castTag(.enum_field_index).?.data;
|
||||
switch (t.tag()) {
|
||||
.enum_simple => return writer.print("{d}", .{field_index}),
|
||||
.enum_full, .enum_nonexhaustive => {
|
||||
const enum_full = t.cast(Type.Payload.EnumFull).?.data;
|
||||
if (enum_full.values.count() != 0) {
|
||||
const tag_val = enum_full.values.entries.items[field_index].key;
|
||||
return dg.renderValue(writer, enum_full.tag_ty, tag_val);
|
||||
} else {
|
||||
return writer.print("{d}", .{field_index});
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
},
|
||||
else => {
|
||||
var int_tag_ty_buffer: Type.Payload.Bits = undefined;
|
||||
const int_tag_ty = t.intTagType(&int_tag_ty_buffer);
|
||||
return dg.renderValue(writer, int_tag_ty, val);
|
||||
},
|
||||
}
|
||||
},
|
||||
else => |e| return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement value {s}", .{
|
||||
@tagName(e),
|
||||
}),
|
||||
@ -472,6 +500,13 @@ pub const DeclGen = struct {
|
||||
try w.writeAll(name);
|
||||
dg.typedefs.putAssumeCapacityNoClobber(t, .{ .name = name, .rendered = rendered });
|
||||
},
|
||||
.Enum => {
|
||||
// For enums, we simply use the integer tag type.
|
||||
var int_tag_ty_buffer: Type.Payload.Bits = undefined;
|
||||
const int_tag_ty = t.intTagType(&int_tag_ty_buffer);
|
||||
|
||||
try dg.renderType(w, int_tag_ty);
|
||||
},
|
||||
.Null, .Undefined => unreachable, // must be const or comptime
|
||||
else => |e| return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement type {s}", .{
|
||||
@tagName(e),
|
||||
|
||||
@ -691,7 +691,7 @@ pub const Type = extern union {
|
||||
return struct_obj.owner_decl.renderFullyQualifiedName(writer);
|
||||
},
|
||||
.enum_full, .enum_nonexhaustive => {
|
||||
const enum_full = ty.castTag(.enum_full).?.data;
|
||||
const enum_full = ty.cast(Payload.EnumFull).?.data;
|
||||
return enum_full.owner_decl.renderFullyQualifiedName(writer);
|
||||
},
|
||||
.enum_simple => {
|
||||
@ -1344,7 +1344,7 @@ pub const Type = extern union {
|
||||
/// Asserts the type is an enum.
|
||||
pub fn intTagType(self: Type, buffer: *Payload.Bits) Type {
|
||||
switch (self.tag()) {
|
||||
.enum_full, .enum_nonexhaustive => return self.castTag(.enum_full).?.data.tag_ty,
|
||||
.enum_full, .enum_nonexhaustive => return self.cast(Payload.EnumFull).?.data.tag_ty,
|
||||
.enum_simple => {
|
||||
const enum_simple = self.castTag(.enum_simple).?.data;
|
||||
const bits = std.math.log2_int_ceil(usize, enum_simple.fields.count());
|
||||
@ -1969,7 +1969,7 @@ pub const Type = extern union {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
.enum_nonexhaustive => ty = ty.castTag(.enum_full).?.data.tag_ty,
|
||||
.enum_nonexhaustive => ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty,
|
||||
|
||||
.empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),
|
||||
.void => return Value.initTag(.void_value),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user