diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-10-28 17:23:02 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-10-28 17:23:02 -0700 |
| commit | 1c93cf52d8b8acab469efe5d4457ed43d76bc6e5 (patch) | |
| tree | 7f85f232fe39aeb3ab43d13dd29ecd70f9921d55 | |
| parent | c59ee3157f5a7fb5c6110422ea8215601285ea28 (diff) | |
| download | zig-1c93cf52d8b8acab469efe5d4457ed43d76bc6e5.tar.gz zig-1c93cf52d8b8acab469efe5d4457ed43d76bc6e5.zip | |
C backend: fix crash when number of Decls passes a threshold
The ensureUnusedCapacity did not reserve a big enough number. I changed
it to no longer guess the capacity because I saw that the number of
possible items was not determinable ahead of time and this can therefore
avoid allocating more memory than necessary.
| -rw-r--r-- | src/link/C.zig | 13 | ||||
| -rw-r--r-- | test/behavior.zig | 1 | ||||
| -rw-r--r-- | test/behavior/if.zig | 15 | ||||
| -rw-r--r-- | test/behavior/if_llvm.zig | 18 |
4 files changed, 22 insertions, 25 deletions
diff --git a/src/link/C.zig b/src/link/C.zig index 86019b1cb7..5237d23a48 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -251,8 +251,8 @@ pub fn flushModule(self: *C, comp: *Compilation) !void { var f: Flush = .{}; defer f.deinit(gpa); - // This is at least enough until we get to the function bodies without error handling. - try f.all_buffers.ensureTotalCapacity(gpa, self.decl_table.count() + 2); + // Covers zig.h and err_typedef_item. + try f.all_buffers.ensureUnusedCapacity(gpa, 2); f.all_buffers.appendAssumeCapacity(.{ .iov_base = zig_h, @@ -261,7 +261,8 @@ pub fn flushModule(self: *C, comp: *Compilation) !void { f.file_size += zig_h.len; const err_typedef_writer = f.err_typedef_buf.writer(gpa); - const err_typedef_item = f.all_buffers.addOneAssumeCapacity(); + const err_typedef_index = f.all_buffers.items.len; + f.all_buffers.items.len += 1; render_errors: { if (module.global_error_set.size == 0) break :render_errors; @@ -291,7 +292,7 @@ pub fn flushModule(self: *C, comp: *Compilation) !void { try flushDecl(self, &f, decl); } - err_typedef_item.* = .{ + f.all_buffers.items[err_typedef_index] = .{ .iov_base = f.err_typedef_buf.items.ptr, .iov_len = f.err_typedef_buf.items.len, }; @@ -371,7 +372,7 @@ fn flushDecl(self: *C, f: *Flush, decl: *const Module.Decl) FlushDeclError!void } } const buf = decl_block.fwd_decl.items; - f.all_buffers.appendAssumeCapacity(.{ + try f.all_buffers.append(gpa, .{ .iov_base = buf.ptr, .iov_len = buf.len, }); @@ -381,7 +382,7 @@ fn flushDecl(self: *C, f: *Flush, decl: *const Module.Decl) FlushDeclError!void f.fn_count += 1; } else if (decl_block.code.items.len != 0) { const buf = decl_block.code.items; - f.all_buffers.appendAssumeCapacity(.{ + try f.all_buffers.append(gpa, .{ .iov_base = buf.ptr, .iov_len = buf.len, }); diff --git a/test/behavior.zig b/test/behavior.zig index 30b76b00bf..4e18eb5d3f 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -43,7 +43,6 @@ test { _ = @import("behavior/generics.zig"); _ = @import("behavior/hasdecl.zig"); _ = @import("behavior/hasfield.zig"); - _ = @import("behavior/if_llvm.zig"); _ = @import("behavior/math.zig"); _ = @import("behavior/maximum_minimum.zig"); _ = @import("behavior/member_func.zig"); diff --git a/test/behavior/if.zig b/test/behavior/if.zig index a1f722d827..e907f288de 100644 --- a/test/behavior/if.zig +++ b/test/behavior/if.zig @@ -73,3 +73,18 @@ test "const result loc, runtime if cond, else unreachable" { const x = if (t) Num.Two else unreachable; try expect(x == .Two); } + +test "if copies its payload" { + const S = struct { + fn doTheTest() !void { + var tmp: ?i32 = 10; + if (tmp) |value| { + // Modify the original variable + tmp = null; + try expect(value == 10); + } else unreachable; + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} diff --git a/test/behavior/if_llvm.zig b/test/behavior/if_llvm.zig deleted file mode 100644 index e6773d90c0..0000000000 --- a/test/behavior/if_llvm.zig +++ /dev/null @@ -1,18 +0,0 @@ -const std = @import("std"); -const expect = std.testing.expect; -const expectEqual = std.testing.expectEqual; - -test "if copies its payload" { - const S = struct { - fn doTheTest() !void { - var tmp: ?i32 = 10; - if (tmp) |value| { - // Modify the original variable - tmp = null; - try expect(value == 10); - } else unreachable; - } - }; - try S.doTheTest(); - comptime try S.doTheTest(); -} |
