authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-26 18:36:57-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-27 04:09:22-07:00
log1606717b5fed83ee64ba1a91e55248e07a51afa6
treea7a1de9fe9ff8ddac0c8b920c6fabd0598434eaf
parent70563aeac3e9efee7e8fb24744bc97197fc0ca9b

C backend: flatten out some of the long-lived state

When the compiler's state lives through multiple Compilation.update() calls, the C backend stores the rendered C source code for each decl code body and forward declarations. With this commit, the state is still stored, but it is managed in one big array list in link/C.zig rather than many array lists, one for each decl. This means simpler serialization and deserialization.

2 files changed, 95 insertions(+), 53 deletions(-)

src/codegen/c.zig+2-2
...@@ -489,9 +489,7 @@ pub const Function = struct {...@@ -489,9 +489,7 @@ pub const Function = struct {
489 f.blocks.deinit(gpa);489 f.blocks.deinit(gpa);
490 f.value_map.deinit();490 f.value_map.deinit();
491 f.lazy_fns.deinit(gpa);491 f.lazy_fns.deinit(gpa);
492 f.object.code.deinit();
493 f.object.dg.ctypes.deinit(gpa);492 f.object.dg.ctypes.deinit(gpa);
494 f.object.dg.fwd_decl.deinit();
495 }493 }
496494
497 fn typeOf(f: *Function, inst: Air.Inst.Ref) Type {495 fn typeOf(f: *Function, inst: Air.Inst.Ref) Type {
...@@ -509,6 +507,7 @@ pub const Function = struct {...@@ -509,6 +507,7 @@ pub const Function = struct {
509/// It is not available when generating .h file.507/// It is not available when generating .h file.
510pub const Object = struct {508pub const Object = struct {
511 dg: DeclGen,509 dg: DeclGen,
510 /// This is a borrowed reference from `link.C`.
512 code: std.ArrayList(u8),511 code: std.ArrayList(u8),
513 /// Goes before code. Initialized and deinitialized in `genFunc`.512 /// Goes before code. Initialized and deinitialized in `genFunc`.
514 code_header: std.ArrayList(u8) = undefined,513 code_header: std.ArrayList(u8) = undefined,
...@@ -525,6 +524,7 @@ pub const DeclGen = struct {...@@ -525,6 +524,7 @@ pub const DeclGen = struct {
525 module: *Module,524 module: *Module,
526 decl: ?*Decl,525 decl: ?*Decl,
527 decl_index: Decl.OptionalIndex,526 decl_index: Decl.OptionalIndex,
527 /// This is a borrowed reference from `link.C`.
528 fwd_decl: std.ArrayList(u8),528 fwd_decl: std.ArrayList(u8),
529 error_msg: ?*Module.ErrorMsg,529 error_msg: ?*Module.ErrorMsg,
530 ctypes: CType.Store,530 ctypes: CType.Store,
src/link/C.zig+93-51
...@@ -23,11 +23,39 @@ base: link.File,...@@ -23,11 +23,39 @@ base: link.File,
23/// Instead, it tracks all declarations in this table, and iterates over it23/// Instead, it tracks all declarations in this table, and iterates over it
24/// in the flush function, stitching pre-rendered pieces of C code together.24/// in the flush function, stitching pre-rendered pieces of C code together.
25decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclBlock) = .{},25decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclBlock) = .{},
26/// All the string bytes of rendered C code, all squished into one array.
27/// While in progress, a separate buffer is used, and then when finished, the
28/// buffer is copied into this one.
29string_bytes: std.ArrayListUnmanaged(u8) = .{},
30
31/// Optimization, `updateDecl` reuses this buffer rather than creating a new
32/// one with every call.
33fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{},
34/// Optimization, `updateDecl` reuses this buffer rather than creating a new
35/// one with every call.
36code_buf: std.ArrayListUnmanaged(u8) = .{},
37/// Optimization, `flush` reuses this buffer rather than creating a new
38/// one with every call.
39lazy_fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{},
40/// Optimization, `flush` reuses this buffer rather than creating a new
41/// one with every call.
42lazy_code_buf: std.ArrayListUnmanaged(u8) = .{},
43
44/// A reference into `string_bytes`.
45const String = struct {
46 start: u32,
47 len: u32,
48
49 const empty: String = .{
50 .start = 0,
51 .len = 0,
52 };
53};
2654
27/// Per-declaration data.55/// Per-declaration data.
28const DeclBlock = struct {56const DeclBlock = struct {
29 code: std.ArrayListUnmanaged(u8) = .{},57 code: String = String.empty,
30 fwd_decl: std.ArrayListUnmanaged(u8) = .{},58 fwd_decl: String = String.empty,
31 /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate59 /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate
32 /// over each `Decl` and generate the definition for each used `CType` once.60 /// over each `Decl` and generate the definition for each used `CType` once.
33 ctypes: codegen.CType.Store = .{},61 ctypes: codegen.CType.Store = .{},
...@@ -37,12 +65,23 @@ const DeclBlock = struct {...@@ -37,12 +65,23 @@ const DeclBlock = struct {
37 fn deinit(db: *DeclBlock, gpa: Allocator) void {65 fn deinit(db: *DeclBlock, gpa: Allocator) void {
38 db.lazy_fns.deinit(gpa);66 db.lazy_fns.deinit(gpa);
39 db.ctypes.deinit(gpa);67 db.ctypes.deinit(gpa);
40 db.fwd_decl.deinit(gpa);
41 db.code.deinit(gpa);
42 db.* = undefined;68 db.* = undefined;
43 }69 }
44};70};
4571
72pub fn getString(this: C, s: String) []const u8 {
73 return this.string_bytes.items[s.start..][0..s.len];
74}
75
76pub fn addString(this: *C, s: []const u8) Allocator.Error!String {
77 const gpa = this.base.allocator;
78 try this.string_bytes.appendSlice(gpa, s);
79 return .{
80 .start = @intCast(this.string_bytes.items.len - s.len),
81 .len = @intCast(s.len),
82 };
83}
84
46pub fn openPath(gpa: Allocator, sub_path: []const u8, options: link.Options) !*C {85pub fn openPath(gpa: Allocator, sub_path: []const u8, options: link.Options) !*C {
47 assert(options.target.ofmt == .c);86 assert(options.target.ofmt == .c);
4887
...@@ -78,6 +117,10 @@ pub fn deinit(self: *C) void {...@@ -78,6 +117,10 @@ pub fn deinit(self: *C) void {
78 db.deinit(gpa);117 db.deinit(gpa);
79 }118 }
80 self.decl_table.deinit(gpa);119 self.decl_table.deinit(gpa);
120
121 self.string_bytes.deinit(gpa);
122 self.fwd_decl_buf.deinit(gpa);
123 self.code_buf.deinit(gpa);
81}124}
82125
83pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void {126pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void {
...@@ -102,12 +145,12 @@ pub fn updateFunc(self: *C, module: *Module, func_index: InternPool.Index, air:...@@ -102,12 +145,12 @@ pub fn updateFunc(self: *C, module: *Module, func_index: InternPool.Index, air:
102 }145 }
103 const ctypes = &gop.value_ptr.ctypes;146 const ctypes = &gop.value_ptr.ctypes;
104 const lazy_fns = &gop.value_ptr.lazy_fns;147 const lazy_fns = &gop.value_ptr.lazy_fns;
105 const fwd_decl = &gop.value_ptr.fwd_decl;148 const fwd_decl = &self.fwd_decl_buf;
106 const code = &gop.value_ptr.code;149 const code = &self.code_buf;
107 ctypes.clearRetainingCapacity(gpa);150 ctypes.clearRetainingCapacity(gpa);
108 lazy_fns.clearRetainingCapacity();151 lazy_fns.clearRetainingCapacity();
109 fwd_decl.shrinkRetainingCapacity(0);152 fwd_decl.clearRetainingCapacity();
110 code.shrinkRetainingCapacity(0);153 code.clearRetainingCapacity();
111154
112 var function: codegen.Function = .{155 var function: codegen.Function = .{
113 .value_map = codegen.CValueMap.init(gpa),156 .value_map = codegen.CValueMap.init(gpa),
...@@ -131,7 +174,11 @@ pub fn updateFunc(self: *C, module: *Module, func_index: InternPool.Index, air:...@@ -131,7 +174,11 @@ pub fn updateFunc(self: *C, module: *Module, func_index: InternPool.Index, air:
131 };174 };
132175
133 function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };176 function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };
134 defer function.deinit();177 defer {
178 fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged();
179 code.* = function.object.code.moveToUnmanaged();
180 function.deinit();
181 }
135182
136 codegen.genFunc(&function) catch |err| switch (err) {183 codegen.genFunc(&function) catch |err| switch (err) {
137 error.AnalysisFail => {184 error.AnalysisFail => {
...@@ -143,14 +190,13 @@ pub fn updateFunc(self: *C, module: *Module, func_index: InternPool.Index, air:...@@ -143,14 +190,13 @@ pub fn updateFunc(self: *C, module: *Module, func_index: InternPool.Index, air:
143190
144 ctypes.* = function.object.dg.ctypes.move();191 ctypes.* = function.object.dg.ctypes.move();
145 lazy_fns.* = function.lazy_fns.move();192 lazy_fns.* = function.lazy_fns.move();
146 fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged();
147 code.* = function.object.code.moveToUnmanaged();
148193
149 // Free excess allocated memory for this Decl.194 // Free excess allocated memory for this Decl.
150 ctypes.shrinkAndFree(gpa, ctypes.count());195 ctypes.shrinkAndFree(gpa, ctypes.count());
151 lazy_fns.shrinkAndFree(gpa, lazy_fns.count());196 lazy_fns.shrinkAndFree(gpa, lazy_fns.count());
152 fwd_decl.shrinkAndFree(gpa, fwd_decl.items.len);197
153 code.shrinkAndFree(gpa, code.items.len);198 gop.value_ptr.code = try self.addString(function.object.code.items);
199 gop.value_ptr.fwd_decl = try self.addString(function.object.dg.fwd_decl.items);
154}200}
155201
156pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !void {202pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !void {
...@@ -164,11 +210,11 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi...@@ -164,11 +210,11 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi
164 gop.value_ptr.* = .{};210 gop.value_ptr.* = .{};
165 }211 }
166 const ctypes = &gop.value_ptr.ctypes;212 const ctypes = &gop.value_ptr.ctypes;
167 const fwd_decl = &gop.value_ptr.fwd_decl;213 const fwd_decl = &self.fwd_decl_buf;
168 const code = &gop.value_ptr.code;214 const code = &self.code_buf;
169 ctypes.clearRetainingCapacity(gpa);215 ctypes.clearRetainingCapacity(gpa);
170 fwd_decl.shrinkRetainingCapacity(0);216 fwd_decl.clearRetainingCapacity();
171 code.shrinkRetainingCapacity(0);217 code.clearRetainingCapacity();
172218
173 const decl = module.declPtr(decl_index);219 const decl = module.declPtr(decl_index);
174220
...@@ -187,9 +233,9 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi...@@ -187,9 +233,9 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi
187 };233 };
188 object.indent_writer = .{ .underlying_writer = object.code.writer() };234 object.indent_writer = .{ .underlying_writer = object.code.writer() };
189 defer {235 defer {
190 object.code.deinit();
191 object.dg.ctypes.deinit(object.dg.gpa);236 object.dg.ctypes.deinit(object.dg.gpa);
192 object.dg.fwd_decl.deinit();237 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
238 code.* = object.code.moveToUnmanaged();
193 }239 }
194240
195 codegen.genDecl(&object) catch |err| switch (err) {241 codegen.genDecl(&object) catch |err| switch (err) {
...@@ -201,13 +247,12 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi...@@ -201,13 +247,12 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi
201 };247 };
202248
203 ctypes.* = object.dg.ctypes.move();249 ctypes.* = object.dg.ctypes.move();
204 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
205 code.* = object.code.moveToUnmanaged();
206250
207 // Free excess allocated memory for this Decl.251 // Free excess allocated memory for this Decl.
208 ctypes.shrinkAndFree(gpa, ctypes.count());252 ctypes.shrinkAndFree(gpa, ctypes.count());
209 fwd_decl.shrinkAndFree(gpa, fwd_decl.items.len);253
210 code.shrinkAndFree(gpa, code.items.len);254 gop.value_ptr.code = try self.addString(object.code.items);
255 gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items);
211}256}
212257
213pub fn updateDeclLineNumber(self: *C, module: *Module, decl_index: Module.Decl.Index) !void {258pub fn updateDeclLineNumber(self: *C, module: *Module, decl_index: Module.Decl.Index) !void {
...@@ -273,7 +318,9 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo...@@ -273,7 +318,9 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo
273 const lazy_index = f.all_buffers.items.len;318 const lazy_index = f.all_buffers.items.len;
274 f.all_buffers.items.len += 1;319 f.all_buffers.items.len += 1;
275320
276 try self.flushErrDecls(&f.lazy_db);321 self.lazy_fwd_decl_buf.clearRetainingCapacity();
322 self.lazy_code_buf.clearRetainingCapacity();
323 try self.flushErrDecls(&f.lazy_ctypes);
277324
278 // `CType`s, forward decls, and non-functions first.325 // `CType`s, forward decls, and non-functions first.
279 // Unlike other backends, the .c code we are emitting is order-dependent. Therefore326 // Unlike other backends, the .c code we are emitting is order-dependent. Therefore
...@@ -306,7 +353,7 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo...@@ -306,7 +353,7 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo
306 // We need to flush lazy ctypes after flushing all decls but before flushing any decl ctypes.353 // We need to flush lazy ctypes after flushing all decls but before flushing any decl ctypes.
307 // This ensures that every lazy CType.Index exactly matches the global CType.Index.354 // This ensures that every lazy CType.Index exactly matches the global CType.Index.
308 assert(f.ctypes.count() == 0);355 assert(f.ctypes.count() == 0);
309 try self.flushCTypes(&f, .none, f.lazy_db.ctypes);356 try self.flushCTypes(&f, .none, f.lazy_ctypes);
310357
311 var it = self.decl_table.iterator();358 var it = self.decl_table.iterator();
312 while (it.next()) |entry|359 while (it.next()) |entry|
...@@ -319,16 +366,17 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo...@@ -319,16 +366,17 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo
319 };366 };
320 f.file_size += f.ctypes_buf.items.len;367 f.file_size += f.ctypes_buf.items.len;
321368
369 const lazy_fwd_decl_len = self.lazy_fwd_decl_buf.items.len;
322 f.all_buffers.items[lazy_index] = .{370 f.all_buffers.items[lazy_index] = .{
323 .iov_base = if (f.lazy_db.fwd_decl.items.len > 0) f.lazy_db.fwd_decl.items.ptr else "",371 .iov_base = if (lazy_fwd_decl_len > 0) self.lazy_fwd_decl_buf.items.ptr else "",
324 .iov_len = f.lazy_db.fwd_decl.items.len,372 .iov_len = lazy_fwd_decl_len,
325 };373 };
326 f.file_size += f.lazy_db.fwd_decl.items.len;374 f.file_size += lazy_fwd_decl_len;
327375
328 // Now the code.376 // Now the code.
329 try f.all_buffers.ensureUnusedCapacity(gpa, 1 + decl_values.len);377 try f.all_buffers.ensureUnusedCapacity(gpa, 1 + decl_values.len);
330 f.appendBufAssumeCapacity(f.lazy_db.code.items);378 f.appendBufAssumeCapacity(self.lazy_code_buf.items);
331 for (decl_values) |decl| f.appendBufAssumeCapacity(decl.code.items);379 for (decl_values) |decl| f.appendBufAssumeCapacity(self.getString(decl.code));
332380
333 const file = self.base.file.?;381 const file = self.base.file.?;
334 try file.setEndPos(f.file_size);382 try file.setEndPos(f.file_size);
...@@ -342,7 +390,7 @@ const Flush = struct {...@@ -342,7 +390,7 @@ const Flush = struct {
342 ctypes_map: std.ArrayListUnmanaged(codegen.CType.Index) = .{},390 ctypes_map: std.ArrayListUnmanaged(codegen.CType.Index) = .{},
343 ctypes_buf: std.ArrayListUnmanaged(u8) = .{},391 ctypes_buf: std.ArrayListUnmanaged(u8) = .{},
344392
345 lazy_db: DeclBlock = .{},393 lazy_ctypes: codegen.CType.Store = .{},
346 lazy_fns: LazyFns = .{},394 lazy_fns: LazyFns = .{},
347395
348 asm_buf: std.ArrayListUnmanaged(u8) = .{},396 asm_buf: std.ArrayListUnmanaged(u8) = .{},
...@@ -364,7 +412,7 @@ const Flush = struct {...@@ -364,7 +412,7 @@ const Flush = struct {
364 f.all_buffers.deinit(gpa);412 f.all_buffers.deinit(gpa);
365 f.asm_buf.deinit(gpa);413 f.asm_buf.deinit(gpa);
366 f.lazy_fns.deinit(gpa);414 f.lazy_fns.deinit(gpa);
367 f.lazy_db.deinit(gpa);415 f.lazy_ctypes.deinit(gpa);
368 f.ctypes_buf.deinit(gpa);416 f.ctypes_buf.deinit(gpa);
369 f.ctypes_map.deinit(gpa);417 f.ctypes_map.deinit(gpa);
370 f.ctypes.deinit(gpa);418 f.ctypes.deinit(gpa);
...@@ -462,12 +510,11 @@ fn flushCTypes(...@@ -462,12 +510,11 @@ fn flushCTypes(
462 }510 }
463}511}
464512
465fn flushErrDecls(self: *C, db: *DeclBlock) FlushDeclError!void {513fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void {
466 const gpa = self.base.allocator;514 const gpa = self.base.allocator;
467515
468 const fwd_decl = &db.fwd_decl;516 const fwd_decl = &self.lazy_fwd_decl_buf;
469 const ctypes = &db.ctypes;517 const code = &self.lazy_code_buf;
470 const code = &db.code;
471518
472 var object = codegen.Object{519 var object = codegen.Object{
473 .dg = .{520 .dg = .{
...@@ -484,9 +531,9 @@ fn flushErrDecls(self: *C, db: *DeclBlock) FlushDeclError!void {...@@ -484,9 +531,9 @@ fn flushErrDecls(self: *C, db: *DeclBlock) FlushDeclError!void {
484 };531 };
485 object.indent_writer = .{ .underlying_writer = object.code.writer() };532 object.indent_writer = .{ .underlying_writer = object.code.writer() };
486 defer {533 defer {
487 object.code.deinit();
488 object.dg.ctypes.deinit(gpa);534 object.dg.ctypes.deinit(gpa);
489 object.dg.fwd_decl.deinit();535 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
536 code.* = object.code.moveToUnmanaged();
490 }537 }
491538
492 codegen.genErrDecls(&object) catch |err| switch (err) {539 codegen.genErrDecls(&object) catch |err| switch (err) {
...@@ -494,17 +541,14 @@ fn flushErrDecls(self: *C, db: *DeclBlock) FlushDeclError!void {...@@ -494,17 +541,14 @@ fn flushErrDecls(self: *C, db: *DeclBlock) FlushDeclError!void {
494 else => |e| return e,541 else => |e| return e,
495 };542 };
496543
497 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
498 ctypes.* = object.dg.ctypes.move();544 ctypes.* = object.dg.ctypes.move();
499 code.* = object.code.moveToUnmanaged();
500}545}
501546
502fn flushLazyFn(self: *C, db: *DeclBlock, lazy_fn: codegen.LazyFnMap.Entry) FlushDeclError!void {547fn flushLazyFn(self: *C, ctypes: *codegen.CType.Store, lazy_fn: codegen.LazyFnMap.Entry) FlushDeclError!void {
503 const gpa = self.base.allocator;548 const gpa = self.base.allocator;
504549
505 const fwd_decl = &db.fwd_decl;550 const fwd_decl = &self.lazy_fwd_decl_buf;
506 const ctypes = &db.ctypes;551 const code = &self.lazy_code_buf;
507 const code = &db.code;
508552
509 var object = codegen.Object{553 var object = codegen.Object{
510 .dg = .{554 .dg = .{
...@@ -521,9 +565,9 @@ fn flushLazyFn(self: *C, db: *DeclBlock, lazy_fn: codegen.LazyFnMap.Entry) Flush...@@ -521,9 +565,9 @@ fn flushLazyFn(self: *C, db: *DeclBlock, lazy_fn: codegen.LazyFnMap.Entry) Flush
521 };565 };
522 object.indent_writer = .{ .underlying_writer = object.code.writer() };566 object.indent_writer = .{ .underlying_writer = object.code.writer() };
523 defer {567 defer {
524 object.code.deinit();
525 object.dg.ctypes.deinit(gpa);568 object.dg.ctypes.deinit(gpa);
526 object.dg.fwd_decl.deinit();569 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
570 code.* = object.code.moveToUnmanaged();
527 }571 }
528572
529 codegen.genLazyFn(&object, lazy_fn) catch |err| switch (err) {573 codegen.genLazyFn(&object, lazy_fn) catch |err| switch (err) {
...@@ -531,21 +575,19 @@ fn flushLazyFn(self: *C, db: *DeclBlock, lazy_fn: codegen.LazyFnMap.Entry) Flush...@@ -531,21 +575,19 @@ fn flushLazyFn(self: *C, db: *DeclBlock, lazy_fn: codegen.LazyFnMap.Entry) Flush
531 else => |e| return e,575 else => |e| return e,
532 };576 };
533577
534 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
535 ctypes.* = object.dg.ctypes.move();578 ctypes.* = object.dg.ctypes.move();
536 code.* = object.code.moveToUnmanaged();
537}579}
538580
539fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError!void {581fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError!void {
540 const gpa = self.base.allocator;582 const gpa = self.base.allocator;
541 try f.lazy_fns.ensureUnusedCapacity(gpa, @as(Flush.LazyFns.Size, @intCast(lazy_fns.count())));583 try f.lazy_fns.ensureUnusedCapacity(gpa, @intCast(lazy_fns.count()));
542584
543 var it = lazy_fns.iterator();585 var it = lazy_fns.iterator();
544 while (it.next()) |entry| {586 while (it.next()) |entry| {
545 const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*);587 const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*);
546 if (gop.found_existing) continue;588 if (gop.found_existing) continue;
547 gop.value_ptr.* = {};589 gop.value_ptr.* = {};
548 try self.flushLazyFn(&f.lazy_db, entry);590 try self.flushLazyFn(&f.lazy_ctypes, entry);
549 }591 }
550}592}
551593
...@@ -573,7 +615,7 @@ fn flushDecl(...@@ -573,7 +615,7 @@ fn flushDecl(
573 try self.flushLazyFns(f, decl_block.lazy_fns);615 try self.flushLazyFns(f, decl_block.lazy_fns);
574 try f.all_buffers.ensureUnusedCapacity(gpa, 1);616 try f.all_buffers.ensureUnusedCapacity(gpa, 1);
575 if (!(decl.isExtern(mod) and export_names.contains(decl.name)))617 if (!(decl.isExtern(mod) and export_names.contains(decl.name)))
576 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);618 f.appendBufAssumeCapacity(self.getString(decl_block.fwd_decl));
577}619}
578620
579pub fn flushEmitH(module: *Module) !void {621pub fn flushEmitH(module: *Module) !void {