lib/choir/src/backends/wasm/emission/symbols.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const ir = @import("../../../core/root.zig");
3 const dialects = @import("../../../dialects/root.zig");
4 const emission = @import("root.zig");
5
6 const BuiltinDialect = dialects.BuiltinDialect;
7 const FuncDialect = dialects.FuncDialect;
8
9 pub const Role = enum {
10 required,
11 provided,
12 };
13
14 pub const Symbol = struct {
15 name: []const u8,
16 role: Role,
17 function_ordinal: usize,
18 };
19
20 pub const Iterator = struct {
21 operations: ir.Block.OperationIterator,
22 options: emission.Options,
23 function_ordinal: usize = 0,
24
25 pub fn init(module: *ir.Operation, options: emission.Options) emission.Error!Iterator {
26 if (!std.mem.eql(u8, module.name.name, BuiltinDialect.ModuleOp.operation_name)) {
27 return error.CodeGenFailed;
28 }
29 const module_op = BuiltinDialect.ModuleOp{ .op = module };
30 return .{
31 .operations = module_op.getBodyBlock().getOperations(),
32 .options = options,
33 };
34 }
35
36 pub fn next(self: *Iterator) emission.Error!?Symbol {
37 while (self.operations.next()) |operation| {
38 const function_ordinal = self.function_ordinal;
39 self.function_ordinal = std.math.add(
40 usize,
41 self.function_ordinal,
42 1,
43 ) catch return error.CapacityOverflow;
44 if (!std.mem.eql(u8, operation.name.name, FuncDialect.FuncOp.operation_name)) {
45 return error.CodeGenFailed;
46 }
47 const function = FuncDialect.FuncOp{ .op = operation };
48 const name = function.getName() orelse return error.CodeGenFailed;
49 if (function.isDeclaration()) {
50 return .{
51 .name = name,
52 .role = .required,
53 .function_ordinal = function_ordinal,
54 };
55 }
56 if (shouldExport(operation, name, self.options.entry)) {
57 return .{
58 .name = name,
59 .role = .provided,
60 .function_ordinal = function_ordinal,
61 };
62 }
63 }
64 return null;
65 }
66 };
67
68 fn shouldExport(
69 operation: *ir.Operation,
70 name: []const u8,
71 entry: ?[]const u8,
72 ) bool {
73 if (entry) |requested| return std.mem.eql(u8, requested, name);
74 return ir.SymbolTable.getSymbolVisibility(operation) == .public;
75 }
76
77 test {
78 std.testing.refAllDecls(@This());
79 }