diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-12-27 01:14:50 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-12-27 01:14:50 -0700 |
| commit | c8fb36b36cd8368e84752770edf720e6e91ed997 (patch) | |
| tree | db0821f54a28f552240d27becaf4b1538b613d2e /test/behavior/enum_llvm.zig | |
| parent | f41b9cdb6d7f954495ffca168108ddd38bf27353 (diff) | |
| download | zig-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.zig | 49 |
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); +} |
