lib/choir/src/backends/gpu/fixture/text.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 //! Parses textual gpu dialect kernels for the emitter tests.
2
3 const std = @import("std");
4 const choir = @import("../../../root.zig");
5 const backends_gpu = @import("../root.zig");
6
7 const lowering = backends_gpu.lowering;
8 const registration = backends_gpu.registration;
9
10 const ir = choir.ir;
11 const testing = std.testing;
12
13 /// Parses `source` into a verified module and checks that it prints back
14 /// byte for byte, so each fixture also witnesses the gpu dialect round trip.
15 pub fn parse(ctx: *ir.Context, source: []const u8) !*ir.Operation {
16 std.debug.assert(source.len > 0);
17 const module = try ir.parse.operation(ctx, source);
18 errdefer module.erase();
19 try ir.verifyOperation(module, .{});
20 const printed = try ir.dump.operationAlloc(testing.allocator, module);
21 defer testing.allocator.free(printed);
22 try testing.expectEqualStrings(source, printed);
23 return module;
24 }
25
26 /// Parses `source` and runs the target lowering pipeline when one is named.
27 /// `ctx` must already hold the compilation dialects.
28 pub fn lower(
29 ctx: *ir.Context,
30 source: []const u8,
31 target: ?lowering.TargetLowering,
32 ) !*ir.Operation {
33 const module = try parse(ctx, source);
34 errdefer module.erase();
35 if (target) |target_lowering| {
36 var pm = choir.passes.PassManager.init(testing.allocator);
37 defer pm.deinit();
38 pm.enableVerifier();
39 try lowering.addTargetLoweringPipeline(&pm, target_lowering);
40 try testing.expectEqual(choir.passes.PassResult.success, pm.run(module, ctx));
41 }
42 return module;
43 }
44
45 /// Parses and lowers `source`, then returns the text that `emit` produces for
46 /// `entry_name`.
47 pub fn emitText(
48 source: []const u8,
49 entry_name: []const u8,
50 target: ?lowering.TargetLowering,
51 comptime emit: anytype,
52 ) ![]u8 {
53 std.debug.assert(entry_name.len > 0);
54 var ctx = try ir.Context.init(testing.allocator, ir.Context.Limits.testing);
55 defer ctx.deinit(testing.allocator);
56 try registration.prepareCompilationDialects(&ctx);
57 const module = try lower(&ctx, source, target);
58 defer module.erase();
59 return emit(testing.allocator, entry_name, module);
60 }
61
62 pub fn expectContains(text: []const u8, needle: []const u8) !void {
63 std.debug.assert(needle.len > 0);
64 if (std.mem.indexOf(u8, text, needle) == null) return error.TestExpectedContains;
65 }
66
67 pub fn expectAbsent(text: []const u8, needle: []const u8) !void {
68 std.debug.assert(needle.len > 0);
69 if (std.mem.indexOf(u8, text, needle) != null) return error.TestUnexpectedContains;
70 }