authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-14 21:21:39-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-14 21:22:11-07:00
log6acd903a9510d0e145b7bba3a9d42d4b9c07cc34
tree5e4c0a76a142358ad96b7eb57328faea9ea103d8
parent0e94530c515dab388828becacc0fe295c5f2b917

stage2: support for machine code model CLI


4 files changed, 35 insertions(+), 9 deletions(-)

BRANCH_TODO-1
......@@ -1,4 +1,3 @@
1 * integrate code model and have_frame_pointer to main() and c objects
21 * integrate target features into building C source files
32 * integrate target features into building assembly code
43 * handle .d files from c objects
src-self-hosted/Compilation.zig+18-8
......@@ -271,6 +271,7 @@ pub const InitOptions = struct {
271271 self_exe_path: ?[]const u8 = null,
272272 version: ?std.builtin.Version = null,
273273 libc_installation: ?*const LibCInstallation = null,
274 machine_code_model: std.builtin.CodeModel = .default,
274275};
275276
276277pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
......@@ -319,6 +320,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
319320 // We would also want to prefer LLVM for architectures that we don't have self-hosted support for too.
320321 break :blk false;
321322 };
323 if (!use_llvm and options.machine_code_model != .default) {
324 return error.MachineCodeModelNotSupported;
325 }
322326
323327 const is_exe_or_dyn_lib = switch (options.output_mode) {
324328 .Obj => false,
......@@ -425,6 +429,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
425429 cache.hash.add(options.strip);
426430 cache.hash.add(options.link_libc);
427431 cache.hash.add(options.output_mode);
432 cache.hash.add(options.machine_code_model);
428433 // TODO audit this and make sure everything is in it
429434
430435 const module: ?*Module = if (options.root_pkg) |root_pkg| blk: {
......@@ -593,6 +598,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
593598 .stack_check = stack_check,
594599 .single_threaded = single_threaded,
595600 .debug_link = options.debug_link,
601 .machine_code_model = options.machine_code_model,
596602 });
597603 errdefer bin_file.destroy();
598604
......@@ -964,10 +970,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
964970 ch.hash.addListOfBytes(comp.clang_argv);
965971 ch.hash.add(comp.bin_file.options.link_libcpp);
966972 ch.hash.addListOfBytes(comp.libc_include_dir_list);
967 // TODO
968 //cache_int(cache_hash, g->code_model);
969 //cache_bool(cache_hash, codegen_have_frame_pointer(g));
970 _ = try ch.addFile(c_object.src_path, null);
973 _ = try ch.addFile(c_object.src.src_path, null);
971974 {
972975 // Hash the extra flags, with special care to call addFile for file parameters.
973976 // 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 {
989992 defer arena_allocator.deinit();
990993 const arena = &arena_allocator.allocator;
991994
992 const c_source_basename = std.fs.path.basename(c_object.src_path);
995 const c_source_basename = std.fs.path.basename(c_object.src.src_path);
993996 // Special case when doing build-obj for just one C file. When there are more than one object
994997 // file and building an object we need to link them together, but with just one it should go
995998 // directly to the output file.
......@@ -1012,14 +1015,14 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
10121015
10131016 try argv.appendSlice(&[_][]const u8{ self_exe_path, "clang", "-c" });
10141017
1015 const ext = classifyFileExt(c_object.src_path);
1018 const ext = classifyFileExt(c_object.src.src_path);
10161019 // TODO capture the .d file and deal with caching stuff
10171020 try comp.addCCArgs(arena, &argv, ext, false, null);
10181021
10191022 try argv.append("-o");
10201023 try argv.append(out_obj_path);
10211024
1022 try argv.append(c_object.src_path);
1025 try argv.append(c_object.src.src_path);
10231026 try argv.appendSlice(c_object.src.extra_flags);
10241027
10251028 if (comp.debug_cc) {
......@@ -1095,7 +1098,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
10951098 try std.os.renameat(zig_cache_tmp_dir.fd, tmp_basename, o_dir.fd, o_basename);
10961099
10971100 ch.writeManifest() catch |err| {
1098 std.log.warn("failed to write cache manifest when compiling '{}': {}", .{ c_object.src_path, @errorName(err) });
1101 std.log.warn("failed to write cache manifest when compiling '{}': {}", .{ c_object.src.src_path, @errorName(err) });
10991102 };
11001103 break :blk digest;
11011104 };
......@@ -1219,6 +1222,10 @@ fn addCCArgs(
12191222 // flag = SplitIterator_next(&it);
12201223 // }
12211224 //}
1225 const mcmodel = comp.bin_file.options.machine_code_model;
1226 if (mcmodel != .default) {
1227 try argv.append(try std.fmt.allocPrint(arena, "-mcmodel={}", .{@tagName(mcmodel)}));
1228 }
12221229 if (translate_c) {
12231230 // This gives us access to preprocessing entities, presumably at the cost of performance.
12241231 try argv.append("-Xclang");
......@@ -1432,6 +1439,9 @@ test "classifyFileExt" {
14321439}
14331440
14341441fn haveFramePointer(comp: *Compilation) bool {
1442 // If you complicate this logic make sure you update the parent cache hash.
1443 // Right now it's not in the cache hash because the value depends on optimize_mode
1444 // and strip which are both already part of the hash.
14351445 return switch (comp.bin_file.options.optimize_mode) {
14361446 .Debug, .ReleaseSafe => !comp.bin_file.options.strip,
14371447 .ReleaseSmall, .ReleaseFast => false,
src-self-hosted/link.zig+1
......@@ -24,6 +24,7 @@ pub const Options = struct {
2424 link_mode: std.builtin.LinkMode,
2525 object_format: std.builtin.ObjectFormat,
2626 optimize_mode: std.builtin.Mode,
27 machine_code_model: std.builtin.CodeModel,
2728 root_name: []const u8,
2829 /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.
2930 module: ?*Module,
src-self-hosted/main.zig+16
......@@ -183,6 +183,9 @@ const usage_build_generic =
183183 \\Compile Options:
184184 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command
185185 \\ -mcpu [cpu] Specify target CPU and feature set
186 \\ -mcmodel=[default|tiny| Limit range of code and data virtual addresses
187 \\ small|kernel|
188 \\ medium|large]
186189 \\ --name [name] Override output name
187190 \\ --mode [mode] Set the build mode
188191 \\ Debug (default) optimizations off, safety on
......@@ -306,6 +309,7 @@ pub fn buildOutputType(
306309 var use_clang: ?bool = null;
307310 var link_eh_frame_hdr = false;
308311 var libc_paths_file: ?[]const u8 = null;
312 var machine_code_model: std.builtin.CodeModel = .default;
309313
310314 var system_libs = std.ArrayList([]const u8).init(gpa);
311315 defer system_libs.deinit();
......@@ -446,10 +450,16 @@ pub fn buildOutputType(
446450 if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg});
447451 i += 1;
448452 target_mcpu = args[i];
453 } else if (mem.eql(u8, arg, "-mcmodel")) {
454 if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg});
455 i += 1;
456 machine_code_model = parseCodeModel(args[i]);
449457 } else if (mem.startsWith(u8, arg, "-ofmt=")) {
450458 target_ofmt = arg["-ofmt=".len..];
451459 } else if (mem.startsWith(u8, arg, "-mcpu=")) {
452460 target_mcpu = arg["-mcpu=".len..];
461 } else if (mem.startsWith(u8, arg, "-mcmodel=")) {
462 machine_code_model = parseCodeModel(arg["-mcmodel=".len..]);
453463 } else if (mem.eql(u8, arg, "--dynamic-linker")) {
454464 if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg});
455465 i += 1;
......@@ -1150,6 +1160,7 @@ pub fn buildOutputType(
11501160 .libc_installation = if (libc_installation) |*lci| lci else null,
11511161 .debug_cc = debug_cc,
11521162 .debug_link = debug_link,
1163 .machine_code_model = machine_code_model,
11531164 }) catch |err| {
11541165 fatal("unable to create compilation: {}", .{@errorName(err)});
11551166 };
......@@ -1917,3 +1928,8 @@ fn is_libcpp_lib_name(target: std.Target, name: []const u8) bool {
19171928 eqlIgnoreCase(ignore_case, name, "stdc++") or
19181929 eqlIgnoreCase(ignore_case, name, "c++abi");
19191930}
1931
1932fn parseCodeModel(arg: []const u8) std.builtin.CodeModel {
1933 return std.meta.stringToEnum(std.builtin.CodeModel, arg) orelse
1934 fatal("unsupported machine code model: '{}'", .{arg});
1935}