mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-10-28 10:45:48 +08:00
main: reimplement compiler debug flags
* Add `.llvmbc`/`.llvmir` to `ObjectFormat` for emitting unoptimized IR * Replace `--verbose-air`, `--verbose-intern-pool`, `--verbose-generic-instances`, `--verbose-llvm-ir`, and `--verbose-llvm-bc` with various `--debug-log` scopes * `--debug-log illegal-air`: pre-legalized Air * `--debug-log legal-air`: post-legalized Air * `--debug-log air`: final Air with liveness * `--debug-log ip-stats`: InternPool statistics * `--debug-log ip-values`: InternPool values * `--debug-log ip-generic-instances`: InternPool generic instances * `--debug-log llvm-ir`: pre-optimized LLVM IR * `--debug-log opt-llvm-ir`: post-optimized LLVM IR * Delete `--verbose-cimport` which does nothing * Delete `--verbose-llvm-cpu-features` which is equivalent to looking at the outputs of `--show-builtin` and `--debug-log llvm-ir`
This commit is contained in:
1 parent
77576c9603
commit
f08a8f0fc2
48 files changed
+349
-421
No files matched your search
+1
-1
@@ -330,7 +330,7 @@ set(ZIG_STAGE2_SOURCES
|
||||
src/Air/Legalize.zig
|
||||
src/Air/Liveness.zig
|
||||
src/Air/Liveness/Verify.zig
|
||||
src/Air/print.zig
|
||||
src/Air/Print.zig
|
||||
src/Builtin.zig
|
||||
src/Compilation.zig
|
||||
src/Compilation/Config.zig
|
||||
|
||||
+1
-1
@@ -179,7 +179,7 @@ int main(int argc, char **argv) {
|
||||
"pub const version: [:0]const u8 = \"%s\";\n"
|
||||
"pub const semver = @import(\"std\").SemanticVersion.parse(version) catch unreachable;\n"
|
||||
"pub const enable_debug_extensions = false;\n"
|
||||
"pub const enable_logging = false;\n"
|
||||
"pub const log_level: @import(\"std\").log.Level = .err;\n"
|
||||
"pub const enable_link_snapshots = false;\n"
|
||||
"pub const enable_tracy = false;\n"
|
||||
"pub const value_tracing = false;\n"
|
||||
|
||||
@@ -25,6 +25,10 @@ pub fn build(b: *std.Build) !void {
|
||||
},
|
||||
});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const is_debug = switch (optimize) {
|
||||
.debug => true,
|
||||
.safe, .fast, .small => false,
|
||||
};
|
||||
|
||||
const flat = b.option(bool, "flat", "Put files into the installation prefix in a manner suited for upstream distribution rather than a posix file system hierarchy standard") orelse false;
|
||||
const single_threaded = b.option(bool, "single-threaded", "Build artifacts that run in single threaded mode");
|
||||
@@ -205,9 +209,9 @@ pub fn build(b: *std.Build) !void {
|
||||
const value_tracing = b.option(bool, "value-tracing", "Enable extra state tracking to help troubleshoot bugs in the compiler (using the std.debug.Trace API)") orelse false;
|
||||
|
||||
const mem_leak_frames: u32 = b.option(u32, "mem-leak-frames", "How many stack frames to print when a memory leak occurs. Tests get 2x this amount.") orelse blk: {
|
||||
if (strip == true) break :blk @as(u32, 0);
|
||||
if (optimize != .debug) break :blk 0;
|
||||
break :blk 4;
|
||||
if (strip == true) break :blk 0;
|
||||
if (is_debug) break :blk 4;
|
||||
break :blk 0;
|
||||
};
|
||||
|
||||
const exe = addCompilerStep(b, .{
|
||||
@@ -255,9 +259,15 @@ pub fn build(b: *std.Build) !void {
|
||||
exe.root_module.link_libc = true;
|
||||
}
|
||||
|
||||
const is_debug = optimize == .debug;
|
||||
const enable_debug_extensions = b.option(bool, "debug-extensions", "Enable commands and options useful for debugging the compiler") orelse is_debug;
|
||||
const enable_logging = b.option(bool, "log", "Enable debug logging with --debug-log") orelse is_debug;
|
||||
const log_level: std.log.Level = b.option(std.log.Level, "log", "Enable logs of the given or higher severity. Passing 'debug' still requires passing '--debug-log' to actually see any debug logs.") orelse switch (enable_debug_extensions) {
|
||||
true => .debug,
|
||||
false => switch (optimize) {
|
||||
.debug => .debug,
|
||||
.safe, .fast => .info,
|
||||
.small => .err,
|
||||
},
|
||||
};
|
||||
|
||||
const opt_version_string = b.option([]const u8, "version-string", "Override Zig version string. Default is to find out with git.");
|
||||
const version_slice = if (opt_version_string) |version| version else v: {
|
||||
@@ -398,7 +408,7 @@ pub fn build(b: *std.Build) !void {
|
||||
exe_options.addOption(std.SemanticVersion, "semver", semver);
|
||||
|
||||
exe_options.addOption(bool, "enable_debug_extensions", enable_debug_extensions);
|
||||
exe_options.addOption(bool, "enable_logging", enable_logging);
|
||||
exe_options.addOption(std.log.Level, "log_level", log_level);
|
||||
exe_options.addOption(bool, "enable_tracy", tracy != null);
|
||||
exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack);
|
||||
exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation);
|
||||
@@ -837,7 +847,7 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
|
||||
exe_options.addOption([:0]const u8, "version", version);
|
||||
exe_options.addOption(std.SemanticVersion, "semver", semver);
|
||||
exe_options.addOption(bool, "enable_debug_extensions", false);
|
||||
exe_options.addOption(bool, "enable_logging", false);
|
||||
exe_options.addOption(std.log.Level, "log_level", .err);
|
||||
exe_options.addOption(bool, "enable_tracy", false);
|
||||
exe_options.addOption(bool, "enable_tracy_callstack", false);
|
||||
exe_options.addOption(bool, "enable_tracy_allocation", false);
|
||||
|
||||
@@ -509,14 +509,10 @@ pub fn main(init: process.Init.Minimal) !void {
|
||||
} else if (mem.eql(u8, arg, "--libc-runtimes") or mem.eql(u8, arg, "--glibc-runtimes")) {
|
||||
// --glibc-runtimes was the old name of the flag; kept for compatibility for now.
|
||||
graph.libc_runtimes_dir = nextArgOrFatal(args, &arg_i);
|
||||
} else if (mem.eql(u8, arg, "--verbose-air")) {
|
||||
graph.verbose_air = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-cc")) {
|
||||
graph.verbose_cc = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-link")) {
|
||||
graph.verbose_link = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
|
||||
graph.verbose_llvm_ir = true;
|
||||
} else if (mem.eql(u8, arg, "--watch")) {
|
||||
watch_flag = true;
|
||||
} else if (mem.eql(u8, arg, "--time-report")) {
|
||||
|
||||
@@ -32,11 +32,8 @@ debug_compile_errors: bool = false,
|
||||
debug_incremental: bool = false,
|
||||
fuzzing: bool = false,
|
||||
verbose: bool = false,
|
||||
verbose_air: bool = false,
|
||||
verbose_cc: bool = false,
|
||||
verbose_link: bool = false,
|
||||
verbose_llvm_cpu_features: bool = false,
|
||||
verbose_llvm_ir: bool = false,
|
||||
libc_file: ?[]const u8 = null,
|
||||
/// What does this do? Nobody bothered to document it, and I think it's a
|
||||
/// smelly option. So unless somebody deletes these passive aggressive comments
|
||||
|
||||
@@ -351,6 +351,8 @@ const general_usage =
|
||||
\\ preferred optimization mode: fast, safe, small
|
||||
\\
|
||||
\\ --verbose Print commands before executing them
|
||||
\\ --verbose-cc Print C compiler commands before executing them
|
||||
\\ --verbose-link Print linker commands before executing them
|
||||
\\ --color [auto|off|on] Enable or disable colored error messages
|
||||
\\ --error-style [style] Control how build errors are printed
|
||||
\\ verbose (Default) Report errors with full context
|
||||
@@ -417,11 +419,5 @@ const general_usage =
|
||||
\\ none (default) No build ID
|
||||
\\ --debug-log [scope] Enable debugging the compiler
|
||||
\\ --debug-pkg-config Fail if unknown pkg-config flags encountered
|
||||
\\ --verbose-link Enable compiler debug output for linking
|
||||
\\ --verbose-air Enable compiler debug output for Zig AIR
|
||||
\\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
|
||||
\\ --verbose-cimport Enable compiler debug output for C imports
|
||||
\\ --verbose-cc Enable compiler debug output for C compilation
|
||||
\\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features
|
||||
\\
|
||||
;
|
||||
@@ -608,11 +608,8 @@ fn lowerZigArgs(
|
||||
|
||||
try addBool(gpa, zig_args, "--debug-compile-errors", graph.debug_compile_errors);
|
||||
try addBool(gpa, zig_args, "--debug-incremental", graph.debug_incremental);
|
||||
try addBool(gpa, zig_args, "--verbose-air", graph.verbose_air);
|
||||
try addBool(gpa, zig_args, "--verbose-llvm-ir", graph.verbose_llvm_ir);
|
||||
try addBool(gpa, zig_args, "--verbose-link", graph.verbose_link or conf_comp.flags.verbose_link);
|
||||
try addBool(gpa, zig_args, "--verbose-cc", graph.verbose_cc or conf_comp.flags.verbose_cc);
|
||||
try addBool(gpa, zig_args, "--verbose-llvm-cpu-features", graph.verbose_llvm_cpu_features);
|
||||
try addBool(gpa, zig_args, "--verbose-link", graph.verbose_link or conf_comp.flags.verbose_link);
|
||||
try addBool(gpa, zig_args, "--time-report", graph.time_report);
|
||||
|
||||
if (conf_comp.generated_bin.value == null) try zig_args.append(gpa, "-fno-emit-bin");
|
||||
|
||||
Vendored
+1
-1
@@ -927,7 +927,7 @@ pub fn parseArgs(
|
||||
break :debug switch (d.comp.target.ofmt) {
|
||||
.elf, .macho, .wasm => .{ .dwarf = .@"32" },
|
||||
.coff => .code_view,
|
||||
.c => switch (d.comp.target.os.tag) {
|
||||
.c, .llvmbc, .llvmir => switch (d.comp.target.os.tag) {
|
||||
.windows, .uefi => .code_view,
|
||||
else => .{ .dwarf = .@"32" },
|
||||
},
|
||||
|
||||
@@ -2519,6 +2519,8 @@ pub const TargetQuery = struct {
|
||||
coff,
|
||||
elf,
|
||||
hex,
|
||||
llvmbc,
|
||||
llvmir,
|
||||
macho,
|
||||
plan9,
|
||||
raw,
|
||||
|
||||
@@ -1043,6 +1043,10 @@ pub const ObjectFormat = enum {
|
||||
elf,
|
||||
/// The Intel HEX format for storing binary code in ASCII text.
|
||||
hex,
|
||||
/// LLVM binary intermediate representation.
|
||||
llvmbc,
|
||||
/// LLVM text intermediate representation.
|
||||
llvmir,
|
||||
/// The Mach object format used by macOS and other Apple platforms.
|
||||
macho,
|
||||
/// The a.out format used by Plan 9 from Bell Labs.
|
||||
@@ -1060,6 +1064,8 @@ pub const ObjectFormat = enum {
|
||||
.coff => ".obj",
|
||||
.elf, .macho, .wasm => ".o",
|
||||
.hex => ".ihex",
|
||||
.llvmbc => ".bc",
|
||||
.llvmir => ".ll",
|
||||
.plan9 => arch.plan9Ext(),
|
||||
.raw => ".bin",
|
||||
.spirv => ".spv",
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@ pub fn TargetInfo(os: std.Target.Os.Tag, arch: std.Target.Cpu.Arch) type {
|
||||
},
|
||||
.macho => @import("debug/SelfInfo/MachO.zig"),
|
||||
.plan9, .spirv, .wasm, .raw, .hex => void,
|
||||
.c => unreachable,
|
||||
.c, .llvmbc, .llvmir => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+7
-1
@@ -285,7 +285,13 @@ pub fn Alt(
|
||||
pub fn alt(
|
||||
context: anytype,
|
||||
comptime func_name: @EnumLiteral(),
|
||||
) Alt(@TypeOf(context), @field(@TypeOf(context), @tagName(func_name))) {
|
||||
) Alt(@TypeOf(context), @field(switch (@typeInfo(@TypeOf(context))) {
|
||||
else => @TypeOf(context),
|
||||
.pointer => |pointer| switch (pointer.size) {
|
||||
else => @TypeOf(context),
|
||||
.one => pointer.child,
|
||||
},
|
||||
}, @tagName(func_name))) {
|
||||
return .{ .data = context };
|
||||
}
|
||||
|
||||
|
||||
@@ -218,6 +218,8 @@ pub fn binNameAlloc(allocator: Allocator, options: BinNameOptions) error{OutOfMe
|
||||
},
|
||||
.Obj => return std.fmt.allocPrint(allocator, "{s}.o", .{root_name}),
|
||||
},
|
||||
.llvmbc => return std.fmt.allocPrint(allocator, "{s}.bc", .{root_name}),
|
||||
.llvmir => return std.fmt.allocPrint(allocator, "{s}.ll", .{root_name}),
|
||||
.macho => switch (options.output_mode) {
|
||||
.Exe => return allocator.dupe(u8, root_name),
|
||||
.Lib => {
|
||||
|
||||
@@ -10855,11 +10855,22 @@ pub fn resolveAlignmentForwardReference(b: *Builder, fwd_ref: Alignment.Lazy, va
|
||||
b.alignment_forward_references.items[index] = value;
|
||||
}
|
||||
|
||||
pub fn dump(b: *Builder, io: Io) void {
|
||||
var buffer: [4000]u8 = undefined;
|
||||
const stderr: Io.File = .stderr();
|
||||
b.printToFile(io, stderr, &buffer) catch {};
|
||||
}
|
||||
pub const Print = struct {
|
||||
name: []const u8,
|
||||
builder: *Builder,
|
||||
err: ?Allocator.Error,
|
||||
|
||||
pub fn format(p: *Print, w: *Writer) Writer.Error!void {
|
||||
try w.print("{q}", .{p.name});
|
||||
p.builder.print(w) catch |err| switch (err) {
|
||||
error.WriteFailed => |e| return e,
|
||||
error.OutOfMemory => |e| {
|
||||
p.err = e;
|
||||
return error.WriteFailed;
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn printToFilePath(b: *Builder, io: Io, dir: Io.Dir, path: []const u8) !void {
|
||||
var buffer: [4000]u8 = undefined;
|
||||
|
||||
+5
-5
@@ -13,10 +13,10 @@ const InternPool = @import("InternPool.zig");
|
||||
const Type = @import("Type.zig");
|
||||
const Value = @import("Value.zig");
|
||||
const Zcu = @import("Zcu.zig");
|
||||
const print = @import("Air/print.zig");
|
||||
|
||||
pub const Legalize = @import("Air/Legalize.zig");
|
||||
pub const Liveness = @import("Air/Liveness.zig");
|
||||
pub const Print = @import("Air/Print.zig");
|
||||
pub const Verify = @import("Air/Verify.zig");
|
||||
|
||||
instructions: std.MultiArrayList(Inst).Slice,
|
||||
@@ -2517,10 +2517,10 @@ pub fn unwrapShuffleTwo(air: *const Air, zcu: *const Zcu, inst_index: Inst.Index
|
||||
}
|
||||
|
||||
pub const legalize = Legalize.legalize;
|
||||
pub const write = print.write;
|
||||
pub const writeInst = print.writeInst;
|
||||
pub const dump = print.dump;
|
||||
pub const dumpInst = print.dumpInst;
|
||||
pub const write = Print.write;
|
||||
pub const writeInst = Print.writeInst;
|
||||
pub const dump = Print.dump;
|
||||
pub const dumpInst = Print.dumpInst;
|
||||
|
||||
pub const CoveragePoint = enum(u1) {
|
||||
/// Indicates the block is not a place of interest corresponding to
|
||||
|
||||
@@ -8,9 +8,20 @@ const Value = @import("../Value.zig");
|
||||
const Type = @import("../Type.zig");
|
||||
const Air = @import("../Air.zig");
|
||||
const InternPool = @import("../InternPool.zig");
|
||||
const Printer = @This();
|
||||
|
||||
zcu: *Zcu,
|
||||
fqn: InternPool.NullTerminatedString,
|
||||
air: *const Air,
|
||||
liveness: *const ?Air.Liveness,
|
||||
|
||||
pub fn format(p: *const Printer, w: *std.Io.Writer) std.Io.Writer.Error!void {
|
||||
try w.print("{qf}:\n", .{p.fqn.fmt(&p.zcu.intern_pool)});
|
||||
try p.air.write(w, p.zcu, p.liveness.*);
|
||||
}
|
||||
|
||||
pub fn write(air: Air, stream: *std.Io.Writer, zcu: *Zcu, liveness: ?Air.Liveness) !void {
|
||||
comptime assert(build_options.enable_debug_extensions);
|
||||
comptime assert(build_options.log_level == .debug);
|
||||
const instruction_bytes = air.instructions.len *
|
||||
// Here we don't use @sizeOf(Air.Inst.Data) because it would include
|
||||
// the debug safety tag but we want to measure release size.
|
||||
@@ -60,7 +71,7 @@ pub fn writeInst(
|
||||
zcu: *Zcu,
|
||||
liveness: ?Air.Liveness,
|
||||
) void {
|
||||
comptime assert(build_options.enable_debug_extensions);
|
||||
comptime assert(build_options.log_level == .debug);
|
||||
var writer: Writer = .{
|
||||
.zcu = zcu,
|
||||
.gpa = zcu.comp.gpa,
|
||||
+28
-84
@@ -20,6 +20,7 @@ const link = @import("link.zig");
|
||||
const tracy = @import("tracy.zig");
|
||||
const trace = tracy.trace;
|
||||
const build_options = @import("build_options");
|
||||
const debugLogScopeEnabled = @import("main.zig").debugLogScopeEnabled;
|
||||
const LibCInstallation = std.zig.LibCInstallation;
|
||||
const glibc = @import("libs/glibc.zig");
|
||||
const musl = @import("libs/musl.zig");
|
||||
@@ -161,12 +162,6 @@ clang_passthrough_mode: bool,
|
||||
clang_preprocessor_mode: ClangPreprocessorMode,
|
||||
/// Whether to print clang argvs to stdout.
|
||||
verbose_cc: bool,
|
||||
verbose_air: bool,
|
||||
verbose_intern_pool: bool,
|
||||
verbose_generic_instances: bool,
|
||||
verbose_llvm_ir: ?[]const u8,
|
||||
verbose_llvm_bc: ?[]const u8,
|
||||
verbose_llvm_cpu_features: bool,
|
||||
verbose_link: bool,
|
||||
link_depfile: ?[]const u8,
|
||||
disable_c_depfile: bool,
|
||||
@@ -1544,13 +1539,7 @@ pub const CreateOptions = struct {
|
||||
clang_passthrough_mode: bool = false,
|
||||
verbose_cc: bool = false,
|
||||
verbose_link: bool = false,
|
||||
verbose_air: bool = false,
|
||||
verbose_intern_pool: bool = false,
|
||||
verbose_generic_instances: bool = false,
|
||||
verbose_llvm_ir: ?[]const u8 = null,
|
||||
verbose_llvm_bc: ?[]const u8 = null,
|
||||
link_depfile: ?[]const u8 = null,
|
||||
verbose_llvm_cpu_features: bool = false,
|
||||
debug_compiler_runtime_libs: ?std.lang.Optimize = null,
|
||||
debug_compile_errors: bool = false,
|
||||
debug_incremental: bool = false,
|
||||
@@ -1932,21 +1921,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
|
||||
try options.root_mod.deps.putNoClobber(arena, "zigc", zigc_mod);
|
||||
}
|
||||
|
||||
if (options.verbose_llvm_cpu_features) {
|
||||
if (options.root_mod.resolved_target.llvm_cpu_features) |cf| {
|
||||
const stderr = try io.lockStderr(&.{}, null);
|
||||
defer io.unlockStderr();
|
||||
const w = &stderr.file_writer.interface;
|
||||
printVerboseLlvmCpuFeatures(w, arena, options.root_name, target, cf) catch |err| switch (err) {
|
||||
error.WriteFailed => switch (stderr.file_writer.err.?) {
|
||||
error.Canceled => |e| return e,
|
||||
else => {},
|
||||
},
|
||||
error.OutOfMemory => |e| return e,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1);
|
||||
const main_mod = options.main_mod orelse options.root_mod;
|
||||
|
||||
@@ -2111,14 +2085,8 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
|
||||
.clang_passthrough_mode = options.clang_passthrough_mode,
|
||||
.clang_preprocessor_mode = options.clang_preprocessor_mode,
|
||||
.verbose_cc = options.verbose_cc,
|
||||
.verbose_air = options.verbose_air,
|
||||
.verbose_intern_pool = options.verbose_intern_pool,
|
||||
.verbose_generic_instances = options.verbose_generic_instances,
|
||||
.verbose_llvm_ir = options.verbose_llvm_ir,
|
||||
.verbose_llvm_bc = options.verbose_llvm_bc,
|
||||
.link_depfile = options.link_depfile,
|
||||
.verbose_llvm_cpu_features = options.verbose_llvm_cpu_features,
|
||||
.verbose_link = options.verbose_link,
|
||||
.link_depfile = options.link_depfile,
|
||||
.disable_c_depfile = options.disable_c_depfile,
|
||||
.reference_trace = options.reference_trace,
|
||||
.time_report = if (options.time_report) .init else null,
|
||||
@@ -2353,8 +2321,9 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
|
||||
comp.emit_asm != null or
|
||||
comp.emit_llvm_ir != null or
|
||||
comp.emit_llvm_bc != null or
|
||||
comp.verbose_llvm_ir != null or
|
||||
comp.verbose_llvm_bc != null))
|
||||
log_llvm_ir: {
|
||||
break :log_llvm_ir debugLogScopeEnabled("llvm-ir") or debugLogScopeEnabled("opt-llvm-ir");
|
||||
}))
|
||||
{
|
||||
if (opt_zcu) |zcu| {
|
||||
dev.check(.llvm_backend);
|
||||
@@ -2566,19 +2535,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
|
||||
return comp;
|
||||
}
|
||||
|
||||
fn printVerboseLlvmCpuFeatures(
|
||||
w: *Writer,
|
||||
arena: Allocator,
|
||||
root_name: []const u8,
|
||||
target: *const std.Target,
|
||||
cf: [*:0]const u8,
|
||||
) (Writer.Error || Allocator.Error)!void {
|
||||
try w.print("compilation: {s}\n", .{root_name});
|
||||
try w.print(" target: {s}\n", .{try target.zigTriple(arena)});
|
||||
try w.print(" cpu: {s}\n", .{target.cpu.model.name});
|
||||
try w.print(" features: {s}\n", .{cf});
|
||||
}
|
||||
|
||||
pub fn destroy(comp: *Compilation) void {
|
||||
const gpa = comp.gpa;
|
||||
const io = comp.io;
|
||||
@@ -2991,14 +2947,19 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
|
||||
try pt.processExports();
|
||||
}
|
||||
|
||||
if (build_options.enable_debug_extensions and comp.verbose_intern_pool) {
|
||||
std.debug.print("intern pool stats for {q}:\n", .{comp.root_name});
|
||||
zcu.intern_pool.dump();
|
||||
}
|
||||
|
||||
if (build_options.enable_debug_extensions and comp.verbose_generic_instances) {
|
||||
std.debug.print("generic instances for '{s}:0x{x}':\n", .{ comp.root_name, @intFromPtr(zcu) });
|
||||
zcu.intern_pool.dumpGenericInstances(gpa);
|
||||
{
|
||||
var d: InternPool.Dump = .{
|
||||
.name = comp.root_name,
|
||||
.arena = arena,
|
||||
.ip = &zcu.intern_pool,
|
||||
.err = null,
|
||||
};
|
||||
std.log.scoped(.@"ip-stats").debug("{f}", .{&d});
|
||||
if (d.err) |err| return err;
|
||||
std.log.scoped(.@"ip-values").debug("{f}", .{std.fmt.alt(&d, .formatAll)});
|
||||
if (d.err) |err| return err;
|
||||
std.log.scoped(.@"ip-generic-instances").debug("{f}", .{std.fmt.alt(&d, .formatGenericInstances)});
|
||||
if (d.err) |err| return err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3220,28 +3181,29 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error
|
||||
comp.time_report.?.stats.real_ns_llvm_emit = ns;
|
||||
};
|
||||
|
||||
const zcu_obj_path: ?Cache.Path = if (comp.bin_file != null) p: {
|
||||
break :p try comp.resolveEmitPathFlush(arena, .temp, llvm_object.out_bin_basename);
|
||||
} else null;
|
||||
const zcu_obj_path: ?Cache.Path = switch (comp.getTarget().ofmt) {
|
||||
.llvmbc, .llvmir => null,
|
||||
else => if (comp.bin_file != null)
|
||||
try comp.resolveEmitPathFlush(arena, .temp, llvm_object.out_bin_basename)
|
||||
else
|
||||
null,
|
||||
};
|
||||
|
||||
const active = zcu.activate(tid);
|
||||
defer active.deactivate();
|
||||
llvm_object.emit(active.pt, .{
|
||||
.pre_ir_path = comp.verbose_llvm_ir,
|
||||
.pre_bc_path = comp.verbose_llvm_bc,
|
||||
|
||||
.bin_path = if (zcu_obj_path) |p| try p.toStringZ(arena) else null,
|
||||
.asm_path = p: {
|
||||
const raw = comp.emit_asm orelse break :p null;
|
||||
const p = try comp.resolveEmitPathFlush(arena, .artifact, raw);
|
||||
break :p try p.toStringZ(arena);
|
||||
},
|
||||
.post_ir_path = p: {
|
||||
.opt_ir_path = p: {
|
||||
const raw = comp.emit_llvm_ir orelse break :p null;
|
||||
const p = try comp.resolveEmitPathFlush(arena, .artifact, raw);
|
||||
break :p try p.toStringZ(arena);
|
||||
},
|
||||
.post_bc_path = p: {
|
||||
.opt_bc_path = p: {
|
||||
const raw = comp.emit_llvm_bc orelse break :p null;
|
||||
const p = try comp.resolveEmitPathFlush(arena, .artifact, raw);
|
||||
break :p try p.toStringZ(arena);
|
||||
@@ -3267,7 +3229,7 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error
|
||||
error.Canceled, error.OutOfMemory => |e| return e,
|
||||
error.AlreadyReported => return,
|
||||
};
|
||||
}
|
||||
} else return;
|
||||
}
|
||||
}
|
||||
if (comp.bin_file) |lf| {
|
||||
@@ -4903,12 +4865,6 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU
|
||||
.emit_bin = .yes_cache,
|
||||
.verbose_cc = comp.verbose_cc,
|
||||
.verbose_link = comp.verbose_link,
|
||||
.verbose_air = comp.verbose_air,
|
||||
.verbose_intern_pool = comp.verbose_intern_pool,
|
||||
.verbose_generic_instances = comp.verbose_intern_pool,
|
||||
.verbose_llvm_ir = comp.verbose_llvm_ir,
|
||||
.verbose_llvm_bc = comp.verbose_llvm_bc,
|
||||
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
|
||||
.environ_map = comp.environ_map,
|
||||
}) catch |err| switch (err) {
|
||||
error.CreateFail => {
|
||||
@@ -7415,12 +7371,6 @@ fn buildOutputFromZig(
|
||||
.data_sections = true,
|
||||
.verbose_cc = comp.verbose_cc,
|
||||
.verbose_link = comp.verbose_link,
|
||||
.verbose_air = comp.verbose_air,
|
||||
.verbose_intern_pool = comp.verbose_intern_pool,
|
||||
.verbose_generic_instances = comp.verbose_intern_pool,
|
||||
.verbose_llvm_ir = comp.verbose_llvm_ir,
|
||||
.verbose_llvm_bc = comp.verbose_llvm_bc,
|
||||
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
|
||||
.clang_passthrough_mode = comp.clang_passthrough_mode,
|
||||
.skip_linker_dependencies = true,
|
||||
.environ_map = comp.environ_map,
|
||||
@@ -7552,12 +7502,6 @@ pub fn build_crt_file(
|
||||
.c_source_files = c_source_files,
|
||||
.verbose_cc = comp.verbose_cc,
|
||||
.verbose_link = comp.verbose_link,
|
||||
.verbose_air = comp.verbose_air,
|
||||
.verbose_intern_pool = comp.verbose_intern_pool,
|
||||
.verbose_generic_instances = comp.verbose_generic_instances,
|
||||
.verbose_llvm_ir = comp.verbose_llvm_ir,
|
||||
.verbose_llvm_bc = comp.verbose_llvm_bc,
|
||||
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
|
||||
.clang_passthrough_mode = comp.clang_passthrough_mode,
|
||||
.skip_linker_dependencies = true,
|
||||
.environ_map = comp.environ_map,
|
||||
|
||||
@@ -190,7 +190,7 @@ pub fn resolve(options: Options) ResolveError!Config {
|
||||
// *If* the LLVM backend were to be selected, should Zig use the LLVM
|
||||
// library to build the LLVM module?
|
||||
const use_lib_llvm = b: {
|
||||
if (!build_options.have_llvm) {
|
||||
if (!build_options.have_llvm or target.ofmt == .llvmbc or target.ofmt == .llvmir) {
|
||||
if (options.use_lib_llvm == true) return error.LlvmLibraryUnavailable;
|
||||
break :b false;
|
||||
}
|
||||
@@ -324,7 +324,7 @@ pub fn resolve(options: Options) ResolveError!Config {
|
||||
if (!options.have_zcu) break :b false;
|
||||
|
||||
// If emitting to LLVM bitcode object format, must use LLVM backend.
|
||||
if (options.emit_llvm_ir or options.emit_llvm_bc) {
|
||||
if (target.ofmt == .llvmbc or target.ofmt == .llvmir or options.emit_llvm_bc or options.emit_llvm_ir) {
|
||||
if (options.use_llvm == false)
|
||||
return error.EmittingLlvmModuleRequiresLlvmBackend;
|
||||
if (!target_util.hasLlvmSupport(target, target.ofmt))
|
||||
@@ -379,7 +379,7 @@ pub fn resolve(options: Options) ResolveError!Config {
|
||||
const backend = target_util.zigBackend(target, use_llvm);
|
||||
|
||||
if (options.emit_bin and options.have_zcu) {
|
||||
if (!use_lib_llvm and use_llvm) {
|
||||
if (target.ofmt != .llvmbc and target.ofmt != .llvmir and !use_lib_llvm and use_llvm) {
|
||||
// Explicit request to use LLVM to produce an object file, but without
|
||||
// using LLVM libraries. Impossible.
|
||||
return error.EmittingBinaryRequiresLlvmLibrary;
|
||||
@@ -513,7 +513,7 @@ pub fn resolve(options: Options) ResolveError!Config {
|
||||
break :b switch (target.ofmt) {
|
||||
.elf, .macho, .wasm => .{ .dwarf = .@"32" },
|
||||
.coff => .code_view,
|
||||
.c => switch (target.os.tag) {
|
||||
.c, .llvmbc, .llvmir => switch (target.os.tag) {
|
||||
.windows, .uefi => .code_view,
|
||||
else => .{ .dwarf = .@"32" },
|
||||
},
|
||||
|
||||
+33
-25
@@ -10591,17 +10591,36 @@ pub fn errorUnionPayload(ip: *const InternPool, ty: Index) Index {
|
||||
return ip.indexToKey(ty).error_union_type.payload_type;
|
||||
}
|
||||
|
||||
pub fn dump(ip: *const InternPool) void {
|
||||
var buffer: [4096]u8 = undefined;
|
||||
const stderr = std.debug.lockStderr(&buffer);
|
||||
defer std.debug.unlockStderr();
|
||||
const w = &stderr.file_writer.interface;
|
||||
dumpDependencyStatsFallible(ip, w) catch return;
|
||||
dumpStatsFallible(ip, w, std.heap.page_allocator) catch return;
|
||||
dumpAllFallible(ip, w) catch return;
|
||||
}
|
||||
pub const Dump = struct {
|
||||
name: []const u8,
|
||||
arena: std.mem.Allocator,
|
||||
ip: *const InternPool,
|
||||
err: ?Allocator.Error,
|
||||
|
||||
fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void {
|
||||
pub fn format(d: *Dump, w: *Io.Writer) Io.Writer.Error!void {
|
||||
try w.print("{q}:\n", .{d.name});
|
||||
try d.ip.dumpDependencyStatsFallible(w);
|
||||
d.ip.dumpStatsFallible(d.arena, w) catch |err| switch (err) {
|
||||
error.WriteFailed => |e| return e,
|
||||
error.OutOfMemory => |e| {
|
||||
d.err = e;
|
||||
return error.WriteFailed;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn formatAll(d: *Dump, w: *Io.Writer) Io.Writer.Error!void {
|
||||
try w.print("{q}:\n", .{d.name});
|
||||
try d.ip.dumpAllFallible(w);
|
||||
}
|
||||
|
||||
pub fn formatGenericInstances(d: *Dump, w: *Io.Writer) Io.Writer.Error!void {
|
||||
try w.print("{q}:\n", .{d.name});
|
||||
d.ip.dumpGenericInstancesFallible(d.arena, w) catch return;
|
||||
}
|
||||
};
|
||||
|
||||
fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) Io.Writer.Error!void {
|
||||
const dep_entries_len = ip.dep_entries.items.len - ip.free_dep_entries.items.len;
|
||||
const src_hash_deps_len = ip.src_hash_deps.count();
|
||||
const nav_val_deps_len = ip.nav_val_deps.count();
|
||||
@@ -10668,7 +10687,7 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void {
|
||||
});
|
||||
}
|
||||
|
||||
fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !void {
|
||||
fn dumpStatsFallible(ip: *const InternPool, arena: Allocator, w: *Io.Writer) (Allocator.Error || Io.Writer.Error)!void {
|
||||
var items_len: usize = 0;
|
||||
var extra_len: usize = 0;
|
||||
var limbs_len: usize = 0;
|
||||
@@ -10968,7 +10987,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo
|
||||
}
|
||||
}
|
||||
|
||||
fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void {
|
||||
fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) Io.Writer.Error!void {
|
||||
for (ip.locals, 0..) |*local, tid| {
|
||||
// Early check for length 0, because `view()` is invalid if capacity is 0
|
||||
if (local.mutate.items.len == 0) continue;
|
||||
@@ -11071,21 +11090,10 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dumpGenericInstances(ip: *const InternPool, allocator: Allocator) void {
|
||||
var buffer: [4096]u8 = undefined;
|
||||
const stderr = std.debug.lockStderr(&buffer);
|
||||
defer std.debug.unlockStderr();
|
||||
const w = &stderr.file_writer.interface;
|
||||
ip.dumpGenericInstancesFallible(allocator, w) catch return;
|
||||
}
|
||||
|
||||
pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator, w: *Io.Writer) !void {
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(allocator);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
pub fn dumpGenericInstancesFallible(ip: *const InternPool, arena: Allocator, w: *Io.Writer) !void {
|
||||
var instances: std.array_hash_map.Auto(Index, std.ArrayList(Index)) = .empty;
|
||||
for (ip.locals, 0..) |*local, tid| {
|
||||
if (local.mutate.items.len == 0) continue;
|
||||
const items = local.shared.items.view().slice();
|
||||
const extra_list = local.shared.extra;
|
||||
for (
|
||||
|
||||
+9
-12
@@ -26,6 +26,7 @@ fully_qualified_name: []const u8,
|
||||
deps: Deps = .{},
|
||||
|
||||
resolved_target: ResolvedTarget,
|
||||
llvm_cpu_features: ?[:0]const u8,
|
||||
optimize_mode: std.lang.Optimize,
|
||||
code_model: std.lang.CodeModel,
|
||||
single_threaded: bool,
|
||||
@@ -94,7 +95,6 @@ pub const ResolvedTarget = struct {
|
||||
is_native_os: bool,
|
||||
is_native_abi: bool,
|
||||
is_explicit_dynamic_linker: bool,
|
||||
llvm_cpu_features: ?[*:0]const u8 = null,
|
||||
};
|
||||
|
||||
pub const CreateError = error{
|
||||
@@ -362,15 +362,13 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
|
||||
break :b 0;
|
||||
};
|
||||
|
||||
const llvm_cpu_features: ?[*:0]const u8 = b: {
|
||||
if (resolved_target.llvm_cpu_features) |x| break :b x;
|
||||
const llvm_cpu_features: ?[:0]const u8 = b: {
|
||||
if (!options.global.use_llvm) break :b null;
|
||||
|
||||
var buf = std.array_list.Managed(u8).init(arena);
|
||||
var disabled_features = std.array_list.Managed(u8).init(arena);
|
||||
defer disabled_features.deinit();
|
||||
if (options.inherited.resolved_target == null) break :b options.parent.?.llvm_cpu_features;
|
||||
|
||||
// Append disabled features after enabled ones, so that their effects aren't overwritten.
|
||||
var buf = std.array_list.Managed(u8).init(arena);
|
||||
var disabled_features = std.array_list.Managed(u8).init(arena);
|
||||
for (target.cpu.arch.allFeaturesList()) |feature| {
|
||||
if (feature.llvm_name) |llvm_name| {
|
||||
// Ignore these until we figure out how to handle the concept of omitting features.
|
||||
@@ -401,10 +399,9 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
|
||||
|
||||
try buf.appendSlice(disabled_features.items);
|
||||
if (buf.items.len == 0) break :b "";
|
||||
assert(std.mem.endsWith(u8, buf.items, ","));
|
||||
assert(buf.items[buf.items.len - 1] == ',');
|
||||
buf.items[buf.items.len - 1] = 0;
|
||||
buf.shrinkAndFree(buf.items.len);
|
||||
break :b buf.items[0 .. buf.items.len - 1 :0].ptr;
|
||||
break :b buf.items[0 .. buf.items.len - 1 :0];
|
||||
};
|
||||
|
||||
const mod = try arena.create(Module);
|
||||
@@ -417,8 +414,8 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module {
|
||||
.is_native_os = resolved_target.is_native_os,
|
||||
.is_native_abi = resolved_target.is_native_abi,
|
||||
.is_explicit_dynamic_linker = resolved_target.is_explicit_dynamic_linker,
|
||||
.llvm_cpu_features = llvm_cpu_features,
|
||||
},
|
||||
.llvm_cpu_features = llvm_cpu_features,
|
||||
.optimize_mode = optimize_mode,
|
||||
.single_threaded = single_threaded,
|
||||
.error_tracing = error_tracing,
|
||||
@@ -494,8 +491,8 @@ pub fn createBuiltin(arena: Allocator, opts: Builtin, dirs: std.zig.Directories)
|
||||
.is_native_os = false,
|
||||
.is_native_abi = false,
|
||||
.is_explicit_dynamic_linker = false,
|
||||
.llvm_cpu_features = null,
|
||||
},
|
||||
.llvm_cpu_features = null,
|
||||
.optimize_mode = opts.optimize_mode,
|
||||
.single_threaded = opts.single_threaded,
|
||||
.error_tracing = opts.error_tracing,
|
||||
|
||||
+3
-5
@@ -1126,6 +1126,8 @@ fn analyzeBodyInner(
|
||||
crash_info.push(sema, block, body);
|
||||
defer crash_info.pop();
|
||||
|
||||
const path = zcu.namespacePtr(block.namespace).fileScope(zcu).path;
|
||||
|
||||
// We use a while (true) loop here to avoid a redundant way of breaking out of
|
||||
// the loop. The only way to break out of the loop is with a `noreturn`
|
||||
// instruction.
|
||||
@@ -1134,11 +1136,7 @@ fn analyzeBodyInner(
|
||||
crash_info.setBodyIndex(i);
|
||||
const inst = body[i];
|
||||
|
||||
// This log is a bit expensive, and LLVM fails to optimize it away.
|
||||
if (build_options.enable_logging) {
|
||||
const path = zcu.namespacePtr(block.namespace).fileScope(zcu).path;
|
||||
std.log.scoped(.sema_zir).debug("sema ZIR {f} %{d}", .{ path.fmt(comp), inst });
|
||||
}
|
||||
std.log.scoped(.sema_zir).debug("sema ZIR {f} %{d}", .{ path.fmt(comp), inst });
|
||||
|
||||
const air_ref: Air.Inst.Ref = inst: switch (tags[@backingInt(inst)]) {
|
||||
// zig fmt: off
|
||||
|
||||
+22
-40
@@ -25,6 +25,7 @@ const InternPool = @import("../InternPool.zig");
|
||||
const AnalUnit = InternPool.AnalUnit;
|
||||
const Module = @import("../Module.zig");
|
||||
const Sema = @import("../Sema.zig");
|
||||
const debugLogScopeEnabled = @import("../main.zig").debugLogScopeEnabled;
|
||||
const target_util = @import("../target.zig");
|
||||
const tracy = @import("../tracy.zig");
|
||||
const trace = tracy.trace;
|
||||
@@ -2303,10 +2304,9 @@ fn analyzeFuncBody(
|
||||
|
||||
const comp = zcu.comp;
|
||||
|
||||
const dump_air = build_options.enable_debug_extensions and comp.verbose_air;
|
||||
const dump_llvm_ir = build_options.enable_debug_extensions and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null);
|
||||
|
||||
if (comp.bin_file != null or zcu.llvm_object != null or dump_air or dump_llvm_ir) {
|
||||
if (comp.bin_file != null or zcu.llvm_object != null or log_air: {
|
||||
break :log_air debugLogScopeEnabled("illegal-air") or debugLogScopeEnabled("legal-air") or debugLogScopeEnabled("air");
|
||||
}) {
|
||||
zcu.codegen_prog_node.increaseEstimatedTotalItems(1);
|
||||
comp.link_prog_node.increaseEstimatedTotalItems(1);
|
||||
|
||||
@@ -4522,32 +4522,28 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
|
||||
tracy_trace.addText(fqn.toSlice(ip));
|
||||
tracy_trace.addTextFmt("func_ip_index={d}", .{func_index});
|
||||
|
||||
Air.Verify.run(pt, func_index, air);
|
||||
|
||||
if (codegen.legalizeFeatures(pt, nav)) |features| {
|
||||
try air.legalize(pt, features);
|
||||
// Verify the AIR again post-legalization.
|
||||
Air.Verify.run(pt, func_index, air);
|
||||
}
|
||||
|
||||
var liveness: ?Air.Liveness = if (codegen.wantsLiveness(pt, nav))
|
||||
try .analyze(zcu, air.*, ip)
|
||||
else
|
||||
null;
|
||||
var liveness: ?Air.Liveness = null;
|
||||
defer if (liveness) |*l| l.deinit(gpa);
|
||||
|
||||
if (build_options.enable_debug_extensions and comp.verbose_air) p: {
|
||||
const io = comp.io;
|
||||
const stderr = try io.lockStderr(&.{}, null);
|
||||
defer io.unlockStderr();
|
||||
printVerboseAir(pt, liveness, fqn, air, &stderr.file_writer.interface) catch |err| switch (err) {
|
||||
error.WriteFailed => switch (stderr.file_writer.err.?) {
|
||||
error.Canceled => |e| return e,
|
||||
else => break :p,
|
||||
},
|
||||
};
|
||||
const ap: Air.Print = .{
|
||||
.zcu = zcu,
|
||||
.fqn = fqn,
|
||||
.air = air,
|
||||
.liveness = &liveness,
|
||||
};
|
||||
std.log.scoped(.@"illegal-air").debug("{f}", .{&ap});
|
||||
|
||||
if (codegen.legalizeFeatures(pt, nav)) |features| {
|
||||
// Verify the AIR again pre-legalization.
|
||||
Air.Verify.run(pt, func_index, air);
|
||||
try air.legalize(pt, features);
|
||||
}
|
||||
|
||||
std.log.scoped(.@"legal-air").debug("{f}", .{&ap});
|
||||
Air.Verify.run(pt, func_index, air);
|
||||
|
||||
if (codegen.wantsLiveness(pt, nav)) liveness = try .analyze(zcu, air.*, ip);
|
||||
std.log.scoped(.air).debug("{f}", .{&ap});
|
||||
if (std.debug.runtime_safety) verify_liveness: {
|
||||
var verify: Air.Liveness.Verify = .{
|
||||
.gpa = gpa,
|
||||
@@ -4577,17 +4573,3 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
|
||||
|
||||
return codegen.generateFunction(lf, pt, func_index, air, &liveness);
|
||||
}
|
||||
|
||||
fn printVerboseAir(
|
||||
pt: Zcu.PerThread,
|
||||
liveness: ?Air.Liveness,
|
||||
fqn: InternPool.NullTerminatedString,
|
||||
air: *const Air,
|
||||
w: *Io.Writer,
|
||||
) Io.Writer.Error!void {
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
try w.print("# Begin Function AIR: {f}:\n", .{fqn.fmt(ip)});
|
||||
try air.write(w, zcu, liveness);
|
||||
try w.print("# End Function AIR: {f}\n\n", .{fqn.fmt(ip)});
|
||||
}
|
||||
+66
-59
@@ -10,6 +10,7 @@ const build_options = @import("build_options");
|
||||
const Air = @import("../Air.zig");
|
||||
const codegen = @import("../codegen.zig");
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const debugLogScopeEnabled = @import("../main.zig").debugLogScopeEnabled;
|
||||
const InternPool = @import("../InternPool.zig");
|
||||
const link = @import("../link.zig");
|
||||
const Module = @import("../Module.zig");
|
||||
@@ -331,12 +332,10 @@ pub const Object = struct {
|
||||
}
|
||||
|
||||
pub const EmitOptions = struct {
|
||||
pre_ir_path: ?[]const u8,
|
||||
pre_bc_path: ?[]const u8,
|
||||
bin_path: ?[:0]const u8,
|
||||
asm_path: ?[:0]const u8,
|
||||
post_ir_path: ?[:0]const u8,
|
||||
post_bc_path: ?[:0]const u8,
|
||||
opt_ir_path: ?[:0]const u8,
|
||||
opt_bc_path: ?[:0]const u8,
|
||||
|
||||
is_debug: bool,
|
||||
is_small: bool,
|
||||
@@ -351,6 +350,7 @@ pub const Object = struct {
|
||||
const comp = zcu.comp;
|
||||
const io = comp.io;
|
||||
const diags = &comp.link_diags;
|
||||
const target = &comp.root_mod.resolved_target.result;
|
||||
|
||||
{
|
||||
if (o.errors_len_variable != .none) {
|
||||
@@ -403,7 +403,7 @@ pub const Object = struct {
|
||||
const behavior_max = try o.builder.metadataConstant(try o.builder.intConst(.i32, 7));
|
||||
const behavior_min = try o.builder.metadataConstant(try o.builder.intConst(.i32, 8));
|
||||
|
||||
if (target_util.llvmMachineAbi(&comp.root_mod.resolved_target.result)) |abi| {
|
||||
if (target_util.llvmMachineAbi(target)) |abi| {
|
||||
module_flags.appendAssumeCapacity(try o.builder.metadataTuple(&.{
|
||||
behavior_error,
|
||||
(try o.builder.metadataString("target-abi")).toMetadata(),
|
||||
@@ -411,7 +411,7 @@ pub const Object = struct {
|
||||
}));
|
||||
}
|
||||
|
||||
const pic_level = target_util.picLevel(&comp.root_mod.resolved_target.result);
|
||||
const pic_level = target_util.picLevel(target);
|
||||
if (comp.root_mod.pic) {
|
||||
module_flags.appendAssumeCapacity(try o.builder.metadataTuple(&.{
|
||||
behavior_min,
|
||||
@@ -434,7 +434,7 @@ pub const Object = struct {
|
||||
(try o.builder.metadataString("Code Model")).toMetadata(),
|
||||
try o.builder.metadataConstant(try o.builder.intConst(.i32, @as(
|
||||
i32,
|
||||
switch (codeModel(comp.root_mod.code_model, &comp.root_mod.resolved_target.result)) {
|
||||
switch (codeModel(comp.root_mod.code_model, target)) {
|
||||
.default => unreachable,
|
||||
.tiny => 0,
|
||||
.small => 1,
|
||||
@@ -480,7 +480,6 @@ pub const Object = struct {
|
||||
}
|
||||
}
|
||||
|
||||
const target = &comp.root_mod.resolved_target.result;
|
||||
if (target.os.tag == .windows and (target.cpu.arch == .x86_64 or target.cpu.arch == .x86)) {
|
||||
// Add the "RegCallv4" flag so that any functions using `x86_regcallcc` use regcall
|
||||
// v4, which is essentially a requirement on Windows. See corresponding logic in
|
||||
@@ -515,21 +514,26 @@ pub const Object = struct {
|
||||
|
||||
const emit_asm_msg = options.asm_path orelse "(none)";
|
||||
const emit_bin_msg = options.bin_path orelse "(none)";
|
||||
const post_llvm_ir_msg = options.post_ir_path orelse "(none)";
|
||||
const post_llvm_bc_msg = options.post_bc_path orelse "(none)";
|
||||
const opt_llvm_ir_msg = options.opt_ir_path orelse "(none)";
|
||||
const opt_llvm_bc_msg = options.opt_bc_path orelse "(none)";
|
||||
log.debug("emit LLVM object asm={s} bin={s} ir={s} bc={s}", .{
|
||||
emit_asm_msg, emit_bin_msg, post_llvm_ir_msg, post_llvm_bc_msg,
|
||||
emit_asm_msg, emit_bin_msg, opt_llvm_ir_msg, opt_llvm_bc_msg,
|
||||
});
|
||||
const log_opt_llvm_ir = debugLogScopeEnabled("opt-llvm-ir");
|
||||
|
||||
const context, const module = emit: {
|
||||
if (options.pre_ir_path) |path| {
|
||||
if (std.mem.eql(u8, path, "-")) {
|
||||
o.builder.dump(io);
|
||||
} else {
|
||||
o.builder.printToFilePath(io, Io.Dir.cwd(), path) catch |err| {
|
||||
log.err("failed printing LLVM module to \"{s}\": {t}", .{ path, err });
|
||||
};
|
||||
}
|
||||
{
|
||||
var p: Builder.Print = .{ .name = comp.root_name, .builder = &o.builder, .err = null };
|
||||
std.log.scoped(.@"llvm-ir").debug("{f}", .{&p});
|
||||
if (p.err) |err| return err;
|
||||
}
|
||||
|
||||
if (target.ofmt == .llvmir) {
|
||||
const path = comp.bin_file.?.emit;
|
||||
o.builder.printToFilePath(io, path.root_dir.handle, path.sub_path) catch |err| {
|
||||
return diags.fail("failed emitting LLVM module to {qf}: {t}", .{ path, err });
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
const bitcode = try o.builder.toBitcode(o.gpa, .{
|
||||
@@ -538,23 +542,26 @@ pub const Object = struct {
|
||||
});
|
||||
defer o.gpa.free(bitcode);
|
||||
|
||||
if (options.pre_bc_path) |path| {
|
||||
var file = Io.Dir.cwd().createFile(io, path, .{}) catch |err|
|
||||
return diags.fail("failed to create '{s}': {t}", .{ path, err });
|
||||
if (target.ofmt == .llvmbc) {
|
||||
const path = comp.bin_file.?.emit;
|
||||
var file = path.root_dir.handle.createFile(io, path.sub_path, .{}) catch |err|
|
||||
return diags.fail("failed to create {qf}: {t}", .{ path, err });
|
||||
defer file.close(io);
|
||||
|
||||
file.writeStreamingAll(io, @ptrCast(bitcode)) catch |err|
|
||||
return diags.fail("failed to write to '{s}': {t}", .{ path, err });
|
||||
return diags.fail("failed to write to {qf}: {t}", .{ path, err });
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.asm_path == null and options.bin_path == null and
|
||||
options.post_ir_path == null and options.post_bc_path == null) return;
|
||||
options.opt_ir_path == null and options.opt_bc_path == null and
|
||||
!log_opt_llvm_ir) return;
|
||||
|
||||
if (!build_options.have_llvm or !comp.config.use_lib_llvm) {
|
||||
return diags.fail("emitting without libllvm not implemented", .{});
|
||||
}
|
||||
|
||||
initializeLLVMTarget(io, comp.root_mod.resolved_target.result.cpu.arch);
|
||||
initializeLLVMTarget(io, target.cpu.arch);
|
||||
|
||||
const context: *bindings.Context = .create();
|
||||
errdefer context.dispose();
|
||||
@@ -577,9 +584,9 @@ pub const Object = struct {
|
||||
};
|
||||
defer context.dispose();
|
||||
|
||||
var target: *bindings.Target = undefined;
|
||||
var llvm_target: *bindings.Target = undefined;
|
||||
var error_message: [*:0]const u8 = undefined;
|
||||
if (bindings.Target.getFromTriple(target_triple_sentinel, &target, &error_message).toBool()) {
|
||||
if (bindings.Target.getFromTriple(target_triple_sentinel, &llvm_target, &error_message).toBool()) {
|
||||
defer bindings.disposeMessage(error_message);
|
||||
return diags.fail("LLVM failed to parse '{s}': {s}", .{ target_triple_sentinel, error_message });
|
||||
}
|
||||
@@ -598,7 +605,7 @@ pub const Object = struct {
|
||||
else
|
||||
.Static;
|
||||
|
||||
const code_model: bindings.CodeModel = switch (codeModel(comp.root_mod.code_model, &comp.root_mod.resolved_target.result)) {
|
||||
const code_model: bindings.CodeModel = switch (codeModel(comp.root_mod.code_model, target)) {
|
||||
.default => .Default,
|
||||
.tiny => .Tiny,
|
||||
.small => .Small,
|
||||
@@ -607,24 +614,22 @@ pub const Object = struct {
|
||||
.large => .Large,
|
||||
};
|
||||
|
||||
const float_abi: bindings.TargetMachine.FloatABI = if (comp.root_mod.resolved_target.result.abi.float() == .hard)
|
||||
.Hard
|
||||
else
|
||||
.Soft;
|
||||
|
||||
var target_machine = bindings.TargetMachine.create(
|
||||
target,
|
||||
llvm_target,
|
||||
target_triple_sentinel,
|
||||
if (comp.root_mod.resolved_target.result.cpu.model.llvm_name) |s| s.ptr else null,
|
||||
comp.root_mod.resolved_target.llvm_cpu_features.?,
|
||||
if (target.cpu.model.llvm_name) |s| s.ptr else null,
|
||||
comp.root_mod.llvm_cpu_features.?,
|
||||
opt_level,
|
||||
reloc_mode,
|
||||
code_model,
|
||||
comp.function_sections,
|
||||
comp.data_sections,
|
||||
float_abi,
|
||||
if (target_util.llvmMachineAbi(&comp.root_mod.resolved_target.result)) |s| s.ptr else null,
|
||||
target_util.useEmulatedTls(&comp.root_mod.resolved_target.result),
|
||||
switch (target.abi.float()) {
|
||||
.hard => .Hard,
|
||||
.soft => .Soft,
|
||||
},
|
||||
if (target_util.llvmMachineAbi(target)) |s| s.ptr else null,
|
||||
target_util.useEmulatedTls(target),
|
||||
);
|
||||
errdefer target_machine.dispose();
|
||||
|
||||
@@ -634,7 +639,10 @@ pub const Object = struct {
|
||||
|
||||
// Unfortunately, LLVM shits the bed when we ask for both binary and assembly.
|
||||
// So we call the entire pipeline multiple times if this is requested.
|
||||
// var error_message: [*:0]const u8 = undefined;
|
||||
var time_report_c_str: ?[*:0]u8 = null;
|
||||
defer if (time_report_c_str) |time_report| bindings.disposeMessage(time_report);
|
||||
var llvm_ir_c_str: ?[*:0]u8 = null;
|
||||
defer if (llvm_ir_c_str) |llvm_ir| bindings.disposeMessage(llvm_ir);
|
||||
var lowered_options: bindings.TargetMachine.EmitOptions = .{
|
||||
.is_debug = options.is_debug,
|
||||
.is_small = options.is_small,
|
||||
@@ -648,11 +656,12 @@ pub const Object = struct {
|
||||
.allow_fast_isel = true,
|
||||
// LLVM's RISC-V backend for some reason enables the machine outliner by default even
|
||||
// though it's clearly not ready and produces multiple miscompilations in our std tests.
|
||||
.allow_machine_outliner = !comp.root_mod.resolved_target.result.cpu.arch.isRISCV(),
|
||||
.allow_machine_outliner = !target.cpu.arch.isRISCV(),
|
||||
.asm_filename = null,
|
||||
.bin_filename = if (options.bin_path) |x| x.ptr else null,
|
||||
.llvm_ir_filename = if (options.post_ir_path) |x| x.ptr else null,
|
||||
.bitcode_filename = if (options.post_bc_path) |x| x.ptr else null,
|
||||
.llvm_ir_filename = if (options.opt_ir_path) |x| x.ptr else null,
|
||||
.bitcode_filename = if (options.opt_bc_path) |x| x.ptr else null,
|
||||
.llvm_ir_out = if (log_opt_llvm_ir) &llvm_ir_c_str else null,
|
||||
|
||||
// `.coverage` value is only used when `.sancov` is enabled.
|
||||
.sancov = options.fuzz or comp.config.san_cov_trace_pc_guard,
|
||||
@@ -684,33 +693,31 @@ pub const Object = struct {
|
||||
};
|
||||
if (options.asm_path != null and options.bin_path != null) {
|
||||
if (target_machine.emitToFile(module, &error_message, &lowered_options)) {
|
||||
defer bindings.disposeMessage(error_message);
|
||||
return diags.fail("LLVM failed to emit bin={s} ir={s}: {s}", .{
|
||||
emit_bin_msg, post_llvm_ir_msg, error_message,
|
||||
emit_bin_msg, opt_llvm_ir_msg, error_message,
|
||||
});
|
||||
}
|
||||
lowered_options.bin_filename = null;
|
||||
lowered_options.llvm_ir_filename = null;
|
||||
lowered_options.bitcode_filename = null;
|
||||
lowered_options.llvm_ir_out = null;
|
||||
}
|
||||
|
||||
var time_report_c_str: [*:0]u8 = undefined;
|
||||
if (options.time_report != null) {
|
||||
lowered_options.time_report_out = &time_report_c_str;
|
||||
}
|
||||
|
||||
if (options.time_report) |_| lowered_options.time_report_out = &time_report_c_str;
|
||||
lowered_options.asm_filename = if (options.asm_path) |x| x.ptr else null;
|
||||
if (target_machine.emitToFile(module, &error_message, &lowered_options)) {
|
||||
defer bindings.disposeMessage(error_message);
|
||||
return diags.fail("LLVM failed to emit asm={s} bin={s} ir={s} bc={s}: {s}", .{
|
||||
emit_asm_msg, emit_bin_msg, post_llvm_ir_msg, post_llvm_bc_msg, error_message,
|
||||
emit_asm_msg, emit_bin_msg, opt_llvm_ir_msg, opt_llvm_bc_msg, error_message,
|
||||
});
|
||||
}
|
||||
if (options.time_report) |tr| {
|
||||
defer std.c.free(time_report_c_str);
|
||||
const time_report_data = std.mem.span(time_report_c_str);
|
||||
assert(tr.llvm_pass_timings.len == 0);
|
||||
tr.llvm_pass_timings = try comp.gpa.dupe(u8, time_report_data);
|
||||
if (log_opt_llvm_ir) std.log.scoped(.@"opt-llvm-ir").debug("{s}", .{
|
||||
llvm_ir_c_str orelse return error.OutOfMemory,
|
||||
});
|
||||
if (options.time_report) |time_report| {
|
||||
assert(time_report.llvm_pass_timings.len == 0);
|
||||
time_report.llvm_pass_timings = try comp.gpa.dupe(u8, std.mem.span(
|
||||
time_report_c_str orelse return error.OutOfMemory,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2184,10 +2191,10 @@ pub const Object = struct {
|
||||
.value = try o.builder.string(s),
|
||||
} }, &o.builder);
|
||||
}
|
||||
if (owner_mod.resolved_target.llvm_cpu_features) |s| {
|
||||
if (owner_mod.llvm_cpu_features) |s| {
|
||||
try attributes.addFnAttr(.{ .string = .{
|
||||
.kind = try o.builder.string("target-features"),
|
||||
.value = try o.builder.string(std.mem.span(s)),
|
||||
.value = try o.builder.string(s),
|
||||
} }, &o.builder);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ pub const Module = opaque {
|
||||
};
|
||||
|
||||
pub const disposeMessage = LLVMDisposeMessage;
|
||||
extern fn LLVMDisposeMessage(Message: [*:0]const u8) void;
|
||||
extern fn LLVMDisposeMessage(Message: ?[*:0]const u8) void;
|
||||
|
||||
pub const TargetMachine = opaque {
|
||||
pub const FloatABI = enum(c_int) {
|
||||
@@ -85,7 +85,7 @@ pub const TargetMachine = opaque {
|
||||
pub const EmitOptions = extern struct {
|
||||
is_debug: bool,
|
||||
is_small: bool,
|
||||
time_report_out: ?*[*:0]u8,
|
||||
time_report_out: ?*?[*:0]u8,
|
||||
tsan: bool,
|
||||
sancov: bool,
|
||||
lto: LtoPhase,
|
||||
@@ -95,6 +95,7 @@ pub const TargetMachine = opaque {
|
||||
bin_filename: ?[*:0]const u8,
|
||||
llvm_ir_filename: ?[*:0]const u8,
|
||||
bitcode_filename: ?[*:0]const u8,
|
||||
llvm_ir_out: ?*?[*:0]u8,
|
||||
coverage: Coverage,
|
||||
|
||||
pub const LtoPhase = enum(c_int) {
|
||||
|
||||
@@ -27,7 +27,7 @@ const Target = std.Target;
|
||||
const log = std.log.scoped(.riscv_codegen);
|
||||
const tracking_log = std.log.scoped(.tracking);
|
||||
const verbose_tracking_log = std.log.scoped(.verbose_tracking);
|
||||
const wip_mir_log = std.log.scoped(.wip_mir);
|
||||
const wip_mir_log = std.log.scoped(.@"wip-mir");
|
||||
const Alignment = InternPool.Alignment;
|
||||
|
||||
const bits = @import("bits.zig");
|
||||
|
||||
@@ -5,7 +5,7 @@ const link = @import("../../link.zig");
|
||||
const log = std.log.scoped(.codegen);
|
||||
const tracking_log = std.log.scoped(.tracking);
|
||||
const verbose_tracking_log = std.log.scoped(.verbose_tracking);
|
||||
const wip_mir_log = std.log.scoped(.wip_mir);
|
||||
const wip_mir_log = std.log.scoped(.@"wip-mir");
|
||||
const Writer = std.Io.Writer;
|
||||
|
||||
const Air = @import("../../Air.zig");
|
||||
|
||||
@@ -112,6 +112,7 @@ pub const Env = enum {
|
||||
.loongarch_backend,
|
||||
.spork8_backend,
|
||||
.lld_linker,
|
||||
.llvm_linker,
|
||||
.coff_linker,
|
||||
.elf_linker,
|
||||
.elf2_linker,
|
||||
@@ -333,6 +334,7 @@ pub const Feature = enum {
|
||||
spork8_backend,
|
||||
|
||||
lld_linker,
|
||||
llvm_linker,
|
||||
coff_linker,
|
||||
elf_linker,
|
||||
elf2_linker,
|
||||
|
||||
@@ -1120,10 +1120,6 @@ fn buildSharedLib(
|
||||
.emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) },
|
||||
.verbose_cc = comp.verbose_cc,
|
||||
.verbose_link = comp.verbose_link,
|
||||
.verbose_air = comp.verbose_air,
|
||||
.verbose_llvm_ir = comp.verbose_llvm_ir,
|
||||
.verbose_llvm_bc = comp.verbose_llvm_bc,
|
||||
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
|
||||
.clang_passthrough_mode = comp.clang_passthrough_mode,
|
||||
.version = version,
|
||||
.version_script = .{
|
||||
|
||||
@@ -1268,10 +1268,6 @@ fn buildSharedLib(
|
||||
.emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) },
|
||||
.verbose_cc = comp.verbose_cc,
|
||||
.verbose_link = comp.verbose_link,
|
||||
.verbose_air = comp.verbose_air,
|
||||
.verbose_llvm_ir = comp.verbose_llvm_ir,
|
||||
.verbose_llvm_bc = comp.verbose_llvm_bc,
|
||||
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
|
||||
.clang_passthrough_mode = comp.clang_passthrough_mode,
|
||||
.version = version,
|
||||
.version_script = .{
|
||||
|
||||
@@ -260,10 +260,6 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
|
||||
.c_source_files = c_source_files.items,
|
||||
.verbose_cc = comp.verbose_cc,
|
||||
.verbose_link = comp.verbose_link,
|
||||
.verbose_air = comp.verbose_air,
|
||||
.verbose_llvm_ir = comp.verbose_llvm_ir,
|
||||
.verbose_llvm_bc = comp.verbose_llvm_bc,
|
||||
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
|
||||
.clang_passthrough_mode = comp.clang_passthrough_mode,
|
||||
.skip_linker_dependencies = true,
|
||||
.environ_map = comp.environ_map,
|
||||
@@ -445,10 +441,6 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
|
||||
.c_source_files = c_source_files.items,
|
||||
.verbose_cc = comp.verbose_cc,
|
||||
.verbose_link = comp.verbose_link,
|
||||
.verbose_air = comp.verbose_air,
|
||||
.verbose_llvm_ir = comp.verbose_llvm_ir,
|
||||
.verbose_llvm_bc = comp.verbose_llvm_bc,
|
||||
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
|
||||
.clang_passthrough_mode = comp.clang_passthrough_mode,
|
||||
.skip_linker_dependencies = true,
|
||||
.environ_map = comp.environ_map,
|
||||
|
||||
@@ -295,10 +295,6 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
|
||||
.c_source_files = c_source_files.items,
|
||||
.verbose_cc = comp.verbose_cc,
|
||||
.verbose_link = comp.verbose_link,
|
||||
.verbose_air = comp.verbose_air,
|
||||
.verbose_llvm_ir = comp.verbose_llvm_ir,
|
||||
.verbose_llvm_bc = comp.verbose_llvm_bc,
|
||||
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
|
||||
.clang_passthrough_mode = comp.clang_passthrough_mode,
|
||||
.skip_linker_dependencies = skip_linker_dependencies,
|
||||
.linker_allow_shlib_undefined = linker_allow_shlib_undefined,
|
||||
|
||||
@@ -157,10 +157,6 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
|
||||
.c_source_files = &c_source_files,
|
||||
.verbose_cc = comp.verbose_cc,
|
||||
.verbose_link = comp.verbose_link,
|
||||
.verbose_air = comp.verbose_air,
|
||||
.verbose_llvm_ir = comp.verbose_llvm_ir,
|
||||
.verbose_llvm_bc = comp.verbose_llvm_bc,
|
||||
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
|
||||
.clang_passthrough_mode = comp.clang_passthrough_mode,
|
||||
.skip_linker_dependencies = true,
|
||||
.environ_map = comp.environ_map,
|
||||
|
||||
@@ -246,9 +246,6 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
|
||||
.emit_bin = .yes_cache,
|
||||
.verbose_cc = comp.verbose_cc,
|
||||
.verbose_link = comp.verbose_link,
|
||||
.verbose_air = comp.verbose_air,
|
||||
.verbose_llvm_ir = comp.verbose_llvm_ir,
|
||||
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
|
||||
.clang_passthrough_mode = comp.clang_passthrough_mode,
|
||||
.c_source_files = &.{
|
||||
.{
|
||||
|
||||
@@ -771,10 +771,6 @@ fn buildSharedLib(
|
||||
.emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) },
|
||||
.verbose_cc = comp.verbose_cc,
|
||||
.verbose_link = comp.verbose_link,
|
||||
.verbose_air = comp.verbose_air,
|
||||
.verbose_llvm_ir = comp.verbose_llvm_ir,
|
||||
.verbose_llvm_bc = comp.verbose_llvm_bc,
|
||||
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
|
||||
.clang_passthrough_mode = comp.clang_passthrough_mode,
|
||||
.version = version,
|
||||
.soname = soname,
|
||||
|
||||
@@ -691,10 +691,6 @@ fn buildSharedLib(
|
||||
.emit_bin = .{ .yes_path = try bin_directory.join(arena, &.{basename}) },
|
||||
.verbose_cc = comp.verbose_cc,
|
||||
.verbose_link = comp.verbose_link,
|
||||
.verbose_air = comp.verbose_air,
|
||||
.verbose_llvm_ir = comp.verbose_llvm_ir,
|
||||
.verbose_llvm_bc = comp.verbose_llvm_bc,
|
||||
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
|
||||
.clang_passthrough_mode = comp.clang_passthrough_mode,
|
||||
.soname = soname,
|
||||
.c_source_files = &c_source_files,
|
||||
|
||||
+35
-4
@@ -550,6 +550,7 @@ pub const File = struct {
|
||||
return &ptr.base;
|
||||
},
|
||||
.lld => unreachable, // not known from ofmt
|
||||
.llvm => |tag| return createDummy(arena, tag, comp, emit),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -573,9 +574,26 @@ pub const File = struct {
|
||||
return &ptr.base;
|
||||
},
|
||||
.lld => unreachable, // not known from ofmt
|
||||
.llvm => |tag| return createDummy(arena, tag, comp, emit),
|
||||
}
|
||||
}
|
||||
|
||||
fn createDummy(arena: Allocator, tag: Tag, comp: *Compilation, path: Path) Allocator.Error!*File {
|
||||
const base = try arena.create(File);
|
||||
base.* = .{
|
||||
.tag = tag,
|
||||
.comp = comp,
|
||||
.emit = path,
|
||||
.file = null,
|
||||
.gc_sections = false,
|
||||
.print_gc_sections = false,
|
||||
.build_id = .none,
|
||||
.allow_shlib_undefined = false,
|
||||
.stack_size = 0,
|
||||
};
|
||||
return base;
|
||||
}
|
||||
|
||||
pub fn cast(base: *File, comptime tag: Tag) if (dev.env.supports(tag.devFeature())) ?*tag.Type() else ?noreturn {
|
||||
return if (dev.env.supports(tag.devFeature()) and base.tag == tag) @fieldParentPtr("base", base) else null;
|
||||
}
|
||||
@@ -606,7 +624,7 @@ pub const File = struct {
|
||||
const gpa = comp.gpa;
|
||||
const io = comp.io;
|
||||
switch (base.tag) {
|
||||
.lld => assert(base.file == null),
|
||||
.lld, .llvm => assert(base.file == null),
|
||||
.elf, .macho, .wasm => {
|
||||
dev.checkAny(&.{ .coff_linker, .elf_linker, .macho_linker, .plan9_linker, .wasm_linker });
|
||||
if (base.file != null) return;
|
||||
@@ -706,7 +724,7 @@ pub const File = struct {
|
||||
if (!base.canMakeExecutable())
|
||||
return;
|
||||
switch (base.tag) {
|
||||
.lld => assert(base.file == null),
|
||||
.lld, .llvm => assert(base.file == null),
|
||||
.elf => if (base.file) |f| {
|
||||
dev.check(.elf_linker);
|
||||
f.close(io);
|
||||
@@ -827,6 +845,7 @@ pub const File = struct {
|
||||
|
||||
switch (base.tag) {
|
||||
.lld => unreachable,
|
||||
.llvm => unreachable,
|
||||
.plan9 => unreachable,
|
||||
inline else => |tag| {
|
||||
dev.check(tag.devFeature());
|
||||
@@ -862,6 +881,7 @@ pub const File = struct {
|
||||
assert(pt.zcu.llvm_object == null);
|
||||
switch (base.tag) {
|
||||
.lld => unreachable,
|
||||
.llvm => unreachable,
|
||||
.plan9 => unreachable,
|
||||
inline else => |tag| {
|
||||
dev.check(tag.devFeature());
|
||||
@@ -897,6 +917,7 @@ pub const File = struct {
|
||||
}
|
||||
switch (base.tag) {
|
||||
.lld => unreachable,
|
||||
.llvm => unreachable,
|
||||
.plan9 => unreachable,
|
||||
.spirv => {},
|
||||
.coff => {},
|
||||
@@ -941,6 +962,7 @@ pub const File = struct {
|
||||
base.releaseLock();
|
||||
if (base.file) |f| f.close(io);
|
||||
switch (base.tag) {
|
||||
.llvm => {},
|
||||
.plan9 => unreachable,
|
||||
inline else => |tag| {
|
||||
dev.check(tag.devFeature());
|
||||
@@ -1003,6 +1025,7 @@ pub const File = struct {
|
||||
}
|
||||
assert(base.post_prelink);
|
||||
switch (base.tag) {
|
||||
.llvm => {},
|
||||
.plan9 => unreachable,
|
||||
inline else => |tag| {
|
||||
dev.check(tag.devFeature());
|
||||
@@ -1030,6 +1053,7 @@ pub const File = struct {
|
||||
|
||||
switch (base.tag) {
|
||||
.lld => unreachable,
|
||||
.llvm => unreachable,
|
||||
.plan9 => unreachable,
|
||||
inline else => |tag| {
|
||||
dev.check(tag.devFeature());
|
||||
@@ -1056,6 +1080,7 @@ pub const File = struct {
|
||||
assert(base.comp.zcu.?.llvm_object == null);
|
||||
switch (base.tag) {
|
||||
.lld => unreachable,
|
||||
.llvm => unreachable,
|
||||
.c => unreachable,
|
||||
.spirv => unreachable,
|
||||
.wasm => unreachable,
|
||||
@@ -1078,6 +1103,7 @@ pub const File = struct {
|
||||
assert(pt.zcu.llvm_object == null);
|
||||
switch (base.tag) {
|
||||
.lld => unreachable,
|
||||
.llvm => unreachable,
|
||||
.c => unreachable,
|
||||
.spirv => unreachable,
|
||||
.wasm => unreachable,
|
||||
@@ -1095,6 +1121,7 @@ pub const File = struct {
|
||||
assert(base.comp.zcu.?.llvm_object == null);
|
||||
switch (base.tag) {
|
||||
.lld => unreachable,
|
||||
.llvm => unreachable,
|
||||
.c => unreachable,
|
||||
.spirv => unreachable,
|
||||
.wasm => unreachable,
|
||||
@@ -1124,6 +1151,7 @@ pub const File = struct {
|
||||
.spirv,
|
||||
.plan9,
|
||||
.lld,
|
||||
.llvm,
|
||||
.spork8,
|
||||
=> return .unimplemented,
|
||||
inline else => |tag| {
|
||||
@@ -1240,7 +1268,7 @@ pub const File = struct {
|
||||
dev.check(tag.devFeature());
|
||||
return @as(*tag.Type(), @fieldParentPtr("base", base)).loadInput(input);
|
||||
},
|
||||
.c, .spork8, .plan9, .lld => {},
|
||||
.c, .spork8, .plan9, .lld, .llvm => {},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1352,6 +1380,7 @@ pub const File = struct {
|
||||
coff,
|
||||
elf,
|
||||
elf2,
|
||||
llvm,
|
||||
macho,
|
||||
macho2,
|
||||
c,
|
||||
@@ -1366,13 +1395,14 @@ pub const File = struct {
|
||||
.coff => Coff,
|
||||
.elf => Elf,
|
||||
.elf2 => Elf2,
|
||||
.llvm => File,
|
||||
.macho => MachO,
|
||||
.macho2 => MachO2,
|
||||
.c => C,
|
||||
.wasm => Wasm,
|
||||
.spirv => Spirv,
|
||||
.lld => Lld,
|
||||
.plan9 => comptime unreachable,
|
||||
.plan9 => unreachable,
|
||||
.spork8 => Spork8,
|
||||
};
|
||||
}
|
||||
@@ -1381,6 +1411,7 @@ pub const File = struct {
|
||||
return switch (ofmt) {
|
||||
.coff => .coff,
|
||||
.elf => if (use_new_linker) .elf2 else .elf,
|
||||
.llvmbc, .llvmir => .llvm,
|
||||
.macho => if (use_new_linker) .macho2 else .macho,
|
||||
.wasm => .wasm,
|
||||
.plan9 => .plan9,
|
||||
|
||||
+1
-3
@@ -860,9 +860,7 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
|
||||
|
||||
// Dump the state for easy debugging.
|
||||
// State can be dumped via `--debug-log link_state`.
|
||||
if (build_options.enable_logging) {
|
||||
state_log.debug("{f}", .{self.dumpState()});
|
||||
}
|
||||
state_log.debug("{f}", .{self.dumpState()});
|
||||
|
||||
// Beyond this point, everything has been allocated a virtual address and we can resolve
|
||||
// the relocations, and commit objects to file.
|
||||
|
||||
@@ -291,7 +291,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
|
||||
if (metadata.rodata_state != .unused) metadata.rodata_state = .flushed;
|
||||
}
|
||||
|
||||
if (build_options.enable_logging) {
|
||||
if (build_options.enable_debug_extensions) {
|
||||
const active = elf_file.base.comp.zcu.?.activate(tid);
|
||||
defer active.deactivate();
|
||||
for (self.navs.keys(), self.navs.values()) |nav_index, meta| {
|
||||
|
||||
+1
-1
@@ -98,7 +98,7 @@ fn markAtom(atom: *Atom) bool {
|
||||
}
|
||||
|
||||
fn markLive(atom: *Atom, elf_file: *Elf) void {
|
||||
if (@import("build_options").enable_logging) track_live_level.incr();
|
||||
if (@import("build_options").enable_debug_extensions) track_live_level.incr();
|
||||
|
||||
assert(atom.visited);
|
||||
const file = atom.file(elf_file).?;
|
||||
|
||||
@@ -51,9 +51,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
|
||||
try allocateAllocSections(elf_file);
|
||||
try elf_file.allocateNonAllocSections();
|
||||
|
||||
if (build_options.enable_logging) {
|
||||
state_log.debug("{f}", .{elf_file.dumpState()});
|
||||
}
|
||||
state_log.debug("{f}", .{elf_file.dumpState()});
|
||||
|
||||
try elf_file.writeMergeSections();
|
||||
try writeSyntheticSections(elf_file);
|
||||
@@ -117,10 +115,8 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
|
||||
break :blk pos;
|
||||
};
|
||||
|
||||
if (build_options.enable_logging) {
|
||||
state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(elf_file)});
|
||||
state_log.debug("ar_strtab\n{f}\n", .{ar_strtab});
|
||||
}
|
||||
state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(elf_file)});
|
||||
state_log.debug("ar_strtab\n{f}\n", .{ar_strtab});
|
||||
|
||||
const buffer = try gpa.alloc(u8, total_size);
|
||||
defer gpa.free(buffer);
|
||||
@@ -193,9 +189,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void {
|
||||
try allocateAllocSections(elf_file);
|
||||
try elf_file.allocateNonAllocSections();
|
||||
|
||||
if (build_options.enable_logging) {
|
||||
state_log.debug("{f}", .{elf_file.dumpState()});
|
||||
}
|
||||
state_log.debug("{f}", .{elf_file.dumpState()});
|
||||
|
||||
try writeAtoms(elf_file);
|
||||
try elf_file.writeMergeSections();
|
||||
|
||||
+1
-3
@@ -456,9 +456,7 @@ pub fn flush(
|
||||
self.allocateSegments();
|
||||
self.allocateSyntheticSymbols();
|
||||
|
||||
if (build_options.enable_logging) {
|
||||
state_log.debug("{f}", .{self.dumpState()});
|
||||
}
|
||||
state_log.debug("{f}", .{self.dumpState()});
|
||||
|
||||
// Beyond this point, everything has been allocated a virtual address and we can resolve
|
||||
// the relocations, and commit objects to file.
|
||||
|
||||
@@ -123,8 +123,9 @@ fn markLive(atom: *Atom, macho_file: *MachO) void {
|
||||
atom.getName(macho_file),
|
||||
});
|
||||
|
||||
if (build_options.enable_logging)
|
||||
if (build_options.enable_debug_extensions) {
|
||||
track_live_level.incr();
|
||||
}
|
||||
|
||||
for (atom.getRelocs(macho_file)) |rel| {
|
||||
const target_atom = switch (rel.tag) {
|
||||
|
||||
@@ -61,9 +61,7 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation) link.Error!void {
|
||||
};
|
||||
allocateSegment(macho_file);
|
||||
|
||||
if (build_options.enable_logging) {
|
||||
state_log.debug("{f}", .{macho_file.dumpState()});
|
||||
}
|
||||
state_log.debug("{f}", .{macho_file.dumpState()});
|
||||
|
||||
try writeSections(macho_file);
|
||||
sortRelocs(macho_file);
|
||||
@@ -107,9 +105,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation) link.Error!void {
|
||||
return diags.fail("failed to allocate sections: {s}", .{@errorName(err)});
|
||||
allocateSegment(macho_file);
|
||||
|
||||
if (build_options.enable_logging) {
|
||||
state_log.debug("{f}", .{macho_file.dumpState()});
|
||||
}
|
||||
state_log.debug("{f}", .{macho_file.dumpState()});
|
||||
|
||||
try writeSections(macho_file);
|
||||
sortRelocs(macho_file);
|
||||
@@ -185,9 +181,7 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation) link.Error!void {
|
||||
break :blk pos;
|
||||
};
|
||||
|
||||
if (build_options.enable_logging) {
|
||||
state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(macho_file)});
|
||||
}
|
||||
state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(macho_file)});
|
||||
|
||||
const buffer = try gpa.alloc(u8, total_size);
|
||||
defer gpa.free(buffer);
|
||||
|
||||
+40
-74
@@ -42,11 +42,8 @@ const thread_stack_size = 60 << 20;
|
||||
|
||||
pub const std_options: std.Options = .{
|
||||
.logFn = log,
|
||||
|
||||
.log_level = switch (builtin.mode) {
|
||||
.debug => .debug,
|
||||
.safe, .fast => .info,
|
||||
.small => .err,
|
||||
.log_level = switch (build_options.log_level) {
|
||||
inline else => |log_level| @field(std.log.Level, @tagName(log_level)),
|
||||
},
|
||||
};
|
||||
pub const std_options_cwd = if (native_os == .wasi) wasi_cwd else null;
|
||||
@@ -104,7 +101,7 @@ const normal_usage =
|
||||
\\ help Print this help and exit
|
||||
\\ cache-cat Print a zig-cache manifest file as zon
|
||||
\\ std View standard library documentation in a browser
|
||||
\\ libc Display native libc paths file or validate one
|
||||
\\ libc Print native libc paths file or validate one
|
||||
\\ targets List available compilation targets
|
||||
\\ version Print version number and exit
|
||||
\\ zen Print Zen of Zig and exit
|
||||
@@ -126,7 +123,15 @@ const debug_usage = normal_usage ++
|
||||
|
||||
const usage = if (build_options.enable_debug_extensions) debug_usage else normal_usage;
|
||||
|
||||
var log_scopes: std.ArrayList([]const u8) = .empty;
|
||||
var log_scopes: std.array_hash_map.String(void) = .empty;
|
||||
|
||||
pub fn debugLogScopeEnabled(scope: []const u8) bool {
|
||||
switch (build_options.log_level) {
|
||||
else => {},
|
||||
.debug => if (log_scopes.contains(scope)) return true,
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn log(
|
||||
comptime level: std.log.Level,
|
||||
@@ -135,18 +140,11 @@ pub fn log(
|
||||
args: anytype,
|
||||
) void {
|
||||
// Hide debug messages unless:
|
||||
// * logging enabled with `-Dlog`.
|
||||
// * logging enabled with `-Ddebug-extensions` or `-Dlog=debug`.
|
||||
// * the --debug-log arg for the scope has been provided
|
||||
if (@backingInt(level) > @backingInt(std.options.log_level) or
|
||||
@backingInt(level) > @backingInt(std.log.Level.info))
|
||||
{
|
||||
if (!build_options.enable_logging) return;
|
||||
|
||||
const scope_name = @tagName(scope);
|
||||
for (log_scopes.items) |log_scope| {
|
||||
if (mem.eql(u8, log_scope, scope_name))
|
||||
break;
|
||||
} else return;
|
||||
switch (level) {
|
||||
else => {},
|
||||
.debug => if (!debugLogScopeEnabled(@tagName(scope))) return,
|
||||
}
|
||||
|
||||
// Otherwise, use the default implementation.
|
||||
@@ -557,11 +555,14 @@ const compile_usage =
|
||||
\\ -fno-emit-docs (default) Do not produce docs/ dir with html documentation
|
||||
\\ -femit-implib[=path] (default) Produce an import .lib when building a Windows DLL
|
||||
\\ -fno-emit-implib Do not produce an import .lib when building a Windows DLL
|
||||
\\ --show-builtin Output the source of @import("builtin") then exit
|
||||
\\ --cache-dir [path] Override the local cache directory
|
||||
\\ --global-cache-dir [path] Override the global cache directory
|
||||
\\ --zig-lib-dir [path] Override path to Zig installation lib directory
|
||||
\\ --build-root [path] Override path to project source files
|
||||
\\ --show-builtin Output the source of @import("builtin") then exit
|
||||
\\ --time-report Send timing diagnostics to '--listen' clients
|
||||
\\ --verbose-cc Print C compiler commands before executing them
|
||||
\\ --verbose-link Print linker commands before executing them
|
||||
\\
|
||||
\\Global Compile Options:
|
||||
\\ --name [name] Compilation unit name (not a file path)
|
||||
@@ -593,7 +594,6 @@ const compile_usage =
|
||||
\\ -fpatchable-function-entry=[num] Add num NOPs of padding in function prologues
|
||||
\\ -mexec-model=[value] (WASI) Execution model
|
||||
\\ -municode (Windows) Use wmain/wWinMain as entry point
|
||||
\\ --time-report Send timing diagnostics to '--listen' clients
|
||||
\\
|
||||
\\Per-Module Compile Options:
|
||||
\\ --dep [[import=]name] Add an entry to the next module's import table
|
||||
@@ -604,13 +604,15 @@ const compile_usage =
|
||||
\\ safe Enable both safety checks and machine code optimizations
|
||||
\\ small Prioritize small binary size. Safety checks off.
|
||||
\\ -ofmt=[fmt] Override target object format
|
||||
\\ elf Executable and Linking Format
|
||||
\\ c C source code
|
||||
\\ wasm WebAssembly
|
||||
\\ coff Common Object File Format (Windows)
|
||||
\\ elf Executable and Linking Format
|
||||
\\ llvmir LLVM text intermediate representation
|
||||
\\ llvmbc LLVM binary intermediate representation
|
||||
\\ macho macOS relocatables
|
||||
\\ spirv Standard, Portable Intermediate Representation V (SPIR-V)
|
||||
\\ plan9 Plan 9 from Bell Labs object format
|
||||
\\ spirv Standard, Portable Intermediate Representation V (SPIR-V)
|
||||
\\ wasm WebAssembly
|
||||
\\ hex (planned feature) Intel IHEX
|
||||
\\ raw (planned feature) Dump machine code directly
|
||||
\\ -mcpu [cpu] Specify target CPU and feature set
|
||||
@@ -791,15 +793,6 @@ const compile_usage =
|
||||
\\Debug Options (Zig Compiler Development):
|
||||
\\ -fopt-bisect-limit=[limit] Only run [limit] first LLVM optimization passes
|
||||
\\ -fstack-report Print stack size diagnostics
|
||||
\\ --verbose-link Display linker invocations
|
||||
\\ --verbose-cc Display C compiler invocations
|
||||
\\ --verbose-air Enable compiler debug output for Zig AIR
|
||||
\\ --verbose-intern-pool Enable compiler debug output for InternPool
|
||||
\\ --verbose-generic-instances Enable compiler debug output for generic instance generation
|
||||
\\ --verbose-llvm-ir[=path] Enable compiler debug output for unoptimized LLVM IR
|
||||
\\ --verbose-llvm-bc=[path] Enable compiler debug output for unoptimized LLVM BC
|
||||
\\ --verbose-cimport Enable compiler debug output for C imports
|
||||
\\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features
|
||||
\\ --debug-log [scope] Enable printing debug/info log messages for scope
|
||||
\\ --debug-compile-errors Crash with helpful diagnostics at the first compile error
|
||||
\\ --debug-link-snapshot Dump linker state and output file information for troubleshooting
|
||||
@@ -933,17 +926,11 @@ fn buildOutputType(
|
||||
var listen: Listen = .none;
|
||||
var debug_compile_errors = false;
|
||||
var debug_incremental = false;
|
||||
var verbose_link = (native_os != .wasi or builtin.link_libc) and
|
||||
EnvVar.ZIG_VERBOSE_LINK.isSet(environ_map);
|
||||
var verbose_cc = (native_os != .wasi or builtin.link_libc) and
|
||||
EnvVar.ZIG_VERBOSE_CC.isSet(environ_map);
|
||||
var verbose_air = false;
|
||||
var verbose_intern_pool = false;
|
||||
var verbose_generic_instances = false;
|
||||
var verbose_llvm_ir: ?[]const u8 = null;
|
||||
var verbose_llvm_bc: ?[]const u8 = null;
|
||||
var verbose_link = (native_os != .wasi or builtin.link_libc) and
|
||||
EnvVar.ZIG_VERBOSE_LINK.isSet(environ_map);
|
||||
var link_depfile: ?[]const u8 = null;
|
||||
var verbose_llvm_cpu_features = false;
|
||||
var time_report = false;
|
||||
var stack_report = false;
|
||||
var show_builtin = false;
|
||||
@@ -1809,24 +1796,10 @@ fn buildOutputType(
|
||||
} else {
|
||||
warn("Zig was compiled without debug extensions. --debug-compile-errors has no effect.", .{});
|
||||
}
|
||||
} else if (mem.eql(u8, arg, "--verbose-link")) {
|
||||
verbose_link = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-cc")) {
|
||||
verbose_cc = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-air")) {
|
||||
verbose_air = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-intern-pool")) {
|
||||
verbose_intern_pool = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-generic-instances")) {
|
||||
verbose_generic_instances = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
|
||||
verbose_llvm_ir = "-";
|
||||
} else if (mem.cutPrefix(u8, arg, "--verbose-llvm-ir=")) |rest| {
|
||||
verbose_llvm_ir = rest;
|
||||
} else if (mem.cutPrefix(u8, arg, "--verbose-llvm-bc=")) |rest| {
|
||||
verbose_llvm_bc = rest;
|
||||
} else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) {
|
||||
verbose_llvm_cpu_features = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-link")) {
|
||||
verbose_link = true;
|
||||
} else if (mem.cutPrefix(u8, arg, "-T")) |rest| {
|
||||
linker_script = rest;
|
||||
} else if (mem.cutPrefix(u8, arg, "-L")) |rest| {
|
||||
@@ -3729,13 +3702,7 @@ fn buildOutputType(
|
||||
.libc_installation = if (create_module.libc_installation) |*lci| lci else null,
|
||||
.verbose_cc = verbose_cc,
|
||||
.verbose_link = verbose_link,
|
||||
.verbose_air = verbose_air,
|
||||
.verbose_intern_pool = verbose_intern_pool,
|
||||
.verbose_generic_instances = verbose_generic_instances,
|
||||
.verbose_llvm_ir = verbose_llvm_ir,
|
||||
.verbose_llvm_bc = verbose_llvm_bc,
|
||||
.link_depfile = link_depfile,
|
||||
.verbose_llvm_cpu_features = verbose_llvm_cpu_features,
|
||||
.time_report = time_report,
|
||||
.stack_report = stack_report,
|
||||
.build_id = build_id,
|
||||
@@ -3956,10 +3923,10 @@ fn buildOutputType(
|
||||
});
|
||||
}
|
||||
|
||||
try test_exec_args.ensureUnusedCapacity(arena, 2 * log_scopes.items.len + @intFromBool(verbose_link) + @intFromBool(verbose_cc));
|
||||
for (log_scopes.items) |log_scope| test_exec_args.appendSliceAssumeCapacity(&.{ "--debug-log", log_scope });
|
||||
if (verbose_link) test_exec_args.appendAssumeCapacity("--verbose-link");
|
||||
try test_exec_args.ensureUnusedCapacity(arena, 2 * log_scopes.count() + @intFromBool(verbose_link) + @intFromBool(verbose_cc));
|
||||
for (log_scopes.keys()) |log_scope| test_exec_args.appendSliceAssumeCapacity(&.{ "--debug-log", log_scope });
|
||||
if (verbose_cc) test_exec_args.appendAssumeCapacity("--verbose-cc");
|
||||
if (verbose_link) test_exec_args.appendAssumeCapacity("--verbose-link");
|
||||
}
|
||||
|
||||
try runOrTest(
|
||||
@@ -5627,17 +5594,17 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8, environ_map:
|
||||
}
|
||||
}
|
||||
|
||||
const display_path = zig_source_path orelse "<stdin>";
|
||||
const print_path = zig_source_path orelse "<stdin>";
|
||||
const source: [:0]const u8 = s: {
|
||||
var f = if (zig_source_path) |p| file: {
|
||||
break :file Io.Dir.cwd().openFile(io, p, .{}) catch |err| {
|
||||
fatal("unable to open file {q} for ast-check: {t}", .{ display_path, err });
|
||||
fatal("unable to open file {q} for ast-check: {t}", .{ print_path, err });
|
||||
};
|
||||
} else Io.File.stdin();
|
||||
defer if (zig_source_path != null) f.close(io);
|
||||
var file_reader: Io.File.Reader = f.reader(io, &stdin_buffer);
|
||||
break :s std.zig.readSourceFileToEndAlloc(arena, &file_reader) catch |err| {
|
||||
fatal("unable to load file {q} for ast-check: {t}", .{ display_path, err });
|
||||
fatal("unable to load file {q} for ast-check: {t}", .{ print_path, err });
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5661,7 +5628,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8, environ_map:
|
||||
|
||||
if (zir.hasCompileErrors()) {
|
||||
var wip_errors: std.zig.ErrorBundle.Wip = try .init(arena);
|
||||
try wip_errors.addZirErrorMessages(zir, tree, source, display_path);
|
||||
try wip_errors.addZirErrorMessages(zir, tree, source, print_path);
|
||||
var error_bundle = try wip_errors.toOwnedBundle("");
|
||||
try error_bundle.renderToStderr(io, .{}, color);
|
||||
if (zir.loweringFailed()) {
|
||||
@@ -5731,7 +5698,7 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8, environ_map:
|
||||
const zoir = try ZonGen.generate(arena, tree, .{});
|
||||
if (zoir.hasCompileErrors()) {
|
||||
var wip_errors: std.zig.ErrorBundle.Wip = try .init(arena);
|
||||
try wip_errors.addZoirErrorMessages(zoir, tree, source, display_path);
|
||||
try wip_errors.addZoirErrorMessages(zoir, tree, source, print_path);
|
||||
var error_bundle = try wip_errors.toOwnedBundle("");
|
||||
error_bundle.renderToStderr(io, .{}, color) catch {};
|
||||
process.exit(1);
|
||||
@@ -6254,9 +6221,8 @@ fn randInt(io: Io, comptime T: type) T {
|
||||
}
|
||||
|
||||
fn addDebugLog(arena: Allocator, scope_name: []const u8) error{OutOfMemory}!void {
|
||||
if (!build_options.enable_logging) {
|
||||
warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{});
|
||||
} else {
|
||||
try log_scopes.append(arena, scope_name);
|
||||
switch (build_options.log_level) {
|
||||
else => warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}),
|
||||
.debug => try log_scopes.put(arena, try arena.dupe(u8, scope_name), {}),
|
||||
}
|
||||
}
|
||||
@@ -193,6 +193,8 @@ pub fn hasLlvmSupport(target: *const std.Target, ofmt: std.Target.ObjectFormat)
|
||||
.coff,
|
||||
.elf,
|
||||
.hex,
|
||||
.llvmbc,
|
||||
.llvmir,
|
||||
.macho,
|
||||
.spirv,
|
||||
.raw,
|
||||
|
||||
+5
-3
@@ -410,6 +410,10 @@ ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machi
|
||||
// Code generation phase
|
||||
codegen_pm.run(llvm_module);
|
||||
|
||||
if (options->llvm_ir_out != nullptr) {
|
||||
*options->llvm_ir_out = LLVMPrintModuleToString(module_ref);
|
||||
}
|
||||
|
||||
if (options->llvm_ir_filename) {
|
||||
if (LLVMPrintModuleToFile(module_ref, options->llvm_ir_filename, error_message)) {
|
||||
return true;
|
||||
@@ -430,9 +434,7 @@ ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machi
|
||||
auto os = raw_string_ostream(out_str);
|
||||
TimerGroup::printAll(os);
|
||||
TimerGroup::clearAll();
|
||||
auto c_str = (char *)malloc(out_str.length() + 1);
|
||||
strcpy(c_str, out_str.c_str());
|
||||
*options->time_report_out = c_str;
|
||||
*options->time_report_out = LLVMCreateMessage(out_str.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+6
-2
@@ -67,8 +67,8 @@ struct ZigLLVMEmitOptions {
|
||||
bool is_debug;
|
||||
bool is_small;
|
||||
// If not null, and `ZigLLVMTargetMachineEmitToFile` returns `false` indicating success, this
|
||||
// `char *` will be populated with a `malloc`-allocated string containing the serialized (as
|
||||
// JSON) time report data. The caller is responsible for freeing that memory.
|
||||
// `char *` will be populated with the serialized (as JSON) time report data. The caller is
|
||||
// responsible for freeing that memory with `disposeMessage`.
|
||||
char **time_report_out;
|
||||
bool tsan;
|
||||
bool sancov;
|
||||
@@ -79,6 +79,10 @@ struct ZigLLVMEmitOptions {
|
||||
const char *bin_filename;
|
||||
const char *llvm_ir_filename;
|
||||
const char *bitcode_filename;
|
||||
// If not null and `ZigLLVMTargetMachineEmitToFile` returns `false` indicating success, this
|
||||
// `char *` will be populated with the optimized LLVM IR. The caller is responsible for freeing
|
||||
// this memory with `disposeMessage`.
|
||||
char **llvm_ir_out;
|
||||
ZigLLVMCoverageOptions coverage;
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ pub const llvm_has_xtensa = false;
|
||||
pub const version: [:0]const u8 = "@RESOLVED_ZIG_VERSION@";
|
||||
pub const semver = @import("std").SemanticVersion.parse(version) catch unreachable;
|
||||
pub const enable_debug_extensions = false;
|
||||
pub const enable_logging = false;
|
||||
pub const log_level: @import("std").log.Level = .err;
|
||||
pub const enable_link_snapshots = false;
|
||||
pub const enable_tracy = false;
|
||||
pub const value_tracing = false;
|
||||
|
||||
Reference in new issue
Block a user