authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-08 15:04:58-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-25 05:11:28-04:00
logf399dd107a2b0387ca54688741d6c3fa0109ed39
treeb0d7e91c562b7506f2382c4412bf3b1163e75446
parent40b5bb71618825dbdba512b43ebf8c4cb5caf153

cbe: implement tag name


2 files changed, 96 insertions(+), 25 deletions(-)

src/codegen/c.zig+96-21
...@@ -1694,6 +1694,76 @@ pub const DeclGen = struct {...@@ -1694,6 +1694,76 @@ pub const DeclGen = struct {
1694 try w.writeAll(suffix.items);1694 try w.writeAll(suffix.items);
1695 }1695 }
16961696
1697 fn renderTagNameFn(dg: *DeclGen, enum_ty: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1698 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1699 defer buffer.deinit();
1700 const bw = buffer.writer();
1701
1702 const name_slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
1703
1704 try buffer.appendSlice("static ");
1705 try dg.renderType(bw, name_slice_ty);
1706 const name_begin = buffer.items.len + " ".len;
1707 try bw.print(" zig_tagName_{}(", .{typeToCIdentifier(enum_ty, dg.module)});
1708 const name_end = buffer.items.len - "(".len;
1709 try dg.renderTypeAndName(bw, enum_ty, .{ .identifier = "tag" }, .Const, 0);
1710 try buffer.appendSlice(") {\n switch (tag) {\n");
1711 for (enum_ty.enumFields().keys()) |name, index| {
1712 const name_z = try dg.typedefs.allocator.dupeZ(u8, name);
1713 defer dg.typedefs.allocator.free(name_z);
1714 const name_bytes = name_z[0 .. name_z.len + 1];
1715
1716 var tag_val_pl: Value.Payload.U32 = .{
1717 .base = .{ .tag = .enum_field_index },
1718 .data = @intCast(u32, index),
1719 };
1720 const tag_val = Value.initPayload(&tag_val_pl.base);
1721
1722 var int_val_pl: Value.Payload.U64 = undefined;
1723 const int_val = tag_val.enumToInt(enum_ty, &int_val_pl);
1724
1725 var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len };
1726 const name_ty = Type.initPayload(&name_ty_pl.base);
1727
1728 var name_val_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name_bytes };
1729 const name_val = Value.initPayload(&name_val_pl.base);
1730
1731 var len_val_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };
1732 const len_val = Value.initPayload(&len_val_pl.base);
1733
1734 try bw.print(" case {}: {{\n static ", .{try dg.fmtIntLiteral(enum_ty, int_val, .Other)});
1735 try dg.renderTypeAndName(bw, name_ty, .{ .identifier = "name" }, .Const, 0);
1736 try buffer.appendSlice(" = ");
1737 try dg.renderValue(bw, name_ty, name_val, .Other);
1738 try buffer.appendSlice(";\n return (");
1739 try dg.renderTypecast(bw, name_slice_ty);
1740 try bw.print("){{{}, {}}};\n", .{
1741 fmtIdent("name"),
1742 try dg.fmtIntLiteral(Type.usize, len_val, .Other),
1743 });
1744
1745 try buffer.appendSlice(" }\n");
1746 }
1747 try buffer.appendSlice(" }\n while (true) zig_breakpoint();\n}\n");
1748
1749 const rendered = buffer.toOwnedSlice();
1750 errdefer dg.typedefs.allocator.free(rendered);
1751 const name = rendered[name_begin..name_end];
1752
1753 try dg.typedefs.ensureUnusedCapacity(1);
1754 dg.typedefs.putAssumeCapacityNoClobber(
1755 try enum_ty.copy(dg.typedefs_arena),
1756 .{ .name = name, .rendered = rendered },
1757 );
1758
1759 return name;
1760 }
1761
1762 fn getTagNameFn(dg: *DeclGen, enum_ty: Type) ![]const u8 {
1763 return dg.getTypedefName(enum_ty) orelse
1764 try dg.renderTagNameFn(enum_ty);
1765 }
1766
1697 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {1767 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {
1698 switch (tv.val.tag()) {1768 switch (tv.val.tag()) {
1699 .extern_fn => return true,1769 .extern_fn => return true,
...@@ -1805,25 +1875,22 @@ pub fn genErrDecls(o: *Object) !void {...@@ -1805,25 +1875,22 @@ pub fn genErrDecls(o: *Object) !void {
1805 o.indent_writer.popIndent();1875 o.indent_writer.popIndent();
1806 try writer.writeAll("};\n");1876 try writer.writeAll("};\n");
18071877
1808 const name_prefix = "zig_errorName_";1878 const name_prefix = "zig_errorName";
1809 const name_buf = try o.dg.gpa.alloc(u8, name_prefix.len + max_name_len + 1);1879 const name_buf = try o.dg.gpa.alloc(u8, name_prefix.len + "_".len + max_name_len + 1);
1810 defer o.dg.gpa.free(name_buf);1880 defer o.dg.gpa.free(name_buf);
18111881
1812 std.mem.copy(u8, name_buf, name_prefix);1882 std.mem.copy(u8, name_buf, name_prefix ++ "_");
1813 for (o.dg.module.error_name_list.items) |name| {1883 for (o.dg.module.error_name_list.items) |name| {
1814 std.mem.copy(u8, name_buf[name_prefix.len..], name);1884 std.mem.copy(u8, name_buf[name_prefix.len + "_".len ..], name);
1815 name_buf[name_prefix.len + name.len] = 0;1885 name_buf[name_prefix.len + "_".len + name.len] = 0;
18161886
1817 const identifier = name_buf[0 .. name_prefix.len + name.len :0];1887 const identifier = name_buf[0 .. name_prefix.len + "_".len + name.len :0];
1818 const nameZ = identifier[name_prefix.len..];1888 const name_z = identifier[name_prefix.len + "_".len ..];
18191889
1820 var name_ty_pl = Type.Payload.Len{1890 var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len };
1821 .base = .{ .tag = .array_u8_sentinel_0 },
1822 .data = name.len,
1823 };
1824 const name_ty = Type.initPayload(&name_ty_pl.base);1891 const name_ty = Type.initPayload(&name_ty_pl.base);
18251892
1826 var name_val_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = nameZ };1893 var name_val_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name_z };
1827 const name_val = Value.initPayload(&name_val_pl.base);1894 const name_val = Value.initPayload(&name_val_pl.base);
18281895
1829 try writer.writeAll("static ");1896 try writer.writeAll("static ");
...@@ -1840,11 +1907,18 @@ pub fn genErrDecls(o: *Object) !void {...@@ -1840,11 +1907,18 @@ pub fn genErrDecls(o: *Object) !void {
1840 const name_array_ty = Type.initPayload(&name_array_ty_pl.base);1907 const name_array_ty = Type.initPayload(&name_array_ty_pl.base);
18411908
1842 try writer.writeAll("static ");1909 try writer.writeAll("static ");
1843 try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = "zig_errorName" }, .Const, 0);1910 try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = name_prefix }, .Const, 0);
1844 try writer.writeAll(" = {");1911 try writer.writeAll(" = {");
1845 for (o.dg.module.error_name_list.items) |name, value| {1912 for (o.dg.module.error_name_list.items) |name, value| {
1846 if (value != 0) try writer.writeByte(',');1913 if (value != 0) try writer.writeByte(',');
1847 try writer.print("{{zig_errorName_{}, {d}u}}", .{ fmtIdent(name), name.len });1914
1915 var len_val_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };
1916 const len_val = Value.initPayload(&len_val_pl.base);
1917
1918 try writer.print("{{" ++ name_prefix ++ "_{}, {}}}", .{
1919 fmtIdent(name),
1920 try o.dg.fmtIntLiteral(Type.usize, len_val, .Other),
1921 });
1848 }1922 }
1849 try writer.writeAll("};\n");1923 try writer.writeAll("};\n");
1850}1924}
...@@ -4210,18 +4284,19 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4210,18 +4284,19 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
4210 if (f.liveness.isUnused(inst)) return CValue.none;4284 if (f.liveness.isUnused(inst)) return CValue.none;
42114285
4212 const un_op = f.air.instructions.items(.data)[inst].un_op;4286 const un_op = f.air.instructions.items(.data)[inst].un_op;
4213 const writer = f.object.writer();
4214 const inst_ty = f.air.typeOfIndex(inst);4287 const inst_ty = f.air.typeOfIndex(inst);
4288 const enum_ty = f.air.typeOf(un_op);
4215 const operand = try f.resolveInst(un_op);4289 const operand = try f.resolveInst(un_op);
4290
4291 const writer = f.object.writer();
4216 const local = try f.allocLocal(inst_ty, .Const);4292 const local = try f.allocLocal(inst_ty, .Const);
4293 try writer.print(" = {s}(", .{try f.object.dg.getTagNameFn(enum_ty)});
4294 try f.writeCValue(writer, operand);
4295 try writer.writeAll(");\n");
42174296
4218 try writer.writeAll(" = ");4297 try f.object.dg.fwd_decl.writer().writeAll("// This is where the fwd decl for tagName ended up\n");
42194298
4220 _ = operand;4299 return local;
4221 _ = local;
4222 return f.fail("TODO: C backend: implement airTagName", .{});
4223 //try writer.writeAll(";\n");
4224 //return local;
4225}4300}
42264301
4227fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {4302fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
test/behavior/enum.zig-4
...@@ -972,7 +972,6 @@ fn test3_2(f: Test3Foo) !void {...@@ -972,7 +972,6 @@ fn test3_2(f: Test3Foo) !void {
972}972}
973973
974test "@tagName" {974test "@tagName" {
975 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
976 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO975 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
977 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;976 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
978 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;977 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
...@@ -989,7 +988,6 @@ fn testEnumTagNameBare(n: anytype) []const u8 {...@@ -989,7 +988,6 @@ fn testEnumTagNameBare(n: anytype) []const u8 {
989const BareNumber = enum { One, Two, Three };988const BareNumber = enum { One, Two, Three };
990989
991test "@tagName non-exhaustive enum" {990test "@tagName non-exhaustive enum" {
992 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
993 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO991 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
994 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;992 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
995 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;993 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
...@@ -1001,7 +999,6 @@ test "@tagName non-exhaustive enum" {...@@ -1001,7 +999,6 @@ test "@tagName non-exhaustive enum" {
1001const NonExhaustive = enum(u8) { A, B, _ };999const NonExhaustive = enum(u8) { A, B, _ };
10021000
1003test "@tagName is null-terminated" {1001test "@tagName is null-terminated" {
1004 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1005 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1002 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1006 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;1003 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1007 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;1004 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
...@@ -1017,7 +1014,6 @@ test "@tagName is null-terminated" {...@@ -1017,7 +1014,6 @@ test "@tagName is null-terminated" {
1017}1014}
10181015
1019test "tag name with assigned enum values" {1016test "tag name with assigned enum values" {
1020 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1021 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1017 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1022 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;1018 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1023 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;1019 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;