Commit 6acd903a95

Andrew Kelley <andrew@ziglang.org>
2020-09-15 06:21:39
stage2: support for machine code model CLI
1 parent 0e94530
Changed files (4)
src-self-hosted/Compilation.zig
@@ -271,6 +271,7 @@ pub const InitOptions = struct {
     self_exe_path: ?[]const u8 = null,
     version: ?std.builtin.Version = null,
     libc_installation: ?*const LibCInstallation = null,
+    machine_code_model: std.builtin.CodeModel = .default,
 };
 
 pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
@@ -319,6 +320,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
             // We would also want to prefer LLVM for architectures that we don't have self-hosted support for too.
             break :blk false;
         };
+        if (!use_llvm and options.machine_code_model != .default) {
+            return error.MachineCodeModelNotSupported;
+        }
 
         const is_exe_or_dyn_lib = switch (options.output_mode) {
             .Obj => false,
@@ -425,6 +429,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
         cache.hash.add(options.strip);
         cache.hash.add(options.link_libc);
         cache.hash.add(options.output_mode);
+        cache.hash.add(options.machine_code_model);
         // TODO audit this and make sure everything is in it
 
         const module: ?*Module = if (options.root_pkg) |root_pkg| blk: {
@@ -593,6 +598,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
             .stack_check = stack_check,
             .single_threaded = single_threaded,
             .debug_link = options.debug_link,
+            .machine_code_model = options.machine_code_model,
         });
         errdefer bin_file.destroy();
 
@@ -964,10 +970,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
     ch.hash.addListOfBytes(comp.clang_argv);
     ch.hash.add(comp.bin_file.options.link_libcpp);
     ch.hash.addListOfBytes(comp.libc_include_dir_list);
