Commit fef94da958

Veikka Tuominen <git@vexu.eu>
2023-05-25 11:30:02
add compiler flag for selecting C frontend
1 parent af40bce
Changed files (2)
src/Compilation.zig
@@ -32,7 +32,6 @@ const Module = @import("Module.zig");
 const InternPool = @import("InternPool.zig");
 const BuildId = std.Build.CompileStep.BuildId;
 const Cache = std.Build.Cache;
-const translate_c = @import("translate_c.zig");
 const c_codegen = @import("codegen/c.zig");
 const libtsan = @import("libtsan.zig");
 const Zir = @import("Zir.zig");
@@ -88,7 +87,7 @@ failed_win32_resources: if (build_options.only_core_functionality) void else std
 misc_failures: std.AutoArrayHashMapUnmanaged(MiscTask, MiscError) = .{},
 
 keep_source_files_loaded: bool,
-use_clang: bool,
+c_frontend: CFrontend,
 sanitize_c: bool,
 /// When this is `true` it means invoking clang as a sub-process is expected to inherit
 /// stdin, stdout, stderr, and if it returns non success, to forward the exit code.
@@ -515,6 +514,8 @@ pub const cache_helpers = struct {
     }
 };
 
+pub const CFrontend = enum { clang, aro };
+
 pub const ClangPreprocessorMode = enum {
     no,
     /// This means we are doing `zig cc -E -o <path>`.
@@ -1046,14 +1047,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
             break :pic explicit;
         } else pie or must_pic;
 
