| ... | ... | @@ -34,6 +34,9 @@ fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{}, |
| 34 | 34 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new |
| 35 | 35 | /// one with every call. |
| 36 | 36 | 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) = .{}, |
| 37 | 40 | /// Optimization, `flush` reuses this buffer rather than creating a new |
| 38 | 41 | /// one with every call. |
| 39 | 42 | lazy_fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{}, |
| ... | ... | @@ -51,7 +54,6 @@ const String = struct { |
| 51 | 54 | .len = 0, |
| 52 | 55 | }; |
| 53 | 56 | }; |
| 54 | | |
| 55 | 57 | /// Per-declaration data. |
| 56 | 58 | const DeclBlock = struct { |
| 57 | 59 | code: String = String.empty, |
| ... | ... | @@ -98,7 +100,7 @@ pub fn openPath(gpa: Allocator, sub_path: []const u8, options: link.Options) !*C |
| 98 | 100 | var c_file = try gpa.create(C); |
| 99 | 101 | errdefer gpa.destroy(c_file); |
| 100 | 102 | |
| 101 | | c_file.* = C{ |
| 103 | c_file.* = .{ |
| 102 | 104 | .base = .{ |
| 103 | 105 | .tag = .c, |
| 104 | 106 | .options = options, |
| ... | ... | @@ -121,6 +123,7 @@ pub fn deinit(self: *C) void { |
| 121 | 123 | self.string_bytes.deinit(gpa); |
| 122 | 124 | self.fwd_decl_buf.deinit(gpa); |
| 123 | 125 | self.code_buf.deinit(gpa); |
| 126 | self.scratch_anon_decl_deps.deinit(gpa); |
| 124 | 127 | } |
| 125 | 128 | |
| 126 | 129 | pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void { |
| ... | ... | @@ -131,10 +134,13 @@ pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void { |
| 131 | 134 | } |
| 132 | 135 | } |
| 133 | 136 | |
| 134 | | pub fn updateFunc(self: *C, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void { |
| 135 | | const tracy = trace(@src()); |
| 136 | | defer tracy.end(); |
| 137 | | |
| 137 | pub fn updateFunc( |
| 138 | self: *C, |
| 139 | module: *Module, |
| 140 | func_index: InternPool.Index, |
| 141 | air: Air, |
| 142 | liveness: Liveness, |
| 143 | ) !void { |
| 138 | 144 | const gpa = self.base.allocator; |
| 139 | 145 | |
| 140 | 146 | const func = module.funcInfo(func_index); |
| ... | ... | @@ -152,52 +158,57 @@ pub fn updateFunc(self: *C, module: *Module, func_index: InternPool.Index, air: |
| 152 | 158 | lazy_fns.clearRetainingCapacity(); |
| 153 | 159 | fwd_decl.clearRetainingCapacity(); |
| 154 | 160 | code.clearRetainingCapacity(); |
| 161 | self.scratch_anon_decl_deps.clearRetainingCapacity(); |
| 155 | 162 | |
| 156 | | var function: codegen.Function = .{ |
| 157 | | .value_map = codegen.CValueMap.init(gpa), |
| 158 | | .air = air, |
| 159 | | .liveness = liveness, |
| 160 | | .func_index = func_index, |
| 161 | | .object = .{ |
| 162 | | .dg = .{ |
| 163 | | .gpa = gpa, |
| 164 | | .module = module, |
| 165 | | .error_msg = null, |
| 166 | | .decl_index = decl_index.toOptional(), |
| 167 | | .is_naked_fn = decl.ty.fnCallingConvention(module) == .Naked, |
| 168 | | .fwd_decl = fwd_decl.toManaged(gpa), |
| 169 | | .ctypes = ctypes.*, |
| 163 | { |
| 164 | var function: codegen.Function = .{ |
| 165 | .value_map = codegen.CValueMap.init(gpa), |
| 166 | .air = air, |
| 167 | .liveness = liveness, |
| 168 | .func_index = func_index, |
| 169 | .object = .{ |
| 170 | .dg = .{ |
| 171 | .gpa = gpa, |
| 172 | .module = module, |
| 173 | .error_msg = null, |
| 174 | .decl_index = decl_index.toOptional(), |
| 175 | .is_naked_fn = decl.ty.fnCallingConvention(module) == .Naked, |
| 176 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 177 | .ctypes = ctypes.*, |
| 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 |
| 170 | 182 | }, |
| 171 | | .code = code.toManaged(gpa), |
| 172 | | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| 173 | | }, |
| 174 | | .lazy_fns = lazy_fns.*, |
| 175 | | }; |
| 183 | .lazy_fns = lazy_fns.*, |
| 184 | }; |
| 176 | 185 | |
| 177 | | function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() }; |
| 178 | | defer { |
| 179 | | fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged(); |
| 180 | | code.* = function.object.code.moveToUnmanaged(); |
| 181 | | function.deinit(); |
| 182 | | } |
| 186 | function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() }; |
| 187 | defer { |
| 188 | self.scratch_anon_decl_deps = function.object.dg.anon_decl_deps; |
| 189 | fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged(); |
| 190 | code.* = function.object.code.moveToUnmanaged(); |
| 191 | function.deinit(); |
| 192 | } |
| 183 | 193 | |
| 184 | | codegen.genFunc(&function) catch |err| switch (err) { |
| 185 | | error.AnalysisFail => { |
| 186 | | try module.failed_decls.put(gpa, decl_index, function.object.dg.error_msg.?); |
| 187 | | return; |
| 188 | | }, |
| 189 | | else => |e| return e, |
| 190 | | }; |
| 194 | codegen.genFunc(&function) catch |err| switch (err) { |
| 195 | error.AnalysisFail => { |
| 196 | try module.failed_decls.put(gpa, decl_index, function.object.dg.error_msg.?); |
| 197 | return; |
| 198 | }, |
| 199 | else => |e| return e, |
| 200 | }; |
| 191 | 201 | |
| 192 | | ctypes.* = function.object.dg.ctypes.move(); |
| 193 | | lazy_fns.* = function.lazy_fns.move(); |
| 202 | ctypes.* = function.object.dg.ctypes.move(); |
| 203 | lazy_fns.* = function.lazy_fns.move(); |
| 194 | 204 | |
| 195 | | // Free excess allocated memory for this Decl. |
| 196 | | ctypes.shrinkAndFree(gpa, ctypes.count()); |
| 197 | | lazy_fns.shrinkAndFree(gpa, lazy_fns.count()); |
| 205 | // Free excess allocated memory for this Decl. |
| 206 | ctypes.shrinkAndFree(gpa, ctypes.count()); |
| 207 | lazy_fns.shrinkAndFree(gpa, lazy_fns.count()); |
| 198 | 208 | |
| 199 | | gop.value_ptr.code = try self.addString(function.object.code.items); |
| 200 | | gop.value_ptr.fwd_decl = try self.addString(function.object.dg.fwd_decl.items); |
| 209 | gop.value_ptr.code = try self.addString(function.object.code.items); |
| 210 | gop.value_ptr.fwd_decl = try self.addString(function.object.dg.fwd_decl.items); |
| 211 | } |
| 201 | 212 | } |
| 202 | 213 | |
| 203 | 214 | pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !void { |
| ... | ... | @@ -216,6 +227,7 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi |
| 216 | 227 | ctypes.clearRetainingCapacity(gpa); |
| 217 | 228 | fwd_decl.clearRetainingCapacity(); |
| 218 | 229 | code.clearRetainingCapacity(); |
| 230 | self.scratch_anon_decl_deps.clearRetainingCapacity(); |
| 219 | 231 | |
| 220 | 232 | var object: codegen.Object = .{ |
| 221 | 233 | .dg = .{ |
| ... | ... | @@ -226,12 +238,14 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi |
| 226 | 238 | .is_naked_fn = false, |
| 227 | 239 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 228 | 240 | .ctypes = ctypes.*, |
| 241 | .anon_decl_deps = self.scratch_anon_decl_deps, |
| 229 | 242 | }, |
| 230 | 243 | .code = code.toManaged(gpa), |
| 231 | 244 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| 232 | 245 | }; |
| 233 | 246 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 234 | 247 | defer { |
| 248 | self.scratch_anon_decl_deps = object.dg.anon_decl_deps; |
| 235 | 249 | object.dg.ctypes.deinit(object.dg.gpa); |
| 236 | 250 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 237 | 251 | code.* = object.code.moveToUnmanaged(); |
| ... | ... | @@ -512,12 +526,16 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { |
| 512 | 526 | .is_naked_fn = false, |
| 513 | 527 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 514 | 528 | .ctypes = ctypes.*, |
| 529 | .anon_decl_deps = .{}, |
| 515 | 530 | }, |
| 516 | 531 | .code = code.toManaged(gpa), |
| 517 | 532 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| 518 | 533 | }; |
| 519 | 534 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 520 | 535 | defer { |
| 536 | // If this assert trips just handle the anon_decl_deps the same as |
| 537 | // `updateFunc()` does. |
| 538 | assert(object.dg.anon_decl_deps.count() == 0); |
| 521 | 539 | object.dg.ctypes.deinit(gpa); |
| 522 | 540 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 523 | 541 | code.* = object.code.moveToUnmanaged(); |
| ... | ... | @@ -531,7 +549,11 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { |
| 531 | 549 | ctypes.* = object.dg.ctypes.move(); |
| 532 | 550 | } |
| 533 | 551 | |
| 534 | | fn flushLazyFn(self: *C, ctypes: *codegen.CType.Store, lazy_fn: codegen.LazyFnMap.Entry) FlushDeclError!void { |
| 552 | fn flushLazyFn( |
| 553 | self: *C, |
| 554 | ctypes: *codegen.CType.Store, |
| 555 | lazy_fn: codegen.LazyFnMap.Entry, |
| 556 | ) FlushDeclError!void { |
| 535 | 557 | const gpa = self.base.allocator; |
| 536 | 558 | |
| 537 | 559 | const fwd_decl = &self.lazy_fwd_decl_buf; |
| ... | ... | @@ -546,12 +568,16 @@ fn flushLazyFn(self: *C, ctypes: *codegen.CType.Store, lazy_fn: codegen.LazyFnMa |
| 546 | 568 | .is_naked_fn = false, |
| 547 | 569 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 548 | 570 | .ctypes = ctypes.*, |
| 571 | .anon_decl_deps = .{}, |
| 549 | 572 | }, |
| 550 | 573 | .code = code.toManaged(gpa), |
| 551 | 574 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| 552 | 575 | }; |
| 553 | 576 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 554 | 577 | defer { |
| 578 | // If this assert trips just handle the anon_decl_deps the same as |
| 579 | // `updateFunc()` does. |
| 580 | assert(object.dg.anon_decl_deps.count() == 0); |
| 555 | 581 | object.dg.ctypes.deinit(gpa); |
| 556 | 582 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 557 | 583 | code.* = object.code.moveToUnmanaged(); |