-    // TODO
-    //cache_int(cache_hash, g->code_model);
-    //cache_bool(cache_hash, codegen_have_frame_pointer(g));
-    _ = try ch.addFile(c_object.src_path, null);
+    _ = try ch.addFile(c_object.src.src_path, null);
     {
         // Hash the extra flags, with special care to call addFile for file parameters.
         // TODO this logic can likely be improved by utilizing clang_options_data.zig.
@@ -989,7 +992,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
     defer arena_allocator.deinit();
     const arena = &arena_allocator.allocator;
 
-    const c_source_basename = std.fs.path.basename(c_object.src_path);
+    const c_source_basename = std.fs.path.basename(c_object.src.src_path);
     // Special case when doing build-obj for just one C file. When there are more than one object
     // file and building an object we need to link them together, but with just one it should go
     // directly to the output file.
@@ -1012,14 +1015,14 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
 
         try argv.appendSlice(&[_][]const u8{ self_exe_path, "clang", "-c" });
 
-        const ext = classifyFileExt(c_object.src_path);
+        const ext = classifyFileExt(c_object.src.src_path);
         // TODO capture the .d file and deal with caching stuff
         try comp.addCCArgs(arena, &argv, ext, false, null);
 
         try argv.append("-o");
         try argv.append(out_obj_path);
 
-        try argv.append(c_object.src_path);
+        try argv.append(c_object.src.src_path);
         try argv.appendSlice(c_object.src.extra_flags);
 
         if (comp.debug_cc) {
@@ -1095,7 +1098,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
         try std.os.renameat(zig_cache_tmp_dir.fd, tmp_basename, o_dir.fd, o_basename);
 
         ch.writeManifest() catch |err| {
-            std.log.warn("failed to write cache manifest when compiling '{}': {}", .{ c_object.src_path, @errorName(err) });
+            std.log.warn("failed to write cache manifest when compiling '{}': {}", .{ c_object.src.src_path, @errorName(err) });
         };
         break :blk digest;
     };
@@ -1219,6 +1222,10 @@ fn addCCArgs(
             //        flag = SplitIterator_next(&it);
             //    }
             //}
+            const mcmodel = comp.bin_file.options.machine_code_model;
+            if (mcmodel != .default) {
+                try argv.append(try std.fmt.allocPrint(arena, "-mcmodel={}", .{@tagName(mcmodel)}));
+            }
             if (translate_c) {
                 // This gives us access to preprocessing entities, presumably at the cost of performance.
                 try argv.append("-Xclang");
@@ -1432,6 +1439,9 @@ test "classifyFileExt" {
 }
 
 fn haveFramePointer(comp: *Compilation) bool {
+    // If you complicate this logic make sure you update the parent cache hash.
+    // Right now it's not in the cache hash because the value depends on optimize_mode
+    // and strip which are both already part of the hash.
     return switch (comp.bin_file.options.optimize_mode) {
         .Debug, .ReleaseSafe => !comp.bin_file.options.strip,
         .ReleaseSmall, .ReleaseFast => false,
src-self-hosted/link.zig
@@ -24,6 +24,7 @@ pub const Options = struct {
     link_mode: std.builtin.LinkMode,
     object_format: std.builtin.ObjectFormat,
     optimize_mode: std.builtin.Mode,
+    machine_code_model: std.builtin.CodeModel,
     root_name: []const u8,
     /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.
     module: ?*Module,
src-self-hosted/main.zig
@@ -183,6 +183,9 @@ const usage_build_generic =
     \\Compile Options:
     \\  -target [name]            <arch><sub>-<os>-<abi> see the targets command
     \\  -mcpu [cpu]               Specify target CPU and feature set
+    \\  -mcmodel=[default|tiny|   Limit range of code and data virtual addresses
+    \\            small|kernel|
+    \\            medium|large]
     \\  --name [name]             Override output name
     \\  --mode [mode]             Set the build mode
     \\    Debug                   (default) optimizations off, safety on
@@ -306,6 +309,7 @@ pub fn buildOutputType(
     var use_clang: ?bool = null;
     var link_eh_frame_hdr = false;
     var libc_paths_file: ?[]const u8 = null;
+    var machine_code_model: std.builtin.CodeModel = .default;
 
     var system_libs = std.ArrayList([]const u8).init(gpa);
     defer system_libs.deinit();
@@ -446,10 +450,16 @@ pub fn buildOutputType(
                     if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg});
                     i += 1;
                     target_mcpu = args[i];
+                } else if (mem.eql(u8, arg, "-mcmodel")) {
+                    if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg});
+                    i += 1;
+                    machine_code_model = parseCodeModel(args[i]);
                 } else if (mem.startsWith(u8, arg, "-ofmt=")) {
                     target_ofmt = arg["-ofmt=".len..];
                 } else if (mem.startsWith(u8, arg, "-mcpu=")) {
                     target_mcpu = arg["-mcpu=".len..];
+                } else if (mem.startsWith(u8, arg, "-mcmodel=")) {
+                    machine_code_model = parseCodeModel(arg["-mcmodel=".len..]);
                 } else if (mem.eql(u8, arg, "--dynamic-linker")) {
                     if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg});
                     i += 1;
@@ -1150,6 +1160,7 @@ pub fn buildOutputType(
         .libc_installation = if (libc_installation) |*lci| lci else null,
         .debug_cc = debug_cc,
         .debug_link = debug_link,
+        .machine_code_model = machine_code_model,
     }) catch |err| {
         fatal("unable to create compilation: {}", .{@errorName(err)});
     };
@@ -1917,3 +1928,8 @@ fn is_libcpp_lib_name(target: std.Target, name: []const u8) bool {
         eqlIgnoreCase(ignore_case, name, "stdc++") or
         eqlIgnoreCase(ignore_case, name, "c++abi");
 }
+
+fn parseCodeModel(arg: []const u8) std.builtin.CodeModel {
+    return std.meta.stringToEnum(std.builtin.CodeModel, arg) orelse
+        fatal("unsupported machine code model: '{}'", .{arg});
+}
BRANCH_TODO
@@ -1,4 +1,3 @@
- * integrate code model and have_frame_pointer to main() and c objects
  * integrate target features into building C source files
  * integrate target features into building assembly code
  * handle .d files from c objects