| ... | @@ -27,6 +27,9 @@ decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclBlock) = .{}, | ... | @@ -27,6 +27,9 @@ decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclBlock) = .{}, |
| 27 | /// While in progress, a separate buffer is used, and then when finished, the | 27 | /// While in progress, a separate buffer is used, and then when finished, the |
| 28 | /// buffer is copied into this one. | 28 | /// buffer is copied into this one. |
| 29 | string_bytes: std.ArrayListUnmanaged(u8) = .{}, | 29 | string_bytes: std.ArrayListUnmanaged(u8) = .{}, |
| | 30 | /// Tracks all the anonymous decls that are used by all the decls so they can |
| | 31 | /// be rendered during flush(). |
| | 32 | anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, DeclBlock) = .{}, |
| 30 | | 33 | |
| 31 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new | 34 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new |
| 32 | /// one with every call. | 35 | /// one with every call. |
| ... | @@ -34,9 +37,6 @@ fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{}, | ... | @@ -34,9 +37,6 @@ fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{}, |
| 34 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new | 37 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new |
| 35 | /// one with every call. | 38 | /// one with every call. |
| 36 | code_buf: std.ArrayListUnmanaged(u8) = .{}, | 39 | code_buf: std.ArrayListUnmanaged(u8) = .{}, |
| 37 | /// Optimization, `updateDecl` reuses this table rather than creating a new one | | |
| 38 | /// with every call. | | |
| 39 | scratch_anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{}, | | |
| 40 | /// Optimization, `flush` reuses this buffer rather than creating a new | 40 | /// Optimization, `flush` reuses this buffer rather than creating a new |
| 41 | /// one with every call. | 41 | /// one with every call. |
| 42 | lazy_fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{}, | 42 | lazy_fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{}, |
| ... | @@ -45,7 +45,7 @@ lazy_fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{}, | ... | @@ -45,7 +45,7 @@ lazy_fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{}, |
| 45 | lazy_code_buf: std.ArrayListUnmanaged(u8) = .{}, | 45 | lazy_code_buf: std.ArrayListUnmanaged(u8) = .{}, |
| 46 | | 46 | |
| 47 | /// A reference into `string_bytes`. | 47 | /// A reference into `string_bytes`. |
| 48 | const String = struct { | 48 | const String = extern struct { |
| 49 | start: u32, | 49 | start: u32, |
| 50 | len: u32, | 50 | len: u32, |
| 51 | | 51 | |
| ... | @@ -54,8 +54,9 @@ const String = struct { | ... | @@ -54,8 +54,9 @@ const String = struct { |
| 54 | .len = 0, | 54 | .len = 0, |
| 55 | }; | 55 | }; |
| 56 | }; | 56 | }; |
| | 57 | |
| 57 | /// Per-declaration data. | 58 | /// Per-declaration data. |
| 58 | const DeclBlock = struct { | 59 | pub const DeclBlock = struct { |
| 59 | code: String = String.empty, | 60 | code: String = String.empty, |
| 60 | fwd_decl: String = String.empty, | 61 | fwd_decl: String = String.empty, |
| 61 | /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate | 62 | /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate |
| ... | @@ -120,10 +121,14 @@ pub fn deinit(self: *C) void { | ... | @@ -120,10 +121,14 @@ pub fn deinit(self: *C) void { |
| 120 | } | 121 | } |
| 121 | self.decl_table.deinit(gpa); | 122 | self.decl_table.deinit(gpa); |
| 122 | | 123 | |
| | 124 | for (self.anon_decls.values()) |*db| { |
| | 125 | db.deinit(gpa); |
| | 126 | } |
| | 127 | self.anon_decls.deinit(gpa); |
| | 128 | |
| 123 | self.string_bytes.deinit(gpa); | 129 | self.string_bytes.deinit(gpa); |
| 124 | self.fwd_decl_buf.deinit(gpa); | 130 | self.fwd_decl_buf.deinit(gpa); |
| 125 | self.code_buf.deinit(gpa); | 131 | self.code_buf.deinit(gpa); |
| 126 | self.scratch_anon_decl_deps.deinit(gpa); | | |
| 127 | } | 132 | } |
| 128 | | 133 | |
| 129 | pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void { | 134 | pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void { |
| ... | @@ -158,57 +163,110 @@ pub fn updateFunc( | ... | @@ -158,57 +163,110 @@ pub fn updateFunc( |
| 158 | lazy_fns.clearRetainingCapacity(); | 163 | lazy_fns.clearRetainingCapacity(); |
| 159 | fwd_decl.clearRetainingCapacity(); | 164 | fwd_decl.clearRetainingCapacity(); |
| 160 | code.clearRetainingCapacity(); | 165 | code.clearRetainingCapacity(); |
| 161 | self.scratch_anon_decl_deps.clearRetainingCapacity(); | | |
| 162 | | 166 | |
| 163 | { | 167 | var function: codegen.Function = .{ |
| 164 | var function: codegen.Function = .{ | 168 | .value_map = codegen.CValueMap.init(gpa), |
| 165 | .value_map = codegen.CValueMap.init(gpa), | 169 | .air = air, |
| 166 | .air = air, | 170 | .liveness = liveness, |
| 167 | .liveness = liveness, | 171 | .func_index = func_index, |
| 168 | .func_index = func_index, | 172 | .object = .{ |
| 169 | .object = .{ | 173 | .dg = .{ |
| 170 | .dg = .{ | 174 | .gpa = gpa, |
| 171 | .gpa = gpa, | 175 | .module = module, |
| 172 | .module = module, | 176 | .error_msg = null, |
| 173 | .error_msg = null, | 177 | .decl_index = decl_index.toOptional(), |
| 174 | .decl_index = decl_index.toOptional(), | 178 | .is_naked_fn = decl.ty.fnCallingConvention(module) == .Naked, |
| 175 | .is_naked_fn = decl.ty.fnCallingConvention(module) == .Naked, | 179 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 176 | .fwd_decl = fwd_decl.toManaged(gpa), | 180 | .ctypes = ctypes.*, |
| 177 | .ctypes = ctypes.*, | 181 | .anon_decl_deps = self.anon_decls, |
| 178 | .anon_decl_deps = self.scratch_anon_decl_deps, | | |
| 179 | }, | | |
| 180 | .code = code.toManaged(gpa), | | |
| 181 | .indent_writer = undefined, // set later so we can get a pointer to object.code | | |
| 182 | }, | 182 | }, |
| 183 | .lazy_fns = lazy_fns.*, | 183 | .code = code.toManaged(gpa), |
| 184 | }; | 184 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| | 185 | }, |
| | 186 | .lazy_fns = lazy_fns.*, |
| | 187 | }; |
| 185 | | 188 | |
| 186 | function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() }; | 189 | function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() }; |
| 187 | defer { | 190 | defer { |
| 188 | self.scratch_anon_decl_deps = function.object.dg.anon_decl_deps; | 191 | self.anon_decls = function.object.dg.anon_decl_deps; |
| 189 | fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged(); | 192 | fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged(); |
| 190 | code.* = function.object.code.moveToUnmanaged(); | 193 | code.* = function.object.code.moveToUnmanaged(); |
| 191 | function.deinit(); | 194 | function.deinit(); |
| 192 | } | 195 | } |
| 193 | | 196 | |
| 194 | codegen.genFunc(&function) catch |err| switch (err) { | 197 | codegen.genFunc(&function) catch |err| switch (err) { |
| 195 | error.AnalysisFail => { | 198 | error.AnalysisFail => { |
| 196 | try module.failed_decls.put(gpa, decl_index, function.object.dg.error_msg.?); | 199 | try module.failed_decls.put(gpa, decl_index, function.object.dg.error_msg.?); |
| 197 | return; | 200 | return; |
| 198 | }, | 201 | }, |
| 199 | else => |e| return e, | 202 | else => |e| return e, |
| 200 | }; | 203 | }; |
| | 204 | |
| | 205 | ctypes.* = function.object.dg.ctypes.move(); |
| | 206 | lazy_fns.* = function.lazy_fns.move(); |
| 201 | | 207 | |
| 202 | ctypes.* = function.object.dg.ctypes.move(); | 208 | // Free excess allocated memory for this Decl. |
| 203 | lazy_fns.* = function.lazy_fns.move(); | 209 | ctypes.shrinkAndFree(gpa, ctypes.count()); |
| | 210 | lazy_fns.shrinkAndFree(gpa, lazy_fns.count()); |
| | 211 | |
| | 212 | gop.value_ptr.code = try self.addString(function.object.code.items); |
| | 213 | gop.value_ptr.fwd_decl = try self.addString(function.object.dg.fwd_decl.items); |
| | 214 | } |
| | 215 | |
| | 216 | fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { |
| | 217 | const gpa = self.base.allocator; |
| | 218 | const anon_decl = self.anon_decls.keys()[i]; |
| 204 | | 219 | |
| 205 | // Free excess allocated memory for this Decl. | 220 | const fwd_decl = &self.fwd_decl_buf; |
| 206 | ctypes.shrinkAndFree(gpa, ctypes.count()); | 221 | const code = &self.code_buf; |
| 207 | lazy_fns.shrinkAndFree(gpa, lazy_fns.count()); | 222 | fwd_decl.clearRetainingCapacity(); |
| | 223 | code.clearRetainingCapacity(); |
| 208 | | 224 | |
| 209 | gop.value_ptr.code = try self.addString(function.object.code.items); | 225 | var object: codegen.Object = .{ |
| 210 | gop.value_ptr.fwd_decl = try self.addString(function.object.dg.fwd_decl.items); | 226 | .dg = .{ |
| | 227 | .gpa = gpa, |
| | 228 | .module = module, |
| | 229 | .error_msg = null, |
| | 230 | .decl_index = .none, |
| | 231 | .is_naked_fn = false, |
| | 232 | .fwd_decl = fwd_decl.toManaged(gpa), |
| | 233 | .ctypes = .{}, |
| | 234 | .anon_decl_deps = self.anon_decls, |
| | 235 | }, |
| | 236 | .code = code.toManaged(gpa), |
| | 237 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| | 238 | }; |
| | 239 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| | 240 | |
| | 241 | defer { |
| | 242 | self.anon_decls = object.dg.anon_decl_deps; |
| | 243 | object.dg.ctypes.deinit(object.dg.gpa); |
| | 244 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| | 245 | code.* = object.code.moveToUnmanaged(); |
| 211 | } | 246 | } |
| | 247 | |
| | 248 | const tv: @import("../TypedValue.zig") = .{ |
| | 249 | .ty = module.intern_pool.typeOf(anon_decl).toType(), |
| | 250 | .val = anon_decl.toValue(), |
| | 251 | }; |
| | 252 | const c_value: codegen.CValue = .{ .constant = anon_decl }; |
| | 253 | codegen.genDeclValue(&object, tv, false, c_value, .none, .none) catch |err| switch (err) { |
| | 254 | error.AnalysisFail => { |
| | 255 | @panic("TODO: C backend AnalysisFail on anonymous decl"); |
| | 256 | //try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); |
| | 257 | //return; |
| | 258 | }, |
| | 259 | else => |e| return e, |
| | 260 | }; |
| | 261 | |
| | 262 | // Free excess allocated memory for this Decl. |
| | 263 | object.dg.ctypes.shrinkAndFree(gpa, object.dg.ctypes.count()); |
| | 264 | |
| | 265 | object.dg.anon_decl_deps.values()[i] = .{ |
| | 266 | .code = try self.addString(object.code.items), |
| | 267 | .fwd_decl = try self.addString(object.dg.fwd_decl.items), |
| | 268 | .ctypes = object.dg.ctypes.move(), |
| | 269 | }; |
| 212 | } | 270 | } |
| 213 | | 271 | |
| 214 | pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !void { | 272 | pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !void { |
| ... | @@ -227,7 +285,6 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi | ... | @@ -227,7 +285,6 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi |
| 227 | ctypes.clearRetainingCapacity(gpa); | 285 | ctypes.clearRetainingCapacity(gpa); |
| 228 | fwd_decl.clearRetainingCapacity(); | 286 | fwd_decl.clearRetainingCapacity(); |
| 229 | code.clearRetainingCapacity(); | 287 | code.clearRetainingCapacity(); |
| 230 | self.scratch_anon_decl_deps.clearRetainingCapacity(); | | |
| 231 | | 288 | |
| 232 | var object: codegen.Object = .{ | 289 | var object: codegen.Object = .{ |
| 233 | .dg = .{ | 290 | .dg = .{ |
| ... | @@ -238,14 +295,14 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi | ... | @@ -238,14 +295,14 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi |
| 238 | .is_naked_fn = false, | 295 | .is_naked_fn = false, |
| 239 | .fwd_decl = fwd_decl.toManaged(gpa), | 296 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 240 | .ctypes = ctypes.*, | 297 | .ctypes = ctypes.*, |
| 241 | .anon_decl_deps = self.scratch_anon_decl_deps, | 298 | .anon_decl_deps = self.anon_decls, |
| 242 | }, | 299 | }, |
| 243 | .code = code.toManaged(gpa), | 300 | .code = code.toManaged(gpa), |
| 244 | .indent_writer = undefined, // set later so we can get a pointer to object.code | 301 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| 245 | }; | 302 | }; |
| 246 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; | 303 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 247 | defer { | 304 | defer { |
| 248 | self.scratch_anon_decl_deps = object.dg.anon_decl_deps; | 305 | self.anon_decls = object.dg.anon_decl_deps; |
| 249 | object.dg.ctypes.deinit(object.dg.gpa); | 306 | object.dg.ctypes.deinit(object.dg.gpa); |
| 250 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 307 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 251 | code.* = object.code.moveToUnmanaged(); | 308 | code.* = object.code.moveToUnmanaged(); |
| ... | @@ -303,6 +360,13 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo | ... | @@ -303,6 +360,13 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo |
| 303 | const gpa = self.base.allocator; | 360 | const gpa = self.base.allocator; |
| 304 | const module = self.base.options.module.?; | 361 | const module = self.base.options.module.?; |
| 305 | | 362 | |
| | 363 | { |
| | 364 | var i: usize = 0; |
| | 365 | while (i < self.anon_decls.count()) : (i += 1) { |
| | 366 | try updateAnonDecl(self, module, i); |
| | 367 | } |
| | 368 | } |
| | 369 | |
| 306 | // This code path happens exclusively with -ofmt=c. The flush logic for | 370 | // This code path happens exclusively with -ofmt=c. The flush logic for |
| 307 | // emit-h is in `flushEmitH` below. | 371 | // emit-h is in `flushEmitH` below. |
| 308 | | 372 | |
| ... | @@ -345,10 +409,15 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo | ... | @@ -345,10 +409,15 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo |
| 345 | for (module.decl_exports.values()) |exports| for (exports.items) |@"export"| | 409 | for (module.decl_exports.values()) |exports| for (exports.items) |@"export"| |
| 346 | try export_names.put(gpa, @"export".opts.name, {}); | 410 | try export_names.put(gpa, @"export".opts.name, {}); |
| 347 | | 411 | |
| 348 | const decl_keys = self.decl_table.keys(); | 412 | for (self.anon_decls.values()) |*decl_block| { |
| 349 | for (decl_keys) |decl_index| { | 413 | try self.flushDeclBlock(&f, decl_block, export_names, .none); |
| | 414 | } |
| | 415 | |
| | 416 | for (self.decl_table.keys(), self.decl_table.values()) |decl_index, *decl_block| { |
| 350 | assert(module.declPtr(decl_index).has_tv); | 417 | assert(module.declPtr(decl_index).has_tv); |
| 351 | try self.flushDecl(&f, decl_index, export_names); | 418 | const decl = module.declPtr(decl_index); |
| | 419 | const extern_symbol_name = if (decl.isExtern(module)) decl.name.toOptional() else .none; |
| | 420 | try self.flushDeclBlock(&f, decl_block, export_names, extern_symbol_name); |
| 352 | } | 421 | } |
| 353 | } | 422 | } |
| 354 | | 423 | |
| ... | @@ -358,8 +427,12 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo | ... | @@ -358,8 +427,12 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo |
| 358 | assert(f.ctypes.count() == 0); | 427 | assert(f.ctypes.count() == 0); |
| 359 | try self.flushCTypes(&f, .none, f.lazy_ctypes); | 428 | try self.flushCTypes(&f, .none, f.lazy_ctypes); |
| 360 | | 429 | |
| 361 | for (self.decl_table.keys(), self.decl_table.values()) |decl_index, db| { | 430 | for (self.anon_decls.values()) |decl_block| { |
| 362 | try self.flushCTypes(&f, decl_index.toOptional(), db.ctypes); | 431 | try self.flushCTypes(&f, .none, decl_block.ctypes); |
| | 432 | } |
| | 433 | |
| | 434 | for (self.decl_table.keys(), self.decl_table.values()) |decl_index, decl_block| { |
| | 435 | try self.flushCTypes(&f, decl_index.toOptional(), decl_block.ctypes); |
| 363 | } | 436 | } |
| 364 | } | 437 | } |
| 365 | | 438 | |
| ... | @@ -377,10 +450,12 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo | ... | @@ -377,10 +450,12 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo |
| 377 | f.file_size += lazy_fwd_decl_len; | 450 | f.file_size += lazy_fwd_decl_len; |
| 378 | | 451 | |
| 379 | // Now the code. | 452 | // Now the code. |
| | 453 | const anon_decl_values = self.anon_decls.values(); |
| 380 | const decl_values = self.decl_table.values(); | 454 | const decl_values = self.decl_table.values(); |
| 381 | try f.all_buffers.ensureUnusedCapacity(gpa, 1 + decl_values.len); | 455 | try f.all_buffers.ensureUnusedCapacity(gpa, 1 + anon_decl_values.len + decl_values.len); |
| 382 | f.appendBufAssumeCapacity(self.lazy_code_buf.items); | 456 | f.appendBufAssumeCapacity(self.lazy_code_buf.items); |
| 383 | for (decl_values) |decl| f.appendBufAssumeCapacity(self.getString(decl.code)); | 457 | for (anon_decl_values) |db| f.appendBufAssumeCapacity(self.getString(db.code)); |
| | 458 | for (decl_values) |db| f.appendBufAssumeCapacity(self.getString(db.code)); |
| 384 | | 459 | |
| 385 | const file = self.base.file.?; | 460 | const file = self.base.file.?; |
| 386 | try file.setEndPos(f.file_size); | 461 | try file.setEndPos(f.file_size); |
| ... | @@ -526,16 +601,14 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { | ... | @@ -526,16 +601,14 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { |
| 526 | .is_naked_fn = false, | 601 | .is_naked_fn = false, |
| 527 | .fwd_decl = fwd_decl.toManaged(gpa), | 602 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 528 | .ctypes = ctypes.*, | 603 | .ctypes = ctypes.*, |
| 529 | .anon_decl_deps = .{}, | 604 | .anon_decl_deps = self.anon_decls, |
| 530 | }, | 605 | }, |
| 531 | .code = code.toManaged(gpa), | 606 | .code = code.toManaged(gpa), |
| 532 | .indent_writer = undefined, // set later so we can get a pointer to object.code | 607 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| 533 | }; | 608 | }; |
| 534 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; | 609 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 535 | defer { | 610 | defer { |
| 536 | // If this assert trips just handle the anon_decl_deps the same as | 611 | self.anon_decls = object.dg.anon_decl_deps; |
| 537 | // `updateFunc()` does. | | |
| 538 | assert(object.dg.anon_decl_deps.count() == 0); | | |
| 539 | object.dg.ctypes.deinit(gpa); | 612 | object.dg.ctypes.deinit(gpa); |
| 540 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 613 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 541 | code.* = object.code.moveToUnmanaged(); | 614 | code.* = object.code.moveToUnmanaged(); |
| ... | @@ -604,22 +677,22 @@ fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError | ... | @@ -604,22 +677,22 @@ fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError |
| 604 | } | 677 | } |
| 605 | } | 678 | } |
| 606 | | 679 | |
| 607 | fn flushDecl( | 680 | fn flushDeclBlock( |
| 608 | self: *C, | 681 | self: *C, |
| 609 | f: *Flush, | 682 | f: *Flush, |
| 610 | decl_index: Module.Decl.Index, | 683 | decl_block: *DeclBlock, |
| 611 | export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void), | 684 | export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void), |
| | 685 | extern_symbol_name: InternPool.OptionalNullTerminatedString, |
| 612 | ) FlushDeclError!void { | 686 | ) FlushDeclError!void { |
| 613 | const gpa = self.base.allocator; | 687 | const gpa = self.base.allocator; |
| 614 | const mod = self.base.options.module.?; | | |
| 615 | const decl = mod.declPtr(decl_index); | | |
| 616 | | | |
| 617 | const decl_block = self.decl_table.getPtr(decl_index).?; | | |
| 618 | | | |
| 619 | try self.flushLazyFns(f, decl_block.lazy_fns); | 688 | try self.flushLazyFns(f, decl_block.lazy_fns); |
| 620 | try f.all_buffers.ensureUnusedCapacity(gpa, 1); | 689 | try f.all_buffers.ensureUnusedCapacity(gpa, 1); |
| 621 | if (!(decl.isExtern(mod) and export_names.contains(decl.name))) | 690 | fwd_decl: { |
| | 691 | if (extern_symbol_name.unwrap()) |name| { |
| | 692 | if (export_names.contains(name)) break :fwd_decl; |
| | 693 | } |
| 622 | f.appendBufAssumeCapacity(self.getString(decl_block.fwd_decl)); | 694 | f.appendBufAssumeCapacity(self.getString(decl_block.fwd_decl)); |
| | 695 | } |
| 623 | } | 696 | } |
| 624 | | 697 | |
| 625 | pub fn flushEmitH(module: *Module) !void { | 698 | pub fn flushEmitH(module: *Module) !void { |