| ... | @@ -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 it | 23 | /// 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. |
| 25 | decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclBlock) = .{}, | 25 | decl_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. |
| | 29 | string_bytes: std.ArrayListUnmanaged(u8) = .{}, |
| | 30 | |
| | 31 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new |
| | 32 | /// one with every call. |
| | 33 | fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{}, |
| | 34 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new |
| | 35 | /// one with every call. |
| | 36 | code_buf: std.ArrayListUnmanaged(u8) = .{}, |
| | 37 | /// Optimization, `flush` reuses this buffer rather than creating a new |
| | 38 | /// one with every call. |
| | 39 | lazy_fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{}, |
| | 40 | /// Optimization, `flush` reuses this buffer rather than creating a new |
| | 41 | /// one with every call. |
| | 42 | lazy_code_buf: std.ArrayListUnmanaged(u8) = .{}, |
| | 43 | |
| | 44 | /// A reference into `string_bytes`. |
| | 45 | const String = struct { |
| | 46 | start: u32, |
| | 47 | len: u32, |
| | 48 | |
| | 49 | const empty: String = .{ |
| | 50 | .start = 0, |
| | 51 | .len = 0, |
| | 52 | }; |
| | 53 | }; |
| 26 | | 54 | |
| 27 | /// Per-declaration data. | 55 | /// Per-declaration data. |
| 28 | const DeclBlock = struct { | 56 | const 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 iterate | 59 | /// 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 | }; |
| 45 | | 71 | |
| | 72 | pub fn getString(this: C, s: String) []const u8 { |
| | 73 | return this.string_bytes.items[s.start..][0..s.len]; |
| | 74 | } |
| | 75 | |
| | 76 | pub 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 | |
| 46 | pub fn openPath(gpa: Allocator, sub_path: []const u8, options: link.Options) !*C { | 85 | pub fn openPath(gpa: Allocator, sub_path: []const u8, options: link.Options) !*C { |
| 47 | assert(options.target.ofmt == .c); | 86 | assert(options.target.ofmt == .c); |
| 48 | | 87 | |
| ... | @@ -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 | } |
| 82 | | 125 | |
| 83 | pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void { | 126 | pub 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(); |
| 111 | | 154 | |
| 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 | }; |
| 132 | | 175 | |
| 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 | } |
| 135 | | 182 | |
| 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: |
| 143 | | 190 | |
| 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(); | | |
| 148 | | 193 | |
| 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 | } |
| 155 | | 201 | |
| 156 | pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !void { | 202 | pub 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(); |
| 172 | | 218 | |
| 173 | const decl = module.declPtr(decl_index); | 219 | const decl = module.declPtr(decl_index); |
| 174 | | 220 | |
| ... | @@ -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 | } |
| 194 | | 240 | |
| 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 | }; |
| 202 | | 248 | |
| 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(); | | |
| 206 | | 250 | |
| 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 | } |
| 212 | | 257 | |
| 213 | pub fn updateDeclLineNumber(self: *C, module: *Module, decl_index: Module.Decl.Index) !void { | 258 | pub 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; |
| 275 | | 320 | |
| 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); |
| 277 | | 324 | |
| 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. Therefore | 326 | // 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); |
| 310 | | 357 | |
| 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; |
| 321 | | 368 | |
| | 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; |
| 327 | | 375 | |
| 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)); |
| 332 | | 380 | |
| 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) = .{}, |
| 344 | | 392 | |
| 345 | lazy_db: DeclBlock = .{}, | 393 | lazy_ctypes: codegen.CType.Store = .{}, |
| 346 | lazy_fns: LazyFns = .{}, | 394 | lazy_fns: LazyFns = .{}, |
| 347 | | 395 | |
| 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 | } |
| 464 | | 512 | |
| 465 | fn flushErrDecls(self: *C, db: *DeclBlock) FlushDeclError!void { | 513 | fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { |
| 466 | const gpa = self.base.allocator; | 514 | const gpa = self.base.allocator; |
| 467 | | 515 | |
| 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; | | |
| 471 | | 518 | |
| 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 | } |
| 491 | | 538 | |
| 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 | }; |
| 496 | | 543 | |
| 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 | } |
| 501 | | 546 | |
| 502 | fn flushLazyFn(self: *C, db: *DeclBlock, lazy_fn: codegen.LazyFnMap.Entry) FlushDeclError!void { | 547 | fn 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; |
| 504 | | 549 | |
| 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; | | |
| 508 | | 552 | |
| 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 | } |
| 528 | | 572 | |
| 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 | }; |
| 533 | | 577 | |
| 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 | } |
| 538 | | 580 | |
| 539 | fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError!void { | 581 | fn 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())); |
| 542 | | 584 | |
| 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 | } |
| 551 | | 593 | |
| ... | @@ -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 | } |
| 578 | | 620 | |
| 579 | pub fn flushEmitH(module: *Module) !void { | 621 | pub fn flushEmitH(module: *Module) !void { |