mirror of
https://github.com/ziglang/zig.git
synced 2025-12-30 10:03:21 +00:00
* CLI: change to -mred-zone and -mno-red-zone to match gcc/clang.
* build.zig: remove the double negative and make it an optional bool.
This follows precedent from other flags, allowing the compiler CLI to
be the decider of what is default instead of duplicating the default
value into the build system code.
* Compilation: make it an optional `want_red_zone` instead of a
`no_red_zone` bool. The default is decided by a call to
`target_util.hasRedZone`.
* When creating a Clang command line, put -mred-zone on the command
line if we are forcing it to be enabled.
* Update update_clang_options.zig with respect to the recent {s}/{} format changes.
* `zig cc` integration with red zone preference.
452 lines
12 KiB
Zig
452 lines
12 KiB
Zig
//! This is the main entry point for the Zig/C++ hybrid compiler (stage1).
|
|
//! It has the functions exported from Zig, called in C++, and bindings for
|
|
//! the functions exported from C++, called from Zig.
|
|
|
|
const std = @import("std");
|
|
const assert = std.debug.assert;
|
|
const mem = std.mem;
|
|
const CrossTarget = std.zig.CrossTarget;
|
|
const Target = std.Target;
|
|
|
|
const build_options = @import("build_options");
|
|
const stage2 = @import("main.zig");
|
|
const fatal = stage2.fatal;
|
|
const Compilation = @import("Compilation.zig");
|
|
const translate_c = @import("translate_c.zig");
|
|
const target_util = @import("target.zig");
|
|
|
|
comptime {
|
|
assert(std.builtin.link_libc);
|
|
assert(build_options.is_stage1);
|
|
assert(build_options.have_llvm);
|
|
_ = @import("compiler_rt");
|
|
}
|
|
|
|
pub const log = stage2.log;
|
|
pub const log_level = stage2.log_level;
|
|
|
|
pub export fn main(argc: c_int, argv: [*][*:0]u8) c_int {
|
|
std.os.argv = argv[0..@intCast(usize, argc)];
|
|
|
|
std.debug.maybeEnableSegfaultHandler();
|
|
|
|
zig_stage1_os_init();
|
|
|
|
const gpa = std.heap.c_allocator;
|
|
var arena_instance = std.heap.ArenaAllocator.init(gpa);
|
|
defer arena_instance.deinit();
|
|
const arena = &arena_instance.allocator;
|
|
|
|
const args = arena.alloc([]const u8, @intCast(usize, argc)) catch fatal("{s}", .{"OutOfMemory"});
|
|
for (args) |*arg, i| {
|
|
arg.* = mem.spanZ(argv[i]);
|
|
}
|
|
if (std.builtin.mode == .Debug) {
|
|
stage2.mainArgs(gpa, arena, args) catch unreachable;
|
|
} else {
|
|
stage2.mainArgs(gpa, arena, args) catch |err| fatal("{s}", .{@errorName(err)});
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/// Matches stage2.Color;
|
|
pub const ErrColor = c_int;
|
|
/// Matches std.builtin.CodeModel
|
|
pub const CodeModel = c_int;
|
|
/// Matches std.Target.Os.Tag
|
|
pub const OS = c_int;
|
|
/// Matches std.builtin.BuildMode
|
|
pub const BuildMode = c_int;
|
|
|
|
pub const TargetSubsystem = extern enum(c_int) {
|
|
Console,
|
|
Windows,
|
|
Posix,
|
|
Native,
|
|
EfiApplication,
|
|
EfiBootServiceDriver,
|
|
EfiRom,
|
|
EfiRuntimeDriver,
|
|
Auto,
|
|
};
|
|
|
|
pub const Pkg = extern struct {
|
|
name_ptr: [*]const u8,
|
|
name_len: usize,
|
|
path_ptr: [*]const u8,
|
|
path_len: usize,
|
|
children_ptr: [*]*Pkg,
|
|
children_len: usize,
|
|
parent: ?*Pkg,
|
|
};
|
|
|
|
pub const Module = extern struct {
|
|
root_name_ptr: [*]const u8,
|
|
root_name_len: usize,
|
|
emit_o_ptr: [*]const u8,
|
|
emit_o_len: usize,
|
|
emit_h_ptr: [*]const u8,
|
|
emit_h_len: usize,
|
|
emit_asm_ptr: [*]const u8,
|
|
emit_asm_len: usize,
|
|
emit_llvm_ir_ptr: [*]const u8,
|
|
emit_llvm_ir_len: usize,
|
|
emit_analysis_json_ptr: [*]const u8,
|
|
emit_analysis_json_len: usize,
|
|
emit_docs_ptr: [*]const u8,
|
|
emit_docs_len: usize,
|
|
builtin_zig_path_ptr: [*]const u8,
|
|
builtin_zig_path_len: usize,
|
|
test_filter_ptr: [*]const u8,
|
|
test_filter_len: usize,
|
|
test_name_prefix_ptr: [*]const u8,
|
|
test_name_prefix_len: usize,
|
|
userdata: usize,
|
|
root_pkg: *Pkg,
|
|
main_progress_node: ?*std.Progress.Node,
|
|
code_model: CodeModel,
|
|
subsystem: TargetSubsystem,
|
|
err_color: ErrColor,
|
|
pic: bool,
|
|
pie: bool,
|
|
link_libc: bool,
|
|
link_libcpp: bool,
|
|
strip: bool,
|
|
is_single_threaded: bool,
|
|
dll_export_fns: bool,
|
|
link_mode_dynamic: bool,
|
|
valgrind_enabled: bool,
|
|
tsan_enabled: bool,
|
|
function_sections: bool,
|
|
enable_stack_probing: bool,
|
|
red_zone: bool,
|
|
enable_time_report: bool,
|
|
enable_stack_report: bool,
|
|
test_is_evented: bool,
|
|
verbose_tokenize: bool,
|
|
verbose_ast: bool,
|
|
verbose_ir: bool,
|
|
verbose_llvm_ir: bool,
|
|
verbose_cimport: bool,
|
|
verbose_llvm_cpu_features: bool,
|
|
|
|
// Set by stage1
|
|
have_c_main: bool,
|
|
have_winmain: bool,
|
|
have_wwinmain: bool,
|
|
have_winmain_crt_startup: bool,
|
|
have_wwinmain_crt_startup: bool,
|
|
have_dllmain_crt_startup: bool,
|
|
|
|
pub fn build_object(mod: *Module) void {
|
|
zig_stage1_build_object(mod);
|
|
}
|
|
|
|
pub fn destroy(mod: *Module) void {
|
|
zig_stage1_destroy(mod);
|
|
}
|
|
};
|
|
|
|
extern fn zig_stage1_os_init() void;
|
|
|
|
pub const create = zig_stage1_create;
|
|
extern fn zig_stage1_create(
|
|
optimize_mode: BuildMode,
|
|
main_pkg_path_ptr: [*]const u8,
|
|
main_pkg_path_len: usize,
|
|
root_src_path_ptr: [*]const u8,
|
|
root_src_path_len: usize,
|
|
zig_lib_dir_ptr: [*c]const u8,
|
|
zig_lib_dir_len: usize,
|
|
target: [*c]const Stage2Target,
|
|
is_test_build: bool,
|
|
) ?*Module;
|
|
|
|
extern fn zig_stage1_build_object(*Module) void;
|
|
extern fn zig_stage1_destroy(*Module) void;
|
|
|
|
// ABI warning
|
|
export fn stage2_panic(ptr: [*]const u8, len: usize) void {
|
|
@panic(ptr[0..len]);
|
|
}
|
|
|
|
// ABI warning
|
|
const Error = extern enum {
|
|
None,
|
|
OutOfMemory,
|
|
InvalidFormat,
|
|
SemanticAnalyzeFail,
|
|
AccessDenied,
|
|
Interrupted,
|
|
SystemResources,
|
|
FileNotFound,
|
|
FileSystem,
|
|
FileTooBig,
|
|
DivByZero,
|
|
Overflow,
|
|
PathAlreadyExists,
|
|
Unexpected,
|
|
ExactDivRemainder,
|
|
NegativeDenominator,
|
|
ShiftedOutOneBits,
|
|
CCompileErrors,
|
|
EndOfFile,
|
|
IsDir,
|
|
NotDir,
|
|
UnsupportedOperatingSystem,
|
|
SharingViolation,
|
|
PipeBusy,
|
|
PrimitiveTypeNotFound,
|
|
CacheUnavailable,
|
|
PathTooLong,
|
|
CCompilerCannotFindFile,
|
|
NoCCompilerInstalled,
|
|
ReadingDepFile,
|
|
InvalidDepFile,
|
|
MissingArchitecture,
|
|
MissingOperatingSystem,
|
|
UnknownArchitecture,
|
|
UnknownOperatingSystem,
|
|
UnknownABI,
|
|
InvalidFilename,
|
|
DiskQuota,
|
|
DiskSpace,
|
|
UnexpectedWriteFailure,
|
|
UnexpectedSeekFailure,
|
|
UnexpectedFileTruncationFailure,
|
|
Unimplemented,
|
|
OperationAborted,
|
|
BrokenPipe,
|
|
NoSpaceLeft,
|
|
NotLazy,
|
|
IsAsync,
|
|
ImportOutsidePkgPath,
|
|
UnknownCpuModel,
|
|
UnknownCpuFeature,
|
|
InvalidCpuFeatures,
|
|
InvalidLlvmCpuFeaturesFormat,
|
|
UnknownApplicationBinaryInterface,
|
|
ASTUnitFailure,
|
|
BadPathName,
|
|
SymLinkLoop,
|
|
ProcessFdQuotaExceeded,
|
|
SystemFdQuotaExceeded,
|
|
NoDevice,
|
|
DeviceBusy,
|
|
UnableToSpawnCCompiler,
|
|
CCompilerExitCode,
|
|
CCompilerCrashed,
|
|
CCompilerCannotFindHeaders,
|
|
LibCRuntimeNotFound,
|
|
LibCStdLibHeaderNotFound,
|
|
LibCKernel32LibNotFound,
|
|
UnsupportedArchitecture,
|
|
WindowsSdkNotFound,
|
|
UnknownDynamicLinkerPath,
|
|
TargetHasNoDynamicLinker,
|
|
InvalidAbiVersion,
|
|
InvalidOperatingSystemVersion,
|
|
UnknownClangOption,
|
|
NestedResponseFile,
|
|
ZigIsTheCCompiler,
|
|
FileBusy,
|
|
Locked,
|
|
};
|
|
|
|
// ABI warning
|
|
export fn stage2_version_string() [*:0]const u8 {
|
|
return build_options.version;
|
|
}
|
|
|
|
// ABI warning
|
|
export fn stage2_version() Stage2SemVer {
|
|
return .{
|
|
.major = build_options.semver.major,
|
|
.minor = build_options.semver.minor,
|
|
.patch = build_options.semver.patch,
|
|
};
|
|
}
|
|
|
|
// ABI warning
|
|
export fn stage2_attach_segfault_handler() void {
|
|
if (std.debug.runtime_safety and std.debug.have_segfault_handling_support) {
|
|
std.debug.attachSegfaultHandler();
|
|
}
|
|
}
|
|
|
|
// ABI warning
|
|
export fn stage2_progress_create() *std.Progress {
|
|
const ptr = std.heap.c_allocator.create(std.Progress) catch @panic("out of memory");
|
|
ptr.* = std.Progress{};
|
|
return ptr;
|
|
}
|
|
|
|
// ABI warning
|
|
export fn stage2_progress_destroy(progress: *std.Progress) void {
|
|
std.heap.c_allocator.destroy(progress);
|
|
}
|
|
|
|
// ABI warning
|
|
export fn stage2_progress_start_root(
|
|
progress: *std.Progress,
|
|
name_ptr: [*]const u8,
|
|
name_len: usize,
|
|
estimated_total_items: usize,
|
|
) *std.Progress.Node {
|
|
return progress.start(
|
|
name_ptr[0..name_len],
|
|
estimated_total_items,
|
|
) catch @panic("timer unsupported");
|
|
}
|
|
|
|
// ABI warning
|
|
export fn stage2_progress_disable_tty(progress: *std.Progress) void {
|
|
progress.terminal = null;
|
|
}
|
|
|
|
// ABI warning
|
|
export fn stage2_progress_start(
|
|
node: *std.Progress.Node,
|
|
name_ptr: [*]const u8,
|
|
name_len: usize,
|
|
estimated_total_items: usize,
|
|
) *std.Progress.Node {
|
|
const child_node = std.heap.c_allocator.create(std.Progress.Node) catch @panic("out of memory");
|
|
child_node.* = node.start(
|
|
name_ptr[0..name_len],
|
|
estimated_total_items,
|
|
);
|
|
child_node.activate();
|
|
return child_node;
|
|
}
|
|
|
|
// ABI warning
|
|
export fn stage2_progress_end(node: *std.Progress.Node) void {
|
|
node.end();
|
|
if (&node.context.root != node) {
|
|
std.heap.c_allocator.destroy(node);
|
|
}
|
|
}
|
|
|
|
// ABI warning
|
|
export fn stage2_progress_complete_one(node: *std.Progress.Node) void {
|
|
node.completeOne();
|
|
}
|
|
|
|
// ABI warning
|
|
export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usize, total_count: usize) void {
|
|
node.setCompletedItems(done_count);
|
|
node.setEstimatedTotalItems(total_count);
|
|
node.activate();
|
|
node.context.maybeRefresh();
|
|
}
|
|
|
|
// ABI warning
|
|
pub const Stage2Target = extern struct {
|
|
arch: c_int,
|
|
os: OS,
|
|
abi: c_int,
|
|
|
|
is_native_os: bool,
|
|
is_native_cpu: bool,
|
|
|
|
llvm_cpu_name: ?[*:0]const u8,
|
|
llvm_cpu_features: ?[*:0]const u8,
|
|
};
|
|
|
|
// ABI warning
|
|
const Stage2SemVer = extern struct {
|
|
major: u32,
|
|
minor: u32,
|
|
patch: u32,
|
|
};
|
|
|
|
// ABI warning
|
|
export fn stage2_cimport(
|
|
stage1: *Module,
|
|
c_src_ptr: [*]const u8,
|
|
c_src_len: usize,
|
|
out_zig_path_ptr: *[*]const u8,
|
|
out_zig_path_len: *usize,
|
|
out_errors_ptr: *[*]translate_c.ClangErrMsg,
|
|
out_errors_len: *usize,
|
|
) Error {
|
|
const comp = @intToPtr(*Compilation, stage1.userdata);
|
|
const c_src = c_src_ptr[0..c_src_len];
|
|
const result = comp.cImport(c_src) catch |err| switch (err) {
|
|
error.SystemResources => return .SystemResources,
|
|
error.OperationAborted => return .OperationAborted,
|
|
error.BrokenPipe => return .BrokenPipe,
|
|
error.DiskQuota => return .DiskQuota,
|
|
error.FileTooBig => return .FileTooBig,
|
|
error.NoSpaceLeft => return .NoSpaceLeft,
|
|
error.AccessDenied => return .AccessDenied,
|
|
error.OutOfMemory => return .OutOfMemory,
|
|
error.Unexpected => return .Unexpected,
|
|
error.InputOutput => return .FileSystem,
|
|
error.ASTUnitFailure => return .ASTUnitFailure,
|
|
error.CacheUnavailable => return .CacheUnavailable,
|
|
else => return .Unexpected,
|
|
};
|
|
out_zig_path_ptr.* = result.out_zig_path.ptr;
|
|
out_zig_path_len.* = result.out_zig_path.len;
|
|
out_errors_ptr.* = result.errors.ptr;
|
|
out_errors_len.* = result.errors.len;
|
|
if (result.errors.len != 0) return .CCompileErrors;
|
|
return Error.None;
|
|
}
|
|
|
|
export fn stage2_add_link_lib(
|
|
stage1: *Module,
|
|
lib_name_ptr: [*c]const u8,
|
|
lib_name_len: usize,
|
|
symbol_name_ptr: [*c]const u8,
|
|
symbol_name_len: usize,
|
|
) ?[*:0]const u8 {
|
|
const comp = @intToPtr(*Compilation, stage1.userdata);
|
|
const lib_name = std.ascii.allocLowerString(comp.gpa, lib_name_ptr[0..lib_name_len]) catch return "out of memory";
|
|
const target = comp.getTarget();
|
|
const is_libc = target_util.is_libc_lib_name(target, lib_name);
|
|
if (is_libc) {
|
|
if (!comp.bin_file.options.link_libc) {
|
|
return "dependency on libc must be explicitly specified in the build command";
|
|
}
|
|
return null;
|
|
}
|
|
if (target_util.is_libcpp_lib_name(target, lib_name)) {
|
|
if (!comp.bin_file.options.link_libcpp) {
|
|
return "dependency on libc++ must be explicitly specified in the build command";
|
|
}
|
|
return null;
|
|
}
|
|
if (!target.isWasm() and !comp.bin_file.options.pic) {
|
|
return std.fmt.allocPrint0(
|
|
comp.gpa,
|
|
"dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by `-l{s}` or `-fPIC`.",
|
|
.{ lib_name, lib_name },
|
|
) catch "out of memory";
|
|
}
|
|
comp.stage1AddLinkLib(lib_name) catch |err| {
|
|
return std.fmt.allocPrint0(comp.gpa, "unable to add link lib '{s}': {s}", .{
|
|
lib_name, @errorName(err),
|
|
}) catch "out of memory";
|
|
};
|
|
return null;
|
|
}
|
|
|
|
export fn stage2_fetch_file(
|
|
stage1: *Module,
|
|
path_ptr: [*]const u8,
|
|
path_len: usize,
|
|
result_len: *usize,
|
|
) ?[*]const u8 {
|
|
const comp = @intToPtr(*Compilation, stage1.userdata);
|
|
const file_path = path_ptr[0..path_len];
|
|
const max_file_size = std.math.maxInt(u32);
|
|
const contents = comp.stage1_cache_manifest.addFilePostFetch(file_path, max_file_size) catch return null;
|
|
result_len.* = contents.len;
|
|
// TODO https://github.com/ziglang/zig/issues/3328#issuecomment-716749475
|
|
if (contents.len == 0) return @intToPtr(?[*]const u8, 0x1);
|
|
return contents.ptr;
|
|
}
|