diff --git a/CMakeLists.txt b/CMakeLists.txt index 7891d4b73f..131b850e0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,18 +5,6 @@ if(NOT CMAKE_BUILD_TYPE) "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE) endif() -set(_list "None;Debug;Release;RelWithDebInfo;MinSizeRel") -list(FIND _list ${CMAKE_BUILD_TYPE} _index) -if(${_index} EQUAL -1) - string(REPLACE ";" ", " _list_pretty "${_list}") - message("::") - message(":: ERROR: Invalid build type: ${CMAKE_BUILD_TYPE}") - message("::") - message(":: valid types: { ${_list_pretty} }") - message("::") - message(FATAL_ERROR) -endif() - if(NOT CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}" CACHE STRING "Directory to install zig to" FORCE) @@ -256,7 +244,7 @@ set(ZIG_MAIN_SRC "${CMAKE_SOURCE_DIR}/src/main.cpp") set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/userland.cpp") if(ZIG_ENABLE_MEM_PROFILE) - set(ZIG_SOURCES_MEM_PROFILE "${CMAKE_SOURCE_DIR}/src/memory_profiling.cpp") + set(ZIG_SOURCES_MEM_PROFILE "${CMAKE_SOURCE_DIR}/src/mem_profile.cpp") endif() set(ZIG_SOURCES @@ -272,10 +260,12 @@ set(ZIG_SOURCES "${CMAKE_SOURCE_DIR}/src/errmsg.cpp" "${CMAKE_SOURCE_DIR}/src/error.cpp" "${CMAKE_SOURCE_DIR}/src/glibc.cpp" + "${CMAKE_SOURCE_DIR}/src/heap.cpp" "${CMAKE_SOURCE_DIR}/src/ir.cpp" "${CMAKE_SOURCE_DIR}/src/ir_print.cpp" "${CMAKE_SOURCE_DIR}/src/libc_installation.cpp" "${CMAKE_SOURCE_DIR}/src/link.cpp" + "${CMAKE_SOURCE_DIR}/src/mem.cpp" "${CMAKE_SOURCE_DIR}/src/os.cpp" "${CMAKE_SOURCE_DIR}/src/parser.cpp" "${CMAKE_SOURCE_DIR}/src/range_set.cpp" diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig index b028390465..f212ae8659 100644 --- a/lib/std/array_list.zig +++ b/lib/std/array_list.zig @@ -244,10 +244,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { } test "std.ArrayList.init" { - var bytes: [1024]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator; - - var list = ArrayList(i32).init(allocator); + var list = ArrayList(i32).init(testing.allocator); defer list.deinit(); testing.expect(list.len == 0); @@ -255,19 +252,14 @@ test "std.ArrayList.init" { } test "std.ArrayList.initCapacity" { - var bytes: [1024]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator; - var list = try ArrayList(i8).initCapacity(allocator, 200); + var list = try ArrayList(i8).initCapacity(testing.allocator, 200); defer list.deinit(); testing.expect(list.len == 0); testing.expect(list.capacity() >= 200); } test "std.ArrayList.basic" { - var bytes: [1024]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator; - - var list = ArrayList(i32).init(allocator); + var list = ArrayList(i32).init(testing.allocator); defer list.deinit(); // setting on empty list is out of bounds diff --git a/lib/std/ascii.zig b/lib/std/ascii.zig index 71f52bfd17..8bd959b46d 100644 --- a/lib/std/ascii.zig +++ b/lib/std/ascii.zig @@ -236,9 +236,8 @@ pub fn allocLowerString(allocator: *std.mem.Allocator, ascii_string: []const u8) } test "allocLowerString" { - var buf: [100]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(&buf).allocator; - const result = try allocLowerString(allocator, "aBcDeFgHiJkLmNOPqrst0234+💩!"); + const result = try allocLowerString(std.testing.allocator, "aBcDeFgHiJkLmNOPqrst0234+💩!"); + defer std.testing.allocator.free(result); std.testing.expect(std.mem.eql(u8, "abcdefghijklmnopqrst0234+💩!", result)); } diff --git a/lib/std/c/tokenizer.zig b/lib/std/c/tokenizer.zig index 80fd604eb5..66e6d9d52d 100644 --- a/lib/std/c/tokenizer.zig +++ b/lib/std/c/tokenizer.zig @@ -651,6 +651,7 @@ pub const Tokenizer = struct { state = .StringLiteral; }, else => { + self.index -= 1; state = .Identifier; }, }, @@ -660,6 +661,7 @@ pub const Tokenizer = struct { state = .StringLiteral; }, else => { + self.index -= 1; state = .Identifier; }, }, @@ -673,6 +675,7 @@ pub const Tokenizer = struct { state = .StringLiteral; }, else => { + self.index -= 1; state = .Identifier; }, }, @@ -686,6 +689,7 @@ pub const Tokenizer = struct { state = .StringLiteral; }, else => { + self.index -= 1; state = .Identifier; }, }, @@ -1079,6 +1083,9 @@ pub const Tokenizer = struct { 'x', 'X' => { state = .IntegerLiteralHex; }, + '.' => { + state = .FloatFraction; + }, else => { state = .IntegerSuffix; self.index -= 1; @@ -1261,13 +1268,16 @@ pub const Tokenizer = struct { .UnicodeEscape, .MultiLineComment, .MultiLineCommentAsterisk, - .FloatFraction, - .FloatFractionHex, .FloatExponent, - .FloatExponentDigits, .MacroString, => result.id = .Invalid, + .FloatExponentDigits => result.id = if (counter == 0) .Invalid else .{ .FloatLiteral = .None }, + + .FloatFraction, + .FloatFractionHex, + => result.id = .{ .FloatLiteral = .None }, + .IntegerLiteralOct, .IntegerLiteralBinary, .IntegerLiteralHex, diff --git a/lib/std/cstr.zig b/lib/std/cstr.zig index 5194dc1a13..5d16e9387b 100644 --- a/lib/std/cstr.zig +++ b/lib/std/cstr.zig @@ -41,9 +41,8 @@ pub fn addNullByte(allocator: *mem.Allocator, slice: []const u8) ![:0]u8 { } test "addNullByte" { - var buf: [30]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(&buf).allocator; - const slice = try addNullByte(allocator, "hello"[0..4]); + const slice = try addNullByte(std.testing.allocator, "hello"[0..4]); + defer std.testing.allocator.free(slice); testing.expect(slice.len == 4); testing.expect(slice[4] == 0); } diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 370717a4f7..a0ec668769 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -69,12 +69,12 @@ fn peekIsAlign(comptime fmt: []const u8) bool { /// /// If a formatted user type contains a function of the type /// ``` -/// fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, context: var, comptime Errors: type, output: fn (@TypeOf(context), []const u8) Errors!void) Errors!void +/// fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, context: var, comptime Errors: type, comptime output: fn (@TypeOf(context), []const u8) Errors!void) Errors!void /// ``` /// with `?` being the type formatted, this function will be called instead of the default implementation. /// This allows user types to be formatted in a logical manner instead of dumping all fields of the type. /// -/// A user type may be a `struct`, `union` or `enum` type. +/// A user type may be a `struct`, `vector`, `union` or `enum` type. pub fn format( context: var, comptime Errors: type, @@ -373,11 +373,11 @@ pub fn formatType( try output(context, @typeName(T)); if (enumInfo.is_exhaustive) { try output(context, "."); - return formatType(@tagName(value), "", options, context, Errors, output, max_depth); + try output(context, @tagName(value)); } else { // TODO: when @tagName works on exhaustive enums print known enum strings try output(context, "("); - try formatType(@enumToInt(value), "", options, context, Errors, output, max_depth); + try formatType(@enumToInt(value), fmt, options, context, Errors, output, max_depth); try output(context, ")"); } }, @@ -397,7 +397,7 @@ pub fn formatType( try output(context, " = "); inline for (info.fields) |u_field| { if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) { - try formatType(@field(value, u_field.name), "", options, context, Errors, output, max_depth - 1); + try formatType(@field(value, u_field.name), fmt, options, context, Errors, output, max_depth - 1); } } try output(context, " }"); @@ -424,7 +424,7 @@ pub fn formatType( } try output(context, @memberName(T, field_i)); try output(context, " = "); - try formatType(@field(value, @memberName(T, field_i)), "", options, context, Errors, output, max_depth - 1); + try formatType(@field(value, @memberName(T, field_i)), fmt, options, context, Errors, output, max_depth - 1); } try output(context, " }"); }, @@ -474,6 +474,18 @@ pub fn formatType( }); return formatType(@as(Slice, &value), fmt, options, context, Errors, output, max_depth); }, + .Vector => { + const len = @typeInfo(T).Vector.len; + try output(context, "{ "); + var i: usize = 0; + while (i < len) : (i += 1) { + try formatValue(value[i], fmt, options, context, Errors, output); + if (i < len - 1) { + try output(context, ", "); + } + } + try output(context, " }"); + }, .Fn => { return format(context, Errors, output, "{}@{x}", .{ @typeName(T), @ptrToInt(value) }); }, @@ -500,6 +512,7 @@ fn formatValue( switch (@typeId(T)) { .Float => return formatFloatValue(value, fmt, options, context, Errors, output), .Int, .ComptimeInt => return formatIntValue(value, fmt, options, context, Errors, output), + .Bool => return output(context, if (value) "true" else "false"), else => comptime unreachable, } } @@ -1343,6 +1356,20 @@ test "enum" { try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value}); } +test "non-exhaustive enum" { + const Enum = enum(u16) { + One = 0x000f, + Two = 0xbeef, + _, + }; + try testFmt("enum: Enum(15)\n", "enum: {}\n", .{Enum.One}); + try testFmt("enum: Enum(48879)\n", "enum: {}\n", .{Enum.Two}); + try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)}); + try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One}); + try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two}); + try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)}); +} + test "float.scientific" { try testFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)}); try testFmt("f32: 1.23400001e+01", "f32: {e}", .{@as(f32, 12.34)}); @@ -1699,3 +1726,20 @@ test "positional with specifier" { test "positional/alignment/width/precision" { try testFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)}); } + +test "vector" { + // https://github.com/ziglang/zig/issues/3317 + if (builtin.arch == .mipsel) return error.SkipZigTest; + + const vbool: @Vector(4, bool) = [_]bool{ true, false, true, false }; + const vi64: @Vector(4, i64) = [_]i64{ -2, -1, 0, 1 }; + const vu64: @Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 }; + + try testFmt("{ true, false, true, false }", "{}", .{vbool}); + try testFmt("{ -2, -1, 0, 1 }", "{}", .{vi64}); + try testFmt("{ - 2, - 1, + 0, + 1 }", "{d:5}", .{vi64}); + try testFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64}); + try testFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64}); + try testFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64}); + try testFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64}); +} diff --git a/lib/std/fs/get_app_data_dir.zig b/lib/std/fs/get_app_data_dir.zig index cb26e335de..35c0265435 100644 --- a/lib/std/fs/get_app_data_dir.zig +++ b/lib/std/fs/get_app_data_dir.zig @@ -56,9 +56,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD } test "getAppDataDir" { - var buf: [512]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator; - // We can't actually validate the result - _ = getAppDataDir(allocator, "zig") catch return; + const dir = getAppDataDir(std.testing.allocator, "zig") catch return; + defer std.testing.allocator.free(dir); } diff --git a/lib/std/fs/path.zig b/lib/std/fs/path.zig index f6f34585be..5d1c775629 100644 --- a/lib/std/fs/path.zig +++ b/lib/std/fs/path.zig @@ -89,16 +89,14 @@ pub fn joinPosix(allocator: *Allocator, paths: []const []const u8) ![]u8 { } fn testJoinWindows(paths: []const []const u8, expected: []const u8) void { - var buf: [1024]u8 = undefined; - const a = &std.heap.FixedBufferAllocator.init(&buf).allocator; - const actual = joinWindows(a, paths) catch @panic("fail"); + const actual = joinWindows(testing.allocator, paths) catch @panic("fail"); + defer testing.allocator.free(actual); testing.expectEqualSlices(u8, expected, actual); } fn testJoinPosix(paths: []const []const u8, expected: []const u8) void { - var buf: [1024]u8 = undefined; - const a = &std.heap.FixedBufferAllocator.init(&buf).allocator; - const actual = joinPosix(a, paths) catch @panic("fail"); + const actual = joinPosix(testing.allocator, paths) catch @panic("fail"); + defer testing.allocator.free(actual); testing.expectEqualSlices(u8, expected, actual); } diff --git a/lib/std/heap.zig b/lib/std/heap.zig index e7196f82f2..1bce45081d 100644 --- a/lib/std/heap.zig +++ b/lib/std/heap.zig @@ -533,7 +533,7 @@ pub const ArenaAllocator = struct { }; } - pub fn deinit(self: *ArenaAllocator) void { + pub fn deinit(self: ArenaAllocator) void { var it = self.buffer_list.first; while (it) |node| { // this has to occur before the free because the free frees node diff --git a/lib/std/http/headers.zig b/lib/std/http/headers.zig index dfe53fe750..a7a1464f99 100644 --- a/lib/std/http/headers.zig +++ b/lib/std/http/headers.zig @@ -83,12 +83,8 @@ const HeaderEntry = struct { } }; -var test_memory: [32 * 1024]u8 = undefined; -var test_fba_state = std.heap.FixedBufferAllocator.init(&test_memory); -const test_allocator = &test_fba_state.allocator; - test "HeaderEntry" { - var e = try HeaderEntry.init(test_allocator, "foo", "bar", null); + var e = try HeaderEntry.init(testing.allocator, "foo", "bar", null); defer e.deinit(); testing.expectEqualSlices(u8, "foo", e.name); testing.expectEqualSlices(u8, "bar", e.value); @@ -368,7 +364,7 @@ pub const Headers = struct { }; test "Headers.iterator" { - var h = Headers.init(test_allocator); + var h = Headers.init(testing.allocator); defer h.deinit(); try h.append("foo", "bar", null); try h.append("cookie", "somevalue", null); @@ -390,7 +386,7 @@ test "Headers.iterator" { } test "Headers.contains" { - var h = Headers.init(test_allocator); + var h = Headers.init(testing.allocator); defer h.deinit(); try h.append("foo", "bar", null); try h.append("cookie", "somevalue", null); @@ -400,7 +396,7 @@ test "Headers.contains" { } test "Headers.delete" { - var h = Headers.init(test_allocator); + var h = Headers.init(testing.allocator); defer h.deinit(); try h.append("foo", "bar", null); try h.append("baz", "qux", null); @@ -428,7 +424,7 @@ test "Headers.delete" { } test "Headers.orderedRemove" { - var h = Headers.init(test_allocator); + var h = Headers.init(testing.allocator); defer h.deinit(); try h.append("foo", "bar", null); try h.append("baz", "qux", null); @@ -451,7 +447,7 @@ test "Headers.orderedRemove" { } test "Headers.swapRemove" { - var h = Headers.init(test_allocator); + var h = Headers.init(testing.allocator); defer h.deinit(); try h.append("foo", "bar", null); try h.append("baz", "qux", null); @@ -474,7 +470,7 @@ test "Headers.swapRemove" { } test "Headers.at" { - var h = Headers.init(test_allocator); + var h = Headers.init(testing.allocator); defer h.deinit(); try h.append("foo", "bar", null); try h.append("cookie", "somevalue", null); @@ -494,7 +490,7 @@ test "Headers.at" { } test "Headers.getIndices" { - var h = Headers.init(test_allocator); + var h = Headers.init(testing.allocator); defer h.deinit(); try h.append("foo", "bar", null); try h.append("set-cookie", "x=1", null); @@ -506,27 +502,27 @@ test "Headers.getIndices" { } test "Headers.get" { - var h = Headers.init(test_allocator); + var h = Headers.init(testing.allocator); defer h.deinit(); try h.append("foo", "bar", null); try h.append("set-cookie", "x=1", null); try h.append("set-cookie", "y=2", null); { - const v = try h.get(test_allocator, "not-present"); + const v = try h.get(testing.allocator, "not-present"); testing.expect(null == v); } { - const v = (try h.get(test_allocator, "foo")).?; - defer test_allocator.free(v); + const v = (try h.get(testing.allocator, "foo")).?; + defer testing.allocator.free(v); const e = v[0]; testing.expectEqualSlices(u8, "foo", e.name); testing.expectEqualSlices(u8, "bar", e.value); testing.expectEqual(false, e.never_index); } { - const v = (try h.get(test_allocator, "set-cookie")).?; - defer test_allocator.free(v); + const v = (try h.get(testing.allocator, "set-cookie")).?; + defer testing.allocator.free(v); { const e = v[0]; testing.expectEqualSlices(u8, "set-cookie", e.name); @@ -543,30 +539,30 @@ test "Headers.get" { } test "Headers.getCommaSeparated" { - var h = Headers.init(test_allocator); + var h = Headers.init(testing.allocator); defer h.deinit(); try h.append("foo", "bar", null); try h.append("set-cookie", "x=1", null); try h.append("set-cookie", "y=2", null); { - const v = try h.getCommaSeparated(test_allocator, "not-present"); + const v = try h.getCommaSeparated(testing.allocator, "not-present"); testing.expect(null == v); } { - const v = (try h.getCommaSeparated(test_allocator, "foo")).?; - defer test_allocator.free(v); + const v = (try h.getCommaSeparated(testing.allocator, "foo")).?; + defer testing.allocator.free(v); testing.expectEqualSlices(u8, "bar", v); } { - const v = (try h.getCommaSeparated(test_allocator, "set-cookie")).?; - defer test_allocator.free(v); + const v = (try h.getCommaSeparated(testing.allocator, "set-cookie")).?; + defer testing.allocator.free(v); testing.expectEqualSlices(u8, "x=1,y=2", v); } } test "Headers.sort" { - var h = Headers.init(test_allocator); + var h = Headers.init(testing.allocator); defer h.deinit(); try h.append("foo", "bar", null); try h.append("cookie", "somevalue", null); @@ -587,7 +583,7 @@ test "Headers.sort" { } test "Headers.format" { - var h = Headers.init(test_allocator); + var h = Headers.init(testing.allocator); defer h.deinit(); try h.append("foo", "bar", null); try h.append("cookie", "somevalue", null); diff --git a/lib/std/io.zig b/lib/std/io.zig index 341b73e33c..16bfffdcad 100644 --- a/lib/std/io.zig +++ b/lib/std/io.zig @@ -223,15 +223,13 @@ test "io.BufferedInStream" { } }; - var buf: [100]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator; - const str = "This is a test"; var one_byte_stream = OneByteReadInStream.init(str); var buf_in_stream = BufferedInStream(OneByteReadInStream.Error).init(&one_byte_stream.stream); const stream = &buf_in_stream.stream; - const res = try stream.readAllAlloc(allocator, str.len + 1); + const res = try stream.readAllAlloc(testing.allocator, str.len + 1); + defer testing.allocator.free(res); testing.expectEqualSlices(u8, str, res); } @@ -874,10 +872,8 @@ pub fn readLineFrom(stream: var, buf: *std.Buffer) ![]u8 { } test "io.readLineFrom" { - var bytes: [128]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator; - - var buf = try std.Buffer.initSize(allocator, 0); + var buf = try std.Buffer.initSize(testing.allocator, 0); + defer buf.deinit(); var mem_stream = SliceInStream.init( \\Line 1 \\Line 22 diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig index 92259fd6e9..920cd801af 100644 --- a/lib/std/io/test.zig +++ b/lib/std/io/test.zig @@ -11,9 +11,6 @@ const fs = std.fs; const File = std.fs.File; test "write a file, read it, then delete it" { - var raw_bytes: [200 * 1024]u8 = undefined; - var allocator = &std.heap.FixedBufferAllocator.init(raw_bytes[0..]).allocator; - const cwd = fs.cwd(); var data: [1024]u8 = undefined; @@ -53,8 +50,8 @@ test "write a file, read it, then delete it" { var file_in_stream = file.inStream(); var buf_stream = io.BufferedInStream(File.ReadError).init(&file_in_stream.stream); const st = &buf_stream.stream; - const contents = try st.readAllAlloc(allocator, 2 * 1024); - defer allocator.free(contents); + const contents = try st.readAllAlloc(std.testing.allocator, 2 * 1024); + defer std.testing.allocator.free(contents); expect(mem.eql(u8, contents[0.."begin".len], "begin")); expect(mem.eql(u8, contents["begin".len .. contents.len - "end".len], &data)); @@ -64,10 +61,8 @@ test "write a file, read it, then delete it" { } test "BufferOutStream" { - var bytes: [100]u8 = undefined; - var allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator; - - var buffer = try std.Buffer.initSize(allocator, 0); + var buffer = try std.Buffer.initSize(std.testing.allocator, 0); + defer buffer.deinit(); var buf_stream = &std.io.BufferOutStream.init(&buffer).stream; const x: i32 = 42; diff --git a/lib/std/json.zig b/lib/std/json.zig index 1b10be0763..74e008d76e 100644 --- a/lib/std/json.zig +++ b/lib/std/json.zig @@ -1495,10 +1495,7 @@ fn unescapeString(output: []u8, input: []const u8) !void { } test "json.parser.dynamic" { - var memory: [1024 * 16]u8 = undefined; - var buf_alloc = std.heap.FixedBufferAllocator.init(&memory); - - var p = Parser.init(&buf_alloc.allocator, false); + var p = Parser.init(testing.allocator, false); defer p.deinit(); const s = @@ -1588,10 +1585,10 @@ test "write json then parse it" { try jw.endObject(); - var mem_buffer: [1024 * 20]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(&mem_buffer).allocator; - var parser = Parser.init(allocator, false); - const tree = try parser.parse(slice_out_stream.getWritten()); + var parser = Parser.init(testing.allocator, false); + defer parser.deinit(); + var tree = try parser.parse(slice_out_stream.getWritten()); + defer tree.deinit(); testing.expect(tree.root.Object.get("f").?.value.Bool == false); testing.expect(tree.root.Object.get("t").?.value.Bool == true); @@ -1601,21 +1598,21 @@ test "write json then parse it" { testing.expect(mem.eql(u8, tree.root.Object.get("str").?.value.String, "hello")); } -fn test_parse(memory: []u8, json_str: []const u8) !Value { - // buf_alloc goes out of scope, but we don't use it after parsing - var buf_alloc = std.heap.FixedBufferAllocator.init(memory); - var p = Parser.init(&buf_alloc.allocator, false); +fn test_parse(arena_allocator: *std.mem.Allocator, json_str: []const u8) !Value { + var p = Parser.init(arena_allocator, false); return (try p.parse(json_str)).root; } test "parsing empty string gives appropriate error" { - var memory: [1024 * 4]u8 = undefined; - testing.expectError(error.UnexpectedEndOfJson, test_parse(&memory, "")); + var arena_allocator = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena_allocator.deinit(); + testing.expectError(error.UnexpectedEndOfJson, test_parse(&arena_allocator.allocator, "")); } test "integer after float has proper type" { - var memory: [1024 * 8]u8 = undefined; - const json = try test_parse(&memory, + var arena_allocator = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena_allocator.deinit(); + const json = try test_parse(&arena_allocator.allocator, \\{ \\ "float": 3.14, \\ "ints": [1, 2, 3] @@ -1625,7 +1622,8 @@ test "integer after float has proper type" { } test "escaped characters" { - var memory: [1024 * 16]u8 = undefined; + var arena_allocator = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena_allocator.deinit(); const input = \\{ \\ "backslash": "\\", @@ -1641,7 +1639,7 @@ test "escaped characters" { \\} ; - const obj = (try test_parse(&memory, input)).Object; + const obj = (try test_parse(&arena_allocator.allocator, input)).Object; testing.expectEqualSlices(u8, obj.get("backslash").?.value.String, "\\"); testing.expectEqualSlices(u8, obj.get("forwardslash").?.value.String, "/"); @@ -1665,13 +1663,13 @@ test "string copy option" { \\} ; - var mem_buffer: [1024 * 16]u8 = undefined; - var buf_alloc = std.heap.FixedBufferAllocator.init(&mem_buffer); + var arena_allocator = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena_allocator.deinit(); - const tree_nocopy = try Parser.init(&buf_alloc.allocator, false).parse(input); + const tree_nocopy = try Parser.init(&arena_allocator.allocator, false).parse(input); const obj_nocopy = tree_nocopy.root.Object; - const tree_copy = try Parser.init(&buf_alloc.allocator, true).parse(input); + const tree_copy = try Parser.init(&arena_allocator.allocator, true).parse(input); const obj_copy = tree_copy.root.Object; for ([_][]const u8{ "noescape", "simple", "unicode", "surrogatepair" }) |field_name| { diff --git a/lib/std/json/test.zig b/lib/std/json/test.zig index 28fdca1b0f..6873fa038a 100644 --- a/lib/std/json/test.zig +++ b/lib/std/json/test.zig @@ -8,19 +8,18 @@ const std = @import("../std.zig"); fn ok(comptime s: []const u8) void { std.testing.expect(std.json.validate(s)); - var mem_buffer: [1024 * 20]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(&mem_buffer).allocator; - var p = std.json.Parser.init(allocator, false); + var p = std.json.Parser.init(std.testing.allocator, false); + defer p.deinit(); - _ = p.parse(s) catch unreachable; + var tree = p.parse(s) catch unreachable; + defer tree.deinit(); } fn err(comptime s: []const u8) void { std.testing.expect(!std.json.validate(s)); - var mem_buffer: [1024 * 20]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(&mem_buffer).allocator; - var p = std.json.Parser.init(allocator, false); + var p = std.json.Parser.init(std.testing.allocator, false); + defer p.deinit(); if (p.parse(s)) |_| { unreachable; @@ -30,9 +29,8 @@ fn err(comptime s: []const u8) void { fn utf8Error(comptime s: []const u8) void { std.testing.expect(!std.json.validate(s)); - var mem_buffer: [1024 * 20]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(&mem_buffer).allocator; - var p = std.json.Parser.init(allocator, false); + var p = std.json.Parser.init(std.testing.allocator, false); + defer p.deinit(); if (p.parse(s)) |_| { unreachable; @@ -44,19 +42,18 @@ fn utf8Error(comptime s: []const u8) void { fn any(comptime s: []const u8) void { _ = std.json.validate(s); - var mem_buffer: [1024 * 20]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(&mem_buffer).allocator; - var p = std.json.Parser.init(allocator, false); + var p = std.json.Parser.init(std.testing.allocator, false); + defer p.deinit(); - _ = p.parse(s) catch {}; + var tree = p.parse(s) catch return; + defer tree.deinit(); } fn anyStreamingErrNonStreaming(comptime s: []const u8) void { _ = std.json.validate(s); - var mem_buffer: [1024 * 20]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(&mem_buffer).allocator; - var p = std.json.Parser.init(allocator, false); + var p = std.json.Parser.init(std.testing.allocator, false); + defer p.deinit(); if (p.parse(s)) |_| { unreachable; diff --git a/lib/std/json/write_stream.zig b/lib/std/json/write_stream.zig index 51afe7fcbc..213b6768d4 100644 --- a/lib/std/json/write_stream.zig +++ b/lib/std/json/write_stream.zig @@ -254,11 +254,11 @@ test "json write stream" { var slice_stream = std.io.SliceOutStream.init(&out_buf); const out = &slice_stream.stream; - var mem_buf: [1024 * 10]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(&mem_buf).allocator; + var arena_allocator = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena_allocator.deinit(); var w = std.json.WriteStream(@TypeOf(out).Child, 10).init(out); - try w.emitJson(try getJson(allocator)); + try w.emitJson(try getJson(&arena_allocator.allocator)); const result = slice_stream.getWritten(); const expected = diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index 7d8d3a195b..d42d9fc676 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -137,10 +137,9 @@ pub const Int = struct { } /// Frees all memory associated with an Int. - pub fn deinit(self: *Int) void { + pub fn deinit(self: Int) void { self.assertWritable(); self.allocator.?.free(self.limbs); - self.* = undefined; } /// Clones an Int and returns a new Int with the same value. The new Int is a deep copy and @@ -1361,13 +1360,10 @@ pub const Int = struct { // They will still run on larger than this and should pass, but the multi-limb code-paths // may be untested in some cases. -var buffer: [64 * 8192]u8 = undefined; -var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]); -const al = &fixed.allocator; - test "big.int comptime_int set" { comptime var s = 0xefffffff00000001eeeeeeefaaaaaaab; - var a = try Int.initSet(al, s); + var a = try Int.initSet(testing.allocator, s); + defer a.deinit(); const s_limb_count = 128 / Limb.bit_count; @@ -1381,39 +1377,45 @@ test "big.int comptime_int set" { } test "big.int comptime_int set negative" { - var a = try Int.initSet(al, -10); + var a = try Int.initSet(testing.allocator, -10); + defer a.deinit(); testing.expect(a.limbs[0] == 10); testing.expect(a.isPositive() == false); } test "big.int int set unaligned small" { - var a = try Int.initSet(al, @as(u7, 45)); + var a = try Int.initSet(testing.allocator, @as(u7, 45)); + defer a.deinit(); testing.expect(a.limbs[0] == 45); testing.expect(a.isPositive() == true); } test "big.int comptime_int to" { - const a = try Int.initSet(al, 0xefffffff00000001eeeeeeefaaaaaaab); + const a = try Int.initSet(testing.allocator, 0xefffffff00000001eeeeeeefaaaaaaab); + defer a.deinit(); testing.expect((try a.to(u128)) == 0xefffffff00000001eeeeeeefaaaaaaab); } test "big.int sub-limb to" { - const a = try Int.initSet(al, 10); + const a = try Int.initSet(testing.allocator, 10); + defer a.deinit(); testing.expect((try a.to(u8)) == 10); } test "big.int to target too small error" { - const a = try Int.initSet(al, 0xffffffff); + const a = try Int.initSet(testing.allocator, 0xffffffff); + defer a.deinit(); testing.expectError(error.TargetTooSmall, a.to(u8)); } test "big.int normalize" { - var a = try Int.init(al); + var a = try Int.init(testing.allocator); + defer a.deinit(); try a.ensureCapacity(8); a.limbs[0] = 1; @@ -1440,7 +1442,8 @@ test "big.int normalize" { } test "big.int normalize multi" { - var a = try Int.init(al); + var a = try Int.init(testing.allocator); + defer a.deinit(); try a.ensureCapacity(8); a.limbs[0] = 1; @@ -1469,7 +1472,9 @@ test "big.int normalize multi" { } test "big.int parity" { - var a = try Int.init(al); + var a = try Int.init(testing.allocator); + defer a.deinit(); + try a.set(0); testing.expect(a.isEven()); testing.expect(!a.isOdd()); @@ -1480,7 +1485,8 @@ test "big.int parity" { } test "big.int bitcount + sizeInBase" { - var a = try Int.init(al); + var a = try Int.init(testing.allocator); + defer a.deinit(); try a.set(0b100); testing.expect(a.bitCountAbs() == 3); @@ -1507,7 +1513,8 @@ test "big.int bitcount + sizeInBase" { } test "big.int bitcount/to" { - var a = try Int.init(al); + var a = try Int.init(testing.allocator); + defer a.deinit(); try a.set(0); testing.expect(a.bitCountTwosComp() == 0); @@ -1537,7 +1544,8 @@ test "big.int bitcount/to" { } test "big.int fits" { - var a = try Int.init(al); + var a = try Int.init(testing.allocator); + defer a.deinit(); try a.set(0); testing.expect(a.fits(u0)); @@ -1564,82 +1572,100 @@ test "big.int fits" { } test "big.int string set" { - var a = try Int.init(al); - try a.setString(10, "120317241209124781241290847124"); + var a = try Int.init(testing.allocator); + defer a.deinit(); + try a.setString(10, "120317241209124781241290847124"); testing.expect((try a.to(u128)) == 120317241209124781241290847124); } test "big.int string negative" { - var a = try Int.init(al); + var a = try Int.init(testing.allocator); + defer a.deinit(); + try a.setString(10, "-1023"); testing.expect((try a.to(i32)) == -1023); } test "big.int string set bad char error" { - var a = try Int.init(al); + var a = try Int.init(testing.allocator); + defer a.deinit(); testing.expectError(error.InvalidCharForDigit, a.setString(10, "x")); } test "big.int string set bad base error" { - var a = try Int.init(al); + var a = try Int.init(testing.allocator); + defer a.deinit(); testing.expectError(error.InvalidBase, a.setString(45, "10")); } test "big.int string to" { - const a = try Int.initSet(al, 120317241209124781241290847124); + const a = try Int.initSet(testing.allocator, 120317241209124781241290847124); + defer a.deinit(); - const as = try a.toString(al, 10); + const as = try a.toString(testing.allocator, 10); + defer testing.allocator.free(as); const es = "120317241209124781241290847124"; testing.expect(mem.eql(u8, as, es)); } test "big.int string to base base error" { - const a = try Int.initSet(al, 0xffffffff); + const a = try Int.initSet(testing.allocator, 0xffffffff); + defer a.deinit(); - testing.expectError(error.InvalidBase, a.toString(al, 45)); + testing.expectError(error.InvalidBase, a.toString(testing.allocator, 45)); } test "big.int string to base 2" { - const a = try Int.initSet(al, -0b1011); + const a = try Int.initSet(testing.allocator, -0b1011); + defer a.deinit(); - const as = try a.toString(al, 2); + const as = try a.toString(testing.allocator, 2); + defer testing.allocator.free(as); const es = "-1011"; testing.expect(mem.eql(u8, as, es)); } test "big.int string to base 16" { - const a = try Int.initSet(al, 0xefffffff00000001eeeeeeefaaaaaaab); + const a = try Int.initSet(testing.allocator, 0xefffffff00000001eeeeeeefaaaaaaab); + defer a.deinit(); - const as = try a.toString(al, 16); + const as = try a.toString(testing.allocator, 16); + defer testing.allocator.free(as); const es = "efffffff00000001eeeeeeefaaaaaaab"; testing.expect(mem.eql(u8, as, es)); } test "big.int neg string to" { - const a = try Int.initSet(al, -123907434); + const a = try Int.initSet(testing.allocator, -123907434); + defer a.deinit(); - const as = try a.toString(al, 10); + const as = try a.toString(testing.allocator, 10); + defer testing.allocator.free(as); const es = "-123907434"; testing.expect(mem.eql(u8, as, es)); } test "big.int zero string to" { - const a = try Int.initSet(al, 0); + const a = try Int.initSet(testing.allocator, 0); + defer a.deinit(); - const as = try a.toString(al, 10); + const as = try a.toString(testing.allocator, 10); + defer testing.allocator.free(as); const es = "0"; testing.expect(mem.eql(u8, as, es)); } test "big.int clone" { - var a = try Int.initSet(al, 1234); + var a = try Int.initSet(testing.allocator, 1234); + defer a.deinit(); const b = try a.clone(); + defer b.deinit(); testing.expect((try a.to(u32)) == 1234); testing.expect((try b.to(u32)) == 1234); @@ -1650,8 +1676,10 @@ test "big.int clone" { } test "big.int swap" { - var a = try Int.initSet(al, 1234); - var b = try Int.initSet(al, 5678); + var a = try Int.initSet(testing.allocator, 1234); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 5678); + defer b.deinit(); testing.expect((try a.to(u32)) == 1234); testing.expect((try b.to(u32)) == 5678); @@ -1663,53 +1691,65 @@ test "big.int swap" { } test "big.int to negative" { - var a = try Int.initSet(al, -10); + var a = try Int.initSet(testing.allocator, -10); + defer a.deinit(); testing.expect((try a.to(i32)) == -10); } test "big.int compare" { - var a = try Int.initSet(al, -11); - var b = try Int.initSet(al, 10); + var a = try Int.initSet(testing.allocator, -11); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 10); + defer b.deinit(); testing.expect(a.cmpAbs(b) == 1); testing.expect(a.cmp(b) == -1); } test "big.int compare similar" { - var a = try Int.initSet(al, 0xffffffffeeeeeeeeffffffffeeeeeeee); - var b = try Int.initSet(al, 0xffffffffeeeeeeeeffffffffeeeeeeef); + var a = try Int.initSet(testing.allocator, 0xffffffffeeeeeeeeffffffffeeeeeeee); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0xffffffffeeeeeeeeffffffffeeeeeeef); + defer b.deinit(); testing.expect(a.cmpAbs(b) == -1); testing.expect(b.cmpAbs(a) == 1); } test "big.int compare different limb size" { - var a = try Int.initSet(al, maxInt(Limb) + 1); - var b = try Int.initSet(al, 1); + var a = try Int.initSet(testing.allocator, maxInt(Limb) + 1); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 1); + defer b.deinit(); testing.expect(a.cmpAbs(b) == 1); testing.expect(b.cmpAbs(a) == -1); } test "big.int compare multi-limb" { - var a = try Int.initSet(al, -0x7777777799999999ffffeeeeffffeeeeffffeeeef); - var b = try Int.initSet(al, 0x7777777799999999ffffeeeeffffeeeeffffeeeee); + var a = try Int.initSet(testing.allocator, -0x7777777799999999ffffeeeeffffeeeeffffeeeef); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0x7777777799999999ffffeeeeffffeeeeffffeeeee); + defer b.deinit(); testing.expect(a.cmpAbs(b) == 1); testing.expect(a.cmp(b) == -1); } test "big.int equality" { - var a = try Int.initSet(al, 0xffffffff1); - var b = try Int.initSet(al, -0xffffffff1); + var a = try Int.initSet(testing.allocator, 0xffffffff1); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, -0xffffffff1); + defer b.deinit(); testing.expect(a.eqAbs(b)); testing.expect(!a.eq(b)); } test "big.int abs" { - var a = try Int.initSet(al, -5); + var a = try Int.initSet(testing.allocator, -5); + defer a.deinit(); a.abs(); testing.expect((try a.to(u32)) == 5); @@ -1719,7 +1759,8 @@ test "big.int abs" { } test "big.int negate" { - var a = try Int.initSet(al, 5); + var a = try Int.initSet(testing.allocator, 5); + defer a.deinit(); a.negate(); testing.expect((try a.to(i32)) == -5); @@ -1729,20 +1770,26 @@ test "big.int negate" { } test "big.int add single-single" { - var a = try Int.initSet(al, 50); - var b = try Int.initSet(al, 5); + var a = try Int.initSet(testing.allocator, 50); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 5); + defer b.deinit(); - var c = try Int.init(al); + var c = try Int.init(testing.allocator); + defer c.deinit(); try c.add(a, b); testing.expect((try c.to(u32)) == 55); } test "big.int add multi-single" { - var a = try Int.initSet(al, maxInt(Limb) + 1); - var b = try Int.initSet(al, 1); + var a = try Int.initSet(testing.allocator, maxInt(Limb) + 1); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 1); + defer b.deinit(); - var c = try Int.init(al); + var c = try Int.init(testing.allocator); + defer c.deinit(); try c.add(a, b); testing.expect((try c.to(DoubleLimb)) == maxInt(Limb) + 2); @@ -1754,20 +1801,26 @@ test "big.int add multi-single" { test "big.int add multi-multi" { const op1 = 0xefefefef7f7f7f7f; const op2 = 0xfefefefe9f9f9f9f; - var a = try Int.initSet(al, op1); - var b = try Int.initSet(al, op2); + var a = try Int.initSet(testing.allocator, op1); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, op2); + defer b.deinit(); - var c = try Int.init(al); + var c = try Int.init(testing.allocator); + defer c.deinit(); try c.add(a, b); testing.expect((try c.to(u128)) == op1 + op2); } test "big.int add zero-zero" { - var a = try Int.initSet(al, 0); - var b = try Int.initSet(al, 0); + var a = try Int.initSet(testing.allocator, 0); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0); + defer b.deinit(); - var c = try Int.init(al); + var c = try Int.init(testing.allocator); + defer c.deinit(); try c.add(a, b); testing.expect((try c.to(u32)) == 0); @@ -1775,8 +1828,10 @@ test "big.int add zero-zero" { test "big.int add alias multi-limb nonzero-zero" { const op1 = 0xffffffff777777771; - var a = try Int.initSet(al, op1); - var b = try Int.initSet(al, 0); + var a = try Int.initSet(testing.allocator, op1); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0); + defer b.deinit(); try a.add(a, b); @@ -1784,12 +1839,17 @@ test "big.int add alias multi-limb nonzero-zero" { } test "big.int add sign" { - var a = try Int.init(al); + var a = try Int.init(testing.allocator); + defer a.deinit(); - const one = try Int.initSet(al, 1); - const two = try Int.initSet(al, 2); - const neg_one = try Int.initSet(al, -1); - const neg_two = try Int.initSet(al, -2); + const one = try Int.initSet(testing.allocator, 1); + defer one.deinit(); + const two = try Int.initSet(testing.allocator, 2); + defer two.deinit(); + const neg_one = try Int.initSet(testing.allocator, -1); + defer neg_one.deinit(); + const neg_two = try Int.initSet(testing.allocator, -2); + defer neg_two.deinit(); try a.add(one, two); testing.expect((try a.to(i32)) == 3); @@ -1805,20 +1865,26 @@ test "big.int add sign" { } test "big.int sub single-single" { - var a = try Int.initSet(al, 50); - var b = try Int.initSet(al, 5); + var a = try Int.initSet(testing.allocator, 50); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 5); + defer b.deinit(); - var c = try Int.init(al); + var c = try Int.init(testing.allocator); + defer c.deinit(); try c.sub(a, b); testing.expect((try c.to(u32)) == 45); } test "big.int sub multi-single" { - var a = try Int.initSet(al, maxInt(Limb) + 1); - var b = try Int.initSet(al, 1); + var a = try Int.initSet(testing.allocator, maxInt(Limb) + 1); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 1); + defer b.deinit(); - var c = try Int.init(al); + var c = try Int.init(testing.allocator); + defer c.deinit(); try c.sub(a, b); testing.expect((try c.to(Limb)) == maxInt(Limb)); @@ -1828,32 +1894,43 @@ test "big.int sub multi-multi" { const op1 = 0xefefefefefefefefefefefef; const op2 = 0xabababababababababababab; - var a = try Int.initSet(al, op1); - var b = try Int.initSet(al, op2); + var a = try Int.initSet(testing.allocator, op1); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, op2); + defer b.deinit(); - var c = try Int.init(al); + var c = try Int.init(testing.allocator); + defer c.deinit(); try c.sub(a, b); testing.expect((try c.to(u128)) == op1 - op2); } test "big.int sub equal" { - var a = try Int.initSet(al, 0x11efefefefefefefefefefefef); - var b = try Int.initSet(al, 0x11efefefefefefefefefefefef); + var a = try Int.initSet(testing.allocator, 0x11efefefefefefefefefefefef); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0x11efefefefefefefefefefefef); + defer b.deinit(); - var c = try Int.init(al); + var c = try Int.init(testing.allocator); + defer c.deinit(); try c.sub(a, b); testing.expect((try c.to(u32)) == 0); } test "big.int sub sign" { - var a = try Int.init(al); + var a = try Int.init(testing.allocator); + defer a.deinit(); - const one = try Int.initSet(al, 1); - const two = try Int.initSet(al, 2); - const neg_one = try Int.initSet(al, -1); - const neg_two = try Int.initSet(al, -2); + const one = try Int.initSet(testing.allocator, 1); + defer one.deinit(); + const two = try Int.initSet(testing.allocator, 2); + defer two.deinit(); + const neg_one = try Int.initSet(testing.allocator, -1); + defer neg_one.deinit(); + const neg_two = try Int.initSet(testing.allocator, -2); + defer neg_two.deinit(); try a.sub(one, two); testing.expect((try a.to(i32)) == -1); @@ -1872,20 +1949,26 @@ test "big.int sub sign" { } test "big.int mul single-single" { - var a = try Int.initSet(al, 50); - var b = try Int.initSet(al, 5); + var a = try Int.initSet(testing.allocator, 50); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 5); + defer b.deinit(); - var c = try Int.init(al); + var c = try Int.init(testing.allocator); + defer c.deinit(); try c.mul(a, b); testing.expect((try c.to(u64)) == 250); } test "big.int mul multi-single" { - var a = try Int.initSet(al, maxInt(Limb)); - var b = try Int.initSet(al, 2); + var a = try Int.initSet(testing.allocator, maxInt(Limb)); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 2); + defer b.deinit(); - var c = try Int.init(al); + var c = try Int.init(testing.allocator); + defer c.deinit(); try c.mul(a, b); testing.expect((try c.to(DoubleLimb)) == 2 * maxInt(Limb)); @@ -1894,18 +1977,23 @@ test "big.int mul multi-single" { test "big.int mul multi-multi" { const op1 = 0x998888efefefefefefefef; const op2 = 0x333000abababababababab; - var a = try Int.initSet(al, op1); - var b = try Int.initSet(al, op2); + var a = try Int.initSet(testing.allocator, op1); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, op2); + defer b.deinit(); - var c = try Int.init(al); + var c = try Int.init(testing.allocator); + defer c.deinit(); try c.mul(a, b); testing.expect((try c.to(u256)) == op1 * op2); } test "big.int mul alias r with a" { - var a = try Int.initSet(al, maxInt(Limb)); - var b = try Int.initSet(al, 2); + var a = try Int.initSet(testing.allocator, maxInt(Limb)); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 2); + defer b.deinit(); try a.mul(a, b); @@ -1913,8 +2001,10 @@ test "big.int mul alias r with a" { } test "big.int mul alias r with b" { - var a = try Int.initSet(al, maxInt(Limb)); - var b = try Int.initSet(al, 2); + var a = try Int.initSet(testing.allocator, maxInt(Limb)); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 2); + defer b.deinit(); try a.mul(b, a); @@ -1922,7 +2012,8 @@ test "big.int mul alias r with b" { } test "big.int mul alias r with a and b" { - var a = try Int.initSet(al, maxInt(Limb)); + var a = try Int.initSet(testing.allocator, maxInt(Limb)); + defer a.deinit(); try a.mul(a, a); @@ -1930,31 +2021,41 @@ test "big.int mul alias r with a and b" { } test "big.int mul a*0" { - var a = try Int.initSet(al, 0xefefefefefefefef); - var b = try Int.initSet(al, 0); + var a = try Int.initSet(testing.allocator, 0xefefefefefefefef); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0); + defer b.deinit(); - var c = try Int.init(al); + var c = try Int.init(testing.allocator); + defer c.deinit(); try c.mul(a, b); testing.expect((try c.to(u32)) == 0); } test "big.int mul 0*0" { - var a = try Int.initSet(al, 0); - var b = try Int.initSet(al, 0); + var a = try Int.initSet(testing.allocator, 0); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0); + defer b.deinit(); - var c = try Int.init(al); + var c = try Int.init(testing.allocator); + defer c.deinit(); try c.mul(a, b); testing.expect((try c.to(u32)) == 0); } test "big.int div single-single no rem" { - var a = try Int.initSet(al, 50); - var b = try Int.initSet(al, 5); + var a = try Int.initSet(testing.allocator, 50); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 5); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); testing.expect((try q.to(u32)) == 10); @@ -1962,11 +2063,15 @@ test "big.int div single-single no rem" { } test "big.int div single-single with rem" { - var a = try Int.initSet(al, 49); - var b = try Int.initSet(al, 5); + var a = try Int.initSet(testing.allocator, 49); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 5); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); testing.expect((try q.to(u32)) == 9); @@ -1977,11 +2082,15 @@ test "big.int div multi-single no rem" { const op1 = 0xffffeeeeddddcccc; const op2 = 34; - var a = try Int.initSet(al, op1); - var b = try Int.initSet(al, op2); + var a = try Int.initSet(testing.allocator, op1); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, op2); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); testing.expect((try q.to(u64)) == op1 / op2); @@ -1992,11 +2101,15 @@ test "big.int div multi-single with rem" { const op1 = 0xffffeeeeddddcccf; const op2 = 34; - var a = try Int.initSet(al, op1); - var b = try Int.initSet(al, op2); + var a = try Int.initSet(testing.allocator, op1); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, op2); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); testing.expect((try q.to(u64)) == op1 / op2); @@ -2007,11 +2120,15 @@ test "big.int div multi>2-single" { const op1 = 0xfefefefefefefefefefefefefefefefe; const op2 = 0xefab8; - var a = try Int.initSet(al, op1); - var b = try Int.initSet(al, op2); + var a = try Int.initSet(testing.allocator, op1); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, op2); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); testing.expect((try q.to(u128)) == op1 / op2); @@ -2019,11 +2136,15 @@ test "big.int div multi>2-single" { } test "big.int div single-single q < r" { - var a = try Int.initSet(al, 0x0078f432); - var b = try Int.initSet(al, 0x01000000); + var a = try Int.initSet(testing.allocator, 0x0078f432); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0x01000000); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); testing.expect((try q.to(u64)) == 0); @@ -2031,11 +2152,15 @@ test "big.int div single-single q < r" { } test "big.int div single-single q == r" { - var a = try Int.initSet(al, 10); - var b = try Int.initSet(al, 10); + var a = try Int.initSet(testing.allocator, 10); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 10); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); testing.expect((try q.to(u64)) == 1); @@ -2043,8 +2168,10 @@ test "big.int div single-single q == r" { } test "big.int div q=0 alias" { - var a = try Int.initSet(al, 3); - var b = try Int.initSet(al, 10); + var a = try Int.initSet(testing.allocator, 3); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 10); + defer b.deinit(); try Int.divTrunc(&a, &b, a, b); @@ -2055,11 +2182,15 @@ test "big.int div q=0 alias" { test "big.int div multi-multi q < r" { const op1 = 0x1ffffffff0078f432; const op2 = 0x1ffffffff01000000; - var a = try Int.initSet(al, op1); - var b = try Int.initSet(al, op2); + var a = try Int.initSet(testing.allocator, op1); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, op2); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); testing.expect((try q.to(u128)) == 0); @@ -2070,11 +2201,15 @@ test "big.int div trunc single-single +/+" { const u: i32 = 5; const v: i32 = 3; - var a = try Int.initSet(al, u); - var b = try Int.initSet(al, v); + var a = try Int.initSet(testing.allocator, u); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, v); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); // n = q * d + r @@ -2090,11 +2225,15 @@ test "big.int div trunc single-single -/+" { const u: i32 = -5; const v: i32 = 3; - var a = try Int.initSet(al, u); - var b = try Int.initSet(al, v); + var a = try Int.initSet(testing.allocator, u); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, v); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); // n = q * d + r @@ -2110,11 +2249,15 @@ test "big.int div trunc single-single +/-" { const u: i32 = 5; const v: i32 = -3; - var a = try Int.initSet(al, u); - var b = try Int.initSet(al, v); + var a = try Int.initSet(testing.allocator, u); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, v); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); // n = q * d + r @@ -2130,11 +2273,15 @@ test "big.int div trunc single-single -/-" { const u: i32 = -5; const v: i32 = -3; - var a = try Int.initSet(al, u); - var b = try Int.initSet(al, v); + var a = try Int.initSet(testing.allocator, u); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, v); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); // n = q * d + r @@ -2150,11 +2297,15 @@ test "big.int div floor single-single +/+" { const u: i32 = 5; const v: i32 = 3; - var a = try Int.initSet(al, u); - var b = try Int.initSet(al, v); + var a = try Int.initSet(testing.allocator, u); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, v); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divFloor(&q, &r, a, b); // n = q * d + r @@ -2170,11 +2321,15 @@ test "big.int div floor single-single -/+" { const u: i32 = -5; const v: i32 = 3; - var a = try Int.initSet(al, u); - var b = try Int.initSet(al, v); + var a = try Int.initSet(testing.allocator, u); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, v); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divFloor(&q, &r, a, b); // n = q * d + r @@ -2190,11 +2345,15 @@ test "big.int div floor single-single +/-" { const u: i32 = 5; const v: i32 = -3; - var a = try Int.initSet(al, u); - var b = try Int.initSet(al, v); + var a = try Int.initSet(testing.allocator, u); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, v); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divFloor(&q, &r, a, b); // n = q * d + r @@ -2210,11 +2369,15 @@ test "big.int div floor single-single -/-" { const u: i32 = -5; const v: i32 = -3; - var a = try Int.initSet(al, u); - var b = try Int.initSet(al, v); + var a = try Int.initSet(testing.allocator, u); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, v); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divFloor(&q, &r, a, b); // n = q * d + r @@ -2227,11 +2390,15 @@ test "big.int div floor single-single -/-" { } test "big.int div multi-multi with rem" { - var a = try Int.initSet(al, 0x8888999911110000ffffeeeeddddccccbbbbaaaa9999); - var b = try Int.initSet(al, 0x99990000111122223333); + var a = try Int.initSet(testing.allocator, 0x8888999911110000ffffeeeeddddccccbbbbaaaa9999); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0x99990000111122223333); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); testing.expect((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b); @@ -2239,11 +2406,15 @@ test "big.int div multi-multi with rem" { } test "big.int div multi-multi no rem" { - var a = try Int.initSet(al, 0x8888999911110000ffffeeeedb4fec200ee3a4286361); - var b = try Int.initSet(al, 0x99990000111122223333); + var a = try Int.initSet(testing.allocator, 0x8888999911110000ffffeeeedb4fec200ee3a4286361); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0x99990000111122223333); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); testing.expect((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b); @@ -2251,11 +2422,15 @@ test "big.int div multi-multi no rem" { } test "big.int div multi-multi (2 branch)" { - var a = try Int.initSet(al, 0x866666665555555588888887777777761111111111111111); - var b = try Int.initSet(al, 0x86666666555555554444444433333333); + var a = try Int.initSet(testing.allocator, 0x866666665555555588888887777777761111111111111111); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0x86666666555555554444444433333333); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); testing.expect((try q.to(u128)) == 0x10000000000000000); @@ -2263,11 +2438,15 @@ test "big.int div multi-multi (2 branch)" { } test "big.int div multi-multi (3.1/3.3 branch)" { - var a = try Int.initSet(al, 0x11111111111111111111111111111111111111111111111111111111111111); - var b = try Int.initSet(al, 0x1111111111111111111111111111111111111111171); + var a = try Int.initSet(testing.allocator, 0x11111111111111111111111111111111111111111111111111111111111111); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0x1111111111111111111111111111111111111111171); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); testing.expect((try q.to(u128)) == 0xfffffffffffffffffff); @@ -2275,145 +2454,189 @@ test "big.int div multi-multi (3.1/3.3 branch)" { } test "big.int div multi-single zero-limb trailing" { - var a = try Int.initSet(al, 0x60000000000000000000000000000000000000000000000000000000000000000); - var b = try Int.initSet(al, 0x10000000000000000); + var a = try Int.initSet(testing.allocator, 0x60000000000000000000000000000000000000000000000000000000000000000); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0x10000000000000000); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); - var expected = try Int.initSet(al, 0x6000000000000000000000000000000000000000000000000); + var expected = try Int.initSet(testing.allocator, 0x6000000000000000000000000000000000000000000000000); + defer expected.deinit(); testing.expect(q.eq(expected)); testing.expect(r.eqZero()); } test "big.int div multi-multi zero-limb trailing (with rem)" { - var a = try Int.initSet(al, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000); - var b = try Int.initSet(al, 0x8666666655555555444444443333333300000000000000000000000000000000); + var a = try Int.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); testing.expect((try q.to(u128)) == 0x10000000000000000); - const rs = try r.toString(al, 16); + const rs = try r.toString(testing.allocator, 16); + defer testing.allocator.free(rs); testing.expect(std.mem.eql(u8, rs, "4444444344444443111111111111111100000000000000000000000000000000")); } test "big.int div multi-multi zero-limb trailing (with rem) and dividend zero-limb count > divisor zero-limb count" { - var a = try Int.initSet(al, 0x8666666655555555888888877777777611111111111111110000000000000000); - var b = try Int.initSet(al, 0x8666666655555555444444443333333300000000000000000000000000000000); + var a = try Int.initSet(testing.allocator, 0x8666666655555555888888877777777611111111111111110000000000000000); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); testing.expect((try q.to(u128)) == 0x1); - const rs = try r.toString(al, 16); + const rs = try r.toString(testing.allocator, 16); + defer testing.allocator.free(rs); testing.expect(std.mem.eql(u8, rs, "444444434444444311111111111111110000000000000000")); } test "big.int div multi-multi zero-limb trailing (with rem) and dividend zero-limb count < divisor zero-limb count" { - var a = try Int.initSet(al, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000); - var b = try Int.initSet(al, 0x866666665555555544444444333333330000000000000000); + var a = try Int.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0x866666665555555544444444333333330000000000000000); + defer b.deinit(); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); - const qs = try q.toString(al, 16); + const qs = try q.toString(testing.allocator, 16); + defer testing.allocator.free(qs); testing.expect(std.mem.eql(u8, qs, "10000000000000000820820803105186f")); - const rs = try r.toString(al, 16); + const rs = try r.toString(testing.allocator, 16); + defer testing.allocator.free(rs); testing.expect(std.mem.eql(u8, rs, "4e11f2baa5896a321d463b543d0104e30000000000000000")); } test "big.int div multi-multi fuzz case #1" { - var a = try Int.init(al); - var b = try Int.init(al); + var a = try Int.init(testing.allocator); + defer a.deinit(); + var b = try Int.init(testing.allocator); + defer b.deinit(); try a.setString(16, "ffffffffffffffffffffffffffffc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); try b.setString(16, "3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000000000000000000007fffffffffff"); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); - const qs = try q.toString(al, 16); + const qs = try q.toString(testing.allocator, 16); + defer testing.allocator.free(qs); testing.expect(std.mem.eql(u8, qs, "3ffffffffffffffffffffffffffff0000000000000000000000000000000000001ffffffffffffffffffffffffffff7fffffffe000000000000000000000000000180000000000000000000003fffffbfffffffdfffffffffffffeffff800000100101000000100000000020003fffffdfbfffffe3ffffffffffffeffff7fffc00800a100000017ffe000002000400007efbfff7fe9f00000037ffff3fff7fffa004006100000009ffe00000190038200bf7d2ff7fefe80400060000f7d7f8fbf9401fe38e0403ffc0bdffffa51102c300d7be5ef9df4e5060007b0127ad3fa69f97d0f820b6605ff617ddf7f32ad7a05c0d03f2e7bc78a6000e087a8bbcdc59e07a5a079128a7861f553ddebed7e8e56701756f9ead39b48cd1b0831889ea6ec1fddf643d0565b075ff07e6caea4e2854ec9227fd635ed60a2f5eef2893052ffd54718fa08604acbf6a15e78a467c4a3c53c0278af06c4416573f925491b195e8fd79302cb1aaf7caf4ecfc9aec1254cc969786363ac729f914c6ddcc26738d6b0facd54eba026580aba2eb6482a088b0d224a8852420b91ec1")); - const rs = try r.toString(al, 16); + const rs = try r.toString(testing.allocator, 16); + defer testing.allocator.free(rs); testing.expect(std.mem.eql(u8, rs, "310d1d4c414426b4836c2635bad1df3a424e50cbdd167ffccb4dfff57d36b4aae0d6ca0910698220171a0f3373c1060a046c2812f0027e321f72979daa5e7973214170d49e885de0c0ecc167837d44502430674a82522e5df6a0759548052420b91ec1")); } test "big.int div multi-multi fuzz case #2" { - var a = try Int.init(al); - var b = try Int.init(al); + var a = try Int.init(testing.allocator); + defer a.deinit(); + var b = try Int.init(testing.allocator); + defer b.deinit(); try a.setString(16, "3ffffffffe00000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000000000000000001fffffffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffc000000000000000000000000000000000000000000000000000000000000000"); try b.setString(16, "ffc0000000000000000000000000000000000000000000000000"); - var q = try Int.init(al); - var r = try Int.init(al); + var q = try Int.init(testing.allocator); + defer q.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try Int.divTrunc(&q, &r, a, b); - const qs = try q.toString(al, 16); + const qs = try q.toString(testing.allocator, 16); + defer testing.allocator.free(qs); testing.expect(std.mem.eql(u8, qs, "40100400fe3f8fe3f8fe3f8fe3f8fe3f8fe4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f93e4f91e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4992649926499264991e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4791e4792e4b92e4b92e4b92e4b92a4a92a4a92a4")); - const rs = try r.toString(al, 16); + const rs = try r.toString(testing.allocator, 16); + defer testing.allocator.free(rs); testing.expect(std.mem.eql(u8, rs, "a900000000000000000000000000000000000000000000000000")); } test "big.int shift-right single" { - var a = try Int.initSet(al, 0xffff0000); + var a = try Int.initSet(testing.allocator, 0xffff0000); + defer a.deinit(); try a.shiftRight(a, 16); testing.expect((try a.to(u32)) == 0xffff); } test "big.int shift-right multi" { - var a = try Int.initSet(al, 0xffff0000eeee1111dddd2222cccc3333); + var a = try Int.initSet(testing.allocator, 0xffff0000eeee1111dddd2222cccc3333); + defer a.deinit(); try a.shiftRight(a, 67); testing.expect((try a.to(u64)) == 0x1fffe0001dddc222); } test "big.int shift-left single" { - var a = try Int.initSet(al, 0xffff); + var a = try Int.initSet(testing.allocator, 0xffff); + defer a.deinit(); try a.shiftLeft(a, 16); testing.expect((try a.to(u64)) == 0xffff0000); } test "big.int shift-left multi" { - var a = try Int.initSet(al, 0x1fffe0001dddc222); + var a = try Int.initSet(testing.allocator, 0x1fffe0001dddc222); + defer a.deinit(); try a.shiftLeft(a, 67); testing.expect((try a.to(u128)) == 0xffff0000eeee11100000000000000000); } test "big.int shift-right negative" { - var a = try Int.init(al); + var a = try Int.init(testing.allocator); + defer a.deinit(); - try a.shiftRight(try Int.initSet(al, -20), 2); + try a.shiftRight(try Int.initSet(testing.allocator, -20), 2); + defer a.deinit(); testing.expect((try a.to(i32)) == -20 >> 2); - try a.shiftRight(try Int.initSet(al, -5), 10); + try a.shiftRight(try Int.initSet(testing.allocator, -5), 10); + defer a.deinit(); testing.expect((try a.to(i32)) == -5 >> 10); } test "big.int shift-left negative" { - var a = try Int.init(al); + var a = try Int.init(testing.allocator); + defer a.deinit(); - try a.shiftRight(try Int.initSet(al, -10), 1232); + try a.shiftRight(try Int.initSet(testing.allocator, -10), 1232); + defer a.deinit(); testing.expect((try a.to(i32)) == -10 >> 1232); } test "big.int bitwise and simple" { - var a = try Int.initSet(al, 0xffffffff11111111); - var b = try Int.initSet(al, 0xeeeeeeee22222222); + var a = try Int.initSet(testing.allocator, 0xffffffff11111111); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0xeeeeeeee22222222); + defer b.deinit(); try a.bitAnd(a, b); @@ -2421,8 +2644,10 @@ test "big.int bitwise and simple" { } test "big.int bitwise and multi-limb" { - var a = try Int.initSet(al, maxInt(Limb) + 1); - var b = try Int.initSet(al, maxInt(Limb)); + var a = try Int.initSet(testing.allocator, maxInt(Limb) + 1); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, maxInt(Limb)); + defer b.deinit(); try a.bitAnd(a, b); @@ -2430,8 +2655,10 @@ test "big.int bitwise and multi-limb" { } test "big.int bitwise xor simple" { - var a = try Int.initSet(al, 0xffffffff11111111); - var b = try Int.initSet(al, 0xeeeeeeee22222222); + var a = try Int.initSet(testing.allocator, 0xffffffff11111111); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0xeeeeeeee22222222); + defer b.deinit(); try a.bitXor(a, b); @@ -2439,8 +2666,10 @@ test "big.int bitwise xor simple" { } test "big.int bitwise xor multi-limb" { - var a = try Int.initSet(al, maxInt(Limb) + 1); - var b = try Int.initSet(al, maxInt(Limb)); + var a = try Int.initSet(testing.allocator, maxInt(Limb) + 1); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, maxInt(Limb)); + defer b.deinit(); try a.bitXor(a, b); @@ -2448,8 +2677,10 @@ test "big.int bitwise xor multi-limb" { } test "big.int bitwise or simple" { - var a = try Int.initSet(al, 0xffffffff11111111); - var b = try Int.initSet(al, 0xeeeeeeee22222222); + var a = try Int.initSet(testing.allocator, 0xffffffff11111111); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0xeeeeeeee22222222); + defer b.deinit(); try a.bitOr(a, b); @@ -2457,8 +2688,10 @@ test "big.int bitwise or simple" { } test "big.int bitwise or multi-limb" { - var a = try Int.initSet(al, maxInt(Limb) + 1); - var b = try Int.initSet(al, maxInt(Limb)); + var a = try Int.initSet(testing.allocator, maxInt(Limb) + 1); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, maxInt(Limb)); + defer b.deinit(); try a.bitOr(a, b); @@ -2467,11 +2700,19 @@ test "big.int bitwise or multi-limb" { } test "big.int var args" { - var a = try Int.initSet(al, 5); + var a = try Int.initSet(testing.allocator, 5); + defer a.deinit(); - try a.add(a, try Int.initSet(al, 6)); + const b = try Int.initSet(testing.allocator, 6); + defer b.deinit(); + try a.add(a, b); testing.expect((try a.to(u64)) == 11); - testing.expect(a.cmp(try Int.initSet(al, 11)) == 0); - testing.expect(a.cmp(try Int.initSet(al, 14)) <= 0); + const c = try Int.initSet(testing.allocator, 11); + defer c.deinit(); + testing.expect(a.cmp(c) == 0); + + const d = try Int.initSet(testing.allocator, 14); + defer d.deinit(); + testing.expect(a.cmp(d) <= 0); } diff --git a/lib/std/math/big/rational.zig b/lib/std/math/big/rational.zig index 27a3b7300f..438c6c94fc 100644 --- a/lib/std/math/big/rational.zig +++ b/lib/std/math/big/rational.zig @@ -587,14 +587,13 @@ fn gcdLehmer(r: *Int, xa: Int, ya: Int) !void { r.swap(&x); } -var buffer: [64 * 8192]u8 = undefined; -var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]); -var al = &fixed.allocator; - test "big.rational gcd non-one small" { - var a = try Int.initSet(al, 17); - var b = try Int.initSet(al, 97); - var r = try Int.init(al); + var a = try Int.initSet(testing.allocator, 17); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 97); + defer b.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try gcd(&r, a, b); @@ -602,9 +601,12 @@ test "big.rational gcd non-one small" { } test "big.rational gcd non-one small" { - var a = try Int.initSet(al, 4864); - var b = try Int.initSet(al, 3458); - var r = try Int.init(al); + var a = try Int.initSet(testing.allocator, 4864); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 3458); + defer b.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try gcd(&r, a, b); @@ -612,9 +614,12 @@ test "big.rational gcd non-one small" { } test "big.rational gcd non-one large" { - var a = try Int.initSet(al, 0xffffffffffffffff); - var b = try Int.initSet(al, 0xffffffffffffffff7777); - var r = try Int.init(al); + var a = try Int.initSet(testing.allocator, 0xffffffffffffffff); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0xffffffffffffffff7777); + defer b.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try gcd(&r, a, b); @@ -622,9 +627,12 @@ test "big.rational gcd non-one large" { } test "big.rational gcd large multi-limb result" { - var a = try Int.initSet(al, 0x12345678123456781234567812345678123456781234567812345678); - var b = try Int.initSet(al, 0x12345671234567123456712345671234567123456712345671234567); - var r = try Int.init(al); + var a = try Int.initSet(testing.allocator, 0x12345678123456781234567812345678123456781234567812345678); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 0x12345671234567123456712345671234567123456712345671234567); + defer b.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try gcd(&r, a, b); @@ -632,9 +640,12 @@ test "big.rational gcd large multi-limb result" { } test "big.rational gcd one large" { - var a = try Int.initSet(al, 1897056385327307); - var b = try Int.initSet(al, 2251799813685248); - var r = try Int.init(al); + var a = try Int.initSet(testing.allocator, 1897056385327307); + defer a.deinit(); + var b = try Int.initSet(testing.allocator, 2251799813685248); + defer b.deinit(); + var r = try Int.init(testing.allocator); + defer r.deinit(); try gcd(&r, a, b); @@ -661,7 +672,8 @@ fn extractLowBits(a: Int, comptime T: type) T { } test "big.rational extractLowBits" { - var a = try Int.initSet(al, 0x11112222333344441234567887654321); + var a = try Int.initSet(testing.allocator, 0x11112222333344441234567887654321); + defer a.deinit(); const a1 = extractLowBits(a, u8); testing.expect(a1 == 0x21); @@ -680,7 +692,8 @@ test "big.rational extractLowBits" { } test "big.rational set" { - var a = try Rational.init(al); + var a = try Rational.init(testing.allocator); + defer a.deinit(); try a.setInt(5); testing.expect((try a.p.to(u32)) == 5); @@ -708,7 +721,8 @@ test "big.rational set" { } test "big.rational setFloat" { - var a = try Rational.init(al); + var a = try Rational.init(testing.allocator); + defer a.deinit(); try a.setFloat(f64, 2.5); testing.expect((try a.p.to(i32)) == 5); @@ -732,7 +746,8 @@ test "big.rational setFloat" { } test "big.rational setFloatString" { - var a = try Rational.init(al); + var a = try Rational.init(testing.allocator); + defer a.deinit(); try a.setFloatString("72.14159312071241458852455252781510353"); @@ -742,7 +757,8 @@ test "big.rational setFloatString" { } test "big.rational toFloat" { - var a = try Rational.init(al); + var a = try Rational.init(testing.allocator); + defer a.deinit(); // = 3.14159297943115234375 try a.setRatio(3294199, 1048576); @@ -754,7 +770,8 @@ test "big.rational toFloat" { } test "big.rational set/to Float round-trip" { - var a = try Rational.init(al); + var a = try Rational.init(testing.allocator); + defer a.deinit(); var prng = std.rand.DefaultPrng.init(0x5EED); var i: usize = 0; while (i < 512) : (i += 1) { @@ -765,23 +782,29 @@ test "big.rational set/to Float round-trip" { } test "big.rational copy" { - var a = try Rational.init(al); + var a = try Rational.init(testing.allocator); + defer a.deinit(); - const b = try Int.initSet(al, 5); + const b = try Int.initSet(testing.allocator, 5); + defer b.deinit(); try a.copyInt(b); testing.expect((try a.p.to(u32)) == 5); testing.expect((try a.q.to(u32)) == 1); - const c = try Int.initSet(al, 7); - const d = try Int.initSet(al, 3); + const c = try Int.initSet(testing.allocator, 7); + defer c.deinit(); + const d = try Int.initSet(testing.allocator, 3); + defer d.deinit(); try a.copyRatio(c, d); testing.expect((try a.p.to(u32)) == 7); testing.expect((try a.q.to(u32)) == 3); - const e = try Int.initSet(al, 9); - const f = try Int.initSet(al, 3); + const e = try Int.initSet(testing.allocator, 9); + defer e.deinit(); + const f = try Int.initSet(testing.allocator, 3); + defer f.deinit(); try a.copyRatio(e, f); testing.expect((try a.p.to(u32)) == 3); @@ -789,7 +812,8 @@ test "big.rational copy" { } test "big.rational negate" { - var a = try Rational.init(al); + var a = try Rational.init(testing.allocator); + defer a.deinit(); try a.setInt(-50); testing.expect((try a.p.to(i32)) == -50); @@ -805,7 +829,8 @@ test "big.rational negate" { } test "big.rational abs" { - var a = try Rational.init(al); + var a = try Rational.init(testing.allocator); + defer a.deinit(); try a.setInt(-50); testing.expect((try a.p.to(i32)) == -50); @@ -821,8 +846,10 @@ test "big.rational abs" { } test "big.rational swap" { - var a = try Rational.init(al); - var b = try Rational.init(al); + var a = try Rational.init(testing.allocator); + defer a.deinit(); + var b = try Rational.init(testing.allocator); + defer b.deinit(); try a.setRatio(50, 23); try b.setRatio(17, 3); @@ -843,8 +870,10 @@ test "big.rational swap" { } test "big.rational cmp" { - var a = try Rational.init(al); - var b = try Rational.init(al); + var a = try Rational.init(testing.allocator); + defer a.deinit(); + var b = try Rational.init(testing.allocator); + defer b.deinit(); try a.setRatio(500, 231); try b.setRatio(18903, 8584); @@ -856,8 +885,10 @@ test "big.rational cmp" { } test "big.rational add single-limb" { - var a = try Rational.init(al); - var b = try Rational.init(al); + var a = try Rational.init(testing.allocator); + defer a.deinit(); + var b = try Rational.init(testing.allocator); + defer b.deinit(); try a.setRatio(500, 231); try b.setRatio(18903, 8584); @@ -869,9 +900,12 @@ test "big.rational add single-limb" { } test "big.rational add" { - var a = try Rational.init(al); - var b = try Rational.init(al); - var r = try Rational.init(al); + var a = try Rational.init(testing.allocator); + defer a.deinit(); + var b = try Rational.init(testing.allocator); + defer b.deinit(); + var r = try Rational.init(testing.allocator); + defer r.deinit(); try a.setRatio(78923, 23341); try b.setRatio(123097, 12441414); @@ -882,9 +916,12 @@ test "big.rational add" { } test "big.rational sub" { - var a = try Rational.init(al); - var b = try Rational.init(al); - var r = try Rational.init(al); + var a = try Rational.init(testing.allocator); + defer a.deinit(); + var b = try Rational.init(testing.allocator); + defer b.deinit(); + var r = try Rational.init(testing.allocator); + defer r.deinit(); try a.setRatio(78923, 23341); try b.setRatio(123097, 12441414); @@ -895,9 +932,12 @@ test "big.rational sub" { } test "big.rational mul" { - var a = try Rational.init(al); - var b = try Rational.init(al); - var r = try Rational.init(al); + var a = try Rational.init(testing.allocator); + defer a.deinit(); + var b = try Rational.init(testing.allocator); + defer b.deinit(); + var r = try Rational.init(testing.allocator); + defer r.deinit(); try a.setRatio(78923, 23341); try b.setRatio(123097, 12441414); @@ -908,9 +948,12 @@ test "big.rational mul" { } test "big.rational div" { - var a = try Rational.init(al); - var b = try Rational.init(al); - var r = try Rational.init(al); + var a = try Rational.init(testing.allocator); + defer a.deinit(); + var b = try Rational.init(testing.allocator); + defer b.deinit(); + var r = try Rational.init(testing.allocator); + defer r.deinit(); try a.setRatio(78923, 23341); try b.setRatio(123097, 12441414); @@ -921,8 +964,10 @@ test "big.rational div" { } test "big.rational div" { - var a = try Rational.init(al); - var r = try Rational.init(al); + var a = try Rational.init(testing.allocator); + defer a.deinit(); + var r = try Rational.init(testing.allocator); + defer r.deinit(); try a.setRatio(78923, 23341); a.invert(); diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 8f4987e0c9..a1b4a3c809 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -1011,11 +1011,21 @@ pub fn join(allocator: *Allocator, separator: []const u8, slices: []const []cons } test "mem.join" { - var buf: [1024]u8 = undefined; - const a = &std.heap.FixedBufferAllocator.init(&buf).allocator; - testing.expect(eql(u8, try join(a, ",", &[_][]const u8{ "a", "b", "c" }), "a,b,c")); - testing.expect(eql(u8, try join(a, ",", &[_][]const u8{"a"}), "a")); - testing.expect(eql(u8, try join(a, ",", &[_][]const u8{ "a", "", "b", "", "c" }), "a,,b,,c")); + { + const str = try join(testing.allocator, ",", &[_][]const u8{ "a", "b", "c" }); + defer testing.allocator.free(str); + testing.expect(eql(u8, str, "a,b,c")); + } + { + const str = try join(testing.allocator, ",", &[_][]const u8{"a"}); + defer testing.allocator.free(str); + testing.expect(eql(u8, str, "a")); + } + { + const str = try join(testing.allocator, ",", &[_][]const u8{ "a", "", "b", "", "c" }); + defer testing.allocator.free(str); + testing.expect(eql(u8, str, "a,,b,,c")); + } } /// Copies each T from slices into a new slice that exactly holds all the elements. @@ -1044,15 +1054,21 @@ pub fn concat(allocator: *Allocator, comptime T: type, slices: []const []const T } test "concat" { - var buf: [1024]u8 = undefined; - const a = &std.heap.FixedBufferAllocator.init(&buf).allocator; - testing.expect(eql(u8, try concat(a, u8, &[_][]const u8{ "abc", "def", "ghi" }), "abcdefghi")); - testing.expect(eql(u32, try concat(a, u32, &[_][]const u32{ - &[_]u32{ 0, 1 }, - &[_]u32{ 2, 3, 4 }, - &[_]u32{}, - &[_]u32{5}, - }), &[_]u32{ 0, 1, 2, 3, 4, 5 })); + { + const str = try concat(testing.allocator, u8, &[_][]const u8{ "abc", "def", "ghi" }); + defer testing.allocator.free(str); + testing.expect(eql(u8, str, "abcdefghi")); + } + { + const str = try concat(testing.allocator, u32, &[_][]const u32{ + &[_]u32{ 0, 1 }, + &[_]u32{ 2, 3, 4 }, + &[_]u32{}, + &[_]u32{5}, + }); + defer testing.allocator.free(str); + testing.expect(eql(u32, str, &[_]u32{ 0, 1, 2, 3, 4, 5 })); + } } test "testStringEquality" { diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 5cb9c6589c..9c83b8304d 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -7,13 +7,12 @@ const testing = std.testing; pub const trait = @import("meta/trait.zig"); -const TypeId = builtin.TypeId; const TypeInfo = builtin.TypeInfo; pub fn tagName(v: var) []const u8 { const T = @TypeOf(v); switch (@typeInfo(T)) { - TypeId.ErrorSet => return @errorName(v), + .ErrorSet => return @errorName(v), else => return @tagName(v), } } @@ -55,7 +54,7 @@ test "std.meta.tagName" { pub fn stringToEnum(comptime T: type, str: []const u8) ?T { inline for (@typeInfo(T).Enum.fields) |enumField| { - if (std.mem.eql(u8, str, enumField.name)) { + if (mem.eql(u8, str, enumField.name)) { return @field(T, enumField.name); } } @@ -74,9 +73,9 @@ test "std.meta.stringToEnum" { pub fn bitCount(comptime T: type) comptime_int { return switch (@typeInfo(T)) { - TypeId.Bool => 1, - TypeId.Int => |info| info.bits, - TypeId.Float => |info| info.bits, + .Bool => 1, + .Int => |info| info.bits, + .Float => |info| info.bits, else => @compileError("Expected bool, int or float type, found '" ++ @typeName(T) ++ "'"), }; } @@ -88,7 +87,7 @@ test "std.meta.bitCount" { pub fn alignment(comptime T: type) comptime_int { //@alignOf works on non-pointer types - const P = if (comptime trait.is(TypeId.Pointer)(T)) T else *T; + const P = if (comptime trait.is(.Pointer)(T)) T else *T; return @typeInfo(P).Pointer.alignment; } @@ -102,9 +101,9 @@ test "std.meta.alignment" { pub fn Child(comptime T: type) type { return switch (@typeInfo(T)) { - TypeId.Array => |info| info.child, - TypeId.Pointer => |info| info.child, - TypeId.Optional => |info| info.child, + .Array => |info| info.child, + .Pointer => |info| info.child, + .Optional => |info| info.child, else => @compileError("Expected pointer, optional, or array type, " ++ "found '" ++ @typeName(T) ++ "'"), }; } @@ -118,9 +117,9 @@ test "std.meta.Child" { pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout { return switch (@typeInfo(T)) { - TypeId.Struct => |info| info.layout, - TypeId.Enum => |info| info.layout, - TypeId.Union => |info| info.layout, + .Struct => |info| info.layout, + .Enum => |info| info.layout, + .Union => |info| info.layout, else => @compileError("Expected struct, enum or union type, found '" ++ @typeName(T) ++ "'"), }; } @@ -148,22 +147,22 @@ test "std.meta.containerLayout" { a: u8, }; - testing.expect(containerLayout(E1) == TypeInfo.ContainerLayout.Auto); - testing.expect(containerLayout(E2) == TypeInfo.ContainerLayout.Packed); - testing.expect(containerLayout(E3) == TypeInfo.ContainerLayout.Extern); - testing.expect(containerLayout(S1) == TypeInfo.ContainerLayout.Auto); - testing.expect(containerLayout(S2) == TypeInfo.ContainerLayout.Packed); - testing.expect(containerLayout(S3) == TypeInfo.ContainerLayout.Extern); - testing.expect(containerLayout(U1) == TypeInfo.ContainerLayout.Auto); - testing.expect(containerLayout(U2) == TypeInfo.ContainerLayout.Packed); - testing.expect(containerLayout(U3) == TypeInfo.ContainerLayout.Extern); + testing.expect(containerLayout(E1) == .Auto); + testing.expect(containerLayout(E2) == .Packed); + testing.expect(containerLayout(E3) == .Extern); + testing.expect(containerLayout(S1) == .Auto); + testing.expect(containerLayout(S2) == .Packed); + testing.expect(containerLayout(S3) == .Extern); + testing.expect(containerLayout(U1) == .Auto); + testing.expect(containerLayout(U2) == .Packed); + testing.expect(containerLayout(U3) == .Extern); } pub fn declarations(comptime T: type) []TypeInfo.Declaration { return switch (@typeInfo(T)) { - TypeId.Struct => |info| info.decls, - TypeId.Enum => |info| info.decls, - TypeId.Union => |info| info.decls, + .Struct => |info| info.decls, + .Enum => |info| info.decls, + .Union => |info| info.decls, else => @compileError("Expected struct, enum or union type, found '" ++ @typeName(T) ++ "'"), }; } @@ -232,17 +231,17 @@ test "std.meta.declarationInfo" { } pub fn fields(comptime T: type) switch (@typeInfo(T)) { - TypeId.Struct => []TypeInfo.StructField, - TypeId.Union => []TypeInfo.UnionField, - TypeId.ErrorSet => []TypeInfo.Error, - TypeId.Enum => []TypeInfo.EnumField, + .Struct => []TypeInfo.StructField, + .Union => []TypeInfo.UnionField, + .ErrorSet => []TypeInfo.Error, + .Enum => []TypeInfo.EnumField, else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"), } { return switch (@typeInfo(T)) { - TypeId.Struct => |info| info.fields, - TypeId.Union => |info| info.fields, - TypeId.Enum => |info| info.fields, - TypeId.ErrorSet => |errors| errors.?, // must be non global error set + .Struct => |info| info.fields, + .Union => |info| info.fields, + .Enum => |info| info.fields, + .ErrorSet => |errors| errors.?, // must be non global error set else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"), }; } @@ -277,10 +276,10 @@ test "std.meta.fields" { } pub fn fieldInfo(comptime T: type, comptime field_name: []const u8) switch (@typeInfo(T)) { - TypeId.Struct => TypeInfo.StructField, - TypeId.Union => TypeInfo.UnionField, - TypeId.ErrorSet => TypeInfo.Error, - TypeId.Enum => TypeInfo.EnumField, + .Struct => TypeInfo.StructField, + .Union => TypeInfo.UnionField, + .ErrorSet => TypeInfo.Error, + .Enum => TypeInfo.EnumField, else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"), } { inline for (comptime fields(T)) |field| { @@ -318,8 +317,8 @@ test "std.meta.fieldInfo" { pub fn TagType(comptime T: type) type { return switch (@typeInfo(T)) { - TypeId.Enum => |info| info.tag_type, - TypeId.Union => |info| if (info.tag_type) |Tag| Tag else null, + .Enum => |info| info.tag_type, + .Union => |info| if (info.tag_type) |Tag| Tag else null, else => @compileError("expected enum or union type, found '" ++ @typeName(T) ++ "'"), }; } @@ -365,7 +364,7 @@ test "std.meta.activeTag" { ///Given a tagged union type, and an enum, return the type of the union /// field corresponding to the enum tag. pub fn TagPayloadType(comptime U: type, tag: @TagType(U)) type { - testing.expect(trait.is(builtin.TypeId.Union)(U)); + testing.expect(trait.is(.Union)(U)); const info = @typeInfo(U).Union; @@ -387,30 +386,26 @@ test "std.meta.TagPayloadType" { testing.expect(MovedEvent == @TypeOf(e.Moved)); } -///Compares two of any type for equality. Containers are compared on a field-by-field basis, +/// Compares two of any type for equality. Containers are compared on a field-by-field basis, /// where possible. Pointers are not followed. pub fn eql(a: var, b: @TypeOf(a)) bool { const T = @TypeOf(a); - switch (@typeId(T)) { - builtin.TypeId.Struct => { - const info = @typeInfo(T).Struct; - + switch (@typeInfo(T)) { + .Struct => |info| { inline for (info.fields) |field_info| { if (!eql(@field(a, field_info.name), @field(b, field_info.name))) return false; } return true; }, - builtin.TypeId.ErrorUnion => { + .ErrorUnion => { if (a) |a_p| { if (b) |b_p| return eql(a_p, b_p) else |_| return false; } else |a_e| { if (b) |_| return false else |b_e| return a_e == b_e; } }, - builtin.TypeId.Union => { - const info = @typeInfo(T).Union; - + .Union => |info| { if (info.tag_type) |_| { const tag_a = activeTag(a); const tag_b = activeTag(b); @@ -427,23 +422,26 @@ pub fn eql(a: var, b: @TypeOf(a)) bool { @compileError("cannot compare untagged union type " ++ @typeName(T)); }, - builtin.TypeId.Array => { + .Array => { if (a.len != b.len) return false; for (a) |e, i| if (!eql(e, b[i])) return false; return true; }, - builtin.TypeId.Pointer => { - const info = @typeInfo(T).Pointer; - switch (info.size) { - builtin.TypeInfo.Pointer.Size.One, - builtin.TypeInfo.Pointer.Size.Many, - builtin.TypeInfo.Pointer.Size.C, - => return a == b, - builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len, + .Vector => |info| { + var i: usize = 0; + while (i < info.len) : (i += 1) { + if (!eql(a[i], b[i])) return false; } + return true; }, - builtin.TypeId.Optional => { + .Pointer => |info| { + return switch (info.size) { + .One, .Many, .C, => a == b, + .Slice => a.ptr == b.ptr and a.len == b.len, + }; + }, + .Optional => { if (a == null and b == null) return true; if (a == null or b == null) return false; return eql(a.?, b.?); @@ -510,6 +508,13 @@ test "std.meta.eql" { testing.expect(eql(EU.tst(true), EU.tst(true))); testing.expect(eql(EU.tst(false), EU.tst(false))); testing.expect(!eql(EU.tst(false), EU.tst(true))); + + var v1 = @splat(4, @as(u32, 1)); + var v2 = @splat(4, @as(u32, 1)); + var v3 = @splat(4, @as(u32, 2)); + + testing.expect(eql(v1, v2)); + testing.expect(!eql(v1, v3)); } test "intToEnum with error return" { diff --git a/lib/std/meta/trait.zig b/lib/std/meta/trait.zig index d17f2dedaf..b1fd233ff2 100644 --- a/lib/std/meta/trait.zig +++ b/lib/std/meta/trait.zig @@ -7,17 +7,11 @@ const warn = debug.warn; const meta = @import("../meta.zig"); -//This is necessary if we want to return generic functions directly because of how the -// the type erasure works. see: #1375 -fn traitFnWorkaround(comptime T: type) bool { - return false; -} - -pub const TraitFn = @TypeOf(traitFnWorkaround); +pub const TraitFn = fn (type) bool; //////Trait generators -//Need TraitList because compiler can't do varargs at comptime yet +// TODO convert to tuples when #4335 is done pub const TraitList = []const TraitFn; pub fn multiTrait(comptime traits: TraitList) TraitFn { const Closure = struct { @@ -60,8 +54,7 @@ pub fn hasFn(comptime name: []const u8) TraitFn { if (!comptime isContainer(T)) return false; if (!comptime @hasDecl(T, name)) return false; const DeclType = @TypeOf(@field(T, name)); - const decl_type_id = @typeId(DeclType); - return decl_type_id == builtin.TypeId.Fn; + return @typeId(DeclType) == .Fn; } }; return Closure.trait; @@ -80,11 +73,10 @@ test "std.meta.trait.hasFn" { pub fn hasField(comptime name: []const u8) TraitFn { const Closure = struct { pub fn trait(comptime T: type) bool { - const info = @typeInfo(T); - const fields = switch (info) { - builtin.TypeId.Struct => |s| s.fields, - builtin.TypeId.Union => |u| u.fields, - builtin.TypeId.Enum => |e| e.fields, + const fields = switch (@typeInfo(T)) { + .Struct => |s| s.fields, + .Union => |u| u.fields, + .Enum => |e| e.fields, else => return false, }; @@ -120,11 +112,11 @@ pub fn is(comptime id: builtin.TypeId) TraitFn { } test "std.meta.trait.is" { - testing.expect(is(builtin.TypeId.Int)(u8)); - testing.expect(!is(builtin.TypeId.Int)(f32)); - testing.expect(is(builtin.TypeId.Pointer)(*u8)); - testing.expect(is(builtin.TypeId.Void)(void)); - testing.expect(!is(builtin.TypeId.Optional)(anyerror)); + testing.expect(is(.Int)(u8)); + testing.expect(!is(.Int)(f32)); + testing.expect(is(.Pointer)(*u8)); + testing.expect(is(.Void)(void)); + testing.expect(!is(.Optional)(anyerror)); } pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn { @@ -138,9 +130,9 @@ pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn { } test "std.meta.trait.isPtrTo" { - testing.expect(!isPtrTo(builtin.TypeId.Struct)(struct {})); - testing.expect(isPtrTo(builtin.TypeId.Struct)(*struct {})); - testing.expect(!isPtrTo(builtin.TypeId.Struct)(**struct {})); + testing.expect(!isPtrTo(.Struct)(struct {})); + testing.expect(isPtrTo(.Struct)(*struct {})); + testing.expect(!isPtrTo(.Struct)(**struct {})); } ///////////Strait trait Fns @@ -149,12 +141,10 @@ test "std.meta.trait.isPtrTo" { // Somewhat limited since we can't apply this logic to normal variables, fields, or // Fns yet. Should be isExternType? pub fn isExtern(comptime T: type) bool { - const Extern = builtin.TypeInfo.ContainerLayout.Extern; - const info = @typeInfo(T); - return switch (info) { - builtin.TypeId.Struct => |s| s.layout == Extern, - builtin.TypeId.Union => |u| u.layout == Extern, - builtin.TypeId.Enum => |e| e.layout == Extern, + return switch (@typeInfo(T)) { + .Struct => |s| s.layout == .Extern, + .Union => |u| u.layout == .Extern, + .Enum => |e| e.layout == .Extern, else => false, }; } @@ -169,12 +159,10 @@ test "std.meta.trait.isExtern" { } pub fn isPacked(comptime T: type) bool { - const Packed = builtin.TypeInfo.ContainerLayout.Packed; - const info = @typeInfo(T); - return switch (info) { - builtin.TypeId.Struct => |s| s.layout == Packed, - builtin.TypeId.Union => |u| u.layout == Packed, - builtin.TypeId.Enum => |e| e.layout == Packed, + return switch (@typeInfo(T)) { + .Struct => |s| s.layout == .Packed, + .Union => |u| u.layout == .Packed, + .Enum => |e| e.layout == .Packed, else => false, }; } @@ -189,8 +177,8 @@ test "std.meta.trait.isPacked" { } pub fn isUnsignedInt(comptime T: type) bool { - return switch (@typeId(T)) { - builtin.TypeId.Int => !@typeInfo(T).Int.is_signed, + return switch (@typeInfo(T)) { + .Int => |i| !i.is_signed, else => false, }; } @@ -203,9 +191,9 @@ test "isUnsignedInt" { } pub fn isSignedInt(comptime T: type) bool { - return switch (@typeId(T)) { - builtin.TypeId.ComptimeInt => true, - builtin.TypeId.Int => @typeInfo(T).Int.is_signed, + return switch (@typeInfo(T)) { + .ComptimeInt => true, + .Int => |i| i.is_signed, else => false, }; } @@ -218,9 +206,8 @@ test "isSignedInt" { } pub fn isSingleItemPtr(comptime T: type) bool { - if (comptime is(builtin.TypeId.Pointer)(T)) { - const info = @typeInfo(T); - return info.Pointer.size == builtin.TypeInfo.Pointer.Size.One; + if (comptime is(.Pointer)(T)) { + return @typeInfo(T).Pointer.size == .One; } return false; } @@ -233,9 +220,8 @@ test "std.meta.trait.isSingleItemPtr" { } pub fn isManyItemPtr(comptime T: type) bool { - if (comptime is(builtin.TypeId.Pointer)(T)) { - const info = @typeInfo(T); - return info.Pointer.size == builtin.TypeInfo.Pointer.Size.Many; + if (comptime is(.Pointer)(T)) { + return @typeInfo(T).Pointer.size == .Many; } return false; } @@ -249,9 +235,8 @@ test "std.meta.trait.isManyItemPtr" { } pub fn isSlice(comptime T: type) bool { - if (comptime is(builtin.TypeId.Pointer)(T)) { - const info = @typeInfo(T); - return info.Pointer.size == builtin.TypeInfo.Pointer.Size.Slice; + if (comptime is(.Pointer)(T)) { + return @typeInfo(T).Pointer.size == .Slice; } return false; } @@ -264,15 +249,13 @@ test "std.meta.trait.isSlice" { } pub fn isIndexable(comptime T: type) bool { - if (comptime is(builtin.TypeId.Pointer)(T)) { - const info = @typeInfo(T); - if (info.Pointer.size == builtin.TypeInfo.Pointer.Size.One) { - if (comptime is(builtin.TypeId.Array)(meta.Child(T))) return true; - return false; + if (comptime is(.Pointer)(T)) { + if (@typeInfo(T).Pointer.size == .One) { + return (comptime is(.Array)(meta.Child(T))); } return true; } - return comptime is(builtin.TypeId.Array)(T); + return comptime is(.Array)(T); } test "std.meta.trait.isIndexable" { @@ -287,7 +270,7 @@ test "std.meta.trait.isIndexable" { pub fn isNumber(comptime T: type) bool { return switch (@typeId(T)) { - builtin.TypeId.Int, builtin.TypeId.Float, builtin.TypeId.ComptimeInt, builtin.TypeId.ComptimeFloat => true, + .Int, .Float, .ComptimeInt, .ComptimeFloat => true, else => false, }; } @@ -307,9 +290,8 @@ test "std.meta.trait.isNumber" { } pub fn isConstPtr(comptime T: type) bool { - if (!comptime is(builtin.TypeId.Pointer)(T)) return false; - const info = @typeInfo(T); - return info.Pointer.is_const; + if (!comptime is(.Pointer)(T)) return false; + return @typeInfo(T).Pointer.is_const; } test "std.meta.trait.isConstPtr" { @@ -322,11 +304,8 @@ test "std.meta.trait.isConstPtr" { } pub fn isContainer(comptime T: type) bool { - const info = @typeInfo(T); - return switch (info) { - builtin.TypeId.Struct => true, - builtin.TypeId.Union => true, - builtin.TypeId.Enum => true, + return switch (@typeId(T)) { + .Struct, .Union, .Enum => true, else => false, }; } diff --git a/lib/std/net/test.zig b/lib/std/net/test.zig index 703a804bfb..45d8b1cffd 100644 --- a/lib/std/net/test.zig +++ b/lib/std/net/test.zig @@ -67,10 +67,8 @@ test "resolve DNS" { // DNS resolution not implemented on Windows yet. return error.SkipZigTest; } - var buf: [1000 * 10]u8 = undefined; - const a = &std.heap.FixedBufferAllocator.init(&buf).allocator; - const address_list = net.getAddressList(a, "example.com", 80) catch |err| switch (err) { + const address_list = net.getAddressList(testing.allocator, "example.com", 80) catch |err| switch (err) { // The tests are required to work even when there is no Internet connection, // so some of these errors we must accept and skip the test. error.UnknownHostName => return error.SkipZigTest, diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index f33b5d5261..9b967955ec 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -95,8 +95,6 @@ test "cpu count" { } test "AtomicFile" { - var buffer: [1024]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(buffer[0..]).allocator; const test_out_file = "tmp_atomic_file_test_dest.txt"; const test_content = \\ hello! @@ -108,7 +106,8 @@ test "AtomicFile" { try af.file.write(test_content); try af.finish(); } - const content = try io.readFileAlloc(allocator, test_out_file); + const content = try io.readFileAlloc(testing.allocator, test_out_file); + defer testing.allocator.free(content); expect(mem.eql(u8, content, test_content)); try fs.cwd().deleteFile(test_out_file); @@ -276,8 +275,11 @@ test "mmap" { testing.expectEqual(@as(usize, 1234), data.len); // By definition the data returned by mmap is zero-filled - std.mem.set(u8, data[0 .. data.len - 1], 0x55); - testing.expect(mem.indexOfScalar(u8, data, 0).? == 1234 - 1); + testing.expect(mem.eql(u8, data, &[_]u8{0x00} ** 1234)); + + // Make sure the memory is writeable as requested + std.mem.set(u8, data, 0x55); + testing.expect(mem.eql(u8, data, &[_]u8{0x55} ** 1234)); } const test_out_file = "os_tmp_test"; @@ -300,10 +302,7 @@ test "mmap" { // Map the whole file { - const file = try fs.cwd().createFile(test_out_file, .{ - .read = true, - .truncate = false, - }); + const file = try fs.cwd().openFile(test_out_file, .{}); defer file.close(); const data = try os.mmap( @@ -327,15 +326,12 @@ test "mmap" { // Map the upper half of the file { - const file = try fs.cwd().createFile(test_out_file, .{ - .read = true, - .truncate = false, - }); + const file = try fs.cwd().openFile(test_out_file, .{}); defer file.close(); const data = try os.mmap( null, - alloc_size, + alloc_size / 2, os.PROT_READ, os.MAP_PRIVATE, file.handle, diff --git a/lib/std/process.zig b/lib/std/process.zig index ca5ca3a3bb..0178f6fa91 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -27,10 +27,8 @@ pub fn getCwdAlloc(allocator: *Allocator) ![]u8 { } test "getCwdAlloc" { - // at least call it so it gets compiled - var buf: [1000]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(&buf).allocator; - _ = getCwdAlloc(allocator) catch undefined; + const cwd = try getCwdAlloc(testing.allocator); + testing.allocator.free(cwd); } /// Caller must free result when done. diff --git a/lib/std/sort.zig b/lib/std/sort.zig index df9702b325..938c5e98f1 100644 --- a/lib/std/sort.zig +++ b/lib/std/sort.zig @@ -1220,16 +1220,16 @@ test "sort fuzz testing" { const test_case_count = 10; var i: usize = 0; while (i < test_case_count) : (i += 1) { - fuzzTest(&prng.random); + try fuzzTest(&prng.random); } } var fixed_buffer_mem: [100 * 1024]u8 = undefined; -fn fuzzTest(rng: *std.rand.Random) void { +fn fuzzTest(rng: *std.rand.Random) !void { const array_size = rng.range(usize, 0, 1000); - var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]); - var array = fixed_allocator.allocator.alloc(IdAndValue, array_size) catch unreachable; + var array = try testing.allocator.alloc(IdAndValue, array_size); + defer testing.allocator.free(array); // populate with random data for (array) |*item, index| { item.id = index; diff --git a/lib/std/special/compiler_rt.zig b/lib/std/special/compiler_rt.zig index f5e83b5278..8d49fdbd2a 100644 --- a/lib/std/special/compiler_rt.zig +++ b/lib/std/special/compiler_rt.zig @@ -149,7 +149,7 @@ comptime { @export(@import("compiler_rt/clzsi2.zig").__clzsi2, .{ .name = "__clzsi2", .linkage = linkage }); - if (builtin.arch.isARM() and !is_test) { + if ((builtin.arch.isARM() or builtin.arch.isThumb()) and !is_test) { @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = linkage }); @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = linkage }); @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = linkage }); diff --git a/lib/std/target/riscv.zig b/lib/std/target/riscv.zig index a02f668b78..efb71a35e8 100644 --- a/lib/std/target/riscv.zig +++ b/lib/std/target/riscv.zig @@ -270,7 +270,6 @@ pub const cpu = struct { .d, .f, .m, - .relax, }), }; @@ -284,7 +283,6 @@ pub const cpu = struct { .d, .f, .m, - .relax, }), }; diff --git a/lib/std/testing.zig b/lib/std/testing.zig index f8247b5a9d..348f651a88 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -12,7 +12,7 @@ pub var allocator_instance = LeakCountAllocator.init(&base_allocator_instance.al pub const failing_allocator = &FailingAllocator.init(&base_allocator_instance.allocator, 0).allocator; pub var base_allocator_instance = std.heap.ThreadSafeFixedBufferAllocator.init(allocator_mem[0..]); -var allocator_mem: [512 * 1024]u8 = undefined; +var allocator_mem: [1024 * 1024]u8 = undefined; /// This function is intended to be used only in tests. It prints diagnostics to stderr /// and then aborts when actual_error_union is not expected_error. @@ -56,7 +56,6 @@ pub fn expectEqual(expected: var, actual: @TypeOf(expected)) void { .EnumLiteral, .Enum, .Fn, - .Vector, .ErrorSet, => { if (actual != expected) { @@ -88,6 +87,15 @@ pub fn expectEqual(expected: var, actual: @TypeOf(expected)) void { .Array => |array| expectEqualSlices(array.child, &expected, &actual), + .Vector => |vectorType| { + var i: usize = 0; + while (i < vectorType.len) : (i += 1) { + if (!std.meta.eql(expected[i], actual[i])) { + std.debug.panic("index {} incorrect. expected {}, found {}", .{ i, expected[i], actual[i] }); + } + } + }, + .Struct => |structType| { inline for (structType.fields) |field| { expectEqual(@field(expected, field.name), @field(actual, field.name)); @@ -202,3 +210,10 @@ test "expectEqual nested array" { expectEqual(a, b); } + +test "expectEqual vector" { + var a = @splat(4, @as(u32, 4)); + var b = @splat(4, @as(u32, 4)); + + expectEqual(a, b); +} diff --git a/lib/std/unicode.zig b/lib/std/unicode.zig index da0dbc3cb2..ed24f83c33 100644 --- a/lib/std/unicode.zig +++ b/lib/std/unicode.zig @@ -617,16 +617,14 @@ test "utf8ToUtf16Le" { test "utf8ToUtf16LeWithNull" { { - var bytes: [128]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator; - const utf16 = try utf8ToUtf16LeWithNull(allocator, "𐐷"); + const utf16 = try utf8ToUtf16LeWithNull(testing.allocator, "𐐷"); + defer testing.allocator.free(utf16); testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc", @sliceToBytes(utf16[0..])); testing.expect(utf16[2] == 0); } { - var bytes: [128]u8 = undefined; - const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator; - const utf16 = try utf8ToUtf16LeWithNull(allocator, "\u{10FFFF}"); + const utf16 = try utf8ToUtf16LeWithNull(testing.allocator, "\u{10FFFF}"); + defer testing.allocator.free(utf16); testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf", @sliceToBytes(utf16[0..])); testing.expect(utf16[2] == 0); } diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index c31ef9c64b..03bb8d4222 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -2886,8 +2886,7 @@ fn testCanonical(source: []const u8) !void { } fn testError(source: []const u8) !void { - var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]); - const tree = try std.zig.parse(&fixed_allocator.allocator, source); + const tree = try std.zig.parse(std.testing.allocator, source); defer tree.deinit(); std.testing.expect(tree.errors.len != 0); diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 01df8a3b1f..df7f9edbfd 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -5123,6 +5123,8 @@ fn parseCNumLit(c: *Context, tok: *CToken, source: []const u8, source_loc: ZigCl cast_node.rparen_token = try appendToken(c, .RParen, ")"); return &cast_node.base; } else if (tok.id == .FloatLiteral) { + if (lit_bytes[0] == '.') + lit_bytes = try std.fmt.allocPrint(c.a(), "0{}", .{lit_bytes}); if (tok.id.FloatLiteral == .None) { return transCreateNodeFloat(c, lit_bytes); } @@ -5340,12 +5342,27 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, .LParen => { const inner_node = try parseCExpr(c, it, source, source_loc, scope); - if (it.peek().?.id == .RParen) { - _ = it.next(); - if (it.peek().?.id != .LParen) { - return inner_node; - } - _ = it.next(); + if (it.next().?.id != .RParen) { + const first_tok = it.list.at(0); + try failDecl( + c, + source_loc, + source[first_tok.start..first_tok.end], + "unable to translate C expr: expected ')'' here", + .{}, + ); + return error.ParseError; + } + var saw_l_paren = false; + switch (it.peek().?.id) { + // (type)(to_cast) + .LParen => { + saw_l_paren = true; + _ = it.next(); + }, + // (type)identifier + .Identifier => {}, + else => return inner_node, } // hack to get zig fmt to render a comma in builtin calls @@ -5353,7 +5370,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, const node_to_cast = try parseCExpr(c, it, source, source_loc, scope); - if (it.next().?.id != .RParen) { + if (saw_l_paren and it.next().?.id != .RParen) { const first_tok = it.list.at(0); try failDecl( c, @@ -5494,7 +5511,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, // hack to get zig fmt to render a comma in builtin calls _ = try appendToken(c, .Comma, ","); - const ptr_kind = blk:{ + const ptr_kind = blk: { // * token _ = it.prev(); // last token of `node` diff --git a/src/all_types.hpp b/src/all_types.hpp index fb6bc02e37..cc17fc77d5 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1999,6 +1999,9 @@ struct CFile { // When adding fields, check if they should be added to the hash computation in build_with_cache struct CodeGen { + // arena allocator destroyed just prior to codegen emit + heap::ArenaAllocator *pass1_arena; + //////////////////////////// Runtime State LLVMModuleRef module; ZigList errors; @@ -2279,7 +2282,6 @@ struct ZigVar { Scope *parent_scope; Scope *child_scope; LLVMValueRef param_value_ref; - IrExecutableSrc *owner_exec; Buf *section_name; diff --git a/src/analyze.cpp b/src/analyze.cpp index 443cd95784..fc1a805d82 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -80,7 +80,7 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, } ZigType *new_type_table_entry(ZigTypeId id) { - ZigType *entry = allocate(1); + ZigType *entry = heap::c_allocator.create(); entry->id = id; return entry; } @@ -140,7 +140,7 @@ void init_scope(CodeGen *g, Scope *dest, ScopeId id, AstNode *source_node, Scope static ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ZigType *container_type, ZigType *import, Buf *bare_name) { - ScopeDecls *scope = allocate(1); + ScopeDecls *scope = heap::c_allocator.create(); init_scope(g, &scope->base, ScopeIdDecls, node, parent); scope->decl_table.init(4); scope->container_type = container_type; @@ -151,7 +151,7 @@ static ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ScopeBlock *create_block_scope(CodeGen *g, AstNode *node, Scope *parent) { assert(node->type == NodeTypeBlock); - ScopeBlock *scope = allocate(1); + ScopeBlock *scope = heap::c_allocator.create(); init_scope(g, &scope->base, ScopeIdBlock, node, parent); scope->name = node->data.block.name; return scope; @@ -159,20 +159,20 @@ ScopeBlock *create_block_scope(CodeGen *g, AstNode *node, Scope *parent) { ScopeDefer *create_defer_scope(CodeGen *g, AstNode *node, Scope *parent) { assert(node->type == NodeTypeDefer); - ScopeDefer *scope = allocate(1); + ScopeDefer *scope = heap::c_allocator.create(); init_scope(g, &scope->base, ScopeIdDefer, node, parent); return scope; } ScopeDeferExpr *create_defer_expr_scope(CodeGen *g, AstNode *node, Scope *parent) { assert(node->type == NodeTypeDefer); - ScopeDeferExpr *scope = allocate(1); + ScopeDeferExpr *scope = heap::c_allocator.create(); init_scope(g, &scope->base, ScopeIdDeferExpr, node, parent); return scope; } Scope *create_var_scope(CodeGen *g, AstNode *node, Scope *parent, ZigVar *var) { - ScopeVarDecl *scope = allocate(1); + ScopeVarDecl *scope = heap::c_allocator.create(); init_scope(g, &scope->base, ScopeIdVarDecl, node, parent); scope->var = var; return &scope->base; @@ -180,14 +180,14 @@ Scope *create_var_scope(CodeGen *g, AstNode *node, Scope *parent, ZigVar *var) { ScopeCImport *create_cimport_scope(CodeGen *g, AstNode *node, Scope *parent) { assert(node->type == NodeTypeFnCallExpr); - ScopeCImport *scope = allocate(1); + ScopeCImport *scope = heap::c_allocator.create(); init_scope(g, &scope->base, ScopeIdCImport, node, parent); buf_resize(&scope->buf, 0); return scope; } ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent) { - ScopeLoop *scope = allocate(1); + ScopeLoop *scope = heap::c_allocator.create(); init_scope(g, &scope->base, ScopeIdLoop, node, parent); if (node->type == NodeTypeWhileExpr) { scope->name = node->data.while_expr.name; @@ -200,7 +200,7 @@ ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent) { } Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc *is_comptime) { - ScopeRuntime *scope = allocate(1); + ScopeRuntime *scope = heap::c_allocator.create(); scope->is_comptime = is_comptime; init_scope(g, &scope->base, ScopeIdRuntime, node, parent); return &scope->base; @@ -208,37 +208,37 @@ Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent) { assert(node->type == NodeTypeSuspend); - ScopeSuspend *scope = allocate(1); + ScopeSuspend *scope = heap::c_allocator.create(); init_scope(g, &scope->base, ScopeIdSuspend, node, parent); return scope; } ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry) { - ScopeFnDef *scope = allocate(1); + ScopeFnDef *scope = heap::c_allocator.create(); init_scope(g, &scope->base, ScopeIdFnDef, node, parent); scope->fn_entry = fn_entry; return scope; } Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent) { - ScopeCompTime *scope = allocate(1); + ScopeCompTime *scope = heap::c_allocator.create(); init_scope(g, &scope->base, ScopeIdCompTime, node, parent); return &scope->base; } Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent) { - ScopeTypeOf *scope = allocate(1); + ScopeTypeOf *scope = heap::c_allocator.create(); init_scope(g, &scope->base, ScopeIdTypeOf, node, parent); return &scope->base; } ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent) { - ScopeExpr *scope = allocate(1); + ScopeExpr *scope = heap::c_allocator.create(); init_scope(g, &scope->base, ScopeIdExpr, node, parent); ScopeExpr *parent_expr = find_expr_scope(parent); if (parent_expr != nullptr) { size_t new_len = parent_expr->children_len + 1; - parent_expr->children_ptr = reallocate_nonzero( + parent_expr->children_ptr = heap::c_allocator.reallocate_nonzero( parent_expr->children_ptr, parent_expr->children_len, new_len); parent_expr->children_ptr[parent_expr->children_len] = scope; parent_expr->children_len = new_len; @@ -1104,8 +1104,8 @@ ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType * { Error err; - ZigValue *result = create_const_vals(1); - ZigValue *result_ptr = create_const_vals(1); + ZigValue *result = g->pass1_arena->create(); + ZigValue *result_ptr = g->pass1_arena->create(); result->special = ConstValSpecialUndef; result->type = (type_entry == nullptr) ? g->builtin_types.entry_var : type_entry; result_ptr->special = ConstValSpecialStatic; @@ -1122,7 +1122,6 @@ ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType * { return g->invalid_inst_gen->value; } - destroy(result_ptr, "ZigValue"); return result; } @@ -1507,7 +1506,7 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, CallingConventio fn_type_id->cc = cc; fn_type_id->param_count = fn_proto->params.length; - fn_type_id->param_info = allocate(param_count_alloc); + fn_type_id->param_info = heap::c_allocator.allocate(param_count_alloc); fn_type_id->next_param_index = 0; fn_type_id->is_var_args = fn_proto->is_var_args; } @@ -2171,7 +2170,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked); struct_type->data.structure.resolve_loop_flag_other = true; - uint32_t *host_int_bytes = packed ? allocate(struct_type->data.structure.gen_field_count) : nullptr; + uint32_t *host_int_bytes = packed ? heap::c_allocator.allocate(struct_type->data.structure.gen_field_count) : nullptr; size_t packed_bits_offset = 0; size_t next_offset = 0; @@ -2657,7 +2656,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { } enum_type->data.enumeration.src_field_count = field_count; - enum_type->data.enumeration.fields = allocate(field_count); + enum_type->data.enumeration.fields = heap::c_allocator.allocate(field_count); enum_type->data.enumeration.fields_by_name.init(field_count); HashMap occupied_tag_values = {}; @@ -3034,7 +3033,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { return ErrorSemanticAnalyzeFail; } union_type->data.unionation.src_field_count = field_count; - union_type->data.unionation.fields = allocate(field_count); + union_type->data.unionation.fields = heap::c_allocator.allocate(field_count); union_type->data.unionation.fields_by_name.init(field_count); Scope *scope = &union_type->data.unionation.decls_scope->base; @@ -3053,7 +3052,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { if (create_enum_type) { occupied_tag_values.init(field_count); - di_enumerators = allocate(field_count); + di_enumerators = heap::c_allocator.allocate(field_count); ZigType *tag_int_type; if (enum_type_node != nullptr) { @@ -3086,7 +3085,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { tag_type->data.enumeration.decl_node = decl_node; tag_type->data.enumeration.layout = ContainerLayoutAuto; tag_type->data.enumeration.src_field_count = field_count; - tag_type->data.enumeration.fields = allocate(field_count); + tag_type->data.enumeration.fields = heap::c_allocator.allocate(field_count); tag_type->data.enumeration.fields_by_name.init(field_count); tag_type->data.enumeration.decls_scope = union_type->data.unionation.decls_scope; } else if (enum_type_node != nullptr) { @@ -3106,7 +3105,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { return err; } tag_type = enum_type; - covered_enum_fields = allocate(enum_type->data.enumeration.src_field_count); + covered_enum_fields = heap::c_allocator.allocate(enum_type->data.enumeration.src_field_count); } else { tag_type = nullptr; } @@ -3244,7 +3243,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { } covered_enum_fields[union_field->enum_field->decl_index] = true; } else { - union_field->enum_field = allocate(1); + union_field->enum_field = heap::c_allocator.create(); union_field->enum_field->name = field_name; union_field->enum_field->decl_index = i; bigint_init_unsigned(&union_field->enum_field->value, i); @@ -3366,8 +3365,8 @@ static void get_fully_qualified_decl_name(CodeGen *g, Buf *buf, Tld *tld, bool i } ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value) { - ZigFn *fn_entry = allocate(1, "ZigFn"); - fn_entry->ir_executable = allocate(1, "IrExecutableSrc"); + ZigFn *fn_entry = heap::c_allocator.create(); + fn_entry->ir_executable = heap::c_allocator.create(); fn_entry->prealloc_backward_branch_quota = default_backward_branch_quota; @@ -3642,7 +3641,7 @@ static void preview_test_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope return; } - TldFn *tld_fn = allocate(1); + TldFn *tld_fn = heap::c_allocator.create(); init_tld(&tld_fn->base, TldIdFn, test_name, VisibModPrivate, node, &decls_scope->base); g->resolve_queue.append(&tld_fn->base); } @@ -3650,7 +3649,7 @@ static void preview_test_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope static void preview_comptime_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) { assert(node->type == NodeTypeCompTime); - TldCompTime *tld_comptime = allocate(1); + TldCompTime *tld_comptime = heap::c_allocator.create(); init_tld(&tld_comptime->base, TldIdCompTime, nullptr, VisibModPrivate, node, &decls_scope->base); g->resolve_queue.append(&tld_comptime->base); } @@ -3673,7 +3672,7 @@ void update_compile_var(CodeGen *g, Buf *name, ZigValue *value) { resolve_top_level_decl(g, tld, tld->source_node, false); assert(tld->id == TldIdVar && tld->resolution == TldResolutionOk); TldVar *tld_var = (TldVar *)tld; - copy_const_val(tld_var->var->const_value, value); + copy_const_val(g, tld_var->var->const_value, value); tld_var->var->var_type = value->type; tld_var->var->align_bytes = get_abi_alignment(g, value->type); } @@ -3693,7 +3692,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { { Buf *name = node->data.variable_declaration.symbol; VisibMod visib_mod = node->data.variable_declaration.visib_mod; - TldVar *tld_var = allocate(1); + TldVar *tld_var = heap::c_allocator.create(); init_tld(&tld_var->base, TldIdVar, name, visib_mod, node, &decls_scope->base); tld_var->extern_lib_name = node->data.variable_declaration.lib_name; add_top_level_decl(g, decls_scope, &tld_var->base); @@ -3709,7 +3708,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { } VisibMod visib_mod = node->data.fn_proto.visib_mod; - TldFn *tld_fn = allocate(1); + TldFn *tld_fn = heap::c_allocator.create(); init_tld(&tld_fn->base, TldIdFn, fn_name, visib_mod, node, &decls_scope->base); tld_fn->extern_lib_name = node->data.fn_proto.lib_name; add_top_level_decl(g, decls_scope, &tld_fn->base); @@ -3718,7 +3717,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { } case NodeTypeUsingNamespace: { VisibMod visib_mod = node->data.using_namespace.visib_mod; - TldUsingNamespace *tld_using_namespace = allocate(1); + TldUsingNamespace *tld_using_namespace = heap::c_allocator.create(); init_tld(&tld_using_namespace->base, TldIdUsingNamespace, nullptr, visib_mod, node, &decls_scope->base); add_top_level_decl(g, decls_scope, &tld_using_namespace->base); decls_scope->use_decls.append(tld_using_namespace); @@ -3845,7 +3844,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf assert(const_value != nullptr); assert(var_type != nullptr); - ZigVar *variable_entry = allocate(1); + ZigVar *variable_entry = heap::c_allocator.create(); variable_entry->const_value = const_value; variable_entry->var_type = var_type; variable_entry->parent_scope = parent_scope; @@ -3984,7 +3983,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) { ZigType *type = explicit_type ? explicit_type : implicit_type; assert(type != nullptr); // should have been caught by the parser - ZigValue *init_val = (init_value != nullptr) ? init_value : create_const_runtime(type); + ZigValue *init_val = (init_value != nullptr) ? init_value : create_const_runtime(g, type); tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol, is_const, init_val, &tld_var->base, type); @@ -4491,7 +4490,7 @@ static Error define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) { } ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope, - param_name, true, create_const_runtime(param_type), nullptr, param_type); + param_name, true, create_const_runtime(g, param_type), nullptr, param_type); var->src_arg_index = i; fn_table_entry->child_scope = var->child_scope; var->shadowable = var->shadowable || is_var_args; @@ -4786,7 +4785,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) { } else { return_err_set_type->data.error_set.err_count = inferred_err_set_type->data.error_set.err_count; if (inferred_err_set_type->data.error_set.err_count > 0) { - return_err_set_type->data.error_set.errors = allocate(inferred_err_set_type->data.error_set.err_count); + return_err_set_type->data.error_set.errors = heap::c_allocator.allocate(inferred_err_set_type->data.error_set.err_count); for (uint32_t i = 0; i < inferred_err_set_type->data.error_set.err_count; i += 1) { return_err_set_type->data.error_set.errors[i] = inferred_err_set_type->data.error_set.errors[i]; } @@ -4919,7 +4918,7 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu Buf *bare_name = buf_alloc(); os_path_extname(src_basename, bare_name, nullptr); - RootStruct *root_struct = allocate(1); + RootStruct *root_struct = heap::c_allocator.create(); root_struct->package = package; root_struct->source_code = source_code; root_struct->line_offsets = tokenization.line_offsets; @@ -4946,7 +4945,7 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu scan_decls(g, import_entry->data.structure.decls_scope, top_level_decl); } - TldContainer *tld_container = allocate(1); + TldContainer *tld_container = heap::c_allocator.create(); init_tld(&tld_container->base, TldIdContainer, namespace_name, VisibModPub, root_node, nullptr); tld_container->type_entry = import_entry; tld_container->decls_scope = import_entry->data.structure.decls_scope; @@ -5694,14 +5693,14 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) { if (entry != nullptr) { return entry->value; } - ZigValue *result = create_const_vals(1); + ZigValue *result = g->pass1_arena->create(); result->type = type_entry; result->special = ConstValSpecialStatic; if (result->type->id == ZigTypeIdStruct) { // The fields array cannot be left unpopulated const ZigType *struct_type = result->type; const size_t field_count = struct_type->data.structure.src_field_count; - result->data.x_struct.fields = alloc_const_vals_ptrs(field_count); + result->data.x_struct.fields = alloc_const_vals_ptrs(g, field_count); for (size_t i = 0; i < field_count; i += 1) { TypeStructField *field = struct_type->data.structure.fields[i]; ZigType *field_type = resolve_struct_field_type(g, field); @@ -5786,7 +5785,7 @@ void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str) { } // first we build the underlying array - ZigValue *array_val = create_const_vals(1); + ZigValue *array_val = g->pass1_arena->create(); array_val->special = ConstValSpecialStatic; array_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str), g->intern.for_zero_byte()); array_val->data.x_array.special = ConstArraySpecialBuf; @@ -5803,7 +5802,7 @@ void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str) { } ZigValue *create_const_str_lit(CodeGen *g, Buf *str) { - ZigValue *const_val = create_const_vals(1); + ZigValue *const_val = g->pass1_arena->create(); init_const_str_lit(g, const_val, str); return const_val; } @@ -5814,8 +5813,8 @@ void init_const_bigint(ZigValue *const_val, ZigType *type, const BigInt *bigint) bigint_init_bigint(&const_val->data.x_bigint, bigint); } -ZigValue *create_const_bigint(ZigType *type, const BigInt *bigint) { - ZigValue *const_val = create_const_vals(1); +ZigValue *create_const_bigint(CodeGen *g, ZigType *type, const BigInt *bigint) { + ZigValue *const_val = g->pass1_arena->create(); init_const_bigint(const_val, type, bigint); return const_val; } @@ -5828,8 +5827,8 @@ void init_const_unsigned_negative(ZigValue *const_val, ZigType *type, uint64_t x const_val->data.x_bigint.is_negative = negative; } -ZigValue *create_const_unsigned_negative(ZigType *type, uint64_t x, bool negative) { - ZigValue *const_val = create_const_vals(1); +ZigValue *create_const_unsigned_negative(CodeGen *g, ZigType *type, uint64_t x, bool negative) { + ZigValue *const_val = g->pass1_arena->create(); init_const_unsigned_negative(const_val, type, x, negative); return const_val; } @@ -5839,7 +5838,7 @@ void init_const_usize(CodeGen *g, ZigValue *const_val, uint64_t x) { } ZigValue *create_const_usize(CodeGen *g, uint64_t x) { - return create_const_unsigned_negative(g->builtin_types.entry_usize, x, false); + return create_const_unsigned_negative(g, g->builtin_types.entry_usize, x, false); } void init_const_signed(ZigValue *const_val, ZigType *type, int64_t x) { @@ -5848,8 +5847,8 @@ void init_const_signed(ZigValue *const_val, ZigType *type, int64_t x) { bigint_init_signed(&const_val->data.x_bigint, x); } -ZigValue *create_const_signed(ZigType *type, int64_t x) { - ZigValue *const_val = create_const_vals(1); +ZigValue *create_const_signed(CodeGen *g, ZigType *type, int64_t x) { + ZigValue *const_val = g->pass1_arena->create(); init_const_signed(const_val, type, x); return const_val; } @@ -5860,8 +5859,8 @@ void init_const_null(ZigValue *const_val, ZigType *type) { const_val->data.x_optional = nullptr; } -ZigValue *create_const_null(ZigType *type) { - ZigValue *const_val = create_const_vals(1); +ZigValue *create_const_null(CodeGen *g, ZigType *type) { + ZigValue *const_val = g->pass1_arena->create(); init_const_null(const_val, type); return const_val; } @@ -5893,8 +5892,8 @@ void init_const_float(ZigValue *const_val, ZigType *type, double value) { } } -ZigValue *create_const_float(ZigType *type, double value) { - ZigValue *const_val = create_const_vals(1); +ZigValue *create_const_float(CodeGen *g, ZigType *type, double value) { + ZigValue *const_val = g->pass1_arena->create(); init_const_float(const_val, type, value); return const_val; } @@ -5905,8 +5904,8 @@ void init_const_enum(ZigValue *const_val, ZigType *type, const BigInt *tag) { bigint_init_bigint(&const_val->data.x_enum_tag, tag); } -ZigValue *create_const_enum(ZigType *type, const BigInt *tag) { - ZigValue *const_val = create_const_vals(1); +ZigValue *create_const_enum(CodeGen *g, ZigType *type, const BigInt *tag) { + ZigValue *const_val = g->pass1_arena->create(); init_const_enum(const_val, type, tag); return const_val; } @@ -5919,7 +5918,7 @@ void init_const_bool(CodeGen *g, ZigValue *const_val, bool value) { } ZigValue *create_const_bool(CodeGen *g, bool value) { - ZigValue *const_val = create_const_vals(1); + ZigValue *const_val = g->pass1_arena->create(); init_const_bool(g, const_val, value); return const_val; } @@ -5929,8 +5928,8 @@ void init_const_runtime(ZigValue *const_val, ZigType *type) { const_val->type = type; } -ZigValue *create_const_runtime(ZigType *type) { - ZigValue *const_val = create_const_vals(1); +ZigValue *create_const_runtime(CodeGen *g, ZigType *type) { + ZigValue *const_val = g->pass1_arena->create(); init_const_runtime(const_val, type); return const_val; } @@ -5942,7 +5941,7 @@ void init_const_type(CodeGen *g, ZigValue *const_val, ZigType *type_value) { } ZigValue *create_const_type(CodeGen *g, ZigType *type_value) { - ZigValue *const_val = create_const_vals(1); + ZigValue *const_val = g->pass1_arena->create(); init_const_type(g, const_val, type_value); return const_val; } @@ -5957,7 +5956,7 @@ void init_const_slice(CodeGen *g, ZigValue *const_val, ZigValue *array_val, const_val->special = ConstValSpecialStatic; const_val->type = get_slice_type(g, ptr_type); - const_val->data.x_struct.fields = alloc_const_vals_ptrs(2); + const_val->data.x_struct.fields = alloc_const_vals_ptrs(g, 2); init_const_ptr_array(g, const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const, PtrLenUnknown); @@ -5965,7 +5964,7 @@ void init_const_slice(CodeGen *g, ZigValue *const_val, ZigValue *array_val, } ZigValue *create_const_slice(CodeGen *g, ZigValue *array_val, size_t start, size_t len, bool is_const) { - ZigValue *const_val = create_const_vals(1); + ZigValue *const_val = g->pass1_arena->create(); init_const_slice(g, const_val, array_val, start, len, is_const); return const_val; } @@ -5987,7 +5986,7 @@ void init_const_ptr_array(CodeGen *g, ZigValue *const_val, ZigValue *array_val, ZigValue *create_const_ptr_array(CodeGen *g, ZigValue *array_val, size_t elem_index, bool is_const, PtrLen ptr_len) { - ZigValue *const_val = create_const_vals(1); + ZigValue *const_val = g->pass1_arena->create(); init_const_ptr_array(g, const_val, array_val, elem_index, is_const, ptr_len); return const_val; } @@ -6000,7 +5999,7 @@ void init_const_ptr_ref(CodeGen *g, ZigValue *const_val, ZigValue *pointee_val, } ZigValue *create_const_ptr_ref(CodeGen *g, ZigValue *pointee_val, bool is_const) { - ZigValue *const_val = create_const_vals(1); + ZigValue *const_val = g->pass1_arena->create(); init_const_ptr_ref(g, const_val, pointee_val, is_const); return const_val; } @@ -6017,25 +6016,21 @@ void init_const_ptr_hard_coded_addr(CodeGen *g, ZigValue *const_val, ZigType *po ZigValue *create_const_ptr_hard_coded_addr(CodeGen *g, ZigType *pointee_type, size_t addr, bool is_const) { - ZigValue *const_val = create_const_vals(1); + ZigValue *const_val = g->pass1_arena->create(); init_const_ptr_hard_coded_addr(g, const_val, pointee_type, addr, is_const); return const_val; } -ZigValue *create_const_vals(size_t count) { - return allocate(count, "ZigValue"); +ZigValue **alloc_const_vals_ptrs(CodeGen *g, size_t count) { + return realloc_const_vals_ptrs(g, nullptr, 0, count); } -ZigValue **alloc_const_vals_ptrs(size_t count) { - return realloc_const_vals_ptrs(nullptr, 0, count); -} - -ZigValue **realloc_const_vals_ptrs(ZigValue **ptr, size_t old_count, size_t new_count) { +ZigValue **realloc_const_vals_ptrs(CodeGen *g, ZigValue **ptr, size_t old_count, size_t new_count) { assert(new_count >= old_count); size_t new_item_count = new_count - old_count; - ZigValue **result = reallocate(ptr, old_count, new_count, "ZigValue*"); - ZigValue *vals = create_const_vals(new_item_count); + ZigValue **result = heap::c_allocator.reallocate(ptr, old_count, new_count); + ZigValue *vals = g->pass1_arena->allocate(new_item_count); for (size_t i = old_count; i < new_count; i += 1) { result[i] = &vals[i - old_count]; } @@ -6050,8 +6045,8 @@ TypeStructField **realloc_type_struct_fields(TypeStructField **ptr, size_t old_c assert(new_count >= old_count); size_t new_item_count = new_count - old_count; - TypeStructField **result = reallocate(ptr, old_count, new_count, "TypeStructField*"); - TypeStructField *vals = allocate(new_item_count, "TypeStructField"); + TypeStructField **result = heap::c_allocator.reallocate(ptr, old_count, new_count); + TypeStructField *vals = heap::c_allocator.allocate(new_item_count); for (size_t i = old_count; i < new_count; i += 1) { result[i] = &vals[i - old_count]; } @@ -6062,7 +6057,7 @@ static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) { if (orig_fn_type->data.fn.fn_type_id.cc == CallingConventionAsync) return orig_fn_type; - ZigType *fn_type = allocate_nonzero(1); + ZigType *fn_type = heap::c_allocator.allocate_nonzero(1); *fn_type = *orig_fn_type; fn_type->data.fn.fn_type_id.cc = CallingConventionAsync; fn_type->llvm_type = nullptr; @@ -6236,11 +6231,11 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { ZigType *fn_type = get_async_fn_type(g, fn->type_entry); if (fn->analyzed_executable.need_err_code_spill) { - IrInstGenAlloca *alloca_gen = allocate(1); + IrInstGenAlloca *alloca_gen = heap::c_allocator.create(); alloca_gen->base.id = IrInstGenIdAlloca; alloca_gen->base.base.source_node = fn->proto_node; alloca_gen->base.base.scope = fn->child_scope; - alloca_gen->base.value = allocate(1, "ZigValue"); + alloca_gen->base.value = g->pass1_arena->create(); alloca_gen->base.value->type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false); alloca_gen->base.base.ref_count = 1; alloca_gen->name_hint = ""; @@ -6942,9 +6937,9 @@ static void render_const_val_array(CodeGen *g, Buf *buf, Buf *type_name, ZigValu return; } case ConstArraySpecialNone: { - ZigValue *base = &array->data.s_none.elements[start]; - assert(base != nullptr); assert(start + len <= const_val->type->data.array.len); + ZigValue *base = &array->data.s_none.elements[start]; + assert(len == 0 || base != nullptr); buf_appendf(buf, "%s{", buf_ptr(type_name)); for (uint64_t i = 0; i < len; i += 1) { @@ -7375,7 +7370,7 @@ static void init_const_undefined(CodeGen *g, ZigValue *const_val) { const_val->special = ConstValSpecialStatic; size_t field_count = wanted_type->data.structure.src_field_count; - const_val->data.x_struct.fields = alloc_const_vals_ptrs(field_count); + const_val->data.x_struct.fields = alloc_const_vals_ptrs(g, field_count); for (size_t i = 0; i < field_count; i += 1) { ZigValue *field_val = const_val->data.x_struct.fields[i]; field_val->type = resolve_struct_field_type(g, wanted_type->data.structure.fields[i]); @@ -7418,7 +7413,7 @@ void expand_undef_array(CodeGen *g, ZigValue *const_val) { return; case ConstArraySpecialUndef: { const_val->data.x_array.special = ConstArraySpecialNone; - const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count); + const_val->data.x_array.data.s_none.elements = g->pass1_arena->allocate(elem_count); for (size_t i = 0; i < elem_count; i += 1) { ZigValue *element_val = &const_val->data.x_array.data.s_none.elements[i]; element_val->type = elem_type; @@ -7437,7 +7432,7 @@ void expand_undef_array(CodeGen *g, ZigValue *const_val) { const_val->data.x_array.special = ConstArraySpecialNone; assert(elem_count == buf_len(buf)); - const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count); + const_val->data.x_array.data.s_none.elements = g->pass1_arena->allocate(elem_count); for (size_t i = 0; i < elem_count; i += 1) { ZigValue *this_char = &const_val->data.x_array.data.s_none.elements[i]; this_char->special = ConstValSpecialStatic; @@ -7609,7 +7604,7 @@ const char *type_id_name(ZigTypeId id) { } LinkLib *create_link_lib(Buf *name) { - LinkLib *link_lib = allocate(1); + LinkLib *link_lib = heap::c_allocator.create(); link_lib->name = name; return link_lib; } @@ -8137,7 +8132,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS size_t field_count = struct_type->data.structure.src_field_count; // Every field could potentially have a generated padding field after it. - LLVMTypeRef *element_types = allocate(field_count * 2); + LLVMTypeRef *element_types = heap::c_allocator.allocate(field_count * 2); bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked); size_t packed_bits_offset = 0; @@ -8272,7 +8267,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS (unsigned)struct_type->data.structure.gen_field_count, packed); } - ZigLLVMDIType **di_element_types = allocate(debug_field_count); + ZigLLVMDIType **di_element_types = heap::c_allocator.allocate(debug_field_count); size_t debug_field_index = 0; for (size_t i = 0; i < field_count; i += 1) { TypeStructField *field = struct_type->data.structure.fields[i]; @@ -8389,7 +8384,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu uint32_t field_count = enum_type->data.enumeration.src_field_count; assert(field_count == 0 || enum_type->data.enumeration.fields != nullptr); - ZigLLVMDIEnumerator **di_enumerators = allocate(field_count); + ZigLLVMDIEnumerator **di_enumerators = heap::c_allocator.allocate(field_count); for (uint32_t i = 0; i < field_count; i += 1) { TypeEnumField *enum_field = &enum_type->data.enumeration.fields[i]; @@ -8456,7 +8451,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return; } - ZigLLVMDIType **union_inner_di_types = allocate(gen_field_count); + ZigLLVMDIType **union_inner_di_types = heap::c_allocator.allocate(gen_field_count); uint32_t field_count = union_type->data.unionation.src_field_count; for (uint32_t i = 0; i < field_count; i += 1) { TypeUnionField *union_field = &union_type->data.unionation.fields[i]; @@ -8895,7 +8890,7 @@ static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) { param_di_types.append(get_llvm_di_type(g, gen_type)); } if (is_async) { - fn_type->data.fn.gen_param_info = allocate(2); + fn_type->data.fn.gen_param_info = heap::c_allocator.allocate(2); ZigType *frame_type = get_any_frame_type(g, fn_type_id->return_type); gen_param_types.append(get_llvm_type(g, frame_type)); @@ -8912,7 +8907,7 @@ static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) { fn_type->data.fn.gen_param_info[1].gen_index = 1; fn_type->data.fn.gen_param_info[1].type = g->builtin_types.entry_usize; } else { - fn_type->data.fn.gen_param_info = allocate(fn_type_id->param_count); + fn_type->data.fn.gen_param_info = heap::c_allocator.allocate(fn_type_id->param_count); for (size_t i = 0; i < fn_type_id->param_count; i += 1) { FnTypeParamInfo *src_param_info = &fn_type->data.fn.fn_type_id.param_info[i]; ZigType *type_entry = src_param_info->type; @@ -9369,7 +9364,7 @@ bool type_has_optional_repr(ZigType *ty) { } } -void copy_const_val(ZigValue *dest, ZigValue *src) { +void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src) { uint32_t prev_align = dest->llvm_align; ConstParent prev_parent = dest->parent; memcpy(dest, src, sizeof(ZigValue)); @@ -9378,26 +9373,26 @@ void copy_const_val(ZigValue *dest, ZigValue *src) { return; dest->parent = prev_parent; if (dest->type->id == ZigTypeIdStruct) { - dest->data.x_struct.fields = alloc_const_vals_ptrs(dest->type->data.structure.src_field_count); + dest->data.x_struct.fields = alloc_const_vals_ptrs(g, dest->type->data.structure.src_field_count); for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) { - copy_const_val(dest->data.x_struct.fields[i], src->data.x_struct.fields[i]); + copy_const_val(g, dest->data.x_struct.fields[i], src->data.x_struct.fields[i]); dest->data.x_struct.fields[i]->parent.id = ConstParentIdStruct; dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest; dest->data.x_struct.fields[i]->parent.data.p_struct.field_index = i; } } else if (dest->type->id == ZigTypeIdArray) { if (dest->data.x_array.special == ConstArraySpecialNone) { - dest->data.x_array.data.s_none.elements = create_const_vals(dest->type->data.array.len); + dest->data.x_array.data.s_none.elements = g->pass1_arena->allocate(dest->type->data.array.len); for (uint64_t i = 0; i < dest->type->data.array.len; i += 1) { - copy_const_val(&dest->data.x_array.data.s_none.elements[i], &src->data.x_array.data.s_none.elements[i]); + copy_const_val(g, &dest->data.x_array.data.s_none.elements[i], &src->data.x_array.data.s_none.elements[i]); dest->data.x_array.data.s_none.elements[i].parent.id = ConstParentIdArray; dest->data.x_array.data.s_none.elements[i].parent.data.p_array.array_val = dest; dest->data.x_array.data.s_none.elements[i].parent.data.p_array.elem_index = i; } } } else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) { - dest->data.x_optional = create_const_vals(1); - copy_const_val(dest->data.x_optional, src->data.x_optional); + dest->data.x_optional = g->pass1_arena->create(); + copy_const_val(g, dest->data.x_optional, src->data.x_optional); dest->data.x_optional->parent.id = ConstParentIdOptionalPayload; dest->data.x_optional->parent.data.p_optional_payload.optional_val = dest; } diff --git a/src/analyze.hpp b/src/analyze.hpp index c0026945e2..eb3781789d 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -128,22 +128,22 @@ void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str); ZigValue *create_const_str_lit(CodeGen *g, Buf *str); void init_const_bigint(ZigValue *const_val, ZigType *type, const BigInt *bigint); -ZigValue *create_const_bigint(ZigType *type, const BigInt *bigint); +ZigValue *create_const_bigint(CodeGen *g, ZigType *type, const BigInt *bigint); void init_const_unsigned_negative(ZigValue *const_val, ZigType *type, uint64_t x, bool negative); -ZigValue *create_const_unsigned_negative(ZigType *type, uint64_t x, bool negative); +ZigValue *create_const_unsigned_negative(CodeGen *g, ZigType *type, uint64_t x, bool negative); void init_const_signed(ZigValue *const_val, ZigType *type, int64_t x); -ZigValue *create_const_signed(ZigType *type, int64_t x); +ZigValue *create_const_signed(CodeGen *g, ZigType *type, int64_t x); void init_const_usize(CodeGen *g, ZigValue *const_val, uint64_t x); ZigValue *create_const_usize(CodeGen *g, uint64_t x); void init_const_float(ZigValue *const_val, ZigType *type, double value); -ZigValue *create_const_float(ZigType *type, double value); +ZigValue *create_const_float(CodeGen *g, ZigType *type, double value); void init_const_enum(ZigValue *const_val, ZigType *type, const BigInt *tag); -ZigValue *create_const_enum(ZigType *type, const BigInt *tag); +ZigValue *create_const_enum(CodeGen *g, ZigType *type, const BigInt *tag); void init_const_bool(CodeGen *g, ZigValue *const_val, bool value); ZigValue *create_const_bool(CodeGen *g, bool value); @@ -152,7 +152,7 @@ void init_const_type(CodeGen *g, ZigValue *const_val, ZigType *type_value); ZigValue *create_const_type(CodeGen *g, ZigType *type_value); void init_const_runtime(ZigValue *const_val, ZigType *type); -ZigValue *create_const_runtime(ZigType *type); +ZigValue *create_const_runtime(CodeGen *g, ZigType *type); void init_const_ptr_ref(CodeGen *g, ZigValue *const_val, ZigValue *pointee_val, bool is_const); ZigValue *create_const_ptr_ref(CodeGen *g, ZigValue *pointee_val, bool is_const); @@ -172,11 +172,10 @@ void init_const_slice(CodeGen *g, ZigValue *const_val, ZigValue *array_val, ZigValue *create_const_slice(CodeGen *g, ZigValue *array_val, size_t start, size_t len, bool is_const); void init_const_null(ZigValue *const_val, ZigType *type); -ZigValue *create_const_null(ZigType *type); +ZigValue *create_const_null(CodeGen *g, ZigType *type); -ZigValue *create_const_vals(size_t count); -ZigValue **alloc_const_vals_ptrs(size_t count); -ZigValue **realloc_const_vals_ptrs(ZigValue **ptr, size_t old_count, size_t new_count); +ZigValue **alloc_const_vals_ptrs(CodeGen *g, size_t count); +ZigValue **realloc_const_vals_ptrs(CodeGen *g, ZigValue **ptr, size_t old_count, size_t new_count); TypeStructField **alloc_type_struct_fields(size_t count); TypeStructField **realloc_type_struct_fields(TypeStructField **ptr, size_t old_count, size_t new_count); @@ -275,7 +274,7 @@ Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_targe ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path); ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry); bool is_anon_container(ZigType *ty); -void copy_const_val(ZigValue *dest, ZigValue *src); +void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src); bool type_has_optional_repr(ZigType *ty); bool is_opt_err_set(ZigType *ty); bool type_is_numeric(ZigType *ty); diff --git a/src/bigint.cpp b/src/bigint.cpp index 1127033d02..644e25837e 100644 --- a/src/bigint.cpp +++ b/src/bigint.cpp @@ -93,7 +93,7 @@ static void to_twos_complement(BigInt *dest, const BigInt *op, size_t bit_count) if (dest->data.digit == 0) dest->digit_count = 0; return; } - dest->data.digits = allocate_nonzero(dest->digit_count); + dest->data.digits = heap::c_allocator.allocate_nonzero(dest->digit_count); for (size_t i = 0; i < digits_to_copy; i += 1) { uint64_t digit = (i < op->digit_count) ? op_digits[i] : 0; dest->data.digits[i] = digit; @@ -174,7 +174,7 @@ void bigint_init_data(BigInt *dest, const uint64_t *digits, size_t digit_count, dest->digit_count = digit_count; dest->is_negative = is_negative; - dest->data.digits = allocate_nonzero(digit_count); + dest->data.digits = heap::c_allocator.allocate_nonzero(digit_count); memcpy(dest->data.digits, digits, sizeof(uint64_t) * digit_count); bigint_normalize(dest); @@ -191,13 +191,13 @@ void bigint_init_bigint(BigInt *dest, const BigInt *src) { } dest->is_negative = src->is_negative; dest->digit_count = src->digit_count; - dest->data.digits = allocate_nonzero(dest->digit_count); + dest->data.digits = heap::c_allocator.allocate_nonzero(dest->digit_count); memcpy(dest->data.digits, src->data.digits, sizeof(uint64_t) * dest->digit_count); } void bigint_deinit(BigInt *bi) { if (bi->digit_count > 1) - deallocate(bi->data.digits, bi->digit_count); + heap::c_allocator.deallocate(bi->data.digits, bi->digit_count); } void bigint_init_bigfloat(BigInt *dest, const BigFloat *op) { @@ -227,7 +227,7 @@ void bigint_init_bigfloat(BigInt *dest, const BigFloat *op) { f128M_rem(&abs_val, &max_u64, &remainder); dest->digit_count = 2; - dest->data.digits = allocate_nonzero(dest->digit_count); + dest->data.digits = heap::c_allocator.allocate_nonzero(dest->digit_count); dest->data.digits[0] = f128M_to_ui64(&remainder, softfloat_round_minMag, false); dest->data.digits[1] = f128M_to_ui64(&amt, softfloat_round_minMag, false); bigint_normalize(dest); @@ -345,7 +345,7 @@ void bigint_read_twos_complement(BigInt *dest, const uint8_t *buf, size_t bit_co if (dest->digit_count == 1) { digits = &dest->data.digit; } else { - digits = allocate_nonzero(dest->digit_count); + digits = heap::c_allocator.allocate_nonzero(dest->digit_count); dest->data.digits = digits; } @@ -464,7 +464,7 @@ void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2) { } size_t i = 1; uint64_t first_digit = dest->data.digit; - dest->data.digits = allocate_nonzero(max(op1->digit_count, op2->digit_count) + 1); + dest->data.digits = heap::c_allocator.allocate_nonzero(max(op1->digit_count, op2->digit_count) + 1); dest->data.digits[0] = first_digit; for (;;) { @@ -532,7 +532,7 @@ void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2) { return; } uint64_t first_digit = dest->data.digit; - dest->data.digits = allocate_nonzero(bigger_op->digit_count); + dest->data.digits = heap::c_allocator.allocate_nonzero(bigger_op->digit_count); dest->data.digits[0] = first_digit; size_t i = 1; @@ -1032,7 +1032,7 @@ static void bigint_unsigned_division(const BigInt *op1, const BigInt *op2, BigIn if (lhsWords == 1) { Quotient->data.digit = Make_64(Q[1], Q[0]); } else { - Quotient->data.digits = allocate(lhsWords); + Quotient->data.digits = heap::c_allocator.allocate(lhsWords); for (size_t i = 0; i < lhsWords; i += 1) { Quotient->data.digits[i] = Make_64(Q[i*2+1], Q[i*2]); } @@ -1046,7 +1046,7 @@ static void bigint_unsigned_division(const BigInt *op1, const BigInt *op2, BigIn if (rhsWords == 1) { Remainder->data.digit = Make_64(R[1], R[0]); } else { - Remainder->data.digits = allocate(rhsWords); + Remainder->data.digits = heap::c_allocator.allocate(rhsWords); for (size_t i = 0; i < rhsWords; i += 1) { Remainder->data.digits[i] = Make_64(R[i*2+1], R[i*2]); } @@ -1218,7 +1218,7 @@ void bigint_or(BigInt *dest, const BigInt *op1, const BigInt *op2) { return; } dest->digit_count = max(op1->digit_count, op2->digit_count); - dest->data.digits = allocate_nonzero(dest->digit_count); + dest->data.digits = heap::c_allocator.allocate_nonzero(dest->digit_count); for (size_t i = 0; i < dest->digit_count; i += 1) { uint64_t digit = 0; if (i < op1->digit_count) { @@ -1262,7 +1262,7 @@ void bigint_and(BigInt *dest, const BigInt *op1, const BigInt *op2) { } dest->digit_count = max(op1->digit_count, op2->digit_count); - dest->data.digits = allocate_nonzero(dest->digit_count); + dest->data.digits = heap::c_allocator.allocate_nonzero(dest->digit_count); size_t i = 0; for (; i < op1->digit_count && i < op2->digit_count; i += 1) { @@ -1308,7 +1308,7 @@ void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) { return; } dest->digit_count = max(op1->digit_count, op2->digit_count); - dest->data.digits = allocate_nonzero(dest->digit_count); + dest->data.digits = heap::c_allocator.allocate_nonzero(dest->digit_count); size_t i = 0; for (; i < op1->digit_count && i < op2->digit_count; i += 1) { dest->data.digits[i] = op1_digits[i] ^ op2_digits[i]; @@ -1358,7 +1358,7 @@ void bigint_shl(BigInt *dest, const BigInt *op1, const BigInt *op2) { uint64_t digit_shift_count = shift_amt / 64; uint64_t leftover_shift_count = shift_amt % 64; - dest->data.digits = allocate(op1->digit_count + digit_shift_count + 1); + dest->data.digits = heap::c_allocator.allocate(op1->digit_count + digit_shift_count + 1); dest->digit_count = digit_shift_count; uint64_t carry = 0; for (size_t i = 0; i < op1->digit_count; i += 1) { @@ -1421,7 +1421,7 @@ void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2) { if (dest->digit_count == 1) { digits = &dest->data.digit; } else { - digits = allocate(dest->digit_count); + digits = heap::c_allocator.allocate(dest->digit_count); dest->data.digits = digits; } @@ -1492,7 +1492,7 @@ void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed } dest->digit_count = (bit_count + 63) / 64; assert(dest->digit_count >= op->digit_count); - dest->data.digits = allocate_nonzero(dest->digit_count); + dest->data.digits = heap::c_allocator.allocate_nonzero(dest->digit_count); size_t i = 0; for (; i < op->digit_count; i += 1) { dest->data.digits[i] = ~op_digits[i]; diff --git a/src/buffer.hpp b/src/buffer.hpp index 6442e4f123..82bcb56611 100644 --- a/src/buffer.hpp +++ b/src/buffer.hpp @@ -50,7 +50,7 @@ static inline void buf_resize(Buf *buf, size_t new_len) { } static inline Buf *buf_alloc_fixed(size_t size) { - Buf *buf = allocate(1); + Buf *buf = heap::c_allocator.create(); buf_resize(buf, size); return buf; } @@ -65,7 +65,7 @@ static inline void buf_deinit(Buf *buf) { static inline void buf_destroy(Buf *buf) { buf_deinit(buf); - free(buf); + heap::c_allocator.destroy(buf); } static inline void buf_init_from_mem(Buf *buf, const char *ptr, size_t len) { @@ -85,7 +85,7 @@ static inline void buf_init_from_buf(Buf *buf, Buf *other) { static inline Buf *buf_create_from_mem(const char *ptr, size_t len) { assert(len != SIZE_MAX); - Buf *buf = allocate(1); + Buf *buf = heap::c_allocator.create(); buf_init_from_mem(buf, ptr, len); return buf; } @@ -108,7 +108,7 @@ static inline Buf *buf_slice(Buf *in_buf, size_t start, size_t end) { assert(end != SIZE_MAX); assert(start < buf_len(in_buf)); assert(end <= buf_len(in_buf)); - Buf *out_buf = allocate(1); + Buf *out_buf = heap::c_allocator.create(); out_buf->list.resize(end - start + 1); memcpy(buf_ptr(out_buf), buf_ptr(in_buf) + start, end - start); out_buf->list.at(buf_len(out_buf)) = 0; @@ -211,5 +211,4 @@ static inline void buf_replace(Buf* buf, char from, char to) { } } - #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index 998f7d1a08..f17d537863 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -21,6 +21,7 @@ #include "userland.h" #include "dump_analysis.hpp" #include "softfloat.hpp" +#include "mem_profile.hpp" #include #include @@ -57,7 +58,7 @@ static void init_darwin_native(CodeGen *g) { } static ZigPackage *new_package(const char *root_src_dir, const char *root_src_path, const char *pkg_path) { - ZigPackage *entry = allocate(1); + ZigPackage *entry = heap::c_allocator.create(); entry->package_table.init(4); buf_init_from_str(&entry->root_src_dir, root_src_dir); buf_init_from_str(&entry->root_src_path, root_src_path); @@ -4323,7 +4324,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn } size_t field_count = arg_calc.field_index; - LLVMTypeRef *field_types = allocate_nonzero(field_count); + LLVMTypeRef *field_types = heap::c_allocator.allocate_nonzero(field_count); LLVMGetStructElementTypes(LLVMGetElementType(LLVMTypeOf(frame_result_loc)), field_types); assert(LLVMCountStructElementTypes(LLVMGetElementType(LLVMTypeOf(frame_result_loc))) == arg_calc_start.field_index); @@ -4676,8 +4677,8 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, IrExecutableGen *executable, I instruction->return_count; size_t total_index = 0; size_t param_index = 0; - LLVMTypeRef *param_types = allocate(input_and_output_count); - LLVMValueRef *param_values = allocate(input_and_output_count); + LLVMTypeRef *param_types = heap::c_allocator.allocate(input_and_output_count); + LLVMValueRef *param_values = heap::c_allocator.allocate(input_and_output_count); for (size_t i = 0; i < asm_expr->output_list.length; i += 1, total_index += 1) { AsmOutput *asm_output = asm_expr->output_list.at(i); bool is_return = (asm_output->return_type != nullptr); @@ -4919,7 +4920,7 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutableGen *execut // second vector. These start at -1 and go down, and are easiest to use // with the ~ operator. Here we convert between the two formats. IrInstGen *mask = instruction->mask; - LLVMValueRef *values = allocate(len_mask); + LLVMValueRef *values = heap::c_allocator.allocate(len_mask); for (uint64_t i = 0; i < len_mask; i++) { if (mask->value->data.x_array.data.s_none.elements[i].special == ConstValSpecialUndef) { values[i] = LLVMGetUndef(LLVMInt32Type()); @@ -4931,7 +4932,7 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutableGen *execut } LLVMValueRef llvm_mask_value = LLVMConstVector(values, len_mask); - free(values); + heap::c_allocator.deallocate(values, len_mask); return LLVMBuildShuffleVector(g->builder, ir_llvm_value(g, instruction->a), @@ -4999,8 +5000,8 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutableGen *executable, IrIns } LLVMValueRef phi = LLVMBuildPhi(g->builder, phi_type, ""); - LLVMValueRef *incoming_values = allocate(instruction->incoming_count); - LLVMBasicBlockRef *incoming_blocks = allocate(instruction->incoming_count); + LLVMValueRef *incoming_values = heap::c_allocator.allocate(instruction->incoming_count); + LLVMBasicBlockRef *incoming_blocks = heap::c_allocator.allocate(instruction->incoming_count); for (size_t i = 0; i < instruction->incoming_count; i += 1) { incoming_values[i] = ir_llvm_value(g, instruction->incoming_values[i]); incoming_blocks[i] = instruction->incoming_blocks[i]->llvm_exit_block; @@ -5972,12 +5973,12 @@ static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutableGen *executable, IrI LLVMValueRef shift_amt = LLVMConstInt(get_llvm_type(g, extended_type), 8, false); if (is_vector) { extended_type = get_vector_type(g, expr_type->data.vector.len, extended_type); - LLVMValueRef *values = allocate_nonzero(expr_type->data.vector.len); + LLVMValueRef *values = heap::c_allocator.allocate_nonzero(expr_type->data.vector.len); for (uint32_t i = 0; i < expr_type->data.vector.len; i += 1) { values[i] = shift_amt; } shift_amt = LLVMConstVector(values, expr_type->data.vector.len); - free(values); + heap::c_allocator.deallocate(values, expr_type->data.vector.len); } // aabbcc LLVMValueRef extended = LLVMBuildZExt(g->builder, op, get_llvm_type(g, extended_type), ""); @@ -7010,7 +7011,7 @@ check: switch (const_val->special) { } case ZigTypeIdStruct: { - LLVMValueRef *fields = allocate(type_entry->data.structure.gen_field_count); + LLVMValueRef *fields = heap::c_allocator.allocate(type_entry->data.structure.gen_field_count); size_t src_field_count = type_entry->data.structure.src_field_count; bool make_unnamed_struct = false; assert(type_entry->data.structure.resolve_status == ResolveStatusLLVMFull); @@ -7069,7 +7070,7 @@ check: switch (const_val->special) { } else { const LLVMValueRef AMT = LLVMConstInt(LLVMTypeOf(val), 8, false); - LLVMValueRef *values = allocate(size_in_bytes); + LLVMValueRef *values = heap::c_allocator.allocate(size_in_bytes); for (size_t i = 0; i < size_in_bytes; i++) { const size_t idx = is_big_endian ? size_in_bytes - 1 - i : i; values[idx] = LLVMConstTruncOrBitCast(val, LLVMInt8Type()); @@ -7133,7 +7134,7 @@ check: switch (const_val->special) { case ConstArraySpecialNone: { uint64_t extra_len_from_sentinel = (type_entry->data.array.sentinel != nullptr) ? 1 : 0; uint64_t full_len = len + extra_len_from_sentinel; - LLVMValueRef *values = allocate(full_len); + LLVMValueRef *values = heap::c_allocator.allocate(full_len); LLVMTypeRef element_type_ref = get_llvm_type(g, type_entry->data.array.child_type); bool make_unnamed_struct = false; for (uint64_t i = 0; i < len; i += 1) { @@ -7165,7 +7166,7 @@ check: switch (const_val->special) { case ConstArraySpecialUndef: return LLVMGetUndef(get_llvm_type(g, type_entry)); case ConstArraySpecialNone: { - LLVMValueRef *values = allocate(len); + LLVMValueRef *values = heap::c_allocator.allocate(len); for (uint64_t i = 0; i < len; i += 1) { ZigValue *elem_value = &const_val->data.x_array.data.s_none.elements[i]; values[i] = gen_const_val(g, elem_value, ""); @@ -7175,7 +7176,7 @@ check: switch (const_val->special) { case ConstArraySpecialBuf: { Buf *buf = const_val->data.x_array.data.s_buf; assert(buf_len(buf) == len); - LLVMValueRef *values = allocate(len); + LLVMValueRef *values = heap::c_allocator.allocate(len); for (uint64_t i = 0; i < len; i += 1) { values[i] = LLVMConstInt(g->builtin_types.entry_u8->llvm_type, buf_ptr(buf)[i], false); } @@ -7377,7 +7378,7 @@ static void generate_error_name_table(CodeGen *g) { PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false); ZigType *str_type = get_slice_type(g, u8_ptr_type); - LLVMValueRef *values = allocate(g->errors_by_index.length); + LLVMValueRef *values = heap::c_allocator.allocate(g->errors_by_index.length); values[0] = LLVMGetUndef(get_llvm_type(g, str_type)); for (size_t i = 1; i < g->errors_by_index.length; i += 1) { ErrorTableEntry *err_entry = g->errors_by_index.at(i); @@ -7906,6 +7907,9 @@ static void do_code_gen(CodeGen *g) { } static void zig_llvm_emit_output(CodeGen *g) { + g->pass1_arena->destruct(&heap::c_allocator); + g->pass1_arena = nullptr; + bool is_small = g->build_mode == BuildModeSmallRelease; Buf *output_path = &g->o_file_output_path; @@ -8202,7 +8206,7 @@ static void define_intern_values(CodeGen *g) { } static BuiltinFnEntry *create_builtin_fn(CodeGen *g, BuiltinFnId id, const char *name, size_t count) { - BuiltinFnEntry *builtin_fn = allocate(1); + BuiltinFnEntry *builtin_fn = heap::c_allocator.create(); buf_init_from_str(&builtin_fn->name, name); builtin_fn->id = id; builtin_fn->param_count = count; @@ -8919,16 +8923,16 @@ static void init(CodeGen *g) { define_builtin_types(g); define_intern_values(g); - IrInstGen *sentinel_instructions = allocate(2); + IrInstGen *sentinel_instructions = heap::c_allocator.allocate(2); g->invalid_inst_gen = &sentinel_instructions[0]; - g->invalid_inst_gen->value = allocate(1, "ZigValue"); + g->invalid_inst_gen->value = g->pass1_arena->create(); g->invalid_inst_gen->value->type = g->builtin_types.entry_invalid; g->unreach_instruction = &sentinel_instructions[1]; - g->unreach_instruction->value = allocate(1, "ZigValue"); + g->unreach_instruction->value = g->pass1_arena->create(); g->unreach_instruction->value->type = g->builtin_types.entry_unreachable; - g->invalid_inst_src = allocate(1); + g->invalid_inst_src = heap::c_allocator.create(); define_builtin_fns(g); Error err; @@ -9010,7 +9014,7 @@ static void detect_libc(CodeGen *g) { buf_ptr(g->zig_lib_dir), target_os_name(g->zig_target->os)); g->libc_include_dir_len = 4; - g->libc_include_dir_list = allocate(g->libc_include_dir_len); + g->libc_include_dir_list = heap::c_allocator.allocate(g->libc_include_dir_len); g->libc_include_dir_list[0] = arch_include_dir; g->libc_include_dir_list[1] = generic_include_dir; g->libc_include_dir_list[2] = arch_os_include_dir; @@ -9019,7 +9023,7 @@ static void detect_libc(CodeGen *g) { } if (g->zig_target->is_native) { - g->libc = allocate(1); + g->libc = heap::c_allocator.create(); // search for native_libc.txt in following dirs: // - LOCAL_CACHE_DIR @@ -9099,7 +9103,7 @@ static void detect_libc(CodeGen *g) { size_t want_um_and_shared_dirs = (g->zig_target->os == OsWindows) ? 2 : 0; size_t dir_count = 1 + want_sys_dir + want_um_and_shared_dirs; g->libc_include_dir_len = 0; - g->libc_include_dir_list = allocate(dir_count); + g->libc_include_dir_list = heap::c_allocator.allocate(dir_count); g->libc_include_dir_list[g->libc_include_dir_len] = &g->libc->include_dir; g->libc_include_dir_len += 1; @@ -9466,10 +9470,10 @@ static void update_test_functions_builtin_decl(CodeGen *g) { if ((err = type_resolve(g, struct_type, ResolveStatusSizeKnown))) zig_unreachable(); - ZigValue *test_fn_array = create_const_vals(1); + ZigValue *test_fn_array = g->pass1_arena->create(); test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length, nullptr); test_fn_array->special = ConstValSpecialStatic; - test_fn_array->data.x_array.data.s_none.elements = create_const_vals(g->test_fns.length); + test_fn_array->data.x_array.data.s_none.elements = g->pass1_arena->allocate(g->test_fns.length); for (size_t i = 0; i < g->test_fns.length; i += 1) { ZigFn *test_fn_entry = g->test_fns.at(i); @@ -9480,7 +9484,7 @@ static void update_test_functions_builtin_decl(CodeGen *g) { this_val->parent.id = ConstParentIdArray; this_val->parent.data.p_array.array_val = test_fn_array; this_val->parent.data.p_array.elem_index = i; - this_val->data.x_struct.fields = alloc_const_vals_ptrs(3); + this_val->data.x_struct.fields = alloc_const_vals_ptrs(g, 3); ZigValue *name_field = this_val->data.x_struct.fields[0]; ZigValue *name_array_val = create_const_str_lit(g, &test_fn_entry->symbol_name)->data.x_ptr.data.ref.pointee; @@ -9499,7 +9503,7 @@ static void update_test_functions_builtin_decl(CodeGen *g) { frame_size_field->data.x_optional = nullptr; if (fn_is_async(test_fn_entry)) { - frame_size_field->data.x_optional = create_const_vals(1); + frame_size_field->data.x_optional = g->pass1_arena->create(); frame_size_field->data.x_optional->special = ConstValSpecialStatic; frame_size_field->data.x_optional->type = g->builtin_types.entry_usize; bigint_init_unsigned(&frame_size_field->data.x_optional->data.x_bigint, @@ -9634,7 +9638,7 @@ static Error get_tmp_filename(CodeGen *g, Buf *out, Buf *suffix) { Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose) { Error err; - CacheHash *cache_hash = allocate(1); + CacheHash *cache_hash = heap::c_allocator.create(); Buf *manifest_dir = buf_sprintf("%s" OS_SEP CACHE_HASH_SUBDIR, buf_ptr(g->cache_dir)); cache_init(cache_hash, manifest_dir); @@ -10788,7 +10792,8 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget OutType out_type, BuildMode build_mode, Buf *override_lib_dir, ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node) { - CodeGen *g = allocate(1); + CodeGen *g = heap::c_allocator.create(); + g->pass1_arena = heap::ArenaAllocator::construct(&heap::c_allocator, &heap::c_allocator, "pass1"); g->main_progress_node = progress_node; codegen_add_time_event(g, "Initialize"); @@ -10931,35 +10936,35 @@ void codegen_switch_sub_prog_node(CodeGen *g, Stage2ProgressNode *node) { ZigValue *CodeGen::Intern::for_undefined() { #ifdef ZIG_ENABLE_MEM_PROFILE - memprof_intern_count.x_undefined += 1; + mem::intern_counters.x_undefined += 1; #endif return &this->x_undefined; } ZigValue *CodeGen::Intern::for_void() { #ifdef ZIG_ENABLE_MEM_PROFILE - memprof_intern_count.x_void += 1; + mem::intern_counters.x_void += 1; #endif return &this->x_void; } ZigValue *CodeGen::Intern::for_null() { #ifdef ZIG_ENABLE_MEM_PROFILE - memprof_intern_count.x_null += 1; + mem::intern_counters.x_null += 1; #endif return &this->x_null; } ZigValue *CodeGen::Intern::for_unreachable() { #ifdef ZIG_ENABLE_MEM_PROFILE - memprof_intern_count.x_unreachable += 1; + mem::intern_counters.x_unreachable += 1; #endif return &this->x_unreachable; } ZigValue *CodeGen::Intern::for_zero_byte() { #ifdef ZIG_ENABLE_MEM_PROFILE - memprof_intern_count.zero_byte += 1; + mem::intern_counters.zero_byte += 1; #endif return &this->zero_byte; } diff --git a/src/errmsg.cpp b/src/errmsg.cpp index 9425b110c3..7bf096547f 100644 --- a/src/errmsg.cpp +++ b/src/errmsg.cpp @@ -99,7 +99,7 @@ void err_msg_add_note(ErrorMsg *parent, ErrorMsg *note) { ErrorMsg *err_msg_create_with_offset(Buf *path, size_t line, size_t column, size_t offset, const char *source, Buf *msg) { - ErrorMsg *err_msg = allocate(1); + ErrorMsg *err_msg = heap::c_allocator.create(); err_msg->path = path; err_msg->line_start = line; err_msg->column_start = column; @@ -138,7 +138,7 @@ ErrorMsg *err_msg_create_with_offset(Buf *path, size_t line, size_t column, size ErrorMsg *err_msg_create_with_line(Buf *path, size_t line, size_t column, Buf *source, ZigList *line_offsets, Buf *msg) { - ErrorMsg *err_msg = allocate(1); + ErrorMsg *err_msg = heap::c_allocator.create(); err_msg->path = path; err_msg->line_start = line; err_msg->column_start = column; diff --git a/src/glibc.cpp b/src/glibc.cpp index 08faf6fb60..ec45b6afa7 100644 --- a/src/glibc.cpp +++ b/src/glibc.cpp @@ -21,7 +21,7 @@ static const ZigGLibCLib glibc_libs[] = { Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbose) { Error err; - ZigGLibCAbi *glibc_abi = allocate(1); + ZigGLibCAbi *glibc_abi = heap::c_allocator.create(); glibc_abi->vers_txt_path = buf_sprintf("%s" OS_SEP "libc" OS_SEP "glibc" OS_SEP "vers.txt", buf_ptr(zig_lib_dir)); glibc_abi->fns_txt_path = buf_sprintf("%s" OS_SEP "libc" OS_SEP "glibc" OS_SEP "fns.txt", buf_ptr(zig_lib_dir)); glibc_abi->abi_txt_path = buf_sprintf("%s" OS_SEP "libc" OS_SEP "glibc" OS_SEP "abi.txt", buf_ptr(zig_lib_dir)); @@ -100,10 +100,10 @@ Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbo Optional> opt_line = SplitIterator_next_separate(&it); if (!opt_line.is_some) break; - ver_list_base = allocate(glibc_abi->all_functions.length); + ver_list_base = heap::c_allocator.allocate(glibc_abi->all_functions.length); SplitIterator line_it = memSplit(opt_line.value, str(" ")); for (;;) { - ZigTarget *target = allocate(1); + ZigTarget *target = heap::c_allocator.create(); Optional> opt_target = SplitIterator_next(&line_it); if (!opt_target.is_some) break; @@ -174,7 +174,7 @@ Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, con Error err; Buf *cache_dir = get_global_cache_dir(); - CacheHash *cache_hash = allocate(1); + CacheHash *cache_hash = heap::c_allocator.create(); Buf *manifest_dir = buf_sprintf("%s" OS_SEP CACHE_HASH_SUBDIR, buf_ptr(cache_dir)); cache_init(cache_hash, manifest_dir); diff --git a/src/hash_map.hpp b/src/hash_map.hpp index e819ea1c10..69e5568093 100644 --- a/src/hash_map.hpp +++ b/src/hash_map.hpp @@ -19,7 +19,7 @@ public: init_capacity(capacity); } void deinit(void) { - free(_entries); + heap::c_allocator.deallocate(_entries, _capacity); } struct Entry { @@ -57,7 +57,7 @@ public: if (old_entry->used) internal_put(old_entry->key, old_entry->value); } - free(old_entries); + heap::c_allocator.deallocate(old_entries, old_capacity); } } @@ -164,7 +164,7 @@ private: void init_capacity(int capacity) { _capacity = capacity; - _entries = allocate(_capacity); + _entries = heap::c_allocator.allocate(_capacity); _size = 0; _max_distance_from_start_index = 0; for (int i = 0; i < _capacity; i += 1) { diff --git a/src/heap.cpp b/src/heap.cpp new file mode 100644 index 0000000000..79c44d13dc --- /dev/null +++ b/src/heap.cpp @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2020 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#include +#include + +#include "config.h" +#include "heap.hpp" +#include "mem_profile.hpp" + +namespace heap { + +extern mem::Allocator &bootstrap_allocator; + +// +// BootstrapAllocator implementation is identical to CAllocator minus +// profile profile functionality. Splitting off to a base interface doesn't +// seem worthwhile. +// + +void BootstrapAllocator::init(const char *name) {} +void BootstrapAllocator::deinit() {} + +void *BootstrapAllocator::internal_allocate(const mem::TypeInfo &info, size_t count) { + return mem::os::calloc(count, info.size); +} + +void *BootstrapAllocator::internal_allocate_nonzero(const mem::TypeInfo &info, size_t count) { + return mem::os::malloc(count * info.size); +} + +void *BootstrapAllocator::internal_reallocate(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) { + auto new_ptr = this->internal_reallocate_nonzero(info, old_ptr, old_count, new_count); + if (new_count > old_count) + memset(reinterpret_cast(new_ptr) + (old_count * info.size), 0, (new_count - old_count) * info.size); + return new_ptr; +} + +void *BootstrapAllocator::internal_reallocate_nonzero(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) { + return mem::os::realloc(old_ptr, new_count * info.size); +} + +void BootstrapAllocator::internal_deallocate(const mem::TypeInfo &info, void *ptr, size_t count) { + mem::os::free(ptr); +} + +void CAllocator::init(const char *name) { +#ifdef ZIG_ENABLE_MEM_PROFILE + this->profile = bootstrap_allocator.create(); + this->profile->init(name, "CAllocator"); +#endif +} + +void CAllocator::deinit() { +#ifdef ZIG_ENABLE_MEM_PROFILE + assert(this->profile); + this->profile->deinit(); + bootstrap_allocator.destroy(this->profile); + this->profile = nullptr; +#endif +} + +CAllocator *CAllocator::construct(mem::Allocator *allocator, const char *name) { + auto p = new(allocator->create()) CAllocator(); + p->init(name); + return p; +} + +void CAllocator::destruct(mem::Allocator *allocator) { + this->deinit(); + allocator->destroy(this); +} + +#ifdef ZIG_ENABLE_MEM_PROFILE +void CAllocator::print_report(FILE *file) { + this->profile->print_report(file); +} +#endif + +void *CAllocator::internal_allocate(const mem::TypeInfo &info, size_t count) { +#ifdef ZIG_ENABLE_MEM_PROFILE + this->profile->record_alloc(info, count); +#endif + return mem::os::calloc(count, info.size); +} + +void *CAllocator::internal_allocate_nonzero(const mem::TypeInfo &info, size_t count) { +#ifdef ZIG_ENABLE_MEM_PROFILE + this->profile->record_alloc(info, count); +#endif + return mem::os::malloc(count * info.size); +} + +void *CAllocator::internal_reallocate(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) { + auto new_ptr = this->internal_reallocate_nonzero(info, old_ptr, old_count, new_count); + if (new_count > old_count) + memset(reinterpret_cast(new_ptr) + (old_count * info.size), 0, (new_count - old_count) * info.size); + return new_ptr; +} + +void *CAllocator::internal_reallocate_nonzero(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) { +#ifdef ZIG_ENABLE_MEM_PROFILE + this->profile->record_dealloc(info, old_count); + this->profile->record_alloc(info, new_count); +#endif + return mem::os::realloc(old_ptr, new_count * info.size); +} + +void CAllocator::internal_deallocate(const mem::TypeInfo &info, void *ptr, size_t count) { +#ifdef ZIG_ENABLE_MEM_PROFILE + this->profile->record_dealloc(info, count); +#endif + mem::os::free(ptr); +} + +struct ArenaAllocator::Impl { + Allocator *backing; + + // regular allocations bump through a segment of static size + struct Segment { + static constexpr size_t size = 65536; + static constexpr size_t object_threshold = 4096; + + uint8_t data[size]; + }; + + // active segment + Segment *segment; + size_t segment_offset; + + // keep track of segments + struct SegmentTrack { + static constexpr size_t size = (4096 - sizeof(SegmentTrack *)) / sizeof(Segment *); + + // null if first + SegmentTrack *prev; + Segment *segments[size]; + }; + static_assert(sizeof(SegmentTrack) <= 4096, "unwanted struct padding"); + + // active segment track + SegmentTrack *segment_track; + size_t segment_track_remain; + + // individual allocations punted to backing allocator + struct Object { + uint8_t *ptr; + size_t len; + }; + + // keep track of objects + struct ObjectTrack { + static constexpr size_t size = (4096 - sizeof(ObjectTrack *)) / sizeof(Object); + + // null if first + ObjectTrack *prev; + Object objects[size]; + }; + static_assert(sizeof(ObjectTrack) <= 4096, "unwanted struct padding"); + + // active object track + ObjectTrack *object_track; + size_t object_track_remain; + + ATTRIBUTE_RETURNS_NOALIAS inline void *allocate(const mem::TypeInfo& info, size_t count); + inline void *reallocate(const mem::TypeInfo& info, void *old_ptr, size_t old_count, size_t new_count); + + inline void new_segment(); + inline void track_segment(); + inline void track_object(Object object); +}; + +void *ArenaAllocator::Impl::allocate(const mem::TypeInfo& info, size_t count) { +#ifndef NDEBUG + // make behavior when size == 0 portable + if (info.size == 0 || count == 0) + return nullptr; +#endif + const size_t nbytes = info.size * count; + this->segment_offset = (this->segment_offset + (info.alignment - 1)) & ~(info.alignment - 1); + if (nbytes >= Segment::object_threshold) { + auto ptr = this->backing->allocate(nbytes); + this->track_object({ptr, nbytes}); + return ptr; + } + if (this->segment_offset + nbytes > Segment::size) + this->new_segment(); + auto ptr = &this->segment->data[this->segment_offset]; + this->segment_offset += nbytes; + return ptr; +} + +void *ArenaAllocator::Impl::reallocate(const mem::TypeInfo& info, void *old_ptr, size_t old_count, size_t new_count) { +#ifndef NDEBUG + // make behavior when size == 0 portable + if (info.size == 0 && old_ptr == nullptr) + return nullptr; +#endif + const size_t new_nbytes = info.size * new_count; + if (new_nbytes <= info.size * old_count) + return old_ptr; + const size_t old_nbytes = info.size * old_count; + this->segment_offset = (this->segment_offset + (info.alignment - 1)) & ~(info.alignment - 1); + if (new_nbytes >= Segment::object_threshold) { + auto new_ptr = this->backing->allocate(new_nbytes); + this->track_object({new_ptr, new_nbytes}); + memcpy(new_ptr, old_ptr, old_nbytes); + return new_ptr; + } + if (this->segment_offset + new_nbytes > Segment::size) + this->new_segment(); + auto new_ptr = &this->segment->data[this->segment_offset]; + this->segment_offset += new_nbytes; + memcpy(new_ptr, old_ptr, old_nbytes); + return new_ptr; +} + +void ArenaAllocator::Impl::new_segment() { + this->segment = this->backing->create(); + this->segment_offset = 0; + this->track_segment(); +} + +void ArenaAllocator::Impl::track_segment() { + assert(this->segment != nullptr); + if (this->segment_track_remain < 1) { + auto prev = this->segment_track; + this->segment_track = this->backing->create(); + this->segment_track->prev = prev; + this->segment_track_remain = SegmentTrack::size; + } + this->segment_track_remain -= 1; + this->segment_track->segments[this->segment_track_remain] = this->segment; +} + +void ArenaAllocator::Impl::track_object(Object object) { + if (this->object_track_remain < 1) { + auto prev = this->object_track; + this->object_track = this->backing->create(); + this->object_track->prev = prev; + this->object_track_remain = ObjectTrack::size; + } + this->object_track_remain -= 1; + this->object_track->objects[this->object_track_remain] = object; +} + +void ArenaAllocator::init(Allocator *backing, const char *name) { +#ifdef ZIG_ENABLE_MEM_PROFILE + this->profile = bootstrap_allocator.create(); + this->profile->init(name, "ArenaAllocator"); +#endif + this->impl = bootstrap_allocator.create(); + { + auto &r = *this->impl; + r.backing = backing; + r.segment_offset = Impl::Segment::size; + } +} + +void ArenaAllocator::deinit() { + auto &backing = *this->impl->backing; + + // segments + if (this->impl->segment_track) { + // active track is not full and bounded by track_remain + auto prev = this->impl->segment_track->prev; + { + auto t = this->impl->segment_track; + for (size_t i = this->impl->segment_track_remain; i < Impl::SegmentTrack::size; ++i) + backing.destroy(t->segments[i]); + backing.destroy(t); + } + + // previous tracks are full + for (auto t = prev; t != nullptr;) { + for (size_t i = 0; i < Impl::SegmentTrack::size; ++i) + backing.destroy(t->segments[i]); + prev = t->prev; + backing.destroy(t); + t = prev; + } + } + + // objects + if (this->impl->object_track) { + // active track is not full and bounded by track_remain + auto prev = this->impl->object_track->prev; + { + auto t = this->impl->object_track; + for (size_t i = this->impl->object_track_remain; i < Impl::ObjectTrack::size; ++i) { + auto &obj = t->objects[i]; + backing.deallocate(obj.ptr, obj.len); + } + backing.destroy(t); + } + + // previous tracks are full + for (auto t = prev; t != nullptr;) { + for (size_t i = 0; i < Impl::ObjectTrack::size; ++i) { + auto &obj = t->objects[i]; + backing.deallocate(obj.ptr, obj.len); + } + prev = t->prev; + backing.destroy(t); + t = prev; + } + } + +#ifdef ZIG_ENABLE_MEM_PROFILE + assert(this->profile); + this->profile->deinit(); + bootstrap_allocator.destroy(this->profile); + this->profile = nullptr; +#endif +} + +ArenaAllocator *ArenaAllocator::construct(mem::Allocator *allocator, mem::Allocator *backing, const char *name) { + auto p = new(allocator->create()) ArenaAllocator; + p->init(backing, name); + return p; +} + +void ArenaAllocator::destruct(mem::Allocator *allocator) { + this->deinit(); + allocator->destroy(this); +} + +#ifdef ZIG_ENABLE_MEM_PROFILE +void ArenaAllocator::print_report(FILE *file) { + this->profile->print_report(file); +} +#endif + +void *ArenaAllocator::internal_allocate(const mem::TypeInfo &info, size_t count) { +#ifdef ZIG_ENABLE_MEM_PROFILE + this->profile->record_alloc(info, count); +#endif + return this->impl->allocate(info, count); +} + +void *ArenaAllocator::internal_allocate_nonzero(const mem::TypeInfo &info, size_t count) { +#ifdef ZIG_ENABLE_MEM_PROFILE + this->profile->record_alloc(info, count); +#endif + return this->impl->allocate(info, count); +} + +void *ArenaAllocator::internal_reallocate(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) { + return this->internal_reallocate_nonzero(info, old_ptr, old_count, new_count); +} + +void *ArenaAllocator::internal_reallocate_nonzero(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) { +#ifdef ZIG_ENABLE_MEM_PROFILE + this->profile->record_dealloc(info, old_count); + this->profile->record_alloc(info, new_count); +#endif + return this->impl->reallocate(info, old_ptr, old_count, new_count); +} + +void ArenaAllocator::internal_deallocate(const mem::TypeInfo &info, void *ptr, size_t count) { +#ifdef ZIG_ENABLE_MEM_PROFILE + this->profile->record_dealloc(info, count); +#endif + // noop +} + +BootstrapAllocator bootstrap_allocator_state; +mem::Allocator &bootstrap_allocator = bootstrap_allocator_state; + +CAllocator c_allocator_state; +mem::Allocator &c_allocator = c_allocator_state; + +} // namespace heap diff --git a/src/heap.hpp b/src/heap.hpp new file mode 100644 index 0000000000..e22ec42967 --- /dev/null +++ b/src/heap.hpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2020 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef ZIG_HEAP_HPP +#define ZIG_HEAP_HPP + +#include "config.h" +#include "util_base.hpp" +#include "mem.hpp" + +#ifdef ZIG_ENABLE_MEM_PROFILE +namespace mem { + struct Profile; +} +#endif + +namespace heap { + +struct BootstrapAllocator final : mem::Allocator { + void init(const char *name); + void deinit(); + void destruct(Allocator *allocator) {} + +private: + ATTRIBUTE_RETURNS_NOALIAS void *internal_allocate(const mem::TypeInfo &info, size_t count) final; + ATTRIBUTE_RETURNS_NOALIAS void *internal_allocate_nonzero(const mem::TypeInfo &info, size_t count) final; + void *internal_reallocate(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) final; + void *internal_reallocate_nonzero(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) final; + void internal_deallocate(const mem::TypeInfo &info, void *ptr, size_t count) final; +}; + +struct CAllocator final : mem::Allocator { + void init(const char *name); + void deinit(); + + static CAllocator *construct(mem::Allocator *allocator, const char *name); + void destruct(mem::Allocator *allocator) final; + +#ifdef ZIG_ENABLE_MEM_PROFILE + void print_report(FILE *file = nullptr); +#endif + +private: + ATTRIBUTE_RETURNS_NOALIAS void *internal_allocate(const mem::TypeInfo &info, size_t count) final; + ATTRIBUTE_RETURNS_NOALIAS void *internal_allocate_nonzero(const mem::TypeInfo &info, size_t count) final; + void *internal_reallocate(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) final; + void *internal_reallocate_nonzero(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) final; + void internal_deallocate(const mem::TypeInfo &info, void *ptr, size_t count) final; + +#ifdef ZIG_ENABLE_MEM_PROFILE + mem::Profile *profile; +#endif +}; + +// +// arena allocator +// +// - allocations are backed by the underlying allocator's memory +// - allocations are N:1 relationship to underlying allocations +// - dellocations are noops +// - deinit() releases all underlying memory +// +struct ArenaAllocator final : mem::Allocator { + void init(Allocator *backing, const char *name); + void deinit(); + + static ArenaAllocator *construct(mem::Allocator *allocator, mem::Allocator *backing, const char *name); + void destruct(mem::Allocator *allocator) final; + +#ifdef ZIG_ENABLE_MEM_PROFILE + void print_report(FILE *file = nullptr); +#endif + +private: + ATTRIBUTE_RETURNS_NOALIAS void *internal_allocate(const mem::TypeInfo &info, size_t count) final; + ATTRIBUTE_RETURNS_NOALIAS void *internal_allocate_nonzero(const mem::TypeInfo &info, size_t count) final; + void *internal_reallocate(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) final; + void *internal_reallocate_nonzero(const mem::TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) final; + void internal_deallocate(const mem::TypeInfo &info, void *ptr, size_t count) final; + +#ifdef ZIG_ENABLE_MEM_PROFILE + mem::Profile *profile; +#endif + + struct Impl; + Impl *impl; +}; + +extern BootstrapAllocator bootstrap_allocator_state; +extern mem::Allocator &bootstrap_allocator; + +extern CAllocator c_allocator_state; +extern mem::Allocator &c_allocator; + +} // namespace heap + +#endif diff --git a/src/ir.cpp b/src/ir.cpp index a486ae8e6d..da02313089 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -267,479 +267,470 @@ static IrInstGen *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, static ResultLoc *no_result_loc(void); static IrInstGen *ir_analyze_test_non_null(IrAnalyze *ira, IrInst *source_inst, IrInstGen *value); static IrInstGen *ir_error_dependency_loop(IrAnalyze *ira, IrInst *source_instr); +static IrInstGen *ir_const_undef(IrAnalyze *ira, IrInst *source_instruction, ZigType *ty); static void destroy_instruction_src(IrInstSrc *inst) { -#ifdef ZIG_ENABLE_MEM_PROFILE - const char *name = ir_inst_src_type_str(inst->id); -#else - const char *name = nullptr; -#endif switch (inst->id) { case IrInstSrcIdInvalid: zig_unreachable(); case IrInstSrcIdReturn: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdConst: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdBinOp: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdMergeErrSets: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdDeclVar: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdCall: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdCallExtra: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdUnOp: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdCondBr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdBr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdPhi: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdContainerInitList: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdContainerInitFields: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdUnreachable: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdElemPtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdVarPtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdLoadPtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdStorePtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdTypeOf: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdFieldPtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSetCold: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSetRuntimeSafety: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSetFloatMode: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdArrayType: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSliceType: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdAnyFrameType: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdAsm: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSizeOf: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdTestNonNull: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdOptionalUnwrapPtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdPopCount: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdClz: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdCtz: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdBswap: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdBitReverse: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSwitchBr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSwitchVar: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSwitchElseVar: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSwitchTarget: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdImport: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdRef: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdCompileErr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdCompileLog: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdErrName: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdCImport: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdCInclude: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdCDefine: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdCUndef: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdEmbedFile: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdCmpxchg: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdFence: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdTruncate: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdIntCast: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdFloatCast: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdErrSetCast: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdFromBytes: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdToBytes: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdIntToFloat: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdFloatToInt: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdBoolToInt: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdIntType: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdVectorType: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdShuffleVector: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSplat: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdBoolNot: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdMemset: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdMemcpy: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSlice: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdMemberCount: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdMemberType: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdMemberName: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdBreakpoint: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdReturnAddress: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdFrameAddress: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdFrameHandle: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdFrameType: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdFrameSize: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdAlignOf: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdOverflowOp: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdTestErr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdUnwrapErrCode: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdUnwrapErrPayload: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdFnProto: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdTestComptime: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdPtrCast: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdBitCast: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdPtrToInt: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdIntToPtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdIntToEnum: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdIntToErr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdErrToInt: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdCheckSwitchProngs: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdCheckStatementIsVoid: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdTypeName: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdTagName: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdPtrType: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdDeclRef: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdPanic: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdFieldParentPtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdByteOffsetOf: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdBitOffsetOf: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdTypeInfo: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdType: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdHasField: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdTypeId: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSetEvalBranchQuota: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdAlignCast: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdImplicitCast: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdResolveResult: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdResetResult: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdOpaqueType: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSetAlignStack: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdArgType: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdTagType: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdExport: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdErrorReturnTrace: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdErrorUnion: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdAtomicRmw: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSaveErrRetAddr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdAddImplicitReturnType: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdFloatOp: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdMulAdd: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdAtomicLoad: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdAtomicStore: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdEnumToInt: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdCheckRuntimeScope: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdHasDecl: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdUndeclaredIdent: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdAlloca: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdEndExpr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdUnionInitNamedField: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSuspendBegin: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSuspendFinish: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdResume: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdAwait: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSpillBegin: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSpillEnd: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdCallArgs: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); } zig_unreachable(); } void destroy_instruction_gen(IrInstGen *inst) { -#ifdef ZIG_ENABLE_MEM_PROFILE - const char *name = ir_inst_gen_type_str(inst->id); -#else - const char *name = nullptr; -#endif switch (inst->id) { case IrInstGenIdInvalid: zig_unreachable(); case IrInstGenIdReturn: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdConst: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdBinOp: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdCast: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdCall: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdCondBr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdBr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdPhi: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdUnreachable: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdElemPtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdVarPtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdReturnPtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdLoadPtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdStorePtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdVectorStoreElem: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdStructFieldPtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdUnionFieldPtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdAsm: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdTestNonNull: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdOptionalUnwrapPtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdPopCount: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdClz: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdCtz: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdBswap: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdBitReverse: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdSwitchBr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdUnionTag: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdRef: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdErrName: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdCmpxchg: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdFence: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdTruncate: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdShuffleVector: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdSplat: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdBoolNot: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdMemset: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdMemcpy: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdSlice: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdBreakpoint: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdReturnAddress: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdFrameAddress: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdFrameHandle: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdFrameSize: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdOverflowOp: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdTestErr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdUnwrapErrCode: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdUnwrapErrPayload: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdOptionalWrap: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdErrWrapCode: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdErrWrapPayload: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdPtrCast: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdBitCast: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdWidenOrShorten: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdPtrToInt: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdIntToPtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdIntToEnum: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdIntToErr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdErrToInt: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdTagName: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdPanic: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdFieldParentPtr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdAlignCast: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdErrorReturnTrace: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdAtomicRmw: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdSaveErrRetAddr: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdFloatOp: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdMulAdd: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdAtomicLoad: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdAtomicStore: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdDeclVar: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdArrayToVector: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdVectorToArray: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdPtrOfArrayToSlice: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdAssertZero: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdAssertNonNull: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdResizeSlice: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdAlloca: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdSuspendBegin: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdSuspendFinish: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdResume: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdAwait: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdSpillBegin: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdSpillEnd: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdVectorExtractElem: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdBinaryNot: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdNegation: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdNegationWrapping: - return destroy(reinterpret_cast(inst), name); + return heap::c_allocator.destroy(reinterpret_cast(inst)); } zig_unreachable(); } @@ -760,34 +751,19 @@ static void ira_deref(IrAnalyze *ira) { IrInstSrc *pass1_inst = pass1_bb->instruction_list.items[inst_i]; destroy_instruction_src(pass1_inst); } - destroy(pass1_bb, "IrBasicBlockSrc"); + heap::c_allocator.destroy(pass1_bb); } ira->old_irb.exec->basic_block_list.deinit(); ira->old_irb.exec->tld_list.deinit(); - // cannot destroy here because of var->owner_exec - //destroy(ira->old_irb.exec, "IrExecutableSrc"); + heap::c_allocator.destroy(ira->old_irb.exec); ira->src_implicit_return_type_list.deinit(); ira->resume_stack.deinit(); - destroy(ira, "IrAnalyze"); + heap::c_allocator.destroy(ira); } -static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) { +static ZigValue *const_ptr_pointee_unchecked_no_isf(CodeGen *g, ZigValue *const_val) { assert(get_src_ptr_type(const_val->type) != nullptr); assert(const_val->special == ConstValSpecialStatic); - ZigValue *result; - - InferredStructField *isf = const_val->type->data.pointer.inferred_struct_field; - if (isf != nullptr) { - TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name); - assert(field != nullptr); - if (field->is_comptime) { - assert(field->init_val != nullptr); - return field->init_val; - } - assert(const_val->data.x_ptr.special == ConstPtrSpecialRef); - ZigValue *struct_val = const_val->data.x_ptr.data.ref.pointee; - return struct_val->data.x_struct.fields[field->src_index]; - } switch (type_has_one_possible_value(g, const_val->type->data.pointer.child_type)) { case OnePossibleValueInvalid: @@ -798,6 +774,7 @@ static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) { break; } + ZigValue *result; switch (const_val->data.x_ptr.special) { case ConstPtrSpecialInvalid: zig_unreachable(); @@ -843,6 +820,26 @@ static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) { return result; } +static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) { + assert(get_src_ptr_type(const_val->type) != nullptr); + assert(const_val->special == ConstValSpecialStatic); + + InferredStructField *isf = const_val->type->data.pointer.inferred_struct_field; + if (isf != nullptr) { + TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name); + assert(field != nullptr); + if (field->is_comptime) { + assert(field->init_val != nullptr); + return field->init_val; + } + ZigValue *struct_val = const_ptr_pointee_unchecked_no_isf(g, const_val); + assert(struct_val->type->id == ZigTypeIdStruct); + return struct_val->data.x_struct.fields[field->src_index]; + } + + return const_ptr_pointee_unchecked_no_isf(g, const_val); +} + static bool is_tuple(ZigType *type) { return type->id == ZigTypeIdStruct && type->data.structure.special == StructSpecialInferredTuple; } @@ -1010,8 +1007,8 @@ static void ir_ref_var(ZigVar *var) { static void create_result_ptr(CodeGen *codegen, ZigType *expected_type, ZigValue **out_result, ZigValue **out_result_ptr) { - ZigValue *result = create_const_vals(1); - ZigValue *result_ptr = create_const_vals(1); + ZigValue *result = codegen->pass1_arena->create(); + ZigValue *result_ptr = codegen->pass1_arena->create(); result->special = ConstValSpecialUndef; result->type = expected_type; result_ptr->special = ConstValSpecialStatic; @@ -1043,14 +1040,11 @@ ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) { assert(result->special != ConstValSpecialRuntime); ZigType *res_type = result->data.x_type; - destroy(result_ptr, "ZigValue"); - destroy(result, "ZigValue"); - return res_type; } static IrBasicBlockSrc *ir_create_basic_block(IrBuilderSrc *irb, Scope *scope, const char *name_hint) { - IrBasicBlockSrc *result = allocate(1, "IrBasicBlockSrc"); + IrBasicBlockSrc *result = heap::c_allocator.create(); result->scope = scope; result->name_hint = name_hint; result->debug_id = exec_next_debug_id(irb->exec); @@ -1059,7 +1053,7 @@ static IrBasicBlockSrc *ir_create_basic_block(IrBuilderSrc *irb, Scope *scope, c } static IrBasicBlockGen *ir_create_basic_block_gen(IrAnalyze *ira, Scope *scope, const char *name_hint) { - IrBasicBlockGen *result = allocate(1, "IrBasicBlockGen"); + IrBasicBlockGen *result = heap::c_allocator.create(); result->scope = scope; result->name_hint = name_hint; result->debug_id = exec_next_debug_id_gen(ira->new_irb.exec); @@ -1976,12 +1970,7 @@ static constexpr IrInstGenId ir_inst_id(IrInstGenConst *) { template static T *ir_create_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { - const char *name = nullptr; -#ifdef ZIG_ENABLE_MEM_PROFILE - T *dummy = nullptr; - name = ir_inst_src_type_str(ir_inst_id(dummy)); -#endif - T *special_instruction = allocate(1, name); + T *special_instruction = heap::c_allocator.create(); special_instruction->base.id = ir_inst_id(special_instruction); special_instruction->base.base.scope = scope; special_instruction->base.base.source_node = source_node; @@ -1992,29 +1981,19 @@ static T *ir_create_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source template static T *ir_create_inst_gen(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { - const char *name = nullptr; -#ifdef ZIG_ENABLE_MEM_PROFILE - T *dummy = nullptr; - name = ir_inst_gen_type_str(ir_inst_id(dummy)); -#endif - T *special_instruction = allocate(1, name); + T *special_instruction = heap::c_allocator.create(); special_instruction->base.id = ir_inst_id(special_instruction); special_instruction->base.base.scope = scope; special_instruction->base.base.source_node = source_node; special_instruction->base.base.debug_id = exec_next_debug_id_gen(irb->exec); special_instruction->base.owner_bb = irb->current_basic_block; - special_instruction->base.value = allocate(1, "ZigValue"); + special_instruction->base.value = irb->codegen->pass1_arena->create(); return special_instruction; } template static T *ir_create_inst_noval(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { - const char *name = nullptr; -#ifdef ZIG_ENABLE_MEM_PROFILE - T *dummy = nullptr; - name = ir_inst_gen_type_str(ir_inst_id(dummy)); -#endif - T *special_instruction = allocate(1, name); + T *special_instruction = heap::c_allocator.create(); special_instruction->base.id = ir_inst_id(special_instruction); special_instruction->base.base.scope = scope; special_instruction->base.base.source_node = source_node; @@ -2056,11 +2035,11 @@ static T *ir_build_inst_void(IrBuilderGen *irb, Scope *scope, AstNode *source_no IrInstGen *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn, ZigType *var_type, const char *name_hint) { - IrInstGenAlloca *alloca_gen = allocate(1); + IrInstGenAlloca *alloca_gen = heap::c_allocator.create(); alloca_gen->base.id = IrInstGenIdAlloca; alloca_gen->base.base.source_node = source_node; alloca_gen->base.base.scope = scope; - alloca_gen->base.value = allocate(1, "ZigValue"); + alloca_gen->base.value = g->pass1_arena->create(); alloca_gen->base.value->type = get_pointer_to_type(g, var_type, false); alloca_gen->base.base.ref_count = 1; alloca_gen->name_hint = name_hint; @@ -2150,7 +2129,7 @@ static IrInstSrc *ir_build_const_undefined(IrBuilderSrc *irb, Scope *scope, AstN static IrInstSrc *ir_build_const_uint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, uint64_t value) { IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = create_const_vals(1); + const_instruction->value = irb->codegen->pass1_arena->create(); const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_int; const_instruction->value->special = ConstValSpecialStatic; bigint_init_unsigned(&const_instruction->value->data.x_bigint, value); @@ -2159,7 +2138,7 @@ static IrInstSrc *ir_build_const_uint(IrBuilderSrc *irb, Scope *scope, AstNode * static IrInstSrc *ir_build_const_bigint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, BigInt *bigint) { IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = create_const_vals(1); + const_instruction->value = irb->codegen->pass1_arena->create(); const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_int; const_instruction->value->special = ConstValSpecialStatic; bigint_init_bigint(&const_instruction->value->data.x_bigint, bigint); @@ -2168,7 +2147,7 @@ static IrInstSrc *ir_build_const_bigint(IrBuilderSrc *irb, Scope *scope, AstNode static IrInstSrc *ir_build_const_bigfloat(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, BigFloat *bigfloat) { IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = create_const_vals(1); + const_instruction->value = irb->codegen->pass1_arena->create(); const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_float; const_instruction->value->special = ConstValSpecialStatic; bigfloat_init_bigfloat(&const_instruction->value->data.x_bigfloat, bigfloat); @@ -2184,7 +2163,7 @@ static IrInstSrc *ir_build_const_null(IrBuilderSrc *irb, Scope *scope, AstNode * static IrInstSrc *ir_build_const_usize(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, uint64_t value) { IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = create_const_vals(1); + const_instruction->value = irb->codegen->pass1_arena->create(); const_instruction->value->type = irb->codegen->builtin_types.entry_usize; const_instruction->value->special = ConstValSpecialStatic; bigint_init_unsigned(&const_instruction->value->data.x_bigint, value); @@ -2195,7 +2174,7 @@ static IrInstSrc *ir_create_const_type(IrBuilderSrc *irb, Scope *scope, AstNode ZigType *type_entry) { IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); - const_instruction->value = create_const_vals(1); + const_instruction->value = irb->codegen->pass1_arena->create(); const_instruction->value->type = irb->codegen->builtin_types.entry_type; const_instruction->value->special = ConstValSpecialStatic; const_instruction->value->data.x_type = type_entry; @@ -2212,7 +2191,7 @@ static IrInstSrc *ir_build_const_type(IrBuilderSrc *irb, Scope *scope, AstNode * static IrInstSrc *ir_build_const_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigType *import) { IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = create_const_vals(1); + const_instruction->value = irb->codegen->pass1_arena->create(); const_instruction->value->type = irb->codegen->builtin_types.entry_type; const_instruction->value->special = ConstValSpecialStatic; const_instruction->value->data.x_type = import; @@ -2221,7 +2200,7 @@ static IrInstSrc *ir_build_const_import(IrBuilderSrc *irb, Scope *scope, AstNode static IrInstSrc *ir_build_const_bool(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, bool value) { IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = create_const_vals(1); + const_instruction->value = irb->codegen->pass1_arena->create(); const_instruction->value->type = irb->codegen->builtin_types.entry_bool; const_instruction->value->special = ConstValSpecialStatic; const_instruction->value->data.x_bool = value; @@ -2230,7 +2209,7 @@ static IrInstSrc *ir_build_const_bool(IrBuilderSrc *irb, Scope *scope, AstNode * static IrInstSrc *ir_build_const_enum_literal(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *name) { IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->value = create_const_vals(1); + const_instruction->value = irb->codegen->pass1_arena->create(); const_instruction->value->type = irb->codegen->builtin_types.entry_enum_literal; const_instruction->value->special = ConstValSpecialStatic; const_instruction->value->data.x_enum_literal = name; @@ -2239,7 +2218,7 @@ static IrInstSrc *ir_build_const_enum_literal(IrBuilderSrc *irb, Scope *scope, A static IrInstSrc *ir_create_const_str_lit(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *str) { IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); - const_instruction->value = create_const_vals(1); + const_instruction->value = irb->codegen->pass1_arena->create(); init_const_str_lit(irb->codegen, const_instruction->value, str); return &const_instruction->base; @@ -5237,7 +5216,7 @@ static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node, switch (node->data.return_expr.kind) { case ReturnKindUnconditional: { - ResultLocReturn *result_loc_ret = allocate(1, "ResultLocReturn"); + ResultLocReturn *result_loc_ret = heap::c_allocator.create(); result_loc_ret->base.id = ResultLocIdReturn; ir_build_reset_result(irb, scope, node, &result_loc_ret->base); @@ -5325,7 +5304,7 @@ static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node, ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val, nullptr)); IrInstSrcSpillBegin *spill_begin = ir_build_spill_begin_src(irb, scope, node, err_val, SpillIdRetErrCode); - ResultLocReturn *result_loc_ret = allocate(1, "ResultLocReturn"); + ResultLocReturn *result_loc_ret = heap::c_allocator.create(); result_loc_ret->base.id = ResultLocIdReturn; ir_build_reset_result(irb, scope, node, &result_loc_ret->base); ir_build_end_expr(irb, scope, node, err_val, &result_loc_ret->base); @@ -5353,12 +5332,12 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime, bool skip_name_check) { - ZigVar *variable_entry = allocate(1, "ZigVar"); + ZigVar *variable_entry = heap::c_allocator.create(); variable_entry->parent_scope = parent_scope; variable_entry->shadowable = is_shadowable; variable_entry->is_comptime = is_comptime; variable_entry->src_arg_index = SIZE_MAX; - variable_entry->const_value = create_const_vals(1); + variable_entry->const_value = codegen->pass1_arena->create(); if (is_comptime != nullptr) { is_comptime->base.ref_count += 1; @@ -5418,15 +5397,12 @@ static ZigVar *ir_create_var(IrBuilderSrc *irb, AstNode *node, Scope *scope, Buf ZigVar *var = create_local_var(irb->codegen, node, scope, (is_underscored ? nullptr : name), src_is_const, gen_is_const, (is_underscored ? true : is_shadowable), is_comptime, false); - if (is_comptime != nullptr || gen_is_const) { - var->owner_exec = irb->exec; - } assert(var->child_scope); return var; } static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) { - ResultLocPeer *result = allocate(1, "ResultLocPeer"); + ResultLocPeer *result = heap::c_allocator.create(); result->base.id = ResultLocIdPeer; result->base.source_instruction = peer_parent->base.source_instruction; result->parent = peer_parent; @@ -5465,7 +5441,7 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode * scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, ir_should_inline(irb->exec, parent_scope)); - scope_block->peer_parent = allocate(1, "ResultLocPeerParent"); + scope_block->peer_parent = heap::c_allocator.create(); scope_block->peer_parent->base.id = ResultLocIdPeerParent; scope_block->peer_parent->base.source_instruction = scope_block->is_comptime; scope_block->peer_parent->base.allow_write_through_const = result_loc->allow_write_through_const; @@ -5555,7 +5531,7 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode * // only generate unconditional defers ir_mark_gen(ir_build_add_implicit_return_type(irb, child_scope, block_node, result, nullptr)); - ResultLocReturn *result_loc_ret = allocate(1, "ResultLocReturn"); + ResultLocReturn *result_loc_ret = heap::c_allocator.create(); result_loc_ret->base.id = ResultLocIdReturn; ir_build_reset_result(irb, parent_scope, block_node, &result_loc_ret->base); ir_mark_gen(ir_build_end_expr(irb, parent_scope, block_node, result, &result_loc_ret->base)); @@ -5597,7 +5573,7 @@ static IrInstSrc *ir_gen_assign(IrBuilderSrc *irb, Scope *scope, AstNode *node) if (lvalue == irb->codegen->invalid_inst_src) return irb->codegen->invalid_inst_src; - ResultLocInstruction *result_loc_inst = allocate(1, "ResultLocInstruction"); + ResultLocInstruction *result_loc_inst = heap::c_allocator.create(); result_loc_inst->base.id = ResultLocIdInstruction; result_loc_inst->base.source_instruction = lvalue; ir_ref_instruction(lvalue, irb->current_basic_block); @@ -5669,10 +5645,10 @@ static IrInstSrc *ir_gen_bool_or(IrBuilderSrc *irb, Scope *scope, AstNode *node) ir_set_cursor_at_end_and_append_block(irb, true_block); - IrInstSrc **incoming_values = allocate(2, "IrInstSrc *"); + IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = val1; incoming_values[1] = val2; - IrBasicBlockSrc **incoming_blocks = allocate(2, "IrBasicBlockSrc *"); + IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); incoming_blocks[0] = post_val1_block; incoming_blocks[1] = post_val2_block; @@ -5711,10 +5687,10 @@ static IrInstSrc *ir_gen_bool_and(IrBuilderSrc *irb, Scope *scope, AstNode *node ir_set_cursor_at_end_and_append_block(irb, false_block); - IrInstSrc **incoming_values = allocate(2); + IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = val1; incoming_values[1] = val2; - IrBasicBlockSrc **incoming_blocks = allocate(2, "IrBasicBlockSrc *"); + IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); incoming_blocks[0] = post_val1_block; incoming_blocks[1] = post_val2_block; @@ -5724,7 +5700,7 @@ static IrInstSrc *ir_gen_bool_and(IrBuilderSrc *irb, Scope *scope, AstNode *node static ResultLocPeerParent *ir_build_result_peers(IrBuilderSrc *irb, IrInstSrc *cond_br_inst, IrBasicBlockSrc *end_block, ResultLoc *parent, IrInstSrc *is_comptime) { - ResultLocPeerParent *peer_parent = allocate(1); + ResultLocPeerParent *peer_parent = heap::c_allocator.create(); peer_parent->base.id = ResultLocIdPeerParent; peer_parent->base.source_instruction = cond_br_inst; peer_parent->base.allow_write_through_const = parent->allow_write_through_const; @@ -5802,10 +5778,10 @@ static IrInstSrc *ir_gen_orelse(IrBuilderSrc *irb, Scope *parent_scope, AstNode ir_build_br(irb, parent_scope, node, end_block, is_comptime); ir_set_cursor_at_end_and_append_block(irb, end_block); - IrInstSrc **incoming_values = allocate(2); + IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = null_result; incoming_values[1] = unwrapped_payload; - IrBasicBlockSrc **incoming_blocks = allocate(2, "IrBasicBlockSrc *"); + IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); incoming_blocks[0] = after_null_block; incoming_blocks[1] = after_ok_block; IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); @@ -5959,7 +5935,7 @@ static void populate_invalid_variable_in_scope(CodeGen *g, Scope *scope, AstNode } scope = scope->parent; } - TldVar *tld_var = allocate(1); + TldVar *tld_var = heap::c_allocator.create(); init_tld(&tld_var->base, TldIdVar, var_name, VisibModPub, node, &scope_decls->base); tld_var->base.resolution = TldResolutionInvalid; tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false, @@ -5976,7 +5952,7 @@ static IrInstSrc *ir_gen_symbol(IrBuilderSrc *irb, Scope *scope, AstNode *node, if (buf_eql_str(variable_name, "_")) { if (lval == LValPtr) { IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, node); - const_instruction->value = create_const_vals(1); + const_instruction->value = irb->codegen->pass1_arena->create(); const_instruction->value->type = get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_void, false); const_instruction->value->special = ConstValSpecialStatic; @@ -6170,7 +6146,7 @@ static IrInstSrc *ir_gen_async_call(IrBuilderSrc *irb, Scope *scope, AstNode *aw return fn_ref; size_t arg_count = call_node->data.fn_call_expr.params.length - arg_offset; - IrInstSrc **args = allocate(arg_count); + IrInstSrc **args = heap::c_allocator.allocate(arg_count); for (size_t i = 0; i < arg_count; i += 1) { AstNode *arg_node = call_node->data.fn_call_expr.params.at(i + arg_offset); IrInstSrc *arg = ir_gen_node(irb, arg_node, scope); @@ -6196,7 +6172,7 @@ static IrInstSrc *ir_gen_fn_call_with_args(IrBuilderSrc *irb, Scope *scope, AstN IrInstSrc *fn_type = ir_build_typeof(irb, scope, source_node, fn_ref); - IrInstSrc **args = allocate(args_len); + IrInstSrc **args = heap::c_allocator.allocate(args_len); for (size_t i = 0; i < args_len; i += 1) { AstNode *arg_node = args_ptr[i]; @@ -6381,7 +6357,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod } case BuiltinFnIdCompileLog: { - IrInstSrc **args = allocate(actual_param_count); + IrInstSrc **args = heap::c_allocator.allocate(actual_param_count); for (size_t i = 0; i < actual_param_count; i += 1) { AstNode *arg_node = node->data.fn_call_expr.params.at(i); @@ -7006,7 +6982,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod if (dest_type == irb->codegen->invalid_inst_src) return dest_type; - ResultLocBitCast *result_loc_bit_cast = allocate(1); + ResultLocBitCast *result_loc_bit_cast = heap::c_allocator.create(); result_loc_bit_cast->base.id = ResultLocIdBitCast; result_loc_bit_cast->base.source_instruction = dest_type; result_loc_bit_cast->base.allow_write_through_const = result_loc->allow_write_through_const; @@ -7555,10 +7531,10 @@ static IrInstSrc *ir_gen_if_bool_expr(IrBuilderSrc *irb, Scope *scope, AstNode * ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); ir_set_cursor_at_end_and_append_block(irb, endif_block); - IrInstSrc **incoming_values = allocate(2); + IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = then_expr_result; incoming_values[1] = else_expr_result; - IrBasicBlockSrc **incoming_blocks = allocate(2, "IrBasicBlockSrc *"); + IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); incoming_blocks[0] = after_then_block; incoming_blocks[1] = after_else_block; @@ -7759,7 +7735,7 @@ static IrInstSrc *ir_gen_union_init_expr(IrBuilderSrc *irb, Scope *scope, AstNod IrInstSrc *field_ptr = ir_build_field_ptr_instruction(irb, scope, source_node, container_ptr, field_name, true); - ResultLocInstruction *result_loc_inst = allocate(1); + ResultLocInstruction *result_loc_inst = heap::c_allocator.create(); result_loc_inst->base.id = ResultLocIdInstruction; result_loc_inst->base.source_instruction = field_ptr; ir_ref_instruction(field_ptr, irb->current_basic_block); @@ -7835,7 +7811,7 @@ static IrInstSrc *ir_gen_container_init_expr(IrBuilderSrc *irb, Scope *scope, As nullptr); size_t field_count = container_init_expr->entries.length; - IrInstSrcContainerInitFieldsField *fields = allocate(field_count); + IrInstSrcContainerInitFieldsField *fields = heap::c_allocator.allocate(field_count); for (size_t i = 0; i < field_count; i += 1) { AstNode *entry_node = container_init_expr->entries.at(i); assert(entry_node->type == NodeTypeStructValueField); @@ -7844,7 +7820,7 @@ static IrInstSrc *ir_gen_container_init_expr(IrBuilderSrc *irb, Scope *scope, As AstNode *expr_node = entry_node->data.struct_val_field.expr; IrInstSrc *field_ptr = ir_build_field_ptr(irb, scope, entry_node, container_ptr, name, true); - ResultLocInstruction *result_loc_inst = allocate(1); + ResultLocInstruction *result_loc_inst = heap::c_allocator.create(); result_loc_inst->base.id = ResultLocIdInstruction; result_loc_inst->base.source_instruction = field_ptr; result_loc_inst->base.allow_write_through_const = true; @@ -7874,14 +7850,14 @@ static IrInstSrc *ir_gen_container_init_expr(IrBuilderSrc *irb, Scope *scope, As IrInstSrc *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, nullptr); - IrInstSrc **result_locs = allocate(item_count); + IrInstSrc **result_locs = heap::c_allocator.allocate(item_count); for (size_t i = 0; i < item_count; i += 1) { AstNode *expr_node = container_init_expr->entries.at(i); IrInstSrc *elem_index = ir_build_const_usize(irb, scope, expr_node, i); IrInstSrc *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, elem_index, false, PtrLenSingle, init_array_type_source_node); - ResultLocInstruction *result_loc_inst = allocate(1); + ResultLocInstruction *result_loc_inst = heap::c_allocator.create(); result_loc_inst->base.id = ResultLocIdInstruction; result_loc_inst->base.source_instruction = elem_ptr; result_loc_inst->base.allow_write_through_const = true; @@ -7907,7 +7883,7 @@ static IrInstSrc *ir_gen_container_init_expr(IrBuilderSrc *irb, Scope *scope, As } static ResultLocVar *ir_build_var_result_loc(IrBuilderSrc *irb, IrInstSrc *alloca, ZigVar *var) { - ResultLocVar *result_loc_var = allocate(1); + ResultLocVar *result_loc_var = heap::c_allocator.create(); result_loc_var->base.id = ResultLocIdVar; result_loc_var->base.source_instruction = alloca; result_loc_var->base.allow_write_through_const = true; @@ -7921,7 +7897,7 @@ static ResultLocVar *ir_build_var_result_loc(IrBuilderSrc *irb, IrInstSrc *alloc static ResultLocCast *ir_build_cast_result_loc(IrBuilderSrc *irb, IrInstSrc *dest_type, ResultLoc *parent_result_loc) { - ResultLocCast *result_loc_cast = allocate(1); + ResultLocCast *result_loc_cast = heap::c_allocator.create(); result_loc_cast->base.id = ResultLocIdCast; result_loc_cast->base.source_instruction = dest_type; result_loc_cast->base.allow_write_through_const = parent_result_loc->allow_write_through_const; @@ -8764,9 +8740,9 @@ static IrInstSrc *ir_gen_asm_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node nullptr, 0, is_volatile, true); } - IrInstSrc **input_list = allocate(asm_expr->input_list.length); - IrInstSrc **output_types = allocate(asm_expr->output_list.length); - ZigVar **output_vars = allocate(asm_expr->output_list.length); + IrInstSrc **input_list = heap::c_allocator.allocate(asm_expr->input_list.length); + IrInstSrc **output_types = heap::c_allocator.allocate(asm_expr->output_list.length); + ZigVar **output_vars = heap::c_allocator.allocate(asm_expr->output_list.length); size_t return_count = 0; if (!is_volatile && asm_expr->output_list.length == 0) { add_node_error(irb->codegen, node, @@ -8900,10 +8876,10 @@ static IrInstSrc *ir_gen_if_optional_expr(IrBuilderSrc *irb, Scope *scope, AstNo ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); ir_set_cursor_at_end_and_append_block(irb, endif_block); - IrInstSrc **incoming_values = allocate(2); + IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = then_expr_result; incoming_values[1] = else_expr_result; - IrBasicBlockSrc **incoming_blocks = allocate(2, "IrBasicBlockSrc *"); + IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); incoming_blocks[0] = after_then_block; incoming_blocks[1] = after_else_block; @@ -8997,10 +8973,10 @@ static IrInstSrc *ir_gen_if_err_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); ir_set_cursor_at_end_and_append_block(irb, endif_block); - IrInstSrc **incoming_values = allocate(2); + IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = then_expr_result; incoming_values[1] = else_expr_result; - IrBasicBlockSrc **incoming_blocks = allocate(2, "IrBasicBlockSrc *"); + IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); incoming_blocks[0] = after_then_block; incoming_blocks[1] = after_else_block; @@ -9093,7 +9069,7 @@ static IrInstSrc *ir_gen_switch_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n IrInstSrcSwitchElseVar *switch_else_var = nullptr; - ResultLocPeerParent *peer_parent = allocate(1); + ResultLocPeerParent *peer_parent = heap::c_allocator.create(); peer_parent->base.id = ResultLocIdPeerParent; peer_parent->base.allow_write_through_const = result_loc->allow_write_through_const; peer_parent->end_bb = end_block; @@ -9255,7 +9231,7 @@ static IrInstSrc *ir_gen_switch_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); IrBasicBlockSrc *prong_block = ir_create_basic_block(irb, scope, "SwitchProng"); - IrInstSrc **items = allocate(prong_item_count); + IrInstSrc **items = heap::c_allocator.allocate(prong_item_count); for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) { AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); @@ -9637,10 +9613,10 @@ static IrInstSrc *ir_gen_catch(IrBuilderSrc *irb, Scope *parent_scope, AstNode * ir_build_br(irb, parent_scope, node, end_block, is_comptime); ir_set_cursor_at_end_and_append_block(irb, end_block); - IrInstSrc **incoming_values = allocate(2); + IrInstSrc **incoming_values = heap::c_allocator.allocate(2); incoming_values[0] = err_result; incoming_values[1] = unwrapped_payload; - IrBasicBlockSrc **incoming_blocks = allocate(2, "IrBasicBlockSrc *"); + IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate(2); incoming_blocks[0] = after_err_block; incoming_blocks[1] = after_ok_block; IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); @@ -9707,7 +9683,7 @@ static IrInstSrc *ir_gen_container_decl(IrBuilderSrc *irb, Scope *parent_scope, scan_decls(irb->codegen, child_scope, child_node); } - TldContainer *tld_container = allocate(1); + TldContainer *tld_container = heap::c_allocator.create(); init_tld(&tld_container->base, TldIdContainer, bare_name, VisibModPub, node, parent_scope); tld_container->type_entry = container_type; tld_container->decls_scope = child_scope; @@ -9750,7 +9726,7 @@ static ZigType *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, ZigTyp } err_set_type->data.error_set.err_count = count; - err_set_type->data.error_set.errors = allocate(count); + err_set_type->data.error_set.errors = heap::c_allocator.allocate(count); bool need_comma = false; for (uint32_t i = 0; i < set1->data.error_set.err_count; i += 1) { @@ -9797,7 +9773,7 @@ static ZigType *make_err_set_with_one_item(CodeGen *g, Scope *parent_scope, AstN err_set_type->abi_align = g->builtin_types.entry_global_error_set->abi_align; err_set_type->abi_size = g->builtin_types.entry_global_error_set->abi_size; err_set_type->data.error_set.err_count = 1; - err_set_type->data.error_set.errors = allocate(1); + err_set_type->data.error_set.errors = heap::c_allocator.create(); err_set_type->data.error_set.errors[0] = err_entry; @@ -9828,16 +9804,16 @@ static IrInstSrc *ir_gen_err_set_decl(IrBuilderSrc *irb, Scope *parent_scope, As err_set_type->size_in_bits = irb->codegen->builtin_types.entry_global_error_set->size_in_bits; err_set_type->abi_align = irb->codegen->builtin_types.entry_global_error_set->abi_align; err_set_type->abi_size = irb->codegen->builtin_types.entry_global_error_set->abi_size; - err_set_type->data.error_set.errors = allocate(err_count); + err_set_type->data.error_set.errors = heap::c_allocator.allocate(err_count); size_t errors_count = irb->codegen->errors_by_index.length + err_count; - ErrorTableEntry **errors = allocate(errors_count, "ErrorTableEntry *"); + ErrorTableEntry **errors = heap::c_allocator.allocate(errors_count); for (uint32_t i = 0; i < err_count; i += 1) { AstNode *field_node = node->data.err_set_decl.decls.at(i); AstNode *symbol_node = ast_field_to_symbol_node(field_node); Buf *err_name = symbol_node->data.symbol_expr.symbol; - ErrorTableEntry *err = allocate(1); + ErrorTableEntry *err = heap::c_allocator.create(); err->decl_node = field_node; buf_init_from_buf(&err->name, err_name); @@ -9862,7 +9838,7 @@ static IrInstSrc *ir_gen_err_set_decl(IrBuilderSrc *irb, Scope *parent_scope, As } errors[err->value] = err; } - deallocate(errors, errors_count, "ErrorTableEntry *"); + heap::c_allocator.deallocate(errors, errors_count); return ir_build_const_type(irb, parent_scope, node, err_set_type); } @@ -9870,7 +9846,7 @@ static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNod assert(node->type == NodeTypeFnProto); size_t param_count = node->data.fn_proto.params.length; - IrInstSrc **param_types = allocate(param_count); + IrInstSrc **param_types = heap::c_allocator.allocate(param_count); bool is_var_args = false; for (size_t i = 0; i < param_count; i += 1) { @@ -10151,7 +10127,7 @@ static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope } static ResultLoc *no_result_loc(void) { - ResultLocNone *result_loc_none = allocate(1); + ResultLocNone *result_loc_none = heap::c_allocator.create(); result_loc_none->base.id = ResultLocIdNone; return &result_loc_none->base; } @@ -10240,7 +10216,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutableSrc *ir_e if (!instr_is_unreachable(result)) { ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->base.source_node, result, nullptr)); // no need for save_err_ret_addr because this cannot return error - ResultLocReturn *result_loc_ret = allocate(1, "ResultLocReturn"); + ResultLocReturn *result_loc_ret = heap::c_allocator.create(); result_loc_ret->base.id = ResultLocIdReturn; ir_build_reset_result(irb, scope, node, &result_loc_ret->base); ir_mark_gen(ir_build_end_expr(irb, scope, node, result, &result_loc_ret->base)); @@ -10332,7 +10308,7 @@ static Error eval_comptime_ptr_reinterpret(IrAnalyze *ira, CodeGen *codegen, Ast if ((err = ir_read_const_ptr(ira, codegen, source_node, &tmp, ptr_val))) return err; ZigValue *child_val = const_ptr_pointee_unchecked(codegen, ptr_val); - copy_const_val(child_val, &tmp); + copy_const_val(codegen, child_val, &tmp); return ErrorNone; } @@ -11482,7 +11458,7 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp return set1; } size_t errors_count = ira->codegen->errors_by_index.length; - ErrorTableEntry **errors = allocate(errors_count, "ErrorTableEntry *"); + ErrorTableEntry **errors = heap::c_allocator.allocate(errors_count); populate_error_set_table(errors, set1); ZigList intersection_list = {}; @@ -11503,7 +11479,7 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp buf_appendf(&err_set_type->name, "%s%s", comma, buf_ptr(&existing_entry_with_docs->name)); } } - deallocate(errors, errors_count, "ErrorTableEntry *"); + heap::c_allocator.deallocate(errors, errors_count); err_set_type->data.error_set.err_count = intersection_list.length; err_set_type->data.error_set.errors = intersection_list.items; @@ -11552,10 +11528,11 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted wanted_ptr_type->data.pointer.sentinel == nullptr || (actual_ptr_type->data.pointer.sentinel != nullptr && const_values_equal(ira->codegen, wanted_ptr_type->data.pointer.sentinel, - actual_ptr_type->data.pointer.sentinel)); + actual_ptr_type->data.pointer.sentinel)) || + actual_ptr_type->data.pointer.ptr_len == PtrLenC; if (!ok_null_term_ptrs) { result.id = ConstCastResultIdPtrSentinel; - result.data.bad_ptr_sentinel = allocate_nonzero(1); + result.data.bad_ptr_sentinel = heap::c_allocator.allocate_nonzero(1); result.data.bad_ptr_sentinel->wanted_type = wanted_ptr_type; result.data.bad_ptr_sentinel->actual_type = actual_ptr_type; return result; @@ -11571,7 +11548,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile); if (!ok_cv_qualifiers) { result.id = ConstCastResultIdCV; - result.data.bad_cv = allocate_nonzero(1); + result.data.bad_cv = heap::c_allocator.allocate_nonzero(1); result.data.bad_cv->wanted_type = wanted_ptr_type; result.data.bad_cv->actual_type = actual_ptr_type; return result; @@ -11583,7 +11560,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted return child; if (child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdPointerChild; - result.data.pointer_mismatch = allocate_nonzero(1); + result.data.pointer_mismatch = heap::c_allocator.allocate_nonzero(1); result.data.pointer_mismatch->child = child; result.data.pointer_mismatch->wanted_child = wanted_ptr_type->data.pointer.child_type; result.data.pointer_mismatch->actual_child = actual_ptr_type->data.pointer.child_type; @@ -11594,7 +11571,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted (!wanted_allows_zero && !actual_allows_zero); if (!ok_allows_zero) { result.id = ConstCastResultIdBadAllowsZero; - result.data.bad_allows_zero = allocate_nonzero(1); + result.data.bad_allows_zero = heap::c_allocator.allocate_nonzero(1); result.data.bad_allows_zero->wanted_type = wanted_type; result.data.bad_allows_zero->actual_type = actual_type; return result; @@ -11634,7 +11611,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted return child; if (child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdArrayChild; - result.data.array_mismatch = allocate_nonzero(1); + result.data.array_mismatch = heap::c_allocator.allocate_nonzero(1); result.data.array_mismatch->child = child; result.data.array_mismatch->wanted_child = wanted_type->data.array.child_type; result.data.array_mismatch->actual_child = actual_type->data.array.child_type; @@ -11645,7 +11622,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted const_values_equal(ira->codegen, wanted_type->data.array.sentinel, actual_type->data.array.sentinel)); if (!ok_null_terminated) { result.id = ConstCastResultIdSentinelArrays; - result.data.sentinel_arrays = allocate_nonzero(1); + result.data.sentinel_arrays = heap::c_allocator.allocate_nonzero(1); result.data.sentinel_arrays->child = child; result.data.sentinel_arrays->wanted_type = wanted_type; result.data.sentinel_arrays->actual_type = actual_type; @@ -11673,7 +11650,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted actual_ptr_type->data.pointer.sentinel)); if (!ok_sentinels) { result.id = ConstCastResultIdPtrSentinel; - result.data.bad_ptr_sentinel = allocate_nonzero(1); + result.data.bad_ptr_sentinel = heap::c_allocator.allocate_nonzero(1); result.data.bad_ptr_sentinel->wanted_type = wanted_ptr_type; result.data.bad_ptr_sentinel->actual_type = actual_ptr_type; return result; @@ -11690,7 +11667,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted return child; if (child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdSliceChild; - result.data.slice_mismatch = allocate_nonzero(1); + result.data.slice_mismatch = heap::c_allocator.allocate_nonzero(1); result.data.slice_mismatch->child = child; result.data.slice_mismatch->actual_child = actual_ptr_type->data.pointer.child_type; result.data.slice_mismatch->wanted_child = wanted_ptr_type->data.pointer.child_type; @@ -11707,7 +11684,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted return child; if (child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdOptionalChild; - result.data.optional = allocate_nonzero(1); + result.data.optional = heap::c_allocator.allocate_nonzero(1); result.data.optional->child = child; result.data.optional->wanted_child = wanted_type->data.maybe.child_type; result.data.optional->actual_child = actual_type->data.maybe.child_type; @@ -11723,7 +11700,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted return payload_child; if (payload_child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdErrorUnionPayload; - result.data.error_union_payload = allocate_nonzero(1); + result.data.error_union_payload = heap::c_allocator.allocate_nonzero(1); result.data.error_union_payload->child = payload_child; result.data.error_union_payload->wanted_payload = wanted_type->data.error_union.payload_type; result.data.error_union_payload->actual_payload = actual_type->data.error_union.payload_type; @@ -11735,7 +11712,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted return error_set_child; if (error_set_child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdErrorUnionErrorSet; - result.data.error_union_error_set = allocate_nonzero(1); + result.data.error_union_error_set = heap::c_allocator.allocate_nonzero(1); result.data.error_union_error_set->child = error_set_child; result.data.error_union_error_set->wanted_err_set = wanted_type->data.error_union.err_set_type; result.data.error_union_error_set->actual_err_set = actual_type->data.error_union.err_set_type; @@ -11769,7 +11746,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted } size_t errors_count = g->errors_by_index.length; - ErrorTableEntry **errors = allocate(errors_count, "ErrorTableEntry *"); + ErrorTableEntry **errors = heap::c_allocator.allocate(errors_count); for (uint32_t i = 0; i < container_set->data.error_set.err_count; i += 1) { ErrorTableEntry *error_entry = container_set->data.error_set.errors[i]; assert(errors[error_entry->value] == nullptr); @@ -11781,12 +11758,12 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted if (error_entry == nullptr) { if (result.id == ConstCastResultIdOk) { result.id = ConstCastResultIdErrSet; - result.data.error_set_mismatch = allocate(1); + result.data.error_set_mismatch = heap::c_allocator.create(); } result.data.error_set_mismatch->missing_errors.append(contained_error_entry); } } - deallocate(errors, errors_count, "ErrorTableEntry *"); + heap::c_allocator.deallocate(errors, errors_count); return result; } @@ -11815,7 +11792,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted return child; if (child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdFnReturnType; - result.data.return_type = allocate_nonzero(1); + result.data.return_type = heap::c_allocator.allocate_nonzero(1); *result.data.return_type = child; return result; } @@ -11844,7 +11821,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted result.data.fn_arg.arg_index = i; result.data.fn_arg.actual_param_type = actual_param_info->type; result.data.fn_arg.expected_param_type = expected_param_info->type; - result.data.fn_arg.child = allocate_nonzero(1); + result.data.fn_arg.child = heap::c_allocator.allocate_nonzero(1); *result.data.fn_arg.child = arg_child; return result; } @@ -11864,15 +11841,20 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted } if (wanted_type->id == ZigTypeIdInt && actual_type->id == ZigTypeIdInt) { - result.id = ConstCastResultIdIntShorten; - result.data.int_shorten = allocate_nonzero(1); - result.data.int_shorten->wanted_type = wanted_type; - result.data.int_shorten->actual_type = actual_type; + if (wanted_type->data.integral.is_signed != actual_type->data.integral.is_signed || + wanted_type->data.integral.bit_count != actual_type->data.integral.bit_count) + { + result.id = ConstCastResultIdIntShorten; + result.data.int_shorten = heap::c_allocator.allocate_nonzero(1); + result.data.int_shorten->wanted_type = wanted_type; + result.data.int_shorten->actual_type = actual_type; + return result; + } return result; } result.id = ConstCastResultIdType; - result.data.type_mismatch = allocate_nonzero(1); + result.data.type_mismatch = heap::c_allocator.allocate_nonzero(1); result.data.type_mismatch->wanted_type = wanted_type; result.data.type_mismatch->actual_type = actual_type; return result; @@ -11881,7 +11863,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *errors_count) { size_t old_errors_count = *errors_count; *errors_count = g->errors_by_index.length; - *errors = reallocate(*errors, old_errors_count, *errors_count); + *errors = heap::c_allocator.reallocate(*errors, old_errors_count, *errors_count); } static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type, @@ -12551,7 +12533,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT return ira->codegen->builtin_types.entry_invalid; } - free(errors); + heap::c_allocator.deallocate(errors, errors_count); if (convert_to_const_slice) { if (prev_inst->value->type->id == ZigTypeIdPointer) { @@ -12630,7 +12612,7 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInst *source_instr, case CastOpBitCast: zig_panic("TODO"); case CastOpNoop: { - copy_const_val(const_val, other_val); + copy_const_val(ira->codegen, const_val, other_val); const_val->type = new_type; break; } @@ -12770,13 +12752,19 @@ static IrInstGen *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira, IrI wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value->type)); if (instr_is_comptime(value)) { - ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, value->value, source_instr->source_node); + ZigValue *val = ir_resolve_const(ira, value, UndefOk); + if (val == nullptr) + return ira->codegen->invalid_inst_gen; + if (val->special == ConstValSpecialUndef) + return ir_const_undef(ira, source_instr, wanted_type); + + ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node); if (pointee == nullptr) return ira->codegen->invalid_inst_gen; if (pointee->special != ConstValSpecialRuntime) { IrInstGen *result = ir_const(ira, source_instr, wanted_type); result->value->data.x_ptr.special = ConstPtrSpecialBaseArray; - result->value->data.x_ptr.mut = value->value->data.x_ptr.mut; + result->value->data.x_ptr.mut = val->data.x_ptr.mut; result->value->data.x_ptr.data.base_array.array_val = pointee; result->value->data.x_ptr.data.base_array.elem_index = 0; return result; @@ -13159,7 +13147,7 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, if (type_is_invalid(return_ptr->type)) return ErrorSemanticAnalyzeFail; - IrExecutableSrc *ir_executable = allocate(1, "IrExecutableSrc"); + IrExecutableSrc *ir_executable = heap::c_allocator.create(); ir_executable->source_node = source_node; ir_executable->parent_exec = parent_exec; ir_executable->name = exec_name; @@ -13183,7 +13171,7 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ir_print_src(codegen, stderr, ir_executable, 2); fprintf(stderr, "}\n"); } - IrExecutableGen *analyzed_executable = allocate(1, "IrExecutableGen"); + IrExecutableGen *analyzed_executable = heap::c_allocator.create(); analyzed_executable->source_node = source_node; analyzed_executable->parent_exec = parent_exec; analyzed_executable->source_exec = ir_executable; @@ -13384,7 +13372,7 @@ static IrInstGen *ir_analyze_optional_wrap(IrAnalyze *ira, IrInst* source_instr, source_instr->scope, source_instr->source_node); const_instruction->base.value->special = ConstValSpecialStatic; if (types_have_same_zig_comptime_repr(ira->codegen, wanted_type, payload_type)) { - copy_const_val(const_instruction->base.value, val); + copy_const_val(ira->codegen, const_instruction->base.value, val); } else { const_instruction->base.value->data.x_optional = val; } @@ -13425,7 +13413,7 @@ static IrInstGen *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInst* source_ins if (val == nullptr) return ira->codegen->invalid_inst_gen; - ZigValue *err_set_val = create_const_vals(1); + ZigValue *err_set_val = ira->codegen->pass1_arena->create(); err_set_val->type = err_set_type; err_set_val->special = ConstValSpecialStatic; err_set_val->data.x_err_set = nullptr; @@ -13537,7 +13525,7 @@ static IrInstGen *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInst* source_instr, if (!val) return ira->codegen->invalid_inst_gen; - ZigValue *err_set_val = create_const_vals(1); + ZigValue *err_set_val = ira->codegen->pass1_arena->create(); err_set_val->special = ConstValSpecialStatic; err_set_val->type = wanted_type->data.error_union.err_set_type; err_set_val->data.x_err_set = val->data.x_err_set; @@ -13802,7 +13790,7 @@ static IrInstGen *ir_analyze_enum_to_union(IrAnalyze *ira, IrInst* source_instr, result->value->special = ConstValSpecialStatic; result->value->type = wanted_type; bigint_init_bigint(&result->value->data.x_union.tag, &val->data.x_enum_tag); - result->value->data.x_union.payload = create_const_vals(1); + result->value->data.x_union.payload = ira->codegen->pass1_arena->create(); result->value->data.x_union.payload->special = ConstValSpecialStatic; result->value->data.x_union.payload->type = field_type; return result; @@ -14107,7 +14095,7 @@ static IrInstGen *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInst* source_instr, if (pointee == nullptr) return ira->codegen->invalid_inst_gen; if (pointee->special != ConstValSpecialRuntime) { - ZigValue *array_val = create_const_vals(1); + ZigValue *array_val = ira->codegen->pass1_arena->create(); array_val->special = ConstValSpecialStatic; array_val->type = array_type; array_val->data.x_array.special = ConstArraySpecialNone; @@ -14321,7 +14309,7 @@ static IrInstGen *ir_analyze_array_to_vector(IrAnalyze *ira, IrInst* source_inst if (instr_is_comptime(array)) { // arrays and vectors have the same ZigValue representation IrInstGen *result = ir_const(ira, source_instr, vector_type); - copy_const_val(result->value, array->value); + copy_const_val(ira->codegen, result->value, array->value); result->value->type = vector_type; return result; } @@ -14334,7 +14322,7 @@ static IrInstGen *ir_analyze_vector_to_array(IrAnalyze *ira, IrInst* source_inst if (instr_is_comptime(vector)) { // arrays and vectors have the same ZigValue representation IrInstGen *result = ir_const(ira, source_instr, array_type); - copy_const_val(result->value, vector->value); + copy_const_val(ira->codegen, result->value, vector->value); result->value->type = array_type; return result; } @@ -14634,7 +14622,7 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr, if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) { IrInstGen *result = ir_const(ira, source_instr, wanted_type); if (actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdInt) { - copy_const_val(result->value, value->value); + copy_const_val(ira->codegen, result->value, value->value); result->value->type = wanted_type; } else { float_init_bigint(&result->value->data.x_bigint, value->value); @@ -14826,6 +14814,16 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr, } } + // @Vector(N,T1) to @Vector(N,T2) + if (actual_type->id == ZigTypeIdVector && wanted_type->id == ZigTypeIdVector) { + if (actual_type->data.vector.len == wanted_type->data.vector.len && + types_match_const_cast_only(ira, wanted_type->data.vector.elem_type, + actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk) + { + return ir_analyze_bit_cast(ira, source_instr, value, wanted_type); + } + } + // *@Frame(func) to anyframe->T or anyframe // *@Frame(func) to ?anyframe->T or ?anyframe // *@Frame(func) to E!anyframe->T or E!anyframe @@ -16395,9 +16393,11 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i case ZigTypeIdComptimeInt: case ZigTypeIdInt: case ZigTypeIdFloat: - case ZigTypeIdVector: zig_unreachable(); // handled with the type_is_numeric checks above + case ZigTypeIdVector: + // Not every case is handled by the type_is_numeric checks above, + // vectors of bool trigger this code path case ZigTypeIdBool: case ZigTypeIdMetaType: case ZigTypeIdVoid: @@ -16467,7 +16467,7 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i IrInstGen *result = ir_const(ira, &bin_op_instruction->base.base, get_vector_type(ira->codegen, resolved_type->data.vector.len, ira->codegen->builtin_types.entry_bool)); result->value->data.x_array.data.s_none.elements = - create_const_vals(resolved_type->data.vector.len); + ira->codegen->pass1_arena->allocate(resolved_type->data.vector.len); expand_undef_array(ira->codegen, result->value); for (size_t i = 0;i < resolved_type->data.vector.len;i++) { @@ -16475,7 +16475,7 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i &op1_val->data.x_array.data.s_none.elements[i], &op2_val->data.x_array.data.s_none.elements[i], bin_op_instruction, op_id, one_possible_value); - copy_const_val(&result->value->data.x_array.data.s_none.elements[i], cur_res->value); + copy_const_val(ira->codegen, &result->value->data.x_array.data.s_none.elements[i], cur_res->value); } return result; } @@ -17375,7 +17375,7 @@ static IrInstGen *ir_analyze_array_cat(IrAnalyze *ira, IrInstSrcBinOp *instructi ZigValue *out_array_val; size_t new_len = (op1_array_end - op1_array_index) + (op2_array_end - op2_array_index); if (op1_type->id == ZigTypeIdPointer || op2_type->id == ZigTypeIdPointer) { - out_array_val = create_const_vals(1); + out_array_val = ira->codegen->pass1_arena->create(); out_array_val->special = ConstValSpecialStatic; out_array_val->type = get_array_type(ira->codegen, child_type, new_len, sentinel); @@ -17387,11 +17387,11 @@ static IrInstGen *ir_analyze_array_cat(IrAnalyze *ira, IrInstSrcBinOp *instructi true, false, PtrLenUnknown, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, sentinel); result->value->type = get_slice_type(ira->codegen, ptr_type); - out_array_val = create_const_vals(1); + out_array_val = ira->codegen->pass1_arena->create(); out_array_val->special = ConstValSpecialStatic; out_array_val->type = get_array_type(ira->codegen, child_type, new_len, sentinel); - out_val->data.x_struct.fields = alloc_const_vals_ptrs(2); + out_val->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, 2); out_val->data.x_struct.fields[slice_ptr_index]->type = ptr_type; out_val->data.x_struct.fields[slice_ptr_index]->special = ConstValSpecialStatic; @@ -17408,7 +17408,7 @@ static IrInstGen *ir_analyze_array_cat(IrAnalyze *ira, IrInstSrcBinOp *instructi } else { result->value->type = get_pointer_to_type_extra2(ira->codegen, child_type, true, false, PtrLenUnknown, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, sentinel); - out_array_val = create_const_vals(1); + out_array_val = ira->codegen->pass1_arena->create(); out_array_val->special = ConstValSpecialStatic; out_array_val->type = get_array_type(ira->codegen, child_type, new_len, sentinel); out_val->data.x_ptr.special = ConstPtrSpecialBaseArray; @@ -17424,7 +17424,7 @@ static IrInstGen *ir_analyze_array_cat(IrAnalyze *ira, IrInstSrcBinOp *instructi } uint64_t full_len = new_len + ((sentinel != nullptr) ? 1 : 0); - out_array_val->data.x_array.data.s_none.elements = create_const_vals(full_len); + out_array_val->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate(full_len); // TODO handle the buf case here for an optimization expand_undef_array(ira->codegen, op1_array_val); expand_undef_array(ira->codegen, op2_array_val); @@ -17432,21 +17432,21 @@ static IrInstGen *ir_analyze_array_cat(IrAnalyze *ira, IrInstSrcBinOp *instructi size_t next_index = 0; for (size_t i = op1_array_index; i < op1_array_end; i += 1, next_index += 1) { ZigValue *elem_dest_val = &out_array_val->data.x_array.data.s_none.elements[next_index]; - copy_const_val(elem_dest_val, &op1_array_val->data.x_array.data.s_none.elements[i]); + copy_const_val(ira->codegen, elem_dest_val, &op1_array_val->data.x_array.data.s_none.elements[i]); elem_dest_val->parent.id = ConstParentIdArray; elem_dest_val->parent.data.p_array.array_val = out_array_val; elem_dest_val->parent.data.p_array.elem_index = next_index; } for (size_t i = op2_array_index; i < op2_array_end; i += 1, next_index += 1) { ZigValue *elem_dest_val = &out_array_val->data.x_array.data.s_none.elements[next_index]; - copy_const_val(elem_dest_val, &op2_array_val->data.x_array.data.s_none.elements[i]); + copy_const_val(ira->codegen, elem_dest_val, &op2_array_val->data.x_array.data.s_none.elements[i]); elem_dest_val->parent.id = ConstParentIdArray; elem_dest_val->parent.data.p_array.array_val = out_array_val; elem_dest_val->parent.data.p_array.elem_index = next_index; } if (next_index < full_len) { ZigValue *elem_dest_val = &out_array_val->data.x_array.data.s_none.elements[next_index]; - copy_const_val(elem_dest_val, sentinel); + copy_const_val(ira->codegen, elem_dest_val, sentinel); elem_dest_val->parent.id = ConstParentIdArray; elem_dest_val->parent.data.p_array.array_val = out_array_val; elem_dest_val->parent.data.p_array.elem_index = next_index; @@ -17525,13 +17525,13 @@ static IrInstGen *ir_analyze_array_mult(IrAnalyze *ira, IrInstSrcBinOp *instruct // TODO optimize the buf case expand_undef_array(ira->codegen, array_val); size_t extra_null_term = (array_type->data.array.sentinel != nullptr) ? 1 : 0; - out_val->data.x_array.data.s_none.elements = create_const_vals(new_array_len + extra_null_term); + out_val->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate(new_array_len + extra_null_term); uint64_t i = 0; for (uint64_t x = 0; x < mult_amt; x += 1) { for (uint64_t y = 0; y < old_array_len; y += 1) { ZigValue *elem_dest_val = &out_val->data.x_array.data.s_none.elements[i]; - copy_const_val(elem_dest_val, &array_val->data.x_array.data.s_none.elements[y]); + copy_const_val(ira->codegen, elem_dest_val, &array_val->data.x_array.data.s_none.elements[y]); elem_dest_val->parent.id = ConstParentIdArray; elem_dest_val->parent.data.p_array.array_val = out_val; elem_dest_val->parent.data.p_array.elem_index = i; @@ -17542,7 +17542,7 @@ static IrInstGen *ir_analyze_array_mult(IrAnalyze *ira, IrInstSrcBinOp *instruct if (array_type->data.array.sentinel != nullptr) { ZigValue *elem_dest_val = &out_val->data.x_array.data.s_none.elements[i]; - copy_const_val(elem_dest_val, array_type->data.array.sentinel); + copy_const_val(ira->codegen, elem_dest_val, array_type->data.array.sentinel); elem_dest_val->parent.id = ConstParentIdArray; elem_dest_val->parent.data.p_array.array_val = out_val; elem_dest_val->parent.data.p_array.elem_index = i; @@ -17583,14 +17583,14 @@ static IrInstGen *ir_analyze_instruction_merge_err_sets(IrAnalyze *ira, } size_t errors_count = ira->codegen->errors_by_index.length; - ErrorTableEntry **errors = allocate(errors_count, "ErrorTableEntry *"); + ErrorTableEntry **errors = heap::c_allocator.allocate(errors_count); for (uint32_t i = 0, count = op1_type->data.error_set.err_count; i < count; i += 1) { ErrorTableEntry *error_entry = op1_type->data.error_set.errors[i]; assert(errors[error_entry->value] == nullptr); errors[error_entry->value] = error_entry; } ZigType *result_type = get_error_set_union(ira->codegen, errors, op1_type, op2_type, instruction->type_name); - deallocate(errors, errors_count, "ErrorTableEntry *"); + heap::c_allocator.deallocate(errors, errors_count); return ir_const_type(ira, &instruction->base.base, result_type); } @@ -17689,8 +17689,8 @@ static IrInstGen *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstSrcDeclV if (var->gen_is_const) { var->const_value = init_val; } else { - var->const_value = create_const_vals(1); - copy_const_val(var->const_value, init_val); + var->const_value = ira->codegen->pass1_arena->create(); + copy_const_val(ira->codegen, var->const_value, init_val); } } } @@ -17864,7 +17864,7 @@ static IrInstGen *ir_analyze_instruction_export(IrAnalyze *ira, IrInstSrcExport // It's not clear how all the different types are supposed to be handled. // Need comprehensive tests for exporting one thing in one file and declaring an extern var // in another file. - TldFn *tld_fn = allocate(1); + TldFn *tld_fn = heap::c_allocator.create(); tld_fn->base.id = TldIdFn; tld_fn->base.source_node = instruction->base.base.source_node; @@ -18093,7 +18093,7 @@ static IrInstGen *ir_analyze_instruction_error_union(IrAnalyze *ira, IrInstSrcEr IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; - LazyValueErrUnionType *lazy_err_union_type = allocate(1, "LazyValueErrUnionType"); + LazyValueErrUnionType *lazy_err_union_type = heap::c_allocator.create(); lazy_err_union_type->ira = ira; ira_ref(ira); result->value->data.x_lazy = &lazy_err_union_type->base; lazy_err_union_type->base.id = LazyValueIdErrUnionType; @@ -18114,7 +18114,7 @@ static IrInstGen *ir_analyze_alloca(IrAnalyze *ira, IrInst *source_inst, ZigType { Error err; - ZigValue *pointee = create_const_vals(1); + ZigValue *pointee = ira->codegen->pass1_arena->create(); pointee->special = ConstValSpecialUndef; pointee->llvm_align = align; @@ -18195,8 +18195,8 @@ static bool type_can_bit_cast(ZigType *t) { } } -static void set_up_result_loc_for_inferred_comptime(IrInstGen *ptr) { - ZigValue *undef_child = create_const_vals(1); +static void set_up_result_loc_for_inferred_comptime(IrAnalyze *ira, IrInstGen *ptr) { + ZigValue *undef_child = ira->codegen->pass1_arena->create(); undef_child->type = ptr->value->type->data.pointer.child_type; undef_child->special = ConstValSpecialUndef; ptr->value->special = ConstValSpecialStatic; @@ -18242,7 +18242,7 @@ static IrInstGen *ir_resolve_no_result_loc(IrAnalyze *ira, IrInst *suspend_sourc IrInstGenAlloca *alloca_gen = ir_build_alloca_gen(ira, suspend_source_instr, 0, ""); alloca_gen->base.value->type = get_pointer_to_type_extra(ira->codegen, value_type, false, false, PtrLenSingle, 0, 0, 0, false); - set_up_result_loc_for_inferred_comptime(&alloca_gen->base); + set_up_result_loc_for_inferred_comptime(ira, &alloca_gen->base); ZigFn *fn_entry = ira->new_irb.exec->fn_entry; if (fn_entry != nullptr && get_scope_typeof(suspend_source_instr->scope) == nullptr) { fn_entry->alloca_gen_list.append(alloca_gen); @@ -18306,7 +18306,6 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i ZigVar *new_var = create_local_var(ira->codegen, var->decl_node, var->child_scope, buf_create_from_str(var->name), var->src_is_const, var->gen_is_const, var->shadowable, var->is_comptime, true); - new_var->owner_exec = var->owner_exec; new_var->align_bytes = var->align_bytes; var->next_var = new_var; @@ -18645,15 +18644,15 @@ static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr if (!val) return ira->codegen->invalid_inst_gen; field->is_comptime = true; - field->init_val = create_const_vals(1); - copy_const_val(field->init_val, val); + field->init_val = ira->codegen->pass1_arena->create(); + copy_const_val(ira->codegen, field->init_val, val); return result_loc; } ZigType *struct_ptr_type = get_pointer_to_type(ira->codegen, isf->inferred_struct_type, false); if (instr_is_comptime(result_loc)) { casted_ptr = ir_const(ira, suspend_source_instr, struct_ptr_type); - copy_const_val(casted_ptr->value, result_loc->value); + copy_const_val(ira->codegen, casted_ptr->value, result_loc->value); casted_ptr->value->type = struct_ptr_type; } else { casted_ptr = result_loc; @@ -18666,8 +18665,8 @@ static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr ZigValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, suspend_source_instr->source_node); struct_val->special = ConstValSpecialStatic; - struct_val->data.x_struct.fields = realloc_const_vals_ptrs(struct_val->data.x_struct.fields, - old_field_count, new_field_count); + struct_val->data.x_struct.fields = realloc_const_vals_ptrs(ira->codegen, + struct_val->data.x_struct.fields, old_field_count, new_field_count); ZigValue *field_val = struct_val->data.x_struct.fields[old_field_count]; field_val->special = ConstValSpecialUndef; @@ -18967,10 +18966,10 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod if (!arg_val) return false; } else { - arg_val = create_const_runtime(casted_arg->value->type); + arg_val = create_const_runtime(ira->codegen, casted_arg->value->type); } if (arg_part_of_generic_id) { - copy_const_val(&generic_id->params[generic_id->param_count], arg_val); + copy_const_val(ira->codegen, &generic_id->params[generic_id->param_count], arg_val); generic_id->param_count += 1; } @@ -19119,7 +19118,7 @@ static IrInstGen *ir_analyze_store_ptr(IrAnalyze *ira, IrInst* source_instr, if (dest_val == nullptr) return ira->codegen->invalid_inst_gen; if (dest_val->special != ConstValSpecialRuntime) { - copy_const_val(dest_val, value->value); + copy_const_val(ira->codegen, dest_val, value->value); if (ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar && !ira->new_irb.current_basic_block->must_be_comptime_source_instr) @@ -19354,8 +19353,6 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, { return ira->codegen->invalid_inst_gen; } - destroy(result_ptr, "ZigValue"); - result_ptr = nullptr; if (inferred_err_set_type != nullptr) { inferred_err_set_type->data.error_set.incomplete = false; @@ -19363,7 +19360,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, ErrorTableEntry *err = result->data.x_err_union.error_set->data.x_err_set; if (err != nullptr) { inferred_err_set_type->data.error_set.err_count = 1; - inferred_err_set_type->data.error_set.errors = allocate(1); + inferred_err_set_type->data.error_set.errors = heap::c_allocator.create(); inferred_err_set_type->data.error_set.errors[0] = err; } ZigType *fn_inferred_err_set_type = result->type->data.error_union.err_set_type; @@ -19397,12 +19394,12 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, size_t new_fn_arg_count = first_arg_1_or_0 + args_len; - IrInstGen **casted_args = allocate(new_fn_arg_count); + IrInstGen **casted_args = heap::c_allocator.allocate(new_fn_arg_count); // Fork a scope of the function with known values for the parameters. Scope *parent_scope = fn_entry->fndef_scope->base.parent; ZigFn *impl_fn = create_fn(ira->codegen, fn_proto_node); - impl_fn->param_source_nodes = allocate(new_fn_arg_count); + impl_fn->param_source_nodes = heap::c_allocator.allocate(new_fn_arg_count); buf_init_from_buf(&impl_fn->symbol_name, &fn_entry->symbol_name); impl_fn->fndef_scope = create_fndef_scope(ira->codegen, impl_fn->body_node, parent_scope, impl_fn); impl_fn->child_scope = &impl_fn->fndef_scope->base; @@ -19413,10 +19410,10 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, // TODO maybe GenericFnTypeId can be replaced with using the child_scope directly // as the key in generic_table - GenericFnTypeId *generic_id = allocate(1); + GenericFnTypeId *generic_id = heap::c_allocator.create(); generic_id->fn_entry = fn_entry; generic_id->param_count = 0; - generic_id->params = create_const_vals(new_fn_arg_count); + generic_id->params = ira->codegen->pass1_arena->allocate(new_fn_arg_count); size_t next_proto_i = 0; if (first_arg_ptr) { @@ -19476,7 +19473,6 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, IrInstGenConst *const_instruction = ir_create_inst_noval(&ira->new_irb, impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr); const_instruction->base.value = align_result; - destroy(result_ptr, "ZigValue"); uint32_t align_bytes = 0; ir_resolve_align(ira, &const_instruction->base, nullptr, &align_bytes); @@ -19609,7 +19605,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, } - IrInstGen **casted_args = allocate(call_param_count); + IrInstGen **casted_args = heap::c_allocator.allocate(call_param_count); size_t next_arg_index = 0; if (first_arg_ptr) { assert(first_arg_ptr->value->type->id == ZigTypeIdPointer); @@ -19741,7 +19737,7 @@ static IrInstGen *ir_analyze_fn_call_src(IrAnalyze *ira, IrInstSrcCall *call_ins return ira->codegen->invalid_inst_gen; new_stack_src = &call_instruction->new_stack->base; } - IrInstGen **args_ptr = allocate(call_instruction->arg_count, "IrInstGen *"); + IrInstGen **args_ptr = heap::c_allocator.allocate(call_instruction->arg_count); for (size_t i = 0; i < call_instruction->arg_count; i += 1) { args_ptr[i] = call_instruction->args[i]->child; if (type_is_invalid(args_ptr[i]->value->type)) @@ -19757,7 +19753,7 @@ static IrInstGen *ir_analyze_fn_call_src(IrAnalyze *ira, IrInstSrcCall *call_ins first_arg_ptr, first_arg_ptr_src, modifier, new_stack, new_stack_src, call_instruction->is_async_call_builtin, args_ptr, call_instruction->arg_count, ret_ptr, call_instruction->result_loc); - deallocate(args_ptr, call_instruction->arg_count, "IrInstGen *"); + heap::c_allocator.deallocate(args_ptr, call_instruction->arg_count); return result; } @@ -19877,7 +19873,7 @@ static IrInstGen *ir_analyze_instruction_call_extra(IrAnalyze *ira, IrInstSrcCal if (is_tuple(args_type)) { args_len = args_type->data.structure.src_field_count; - args_ptr = allocate(args_len, "IrInstGen *"); + args_ptr = heap::c_allocator.allocate(args_len); for (size_t i = 0; i < args_len; i += 1) { TypeStructField *arg_field = args_type->data.structure.fields[i]; args_ptr[i] = ir_analyze_struct_value_field_value(ira, &instruction->base.base, args, arg_field); @@ -19890,12 +19886,12 @@ static IrInstGen *ir_analyze_instruction_call_extra(IrAnalyze *ira, IrInstSrcCal } IrInstGen *result = ir_analyze_call_extra(ira, &instruction->base.base, instruction->options, instruction->fn_ref, args_ptr, args_len, instruction->result_loc); - deallocate(args_ptr, args_len, "IrInstGen *"); + heap::c_allocator.deallocate(args_ptr, args_len); return result; } static IrInstGen *ir_analyze_instruction_call_args(IrAnalyze *ira, IrInstSrcCallArgs *instruction) { - IrInstGen **args_ptr = allocate(instruction->args_len, "IrInstGen *"); + IrInstGen **args_ptr = heap::c_allocator.allocate(instruction->args_len); for (size_t i = 0; i < instruction->args_len; i += 1) { args_ptr[i] = instruction->args_ptr[i]->child; if (type_is_invalid(args_ptr[i]->value->type)) @@ -19904,7 +19900,7 @@ static IrInstGen *ir_analyze_instruction_call_args(IrAnalyze *ira, IrInstSrcCall IrInstGen *result = ir_analyze_call_extra(ira, &instruction->base.base, instruction->options, instruction->fn_ref, args_ptr, instruction->args_len, instruction->result_loc); - deallocate(args_ptr, instruction->args_len, "IrInstGen *"); + heap::c_allocator.deallocate(args_ptr, instruction->args_len); return result; } @@ -19979,7 +19975,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source if (dst_size <= src_size) { if (src_size == dst_size && types_have_same_zig_comptime_repr(codegen, out_val->type, pointee->type)) { - copy_const_val(out_val, pointee); + copy_const_val(codegen, out_val, pointee); return ErrorNone; } Buf buf = BUF_INIT; @@ -20047,7 +20043,7 @@ static IrInstGen *ir_analyze_optional_type(IrAnalyze *ira, IrInstSrcUnOp *instru IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; - LazyValueOptType *lazy_opt_type = allocate(1, "LazyValueOptType"); + LazyValueOptType *lazy_opt_type = heap::c_allocator.create(); lazy_opt_type->ira = ira; ira_ref(ira); result->value->data.x_lazy = &lazy_opt_type->base; lazy_opt_type->base.id = LazyValueIdOptType; @@ -20331,7 +20327,7 @@ static IrInstGen *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstSrcPhi *phi_i if (value->value->special != ConstValSpecialRuntime) { IrInstGen *result = ir_const(ira, &phi_instruction->base.base, nullptr); - copy_const_val(result->value, value->value); + copy_const_val(ira->codegen, result->value, value->value); return result; } else { return value; @@ -20345,7 +20341,7 @@ static IrInstGen *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstSrcPhi *phi_i peer_parent->peers.length >= 2) { if (peer_parent->resolved_type == nullptr) { - IrInstGen **instructions = allocate(peer_parent->peers.length); + IrInstGen **instructions = heap::c_allocator.allocate(peer_parent->peers.length); for (size_t i = 0; i < peer_parent->peers.length; i += 1) { ResultLocPeer *this_peer = peer_parent->peers.at(i); @@ -20718,7 +20714,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP if (index == array_len && array_type->data.array.sentinel != nullptr) { ZigType *elem_type = array_type->data.array.child_type; IrInstGen *sentinel_elem = ir_const(ira, &elem_ptr_instruction->base.base, elem_type); - copy_const_val(sentinel_elem->value, array_type->data.array.sentinel); + copy_const_val(ira->codegen, sentinel_elem->value, array_type->data.array.sentinel); return ir_get_ref(ira, &elem_ptr_instruction->base.base, sentinel_elem, true, false); } if (index >= array_len) { @@ -20782,7 +20778,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP { if (array_type->id == ZigTypeIdArray || array_type->id == ZigTypeIdVector) { array_ptr_val->data.x_array.special = ConstArraySpecialNone; - array_ptr_val->data.x_array.data.s_none.elements = create_const_vals(array_type->data.array.len); + array_ptr_val->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate(array_type->data.array.len); array_ptr_val->special = ConstValSpecialStatic; for (size_t i = 0; i < array_type->data.array.len; i += 1) { ZigValue *elem_val = &array_ptr_val->data.x_array.data.s_none.elements[i]; @@ -20805,11 +20801,11 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP return ira->codegen->invalid_inst_gen; } - ZigValue *array_init_val = create_const_vals(1); + ZigValue *array_init_val = ira->codegen->pass1_arena->create(); array_init_val->special = ConstValSpecialStatic; array_init_val->type = actual_array_type; array_init_val->data.x_array.special = ConstArraySpecialNone; - array_init_val->data.x_array.data.s_none.elements = create_const_vals(actual_array_type->data.array.len); + array_init_val->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate(actual_array_type->data.array.len); array_init_val->special = ConstValSpecialStatic; for (size_t i = 0; i < actual_array_type->data.array.len; i += 1) { ZigValue *elem_val = &array_init_val->data.x_array.data.s_none.elements[i]; @@ -21135,7 +21131,7 @@ static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_ins if (field->is_comptime) { IrInstGen *elem = ir_const(ira, source_instr, field_type); memoize_field_init_val(ira->codegen, struct_type, field); - copy_const_val(elem->value, field->init_val); + copy_const_val(ira->codegen, elem->value, field->init_val); return ir_get_ref2(ira, source_instr, elem, field_type, true, false); } switch (type_has_one_possible_value(ira->codegen, field_type)) { @@ -21183,7 +21179,7 @@ static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_ins if (type_is_invalid(struct_val->type)) return ira->codegen->invalid_inst_gen; if (initializing && struct_val->special == ConstValSpecialUndef) { - struct_val->data.x_struct.fields = alloc_const_vals_ptrs(struct_type->data.structure.src_field_count); + struct_val->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, struct_type->data.structure.src_field_count); struct_val->special = ConstValSpecialStatic; for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) { ZigValue *field_val = struct_val->data.x_struct.fields[i]; @@ -21225,7 +21221,7 @@ static IrInstGen *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, ZigType *container_ptr_type = container_ptr->value->type; ir_assert(container_ptr_type->id == ZigTypeIdPointer, source_instr); - InferredStructField *inferred_struct_field = allocate(1, "InferredStructField"); + InferredStructField *inferred_struct_field = heap::c_allocator.create(); inferred_struct_field->inferred_struct_type = container_type; inferred_struct_field->field_name = field_name; @@ -21245,7 +21241,7 @@ static IrInstGen *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, } else { result = ir_const(ira, source_instr, field_ptr_type); } - copy_const_val(result->value, ptr_val); + copy_const_val(ira->codegen, result->value, ptr_val); result->value->type = field_ptr_type; return result; } @@ -21316,7 +21312,7 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name return ira->codegen->invalid_inst_gen; if (initializing) { - ZigValue *payload_val = create_const_vals(1); + ZigValue *payload_val = ira->codegen->pass1_arena->create(); payload_val->special = ConstValSpecialUndef; payload_val->type = field_type; payload_val->parent.id = ConstParentIdUnion; @@ -21499,7 +21495,7 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel } } else if (is_array_ref(container_type) && !field_ptr_instruction->initializing) { if (buf_eql_str(field_name, "len")) { - ZigValue *len_val = create_const_vals(1); + ZigValue *len_val = ira->codegen->pass1_arena->create(); if (container_type->id == ZigTypeIdPointer) { init_const_usize(ira->codegen, len_val, container_type->data.pointer.child_type->data.array.len); } else { @@ -21545,7 +21541,7 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel bool ptr_is_const = true; bool ptr_is_volatile = false; return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, - create_const_enum(child_type, &field->value), child_type, + create_const_enum(ira->codegen, child_type, &field->value), child_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } } @@ -21574,7 +21570,7 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel bool ptr_is_const = true; bool ptr_is_volatile = false; return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, - create_const_enum(enum_type, &field->enum_field->value), enum_type, + create_const_enum(ira->codegen, enum_type, &field->enum_field->value), enum_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } } @@ -21592,7 +21588,7 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel if (existing_entry) { err_entry = existing_entry->value; } else { - err_entry = allocate(1); + err_entry = heap::c_allocator.create(); err_entry->decl_node = field_ptr_instruction->base.base.source_node; buf_init_from_buf(&err_entry->name, field_name); size_t error_value_count = ira->codegen->errors_by_index.length; @@ -21619,7 +21615,7 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel } err_set_type = child_type; } - ZigValue *const_val = create_const_vals(1); + ZigValue *const_val = ira->codegen->pass1_arena->create(); const_val->special = ConstValSpecialStatic; const_val->type = err_set_type; const_val->data.x_err_set = err_entry; @@ -21633,7 +21629,7 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel bool ptr_is_const = true; bool ptr_is_volatile = false; return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, - create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int, + create_const_unsigned_negative(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int, child_type->data.integral.bit_count, false), ira->codegen->builtin_types.entry_num_lit_int, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); @@ -21655,7 +21651,7 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel bool ptr_is_const = true; bool ptr_is_volatile = false; return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, - create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int, + create_const_unsigned_negative(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int, child_type->data.floating.bit_count, false), ira->codegen->builtin_types.entry_num_lit_int, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); @@ -21682,7 +21678,7 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel return ira->codegen->invalid_inst_gen; } return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, - create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int, + create_const_unsigned_negative(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int, get_ptr_align(ira->codegen, child_type), false), ira->codegen->builtin_types.entry_num_lit_int, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); @@ -21704,7 +21700,7 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel bool ptr_is_const = true; bool ptr_is_volatile = false; return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, - create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int, + create_const_unsigned_negative(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int, child_type->data.array.len, false), ira->codegen->builtin_types.entry_num_lit_int, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); @@ -21984,7 +21980,7 @@ static IrInstGen *ir_analyze_instruction_slice_type(IrAnalyze *ira, IrInstSrcSli IrInstGen *result = ir_const(ira, &slice_type_instruction->base.base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; - LazyValueSliceType *lazy_slice_type = allocate(1, "LazyValueSliceType"); + LazyValueSliceType *lazy_slice_type = heap::c_allocator.create(); lazy_slice_type->ira = ira; ira_ref(ira); result->value->data.x_lazy = &lazy_slice_type->base; lazy_slice_type->base.id = LazyValueIdSliceType; @@ -22057,8 +22053,8 @@ static IrInstGen *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstSrcAsm *asm_i // TODO validate the output types and variable types - IrInstGen **input_list = allocate(asm_expr->input_list.length); - IrInstGen **output_types = allocate(asm_expr->output_list.length); + IrInstGen **input_list = heap::c_allocator.allocate(asm_expr->input_list.length); + IrInstGen **output_types = heap::c_allocator.allocate(asm_expr->output_list.length); ZigType *return_type = ira->codegen->builtin_types.entry_void; for (size_t i = 0; i < asm_expr->output_list.length; i += 1) { @@ -22097,7 +22093,7 @@ static IrInstGen *ir_analyze_instruction_array_type(IrAnalyze *ira, IrInstSrcArr IrInstGen *result = ir_const(ira, &array_type_instruction->base.base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; - LazyValueArrayType *lazy_array_type = allocate(1, "LazyValueArrayType"); + LazyValueArrayType *lazy_array_type = heap::c_allocator.create(); lazy_array_type->ira = ira; ira_ref(ira); result->value->data.x_lazy = &lazy_array_type->base; lazy_array_type->base.id = LazyValueIdArrayType; @@ -22122,7 +22118,7 @@ static IrInstGen *ir_analyze_instruction_size_of(IrAnalyze *ira, IrInstSrcSizeOf IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_num_lit_int); result->value->special = ConstValSpecialLazy; - LazyValueSizeOf *lazy_size_of = allocate(1, "LazyValueSizeOf"); + LazyValueSizeOf *lazy_size_of = heap::c_allocator.create(); lazy_size_of->ira = ira; ira_ref(ira); result->value->data.x_lazy = &lazy_size_of->base; lazy_size_of->base.id = LazyValueIdSizeOf; @@ -22242,7 +22238,7 @@ static IrInstGen *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInst* sou return ira->codegen->invalid_inst_gen; case OnePossibleValueNo: if (!same_comptime_repr) { - ZigValue *payload_val = create_const_vals(1); + ZigValue *payload_val = ira->codegen->pass1_arena->create(); payload_val->type = child_type; payload_val->special = ConstValSpecialUndef; payload_val->parent.id = ConstParentIdOptionalPayload; @@ -22489,7 +22485,7 @@ static IrInstGen *ir_analyze_instruction_switch_br(IrAnalyze *ira, } } - IrInstGenSwitchBrCase *cases = allocate(case_count); + IrInstGenSwitchBrCase *cases = heap::c_allocator.allocate(case_count); for (size_t i = 0; i < case_count; i += 1) { IrInstSrcSwitchBrCase *old_case = &switch_br_instruction->cases[i]; IrInstGenSwitchBrCase *new_case = &cases[i]; @@ -22574,7 +22570,7 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira, case ZigTypeIdErrorSet: { if (pointee_val) { IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, nullptr); - copy_const_val(result->value, pointee_val); + copy_const_val(ira->codegen, result->value, pointee_val); result->value->type = target_type; return result; } @@ -22794,7 +22790,7 @@ static IrInstGen *ir_analyze_instruction_switch_else_var(IrAnalyze *ira, return target_value_ptr; } // Make note of the errors handled by other cases - ErrorTableEntry **errors = allocate(ira->codegen->errors_by_index.length); + ErrorTableEntry **errors = heap::c_allocator.allocate(ira->codegen->errors_by_index.length); // We may not have any case in the switch if this is a lone else const size_t switch_cases = instruction->switch_br ? instruction->switch_br->case_count : 0; for (size_t case_i = 0; case_i < switch_cases; case_i += 1) { @@ -22830,7 +22826,7 @@ static IrInstGen *ir_analyze_instruction_switch_else_var(IrAnalyze *ira, buf_appendf(&err_set_type->name, "%s,", buf_ptr(&error_entry->name)); } } - free(errors); + heap::c_allocator.deallocate(errors, ira->codegen->errors_by_index.length); err_set_type->data.error_set.err_count = result_list.length; err_set_type->data.error_set.errors = result_list.items; @@ -22978,7 +22974,7 @@ static IrInstGen *ir_analyze_container_init_fields(IrAnalyze *ira, IrInst *sourc IrInstGen *first_non_const_instruction = nullptr; - AstNode **field_assign_nodes = allocate(actual_field_count); + AstNode **field_assign_nodes = heap::c_allocator.allocate(actual_field_count); ZigList const_ptrs = {}; bool is_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope) @@ -23049,7 +23045,7 @@ static IrInstGen *ir_analyze_container_init_fields(IrAnalyze *ira, IrInst *sourc return ira->codegen->invalid_inst_gen; IrInstGen *runtime_inst = ir_const(ira, source_instr, field->init_val->type); - copy_const_val(runtime_inst->value, field->init_val); + copy_const_val(ira->codegen, runtime_inst->value, field->init_val); IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, field, result_loc, container_type, true); @@ -23313,7 +23309,7 @@ static IrInstGen *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstSrcErrNa err->cached_error_name_val = create_const_slice(ira->codegen, array_val, 0, buf_len(&err->name), true); } IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); - copy_const_val(result->value, err->cached_error_name_val); + copy_const_val(ira->codegen, result->value, err->cached_error_name_val); result->value->type = str_type; return result; } @@ -23639,11 +23635,11 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa } } - ZigValue *declaration_array = create_const_vals(1); + ZigValue *declaration_array = ira->codegen->pass1_arena->create(); declaration_array->special = ConstValSpecialStatic; declaration_array->type = get_array_type(ira->codegen, type_info_declaration_type, declaration_count, nullptr); declaration_array->data.x_array.special = ConstArraySpecialNone; - declaration_array->data.x_array.data.s_none.elements = create_const_vals(declaration_count); + declaration_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate(declaration_count); init_const_slice(ira->codegen, out_val, declaration_array, 0, declaration_count, false); // Loop through the declarations and generate info. @@ -23665,7 +23661,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa declaration_val->special = ConstValSpecialStatic; declaration_val->type = type_info_declaration_type; - ZigValue **inner_fields = alloc_const_vals_ptrs(3); + ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 3); ZigValue *name = create_const_str_lit(ira->codegen, curr_entry->key)->data.x_ptr.data.ref.pointee; init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(curr_entry->key), true); inner_fields[1]->special = ConstValSpecialStatic; @@ -23696,7 +23692,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa // 1: Data.Var: type bigint_init_unsigned(&inner_fields[2]->data.x_union.tag, 1); - ZigValue *payload = create_const_vals(1); + ZigValue *payload = ira->codegen->pass1_arena->create(); payload->special = ConstValSpecialStatic; payload->type = ira->codegen->builtin_types.entry_type; payload->data.x_type = var->const_value->type; @@ -23717,13 +23713,13 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa AstNodeFnProto *fn_node = &fn_entry->proto_node->data.fn_proto; - ZigValue *fn_decl_val = create_const_vals(1); + ZigValue *fn_decl_val = ira->codegen->pass1_arena->create(); fn_decl_val->special = ConstValSpecialStatic; fn_decl_val->type = type_info_fn_decl_type; fn_decl_val->parent.id = ConstParentIdUnion; fn_decl_val->parent.data.p_union.union_val = inner_fields[2]; - ZigValue **fn_decl_fields = alloc_const_vals_ptrs(9); + ZigValue **fn_decl_fields = alloc_const_vals_ptrs(ira->codegen, 9); fn_decl_val->data.x_struct.fields = fn_decl_fields; // fn_type: type @@ -23761,7 +23757,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa 0, 0, 0, false); fn_decl_fields[5]->type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr)); if (fn_node->is_extern && fn_node->lib_name != nullptr && buf_len(fn_node->lib_name) > 0) { - fn_decl_fields[5]->data.x_optional = create_const_vals(1); + fn_decl_fields[5]->data.x_optional = ira->codegen->pass1_arena->create(); ZigValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name)->data.x_ptr.data.ref.pointee; init_const_slice(ira->codegen, fn_decl_fields[5]->data.x_optional, lib_name, 0, buf_len(fn_node->lib_name), true); @@ -23776,12 +23772,12 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa // arg_names: [][] const u8 ensure_field_index(fn_decl_val->type, "arg_names", 7); size_t fn_arg_count = fn_entry->variable_list.length; - ZigValue *fn_arg_name_array = create_const_vals(1); + ZigValue *fn_arg_name_array = ira->codegen->pass1_arena->create(); fn_arg_name_array->special = ConstValSpecialStatic; fn_arg_name_array->type = get_array_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr), fn_arg_count, nullptr); fn_arg_name_array->data.x_array.special = ConstArraySpecialNone; - fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count); + fn_arg_name_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate(fn_arg_count); init_const_slice(ira->codegen, fn_decl_fields[7], fn_arg_name_array, 0, fn_arg_count, false); @@ -23808,7 +23804,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa // This is a type. bigint_init_unsigned(&inner_fields[2]->data.x_union.tag, 0); - ZigValue *payload = create_const_vals(1); + ZigValue *payload = ira->codegen->pass1_arena->create(); payload->special = ConstValSpecialStatic; payload->type = ira->codegen->builtin_types.entry_type; payload->data.x_type = type_entry; @@ -23874,11 +23870,11 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_ent ZigType *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer", nullptr); assertNoError(type_resolve(ira->codegen, type_info_pointer_type, ResolveStatusSizeKnown)); - ZigValue *result = create_const_vals(1); + ZigValue *result = ira->codegen->pass1_arena->create(); result->special = ConstValSpecialStatic; result->type = type_info_pointer_type; - ZigValue **fields = alloc_const_vals_ptrs(7); + ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 7); result->data.x_struct.fields = fields; // size: Size @@ -23933,7 +23929,7 @@ static void make_enum_field_val(IrAnalyze *ira, ZigValue *enum_field_val, TypeEn enum_field_val->special = ConstValSpecialStatic; enum_field_val->type = type_info_enum_field_type; - ZigValue **inner_fields = alloc_const_vals_ptrs(2); + ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 2); inner_fields[1]->special = ConstValSpecialStatic; inner_fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int; @@ -23979,11 +23975,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy break; case ZigTypeIdInt: { - result = create_const_vals(1); + result = ira->codegen->pass1_arena->create(); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Int", nullptr); - ZigValue **fields = alloc_const_vals_ptrs(2); + ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 2); result->data.x_struct.fields = fields; // is_signed: bool @@ -24001,11 +23997,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy } case ZigTypeIdFloat: { - result = create_const_vals(1); + result = ira->codegen->pass1_arena->create(); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Float", nullptr); - ZigValue **fields = alloc_const_vals_ptrs(1); + ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 1); result->data.x_struct.fields = fields; // bits: u8 @@ -24025,11 +24021,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy } case ZigTypeIdArray: { - result = create_const_vals(1); + result = ira->codegen->pass1_arena->create(); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Array", nullptr); - ZigValue **fields = alloc_const_vals_ptrs(3); + ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 3); result->data.x_struct.fields = fields; // len: usize @@ -24049,11 +24045,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy break; } case ZigTypeIdVector: { - result = create_const_vals(1); + result = ira->codegen->pass1_arena->create(); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Vector", nullptr); - ZigValue **fields = alloc_const_vals_ptrs(2); + ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 2); result->data.x_struct.fields = fields; // len: usize @@ -24071,11 +24067,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy } case ZigTypeIdOptional: { - result = create_const_vals(1); + result = ira->codegen->pass1_arena->create(); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Optional", nullptr); - ZigValue **fields = alloc_const_vals_ptrs(1); + ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 1); result->data.x_struct.fields = fields; // child: type @@ -24087,11 +24083,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy break; } case ZigTypeIdAnyFrame: { - result = create_const_vals(1); + result = ira->codegen->pass1_arena->create(); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "AnyFrame", nullptr); - ZigValue **fields = alloc_const_vals_ptrs(1); + ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 1); result->data.x_struct.fields = fields; // child: ?type @@ -24104,11 +24100,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy } case ZigTypeIdEnum: { - result = create_const_vals(1); + result = ira->codegen->pass1_arena->create(); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Enum", nullptr); - ZigValue **fields = alloc_const_vals_ptrs(5); + ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 5); result->data.x_struct.fields = fields; // layout: ContainerLayout @@ -24130,11 +24126,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy } uint32_t enum_field_count = type_entry->data.enumeration.src_field_count; - ZigValue *enum_field_array = create_const_vals(1); + ZigValue *enum_field_array = ira->codegen->pass1_arena->create(); enum_field_array->special = ConstValSpecialStatic; enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count, nullptr); enum_field_array->data.x_array.special = ConstArraySpecialNone; - enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count); + enum_field_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate(enum_field_count); init_const_slice(ira->codegen, fields[2], enum_field_array, 0, enum_field_count, false); @@ -24164,7 +24160,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy } case ZigTypeIdErrorSet: { - result = create_const_vals(1); + result = ira->codegen->pass1_arena->create(); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "ErrorSet", nullptr); @@ -24179,15 +24175,15 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy if ((err = type_resolve(ira->codegen, type_info_error_type, ResolveStatusSizeKnown))) { zig_unreachable(); } - ZigValue *slice_val = create_const_vals(1); + ZigValue *slice_val = ira->codegen->pass1_arena->create(); result->data.x_optional = slice_val; uint32_t error_count = type_entry->data.error_set.err_count; - ZigValue *error_array = create_const_vals(1); + ZigValue *error_array = ira->codegen->pass1_arena->create(); error_array->special = ConstValSpecialStatic; error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count, nullptr); error_array->data.x_array.special = ConstArraySpecialNone; - error_array->data.x_array.data.s_none.elements = create_const_vals(error_count); + error_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate(error_count); init_const_slice(ira->codegen, slice_val, error_array, 0, error_count, false); for (uint32_t error_index = 0; error_index < error_count; error_index++) { @@ -24197,7 +24193,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy error_val->special = ConstValSpecialStatic; error_val->type = type_info_error_type; - ZigValue **inner_fields = alloc_const_vals_ptrs(2); + ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 2); inner_fields[1]->special = ConstValSpecialStatic; inner_fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int; @@ -24219,11 +24215,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy } case ZigTypeIdErrorUnion: { - result = create_const_vals(1); + result = ira->codegen->pass1_arena->create(); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "ErrorUnion", nullptr); - ZigValue **fields = alloc_const_vals_ptrs(2); + ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 2); result->data.x_struct.fields = fields; // error_set: type @@ -24242,11 +24238,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy } case ZigTypeIdUnion: { - result = create_const_vals(1); + result = ira->codegen->pass1_arena->create(); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Union", nullptr); - ZigValue **fields = alloc_const_vals_ptrs(4); + ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 4); result->data.x_struct.fields = fields; // layout: ContainerLayout @@ -24263,7 +24259,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy if (union_decl_node->data.container_decl.auto_enum || union_decl_node->data.container_decl.init_arg_expr != nullptr) { - ZigValue *tag_type = create_const_vals(1); + ZigValue *tag_type = ira->codegen->pass1_arena->create(); tag_type->special = ConstValSpecialStatic; tag_type->type = ira->codegen->builtin_types.entry_type; tag_type->data.x_type = type_entry->data.unionation.tag_type; @@ -24279,11 +24275,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy zig_unreachable(); uint32_t union_field_count = type_entry->data.unionation.src_field_count; - ZigValue *union_field_array = create_const_vals(1); + ZigValue *union_field_array = ira->codegen->pass1_arena->create(); union_field_array->special = ConstValSpecialStatic; union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count, nullptr); union_field_array->data.x_array.special = ConstArraySpecialNone; - union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count); + union_field_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate(union_field_count); init_const_slice(ira->codegen, fields[2], union_field_array, 0, union_field_count, false); @@ -24296,14 +24292,14 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy union_field_val->special = ConstValSpecialStatic; union_field_val->type = type_info_union_field_type; - ZigValue **inner_fields = alloc_const_vals_ptrs(3); + ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 3); inner_fields[1]->special = ConstValSpecialStatic; inner_fields[1]->type = get_optional_type(ira->codegen, type_info_enum_field_type); if (fields[1]->data.x_optional == nullptr) { inner_fields[1]->data.x_optional = nullptr; } else { - inner_fields[1]->data.x_optional = create_const_vals(1); + inner_fields[1]->data.x_optional = ira->codegen->pass1_arena->create(); make_enum_field_val(ira, inner_fields[1]->data.x_optional, union_field->enum_field, type_info_enum_field_type); } @@ -24338,11 +24334,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy break; } - result = create_const_vals(1); + result = ira->codegen->pass1_arena->create(); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Struct", nullptr); - ZigValue **fields = alloc_const_vals_ptrs(3); + ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 3); result->data.x_struct.fields = fields; // layout: ContainerLayout @@ -24359,11 +24355,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy } uint32_t struct_field_count = type_entry->data.structure.src_field_count; - ZigValue *struct_field_array = create_const_vals(1); + ZigValue *struct_field_array = ira->codegen->pass1_arena->create(); struct_field_array->special = ConstValSpecialStatic; struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count, nullptr); struct_field_array->data.x_array.special = ConstArraySpecialNone; - struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count); + struct_field_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate(struct_field_count); init_const_slice(ira->codegen, fields[1], struct_field_array, 0, struct_field_count, false); @@ -24374,7 +24370,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy struct_field_val->special = ConstValSpecialStatic; struct_field_val->type = type_info_struct_field_type; - ZigValue **inner_fields = alloc_const_vals_ptrs(4); + ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 4); inner_fields[1]->special = ConstValSpecialStatic; inner_fields[1]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int); @@ -24387,7 +24383,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy inner_fields[1]->data.x_optional = nullptr; } else { size_t byte_offset = struct_field->offset; - inner_fields[1]->data.x_optional = create_const_vals(1); + inner_fields[1]->data.x_optional = ira->codegen->pass1_arena->create(); inner_fields[1]->data.x_optional->special = ConstValSpecialStatic; inner_fields[1]->data.x_optional->type = ira->codegen->builtin_types.entry_num_lit_int; bigint_init_unsigned(&inner_fields[1]->data.x_optional->data.x_bigint, byte_offset); @@ -24423,11 +24419,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy } case ZigTypeIdFn: { - result = create_const_vals(1); + result = ira->codegen->pass1_arena->create(); result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Fn", nullptr); - ZigValue **fields = alloc_const_vals_ptrs(5); + ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 5); result->data.x_struct.fields = fields; // calling_convention: TypeInfo.CallingConvention @@ -24454,7 +24450,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy if (type_entry->data.fn.fn_type_id.return_type == nullptr) fields[3]->data.x_optional = nullptr; else { - ZigValue *return_type = create_const_vals(1); + ZigValue *return_type = ira->codegen->pass1_arena->create(); return_type->special = ConstValSpecialStatic; return_type->type = ira->codegen->builtin_types.entry_type; return_type->data.x_type = type_entry->data.fn.fn_type_id.return_type; @@ -24468,11 +24464,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy size_t fn_arg_count = type_entry->data.fn.fn_type_id.param_count - (is_varargs && type_entry->data.fn.fn_type_id.cc != CallingConventionC); - ZigValue *fn_arg_array = create_const_vals(1); + ZigValue *fn_arg_array = ira->codegen->pass1_arena->create(); fn_arg_array->special = ConstValSpecialStatic; fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count, nullptr); fn_arg_array->data.x_array.special = ConstArraySpecialNone; - fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count); + fn_arg_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate(fn_arg_count); init_const_slice(ira->codegen, fields[4], fn_arg_array, 0, fn_arg_count, false); @@ -24486,7 +24482,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy bool arg_is_generic = fn_param_info->type == nullptr; if (arg_is_generic) assert(is_generic); - ZigValue **inner_fields = alloc_const_vals_ptrs(3); + ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 3); inner_fields[0]->special = ConstValSpecialStatic; inner_fields[0]->type = ira->codegen->builtin_types.entry_bool; inner_fields[0]->data.x_bool = arg_is_generic; @@ -24499,7 +24495,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy if (arg_is_generic) inner_fields[2]->data.x_optional = nullptr; else { - ZigValue *arg_type = create_const_vals(1); + ZigValue *arg_type = ira->codegen->pass1_arena->create(); arg_type->special = ConstValSpecialStatic; arg_type->type = ira->codegen->builtin_types.entry_type; arg_type->data.x_type = fn_param_info->type; @@ -24524,7 +24520,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy break; } case ZigTypeIdFnFrame: - zig_panic("TODO @typeInfo for async function frames"); + ir_add_error(ira, source_instr, + buf_sprintf("compiler bug: TODO @typeInfo for async function frames. https://github.com/ziglang/zig/issues/3066")); + return ErrorSemanticAnalyzeFail; } assert(result != nullptr); @@ -24823,7 +24821,7 @@ static IrInstGen *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstSrcType type_entry->cached_const_name_val = create_const_str_lit(ira->codegen, type_bare_name(type_entry)); } IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); - copy_const_val(result->value, type_entry->cached_const_name_val); + copy_const_val(ira->codegen, result->value, type_entry->cached_const_name_val); return result; } @@ -24855,7 +24853,6 @@ static IrInstGen *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstSrcCImpo } if (type_is_invalid(cimport_result->type)) return ira->codegen->invalid_inst_gen; - destroy(result_ptr, "ZigValue"); ZigPackage *cur_scope_pkg = scope_package(instruction->base.base.scope); Buf *namespace_name = buf_sprintf("%s.cimport:%" ZIG_PRI_usize ":%" ZIG_PRI_usize, @@ -25534,11 +25531,11 @@ static IrInstGen *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstSrcToByt return ira->codegen->invalid_inst_gen; IrInstGen *result = ir_const(ira, &instruction->base.base, dest_slice_type); - result->value->data.x_struct.fields = alloc_const_vals_ptrs(2); + result->value->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, 2); ZigValue *ptr_val = result->value->data.x_struct.fields[slice_ptr_index]; ZigValue *target_ptr_val = target_val->data.x_struct.fields[slice_ptr_index]; - copy_const_val(ptr_val, target_ptr_val); + copy_const_val(ira->codegen, ptr_val, target_ptr_val); ptr_val->type = dest_ptr_type; ZigValue *len_val = result->value->data.x_struct.fields[slice_len_index]; @@ -25825,7 +25822,7 @@ static IrInstGen *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInst* source_instr expand_undef_array(ira->codegen, b_val); IrInstGen *result = ir_const(ira, source_instr, result_type); - result->value->data.x_array.data.s_none.elements = create_const_vals(len_mask); + result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate(len_mask); for (uint32_t i = 0; i < mask_val->type->data.vector.len; i += 1) { ZigValue *mask_elem_val = &mask_val->data.x_array.data.s_none.elements[i]; ZigValue *result_elem_val = &result->value->data.x_array.data.s_none.elements[i]; @@ -25838,7 +25835,7 @@ static IrInstGen *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInst* source_instr ZigValue *src_elem_val = (v >= 0) ? &a->value->data.x_array.data.s_none.elements[v] : &b->value->data.x_array.data.s_none.elements[~v]; - copy_const_val(result_elem_val, src_elem_val); + copy_const_val(ira->codegen, result_elem_val, src_elem_val); ir_assert(result_elem_val->special == ConstValSpecialStatic, source_instr); } @@ -25858,7 +25855,7 @@ static IrInstGen *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInst* source_instr IrInstGen *expand_mask = ir_const(ira, &mask->base, get_vector_type(ira->codegen, len_max, ira->codegen->builtin_types.entry_i32)); - expand_mask->value->data.x_array.data.s_none.elements = create_const_vals(len_max); + expand_mask->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate(len_max); uint32_t i = 0; for (; i < len_min; i += 1) bigint_init_unsigned(&expand_mask->value->data.x_array.data.s_none.elements[i].data.x_bigint, i); @@ -25928,9 +25925,9 @@ static IrInstGen *ir_analyze_instruction_splat(IrAnalyze *ira, IrInstSrcSplat *i return ir_const_undef(ira, &instruction->base.base, return_type); IrInstGen *result = ir_const(ira, &instruction->base.base, return_type); - result->value->data.x_array.data.s_none.elements = create_const_vals(len_int); + result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate(len_int); for (uint32_t i = 0; i < len_int; i += 1) { - copy_const_val(&result->value->data.x_array.data.s_none.elements[i], scalar_val); + copy_const_val(ira->codegen, &result->value->data.x_array.data.s_none.elements[i], scalar_val); } return result; } @@ -26068,7 +26065,7 @@ static IrInstGen *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstSrcMemset } for (size_t i = start; i < end; i += 1) { - copy_const_val(&dest_elements[i], byte_val); + copy_const_val(ira->codegen, &dest_elements[i], byte_val); } return ir_const_void(ira, &instruction->base.base); @@ -26244,7 +26241,7 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy // TODO check for noalias violations - this should be generalized to work for any function for (size_t i = 0; i < count; i += 1) { - copy_const_val(&dest_elements[dest_start + i], &src_elements[src_start + i]); + copy_const_val(ira->codegen, &dest_elements[dest_start + i], &src_elements[src_start + i]); } return ir_const_void(ira, &instruction->base.base); @@ -26528,7 +26525,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i IrInstGen *result = ir_const(ira, &instruction->base.base, return_type); ZigValue *out_val = result->value; - out_val->data.x_struct.fields = alloc_const_vals_ptrs(2); + out_val->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, 2); ZigValue *ptr_val = out_val->data.x_struct.fields[slice_ptr_index]; @@ -26823,7 +26820,7 @@ static IrInstGen *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstSrcAlign IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_num_lit_int); result->value->special = ConstValSpecialLazy; - LazyValueAlignOf *lazy_align_of = allocate(1, "LazyValueAlignOf"); + LazyValueAlignOf *lazy_align_of = heap::c_allocator.create(); lazy_align_of->ira = ira; ira_ref(ira); result->value->data.x_lazy = &lazy_align_of->base; lazy_align_of->base.id = LazyValueIdAlignOf; @@ -27149,7 +27146,7 @@ static IrInstGen *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInst* source_inst return ira->codegen->invalid_inst_gen; if (initializing && err_union_val->special == ConstValSpecialUndef) { - ZigValue *vals = create_const_vals(2); + ZigValue *vals = ira->codegen->pass1_arena->allocate(2); ZigValue *err_set_val = &vals[0]; ZigValue *payload_val = &vals[1]; @@ -27230,7 +27227,7 @@ static IrInstGen *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInst* source if (err_union_val == nullptr) return ira->codegen->invalid_inst_gen; if (initializing && err_union_val->special == ConstValSpecialUndef) { - ZigValue *vals = create_const_vals(2); + ZigValue *vals = ira->codegen->pass1_arena->allocate(2); ZigValue *err_set_val = &vals[0]; ZigValue *payload_val = &vals[1]; @@ -27292,7 +27289,7 @@ static IrInstGen *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstSrcFnPro IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; - LazyValueFnType *lazy_fn_type = allocate(1, "LazyValueFnType"); + LazyValueFnType *lazy_fn_type = heap::c_allocator.create(); lazy_fn_type->ira = ira; ira_ref(ira); result->value->data.x_lazy = &lazy_fn_type->base; lazy_fn_type->base.id = LazyValueIdFnType; @@ -27320,7 +27317,7 @@ static IrInstGen *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstSrcFnPro size_t param_count = proto_node->data.fn_proto.params.length; lazy_fn_type->proto_node = proto_node; - lazy_fn_type->param_types = allocate(param_count); + lazy_fn_type->param_types = heap::c_allocator.allocate(param_count); for (size_t param_index = 0; param_index < param_count; param_index += 1) { AstNode *param_node = proto_node->data.fn_proto.params.at(param_index); @@ -27475,7 +27472,7 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, } size_t field_prev_uses_count = ira->codegen->errors_by_index.length; - AstNode **field_prev_uses = allocate(field_prev_uses_count, "AstNode *"); + AstNode **field_prev_uses = heap::c_allocator.allocate(field_prev_uses_count); for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { IrInstSrcCheckSwitchProngsRange *range = &instruction->ranges[range_i]; @@ -27532,7 +27529,7 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, } } - deallocate(field_prev_uses, field_prev_uses_count, "AstNode *"); + heap::c_allocator.deallocate(field_prev_uses, field_prev_uses_count); } else if (switch_type->id == ZigTypeIdInt) { RangeSet rs = {0}; for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { @@ -27725,7 +27722,7 @@ static IrInstGen *ir_align_cast(IrAnalyze *ira, IrInstGen *target, uint32_t alig } IrInstGen *result = ir_const(ira, &target->base, result_type); - copy_const_val(result->value, val); + copy_const_val(ira->codegen, result->value, val); result->value->type = result_type; return result; } @@ -27821,7 +27818,7 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn InferredStructField *isf = (val->type->id == ZigTypeIdPointer) ? val->type->data.pointer.inferred_struct_field : nullptr; if (isf == nullptr) { - copy_const_val(result->value, val); + copy_const_val(ira->codegen, result->value, val); } else { // The destination value should have x_ptr struct pointing to underlying struct value result->value->data.x_ptr.mut = val->data.x_ptr.mut; @@ -27978,7 +27975,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val) while (gen_i < gen_field_count) { size_t big_int_byte_count = val->type->data.structure.host_int_bytes[gen_i]; if (big_int_byte_count > child_buf_len) { - child_buf = allocate_nonzero(big_int_byte_count); + child_buf = heap::c_allocator.allocate_nonzero(big_int_byte_count); child_buf_len = big_int_byte_count; } BigInt big_int; @@ -28041,7 +28038,7 @@ static Error buf_read_value_bytes_array(IrAnalyze *ira, CodeGen *codegen, AstNod switch (val->data.x_array.special) { case ConstArraySpecialNone: - val->data.x_array.data.s_none.elements = create_const_vals(len); + val->data.x_array.data.s_none.elements = codegen->pass1_arena->allocate(len); for (size_t i = 0; i < len; i++) { ZigValue *elem = &val->data.x_array.data.s_none.elements[i]; elem->special = ConstValSpecialStatic; @@ -28127,7 +28124,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou } case ContainerLayoutExtern: { size_t src_field_count = val->type->data.structure.src_field_count; - val->data.x_struct.fields = alloc_const_vals_ptrs(src_field_count); + val->data.x_struct.fields = alloc_const_vals_ptrs(codegen, src_field_count); for (size_t field_i = 0; field_i < src_field_count; field_i += 1) { ZigValue *field_val = val->data.x_struct.fields[field_i]; field_val->special = ConstValSpecialStatic; @@ -28144,7 +28141,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou } case ContainerLayoutPacked: { size_t src_field_count = val->type->data.structure.src_field_count; - val->data.x_struct.fields = alloc_const_vals_ptrs(src_field_count); + val->data.x_struct.fields = alloc_const_vals_ptrs(codegen, src_field_count); size_t gen_field_count = val->type->data.structure.gen_field_count; size_t gen_i = 0; size_t src_i = 0; @@ -28156,7 +28153,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou while (gen_i < gen_field_count) { size_t big_int_byte_count = val->type->data.structure.host_int_bytes[gen_i]; if (big_int_byte_count > child_buf_len) { - child_buf = allocate_nonzero(big_int_byte_count); + child_buf = heap::c_allocator.allocate_nonzero(big_int_byte_count); child_buf_len = big_int_byte_count; } BigInt big_int; @@ -28266,7 +28263,7 @@ static IrInstGen *ir_analyze_bit_cast(IrAnalyze *ira, IrInst* source_instr, IrIn return ira->codegen->invalid_inst_gen; IrInstGen *result = ir_const(ira, source_instr, dest_type); - uint8_t *buf = allocate_nonzero(src_size_bytes); + uint8_t *buf = heap::c_allocator.allocate_nonzero(src_size_bytes); buf_write_value_bytes(ira->codegen, buf, val); if ((err = buf_read_value_bytes(ira, ira->codegen, source_instr->source_node, buf, result->value))) return ira->codegen->invalid_inst_gen; @@ -28408,7 +28405,7 @@ static IrInstGen *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstSrcPtrTy IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; - LazyValuePtrType *lazy_ptr_type = allocate(1, "LazyValuePtrType"); + LazyValuePtrType *lazy_ptr_type = heap::c_allocator.create(); lazy_ptr_type->ira = ira; ira_ref(ira); result->value->data.x_lazy = &lazy_ptr_type->base; lazy_ptr_type->base.id = LazyValueIdPtrType; @@ -29107,11 +29104,11 @@ static IrInstGen *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstSrcBswap *i return ir_const_undef(ira, &instruction->base.base, op_type); IrInstGen *result = ir_const(ira, &instruction->base.base, op_type); - size_t buf_size = int_type->data.integral.bit_count / 8; - uint8_t *buf = allocate_nonzero(buf_size); + const size_t buf_size = int_type->data.integral.bit_count / 8; + uint8_t *buf = heap::c_allocator.allocate_nonzero(buf_size); if (is_vector) { expand_undef_array(ira->codegen, val); - result->value->data.x_array.data.s_none.elements = create_const_vals(op_type->data.vector.len); + result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate(op_type->data.vector.len); for (unsigned i = 0; i < op_type->data.vector.len; i += 1) { ZigValue *op_elem_val = &val->data.x_array.data.s_none.elements[i]; if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, instruction->base.base.source_node, @@ -29135,7 +29132,7 @@ static IrInstGen *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstSrcBswap *i bigint_read_twos_complement(&result->value->data.x_bigint, buf, int_type->data.integral.bit_count, false, int_type->data.integral.is_signed); } - free(buf); + heap::c_allocator.deallocate(buf, buf_size); return result; } @@ -29167,8 +29164,8 @@ static IrInstGen *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstSrcBi IrInstGen *result = ir_const(ira, &instruction->base.base, int_type); size_t num_bits = int_type->data.integral.bit_count; size_t buf_size = (num_bits + 7) / 8; - uint8_t *comptime_buf = allocate_nonzero(buf_size); - uint8_t *result_buf = allocate_nonzero(buf_size); + uint8_t *comptime_buf = heap::c_allocator.allocate_nonzero(buf_size); + uint8_t *result_buf = heap::c_allocator.allocate_nonzero(buf_size); memset(comptime_buf,0,buf_size); memset(result_buf,0,buf_size); @@ -29854,7 +29851,7 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutableSrc *old_exec, IrExecutableGen assert(old_exec->first_err_trace_msg == nullptr); assert(expected_type == nullptr || !type_is_invalid(expected_type)); - IrAnalyze *ira = allocate(1, "IrAnalyze"); + IrAnalyze *ira = heap::c_allocator.create(); ira->ref_count = 1; old_exec->analysis = ira; ira->codegen = codegen; diff --git a/src/ir.hpp b/src/ir.hpp index 58aad6ad9b..3686771287 100644 --- a/src/ir.hpp +++ b/src/ir.hpp @@ -37,6 +37,4 @@ ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_va void dbg_ir_break(const char *src_file, uint32_t line); void dbg_ir_clear(void); -void destroy_instruction_gen(IrInstGen *inst); - #endif diff --git a/src/link.cpp b/src/link.cpp index aa5cda9bab..022e2f857f 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -650,7 +650,7 @@ static const char *build_libunwind(CodeGen *parent, Stage2ProgressNode *progress }; ZigList c_source_files = {0}; for (size_t i = 0; i < array_length(unwind_src); i += 1) { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = path_from_libunwind(parent, unwind_src[i].path); switch (unwind_src[i].kind) { case SrcC: @@ -1111,7 +1111,7 @@ static const char *build_musl(CodeGen *parent, Stage2ProgressNode *progress_node Buf *full_path = buf_sprintf("%s" OS_SEP "libc" OS_SEP "%s", buf_ptr(parent->zig_lib_dir), buf_ptr(src_file)); - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = buf_ptr(full_path); musl_add_cc_args(parent, c_file, src_kind == MuslSrcO3); @@ -1127,7 +1127,7 @@ static const char *build_musl(CodeGen *parent, Stage2ProgressNode *progress_node } static void add_msvcrt_os_dep(CodeGen *parent, CodeGen *child_gen, const char *src_path) { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = buf_ptr(buf_sprintf("%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "%s", buf_ptr(parent->zig_lib_dir), src_path)); c_file->args.append("-DHAVE_CONFIG_H"); @@ -1151,7 +1151,7 @@ static void add_msvcrt_os_dep(CodeGen *parent, CodeGen *child_gen, const char *s } static void add_mingwex_os_dep(CodeGen *parent, CodeGen *child_gen, const char *src_path) { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = buf_ptr(buf_sprintf("%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "%s", buf_ptr(parent->zig_lib_dir), src_path)); c_file->args.append("-DHAVE_CONFIG_H"); @@ -1178,7 +1178,7 @@ static void add_mingwex_os_dep(CodeGen *parent, CodeGen *child_gen, const char * static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2ProgressNode *progress_node) { if (parent->libc == nullptr && parent->zig_target->os == OsWindows) { if (strcmp(file, "crt2.o") == 0) { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = buf_ptr(buf_sprintf( "%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "crt" OS_SEP "crtexe.c", buf_ptr(parent->zig_lib_dir))); mingw_add_cc_args(parent, c_file); @@ -1190,7 +1190,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr //c_file->args.append("-DWPRFLAG=1"); return build_libc_object(parent, "crt2", c_file, progress_node); } else if (strcmp(file, "dllcrt2.o") == 0) { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = buf_ptr(buf_sprintf( "%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "crt" OS_SEP "crtdll.c", buf_ptr(parent->zig_lib_dir))); mingw_add_cc_args(parent, c_file); @@ -1231,7 +1231,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr "mingw" OS_SEP "crt" OS_SEP "cxa_atexit.c", }; for (size_t i = 0; i < array_length(deps); i += 1) { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = path_from_libc(parent, deps[i]); c_file->args.append("-DHAVE_CONFIG_H"); c_file->args.append("-D_SYSCRT=1"); @@ -1301,7 +1301,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr } } else if (parent->libc == nullptr && target_is_glibc(parent->zig_target)) { if (strcmp(file, "crti.o") == 0) { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = glibc_start_asm_path(parent, "crti.S"); glibc_add_include_dirs(parent, c_file); c_file->args.append("-D_LIBC_REENTRANT"); @@ -1317,7 +1317,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr c_file->args.append("-Wa,--noexecstack"); return build_libc_object(parent, "crti", c_file, progress_node); } else if (strcmp(file, "crtn.o") == 0) { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = glibc_start_asm_path(parent, "crtn.S"); glibc_add_include_dirs(parent, c_file); c_file->args.append("-D_LIBC_REENTRANT"); @@ -1328,7 +1328,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr c_file->args.append("-Wa,--noexecstack"); return build_libc_object(parent, "crtn", c_file, progress_node); } else if (strcmp(file, "start.os") == 0) { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = glibc_start_asm_path(parent, "start.S"); glibc_add_include_dirs(parent, c_file); c_file->args.append("-D_LIBC_REENTRANT"); @@ -1346,7 +1346,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr c_file->args.append("-Wa,--noexecstack"); return build_libc_object(parent, "start", c_file, progress_node); } else if (strcmp(file, "abi-note.o") == 0) { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = path_from_libc(parent, "glibc" OS_SEP "csu" OS_SEP "abi-note.S"); c_file->args.append("-I"); c_file->args.append(path_from_libc(parent, "glibc" OS_SEP "csu")); @@ -1369,7 +1369,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr } else if (strcmp(file, "libc_nonshared.a") == 0) { CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c_nonshared", progress_node); { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = path_from_libc(parent, "glibc" OS_SEP "csu" OS_SEP "elf-init.c"); c_file->args.append("-std=gnu11"); c_file->args.append("-fgnu89-inline"); @@ -1419,7 +1419,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr {"stack_chk_fail_local", "glibc" OS_SEP "debug" OS_SEP "stack_chk_fail_local.c"}, }; for (size_t i = 0; i < array_length(deps); i += 1) { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = path_from_libc(parent, deps[i].path); c_file->args.append("-std=gnu11"); c_file->args.append("-fgnu89-inline"); @@ -1451,26 +1451,26 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr } } else if (parent->libc == nullptr && target_is_musl(parent->zig_target)) { if (strcmp(file, "crti.o") == 0) { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = musl_start_asm_path(parent, "crti.s"); musl_add_cc_args(parent, c_file, false); c_file->args.append("-Qunused-arguments"); return build_libc_object(parent, "crti", c_file, progress_node); } else if (strcmp(file, "crtn.o") == 0) { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = musl_start_asm_path(parent, "crtn.s"); c_file->args.append("-Qunused-arguments"); musl_add_cc_args(parent, c_file, false); return build_libc_object(parent, "crtn", c_file, progress_node); } else if (strcmp(file, "crt1.o") == 0) { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = path_from_libc(parent, "musl" OS_SEP "crt" OS_SEP "crt1.c"); musl_add_cc_args(parent, c_file, false); c_file->args.append("-fno-stack-protector"); c_file->args.append("-DCRT"); return build_libc_object(parent, "crt1", c_file, progress_node); } else if (strcmp(file, "Scrt1.o") == 0) { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); c_file->source_path = path_from_libc(parent, "musl" OS_SEP "crt" OS_SEP "Scrt1.c"); musl_add_cc_args(parent, c_file, false); c_file->args.append("-fPIC"); @@ -1987,7 +1987,7 @@ static const char *get_def_lib(CodeGen *parent, const char *name, Buf *def_in_fi Buf *def_include_dir = buf_sprintf("%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "def-include", buf_ptr(parent->zig_lib_dir)); - CacheHash *cache_hash = allocate(1); + CacheHash *cache_hash = heap::c_allocator.create(); cache_init(cache_hash, manifest_dir); cache_buf(cache_hash, compiler_id); @@ -2372,7 +2372,7 @@ static void construct_linker_job_coff(LinkJob *lj) { lj->args.append(get_def_lib(g, name, &lib_path)); - free(name); + mem::os::free(name); } } @@ -2647,13 +2647,6 @@ void codegen_link(CodeGen *g) { lj.rpath_table.init(4); lj.codegen = g; - if (g->verbose_llvm_ir) { - fprintf(stderr, "\nOptimization:\n"); - fprintf(stderr, "---------------\n"); - fflush(stderr); - LLVMDumpModule(g->module); - } - if (g->out_type == OutTypeObj) { lj.args.append("-r"); } diff --git a/src/list.hpp b/src/list.hpp index 4b2833843b..2c6d90c855 100644 --- a/src/list.hpp +++ b/src/list.hpp @@ -13,7 +13,7 @@ template struct ZigList { void deinit() { - deallocate(items, capacity); + heap::c_allocator.deallocate(items, capacity); } void append(const T& item) { ensure_capacity(length + 1); @@ -70,7 +70,7 @@ struct ZigList { better_capacity = better_capacity * 5 / 2 + 8; } while (better_capacity < new_capacity); - items = reallocate_nonzero(items, capacity, better_capacity); + items = heap::c_allocator.reallocate_nonzero(items, capacity, better_capacity); capacity = better_capacity; } @@ -91,5 +91,3 @@ struct ZigList { }; #endif - - diff --git a/src/main.cpp b/src/main.cpp index e58120e057..9e16b516bd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,12 +11,14 @@ #include "compiler.hpp" #include "config.h" #include "error.hpp" +#include "heap.hpp" #include "os.hpp" #include "target.hpp" #include "libc_installation.hpp" #include "userland.h" #include "glibc.hpp" #include "dump_analysis.hpp" +#include "mem_profile.hpp" #include @@ -243,21 +245,10 @@ int main_exit(Stage2ProgressNode *root_progress_node, int exit_code) { if (root_progress_node != nullptr) { stage2_progress_end(root_progress_node); } -#ifdef ZIG_ENABLE_MEM_PROFILE - if (mem_report) { - memprof_dump_stats(stderr); - } -#endif return exit_code; } -int main(int argc, char **argv) { - stage2_attach_segfault_handler(); - -#ifdef ZIG_ENABLE_MEM_PROFILE - memprof_init(); -#endif - +static int main0(int argc, char **argv) { char *arg0 = argv[0]; Error err; @@ -279,9 +270,6 @@ int main(int argc, char **argv) { return ZigClang_main(argc, argv); } - // Must be before all os.hpp function calls. - os_init(); - if (argc == 2 && strcmp(argv[1], "id") == 0) { Buf *compiler_id; if ((err = get_compiler_id(&compiler_id))) { @@ -440,7 +428,7 @@ int main(int argc, char **argv) { bool enable_doc_generation = false; bool disable_bin_generation = false; const char *cache_dir = nullptr; - CliPkg *cur_pkg = allocate(1); + CliPkg *cur_pkg = heap::c_allocator.create(); BuildMode build_mode = BuildModeDebug; ZigList test_exec_args = {0}; int runtime_args_start = -1; @@ -636,6 +624,7 @@ int main(int argc, char **argv) { } else if (strcmp(arg, "-fmem-report") == 0) { #ifdef ZIG_ENABLE_MEM_PROFILE mem_report = true; + mem::report_print = true; #else fprintf(stderr, "-fmem-report requires configuring with -DZIG_ENABLE_MEM_PROFILE=ON\n"); return print_error_usage(arg0); @@ -696,7 +685,7 @@ int main(int argc, char **argv) { fprintf(stderr, "Expected 2 arguments after --pkg-begin\n"); return print_error_usage(arg0); } - CliPkg *new_cur_pkg = allocate(1); + CliPkg *new_cur_pkg = heap::c_allocator.create(); i += 1; new_cur_pkg->name = argv[i]; i += 1; @@ -811,7 +800,7 @@ int main(int argc, char **argv) { } else if (strcmp(arg, "--object") == 0) { objects.append(argv[i]); } else if (strcmp(arg, "--c-source") == 0) { - CFile *c_file = allocate(1); + CFile *c_file = heap::c_allocator.create(); for (;;) { if (argv[i][0] == '-') { c_file->args.append(argv[i]); @@ -991,7 +980,7 @@ int main(int argc, char **argv) { } } if (target_is_glibc(&target)) { - target.glibc_version = allocate(1); + target.glibc_version = heap::c_allocator.create(); if (target_glibc != nullptr) { if ((err = target_parse_glibc_version(target.glibc_version, target_glibc))) { @@ -1139,7 +1128,7 @@ int main(int argc, char **argv) { } ZigLibCInstallation *libc = nullptr; if (libc_txt != nullptr) { - libc = allocate(1); + libc = heap::c_allocator.create(); if ((err = zig_libc_parse(libc, buf_create_from_str(libc_txt), &target, true))) { fprintf(stderr, "Unable to parse --libc text file: %s\n", err_str(err)); return main_exit(root_progress_node, EXIT_FAILURE); @@ -1270,7 +1259,8 @@ int main(int argc, char **argv) { if (cmd == CmdRun) { #ifdef ZIG_ENABLE_MEM_PROFILE - memprof_dump_stats(stderr); + if (mem::report_print) + mem::print_report(); #endif const char *exec_path = buf_ptr(&g->output_file_path); @@ -1385,4 +1375,20 @@ int main(int argc, char **argv) { case CmdNone: return print_full_usage(arg0, stderr, EXIT_FAILURE); } + zig_unreachable(); +} + +int main(int argc, char **argv) { + stage2_attach_segfault_handler(); + os_init(); + mem::init(); + + auto result = main0(argc, argv); + +#ifdef ZIG_ENABLE_MEM_PROFILE + if (mem::report_print) + mem::intern_counters.print_report(); +#endif + mem::deinit(); + return result; } diff --git a/src/mem.cpp b/src/mem.cpp new file mode 100644 index 0000000000..51ee9a27ee --- /dev/null +++ b/src/mem.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#include "config.h" +#include "mem.hpp" +#include "mem_profile.hpp" +#include "heap.hpp" + +namespace mem { + +void init() { + heap::bootstrap_allocator_state.init("heap::bootstrap_allocator"); + heap::c_allocator_state.init("heap::c_allocator"); +} + +void deinit() { + heap::c_allocator_state.deinit(); + heap::bootstrap_allocator_state.deinit(); +} + +#ifdef ZIG_ENABLE_MEM_PROFILE +void print_report(FILE *file) { + heap::c_allocator_state.print_report(file); + intern_counters.print_report(file); +} +#endif + +#ifdef ZIG_ENABLE_MEM_PROFILE +bool report_print = false; +FILE *report_file{nullptr}; +#endif + +} // namespace mem diff --git a/src/mem.hpp b/src/mem.hpp new file mode 100644 index 0000000000..9e262b7d53 --- /dev/null +++ b/src/mem.hpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2020 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef ZIG_MEM_HPP +#define ZIG_MEM_HPP + +#include +#include +#include + +#include "config.h" +#include "util_base.hpp" +#include "mem_type_info.hpp" + +// +// -- Memory Allocation General Notes -- +// +// `heap::c_allocator` is the preferred general allocator. +// +// `heap::bootstrap_allocator` is an implementation detail for use +// by allocators themselves when incidental heap may be required for +// profiling and statistics. It breaks the infinite recursion cycle. +// +// `mem::os` contains a raw wrapper for system malloc API used in +// preference to calling ::{malloc, free, calloc, realloc} directly. +// This isolates usage and helps with audits: +// +// mem::os::malloc +// mem::os::free +// mem::os::calloc +// mem::os::realloc +// +namespace mem { + +// initialize mem module before any use +void init(); + +// deinitialize mem module to free memory and print report +void deinit(); + +// isolate system/libc allocators +namespace os { + +ATTRIBUTE_RETURNS_NOALIAS +inline void *malloc(size_t size) { +#ifndef NDEBUG + // make behavior when size == 0 portable + if (size == 0) + return nullptr; +#endif + auto ptr = ::malloc(size); + if (ptr == nullptr) + zig_panic("allocation failed"); + return ptr; +} + +inline void free(void *ptr) { + ::free(ptr); +} + +ATTRIBUTE_RETURNS_NOALIAS +inline void *calloc(size_t count, size_t size) { +#ifndef NDEBUG + // make behavior when size == 0 portable + if (count == 0 || size == 0) + return nullptr; +#endif + auto ptr = ::calloc(count, size); + if (ptr == nullptr) + zig_panic("allocation failed"); + return ptr; +} + +inline void *realloc(void *old_ptr, size_t size) { +#ifndef NDEBUG + // make behavior when size == 0 portable + if (old_ptr == nullptr && size == 0) + return nullptr; +#endif + auto ptr = ::realloc(old_ptr, size); + if (ptr == nullptr) + zig_panic("allocation failed"); + return ptr; +} + +} // namespace os + +struct Allocator { + virtual void destruct(Allocator *allocator) = 0; + + template ATTRIBUTE_RETURNS_NOALIAS + T *allocate(size_t count) { + return reinterpret_cast(this->internal_allocate(TypeInfo::make(), count)); + } + + template ATTRIBUTE_RETURNS_NOALIAS + T *allocate_nonzero(size_t count) { + return reinterpret_cast(this->internal_allocate_nonzero(TypeInfo::make(), count)); + } + + template + T *reallocate(T *old_ptr, size_t old_count, size_t new_count) { + return reinterpret_cast(this->internal_reallocate(TypeInfo::make(), old_ptr, old_count, new_count)); + } + + template + T *reallocate_nonzero(T *old_ptr, size_t old_count, size_t new_count) { + return reinterpret_cast(this->internal_reallocate_nonzero(TypeInfo::make(), old_ptr, old_count, new_count)); + } + + template + void deallocate(T *ptr, size_t count) { + this->internal_deallocate(TypeInfo::make(), ptr, count); + } + + template + T *create() { + return reinterpret_cast(this->internal_allocate(TypeInfo::make(), 1)); + } + + template + void destroy(T *ptr) { + this->internal_deallocate(TypeInfo::make(), ptr, 1); + } + +protected: + ATTRIBUTE_RETURNS_NOALIAS virtual void *internal_allocate(const TypeInfo &info, size_t count) = 0; + ATTRIBUTE_RETURNS_NOALIAS virtual void *internal_allocate_nonzero(const TypeInfo &info, size_t count) = 0; + virtual void *internal_reallocate(const TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) = 0; + virtual void *internal_reallocate_nonzero(const TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) = 0; + virtual void internal_deallocate(const TypeInfo &info, void *ptr, size_t count) = 0; +}; + +#ifdef ZIG_ENABLE_MEM_PROFILE +void print_report(FILE *file = nullptr); + +// global memory report flag +extern bool report_print; +// global memory report default destination +extern FILE *report_file; +#endif + +} // namespace mem + +#endif diff --git a/src/mem_hash_map.hpp b/src/mem_hash_map.hpp new file mode 100644 index 0000000000..6abbbf6650 --- /dev/null +++ b/src/mem_hash_map.hpp @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2015 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef ZIG_MEM_HASH_MAP_HPP +#define ZIG_MEM_HASH_MAP_HPP + +#include "mem.hpp" + +namespace mem { + +template +class HashMap { +public: + void init(Allocator& allocator, int capacity) { + init_capacity(allocator, capacity); + } + void deinit(Allocator& allocator) { + allocator.deallocate(_entries, _capacity); + } + + struct Entry { + K key; + V value; + bool used; + int distance_from_start_index; + }; + + void clear() { + for (int i = 0; i < _capacity; i += 1) { + _entries[i].used = false; + } + _size = 0; + _max_distance_from_start_index = 0; + _modification_count += 1; + } + + int size() const { + return _size; + } + + void put(Allocator& allocator, const K &key, const V &value) { + _modification_count += 1; + internal_put(key, value); + + // if we get too full (60%), double the capacity + if (_size * 5 >= _capacity * 3) { + Entry *old_entries = _entries; + int old_capacity = _capacity; + init_capacity(allocator, _capacity * 2); + // dump all of the old elements into the new table + for (int i = 0; i < old_capacity; i += 1) { + Entry *old_entry = &old_entries[i]; + if (old_entry->used) + internal_put(old_entry->key, old_entry->value); + } + allocator.deallocate(old_entries, old_capacity); + } + } + + Entry *put_unique(Allocator& allocator, const K &key, const V &value) { + // TODO make this more efficient + Entry *entry = internal_get(key); + if (entry) + return entry; + put(allocator, key, value); + return nullptr; + } + + const V &get(const K &key) const { + Entry *entry = internal_get(key); + if (!entry) + zig_panic("key not found"); + return entry->value; + } + + Entry *maybe_get(const K &key) const { + return internal_get(key); + } + + void maybe_remove(const K &key) { + if (maybe_get(key)) { + remove(key); + } + } + + void remove(const K &key) { + _modification_count += 1; + int start_index = key_to_index(key); + for (int roll_over = 0; roll_over <= _max_distance_from_start_index; roll_over += 1) { + int index = (start_index + roll_over) % _capacity; + Entry *entry = &_entries[index]; + + if (!entry->used) + zig_panic("key not found"); + + if (!EqualFn(entry->key, key)) + continue; + + for (; roll_over < _capacity; roll_over += 1) { + int next_index = (start_index + roll_over + 1) % _capacity; + Entry *next_entry = &_entries[next_index]; + if (!next_entry->used || next_entry->distance_from_start_index == 0) { + entry->used = false; + _size -= 1; + return; + } + *entry = *next_entry; + entry->distance_from_start_index -= 1; + entry = next_entry; + } + zig_panic("shifting everything in the table"); + } + zig_panic("key not found"); + } + + class Iterator { + public: + Entry *next() { + if (_inital_modification_count != _table->_modification_count) + zig_panic("concurrent modification"); + if (_count >= _table->size()) + return NULL; + for (; _index < _table->_capacity; _index += 1) { + Entry *entry = &_table->_entries[_index]; + if (entry->used) { + _index += 1; + _count += 1; + return entry; + } + } + zig_panic("no next item"); + } + + private: + const HashMap * _table; + // how many items have we returned + int _count = 0; + // iterator through the entry array + int _index = 0; + // used to detect concurrent modification + uint32_t _inital_modification_count; + Iterator(const HashMap * table) : + _table(table), _inital_modification_count(table->_modification_count) { + } + friend HashMap; + }; + + // you must not modify the underlying HashMap while this iterator is still in use + Iterator entry_iterator() const { + return Iterator(this); + } + +private: + Entry *_entries; + int _capacity; + int _size; + int _max_distance_from_start_index; + // this is used to detect bugs where a hashtable is edited while an iterator is running. + uint32_t _modification_count; + + void init_capacity(Allocator& allocator, int capacity) { + _capacity = capacity; + _entries = allocator.allocate(_capacity); + _size = 0; + _max_distance_from_start_index = 0; + for (int i = 0; i < _capacity; i += 1) { + _entries[i].used = false; + } + } + + void internal_put(K key, V value) { + int start_index = key_to_index(key); + for (int roll_over = 0, distance_from_start_index = 0; + roll_over < _capacity; roll_over += 1, distance_from_start_index += 1) + { + int index = (start_index + roll_over) % _capacity; + Entry *entry = &_entries[index]; + + if (entry->used && !EqualFn(entry->key, key)) { + if (entry->distance_from_start_index < distance_from_start_index) { + // robin hood to the rescue + Entry tmp = *entry; + if (distance_from_start_index > _max_distance_from_start_index) + _max_distance_from_start_index = distance_from_start_index; + *entry = { + key, + value, + true, + distance_from_start_index, + }; + key = tmp.key; + value = tmp.value; + distance_from_start_index = tmp.distance_from_start_index; + } + continue; + } + + if (!entry->used) { + // adding an entry. otherwise overwriting old value with + // same key + _size += 1; + } + + if (distance_from_start_index > _max_distance_from_start_index) + _max_distance_from_start_index = distance_from_start_index; + *entry = { + key, + value, + true, + distance_from_start_index, + }; + return; + } + zig_panic("put into a full HashMap"); + } + + + Entry *internal_get(const K &key) const { + int start_index = key_to_index(key); + for (int roll_over = 0; roll_over <= _max_distance_from_start_index; roll_over += 1) { + int index = (start_index + roll_over) % _capacity; + Entry *entry = &_entries[index]; + + if (!entry->used) + return NULL; + + if (EqualFn(entry->key, key)) + return entry; + } + return NULL; + } + + int key_to_index(const K &key) const { + return (int)(HashFunction(key) % ((uint32_t)_capacity)); + } +}; + +} // namespace mem + +#endif diff --git a/src/mem_list.hpp b/src/mem_list.hpp new file mode 100644 index 0000000000..a09d4d1c8d --- /dev/null +++ b/src/mem_list.hpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef ZIG_MEM_LIST_HPP +#define ZIG_MEM_LIST_HPP + +#include "mem.hpp" + +namespace mem { + +template +struct List { + void deinit(Allocator& allocator) { + allocator.deallocate(items, capacity); + } + + void append(Allocator& allocator, const T& item) { + ensure_capacity(allocator, length + 1); + items[length++] = item; + } + + // remember that the pointer to this item is invalid after you + // modify the length of the list + const T & at(size_t index) const { + assert(index != SIZE_MAX); + assert(index < length); + return items[index]; + } + + T & at(size_t index) { + assert(index != SIZE_MAX); + assert(index < length); + return items[index]; + } + + T pop() { + assert(length >= 1); + return items[--length]; + } + + T *add_one() { + resize(length + 1); + return &last(); + } + + const T & last() const { + assert(length >= 1); + return items[length - 1]; + } + + T & last() { + assert(length >= 1); + return items[length - 1]; + } + + void resize(Allocator& allocator, size_t new_length) { + assert(new_length != SIZE_MAX); + ensure_capacity(allocator, new_length); + length = new_length; + } + + void clear() { + length = 0; + } + + void ensure_capacity(Allocator& allocator, size_t new_capacity) { + if (capacity >= new_capacity) + return; + + size_t better_capacity = capacity; + do { + better_capacity = better_capacity * 5 / 2 + 8; + } while (better_capacity < new_capacity); + + items = allocator.reallocate_nonzero(items, capacity, better_capacity); + capacity = better_capacity; + } + + T swap_remove(size_t index) { + if (length - 1 == index) return pop(); + + assert(index != SIZE_MAX); + assert(index < length); + + T old_item = items[index]; + items[index] = pop(); + return old_item; + } + + T *items{nullptr}; + size_t length{0}; + size_t capacity{0}; +}; + +} // namespace mem + +#endif diff --git a/src/mem_profile.cpp b/src/mem_profile.cpp new file mode 100644 index 0000000000..ef47c3f426 --- /dev/null +++ b/src/mem_profile.cpp @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2020 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#include "config.h" + +#ifdef ZIG_ENABLE_MEM_PROFILE + +#include "mem.hpp" +#include "mem_list.hpp" +#include "mem_profile.hpp" +#include "heap.hpp" + +namespace mem { + +void Profile::init(const char *name, const char *kind) { + this->name = name; + this->kind = kind; + this->usage_table.init(heap::bootstrap_allocator, 1024); +} + +void Profile::deinit() { + assert(this->name != nullptr); + if (mem::report_print) + this->print_report(); + this->usage_table.deinit(heap::bootstrap_allocator); + this->name = nullptr; +} + +void Profile::record_alloc(const TypeInfo &info, size_t count) { + if (count == 0) return; + auto existing_entry = this->usage_table.put_unique( + heap::bootstrap_allocator, + UsageKey{info.name_ptr, info.name_len}, + Entry{info, 1, count, 0, 0} ); + if (existing_entry != nullptr) { + assert(existing_entry->value.info.size == info.size); // allocated name does not match type + existing_entry->value.alloc.calls += 1; + existing_entry->value.alloc.objects += count; + } +} + +void Profile::record_dealloc(const TypeInfo &info, size_t count) { + if (count == 0) return; + auto existing_entry = this->usage_table.maybe_get(UsageKey{info.name_ptr, info.name_len}); + if (existing_entry == nullptr) { + fprintf(stderr, "deallocated name '"); + for (size_t i = 0; i < info.name_len; ++i) + fputc(info.name_ptr[i], stderr); + zig_panic("' (size %zu) not found in allocated table; compromised memory usage stats", info.size); + } + if (existing_entry->value.info.size != info.size) { + fprintf(stderr, "deallocated name '"); + for (size_t i = 0; i < info.name_len; ++i) + fputc(info.name_ptr[i], stderr); + zig_panic("' does not match expected type size %zu", info.size); + } + assert(existing_entry->value.alloc.calls - existing_entry->value.dealloc.calls > 0); + assert(existing_entry->value.alloc.objects - existing_entry->value.dealloc.objects >= count); + existing_entry->value.dealloc.calls += 1; + existing_entry->value.dealloc.objects += count; +} + +static size_t entry_remain_total_bytes(const Profile::Entry *entry) { + return (entry->alloc.objects - entry->dealloc.objects) * entry->info.size; +} + +static int entry_compare(const void *a, const void *b) { + size_t total_a = entry_remain_total_bytes(*reinterpret_cast(a)); + size_t total_b = entry_remain_total_bytes(*reinterpret_cast(b)); + if (total_a > total_b) + return -1; + if (total_a < total_b) + return 1; + return 0; +}; + +void Profile::print_report(FILE *file) { + if (!file) { + file = report_file; + if (!file) + file = stderr; + } + fprintf(file, "\n--- MEMORY PROFILE REPORT [%s]: %s ---\n", this->kind, this->name); + + List list; + auto it = this->usage_table.entry_iterator(); + for (;;) { + auto entry = it.next(); + if (!entry) + break; + list.append(heap::bootstrap_allocator, &entry->value); + } + + qsort(list.items, list.length, sizeof(const Entry *), entry_compare); + + size_t total_bytes_alloc = 0; + size_t total_bytes_dealloc = 0; + + size_t total_calls_alloc = 0; + size_t total_calls_dealloc = 0; + + for (size_t i = 0; i < list.length; i += 1) { + const Entry *entry = list.at(i); + fprintf(file, " "); + for (size_t j = 0; j < entry->info.name_len; ++j) + fputc(entry->info.name_ptr[j], file); + fprintf(file, ": %zu bytes each", entry->info.size); + + fprintf(file, ", alloc{ %zu calls, %zu objects, total ", entry->alloc.calls, entry->alloc.objects); + const auto alloc_num_bytes = entry->alloc.objects * entry->info.size; + zig_pretty_print_bytes(file, alloc_num_bytes); + + fprintf(file, " }, dealloc{ %zu calls, %zu objects, total ", entry->dealloc.calls, entry->dealloc.objects); + const auto dealloc_num_bytes = entry->dealloc.objects * entry->info.size; + zig_pretty_print_bytes(file, dealloc_num_bytes); + + fprintf(file, " }, remain{ %zu calls, %zu objects, total ", + entry->alloc.calls - entry->dealloc.calls, + entry->alloc.objects - entry->dealloc.objects ); + const auto remain_num_bytes = alloc_num_bytes - dealloc_num_bytes; + zig_pretty_print_bytes(file, remain_num_bytes); + + fprintf(file, " }\n"); + + total_bytes_alloc += alloc_num_bytes; + total_bytes_dealloc += dealloc_num_bytes; + + total_calls_alloc += entry->alloc.calls; + total_calls_dealloc += entry->dealloc.calls; + } + + fprintf(file, "\n Total bytes allocated: "); + zig_pretty_print_bytes(file, total_bytes_alloc); + fprintf(file, ", deallocated: "); + zig_pretty_print_bytes(file, total_bytes_dealloc); + fprintf(file, ", remaining: "); + zig_pretty_print_bytes(file, total_bytes_alloc - total_bytes_dealloc); + + fprintf(file, "\n Total calls alloc: %zu, dealloc: %zu, remain: %zu\n", + total_calls_alloc, total_calls_dealloc, (total_calls_alloc - total_calls_dealloc)); + + list.deinit(heap::bootstrap_allocator); +} + +uint32_t Profile::usage_hash(UsageKey key) { + // FNV 32-bit hash + uint32_t h = 2166136261; + for (size_t i = 0; i < key.name_len; ++i) { + h = h ^ key.name_ptr[i]; + h = h * 16777619; + } + return h; +} + +bool Profile::usage_equal(UsageKey a, UsageKey b) { + return memcmp(a.name_ptr, b.name_ptr, a.name_len > b.name_len ? a.name_len : b.name_len) == 0; +} + +void InternCounters::print_report(FILE *file) { + if (!file) { + file = report_file; + if (!file) + file = stderr; + } + fprintf(file, "\n--- IR INTERNING REPORT ---\n"); + fprintf(file, " undefined: interned %zu times\n", intern_counters.x_undefined); + fprintf(file, " void: interned %zu times\n", intern_counters.x_void); + fprintf(file, " null: interned %zu times\n", intern_counters.x_null); + fprintf(file, " unreachable: interned %zu times\n", intern_counters.x_unreachable); + fprintf(file, " zero_byte: interned %zu times\n", intern_counters.zero_byte); +} + +InternCounters intern_counters; + +} // namespace mem + +#endif diff --git a/src/mem_profile.hpp b/src/mem_profile.hpp new file mode 100644 index 0000000000..3b13b7680b --- /dev/null +++ b/src/mem_profile.hpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef ZIG_MEM_PROFILE_HPP +#define ZIG_MEM_PROFILE_HPP + +#include "config.h" + +#ifdef ZIG_ENABLE_MEM_PROFILE + +#include + +#include "mem.hpp" +#include "mem_hash_map.hpp" +#include "util.hpp" + +namespace mem { + +struct Profile { + void init(const char *name, const char *kind); + void deinit(); + + void record_alloc(const TypeInfo &info, size_t count); + void record_dealloc(const TypeInfo &info, size_t count); + + void print_report(FILE *file = nullptr); + + struct Entry { + TypeInfo info; + + struct Use { + size_t calls; + size_t objects; + } alloc, dealloc; + }; + +private: + const char *name; + const char *kind; + + struct UsageKey { + const char *name_ptr; + size_t name_len; + }; + + static uint32_t usage_hash(UsageKey key); + static bool usage_equal(UsageKey a, UsageKey b); + + HashMap usage_table; +}; + +struct InternCounters { + size_t x_undefined; + size_t x_void; + size_t x_null; + size_t x_unreachable; + size_t zero_byte; + + void print_report(FILE *file = nullptr); +}; + +extern InternCounters intern_counters; + +} // namespace mem + +#endif +#endif diff --git a/src/mem_type_info.hpp b/src/mem_type_info.hpp new file mode 100644 index 0000000000..8698992ca0 --- /dev/null +++ b/src/mem_type_info.hpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2020 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef ZIG_MEM_TYPE_INFO_HPP +#define ZIG_MEM_TYPE_INFO_HPP + +#include "config.h" + +#ifndef ZIG_TYPE_INFO_IMPLEMENTATION +# ifdef ZIG_ENABLE_MEM_PROFILE +# define ZIG_TYPE_INFO_IMPLEMENTATION 1 +# else +# define ZIG_TYPE_INFO_IMPLEMENTATION 0 +# endif +#endif + +namespace mem { + +#if ZIG_TYPE_INFO_IMPLEMENTATION == 0 + +struct TypeInfo { + size_t size; + size_t alignment; + + template + static constexpr TypeInfo make() { + return {sizeof(T), alignof(T)}; + } +}; + +#elif ZIG_TYPE_INFO_IMPLEMENTATION == 1 + +// +// A non-portable way to get a human-readable type-name compatible with +// non-RTTI C++ compiler mode; eg. `-fno-rtti`. +// +// Minimum requirements are c++11 and a compiler that has a constant for the +// current function's decorated name whereby a template-type name can be +// computed. eg. `__PRETTY_FUNCTION__` or `__FUNCSIG__`. +// +// given the following snippet: +// +// | #include +// | +// | struct Top {}; +// | namespace mynamespace { +// | using custom = unsigned int; +// | struct Foo { +// | struct Bar {}; +// | }; +// | }; +// | +// | template +// | void foobar() { +// | #ifdef _MSC_VER +// | fprintf(stderr, "--> %s\n", __FUNCSIG__); +// | #else +// | fprintf(stderr, "--> %s\n", __PRETTY_FUNCTION__); +// | #endif +// | } +// | +// | int main() { +// | foobar(); +// | foobar(); +// | foobar(); +// | foobar(); +// | foobar(); +// | } +// +// gcc 9.2.0 produces: +// --> void foobar() [with T = Top] +// --> void foobar() [with T = unsigned int] +// --> void foobar() [with T = unsigned int] +// --> void foobar() [with T = mynamespace::Foo*] +// --> void foobar() [with T = mynamespace::Foo::Bar*] +// +// xcode 11.3.1/clang produces: +// --> void foobar() [T = Top] +// --> void foobar() [T = unsigned int] +// --> void foobar() [T = unsigned int] +// --> void foobar() [T = mynamespace::Foo *] +// --> void foobar() [T = mynamespace::Foo::Bar *] +// +// VStudio 2019 16.5.0/msvc produces: +// --> void __cdecl foobar(void) +// --> void __cdecl foobar(void) +// --> void __cdecl foobar(void) +// --> void __cdecl foobar(void) +// --> void __cdecl foobar(void) +// +struct TypeInfo { + const char *name_ptr; + size_t name_len; + size_t size; + size_t alignment; + + static constexpr TypeInfo to_type_info(const char *str, size_t start, size_t end, size_t size, size_t alignment) { + return TypeInfo{str + start, end - start, size, alignment}; + } + + static constexpr size_t index_of(const char *str, char c) { + return *str == c ? 0 : 1 + index_of(str + 1, c); + } + + template + static constexpr const char *decorated_name() { +#ifdef _MSC_VER + return __FUNCSIG__; +#else + return __PRETTY_FUNCTION__; +#endif + } + + static constexpr TypeInfo extract(const char *decorated, size_t size, size_t alignment) { +#ifdef _MSC_VER + return to_type_info(decorated, index_of(decorated, '<') + 1, index_of(decorated, '>'), size, alignment); +#else + return to_type_info(decorated, index_of(decorated, '=') + 2, index_of(decorated, ']'), size, alignment); +#endif + } + + template + static constexpr TypeInfo make() { + return TypeInfo::extract(TypeInfo::decorated_name(), sizeof(T), alignof(T)); + } +}; + +#endif // ZIG_TYPE_INFO_IMPLEMENTATION + +} // namespace mem + +#endif diff --git a/src/memory_profiling.cpp b/src/memory_profiling.cpp deleted file mode 100644 index 4bd4cea7ba..0000000000 --- a/src/memory_profiling.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include "memory_profiling.hpp" -#include "hash_map.hpp" -#include "list.hpp" -#include "util.hpp" -#include - -#ifdef ZIG_ENABLE_MEM_PROFILE - -MemprofInternCount memprof_intern_count; - -static bool str_eql_str(const char *a, const char *b) { - return strcmp(a, b) == 0; -} - -static uint32_t str_hash(const char *s) { - // FNV 32-bit hash - uint32_t h = 2166136261; - for (; *s; s += 1) { - h = h ^ *s; - h = h * 16777619; - } - return h; -} - -struct CountAndSize { - size_t item_count; - size_t type_size; -}; - -ZigList unknown_names = {}; -HashMap usage_table = {}; -bool table_active = false; - -static const char *get_default_name(const char *name_or_null, size_t type_size) { - if (name_or_null != nullptr) return name_or_null; - if (type_size >= unknown_names.length) { - table_active = false; - while (type_size >= unknown_names.length) { - unknown_names.append(nullptr); - } - table_active = true; - } - if (unknown_names.at(type_size) == nullptr) { - char buf[100]; - sprintf(buf, "Unknown_%zu%c", type_size, 0); - unknown_names.at(type_size) = strdup(buf); - } - return unknown_names.at(type_size); -} - -void memprof_alloc(const char *name, size_t count, size_t type_size) { - if (!table_active) return; - if (count == 0) return; - // temporarily disable during table put - table_active = false; - name = get_default_name(name, type_size); - auto existing_entry = usage_table.put_unique(name, {count, type_size}); - if (existing_entry != nullptr) { - assert(existing_entry->value.type_size == type_size); // allocated name does not match type - existing_entry->value.item_count += count; - } - table_active = true; -} - -void memprof_dealloc(const char *name, size_t count, size_t type_size) { - if (!table_active) return; - if (count == 0) return; - name = get_default_name(name, type_size); - auto existing_entry = usage_table.maybe_get(name); - if (existing_entry == nullptr) { - zig_panic("deallocated name '%s' (size %zu) not found in allocated table; compromised memory usage stats", - name, type_size); - } - if (existing_entry->value.type_size != type_size) { - zig_panic("deallocated name '%s' does not match expected type size %zu", name, type_size); - } - existing_entry->value.item_count -= count; -} - -void memprof_init(void) { - usage_table.init(1024); - table_active = true; -} - -struct MemItem { - const char *type_name; - CountAndSize count_and_size; -}; - -static size_t get_bytes(const MemItem *item) { - return item->count_and_size.item_count * item->count_and_size.type_size; -} - -static int compare_bytes_desc(const void *a, const void *b) { - size_t size_a = get_bytes((const MemItem *)(a)); - size_t size_b = get_bytes((const MemItem *)(b)); - if (size_a > size_b) - return -1; - if (size_a < size_b) - return 1; - return 0; -} - -void memprof_dump_stats(FILE *file) { - assert(table_active); - // disable modifications from this function - table_active = false; - - ZigList list = {}; - - auto it = usage_table.entry_iterator(); - for (;;) { - auto *entry = it.next(); - if (!entry) - break; - - list.append({entry->key, entry->value}); - } - - qsort(list.items, list.length, sizeof(MemItem), compare_bytes_desc); - - size_t total_bytes_used = 0; - - for (size_t i = 0; i < list.length; i += 1) { - const MemItem *item = &list.at(i); - fprintf(file, "%s: %zu items, %zu bytes each, total ", item->type_name, - item->count_and_size.item_count, item->count_and_size.type_size); - size_t bytes = get_bytes(item); - zig_pretty_print_bytes(file, bytes); - fprintf(file, "\n"); - - total_bytes_used += bytes; - } - - fprintf(stderr, "Total bytes used: "); - zig_pretty_print_bytes(file, total_bytes_used); - fprintf(file, "\n"); - - list.deinit(); - table_active = true; - - fprintf(stderr, "\n"); - fprintf(stderr, "undefined: interned %zu times\n", memprof_intern_count.x_undefined); - fprintf(stderr, "void: interned %zu times\n", memprof_intern_count.x_void); - fprintf(stderr, "null: interned %zu times\n", memprof_intern_count.x_null); - fprintf(stderr, "unreachable: interned %zu times\n", memprof_intern_count.x_unreachable); - fprintf(stderr, "zero_byte: interned %zu times\n", memprof_intern_count.zero_byte); -} - -#endif diff --git a/src/memory_profiling.hpp b/src/memory_profiling.hpp deleted file mode 100644 index 78e77a89f1..0000000000 --- a/src/memory_profiling.hpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2019 Andrew Kelley - * - * This file is part of zig, which is MIT licensed. - * See http://opensource.org/licenses/MIT - */ - -#ifndef ZIG_MEMORY_PROFILING_HPP -#define ZIG_MEMORY_PROFILING_HPP - -#include "config.h" - -#include -#include - -struct MemprofInternCount { - size_t x_undefined; - size_t x_void; - size_t x_null; - size_t x_unreachable; - size_t zero_byte; -}; -extern MemprofInternCount memprof_intern_count; - -void memprof_init(void); - -void memprof_alloc(const char *name, size_t item_count, size_t type_size); -void memprof_dealloc(const char *name, size_t item_count, size_t type_size); - -void memprof_dump_stats(FILE *file); -#endif diff --git a/src/os.cpp b/src/os.cpp index c348851389..3eeab2b755 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -107,7 +107,7 @@ static void populate_termination(Termination *term, int status) { } static void os_spawn_process_posix(ZigList &args, Termination *term) { - const char **argv = allocate(args.length + 1); + const char **argv = heap::c_allocator.allocate(args.length + 1); for (size_t i = 0; i < args.length; i += 1) { argv[i] = args.at(i); } @@ -688,7 +688,7 @@ static Buf os_path_resolve_posix(Buf **paths_ptr, size_t paths_len) { if (have_abs) { result_len = max_size; - result_ptr = allocate_nonzero(result_len); + result_ptr = heap::c_allocator.allocate_nonzero(result_len); } else { Buf cwd = BUF_INIT; int err; @@ -696,7 +696,7 @@ static Buf os_path_resolve_posix(Buf **paths_ptr, size_t paths_len) { zig_panic("get cwd failed"); } result_len = max_size + buf_len(&cwd) + 1; - result_ptr = allocate_nonzero(result_len); + result_ptr = heap::c_allocator.allocate_nonzero(result_len); memcpy(result_ptr, buf_ptr(&cwd), buf_len(&cwd)); result_index += buf_len(&cwd); } @@ -816,7 +816,7 @@ static Error os_exec_process_posix(ZigList &args, if (dup2(stderr_pipe[1], STDERR_FILENO) == -1) zig_panic("dup2 failed"); - const char **argv = allocate(args.length + 1); + const char **argv = heap::c_allocator.allocate(args.length + 1); argv[args.length] = nullptr; for (size_t i = 0; i < args.length; i += 1) { argv[i] = args.at(i); @@ -1134,7 +1134,7 @@ static bool is_stderr_cyg_pty(void) { if (stderr_handle == INVALID_HANDLE_VALUE) return false; - int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH; + const int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH; FILE_NAME_INFO *nameinfo; WCHAR *p = NULL; @@ -1142,7 +1142,7 @@ static bool is_stderr_cyg_pty(void) { if (GetFileType(stderr_handle) != FILE_TYPE_PIPE) { return 0; } - nameinfo = (FILE_NAME_INFO *)allocate(size); + nameinfo = reinterpret_cast(heap::c_allocator.allocate(size)); if (nameinfo == NULL) { return 0; } @@ -1179,7 +1179,7 @@ static bool is_stderr_cyg_pty(void) { } } } - free(nameinfo); + heap::c_allocator.deallocate(reinterpret_cast(nameinfo), size); return (p != NULL); } #endif diff --git a/src/parser.cpp b/src/parser.cpp index 0da7aac639..ef2121e20d 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -147,7 +147,7 @@ static void ast_invalid_token_error(ParseContext *pc, Token *token) { } static AstNode *ast_create_node_no_line_info(ParseContext *pc, NodeType type) { - AstNode *node = allocate(1, "AstNode"); + AstNode *node = heap::c_allocator.create(); node->type = type; node->owner = pc->owner; return node; @@ -1966,7 +1966,7 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) { expect_token(pc, TokenIdRParen); - AsmOutput *res = allocate(1); + AsmOutput *res = heap::c_allocator.create(); res->asm_symbolic_name = token_buf(sym_name); res->constraint = token_buf(str); res->variable_name = token_buf(var_name); @@ -2003,7 +2003,7 @@ static AsmInput *ast_parse_asm_input_item(ParseContext *pc) { AstNode *expr = ast_expect(pc, ast_parse_expr); expect_token(pc, TokenIdRParen); - AsmInput *res = allocate(1); + AsmInput *res = heap::c_allocator.create(); res->asm_symbolic_name = token_buf(sym_name); res->constraint = token_buf(constraint); res->expr = expr; diff --git a/src/target.cpp b/src/target.cpp index b7629f2168..3d1fa2a969 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -524,7 +524,7 @@ void get_native_target(ZigTarget *target) { target->abi = target_default_abi(target->arch, target->os); } if (target_is_glibc(target)) { - target->glibc_version = allocate(1); + target->glibc_version = heap::c_allocator.create(); target_init_default_glibc_version(target); #ifdef ZIG_OS_LINUX Error err; diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 2aae048cdf..d3390aef3c 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -397,10 +397,10 @@ static void invalid_char_error(Tokenize *t, uint8_t c) { void tokenize(Buf *buf, Tokenization *out) { Tokenize t = {0}; t.out = out; - t.tokens = out->tokens = allocate>(1); + t.tokens = out->tokens = heap::c_allocator.create>(); t.buf = buf; - out->line_offsets = allocate>(1); + out->line_offsets = heap::c_allocator.create>(); out->line_offsets->append(0); // Skip the UTF-8 BOM if present diff --git a/src/userland.cpp b/src/userland.cpp index 8524be5739..ba0e906cf9 100644 --- a/src/userland.cpp +++ b/src/userland.cpp @@ -101,7 +101,7 @@ Error stage2_cpu_features_parse(struct Stage2CpuFeatures **out, const char *zig_ const char *cpu_name, const char *cpu_features) { if (zig_triple == nullptr) { - Stage2CpuFeatures *result = allocate(1, "Stage2CpuFeatures"); + Stage2CpuFeatures *result = heap::c_allocator.create(); result->llvm_cpu_name = ZigLLVMGetHostCPUName(); result->llvm_cpu_features = ZigLLVMGetNativeFeatures(); result->builtin_str = "arch.getBaselineCpuFeatures();\n"; @@ -110,7 +110,7 @@ Error stage2_cpu_features_parse(struct Stage2CpuFeatures **out, const char *zig_ return ErrorNone; } if (cpu_name == nullptr && cpu_features == nullptr) { - Stage2CpuFeatures *result = allocate(1, "Stage2CpuFeatures"); + Stage2CpuFeatures *result = heap::c_allocator.create(); result->builtin_str = "arch.getBaselineCpuFeatures();\n"; result->cache_hash = "\n\n"; *out = result; diff --git a/src/util.hpp b/src/util.hpp index e1722921f5..a119606245 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -8,69 +8,19 @@ #ifndef ZIG_UTIL_HPP #define ZIG_UTIL_HPP -#include "memory_profiling.hpp" - #include #include #include -#include #include #if defined(_MSC_VER) - #include - -#define ATTRIBUTE_COLD __declspec(noinline) -#define ATTRIBUTE_PRINTF(a, b) -#define ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict) -#define ATTRIBUTE_NORETURN __declspec(noreturn) -#define ATTRIBUTE_MUST_USE - -#define BREAKPOINT __debugbreak() - -#else - -#define ATTRIBUTE_COLD __attribute__((cold)) -#define ATTRIBUTE_PRINTF(a, b) __attribute__((format(printf, a, b))) -#define ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__)) -#define ATTRIBUTE_NORETURN __attribute__((noreturn)) -#define ATTRIBUTE_MUST_USE __attribute__((warn_unused_result)) - -#if defined(__MINGW32__) || defined(__MINGW64__) -#define BREAKPOINT __debugbreak() -#elif defined(__i386__) || defined(__x86_64__) -#define BREAKPOINT __asm__ volatile("int $0x03"); -#elif defined(__clang__) -#define BREAKPOINT __builtin_debugtrap() -#elif defined(__GNUC__) -#define BREAKPOINT __builtin_trap() -#else -#include -#define BREAKPOINT raise(SIGTRAP) #endif -#endif - -ATTRIBUTE_COLD -ATTRIBUTE_NORETURN -ATTRIBUTE_PRINTF(1, 2) -void zig_panic(const char *format, ...); - -static inline void zig_assert(bool ok, const char *file, int line, const char *func) { - if (!ok) { - zig_panic("Assertion failed at %s:%d in %s. This is a bug in the Zig compiler.", file, line, func); - } -} - -#ifdef _WIN32 -#define __func__ __FUNCTION__ -#endif - -#define zig_unreachable() zig_panic("Unreachable at %s:%d in %s. This is a bug in the Zig compiler.", __FILE__, __LINE__, __func__) - -// Assertions in stage1 are always on, and they call zig @panic. -#undef assert -#define assert(ok) zig_assert(ok, __FILE__, __LINE__, __func__) +#include "config.h" +#include "util_base.hpp" +#include "heap.hpp" +#include "mem.hpp" #if defined(_MSC_VER) static inline int clzll(unsigned long long mask) { @@ -107,78 +57,6 @@ static inline int ctzll(unsigned long long mask) { #define ctzll(x) __builtin_ctzll(x) #endif - -template -ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count, const char *name = nullptr) { -#ifdef ZIG_ENABLE_MEM_PROFILE - memprof_alloc(name, count, sizeof(T)); -#endif -#ifndef NDEBUG - // make behavior when size == 0 portable - if (count == 0) - return nullptr; -#endif - T *ptr = reinterpret_cast(malloc(count * sizeof(T))); - if (!ptr) - zig_panic("allocation failed"); - return ptr; -} - -template -ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate(size_t count, const char *name = nullptr) { -#ifdef ZIG_ENABLE_MEM_PROFILE - memprof_alloc(name, count, sizeof(T)); -#endif -#ifndef NDEBUG - // make behavior when size == 0 portable - if (count == 0) - return nullptr; -#endif - T *ptr = reinterpret_cast(calloc(count, sizeof(T))); - if (!ptr) - zig_panic("allocation failed"); - return ptr; -} - -template -static inline T *reallocate(T *old, size_t old_count, size_t new_count, const char *name = nullptr) { - T *ptr = reallocate_nonzero(old, old_count, new_count); - if (new_count > old_count) { - memset(&ptr[old_count], 0, (new_count - old_count) * sizeof(T)); - } - return ptr; -} - -template -static inline T *reallocate_nonzero(T *old, size_t old_count, size_t new_count, const char *name = nullptr) { -#ifdef ZIG_ENABLE_MEM_PROFILE - memprof_dealloc(name, old_count, sizeof(T)); - memprof_alloc(name, new_count, sizeof(T)); -#endif -#ifndef NDEBUG - // make behavior when size == 0 portable - if (new_count == 0 && old == nullptr) - return nullptr; -#endif - T *ptr = reinterpret_cast(realloc(old, new_count * sizeof(T))); - if (!ptr) - zig_panic("allocation failed"); - return ptr; -} - -template -static inline void deallocate(T *old, size_t count, const char *name = nullptr) { -#ifdef ZIG_ENABLE_MEM_PROFILE - memprof_dealloc(name, count, sizeof(T)); -#endif - free(old); -} - -template -static inline void destroy(T *old, const char *name = nullptr) { - return deallocate(old, 1, name); -} - template constexpr size_t array_length(const T (&)[n]) { return n; @@ -293,7 +171,7 @@ struct Slice { } static inline Slice alloc(size_t n) { - return {allocate_nonzero(n), n}; + return {heap::c_allocator.allocate_nonzero(n), n}; } }; diff --git a/src/util_base.hpp b/src/util_base.hpp new file mode 100644 index 0000000000..f6cea45c20 --- /dev/null +++ b/src/util_base.hpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef ZIG_UTIL_BASE_HPP +#define ZIG_UTIL_BASE_HPP + +#include + +#if defined(_MSC_VER) + +#define ATTRIBUTE_COLD __declspec(noinline) +#define ATTRIBUTE_PRINTF(a, b) +#define ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict) +#define ATTRIBUTE_NORETURN __declspec(noreturn) +#define ATTRIBUTE_MUST_USE + +#define BREAKPOINT __debugbreak() + +#else + +#define ATTRIBUTE_COLD __attribute__((cold)) +#define ATTRIBUTE_PRINTF(a, b) __attribute__((format(printf, a, b))) +#define ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__)) +#define ATTRIBUTE_NORETURN __attribute__((noreturn)) +#define ATTRIBUTE_MUST_USE __attribute__((warn_unused_result)) + +#if defined(__MINGW32__) || defined(__MINGW64__) +#define BREAKPOINT __debugbreak() +#elif defined(__i386__) || defined(__x86_64__) +#define BREAKPOINT __asm__ volatile("int $0x03"); +#elif defined(__clang__) +#define BREAKPOINT __builtin_debugtrap() +#elif defined(__GNUC__) +#define BREAKPOINT __builtin_trap() +#else +#include +#define BREAKPOINT raise(SIGTRAP) +#endif + +#endif + +ATTRIBUTE_COLD +ATTRIBUTE_NORETURN +ATTRIBUTE_PRINTF(1, 2) +void zig_panic(const char *format, ...); + +static inline void zig_assert(bool ok, const char *file, int line, const char *func) { + if (!ok) { + zig_panic("Assertion failed at %s:%d in %s. This is a bug in the Zig compiler.", file, line, func); + } +} + +#ifdef _WIN32 +#define __func__ __FUNCTION__ +#endif + +#define zig_unreachable() zig_panic("Unreachable at %s:%d in %s. This is a bug in the Zig compiler.", __FILE__, __LINE__, __func__) + +// Assertions in stage1 are always on, and they call zig @panic. +#undef assert +#define assert(ok) zig_assert(ok, __FILE__, __LINE__, __func__) + +#endif diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 45586ce0e0..cc2863a046 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3,6 +3,22 @@ const builtin = @import("builtin"); const Target = @import("std").Target; pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.addTest("duplicate field in anonymous struct literal", + \\export fn entry() void { + \\ const anon = .{ + \\ .inner = .{ + \\ .a = .{ + \\ .something = "text", + \\ }, + \\ .a = .{}, + \\ }, + \\ }; + \\} + , &[_][]const u8{ + "tmp.zig:7:13: error: duplicate field", + "tmp.zig:4:13: note: other field here", + }); + cases.addTest("type mismatch in C prototype with varargs", \\const fn_ty = ?fn ([*c]u8, ...) callconv(.C) void; \\extern fn fn_decl(fmt: [*:0]u8, ...) void; diff --git a/test/stage1/behavior/atomics.zig b/test/stage1/behavior/atomics.zig index 1ae59ca2d7..ae98caae0a 100644 --- a/test/stage1/behavior/atomics.zig +++ b/test/stage1/behavior/atomics.zig @@ -146,10 +146,10 @@ fn testAtomicStore() void { } test "atomicrmw with floats" { - if (builtin.arch == .aarch64 or - builtin.arch == .arm or - builtin.arch == .riscv64) - return; + if (builtin.arch == .aarch64 or builtin.arch == .arm or builtin.arch == .riscv64) { + // https://github.com/ziglang/zig/issues/4457 + return error.SkipZigTest; + } testAtomicRmwFloat(); } diff --git a/test/stage1/behavior/bugs/1851.zig b/test/stage1/behavior/bugs/1851.zig index 679f4bf835..f3e7393b96 100644 --- a/test/stage1/behavior/bugs/1851.zig +++ b/test/stage1/behavior/bugs/1851.zig @@ -6,10 +6,9 @@ test "allocation and looping over 3-byte integer" { expect(@sizeOf([1]u24) == 4); expect(@alignOf(u24) == 4); expect(@alignOf([1]u24) == 4); - var buffer: [100]u8 = undefined; - const a = &std.heap.FixedBufferAllocator.init(&buffer).allocator; - var x = a.alloc(u24, 2) catch unreachable; + var x = try std.testing.allocator.alloc(u24, 2); + defer std.testing.allocator.free(x); expect(x.len == 2); x[0] = 0xFFFFFF; x[1] = 0xFFFFFF; diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig index b928ffc356..0d73ef6571 100644 --- a/test/stage1/behavior/cast.zig +++ b/test/stage1/behavior/cast.zig @@ -764,3 +764,30 @@ test "variable initialization uses result locations properly with regards to the const x: i32 = if (b) 1 else 2; expect(x == 1); } + +test "cast between [*c]T and ?[*:0]T on fn parameter" { + const S = struct { + const Handler = ?extern fn ([*c]const u8) void; + fn addCallback(handler: Handler) void {} + + fn myCallback(cstr: ?[*:0]const u8) callconv(.C) void {} + + fn doTheTest() void { + addCallback(myCallback); + } + }; + S.doTheTest(); +} + +test "cast between C pointer with different but compatible types" { + const S = struct { + fn foo(arg: [*]c_ushort) u16 { + return arg[0]; + } + fn doTheTest() void { + var x = [_]u16{ 4, 2, 1, 3 }; + expect(foo(@ptrCast([*]u16, &x)) == 4); + } + }; + S.doTheTest(); +} diff --git a/test/stage1/behavior/vector.zig b/test/stage1/behavior/vector.zig index 338f24d806..e89399c5e2 100644 --- a/test/stage1/behavior/vector.zig +++ b/test/stage1/behavior/vector.zig @@ -1,6 +1,7 @@ const std = @import("std"); const mem = std.mem; const expect = std.testing.expect; +const expectEqual = std.testing.expectEqual; const builtin = @import("builtin"); test "implicit cast vector to array - bool" { @@ -250,3 +251,29 @@ test "initialize vector which is a struct field" { S.doTheTest(); comptime S.doTheTest(); } + +test "vector comparison operators" { + const S = struct { + fn doTheTest() void { + { + const v1: @Vector(4, bool) = [_]bool{ true, false, true, false }; + const v2: @Vector(4, bool) = [_]bool{ false, true, false, true }; + expectEqual(@splat(4, true), v1 == v1); + expectEqual(@splat(4, false), v1 == v2); + expectEqual(@splat(4, true), v1 != v2); + expectEqual(@splat(4, false), v2 != v2); + } + { + const v1 = @splat(4, @as(u32, 0xc0ffeeee)); + const v2: @Vector(4, c_uint) = v1; + const v3 = @splat(4, @as(u32, 0xdeadbeef)); + expectEqual(@splat(4, true), v1 == v2); + expectEqual(@splat(4, false), v1 == v3); + expectEqual(@splat(4, true), v1 != v3); + expectEqual(@splat(4, false), v1 != v2); + } + } + }; + S.doTheTest(); + comptime S.doTheTest(); +} diff --git a/test/translate_c.zig b/test/translate_c.zig index 6246742c5f..bb2a310b0f 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -621,9 +621,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { cases.add("float suffixes", \\#define foo 3.14f \\#define bar 16.e-2l + \\#define FOO 0.12345 + \\#define BAR .12345 , &[_][]const u8{ "pub const foo = @as(f32, 3.14);", "pub const bar = @as(c_longdouble, 16.e-2);", + "pub const FOO = 0.12345;", + "pub const BAR = 0.12345;", }); cases.add("comments", @@ -1358,12 +1362,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void { cases.add("basic macro function", \\extern int c; \\#define BASIC(c) (c*2) + \\#define FOO(L,b) (L + b) , &[_][]const u8{ \\pub extern var c: c_int; , \\pub inline fn BASIC(c_1: var) @TypeOf(c_1 * 2) { \\ return c_1 * 2; \\} + , + \\pub inline fn FOO(L: var, b: var) @TypeOf(L + b) { + \\ return L + b; + \\} }); cases.add("macro defines string literal with hex", @@ -2529,10 +2538,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { cases.add("macro cast", \\#define FOO(bar) baz((void *)(baz)) + \\#define BAR (void*) a , &[_][]const u8{ \\pub inline fn FOO(bar: var) @TypeOf(baz(if (@typeId(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeId(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz))) { \\ return baz(if (@typeId(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeId(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz)); \\} + , + \\pub const BAR = if (@typeId(@TypeOf(a)) == .Pointer) @ptrCast(*c_void, a) else if (@typeId(@TypeOf(a)) == .Int) @intToPtr(*c_void, a) else @as(*c_void, a); }); cases.add("macro conditional operator",