| 1 | const std = @import("std"); |
| 2 | const mem = std.mem; |
| 3 | const process = std.process; |
| 4 | const Allocator = mem.Allocator; |
| 5 | const build_options = @import("build_options"); |
| 6 | |
| 7 | const aro = @import("aro"); |
| 8 | const Compilation = aro.Compilation; |
| 9 | const Diagnostics = aro.Diagnostics; |
| 10 | const Driver = aro.Driver; |
| 11 | const Toolchain = aro.Toolchain; |
| 12 | const assembly_backend = @import("assembly_backend"); |
| 13 | |
| 14 | var debug_allocator: std.heap.DebugAllocator(.{ |
| 15 | .stack_trace_frames = if (build_options.debug_allocations and std.debug.sys_can_stack_trace) 10 else 0, |
| 16 | .resize_stack_traces = build_options.debug_allocations, |
| 17 | // A unique value so that when a default-constructed |
| 18 | // GeneralPurposeAllocator is incorrectly passed to testing allocator, or |
| 19 | // vice versa, panic occurs. |
| 20 | .canary = @truncate(0xc647026dc6875134), |
| 21 | }) = .{}; |
| 22 | |
| 23 | pub fn main(init: process.Init.Minimal) u8 { |
| 24 | const gpa = if (@import("builtin").link_libc) |
| 25 | std.heap.c_allocator |
| 26 | else |
| 27 | debug_allocator.allocator(); |
| 28 | defer if (!@import("builtin").link_libc) { |
| 29 | _ = debug_allocator.deinit(); |
| 30 | }; |
| 31 | |
| 32 | var arena_instance = std.heap.ArenaAllocator.init(gpa); |
| 33 | defer arena_instance.deinit(); |
| 34 | const arena = arena_instance.allocator(); |
| 35 | |
| 36 | var threaded: std.Io.Threaded = .init(gpa, .{ |
| 37 | .argv0 = .init(init.args), |
| 38 | .environ = init.environ, |
| 39 | }); |
| 40 | defer threaded.deinit(); |
| 41 | const io = threaded.io(); |
| 42 | |
| 43 | const fast_exit = @import("builtin").mode != .debug; |
| 44 | |
| 45 | const args = init.args.toSlice(arena) catch { |
| 46 | std.debug.print("out of memory\n", .{}); |
| 47 | if (fast_exit) process.exit(1); |
| 48 | return 1; |
| 49 | }; |
| 50 | |
| 51 | var environ_map = std.process.Environ.createMap(init.environ, gpa) catch |err| |
| 52 | std.process.fatal("failed to parse environment variables: {t}", .{err}); |
| 53 | defer environ_map.deinit(); |
| 54 | |
| 55 | const aro_name = std.process.executableDirPathAlloc(io, gpa) catch { |
| 56 | std.debug.print("unable to find Aro executable path\n", .{}); |
| 57 | if (fast_exit) process.exit(1); |
| 58 | return 1; |
| 59 | }; |
| 60 | defer gpa.free(aro_name); |
| 61 | |
| 62 | var stderr_buf: [1024]u8 = undefined; |
| 63 | var stderr = std.Io.File.stderr().writer(io, &stderr_buf); |
| 64 | var diagnostics: Diagnostics = .{ |
| 65 | .output = .{ .to_writer = .{ |
| 66 | .mode = std.Io.Terminal.Mode.detect(io, stderr.file, false, false) catch .no_color, |
| 67 | .writer = &stderr.interface, |
| 68 | } }, |
| 69 | }; |
| 70 | |
| 71 | var comp = Compilation.init(.{ |
| 72 | .gpa = gpa, |
| 73 | .arena = arena, |
| 74 | .io = io, |
| 75 | .diagnostics = &diagnostics, |
| 76 | .environ_map = &environ_map, |
| 77 | }) catch |er| switch (er) { |
| 78 | error.OutOfMemory => { |
| 79 | std.debug.print("out of memory\n", .{}); |
| 80 | if (fast_exit) process.exit(1); |
| 81 | return 1; |
| 82 | }, |
| 83 | }; |
| 84 | defer comp.deinit(); |
| 85 | |
| 86 | var driver: Driver = .{ .comp = &comp, .aro_name = aro_name, .diagnostics = &diagnostics }; |
| 87 | defer driver.deinit(); |
| 88 | |
| 89 | var toolchain: Toolchain = .{ .driver = &driver }; |
| 90 | defer toolchain.deinit(); |
| 91 | |
| 92 | driver.main(&toolchain, args, fast_exit, assembly_backend.genAsm) catch |er| switch (er) { |
| 93 | error.OutOfMemory => { |
| 94 | std.debug.print("out of memory\n", .{}); |
| 95 | if (fast_exit) process.exit(1); |
| 96 | return 1; |
| 97 | }, |
| 98 | error.FatalError => { |
| 99 | driver.printDiagnosticsStats(); |
| 100 | if (fast_exit) process.exit(1); |
| 101 | return 1; |
| 102 | }, |
| 103 | error.Canceled => unreachable, |
| 104 | }; |
| 105 | if (fast_exit) process.exit(@intFromBool(comp.diagnostics.errors != 0)); |
| 106 | return @intFromBool(diagnostics.errors != 0); |
| 107 | } |