mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
parent
6d37ae95ed
commit
d11f42c2b2
@ -849,10 +849,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
|||||||
if (options.use_llvm) |explicit|
|
if (options.use_llvm) |explicit|
|
||||||
break :blk explicit;
|
break :blk explicit;
|
||||||
|
|
||||||
// If we have no zig code to compile, no need for LLVM.
|
|
||||||
if (options.main_pkg == null)
|
|
||||||
break :blk false;
|
|
||||||
|
|
||||||
// If we are outputting .c code we must use Zig backend.
|
// If we are outputting .c code we must use Zig backend.
|
||||||
if (ofmt == .c)
|
if (ofmt == .c)
|
||||||
break :blk false;
|
break :blk false;
|
||||||
@ -861,6 +857,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
|||||||
if (options.emit_llvm_ir != null or options.emit_llvm_bc != null)
|
if (options.emit_llvm_ir != null or options.emit_llvm_bc != null)
|
||||||
break :blk true;
|
break :blk true;
|
||||||
|
|
||||||
|
// If we have no zig code to compile, no need for LLVM.
|
||||||
|
if (options.main_pkg == null)
|
||||||
|
break :blk false;
|
||||||
|
|
||||||
// The stage1 compiler depends on the stage1 C++ LLVM backend
|
// The stage1 compiler depends on the stage1 C++ LLVM backend
|
||||||
// to compile zig code.
|
// to compile zig code.
|
||||||
if (use_stage1)
|
if (use_stage1)
|
||||||
@ -876,9 +876,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
|||||||
if (options.use_llvm == true) {
|
if (options.use_llvm == true) {
|
||||||
return error.ZigCompilerNotBuiltWithLLVMExtensions;
|
return error.ZigCompilerNotBuiltWithLLVMExtensions;
|
||||||
}
|
}
|
||||||
if (options.machine_code_model != .default) {
|
|
||||||
return error.MachineCodeModelNotSupportedWithoutLlvm;
|
|
||||||
}
|
|
||||||
if (options.emit_llvm_ir != null or options.emit_llvm_bc != null) {
|
if (options.emit_llvm_ir != null or options.emit_llvm_bc != null) {
|
||||||
return error.EmittingLlvmModuleRequiresUsingLlvmBackend;
|
return error.EmittingLlvmModuleRequiresUsingLlvmBackend;
|
||||||
}
|
}
|
||||||
@ -1793,6 +1790,10 @@ pub fn update(self: *Compilation) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flush takes care of -femit-bin, but we still have -femit-llvm-ir, -femit-llvm-bc, and
|
||||||
|
// -femit-asm to handle, in the case of C objects.
|
||||||
|
try self.emitOthers();
|
||||||
|
|
||||||
// If there are any errors, we anticipate the source files being loaded
|
// If there are any errors, we anticipate the source files being loaded
|
||||||
// to report error messages. Otherwise we unload all source files to save memory.
|
// to report error messages. Otherwise we unload all source files to save memory.
|
||||||
// The ZIR needs to stay loaded in memory because (1) Decl objects contain references
|
// The ZIR needs to stay loaded in memory because (1) Decl objects contain references
|
||||||
@ -1808,6 +1809,37 @@ pub fn update(self: *Compilation) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emitOthers(comp: *Compilation) !void {
|
||||||
|
if (comp.bin_file.options.output_mode != .Obj or comp.bin_file.options.module != null or
|
||||||
|
comp.c_object_table.count() == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const obj_path = comp.c_object_table.keys()[0].status.success.object_path;
|
||||||
|
const cwd = std.fs.cwd();
|
||||||
|
const ext = std.fs.path.extension(obj_path);
|
||||||
|
const basename = obj_path[0 .. obj_path.len - ext.len];
|
||||||
|
// This obj path always ends with the object file extension, but if we change the
|
||||||
|
// extension to .ll, .bc, or .s, then it will be the path to those things.
|
||||||
|
const outs = [_]struct {
|
||||||
|
emit: ?EmitLoc,
|
||||||
|
ext: []const u8,
|
||||||
|
}{
|
||||||
|
.{ .emit = comp.emit_asm, .ext = ".s" },
|
||||||
|
.{ .emit = comp.emit_llvm_ir, .ext = ".ll" },
|
||||||
|
.{ .emit = comp.emit_llvm_bc, .ext = ".bc" },
|
||||||
|
};
|
||||||
|
for (outs) |out| {
|
||||||
|
if (out.emit) |loc| {
|
||||||
|
if (loc.directory) |directory| {
|
||||||
|
const src_path = try std.fmt.allocPrint(comp.gpa, "{s}{s}", .{ basename, out.ext });
|
||||||
|
defer comp.gpa.free(src_path);
|
||||||
|
try cwd.copyFile(src_path, directory.handle, loc.basename, .{});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Having the file open for writing is problematic as far as executing the
|
/// Having the file open for writing is problematic as far as executing the
|
||||||
/// binary is concerned. This will remove the write flag, or close the file,
|
/// binary is concerned. This will remove the write flag, or close the file,
|
||||||
/// or whatever is needed so that it can be executed.
|
/// or whatever is needed so that it can be executed.
|
||||||
@ -2764,6 +2796,9 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
|
|||||||
defer man.deinit();
|
defer man.deinit();
|
||||||
|
|
||||||
man.hash.add(comp.clang_preprocessor_mode);
|
man.hash.add(comp.clang_preprocessor_mode);
|
||||||
|
man.hash.addOptionalEmitLoc(comp.emit_asm);
|
||||||
|
man.hash.addOptionalEmitLoc(comp.emit_llvm_ir);
|
||||||
|
man.hash.addOptionalEmitLoc(comp.emit_llvm_bc);
|
||||||
|
|
||||||
try man.hashCSource(c_object.src);
|
try man.hashCSource(c_object.src);
|
||||||
|
|
||||||
@ -2787,16 +2822,29 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
|
|||||||
comp.bin_file.options.root_name
|
comp.bin_file.options.root_name
|
||||||
else
|
else
|
||||||
c_source_basename[0 .. c_source_basename.len - std.fs.path.extension(c_source_basename).len];
|
c_source_basename[0 .. c_source_basename.len - std.fs.path.extension(c_source_basename).len];
|
||||||
const o_basename = try std.fmt.allocPrint(arena, "{s}{s}", .{
|
|
||||||
o_basename_noext,
|
|
||||||
comp.bin_file.options.object_format.fileExt(comp.bin_file.options.target.cpu.arch),
|
|
||||||
});
|
|
||||||
|
|
||||||
|
const o_ext = comp.bin_file.options.object_format.fileExt(comp.bin_file.options.target.cpu.arch);
|
||||||
const digest = if (!comp.disable_c_depfile and try man.hit()) man.final() else blk: {
|
const digest = if (!comp.disable_c_depfile and try man.hit()) man.final() else blk: {
|
||||||
var argv = std.ArrayList([]const u8).init(comp.gpa);
|
var argv = std.ArrayList([]const u8).init(comp.gpa);
|
||||||
defer argv.deinit();
|
defer argv.deinit();
|
||||||
|
|
||||||
// We can't know the digest until we do the C compiler invocation, so we need a temporary filename.
|
// In case we are doing passthrough mode, we need to detect -S and -emit-llvm.
|
||||||
|
const out_ext = e: {
|
||||||
|
if (!comp.clang_passthrough_mode)
|
||||||
|
break :e o_ext;
|
||||||
|
if (comp.emit_asm != null)
|
||||||
|
break :e ".s";
|
||||||
|
if (comp.emit_llvm_ir != null)
|
||||||
|
break :e ".ll";
|
||||||
|
if (comp.emit_llvm_bc != null)
|
||||||
|
break :e ".bc";
|
||||||
|
|
||||||
|
break :e o_ext;
|
||||||
|
};
|
||||||
|
const o_basename = try std.fmt.allocPrint(arena, "{s}{s}", .{ o_basename_noext, out_ext });
|
||||||
|
|
||||||
|
// We can't know the digest until we do the C compiler invocation,
|
||||||
|
// so we need a temporary filename.
|
||||||
const out_obj_path = try comp.tmpFilePath(arena, o_basename);
|
const out_obj_path = try comp.tmpFilePath(arena, o_basename);
|
||||||
var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{});
|
var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{});
|
||||||
defer zig_cache_tmp_dir.close();
|
defer zig_cache_tmp_dir.close();
|
||||||
@ -2810,15 +2858,23 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
|
|||||||
try std.fmt.allocPrint(arena, "{s}.d", .{out_obj_path});
|
try std.fmt.allocPrint(arena, "{s}.d", .{out_obj_path});
|
||||||
try comp.addCCArgs(arena, &argv, ext, out_dep_path);
|
try comp.addCCArgs(arena, &argv, ext, out_dep_path);
|
||||||
|
|
||||||
try argv.ensureCapacity(argv.items.len + 3);
|
try argv.ensureUnusedCapacity(6 + c_object.src.extra_flags.len);
|
||||||
switch (comp.clang_preprocessor_mode) {
|
switch (comp.clang_preprocessor_mode) {
|
||||||
.no => argv.appendSliceAssumeCapacity(&[_][]const u8{ "-c", "-o", out_obj_path }),
|
.no => argv.appendSliceAssumeCapacity(&[_][]const u8{ "-c", "-o", out_obj_path }),
|
||||||
.yes => argv.appendSliceAssumeCapacity(&[_][]const u8{ "-E", "-o", out_obj_path }),
|
.yes => argv.appendSliceAssumeCapacity(&[_][]const u8{ "-E", "-o", out_obj_path }),
|
||||||
.stdout => argv.appendAssumeCapacity("-E"),
|
.stdout => argv.appendAssumeCapacity("-E"),
|
||||||
}
|
}
|
||||||
|
if (comp.clang_passthrough_mode) {
|
||||||
try argv.append(c_object.src.src_path);
|
if (comp.emit_asm != null) {
|
||||||
try argv.appendSlice(c_object.src.extra_flags);
|
argv.appendAssumeCapacity("-S");
|
||||||
|
} else if (comp.emit_llvm_ir != null) {
|
||||||
|
argv.appendSliceAssumeCapacity(&[_][]const u8{ "-emit-llvm", "-S" });
|
||||||
|
} else if (comp.emit_llvm_bc != null) {
|
||||||
|
argv.appendAssumeCapacity("-emit-llvm");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argv.appendAssumeCapacity(c_object.src.src_path);
|
||||||
|
argv.appendSliceAssumeCapacity(c_object.src.extra_flags);
|
||||||
|
|
||||||
if (comp.verbose_cc) {
|
if (comp.verbose_cc) {
|
||||||
dump_argv(argv.items);
|
dump_argv(argv.items);
|
||||||
@ -2838,8 +2894,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
|
|||||||
switch (term) {
|
switch (term) {
|
||||||
.Exited => |code| {
|
.Exited => |code| {
|
||||||
if (code != 0) {
|
if (code != 0) {
|
||||||
// TODO https://github.com/ziglang/zig/issues/6342
|
std.process.exit(code);
|
||||||
std.process.exit(1);
|
|
||||||
}
|
}
|
||||||
if (comp.clang_preprocessor_mode == .stdout)
|
if (comp.clang_preprocessor_mode == .stdout)
|
||||||
std.process.exit(0);
|
std.process.exit(0);
|
||||||
@ -2855,9 +2910,6 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
|
|||||||
|
|
||||||
const stderr_reader = child.stderr.?.reader();
|
const stderr_reader = child.stderr.?.reader();
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/6343
|
|
||||||
// Please uncomment and use stdout once this issue is fixed
|
|
||||||
// const stdout = try stdout_reader.readAllAlloc(arena, std.math.maxInt(u32));
|
|
||||||
const stderr = try stderr_reader.readAllAlloc(arena, 10 * 1024 * 1024);
|
const stderr = try stderr_reader.readAllAlloc(arena, 10 * 1024 * 1024);
|
||||||
|
|
||||||
const term = child.wait() catch |err| {
|
const term = child.wait() catch |err| {
|
||||||
@ -2907,6 +2959,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
|
|||||||
break :blk digest;
|
break :blk digest;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const o_basename = try std.fmt.allocPrint(arena, "{s}{s}", .{ o_basename_noext, o_ext });
|
||||||
|
|
||||||
c_object.status = .{
|
c_object.status = .{
|
||||||
.success = .{
|
.success = .{
|
||||||
.object_path = try comp.local_cache_directory.join(comp.gpa, &[_][]const u8{
|
.object_path = try comp.local_cache_directory.join(comp.gpa, &[_][]const u8{
|
||||||
|
|||||||
@ -2434,7 +2434,14 @@ flagpd1("emit-codegen-only"),
|
|||||||
flagpd1("emit-header-module"),
|
flagpd1("emit-header-module"),
|
||||||
flagpd1("emit-html"),
|
flagpd1("emit-html"),
|
||||||
flagpd1("emit-interface-stubs"),
|
flagpd1("emit-interface-stubs"),
|
||||||
flagpd1("emit-llvm"),
|
.{
|
||||||
|
.name = "emit-llvm",
|
||||||
|
.syntax = .flag,
|
||||||
|
.zig_equivalent = .emit_llvm,
|
||||||
|
.pd1 = true,
|
||||||
|
.pd2 = false,
|
||||||
|
.psl = false,
|
||||||
|
},
|
||||||
flagpd1("emit-llvm-bc"),
|
flagpd1("emit-llvm-bc"),
|
||||||
flagpd1("emit-llvm-only"),
|
flagpd1("emit-llvm-only"),
|
||||||
flagpd1("emit-llvm-uselists"),
|
flagpd1("emit-llvm-uselists"),
|
||||||
|
|||||||
23
src/main.zig
23
src/main.zig
@ -1151,6 +1151,7 @@ fn buildOutputType(
|
|||||||
var is_shared_lib = false;
|
var is_shared_lib = false;
|
||||||
var linker_args = std.ArrayList([]const u8).init(arena);
|
var linker_args = std.ArrayList([]const u8).init(arena);
|
||||||
var it = ClangArgIterator.init(arena, all_args);
|
var it = ClangArgIterator.init(arena, all_args);
|
||||||
|
var emit_llvm = false;
|
||||||
while (it.has_next) {
|
while (it.has_next) {
|
||||||
it.next() catch |err| {
|
it.next() catch |err| {
|
||||||
fatal("unable to parse command line parameters: {s}", .{@errorName(err)});
|
fatal("unable to parse command line parameters: {s}", .{@errorName(err)});
|
||||||
@ -1161,6 +1162,7 @@ fn buildOutputType(
|
|||||||
.c => c_out_mode = .object, // -c
|
.c => c_out_mode = .object, // -c
|
||||||
.asm_only => c_out_mode = .assembly, // -S
|
.asm_only => c_out_mode = .assembly, // -S
|
||||||
.preprocess_only => c_out_mode = .preprocessor, // -E
|
.preprocess_only => c_out_mode = .preprocessor, // -E
|
||||||
|
.emit_llvm => emit_llvm = true,
|
||||||
.other => {
|
.other => {
|
||||||
try clang_argv.appendSlice(it.other_args);
|
try clang_argv.appendSlice(it.other_args);
|
||||||
},
|
},
|
||||||
@ -1518,23 +1520,43 @@ fn buildOutputType(
|
|||||||
output_mode = if (is_shared_lib) .Lib else .Exe;
|
output_mode = if (is_shared_lib) .Lib else .Exe;
|
||||||
emit_bin = if (out_path) |p| .{ .yes = p } else EmitBin.yes_a_out;
|
emit_bin = if (out_path) |p| .{ .yes = p } else EmitBin.yes_a_out;
|
||||||
enable_cache = true;
|
enable_cache = true;
|
||||||
|
if (emit_llvm) {
|
||||||
|
fatal("-emit-llvm cannot be used when linking", .{});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
.object => {
|
.object => {
|
||||||
output_mode = .Obj;
|
output_mode = .Obj;
|
||||||
|
if (emit_llvm) {
|
||||||
|
emit_bin = .no;
|
||||||
|
if (out_path) |p| {
|
||||||
|
emit_llvm_bc = .{ .yes = p };
|
||||||
|
} else {
|
||||||
|
emit_llvm_bc = .yes_default_path;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (out_path) |p| {
|
if (out_path) |p| {
|
||||||
emit_bin = .{ .yes = p };
|
emit_bin = .{ .yes = p };
|
||||||
} else {
|
} else {
|
||||||
emit_bin = .yes_default_path;
|
emit_bin = .yes_default_path;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
.assembly => {
|
.assembly => {
|
||||||
output_mode = .Obj;
|
output_mode = .Obj;
|
||||||
emit_bin = .no;
|
emit_bin = .no;
|
||||||
|
if (emit_llvm) {
|
||||||
|
if (out_path) |p| {
|
||||||
|
emit_llvm_ir = .{ .yes = p };
|
||||||
|
} else {
|
||||||
|
emit_llvm_ir = .yes_default_path;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (out_path) |p| {
|
if (out_path) |p| {
|
||||||
emit_asm = .{ .yes = p };
|
emit_asm = .{ .yes = p };
|
||||||
} else {
|
} else {
|
||||||
emit_asm = .yes_default_path;
|
emit_asm = .yes_default_path;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
.preprocessor => {
|
.preprocessor => {
|
||||||
output_mode = .Obj;
|
output_mode = .Obj;
|
||||||
@ -3663,6 +3685,7 @@ pub const ClangArgIterator = struct {
|
|||||||
no_red_zone,
|
no_red_zone,
|
||||||
strip,
|
strip,
|
||||||
exec_model,
|
exec_model,
|
||||||
|
emit_llvm,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Args = struct {
|
const Args = struct {
|
||||||
|
|||||||
@ -376,6 +376,10 @@ const known_options = [_]KnownOpt{
|
|||||||
.name = "mexec-model",
|
.name = "mexec-model",
|
||||||
.ident = "exec_model",
|
.ident = "exec_model",
|
||||||
},
|
},
|
||||||
|
.{
|
||||||
|
.name = "emit-llvm",
|
||||||
|
.ident = "emit_llvm",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const blacklisted_options = [_][]const u8{};
|
const blacklisted_options = [_][]const u8{};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user