From 5780ba278950f0d8842d6f04e9fb28c4714b1aa6 Mon Sep 17 00:00:00 2001 From: David Gonzalez Martin Date: Fri, 26 Apr 2024 12:44:46 -0600 Subject: [PATCH] Reduce to min dependency on std.mem.Allocator --- bootstrap/Compilation.zig | 161 +++++++++++++++++++---------------- bootstrap/backend/llvm.zig | 9 +- bootstrap/frontend/lexer.zig | 7 -- bootstrap/fs.zig | 7 -- bootstrap/library.zig | 27 +++++- bootstrap/linker/lld.zig | 4 +- bootstrap/main.zig | 16 ++-- build/test_runner.zig | 2 - 8 files changed, 128 insertions(+), 105 deletions(-) delete mode 100644 bootstrap/fs.zig diff --git a/bootstrap/Compilation.zig b/bootstrap/Compilation.zig index a278077..8afc6c9 100644 --- a/bootstrap/Compilation.zig +++ b/bootstrap/Compilation.zig @@ -17,7 +17,6 @@ const first_slice = library.first_slice; const starts_with_slice = library.starts_with_slice; const PinnedArray = library.PinnedArray; const PinnedArrayAdvanced = library.PinnedArrayAdvanced; -const MyAllocator = library.MyAllocator; const PinnedHashMap = library.PinnedHashMap; const span = library.span; const format_int = library.format_int; @@ -68,18 +67,18 @@ const Optimization = enum { aggressively_optimize_for_size, }; -pub fn createContext(allocator: Allocator) !*const Context { - const context: *Context = try allocator.create(Context); +pub fn createContext() !*const Context { + const arena = try Arena.init(4 * 1024 * 1024); + const context = try arena.new(Context); - const self_exe_path = try std.fs.selfExePathAlloc(allocator); - const self_exe_dir_path = std.fs.path.dirname(self_exe_path).?; + const self_exe_absolute_path = try self_exe_path(arena); + const self_exe_dir_path = std.fs.path.dirname(self_exe_absolute_path).?; context.* = .{ - .allocator = allocator, - .cwd_absolute_path = try realpathAlloc(allocator, "."), - .executable_absolute_path = self_exe_path, + .cwd_absolute_path = try realpath(arena, std.fs.cwd(), "."), + .executable_absolute_path = self_exe_absolute_path, .directory_absolute_path = self_exe_dir_path, .build_directory = try std.fs.cwd().makeOpenPath("nat", .{}), - .arena = try Arena.init(4 * 1024 * 1024), + .arena = arena, }; try context.build_directory.makePath(cache_dir_name); @@ -120,9 +119,14 @@ pub fn compileBuildExecutable(context: *const Context, arguments: []const []cons }); try unit.compile(context); + const argv: []const []const u8 = &.{ "nat/build", "-compiler_path", context.executable_absolute_path }; + + var arena_allocator = std.heap.ArenaAllocator.init(std.heap.page_allocator); + const allocator = arena_allocator.allocator(); + const result = try std.ChildProcess.run(.{ - .allocator = context.allocator, + .allocator = allocator, .argv = argv, }); @@ -147,8 +151,8 @@ pub fn compileBuildExecutable(context: *const Context, arguments: []const []cons } } -fn clang_job(arguments: []const []const u8) !void { - const exit_code = try clangMain(std.heap.page_allocator, arguments); +fn clang_job(arena: *Arena, arguments: []const []const u8) !void { + const exit_code = try clangMain(arena, arguments); if (exit_code != 0) unreachable; } @@ -167,7 +171,7 @@ const MuslContext = struct { fn init(context: *const Context) !MuslContext { const home_dir = std.posix.getenv("HOME") orelse unreachable; return .{ - .global_cache_dir = try std.mem.concat(context.allocator, u8, &.{ home_dir, "/.cache/nat/musl/" }), + .global_cache_dir = try context.arena.join(&.{ home_dir, "/.cache/nat/musl/" }), .arch_include_path = try context.pathFromCompiler(musl_lib_dir_relative_path ++ "arch/x86_64"), .arch_generic_include_path = try context.pathFromCompiler(musl_lib_dir_relative_path ++ "arch/generic"), .src_include_path = try context.pathFromCompiler(musl_lib_dir_relative_path ++ "src/include"), @@ -189,7 +193,7 @@ const MuslContext = struct { context.executable_absolute_path, "--no-default-config", "-fno-caret-diagnostics", "-target", "x86_64-unknown-linux-musl", "-std=c99", "-ffreestanding", "-mred-zone", "-fno-omit-frame-pointer", "-fno-stack-protector", "-O2", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables", "-ffunction-sections", "-fdata-sections", "-gdwarf-4", "-gdwarf32", "-Wa,--noexecstack", "-D_XOPEN_SOURCE=700", "-I", musl.arch_include_path, "-I", musl.arch_generic_include_path, "-I", musl.src_include_path, "-I", musl.src_internal_path, "-I", musl.include_path, "-I", musl.triple_include_path, "-I", musl.generic_include_path, "-c", src_file_path, "-o", target_path, }; - const exit_code = try clangMain(context.allocator, args); + const exit_code = try clangMain(context.arena, args); if (exit_code != 0) unreachable; } }; @@ -218,15 +222,15 @@ fn compileMusl(context: *const Context) MuslContext { var ar_args = BoundedArray([]const u8, 4096){}; ar_args.appendAssumeCapacity("ar"); ar_args.appendAssumeCapacity("rcs"); - ar_args.appendAssumeCapacity(try std.mem.concat(context.allocator, u8, &.{ musl.global_cache_dir, "libc.a" })); + ar_args.appendAssumeCapacity(try context.arena.join(&.{ musl.global_cache_dir, "libc.a" })); for (generic_musl_source_files) |src_file_relative_path| { const basename = std.fs.path.basename(src_file_relative_path); - const target = try context.allocator.dupe(u8, basename); + const target = try context.arena.duplicate_bytes(basename); target[target.len - 1] = 'o'; const hash = my_hash(src_file_relative_path); const hash_string = format_int(&buffer, hash, 16, false); - const target_path = try std.mem.concat(context.allocator, u8, &.{ musl.global_cache_dir, hash_string, target }); + const target_path = try context.arena.join(&.{ musl.global_cache_dir, hash_string, target }); try musl.compileFileWithClang(context, src_file_relative_path, target_path); ar_args.appendAssumeCapacity(target_path); @@ -234,41 +238,41 @@ fn compileMusl(context: *const Context) MuslContext { for (musl_x86_64_source_files) |src_file_relative_path| { const basename = std.fs.path.basename(src_file_relative_path); - const target = try context.allocator.dupe(u8, basename); + const target = try context.arena.duplicate_bytes(u8, basename); target[target.len - 1] = 'o'; const hash = my_hash(src_file_relative_path); const hash_string = format_int(&buffer, hash, 16, false); - const target_path = try std.mem.concat(context.allocator, u8, &.{ musl.global_cache_dir, hash_string, target }); + const target_path = try context.arena.join(&.{ musl.global_cache_dir, hash_string, target }); try musl.compileFileWithClang(context, src_file_relative_path, target_path); ar_args.appendAssumeCapacity(target_path); } - if (try arMain(context.allocator, ar_args.slice()) != 0) { + if (try arMain(context.arena, ar_args.slice()) != 0) { unreachable; } - const crt1_output_path = try std.mem.concat(context.allocator, u8, &.{ musl.global_cache_dir, "crt1.o" }); + const crt1_output_path = try context.arena.join(&.{ musl.global_cache_dir, "crt1.o" }); { const crt_path = try context.pathFromCompiler("lib/libc/musl/crt/crt1.c"); const args: []const []const u8 = &.{ context.executable_absolute_path, "--no-default-config", "-fno-caret-diagnostics", "-target", "x86_64-unknown-linux-musl", "-std=c99", "-ffreestanding", "-mred-zone", "-fno-omit-frame-pointer", "-fno-stack-protector", "-O2", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables", "-ffunction-sections", "-fdata-sections", "-gdwarf-4", "-gdwarf32", "-Wa,--noexecstack", "-D_XOPEN_SOURCE=700", "-DCRT", "-I", musl.arch_include_path, "-I", musl.arch_generic_include_path, "-I", musl.src_include_path, "-I", musl.src_internal_path, "-I", musl.include_path, "-I", musl.triple_include_path, "-I", musl.generic_include_path, "-c", crt_path, "-o", crt1_output_path, }; - const exit_code = try clangMain(context.allocator, args); + const exit_code = try clangMain(context.arena, args); if (exit_code != 0) { unreachable; } } - const crti_output_path = try std.mem.concat(context.allocator, u8, &.{ musl.global_cache_dir, "crti.o" }); + const crti_output_path = try context.arena.join(&.{ musl.global_cache_dir, "crti.o" }); { const crt_path = try context.pathFromCompiler("lib/libc/musl/crt/crti.c"); const args: []const []const u8 = &.{ context.executable_absolute_path, "--no-default-config", "-fno-caret-diagnostics", "-target", "x86_64-unknown-linux-musl", "-std=c99", "-ffreestanding", "-mred-zone", "-fno-omit-frame-pointer", "-fno-stack-protector", "-O2", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables", "-ffunction-sections", "-fdata-sections", "-gdwarf-4", "-gdwarf32", "-Wa,--noexecstack", "-D_XOPEN_SOURCE=700", "-DCRT", "-I", musl.arch_include_path, "-I", musl.arch_generic_include_path, "-I", musl.src_include_path, "-I", musl.src_internal_path, "-I", musl.include_path, "-I", musl.triple_include_path, "-I", musl.generic_include_path, "-c", crt_path, "-o", crti_output_path, }; - const exit_code = try clangMain(context.allocator, args); + const exit_code = try clangMain(context.arena, args); if (exit_code != 0) { unreachable; } @@ -276,12 +280,12 @@ fn compileMusl(context: *const Context) MuslContext { { const crt_path = try context.pathFromCompiler("lib/libc/musl/crt/x86_64/crtn.s"); - const crt_output_path = try std.mem.concat(context.allocator, u8, &.{ musl.global_cache_dir, "crtn.o" }); + const crt_output_path = try context.arena.join(&.{ musl.global_cache_dir, "crtn.o" }); const args: []const []const u8 = &.{ context.executable_absolute_path, "--no-default-config", "-fno-caret-diagnostics", "-target", "x86_64-unknown-linux-musl", "-std=c99", "-ffreestanding", "-mred-zone", "-fno-omit-frame-pointer", "-fno-stack-protector", "-O2", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables", "-ffunction-sections", "-fdata-sections", "-gdwarf-4", "-gdwarf32", "-Wa,--noexecstack", "-D_XOPEN_SOURCE=700", "-I", musl.arch_include_path, "-I", musl.arch_generic_include_path, "-I", musl.src_include_path, "-I", musl.src_internal_path, "-I", musl.include_path, "-I", musl.triple_include_path, "-I", musl.generic_include_path, "-c", crt_path, "-o", crt_output_path, }; - const exit_code = try clangMain(context.allocator, args); + const exit_code = try clangMain(context.arena, args); if (exit_code != 0) { unreachable; } @@ -598,7 +602,7 @@ pub fn compileCSourceFile(context: *const Context, arguments: []const []const u8 const object_path = switch (mode) { .object => out_path.?, - .link => try std.mem.concat(context.allocator, u8, &.{ if (out_path) |op| op else "a.o", ".o" }), + .link => try context.arena.join(&.{ if (out_path) |op| op else "a.o", ".o" }), }; link_objects.appendAssumeCapacity(.{ @@ -753,7 +757,7 @@ pub fn compileCSourceFile(context: *const Context, arguments: []const []const u8 if (debug_clang_args) { std.debug.print("Argv: {s}\n", .{argv.slice()}); } - const result = try clangMain(context.allocator, argv.slice()); + const result = try clangMain(context.arena, argv.slice()); if (result != 0) { unreachable; } @@ -763,7 +767,7 @@ pub fn compileCSourceFile(context: *const Context, arguments: []const []const u8 argv.appendAssumeCapacity("clang"); argv.appendAssumeCapacity("--no-default-config"); argv.appendSliceAssumeCapacity(cc_argv.slice()); - const result = try clangMain(context.allocator, argv.slice()); + const result = try clangMain(context.arena, argv.slice()); if (result != 0) { unreachable; } @@ -884,13 +888,13 @@ pub fn compileCSourceFile(context: *const Context, arguments: []const []const u8 // try clang_args.appendAssumeCapacity(span(arg)); // } // - // const result = try clangMain(context.allocator, clang_args.slice()); + // const result = try clangMain(context.arena, clang_args.slice()); // if (result != 0) { // unreachable; // } // const output_object_file = "nat/main.o"; - // const exit_code = try clangMain(context.allocator, &.{ context.executable_absolute_path, "--no-default-config", "-target", "x86_64-unknown-linux-musl", "-nostdinc", "-fno-spell-checking", "-isystem", "lib/include", "-isystem", "lib/libc/include/x86_64-linux-musl", "-isystem", "lib/libc/include/generic-musl", "-isystem", "lib/libc/include/x86-linux-any", "-isystem", "lib/libc/include/any-linux-any", "-c", argument, "-o", output_object_file }); + // const exit_code = try clangMain(context.arena, &.{ context.executable_absolute_path, "--no-default-config", "-target", "x86_64-unknown-linux-musl", "-nostdinc", "-fno-spell-checking", "-isystem", "lib/include", "-isystem", "lib/libc/include/x86_64-linux-musl", "-isystem", "lib/libc/include/generic-musl", "-isystem", "lib/libc/include/x86-linux-any", "-isystem", "lib/libc/include/any-linux-any", "-c", argument, "-o", output_object_file }); // if (exit_code != 0) { // unreachable; // } @@ -910,12 +914,12 @@ pub fn compileCSourceFile(context: *const Context, arguments: []const []const u8 // try lld_args.appendAssumeCapacity("-static"); // try lld_args.appendAssumeCapacity("-o"); // try lld_args.appendAssumeCapacity("nat/main"); - // try lld_args.appendAssumeCapacity(try std.mem.joinZ(context.allocator, "", &.{ musl.global_cache_dir, "crt1.o" })); - // try lld_args.appendAssumeCapacity(try std.mem.joinZ(context.allocator, "", &.{ musl.global_cache_dir, "crti.o" })); + // try lld_args.appendAssumeCapacity(try std.mem.joinZ(context.arena, "", &.{ musl.global_cache_dir, "crt1.o" })); + // try lld_args.appendAssumeCapacity(try std.mem.joinZ(context.arena, "", &.{ musl.global_cache_dir, "crti.o" })); // try lld_args.appendAssumeCapacity(output_object_file); // try lld_args.appendAssumeCapacity("--as-needed"); - // try lld_args.appendAssumeCapacity(try std.mem.joinZ(context.allocator, "", &.{ musl.global_cache_dir, "libc.a" })); - // try lld_args.appendAssumeCapacity(try std.mem.joinZ(context.allocator, "", &.{ musl.global_cache_dir, "crtn.o" })); + // try lld_args.appendAssumeCapacity(try std.mem.joinZ(context.arena, "", &.{ musl.global_cache_dir, "libc.a" })); + // try lld_args.appendAssumeCapacity(try std.mem.joinZ(context.arena, "", &.{ musl.global_cache_dir, "crtn.o" })); // // var stdout_ptr: [*]const u8 = undefined; // var stdout_len: usize = 0; @@ -2735,24 +2739,27 @@ const musl_arch_files = [_][]const u8{ musl_lib_dir_relative_path ++ "src/unistd/x32/lseek.c", }; -pub fn argsCopyZ(alloc: Allocator, args: []const []const u8) ![:null]?[*:0]u8 { - var argv = try alloc.allocSentinel(?[*:0]u8, args.len, null); - for (args, 0..) |arg, i| { - argv[i] = try alloc.dupeZ(u8, arg); // TODO If there was an argsAllocZ we could avoid this allocation. +pub fn argsCopyZ(arena: *Arena, args: []const []const u8) ![:null]?[*:0]u8 { + var result = try arena.new_array(?[*:0]u8, args.len + 1); + result[args.len] = null; + + for (args, 0..) |argument, i| { + result[i] = try arena.duplicate_bytes_zero_terminated(argument); } - return argv; + + return result[0..args.len:null]; } extern "c" fn NativityLLVMArchiverMain(argc: c_int, argv: [*:null]?[*:0]u8) c_int; -fn arMain(allocator: Allocator, arguments: []const []const u8) !u8 { - const argv = try argsCopyZ(allocator, arguments); +fn arMain(arena: *Arena, arguments: []const []const u8) !u8 { + const argv = try argsCopyZ(arena, arguments); const exit_code = NativityLLVMArchiverMain(@as(c_int, @intCast(arguments.len)), argv.ptr); return @as(u8, @bitCast(@as(i8, @truncate(exit_code)))); } extern "c" fn NativityClangMain(argc: c_int, argv: [*:null]?[*:0]u8) c_int; -pub fn clangMain(allocator: Allocator, arguments: []const []const u8) !u8 { - const argv = try argsCopyZ(allocator, arguments); +pub fn clangMain(arena: *Arena, arguments: []const []const u8) !u8 { + const argv = try argsCopyZ(arena, arguments); const exit_code = NativityClangMain(@as(c_int, @intCast(arguments.len)), argv.ptr); return @as(u8, @bitCast(@as(i8, @truncate(exit_code)))); } @@ -2958,12 +2965,12 @@ pub fn buildExecutable(context: *const Context, arguments: []const []const u8, o const executable_path = maybe_executable_path orelse blk: { assert(executable_name.len > 0); - const result = try std.mem.concat(context.allocator, u8, &.{ "nat/", executable_name }); + const result = try context.arena.join(&.{ "nat/", executable_name }); break :blk result; }; const object_file_path = blk: { - const slice = try context.allocator.alloc(u8, executable_path.len + 2); + const slice = try context.arena.new_array(u8, executable_path.len + 2); @memcpy(slice[0..executable_path.len], executable_path); slice[executable_path.len] = '.'; slice[executable_path.len + 1] = 'o'; @@ -3004,7 +3011,7 @@ fn createUnit(context: *const Context, arguments: struct { is_test: bool, c_source_files: []const []const u8, }) !*Unit { - const unit = try context.allocator.create(Unit); + const unit = try context.arena.new(Unit); unit.* = .{ .descriptor = .{ .main_package_path = arguments.main_package_path, @@ -3080,10 +3087,17 @@ fn createUnit(context: *const Context, arguments: struct { return unit; } -fn realpathAlloc(allocator: Allocator, pathname: []const u8) ![]const u8 { - var path_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined; - const realpathInStack = try std.posix.realpath(pathname, &path_buffer); - return allocator.dupe(u8, realpathInStack); +pub fn self_exe_path(arena: *Arena) ![]const u8 { + var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined; + return try arena.duplicate_bytes(try std.fs.selfExePath(&buffer)); +} + +pub fn realpath(arena: *Arena, dir: std.fs.Dir, relative_path: []const u8) ![]const u8 { + var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined; + const stack_realpath = try dir.realpath(relative_path, &buffer); + const heap_realpath = try arena.new_array(u8, stack_realpath.len); + @memcpy(heap_realpath, stack_realpath); + return heap_realpath; } pub const ContainerType = enum { @@ -4129,7 +4143,6 @@ pub const Struct = struct { }; pub const Context = struct { - allocator: Allocator, arena: *Arena, cwd_absolute_path: []const u8, directory_absolute_path: []const u8, @@ -4146,7 +4159,7 @@ pub const Context = struct { }; pub fn joinPath(context: *const Context, a: []const u8, b: []const u8) ![]const u8 { - return if (a.len != 0 and b.len != 0) try std.mem.concat(context.allocator, u8, &.{ a, "/", b }) else b; + return if (a.len != 0 and b.len != 0) try context.arena.join(&.{ a, "/", b }) else b; } pub const PolymorphicFunction = struct { @@ -4427,8 +4440,8 @@ pub const Debug = struct { analyzed, }; - pub fn getPath(file: *File, allocator: Allocator) ![]const u8 { - return try std.mem.concat(allocator, u8, &.{ file.package.directory.path, "/", file.relative_path }); + pub fn getPath(file: *File, arena: *Arena) ![]const u8 { + return try arena.join(&.{ file.package.directory.path, "/", file.relative_path }); } }; }; @@ -5103,7 +5116,7 @@ pub const Builder = struct { .enum_value => |enum_field_index| { const enum_field = unit.enum_fields.get(enum_field_index); const enum_name = unit.getIdentifier(enum_field.name); - const enum_name_z = try context.allocator.dupeZ(u8, enum_name); + const enum_name_z = try context.arena.duplicate_bytes_zero_terminated(enum_name); const string_literal = try builder.processStringLiteralFromStringAndDebugInfo(unit, context, enum_name_z, .{ .line = 0, .column = 0, @@ -5288,7 +5301,7 @@ pub const Builder = struct { const case_block = try builder.newBasicBlock(unit); builder.current_basic_block = case_block; const identifier = unit.getIdentifier(enum_field.name); - const identifier_z = try context.allocator.dupeZ(u8, identifier); + const identifier_z = try context.arena.duplicate_bytes_zero_terminated(identifier); const string_literal = try builder.processStringLiteralFromStringAndDebugInfo(unit, context, identifier_z, .{ .line = 0, .column = 0, @@ -5345,7 +5358,12 @@ pub const Builder = struct { const global = unit.global_declarations.append(.{ .declaration = .{ .scope = builder.current_scope, - .name = try unit.processIdentifier(context, try std.fmt.allocPrint(context.allocator, "get_enum_name_{}", .{@intFromEnum(type_index)})), + .name = b: { + var buffer: [65]u8 = undefined; + const slice = format_int(&buffer, @intFromEnum(type_index), 10, false); + const name = try context.arena.join(&.{"get_enum_name_", slice}); + break :b try unit.processIdentifier(context, name); + }, .type = function_type_index, .line = 0, .column = 0, @@ -7601,7 +7619,7 @@ pub const Builder = struct { .discard => b: { var buffer: [65]u8 = undefined; const formatted_int = format_int(&buffer, argument_index, 10, false); - break :b try std.mem.concat(context.allocator, u8, &.{ "_anon_arg_", formatted_int }); + break :b try context.arena.join(&.{ "_anon_arg_", formatted_int }); }, else => |t| @panic(@tagName(t)), }; @@ -8926,7 +8944,7 @@ pub const Builder = struct { const identifier = switch (unit.token_buffer.tokens.get(field_node.token).id) { .identifier => unit.getExpectedTokenBytes(field_node.token, .identifier), .string_literal => try unit.fixupStringLiteral(context, field_node.token), - .discard => try std.mem.concat(context.allocator, u8, &.{ "_", &.{'0' + b: { + .discard => try context.arena.join(&.{ "_", &.{'0' + b: { const ch = '0' + ignore_field_count; ignore_field_count += 1; break :b ch; @@ -16815,7 +16833,7 @@ pub const Builder = struct { const token_debug_info = builder.getTokenDebugInfo(unit, err_node.token); const line = token_debug_info.line + 1; const column = token_debug_info.column + 1; - const file_path = file.getPath(context.allocator) catch unreachable; + const file_path = file.getPath(context.arena) catch unreachable; write(.panic, file_path) catch unreachable; write(.panic, ":") catch unreachable; Unit.dumpInt(line, 10, false) catch unreachable; @@ -16836,7 +16854,7 @@ pub const Builder = struct { _ = file; // autofix const token_debug_info = builder.getTokenDebugInfo(unit, err_node.token); _ = token_debug_info; // autofix - // std.io.getStdOut().writer().print("{s}:{}:{}: \x1b[31merror:\x1b[0m ", .{ file.getPath(context.allocator) catch unreachable, token_debug_info.line + 1, token_debug_info.column + 1 }) catch unreachable; + // std.io.getStdOut().writer().print("{s}:{}:{}: \x1b[31merror:\x1b[0m ", .{ file.getPath(context.arena) catch unreachable, token_debug_info.line + 1, token_debug_info.column + 1 }) catch unreachable; // std.io.getStdOut().writer().print(format, args) catch unreachable; // std.io.getStdOut().writer().writeByte('\n') catch unreachable; std.os.abort(); @@ -17607,7 +17625,7 @@ pub const Unit = struct { }; const file_size = try source_file.getEndPos(); - var file_buffer = try context.allocator.alloc(u8, file_size); + var file_buffer = try context.arena.new_array(u8, file_size); const read_byte_count = try source_file.readAll(file_buffer); assert(read_byte_count == file_size); @@ -17632,7 +17650,7 @@ pub const Unit = struct { } fn importPackage(unit: *Unit, context: *const Context, package: *Package) !ImportPackageResult { - const full_path = try package.directory.handle.realpathAlloc(context.allocator, package.source_path); //try std.fs.path.resolve(context.allocator, &.{ package.directory.path, package.source_path }); + const full_path = try realpath(context.arena, package.directory.handle, package.source_path); //try std.fs.path.resolve(context.arena, &.{ package.directory.path, package.source_path }); // logln(.compilation, .import, "Import full path: {s}\n", .{full_path}); const import_file = try unit.getFile(full_path, package.source_path, package); @@ -17762,7 +17780,7 @@ pub const Unit = struct { }; unit.root_package = if (unit.descriptor.is_test) blk: { - const package = try context.allocator.create(Package); + const package = try context.arena.new(Package); const directory_path = try context.pathFromCompiler("lib"); package.* = .{ .directory = .{ @@ -17789,7 +17807,7 @@ pub const Unit = struct { .{ .name = "builtin", .directory_path = blk: { - const result = try cache_dir.realpathAlloc(context.allocator, "."); + const result = try realpath(context.arena, cache_dir, "."); cache_dir.close(); break :blk result; }, @@ -17798,13 +17816,13 @@ pub const Unit = struct { var packages: [package_descriptors.len]*Package = undefined; for (package_descriptors, &packages) |package_descriptor, *package_ptr| { - const package = try context.allocator.create(Package); + const package = try context.arena.new(Package); package.* = .{ .directory = .{ .path = package_descriptor.directory_path, .handle = try std.fs.openDirAbsolute(package_descriptor.directory_path, .{}), }, - .source_path = try std.mem.concat(context.allocator, u8, &.{ package_descriptor.name, ".nat" }), + .source_path = try context.arena.join(&.{ package_descriptor.name, ".nat" }), .dependencies = try PinnedHashMap([]const u8, *Package).init(std.mem.page_size), }; @@ -17839,11 +17857,8 @@ pub const Unit = struct { const dot_index = last_byte(c_source_file, '.') orelse unreachable; const path_without_extension = c_source_file[0..dot_index]; const basename = std.fs.path.basename(path_without_extension); - const o_file = try std.mem.concat(context.allocator, u8, &.{ basename, ".o" }); - const object_path = try std.mem.concat(context.allocator, u8, &.{ - "nat/", - o_file, - }); + const o_file = try context.arena.join(&.{ basename, ".o" }); + const object_path = try context.arena.join(&.{ "nat/", o_file }); var arguments = [_][]const u8{ "-c", c_source_file, "-o", object_path, "-g", "-fno-stack-protector" }; try compileCSourceFile(context, &arguments, .c); diff --git a/bootstrap/backend/llvm.zig b/bootstrap/backend/llvm.zig index fbed358..6a91ba4 100644 --- a/bootstrap/backend/llvm.zig +++ b/bootstrap/backend/llvm.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const Allocator = std.mem.Allocator; const assert = std.debug.assert; const Compilation = @import("../Compilation.zig"); const write = Compilation.write; @@ -2043,7 +2042,7 @@ pub const LLVM = struct { fn createBasicBlock(llvm: *LLVM, context: *const Compilation.Context, basic_block_index: Compilation.BasicBlock.Index, name: []const u8) !*BasicBlockList.Node { const basic_block = llvm.context.createBasicBlock(name.ptr, name.len, llvm.function, null) orelse return Error.basic_block; - const basic_block_node = try context.allocator.create(BasicBlockList.Node); + const basic_block_node = try context.arena.new(BasicBlockList.Node); basic_block_node.* = .{ .data = basic_block_index, }; @@ -2435,7 +2434,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo }; if (unit.descriptor.generate_debug_information) { - const full_path = try std.fs.cwd().realpathAlloc(context.allocator, unit.descriptor.main_package_path); + const full_path = try Compilation.realpath(context.arena, std.fs.cwd(), unit.descriptor.main_package_path); const filename = std.fs.path.basename(full_path); const directory = full_path[0 .. full_path.len - filename.len]; const debug_info_file = llvm.debug_info_builder.createFile(filename.ptr, filename.len, directory.ptr, directory.len) orelse unreachable; @@ -2679,7 +2678,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo _ = assembly_statements.pop(); - // try constraints.append_slice(context.allocator, ",~{dirflag},~{fpsr},~{flags}"); + // try constraints.append_slice(context.arena, ",~{dirflag},~{fpsr},~{flags}"); }, .aarch64 => { for (assembly_block.instructions) |assembly_instruction_index| { @@ -3427,7 +3426,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo llvm.module.setTargetTriple(target_triple.ptr, target_triple.len); const file_path = unit.descriptor.executable_path; const object_file_path = blk: { - const slice = try context.allocator.alloc(u8, file_path.len + 3); + const slice = try context.arena.new_array(u8, file_path.len + 3); @memcpy(slice[0..file_path.len], file_path); slice[file_path.len] = '.'; slice[file_path.len + 1] = 'o'; diff --git a/bootstrap/frontend/lexer.zig b/bootstrap/frontend/lexer.zig index 8e6f54e..2881055 100644 --- a/bootstrap/frontend/lexer.zig +++ b/bootstrap/frontend/lexer.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const Allocator = std.mem.Allocator; const assert = std.debug.assert; const log = std.log; @@ -7,14 +6,12 @@ const library = @import("../library.zig"); const byte_equal = library.byte_equal; const enumFromString = library.enumFromString; const exit_with_error = library.exit_with_error; -const MyAllocator = library.MyAllocator; const PinnedArray = library.PinnedArray; const Compilation = @import("../Compilation.zig"); const File = Compilation.File; const logln = Compilation.logln; const Token = Compilation.Token; -const fs = @import("../fs.zig"); // Needed information // Token: u8 @@ -69,10 +66,6 @@ pub fn analyze(text: []const u8, token_buffer: *Token.Buffer) !Result { var index: u32 = 0; var line_index: u32 = lexer.line_offset; - // try token_buffer.ensure_with_capacity(allocator, len / 3); - - // logln(.lexer, .end, "START LEXER - TOKEN OFFSET: {} - LINE OFFSET: {}", .{ Token.unwrap(lexer.offset), lexer.line_offset }); - while (index < len) { const start_index = index; const start_character = text[index]; diff --git a/bootstrap/fs.zig b/bootstrap/fs.zig deleted file mode 100644 index a8ec0ec..0000000 --- a/bootstrap/fs.zig +++ /dev/null @@ -1,7 +0,0 @@ -const std = @import("std"); -const Allocator = std.mem.Allocator; - -pub fn readFile(allocator: Allocator, file_relative_path: []const u8) ![]const u8 { - const file = try std.fs.cwd().readFileAlloc(allocator, file_relative_path, std.math.maxInt(usize)); - return file; -} diff --git a/bootstrap/library.zig b/bootstrap/library.zig index 449c12f..7f3a22e 100644 --- a/bootstrap/library.zig +++ b/bootstrap/library.zig @@ -8,7 +8,6 @@ pub fn assert(ok: bool) void { if (!ok) unreachable; } -pub const Allocator = std.mem.Allocator; pub const BoundedArray = std.BoundedArray; pub const Arena = struct { @@ -86,6 +85,32 @@ pub const Arena = struct { @memcpy(slice, bytes); return slice; } + + pub fn duplicate_bytes_zero_terminated(arena: *Arena, bytes: []const u8) ![:0]u8 { + const slice = try arena.new_array(u8, bytes.len + 1); + slice[bytes.len] = 0; + @memcpy(slice[0..bytes.len], bytes); + return slice[0..bytes.len:0]; + } + + pub fn join(arena: *Arena, slices: []const []const u8) ![]u8 { + var byte_count: usize = 0; + + for (slices) |slice| { + byte_count += slice.len; + } + + const result = try arena.new_array(u8, byte_count); + + byte_count = 0; + + for (slices) |slice| { + @memcpy(result[byte_count..][0..slice.len], slice); + byte_count += slice.len; + } + + return result; + } }; pub fn DynamicBoundedArray(comptime T: type) type { diff --git a/bootstrap/linker/lld.zig b/bootstrap/linker/lld.zig index 4354bdf..807de82 100644 --- a/bootstrap/linker/lld.zig +++ b/bootstrap/linker/lld.zig @@ -138,10 +138,10 @@ pub fn link(context: *const Compilation.Context, options: linker.Options) !void } for (options.libraries) |lib| { - _ = argv.append(try std.mem.concat(context.allocator, u8, &.{ "-l", lib.path })); + _ = argv.append(try context.arena.join(&.{"-l", lib.path})); } - const argv_zero_terminated = try Compilation.argsCopyZ(context.allocator, argv.const_slice()); + const argv_zero_terminated = try Compilation.argsCopyZ(context.arena, argv.const_slice()); var stdout_ptr: [*]const u8 = undefined; var stdout_len: usize = 0; diff --git a/bootstrap/main.zig b/bootstrap/main.zig index 93d82e2..a1c7afa 100644 --- a/bootstrap/main.zig +++ b/bootstrap/main.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const Allocator = std.mem.Allocator; const assert = std.debug.assert; const Compilation = @import("Compilation.zig"); @@ -7,8 +6,6 @@ pub const panic = Compilation.panic; const library = @import("library.zig"); const byte_equal = library.byte_equal; -const MyAllocator = library.MyAllocator; -const PageAllocator = library.PageAllocator; const env_detecting_libc_paths = "NATIVITY_IS_DETECTING_LIBC_PATHS"; @@ -22,10 +19,13 @@ fn todo() noreturn { } pub fn main() !void { - var arena_allocator = std.heap.ArenaAllocator.init(std.heap.page_allocator); - const allocator = arena_allocator.allocator(); - const arguments: []const []const u8 = try std.process.argsAlloc(allocator); - const context = try Compilation.createContext(allocator); + var arg_iterator = std.process.ArgIterator.init(); + var buffer = library.BoundedArray([]const u8, 512){}; + while (arg_iterator.next()) |argument| { + buffer.appendAssumeCapacity(argument); + } + const arguments = buffer.slice(); + const context = try Compilation.createContext(); if (arguments.len <= 1) { return error.InvalidInput; @@ -41,7 +41,7 @@ pub fn main() !void { if (byte_equal(command, "build")) { try Compilation.compileBuildExecutable(context, command_arguments); } else if (byte_equal(command, "clang") or byte_equal(command, "-cc1") or byte_equal(command, "-cc1as")) { - const exit_code = try Compilation.clangMain(allocator, arguments); + const exit_code = try Compilation.clangMain(context.arena, arguments); std.process.exit(exit_code); } else if (byte_equal(command, "cc")) { try Compilation.compileCSourceFile(context, command_arguments, .c); diff --git a/build/test_runner.zig b/build/test_runner.zig index 6a52ddb..5138c11 100644 --- a/build/test_runner.zig +++ b/build/test_runner.zig @@ -244,8 +244,6 @@ fn runStdTests(allocator: Allocator, args: struct { var errors = false; std.debug.print("std... ", .{}); - std.debug.print("CWD: {s}\n", .{std.fs.cwd().realpathAlloc(allocator, ".") catch unreachable}); - const argv = &.{ args.compiler_path, "test", "-main_source_file", "lib/std/std.nat", "-name", "std" }; const result = std.ChildProcess.run(.{