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