1const std = @import("std");
2const mem = std.mem;
3const process = std.process;
4const Allocator = mem.Allocator;
5const build_options = @import("build_options");
6
7const aro = @import("aro");
8const Compilation = aro.Compilation;
9const Diagnostics = aro.Diagnostics;
10const Driver = aro.Driver;
11const Toolchain = aro.Toolchain;
12const assembly_backend = @import("assembly_backend");
13
14var 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
23pub 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}