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 }