-        // Make a decision on whether to use Clang for translate-c and compiling C files.
-        const use_clang = if (options.use_clang) |explicit| explicit else blk: {
-            if (build_options.have_llvm) {
-                // Can't use it if we don't have it!
-                break :blk false;
-            }
-            // It's not planned to do our own translate-c or C compilation.
-            break :blk true;
+        // Make a decision on whether to use Clang or Aro for translate-c and compiling C files.
+        const c_frontend: CFrontend = blk: {
+            if (!build_options.have_llvm) break :blk .aro;
+            if (options.use_clang) |explicit| if (explicit) break :blk .clang;
+            break :blk .clang;
         };
 
         const is_safe_mode = switch (options.optimize_mode) {
@@ -1677,7 +1675,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
             .astgen_work_queue = std.fifo.LinearFifo(*Module.File, .Dynamic).init(gpa),
             .embed_file_work_queue = std.fifo.LinearFifo(*Module.EmbedFile, .Dynamic).init(gpa),
             .keep_source_files_loaded = options.keep_source_files_loaded,
-            .use_clang = use_clang,
+            .c_frontend = c_frontend,
             .clang_argv = options.clang_argv,
             .c_source_files = options.c_source_files,
             .rc_source_files = options.rc_source_files,
@@ -3918,9 +3916,7 @@ pub const CImportResult = struct {
 /// This API is currently coupled pretty tightly to stage1's needs; it will need to be reworked
 /// a bit when we want to start using it from self-hosted.
 pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
-    if (!build_options.have_llvm)
-        return error.ZigCompilerNotBuiltWithLLVMExtensions;
-
+    if (build_options.only_c) unreachable; // @cImport is not needed for bootstrapping
     const tracy_trace = trace(@src());
     defer tracy_trace.end();
 
@@ -3967,7 +3963,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
         var argv = std.ArrayList([]const u8).init(comp.gpa);
         defer argv.deinit();
 
-        try argv.append(""); // argv[0] is program name, actual args start at [1]
+        try argv.append(@tagName(comp.c_frontend)); // argv[0] is program name, actual args start at [1]
         try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path);
 
         try argv.append(out_h_path);
@@ -3975,31 +3971,43 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
         if (comp.verbose_cc) {
             dump_argv(argv.items);
         }
+        var tree = switch (comp.c_frontend) {
+            .aro => tree: {
+                if (builtin.zig_backend == .stage2_c) @panic("the CBE cannot compile Aro yet!");
+                const translate_c = @import("aro_translate_c.zig");
+                _ = translate_c;
+                break :tree undefined;
+            },
+            .clang => tree: {
+                if (!build_options.have_llvm) unreachable;
+                const translate_c = @import("translate_c.zig");
+
+                // Convert to null terminated args.
+                const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, argv.items.len + 1);
+                new_argv_with_sentinel[argv.items.len] = null;
+                const new_argv = new_argv_with_sentinel[0..argv.items.len :null];
+                for (argv.items, 0..) |arg, i| {
+                    new_argv[i] = try arena.dupeZ(u8, arg);
+                }
 
-        // Convert to null terminated args.
-        const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, argv.items.len + 1);
-        new_argv_with_sentinel[argv.items.len] = null;
-        const new_argv = new_argv_with_sentinel[0..argv.items.len :null];
-        for (argv.items, 0..) |arg, i| {
-            new_argv[i] = try arena.dupeZ(u8, arg);
-        }
-
-        const c_headers_dir_path_z = try comp.zig_lib_directory.joinZ(arena, &[_][]const u8{"include"});
-        var errors = std.zig.ErrorBundle.empty;
-        errdefer errors.deinit(comp.gpa);
-        var tree = translate_c.translate(
-            comp.gpa,
-            new_argv.ptr,
-            new_argv.ptr + new_argv.len,
-            &errors,
-            c_headers_dir_path_z,
-        ) catch |err| switch (err) {
-            error.OutOfMemory => return error.OutOfMemory,
-            error.SemanticAnalyzeFail => {
-                return CImportResult{
-                    .out_zig_path = "",
-                    .cache_hit = actual_hit,
-                    .errors = errors,
+                const c_headers_dir_path_z = try comp.zig_lib_directory.joinZ(arena, &[_][]const u8{"include"});
+                var errors = std.zig.ErrorBundle.empty;
+                errdefer errors.deinit(comp.gpa);
+                break :tree translate_c.translate(
+                    comp.gpa,
+                    new_argv.ptr,
+                    new_argv.ptr + new_argv.len,
+                    &errors,
+                    c_headers_dir_path_z,
+                ) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.SemanticAnalyzeFail => {
+                        return CImportResult{
+                            .out_zig_path = "",
+                            .cache_hit = actual_hit,
+                            .errors = errors,
+                        };
+                    },
                 };
             },
         };
@@ -4249,6 +4257,9 @@ fn reportRetryableEmbedFileError(
 }
 
 fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.Progress.Node) !void {
+    if (comp.c_frontend == .aro) {
+        return comp.failCObj(c_object, "aro does not support compiling C objects yet", .{});
+    }
     if (!build_options.have_llvm) {
         return comp.failCObj(c_object, "clang not available: compiler built without LLVM extensions", .{});
     }
src/main.zig
@@ -20,7 +20,6 @@ const build_options = @import("build_options");
 const introspect = @import("introspect.zig");
 const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
 const wasi_libc = @import("wasi_libc.zig");
-const translate_c = @import("translate_c.zig");
 const BuildId = std.Build.CompileStep.BuildId;
 const Cache = std.Build.Cache;
 const target_util = @import("target.zig");
@@ -4204,9 +4203,7 @@ fn updateModule(comp: *Compilation) !void {
 }
 
 fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilation.CImportResult) !void {
-    if (!build_options.have_llvm)
-        fatal("cannot translate-c: compiler built without LLVM extensions", .{});
-
+    if (build_options.only_c) unreachable; // translate-c is not needed for bootstrapping
     assert(comp.c_source_files.len == 1);
     const c_source_file = comp.c_source_files[0];
 
@@ -4225,7 +4222,7 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati
     const digest = if (try man.hit()) man.final() else digest: {
         if (fancy_output) |p| p.cache_hit = false;
         var argv = std.ArrayList([]const u8).init(arena);
-        try argv.append(""); // argv[0] is program name, actual args start at [1]
+        try argv.append(@tagName(comp.c_frontend)); // argv[0] is program name, actual args start at [1]
 
         var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{});
         defer zig_cache_tmp_dir.close();
@@ -4245,40 +4242,52 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati
         try argv.append(c_source_file.src_path);
 
         if (comp.verbose_cc) {
-            std.debug.print("clang ", .{});
             Compilation.dump_argv(argv.items);
         }
 
-        // Convert to null terminated args.
-        const clang_args_len = argv.items.len + c_source_file.extra_flags.len;
-        const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, clang_args_len + 1);
-        new_argv_with_sentinel[clang_args_len] = null;
-        const new_argv = new_argv_with_sentinel[0..clang_args_len :null];
-        for (argv.items, 0..) |arg, i| {
-            new_argv[i] = try arena.dupeZ(u8, arg);
-        }
-        for (c_source_file.extra_flags, 0..) |arg, i| {
-            new_argv[argv.items.len + i] = try arena.dupeZ(u8, arg);
-        }
-
-        const c_headers_dir_path_z = try comp.zig_lib_directory.joinZ(arena, &[_][]const u8{"include"});
-        var errors = std.zig.ErrorBundle.empty;
-        var tree = translate_c.translate(
-            comp.gpa,
-            new_argv.ptr,
-            new_argv.ptr + new_argv.len,
-            &errors,
-            c_headers_dir_path_z,
-        ) catch |err| switch (err) {
-            error.OutOfMemory => return error.OutOfMemory,
-            error.SemanticAnalyzeFail => {
-                if (fancy_output) |p| {
-                    p.errors = errors;
-                    return;
-                } else {
-                    errors.renderToStdErr(renderOptions(comp.color));
-                    process.exit(1);
+        var tree = switch (comp.c_frontend) {
+            .aro => tree: {
+                if (builtin.zig_backend == .stage2_c) @panic("the CBE cannot compile Aro yet!");
+                const translate_c = @import("aro_translate_c.zig");
+                _ = translate_c;
+                break :tree undefined;
+            },
+            .clang => tree: {
+                if (!build_options.have_llvm) unreachable;
+                const translate_c = @import("translate_c.zig");
+
+                // Convert to null terminated args.
+                const clang_args_len = argv.items.len + c_source_file.extra_flags.len;
+                const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, clang_args_len + 1);
+                new_argv_with_sentinel[clang_args_len] = null;
+                const new_argv = new_argv_with_sentinel[0..clang_args_len :null];
+                for (argv.items, 0..) |arg, i| {
+                    new_argv[i] = try arena.dupeZ(u8, arg);
+                }
+                for (c_source_file.extra_flags, 0..) |arg, i| {
+                    new_argv[argv.items.len + i] = try arena.dupeZ(u8, arg);
                 }
+
+                const c_headers_dir_path_z = try comp.zig_lib_directory.joinZ(arena, &[_][]const u8{"include"});
+                var errors = std.zig.ErrorBundle.empty;
+                break :tree translate_c.translate(
+                    comp.gpa,
+                    new_argv.ptr,
+                    new_argv.ptr + new_argv.len,
+                    &errors,
+                    c_headers_dir_path_z,
+                ) catch |err| switch (err) {
+                    error.OutOfMemory => return error.OutOfMemory,
+                    error.SemanticAnalyzeFail => {
+                        if (fancy_output) |p| {
+                            p.errors = errors;
+                            return;
+                        } else {
+                            errors.renderToStdErr(renderOptions(comp.color));
+                            process.exit(1);
+                        }
+                    },
+                };
             },
         };
         defer tree.deinit(comp.gpa);