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,4 +1,3 @@
1 * integrate code model and have_frame_pointer to main() and c objects
2 * integrate target features into building C source files1 * integrate target features into building C source files
3 * integrate target features into building assembly code2 * integrate target features into building assembly code
4 * handle .d files from c objects3 * handle .d files from c objects
src-self-hosted/Compilation.zig+18-8
...@@ -271,6 +271,7 @@ pub const InitOptions = struct {...@@ -271,6 +271,7 @@ pub const InitOptions = struct {
271 self_exe_path: ?[]const u8 = null,271 self_exe_path: ?[]const u8 = null,
272 version: ?std.builtin.Version = null,272 version: ?std.builtin.Version = null,
273 libc_installation: ?*const LibCInstallation = null,273 libc_installation: ?*const LibCInstallation = null,
274 machine_code_model: std.builtin.CodeModel = .default,
274};275};
275276
276pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {277pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
...@@ -319,6 +320,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -319,6 +320,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
319 // We would also want to prefer LLVM for architectures that we don't have self-hosted support for too.320 // We would also want to prefer LLVM for architectures that we don't have self-hosted support for too.
320 break :blk false;321 break :blk false;
321 };322 };
323 if (!use_llvm and options.machine_code_model != .default) {
324 return error.MachineCodeModelNotSupported;
325 }
322326
323 const is_exe_or_dyn_lib = switch (options.output_mode) {327 const is_exe_or_dyn_lib = switch (options.output_mode) {
324 .Obj => false,328 .Obj => false,
...@@ -425,6 +429,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -425,6 +429,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
425 cache.hash.add(options.strip);429 cache.hash.add(options.strip);
426 cache.hash.add(options.link_libc);430 cache.hash.add(options.link_libc);
427 cache.hash.add(options.output_mode);431 cache.hash.add(options.output_mode);
432 cache.hash.add(options.machine_code_model);
428 // TODO audit this and make sure everything is in it433 // TODO audit this and make sure everything is in it
429434
430 const module: ?*Module = if (options.root_pkg) |root_pkg| blk: {435 const module: ?*Module = if (options.root_pkg) |root_pkg| blk: {
...@@ -593,6 +598,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -593,6 +598,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
593 .stack_check = stack_check,598 .stack_check = stack_check,
594 .single_threaded = single_threaded,599 .single_threaded = single_threaded,
595 .debug_link = options.debug_link,600 .debug_link = options.debug_link,
601 .machine_code_model = options.machine_code_model,
596 });602 });
597 errdefer bin_file.destroy();603 errdefer bin_file.destroy();
598604
...@@ -964,10 +970,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {...@@ -964,10 +970,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
964 ch.hash.addListOfBytes(comp.clang_argv);970 ch.hash.addListOfBytes(comp.clang_argv);
965 ch.hash.add(comp.bin_file.options.link_libcpp);971 ch.hash.add(comp.bin_file.options.link_libcpp);
966 ch.hash.addListOfBytes(comp.libc_include_dir_list);972 ch.hash.addListOfBytes(comp.libc_include_dir_list);
967 // TODO973 _ = try ch.addFile(c_object.src.src_path, null);
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);
971 {974 {
972 // Hash the extra flags, with special care to call addFile for file parameters.975 // Hash the extra flags, with special care to call addFile for file parameters.
973 // TODO this logic can likely be improved by utilizing clang_options_data.zig.976 // 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 {...@@ -989,7 +992,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
989 defer arena_allocator.deinit();992 defer arena_allocator.deinit();
990 const arena = &arena_allocator.allocator;993 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);
993 // Special case when doing build-obj for just one C file. When there are more than one object996 // Special case when doing build-obj for just one C file. When there are more than one object
994 // file and building an object we need to link them together, but with just one it should go997 // file and building an object we need to link them together, but with just one it should go
995 // directly to the output file.998 // directly to the output file.
...@@ -1012,14 +1015,14 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {...@@ -1012,14 +1015,14 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
10121015
1013 try argv.appendSlice(&[_][]const u8{ self_exe_path, "clang", "-c" });1016 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);
1016 // TODO capture the .d file and deal with caching stuff1019 // TODO capture the .d file and deal with caching stuff
1017 try comp.addCCArgs(arena, &argv, ext, false, null);1020 try comp.addCCArgs(arena, &argv, ext, false, null);
10181021
1019 try argv.append("-o");1022 try argv.append("-o");
1020 try argv.append(out_obj_path);1023 try argv.append(out_obj_path);
10211024
1022 try argv.append(c_object.src_path);1025 try argv.append(c_object.src.src_path);
1023 try argv.appendSlice(c_object.src.extra_flags);1026 try argv.appendSlice(c_object.src.extra_flags);
10241027
1025 if (comp.debug_cc) {1028 if (comp.debug_cc) {
...@@ -1095,7 +1098,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {...@@ -1095,7 +1098,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
1095 try std.os.renameat(zig_cache_tmp_dir.fd, tmp_basename, o_dir.fd, o_basename);1098 try std.os.renameat(zig_cache_tmp_dir.fd, tmp_basename, o_dir.fd, o_basename);
10961099
1097 ch.writeManifest() catch |err| {1100 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) });
1099 };1102 };
1100 break :blk digest;1103 break :blk digest;
1101 };1104 };
...@@ -1219,6 +1222,10 @@ fn addCCArgs(...@@ -1219,6 +1222,10 @@ fn addCCArgs(
1219 // flag = SplitIterator_next(&it);1222 // flag = SplitIterator_next(&it);
1220 // }1223 // }
1221 //}1224 //}
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 }
1222 if (translate_c) {1229 if (translate_c) {
1223 // This gives us access to preprocessing entities, presumably at the cost of performance.1230 // This gives us access to preprocessing entities, presumably at the cost of performance.
1224 try argv.append("-Xclang");1231 try argv.append("-Xclang");
...@@ -1432,6 +1439,9 @@ test "classifyFileExt" {...@@ -1432,6 +1439,9 @@ test "classifyFileExt" {
1432}1439}
14331440
1434fn haveFramePointer(comp: *Compilation) bool {1441fn 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.
1435 return switch (comp.bin_file.options.optimize_mode) {1445 return switch (comp.bin_file.options.optimize_mode) {
1436 .Debug, .ReleaseSafe => !comp.bin_file.options.strip,1446 .Debug, .ReleaseSafe => !comp.bin_file.options.strip,
1437 .ReleaseSmall, .ReleaseFast => false,1447 .ReleaseSmall, .ReleaseFast => false,
src-self-hosted/link.zig+1
...@@ -24,6 +24,7 @@ pub const Options = struct {...@@ -24,6 +24,7 @@ pub const Options = struct {
24 link_mode: std.builtin.LinkMode,24 link_mode: std.builtin.LinkMode,
25 object_format: std.builtin.ObjectFormat,25 object_format: std.builtin.ObjectFormat,
26 optimize_mode: std.builtin.Mode,26 optimize_mode: std.builtin.Mode,
27 machine_code_model: std.builtin.CodeModel,
27 root_name: []const u8,28 root_name: []const u8,
28 /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.29 /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.
29 module: ?*Module,30 module: ?*Module,
src-self-hosted/main.zig+16
...@@ -183,6 +183,9 @@ const usage_build_generic =...@@ -183,6 +183,9 @@ const usage_build_generic =
183 \\Compile Options:183 \\Compile Options:
184 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command184 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command
185 \\ -mcpu [cpu] Specify target CPU and feature set185 \\ -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]
186 \\ --name [name] Override output name189 \\ --name [name] Override output name
187 \\ --mode [mode] Set the build mode190 \\ --mode [mode] Set the build mode
188 \\ Debug (default) optimizations off, safety on191 \\ Debug (default) optimizations off, safety on
...@@ -306,6 +309,7 @@ pub fn buildOutputType(...@@ -306,6 +309,7 @@ pub fn buildOutputType(
306 var use_clang: ?bool = null;309 var use_clang: ?bool = null;
307 var link_eh_frame_hdr = false;310 var link_eh_frame_hdr = false;
308 var libc_paths_file: ?[]const u8 = null;311 var libc_paths_file: ?[]const u8 = null;
312 var machine_code_model: std.builtin.CodeModel = .default;
309313
310 var system_libs = std.ArrayList([]const u8).init(gpa);314 var system_libs = std.ArrayList([]const u8).init(gpa);
311 defer system_libs.deinit();315 defer system_libs.deinit();
...@@ -446,10 +450,16 @@ pub fn buildOutputType(...@@ -446,10 +450,16 @@ pub fn buildOutputType(
446 if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg});450 if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg});
447 i += 1;451 i += 1;
448 target_mcpu = args[i];452 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]);
449 } else if (mem.startsWith(u8, arg, "-ofmt=")) {457 } else if (mem.startsWith(u8, arg, "-ofmt=")) {
450 target_ofmt = arg["-ofmt=".len..];458 target_ofmt = arg["-ofmt=".len..];
451 } else if (mem.startsWith(u8, arg, "-mcpu=")) {459 } else if (mem.startsWith(u8, arg, "-mcpu=")) {
452 target_mcpu = arg["-mcpu=".len..];460 target_mcpu = arg["-mcpu=".len..];
461 } else if (mem.startsWith(u8, arg, "-mcmodel=")) {
462 machine_code_model = parseCodeModel(arg["-mcmodel=".len..]);
453 } else if (mem.eql(u8, arg, "--dynamic-linker")) {463 } else if (mem.eql(u8, arg, "--dynamic-linker")) {
454 if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg});464 if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg});
455 i += 1;465 i += 1;
...@@ -1150,6 +1160,7 @@ pub fn buildOutputType(...@@ -1150,6 +1160,7 @@ pub fn buildOutputType(
1150 .libc_installation = if (libc_installation) |*lci| lci else null,1160 .libc_installation = if (libc_installation) |*lci| lci else null,
1151 .debug_cc = debug_cc,1161 .debug_cc = debug_cc,
1152 .debug_link = debug_link,1162 .debug_link = debug_link,
1163 .machine_code_model = machine_code_model,
1153 }) catch |err| {1164 }) catch |err| {
1154 fatal("unable to create compilation: {}", .{@errorName(err)});1165 fatal("unable to create compilation: {}", .{@errorName(err)});
1155 };1166 };
...@@ -1917,3 +1928,8 @@ fn is_libcpp_lib_name(target: std.Target, name: []const u8) bool {...@@ -1917,3 +1928,8 @@ fn is_libcpp_lib_name(target: std.Target, name: []const u8) bool {
1917 eqlIgnoreCase(ignore_case, name, "stdc++") or1928 eqlIgnoreCase(ignore_case, name, "stdc++") or
1918 eqlIgnoreCase(ignore_case, name, "c++abi");1929 eqlIgnoreCase(ignore_case, name, "c++abi");
1919}1930}
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}