| ... | ... | @@ -322,29 +322,19 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo |
| 322 | 322 | self.lazy_code_buf.clearRetainingCapacity(); |
| 323 | 323 | try self.flushErrDecls(&f.lazy_ctypes); |
| 324 | 324 | |
| 325 | // Unlike other backends, the .c code we are emitting has order-dependent decls. |
| 325 | 326 | // `CType`s, forward decls, and non-functions first. |
| 326 | | // Unlike other backends, the .c code we are emitting is order-dependent. Therefore |
| 327 | | // we must traverse the set of Decls that we are emitting according to their dependencies. |
| 328 | | // Our strategy is to populate a set of remaining decls, pop Decls one by one, |
| 329 | | // recursively chasing their dependencies. |
| 330 | | try f.remaining_decls.ensureUnusedCapacity(gpa, self.decl_table.count()); |
| 331 | | |
| 332 | | const decl_keys = self.decl_table.keys(); |
| 333 | | const decl_values = self.decl_table.values(); |
| 334 | | for (decl_keys) |decl_index| { |
| 335 | | assert(module.declPtr(decl_index).has_tv); |
| 336 | | f.remaining_decls.putAssumeCapacityNoClobber(decl_index, {}); |
| 337 | | } |
| 338 | 327 | |
| 339 | 328 | { |
| 340 | 329 | var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{}; |
| 341 | 330 | defer export_names.deinit(gpa); |
| 342 | | try export_names.ensureTotalCapacity(gpa, @as(u32, @intCast(module.decl_exports.entries.len))); |
| 331 | try export_names.ensureTotalCapacity(gpa, @intCast(module.decl_exports.entries.len)); |
| 343 | 332 | for (module.decl_exports.values()) |exports| for (exports.items) |@"export"| |
| 344 | 333 | try export_names.put(gpa, @"export".opts.name, {}); |
| 345 | 334 | |
| 346 | | while (f.remaining_decls.popOrNull()) |kv| { |
| 347 | | const decl_index = kv.key; |
| 335 | const decl_keys = self.decl_table.keys(); |
| 336 | for (decl_keys) |decl_index| { |
| 337 | assert(module.declPtr(decl_index).has_tv); |
| 348 | 338 | try self.flushDecl(&f, decl_index, export_names); |
| 349 | 339 | } |
| 350 | 340 | } |
| ... | ... | @@ -374,6 +364,7 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo |
| 374 | 364 | f.file_size += lazy_fwd_decl_len; |
| 375 | 365 | |
| 376 | 366 | // Now the code. |
| 367 | const decl_values = self.decl_table.values(); |
| 377 | 368 | try f.all_buffers.ensureUnusedCapacity(gpa, 1 + decl_values.len); |
| 378 | 369 | f.appendBufAssumeCapacity(self.lazy_code_buf.items); |
| 379 | 370 | for (decl_values) |decl| f.appendBufAssumeCapacity(self.getString(decl.code)); |
| ... | ... | @@ -384,8 +375,6 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo |
| 384 | 375 | } |
| 385 | 376 | |
| 386 | 377 | const Flush = struct { |
| 387 | | remaining_decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void) = .{}, |
| 388 | | |
| 389 | 378 | ctypes: codegen.CType.Store = .{}, |
| 390 | 379 | ctypes_map: std.ArrayListUnmanaged(codegen.CType.Index) = .{}, |
| 391 | 380 | ctypes_buf: std.ArrayListUnmanaged(u8) = .{}, |
| ... | ... | @@ -416,7 +405,6 @@ const Flush = struct { |
| 416 | 405 | f.ctypes_buf.deinit(gpa); |
| 417 | 406 | f.ctypes_map.deinit(gpa); |
| 418 | 407 | f.ctypes.deinit(gpa); |
| 419 | | f.remaining_decls.deinit(gpa); |
| 420 | 408 | } |
| 421 | 409 | }; |
| 422 | 410 | |
| ... | ... | @@ -591,7 +579,6 @@ fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError |
| 591 | 579 | } |
| 592 | 580 | } |
| 593 | 581 | |
| 594 | | /// Assumes `decl` was in the `remaining_decls` set, and has already been removed. |
| 595 | 582 | fn flushDecl( |
| 596 | 583 | self: *C, |
| 597 | 584 | f: *Flush, |
| ... | ... | @@ -601,14 +588,6 @@ fn flushDecl( |
| 601 | 588 | const gpa = self.base.allocator; |
| 602 | 589 | const mod = self.base.options.module.?; |
| 603 | 590 | const decl = mod.declPtr(decl_index); |
| 604 | | // Before flushing any particular Decl we must ensure its |
| 605 | | // dependencies are already flushed, so that the order in the .c |
| 606 | | // file comes out correctly. |
| 607 | | for (decl.dependencies.keys()) |dep| { |
| 608 | | if (f.remaining_decls.swapRemove(dep)) { |
| 609 | | try flushDecl(self, f, dep, export_names); |
| 610 | | } |
| 611 | | } |
| 612 | 591 | |
| 613 | 592 | const decl_block = self.decl_table.getPtr(decl_index).?; |
| 614 | 593 | |