lib/choir/src/backends/wasm/emission/module/root.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const std = @import("std");
 2 const wasm = @import("../../root.zig");
 3 const emission = @import("../root.zig");
 4 const section = @import("section/root.zig");
 5 
 6 pub const common = @import("common.zig");
 7 
 8 pub fn preparePlan(
 9     plan: *emission.Plan,
10     module: *common.ir.Operation,
11     options: emission.Options,
12     frames: []emission.function.Frame,
13 ) emission.Error!usize {
14     _ = try common.moduleOperation(module);
15     if (options.entry) |entry| {
16         if (plan.functionIndex(entry) == null) return error.FunctionNotFound;
17     }
18 
19     try section.code.prepareBodies(plan, module, frames);
20     plan.sections.type = try section.type_section.countBody(plan, module);
21     if (plan.importCount() > 0) {
22         plan.sections.import = try section.import_section.countBody(plan, module);
23     }
24     if (plan.definitionCount() > 0) {
25         plan.sections.function = try section.function_section.countBody(plan, module);
26         plan.sections.code = try section.code.countBody(plan, module);
27     }
28     if (plan.needsMemory()) {
29         plan.sections.memory = try section.memory.countBody();
30     }
31     if (try section.export_section.entryCount(module, options, plan.needsMemory()) > 0) {
32         plan.sections.export_ = try section.export_section.countBody(plan, module, options);
33     }
34     return moduleByteSize(plan);
35 }
36 
37 pub fn write(
38     out: anytype,
39     plan: *const emission.Plan,
40     module: *common.ir.Operation,
41     options: emission.Options,
42     frames: []emission.function.Frame,
43 ) emission.Error!void {
44     _ = try common.moduleOperation(module);
45     try wasm.binary.writeHeader(out);
46     try section.type_section.write(out, plan, module);
47     if (plan.importCount() > 0) {
48         try section.import_section.write(out, plan, module);
49     }
50     if (plan.definitionCount() > 0) {
51         try section.function_section.write(out, plan, module);
52     }
53     if (plan.needsMemory()) {
54         try section.memory.write(out, plan);
55     }
56     if (plan.sections.export_ > 0) {
57         try section.export_section.write(out, plan, module, options);
58     }
59     if (plan.definitionCount() > 0) {
60         try section.code.write(out, plan, module, frames);
61     }
62 }
63 
64 fn moduleByteSize(plan: *const emission.Plan) emission.Error!usize {
65     var count = wasm.binary.Count{};
66     try wasm.binary.writeHeader(&count);
67     try addSectionSize(&count, .type, plan.sections.type);
68     if (plan.importCount() > 0) {
69         try addSectionSize(&count, .import, plan.sections.import);
70     }
71     if (plan.definitionCount() > 0) {
72         try addSectionSize(&count, .function, plan.sections.function);
73     }
74     if (plan.needsMemory()) {
75         try addSectionSize(&count, .memory, plan.sections.memory);
76     }
77     if (plan.sections.export_ > 0) {
78         try addSectionSize(&count, .export_, plan.sections.export_);
79     }
80     if (plan.definitionCount() > 0) {
81         try addSectionSize(&count, .code, plan.sections.code);
82     }
83     return count.len;
84 }
85 
86 fn addSectionSize(
87     count: *wasm.binary.Count,
88     section_id: wasm.binary.Section,
89     body_bytes: usize,
90 ) emission.Error!void {
91     try common.writeSectionHeader(count, section_id, body_bytes);
92     count.len = std.math.add(usize, count.len, body_bytes) catch
93         return error.CapacityOverflow;
94 }