aboutsummaryrefslogtreecommitdiff
path: root/test/behavior/enum_llvm.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-12-27 01:14:50 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-12-27 01:14:50 -0700
commitc8fb36b36cd8368e84752770edf720e6e91ed997 (patch)
treedb0821f54a28f552240d27becaf4b1538b613d2e /test/behavior/enum_llvm.zig
parentf41b9cdb6d7f954495ffca168108ddd38bf27353 (diff)
downloadzig-c8fb36b36cd8368e84752770edf720e6e91ed997.tar.gz
zig-c8fb36b36cd8368e84752770edf720e6e91ed997.zip
stage2: LLVM backend: implement `@tagName` for enums
Introduced a new AIR instruction: `tag_name`. Reasons to do this instead of lowering it in Sema to a switch, function call, array lookup, or if-else tower: * Sema is a bottleneck; do less work in Sema whenever possible. * If any optimization passes run, and the operand to becomes comptime-known, then it could change to have a comptime result value instead of lowering to a function or array or something which would then have to be garbage-collected. * Backends may want to choose to use a function and a switch branch, or they may want to use a different strategy. Codegen for `@tagName` is implemented for the LLVM backend but not any others yet. Introduced some new `Type` tags: * `const_slice_u8_sentinel_0` * `manyptr_const_u8_sentinel_0` The motivation for this was to make typeof() on the tag_name AIR instruction non-allocating. A bunch more enum tests are passing now.
Diffstat (limited to 'test/behavior/enum_llvm.zig')
-rw-r--r--test/behavior/enum_llvm.zig49
1 files changed, 49 insertions, 0 deletions
diff --git a/test/behavior/enum_llvm.zig b/test/behavior/enum_llvm.zig
new file mode 100644
index 0000000000..bd93f48db7
--- /dev/null
+++ b/test/behavior/enum_llvm.zig
@@ -0,0 +1,49 @@
+const std = @import("std");
+const expect = std.testing.expect;
+const mem = std.mem;
+const Tag = std.meta.Tag;
+
+test "@tagName" {
+ try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
+ comptime try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
+}
+
+fn testEnumTagNameBare(n: anytype) []const u8 {
+ return @tagName(n);
+}
+
+const BareNumber = enum { One, Two, Three };
+
+test "@tagName non-exhaustive enum" {
+ try expect(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));
+ comptime try expect(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));
+}
+const NonExhaustive = enum(u8) { A, B, _ };
+
+test "@tagName is null-terminated" {
+ const S = struct {
+ fn doTheTest(n: BareNumber) !void {
+ try expect(@tagName(n)[3] == 0);
+ }
+ };
+ try S.doTheTest(.Two);
+ try comptime S.doTheTest(.Two);
+}
+
+test "tag name with assigned enum values" {
+ const LocalFoo = enum(u8) {
+ A = 1,
+ B = 0,
+ };
+ var b = LocalFoo.B;
+ try expect(mem.eql(u8, @tagName(b), "B"));
+}
+
+const Bar = enum { A, B, C, D };
+
+test "enum literal casting to optional" {
+ var bar: ?Bar = undefined;
+ bar = .B;
+
+ try expect(bar.? == Bar.B);
+}