From 70a4794c57425d75505583e03919df983c4d8ccd Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 10 Feb 2020 10:57:40 -0500 Subject: [PATCH 01/33] fix compiler assertion when duplicating fields... ...in nested anonymous struct literals closes #4391 --- src/ir.cpp | 37 ++++++++++++++++++++++--------------- test/compile_errors.zig | 16 ++++++++++++++++ 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index f71fe73567..f73b5ede1b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -771,23 +771,9 @@ static void ira_deref(IrAnalyze *ira) { destroy(ira, "IrAnalyze"); } -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 +784,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 +830,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; } 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; From ae5ba369e193ccf3f8103476efed34a6ff141a8d Mon Sep 17 00:00:00 2001 From: Vexu Date: Mon, 10 Feb 2020 16:37:37 +0200 Subject: [PATCH 02/33] translate-c float fixes --- lib/std/c/tokenizer.zig | 12 +++++++++--- src-self-hosted/translate_c.zig | 4 +++- test/translate_c.zig | 4 ++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/std/c/tokenizer.zig b/lib/std/c/tokenizer.zig index 80fd604eb5..a7342ba7f9 100644 --- a/lib/std/c/tokenizer.zig +++ b/lib/std/c/tokenizer.zig @@ -1079,6 +1079,9 @@ pub const Tokenizer = struct { 'x', 'X' => { state = .IntegerLiteralHex; }, + '.' => { + state = .FloatFraction; + }, else => { state = .IntegerSuffix; self.index -= 1; @@ -1261,13 +1264,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/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 221e4201ca..85ff72c9dc 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -5122,6 +5122,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); } @@ -5493,7 +5495,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/test/translate_c.zig b/test/translate_c.zig index 6246742c5f..a2eb69100f 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", From 1cdefeb10b7496126bbb7d00709235abfee56a4a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 10 Feb 2020 12:03:11 -0500 Subject: [PATCH 03/33] windows: remove the 'A' versions of psapi functions See #534 --- lib/std/os/windows/psapi.zig | 7 ------- 1 file changed, 7 deletions(-) diff --git a/lib/std/os/windows/psapi.zig b/lib/std/os/windows/psapi.zig index 1a5a7d4bf2..fd0b2ee535 100644 --- a/lib/std/os/windows/psapi.zig +++ b/lib/std/os/windows/psapi.zig @@ -2,24 +2,17 @@ usingnamespace @import("bits.zig"); pub extern "psapi" fn EmptyWorkingSet(hProcess: HANDLE) callconv(.Stdcall) BOOL; pub extern "psapi" fn EnumDeviceDrivers(lpImageBase: [*]LPVOID, cb: DWORD, lpcbNeeded: LPDWORD) callconv(.Stdcall) BOOL; -pub extern "psapi" fn EnumPageFilesA(pCallBackRoutine: PENUM_PAGE_FILE_CALLBACKA, pContext: LPVOID) callconv(.Stdcall) BOOL; pub extern "psapi" fn EnumPageFilesW(pCallBackRoutine: PENUM_PAGE_FILE_CALLBACKW, pContext: LPVOID) callconv(.Stdcall) BOOL; pub extern "psapi" fn EnumProcessModules(hProcess: HANDLE, lphModule: [*]HMODULE, cb: DWORD, lpcbNeeded: LPDWORD) callconv(.Stdcall) BOOL; pub extern "psapi" fn EnumProcessModulesEx(hProcess: HANDLE, lphModule: [*]HMODULE, cb: DWORD, lpcbNeeded: LPDWORD, dwFilterFlag: DWORD) callconv(.Stdcall) BOOL; pub extern "psapi" fn EnumProcesses(lpidProcess: [*]DWORD, cb: DWORD, cbNeeded: LPDWORD) callconv(.Stdcall) BOOL; -pub extern "psapi" fn GetDeviceDriverBaseNameA(ImageBase: LPVOID, lpBaseName: LPSTR, nSize: DWORD) callconv(.Stdcall) DWORD; pub extern "psapi" fn GetDeviceDriverBaseNameW(ImageBase: LPVOID, lpBaseName: LPWSTR, nSize: DWORD) callconv(.Stdcall) DWORD; -pub extern "psapi" fn GetDeviceDriverFileNameA(ImageBase: LPVOID, lpFilename: LPSTR, nSize: DWORD) callconv(.Stdcall) DWORD; pub extern "psapi" fn GetDeviceDriverFileNameW(ImageBase: LPVOID, lpFilename: LPWSTR, nSize: DWORD) callconv(.Stdcall) DWORD; -pub extern "psapi" fn GetMappedFileNameA(hProcess: HANDLE, lpv: ?LPVOID, lpFilename: LPSTR, nSize: DWORD) callconv(.Stdcall) DWORD; pub extern "psapi" fn GetMappedFileNameW(hProcess: HANDLE, lpv: ?LPVOID, lpFilename: LPWSTR, nSize: DWORD) callconv(.Stdcall) DWORD; -pub extern "psapi" fn GetModuleBaseNameA(hProcess: HANDLE, hModule: ?HMODULE, lpBaseName: LPSTR, nSize: DWORD) callconv(.Stdcall) DWORD; pub extern "psapi" fn GetModuleBaseNameW(hProcess: HANDLE, hModule: ?HMODULE, lpBaseName: LPWSTR, nSize: DWORD) callconv(.Stdcall) DWORD; -pub extern "psapi" fn GetModuleFileNameExA(hProcess: HANDLE, hModule: ?HMODULE, lpFilename: LPSTR, nSize: DWORD) callconv(.Stdcall) DWORD; pub extern "psapi" fn GetModuleFileNameExW(hProcess: HANDLE, hModule: ?HMODULE, lpFilename: LPWSTR, nSize: DWORD) callconv(.Stdcall) DWORD; pub extern "psapi" fn GetModuleInformation(hProcess: HANDLE, hModule: HMODULE, lpmodinfo: LPMODULEINFO, cb: DWORD) callconv(.Stdcall) BOOL; pub extern "psapi" fn GetPerformanceInfo(pPerformanceInformation: PPERFORMACE_INFORMATION, cb: DWORD) callconv(.Stdcall) BOOL; -pub extern "psapi" fn GetProcessImageFileNameA(hProcess: HANDLE, lpImageFileName: LPSTR, nSize: DWORD) callconv(.Stdcall) DWORD; pub extern "psapi" fn GetProcessImageFileNameW(hProcess: HANDLE, lpImageFileName: LPWSTR, nSize: DWORD) callconv(.Stdcall) DWORD; pub extern "psapi" fn GetProcessMemoryInfo(Process: HANDLE, ppsmemCounters: PPROCESS_MEMORY_COUNTERS, cb: DWORD) callconv(.Stdcall) BOOL; pub extern "psapi" fn GetWsChanges(hProcess: HANDLE, lpWatchInfo: PPSAPI_WS_WATCH_INFORMATION, cb: DWORD) callconv(.Stdcall) BOOL; From 702398dd0e2188ad03b3c4760c08ea673573489e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 10 Feb 2020 12:30:20 -0500 Subject: [PATCH 04/33] Revert "windows: remove the 'A' versions of psapi functions" This reverts commit 1cdefeb10b7496126bbb7d00709235abfee56a4a. See #4426 --- lib/std/os/windows/psapi.zig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/std/os/windows/psapi.zig b/lib/std/os/windows/psapi.zig index fd0b2ee535..1a5a7d4bf2 100644 --- a/lib/std/os/windows/psapi.zig +++ b/lib/std/os/windows/psapi.zig @@ -2,17 +2,24 @@ usingnamespace @import("bits.zig"); pub extern "psapi" fn EmptyWorkingSet(hProcess: HANDLE) callconv(.Stdcall) BOOL; pub extern "psapi" fn EnumDeviceDrivers(lpImageBase: [*]LPVOID, cb: DWORD, lpcbNeeded: LPDWORD) callconv(.Stdcall) BOOL; +pub extern "psapi" fn EnumPageFilesA(pCallBackRoutine: PENUM_PAGE_FILE_CALLBACKA, pContext: LPVOID) callconv(.Stdcall) BOOL; pub extern "psapi" fn EnumPageFilesW(pCallBackRoutine: PENUM_PAGE_FILE_CALLBACKW, pContext: LPVOID) callconv(.Stdcall) BOOL; pub extern "psapi" fn EnumProcessModules(hProcess: HANDLE, lphModule: [*]HMODULE, cb: DWORD, lpcbNeeded: LPDWORD) callconv(.Stdcall) BOOL; pub extern "psapi" fn EnumProcessModulesEx(hProcess: HANDLE, lphModule: [*]HMODULE, cb: DWORD, lpcbNeeded: LPDWORD, dwFilterFlag: DWORD) callconv(.Stdcall) BOOL; pub extern "psapi" fn EnumProcesses(lpidProcess: [*]DWORD, cb: DWORD, cbNeeded: LPDWORD) callconv(.Stdcall) BOOL; +pub extern "psapi" fn GetDeviceDriverBaseNameA(ImageBase: LPVOID, lpBaseName: LPSTR, nSize: DWORD) callconv(.Stdcall) DWORD; pub extern "psapi" fn GetDeviceDriverBaseNameW(ImageBase: LPVOID, lpBaseName: LPWSTR, nSize: DWORD) callconv(.Stdcall) DWORD; +pub extern "psapi" fn GetDeviceDriverFileNameA(ImageBase: LPVOID, lpFilename: LPSTR, nSize: DWORD) callconv(.Stdcall) DWORD; pub extern "psapi" fn GetDeviceDriverFileNameW(ImageBase: LPVOID, lpFilename: LPWSTR, nSize: DWORD) callconv(.Stdcall) DWORD; +pub extern "psapi" fn GetMappedFileNameA(hProcess: HANDLE, lpv: ?LPVOID, lpFilename: LPSTR, nSize: DWORD) callconv(.Stdcall) DWORD; pub extern "psapi" fn GetMappedFileNameW(hProcess: HANDLE, lpv: ?LPVOID, lpFilename: LPWSTR, nSize: DWORD) callconv(.Stdcall) DWORD; +pub extern "psapi" fn GetModuleBaseNameA(hProcess: HANDLE, hModule: ?HMODULE, lpBaseName: LPSTR, nSize: DWORD) callconv(.Stdcall) DWORD; pub extern "psapi" fn GetModuleBaseNameW(hProcess: HANDLE, hModule: ?HMODULE, lpBaseName: LPWSTR, nSize: DWORD) callconv(.Stdcall) DWORD; +pub extern "psapi" fn GetModuleFileNameExA(hProcess: HANDLE, hModule: ?HMODULE, lpFilename: LPSTR, nSize: DWORD) callconv(.Stdcall) DWORD; pub extern "psapi" fn GetModuleFileNameExW(hProcess: HANDLE, hModule: ?HMODULE, lpFilename: LPWSTR, nSize: DWORD) callconv(.Stdcall) DWORD; pub extern "psapi" fn GetModuleInformation(hProcess: HANDLE, hModule: HMODULE, lpmodinfo: LPMODULEINFO, cb: DWORD) callconv(.Stdcall) BOOL; pub extern "psapi" fn GetPerformanceInfo(pPerformanceInformation: PPERFORMACE_INFORMATION, cb: DWORD) callconv(.Stdcall) BOOL; +pub extern "psapi" fn GetProcessImageFileNameA(hProcess: HANDLE, lpImageFileName: LPSTR, nSize: DWORD) callconv(.Stdcall) DWORD; pub extern "psapi" fn GetProcessImageFileNameW(hProcess: HANDLE, lpImageFileName: LPWSTR, nSize: DWORD) callconv(.Stdcall) DWORD; pub extern "psapi" fn GetProcessMemoryInfo(Process: HANDLE, ppsmemCounters: PPROCESS_MEMORY_COUNTERS, cb: DWORD) callconv(.Stdcall) BOOL; pub extern "psapi" fn GetWsChanges(hProcess: HANDLE, lpWatchInfo: PPSAPI_WS_WATCH_INFORMATION, cb: DWORD) callconv(.Stdcall) BOOL; From 3170ead9eb3ca91218fd83ecc72170271f8b494c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 10 Feb 2020 19:14:54 -0500 Subject: [PATCH 05/33] compile error instead of abort for unimplemented `@typeInfo` of `@Frame(func)`. Closes #3995 --- src/ir.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index f73b5ede1b..d16c8a5e36 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -24564,7 +24564,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); From 3237528a592f2dc22659f77f5fbfb061dc14566a Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 10 Feb 2020 14:56:39 +0100 Subject: [PATCH 06/33] fmt: Pass the fmt string to the inner formatters --- lib/std/fmt.zig | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 370717a4f7..4a653823e5 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -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, " }"); }, @@ -1343,6 +1343,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)}); From 26183660558c43133d862912c602e316f43698c7 Mon Sep 17 00:00:00 2001 From: Timon Kruiper Date: Mon, 10 Feb 2020 23:42:07 +0100 Subject: [PATCH 07/33] Add cast between [*c]T and ?[*:0]T on fn parameter Fixes #4176 --- src/ir.cpp | 3 ++- test/stage1/behavior/cast.zig | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index d16c8a5e36..2b3b5f877b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -11592,7 +11592,8 @@ 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); diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig index fe55b445a8..a70467e199 100644 --- a/test/stage1/behavior/cast.zig +++ b/test/stage1/behavior/cast.zig @@ -768,3 +768,17 @@ 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(); +} From edb210905dcbe666fa5222bceacd2e5bdb16bb89 Mon Sep 17 00:00:00 2001 From: Michael Dusan Date: Mon, 10 Feb 2020 21:08:08 -0500 Subject: [PATCH 08/33] stage1: memory/report overhaul - split util_base.hpp from util.hpp - new namespaces: `mem` and `heap` - new `mem::Allocator` interface - new `heap::CAllocator` impl with global `heap::c_allocator` - new `heap::ArenaAllocator` impl - new `mem::TypeInfo` extracts names without RTTI - name extraction is enabled w/ ZIG_ENABLE_MEM_PROFILE=1 - new `mem::List` takes explicit `Allocator&` parameter - new `mem::HashMap` takes explicit `Allocator&` parameter - add Codegen.pass1_arena and use for all `ZigValue` allocs - deinit Codegen.pass1_arena early in `zig_llvm_emit_output()` --- CMakeLists.txt | 4 +- src/all_types.hpp | 4 +- src/analyze.cpp | 189 ++++--- src/analyze.hpp | 21 +- src/bigint.cpp | 32 +- src/buffer.hpp | 9 +- src/codegen.cpp | 75 +-- src/errmsg.cpp | 4 +- src/glibc.cpp | 8 +- src/hash_map.hpp | 6 +- src/heap.cpp | 377 ++++++++++++++ src/heap.hpp | 101 ++++ src/ir.cpp | 1039 ++++++++++++++++++-------------------- src/ir.hpp | 2 - src/link.cpp | 38 +- src/list.hpp | 6 +- src/main.cpp | 48 +- src/mem.cpp | 37 ++ src/mem.hpp | 149 ++++++ src/mem_hash_map.hpp | 244 +++++++++ src/mem_list.hpp | 101 ++++ src/mem_profile.cpp | 181 +++++++ src/mem_profile.hpp | 71 +++ src/mem_type_info.hpp | 136 +++++ src/memory_profiling.cpp | 150 ------ src/memory_profiling.hpp | 31 -- src/os.cpp | 14 +- src/parser.cpp | 6 +- src/target.cpp | 2 +- src/tokenizer.cpp | 4 +- src/userland.cpp | 4 +- src/util.hpp | 132 +---- src/util_base.hpp | 67 +++ 33 files changed, 2210 insertions(+), 1082 deletions(-) create mode 100644 src/heap.cpp create mode 100644 src/heap.hpp create mode 100644 src/mem.cpp create mode 100644 src/mem.hpp create mode 100644 src/mem_hash_map.hpp create mode 100644 src/mem_list.hpp create mode 100644 src/mem_profile.cpp create mode 100644 src/mem_profile.hpp create mode 100644 src/mem_type_info.hpp delete mode 100644 src/memory_profiling.cpp delete mode 100644 src/memory_profiling.hpp create mode 100644 src/util_base.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b4a375e60e..8a8ec226e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -450,7 +450,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 @@ -466,10 +466,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/src/all_types.hpp b/src/all_types.hpp index efbed07124..b514f4ecbc 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -2000,6 +2000,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; @@ -2280,7 +2283,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..c8b63f4535 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 = ""; @@ -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 89f868c925..fd6de466ba 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); @@ -4327,7 +4328,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); @@ -4680,8 +4681,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); @@ -4923,7 +4924,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()); @@ -4935,7 +4936,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), @@ -5003,8 +5004,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; @@ -5977,12 +5978,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), ""); @@ -7015,7 +7016,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); @@ -7074,7 +7075,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()); @@ -7138,7 +7139,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) { @@ -7170,7 +7171,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, ""); @@ -7180,7 +7181,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); } @@ -7382,7 +7383,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); @@ -7911,6 +7912,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; @@ -8207,7 +8211,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; @@ -8925,16 +8929,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; @@ -9016,7 +9020,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; @@ -9025,7 +9029,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 @@ -9105,7 +9109,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; @@ -9472,10 +9476,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); @@ -9486,7 +9490,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; @@ -9505,7 +9509,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, @@ -9640,7 +9644,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); @@ -10794,7 +10798,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"); @@ -10937,35 +10942,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 f73b5ede1b..4667757f11 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -269,477 +269,467 @@ static IrInstGen *ir_analyze_test_non_null(IrAnalyze *ira, IrInst *source_inst, static IrInstGen *ir_error_dependency_loop(IrAnalyze *ira, IrInst *source_instr); 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,15 +750,14 @@ 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_no_isf(CodeGen *g, ZigValue *const_val) { @@ -1017,8 +1006,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; @@ -1050,14 +1039,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); @@ -1066,7 +1052,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); @@ -1983,12 +1969,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; @@ -1999,29 +1980,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; @@ -2063,11 +2034,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; @@ -2157,7 +2128,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); @@ -2166,7 +2137,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); @@ -2175,7 +2146,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); @@ -2191,7 +2162,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); @@ -2202,7 +2173,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; @@ -2219,7 +2190,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; @@ -2228,7 +2199,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; @@ -2237,7 +2208,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; @@ -2246,7 +2217,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; @@ -5244,7 +5215,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); @@ -5332,7 +5303,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); @@ -5360,12 +5331,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; @@ -5425,15 +5396,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; @@ -5472,7 +5440,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; @@ -5562,7 +5530,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)); @@ -5604,7 +5572,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); @@ -5676,10 +5644,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; @@ -5718,10 +5686,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; @@ -5731,7 +5699,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; @@ -5809,10 +5777,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); @@ -5966,7 +5934,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, @@ -5983,7 +5951,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; @@ -6177,7 +6145,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); @@ -6203,7 +6171,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]; @@ -6388,7 +6356,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); @@ -7013,7 +6981,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; @@ -7166,7 +7134,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod size_t arg_count = node->data.fn_call_expr.params.length - 2; - 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 = node->data.fn_call_expr.params.at(i + 2); args[i] = ir_gen_node(irb, arg_node, scope); @@ -7595,10 +7563,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; @@ -7799,7 +7767,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); @@ -7875,7 +7843,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); @@ -7884,7 +7852,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; @@ -7914,14 +7882,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; @@ -7947,7 +7915,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; @@ -7961,7 +7929,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; @@ -8804,9 +8772,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, @@ -8940,10 +8908,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; @@ -9037,10 +9005,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; @@ -9133,7 +9101,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; @@ -9295,7 +9263,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); @@ -9677,10 +9645,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); @@ -9747,7 +9715,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; @@ -9790,7 +9758,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) { @@ -9837,7 +9805,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; @@ -9868,16 +9836,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); @@ -9902,7 +9870,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); } @@ -9910,7 +9878,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) { @@ -10191,7 +10159,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; } @@ -10280,7 +10248,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)); @@ -10372,7 +10340,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; } @@ -11522,7 +11490,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 = {}; @@ -11543,7 +11511,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; @@ -11595,7 +11563,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted actual_ptr_type->data.pointer.sentinel)); 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; @@ -11611,7 +11579,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; @@ -11623,7 +11591,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; @@ -11634,7 +11602,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; @@ -11674,7 +11642,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; @@ -11685,7 +11653,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; @@ -11713,7 +11681,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; @@ -11730,7 +11698,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; @@ -11747,7 +11715,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; @@ -11763,7 +11731,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; @@ -11775,7 +11743,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; @@ -11809,7 +11777,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); @@ -11821,12 +11789,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; } @@ -11855,7 +11823,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; } @@ -11884,7 +11852,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; } @@ -11905,14 +11873,14 @@ 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 = heap::c_allocator.allocate_nonzero(1); result.data.int_shorten->wanted_type = wanted_type; result.data.int_shorten->actual_type = actual_type; 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; @@ -11921,7 +11889,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, @@ -12591,7 +12559,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) { @@ -12670,7 +12638,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; } @@ -13199,7 +13167,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; @@ -13223,7 +13191,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; @@ -13424,7 +13392,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; } @@ -13465,7 +13433,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; @@ -13577,7 +13545,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; @@ -13842,7 +13810,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; @@ -14147,7 +14115,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; @@ -14361,7 +14329,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; } @@ -14374,7 +14342,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; } @@ -14674,7 +14642,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); @@ -16507,7 +16475,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++) { @@ -16515,7 +16483,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; } @@ -17415,7 +17383,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); @@ -17427,11 +17395,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; @@ -17448,7 +17416,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; @@ -17464,7 +17432,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); @@ -17472,21 +17440,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; @@ -17565,13 +17533,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; @@ -17582,7 +17550,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; @@ -17623,14 +17591,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); } @@ -17729,8 +17697,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); } } } @@ -17904,7 +17872,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; @@ -18133,7 +18101,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; @@ -18154,7 +18122,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; @@ -18235,8 +18203,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; @@ -18282,7 +18250,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); @@ -18346,7 +18314,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; @@ -18685,15 +18652,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; @@ -18706,8 +18673,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; @@ -19007,10 +18974,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; } @@ -19159,7 +19126,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) @@ -19394,8 +19361,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; @@ -19403,7 +19368,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; @@ -19437,12 +19402,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; @@ -19453,10 +19418,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) { @@ -19516,7 +19481,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); @@ -19649,7 +19613,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); @@ -19781,7 +19745,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)) @@ -19797,7 +19761,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; } @@ -19917,7 +19881,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); @@ -19930,12 +19894,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)) @@ -19944,7 +19908,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; } @@ -20019,7 +19983,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; @@ -20087,7 +20051,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; @@ -20371,7 +20335,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; @@ -20385,7 +20349,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); @@ -20758,7 +20722,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) { @@ -20822,7 +20786,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]; @@ -20845,11 +20809,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]; @@ -21175,7 +21139,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)) { @@ -21223,7 +21187,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]; @@ -21265,7 +21229,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; @@ -21285,7 +21249,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; } @@ -21356,7 +21320,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; @@ -21539,7 +21503,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 { @@ -21585,7 +21549,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); } } @@ -21614,7 +21578,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); } } @@ -21632,7 +21596,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; @@ -21659,7 +21623,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; @@ -21673,7 +21637,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); @@ -21695,7 +21659,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); @@ -21722,7 +21686,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); @@ -21744,7 +21708,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); @@ -22024,7 +21988,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; @@ -22097,8 +22061,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) { @@ -22137,7 +22101,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; @@ -22162,7 +22126,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; @@ -22282,7 +22246,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; @@ -22529,7 +22493,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]; @@ -22614,7 +22578,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; } @@ -22834,7 +22798,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) { @@ -22870,7 +22834,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; @@ -23018,7 +22982,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) @@ -23089,7 +23053,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); @@ -23353,7 +23317,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; } @@ -23679,11 +23643,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. @@ -23705,7 +23669,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; @@ -23736,7 +23700,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; @@ -23757,13 +23721,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 @@ -23801,7 +23765,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); @@ -23816,12 +23780,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); @@ -23848,7 +23812,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; @@ -23914,11 +23878,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 @@ -23973,7 +23937,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; @@ -24019,11 +23983,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 @@ -24041,11 +24005,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 @@ -24065,11 +24029,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 @@ -24089,11 +24053,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 @@ -24111,11 +24075,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 @@ -24127,11 +24091,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 @@ -24144,11 +24108,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 @@ -24170,11 +24134,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); @@ -24204,7 +24168,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); @@ -24219,15 +24183,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++) { @@ -24237,7 +24201,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; @@ -24259,11 +24223,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 @@ -24282,11 +24246,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 @@ -24303,7 +24267,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; @@ -24319,11 +24283,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); @@ -24336,14 +24300,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); } @@ -24378,11 +24342,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 @@ -24399,11 +24363,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); @@ -24414,7 +24378,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); @@ -24427,7 +24391,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); @@ -24463,11 +24427,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 @@ -24494,7 +24458,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; @@ -24508,11 +24472,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); @@ -24526,7 +24490,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; @@ -24539,7 +24503,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; @@ -24863,7 +24827,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; } @@ -24895,7 +24859,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, @@ -25574,11 +25537,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]; @@ -25865,7 +25828,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]; @@ -25878,7 +25841,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); } @@ -25898,7 +25861,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); @@ -25968,9 +25931,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; } @@ -26108,7 +26071,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); @@ -26284,7 +26247,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); @@ -26568,7 +26531,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]; @@ -26863,7 +26826,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; @@ -27189,7 +27152,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]; @@ -27270,7 +27233,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]; @@ -27332,7 +27295,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; @@ -27360,7 +27323,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); @@ -27515,7 +27478,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]; @@ -27572,7 +27535,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) { @@ -27765,7 +27728,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; } @@ -27861,7 +27824,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; @@ -28018,7 +27981,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; @@ -28081,7 +28044,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; @@ -28167,7 +28130,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; @@ -28184,7 +28147,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; @@ -28196,7 +28159,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; @@ -28306,7 +28269,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; @@ -28448,7 +28411,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; @@ -29147,11 +29110,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, @@ -29175,7 +29138,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; } @@ -29207,8 +29170,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); @@ -29894,7 +29857,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 e3c765475c..d5722ac2f6 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"); @@ -1982,7 +1982,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); @@ -2367,7 +2367,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); } } 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 78bdbe1541..2ff0ab7352 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; @@ -278,9 +269,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))) { @@ -439,7 +427,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; @@ -635,6 +623,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); @@ -695,7 +684,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; @@ -810,7 +799,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]); @@ -990,7 +979,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))) { @@ -1138,7 +1127,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); @@ -1269,7 +1258,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); @@ -1384,4 +1374,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 53d2e598be..b8979d0214 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -520,7 +520,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 From ea8755fda9a76294a711715142e861c8a3333ed2 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 11 Feb 2020 15:24:18 +0100 Subject: [PATCH 09/33] compiler-rt: Export the AEABI builtins when targeting thumb --- lib/std/special/compiler_rt.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 }); From f8fd8c481ad4778c580691ed374561cd650fd7d3 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 11 Feb 2020 15:28:30 +0100 Subject: [PATCH 10/33] test: Skip the atomic-on-fp test for riscv64 --- test/stage1/behavior/atomics.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/stage1/behavior/atomics.zig b/test/stage1/behavior/atomics.zig index 7155e80094..0347f6f94a 100644 --- a/test/stage1/behavior/atomics.zig +++ b/test/stage1/behavior/atomics.zig @@ -146,8 +146,8 @@ fn testAtomicStore() void { } test "atomicrmw with floats" { - if (builtin.arch == .aarch64 or builtin.arch == .arm) - return; + if (builtin.arch == .aarch64 or builtin.arch == .arm or builtin.arch == .riscv64) + return error.SkipZigTest; testAtomicRmwFloat(); } From b81c5be451b18597b38f606dc9a9f3255401190f Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 11 Feb 2020 15:29:06 +0100 Subject: [PATCH 11/33] riscv: Remove 'relax' from the baseline cpu features LLD doesn't implement relaxations at the moment. --- lib/std/target/riscv.zig | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/std/target/riscv.zig b/lib/std/target/riscv.zig index 315329306e..ddf1049a20 100644 --- a/lib/std/target/riscv.zig +++ b/lib/std/target/riscv.zig @@ -78,7 +78,6 @@ pub const cpu = struct { .d, .f, .m, - .relax, }), }; @@ -92,7 +91,6 @@ pub const cpu = struct { .d, .f, .m, - .relax, }), }; From 6c05f0949aa09ac41268097161bacf8dc047e195 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 11 Feb 2020 15:48:35 +0100 Subject: [PATCH 12/33] ir: Fix erroneous error message for ptr casts Don't blindly throw an error if two integer types are checked for compatibility. Bug reported in #4430 --- src/ir.cpp | 13 +++++++++---- test/stage1/behavior/cast.zig | 13 +++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 7f2348caf2..3fc2ddadeb 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -11873,10 +11873,15 @@ 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 = heap::c_allocator.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; } diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig index a70467e199..f393bfebb5 100644 --- a/test/stage1/behavior/cast.zig +++ b/test/stage1/behavior/cast.zig @@ -782,3 +782,16 @@ test "cast between [*c]T and ?[*:0]T on fn parameter" { }; 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(); +} From d06bfc2e2a5e873d3d7e28cf78a46b8454c633aa Mon Sep 17 00:00:00 2001 From: vegecode Date: Wed, 12 Feb 2020 13:16:32 -0600 Subject: [PATCH 13/33] Correct comment to include comptime attribute on format output fn parameter Without comptime, printing custom type through the stream interface fails --- lib/std/fmt.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 4a653823e5..0967d9f069 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -69,7 +69,7 @@ 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. From 327d40e7a3cd67e2f4fbe3af226d4bc6860f6f68 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 12 Feb 2020 23:10:08 +0100 Subject: [PATCH 14/33] Fix a UAF when verbose-llvm-ir is specified The g->module is long gone when codegen_link is called. --- src/link.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/link.cpp b/src/link.cpp index d5722ac2f6..2771b694c1 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -2642,13 +2642,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"); } From 55304128c086989ad4c08e51c7708d61d544e820 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 12 Feb 2020 23:10:53 +0100 Subject: [PATCH 15/33] Fix rendering of empty arrays --- src/analyze.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index c8b63f4535..fc1a805d82 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -6937,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) { From 471662f7c94b881821803b4d1379deee5e6d59ae Mon Sep 17 00:00:00 2001 From: Michael Dusan Date: Wed, 12 Feb 2020 17:23:48 -0500 Subject: [PATCH 16/33] stage1: limit cmake checks on build type Various maintainers pass custom build types and we don't need to check those. We are interested only in checking and diagnosing common errors for Zig project supported types. Check is now limited to look for case-mismatch only on the well-known values { Debug, Release, RelWithDebInfo, MinSizeRel }. --- CMakeLists.txt | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a8ec226e0..a6d5a9e810 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,16 +5,21 @@ 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) +set(_list "Debug;Release;RelWithDebInfo;MinSizeRel") +string(TOLOWER "${_list}" _list_lower) +string(TOLOWER ${CMAKE_BUILD_TYPE} _build_type_lower) +list(FIND _list_lower "${_build_type_lower}" _index) +if(NOT ${_index} EQUAL -1) + list(FIND _list "${CMAKE_BUILD_TYPE}" _index) + if(${_index} EQUAL -1) + string(REPLACE ";" ", " _list_pretty "${_list}") + message("::") + message(":: ERROR: build type case-mismatch: ${CMAKE_BUILD_TYPE}") + message("::") + message(":: valid types: { ${_list_pretty} }") + message("::") + message(FATAL_ERROR) + endif() endif() if(NOT CMAKE_INSTALL_PREFIX) From 699c50a375fb6755a4116c94e6068620d070bd98 Mon Sep 17 00:00:00 2001 From: Benjamin Feng Date: Fri, 31 Jan 2020 19:06:50 -0600 Subject: [PATCH 17/33] Switch a bunch of FBA to use testing.allocator --- lib/std/array_list.zig | 14 ++------- lib/std/ascii.zig | 5 ++-- lib/std/cstr.zig | 5 ++-- lib/std/fs/get_app_data_dir.zig | 6 ++-- lib/std/fs/path.zig | 10 +++---- lib/std/http/headers.zig | 48 ++++++++++++++---------------- lib/std/io.zig | 12 +++----- lib/std/io/test.zig | 13 +++----- lib/std/os/test.zig | 5 ++-- lib/std/process.zig | 6 ++-- lib/std/sort.zig | 8 ++--- lib/std/unicode.zig | 10 +++---- lib/std/zig/parser_test.zig | 3 +- test/stage1/behavior/bugs/1851.zig | 5 ++-- 14 files changed, 58 insertions(+), 92 deletions(-) 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/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/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/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 21ebd723c4..c4e9a1fc06 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/os/test.zig b/lib/std/os/test.zig index f33b5d5261..bd981521f9 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); 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/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/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; From a81ae1223d4ea4aea689fc8a03004abfb865a884 Mon Sep 17 00:00:00 2001 From: Benjamin Feng Date: Fri, 31 Jan 2020 21:27:59 -0600 Subject: [PATCH 18/33] Convert a lot of json tests to use testing.allocator --- lib/std/json.zig | 13 +++++-------- lib/std/json/test.zig | 31 ++++++++++++++----------------- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/lib/std/json.zig b/lib/std/json.zig index 1b10be0763..1e4f19fda8 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); 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; From 4578d13b49d16463b870119005877f7b6e10092e Mon Sep 17 00:00:00 2001 From: data-man Date: Tue, 7 Jan 2020 19:14:37 +0500 Subject: [PATCH 19/33] Vector comparison in meta and testing --- lib/std/meta.zig | 15 +++++++++++++++ lib/std/testing.zig | 17 ++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 5cb9c6589c..f090e1e8e4 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -433,6 +433,14 @@ pub fn eql(a: var, b: @TypeOf(a)) bool { if (!eql(e, b[i])) return false; return true; }, + builtin.TypeId.Vector => { + const info = @typeInfo(T).Vector; + var i: usize = 0; + while (i < info.len) : (i += 1) { + if (!eql(a[i], b[i])) return false; + } + return true; + }, builtin.TypeId.Pointer => { const info = @typeInfo(T).Pointer; switch (info.size) { @@ -510,6 +518,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/testing.zig b/lib/std/testing.zig index f8247b5a9d..8a4491d1d7 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -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); +} From c5260f7f867fd4ccb4eb3fd5b0ab91759cf94546 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 13 Feb 2020 00:38:59 +0100 Subject: [PATCH 20/33] ir: Allow implicit conversion between vector types Only valid when the number of elements match and the types are compatible. Fixes #4334 --- src/ir.cpp | 14 +++++++++++++- test/stage1/behavior/vector.zig | 27 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index 3fc2ddadeb..570fdd0b05 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -14840,6 +14840,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 @@ -16409,9 +16419,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: 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(); +} From f93c219f30b4b4f3bb9280d39be7b585ddcd8447 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 13 Feb 2020 00:49:42 +0100 Subject: [PATCH 21/33] Minor changes for a test case --- lib/std/os/test.zig | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index f33b5d5261..989653116c 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -276,8 +276,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 +303,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 +327,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, From fa377dbd1510fc733607afe47dc04dfe55d5ff88 Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 13 Feb 2020 09:09:49 +0200 Subject: [PATCH 22/33] fix c tokenizer bug --- lib/std/c/tokenizer.zig | 4 ++++ test/translate_c.zig | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/lib/std/c/tokenizer.zig b/lib/std/c/tokenizer.zig index a7342ba7f9..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; }, }, diff --git a/test/translate_c.zig b/test/translate_c.zig index a2eb69100f..b5c889030d 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -1362,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", From 948a463cf1644ab6ceb0b9128b4d2ddbcf09d6b1 Mon Sep 17 00:00:00 2001 From: data-man Date: Sat, 14 Dec 2019 14:23:42 +0500 Subject: [PATCH 23/33] fmt: vector formatting --- lib/std/fmt.zig | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 0967d9f069..11e22c396c 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -74,7 +74,7 @@ fn peekIsAlign(comptime fmt: []const u8) bool { /// 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, @@ -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, } } @@ -1713,3 +1726,19 @@ test "positional with specifier" { test "positional/alignment/width/precision" { try testFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)}); } + +test "vector" { + 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}); +} From cdba521a06353a1ae25c2e37bb44e11c6fec1035 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 13 Feb 2020 16:13:53 -0500 Subject: [PATCH 24/33] annotate skipped test with issue link --- lib/std/fmt.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 11e22c396c..a0ec668769 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -1728,6 +1728,7 @@ test "positional/alignment/width/precision" { } 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 }; From a090a5e3bcf242e8ed69346d9762d9c2fab6059a Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 12 Feb 2020 20:27:08 +0100 Subject: [PATCH 25/33] ir: Don't crash when converting undefined ptrs --- src/ir.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 570fdd0b05..9c1d168b21 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -267,6 +267,7 @@ 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) { switch (inst->id) { @@ -12784,13 +12785,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; From cf67d30cdcdd46264e59184ff6a1bf9062a77878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20=28xq=29=20Quei=C3=9Fner?= Date: Thu, 13 Feb 2020 10:37:49 +0100 Subject: [PATCH 26/33] Makes ArenaAllocator.deinit() not require a mutable reference. --- lib/std/heap.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From fb6b94f80fed42b4c690b43a875bf0a58977493e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 13 Feb 2020 20:47:44 -0500 Subject: [PATCH 27/33] cmake: remove case mismatch detection on build mode See discussion here for context: https://github.com/ziglang/zig/commit/c6df5deb3450e0d8a2ba449c34a0bd195fbce8ec#comments Michael - I appreciate what you did here, making the configure script work better for people in practice. When it was checking the build type against a whitelist, I think it was worth it. However, now that we are supporting systems which use non-standard cmake build modes, I don't think this case-mismatch detection thing is worth it. It's starting to get to the point where it's a lot of complication for very little benefit. Besides, cmake is not case sensitive. If we support non-standard build modes, then we would need to support a hypothetical build mode of `release` (lower case). So let's just remove this and rely on people to use the build system correctly (like they will have to do when building any cmake project from source). --- CMakeLists.txt | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a6d5a9e810..71d4e2cda3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,23 +5,6 @@ if(NOT CMAKE_BUILD_TYPE) "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE) endif() -set(_list "Debug;Release;RelWithDebInfo;MinSizeRel") -string(TOLOWER "${_list}" _list_lower) -string(TOLOWER ${CMAKE_BUILD_TYPE} _build_type_lower) -list(FIND _list_lower "${_build_type_lower}" _index) -if(NOT ${_index} EQUAL -1) - list(FIND _list "${CMAKE_BUILD_TYPE}" _index) - if(${_index} EQUAL -1) - string(REPLACE ";" ", " _list_pretty "${_list}") - message("::") - message(":: ERROR: build type case-mismatch: ${CMAKE_BUILD_TYPE}") - message("::") - message(":: valid types: { ${_list_pretty} }") - message("::") - message(FATAL_ERROR) - endif() -endif() - if(NOT CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}" CACHE STRING "Directory to install zig to" FORCE) From b61e53cc40869504ea75fcfd90379f7d3048b82d Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 14 Feb 2020 18:59:07 +1100 Subject: [PATCH 28/33] std: bigint.deinit() shouldn't need a mutable pointer --- lib/std/math/big/int.zig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index 7d8d3a195b..e85e8d292d 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 From f20ba7c32c1b06104dd91c0c654ac1d0fc0a9c1e Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 14 Feb 2020 18:59:25 +1100 Subject: [PATCH 29/33] std: increase memory available to testing allocator --- lib/std/testing.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/testing.zig b/lib/std/testing.zig index 8a4491d1d7..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. From ca41567924d0576be9a000076d29ec5f46a93e95 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 14 Feb 2020 18:59:40 +1100 Subject: [PATCH 30/33] std: use testing.allocator in big int tests --- lib/std/math/big/int.zig | 732 ++++++++++++++++++++++++++------------- 1 file changed, 487 insertions(+), 245 deletions(-) diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index e85e8d292d..d42d9fc676 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -1360,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; @@ -1380,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; @@ -1439,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; @@ -1468,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()); @@ -1479,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); @@ -1506,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); @@ -1536,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)); @@ -1563,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); @@ -1649,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); @@ -1662,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); @@ -1718,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); @@ -1728,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); @@ -1753,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); @@ -1774,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); @@ -1783,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); @@ -1804,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)); @@ -1827,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); @@ -1871,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)); @@ -1893,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); @@ -1912,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); @@ -1921,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); @@ -1929,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); @@ -1961,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); @@ -1976,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); @@ -1991,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); @@ -2006,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); @@ -2018,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); @@ -2030,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); @@ -2042,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); @@ -2054,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); @@ -2069,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 @@ -2089,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 @@ -2109,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 @@ -2129,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 @@ -2149,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 @@ -2169,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 @@ -2189,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 @@ -2209,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 @@ -2226,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); @@ -2238,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); @@ -2250,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); @@ -2262,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); @@ -2274,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); @@ -2420,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); @@ -2429,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); @@ -2438,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); @@ -2447,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); @@ -2456,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); @@ -2466,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); } From 6ea6d5a4bdcf6f37c43857570522ee1308115de7 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 14 Feb 2020 19:15:09 +1100 Subject: [PATCH 31/33] std: use testing.allocator in tests --- lib/std/json.zig | 29 +++---- lib/std/json/write_stream.zig | 6 +- lib/std/math/big/rational.zig | 151 ++++++++++++++++++++++------------ lib/std/mem.zig | 44 ++++++---- lib/std/net/test.zig | 4 +- 5 files changed, 147 insertions(+), 87 deletions(-) diff --git a/lib/std/json.zig b/lib/std/json.zig index 1e4f19fda8..74e008d76e 100644 --- a/lib/std/json.zig +++ b/lib/std/json.zig @@ -1598,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] @@ -1622,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": "\\", @@ -1638,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, "/"); @@ -1662,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/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/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/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, From 7396b144ba72d28d10ee1e089fc8e4f87239a840 Mon Sep 17 00:00:00 2001 From: xackus <14938807+xackus@users.noreply.github.com> Date: Thu, 13 Feb 2020 23:20:40 +0100 Subject: [PATCH 32/33] modernize std.meta --- lib/std/meta.zig | 114 +++++++++++++++++++---------------------- lib/std/meta/trait.zig | 107 ++++++++++++++++---------------------- 2 files changed, 95 insertions(+), 126 deletions(-) diff --git a/lib/std/meta.zig b/lib/std/meta.zig index f090e1e8e4..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,31 +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.Vector => { - const info = @typeInfo(T).Vector; + .Vector => |info| { var i: usize = 0; while (i < info.len) : (i += 1) { if (!eql(a[i], 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, - } + .Pointer => |info| { + return switch (info.size) { + .One, .Many, .C, => a == b, + .Slice => a.ptr == b.ptr and a.len == b.len, + }; }, - builtin.TypeId.Optional => { + .Optional => { if (a == null and b == null) return true; if (a == null or b == null) return false; return eql(a.?, b.?); 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, }; } From 9206f8a8cde9a8c1eafc606fe6b3f4129e233aef Mon Sep 17 00:00:00 2001 From: Vexu Date: Fri, 14 Feb 2020 13:37:39 +0200 Subject: [PATCH 33/33] translate-c improve macro cast translation --- src-self-hosted/translate_c.zig | 29 ++++++++++++++++++++++------- test/translate_c.zig | 3 +++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 85ff72c9dc..0c7b3868e2 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -5341,12 +5341,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 @@ -5354,7 +5369,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, diff --git a/test/translate_c.zig b/test/translate_c.zig index b5c889030d..bb2a310b0f 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -2538,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",